Merge branch 'beta' into allow-catch-teleporter

This commit is contained in:
Dean 2025-09-10 23:06:16 -07:00 committed by GitHub
commit ae79a6bf34
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
130 changed files with 1244 additions and 1017 deletions

7
.dockerignore Normal file
View File

@ -0,0 +1,7 @@
# .dockerignore
node_modules
*.log
*.md
.gitignore
Dockerfile
.env

View File

@ -55,14 +55,14 @@ jobs:
- name: Create release branch - name: Create release branch
run: git checkout -b release 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. # In order to be able to open a PR into beta, we need the branch to have at least one commit.
- name: Overwrite RELEASE file # The first commit is _usually_ just bumping the version number, so we can kill 2 birds with 1 stone here
- name: Bump release version
run: | run: |
git config --local user.name "github-actions[bot]" git config --local user.name "github-actions[bot]"
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
echo "Release v${{ github.event.inputs.versionName }}" > RELEASE pnpm --no-git-tag-version version ${{ github.events.inputs.versionName }}
git add RELEASE git commit -am "Stage release for v${{ github.events.inputs.versionName }}"
git commit -m "Stage release v${{ github.event.inputs.versionName }}"
- name: Push new branch - name: Push new branch
run: git push origin release run: git push origin release

View File

@ -22,8 +22,6 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:

View File

@ -20,8 +20,6 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:

View File

@ -27,20 +27,18 @@ jobs:
# Only push docs when running on pushes to main/beta # Only push docs when running on pushes to main/beta
DRY_RUN: ${{github.event_name != 'push' || (github.ref_name != 'beta' && github.ref_name != 'main')}} DRY_RUN: ${{github.event_name != 'push' || (github.ref_name != 'beta' && github.ref_name != 'main')}}
strategy:
fail-fast: false
steps: steps:
- name: Checkout repository for Typedoc - name: Checkout repository for Typedoc
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
submodules: 'recursive'
path: pokerogue_docs path: pokerogue_docs
sparse-checkout: |
- name: Install OS package /*
run: | !/public/
sudo apt update /public/images/pokemon/variant/_exp_masterlist.json
sudo apt install -y git openssh-client /public/images/pokemon/variant/_masterlist.json
/public/images/logo.png
sparse-checkout-cone-mode: false
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4

View File

@ -30,8 +30,6 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
with:
version: 10
- name: Set up Node - name: Set up Node
uses: actions/setup-node@v4 uses: actions/setup-node@v4

View File

@ -32,8 +32,6 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
with:
version: 10
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4

View File

@ -28,6 +28,10 @@ jobs:
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
sparse-checkout: |
.github/test-filters.yml
sparse-checkout-cone-mode: false
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36
id: filter id: filter

View File

@ -81,6 +81,7 @@ Notable topics include:
- [Linting & Formatting](./docs/linting.md) - [Linting & Formatting](./docs/linting.md)
- [Localization](./docs/localization.md) - [Localization](./docs/localization.md)
- [Enemy AI move selection](./docs/enemy-ai.md) - [Enemy AI move selection](./docs/enemy-ai.md)
- [Running with Podman](./docs/podman.md)
Again, if you have unanswered questions please feel free to ask! Again, if you have unanswered questions please feel free to ask!

47
Dockerfile Normal file
View File

@ -0,0 +1,47 @@
# syntax=docker/dockerfile:1
ARG NODE_VERSION=22.14
ARG OS=alpine
FROM node:${NODE_VERSION}-${OS}
# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# Install git (for potential runtime needs)
RUN apk add --no-cache git
# Set working directory
WORKDIR /app
# Enable and prepare pnpm
RUN corepack enable && corepack prepare pnpm@10.14.0 --activate
COPY . .
# Copy package files
COPY package.json pnpm-lock.yaml ./
# Install all dependencies
RUN --mount=type=cache,target=/home/appuser/.pnpm-store \
pnpm install --frozen-lockfile && \
rm -rf /home/appuser/.pnpm-store/*
# Change ownership
RUN chown -R appuser:appgroup /app
# Switch to non-root user
USER appuser
# Set environment variables
ENV VITE_BYPASS_LOGIN=1 \
VITE_BYPASS_TUTORIAL=0 \
NEXT_TELEMETRY_DISABLED=1 \
PNP_HOME=/home/appuser/.shrc \
NODE_ENV=development \
PORT=8000
# Expose port
EXPOSE $PORT
# Start the app in development mode
CMD ["pnpm", "run", "start:podman"]

View File

@ -1 +0,0 @@
Release v1.10.0

27
docs/podman.md Normal file
View File

@ -0,0 +1,27 @@
# Using Podman
## Requirements
* `podman >=5.x`
## Steps
1. `podman build -t pokerogue -f Dockerfile .`
2. `podman create --name temp-pokerogue localhost/pokerogue`
3. `podman cp temp-pokerogue:/app/node_modules ./`
4. `podman cp temp-pokerogue:/app/public/locales ./public/`
5. `podman rm temp-pokerogue`
6. `podman run --rm -p 8000:8000 -v $(pwd):/app:Z --userns=keep-id -u $(id -u):$(id -g) localhost/pokerogue`
7. Visit `http://localhost:8000/`
Note:
1. Steps 2,3,4 are required because mounting working directory without installed `node_modules/` and assets locally will be empty,
this way we prevent it by copying them from the container itself to local directory
2. `podman run` may take a couple of minutes to mount the working directory
### Running tests inside container
`podman run --rm -p 8000:8000 -v $(pwd):/app:Z --userns=keep-id -u $(id -u):$(id -g) localhost/pokerogue pnpm test:silent
`

View File

@ -7,6 +7,7 @@
"start:prod": "vite --mode production", "start:prod": "vite --mode production",
"start:beta": "vite --mode beta", "start:beta": "vite --mode beta",
"start:dev": "vite --mode development", "start:dev": "vite --mode development",
"start:podman": "vite --mode development --host 0.0.0.0 --port $PORT",
"build": "vite build", "build": "vite build",
"build:beta": "vite build --mode beta", "build:beta": "vite build --mode beta",
"preview": "vite preview", "preview": "vite preview",
@ -46,7 +47,7 @@
"lefthook": "^1.12.2", "lefthook": "^1.12.2",
"msw": "^2.10.4", "msw": "^2.10.4",
"phaser3spectorjs": "^0.0.8", "phaser3spectorjs": "^0.0.8",
"typedoc": "^0.28.8", "typedoc": "^0.28.12",
"typedoc-github-theme": "^0.3.1", "typedoc-github-theme": "^0.3.1",
"typedoc-plugin-coverage": "^4.0.1", "typedoc-plugin-coverage": "^4.0.1",
"typedoc-plugin-mdn-links": "^5.0.9", "typedoc-plugin-mdn-links": "^5.0.9",
@ -71,5 +72,6 @@
}, },
"engines": { "engines": {
"node": ">=22.0.0" "node": ">=22.0.0"
} },
"packageManager": "pnpm@10.14.0"
} }

View File

@ -59,7 +59,7 @@ importers:
version: 22.16.5 version: 22.16.5
'@vitest/coverage-istanbul': '@vitest/coverage-istanbul':
specifier: ^3.2.4 specifier: ^3.2.4
version: 3.2.4(vitest@3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.0)) version: 3.2.4(vitest@3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.1))
'@vitest/expect': '@vitest/expect':
specifier: ^3.2.4 specifier: ^3.2.4
version: 3.2.4 version: 3.2.4
@ -88,32 +88,32 @@ importers:
specifier: ^0.0.8 specifier: ^0.0.8
version: 0.0.8 version: 0.0.8
typedoc: typedoc:
specifier: ^0.28.8 specifier: ^0.28.12
version: 0.28.8(typescript@5.8.3) version: 0.28.12(typescript@5.8.3)
typedoc-github-theme: typedoc-github-theme:
specifier: ^0.3.1 specifier: ^0.3.1
version: 0.3.1(typedoc@0.28.8(typescript@5.8.3)) version: 0.3.1(typedoc@0.28.12(typescript@5.8.3))
typedoc-plugin-coverage: typedoc-plugin-coverage:
specifier: ^4.0.1 specifier: ^4.0.1
version: 4.0.1(typedoc@0.28.8(typescript@5.8.3)) version: 4.0.1(typedoc@0.28.12(typescript@5.8.3))
typedoc-plugin-mdn-links: typedoc-plugin-mdn-links:
specifier: ^5.0.9 specifier: ^5.0.9
version: 5.0.9(typedoc@0.28.8(typescript@5.8.3)) version: 5.0.9(typedoc@0.28.12(typescript@5.8.3))
typescript: typescript:
specifier: ^5.8.3 specifier: ^5.8.3
version: 5.8.3 version: 5.8.3
vite: vite:
specifier: ^7.0.6 specifier: ^7.0.6
version: 7.0.6(@types/node@22.16.5)(yaml@2.8.0) version: 7.0.6(@types/node@22.16.5)(yaml@2.8.1)
vite-tsconfig-paths: vite-tsconfig-paths:
specifier: ^5.1.4 specifier: ^5.1.4
version: 5.1.4(typescript@5.8.3)(vite@7.0.6(@types/node@22.16.5)(yaml@2.8.0)) version: 5.1.4(typescript@5.8.3)(vite@7.0.6(@types/node@22.16.5)(yaml@2.8.1))
vitest: vitest:
specifier: ^3.2.4 specifier: ^3.2.4
version: 3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.0) version: 3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.1)
vitest-canvas-mock: vitest-canvas-mock:
specifier: ^0.3.3 specifier: ^0.3.3
version: 0.3.3(vitest@3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.0)) version: 0.3.3(vitest@3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.1))
packages: packages:
@ -441,8 +441,8 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@gerrit0/mini-shiki@3.8.1': '@gerrit0/mini-shiki@3.12.2':
resolution: {integrity: sha512-HVZW+8pxoOExr5ZMPK15U79jQAZTO/S6i5byQyyZGjtNj+qaYd82cizTncwFzTQgiLo8uUBym6vh+/1tfJklTw==} resolution: {integrity: sha512-HKZPmO8OSSAAo20H2B3xgJdxZaLTwtlMwxg0967scnrDlPwe6j5+ULGHyIqwgTbFCn9yv/ff8CmfWZLE9YKBzA==}
'@inquirer/checkbox@4.2.0': '@inquirer/checkbox@4.2.0':
resolution: {integrity: sha512-fdSw07FLJEU5vbpOPzXo5c6xmMGDzbZE2+niuDHX5N6mc6V0Ebso/q3xiHra4D73+PMsC8MJmcaZKuAAoaQsSA==} resolution: {integrity: sha512-fdSw07FLJEU5vbpOPzXo5c6xmMGDzbZE2+niuDHX5N6mc6V0Ebso/q3xiHra4D73+PMsC8MJmcaZKuAAoaQsSA==}
@ -712,17 +712,17 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@shikijs/engine-oniguruma@3.8.1': '@shikijs/engine-oniguruma@3.12.2':
resolution: {integrity: sha512-KGQJZHlNY7c656qPFEQpIoqOuC4LrxjyNndRdzk5WKB/Ie87+NJCF1xo9KkOUxwxylk7rT6nhlZyTGTC4fCe1g==} resolution: {integrity: sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w==}
'@shikijs/langs@3.8.1': '@shikijs/langs@3.12.2':
resolution: {integrity: sha512-TjOFg2Wp1w07oKnXjs0AUMb4kJvujML+fJ1C5cmEj45lhjbUXtziT1x2bPQb9Db6kmPhkG5NI2tgYW1/DzhUuQ==} resolution: {integrity: sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww==}
'@shikijs/themes@3.8.1': '@shikijs/themes@3.12.2':
resolution: {integrity: sha512-Vu3t3BBLifc0GB0UPg2Pox1naTemrrvyZv2lkiSw3QayVV60me1ujFQwPZGgUTmwXl1yhCPW8Lieesm0CYruLQ==} resolution: {integrity: sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A==}
'@shikijs/types@3.8.1': '@shikijs/types@3.12.2':
resolution: {integrity: sha512-5C39Q8/8r1I26suLh+5TPk1DTrbY/kn3IdWA5HdizR0FhlhD05zx5nKCqhzSfDHH3p4S0ZefxWd77DLV+8FhGg==} resolution: {integrity: sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q==}
'@shikijs/vscode-textmate@10.0.2': '@shikijs/vscode-textmate@10.0.2':
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
@ -1818,12 +1818,12 @@ packages:
peerDependencies: peerDependencies:
typedoc: 0.27.x || 0.28.x typedoc: 0.27.x || 0.28.x
typedoc@0.28.8: typedoc@0.28.12:
resolution: {integrity: sha512-16GfLopc8icHfdvqZDqdGBoS2AieIRP2rpf9mU+MgN+gGLyEQvAO0QgOa6NJ5QNmQi0LFrDY9in4F2fUNKgJKA==} resolution: {integrity: sha512-H5ODu4f7N+myG4MfuSp2Vh6wV+WLoZaEYxKPt2y8hmmqNEMVrH69DAjjdmYivF4tP/C2jrIZCZhPalZlTU/ipA==}
engines: {node: '>= 18', pnpm: '>= 10'} engines: {node: '>= 18', pnpm: '>= 10'}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x
typescript@5.8.3: typescript@5.8.3:
resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
@ -2020,8 +2020,8 @@ packages:
yallist@3.1.1: yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
yaml@2.8.0: yaml@2.8.1:
resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==} resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==}
engines: {node: '>= 14.6'} engines: {node: '>= 14.6'}
hasBin: true hasBin: true
@ -2300,12 +2300,12 @@ snapshots:
'@esbuild/win32-x64@0.25.8': '@esbuild/win32-x64@0.25.8':
optional: true optional: true
'@gerrit0/mini-shiki@3.8.1': '@gerrit0/mini-shiki@3.12.2':
dependencies: dependencies:
'@shikijs/engine-oniguruma': 3.8.1 '@shikijs/engine-oniguruma': 3.12.2
'@shikijs/langs': 3.8.1 '@shikijs/langs': 3.12.2
'@shikijs/themes': 3.8.1 '@shikijs/themes': 3.12.2
'@shikijs/types': 3.8.1 '@shikijs/types': 3.12.2
'@shikijs/vscode-textmate': 10.0.2 '@shikijs/vscode-textmate': 10.0.2
'@inquirer/checkbox@4.2.0(@types/node@22.16.5)': '@inquirer/checkbox@4.2.0(@types/node@22.16.5)':
@ -2534,20 +2534,20 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.46.1': '@rollup/rollup-win32-x64-msvc@4.46.1':
optional: true optional: true
'@shikijs/engine-oniguruma@3.8.1': '@shikijs/engine-oniguruma@3.12.2':
dependencies: dependencies:
'@shikijs/types': 3.8.1 '@shikijs/types': 3.12.2
'@shikijs/vscode-textmate': 10.0.2 '@shikijs/vscode-textmate': 10.0.2
'@shikijs/langs@3.8.1': '@shikijs/langs@3.12.2':
dependencies: dependencies:
'@shikijs/types': 3.8.1 '@shikijs/types': 3.12.2
'@shikijs/themes@3.8.1': '@shikijs/themes@3.12.2':
dependencies: dependencies:
'@shikijs/types': 3.8.1 '@shikijs/types': 3.12.2
'@shikijs/types@3.8.1': '@shikijs/types@3.12.2':
dependencies: dependencies:
'@shikijs/vscode-textmate': 10.0.2 '@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4 '@types/hast': 3.0.4
@ -2586,7 +2586,7 @@ snapshots:
'@types/unist@3.0.3': {} '@types/unist@3.0.3': {}
'@vitest/coverage-istanbul@3.2.4(vitest@3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.0))': '@vitest/coverage-istanbul@3.2.4(vitest@3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.1))':
dependencies: dependencies:
'@istanbuljs/schema': 0.1.3 '@istanbuljs/schema': 0.1.3
debug: 4.4.1 debug: 4.4.1
@ -2598,7 +2598,7 @@ snapshots:
magicast: 0.3.5 magicast: 0.3.5
test-exclude: 7.0.1 test-exclude: 7.0.1
tinyrainbow: 2.0.0 tinyrainbow: 2.0.0
vitest: 3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.0) vitest: 3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.1)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -2610,14 +2610,14 @@ snapshots:
chai: 5.2.1 chai: 5.2.1
tinyrainbow: 2.0.0 tinyrainbow: 2.0.0
'@vitest/mocker@3.2.4(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(vite@7.0.6(@types/node@22.16.5)(yaml@2.8.0))': '@vitest/mocker@3.2.4(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(vite@7.0.6(@types/node@22.16.5)(yaml@2.8.1))':
dependencies: dependencies:
'@vitest/spy': 3.2.4 '@vitest/spy': 3.2.4
estree-walker: 3.0.3 estree-walker: 3.0.3
magic-string: 0.30.17 magic-string: 0.30.17
optionalDependencies: optionalDependencies:
msw: 2.10.4(@types/node@22.16.5)(typescript@5.8.3) msw: 2.10.4(@types/node@22.16.5)(typescript@5.8.3)
vite: 7.0.6(@types/node@22.16.5)(yaml@2.8.0) vite: 7.0.6(@types/node@22.16.5)(yaml@2.8.1)
'@vitest/pretty-format@3.2.4': '@vitest/pretty-format@3.2.4':
dependencies: dependencies:
@ -3663,26 +3663,26 @@ snapshots:
type-fest@4.41.0: {} type-fest@4.41.0: {}
typedoc-github-theme@0.3.1(typedoc@0.28.8(typescript@5.8.3)): typedoc-github-theme@0.3.1(typedoc@0.28.12(typescript@5.8.3)):
dependencies: dependencies:
typedoc: 0.28.8(typescript@5.8.3) typedoc: 0.28.12(typescript@5.8.3)
typedoc-plugin-coverage@4.0.1(typedoc@0.28.8(typescript@5.8.3)): typedoc-plugin-coverage@4.0.1(typedoc@0.28.12(typescript@5.8.3)):
dependencies: dependencies:
typedoc: 0.28.8(typescript@5.8.3) typedoc: 0.28.12(typescript@5.8.3)
typedoc-plugin-mdn-links@5.0.9(typedoc@0.28.8(typescript@5.8.3)): typedoc-plugin-mdn-links@5.0.9(typedoc@0.28.12(typescript@5.8.3)):
dependencies: dependencies:
typedoc: 0.28.8(typescript@5.8.3) typedoc: 0.28.12(typescript@5.8.3)
typedoc@0.28.8(typescript@5.8.3): typedoc@0.28.12(typescript@5.8.3):
dependencies: dependencies:
'@gerrit0/mini-shiki': 3.8.1 '@gerrit0/mini-shiki': 3.12.2
lunr: 2.3.9 lunr: 2.3.9
markdown-it: 14.1.0 markdown-it: 14.1.0
minimatch: 9.0.5 minimatch: 9.0.5
typescript: 5.8.3 typescript: 5.8.3
yaml: 2.8.0 yaml: 2.8.1
typescript@5.8.3: {} typescript@5.8.3: {}
@ -3705,13 +3705,13 @@ snapshots:
util-deprecate@1.0.2: {} util-deprecate@1.0.2: {}
vite-node@3.2.4(@types/node@22.16.5)(yaml@2.8.0): vite-node@3.2.4(@types/node@22.16.5)(yaml@2.8.1):
dependencies: dependencies:
cac: 6.7.14 cac: 6.7.14
debug: 4.4.1 debug: 4.4.1
es-module-lexer: 1.7.0 es-module-lexer: 1.7.0
pathe: 2.0.3 pathe: 2.0.3
vite: 7.0.6(@types/node@22.16.5)(yaml@2.8.0) vite: 7.0.6(@types/node@22.16.5)(yaml@2.8.1)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/node' - '@types/node'
- jiti - jiti
@ -3726,18 +3726,18 @@ snapshots:
- tsx - tsx
- yaml - yaml
vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@7.0.6(@types/node@22.16.5)(yaml@2.8.0)): vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@7.0.6(@types/node@22.16.5)(yaml@2.8.1)):
dependencies: dependencies:
debug: 4.4.1 debug: 4.4.1
globrex: 0.1.2 globrex: 0.1.2
tsconfck: 3.1.6(typescript@5.8.3) tsconfck: 3.1.6(typescript@5.8.3)
optionalDependencies: optionalDependencies:
vite: 7.0.6(@types/node@22.16.5)(yaml@2.8.0) vite: 7.0.6(@types/node@22.16.5)(yaml@2.8.1)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
- typescript - typescript
vite@7.0.6(@types/node@22.16.5)(yaml@2.8.0): vite@7.0.6(@types/node@22.16.5)(yaml@2.8.1):
dependencies: dependencies:
esbuild: 0.25.8 esbuild: 0.25.8
fdir: 6.4.6(picomatch@4.0.3) fdir: 6.4.6(picomatch@4.0.3)
@ -3748,18 +3748,18 @@ snapshots:
optionalDependencies: optionalDependencies:
'@types/node': 22.16.5 '@types/node': 22.16.5
fsevents: 2.3.3 fsevents: 2.3.3
yaml: 2.8.0 yaml: 2.8.1
vitest-canvas-mock@0.3.3(vitest@3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.0)): vitest-canvas-mock@0.3.3(vitest@3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.1)):
dependencies: dependencies:
jest-canvas-mock: 2.5.2 jest-canvas-mock: 2.5.2
vitest: 3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.0) vitest: 3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.1)
vitest@3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.0): vitest@3.2.4(@types/node@22.16.5)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(yaml@2.8.1):
dependencies: dependencies:
'@types/chai': 5.2.2 '@types/chai': 5.2.2
'@vitest/expect': 3.2.4 '@vitest/expect': 3.2.4
'@vitest/mocker': 3.2.4(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(vite@7.0.6(@types/node@22.16.5)(yaml@2.8.0)) '@vitest/mocker': 3.2.4(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(vite@7.0.6(@types/node@22.16.5)(yaml@2.8.1))
'@vitest/pretty-format': 3.2.4 '@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4 '@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4 '@vitest/snapshot': 3.2.4
@ -3777,8 +3777,8 @@ snapshots:
tinyglobby: 0.2.14 tinyglobby: 0.2.14
tinypool: 1.1.1 tinypool: 1.1.1
tinyrainbow: 2.0.0 tinyrainbow: 2.0.0
vite: 7.0.6(@types/node@22.16.5)(yaml@2.8.0) vite: 7.0.6(@types/node@22.16.5)(yaml@2.8.1)
vite-node: 3.2.4(@types/node@22.16.5)(yaml@2.8.0) vite-node: 3.2.4(@types/node@22.16.5)(yaml@2.8.1)
why-is-node-running: 2.3.0 why-is-node-running: 2.3.0
optionalDependencies: optionalDependencies:
'@types/node': 22.16.5 '@types/node': 22.16.5
@ -3862,7 +3862,7 @@ snapshots:
yallist@3.1.1: {} yallist@3.1.1: {}
yaml@2.8.0: {} yaml@2.8.1: {}
yargs-parser@21.1.1: {} yargs-parser@21.1.1: {}

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

@ -1 +1 @@
Subproject commit 090bfefaf7e9d4efcbca61fa78a9cdf5d701830b Subproject commit 74de730a64272c8e9ca0a4cdcf3426cbf1b0aeda

View File

@ -1,7 +1,10 @@
import { AbilityId } from "#enums/ability-id"; import { AbilityId } from "#enums/ability-id";
import { BattlerIndex } from "#enums/battler-index";
import { MoveId } from "#enums/move-id"; import { MoveId } from "#enums/move-id";
import { MoveResult } from "#enums/move-result";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { GameManager } from "#test/test-utils/game-manager"; import { GameManager } from "#test/test-utils/game-manager";
import i18next from "i18next";
import Phaser from "phaser"; import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
@ -32,12 +35,18 @@ describe("{{description}}", () => {
.enemyLevel(100); .enemyLevel(100);
}); });
// Find more awesome utility functions inside `#test/test-utils`!
it("should do XYZ", async () => { it("should do XYZ", async () => {
await game.classicMode.startBattle([SpeciesId.FEEBAS]); await game.classicMode.startBattle([SpeciesId.FEEBAS]);
const feebas = game.field.getPlayerPokemon();
game.move.use(MoveId.SPLASH); game.move.use(MoveId.SPLASH);
await game.move.forceEnemyMove(MoveId.CELEBRATE);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
await game.toEndOfTurn(); await game.toEndOfTurn();
expect(true).toBe(true); expect(feebas).toHaveUsedMove({ move: MoveId.SPLASH, result: MoveResult.SUCCESS });
expect(game.textInterceptor.logs).toContain(i18next.t("moveTriggers:splash"));
}); });
}); });

View File

@ -1,4 +1,4 @@
import type { SessionSaveData, SystemSaveData } from "#system/game-data"; import type { SessionSaveData, SystemSaveData } from "#types/save-data";
export interface UpdateAllSavedataRequest { export interface UpdateAllSavedataRequest {
system: SystemSaveData; system: SystemSaveData;

View File

@ -1,4 +1,4 @@
import type { SystemSaveData } from "#system/game-data"; import type { SystemSaveData } from "#types/save-data";
export interface GetSystemSavedataRequest { export interface GetSystemSavedataRequest {
clientSessionId: string; clientSessionId: string;

View File

@ -1,7 +1,7 @@
import type { ArenaTagTypeMap } from "#data/arena-tag"; import type { ArenaTagTypeMap } from "#data/arena-tag";
import type { ArenaTagType } from "#enums/arena-tag-type"; import type { ArenaTagType } from "#enums/arena-tag-type";
// biome-ignore lint/correctness/noUnusedImports: TSDocs // biome-ignore lint/correctness/noUnusedImports: TSDocs
import type { SessionSaveData } from "#system/game-data"; import type { SessionSaveData } from "#types/save-data";
import type { ObjectValues } from "#types/type-helpers"; 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. */ /** 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. */
@ -38,6 +38,7 @@ type SerializableArenaTagTypeMap = Pick<ArenaTagTypeMap, SerializableArenaTagTyp
/** /**
* Type mapping all `ArenaTag`s to type-safe representations of their serialized forms. * Type mapping all `ArenaTag`s to type-safe representations of their serialized forms.
*
* @interface * @interface
*/ */
export type ArenaTagDataMap = { export type ArenaTagDataMap = {

View File

@ -1,7 +1,7 @@
// biome-ignore-start lint/correctness/noUnusedImports: Used in a TSDoc comment // biome-ignore-start lint/correctness/noUnusedImports: Used in a TSDoc comment
import type { AbilityBattlerTag, BattlerTagTypeMap, SerializableBattlerTag, TypeBoostTag } from "#data/battler-tags"; import type { AbilityBattlerTag, BattlerTagTypeMap, SerializableBattlerTag, TypeBoostTag } from "#data/battler-tags";
import type { AbilityId } from "#enums/ability-id"; import type { AbilityId } from "#enums/ability-id";
import type { SessionSaveData } from "#system/game-data"; import type { SessionSaveData } from "#types/save-data";
// biome-ignore-end lint/correctness/noUnusedImports: Used in a TSDoc comment // biome-ignore-end lint/correctness/noUnusedImports: Used in a TSDoc comment
import type { BattlerTagType } from "#enums/battler-tag-type"; import type { BattlerTagType } from "#enums/battler-tag-type";

143
src/@types/save-data.ts Normal file
View File

@ -0,0 +1,143 @@
import type { PokeballCounts } from "#app/battle-scene";
import type { Tutorial } from "#app/tutorial";
import type { BattleType } from "#enums/battle-type";
import type { GameModes } from "#enums/game-modes";
import type { MoveId } from "#enums/move-id";
import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
import type { PlayerGender } from "#enums/player-gender";
import type { PokemonType } from "#enums/pokemon-type";
import type { MysteryEncounterSaveData } from "#mystery-encounters/mystery-encounter-save-data";
import type { Variant } from "#sprites/variant";
import type { ArenaData } from "#system/arena-data";
import type { ChallengeData } from "#system/challenge-data";
import type { EggData } from "#system/egg-data";
import type { GameStats } from "#system/game-stats";
import type { ModifierData } from "#system/modifier-data";
import type { PokemonData } from "#system/pokemon-data";
import type { TrainerData } from "#system/trainer-data";
import type { DexData } from "./dex-data";
export interface SystemSaveData {
trainerId: number;
secretId: number;
gender: PlayerGender;
dexData: DexData;
starterData: StarterData;
gameStats: GameStats;
unlocks: Unlocks;
achvUnlocks: AchvUnlocks;
voucherUnlocks: VoucherUnlocks;
voucherCounts: VoucherCounts;
eggs: EggData[];
gameVersion: string;
timestamp: number;
eggPity: number[];
unlockPity: number[];
}
export interface SessionSaveData {
seed: string;
playTime: number;
gameMode: GameModes;
party: PokemonData[];
enemyParty: PokemonData[];
modifiers: ModifierData[];
enemyModifiers: ModifierData[];
arena: ArenaData;
pokeballCounts: PokeballCounts;
money: number;
score: number;
waveIndex: number;
battleType: BattleType;
trainer: TrainerData;
gameVersion: string;
/** The player-chosen name of the run */
name: string;
timestamp: number;
challenges: ChallengeData[];
mysteryEncounterType: MysteryEncounterType | -1; // Only defined when current wave is ME,
mysteryEncounterSaveData: MysteryEncounterSaveData;
/**
* Counts the amount of pokemon fainted in your party during the current arena encounter.
*/
playerFaints: number;
}
export interface Unlocks {
[key: number]: boolean;
}
export interface AchvUnlocks {
[key: string]: number;
}
export interface VoucherUnlocks {
[key: string]: number;
}
export interface VoucherCounts {
[type: string]: number;
}
export type StarterMoveset = [MoveId] | [MoveId, MoveId] | [MoveId, MoveId, MoveId] | [MoveId, MoveId, MoveId, MoveId];
export interface StarterFormMoveData {
[key: number]: StarterMoveset;
}
export interface StarterMoveData {
[key: number]: StarterMoveset | StarterFormMoveData;
}
export interface StarterAttributes {
nature?: number;
ability?: number;
variant?: number;
form?: number;
female?: boolean;
shiny?: boolean;
favorite?: boolean;
nickname?: string;
tera?: PokemonType;
}
export interface DexAttrProps {
shiny: boolean;
female: boolean;
variant: Variant;
formIndex: number;
}
export type RunHistoryData = Record<number, RunEntry>;
export interface RunEntry {
entry: SessionSaveData;
isVictory: boolean;
/*Automatically set to false at the moment - implementation TBD*/
isFavorite: boolean;
}
export interface StarterDataEntry {
moveset: StarterMoveset | StarterFormMoveData | null;
eggMoves: number;
candyCount: number;
friendship: number;
abilityAttr: number;
passiveAttr: number;
valueReduction: number;
classicWinCount: number;
}
export interface StarterData {
[key: number]: StarterDataEntry;
}
// TODO: Rework into a bitmask
export type TutorialFlags = {
[key in Tutorial]: boolean;
};
// TODO: Rework into a bitmask
export interface SeenDialogues {
[key: string]: boolean;
}

View File

@ -1,4 +1,4 @@
import type { SessionSaveData } from "#system/game-data"; import type { SessionSaveData } from "./save-data";
export interface SessionSaveMigrator { export interface SessionSaveMigrator {
version: string; version: string;

View File

@ -1,4 +1,4 @@
import type { SystemSaveData } from "#system/game-data"; import type { SystemSaveData } from "./save-data";
export interface SystemSaveMigrator { export interface SystemSaveMigrator {
version: string; version: string;

View File

@ -3108,7 +3108,7 @@ export class BattleScene extends SceneBase {
* Apply all modifiers that match `modifierType` in a random order * Apply all modifiers that match `modifierType` in a random order
* @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier} * @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier}
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true` * @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
* @param ...args The list of arguments needed to invoke `modifierType.apply` * @param args The list of arguments needed to invoke `modifierType.apply`
* @returns the list of all modifiers that matched `modifierType` and were applied. * @returns the list of all modifiers that matched `modifierType` and were applied.
*/ */
applyShuffledModifiers<T extends PersistentModifier>( applyShuffledModifiers<T extends PersistentModifier>(
@ -3140,7 +3140,7 @@ export class BattleScene extends SceneBase {
* Apply all modifiers that match `modifierType` * Apply all modifiers that match `modifierType`
* @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier} * @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier}
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true` * @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
* @param ...args The list of arguments needed to invoke `modifierType.apply` * @param args The list of arguments needed to invoke `modifierType.apply`
* @returns the list of all modifiers that matched `modifierType` and were applied. * @returns the list of all modifiers that matched `modifierType` and were applied.
*/ */
applyModifiers<T extends PersistentModifier>( applyModifiers<T extends PersistentModifier>(
@ -3175,7 +3175,7 @@ export class BattleScene extends SceneBase {
* Apply the first modifier that matches `modifierType` * Apply the first modifier that matches `modifierType`
* @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier} * @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier}
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true` * @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
* @param ...args The list of arguments needed to invoke `modifierType.apply` * @param args The list of arguments needed to invoke `modifierType.apply`
* @returns the first modifier that matches `modifierType` and was applied; return `null` if none matched * @returns the first modifier that matches `modifierType` and was applied; return `null` if none matched
*/ */
applyModifier<T extends PersistentModifier>( applyModifier<T extends PersistentModifier>(
@ -3323,7 +3323,7 @@ export class BattleScene extends SceneBase {
/** /**
* This function retrieves the sprite and audio keys for active Pokemon. * This function retrieves the sprite and audio keys for active Pokemon.
* Active Pokemon include both enemy and player Pokemon of the current wave. * Active Pokemon include both enemy and player Pokemon of the current wave.
* Note: Questions on garbage collection go to @frutescens * Note: Questions on garbage collection go to `@frutescens`
* @returns a string array of active sprite and audio keys that should not be deleted * @returns a string array of active sprite and audio keys that should not be deleted
*/ */
getActiveKeys(): string[] { getActiveKeys(): string[] {

View File

@ -507,7 +507,7 @@ export class ClearWeatherAbAttr extends AbAttr {
private weather: WeatherType[]; private weather: WeatherType[];
/** /**
* @param weather {@linkcode WeatherType[]} - the weather to be removed * @param weather - The weather to be removed
*/ */
constructor(weather: WeatherType[]) { constructor(weather: WeatherType[]) {
super(true); super(true);
@ -537,7 +537,7 @@ export class ClearTerrainAbAttr extends AbAttr {
private terrain: TerrainType[]; private terrain: TerrainType[];
/** /**
* @param terrain {@linkcode TerrainType[]} - the terrain to be removed * @param terrain - the terrain to be removed
*/ */
constructor(terrain: TerrainType[]) { constructor(terrain: TerrainType[]) {
super(true); super(true);
@ -655,7 +655,6 @@ export class ReceivedMoveDamageMultiplierAbAttr extends PreDefendAbAttr {
/** /**
* Reduces the damage dealt to an allied Pokemon. Used by Friend Guard. * Reduces the damage dealt to an allied Pokemon. Used by Friend Guard.
* @see {@linkcode applyPreDefend}
*/ */
export class AlliedFieldDamageReductionAbAttr extends PreDefendAbAttr { export class AlliedFieldDamageReductionAbAttr extends PreDefendAbAttr {
private damageMultiplier: number; private damageMultiplier: number;
@ -691,8 +690,6 @@ export interface TypeMultiplierAbAttrParams extends AugmentMoveInteractionAbAttr
/** /**
* Determines whether a Pokemon is immune to a move because of an ability. * Determines whether a Pokemon is immune to a move because of an ability.
* @see {@linkcode applyPreDefend}
* @see {@linkcode getCondition}
*/ */
export class TypeImmunityAbAttr extends PreDefendAbAttr { export class TypeImmunityAbAttr extends PreDefendAbAttr {
private immuneType: PokemonType | null; private immuneType: PokemonType | null;
@ -842,7 +839,6 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr {
/** /**
* Attribute implementing the effects of {@link https://bulbapedia.bulbagarden.net/wiki/Tera_Shell_(Ability) | Tera Shell} * Attribute implementing the effects of {@link https://bulbapedia.bulbagarden.net/wiki/Tera_Shell_(Ability) | Tera Shell}
* When the source is at full HP, incoming attacks will have a maximum 0.5x type effectiveness multiplier. * When the source is at full HP, incoming attacks will have a maximum 0.5x type effectiveness multiplier.
* @extends PreDefendAbAttr
*/ */
export class FullHpResistTypeAbAttr extends PreDefendAbAttr { export class FullHpResistTypeAbAttr extends PreDefendAbAttr {
/** /**
@ -1351,11 +1347,9 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr {
} }
} }
/** /**
* @description: This ability applies the Perish Song tag to the attacking pokemon * This ability applies the Perish Song tag to the attacking pokemon
* and the defending pokemon if the move makes physical contact and neither pokemon * and the defending pokemon if the move makes physical contact and neither pokemon
* already has the Perish Song tag. * already has the Perish Song tag.
* @class PostDefendPerishSongAbAttr
* @extends {PostDefendAbAttr}
*/ */
export class PostDefendPerishSongAbAttr extends PostDefendAbAttr { export class PostDefendPerishSongAbAttr extends PostDefendAbAttr {
private turns: number; private turns: number;
@ -1961,19 +1955,16 @@ export class PreAttackFieldMoveTypePowerBoostAbAttr extends FieldMovePowerBoostA
/** /**
* Boosts the power of a specific type of move for all Pokemon in the field. * Boosts the power of a specific type of move for all Pokemon in the field.
* @extends PreAttackFieldMoveTypePowerBoostAbAttr
*/ */
export class FieldMoveTypePowerBoostAbAttr extends PreAttackFieldMoveTypePowerBoostAbAttr {} export class FieldMoveTypePowerBoostAbAttr extends PreAttackFieldMoveTypePowerBoostAbAttr {}
/** /**
* Boosts the power of a specific type of move for the user and its allies. * Boosts the power of a specific type of move for the user and its allies.
* @extends PreAttackFieldMoveTypePowerBoostAbAttr
*/ */
export class UserFieldMoveTypePowerBoostAbAttr extends PreAttackFieldMoveTypePowerBoostAbAttr {} export class UserFieldMoveTypePowerBoostAbAttr extends PreAttackFieldMoveTypePowerBoostAbAttr {}
/** /**
* Boosts the power of moves in specified categories. * Boosts the power of moves in specified categories.
* @extends FieldMovePowerBoostAbAttr
*/ */
export class AllyMoveCategoryPowerBoostAbAttr extends FieldMovePowerBoostAbAttr { export class AllyMoveCategoryPowerBoostAbAttr extends FieldMovePowerBoostAbAttr {
/** /**
@ -2579,7 +2570,6 @@ export class PostIntimidateStatStageChangeAbAttr extends AbAttr {
/** /**
* Base class for defining all {@linkcode Ability} Attributes post summon * Base class for defining all {@linkcode Ability} Attributes post summon
* @see {@linkcode applyPostSummon()}
*/ */
export abstract class PostSummonAbAttr extends AbAttr { export abstract class PostSummonAbAttr extends AbAttr {
/** Should the ability activate when gained in battle? This will almost always be true */ /** Should the ability activate when gained in battle? This will almost always be true */
@ -2619,7 +2609,7 @@ export class PostSummonRemoveArenaTagAbAttr extends PostSummonAbAttr {
private arenaTags: ArenaTagType[]; private arenaTags: ArenaTagType[];
/** /**
* @param arenaTags {@linkcode ArenaTagType[]} - the arena tags to be removed * @param arenaTags - The arena tags to be removed
*/ */
constructor(arenaTags: ArenaTagType[]) { constructor(arenaTags: ArenaTagType[]) {
super(true); super(true);
@ -3180,7 +3170,6 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr {
/** /**
* Reverts weather-based forms to their normal forms when the user is summoned. * Reverts weather-based forms to their normal forms when the user is summoned.
* Used by Cloud Nine and Air Lock. * Used by Cloud Nine and Air Lock.
* @extends PostSummonAbAttr
*/ */
export class PostSummonWeatherSuppressedFormChangeAbAttr extends PostSummonAbAttr { export class PostSummonWeatherSuppressedFormChangeAbAttr extends PostSummonAbAttr {
override canApply(_params: AbAttrBaseParams): boolean { override canApply(_params: AbAttrBaseParams): boolean {
@ -3200,7 +3189,6 @@ export class PostSummonWeatherSuppressedFormChangeAbAttr extends PostSummonAbAtt
/** /**
* Triggers weather-based form change when summoned into an active weather. * Triggers weather-based form change when summoned into an active weather.
* Used by Forecast and Flower Gift. * Used by Forecast and Flower Gift.
* @extends PostSummonAbAttr
*/ */
export class PostSummonFormChangeByWeatherAbAttr extends PostSummonAbAttr { export class PostSummonFormChangeByWeatherAbAttr extends PostSummonAbAttr {
private ability: AbilityId; private ability: AbilityId;
@ -3382,7 +3370,6 @@ export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr {
/** /**
* Attribute for form changes that occur on switching out * Attribute for form changes that occur on switching out
* @see {@linkcode applyPreSwitchOut}
*/ */
export class PreSwitchOutFormChangeAbAttr extends PreSwitchOutAbAttr { export class PreSwitchOutFormChangeAbAttr extends PreSwitchOutAbAttr {
private formFunc: (p: Pokemon) => number; private formFunc: (p: Pokemon) => number;
@ -4249,8 +4236,8 @@ function getAnticipationCondition(): AbAttrCondition {
* Creates an ability condition that causes the ability to fail if that ability * Creates an ability condition that causes the ability to fail if that ability
* has already been used by that pokemon that battle. It requires an ability to * has already been used by that pokemon that battle. It requires an ability to
* be specified due to current limitations in how conditions on abilities work. * be specified due to current limitations in how conditions on abilities work.
* @param {AbilityId} ability The ability to check if it's already been applied * @param ability The ability to check if it's already been applied
* @returns {AbAttrCondition} The condition * @returns The condition
*/ */
function getOncePerBattleCondition(ability: AbilityId): AbAttrCondition { function getOncePerBattleCondition(ability: AbilityId): AbAttrCondition {
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
@ -4641,7 +4628,7 @@ export class PostTurnRestoreBerryAbAttr extends PostTurnAbAttr {
/** /**
* @param procChance - function providing chance to restore an item * @param procChance - function providing chance to restore an item
* @see {@linkcode createEatenBerry()} * @see {@linkcode createEatenBerry}
*/ */
constructor(private procChance: (pokemon: Pokemon) => number) { constructor(private procChance: (pokemon: Pokemon) => number) {
super(); super();
@ -4906,7 +4893,6 @@ export class PostTurnHurtIfSleepingAbAttr extends PostTurnAbAttr {
/** /**
* Grabs the last failed Pokeball used * Grabs the last failed Pokeball used
* @sealed * @sealed
* @see {@linkcode applyPostTurn}
*/ */
export class FetchBallAbAttr extends PostTurnAbAttr { export class FetchBallAbAttr extends PostTurnAbAttr {
override canApply({ simulated, pokemon }: AbAttrBaseParams): boolean { override canApply({ simulated, pokemon }: AbAttrBaseParams): boolean {
@ -4996,7 +4982,6 @@ export class PostMoveUsedAbAttr extends AbAttr {
/** /**
* Triggers after a dance move is used either by the opponent or the player * Triggers after a dance move is used either by the opponent or the player
* @extends PostMoveUsedAbAttr
*/ */
export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr { export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
override canApply({ source, pokemon }: PostMoveUsedAbAttrParams): boolean { override canApply({ source, pokemon }: PostMoveUsedAbAttrParams): boolean {
@ -5055,7 +5040,6 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
/** /**
* Triggers after the Pokemon loses or consumes an item * Triggers after the Pokemon loses or consumes an item
* @extends AbAttr
*/ */
export class PostItemLostAbAttr extends AbAttr { export class PostItemLostAbAttr extends AbAttr {
canApply(_params: Closed<AbAttrBaseParams>): boolean { canApply(_params: Closed<AbAttrBaseParams>): boolean {
@ -5226,7 +5210,6 @@ type ArenaTrapCondition = (user: Pokemon, target: Pokemon) => boolean;
/** /**
* Base class for checking if a Pokemon is trapped by arena trap * Base class for checking if a Pokemon is trapped by arena trap
* @extends AbAttr
* @field {@linkcode arenaTrapCondition} Conditional for trapping abilities. * @field {@linkcode arenaTrapCondition} Conditional for trapping abilities.
* For example, Magnet Pull will only activate if opponent is Steel type. * For example, Magnet Pull will only activate if opponent is Steel type.
* @see {@linkcode applyCheckTrapped} * @see {@linkcode applyCheckTrapped}
@ -5562,7 +5545,6 @@ export interface ReduceStatusEffectDurationAbAttrParams extends AbAttrBaseParams
/** /**
* Used by Early Bird, makes the pokemon wake up faster * Used by Early Bird, makes the pokemon wake up faster
* @param statusEffect - The {@linkcode StatusEffect} to check for * @param statusEffect - The {@linkcode StatusEffect} to check for
* @see {@linkcode apply}
* @sealed * @sealed
*/ */
export class ReduceStatusEffectDurationAbAttr extends AbAttr { export class ReduceStatusEffectDurationAbAttr extends AbAttr {
@ -5849,8 +5831,6 @@ export class IgnoreTypeStatusEffectImmunityAbAttr extends AbAttr {
/** /**
* Gives money to the user after the battle. * Gives money to the user after the battle.
*
* @extends PostBattleAbAttr
*/ */
export class MoneyAbAttr extends PostBattleAbAttr { export class MoneyAbAttr extends PostBattleAbAttr {
override canApply({ simulated, victory }: PostBattleAbAttrParams): boolean { override canApply({ simulated, victory }: PostBattleAbAttrParams): boolean {
@ -5954,7 +5934,6 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
/** /**
* Base class for defining {@linkcode Ability} attributes before summon * Base class for defining {@linkcode Ability} attributes before summon
* (should use {@linkcode PostSummonAbAttr} for most ability) * (should use {@linkcode PostSummonAbAttr} for most ability)
* @see {@linkcode applyPreSummon()}
*/ */
export class PreSummonAbAttr extends AbAttr { export class PreSummonAbAttr extends AbAttr {
private declare readonly _: never; private declare readonly _: never;
@ -6406,8 +6385,6 @@ export class PostDamageAbAttr extends AbAttr {
* and its opponents, and determines whether a forced switch-out should occur. * and its opponents, and determines whether a forced switch-out should occur.
* *
* Used by Wimp Out and Emergency Exit * Used by Wimp Out and Emergency Exit
*
* @see {@linkcode applyPostDamage}
* @sealed * @sealed
*/ */
export class PostDamageForceSwitchAbAttr extends PostDamageAbAttr { export class PostDamageForceSwitchAbAttr extends PostDamageAbAttr {
@ -7026,6 +7003,7 @@ export function initAbilities() {
.attr(StatMultiplierAbAttr, Stat.SPATK, 1.5) .attr(StatMultiplierAbAttr, Stat.SPATK, 1.5)
.condition(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)), .condition(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)),
new Ability(AbilityId.QUICK_FEET, 4) new Ability(AbilityId.QUICK_FEET, 4)
// TODO: This should ignore the speed drop, not manually undo it
.conditionalAttr(pokemon => pokemon.status ? pokemon.status.effect === StatusEffect.PARALYSIS : false, StatMultiplierAbAttr, Stat.SPD, 2) .conditionalAttr(pokemon => pokemon.status ? pokemon.status.effect === StatusEffect.PARALYSIS : false, StatMultiplierAbAttr, Stat.SPD, 2)
.conditionalAttr(pokemon => !!pokemon.status || pokemon.hasAbility(AbilityId.COMATOSE), StatMultiplierAbAttr, Stat.SPD, 1.5), .conditionalAttr(pokemon => !!pokemon.status || pokemon.hasAbility(AbilityId.COMATOSE), StatMultiplierAbAttr, Stat.SPD, 1.5),
new Ability(AbilityId.NORMALIZE, 4) new Ability(AbilityId.NORMALIZE, 4)

View File

@ -1132,7 +1132,7 @@ class ImprisonTag extends EntryHazardTag {
/** /**
* This applies the effects of Imprison to any opposing Pokemon that switch into the field while the source Pokemon is still active * This applies the effects of Imprison to any opposing Pokemon that switch into the field while the source Pokemon is still active
* @param {Pokemon} pokemon the Pokemon Imprison is applied to * @param pokemon the Pokemon Imprison is applied to
* @returns `true` * @returns `true`
*/ */
override activateTrap(pokemon: Pokemon): boolean { override activateTrap(pokemon: Pokemon): boolean {

View File

@ -2159,7 +2159,7 @@ export class HighestStatBoostTag extends AbilityBattlerTag {
null, null,
false, false,
null, null,
true, false,
); );
} }
@ -2474,10 +2474,7 @@ export class RemovedTypeTag extends SerializableBattlerTag {
} }
} }
/** /** Battler tag for effects that ground the source, allowing Ground-type moves to hit them. */
* Battler tag for effects that ground the source, allowing Ground-type moves to hit them.
* @description `IGNORE_FLYING`: Persistent grounding effects (i.e. from Smack Down and Thousand Waves)
*/
export class GroundedTag extends SerializableBattlerTag { export class GroundedTag extends SerializableBattlerTag {
public override readonly tagType = BattlerTagType.IGNORE_FLYING; public override readonly tagType = BattlerTagType.IGNORE_FLYING;
constructor(tagType: BattlerTagType.IGNORE_FLYING, lapseType: BattlerTagLapseType, sourceMove: MoveId) { constructor(tagType: BattlerTagType.IGNORE_FLYING, lapseType: BattlerTagLapseType, sourceMove: MoveId) {
@ -2485,11 +2482,7 @@ export class GroundedTag extends SerializableBattlerTag {
} }
} }
/** /** Removes flying type from a pokemon for a single turn */
* @description `ROOSTED`: Tag for temporary grounding if only source of ungrounding is flying and pokemon uses Roost.
* Roost removes flying type from a pokemon for a single turn.
*/
export class RoostedTag extends BattlerTag { export class RoostedTag extends BattlerTag {
private isBaseFlying: boolean; private isBaseFlying: boolean;
private isBasePureFlying: boolean; private isBasePureFlying: boolean;
@ -2568,7 +2561,7 @@ export class FormBlockDamageTag extends SerializableBattlerTag {
/** /**
* Applies the tag to the Pokémon. * Applies the tag to the Pokémon.
* Triggers a form change if the Pokémon is not in its defense form. * Triggers a form change if the Pokémon is not in its defense form.
* @param {Pokemon} pokemon The Pokémon to which the tag is added. * @param pokemon The Pokémon to which the tag is added.
*/ */
onAdd(pokemon: Pokemon): void { onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon); super.onAdd(pokemon);

View File

@ -23,9 +23,10 @@ import type { EnemyPokemon, PlayerPokemon, Pokemon } from "#field/pokemon";
import { Trainer } from "#field/trainer"; import { Trainer } from "#field/trainer";
import type { ModifierTypeOption } from "#modifiers/modifier-type"; import type { ModifierTypeOption } from "#modifiers/modifier-type";
import { PokemonMove } from "#moves/pokemon-move"; import { PokemonMove } from "#moves/pokemon-move";
import type { DexAttrProps, GameData, StarterDataEntry } from "#system/game-data"; import type { GameData } from "#system/game-data";
import { RibbonData, type RibbonFlag } from "#system/ribbons/ribbon-data"; import { RibbonData, type RibbonFlag } from "#system/ribbons/ribbon-data";
import type { DexEntry } from "#types/dex-data"; import type { DexEntry } from "#types/dex-data";
import type { DexAttrProps, StarterDataEntry } from "#types/save-data";
import { type BooleanHolder, isBetween, type NumberHolder, randSeedItem } from "#utils/common"; import { type BooleanHolder, isBetween, type NumberHolder, randSeedItem } from "#utils/common";
import { deepCopy } from "#utils/data"; import { deepCopy } from "#utils/data";
import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils"; import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils";
@ -58,7 +59,7 @@ export abstract class Challenge {
} }
/** /**
* @param id {@link Challenges} The enum value for the challenge * @param id - The enum value for the challenge
*/ */
constructor(id: Challenges, maxValue: number = Number.MAX_SAFE_INTEGER) { constructor(id: Challenges, maxValue: number = Number.MAX_SAFE_INTEGER) {
this.id = id; this.id = id;
@ -87,9 +88,9 @@ export abstract class Challenge {
} }
/** /**
* Used for unlockable challenges to check if they're unlocked. * Check if an unlockable challenge is unlocked
* @param data {@link GameData} The save data. * @param data - The save data
* @returns {@link boolean} Whether this challenge is unlocked. * @returns Whether this challenge is unlocked
*/ */
isUnlocked(data: GameData): boolean { isUnlocked(data: GameData): boolean {
return this.conditions.every(f => f(data)); return this.conditions.every(f => f(data));
@ -97,8 +98,8 @@ export abstract class Challenge {
/** /**
* Adds an unlock condition to this challenge. * Adds an unlock condition to this challenge.
* @param condition {@link ChallengeCondition} The condition to add. * @param condition - The condition to add
* @returns {@link Challenge} This challenge * @returns This challenge
*/ */
condition(condition: ChallengeCondition): Challenge { condition(condition: ChallengeCondition): Challenge {
this.conditions.push(condition); this.conditions.push(condition);
@ -107,7 +108,7 @@ export abstract class Challenge {
} }
/** /**
* @returns {@link string} The localised name of this challenge. * @returns The localised name of this challenge.
*/ */
getName(): string { getName(): string {
return i18next.t(`challenges:${this.geti18nKey()}.name`); return i18next.t(`challenges:${this.geti18nKey()}.name`);
@ -134,7 +135,7 @@ export abstract class Challenge {
/** /**
* Increase the value of the challenge * Increase the value of the challenge
* @returns {@link boolean} Returns true if the value changed * @returns Returns true if the value changed
*/ */
increaseValue(): boolean { increaseValue(): boolean {
if (this.value < this.maxValue) { if (this.value < this.maxValue) {
@ -146,7 +147,7 @@ export abstract class Challenge {
/** /**
* Decrease the value of the challenge * Decrease the value of the challenge
* @returns {@link boolean} Returns true if the value changed * @returns Returns true if the value changed
*/ */
decreaseValue(): boolean { decreaseValue(): boolean {
if (this.value > 0) { if (this.value > 0) {
@ -165,7 +166,7 @@ export abstract class Challenge {
/** /**
* Decrease the severity of the challenge * Decrease the severity of the challenge
* @returns {@link boolean} Returns true if the value changed * @returns Returns true if the value changed
*/ */
decreaseSeverity(): boolean { decreaseSeverity(): boolean {
if (this.severity > 0) { if (this.severity > 0) {
@ -177,7 +178,7 @@ export abstract class Challenge {
/** /**
* Increase the severity of the challenge * Increase the severity of the challenge
* @returns {@link boolean} Returns true if the value changed * @returns Returns true if the value changed
*/ */
increaseSeverity(): boolean { increaseSeverity(): boolean {
if (this.severity < this.maxSeverity) { if (this.severity < this.maxSeverity) {
@ -189,7 +190,7 @@ export abstract class Challenge {
/** /**
* Gets the "difficulty" value of this challenge. * Gets the "difficulty" value of this challenge.
* @returns {@link integer} The difficulty value. * @returns The difficulty value.
*/ */
getDifficulty(): number { getDifficulty(): number {
return this.value; return this.value;
@ -197,7 +198,7 @@ export abstract class Challenge {
/** /**
* Gets the minimum difficulty added by this challenge. * Gets the minimum difficulty added by this challenge.
* @returns {@link integer} The difficulty value. * @returns The difficulty value.
*/ */
getMinDifficulty(): number { getMinDifficulty(): number {
return 0; return 0;
@ -205,7 +206,7 @@ export abstract class Challenge {
/** /**
* Clones a challenge, either from another challenge or json. Chainable. * Clones a challenge, either from another challenge or json. Chainable.
* @param source The source challenge or json. * @param _source - The source challenge or json.
* @returns This challenge. * @returns This challenge.
*/ */
static loadChallenge(_source: Challenge | any): Challenge { static loadChallenge(_source: Challenge | any): Challenge {
@ -214,10 +215,10 @@ export abstract class Challenge {
/** /**
* An apply function for STARTER_CHOICE challenges. Derived classes should alter this. * An apply function for STARTER_CHOICE challenges. Derived classes should alter this.
* @param _pokemon {@link PokemonSpecies} The pokemon to check the validity of. * @param _pokemon - The Pokémon to check the validity of
* @param _valid {@link BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed. * @param _valid - Holder for whether the Pokémon is valid or not
* @param _dexAttr {@link DexAttrProps} The dex attributes of the pokemon. * @param _dexAttr - The dex attributes of the Pokémon
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything.
*/ */
applyStarterChoice(_pokemon: PokemonSpecies, _valid: BooleanHolder, _dexAttr: DexAttrProps): boolean { applyStarterChoice(_pokemon: PokemonSpecies, _valid: BooleanHolder, _dexAttr: DexAttrProps): boolean {
return false; return false;
@ -225,8 +226,8 @@ export abstract class Challenge {
/** /**
* An apply function for STARTER_POINTS challenges. Derived classes should alter this. * An apply function for STARTER_POINTS challenges. Derived classes should alter this.
* @param _points {@link NumberHolder} The amount of points you have available. * @param _points - Holder for amount of starter points the user has to spend
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything
*/ */
applyStarterPoints(_points: NumberHolder): boolean { applyStarterPoints(_points: NumberHolder): boolean {
return false; return false;
@ -234,9 +235,9 @@ export abstract class Challenge {
/** /**
* An apply function for STARTER_COST challenges. Derived classes should alter this. * An apply function for STARTER_COST challenges. Derived classes should alter this.
* @param _species {@link SpeciesId} The pokemon to change the cost of. * @param _species - The pokémon to change the cost of
* @param _cost {@link NumberHolder} The cost of the starter. * @param _cost - Holder for the cost of the starter Pokémon
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything.
*/ */
applyStarterCost(_species: SpeciesId, _cost: NumberHolder): boolean { applyStarterCost(_species: SpeciesId, _cost: NumberHolder): boolean {
return false; return false;
@ -244,8 +245,8 @@ export abstract class Challenge {
/** /**
* An apply function for STARTER_SELECT_MODIFY challenges. Derived classes should alter this. * An apply function for STARTER_SELECT_MODIFY challenges. Derived classes should alter this.
* @param _pokemon {@link Pokemon} The starter pokemon to modify. * @param _pokemon - The starter Pokémon to modify.
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything.
*/ */
applyStarterSelectModify(_speciesId: SpeciesId, _dexEntry: DexEntry, _starterDataEntry: StarterDataEntry): boolean { applyStarterSelectModify(_speciesId: SpeciesId, _dexEntry: DexEntry, _starterDataEntry: StarterDataEntry): boolean {
return false; return false;
@ -253,8 +254,8 @@ export abstract class Challenge {
/** /**
* An apply function for STARTER_MODIFY challenges. Derived classes should alter this. * An apply function for STARTER_MODIFY challenges. Derived classes should alter this.
* @param _pokemon {@link Pokemon} The starter pokemon to modify. * @param _pokemon - The starter Pokémon to modify.
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything.
*/ */
applyStarterModify(_pokemon: Pokemon): boolean { applyStarterModify(_pokemon: Pokemon): boolean {
return false; return false;
@ -262,9 +263,9 @@ export abstract class Challenge {
/** /**
* An apply function for POKEMON_IN_BATTLE challenges. Derived classes should alter this. * An apply function for POKEMON_IN_BATTLE challenges. Derived classes should alter this.
* @param _pokemon {@link Pokemon} The pokemon to check the validity of. * @param _pokemon - The Pokémon to check the validity of
* @param _valid {@link BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed. * @param _valid - Holds a boolean that will be set to false if the Pokémon isn't allowed
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything
*/ */
applyPokemonInBattle(_pokemon: Pokemon, _valid: BooleanHolder): boolean { applyPokemonInBattle(_pokemon: Pokemon, _valid: BooleanHolder): boolean {
return false; return false;
@ -272,9 +273,9 @@ export abstract class Challenge {
/** /**
* An apply function for FIXED_BATTLE challenges. Derived classes should alter this. * An apply function for FIXED_BATTLE challenges. Derived classes should alter this.
* @param _waveIndex {@link Number} The current wave index. * @param _waveIndex The current wave index
* @param _battleConfig {@link FixedBattleConfig} The battle config to modify. * @param _battleConfig - The battle config to modify
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything
*/ */
applyFixedBattle(_waveIndex: number, _battleConfig: FixedBattleConfig): boolean { applyFixedBattle(_waveIndex: number, _battleConfig: FixedBattleConfig): boolean {
return false; return false;
@ -282,8 +283,8 @@ export abstract class Challenge {
/** /**
* An apply function for TYPE_EFFECTIVENESS challenges. Derived classes should alter this. * An apply function for TYPE_EFFECTIVENESS challenges. Derived classes should alter this.
* @param _effectiveness {@linkcode NumberHolder} The current effectiveness of the move. * @param _effectiveness - The current effectiveness of the move
* @returns Whether this function did anything. * @returns Whether this function did anything
*/ */
applyTypeEffectiveness(_effectiveness: NumberHolder): boolean { applyTypeEffectiveness(_effectiveness: NumberHolder): boolean {
return false; return false;
@ -291,11 +292,11 @@ export abstract class Challenge {
/** /**
* An apply function for AI_LEVEL challenges. Derived classes should alter this. * An apply function for AI_LEVEL challenges. Derived classes should alter this.
* @param _level {@link NumberHolder} The generated level. * @param _level - The generated level.
* @param _levelCap {@link Number} The current level cap. * @param _levelCap - The current level cap.
* @param _isTrainer {@link Boolean} Whether this is a trainer pokemon. * @param _isTrainer - Whether this is a trainer Pokémon
* @param _isBoss {@link Boolean} Whether this is a non-trainer boss pokemon. * @param _isBoss - Whether this is a non-trainer boss Pokémon
* @returns {@link boolean} Whether this function did anything. * @returns - Whether this function did anything
*/ */
applyLevelChange(_level: NumberHolder, _levelCap: number, _isTrainer: boolean, _isBoss: boolean): boolean { applyLevelChange(_level: NumberHolder, _levelCap: number, _isTrainer: boolean, _isBoss: boolean): boolean {
return false; return false;
@ -303,9 +304,9 @@ export abstract class Challenge {
/** /**
* An apply function for AI_MOVE_SLOTS challenges. Derived classes should alter this. * An apply function for AI_MOVE_SLOTS challenges. Derived classes should alter this.
* @param pokemon {@link Pokemon} The pokemon that is being considered. * @param _pokemon - The Pokémon that is being considered
* @param moveSlots {@link NumberHolder} The amount of move slots. * @param _moveSlots - The amount of move slots
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything
*/ */
applyMoveSlot(_pokemon: Pokemon, _moveSlots: NumberHolder): boolean { applyMoveSlot(_pokemon: Pokemon, _moveSlots: NumberHolder): boolean {
return false; return false;
@ -313,9 +314,9 @@ export abstract class Challenge {
/** /**
* An apply function for PASSIVE_ACCESS challenges. Derived classes should alter this. * An apply function for PASSIVE_ACCESS challenges. Derived classes should alter this.
* @param pokemon {@link Pokemon} The pokemon to change. * @param _pokemon - The Pokémon to change
* @param hasPassive {@link BooleanHolder} Whether it should have its passive. * @param _hasPassive - Whether it should have its passive
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything
*/ */
applyPassiveAccess(_pokemon: Pokemon, _hasPassive: BooleanHolder): boolean { applyPassiveAccess(_pokemon: Pokemon, _hasPassive: BooleanHolder): boolean {
return false; return false;
@ -323,7 +324,7 @@ export abstract class Challenge {
/** /**
* An apply function for GAME_MODE_MODIFY challenges. Derived classes should alter this. * An apply function for GAME_MODE_MODIFY challenges. Derived classes should alter this.
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything
*/ */
applyGameModeModify(): boolean { applyGameModeModify(): boolean {
return false; return false;
@ -331,11 +332,11 @@ export abstract class Challenge {
/** /**
* An apply function for MOVE_ACCESS. Derived classes should alter this. * An apply function for MOVE_ACCESS. Derived classes should alter this.
* @param _pokemon {@link Pokemon} What pokemon would learn the move. * @param _pokemon - What Pokémon would learn the move
* @param _moveSource {@link MoveSourceType} What source the pokemon would get the move from. * @param _moveSource - What source the Pokémon would get the move from
* @param _move {@link MoveId} The move in question. * @param _move - The move in question
* @param _level {@link NumberHolder} The level threshold for access. * @param _level - The level threshold for access
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything
*/ */
applyMoveAccessLevel(_pokemon: Pokemon, _moveSource: MoveSourceType, _move: MoveId, _level: NumberHolder): boolean { applyMoveAccessLevel(_pokemon: Pokemon, _moveSource: MoveSourceType, _move: MoveId, _level: NumberHolder): boolean {
return false; return false;
@ -343,21 +344,21 @@ export abstract class Challenge {
/** /**
* An apply function for MOVE_WEIGHT. Derived classes should alter this. * An apply function for MOVE_WEIGHT. Derived classes should alter this.
* @param _pokemon {@link Pokemon} What pokemon would learn the move. * @param _pokemon - What Pokémon would learn the move
* @param _moveSource {@link MoveSourceType} What source the pokemon would get the move from. * @param _moveSource - What source the Pokémon would get the move from
* @param _move {@link MoveId} The move in question. * @param _move - The move in question.
* @param _weight {@link NumberHolder} The base weight of the move * @param _weight - The base weight of the move
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything
*/ */
applyMoveWeight(_pokemon: Pokemon, _moveSource: MoveSourceType, _move: MoveId, _level: NumberHolder): boolean { applyMoveWeight(_pokemon: Pokemon, _moveSource: MoveSourceType, _move: MoveId, _weight: NumberHolder): boolean {
return false; return false;
} }
/** /**
* An apply function for FlipStats. Derived classes should alter this. * An apply function for FlipStats. Derived classes should alter this.
* @param _pokemon {@link Pokemon} What pokemon would learn the move. * @param _pokemon - What Pokémon would learn the move
* @param _baseStats What are the stats to flip. * @param _baseStats What are the stats to flip
* @returns {@link boolean} Whether this function did anything. * @returns Whether this function did anything
*/ */
applyFlipStat(_pokemon: Pokemon, _baseStats: number[]) { applyFlipStat(_pokemon: Pokemon, _baseStats: number[]) {
return false; return false;
@ -383,9 +384,9 @@ export abstract class Challenge {
/** /**
* An apply function for POKEMON_ADD_TO_PARTY. Derived classes should alter this. * An apply function for POKEMON_ADD_TO_PARTY. Derived classes should alter this.
* @param _pokemon - The pokemon being caught * @param _pokemon - The Pokémon being caught
* @param _status - Whether the pokemon can be added to the party or not * @param _status - Whether the Pokémon can be added to the party or not
* @return Whether this function did anything * @returns Whether this function did anything
*/ */
applyPokemonAddToParty(_pokemon: EnemyPokemon, _status: BooleanHolder): boolean { applyPokemonAddToParty(_pokemon: EnemyPokemon, _status: BooleanHolder): boolean {
return false; return false;
@ -393,8 +394,8 @@ export abstract class Challenge {
/** /**
* An apply function for POKEMON_FUSION. Derived classes should alter this. * An apply function for POKEMON_FUSION. Derived classes should alter this.
* @param _pokemon - The pokemon being checked * @param _pokemon - The Pokémon being checked
* @param _status - Whether the selected pokemon is allowed to fuse or not * @param _status - Whether the selected Pokémon is allowed to fuse or not
* @returns Whether this function did anything * @returns Whether this function did anything
*/ */
applyPokemonFusion(_pokemon: PlayerPokemon, _status: BooleanHolder): boolean { applyPokemonFusion(_pokemon: PlayerPokemon, _status: BooleanHolder): boolean {
@ -672,10 +673,7 @@ export class SingleGenerationChallenge extends Challenge {
return false; return false;
} }
/** override getDifficulty(): number {
* @overrides
*/
getDifficulty(): number {
return this.value > 0 ? 1 : 0; return this.value > 0 ? 1 : 0;
} }
@ -758,10 +756,7 @@ export class SingleTypeChallenge extends Challenge {
return false; return false;
} }
/** override getDifficulty(): number {
* @overrides
*/
getDifficulty(): number {
return this.value > 0 ? 1 : 0; return this.value > 0 ? 1 : 0;
} }

View File

@ -1,7 +1,7 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import type { PlayerPokemon } from "#field/pokemon"; import type { PlayerPokemon } from "#field/pokemon";
import type { StarterDataEntry } from "#system/game-data";
import type { DexEntry } from "#types/dex-data"; import type { DexEntry } from "#types/dex-data";
import type { StarterDataEntry } from "#types/save-data";
/** /**
* Stores data associated with a specific egg and the hatched pokemon * Stores data associated with a specific egg and the hatched pokemon

View File

@ -643,9 +643,9 @@ export abstract class Move implements Localizable {
* will not consider {@linkcode AbilityId.WIND_RIDER | Wind Rider }. * will not consider {@linkcode AbilityId.WIND_RIDER | Wind Rider }.
* *
* To simply check whether the move has a flag, use {@linkcode hasFlag}. * To simply check whether the move has a flag, use {@linkcode hasFlag}.
* @param flag {@linkcode MoveFlags} MoveFlag to check on user and/or target * @param flag - MoveFlag to check on user and/or target
* @param user {@linkcode Pokemon} the Pokemon using the move * @param user - the Pokemon using the move
* @param target {@linkcode Pokemon} the Pokemon receiving the move * @param target - the Pokemon receiving the move
* @param isFollowUp (defaults to `false`) `true` if the move was used as a follow up * @param isFollowUp (defaults to `false`) `true` if the move was used as a follow up
* @returns boolean * @returns boolean
* @see {@linkcode hasFlag} * @see {@linkcode hasFlag}
@ -1143,11 +1143,7 @@ function ChargeMove<TBase extends SubMove>(Base: TBase, nameAppend: string) {
export class ChargingAttackMove extends ChargeMove(AttackMove, "ChargingAttackMove") {} export class ChargingAttackMove extends ChargeMove(AttackMove, "ChargingAttackMove") {}
export class ChargingSelfStatusMove extends ChargeMove(SelfStatusMove, "ChargingSelfStatusMove") {} export class ChargingSelfStatusMove extends ChargeMove(SelfStatusMove, "ChargingSelfStatusMove") {}
/** /** Base class defining all {@linkcode Move} Attributes */
* Base class defining all {@linkcode Move} Attributes
* @abstract
* @see {@linkcode apply}
*/
export abstract class MoveAttr { export abstract class MoveAttr {
/** Should this {@linkcode Move} target the user? */ /** Should this {@linkcode Move} target the user? */
public selfTarget: boolean; public selfTarget: boolean;
@ -1243,8 +1239,6 @@ interface MoveEffectAttrOptions {
/** /**
* Base class defining all Move Effect Attributes * Base class defining all Move Effect Attributes
* @extends MoveAttr
* @see {@linkcode apply}
*/ */
export class MoveEffectAttr extends MoveAttr { export class MoveEffectAttr extends MoveAttr {
/** /**
@ -1460,7 +1454,6 @@ export class PreMoveMessageAttr extends MoveAttr {
* Attribute for moves that can be conditionally interrupted to be considered to * Attribute for moves that can be conditionally interrupted to be considered to
* have failed before their "useMove" message is displayed. Currently used by * have failed before their "useMove" message is displayed. Currently used by
* Focus Punch. * Focus Punch.
* @extends MoveAttr
*/ */
export class PreUseInterruptAttr extends MoveAttr { export class PreUseInterruptAttr extends MoveAttr {
protected message: string | MoveMessageFunc; protected message: string | MoveMessageFunc;
@ -1504,7 +1497,6 @@ export class PreUseInterruptAttr extends MoveAttr {
/** /**
* Attribute for Status moves that take attack type effectiveness * Attribute for Status moves that take attack type effectiveness
* into consideration (i.e. {@linkcode https://bulbapedia.bulbagarden.net/wiki/Thunder_Wave_(move) | Thunder Wave}) * into consideration (i.e. {@linkcode https://bulbapedia.bulbagarden.net/wiki/Thunder_Wave_(move) | Thunder Wave})
* @extends MoveAttr
*/ */
export class RespectAttackTypeImmunityAttr extends MoveAttr { } export class RespectAttackTypeImmunityAttr extends MoveAttr { }
@ -1788,9 +1780,7 @@ export class RecoilAttr extends MoveEffectAttr {
/** /**
* Attribute used for moves which self KO the user regardless if the move hits a target * Attribute used for moves which self KO the user regardless if the move hits a target
* @extends MoveEffectAttr */
* @see {@linkcode apply}
**/
export class SacrificialAttr extends MoveEffectAttr { export class SacrificialAttr extends MoveEffectAttr {
constructor() { constructor() {
super(true, { trigger: MoveEffectTrigger.POST_TARGET }); super(true, { trigger: MoveEffectTrigger.POST_TARGET });
@ -1821,9 +1811,7 @@ export class SacrificialAttr extends MoveEffectAttr {
/** /**
* Attribute used for moves which self KO the user but only if the move hits a target * Attribute used for moves which self KO the user but only if the move hits a target
* @extends MoveEffectAttr */
* @see {@linkcode apply}
**/
export class SacrificialAttrOnHit extends MoveEffectAttr { export class SacrificialAttrOnHit extends MoveEffectAttr {
constructor() { constructor() {
super(true); super(true);
@ -1860,8 +1848,6 @@ export class SacrificialAttrOnHit extends MoveEffectAttr {
/** /**
* Attribute used for moves which cut the user's Max HP in half. * Attribute used for moves which cut the user's Max HP in half.
* Triggers using {@linkcode MoveEffectTrigger.POST_TARGET}. * Triggers using {@linkcode MoveEffectTrigger.POST_TARGET}.
* @extends MoveEffectAttr
* @see {@linkcode apply}
*/ */
export class HalfSacrificialAttr extends MoveEffectAttr { export class HalfSacrificialAttr extends MoveEffectAttr {
constructor() { constructor() {
@ -1961,8 +1947,6 @@ export class AddSubstituteAttr extends MoveEffectAttr {
/** /**
* Heals the user or target by {@linkcode healRatio} depending on the value of {@linkcode selfTarget} * Heals the user or target by {@linkcode healRatio} depending on the value of {@linkcode selfTarget}
* @extends MoveEffectAttr
* @see {@linkcode apply}
*/ */
export class HealAttr extends MoveEffectAttr { export class HealAttr extends MoveEffectAttr {
constructor( constructor(
@ -2051,8 +2035,6 @@ export class RestAttr extends HealAttr {
/** /**
* Cures the user's party of non-volatile status conditions, ie. Heal Bell, Aromatherapy * Cures the user's party of non-volatile status conditions, ie. Heal Bell, Aromatherapy
* @extends MoveEffectAttr
* @see {@linkcode apply}
*/ */
export class PartyStatusCureAttr extends MoveEffectAttr { export class PartyStatusCureAttr extends MoveEffectAttr {
/** Message to display after using move */ /** Message to display after using move */
@ -2111,7 +2093,6 @@ export class PartyStatusCureAttr extends MoveEffectAttr {
/** /**
* Applies damage to the target's ally equal to 1/16 of that ally's max HP. * Applies damage to the target's ally equal to 1/16 of that ally's max HP.
* @extends MoveEffectAttr
*/ */
export class FlameBurstAttr extends MoveEffectAttr { export class FlameBurstAttr extends MoveEffectAttr {
constructor() { constructor() {
@ -2200,8 +2181,6 @@ export class SacrificialFullRestoreAttr extends SacrificialAttr {
/** /**
* Attribute used for moves which ignore type-based debuffs from weather, namely Hydro Steam. * Attribute used for moves which ignore type-based debuffs from weather, namely Hydro Steam.
* Called during damage calculation after getting said debuff from getAttackTypeMultiplier in the Pokemon class. * Called during damage calculation after getting said debuff from getAttackTypeMultiplier in the Pokemon class.
* @extends MoveAttr
* @see {@linkcode apply}
*/ */
export class IgnoreWeatherTypeDebuffAttr extends MoveAttr { export class IgnoreWeatherTypeDebuffAttr extends MoveAttr {
/** The {@linkcode WeatherType} this move ignores */ /** The {@linkcode WeatherType} this move ignores */
@ -2280,8 +2259,6 @@ export class SandHealAttr extends WeatherHealAttr {
/** /**
* Heals the target or the user by either {@linkcode normalHealRatio} or {@linkcode boostedHealRatio} * Heals the target or the user by either {@linkcode normalHealRatio} or {@linkcode boostedHealRatio}
* depending on the evaluation of {@linkcode condition} * depending on the evaluation of {@linkcode condition}
* @extends HealAttr
* @see {@linkcode apply}
*/ */
export class BoostHealAttr extends HealAttr { export class BoostHealAttr extends HealAttr {
/** Healing received when {@linkcode condition} is false */ /** Healing received when {@linkcode condition} is false */
@ -2314,8 +2291,6 @@ export class BoostHealAttr extends HealAttr {
/** /**
* Heals the target only if it is the ally * Heals the target only if it is the ally
* @extends HealAttr
* @see {@linkcode apply}
*/ */
export class HealOnAllyAttr extends HealAttr { export class HealOnAllyAttr extends HealAttr {
override canApply(user: Pokemon, target: Pokemon, _move: Move, _args?: any[]): boolean { override canApply(user: Pokemon, target: Pokemon, _move: Move, _args?: any[]): boolean {
@ -2334,9 +2309,6 @@ export class HealOnAllyAttr extends HealAttr {
/** /**
* Heals user as a side effect of a move that hits a target. * Heals user as a side effect of a move that hits a target.
* Healing is based on {@linkcode healRatio} * the amount of damage dealt or a stat of the target. * Healing is based on {@linkcode healRatio} * the amount of damage dealt or a stat of the target.
* @extends MoveEffectAttr
* @see {@linkcode apply}
* @see {@linkcode getUserBenefitScore}
*/ */
// TODO: Make Strength Sap its own attribute that extends off of this one // TODO: Make Strength Sap its own attribute that extends off of this one
export class HitHealAttr extends MoveEffectAttr { export class HitHealAttr extends MoveEffectAttr {
@ -2406,8 +2378,6 @@ export class HitHealAttr extends MoveEffectAttr {
* Attribute used for moves that change priority in a turn given a condition, * Attribute used for moves that change priority in a turn given a condition,
* e.g. Grassy Glide * e.g. Grassy Glide
* Called when move order is calculated in {@linkcode TurnStartPhase}. * Called when move order is calculated in {@linkcode TurnStartPhase}.
* @extends MoveAttr
* @see {@linkcode apply}
*/ */
export class IncrementMovePriorityAttr extends MoveAttr { export class IncrementMovePriorityAttr extends MoveAttr {
/** The condition for a move's priority being incremented */ /** The condition for a move's priority being incremented */
@ -2443,10 +2413,8 @@ export class IncrementMovePriorityAttr extends MoveAttr {
/** /**
* Attribute used for attack moves that hit multiple times per use, e.g. Bullet Seed. * Attribute used for attack moves that hit multiple times per use, e.g. Bullet Seed.
* *
* @remarks
* Applied at the beginning of {@linkcode MoveEffectPhase}. * Applied at the beginning of {@linkcode MoveEffectPhase}.
*
* @extends MoveAttr
* @see {@linkcode apply}
*/ */
export class MultiHitAttr extends MoveAttr { export class MultiHitAttr extends MoveAttr {
/** This move's intrinsic multi-hit type. It should never be modified. */ /** This move's intrinsic multi-hit type. It should never be modified. */
@ -2956,8 +2924,6 @@ export class StealEatBerryAttr extends EatBerryAttr {
/** /**
* Move attribute that signals that the move should cure a status effect * Move attribute that signals that the move should cure a status effect
* @extends MoveEffectAttr
* @see {@linkcode apply()}
*/ */
export class HealStatusEffectAttr extends MoveEffectAttr { export class HealStatusEffectAttr extends MoveEffectAttr {
/** List of Status Effects to cure */ /** List of Status Effects to cure */
@ -3040,8 +3006,6 @@ export class BypassSleepAttr extends MoveAttr {
/** /**
* Attribute used for moves that bypass the burn damage reduction of physical moves, currently only facade * Attribute used for moves that bypass the burn damage reduction of physical moves, currently only facade
* Called during damage calculation * Called during damage calculation
* @extends MoveAttr
* @see {@linkcode apply}
*/ */
export class BypassBurnDamageReductionAttr extends MoveAttr { export class BypassBurnDamageReductionAttr extends MoveAttr {
/** Prevents the move's damage from being reduced by burn /** Prevents the move's damage from being reduced by burn
@ -3150,7 +3114,6 @@ export class OneHitKOAttr extends MoveAttr {
/** /**
* Attribute that allows charge moves to resolve in 1 turn under a given condition. * Attribute that allows charge moves to resolve in 1 turn under a given condition.
* Should only be used for {@linkcode ChargingMove | ChargingMoves} as a `chargeAttr`. * Should only be used for {@linkcode ChargingMove | ChargingMoves} as a `chargeAttr`.
* @extends MoveAttr
*/ */
export class InstantChargeAttr extends MoveAttr { export class InstantChargeAttr extends MoveAttr {
/** The condition in which the move with this attribute instantly charges */ /** The condition in which the move with this attribute instantly charges */
@ -3187,7 +3150,6 @@ export class InstantChargeAttr extends MoveAttr {
/** /**
* Attribute that allows charge moves to resolve in 1 turn while specific {@linkcode WeatherType | Weather} * Attribute that allows charge moves to resolve in 1 turn while specific {@linkcode WeatherType | Weather}
* is active. Should only be used for {@linkcode ChargingMove | ChargingMoves} as a `chargeAttr`. * is active. Should only be used for {@linkcode ChargingMove | ChargingMoves} as a `chargeAttr`.
* @extends InstantChargeAttr
*/ */
export class WeatherInstantChargeAttr extends InstantChargeAttr { export class WeatherInstantChargeAttr extends InstantChargeAttr {
constructor(weatherTypes: WeatherType[]) { constructor(weatherTypes: WeatherType[]) {
@ -3317,7 +3279,6 @@ export class WishAttr extends MoveEffectAttr {
/** /**
* Attribute that cancels the associated move's effects when set to be combined with the user's ally's * Attribute that cancels the associated move's effects when set to be combined with the user's ally's
* subsequent move this turn. Used for Grass Pledge, Water Pledge, and Fire Pledge. * subsequent move this turn. Used for Grass Pledge, Water Pledge, and Fire Pledge.
* @extends OverrideMoveEffectAttr
*/ */
export class AwaitCombinedPledgeAttr extends OverrideMoveEffectAttr { export class AwaitCombinedPledgeAttr extends OverrideMoveEffectAttr {
constructor() { constructor() {
@ -3372,7 +3333,6 @@ export class AwaitCombinedPledgeAttr extends OverrideMoveEffectAttr {
/** /**
* Set of optional parameters that may be applied to stat stage changing effects * Set of optional parameters that may be applied to stat stage changing effects
* @extends MoveEffectAttrOptions
* @see {@linkcode StatStageChangeAttr} * @see {@linkcode StatStageChangeAttr}
*/ */
interface StatStageChangeAttrOptions extends MoveEffectAttrOptions { interface StatStageChangeAttrOptions extends MoveEffectAttrOptions {
@ -3389,9 +3349,6 @@ interface StatStageChangeAttrOptions extends MoveEffectAttrOptions {
* @param stages How many stages to change the stat(s) by, [-6, 6] * @param stages How many stages to change the stat(s) by, [-6, 6]
* @param selfTarget `true` if the move is self-targetting * @param selfTarget `true` if the move is self-targetting
* @param options {@linkcode StatStageChangeAttrOptions} Container for any optional parameters for this attribute. * @param options {@linkcode StatStageChangeAttrOptions} Container for any optional parameters for this attribute.
*
* @extends MoveEffectAttr
* @see {@linkcode apply}
*/ */
export class StatStageChangeAttr extends MoveEffectAttr { export class StatStageChangeAttr extends MoveEffectAttr {
public stats: BattleStat[]; public stats: BattleStat[];
@ -3822,8 +3779,6 @@ export class ResetStatsAttr extends MoveEffectAttr {
/** /**
* Attribute used for status moves, specifically Heart, Guard, and Power Swap, * Attribute used for status moves, specifically Heart, Guard, and Power Swap,
* that swaps the user's and target's corresponding stat stages. * that swaps the user's and target's corresponding stat stages.
* @extends MoveEffectAttr
* @see {@linkcode apply}
*/ */
export class SwapStatStagesAttr extends MoveEffectAttr { export class SwapStatStagesAttr extends MoveEffectAttr {
/** The stat stages to be swapped between the user and the target */ /** The stat stages to be swapped between the user and the target */
@ -4111,8 +4066,6 @@ export class WeightPowerAttr extends VariablePowerAttr {
/** /**
* Attribute used for Electro Ball move. * Attribute used for Electro Ball move.
* @extends VariablePowerAttr
* @see {@linkcode apply}
**/ **/
export class ElectroBallPowerAttr extends VariablePowerAttr { export class ElectroBallPowerAttr extends VariablePowerAttr {
/** /**
@ -4146,8 +4099,6 @@ export class ElectroBallPowerAttr extends VariablePowerAttr {
/** /**
* Attribute used for Gyro Ball move. * Attribute used for Gyro Ball move.
* @extends VariablePowerAttr
* @see {@linkcode apply}
**/ **/
export class GyroBallPowerAttr extends VariablePowerAttr { export class GyroBallPowerAttr extends VariablePowerAttr {
/** /**
@ -4403,11 +4354,11 @@ const countPositiveStatStages = (pokemon: Pokemon): number => {
export class PositiveStatStagePowerAttr extends VariablePowerAttr { export class PositiveStatStagePowerAttr extends VariablePowerAttr {
/** /**
* @param {Pokemon} user The pokemon that is being used to calculate the amount of positive stats * @param user The pokemon that is being used to calculate the amount of positive stats
* @param {Pokemon} target N/A * @param target N/A
* @param {Move} move N/A * @param move N/A
* @param {any[]} args The argument for VariablePowerAttr, accumulates and sets the amount of power multiplied by stats * @param args The argument for VariablePowerAttr, accumulates and sets the amount of power multiplied by stats
* @returns {boolean} Returns true if attribute is applied * @returns Returns true if attribute is applied
*/ */
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const positiveStatStages: number = countPositiveStatStages(user); const positiveStatStages: number = countPositiveStatStages(user);
@ -4427,10 +4378,10 @@ export class PunishmentPowerAttr extends VariablePowerAttr {
private PUNISHMENT_MAX_BASE_POWER = 200; private PUNISHMENT_MAX_BASE_POWER = 200;
/** /**
* @param {Pokemon} user N/A * @param user N/A
* @param {Pokemon} target The pokemon that the move is being used against, as well as calculating the stats for the min/max base power * @param target The pokemon that the move is being used against, as well as calculating the stats for the min/max base power
* @param {Move} move N/A * @param move N/A
* @param {any[]} args The value that is being changed due to VariablePowerAttr * @param args The value that is being changed due to VariablePowerAttr
* @returns Returns true if attribute is applied * @returns Returns true if attribute is applied
*/ */
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
@ -4546,8 +4497,6 @@ const hasStockpileStacksCondition: MoveConditionFunc = (user) => {
/** /**
* Attribute used for multi-hit moves that increase power in increments of the * Attribute used for multi-hit moves that increase power in increments of the
* move's base power for each hit, namely Triple Kick and Triple Axel. * move's base power for each hit, namely Triple Kick and Triple Axel.
* @extends VariablePowerAttr
* @see {@linkcode apply}
*/ */
export class MultiHitPowerIncrementAttr extends VariablePowerAttr { export class MultiHitPowerIncrementAttr extends VariablePowerAttr {
/** The max number of base power increments allowed for this move */ /** The max number of base power increments allowed for this move */
@ -4584,8 +4533,6 @@ export class MultiHitPowerIncrementAttr extends VariablePowerAttr {
* Attribute used for moves that double in power if the given move immediately * Attribute used for moves that double in power if the given move immediately
* preceded the move applying the attribute, namely Fusion Flare and * preceded the move applying the attribute, namely Fusion Flare and
* Fusion Bolt. * Fusion Bolt.
* @extends VariablePowerAttr
* @see {@linkcode apply}
*/ */
export class LastMoveDoublePowerAttr extends VariablePowerAttr { export class LastMoveDoublePowerAttr extends VariablePowerAttr {
/** The move that must precede the current move */ /** The move that must precede the current move */
@ -4688,7 +4635,6 @@ export class CombinedPledgeStabBoostAttr extends MoveAttr {
/** /**
* Variable Power attribute for {@link https://bulbapedia.bulbagarden.net/wiki/Round_(move) | Round}. * Variable Power attribute for {@link https://bulbapedia.bulbagarden.net/wiki/Round_(move) | Round}.
* Doubles power if another Pokemon has previously selected Round this turn. * Doubles power if another Pokemon has previously selected Round this turn.
* @extends VariablePowerAttr
*/ */
export class RoundPowerAttr extends VariablePowerAttr { export class RoundPowerAttr extends VariablePowerAttr {
override apply(user: Pokemon, target: Pokemon, move: Move, args: [NumberHolder]): boolean { override apply(user: Pokemon, target: Pokemon, move: Move, args: [NumberHolder]): boolean {
@ -4706,8 +4652,6 @@ export class RoundPowerAttr extends VariablePowerAttr {
* Attribute for the "combo" effect of {@link https://bulbapedia.bulbagarden.net/wiki/Round_(move) | Round}. * Attribute for the "combo" effect of {@link https://bulbapedia.bulbagarden.net/wiki/Round_(move) | Round}.
* Preempts the next move in the turn order with the first instance of any Pokemon * Preempts the next move in the turn order with the first instance of any Pokemon
* using Round. Also marks the Pokemon using the cued Round to double the move's power. * using Round. Also marks the Pokemon using the cued Round to double the move's power.
* @extends MoveEffectAttr
* @see {@linkcode RoundPowerAttr}
*/ */
export class CueNextRoundAttr extends MoveEffectAttr { export class CueNextRoundAttr extends MoveEffectAttr {
constructor() { constructor() {
@ -4909,8 +4853,6 @@ export class StormAccuracyAttr extends VariableAccuracyAttr {
/** /**
* Attribute used for moves which never miss * Attribute used for moves which never miss
* against Pokemon with the {@linkcode BattlerTagType.MINIMIZED} * against Pokemon with the {@linkcode BattlerTagType.MINIMIZED}
* @extends VariableAccuracyAttr
* @see {@linkcode apply}
*/ */
export class AlwaysHitMinimizeAttr extends VariableAccuracyAttr { export class AlwaysHitMinimizeAttr extends VariableAccuracyAttr {
/** /**
@ -4983,9 +4925,8 @@ export class PhotonGeyserCategoryAttr extends VariableMoveCategoryAttr {
* Attribute used for tera moves that change category based on the user's Atk and SpAtk stats * Attribute used for tera moves that change category based on the user's Atk and SpAtk stats
* Note: Currently, `getEffectiveStat` does not ignore all abilities that affect stats except those * Note: Currently, `getEffectiveStat` does not ignore all abilities that affect stats except those
* with the attribute of `StatMultiplierAbAttr` * with the attribute of `StatMultiplierAbAttr`
* TODO: Remove the `.partial()` tag from Tera Blast and Tera Starstorm when the above issue is resolved
* @extends VariableMoveCategoryAttr
*/ */
// TODO: Remove the `.partial()` tag from Tera Blast and Tera Starstorm when the above issue is resolved
export class TeraMoveCategoryAttr extends VariableMoveCategoryAttr { export class TeraMoveCategoryAttr extends VariableMoveCategoryAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const category = (args[0] as NumberHolder); const category = (args[0] as NumberHolder);
@ -5002,7 +4943,6 @@ export class TeraMoveCategoryAttr extends VariableMoveCategoryAttr {
/** /**
* Increases the power of Tera Blast if the user is Terastallized into Stellar type * Increases the power of Tera Blast if the user is Terastallized into Stellar type
* @extends VariablePowerAttr
*/ */
export class TeraBlastPowerAttr extends VariablePowerAttr { export class TeraBlastPowerAttr extends VariablePowerAttr {
/** /**
@ -5029,8 +4969,6 @@ export class TeraBlastPowerAttr extends VariablePowerAttr {
/** /**
* Change the move category to status when used on the ally * Change the move category to status when used on the ally
* @extends VariableMoveCategoryAttr
* @see {@linkcode apply}
*/ */
export class StatusCategoryOnAllyAttr extends VariableMoveCategoryAttr { export class StatusCategoryOnAllyAttr extends VariableMoveCategoryAttr {
/** /**
@ -5262,8 +5200,6 @@ export class WeatherBallTypeAttr extends VariableMoveTypeAttr {
/** /**
* Changes the move's type to match the current terrain. * Changes the move's type to match the current terrain.
* Has no effect if the user is not grounded. * Has no effect if the user is not grounded.
* @extends VariableMoveTypeAttr
* @see {@linkcode apply}
*/ */
export class TerrainPulseTypeAttr extends VariableMoveTypeAttr { export class TerrainPulseTypeAttr extends VariableMoveTypeAttr {
/** /**
@ -5311,7 +5247,6 @@ export class TerrainPulseTypeAttr extends VariableMoveTypeAttr {
/** /**
* Changes type based on the user's IVs * Changes type based on the user's IVs
* @extends VariableMoveTypeAttr
*/ */
export class HiddenPowerTypeAttr extends VariableMoveTypeAttr { export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
@ -5339,7 +5274,6 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
/** /**
* Changes the type of Tera Blast to match the user's tera type * Changes the type of Tera Blast to match the user's tera type
* @extends VariableMoveTypeAttr
*/ */
export class TeraBlastTypeAttr extends VariableMoveTypeAttr { export class TeraBlastTypeAttr extends VariableMoveTypeAttr {
/** /**
@ -5366,7 +5300,6 @@ export class TeraBlastTypeAttr extends VariableMoveTypeAttr {
/** /**
* Attribute used for Tera Starstorm that changes the move type to Stellar * Attribute used for Tera Starstorm that changes the move type to Stellar
* @extends VariableMoveTypeAttr
*/ */
export class TeraStarstormTypeAttr extends VariableMoveTypeAttr { export class TeraStarstormTypeAttr extends VariableMoveTypeAttr {
/** /**
@ -5412,7 +5345,6 @@ export class MatchUserTypeAttr extends VariableMoveTypeAttr {
/** /**
* Changes the type of a Pledge move based on the Pledge move combined with it. * Changes the type of a Pledge move based on the Pledge move combined with it.
* @extends VariableMoveTypeAttr
*/ */
export class CombinedPledgeTypeAttr extends VariableMoveTypeAttr { export class CombinedPledgeTypeAttr extends VariableMoveTypeAttr {
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
@ -5550,10 +5482,10 @@ export class SheerColdAccuracyAttr extends OneHitKOAccuracyAttr {
/** /**
* Changes the normal One Hit KO Accuracy Attr to implement the Gen VII changes, * Changes the normal One Hit KO Accuracy Attr to implement the Gen VII changes,
* where if the user is Ice-Type, it has more accuracy. * where if the user is Ice-Type, it has more accuracy.
* @param {Pokemon} user Pokemon that is using the move; checks the Pokemon's level. * @param user Pokemon that is using the move; checks the Pokemon's level.
* @param {Pokemon} target Pokemon that is receiving the move; checks the Pokemon's level. * @param target Pokemon that is receiving the move; checks the Pokemon's level.
* @param {Move} move N/A * @param move N/A
* @param {any[]} args Uses the accuracy argument, allowing to change it from either 0 if it doesn't pass * @param args Uses the accuracy argument, allowing to change it from either 0 if it doesn't pass
* the first if/else, or 30/20 depending on the type of the user Pokemon. * the first if/else, or 30/20 depending on the type of the user Pokemon.
* @returns Returns true if move is successful, false if misses. * @returns Returns true if move is successful, false if misses.
*/ */
@ -5668,7 +5600,6 @@ export class FrenzyAttr extends MoveEffectAttr {
/** /**
* Attribute that grants {@link https://bulbapedia.bulbagarden.net/wiki/Semi-invulnerable_turn | semi-invulnerability} to the user during * Attribute that grants {@link https://bulbapedia.bulbagarden.net/wiki/Semi-invulnerable_turn | semi-invulnerability} to the user during
* the associated move's charging phase. Should only be used for {@linkcode ChargingMove | ChargingMoves} as a `chargeAttr`. * the associated move's charging phase. Should only be used for {@linkcode ChargingMove | ChargingMoves} as a `chargeAttr`.
* @extends MoveEffectAttr
*/ */
export class SemiInvulnerableAttr extends MoveEffectAttr { export class SemiInvulnerableAttr extends MoveEffectAttr {
/** The type of {@linkcode SemiInvulnerableTag} to grant to the user */ /** The type of {@linkcode SemiInvulnerableTag} to grant to the user */
@ -5794,7 +5725,6 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
/** /**
* Adds a {@link https://bulbapedia.bulbagarden.net/wiki/Seeding | Seeding} effect to the target * Adds a {@link https://bulbapedia.bulbagarden.net/wiki/Seeding | Seeding} effect to the target
* as seen with Leech Seed and Sappy Seed. * as seen with Leech Seed and Sappy Seed.
* @extends AddBattlerTagAttr
*/ */
export class LeechSeedAttr extends AddBattlerTagAttr { export class LeechSeedAttr extends AddBattlerTagAttr {
constructor() { constructor() {
@ -5804,7 +5734,6 @@ export class LeechSeedAttr extends AddBattlerTagAttr {
/** /**
* Adds the appropriate battler tag for Smack Down and Thousand arrows * Adds the appropriate battler tag for Smack Down and Thousand arrows
* @extends AddBattlerTagAttr
*/ */
export class FallDownAttr extends AddBattlerTagAttr { export class FallDownAttr extends AddBattlerTagAttr {
constructor() { constructor() {
@ -5829,7 +5758,6 @@ export class FallDownAttr extends AddBattlerTagAttr {
/** /**
* Adds the appropriate battler tag for Gulp Missile when Surf or Dive is used. * Adds the appropriate battler tag for Gulp Missile when Surf or Dive is used.
* @extends MoveEffectAttr
*/ */
export class GulpMissileTagAttr extends MoveEffectAttr { export class GulpMissileTagAttr extends MoveEffectAttr {
constructor() { constructor() {
@ -5869,7 +5797,6 @@ export class GulpMissileTagAttr extends MoveEffectAttr {
/** /**
* Attribute to implement Jaw Lock's linked trapping effect between the user and target * Attribute to implement Jaw Lock's linked trapping effect between the user and target
* @extends AddBattlerTagAttr
*/ */
export class JawLockAttr extends AddBattlerTagAttr { export class JawLockAttr extends AddBattlerTagAttr {
constructor() { constructor() {
@ -6035,7 +5962,6 @@ export class ProtectAttr extends AddBattlerTagAttr {
/** /**
* Attribute to remove all Substitutes from the field. * Attribute to remove all Substitutes from the field.
* @extends MoveEffectAttr
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Tidy_Up_(move) | Tidy Up} * @see {@link https://bulbapedia.bulbagarden.net/wiki/Tidy_Up_(move) | Tidy Up}
* @see {@linkcode SubstituteTag} * @see {@linkcode SubstituteTag}
*/ */
@ -6067,7 +5993,6 @@ export class RemoveAllSubstitutesAttr extends MoveEffectAttr {
* Attribute used when a move can deal damage to {@linkcode BattlerTagType} * Attribute used when a move can deal damage to {@linkcode BattlerTagType}
* Moves that always hit but do not deal double damage: Thunder, Fissure, Sky Uppercut, * Moves that always hit but do not deal double damage: Thunder, Fissure, Sky Uppercut,
* Smack Down, Hurricane, Thousand Arrows * Smack Down, Hurricane, Thousand Arrows
* @extends MoveAttr
*/ */
export class HitsTagAttr extends MoveAttr { export class HitsTagAttr extends MoveAttr {
/** The {@linkcode BattlerTagType} this move hits */ /** The {@linkcode BattlerTagType} this move hits */
@ -6181,8 +6106,6 @@ export class AddArenaTrapTagAttr extends AddArenaTagAttr {
/** /**
* Attribute used for Stone Axe and Ceaseless Edge. * Attribute used for Stone Axe and Ceaseless Edge.
* Applies the given ArenaTrapTag when move is used. * Applies the given ArenaTrapTag when move is used.
* @extends AddArenaTagAttr
* @see {@linkcode apply}
*/ */
export class AddArenaTrapTagHitAttr extends AddArenaTagAttr { export class AddArenaTrapTagHitAttr extends AddArenaTagAttr {
/** /**
@ -6275,10 +6198,7 @@ export class RemoveScreensAttr extends MoveEffectAttr {
} }
} }
/*Swaps arena effects between the player and enemy side /** Swaps arena effects between the player and enemy side */
* @extends MoveEffectAttr
* @see {@linkcode apply}
*/
export class SwapArenaTagsAttr extends MoveEffectAttr { export class SwapArenaTagsAttr extends MoveEffectAttr {
public SwapTags: ArenaTagType[]; public SwapTags: ArenaTagType[];
@ -6344,8 +6264,6 @@ export class AddPledgeEffectAttr extends AddArenaTagAttr {
/** /**
* Attribute used for Revival Blessing. * Attribute used for Revival Blessing.
* @extends MoveEffectAttr
* @see {@linkcode apply}
*/ */
export class RevivalBlessingAttr extends MoveEffectAttr { export class RevivalBlessingAttr extends MoveEffectAttr {
constructor() { constructor() {
@ -6410,7 +6328,6 @@ export class RevivalBlessingAttr extends MoveEffectAttr {
} }
} }
export class ForceSwitchOutAttr extends MoveEffectAttr { export class ForceSwitchOutAttr extends MoveEffectAttr {
constructor( constructor(
private selfSwitch: boolean = false, private selfSwitch: boolean = false,
@ -6769,7 +6686,7 @@ export class CopyBiomeTypeAttr extends MoveEffectAttr {
/** /**
* Retrieves a type from the current terrain * Retrieves a type from the current terrain
* @param terrainType {@linkcode TerrainType} * @param terrainType {@linkcode TerrainType}
* @returns {@linkcode Type} * @returns
*/ */
private getTypeForTerrain(terrainType: TerrainType): PokemonType { private getTypeForTerrain(terrainType: TerrainType): PokemonType {
switch (terrainType) { switch (terrainType) {
@ -6790,7 +6707,7 @@ export class CopyBiomeTypeAttr extends MoveEffectAttr {
/** /**
* Retrieves a type from the current biome * Retrieves a type from the current biome
* @param biomeType {@linkcode BiomeId} * @param biomeType {@linkcode BiomeId}
* @returns {@linkcode Type} * @returns
*/ */
private getTypeForBiome(biomeType: BiomeId): PokemonType { private getTypeForBiome(biomeType: BiomeId): PokemonType {
switch (biomeType) { switch (biomeType) {
@ -6923,8 +6840,6 @@ export class FirstMoveTypeAttr extends MoveEffectAttr {
/** /**
* Attribute used to call a move. * Attribute used to call a move.
* Used by other move attributes: {@linkcode RandomMoveAttr}, {@linkcode RandomMovesetMoveAttr}, {@linkcode CopyMoveAttr} * Used by other move attributes: {@linkcode RandomMoveAttr}, {@linkcode RandomMovesetMoveAttr}, {@linkcode CopyMoveAttr}
* @see {@linkcode apply} for move call
* @extends OverrideMoveEffectAttr
*/ */
class CallMoveAttr extends OverrideMoveEffectAttr { class CallMoveAttr extends OverrideMoveEffectAttr {
protected invalidMoves: ReadonlySet<MoveId>; protected invalidMoves: ReadonlySet<MoveId>;
@ -6956,8 +6871,6 @@ class CallMoveAttr extends OverrideMoveEffectAttr {
/** /**
* Attribute used to call a random move. * Attribute used to call a random move.
* Used for {@linkcode MoveId.METRONOME} * Used for {@linkcode MoveId.METRONOME}
* @see {@linkcode apply} for move selection and move call
* @extends CallMoveAttr to call a selected move
*/ */
export class RandomMoveAttr extends CallMoveAttr { export class RandomMoveAttr extends CallMoveAttr {
constructor(invalidMoves: ReadonlySet<MoveId>) { constructor(invalidMoves: ReadonlySet<MoveId>) {
@ -7005,8 +6918,6 @@ export class RandomMoveAttr extends CallMoveAttr {
* Fails if the user has no callable moves. * Fails if the user has no callable moves.
* *
* Invalid moves are indicated by what is passed in to invalidMoves: {@linkcode invalidAssistMoves} or {@linkcode invalidSleepTalkMoves} * Invalid moves are indicated by what is passed in to invalidMoves: {@linkcode invalidAssistMoves} or {@linkcode invalidSleepTalkMoves}
* @extends RandomMoveAttr to use the callMove function on a moveId
* @see {@linkcode getCondition} for move selection
*/ */
export class RandomMovesetMoveAttr extends CallMoveAttr { export class RandomMovesetMoveAttr extends CallMoveAttr {
private includeParty: boolean; private includeParty: boolean;
@ -7192,8 +7103,6 @@ export class NaturePowerAttr extends OverrideMoveEffectAttr {
/** /**
* Attribute used to copy a previously-used move. * Attribute used to copy a previously-used move.
* Used for {@linkcode MoveId.COPYCAT} and {@linkcode MoveId.MIRROR_MOVE} * Used for {@linkcode MoveId.COPYCAT} and {@linkcode MoveId.MIRROR_MOVE}
* @see {@linkcode apply} for move selection and move call
* @extends CallMoveAttr to call a selected move
*/ */
export class CopyMoveAttr extends CallMoveAttr { export class CopyMoveAttr extends CallMoveAttr {
private mirrorMove: boolean; private mirrorMove: boolean;
@ -7529,11 +7438,11 @@ export class SketchAttr extends MoveEffectAttr {
} }
/** /**
* User copies the opponent's last used move, if possible * User copies the opponent's last used move, if possible
* @param {Pokemon} user Pokemon that used the move and will replace Sketch with the copied move * @param user Pokemon that used the move and will replace Sketch with the copied move
* @param {Pokemon} target Pokemon that the user wants to copy a move from * @param target Pokemon that the user wants to copy a move from
* @param {Move} move Move being used * @param move Move being used
* @param {any[]} args Unused * @param args Unused
* @returns {boolean} true if the function succeeds, otherwise false * @returns true if the function succeeds, otherwise false
*/ */
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
@ -7696,10 +7605,6 @@ export class SwitchAbilitiesAttr extends MoveEffectAttr {
/** /**
* Attribute used for moves that suppress abilities like {@linkcode MoveId.GASTRO_ACID}. * Attribute used for moves that suppress abilities like {@linkcode MoveId.GASTRO_ACID}.
* A suppressed ability cannot be activated. * A suppressed ability cannot be activated.
*
* @extends MoveEffectAttr
* @see {@linkcode apply}
* @see {@linkcode getCondition}
*/ */
export class SuppressAbilitiesAttr extends MoveEffectAttr { export class SuppressAbilitiesAttr extends MoveEffectAttr {
/** Sets ability suppression for the target pokemon and displays a message. */ /** Sets ability suppression for the target pokemon and displays a message. */
@ -7725,8 +7630,7 @@ export class SuppressAbilitiesAttr extends MoveEffectAttr {
/** /**
* Applies the effects of {@linkcode SuppressAbilitiesAttr} if the target has already moved this turn. * Applies the effects of {@linkcode SuppressAbilitiesAttr} if the target has already moved this turn.
* @extends MoveEffectAttr * @see {@linkcode MoveId.CORE_ENFORCER}
* @see {@linkcode MoveId.CORE_ENFORCER} (the move which uses this effect)
*/ */
export class SuppressAbilitiesIfActedAttr extends MoveEffectAttr { export class SuppressAbilitiesIfActedAttr extends MoveEffectAttr {
/** /**
@ -7775,8 +7679,6 @@ export class TransformAttr extends MoveEffectAttr {
/** /**
* Attribute used for status moves, namely Speed Swap, * Attribute used for status moves, namely Speed Swap,
* that swaps the user's and target's corresponding stats. * that swaps the user's and target's corresponding stats.
* @extends MoveEffectAttr
* @see {@linkcode apply}
*/ */
export class SwapStatAttr extends MoveEffectAttr { export class SwapStatAttr extends MoveEffectAttr {
/** The stat to be swapped between the user and the target */ /** The stat to be swapped between the user and the target */
@ -7817,7 +7719,6 @@ export class SwapStatAttr extends MoveEffectAttr {
/** /**
* Attribute used to switch the user's own stats. * Attribute used to switch the user's own stats.
* Used by Power Shift. * Used by Power Shift.
* @extends MoveEffectAttr
*/ */
export class ShiftStatAttr extends MoveEffectAttr { export class ShiftStatAttr extends MoveEffectAttr {
private statToSwitch: EffectiveStat; private statToSwitch: EffectiveStat;
@ -7832,7 +7733,7 @@ export class ShiftStatAttr extends MoveEffectAttr {
/** /**
* Switches the user's stats based on the {@linkcode statToSwitch} and {@linkcode statToSwitchWith} attributes. * Switches the user's stats based on the {@linkcode statToSwitch} and {@linkcode statToSwitchWith} attributes.
* @param {Pokemon} user the {@linkcode Pokemon} that used the move * @param user the {@linkcode Pokemon} that used the move
* @param target n/a * @param target n/a
* @param move n/a * @param move n/a
* @param args n/a * @param args n/a
@ -7860,7 +7761,7 @@ export class ShiftStatAttr extends MoveEffectAttr {
/** /**
* Encourages the user to use the move if the stat to switch with is greater than the stat to switch. * Encourages the user to use the move if the stat to switch with is greater than the stat to switch.
* @param {Pokemon} user the {@linkcode Pokemon} that used the move * @param user the {@linkcode Pokemon} that used the move
* @param target n/a * @param target n/a
* @param move n/a * @param move n/a
* @returns number of points to add to the user's benefit score * @returns number of points to add to the user's benefit score
@ -7874,8 +7775,6 @@ export class ShiftStatAttr extends MoveEffectAttr {
* Attribute used for status moves, namely Power Split and Guard Split, * Attribute used for status moves, namely Power Split and Guard Split,
* that take the average of a user's and target's corresponding * that take the average of a user's and target's corresponding
* stats and assign that average back to each corresponding stat. * stats and assign that average back to each corresponding stat.
* @extends MoveEffectAttr
* @see {@linkcode apply}
*/ */
export class AverageStatsAttr extends MoveEffectAttr { export class AverageStatsAttr extends MoveEffectAttr {
/** The stats to be averaged individually between the user and the target */ /** The stats to be averaged individually between the user and the target */
@ -7928,11 +7827,7 @@ export class MoneyAttr extends MoveEffectAttr {
} }
} }
/** /** Applies {@linkcode BattlerTagType.DESTINY_BOND} to the user */
* Applies {@linkcode BattlerTagType.DESTINY_BOND} to the user.
*
* @extends MoveEffectAttr
*/
export class DestinyBondAttr extends MoveEffectAttr { export class DestinyBondAttr extends MoveEffectAttr {
constructor() { constructor() {
super(true, { trigger: MoveEffectTrigger.PRE_APPLY }); super(true, { trigger: MoveEffectTrigger.PRE_APPLY });
@ -7943,7 +7838,7 @@ export class DestinyBondAttr extends MoveEffectAttr {
* @param user {@linkcode Pokemon} that is having the tag applied to. * @param user {@linkcode Pokemon} that is having the tag applied to.
* @param target {@linkcode Pokemon} N/A * @param target {@linkcode Pokemon} N/A
* @param move {@linkcode Move} {@linkcode Move.DESTINY_BOND} * @param move {@linkcode Move} {@linkcode Move.DESTINY_BOND}
* @param {any[]} args N/A * @param args N/A
* @returns true * @returns true
*/ */
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
@ -7953,10 +7848,7 @@ export class DestinyBondAttr extends MoveEffectAttr {
} }
} }
/** /** Attribute to apply a battler tag to the target if they have had their stats boosted this turn */
* Attribute to apply a battler tag to the target if they have had their stats boosted this turn.
* @extends AddBattlerTagAttr
*/
export class AddBattlerTagIfBoostedAttr extends AddBattlerTagAttr { export class AddBattlerTagIfBoostedAttr extends AddBattlerTagAttr {
constructor(tag: BattlerTagType) { constructor(tag: BattlerTagType) {
super(tag, false, false, 2, 5); super(tag, false, false, 2, 5);
@ -7966,7 +7858,7 @@ export class AddBattlerTagIfBoostedAttr extends AddBattlerTagAttr {
* @param user {@linkcode Pokemon} using this move * @param user {@linkcode Pokemon} using this move
* @param target {@linkcode Pokemon} target of this move * @param target {@linkcode Pokemon} target of this move
* @param move {@linkcode Move} being used * @param move {@linkcode Move} being used
* @param {any[]} args N/A * @param args N/A
* @returns true * @returns true
*/ */
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
@ -7979,7 +7871,6 @@ export class AddBattlerTagIfBoostedAttr extends AddBattlerTagAttr {
/** /**
* Attribute to apply a status effect to the target if they have had their stats boosted this turn. * Attribute to apply a status effect to the target if they have had their stats boosted this turn.
* @extends MoveEffectAttr
*/ */
export class StatusIfBoostedAttr extends MoveEffectAttr { export class StatusIfBoostedAttr extends MoveEffectAttr {
public effect: StatusEffect; public effect: StatusEffect;
@ -7993,7 +7884,7 @@ export class StatusIfBoostedAttr extends MoveEffectAttr {
* @param user {@linkcode Pokemon} using this move * @param user {@linkcode Pokemon} using this move
* @param target {@linkcode Pokemon} target of this move * @param target {@linkcode Pokemon} target of this move
* @param move {@linkcode Move} N/A * @param move {@linkcode Move} N/A
* @param {any[]} args N/A * @param args N/A
* @returns true * @returns true
*/ */
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
@ -8075,7 +7966,6 @@ export class AfterYouAttr extends MoveEffectAttr {
/** /**
* Move effect to force the target to move last, ignoring priority. * Move effect to force the target to move last, ignoring priority.
* If applied to multiple targets, they move in speed order after all other moves. * If applied to multiple targets, they move in speed order after all other moves.
* @extends MoveEffectAttr
*/ */
export class ForceLastAttr extends MoveEffectAttr { export class ForceLastAttr extends MoveEffectAttr {
/** /**
@ -8254,11 +8144,11 @@ export class ResistLastMoveTypeAttr extends MoveEffectAttr {
/** /**
* User changes its type to a random type that resists the target's last used move * User changes its type to a random type that resists the target's last used move
* @param {Pokemon} user Pokemon that used the move and will change types * @param user Pokemon that used the move and will change types
* @param {Pokemon} target Opposing pokemon that recently used a move * @param target Opposing pokemon that recently used a move
* @param {Move} move Move being used * @param move Move being used
* @param {any[]} args Unused * @param args Unused
* @returns {boolean} true if the function succeeds * @returns true if the function succeeds
*/ */
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!super.apply(user, target, move, args)) { if (!super.apply(user, target, move, args)) {
@ -8319,9 +8209,6 @@ export class ResistLastMoveTypeAttr extends MoveEffectAttr {
* Drops the target's immunity to types it is immune to * Drops the target's immunity to types it is immune to
* and makes its evasiveness be ignored during accuracy * and makes its evasiveness be ignored during accuracy
* checks. Used by: {@linkcode MoveId.ODOR_SLEUTH | Odor Sleuth}, {@linkcode MoveId.MIRACLE_EYE | Miracle Eye} and {@linkcode MoveId.FORESIGHT | Foresight} * checks. Used by: {@linkcode MoveId.ODOR_SLEUTH | Odor Sleuth}, {@linkcode MoveId.MIRACLE_EYE | Miracle Eye} and {@linkcode MoveId.FORESIGHT | Foresight}
*
* @extends AddBattlerTagAttr
* @see {@linkcode apply}
*/ */
export class ExposedMoveAttr extends AddBattlerTagAttr { export class ExposedMoveAttr extends AddBattlerTagAttr {
constructor(tagType: BattlerTagType) { constructor(tagType: BattlerTagType) {

View File

@ -576,10 +576,9 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
*/ */
/** /**
* @static Defines the type of encounter which is used as an identifier, should be tied to a unique MysteryEncounterType * Defines the type of encounter which is used as an identifier, should be tied to a unique MysteryEncounterType
* NOTE: if new functions are added to {@linkcode MysteryEncounter} class
* @param encounterType * @param encounterType
* @returns this * @returns a new instance of MysteryEncounterBuilder with encounterType set
*/ */
static withEncounterType( static withEncounterType(
encounterType: MysteryEncounterType, encounterType: MysteryEncounterType,

View File

@ -969,7 +969,7 @@ export function handleMysteryEncounterBattleStartEffects() {
/** /**
* Can queue extra phases or logic during {@linkcode TurnInitPhase} * Can queue extra phases or logic during {@linkcode TurnInitPhase}
* Should mostly just be used for injecting custom phases into the battle system on turn start * Should mostly just be used for injecting custom phases into the battle system on turn start
* @return boolean - if true, will skip the remainder of the {@linkcode TurnInitPhase} * @returns boolean - if true, will skip the remainder of the {@linkcode TurnInitPhase}
*/ */
export function handleMysteryEncounterTurnStartEffects(): boolean { export function handleMysteryEncounterTurnStartEffects(): boolean {
const encounter = globalScene.currentBattle.mysteryEncounter; const encounter = globalScene.currentBattle.mysteryEncounter;
@ -986,7 +986,7 @@ export function handleMysteryEncounterTurnStartEffects(): boolean {
* @param level the level of the mon, which differs between MEs * @param level the level of the mon, which differs between MEs
* @param isBoss whether the mon should be a Boss * @param isBoss whether the mon should be a Boss
* @param rerollHidden whether the mon should get an extra roll for Hidden Ability * @param rerollHidden whether the mon should get an extra roll for Hidden Ability
* @returns {@linkcode EnemyPokemon} for the requested encounter * @returns for the requested encounter
*/ */
export function getRandomEncounterSpecies(level: number, isBoss = false, rerollHidden = false): EnemyPokemon { export function getRandomEncounterSpecies(level: number, isBoss = false, rerollHidden = false): EnemyPokemon {
let bossSpecies: PokemonSpecies; let bossSpecies: PokemonSpecies;

View File

@ -289,7 +289,7 @@ export class SpeciesFormChangeRevertWeatherFormTrigger extends SpeciesFormChange
/** /**
* Checks if the Pokemon has the required ability and the weather is one that will revert * Checks if the Pokemon has the required ability and the weather is one that will revert
* the Pokemon to its original form or the weather or ability is suppressed * the Pokemon to its original form or the weather or ability is suppressed
* @param {Pokemon} pokemon the pokemon that is trying to do the form change * @param pokemon the pokemon that is trying to do the form change
* @returns `true` if the Pokemon will revert to its original form, `false` otherwise * @returns `true` if the Pokemon will revert to its original form, `false` otherwise
*/ */
canChange(pokemon: Pokemon): boolean { canChange(pokemon: Pokemon): boolean {

View File

@ -26,8 +26,8 @@ import { loadPokemonVariantAssets } from "#sprites/pokemon-sprite";
import { hasExpSprite } from "#sprites/sprite-utils"; import { hasExpSprite } from "#sprites/sprite-utils";
import type { Variant, VariantSet } from "#sprites/variant"; import type { Variant, VariantSet } from "#sprites/variant";
import { populateVariantColorCache, variantColorCache, variantData } from "#sprites/variant"; import { populateVariantColorCache, variantColorCache, variantData } from "#sprites/variant";
import type { StarterMoveset } from "#system/game-data";
import type { Localizable } from "#types/locales"; import type { Localizable } from "#types/locales";
import type { StarterMoveset } from "#types/save-data";
import { isNullOrUndefined, randSeedFloat, randSeedGauss, randSeedInt } from "#utils/common"; import { isNullOrUndefined, randSeedFloat, randSeedGauss, randSeedInt } from "#utils/common";
import { getPokemonSpecies } from "#utils/pokemon-utils"; import { getPokemonSpecies } from "#utils/pokemon-utils";
import { toCamelCase, toPascalCase } from "#utils/strings"; import { toCamelCase, toPascalCase } from "#utils/strings";
@ -919,7 +919,7 @@ export class PokemonSpecies extends PokemonSpeciesForm implements Localizable {
* The calculation with evolution delay is a weighted average of the easeIn and easeOut functions where preferredMinLevel is the denominator. * The calculation with evolution delay is a weighted average of the easeIn and easeOut functions where preferredMinLevel is the denominator.
* This also means a lower value of x will lead to a higher evolution chance. * This also means a lower value of x will lead to a higher evolution chance.
* @param strength {@linkcode PartyMemberStrength} The strength of the party member in question * @param strength {@linkcode PartyMemberStrength} The strength of the party member in question
* @returns {@linkcode number} The level difference from expected evolution level tolerated for a mon to be unevolved. Lower value = higher evolution chance. * @returns The level difference from expected evolution level tolerated for a mon to be unevolved. Lower value = higher evolution chance.
*/ */
private getStrengthLevelDiff(strength: PartyMemberStrength): number { private getStrengthLevelDiff(strength: PartyMemberStrength): number {
switch (Math.min(strength, PartyMemberStrength.STRONGER)) { switch (Math.min(strength, PartyMemberStrength.STRONGER)) {

View File

@ -234,7 +234,7 @@ const seasonalSplashMessages: Season[] = [
"valentines.happyValentines", "valentines.happyValentines",
"valentines.fullOfLove", "valentines.fullOfLove",
"valentines.applinForYou", "valentines.applinForYou",
"valentines.thePowerOfLoveIsThreeThirtyBST", "valentines.thePowerOfLoveIsThreeThirtyBst",
"valentines.haveAHeartScale", "valentines.haveAHeartScale",
"valentines.i<3You", "valentines.i<3You",
], ],
@ -265,7 +265,7 @@ const seasonalSplashMessages: Season[] = [
"aprilFools.whoIsFinn", "aprilFools.whoIsFinn",
"aprilFools.watchOutForShadowPokemon", "aprilFools.watchOutForShadowPokemon",
"aprilFools.nowWithDarkTypeLuxray", "aprilFools.nowWithDarkTypeLuxray",
"aprilFools.onlyOnPokerogueNetAGAIN", "aprilFools.onlyOnPokerogueNetAgain",
"aprilFools.noFreeVouchers", "aprilFools.noFreeVouchers",
"aprilFools.altffourAchievementPoints", "aprilFools.altffourAchievementPoints",
"aprilFools.rokePogue", "aprilFools.rokePogue",

View File

@ -204,7 +204,7 @@ export class TrainerConfig {
/** /**
* Returns the derived trainer type for a given trainer type. * Returns the derived trainer type for a given trainer type.
* @param trainerTypeToDeriveFrom - The trainer type to derive from. (If null, the this.trainerType property will be used.) * @param trainerTypeToDeriveFrom - The trainer type to derive from. (If null, the this.trainerType property will be used.)
* @returns {TrainerType} - The derived trainer type. * @returns - The derived trainer type.
*/ */
getDerivedType(trainerTypeToDeriveFrom: TrainerType | null = null): TrainerType { getDerivedType(trainerTypeToDeriveFrom: TrainerType | null = null): TrainerType {
let trainerType = trainerTypeToDeriveFrom ? trainerTypeToDeriveFrom : this.trainerType; let trainerType = trainerTypeToDeriveFrom ? trainerTypeToDeriveFrom : this.trainerType;
@ -274,9 +274,9 @@ export class TrainerConfig {
/** /**
* Sets the configuration for trainers with genders, including the female name and encounter background music (BGM). * Sets the configuration for trainers with genders, including the female name and encounter background music (BGM).
* @param {string} [nameFemale] The name of the female trainer. If 'Ivy', a localized name will be assigned. * @param [nameFemale] The name of the female trainer. If 'Ivy', a localized name will be assigned.
* @param {TrainerType | string} [femaleEncounterBgm] The encounter BGM for the female trainer, which can be a TrainerType or a string. * @param [femaleEncounterBgm] The encounter BGM for the female trainer, which can be a TrainerType or a string.
* @returns {TrainerConfig} The updated TrainerConfig instance. * @returns The updated TrainerConfig instance.
*/ */
setHasGenders(nameFemale?: string, femaleEncounterBgm?: TrainerType | string): TrainerConfig { setHasGenders(nameFemale?: string, femaleEncounterBgm?: TrainerType | string): TrainerConfig {
// If the female name is 'Ivy' (the rival), assign a localized name. // If the female name is 'Ivy' (the rival), assign a localized name.
@ -314,7 +314,7 @@ export class TrainerConfig {
* Sets the configuration for trainers with double battles, including the name of the double trainer and the encounter BGM. * Sets the configuration for trainers with double battles, including the name of the double trainer and the encounter BGM.
* @param nameDouble The name of the double trainer (e.g., "Ace Duo" for Trainer Class Doubles or "red_blue_double" for NAMED trainer doubles). * @param nameDouble The name of the double trainer (e.g., "Ace Duo" for Trainer Class Doubles or "red_blue_double" for NAMED trainer doubles).
* @param doubleEncounterBgm The encounter BGM for the double trainer, which can be a TrainerType or a string. * @param doubleEncounterBgm The encounter BGM for the double trainer, which can be a TrainerType or a string.
* @returns {TrainerConfig} The updated TrainerConfig instance. * @returns The updated TrainerConfig instance.
*/ */
setHasDouble(nameDouble: string, doubleEncounterBgm?: TrainerType | string): TrainerConfig { setHasDouble(nameDouble: string, doubleEncounterBgm?: TrainerType | string): TrainerConfig {
this.hasDouble = true; this.hasDouble = true;
@ -331,7 +331,7 @@ export class TrainerConfig {
/** /**
* Sets the trainer type for double battles. * Sets the trainer type for double battles.
* @param trainerTypeDouble The TrainerType of the partner in a double battle. * @param trainerTypeDouble The TrainerType of the partner in a double battle.
* @returns {TrainerConfig} The updated TrainerConfig instance. * @returns The updated TrainerConfig instance.
*/ */
setDoubleTrainerType(trainerTypeDouble: TrainerType): TrainerConfig { setDoubleTrainerType(trainerTypeDouble: TrainerType): TrainerConfig {
this.trainerTypeDouble = trainerTypeDouble; this.trainerTypeDouble = trainerTypeDouble;
@ -356,7 +356,7 @@ export class TrainerConfig {
/** /**
* Sets the title for double trainers * Sets the title for double trainers
* @param titleDouble The key for the title in the i18n file. (e.g., "champion_double"). * @param titleDouble The key for the title in the i18n file. (e.g., "champion_double").
* @returns {TrainerConfig} The updated TrainerConfig instance. * @returns The updated TrainerConfig instance.
*/ */
setDoubleTitle(titleDouble: string): TrainerConfig { setDoubleTitle(titleDouble: string): TrainerConfig {
// First check if i18n is initialized // First check if i18n is initialized
@ -523,9 +523,9 @@ export class TrainerConfig {
* Initializes the trainer configuration for an evil team admin. * Initializes the trainer configuration for an evil team admin.
* @param title The title of the evil team admin. * @param title The title of the evil team admin.
* @param poolName The evil team the admin belongs to. * @param poolName The evil team the admin belongs to.
* @param {SpeciesId | SpeciesId[]} signatureSpecies The signature species for the evil team leader. * @param signatureSpecies The signature species for the evil team leader.
* @param specialtyType The specialty Type of the admin, if they have one * @param specialtyType The specialty Type of the admin, if they have one
* @returns {TrainerConfig} The updated TrainerConfig instance. * @returns The updated TrainerConfig instance.
*/ */
initForEvilTeamAdmin( initForEvilTeamAdmin(
title: string, title: string,
@ -566,7 +566,7 @@ export class TrainerConfig {
/** /**
* Initializes the trainer configuration for a Stat Trainer, as part of the Trainer's Test Mystery Encounter. * Initializes the trainer configuration for a Stat Trainer, as part of the Trainer's Test Mystery Encounter.
* @param _isMale Whether the stat trainer is Male or Female (for localization of the title). * @param _isMale Whether the stat trainer is Male or Female (for localization of the title).
* @returns {TrainerConfig} The updated TrainerConfig instance. * @returns The updated TrainerConfig instance.
*/ */
initForStatTrainer(_isMale = false): TrainerConfig { initForStatTrainer(_isMale = false): TrainerConfig {
if (!getIsInitialized()) { if (!getIsInitialized()) {
@ -590,10 +590,10 @@ export class TrainerConfig {
/** /**
* Initializes the trainer configuration for an evil team leader. Temporarily hardcoding evil leader teams though. * Initializes the trainer configuration for an evil team leader. Temporarily hardcoding evil leader teams though.
* @param {SpeciesId | SpeciesId[]} signatureSpecies The signature species for the evil team leader. * @param signatureSpecies The signature species for the evil team leader.
* @param {PokemonType} specialtyType The specialty type for the evil team Leader. * @param specialtyType The specialty type for the evil team Leader.
* @param boolean Whether or not this is the rematch fight * @param boolean Whether or not this is the rematch fight
* @returns {TrainerConfig} The updated TrainerConfig instance. * @returns The updated TrainerConfig instance.
*/ */
initForEvilTeamLeader( initForEvilTeamLeader(
title: string, title: string,
@ -631,12 +631,12 @@ export class TrainerConfig {
/** /**
* Initializes the trainer configuration for a Gym Leader. * Initializes the trainer configuration for a Gym Leader.
* @param {SpeciesId | SpeciesId[]} signatureSpecies The signature species for the Gym Leader. Added to party in reverse order. * @param signatureSpecies The signature species for the Gym Leader. Added to party in reverse order.
* @param isMale Whether the Gym Leader is Male or Not (for localization of the title). * @param isMale Whether the Gym Leader is Male or Not (for localization of the title).
* @param {PokemonType} specialtyType The specialty type for the Gym Leader. * @param specialtyType The specialty type for the Gym Leader.
* @param ignoreMinTeraWave Whether the Gym Leader always uses Tera (true), or only Teras after {@linkcode GYM_LEADER_TERA_WAVE} (false). Defaults to false. * @param ignoreMinTeraWave Whether the Gym Leader always uses Tera (true), or only Teras after {@linkcode GYM_LEADER_TERA_WAVE} (false). Defaults to false.
* @param teraSlot Optional, sets the party member in this slot to Terastallize. Wraps based on party size. * @param teraSlot Optional, sets the party member in this slot to Terastallize. Wraps based on party size.
* @returns {TrainerConfig} The updated TrainerConfig instance. * @returns The updated TrainerConfig instance.
*/ */
initForGymLeader( initForGymLeader(
signatureSpecies: (SpeciesId | SpeciesId[])[], signatureSpecies: (SpeciesId | SpeciesId[])[],
@ -748,9 +748,9 @@ export class TrainerConfig {
/** /**
* Initializes the trainer configuration for a Champion. * Initializes the trainer configuration for a Champion.
* @param {SpeciesId | SpeciesId[]} signatureSpecies The signature species for the Champion. * @param signatureSpecies The signature species for the Champion.
* @param isMale Whether the Champion is Male or Female (for localization of the title). * @param isMale Whether the Champion is Male or Female (for localization of the title).
* @returns {TrainerConfig} The updated TrainerConfig instance. * @returns The updated TrainerConfig instance.
*/ */
initForChampion(isMale: boolean): TrainerConfig { initForChampion(isMale: boolean): TrainerConfig {
// Check if the internationalization (i18n) system is initialized. // Check if the internationalization (i18n) system is initialized.
@ -785,7 +785,7 @@ export class TrainerConfig {
/** /**
* Sets a localized name for the trainer. This should only be used for trainers that dont use a "initFor" function and are considered "named" trainers * Sets a localized name for the trainer. This should only be used for trainers that dont use a "initFor" function and are considered "named" trainers
* @param name - The name of the trainer. * @param name - The name of the trainer.
* @returns {TrainerConfig} The updated TrainerConfig instance. * @returns The updated TrainerConfig instance.
*/ */
setLocalizedName(name: string): TrainerConfig { setLocalizedName(name: string): TrainerConfig {
// Check if the internationalization (i18n) system is initialized. // Check if the internationalization (i18n) system is initialized.
@ -798,9 +798,9 @@ export class TrainerConfig {
/** /**
* Retrieves the title for the trainer based on the provided trainer slot and variant. * Retrieves the title for the trainer based on the provided trainer slot and variant.
* @param {TrainerSlot} trainerSlot - The slot to determine which title to use. Defaults to TrainerSlot.NONE. * @param trainerSlot - The slot to determine which title to use. Defaults to TrainerSlot.NONE.
* @param {TrainerVariant} variant - The variant of the trainer to determine the specific title. * @param variant - The variant of the trainer to determine the specific title.
* @returns {string} - The title of the trainer. * @returns - The title of the trainer.
*/ */
getTitle(trainerSlot: TrainerSlot = TrainerSlot.NONE, variant: TrainerVariant): string { getTitle(trainerSlot: TrainerSlot = TrainerSlot.NONE, variant: TrainerVariant): string {
const ret = this.name; const ret = this.name;

View File

@ -29,7 +29,7 @@ export enum MoveFlags {
SLICING_MOVE = 1 << 8, SLICING_MOVE = 1 << 8,
/** /**
* Indicates a move should be affected by {@linkcode AbilityId.RECKLESS} * Indicates a move should be affected by {@linkcode AbilityId.RECKLESS}
* @see {@linkcode Move.recklessMove()} * @see {@linkcode Move.recklessMove}
*/ */
RECKLESS_MOVE = 1 << 9, RECKLESS_MOVE = 1 << 9,
/** Indicates a move should be affected by {@linkcode AbilityId.BULLETPROOF} */ /** Indicates a move should be affected by {@linkcode AbilityId.BULLETPROOF} */

View File

@ -16,10 +16,7 @@ export enum ArenaEventType {
TAG_REMOVED = "onTagRemoved", TAG_REMOVED = "onTagRemoved",
} }
/** /** Base container class for all {@linkcode ArenaEventType} events */
* Base container class for all {@linkcode ArenaEventType} events
* @extends Event
*/
export class ArenaEvent extends Event { export class ArenaEvent extends Event {
/** The total duration of the {@linkcode ArenaEventType} */ /** The total duration of the {@linkcode ArenaEventType} */
public duration: number; public duration: number;
@ -29,10 +26,7 @@ export class ArenaEvent extends Event {
this.duration = duration; this.duration = duration;
} }
} }
/** /** Container class for {@linkcode ArenaEventType.WEATHER_CHANGED} events */
* Container class for {@linkcode ArenaEventType.WEATHER_CHANGED} events
* @extends ArenaEvent
*/
export class WeatherChangedEvent extends ArenaEvent { export class WeatherChangedEvent extends ArenaEvent {
/** The {@linkcode WeatherType} being overridden */ /** The {@linkcode WeatherType} being overridden */
public oldWeatherType: WeatherType; public oldWeatherType: WeatherType;
@ -45,10 +39,7 @@ export class WeatherChangedEvent extends ArenaEvent {
this.newWeatherType = newWeatherType; this.newWeatherType = newWeatherType;
} }
} }
/** /** Container class for {@linkcode ArenaEventType.TERRAIN_CHANGED} events */
* Container class for {@linkcode ArenaEventType.TERRAIN_CHANGED} events
* @extends ArenaEvent
*/
export class TerrainChangedEvent extends ArenaEvent { export class TerrainChangedEvent extends ArenaEvent {
/** The {@linkcode TerrainType} being overridden */ /** The {@linkcode TerrainType} being overridden */
public oldTerrainType: TerrainType; public oldTerrainType: TerrainType;
@ -62,10 +53,7 @@ export class TerrainChangedEvent extends ArenaEvent {
} }
} }
/** /** Container class for {@linkcode ArenaEventType.TAG_ADDED} events */
* Container class for {@linkcode ArenaEventType.TAG_ADDED} events
* @extends ArenaEvent
*/
export class TagAddedEvent extends ArenaEvent { export class TagAddedEvent extends ArenaEvent {
/** The {@linkcode ArenaTagType} being added */ /** The {@linkcode ArenaTagType} being added */
public arenaTagType: ArenaTagType; public arenaTagType: ArenaTagType;
@ -91,10 +79,7 @@ export class TagAddedEvent extends ArenaEvent {
this.arenaTagMaxLayers = arenaTagMaxLayers!; // TODO: is this bang correct? this.arenaTagMaxLayers = arenaTagMaxLayers!; // TODO: is this bang correct?
} }
} }
/** /** Container class for {@linkcode ArenaEventType.TAG_REMOVED} events */
* Container class for {@linkcode ArenaEventType.TAG_REMOVED} events
* @extends ArenaEvent
*/
export class TagRemovedEvent extends ArenaEvent { export class TagRemovedEvent extends ArenaEvent {
/** The {@linkcode ArenaTagType} being removed */ /** The {@linkcode ArenaTagType} being removed */
public arenaTagType: ArenaTagType; public arenaTagType: ArenaTagType;

View File

@ -43,10 +43,7 @@ export enum BattleSceneEventType {
NEW_ARENA = "onNewArena", NEW_ARENA = "onNewArena",
} }
/** /** Container class for {@linkcode BattleSceneEventType.CANDY_UPGRADE_NOTIFICATION_CHANGED} events */
* Container class for {@linkcode BattleSceneEventType.CANDY_UPGRADE_NOTIFICATION_CHANGED} events
* @extends Event
*/
export class CandyUpgradeNotificationChangedEvent extends Event { export class CandyUpgradeNotificationChangedEvent extends Event {
/** The new value the setting was changed to */ /** The new value the setting was changed to */
public newValue: number; public newValue: number;
@ -57,10 +54,7 @@ export class CandyUpgradeNotificationChangedEvent extends Event {
} }
} }
/** /** Container class for {@linkcode BattleSceneEventType.MOVE_USED} events */
* Container class for {@linkcode BattleSceneEventType.MOVE_USED} events
* @extends Event
*/
export class MoveUsedEvent extends Event { export class MoveUsedEvent extends Event {
/** The ID of the {@linkcode Pokemon} that used the {@linkcode Move} */ /** The ID of the {@linkcode Pokemon} that used the {@linkcode Move} */
public pokemonId: number; public pokemonId: number;
@ -76,10 +70,7 @@ export class MoveUsedEvent extends Event {
this.ppUsed = ppUsed; this.ppUsed = ppUsed;
} }
} }
/** /** Container class for {@linkcode BattleSceneEventType.BERRY_USED} events */
* Container class for {@linkcode BattleSceneEventType.BERRY_USED} events
* @extends Event
*/
export class BerryUsedEvent extends Event { export class BerryUsedEvent extends Event {
/** The {@linkcode BerryModifier} being used */ /** The {@linkcode BerryModifier} being used */
public berryModifier: BerryModifier; public berryModifier: BerryModifier;
@ -90,28 +81,19 @@ export class BerryUsedEvent extends Event {
} }
} }
/** /** Container class for {@linkcode BattleSceneEventType.ENCOUNTER_PHASE} events */
* Container class for {@linkcode BattleSceneEventType.ENCOUNTER_PHASE} events
* @extends Event
*/
export class EncounterPhaseEvent extends Event { export class EncounterPhaseEvent extends Event {
constructor() { constructor() {
super(BattleSceneEventType.ENCOUNTER_PHASE); super(BattleSceneEventType.ENCOUNTER_PHASE);
} }
} }
/** /** Container class for {@linkcode BattleSceneEventType.TURN_INIT} events */
* Container class for {@linkcode BattleSceneEventType.TURN_INIT} events
* @extends Event
*/
export class TurnInitEvent extends Event { export class TurnInitEvent extends Event {
constructor() { constructor() {
super(BattleSceneEventType.TURN_INIT); super(BattleSceneEventType.TURN_INIT);
} }
} }
/** /** Container class for {@linkcode BattleSceneEventType.TURN_END} events */
* Container class for {@linkcode BattleSceneEventType.TURN_END} events
* @extends Event
*/
export class TurnEndEvent extends Event { export class TurnEndEvent extends Event {
/** The amount of turns in the current battle */ /** The amount of turns in the current battle */
public turnCount: number; public turnCount: number;
@ -121,10 +103,7 @@ export class TurnEndEvent extends Event {
this.turnCount = turnCount; this.turnCount = turnCount;
} }
} }
/** /** Container class for {@linkcode BattleSceneEventType.NEW_ARENA} events */
* Container class for {@linkcode BattleSceneEventType.NEW_ARENA} events
* @extends Event
*/
export class NewArenaEvent extends Event { export class NewArenaEvent extends Event {
constructor() { constructor() {
super(BattleSceneEventType.NEW_ARENA); super(BattleSceneEventType.NEW_ARENA);

View File

@ -8,7 +8,6 @@ export enum EggEventType {
/** /**
* Container class for {@linkcode EggEventType.EGG_COUNT_CHANGED} events * Container class for {@linkcode EggEventType.EGG_COUNT_CHANGED} events
* @extends Event
*/ */
export class EggCountChangedEvent extends Event { export class EggCountChangedEvent extends Event {
/** The updated egg count. */ /** The updated egg count. */

View File

@ -732,14 +732,12 @@ export class Arena {
* Attempt to get a tag from the Arena via {@linkcode getTagOnSide} that applies to both sides * Attempt to get a tag from the Arena via {@linkcode getTagOnSide} that applies to both sides
* @param tagType - The {@linkcode ArenaTagType} to retrieve * @param tagType - The {@linkcode ArenaTagType} to retrieve
* @returns The existing {@linkcode ArenaTag}, or `undefined` if not present. * @returns The existing {@linkcode ArenaTag}, or `undefined` if not present.
* @overload
*/ */
getTag(tagType: ArenaTagType): ArenaTag | undefined; getTag(tagType: ArenaTagType): ArenaTag | undefined;
/** /**
* Attempt to get a tag from the Arena via {@linkcode getTagOnSide} that applies to both sides * Attempt to get a tag from the Arena via {@linkcode getTagOnSide} that applies to both sides
* @param tagType - The constructor of the {@linkcode ArenaTag} to retrieve * @param tagType - The constructor of the {@linkcode ArenaTag} to retrieve
* @returns The existing {@linkcode ArenaTag}, or `undefined` if not present. * @returns The existing {@linkcode ArenaTag}, or `undefined` if not present.
* @overload
*/ */
getTag<T extends ArenaTag>(tagType: Constructor<T> | AbstractConstructor<T>): T | undefined; getTag<T extends ArenaTag>(tagType: Constructor<T> | AbstractConstructor<T>): T | undefined;
getTag(tagType: ArenaTagType | Constructor<ArenaTag> | AbstractConstructor<ArenaTag>): ArenaTag | undefined { getTag(tagType: ArenaTagType | Constructor<ArenaTag> | AbstractConstructor<ArenaTag>): ArenaTag | undefined {

View File

@ -137,13 +137,13 @@ import { loadMoveAnimations } from "#sprites/pokemon-asset-loader";
import type { Variant } from "#sprites/variant"; import type { Variant } from "#sprites/variant";
import { populateVariantColors, variantColorCache, variantData } from "#sprites/variant"; import { populateVariantColors, variantColorCache, variantData } from "#sprites/variant";
import { achvs } from "#system/achv"; import { achvs } from "#system/achv";
import type { StarterDataEntry, StarterMoveset } from "#system/game-data";
import type { PokemonData } from "#system/pokemon-data"; import type { PokemonData } from "#system/pokemon-data";
import { RibbonData } from "#system/ribbons/ribbon-data"; import { RibbonData } from "#system/ribbons/ribbon-data";
import { awardRibbonsToSpeciesLine } from "#system/ribbons/ribbon-methods"; import { awardRibbonsToSpeciesLine } from "#system/ribbons/ribbon-methods";
import type { AbAttrMap, AbAttrString, TypeMultiplierAbAttrParams } from "#types/ability-types"; import type { AbAttrMap, AbAttrString, TypeMultiplierAbAttrParams } from "#types/ability-types";
import type { DamageCalculationResult, DamageResult } from "#types/damage-result"; import type { DamageCalculationResult, DamageResult } from "#types/damage-result";
import type { IllusionData } from "#types/illusion-data"; import type { IllusionData } from "#types/illusion-data";
import type { StarterDataEntry, StarterMoveset } from "#types/save-data";
import type { TurnMove } from "#types/turn-move"; import type { TurnMove } from "#types/turn-move";
import { BattleInfo } from "#ui/battle-info"; import { BattleInfo } from "#ui/battle-info";
import { EnemyBattleInfo } from "#ui/enemy-battle-info"; import { EnemyBattleInfo } from "#ui/enemy-battle-info";
@ -2647,11 +2647,11 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
/** /**
* Gets all level up moves in a given range for a particular pokemon. * Gets all level up moves in a given range for a particular pokemon.
* @param {number} startingLevel Don't include moves below this level * @param startingLevel Don't include moves below this level
* @param {boolean} includeEvolutionMoves Whether to include evolution moves * @param includeEvolutionMoves Whether to include evolution moves
* @param {boolean} simulateEvolutionChain Whether to include moves from prior evolutions * @param simulateEvolutionChain Whether to include moves from prior evolutions
* @param {boolean} includeRelearnerMoves Whether to include moves that would require a relearner. Note the move relearner inherently allows evolution moves * @param includeRelearnerMoves Whether to include moves that would require a relearner. Note the move relearner inherently allows evolution moves
* @returns {LevelMoves} A list of moves and the levels they can be learned at * @returns A list of moves and the levels they can be learned at
*/ */
getLevelMoves( getLevelMoves(
startingLevel?: number, startingLevel?: number,
@ -3209,9 +3209,55 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
Math.ceil(Math.pow(m[1], weightMultiplier) * 100), Math.ceil(Math.pow(m[1], weightMultiplier) * 100),
]); ]);
const STAB_BLACKLIST: ReadonlySet<MoveId> = new Set([
MoveId.BEAT_UP,
MoveId.BELCH,
MoveId.BIDE,
MoveId.COMEUPPANCE,
MoveId.COUNTER,
MoveId.DOOM_DESIRE,
MoveId.DRAGON_RAGE,
MoveId.DREAM_EATER,
MoveId.ENDEAVOR,
MoveId.EXPLOSION,
MoveId.FAKE_OUT,
MoveId.FIRST_IMPRESSION,
MoveId.FISSURE,
MoveId.FLING,
MoveId.FOCUS_PUNCH,
MoveId.FUTURE_SIGHT,
MoveId.GUILLOTINE,
MoveId.HOLD_BACK,
MoveId.HORN_DRILL,
MoveId.LAST_RESORT,
MoveId.METAL_BURST,
MoveId.MIRROR_COAT,
MoveId.MISTY_EXPLOSION,
MoveId.NATURAL_GIFT,
MoveId.NATURES_MADNESS,
MoveId.NIGHT_SHADE,
MoveId.PSYWAVE,
MoveId.RUINATION,
MoveId.SELF_DESTRUCT,
MoveId.SHEER_COLD,
MoveId.SHELL_TRAP,
MoveId.SKY_DROP,
MoveId.SNORE,
MoveId.SONIC_BOOM,
MoveId.SPIT_UP,
MoveId.STEEL_BEAM,
MoveId.STEEL_ROLLER,
MoveId.SUPER_FANG,
MoveId.SYNCHRONOISE,
MoveId.UPPER_HAND,
]);
// All Pokemon force a STAB move first // All Pokemon force a STAB move first
const stabMovePool = baseWeights.filter( const stabMovePool = baseWeights.filter(
m => allMoves[m[0]].category !== MoveCategory.STATUS && this.isOfType(allMoves[m[0]].type), m =>
allMoves[m[0]].category !== MoveCategory.STATUS
&& this.isOfType(allMoves[m[0]].type)
&& !STAB_BLACKLIST.has(m[0]),
); );
if (stabMovePool.length > 0) { if (stabMovePool.length > 0) {
@ -3224,7 +3270,9 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
this.moveset.push(new PokemonMove(stabMovePool[index][0])); this.moveset.push(new PokemonMove(stabMovePool[index][0]));
} else { } else {
// If there are no damaging STAB moves, just force a random damaging move // If there are no damaging STAB moves, just force a random damaging move
const attackMovePool = baseWeights.filter(m => allMoves[m[0]].category !== MoveCategory.STATUS); const attackMovePool = baseWeights.filter(
m => allMoves[m[0]].category !== MoveCategory.STATUS && !STAB_BLACKLIST.has(m[0]),
);
if (attackMovePool.length > 0) { if (attackMovePool.length > 0) {
const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0); const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0);
let rand = randSeedInt(totalWeight); let rand = randSeedInt(totalWeight);
@ -3261,7 +3309,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
} else if (allMoves[m[0]].category !== MoveCategory.STATUS) { } else if (allMoves[m[0]].category !== MoveCategory.STATUS) {
ret = Math.ceil( ret = Math.ceil(
(m[1] / Math.max(Math.pow(4, this.moveset.filter(mo => (mo.getMove().power ?? 0) > 1).length) / 8, 0.5)) (m[1] / Math.max(Math.pow(4, this.moveset.filter(mo => (mo.getMove().power ?? 0) > 1).length) / 8, 0.5))
* (this.isOfType(allMoves[m[0]].type) ? 20 : 1), * (this.isOfType(allMoves[m[0]].type) && !STAB_BLACKLIST.has(m[0]) ? 20 : 1),
); );
} else { } else {
ret = m[1]; ret = m[1];
@ -3448,7 +3496,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
* @param isCritical determines whether a critical hit has occurred or not (`false` by default) * @param isCritical determines whether a critical hit has occurred or not (`false` by default)
* @param simulated determines whether effects are applied without altering game state (`true` by default) * @param simulated determines whether effects are applied without altering game state (`true` by default)
* @param ignoreHeldItems determines whether this Pokemon's held items should be ignored during the stat calculation, default `false` * @param ignoreHeldItems determines whether this Pokemon's held items should be ignored during the stat calculation, default `false`
* @return the stat stage multiplier to be used for effective stat calculation * @returns the stat stage multiplier to be used for effective stat calculation
*/ */
getStatStageMultiplier( getStatStageMultiplier(
stat: EffectiveStat, stat: EffectiveStat,
@ -3504,8 +3552,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
* This method considers various factors such as the user's accuracy level, the target's evasion level, * This method considers various factors such as the user's accuracy level, the target's evasion level,
* abilities, and modifiers to compute the final accuracy multiplier. * abilities, and modifiers to compute the final accuracy multiplier.
* *
* @param target {@linkcode Pokemon} - The target Pokémon against which the move is used. * @param target - The target Pokémon against which the move is used.
* @param sourceMove {@linkcode Move} - The move being used by the user. * @param sourceMove - The move being used by the user.
* @returns The calculated accuracy multiplier. * @returns The calculated accuracy multiplier.
*/ */
getAccuracyMultiplier(target: Pokemon, sourceMove: Move): number { getAccuracyMultiplier(target: Pokemon, sourceMove: Move): number {
@ -4019,7 +4067,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
*/ */
getCriticalHitResult(source: Pokemon, move: Move): boolean { getCriticalHitResult(source: Pokemon, move: Move): boolean {
if (move.hasAttr("FixedDamageAttr")) { if (move.hasAttr("FixedDamageAttr")) {
// fixed damage moves (Dragon Rage, etc.) will nevet crit // fixed damage moves (Dragon Rage, etc.) will never crit
return false; return false;
} }
@ -4243,18 +4291,10 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
return false; return false;
} }
/**@overload */
getTag(tagType: BattlerTagType.GRUDGE): GrudgeTag | undefined; getTag(tagType: BattlerTagType.GRUDGE): GrudgeTag | undefined;
/** @overload */
getTag(tagType: BattlerTagType.SUBSTITUTE): SubstituteTag | undefined; getTag(tagType: BattlerTagType.SUBSTITUTE): SubstituteTag | undefined;
/** @overload */
getTag(tagType: BattlerTagType): BattlerTag | undefined; getTag(tagType: BattlerTagType): BattlerTag | undefined;
/** @overload */
getTag<T extends BattlerTag>(tagType: Constructor<T>): T | undefined; getTag<T extends BattlerTag>(tagType: Constructor<T>): T | undefined;
getTag(tagType: BattlerTagType | Constructor<BattlerTag>): BattlerTag | undefined { getTag(tagType: BattlerTagType | Constructor<BattlerTag>): BattlerTag | undefined {
return typeof tagType === "function" return typeof tagType === "function"
? this.summonData.tags.find(t => t instanceof tagType) ? this.summonData.tags.find(t => t instanceof tagType)
@ -4400,7 +4440,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
* @param user - The move user * @param user - The move user
* @param target - The target of the move * @param target - The target of the move
* *
* @returns {boolean} `true` if the move is disabled for this Pokemon due to the player's target selection * @returns `true` if the move is disabled for this Pokemon due to the player's target selection
* *
* @see {@linkcode MoveRestrictionBattlerTag} * @see {@linkcode MoveRestrictionBattlerTag}
*/ */
@ -5187,7 +5227,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
/** /**
* Reset a {@linkcode Pokemon}'s {@linkcode PokemonWaveData | waveData}. * Reset a {@linkcode Pokemon}'s {@linkcode PokemonWaveData | waveData}.
* Should be called upon starting a new wave in addition to whenever an arena transition occurs. * Should be called upon starting a new wave in addition to whenever an arena transition occurs.
* @see {@linkcode resetBattleAndWaveData()} * @see {@linkcode resetBattleAndWaveData}
*/ */
resetWaveData(): void { resetWaveData(): void {
this.waveData = new PokemonWaveData(); this.waveData = new PokemonWaveData();
@ -5622,7 +5662,6 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
/** /**
* Generates a random number using the current battle's seed, or the global seed if `globalScene.currentBattle` is falsy * Generates a random number using the current battle's seed, or the global seed if `globalScene.currentBattle` is falsy
* <!-- @import "../battle".Battle -->
* This calls either {@linkcode BattleScene.randBattleSeedInt}({@linkcode range}, {@linkcode min}) in `src/battle-scene.ts` * This calls either {@linkcode BattleScene.randBattleSeedInt}({@linkcode range}, {@linkcode min}) in `src/battle-scene.ts`
* which calls {@linkcode Battle.randSeedInt}({@linkcode range}, {@linkcode min}) in `src/battle.ts` * which calls {@linkcode Battle.randSeedInt}({@linkcode range}, {@linkcode min}) in `src/battle.ts`
* which calls {@linkcode randSeedInt randSeedInt}({@linkcode range}, {@linkcode min}) in `src/utils.ts`, * which calls {@linkcode randSeedInt randSeedInt}({@linkcode range}, {@linkcode min}) in `src/utils.ts`,

View File

@ -315,8 +315,8 @@ export class GameMode implements GameModeConfig {
/** /**
* Checks whether there is a fixed battle on this gamemode on a given wave. * Checks whether there is a fixed battle on this gamemode on a given wave.
* @param {number} waveIndex The wave to check. * @param waveIndex The wave to check.
* @returns {boolean} If this game mode has a fixed battle on this wave * @returns If this game mode has a fixed battle on this wave
*/ */
isFixedBattle(waveIndex: number): boolean { isFixedBattle(waveIndex: number): boolean {
const dummyConfig = new FixedBattleConfig(); const dummyConfig = new FixedBattleConfig();
@ -328,8 +328,8 @@ export class GameMode implements GameModeConfig {
/** /**
* Returns the config for the fixed battle for a particular wave. * Returns the config for the fixed battle for a particular wave.
* @param {number} waveIndex The wave to check. * @param waveIndex The wave to check.
* @returns {boolean} The fixed battle for this wave. * @returns The fixed battle for this wave.
*/ */
getFixedBattle(waveIndex: number): FixedBattleConfig { getFixedBattle(waveIndex: number): FixedBattleConfig {
const challengeConfig = new FixedBattleConfig(); const challengeConfig = new FixedBattleConfig();

View File

@ -131,7 +131,6 @@ export class LoadingScene extends SceneBase {
this.loadAtlas("party_transfer", "ui"); this.loadAtlas("party_transfer", "ui");
this.loadImage("summary_bg", "ui"); this.loadImage("summary_bg", "ui");
this.loadImage("summary_overlay_shiny", "ui");
this.loadImage("summary_profile", "ui"); this.loadImage("summary_profile", "ui");
this.loadImage("summary_profile_prompt_z", "ui"); // The pixel Z button prompt 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_prompt_a", "ui"); // The pixel A button prompt
@ -155,6 +154,7 @@ export class LoadingScene extends SceneBase {
this.loadImage("select_gen_cursor", "ui"); this.loadImage("select_gen_cursor", "ui");
this.loadImage("select_gen_cursor_highlight", "ui"); this.loadImage("select_gen_cursor_highlight", "ui");
this.loadImage("language_icon", "ui");
this.loadImage("saving_icon", "ui"); this.loadImage("saving_icon", "ui");
this.loadImage("discord", "ui"); this.loadImage("discord", "ui");
this.loadImage("google", "ui"); this.loadImage("google", "ui");

View File

@ -6,8 +6,8 @@ import i18next from "i18next";
/** /**
* Retrieves the Pokemon's name, potentially with an affix indicating its role (wild or foe) in the current battle context, translated * Retrieves the Pokemon's name, potentially with an affix indicating its role (wild or foe) in the current battle context, translated
* @param pokemon {@linkcode Pokemon} name and battle context will be retrieved from this instance * @param pokemon {@linkcode Pokemon} name and battle context will be retrieved from this instance
* @param {boolean} useIllusion - Whether we want the name of the illusion or not. Default value : true * @param useIllusion - Whether we want the name of the illusion or not. Default value : true
* @returns {string} ex: "Wild Gengar", "Ectoplasma sauvage" * @returns ex: "Wild Gengar", "Ectoplasma sauvage"
*/ */
export function getPokemonNameWithAffix(pokemon: Pokemon | undefined, useIllusion = true): string { export function getPokemonNameWithAffix(pokemon: Pokemon | undefined, useIllusion = true): string {
if (!pokemon) { if (!pokemon) {

View File

@ -150,7 +150,7 @@ export class ModifierType {
/** /**
* Checks if the modifier type is of a specific type * Checks if the modifier type is of a specific type
* @param modifierType - The type to check against * @param modifierType - The type to check against
* @return Whether the modifier type is of the specified type * @returns Whether the modifier type is of the specified type
*/ */
public is<K extends ModifierTypeString>(modifierType: K): this is ModifierTypeInstanceMap[K] { public is<K extends ModifierTypeString>(modifierType: K): this is ModifierTypeInstanceMap[K] {
const targetType = ModifierTypeConstructorMap[modifierType]; const targetType = ModifierTypeConstructorMap[modifierType];
@ -874,11 +874,7 @@ export class AttackTypeBoosterModifierType
export type SpeciesStatBoosterItem = keyof typeof SpeciesStatBoosterModifierTypeGenerator.items; export type SpeciesStatBoosterItem = keyof typeof SpeciesStatBoosterModifierTypeGenerator.items;
/** /** Modifier type for {@linkcode SpeciesStatBoosterModifier} */
* Modifier type for {@linkcode SpeciesStatBoosterModifier}
* @extends PokemonHeldItemModifierType
* @implements GeneratedPersistentModifierType
*/
export class SpeciesStatBoosterModifierType export class SpeciesStatBoosterModifierType
extends PokemonHeldItemModifierType extends PokemonHeldItemModifierType
implements GeneratedPersistentModifierType implements GeneratedPersistentModifierType
@ -1396,7 +1392,6 @@ class TempStatStageBoosterModifierTypeGenerator extends ModifierTypeGenerator {
* Modifier type generator for {@linkcode SpeciesStatBoosterModifierType}, which * Modifier type generator for {@linkcode SpeciesStatBoosterModifierType}, which
* encapsulates the logic for weighting the most useful held item from * encapsulates the logic for weighting the most useful held item from
* the current list of {@linkcode items}. * the current list of {@linkcode items}.
* @extends ModifierTypeGenerator
*/ */
class SpeciesStatBoosterModifierTypeGenerator extends ModifierTypeGenerator { class SpeciesStatBoosterModifierTypeGenerator extends ModifierTypeGenerator {
/** Object comprised of the currently available species-based stat boosting held items */ /** Object comprised of the currently available species-based stat boosting held items */

View File

@ -73,8 +73,8 @@ export class ModifierBar extends Phaser.GameObjects.Container {
/** /**
* Method to update content displayed in {@linkcode ModifierBar} * Method to update content displayed in {@linkcode ModifierBar}
* @param {PersistentModifier[]} modifiers - The list of modifiers to be displayed in the {@linkcode ModifierBar} * @param modifiers - The list of modifiers to be displayed in the {@linkcode ModifierBar}
* @param {boolean} hideHeldItems - If set to "true", only modifiers not assigned to a Pokémon are displayed * @param hideHeldItems - If set to "true", only modifiers not assigned to a Pokémon are displayed
*/ */
updateModifiers(modifiers: PersistentModifier[], hideHeldItems = false) { updateModifiers(modifiers: PersistentModifier[], hideHeldItems = false) {
this.removeAll(true); this.removeAll(true);
@ -345,9 +345,6 @@ export class AddVoucherModifier extends ConsumableModifier {
* modifier will be removed. If a modifier of the same type is to be added, it * modifier will be removed. If a modifier of the same type is to be added, it
* will reset {@linkcode battleCount} back to {@linkcode maxBattles} of the * will reset {@linkcode battleCount} back to {@linkcode maxBattles} of the
* existing modifier instead of adding that modifier directly. * existing modifier instead of adding that modifier directly.
* @extends PersistentModifier
* @abstract
* @see {@linkcode add}
*/ */
export abstract class LapsingPersistentModifier extends PersistentModifier { export abstract class LapsingPersistentModifier extends PersistentModifier {
/** The maximum amount of battles the modifier will exist for */ /** The maximum amount of battles the modifier will exist for */
@ -458,8 +455,6 @@ export abstract class LapsingPersistentModifier extends PersistentModifier {
/** /**
* Modifier used for passive items, specifically lures, that * Modifier used for passive items, specifically lures, that
* temporarily increases the chance of a double battle. * temporarily increases the chance of a double battle.
* @extends LapsingPersistentModifier
* @see {@linkcode apply}
*/ */
export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier { export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier {
public declare type: DoubleBattleChanceBoosterModifierType; public declare type: DoubleBattleChanceBoosterModifierType;
@ -495,8 +490,6 @@ export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier
* Modifier used for party-wide items, specifically the X items, that * Modifier used for party-wide items, specifically the X items, that
* temporarily increases the stat stage multiplier of the corresponding * temporarily increases the stat stage multiplier of the corresponding
* {@linkcode TempBattleStat}. * {@linkcode TempBattleStat}.
* @extends LapsingPersistentModifier
* @see {@linkcode apply}
*/ */
export class TempStatStageBoosterModifier extends LapsingPersistentModifier { export class TempStatStageBoosterModifier extends LapsingPersistentModifier {
/** The stat whose stat stage multiplier will be temporarily increased */ /** The stat whose stat stage multiplier will be temporarily increased */
@ -562,8 +555,6 @@ export class TempStatStageBoosterModifier extends LapsingPersistentModifier {
/** /**
* Modifier used for party-wide items, namely Dire Hit, that * Modifier used for party-wide items, namely Dire Hit, that
* temporarily increments the critical-hit stage * temporarily increments the critical-hit stage
* @extends LapsingPersistentModifier
* @see {@linkcode apply}
*/ */
export class TempCritBoosterModifier extends LapsingPersistentModifier { export class TempCritBoosterModifier extends LapsingPersistentModifier {
clone() { clone() {
@ -818,8 +809,6 @@ export abstract class LapsingPokemonHeldItemModifier extends PokemonHeldItemModi
/** /**
* Modifier used for held items, specifically vitamins like Carbos, Hp Up, etc., that * Modifier used for held items, specifically vitamins like Carbos, Hp Up, etc., that
* increase the value of a given {@linkcode PermanentStat}. * increase the value of a given {@linkcode PermanentStat}.
* @extends PokemonHeldItemModifier
* @see {@linkcode apply}
*/ */
export class BaseStatModifier extends PokemonHeldItemModifier { export class BaseStatModifier extends PokemonHeldItemModifier {
protected stat: PermanentStat; protected stat: PermanentStat;
@ -1126,8 +1115,6 @@ export class PokemonIncrementingStatModifier extends PokemonHeldItemModifier {
/** /**
* Modifier used for held items that Applies {@linkcode Stat} boost(s) * Modifier used for held items that Applies {@linkcode Stat} boost(s)
* using a multiplier. * using a multiplier.
* @extends PokemonHeldItemModifier
* @see {@linkcode apply}
*/ */
export class StatBoosterModifier extends PokemonHeldItemModifier { export class StatBoosterModifier extends PokemonHeldItemModifier {
/** The stats that the held item boosts */ /** The stats that the held item boosts */
@ -1194,8 +1181,6 @@ export class StatBoosterModifier extends PokemonHeldItemModifier {
/** /**
* Modifier used for held items, specifically Eviolite, that apply * Modifier used for held items, specifically Eviolite, that apply
* {@linkcode Stat} boost(s) using a multiplier if the holder can evolve. * {@linkcode Stat} boost(s) using a multiplier if the holder can evolve.
* @extends StatBoosterModifier
* @see {@linkcode apply}
*/ */
export class EvolutionStatBoosterModifier extends StatBoosterModifier { export class EvolutionStatBoosterModifier extends StatBoosterModifier {
matchType(modifier: Modifier): boolean { matchType(modifier: Modifier): boolean {
@ -1216,13 +1201,16 @@ export class EvolutionStatBoosterModifier extends StatBoosterModifier {
/** /**
* Boosts the incoming stat value by a {@linkcode EvolutionStatBoosterModifier.multiplier} if the holder * Boosts the incoming stat value by a {@linkcode EvolutionStatBoosterModifier.multiplier} if the holder
* can evolve. Note that, if the holder is a fusion, they will receive * can evolve
*
* @remarks
* Note that, if the holder is a fusion, they will receive
* only half of the boost if either of the fused members are fully * only half of the boost if either of the fused members are fully
* evolved. However, if they are both unevolved, the full boost * evolved. However, if they are both unevolved, the full boost
* will apply. * will apply.
* @param pokemon {@linkcode Pokemon} that holds the item * @param pokemon - The `Pokemon` holding the item
* @param _stat {@linkcode Stat} The {@linkcode Stat} to be boosted * @param _stat - The `Stat` to be boosted
* @param statValue{@linkcode NumberHolder} that holds the resulting value of the stat * @param statValue - Holds the resulting value of the stat
* @returns `true` if the stat boost applies successfully, false otherwise * @returns `true` if the stat boost applies successfully, false otherwise
* @see shouldApply * @see shouldApply
*/ */
@ -1246,8 +1234,6 @@ export class EvolutionStatBoosterModifier extends StatBoosterModifier {
/** /**
* Modifier used for held items that Applies {@linkcode Stat} boost(s) using a * Modifier used for held items that Applies {@linkcode Stat} boost(s) using a
* multiplier if the holder is of a specific {@linkcode SpeciesId}. * multiplier if the holder is of a specific {@linkcode SpeciesId}.
* @extends StatBoosterModifier
* @see {@linkcode apply}
*/ */
export class SpeciesStatBoosterModifier extends StatBoosterModifier { export class SpeciesStatBoosterModifier extends StatBoosterModifier {
/** The species that the held item's stat boost(s) apply to */ /** The species that the held item's stat boost(s) apply to */
@ -1321,8 +1307,6 @@ export class SpeciesStatBoosterModifier extends StatBoosterModifier {
/** /**
* Modifier used for held items that apply critical-hit stage boost(s). * Modifier used for held items that apply critical-hit stage boost(s).
* @extends PokemonHeldItemModifier
* @see {@linkcode apply}
*/ */
export class CritBoosterModifier extends PokemonHeldItemModifier { export class CritBoosterModifier extends PokemonHeldItemModifier {
/** The amount of stages by which the held item increases the current critical-hit stage value */ /** The amount of stages by which the held item increases the current critical-hit stage value */
@ -1369,8 +1353,6 @@ export class CritBoosterModifier extends PokemonHeldItemModifier {
/** /**
* Modifier used for held items that apply critical-hit stage boost(s) * Modifier used for held items that apply critical-hit stage boost(s)
* if the holder is of a specific {@linkcode SpeciesId}. * if the holder is of a specific {@linkcode SpeciesId}.
* @extends CritBoosterModifier
* @see {@linkcode shouldApply}
*/ */
export class SpeciesCritBoosterModifier extends CritBoosterModifier { export class SpeciesCritBoosterModifier extends CritBoosterModifier {
/** The species that the held item's critical-hit stage boost applies to */ /** The species that the held item's critical-hit stage boost applies to */
@ -1694,8 +1676,6 @@ export class TurnHealModifier extends PokemonHeldItemModifier {
/** /**
* Modifier used for held items, namely Toxic Orb and Flame Orb, that apply a * Modifier used for held items, namely Toxic Orb and Flame Orb, that apply a
* set {@linkcode StatusEffect} at the end of a turn. * set {@linkcode StatusEffect} at the end of a turn.
* @extends PokemonHeldItemModifier
* @see {@linkcode apply}
*/ */
export class TurnStatusEffectModifier extends PokemonHeldItemModifier { export class TurnStatusEffectModifier extends PokemonHeldItemModifier {
/** The status effect to be applied by the held item */ /** The status effect to be applied by the held item */
@ -1721,7 +1701,7 @@ export class TurnStatusEffectModifier extends PokemonHeldItemModifier {
* would be the only item able to {@linkcode apply} successfully. * would be the only item able to {@linkcode apply} successfully.
* @override * @override
* @param modifier {@linkcode Modifier} being type tested * @param modifier {@linkcode Modifier} being type tested
* @return `true` if {@linkcode modifier} is an instance of * @returns `true` if {@linkcode modifier} is an instance of
* TurnStatusEffectModifier, false otherwise * TurnStatusEffectModifier, false otherwise
*/ */
matchType(modifier: Modifier): boolean { matchType(modifier: Modifier): boolean {
@ -1966,8 +1946,6 @@ export class PokemonInstantReviveModifier extends PokemonHeldItemModifier {
/** /**
* Modifier used for held items, namely White Herb, that restore adverse stat * Modifier used for held items, namely White Herb, that restore adverse stat
* stages in battle. * stages in battle.
* @extends PokemonHeldItemModifier
* @see {@linkcode apply}
*/ */
export class ResetNegativeStatStageModifier extends PokemonHeldItemModifier { export class ResetNegativeStatStageModifier extends PokemonHeldItemModifier {
matchType(modifier: Modifier) { matchType(modifier: Modifier) {
@ -2013,8 +1991,6 @@ export class ResetNegativeStatStageModifier extends PokemonHeldItemModifier {
/** /**
* Modifier used for held items, namely Mystical Rock, that extend the * Modifier used for held items, namely Mystical Rock, that extend the
* duration of weather and terrain effects. * duration of weather and terrain effects.
* @extends PokemonHeldItemModifier
* @see {@linkcode apply}
*/ */
export class FieldEffectModifier extends PokemonHeldItemModifier { export class FieldEffectModifier extends PokemonHeldItemModifier {
/** /**
@ -3400,8 +3376,6 @@ export class ExtraModifierModifier extends PersistentModifier {
/** /**
* Modifier used for timed boosts to the player's shop item rewards. * Modifier used for timed boosts to the player's shop item rewards.
* @extends LapsingPersistentModifier
* @see {@linkcode apply}
*/ */
export class TempExtraModifierModifier extends LapsingPersistentModifier { export class TempExtraModifierModifier extends LapsingPersistentModifier {
/** /**

View File

@ -220,7 +220,7 @@ export class CommandPhase extends FieldPhase {
if (!moveStatus.value) { if (!moveStatus.value) {
cannotSelectKey = "battle:moveCannotUseChallenge"; cannotSelectKey = "battle:moveCannotUseChallenge";
} else if (move.getPpRatio() === 0) { } else if (move.getPpRatio() === 0) {
cannotSelectKey = "battle:moveNoPP"; cannotSelectKey = "battle:moveNoPp";
} else if (move.getName().endsWith(" (N)")) { } else if (move.getName().endsWith(" (N)")) {
cannotSelectKey = "battle:moveNotImplemented"; cannotSelectKey = "battle:moveNotImplemented";
} else if (user.isMoveRestricted(move.moveId, user)) { } else if (user.isMoveRestricted(move.moveId, user)) {

View File

@ -11,7 +11,7 @@ import type { EggLapsePhase } from "#phases/egg-lapse-phase";
import { achvs } from "#system/achv"; import { achvs } from "#system/achv";
import { EggCounterContainer } from "#ui/containers/egg-counter-container"; import { EggCounterContainer } from "#ui/containers/egg-counter-container";
import { PokemonInfoContainer } from "#ui/containers/pokemon-info-container"; import { PokemonInfoContainer } from "#ui/containers/pokemon-info-container";
import type { EggHatchSceneHandler } from "#ui/handlers/egg-hatch-scene-handler"; import type { EggHatchSceneUiHandler } from "#ui/handlers/egg-hatch-scene-ui-handler";
import { fixedInt, getFrameMs, randInt } from "#utils/common"; import { fixedInt, getFrameMs, randInt } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
@ -32,7 +32,7 @@ export class EggHatchPhase extends Phase {
private eggCounterContainer: EggCounterContainer; private eggCounterContainer: EggCounterContainer;
/** The scene handler for egg hatching */ /** The scene handler for egg hatching */
private eggHatchHandler: EggHatchSceneHandler; private eggHatchHandler: EggHatchSceneUiHandler;
/** The phaser gameobject container that holds everything */ /** The phaser gameobject container that holds everything */
private eggHatchContainer: Phaser.GameObjects.Container; private eggHatchContainer: Phaser.GameObjects.Container;
/** The phaser image that is the background */ /** The phaser image that is the background */
@ -92,7 +92,7 @@ export class EggHatchPhase extends Phase {
globalScene.fadeOutBgm(undefined, false); globalScene.fadeOutBgm(undefined, false);
this.eggHatchHandler = globalScene.ui.getHandler() as EggHatchSceneHandler; this.eggHatchHandler = globalScene.ui.getHandler() as EggHatchSceneUiHandler;
this.eggHatchContainer = this.eggHatchHandler.eggHatchContainer; this.eggHatchContainer = this.eggHatchHandler.eggHatchContainer;

View File

@ -10,7 +10,7 @@ import { LearnMoveSituation } from "#enums/learn-move-situation";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { cos, sin } from "#field/anims"; import { cos, sin } from "#field/anims";
import type { PlayerPokemon, Pokemon } from "#field/pokemon"; import type { PlayerPokemon, Pokemon } from "#field/pokemon";
import type { EvolutionSceneHandler } from "#ui/handlers/evolution-scene-handler"; import type { EvolutionSceneUiHandler } from "#ui/handlers/evolution-scene-ui-handler";
import { fixedInt, getFrameMs, randInt } from "#utils/common"; import { fixedInt, getFrameMs, randInt } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
@ -29,7 +29,7 @@ export class EvolutionPhase extends Phase {
private evolution: SpeciesFormEvolution | null; private evolution: SpeciesFormEvolution | null;
private fusionSpeciesEvolved: boolean; // Whether the evolution is of the fused species private fusionSpeciesEvolved: boolean; // Whether the evolution is of the fused species
private evolutionBgm: AnySound | null; private evolutionBgm: AnySound | null;
private evolutionHandler: EvolutionSceneHandler; private evolutionHandler: EvolutionSceneUiHandler;
/** Container for all assets used by the scene. When the scene is cleared, the children within this are destroyed. */ /** 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 evolutionContainer: Phaser.GameObjects.Container;
@ -79,7 +79,7 @@ export class EvolutionPhase extends Phase {
* *
*/ */
private setupEvolutionAssets(): void { private setupEvolutionAssets(): void {
this.evolutionHandler = globalScene.ui.getHandler() as EvolutionSceneHandler; this.evolutionHandler = globalScene.ui.getHandler() as EvolutionSceneUiHandler;
this.evolutionContainer = this.evolutionHandler.evolutionContainer; this.evolutionContainer = this.evolutionHandler.evolutionContainer;
this.evolutionBaseBg = globalScene.add.image(0, 0, "default_bg").setOrigin(0); this.evolutionBaseBg = globalScene.add.image(0, 0, "default_bg").setOrigin(0);

View File

@ -16,13 +16,13 @@ import type { EndCardPhase } from "#phases/end-card-phase";
import { achvs, ChallengeAchv } from "#system/achv"; import { achvs, ChallengeAchv } from "#system/achv";
import { ArenaData } from "#system/arena-data"; import { ArenaData } from "#system/arena-data";
import { ChallengeData } from "#system/challenge-data"; import { ChallengeData } from "#system/challenge-data";
import type { SessionSaveData } from "#system/game-data";
import { ModifierData as PersistentModifierData } from "#system/modifier-data"; import { ModifierData as PersistentModifierData } from "#system/modifier-data";
import { PokemonData } from "#system/pokemon-data"; import { PokemonData } from "#system/pokemon-data";
import { RibbonData, type RibbonFlag } from "#system/ribbons/ribbon-data"; import { RibbonData, type RibbonFlag } from "#system/ribbons/ribbon-data";
import { awardRibbonsToSpeciesLine } from "#system/ribbons/ribbon-methods"; import { awardRibbonsToSpeciesLine } from "#system/ribbons/ribbon-methods";
import { TrainerData } from "#system/trainer-data"; import { TrainerData } from "#system/trainer-data";
import { trainerConfigs } from "#trainers/trainer-config"; import { trainerConfigs } from "#trainers/trainer-config";
import type { SessionSaveData } from "#types/save-data";
import { checkSpeciesValidForChallenge, isNuzlockeChallenge } from "#utils/challenge-utils"; import { checkSpeciesValidForChallenge, isNuzlockeChallenge } from "#utils/challenge-utils";
import { isLocal, isLocalServerConnected } from "#utils/common"; import { isLocal, isLocalServerConnected } from "#utils/common";
import { getPokemonSpecies } from "#utils/pokemon-utils"; import { getPokemonSpecies } from "#utils/pokemon-utils";

View File

@ -10,7 +10,7 @@ import { UiMode } from "#enums/ui-mode";
import type { Pokemon } from "#field/pokemon"; import type { Pokemon } from "#field/pokemon";
import type { Move } from "#moves/move"; import type { Move } from "#moves/move";
import { PlayerPartyMemberPokemonPhase } from "#phases/player-party-member-pokemon-phase"; import { PlayerPartyMemberPokemonPhase } from "#phases/player-party-member-pokemon-phase";
import { EvolutionSceneHandler } from "#ui/handlers/evolution-scene-handler"; import { EvolutionSceneUiHandler } from "#ui/handlers/evolution-scene-ui-handler";
import { SummaryUiMode } from "#ui/handlers/summary-ui-handler"; import { SummaryUiMode } from "#ui/handlers/summary-ui-handler";
import i18next from "i18next"; import i18next from "i18next";
@ -47,7 +47,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
} }
this.messageMode = this.messageMode =
globalScene.ui.getHandler() instanceof EvolutionSceneHandler ? UiMode.EVOLUTION_SCENE : UiMode.MESSAGE; globalScene.ui.getHandler() instanceof EvolutionSceneUiHandler ? UiMode.EVOLUTION_SCENE : UiMode.MESSAGE;
globalScene.ui.setMode(this.messageMode); globalScene.ui.setMode(this.messageMode);
// If the Pokemon has less than 4 moves, the new move is added to the largest empty moveset index // If the Pokemon has less than 4 moves, the new move is added to the largest empty moveset index
// If it has 4 moves, the phase then checks if the player wants to replace the move itself. // If it has 4 moves, the phase then checks if the player wants to replace the move itself.

View File

@ -932,7 +932,7 @@ export class MoveEffectPhase extends PokemonPhase {
msg = i18next.t("battle:hitResultNotVeryEffective"); msg = i18next.t("battle:hitResultNotVeryEffective");
break; break;
case HitResult.ONE_HIT_KO: case HitResult.ONE_HIT_KO:
msg = i18next.t("battle:hitResultOneHitKO"); msg = i18next.t("battle:hitResultOneHitKo");
break; break;
} }
if (msg) { if (msg) {

View File

@ -289,10 +289,7 @@ export class MysteryEncounterBattlePhase extends Phase {
this.doMysteryEncounterBattle(); this.doMysteryEncounterBattle();
} }
/** /** Get intro battle message for new battle */
* Gets intro battle message for new battle
* @private
*/
private getBattleMessage(): string { private getBattleMessage(): string {
const enemyField = globalScene.getEnemyField(); const enemyField = globalScene.getEnemyField();
const encounterMode = globalScene.currentBattle.mysteryEncounter!.encounterMode; const encounterMode = globalScene.currentBattle.mysteryEncounter!.encounterMode;
@ -323,8 +320,7 @@ export class MysteryEncounterBattlePhase extends Phase {
} }
/** /**
* Queues {@linkcode SummonPhase}s for the new battle, and handles trainer animations/dialogue if it's a Trainer battle * Queue {@linkcode SummonPhase}s for the new battle and handle trainer animations/dialogue for Trainer battles
* @private
*/ */
private doMysteryEncounterBattle() { private doMysteryEncounterBattle() {
const encounterMode = globalScene.currentBattle.mysteryEncounter!.encounterMode; const encounterMode = globalScene.currentBattle.mysteryEncounter!.encounterMode;
@ -401,7 +397,6 @@ export class MysteryEncounterBattlePhase extends Phase {
/** /**
* Initiate {@linkcode SummonPhase}s, {@linkcode ScanIvsPhase}, {@linkcode PostSummonPhase}s, etc. * Initiate {@linkcode SummonPhase}s, {@linkcode ScanIvsPhase}, {@linkcode PostSummonPhase}s, etc.
* @private
*/ */
private endBattleSetup() { private endBattleSetup() {
const enemyField = globalScene.getEnemyField(); const enemyField = globalScene.getEnemyField();
@ -450,10 +445,7 @@ export class MysteryEncounterBattlePhase extends Phase {
this.end(); this.end();
} }
/** /** Ease in enemy trainer */
* Ease in enemy trainer
* @private
*/
private showEnemyTrainer(): void { private showEnemyTrainer(): void {
// Show enemy trainer // Show enemy trainer
const trainer = globalScene.currentBattle.trainer; const trainer = globalScene.currentBattle.trainer;

View File

@ -14,8 +14,8 @@ import { Unlockables } from "#enums/unlockables";
import { getBiomeKey } from "#field/arena"; import { getBiomeKey } from "#field/arena";
import type { Modifier } from "#modifiers/modifier"; import type { Modifier } from "#modifiers/modifier";
import { getDailyRunStarterModifiers, regenerateModifierPoolThresholds } from "#modifiers/modifier-type"; import { getDailyRunStarterModifiers, regenerateModifierPoolThresholds } from "#modifiers/modifier-type";
import type { SessionSaveData } from "#system/game-data";
import { vouchers } from "#system/voucher"; import { vouchers } from "#system/voucher";
import type { SessionSaveData } from "#types/save-data";
import type { OptionSelectConfig, OptionSelectItem } from "#ui/handlers/abstract-option-select-ui-handler"; import type { OptionSelectConfig, OptionSelectItem } from "#ui/handlers/abstract-option-select-ui-handler";
import { SaveSlotUiMode } from "#ui/handlers/save-slot-select-ui-handler"; import { SaveSlotUiMode } from "#ui/handlers/save-slot-select-ui-handler";
import { isLocal, isLocalServerConnected, isNullOrUndefined } from "#utils/common"; import { isLocal, isLocalServerConnected, isNullOrUndefined } from "#utils/common";

View File

@ -1,5 +1,4 @@
import { ApiBase } from "#api/api-base"; import { ApiBase } from "#api/api-base";
import type { SessionSaveData } from "#system/game-data";
import type { import type {
ClearSessionSavedataRequest, ClearSessionSavedataRequest,
ClearSessionSavedataResponse, ClearSessionSavedataResponse,
@ -8,6 +7,7 @@ import type {
NewClearSessionSavedataRequest, NewClearSessionSavedataRequest,
UpdateSessionSavedataRequest, UpdateSessionSavedataRequest,
} from "#types/api/pokerogue-session-save-data-api"; } from "#types/api/pokerogue-session-save-data-api";
import type { SessionSaveData } from "#types/save-data";
/** /**
* A wrapper for PokéRogue session savedata API requests. * A wrapper for PokéRogue session savedata API requests.

View File

@ -1,6 +1,5 @@
import { pokerogueApi } from "#api/pokerogue-api"; import { pokerogueApi } from "#api/pokerogue-api";
import { clientSessionId, loggedInUser, updateUserInfo } from "#app/account"; import { clientSessionId, loggedInUser, updateUserInfo } from "#app/account";
import type { PokeballCounts } from "#app/battle-scene";
import { defaultStarterSpecies, saveKey } from "#app/constants"; import { defaultStarterSpecies, saveKey } from "#app/constants";
import { getGameMode } from "#app/game-mode"; import { getGameMode } from "#app/game-mode";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
@ -24,11 +23,9 @@ import { Device } from "#enums/devices";
import { DexAttr } from "#enums/dex-attr"; import { DexAttr } from "#enums/dex-attr";
import { GameDataType } from "#enums/game-data-type"; import { GameDataType } from "#enums/game-data-type";
import { GameModes } from "#enums/game-modes"; import { GameModes } from "#enums/game-modes";
import type { MoveId } from "#enums/move-id";
import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { Nature } from "#enums/nature"; import { Nature } from "#enums/nature";
import { PlayerGender } from "#enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
import type { PokemonType } from "#enums/pokemon-type";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import { TrainerVariant } from "#enums/trainer-variant"; import { TrainerVariant } from "#enums/trainer-variant";
@ -62,6 +59,19 @@ import {
import { VoucherType, vouchers } from "#system/voucher"; import { VoucherType, vouchers } from "#system/voucher";
import { trainerConfigs } from "#trainers/trainer-config"; import { trainerConfigs } from "#trainers/trainer-config";
import type { DexData, DexEntry } from "#types/dex-data"; import type { DexData, DexEntry } from "#types/dex-data";
import type {
AchvUnlocks,
DexAttrProps,
RunHistoryData,
SeenDialogues,
SessionSaveData,
StarterData,
SystemSaveData,
TutorialFlags,
Unlocks,
VoucherCounts,
VoucherUnlocks,
} from "#types/save-data";
import { RUN_HISTORY_LIMIT } from "#ui/handlers/run-history-ui-handler"; import { RUN_HISTORY_LIMIT } from "#ui/handlers/run-history-ui-handler";
import { applyChallenges } from "#utils/challenge-utils"; import { applyChallenges } from "#utils/challenge-utils";
import { executeIf, fixedInt, isLocal, NumberHolder, randInt, randSeedItem } from "#utils/common"; import { executeIf, fixedInt, isLocal, NumberHolder, randInt, randSeedItem } from "#utils/common";
@ -94,132 +104,6 @@ function getDataTypeKey(dataType: GameDataType, slotId = 0): string {
} }
} }
// TODO: Move all these exported interfaces to @types
export interface SystemSaveData {
trainerId: number;
secretId: number;
gender: PlayerGender;
dexData: DexData;
starterData: StarterData;
gameStats: GameStats;
unlocks: Unlocks;
achvUnlocks: AchvUnlocks;
voucherUnlocks: VoucherUnlocks;
voucherCounts: VoucherCounts;
eggs: EggData[];
gameVersion: string;
timestamp: number;
eggPity: number[];
unlockPity: number[];
}
export interface SessionSaveData {
seed: string;
playTime: number;
gameMode: GameModes;
party: PokemonData[];
enemyParty: PokemonData[];
modifiers: PersistentModifierData[];
enemyModifiers: PersistentModifierData[];
arena: ArenaData;
pokeballCounts: PokeballCounts;
money: number;
score: number;
waveIndex: number;
battleType: BattleType;
trainer: TrainerData;
gameVersion: string;
/** The player-chosen name of the run */
name: string;
timestamp: number;
challenges: ChallengeData[];
mysteryEncounterType: MysteryEncounterType | -1; // Only defined when current wave is ME,
mysteryEncounterSaveData: MysteryEncounterSaveData;
/**
* Counts the amount of pokemon fainted in your party during the current arena encounter.
*/
playerFaints: number;
}
interface Unlocks {
[key: number]: boolean;
}
export interface AchvUnlocks {
[key: string]: number;
}
export interface VoucherUnlocks {
[key: string]: number;
}
export interface VoucherCounts {
[type: string]: number;
}
export type StarterMoveset = [MoveId] | [MoveId, MoveId] | [MoveId, MoveId, MoveId] | [MoveId, MoveId, MoveId, MoveId];
export interface StarterFormMoveData {
[key: number]: StarterMoveset;
}
export interface StarterMoveData {
[key: number]: StarterMoveset | StarterFormMoveData;
}
export interface StarterAttributes {
nature?: number;
ability?: number;
variant?: number;
form?: number;
female?: boolean;
shiny?: boolean;
favorite?: boolean;
nickname?: string;
tera?: PokemonType;
}
export interface DexAttrProps {
shiny: boolean;
female: boolean;
variant: Variant;
formIndex: number;
}
export type RunHistoryData = Record<number, RunEntry>;
export interface RunEntry {
entry: SessionSaveData;
isVictory: boolean;
/*Automatically set to false at the moment - implementation TBD*/
isFavorite: boolean;
}
export interface StarterDataEntry {
moveset: StarterMoveset | StarterFormMoveData | null;
eggMoves: number;
candyCount: number;
friendship: number;
abilityAttr: number;
passiveAttr: number;
valueReduction: number;
classicWinCount: number;
}
export interface StarterData {
[key: number]: StarterDataEntry;
}
// TODO: Rework into a bitmask
export type TutorialFlags = {
[key in Tutorial]: boolean;
};
// TODO: Rework into a bitmask
export interface SeenDialogues {
[key: string]: boolean;
}
const systemShortKeys = { const systemShortKeys = {
seenAttr: "$sa", seenAttr: "$sa",
caughtAttr: "$ca", caughtAttr: "$ca",
@ -2002,9 +1886,7 @@ export class GameData {
}); });
} }
/** /** Return whether the root species of a given `PokemonSpecies` has been unlocked in the dex */
* Checks whether the root species of a given {@PokemonSpecies} has been unlocked in the dex
*/
isRootSpeciesUnlocked(species: PokemonSpecies): boolean { isRootSpeciesUnlocked(species: PokemonSpecies): boolean {
return !!this.dexData[species.getRootSpeciesId()]?.caughtAttr; return !!this.dexData[species.getRootSpeciesId()]?.caughtAttr;
} }

View File

@ -0,0 +1,101 @@
import { globalScene } from "#app/global-scene";
import type { SettingsDisplayUiHandler } from "#ui/settings-display-ui-handler";
import i18next from "i18next";
const cancelHandler = () => {
globalScene.ui.revertMode();
const handler = globalScene.ui.getHandler();
// Reset the cursor to the current language, if in the settings menu
if (handler && typeof (handler as SettingsDisplayUiHandler).setOptionCursor === "function") {
(handler as SettingsDisplayUiHandler).setOptionCursor(-1, 0, true);
}
};
const changeLocaleHandler = (locale: string): boolean => {
try {
i18next.changeLanguage(locale);
localStorage.setItem("prLang", locale);
cancelHandler();
// Reload the whole game to apply the new locale since also some constants are translated
window.location.reload();
return true;
} catch (error) {
console.error("Error changing locale:", error);
return false;
}
};
export const languageOptions = [
{
label: "English",
handler: () => changeLocaleHandler("en"),
},
{
label: "Español (ES)",
handler: () => changeLocaleHandler("es-ES"),
},
{
label: "Español (LATAM)",
handler: () => changeLocaleHandler("es-MX"),
},
{
label: "Français",
handler: () => changeLocaleHandler("fr"),
},
{
label: "Deutsch",
handler: () => changeLocaleHandler("de"),
},
{
label: "Italiano",
handler: () => changeLocaleHandler("it"),
},
{
label: "Português (BR)",
handler: () => changeLocaleHandler("pt-BR"),
},
{
label: "한국어",
handler: () => changeLocaleHandler("ko"),
},
{
label: "日本語",
handler: () => changeLocaleHandler("ja"),
},
{
label: "简体中文",
handler: () => changeLocaleHandler("zh-CN"),
},
{
label: "繁體中文",
handler: () => changeLocaleHandler("zh-TW"),
},
{
label: "Català (Needs Help)",
handler: () => changeLocaleHandler("ca"),
},
{
label: "Türkçe (Needs Help)",
handler: () => changeLocaleHandler("tr"),
},
{
label: "Русский (Needs Help)",
handler: () => changeLocaleHandler("ru"),
},
{
label: "Dansk (Needs Help)",
handler: () => changeLocaleHandler("da"),
},
{
label: "Română (Needs Help)",
handler: () => changeLocaleHandler("ro"),
},
{
label: "Tagalog (Needs Help)",
handler: () => changeLocaleHandler("tl"),
},
{
label: i18next.t("settings:back"),
handler: () => cancelHandler(),
},
];

View File

@ -6,10 +6,10 @@ import { PlayerGender } from "#enums/player-gender";
import { ShopCursorTarget } from "#enums/shop-cursor-target"; import { ShopCursorTarget } from "#enums/shop-cursor-target";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { CandyUpgradeNotificationChangedEvent } from "#events/battle-scene"; import { CandyUpgradeNotificationChangedEvent } from "#events/battle-scene";
import type { SettingsUiHandler } from "#ui/settings-ui-handler";
import { updateWindowType } from "#ui/ui-theme"; import { updateWindowType } from "#ui/ui-theme";
import { isLocal } from "#utils/common"; import { isLocal } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
import { languageOptions } from "./settings-language";
const VOLUME_OPTIONS: SettingOption[] = [ const VOLUME_OPTIONS: SettingOption[] = [
{ {
@ -120,6 +120,14 @@ export interface Setting {
default: number; default: number;
type: SettingType; type: SettingType;
requireReload?: boolean; requireReload?: boolean;
/**
* Specifies the behavior when navigating left/right at the boundaries of the option
*
* - `true`: the cursor will stay on the boundary instead of moving
* - `false`: the cursor will wrap to the other end of the options list
* @defaultValue `false`
*/
clamp?: boolean;
/** Whether the setting can be activated or not */ /** Whether the setting can be activated or not */
activatable?: boolean; activatable?: boolean;
/** Determines whether the setting should be hidden from the UI */ /** Determines whether the setting should be hidden from the UI */
@ -230,6 +238,7 @@ export const Setting: Array<Setting> = [
], ],
default: 3, default: 3,
type: SettingType.GENERAL, type: SettingType.GENERAL,
clamp: false,
}, },
{ {
key: SettingKeys.HP_Bar_Speed, key: SettingKeys.HP_Bar_Speed,
@ -639,6 +648,7 @@ export const Setting: Array<Setting> = [
options: VOLUME_OPTIONS, options: VOLUME_OPTIONS,
default: 5, default: 5,
type: SettingType.AUDIO, type: SettingType.AUDIO,
clamp: true,
}, },
{ {
key: SettingKeys.BGM_Volume, key: SettingKeys.BGM_Volume,
@ -646,6 +656,7 @@ export const Setting: Array<Setting> = [
options: VOLUME_OPTIONS, options: VOLUME_OPTIONS,
default: 10, default: 10,
type: SettingType.AUDIO, type: SettingType.AUDIO,
clamp: true,
}, },
{ {
key: SettingKeys.Field_Volume, key: SettingKeys.Field_Volume,
@ -653,6 +664,7 @@ export const Setting: Array<Setting> = [
options: VOLUME_OPTIONS, options: VOLUME_OPTIONS,
default: 10, default: 10,
type: SettingType.AUDIO, type: SettingType.AUDIO,
clamp: true,
}, },
{ {
key: SettingKeys.SE_Volume, key: SettingKeys.SE_Volume,
@ -660,6 +672,7 @@ export const Setting: Array<Setting> = [
options: VOLUME_OPTIONS, options: VOLUME_OPTIONS,
default: 10, default: 10,
type: SettingType.AUDIO, type: SettingType.AUDIO,
clamp: true,
}, },
{ {
key: SettingKeys.UI_Volume, key: SettingKeys.UI_Volume,
@ -667,6 +680,7 @@ export const Setting: Array<Setting> = [
options: VOLUME_OPTIONS, options: VOLUME_OPTIONS,
default: 10, default: 10,
type: SettingType.AUDIO, type: SettingType.AUDIO,
clamp: true,
}, },
{ {
key: SettingKeys.Battle_Music, key: SettingKeys.Battle_Music,
@ -897,98 +911,8 @@ export function setSetting(setting: string, value: number): boolean {
break; break;
case SettingKeys.Language: case SettingKeys.Language:
if (value && globalScene.ui) { if (value && globalScene.ui) {
const cancelHandler = () => {
globalScene.ui.revertMode();
(globalScene.ui.getHandler() as SettingsUiHandler).setOptionCursor(-1, 0, true);
};
const changeLocaleHandler = (locale: string): boolean => {
try {
i18next.changeLanguage(locale);
localStorage.setItem("prLang", locale);
cancelHandler();
// Reload the whole game to apply the new locale since also some constants are translated
window.location.reload();
return true;
} catch (error) {
console.error("Error changing locale:", error);
return false;
}
};
globalScene.ui.setOverlayMode(UiMode.OPTION_SELECT, { globalScene.ui.setOverlayMode(UiMode.OPTION_SELECT, {
options: [ options: languageOptions,
{
label: "English",
handler: () => changeLocaleHandler("en"),
},
{
label: "Español (ES)",
handler: () => changeLocaleHandler("es-ES"),
},
{
label: "Español (LATAM)",
handler: () => changeLocaleHandler("es-MX"),
},
{
label: "Français",
handler: () => changeLocaleHandler("fr"),
},
{
label: "Deutsch",
handler: () => changeLocaleHandler("de"),
},
{
label: "Italiano",
handler: () => changeLocaleHandler("it"),
},
{
label: "Português (BR)",
handler: () => changeLocaleHandler("pt-BR"),
},
{
label: "한국어",
handler: () => changeLocaleHandler("ko"),
},
{
label: "日本語",
handler: () => changeLocaleHandler("ja"),
},
{
label: "简体中文",
handler: () => changeLocaleHandler("zh-CN"),
},
{
label: "繁體中文",
handler: () => changeLocaleHandler("zh-TW"),
},
{
label: "Català (Needs Help)",
handler: () => changeLocaleHandler("ca"),
},
{
label: "Türkçe (Needs Help)",
handler: () => changeLocaleHandler("tr"),
},
{
label: "Русский (Needs Help)",
handler: () => changeLocaleHandler("ru"),
},
{
label: "Dansk (Needs Help)",
handler: () => changeLocaleHandler("da"),
},
{
label: "Română (Needs Help)",
handler: () => changeLocaleHandler("ro"),
},
{
label: "Tagalog (Needs Help)",
handler: () => changeLocaleHandler("tl"),
},
{
label: i18next.t("settings:back"),
handler: () => cancelHandler(),
},
],
maxOptions: 7, maxOptions: 7,
}); });
return false; return false;

View File

@ -1,7 +1,7 @@
/** biome-ignore-all lint/performance/noNamespaceImport: Convenience */ /** biome-ignore-all lint/performance/noNamespaceImport: Convenience */
import { version } from "#package.json"; import { version } from "#package.json";
import type { SessionSaveData, SystemSaveData } from "#system/game-data"; import type { SessionSaveData, SystemSaveData } from "#types/save-data";
import type { SessionSaveMigrator } from "#types/session-save-migrator"; import type { SessionSaveMigrator } from "#types/session-save-migrator";
import type { SettingsSaveMigrator } from "#types/settings-save-migrator"; import type { SettingsSaveMigrator } from "#types/settings-save-migrator";
import type { SystemSaveMigrator } from "#types/system-save-migrator"; import type { SystemSaveMigrator } from "#types/system-save-migrator";

View File

@ -3,8 +3,8 @@ import { allSpecies } from "#data/data-lists";
import { CustomPokemonData } from "#data/pokemon-data"; import { CustomPokemonData } from "#data/pokemon-data";
import { AbilityAttr } from "#enums/ability-attr"; import { AbilityAttr } from "#enums/ability-attr";
import { DexAttr } from "#enums/dex-attr"; import { DexAttr } from "#enums/dex-attr";
import type { SessionSaveData, SystemSaveData } from "#system/game-data";
import { SettingKeys } from "#system/settings"; import { SettingKeys } from "#system/settings";
import type { SessionSaveData, SystemSaveData } from "#types/save-data";
import type { SessionSaveMigrator } from "#types/session-save-migrator"; import type { SessionSaveMigrator } from "#types/session-save-migrator";
import type { SettingsSaveMigrator } from "#types/settings-save-migrator"; import type { SettingsSaveMigrator } from "#types/settings-save-migrator";
import type { SystemSaveMigrator } from "#types/system-save-migrator"; import type { SystemSaveMigrator } from "#types/system-save-migrator";

View File

@ -2,7 +2,7 @@ import type { BattlerIndex } from "#enums/battler-index";
import type { MoveId } from "#enums/move-id"; import type { MoveId } from "#enums/move-id";
import type { MoveResult } from "#enums/move-result"; import type { MoveResult } from "#enums/move-result";
import { MoveUseMode } from "#enums/move-use-mode"; import { MoveUseMode } from "#enums/move-use-mode";
import type { SessionSaveData } from "#system/game-data"; import type { SessionSaveData } from "#types/save-data";
import type { SessionSaveMigrator } from "#types/session-save-migrator"; import type { SessionSaveMigrator } from "#types/session-save-migrator";
import type { TurnMove } from "#types/turn-move"; import type { TurnMove } from "#types/turn-move";

View File

@ -1,6 +1,6 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { DexAttr } from "#enums/dex-attr"; import { DexAttr } from "#enums/dex-attr";
import type { SessionSaveData, SystemSaveData } from "#system/game-data"; import type { SessionSaveData, SystemSaveData } from "#types/save-data";
import type { SessionSaveMigrator } from "#types/session-save-migrator"; import type { SessionSaveMigrator } from "#types/session-save-migrator";
import type { SystemSaveMigrator } from "#types/system-save-migrator"; import type { SystemSaveMigrator } from "#types/system-save-migrator";
import { isNullOrUndefined } from "#utils/common"; import { isNullOrUndefined } from "#utils/common";

View File

@ -1,6 +1,6 @@
import { DexAttr } from "#enums/dex-attr"; import { DexAttr } from "#enums/dex-attr";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import type { SystemSaveData } from "#system/game-data"; import type { SystemSaveData } from "#types/save-data";
import type { SystemSaveMigrator } from "#types/system-save-migrator"; import type { SystemSaveMigrator } from "#types/system-save-migrator";
import { getPokemonSpecies } from "#utils/pokemon-utils"; import { getPokemonSpecies } from "#utils/pokemon-utils";

View File

@ -1,7 +1,7 @@
import { MoveId } from "#enums/move-id"; import { MoveId } from "#enums/move-id";
import { PokemonMove } from "#moves/pokemon-move"; import { PokemonMove } from "#moves/pokemon-move";
import type { SessionSaveData } from "#system/game-data";
import type { PokemonData } from "#system/pokemon-data"; import type { PokemonData } from "#system/pokemon-data";
import type { SessionSaveData } from "#types/save-data";
import type { SessionSaveMigrator } from "#types/session-save-migrator"; import type { SessionSaveMigrator } from "#types/session-save-migrator";
/** /**

View File

@ -5,9 +5,9 @@ import type Phaser from "phaser";
const repeatInputDelayMillis = 250; const repeatInputDelayMillis = 250;
export class TouchControl { export class TouchControl {
events: Phaser.Events.EventEmitter; readonly events: Phaser.Events.EventEmitter;
private buttonLock: string[] = []; private buttonLock: string[] = [];
private inputInterval: NodeJS.Timeout[] = []; private readonly inputInterval: NodeJS.Timeout[] = [];
/** Whether touch controls are disabled */ /** Whether touch controls are disabled */
private disabled = false; private disabled = false;
/** Whether the last touch event has finished before disabling */ /** Whether the last touch event has finished before disabling */
@ -61,12 +61,46 @@ export class TouchControl {
* event, removes the keydown state, and removes the 'active' class from the node and the last touched element. * event, removes the keydown state, and removes the 'active' class from the node and the last touched element.
*/ */
bindKey(node: HTMLElement, key: string) { bindKey(node: HTMLElement, key: string) {
node.addEventListener("touchstart", (event: TouchEvent) => {
// Handle touch events for touch devices
this.touchButtonDown(node, key);
event.preventDefault();
// prevent pointer event from also firing (undefined just sets presence of custom attribute)
if (event.currentTarget instanceof HTMLElement) {
event.currentTarget.dataset.skipPointerEvent = undefined;
}
});
node.addEventListener("pointerdown", event => { node.addEventListener("pointerdown", event => {
const currentTarget = event.currentTarget;
if (currentTarget instanceof HTMLElement && "skipPointerDown" in currentTarget.dataset) {
return;
}
event.preventDefault(); event.preventDefault();
this.touchButtonDown(node, key); this.touchButtonDown(node, key);
}); });
node.addEventListener("touchcancel", (event: TouchEvent) => {
if (event.currentTarget instanceof HTMLElement && "skipPointerDown" in event.currentTarget.dataset) {
delete event.currentTarget.dataset.skipPointerEvent;
}
});
node.addEventListener("touchend", (event: TouchEvent) => {
event.preventDefault();
this.touchButtonUp(node, key, event.target?.["id"]);
if (event.currentTarget instanceof HTMLElement && "skipPointerDown" in event.currentTarget.dataset) {
// allow pointer event to once again fire
delete event.currentTarget.dataset.skipPointerEvent;
event.currentTarget.dataset.skipPointerUp = undefined;
}
});
node.addEventListener("pointerup", event => { node.addEventListener("pointerup", event => {
if (event.currentTarget instanceof HTMLElement && "skipPointerUp" in event.currentTarget.dataset) {
delete event.currentTarget.dataset.skipPointerUp;
return;
}
event.preventDefault(); event.preventDefault();
this.touchButtonUp(node, key, event.target?.["id"]); this.touchButtonUp(node, key, event.target?.["id"]);
}); });
@ -143,7 +177,7 @@ export class TouchControl {
* {@link https://stackoverflow.com/a/39778831/4622620|Source} * {@link https://stackoverflow.com/a/39778831/4622620|Source}
* *
* Prevent zoom on specified element * Prevent zoom on specified element
* @param {HTMLElement} element * @param element
*/ */
preventElementZoom(element: HTMLElement | null): void { preventElementZoom(element: HTMLElement | null): void {
if (!element) { if (!element) {

View File

@ -3,8 +3,8 @@ import type { InputsController } from "#app/inputs-controller";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { Setting, SettingKeys, settingIndex } from "#system/settings"; import { Setting, SettingKeys, settingIndex } from "#system/settings";
import { PokedexPageUiHandler } from "#ui/containers/pokedex-page-ui-handler";
import type { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import type { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokedexPageUiHandler } from "#ui/handlers/pokedex-page-ui-handler";
import { PokedexUiHandler } from "#ui/handlers/pokedex-ui-handler"; import { PokedexUiHandler } from "#ui/handlers/pokedex-ui-handler";
import { RunInfoUiHandler } from "#ui/handlers/run-info-ui-handler"; import { RunInfoUiHandler } from "#ui/handlers/run-info-ui-handler";
import { StarterSelectUiHandler } from "#ui/handlers/starter-select-ui-handler"; import { StarterSelectUiHandler } from "#ui/handlers/starter-select-ui-handler";

View File

@ -53,7 +53,7 @@ export class BgmBar extends Phaser.GameObjects.Container {
/* /*
* Set the BGM Name to the BGM bar. * Set the BGM Name to the BGM bar.
* @param {string} bgmName The name of the BGM to set. * @param bgmName The name of the BGM to set.
*/ */
setBgmToBgmBar(bgmName: string): void { setBgmToBgmBar(bgmName: string): void {
this.musicText.setText(`${i18next.t("bgmName:music")}${this.getRealBgmName(bgmName)}`); this.musicText.setText(`${i18next.t("bgmName:music")}${this.getRealBgmName(bgmName)}`);
@ -71,7 +71,7 @@ export class BgmBar extends Phaser.GameObjects.Container {
/* /*
Show or hide the BGM bar. Show or hide the BGM bar.
@param {boolean} visible Whether to show or hide the BGM bar. @param visible Whether to show or hide the BGM bar.
*/ */
public toggleBgmBar(visible: boolean): void { public toggleBgmBar(visible: boolean): void {
/* /*

View File

@ -202,8 +202,8 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container {
* The method fetches the total page count if necessary, followed by fetching the rankings for the specified category * The method fetches the total page count if necessary, followed by fetching the rankings for the specified category
* and page. It updates the UI with the fetched rankings or shows an appropriate message if no rankings are found. * and page. It updates the UI with the fetched rankings or shows an appropriate message if no rankings are found.
* *
* @param {ScoreboardCategory} [category=this.category] - The category to fetch rankings for. Defaults to the current category. * @param [category=this.category] - The category to fetch rankings for. Defaults to the current category.
* @param {number} [page=this.page] - The page number to fetch. Defaults to the current page. * @param [page=this.page] - The page number to fetch. Defaults to the current page.
*/ */
update(category: ScoreboardCategory = this.category, page: number = this.page) { update(category: ScoreboardCategory = this.category, page: number = this.page) {
if (this.isUpdating) { if (this.isUpdating) {
@ -249,7 +249,7 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container {
/** /**
* Sets the state of the navigation buttons. * Sets the state of the navigation buttons.
* @param {boolean} [enabled=true] - Whether the buttons should be enabled or disabled. * @param [enabled=true] - Whether the buttons should be enabled or disabled.
*/ */
setButtonsState(enabled = true) { setButtonsState(enabled = true) {
const buttons = [ const buttons = [

View File

@ -2,14 +2,11 @@ import { globalScene } from "#app/global-scene";
import { TextStyle } from "#enums/text-style"; import { TextStyle } from "#enums/text-style";
import type { EggCountChangedEvent } from "#events/egg"; import type { EggCountChangedEvent } from "#events/egg";
import { EggEventType } from "#events/egg"; import { EggEventType } from "#events/egg";
import type { EggHatchSceneHandler } from "#ui/handlers/egg-hatch-scene-handler"; import type { EggHatchSceneUiHandler } from "#ui/handlers/egg-hatch-scene-ui-handler";
import { addTextObject } from "#ui/text"; import { addTextObject } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
/** /** A container that displays the count of hatching eggs */
* A container that displays the count of hatching eggs.
* @extends Phaser.GameObjects.Container
*/
export class EggCounterContainer extends Phaser.GameObjects.Container { export class EggCounterContainer extends Phaser.GameObjects.Container {
private readonly WINDOW_DEFAULT_WIDTH = 37; private readonly WINDOW_DEFAULT_WIDTH = 37;
private readonly WINDOW_MEDIUM_WIDTH = 42; private readonly WINDOW_MEDIUM_WIDTH = 42;
@ -27,7 +24,7 @@ export class EggCounterContainer extends Phaser.GameObjects.Container {
super(globalScene, 0, 0); super(globalScene, 0, 0);
this.eggCount = eggCount; this.eggCount = eggCount;
const uiHandler = globalScene.ui.getHandler() as EggHatchSceneHandler; const uiHandler = globalScene.ui.getHandler() as EggHatchSceneUiHandler;
uiHandler.eventTarget.addEventListener(EggEventType.EGG_COUNT_CHANGED, this.onEggCountChangedEvent); uiHandler.eventTarget.addEventListener(EggEventType.EGG_COUNT_CHANGED, this.onEggCountChangedEvent);
this.setup(); this.setup();

View File

@ -4,8 +4,8 @@ import { Gender } from "#data/gender";
import type { PokemonSpecies } from "#data/pokemon-species"; import type { PokemonSpecies } from "#data/pokemon-species";
import { DexAttr } from "#enums/dex-attr"; import { DexAttr } from "#enums/dex-attr";
import { getVariantTint } from "#sprites/variant"; import { getVariantTint } from "#sprites/variant";
import type { PokemonIconAnimHandler } from "#ui/handlers/pokemon-icon-anim-handler"; import type { PokemonIconAnimHelper } from "#ui/utils/pokemon-icon-anim-helper";
import { PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler"; import { PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
/** /**
* A container for a Pokemon's sprite and icons to get displayed in the egg summary screen * A container for a Pokemon's sprite and icons to get displayed in the egg summary screen
@ -81,9 +81,9 @@ export class HatchedPokemonContainer extends Phaser.GameObjects.Container {
* Animates the pokemon icon if it has a new form or shiny variant * Animates the pokemon icon if it has a new form or shiny variant
* *
* @param hatchData the {@linkcode EggHatchData} to base the icons on * @param hatchData the {@linkcode EggHatchData} to base the icons on
* @param iconAnimHandler the {@linkcode PokemonIconAnimHandler} to use to animate the sprites * @param iconAnimHandler the {@linkcode PokemonIconAnimHelper} to use to animate the sprites
*/ */
updateAndAnimate(hatchData: EggHatchData, iconAnimHandler: PokemonIconAnimHandler) { updateAndAnimate(hatchData: EggHatchData, iconAnimHandler: PokemonIconAnimHelper) {
const displayPokemon = hatchData.pokemon; const displayPokemon = hatchData.pokemon;
this.species = displayPokemon.species; this.species = displayPokemon.species;

View File

@ -9,11 +9,11 @@ import { PokemonType } from "#enums/pokemon-type";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { TextStyle } from "#enums/text-style"; import { TextStyle } from "#enums/text-style";
import type { PlayerPokemon } from "#field/pokemon"; import type { PlayerPokemon } from "#field/pokemon";
import { PokemonInfoContainer } from "#ui/containers/pokemon-info-container";
import { addTextObject } from "#ui/text"; import { addTextObject } from "#ui/text";
import { padInt, rgbHexToRgba } from "#utils/common"; import { padInt, rgbHexToRgba } from "#utils/common";
import { getPokemonSpeciesForm } from "#utils/pokemon-utils"; import { getPokemonSpeciesForm } from "#utils/pokemon-utils";
import { argbFromRgba } from "@material/material-color-utilities"; import { argbFromRgba } from "@material/material-color-utilities";
import { PokemonInfoContainer } from "./pokemon-info-container";
/** /**
* Class for the hatch info summary of each pokemon * Class for the hatch info summary of each pokemon

View File

@ -6,15 +6,15 @@ import { PokemonType } from "#enums/pokemon-type";
import { TextStyle } from "#enums/text-style"; import { TextStyle } from "#enums/text-style";
import type { Pokemon } from "#field/pokemon"; import type { Pokemon } from "#field/pokemon";
import { getVariantTint } from "#sprites/variant"; import { getVariantTint } from "#sprites/variant";
import type { StarterDataEntry } from "#system/game-data";
import type { DexEntry } from "#types/dex-data"; import type { DexEntry } from "#types/dex-data";
import { StatsContainer } from "#ui/containers/stats-container"; import type { StarterDataEntry } from "#types/save-data";
import { ConfirmUiHandler } from "#ui/handlers/confirm-ui-handler"; import { ConfirmUiHandler } from "#ui/handlers/confirm-ui-handler";
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text"; import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
import { fixedInt, getShinyDescriptor } from "#utils/common"; import { fixedInt, getShinyDescriptor } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
import { StatsContainer } from "./stats-container";
interface LanguageSetting { interface LanguageSetting {
infoContainerTextSize: string; infoContainerTextSize: string;

View File

@ -1,7 +1,7 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { fixedInt } from "#utils/common"; import { fixedInt } from "#utils/common";
export class SavingIconHandler extends Phaser.GameObjects.Container { export class SavingIconContainer extends Phaser.GameObjects.Container {
private icon: Phaser.GameObjects.Sprite; private icon: Phaser.GameObjects.Sprite;
private animActive: boolean; private animActive: boolean;

View File

@ -5,9 +5,9 @@ import { TextStyle } from "#enums/text-style";
import type { UiMode } from "#enums/ui-mode"; import type { UiMode } from "#enums/ui-mode";
import type { Achv } from "#system/achv"; import type { Achv } from "#system/achv";
import { achvs, getAchievementDescription } from "#system/achv"; import { achvs, getAchievementDescription } from "#system/achv";
import type { AchvUnlocks, VoucherUnlocks } from "#system/game-data";
import type { Voucher } from "#system/voucher"; import type { Voucher } from "#system/voucher";
import { getVoucherTypeIcon, getVoucherTypeName, vouchers } from "#system/voucher"; import { getVoucherTypeIcon, getVoucherTypeName, vouchers } from "#system/voucher";
import type { AchvUnlocks, VoucherUnlocks } from "#types/save-data";
import { ScrollBar } from "#ui/containers/scroll-bar"; import { ScrollBar } from "#ui/containers/scroll-bar";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { addTextObject } from "#ui/text"; import { addTextObject } from "#ui/text";

View File

@ -96,7 +96,7 @@ export class EggGachaUiHandler extends MessageUiHandler {
legendaryLabelY = 0; legendaryLabelY = 0;
} }
const gachaUpLabel = addTextObject(gachaX, gachaY, i18next.t("egg:legendaryUPGacha"), gachaTextStyle).setOrigin(0); const gachaUpLabel = addTextObject(gachaX, gachaY, i18next.t("egg:legendaryUpGacha"), gachaTextStyle).setOrigin(0);
gachaInfoContainer.add(gachaUpLabel); gachaInfoContainer.add(gachaUpLabel);
switch (gachaType as GachaType) { switch (gachaType as GachaType) {
@ -124,14 +124,14 @@ export class EggGachaUiHandler extends MessageUiHandler {
gachaUpLabel.setAlign("center").setY(0); gachaUpLabel.setAlign("center").setY(0);
} }
gachaUpLabel.setText(i18next.t("egg:moveUPGacha")).setX(0).setOrigin(0.5, 0); gachaUpLabel.setText(i18next.t("egg:moveUpGacha")).setX(0).setOrigin(0.5, 0);
break; break;
case GachaType.SHINY: case GachaType.SHINY:
if (["de", "fr", "ko", "ru"].includes(currentLanguage)) { if (["de", "fr", "ko", "ru"].includes(currentLanguage)) {
gachaUpLabel.setAlign("center").setY(0); gachaUpLabel.setAlign("center").setY(0);
} }
gachaUpLabel.setText(i18next.t("egg:shinyUPGacha")).setX(0).setOrigin(0.5, 0); gachaUpLabel.setText(i18next.t("egg:shinyUpGacha")).setX(0).setOrigin(0.5, 0);
break; break;
} }

View File

@ -3,7 +3,7 @@ import { Button } from "#enums/buttons";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { UiHandler } from "#ui/handlers/ui-handler"; import { UiHandler } from "#ui/handlers/ui-handler";
export class EggHatchSceneHandler extends UiHandler { export class EggHatchSceneUiHandler extends UiHandler {
public eggHatchContainer: Phaser.GameObjects.Container; public eggHatchContainer: Phaser.GameObjects.Container;
/** /**

View File

@ -4,10 +4,10 @@ import { TextStyle } from "#enums/text-style";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { ScrollBar } from "#ui/containers/scroll-bar"; import { ScrollBar } from "#ui/containers/scroll-bar";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler";
import { ScrollableGridUiHandler } from "#ui/handlers/scrollable-grid-handler";
import { addTextObject } from "#ui/text"; import { addTextObject } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
import { PokemonIconAnimHelper, PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
import { ScrollableGridHelper } from "#ui/utils/scrollable-grid-helper";
import i18next from "i18next"; import i18next from "i18next";
export class EggListUiHandler extends MessageUiHandler { export class EggListUiHandler extends MessageUiHandler {
@ -25,9 +25,9 @@ export class EggListUiHandler extends MessageUiHandler {
private eggListMessageBoxContainer: Phaser.GameObjects.Container; private eggListMessageBoxContainer: Phaser.GameObjects.Container;
private cursorObj: Phaser.GameObjects.Image; private cursorObj: Phaser.GameObjects.Image;
private scrollGridHandler: ScrollableGridUiHandler; private scrollGridHandler: ScrollableGridHelper;
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
constructor() { constructor() {
super(UiMode.EGG_LIST); super(UiMode.EGG_LIST);
@ -45,7 +45,7 @@ export class EggListUiHandler extends MessageUiHandler {
const eggListBg = globalScene.add.image(0, 0, "egg_list_bg").setOrigin(0); const eggListBg = globalScene.add.image(0, 0, "egg_list_bg").setOrigin(0);
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHelper();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
this.eggNameText = addTextObject(8, 68, "", TextStyle.SUMMARY).setOrigin(0); this.eggNameText = addTextObject(8, 68, "", TextStyle.SUMMARY).setOrigin(0);
@ -64,7 +64,7 @@ export class EggListUiHandler extends MessageUiHandler {
const scrollBar = new ScrollBar(310, 5, 4, 170, this.ROWS); const scrollBar = new ScrollBar(310, 5, 4, 170, this.ROWS);
this.scrollGridHandler = new ScrollableGridUiHandler(this, this.ROWS, this.COLUMNS) this.scrollGridHandler = new ScrollableGridHelper(this, this.ROWS, this.COLUMNS)
.withScrollBar(scrollBar) .withScrollBar(scrollBar)
.withUpdateGridCallBack(() => this.updateEggIcons()) .withUpdateGridCallBack(() => this.updateEggIcons())
.withUpdateSingleElementCallback((i: number) => this.setEggDetails(i)); .withUpdateSingleElementCallback((i: number) => this.setEggDetails(i));

View File

@ -7,8 +7,8 @@ import { HatchedPokemonContainer } from "#ui/containers/hatched-pokemon-containe
import { PokemonHatchInfoContainer } from "#ui/containers/pokemon-hatch-info-container"; import { PokemonHatchInfoContainer } from "#ui/containers/pokemon-hatch-info-container";
import { ScrollBar } from "#ui/containers/scroll-bar"; import { ScrollBar } from "#ui/containers/scroll-bar";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler"; import { PokemonIconAnimHelper, PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
import { ScrollableGridUiHandler } from "#ui/handlers/scrollable-grid-handler"; import { ScrollableGridHelper } from "#ui/utils/scrollable-grid-helper";
const iconContainerX = 112; const iconContainerX = 112;
const iconContainerY = 9; const iconContainerY = 9;
@ -34,11 +34,11 @@ export class EggSummaryUiHandler extends MessageUiHandler {
/** hatch info container that displays the current pokemon / hatch (main element on left hand side) */ /** hatch info container that displays the current pokemon / hatch (main element on left hand side) */
private infoContainer: PokemonHatchInfoContainer; private infoContainer: PokemonHatchInfoContainer;
/** handles jumping animations for the pokemon sprite icons */ /** handles jumping animations for the pokemon sprite icons */
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
private eggHatchBg: Phaser.GameObjects.Image; private eggHatchBg: Phaser.GameObjects.Image;
private eggHatchData: EggHatchData[]; private eggHatchData: EggHatchData[];
private scrollGridHandler: ScrollableGridUiHandler; private scrollGridHandler: ScrollableGridHelper;
private cursorObj: Phaser.GameObjects.Image; private cursorObj: Phaser.GameObjects.Image;
/** used to add a delay before which it is not possible to exit the summary */ /** used to add a delay before which it is not possible to exit the summary */
@ -67,7 +67,7 @@ export class EggSummaryUiHandler extends MessageUiHandler {
this.eggHatchContainer.setVisible(false); this.eggHatchContainer.setVisible(false);
ui.add(this.eggHatchContainer); ui.add(this.eggHatchContainer);
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHelper();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
this.eggHatchBg = globalScene.add.image(0, 0, "egg_summary_bg"); this.eggHatchBg = globalScene.add.image(0, 0, "egg_summary_bg");
@ -97,7 +97,7 @@ export class EggSummaryUiHandler extends MessageUiHandler {
); );
this.summaryContainer.add(scrollBar); this.summaryContainer.add(scrollBar);
this.scrollGridHandler = new ScrollableGridUiHandler(this, numRows, numCols) this.scrollGridHandler = new ScrollableGridHelper(this, numRows, numCols)
.withScrollBar(scrollBar) .withScrollBar(scrollBar)
.withUpdateGridCallBack(() => this.updatePokemonIcons()) .withUpdateGridCallBack(() => this.updatePokemonIcons())
.withUpdateSingleElementCallback((i: number) => this.infoContainer.showHatchInfo(this.eggHatchData[i])); .withUpdateSingleElementCallback((i: number) => this.infoContainer.showHatchInfo(this.eggHatchData[i]));

View File

@ -5,7 +5,7 @@ import { UiMode } from "#enums/ui-mode";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { addTextObject } from "#ui/text"; import { addTextObject } from "#ui/text";
export class EvolutionSceneHandler extends MessageUiHandler { export class EvolutionSceneUiHandler extends MessageUiHandler {
public evolutionContainer: Phaser.GameObjects.Container; public evolutionContainer: Phaser.GameObjects.Container;
public messageBg: Phaser.GameObjects.Image; public messageBg: Phaser.GameObjects.Image;
public messageContainer: Phaser.GameObjects.Container; public messageContainer: Phaser.GameObjects.Container;

View File

@ -108,7 +108,7 @@ const displayStats: DisplayStats = {
sourceFunc: gameData => gameData.gameStats.highestDamage.toString(), sourceFunc: gameData => gameData.gameStats.highestDamage.toString(),
}, },
highestHeal: { highestHeal: {
label_key: "highestHPHealed", label_key: "highestHpHealed",
sourceFunc: gameData => gameData.gameStats.highestHeal.toString(), sourceFunc: gameData => gameData.gameStats.highestHeal.toString(),
}, },
pokemonSeen: { pokemonSeen: {

View File

@ -2,6 +2,7 @@ import { pokerogueApi } from "#api/pokerogue-api";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { TextStyle } from "#enums/text-style"; import { TextStyle } from "#enums/text-style";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { languageOptions } from "#system/settings-language";
import type { OptionSelectItem } from "#ui/handlers/abstract-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/handlers/abstract-option-select-ui-handler";
import type { InputFieldConfig } from "#ui/handlers/form-modal-ui-handler"; import type { InputFieldConfig } from "#ui/handlers/form-modal-ui-handler";
import { FormModalUiHandler } from "#ui/handlers/form-modal-ui-handler"; import { FormModalUiHandler } from "#ui/handlers/form-modal-ui-handler";
@ -31,6 +32,7 @@ export class LoginFormUiHandler extends FormModalUiHandler {
private discordImage: Phaser.GameObjects.Image; private discordImage: Phaser.GameObjects.Image;
private usernameInfoImage: Phaser.GameObjects.Image; private usernameInfoImage: Phaser.GameObjects.Image;
private saveDownloadImage: Phaser.GameObjects.Image; private saveDownloadImage: Phaser.GameObjects.Image;
private changeLanguageImage: Phaser.GameObjects.Image;
private externalPartyContainer: Phaser.GameObjects.Container; private externalPartyContainer: Phaser.GameObjects.Container;
private infoContainer: Phaser.GameObjects.Container; private infoContainer: Phaser.GameObjects.Container;
private externalPartyBg: Phaser.GameObjects.NineSlice; private externalPartyBg: Phaser.GameObjects.NineSlice;
@ -82,8 +84,14 @@ export class LoginFormUiHandler extends FormModalUiHandler {
scale: 0.75, scale: 0.75,
}); });
this.changeLanguageImage = this.buildInteractableImage("language_icon", "change-language-icon", {
x: 40,
scale: 0.5,
});
this.infoContainer.add(this.usernameInfoImage); this.infoContainer.add(this.usernameInfoImage);
this.infoContainer.add(this.saveDownloadImage); this.infoContainer.add(this.saveDownloadImage);
this.infoContainer.add(this.changeLanguageImage);
this.getUi().add(this.infoContainer); this.getUi().add(this.infoContainer);
this.infoContainer.setVisible(false); this.infoContainer.setVisible(false);
this.infoContainer.disableInteractive(); this.infoContainer.disableInteractive();
@ -163,13 +171,18 @@ export class LoginFormUiHandler extends FormModalUiHandler {
const [usernameInput, passwordInput] = this.inputs; const [usernameInput, passwordInput] = this.inputs;
pokerogueApi.account.login({ username: usernameInput.text, password: passwordInput.text }).then(error => { pokerogueApi.account
if (!error && originalLoginAction) { .login({
originalLoginAction(); username: usernameInput.text,
} else { password: passwordInput.text,
onFail(error); })
} .then(error => {
}); if (!error && originalLoginAction) {
originalLoginAction();
} else {
onFail(error);
}
});
} }
}; };
@ -185,9 +198,13 @@ export class LoginFormUiHandler extends FormModalUiHandler {
this.infoContainer.setVisible(false); this.infoContainer.setVisible(false);
this.setMouseCursorStyle("default"); //reset cursor this.setMouseCursorStyle("default"); //reset cursor
[this.discordImage, this.googleImage, this.usernameInfoImage, this.saveDownloadImage].forEach(img => [
img.off("pointerdown"), this.discordImage,
); this.googleImage,
this.usernameInfoImage,
this.saveDownloadImage,
this.changeLanguageImage,
].forEach(img => img.off("pointerdown"));
} }
private processExternalProvider(config: ModalConfig): void { private processExternalProvider(config: ModalConfig): void {
@ -206,6 +223,7 @@ export class LoginFormUiHandler extends FormModalUiHandler {
this.getUi().moveTo(this.infoContainer, this.getUi().length - 1); this.getUi().moveTo(this.infoContainer, this.getUi().length - 1);
this.usernameInfoImage.setPositionRelative(this.infoContainer, 0, 0); this.usernameInfoImage.setPositionRelative(this.infoContainer, 0, 0);
this.saveDownloadImage.setPositionRelative(this.infoContainer, 20, 0); this.saveDownloadImage.setPositionRelative(this.infoContainer, 20, 0);
this.changeLanguageImage.setPositionRelative(this.infoContainer, 40, 0);
this.discordImage.on("pointerdown", () => { this.discordImage.on("pointerdown", () => {
const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`); const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`);
@ -288,6 +306,14 @@ export class LoginFormUiHandler extends FormModalUiHandler {
} }
}); });
this.changeLanguageImage.on("pointerdown", () => {
globalScene.ui.setOverlayMode(UiMode.OPTION_SELECT, {
options: languageOptions,
maxOptions: 7,
delay: 1000,
});
});
this.externalPartyContainer.setAlpha(0); this.externalPartyContainer.setAlpha(0);
globalScene.tweens.add({ globalScene.tweens.add({
targets: this.externalPartyContainer, targets: this.externalPartyContainer,

View File

@ -23,9 +23,9 @@ import { getVariantTint } from "#sprites/variant";
import type { TurnMove } from "#types/turn-move"; import type { TurnMove } from "#types/turn-move";
import { MoveInfoOverlay } from "#ui/containers/move-info-overlay"; import { MoveInfoOverlay } from "#ui/containers/move-info-overlay";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler";
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text"; import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
import { PokemonIconAnimHelper, PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
import { applyChallenges } from "#utils/challenge-utils"; import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder, getLocalizedSpriteKey, randInt } from "#utils/common"; import { BooleanHolder, getLocalizedSpriteKey, randInt } from "#utils/common";
import { toCamelCase, toTitleCase } from "#utils/strings"; import { toCamelCase, toTitleCase } from "#utils/strings";
@ -201,7 +201,7 @@ export class PartyUiHandler extends MessageUiHandler {
private tmMoveId: MoveId; private tmMoveId: MoveId;
private showMovePp: boolean; private showMovePp: boolean;
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
private blockInput: boolean; private blockInput: boolean;
@ -320,7 +320,7 @@ export class PartyUiHandler extends MessageUiHandler {
this.optionsContainer = globalScene.add.container(globalScene.scaledCanvas.width - 1, -1); this.optionsContainer = globalScene.add.container(globalScene.scaledCanvas.width - 1, -1);
partyContainer.add(this.optionsContainer); partyContainer.add(this.optionsContainer);
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHelper();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
const partyDiscardModeButton = new PartyDiscardModeButton(DISCARD_BUTTON_X, DISCARD_BUTTON_Y, this); const partyDiscardModeButton = new PartyDiscardModeButton(DISCARD_BUTTON_X, DISCARD_BUTTON_Y, this);
@ -1892,12 +1892,12 @@ class PartySlot extends Phaser.GameObjects.Container {
private slotBgKey: string; private slotBgKey: string;
private pokemonIcon: Phaser.GameObjects.Container; private pokemonIcon: Phaser.GameObjects.Container;
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
constructor( constructor(
slotIndex: number, slotIndex: number,
pokemon: PlayerPokemon, pokemon: PlayerPokemon,
iconAnimHandler: PokemonIconAnimHandler, iconAnimHandler: PokemonIconAnimHelper,
partyUiMode: PartyUiMode, partyUiMode: PartyUiMode,
tmMoveId: MoveId, tmMoveId: MoveId,
) { ) {

View File

@ -43,9 +43,9 @@ import { TimeOfDay } from "#enums/time-of-day";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import type { Variant } from "#sprites/variant"; import type { Variant } from "#sprites/variant";
import { getVariantIcon, getVariantTint } from "#sprites/variant"; import { getVariantIcon, getVariantTint } from "#sprites/variant";
import type { StarterAttributes } from "#system/game-data";
import { SettingKeyboard } from "#system/settings-keyboard"; import { SettingKeyboard } from "#system/settings-keyboard";
import type { DexEntry } from "#types/dex-data"; import type { DexEntry } from "#types/dex-data";
import type { StarterAttributes } from "#types/save-data";
import { BaseStatsOverlay } from "#ui/containers/base-stats-overlay"; import { BaseStatsOverlay } from "#ui/containers/base-stats-overlay";
import { MoveInfoOverlay } from "#ui/containers/move-info-overlay"; import { MoveInfoOverlay } from "#ui/containers/move-info-overlay";
import { PokedexInfoOverlay } from "#ui/containers/pokedex-info-overlay"; import { PokedexInfoOverlay } from "#ui/containers/pokedex-info-overlay";

View File

@ -31,9 +31,9 @@ import { UiMode } from "#enums/ui-mode";
import { UiTheme } from "#enums/ui-theme"; import { UiTheme } from "#enums/ui-theme";
import type { Variant } from "#sprites/variant"; import type { Variant } from "#sprites/variant";
import { getVariantIcon, getVariantTint } from "#sprites/variant"; import { getVariantIcon, getVariantTint } from "#sprites/variant";
import type { DexAttrProps, StarterAttributes } from "#system/game-data";
import { SettingKeyboard } from "#system/settings-keyboard"; import { SettingKeyboard } from "#system/settings-keyboard";
import type { DexEntry } from "#types/dex-data"; import type { DexEntry } from "#types/dex-data";
import type { DexAttrProps, StarterAttributes } from "#types/save-data";
import { import {
DropDown, DropDown,
DropDownLabel, DropDownLabel,
@ -48,9 +48,9 @@ import { PokedexMonContainer } from "#ui/containers/pokedex-mon-container";
import { ScrollBar } from "#ui/containers/scroll-bar"; import { ScrollBar } from "#ui/containers/scroll-bar";
import type { OptionSelectConfig } from "#ui/handlers/abstract-option-select-ui-handler"; import type { OptionSelectConfig } from "#ui/handlers/abstract-option-select-ui-handler";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler";
import { addTextObject, getTextColor } from "#ui/text"; import { addTextObject, getTextColor } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
import { PokemonIconAnimHelper, PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
import { BooleanHolder, fixedInt, getLocalizedSpriteKey, padInt, randIntRange, rgbHexToRgba } from "#utils/common"; import { BooleanHolder, fixedInt, getLocalizedSpriteKey, padInt, randIntRange, rgbHexToRgba } from "#utils/common";
import type { StarterPreferences } from "#utils/data"; import type { StarterPreferences } from "#utils/data";
import { loadStarterPreferences } from "#utils/data"; import { loadStarterPreferences } from "#utils/data";
@ -198,7 +198,7 @@ export class PokedexUiHandler extends MessageUiHandler {
public cursorObj: Phaser.GameObjects.Image; public cursorObj: Phaser.GameObjects.Image;
private pokerusCursorObjs: Phaser.GameObjects.Image[]; private pokerusCursorObjs: Phaser.GameObjects.Image[];
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
private starterPreferences: StarterPreferences; private starterPreferences: StarterPreferences;
@ -482,7 +482,7 @@ export class PokedexUiHandler extends MessageUiHandler {
pokemonContainerWindow.setVisible(false); pokemonContainerWindow.setVisible(false);
} }
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHelper();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
this.pokemonNumberText = addTextObject(6, 141, "", TextStyle.SUMMARY); this.pokemonNumberText = addTextObject(6, 141, "", TextStyle.SUMMARY);

View File

@ -6,8 +6,8 @@ import { PlayerGender } from "#enums/player-gender";
import { TextStyle } from "#enums/text-style"; import { TextStyle } from "#enums/text-style";
import { TrainerVariant } from "#enums/trainer-variant"; import { TrainerVariant } from "#enums/trainer-variant";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import type { RunEntry } from "#system/game-data";
import type { PokemonData } from "#system/pokemon-data"; import type { PokemonData } from "#system/pokemon-data";
import type { RunEntry } from "#types/save-data";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { RunDisplayMode } from "#ui/handlers/run-info-ui-handler"; import { RunDisplayMode } from "#ui/handlers/run-info-ui-handler";
import { addTextObject } from "#ui/text"; import { addTextObject } from "#ui/text";

View File

@ -19,9 +19,9 @@ import { UiMode } from "#enums/ui-mode";
import * as Modifier from "#modifiers/modifier"; import * as Modifier from "#modifiers/modifier";
import { getLuckString, getLuckTextTint } from "#modifiers/modifier-type"; import { getLuckString, getLuckTextTint } from "#modifiers/modifier-type";
import { getVariantTint } from "#sprites/variant"; import { getVariantTint } from "#sprites/variant";
import type { SessionSaveData } from "#system/game-data";
import type { PokemonData } from "#system/pokemon-data"; import type { PokemonData } from "#system/pokemon-data";
import { SettingKeyboard } from "#system/settings-keyboard"; import { SettingKeyboard } from "#system/settings-keyboard";
import type { SessionSaveData } from "#types/save-data";
import { UiHandler } from "#ui/handlers/ui-handler"; import { UiHandler } from "#ui/handlers/ui-handler";
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text"; import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
@ -685,7 +685,7 @@ export class RunInfoUiHandler extends UiHandler {
/** /**
* This function parses the Challenges section of the Run Entry and returns a list of active challenge. * This function parses the Challenges section of the Run Entry and returns a list of active challenge.
* @return string[] of active challenge names * @returns string[] of active challenge names
*/ */
private challengeParser(): string[] { private challengeParser(): string[] {
const rules: string[] = []; const rules: string[] = [];

View File

@ -6,8 +6,8 @@ import { TextStyle } from "#enums/text-style";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
// biome-ignore lint/performance/noNamespaceImport: See `src/system/game-data.ts` // biome-ignore lint/performance/noNamespaceImport: See `src/system/game-data.ts`
import * as Modifier from "#modifiers/modifier"; import * as Modifier from "#modifiers/modifier";
import type { SessionSaveData } from "#system/game-data";
import type { PokemonData } from "#system/pokemon-data"; import type { PokemonData } from "#system/pokemon-data";
import type { SessionSaveData } from "#types/save-data";
import type { OptionSelectConfig } from "#ui/handlers/abstract-option-select-ui-handler"; import type { OptionSelectConfig } from "#ui/handlers/abstract-option-select-ui-handler";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { RunDisplayMode } from "#ui/handlers/run-info-ui-handler"; import { RunDisplayMode } from "#ui/handlers/run-info-ui-handler";

View File

@ -46,10 +46,10 @@ import { BattleSceneEventType } from "#events/battle-scene";
import type { Variant } from "#sprites/variant"; import type { Variant } from "#sprites/variant";
import { getVariantIcon, getVariantTint } from "#sprites/variant"; import { getVariantIcon, getVariantTint } from "#sprites/variant";
import { achvs } from "#system/achv"; import { achvs } from "#system/achv";
import type { DexAttrProps, StarterAttributes, StarterDataEntry, StarterMoveset } from "#system/game-data";
import { RibbonData } from "#system/ribbons/ribbon-data"; import { RibbonData } from "#system/ribbons/ribbon-data";
import { SettingKeyboard } from "#system/settings-keyboard"; import { SettingKeyboard } from "#system/settings-keyboard";
import type { DexEntry } from "#types/dex-data"; import type { DexEntry } from "#types/dex-data";
import type { DexAttrProps, StarterAttributes, StarterDataEntry, StarterMoveset } from "#types/save-data";
import { import {
DropDown, DropDown,
DropDownLabel, DropDownLabel,
@ -65,9 +65,9 @@ import { StarterContainer } from "#ui/containers/starter-container";
import { StatsContainer } from "#ui/containers/stats-container"; import { StatsContainer } from "#ui/containers/stats-container";
import type { OptionSelectItem } from "#ui/handlers/abstract-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/handlers/abstract-option-select-ui-handler";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/handlers/pokemon-icon-anim-handler";
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text"; import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
import { PokemonIconAnimHelper, PokemonIconAnimMode } from "#ui/utils/pokemon-icon-anim-helper";
import { applyChallenges, checkStarterValidForChallenge } from "#utils/challenge-utils"; import { applyChallenges, checkStarterValidForChallenge } from "#utils/challenge-utils";
import { import {
BooleanHolder, BooleanHolder,
@ -398,7 +398,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
private startCursorObj: Phaser.GameObjects.NineSlice; private startCursorObj: Phaser.GameObjects.NineSlice;
private randomCursorObj: Phaser.GameObjects.NineSlice; private randomCursorObj: Phaser.GameObjects.NineSlice;
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHelper;
//variables to keep track of the dynamically rendered list of instruction prompts for starter select //variables to keep track of the dynamically rendered list of instruction prompts for starter select
private instructionRowX = 0; private instructionRowX = 0;
@ -611,7 +611,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
starterContainerWindow.setVisible(false); starterContainerWindow.setVisible(false);
} }
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHelper();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
this.pokemonSprite = globalScene.add.sprite(53, 63, "pkmn__sub"); this.pokemonSprite = globalScene.add.sprite(53, 63, "pkmn__sub");

View File

@ -4,6 +4,7 @@ import { TextStyle } from "#enums/text-style";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import type { SettingType } from "#system/settings"; import type { SettingType } from "#system/settings";
import { Setting, SettingKeys } from "#system/settings"; import { Setting, SettingKeys } from "#system/settings";
import type { AnyFn } from "#types/type-helpers";
import type { InputsIcons } from "#ui/abstract-control-settings-ui-handler"; import type { InputsIcons } from "#ui/abstract-control-settings-ui-handler";
import { ScrollBar } from "#ui/containers/scroll-bar"; import { ScrollBar } from "#ui/containers/scroll-bar";
import { MessageUiHandler } from "#ui/handlers/message-ui-handler"; import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
@ -53,54 +54,47 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
*/ */
setup() { setup() {
const ui = this.getUi(); const ui = this.getUi();
const canvasWidth = globalScene.scaledCanvas.width;
const canvasHeight = globalScene.scaledCanvas.height;
this.settingsContainer = globalScene.add.container(1, -globalScene.scaledCanvas.height + 1); this.settingsContainer = globalScene.add
this.settingsContainer.setName(`settings-${this.title}`); .container(1, -canvasHeight + 1)
this.settingsContainer.setInteractive( .setName(`settings-${this.title}`)
new Phaser.Geom.Rectangle(0, 0, globalScene.scaledCanvas.width, globalScene.scaledCanvas.height - 20), .setInteractive(new Phaser.Geom.Rectangle(0, 0, canvasWidth, canvasHeight - 20), Phaser.Geom.Rectangle.Contains);
Phaser.Geom.Rectangle.Contains,
);
this.navigationIcons = {}; this.navigationIcons = {};
this.navigationContainer = new NavigationMenu(0, 0); this.navigationContainer = new NavigationMenu(0, 0);
const navWidth = this.navigationContainer.width;
const navHeight = this.navigationContainer.height;
this.optionsBg = addWindow( this.optionsBg = addWindow(0, navHeight, canvasWidth - 2, canvasHeight - 16 - navHeight - 2)
0, .setName("window-options-bg")
this.navigationContainer.height, .setOrigin(0);
globalScene.scaledCanvas.width - 2,
globalScene.scaledCanvas.height - 16 - this.navigationContainer.height - 2,
);
this.optionsBg.setName("window-options-bg");
this.optionsBg.setOrigin(0, 0);
const actionsBg = addWindow( const actionsBg = addWindow(0, canvasHeight - navHeight, canvasWidth - 2, 22) // formatting
0, .setOrigin(0);
globalScene.scaledCanvas.height - this.navigationContainer.height,
globalScene.scaledCanvas.width - 2,
22,
);
actionsBg.setOrigin(0, 0);
const iconAction = globalScene.add.sprite(0, 0, "keyboard"); const iconAction = globalScene.add
iconAction.setOrigin(0, -0.1); .sprite(0, 0, "keyboard")
iconAction.setPositionRelative(actionsBg, this.navigationContainer.width - 32, 4); .setOrigin(0, -0.1)
.setPositionRelative(actionsBg, navWidth - 32, 4);
this.navigationIcons["BUTTON_ACTION"] = iconAction; this.navigationIcons["BUTTON_ACTION"] = iconAction;
const actionText = addTextObject(0, 0, i18next.t("settings:action"), TextStyle.SETTINGS_LABEL); const actionText = addTextObject(0, 0, i18next.t("settings:action"), TextStyle.SETTINGS_LABEL).setOrigin(0, 0.15);
actionText.setOrigin(0, 0.15);
actionText.setPositionRelative(iconAction, -actionText.width / 6 - 2, 0); actionText.setPositionRelative(iconAction, -actionText.width / 6 - 2, 0);
const iconCancel = globalScene.add.sprite(0, 0, "keyboard"); const iconCancel = globalScene.add
iconCancel.setOrigin(0, -0.1); .sprite(0, 0, "keyboard")
iconCancel.setPositionRelative(actionsBg, actionText.x - 28, 4); .setOrigin(0, -0.1)
.setPositionRelative(actionsBg, actionText.x - 28, 4);
this.navigationIcons["BUTTON_CANCEL"] = iconCancel; this.navigationIcons["BUTTON_CANCEL"] = iconCancel;
const cancelText = addTextObject(0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL); const cancelText = addTextObject(0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL) // formatting
cancelText.setOrigin(0, 0.15); .setOrigin(0, 0.15);
cancelText.setPositionRelative(iconCancel, -cancelText.width / 6 - 2, 0); cancelText.setPositionRelative(iconCancel, -cancelText.width / 6 - 2, 0);
this.optionsContainer = globalScene.add.container(0, 0); this.optionsContainer = globalScene.add.container();
this.settingLabels = []; this.settingLabels = [];
this.optionValueLabels = []; this.optionValueLabels = [];
@ -113,8 +107,7 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
anyReloadRequired = true; anyReloadRequired = true;
} }
this.settingLabels[s] = addTextObject(8, 28 + s * 16, settingName, TextStyle.SETTINGS_LABEL); this.settingLabels[s] = addTextObject(8, 28 + s * 16, settingName, TextStyle.SETTINGS_LABEL).setOrigin(0);
this.settingLabels[s].setOrigin(0, 0);
this.optionsContainer.add(this.settingLabels[s]); this.optionsContainer.add(this.settingLabels[s]);
this.optionValueLabels.push( this.optionValueLabels.push(
@ -125,7 +118,7 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
option.label, option.label,
setting.default === o ? TextStyle.SETTINGS_SELECTED : TextStyle.SETTINGS_VALUE, setting.default === o ? TextStyle.SETTINGS_SELECTED : TextStyle.SETTINGS_VALUE,
); );
valueLabel.setOrigin(0, 0); valueLabel.setOrigin(0);
this.optionsContainer.add(valueLabel); this.optionsContainer.add(valueLabel);
@ -160,32 +153,33 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
this.scrollBar.setTotalRows(this.settings.length); this.scrollBar.setTotalRows(this.settings.length);
// Two-lines message box // Two-lines message box
this.messageBoxContainer = globalScene.add.container(0, globalScene.scaledCanvas.height); this.messageBoxContainer = globalScene.add
this.messageBoxContainer.setName("settings-message-box"); .container(0, globalScene.scaledCanvas.height)
this.messageBoxContainer.setVisible(false); .setName("settings-message-box")
.setVisible(false);
const settingsMessageBox = addWindow(0, -1, globalScene.scaledCanvas.width - 2, 48); const settingsMessageBox = addWindow(0, -1, globalScene.scaledCanvas.width - 2, 48);
settingsMessageBox.setOrigin(0, 1); settingsMessageBox.setOrigin(0, 1);
this.messageBoxContainer.add(settingsMessageBox); this.messageBoxContainer.add(settingsMessageBox);
const messageText = addTextObject(8, -40, "", TextStyle.WINDOW, { const messageText = addTextObject(8, -40, "", TextStyle.WINDOW, { maxLines: 2 })
maxLines: 2, .setWordWrapWidth(globalScene.game.canvas.width - 60)
}); .setName("settings-message")
messageText.setWordWrapWidth(globalScene.game.canvas.width - 60); .setOrigin(0);
messageText.setName("settings-message");
messageText.setOrigin(0, 0);
this.messageBoxContainer.add(messageText); this.messageBoxContainer.add(messageText);
this.message = messageText; this.message = messageText;
this.settingsContainer.add(this.optionsBg); this.settingsContainer.add([
this.settingsContainer.add(this.scrollBar); this.optionsBg,
this.settingsContainer.add(this.navigationContainer); this.scrollBar,
this.settingsContainer.add(actionsBg); this.navigationContainer,
this.settingsContainer.add(this.optionsContainer); actionsBg,
this.settingsContainer.add(iconAction); this.optionsContainer,
this.settingsContainer.add(iconCancel); iconAction,
this.settingsContainer.add(actionText); iconCancel,
actionText,
]);
// Only add the ReloadRequired text on pages that have settings that require a reload. // Only add the ReloadRequired text on pages that have settings that require a reload.
if (anyReloadRequired) { if (anyReloadRequired) {
const reloadRequired = addTextObject(0, 0, `*${i18next.t("settings:requireReload")}`, TextStyle.SETTINGS_LABEL) const reloadRequired = addTextObject(0, 0, `*${i18next.t("settings:requireReload")}`, TextStyle.SETTINGS_LABEL)
@ -194,8 +188,7 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
.setY(actionText.y); .setY(actionText.y);
this.settingsContainer.add(reloadRequired); this.settingsContainer.add(reloadRequired);
} }
this.settingsContainer.add(cancelText); this.settingsContainer.add([cancelText, this.messageBoxContainer]);
this.settingsContainer.add(this.messageBoxContainer);
ui.add(this.settingsContainer); ui.add(this.settingsContainer);
@ -210,17 +203,13 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
updateBindings(): void { updateBindings(): void {
for (const settingName of Object.keys(this.navigationIcons)) { for (const settingName of Object.keys(this.navigationIcons)) {
if (settingName === "BUTTON_HOME") { if (settingName === "BUTTON_HOME") {
this.navigationIcons[settingName].setTexture("keyboard"); this.navigationIcons[settingName].setTexture("keyboard").setFrame("HOME.png").alpha = 1;
this.navigationIcons[settingName].setFrame("HOME.png");
this.navigationIcons[settingName].alpha = 1;
continue; continue;
} }
const icon = globalScene.inputController?.getIconForLatestInputRecorded(settingName); const icon = globalScene.inputController?.getIconForLatestInputRecorded(settingName);
if (icon) { if (icon) {
const type = globalScene.inputController?.getLastSourceType(); const type = globalScene.inputController?.getLastSourceType();
this.navigationIcons[settingName].setTexture(type); this.navigationIcons[settingName].setTexture(type).setFrame(icon).alpha = 1;
this.navigationIcons[settingName].setFrame(icon);
this.navigationIcons[settingName].alpha = 1;
} else { } else {
this.navigationIcons[settingName].alpha = 0; this.navigationIcons[settingName].alpha = 0;
} }
@ -242,21 +231,43 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
? JSON.parse(localStorage.getItem(this.localStorageKey)!) ? JSON.parse(localStorage.getItem(this.localStorageKey)!)
: {}; // TODO: is this bang correct? : {}; // TODO: is this bang correct?
this.settings.forEach((setting, s) => this.settings.forEach((setting, s) => {
this.setOptionCursor(s, settings.hasOwnProperty(setting.key) ? settings[setting.key] : this.settings[s].default), this.setOptionCursor(s, settings.hasOwnProperty(setting.key) ? settings[setting.key] : this.settings[s].default);
); });
this.settingsContainer.setVisible(true); this.settingsContainer.setVisible(true);
this.setCursor(0); this.setCursor(0);
this.setScrollCursor(0); this.setScrollCursor(0);
this.getUi().moveTo(this.settingsContainer, this.getUi().length - 1); const ui = this.getUi();
this.getUi().hideTooltip(); ui.moveTo(this.settingsContainer, ui.length - 1);
ui.hideTooltip();
return true; return true;
} }
/**
* Submethod of {@linkcode processInput} to handle left/right input for changing option values
*
* @remarks
* If the cursor is positioned on a boundary option, will apply clamping / wrapping as appropriate
* @param cursor - Current cursor position in the settings menu
* @param dir - Direction to pan when scrolling, -1 for left, 1 for right
* @returns `true` if the action associated with the button was successfully processed, `false` otherwise.
*/
private processLeftRightInput(cursor: number, dir: -1 | 1): boolean {
let boundaryAction = Phaser.Math.Wrap;
let upperBound = this.optionValueLabels[cursor].length;
if (this.settings[cursor]?.clamp) {
boundaryAction = Phaser.Math.Clamp;
// clamping is right inclusive; wrapping isn't
upperBound -= 1;
}
return this.setOptionCursor(cursor, boundaryAction(this.optionCursors[cursor] + dir, 0, upperBound), true);
}
/** /**
* Processes input from a specified button. * Processes input from a specified button.
* This method handles navigation through a UI menu, including movement through menu items * This method handles navigation through a UI menu, including movement through menu items
@ -314,20 +325,10 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
} }
break; break;
case Button.LEFT: case Button.LEFT:
// Cycle to the rightmost position when at the leftmost, otherwise move left success = this.processLeftRightInput(cursor, -1);
success = this.setOptionCursor(
cursor,
Phaser.Math.Wrap(this.optionCursors[cursor] - 1, 0, this.optionValueLabels[cursor].length),
true,
);
break; break;
case Button.RIGHT: case Button.RIGHT:
// Cycle to the leftmost position when at the rightmost, otherwise move right success = this.processLeftRightInput(cursor, 1);
success = this.setOptionCursor(
cursor,
Phaser.Math.Wrap(this.optionCursors[cursor] + 1, 0, this.optionValueLabels[cursor].length),
true,
);
break; break;
case Button.CYCLE_FORM: case Button.CYCLE_FORM:
case Button.CYCLE_SHINY: case Button.CYCLE_SHINY:
@ -376,8 +377,9 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
if (!this.cursorObj) { if (!this.cursorObj) {
const cursorWidth = globalScene.scaledCanvas.width - (this.scrollBar.visible ? 16 : 10); const cursorWidth = globalScene.scaledCanvas.width - (this.scrollBar.visible ? 16 : 10);
this.cursorObj = globalScene.add.nineslice(0, 0, "summary_moves_cursor", undefined, cursorWidth, 16, 1, 1, 1, 1); this.cursorObj = globalScene.add
this.cursorObj.setOrigin(0, 0); .nineslice(0, 0, "summary_moves_cursor", undefined, cursorWidth, 16, 1, 1, 1, 1)
.setOrigin(0);
this.optionsContainer.add(this.cursorObj); this.optionsContainer.add(this.cursorObj);
} }
@ -399,18 +401,21 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
settingIndex = this.cursor + this.scrollCursor; settingIndex = this.cursor + this.scrollCursor;
} }
const setting = this.settings[settingIndex]; const setting = this.settings[settingIndex];
const lastCursor = this.optionCursors[settingIndex]; const lastCursor = this.optionCursors[settingIndex];
// do nothing if the option isn't changing
if (cursor === lastCursor) {
return false;
}
const lastValueLabel = this.optionValueLabels[settingIndex][lastCursor]; this.optionValueLabels[settingIndex][lastCursor]
lastValueLabel.setColor(getTextColor(TextStyle.SETTINGS_VALUE)); .setColor(getTextColor(TextStyle.SETTINGS_VALUE))
lastValueLabel.setShadowColor(getTextColor(TextStyle.SETTINGS_VALUE, true)); .setShadowColor(getTextColor(TextStyle.SETTINGS_VALUE, true));
this.optionCursors[settingIndex] = cursor; this.optionCursors[settingIndex] = cursor;
const newValueLabel = this.optionValueLabels[settingIndex][cursor]; this.optionValueLabels[settingIndex][cursor]
newValueLabel.setColor(getTextColor(TextStyle.SETTINGS_SELECTED)); .setColor(getTextColor(TextStyle.SETTINGS_SELECTED))
newValueLabel.setShadowColor(getTextColor(TextStyle.SETTINGS_SELECTED, true)); .setShadowColor(getTextColor(TextStyle.SETTINGS_SELECTED, true));
if (save) { if (save) {
const saveSetting = () => { const saveSetting = () => {
@ -511,7 +516,7 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
override showText( override showText(
text: string, text: string,
delay?: number, delay?: number,
callback?: Function, callback?: AnyFn,
callbackDelay?: number, callbackDelay?: number,
prompt?: boolean, prompt?: boolean,
promptDelay?: number, promptDelay?: number,

View File

@ -197,7 +197,7 @@ export class MoveTouchControlsHandler {
/** /**
* Returns the current positions of all touch controls that have moved from their default positions of this orientation. * Returns the current positions of all touch controls that have moved from their default positions of this orientation.
* @returns {ControlPosition[]} The current positions of all touch controls that have moved from their default positions of this orientation * @returns The current positions of all touch controls that have moved from their default positions of this orientation
*/ */
private getModifiedCurrentPositions(): ControlPosition[] { private getModifiedCurrentPositions(): ControlPosition[] {
return this.getControlGroupElements() return this.getControlGroupElements()

View File

@ -18,11 +18,7 @@ import { addTextObject } from "#ui/text";
import { truncateString } from "#utils/common"; import { truncateString } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
/** /** Class representing the settings UI handler for gamepads */
* Class representing the settings UI handler for gamepads.
*
* @extends AbstractControlSettingsUiHandler
*/
export class SettingsGamepadUiHandler extends AbstractControlSettingsUiHandler { export class SettingsGamepadUiHandler extends AbstractControlSettingsUiHandler {
/** /**

View File

@ -19,11 +19,7 @@ import { truncateString } from "#utils/common";
import { toPascalSnakeCase } from "#utils/strings"; import { toPascalSnakeCase } from "#utils/strings";
import i18next from "i18next"; import i18next from "i18next";
/** /** Class representing the settings UI handler for keyboards */
* Class representing the settings UI handler for keyboards.
*
* @extends AbstractControlSettingsUiHandler
*/
export class SettingsKeyboardUiHandler extends AbstractControlSettingsUiHandler { export class SettingsKeyboardUiHandler extends AbstractControlSettingsUiHandler {
/** /**
* Creates an instance of SettingsKeyboardUiHandler. * Creates an instance of SettingsKeyboardUiHandler.

View File

@ -6,8 +6,7 @@ import { TextStyle } from "#enums/text-style";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { AchvBar } from "#ui/containers/achv-bar"; import { AchvBar } from "#ui/containers/achv-bar";
import type { BgmBar } from "#ui/containers/bgm-bar"; import type { BgmBar } from "#ui/containers/bgm-bar";
import { PokedexPageUiHandler } from "#ui/containers/pokedex-page-ui-handler"; import { SavingIconContainer } from "#ui/containers/saving-icon-handler";
import { SavingIconHandler } from "#ui/containers/saving-icon-handler";
import { GamepadBindingUiHandler } from "#ui/gamepad-binding-ui-handler"; import { GamepadBindingUiHandler } from "#ui/gamepad-binding-ui-handler";
import { AchvsUiHandler } from "#ui/handlers/achvs-ui-handler"; import { AchvsUiHandler } from "#ui/handlers/achvs-ui-handler";
import { AutoCompleteUiHandler } from "#ui/handlers/autocomplete-ui-handler"; import { AutoCompleteUiHandler } from "#ui/handlers/autocomplete-ui-handler";
@ -19,10 +18,10 @@ import { ChangePasswordFormUiHandler } from "#ui/handlers/change-password-form-u
import { CommandUiHandler } from "#ui/handlers/command-ui-handler"; import { CommandUiHandler } from "#ui/handlers/command-ui-handler";
import { ConfirmUiHandler } from "#ui/handlers/confirm-ui-handler"; import { ConfirmUiHandler } from "#ui/handlers/confirm-ui-handler";
import { EggGachaUiHandler } from "#ui/handlers/egg-gacha-ui-handler"; import { EggGachaUiHandler } from "#ui/handlers/egg-gacha-ui-handler";
import { EggHatchSceneHandler } from "#ui/handlers/egg-hatch-scene-handler"; import { EggHatchSceneUiHandler } from "#ui/handlers/egg-hatch-scene-ui-handler";
import { EggListUiHandler } from "#ui/handlers/egg-list-ui-handler"; import { EggListUiHandler } from "#ui/handlers/egg-list-ui-handler";
import { EggSummaryUiHandler } from "#ui/handlers/egg-summary-ui-handler"; import { EggSummaryUiHandler } from "#ui/handlers/egg-summary-ui-handler";
import { EvolutionSceneHandler } from "#ui/handlers/evolution-scene-handler"; import { EvolutionSceneUiHandler } from "#ui/handlers/evolution-scene-ui-handler";
import { FightUiHandler } from "#ui/handlers/fight-ui-handler"; import { FightUiHandler } from "#ui/handlers/fight-ui-handler";
import { GameStatsUiHandler } from "#ui/handlers/game-stats-ui-handler"; import { GameStatsUiHandler } from "#ui/handlers/game-stats-ui-handler";
import { LoadingModalUiHandler } from "#ui/handlers/loading-modal-ui-handler"; import { LoadingModalUiHandler } from "#ui/handlers/loading-modal-ui-handler";
@ -32,6 +31,7 @@ import { MessageUiHandler } from "#ui/handlers/message-ui-handler";
import { ModifierSelectUiHandler } from "#ui/handlers/modifier-select-ui-handler"; import { ModifierSelectUiHandler } from "#ui/handlers/modifier-select-ui-handler";
import { MysteryEncounterUiHandler } from "#ui/handlers/mystery-encounter-ui-handler"; import { MysteryEncounterUiHandler } from "#ui/handlers/mystery-encounter-ui-handler";
import { PartyUiHandler } from "#ui/handlers/party-ui-handler"; import { PartyUiHandler } from "#ui/handlers/party-ui-handler";
import { PokedexPageUiHandler } from "#ui/handlers/pokedex-page-ui-handler";
import { PokedexScanUiHandler } from "#ui/handlers/pokedex-scan-ui-handler"; import { PokedexScanUiHandler } from "#ui/handlers/pokedex-scan-ui-handler";
import { PokedexUiHandler } from "#ui/handlers/pokedex-ui-handler"; import { PokedexUiHandler } from "#ui/handlers/pokedex-ui-handler";
import { RegistrationFormUiHandler } from "#ui/handlers/registration-form-ui-handler"; import { RegistrationFormUiHandler } from "#ui/handlers/registration-form-ui-handler";
@ -115,7 +115,7 @@ export class UI extends Phaser.GameObjects.Container {
private overlay: Phaser.GameObjects.Rectangle; private overlay: Phaser.GameObjects.Rectangle;
public achvBar: AchvBar; public achvBar: AchvBar;
public bgmBar: BgmBar; public bgmBar: BgmBar;
public savingIcon: SavingIconHandler; public savingIcon: SavingIconContainer;
private tooltipContainer: Phaser.GameObjects.Container; private tooltipContainer: Phaser.GameObjects.Container;
private tooltipBg: Phaser.GameObjects.NineSlice; private tooltipBg: Phaser.GameObjects.NineSlice;
@ -141,8 +141,8 @@ export class UI extends Phaser.GameObjects.Container {
new PartyUiHandler(), new PartyUiHandler(),
new SummaryUiHandler(), new SummaryUiHandler(),
new StarterSelectUiHandler(), new StarterSelectUiHandler(),
new EvolutionSceneHandler(), new EvolutionSceneUiHandler(),
new EggHatchSceneHandler(), new EggHatchSceneUiHandler(),
new EggSummaryUiHandler(), new EggSummaryUiHandler(),
new ConfirmUiHandler(), new ConfirmUiHandler(),
new OptionSelectUiHandler(), new OptionSelectUiHandler(),
@ -198,7 +198,7 @@ export class UI extends Phaser.GameObjects.Container {
globalScene.uiContainer.add(this.achvBar); globalScene.uiContainer.add(this.achvBar);
this.savingIcon = new SavingIconHandler(); this.savingIcon = new SavingIconContainer();
this.savingIcon.setup(); this.savingIcon.setup();
globalScene.uiContainer.add(this.savingIcon); globalScene.uiContainer.add(this.savingIcon);

View File

@ -9,7 +9,7 @@ export enum PokemonIconAnimMode {
type PokemonIcon = Phaser.GameObjects.Container | Phaser.GameObjects.Sprite; type PokemonIcon = Phaser.GameObjects.Container | Phaser.GameObjects.Sprite;
export class PokemonIconAnimHandler { export class PokemonIconAnimHelper {
private icons: Map<PokemonIcon, PokemonIconAnimMode>; private icons: Map<PokemonIcon, PokemonIconAnimMode>;
private toggled: boolean; private toggled: boolean;

View File

@ -16,7 +16,7 @@ type UpdateDetailsCallbackFunction = (index: number) => void;
* - in `UiHandler.processInput`: call `processNavigationInput` to have it handle the cursor updates while calling the defined callbacks * - in `UiHandler.processInput`: call `processNavigationInput` to have it handle the cursor updates while calling the defined callbacks
* - in `UiHandler.clear`: call `reset` * - in `UiHandler.clear`: call `reset`
*/ */
export class ScrollableGridUiHandler { export class ScrollableGridHelper {
private readonly ROWS: number; private readonly ROWS: number;
private readonly COLUMNS: number; private readonly COLUMNS: number;
private handler: UiHandler; private handler: UiHandler;
@ -47,7 +47,7 @@ export class ScrollableGridUiHandler {
* @param scrollBar {@linkcode ScrollBar} * @param scrollBar {@linkcode ScrollBar}
* @returns this * @returns this
*/ */
withScrollBar(scrollBar: ScrollBar): ScrollableGridUiHandler { withScrollBar(scrollBar: ScrollBar): ScrollableGridHelper {
this.scrollBar = scrollBar; this.scrollBar = scrollBar;
this.scrollBar.setTotalRows(Math.ceil(this.totalElements / this.COLUMNS)); this.scrollBar.setTotalRows(Math.ceil(this.totalElements / this.COLUMNS));
return this; return this;
@ -58,7 +58,7 @@ export class ScrollableGridUiHandler {
* @param callback {@linkcode UpdateGridCallbackFunction} * @param callback {@linkcode UpdateGridCallbackFunction}
* @returns this * @returns this
*/ */
withUpdateGridCallBack(callback: UpdateGridCallbackFunction): ScrollableGridUiHandler { withUpdateGridCallBack(callback: UpdateGridCallbackFunction): ScrollableGridHelper {
this.updateGridCallback = callback; this.updateGridCallback = callback;
return this; return this;
} }
@ -68,7 +68,7 @@ export class ScrollableGridUiHandler {
* @param callback {@linkcode UpdateDetailsCallbackFunction} * @param callback {@linkcode UpdateDetailsCallbackFunction}
* @returns this * @returns this
*/ */
withUpdateSingleElementCallback(callback: UpdateDetailsCallbackFunction): ScrollableGridUiHandler { withUpdateSingleElementCallback(callback: UpdateDetailsCallbackFunction): ScrollableGridHelper {
this.updateDetailsCallback = callback; this.updateDetailsCallback = callback;
return this; return this;
} }

View File

@ -12,8 +12,8 @@ import type { MoveSourceType } from "#enums/move-source-type";
import type { SpeciesId } from "#enums/species-id"; import type { SpeciesId } from "#enums/species-id";
import type { EnemyPokemon, PlayerPokemon, Pokemon } from "#field/pokemon"; import type { EnemyPokemon, PlayerPokemon, Pokemon } from "#field/pokemon";
import type { ModifierTypeOption } from "#modifiers/modifier-type"; import type { ModifierTypeOption } from "#modifiers/modifier-type";
import type { DexAttrProps, StarterDataEntry } from "#system/game-data";
import type { DexEntry } from "#types/dex-data"; import type { DexEntry } from "#types/dex-data";
import type { DexAttrProps, StarterDataEntry } from "#types/save-data";
import { BooleanHolder, type NumberHolder } from "./common"; import { BooleanHolder, type NumberHolder } from "./common";
import { getPokemonSpecies } from "./pokemon-utils"; import { getPokemonSpecies } from "./pokemon-utils";
@ -204,7 +204,7 @@ export function applyChallenges(challengeType: ChallengeType.SHOP, status: Boole
* @param challengeType - {@linkcode ChallengeType.POKEMON_ADD_TO_PARTY} * @param challengeType - {@linkcode ChallengeType.POKEMON_ADD_TO_PARTY}
* @param pokemon - The pokemon being caught * @param pokemon - The pokemon being caught
* @param status - Whether the pokemon can be added to the party or not * @param status - Whether the pokemon can be added to the party or not
* @return `true` if any challenge was sucessfully applied, `false` otherwise * @returns `true` if any challenge was sucessfully applied, `false` otherwise
*/ */
export function applyChallenges( export function applyChallenges(
challengeType: ChallengeType.POKEMON_ADD_TO_PARTY, challengeType: ChallengeType.POKEMON_ADD_TO_PARTY,
@ -217,7 +217,7 @@ export function applyChallenges(
* @param challengeType - {@linkcode ChallengeType.POKEMON_FUSION} * @param challengeType - {@linkcode ChallengeType.POKEMON_FUSION}
* @param pokemon - The pokemon being checked * @param pokemon - The pokemon being checked
* @param status - Whether the selected pokemon is allowed to fuse or not * @param status - Whether the selected pokemon is allowed to fuse or not
* @return `true` if any challenge was sucessfully applied, `false` otherwise * @returns `true` if any challenge was sucessfully applied, `false` otherwise
*/ */
export function applyChallenges( export function applyChallenges(
challengeType: ChallengeType.POKEMON_FUSION, challengeType: ChallengeType.POKEMON_FUSION,
@ -230,7 +230,7 @@ export function applyChallenges(
* @param challengeType - {@linkcode ChallengeType.POKEMON_MOVE} * @param challengeType - {@linkcode ChallengeType.POKEMON_MOVE}
* @param moveId - The move being checked * @param moveId - The move being checked
* @param status - Whether the move can be used or not * @param status - Whether the move can be used or not
* @return `true` if any challenge was sucessfully applied, `false` otherwise * @returns `true` if any challenge was sucessfully applied, `false` otherwise
*/ */
export function applyChallenges( export function applyChallenges(
challengeType: ChallengeType.POKEMON_MOVE, challengeType: ChallengeType.POKEMON_MOVE,
@ -243,7 +243,7 @@ export function applyChallenges(
* @param challengeType - {@linkcode ChallengeType.SHOP_ITEM} * @param challengeType - {@linkcode ChallengeType.SHOP_ITEM}
* @param shopItem - The item being checked * @param shopItem - The item being checked
* @param status - Whether the item should be added to the shop or not * @param status - Whether the item should be added to the shop or not
* @return `true` if any challenge was sucessfully applied, `false` otherwise * @returns `true` if any challenge was sucessfully applied, `false` otherwise
*/ */
export function applyChallenges( export function applyChallenges(
challengeType: ChallengeType.SHOP_ITEM, challengeType: ChallengeType.SHOP_ITEM,
@ -256,7 +256,7 @@ export function applyChallenges(
* @param challengeType - {@linkcode ChallengeType.WAVE_REWARD} * @param challengeType - {@linkcode ChallengeType.WAVE_REWARD}
* @param reward - The reward being checked * @param reward - The reward being checked
* @param status - Whether the reward should be added to the reward options or not * @param status - Whether the reward should be added to the reward options or not
* @return `true` if any challenge was sucessfully applied, `false` otherwise * @returns `true` if any challenge was sucessfully applied, `false` otherwise
*/ */
export function applyChallenges( export function applyChallenges(
challengeType: ChallengeType.WAVE_REWARD, challengeType: ChallengeType.WAVE_REWARD,
@ -268,7 +268,7 @@ export function applyChallenges(
* Apply all challenges that prevent recovery from fainting * Apply all challenges that prevent recovery from fainting
* @param challengeType - {@linkcode ChallengeType.PREVENT_REVIVE} * @param challengeType - {@linkcode ChallengeType.PREVENT_REVIVE}
* @param status - Whether fainting is a permanent status or not * @param status - Whether fainting is a permanent status or not
* @return `true` if any challenge was sucessfully applied, `false` otherwise * @returns `true` if any challenge was sucessfully applied, `false` otherwise
*/ */
export function applyChallenges(challengeType: ChallengeType.PREVENT_REVIVE, status: BooleanHolder): boolean; export function applyChallenges(challengeType: ChallengeType.PREVENT_REVIVE, status: BooleanHolder): boolean;

View File

@ -135,8 +135,8 @@ export function randSeedItem<T>(items: T[]): T {
/** /**
* Shuffle a list using the seeded rng. Utilises the Fisher-Yates algorithm. * Shuffle a list using the seeded rng. Utilises the Fisher-Yates algorithm.
* @param {Array} items An array of items. * @param items An array of items.
* @returns {Array} A new shuffled array of items. * @returns A new shuffled array of items.
*/ */
export function randSeedShuffle<T>(items: T[]): T[] { export function randSeedShuffle<T>(items: T[]): T[] {
if (items.length <= 1) { if (items.length <= 1) {
@ -340,8 +340,8 @@ export function rgbToHsv(r: number, g: number, b: number) {
/** /**
* Compare color difference in RGB * Compare color difference in RGB
* @param {Array} rgb1 First RGB color in array * @param rgb1 First RGB color in array
* @param {Array} rgb2 Second RGB color in array * @param rgb2 Second RGB color in array
*/ */
export function deltaRgb(rgb1: number[], rgb2: number[]): number { export function deltaRgb(rgb1: number[], rgb2: number[]): number {
const [r1, g1, b1] = rgb1; const [r1, g1, b1] = rgb1;

Some files were not shown because too many files have changed in this diff Show More