Compare commits
41 Commits
05b7f18234
...
4cc3bfafd6
Author | SHA1 | Date | |
---|---|---|---|
|
4cc3bfafd6 | ||
|
aa6cc95117 | ||
|
19885e0558 | ||
|
f2a6fe5c6a | ||
|
218cf025a3 | ||
|
7f1e94e8ca | ||
|
cf9992f9b8 | ||
|
2dff35c407 | ||
|
ff5b227a6b | ||
|
e0bc1d8781 | ||
|
63a416a65b | ||
|
99e17c94eb | ||
|
fc61489d59 | ||
|
0c862839d3 | ||
|
5eab016903 | ||
|
5c79e6258b | ||
|
5182937040 | ||
|
7b5510b055 | ||
|
6c4b60a2fa | ||
|
bb7af15c4a | ||
|
92afcdea8f | ||
|
c102faf157 | ||
|
7b65c51931 | ||
|
f19cd37436 | ||
|
dfb089a2b9 | ||
|
7a7971ec6c | ||
|
378ce95636 | ||
|
d2c5a283d1 | ||
|
af20712cb5 | ||
|
3f6e43a12d | ||
|
7ac6016df3 | ||
|
bda3013c19 | ||
|
31e3293c51 | ||
|
cb6a0b9973 | ||
|
d70ab3eaf6 | ||
|
2fd87a3cad | ||
|
2c784c662f | ||
|
3e932ce2d0 | ||
|
329c9619f6 | ||
|
1415b74682 | ||
|
13797fe322 |
64
.github/workflows/github-pages.yml
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
name: "Github Pages"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
pages:
|
||||
name: Github Pages
|
||||
if: github.repository == 'pagefaultgames/pokerogue'
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
api-dir: ./
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- name: Checkout repository for Typedoc
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: pokerogue_docs
|
||||
|
||||
- name: Install OS package
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y git openssh-client
|
||||
|
||||
- name: Setup Node 20.13.1
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Checkout repository for Github Pages
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: pokerogue_gh
|
||||
ref: gh-pages
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
working-directory: ${{env.api-dir}}
|
||||
run: |
|
||||
cd pokerogue_docs
|
||||
npm ci
|
||||
npm install typedoc --save-dev
|
||||
|
||||
- name: Generate Typedoc docs
|
||||
working-directory: ${{env.api-dir}}
|
||||
run: |
|
||||
cd pokerogue_docs
|
||||
npx typedoc --out /tmp/docs --githubPages false --entryPoints ./src/
|
||||
|
||||
- name: Commit & Push docs
|
||||
run: |
|
||||
cd pokerogue_gh
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config user.name "github-actions[bot]"
|
||||
mkdir -p $GITHUB_REF_NAME
|
||||
rm -rf $GITHUB_REF_NAME/*
|
||||
cp -r /tmp/docs/. $GITHUB_REF_NAME
|
||||
git add $GITHUB_REF_NAME
|
||||
git commit --allow-empty -m "[skip ci] Deploy docs"
|
||||
git push
|
1
.gitignore
vendored
@ -36,3 +36,4 @@ src/data/battle-anim-data.ts
|
||||
src/overrides.ts
|
||||
|
||||
coverage
|
||||
/typedoc
|
||||
|
100
package-lock.json
generated
@ -31,6 +31,7 @@
|
||||
"lefthook": "^1.6.12",
|
||||
"phaser3spectorjs": "^0.0.8",
|
||||
"pokenode-ts": "^1.20.0",
|
||||
"typedoc": "^0.25.13",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-eslint": "^7.10.0",
|
||||
"vite": "^4.5.0",
|
||||
@ -1663,6 +1664,12 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-sequence-parser": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz",
|
||||
"integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
@ -4246,6 +4253,12 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonc-parser": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
|
||||
"integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jsonify": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz",
|
||||
@ -4557,6 +4570,12 @@
|
||||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/lunr": {
|
||||
"version": "2.3.9",
|
||||
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
|
||||
"integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.10",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
|
||||
@ -4592,6 +4611,18 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
|
||||
"integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
@ -5676,6 +5707,18 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shiki": {
|
||||
"version": "0.14.7",
|
||||
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz",
|
||||
"integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-sequence-parser": "^1.1.0",
|
||||
"jsonc-parser": "^3.2.0",
|
||||
"vscode-oniguruma": "^1.7.0",
|
||||
"vscode-textmate": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/side-channel": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
|
||||
@ -6151,6 +6194,51 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/typedoc": {
|
||||
"version": "0.25.13",
|
||||
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.13.tgz",
|
||||
"integrity": "sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lunr": "^2.3.9",
|
||||
"marked": "^4.3.0",
|
||||
"minimatch": "^9.0.3",
|
||||
"shiki": "^0.14.7"
|
||||
},
|
||||
"bin": {
|
||||
"typedoc": "bin/typedoc"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x"
|
||||
}
|
||||
},
|
||||
"node_modules/typedoc/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typedoc/node_modules/minimatch": {
|
||||
"version": "9.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
|
||||
"integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.4.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
|
||||
@ -7482,6 +7570,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-oniguruma": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
|
||||
"integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/vscode-textmate": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz",
|
||||
"integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/w3c-xmlserializer": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
|
||||
|
@ -12,7 +12,8 @@
|
||||
"test:cov": "vitest run --coverage",
|
||||
"test:watch": "vitest watch --coverage",
|
||||
"eslint": "eslint --fix .",
|
||||
"eslint-ci": "eslint ."
|
||||
"eslint-ci": "eslint .",
|
||||
"docs": "typedoc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.3.0",
|
||||
@ -29,6 +30,7 @@
|
||||
"lefthook": "^1.6.12",
|
||||
"phaser3spectorjs": "^0.0.8",
|
||||
"pokenode-ts": "^1.20.0",
|
||||
"typedoc": "^0.25.13",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-eslint": "^7.10.0",
|
||||
"vite": "^4.5.0",
|
||||
|
BIN
public/audio/cry/718-10-pc.m4a
Normal file
BIN
public/images/battle_anims/PRAS- Giga Impact Opp BG.png
Normal file
After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
BIN
public/images/items/flame_orb.png
Normal file
After Width: | Height: | Size: 367 B |
BIN
public/images/items/toxic_orb.png
Normal file
After Width: | Height: | Size: 408 B |
@ -1332,6 +1332,27 @@
|
||||
"h": 24
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "173_2",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 40,
|
||||
"h": 30
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 11,
|
||||
"y": 11,
|
||||
"w": 18,
|
||||
"h": 18
|
||||
},
|
||||
"frame": {
|
||||
"x": 174,
|
||||
"y": 253,
|
||||
"w": 18,
|
||||
"h": 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "173_3",
|
||||
"rotated": false,
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 60 KiB |
41
public/images/trainer/firebreather.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "firebreather.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 80,
|
||||
"h": 72
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 72
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 80,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 80,
|
||||
"h": 72
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:f692676a166fc1915532cd94d5799af4:fb833f76fb6797474657726bb59a7eee:aeb55e30992938f494b6cd2420158dda$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/firebreather.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
440
public/images/types_ko.json
Normal file
@ -0,0 +1,440 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "types_ko.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 32,
|
||||
"h": 280
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "unknown",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "bug",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 14,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "dark",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 28,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "dragon",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 42,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "electric",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 56,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "fairy",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 70,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "fighting",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 84,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "fire",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 98,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "flying",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 112,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "ghost",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 126,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "grass",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 140,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "ground",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 154,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "ice",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 168,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "normal",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 182,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "poison",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 196,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "psychic",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 210,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "rock",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 224,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "steel",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 238,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "water",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 252,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "stellar",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 266,
|
||||
"w": 32,
|
||||
"h": 14
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:f14cf47d9a8f1d40c8e03aa6ba00fff3:6fc4227b57a95d429a1faad4280f7ec8:5961efbfbf4c56b8745347e7a663a32f$"
|
||||
}
|
||||
}
|
BIN
public/images/types_ko.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
@ -1876,7 +1876,20 @@ export default class BattleScene extends SceneBase {
|
||||
});
|
||||
}
|
||||
|
||||
tryTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, transferStack: boolean, playSound: boolean, instant?: boolean, ignoreUpdate?: boolean): Promise<boolean> {
|
||||
/**
|
||||
* Try to transfer a held item to another pokemon.
|
||||
* If the recepient already has the maximum amount allowed for this item, the transfer is cancelled.
|
||||
* The quantity to transfer is automatically capped at how much the recepient can take before reaching the maximum stack size for the item.
|
||||
* A transfer that moves a quantity smaller than what is specified in the transferQuantity parameter is still considered successful.
|
||||
* @param itemModifier {@linkcode PokemonHeldItemModifier} item to transfer (represents the whole stack)
|
||||
* @param target {@linkcode Pokemon} pokemon recepient in this transfer
|
||||
* @param playSound {boolean}
|
||||
* @param transferQuantity {@linkcode integer} how many items of the stack to transfer. Optional, defaults to 1
|
||||
* @param instant {boolean}
|
||||
* @param ignoreUpdate {boolean}
|
||||
* @returns true if the transfer was successful
|
||||
*/
|
||||
tryTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, playSound: boolean, transferQuantity: integer = 1, instant?: boolean, ignoreUpdate?: boolean): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
const source = itemModifier.pokemonId ? itemModifier.getPokemon(target.scene) : null;
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
@ -1894,14 +1907,16 @@ export default class BattleScene extends SceneBase {
|
||||
if (matchingModifier.stackCount >= maxStackCount) {
|
||||
return resolve(false);
|
||||
}
|
||||
const countTaken = transferStack ? Math.min(itemModifier.stackCount, maxStackCount - matchingModifier.stackCount) : 1;
|
||||
const countTaken = Math.min(transferQuantity, itemModifier.stackCount, maxStackCount - matchingModifier.stackCount);
|
||||
itemModifier.stackCount -= countTaken;
|
||||
newItemModifier.stackCount = matchingModifier.stackCount + countTaken;
|
||||
removeOld = !itemModifier.stackCount;
|
||||
} else if (!transferStack) {
|
||||
newItemModifier.stackCount = 1;
|
||||
removeOld = !(--itemModifier.stackCount);
|
||||
} else {
|
||||
const countTaken = Math.min(transferQuantity, itemModifier.stackCount);
|
||||
itemModifier.stackCount -= countTaken;
|
||||
newItemModifier.stackCount = countTaken;
|
||||
}
|
||||
removeOld = !itemModifier.stackCount;
|
||||
if (!removeOld || !source || this.removeModifier(itemModifier, !source.isPlayer())) {
|
||||
const addModifier = () => {
|
||||
if (!matchingModifier || this.removeModifier(matchingModifier, !target.isPlayer())) {
|
||||
|
@ -501,7 +501,7 @@ export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr {
|
||||
applyMoveAttrs(IncrementMovePriorityAttr,attacker,null,move.getMove(),attackPriority);
|
||||
applyAbAttrs(IncrementMovePriorityAbAttr, attacker, null, move.getMove(), attackPriority);
|
||||
|
||||
if (move.getMove().moveTarget===MoveTarget.USER) {
|
||||
if (move.getMove().moveTarget===MoveTarget.USER || move.getMove().moveTarget===MoveTarget.NEAR_ALLY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -674,7 +674,10 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr {
|
||||
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||
if (this.condition(pokemon, attacker, move.getMove())) {
|
||||
if (!pokemon.getTag(this.tagType)) {
|
||||
pokemon.addTag(this.tagType, undefined, undefined, pokemon.id);
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: move.getName() }));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1226,7 +1229,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
||||
const heldItems = this.getTargetHeldItems(defender).filter(i => i.getTransferrable(false));
|
||||
if (heldItems.length) {
|
||||
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
||||
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false, false).then(success => {
|
||||
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
|
||||
if (success) {
|
||||
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` stole\n${defender.name}'s ${stolenItem.type.name}!`));
|
||||
}
|
||||
@ -1315,7 +1318,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
|
||||
const heldItems = this.getTargetHeldItems(attacker).filter(i => i.getTransferrable(false));
|
||||
if (heldItems.length) {
|
||||
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
||||
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false, false).then(success => {
|
||||
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
|
||||
if (success) {
|
||||
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` stole\n${attacker.name}'s ${stolenItem.type.name}!`));
|
||||
}
|
||||
@ -2066,6 +2069,37 @@ export class BlockNonDirectDamageAbAttr extends AbAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This attribute will block any status damage that you put in the parameter.
|
||||
*/
|
||||
export class BlockStatusDamageAbAttr extends BlockNonDirectDamageAbAttr {
|
||||
private effects: StatusEffect[];
|
||||
|
||||
/**
|
||||
* @param {StatusEffect[]} effects The status effect(s) that will be blocked from damaging the ability pokemon
|
||||
*/
|
||||
constructor(...effects: StatusEffect[]) {
|
||||
super(false);
|
||||
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Pokemon} pokemon The pokemon with the ability
|
||||
* @param {boolean} passive N/A
|
||||
* @param {Utils.BooleanHolder} cancelled Whether to cancel the status damage
|
||||
* @param {any[]} args N/A
|
||||
* @returns Returns true if status damage is blocked
|
||||
*/
|
||||
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (this.effects.includes(pokemon.status.effect)) {
|
||||
cancelled.value = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class BlockOneHitKOAbAttr extends AbAttr {
|
||||
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
cancelled.value = true;
|
||||
@ -2380,6 +2414,41 @@ export class PostTurnAbAttr extends AbAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This attribute will heal 1/8th HP if the ability pokemon has the correct status.
|
||||
*/
|
||||
export class PostTurnStatusHealAbAttr extends PostTurnAbAttr {
|
||||
private effects: StatusEffect[];
|
||||
|
||||
/**
|
||||
* @param {StatusEffect[]} effects The status effect(s) that will qualify healing the ability pokemon
|
||||
*/
|
||||
constructor(...effects: StatusEffect[]) {
|
||||
super(false);
|
||||
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Pokemon} pokemon The pokemon with the ability that will receive the healing
|
||||
* @param {Boolean} passive N/A
|
||||
* @param {any[]} args N/A
|
||||
* @returns Returns true if healed from status, false if not
|
||||
*/
|
||||
applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> {
|
||||
if (this.effects.includes(pokemon.status.effect)) {
|
||||
if (pokemon.getMaxHp() !== pokemon.hp) {
|
||||
const scene = pokemon.scene;
|
||||
const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name;
|
||||
scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(),
|
||||
Math.max(Math.floor(pokemon.getMaxHp() / 8), 1), i18next.t("abilityTriggers:poisonHeal", { pokemonName: pokemon.name, abilityName: abilityName}), true));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After the turn ends, resets the status of either the ability holder or their ally
|
||||
* @param {boolean} allyTarget Whether to target ally, defaults to false (self-target)
|
||||
@ -2870,7 +2939,7 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr {
|
||||
const postBattleLoot = pokemon.scene.currentBattle.postBattleLoot;
|
||||
if (postBattleLoot.length) {
|
||||
const randItem = Utils.randSeedItem(postBattleLoot);
|
||||
if (pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, false, true, true)) {
|
||||
if (pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, true, 1, true)) {
|
||||
postBattleLoot.splice(postBattleLoot.indexOf(randItem), 1);
|
||||
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` picked up\n${randItem.type.name}!`));
|
||||
return true;
|
||||
@ -3200,6 +3269,50 @@ export class MoneyAbAttr extends PostBattleAbAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a stat change after a Pokémon is summoned,
|
||||
* conditioned on the presence of a specific arena tag.
|
||||
*
|
||||
* @extends {PostSummonStatChangeAbAttr}
|
||||
*/
|
||||
export class PostSummonStatChangeOnArenaAbAttr extends PostSummonStatChangeAbAttr {
|
||||
/**
|
||||
* The type of arena tag that conditions the stat change.
|
||||
* @private
|
||||
* @type {ArenaTagType}
|
||||
*/
|
||||
private tagType: ArenaTagType;
|
||||
|
||||
/**
|
||||
* Creates an instance of PostSummonStatChangeOnArenaAbAttr.
|
||||
* Initializes the stat change to increase Attack by 1 stage if the specified arena tag is present.
|
||||
*
|
||||
* @param {ArenaTagType} tagType - The type of arena tag to check for.
|
||||
*/
|
||||
constructor(tagType: ArenaTagType) {
|
||||
super([BattleStat.ATK], 1, true, false);
|
||||
this.tagType = tagType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the post-summon stat change if the specified arena tag is present on pokemon's side.
|
||||
* This is used in Wind Rider ability.
|
||||
*
|
||||
* @param {Pokemon} pokemon - The Pokémon being summoned.
|
||||
* @param {boolean} passive - Whether the effect is passive.
|
||||
* @param {any[]} args - Additional arguments.
|
||||
* @returns {boolean} - Returns true if the stat change was applied, otherwise false.
|
||||
*/
|
||||
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
||||
const side = pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
|
||||
|
||||
if (pokemon.scene.arena.getTagOnSide(this.tagType, side)) {
|
||||
return super.applyPostSummon(pokemon, passive, args);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: { new(...args: any[]): TAttr },
|
||||
pokemon: Pokemon, applyFunc: AbAttrApplyFunc<TAttr>, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
@ -3603,9 +3716,9 @@ export function initAbilities() {
|
||||
.conditionalAttr(pokemon => !Utils.randSeedInt(3), PostTurnResetStatusAbAttr),
|
||||
new Ability(Abilities.GUTS, 3)
|
||||
.attr(BypassBurnDamageReductionAbAttr)
|
||||
.conditionalAttr(pokemon => !!pokemon.status, BattleStatMultiplierAbAttr, BattleStat.ATK, 1.5),
|
||||
.conditionalAttr(pokemon => !!pokemon.status || pokemon.hasAbility(Abilities.COMATOSE), BattleStatMultiplierAbAttr, BattleStat.ATK, 1.5),
|
||||
new Ability(Abilities.MARVEL_SCALE, 3)
|
||||
.conditionalAttr(pokemon => !!pokemon.status, BattleStatMultiplierAbAttr, BattleStat.DEF, 1.5)
|
||||
.conditionalAttr(pokemon => !!pokemon.status || pokemon.hasAbility(Abilities.COMATOSE), BattleStatMultiplierAbAttr, BattleStat.DEF, 1.5)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.LIQUID_OOZE, 3)
|
||||
.attr(ReverseDrainAbAttr),
|
||||
@ -3685,7 +3798,8 @@ export function initAbilities() {
|
||||
new Ability(Abilities.IRON_FIST, 4)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.PUNCHING_MOVE), 1.2),
|
||||
new Ability(Abilities.POISON_HEAL, 4)
|
||||
.unimplemented(),
|
||||
.attr(PostTurnStatusHealAbAttr, StatusEffect.TOXIC, StatusEffect.POISON)
|
||||
.attr(BlockStatusDamageAbAttr, StatusEffect.TOXIC, StatusEffect.POISON),
|
||||
new Ability(Abilities.ADAPTABILITY, 4)
|
||||
.attr(StabBoostAbAttr),
|
||||
new Ability(Abilities.SKILL_LINK, 4)
|
||||
@ -3699,7 +3813,7 @@ export function initAbilities() {
|
||||
.condition(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)),
|
||||
new Ability(Abilities.QUICK_FEET, 4)
|
||||
.conditionalAttr(pokemon => pokemon.status ? pokemon.status.effect === StatusEffect.PARALYSIS : false, BattleStatMultiplierAbAttr, BattleStat.SPD, 2)
|
||||
.conditionalAttr(pokemon => !!pokemon.status, BattleStatMultiplierAbAttr, BattleStat.SPD, 1.5),
|
||||
.conditionalAttr(pokemon => !!pokemon.status || pokemon.hasAbility(Abilities.COMATOSE), BattleStatMultiplierAbAttr, BattleStat.SPD, 1.5),
|
||||
new Ability(Abilities.NORMALIZE, 4)
|
||||
.attr(MoveTypeChangeAttr, Type.NORMAL, 1.2, (user, target, move) => move.id !== Moves.HIDDEN_POWER && move.id !== Moves.WEATHER_BALL &&
|
||||
move.id !== Moves.NATURAL_GIFT && move.id !== Moves.JUDGMENT && move.id !== Moves.TECHNO_BLAST),
|
||||
@ -4268,9 +4382,9 @@ export function initAbilities() {
|
||||
.attr(TypeImmunityStatChangeAbAttr, Type.FIRE, BattleStat.DEF, 2)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.WIND_RIDER, 9)
|
||||
.attr(MoveImmunityStatChangeAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.WIND_MOVE), BattleStat.ATK, 1)
|
||||
.ignorable()
|
||||
.partial(),
|
||||
.attr(MoveImmunityStatChangeAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.WIND_MOVE) && move.getMove().category !== MoveCategory.STATUS, BattleStat.ATK, 1)
|
||||
.attr(PostSummonStatChangeOnArenaAbAttr, ArenaTagType.TAILWIND)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.GUARD_DOG, 9)
|
||||
.attr(PostIntimidateStatChangeAbAttr, [BattleStat.ATK], 1, true)
|
||||
.attr(ForceSwitchOutImmunityAbAttr)
|
||||
@ -4278,8 +4392,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.ROCKY_PAYLOAD, 9)
|
||||
.attr(MoveTypePowerBoostAbAttr, Type.ROCK),
|
||||
new Ability(Abilities.WIND_POWER, 9)
|
||||
.attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.hasFlag(MoveFlags.WIND_MOVE), BattlerTagType.CHARGED)
|
||||
.partial(),
|
||||
.attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.hasFlag(MoveFlags.WIND_MOVE), BattlerTagType.CHARGED),
|
||||
new Ability(Abilities.ZERO_TO_HERO, 9)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
|
@ -4,7 +4,7 @@ import * as Utils from "../utils";
|
||||
import { MoveCategory, allMoves, MoveTarget } from "./move";
|
||||
import { getPokemonMessage } from "../messages";
|
||||
import Pokemon, { HitResult, PokemonMove } from "../field/pokemon";
|
||||
import { MoveEffectPhase, PokemonHealPhase, StatChangePhase} from "../phases";
|
||||
import { MoveEffectPhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase} from "../phases";
|
||||
import { StatusEffect } from "./status-effect";
|
||||
import { BattlerIndex } from "../battle";
|
||||
import { Moves } from "./enums/moves";
|
||||
@ -12,6 +12,9 @@ import { ArenaTagType } from "./enums/arena-tag-type";
|
||||
import { BlockNonDirectDamageAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability";
|
||||
import { BattleStat } from "./battle-stat";
|
||||
import { CommonAnim, CommonBattleAnim } from "./battle-anims";
|
||||
import { Abilities } from "./enums/abilities";
|
||||
import { BattlerTagType } from "./enums/battler-tag-type";
|
||||
import i18next from "i18next";
|
||||
|
||||
export enum ArenaTagSide {
|
||||
BOTH,
|
||||
@ -625,6 +628,22 @@ class TailwindTag extends ArenaTag {
|
||||
|
||||
onAdd(arena: Arena): void {
|
||||
arena.scene.queueMessage(`The Tailwind blew from behind${this.side === ArenaTagSide.PLAYER ? "\nyour" : this.side === ArenaTagSide.ENEMY ? "\nthe opposing" : ""} team!`);
|
||||
|
||||
const source = arena.scene.getPokemonById(this.sourceId);
|
||||
const party = source.isPlayer() ? source.scene.getPlayerField() : source.scene.getEnemyField();
|
||||
|
||||
for (const pokemon of party) {
|
||||
// Apply the CHARGED tag to party members with the WIND_POWER ability
|
||||
if (pokemon.hasAbility(Abilities.WIND_POWER) && !pokemon.getTag(BattlerTagType.CHARGED)) {
|
||||
pokemon.addTag(BattlerTagType.CHARGED);
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: this.getMoveName() }));
|
||||
}
|
||||
// Raise attack by one stage if party member has WIND_RIDER ability
|
||||
if (pokemon.hasAbility(Abilities.WIND_RIDER)) {
|
||||
pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.getBattlerIndex()));
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.ATK], 1, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onRemove(arena: Arena): void {
|
||||
|
@ -1823,7 +1823,7 @@ export const biomeTrainerPools: BiomeTrainerPools = {
|
||||
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
||||
},
|
||||
[Biome.VOLCANO]: {
|
||||
[BiomePoolTier.COMMON]: [],
|
||||
[BiomePoolTier.COMMON]: [ TrainerType.FIREBREATHER ],
|
||||
[BiomePoolTier.UNCOMMON]: [],
|
||||
[BiomePoolTier.RARE]: [],
|
||||
[BiomePoolTier.SUPER_RARE]: [],
|
||||
@ -7304,6 +7304,10 @@ export function initBiomes() {
|
||||
[ Biome.GRAVEYARD, BiomePoolTier.UNCOMMON ]
|
||||
]
|
||||
],
|
||||
[ TrainerType.FIREBREATHER, [
|
||||
[ Biome.VOLCANO, BiomePoolTier.COMMON ]
|
||||
]
|
||||
],
|
||||
[ TrainerType.BROCK, [
|
||||
[ Biome.CAVE, BiomePoolTier.BOSS ]
|
||||
]
|
||||
|
@ -421,6 +421,20 @@ export const trainerTypeDialogue: TrainerTypeDialogue = {
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.FIREBREATHER]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:firebreather.encounter.1",
|
||||
"dialogue:firebreather.encounter.2",
|
||||
"dialogue:firebreather.encounter.3",
|
||||
],
|
||||
victory: [
|
||||
"dialogue:firebreather.victory.1",
|
||||
"dialogue:firebreather.victory.2",
|
||||
"dialogue:firebreather.victory.3",
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.BROCK]: {
|
||||
encounter: [
|
||||
"dialogue:brock.encounter.1",
|
||||
|
@ -16,6 +16,7 @@ export enum TrainerType {
|
||||
DANCER,
|
||||
DEPOT_AGENT,
|
||||
DOCTOR,
|
||||
FIREBREATHER,
|
||||
FISHERMAN,
|
||||
GUITARIST,
|
||||
HARLEQUIN,
|
||||
|
@ -423,6 +423,14 @@ export default class Move implements Localizable {
|
||||
export class AttackMove extends Move {
|
||||
constructor(id: Moves, type: Type, category: MoveCategory, power: integer, accuracy: integer, pp: integer, chance: integer, priority: integer, generation: integer) {
|
||||
super(id, type, category, MoveTarget.NEAR_OTHER, power, accuracy, pp, chance, priority, generation);
|
||||
|
||||
/**
|
||||
* {@link https://bulbapedia.bulbagarden.net/wiki/Freeze_(status_condition)}
|
||||
* > All damaging Fire-type moves can now thaw a frozen target, regardless of whether or not they have a chance to burn;
|
||||
*/
|
||||
if (this.type === Type.FIRE) {
|
||||
this.addAttr(new HealStatusEffectAttr(false, StatusEffect.FREEZE));
|
||||
}
|
||||
}
|
||||
|
||||
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
|
||||
@ -1437,7 +1445,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr {
|
||||
const highestItemTier = heldItems.map(m => m.type.getOrInferTier(poolType)).reduce((highestTier, tier) => Math.max(tier, highestTier), 0);
|
||||
const tierHeldItems = heldItems.filter(m => m.type.getOrInferTier(poolType) === highestItemTier);
|
||||
const stolenItem = tierHeldItems[user.randSeedInt(tierHeldItems.length)];
|
||||
user.scene.tryTransferHeldItemModifier(stolenItem, user, false, false).then(success => {
|
||||
user.scene.tryTransferHeldItemModifier(stolenItem, user, false).then(success => {
|
||||
if (success) {
|
||||
user.scene.queueMessage(getPokemonMessage(user, ` stole\n${target.name}'s ${stolenItem.type.name}!`));
|
||||
}
|
||||
@ -1486,7 +1494,7 @@ export class RemoveHeldItemAttr extends MoveEffectAttr {
|
||||
const highestItemTier = heldItems.map(m => m.type.getOrInferTier(poolType)).reduce((highestTier, tier) => Math.max(tier, highestTier), 0);
|
||||
const tierHeldItems = heldItems.filter(m => m.type.getOrInferTier(poolType) === highestItemTier);
|
||||
const stolenItem = tierHeldItems[user.randSeedInt(tierHeldItems.length)];
|
||||
user.scene.tryTransferHeldItemModifier(stolenItem, user, false, false).then(success => {
|
||||
user.scene.tryTransferHeldItemModifier(stolenItem, user, false).then(success => {
|
||||
if (success) {
|
||||
user.scene.queueMessage(getPokemonMessage(user, ` knocked off\n${target.name}'s ${stolenItem.type.name}!`));
|
||||
}
|
||||
@ -1612,15 +1620,31 @@ export class StealEatBerryAttr extends EatBerryAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move attribute that signals that the move should cure a status effect
|
||||
* @extends MoveEffectAttr
|
||||
* @see {@linkcode apply()}
|
||||
*/
|
||||
export class HealStatusEffectAttr extends MoveEffectAttr {
|
||||
/** List of Status Effects to cure */
|
||||
private effects: StatusEffect[];
|
||||
|
||||
/**
|
||||
* @param selfTarget - Whether this move targets the user
|
||||
* @param ...effects - List of status effects to cure
|
||||
*/
|
||||
constructor(selfTarget: boolean, ...effects: StatusEffect[]) {
|
||||
super(selfTarget);
|
||||
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param user {@linkcode Pokemon} source of the move
|
||||
* @param target {@linkcode Pokemon} target of the move
|
||||
* @param move the {@linkcode Move} being used
|
||||
* @returns true if the status is cured
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (!super.apply(user, target, move, args)) {
|
||||
return false;
|
||||
@ -2680,12 +2704,57 @@ export class HitCountPowerAttr extends VariablePowerAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turning a once was (StatChangeCountPowerAttr) statement and making it available to call for any attribute.
|
||||
* @param {Pokemon} pokemon The pokemon that is being used to calculate the count of positive stats
|
||||
* @returns {number} Returns the amount of positive stats
|
||||
*/
|
||||
const countPositiveStats = (pokemon: Pokemon): number => {
|
||||
return pokemon.summonData.battleStats.reduce((total, stat) => (stat && stat > 0) ? total + stat : total, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Attribute that increases power based on the amount of positive stat increases.
|
||||
*/
|
||||
export class StatChangeCountPowerAttr extends VariablePowerAttr {
|
||||
|
||||
/**
|
||||
* @param {Pokemon} user The pokemon that is being used to calculate the amount of positive stats
|
||||
* @param {Pokemon} target N/A
|
||||
* @param {Move} move N/A
|
||||
* @param {any[]} args The argument for VariablePowerAttr, accumulates and sets the amount of power multiplied by stats
|
||||
* @returns {boolean} Returns true if attribute is applied
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const positiveStats: number = user.summonData.battleStats.reduce((total, stat) => stat > 0 && stat ? total + stat : total, 0);
|
||||
const positiveStats: number = countPositiveStats(user);
|
||||
|
||||
(args[0] as Utils.NumberHolder).value += positiveStats * 20;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Punishment normally has a base power of 60,
|
||||
* but gains 20 power for every increased stat stage the target has,
|
||||
* up to a maximum of 200 base power in total.
|
||||
*/
|
||||
export class PunishmentPowerAttr extends VariablePowerAttr {
|
||||
private PUNISHMENT_MIN_BASE_POWER = 60;
|
||||
private PUNISHMENT_MAX_BASE_POWER = 200;
|
||||
|
||||
/**
|
||||
* @param {Pokemon} 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 {Move} move N/A
|
||||
* @param {any[]} args The value that is being changed due to VariablePowerAttr
|
||||
* @returns Returns true if attribute is applied
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const positiveStats: number = countPositiveStats(target);
|
||||
(args[0] as Utils.NumberHolder).value = Math.min(
|
||||
this.PUNISHMENT_MAX_BASE_POWER,
|
||||
this.PUNISHMENT_MIN_BASE_POWER + positiveStats * 20
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -6110,7 +6179,8 @@ export function initMoves() {
|
||||
new StatusMove(Moves.GUARD_SWAP, Type.PSYCHIC, -1, 10, -1, 0, 4)
|
||||
.unimplemented(),
|
||||
new AttackMove(Moves.PUNISHMENT, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 4)
|
||||
.unimplemented(),
|
||||
.makesContact(true)
|
||||
.attr(PunishmentPowerAttr),
|
||||
new AttackMove(Moves.LAST_RESORT, Type.NORMAL, MoveCategory.PHYSICAL, 140, 100, 5, -1, 0, 4)
|
||||
.attr(LastResortAttr),
|
||||
new StatusMove(Moves.WORRY_SEED, Type.GRASS, 100, 10, -1, 0, 4)
|
||||
@ -6681,6 +6751,7 @@ export function initMoves() {
|
||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||
new AttackMove(Moves.STEAM_ERUPTION, Type.WATER, MoveCategory.SPECIAL, 110, 95, 5, 30, 0, 6)
|
||||
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
|
||||
.attr(HealStatusEffectAttr, false, StatusEffect.FREEZE)
|
||||
.attr(StatusEffectAttr, StatusEffect.BURN),
|
||||
new AttackMove(Moves.HYPERSPACE_HOLE, Type.PSYCHIC, MoveCategory.SPECIAL, 80, -1, 5, -1, 0, 6)
|
||||
.ignoresProtect(),
|
||||
@ -7357,6 +7428,7 @@ export function initMoves() {
|
||||
.attr(MultiHitAttr, MultiHitType._2),
|
||||
new AttackMove(Moves.SCORCHING_SANDS, Type.GROUND, MoveCategory.SPECIAL, 70, 100, 10, 30, 0, 8)
|
||||
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
|
||||
.attr(HealStatusEffectAttr, false, StatusEffect.FREEZE)
|
||||
.attr(StatusEffectAttr, StatusEffect.BURN),
|
||||
new StatusMove(Moves.JUNGLE_HEALING, Type.GRASS, -1, 10, -1, 0, 8)
|
||||
.attr(HealAttr, 0.25, true, false)
|
||||
@ -7736,6 +7808,7 @@ export function initMoves() {
|
||||
new AttackMove(Moves.MATCHA_GOTCHA, Type.GRASS, MoveCategory.SPECIAL, 80, 90, 15, 20, 0, 9)
|
||||
.attr(HitHealAttr)
|
||||
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
|
||||
.attr(HealStatusEffectAttr, false, StatusEffect.FREEZE)
|
||||
.attr(StatusEffectAttr, StatusEffect.BURN)
|
||||
.target(MoveTarget.ALL_NEAR_ENEMIES)
|
||||
.triageMove()
|
||||
|
@ -765,10 +765,10 @@ export const pokemonFormChanges: PokemonFormChanges = {
|
||||
new SpeciesFormChange(Species.DURALUDON, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS))
|
||||
],
|
||||
[Species.ZACIAN]: [
|
||||
new SpeciesFormChange(Species.ZACIAN, "hero", "crowned", new SpeciesFormChangeItemTrigger(FormChangeItem.RUSTED_SWORD))
|
||||
new SpeciesFormChange(Species.ZACIAN, "hero-of-many-battles", "crowned", new SpeciesFormChangeItemTrigger(FormChangeItem.RUSTED_SWORD))
|
||||
],
|
||||
[Species.ZAMAZENTA]: [
|
||||
new SpeciesFormChange(Species.ZAMAZENTA, "hero", "crowned", new SpeciesFormChangeItemTrigger(FormChangeItem.RUSTED_SHIELD))
|
||||
new SpeciesFormChange(Species.ZAMAZENTA, "hero-of-many-battles", "crowned", new SpeciesFormChangeItemTrigger(FormChangeItem.RUSTED_SHIELD))
|
||||
],
|
||||
[Species.ETERNATUS]: [
|
||||
new SpeciesFormChange(Species.ETERNATUS, "", SpeciesFormKey.ETERNAMAX, new SpeciesFormChangeManualTrigger()),
|
||||
|
@ -387,9 +387,11 @@ export abstract class PokemonSpeciesForm {
|
||||
case "four":
|
||||
case "droopy":
|
||||
case "stretchy":
|
||||
case "hero":
|
||||
case "roaming":
|
||||
case "complete":
|
||||
case "10":
|
||||
case "10-pc":
|
||||
case "super":
|
||||
case "unbound":
|
||||
case "pau":
|
||||
@ -2137,13 +2139,13 @@ export function initSpecies() {
|
||||
new PokemonForm("Blue Meteor Form", "blue-meteor", Type.ROCK, Type.FLYING, 0.3, 40, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 440, 60, 60, 100, 60, 100, 60, 30, 70, 154, false, "", true),
|
||||
new PokemonForm("Indigo Meteor Form", "indigo-meteor", Type.ROCK, Type.FLYING, 0.3, 40, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 440, 60, 60, 100, 60, 100, 60, 30, 70, 154, false, "", true),
|
||||
new PokemonForm("Violet Meteor Form", "violet-meteor", Type.ROCK, Type.FLYING, 0.3, 40, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 440, 60, 60, 100, 60, 100, 60, 30, 70, 154, false, "", true),
|
||||
new PokemonForm("Red Core Form", "red", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
|
||||
new PokemonForm("Orange Core Form", "orange", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
|
||||
new PokemonForm("Yellow Core Form", "yellow", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
|
||||
new PokemonForm("Green Core Form", "green", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
|
||||
new PokemonForm("Blue Core Form", "blue", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
|
||||
new PokemonForm("Indigo Core Form", "indigo", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
|
||||
new PokemonForm("Violet Core Form", "violet", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
|
||||
new PokemonForm("Red Core Form", "red", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
|
||||
new PokemonForm("Orange Core Form", "orange", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
|
||||
new PokemonForm("Yellow Core Form", "yellow", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
|
||||
new PokemonForm("Green Core Form", "green", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
|
||||
new PokemonForm("Blue Core Form", "blue", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
|
||||
new PokemonForm("Indigo Core Form", "indigo", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
|
||||
new PokemonForm("Violet Core Form", "violet", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
|
||||
),
|
||||
new PokemonSpecies(Species.KOMALA, 7, false, false, false, "Drowsing Pokémon", Type.NORMAL, null, 0.4, 19.9, Abilities.COMATOSE, Abilities.NONE, Abilities.NONE, 480, 65, 115, 65, 75, 95, 65, 45, 70, 168, GrowthRate.SLOW, 50, false),
|
||||
new PokemonSpecies(Species.TURTONATOR, 7, false, false, false, "Blast Turtle Pokémon", Type.FIRE, Type.DRAGON, 2, 212, Abilities.SHELL_ARMOR, Abilities.NONE, Abilities.NONE, 485, 60, 78, 135, 91, 85, 36, 70, 50, 170, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
@ -2272,7 +2274,7 @@ export function initSpecies() {
|
||||
new PokemonSpecies(Species.TOXEL, 8, false, false, false, "Baby Pokémon", Type.ELECTRIC, Type.POISON, 0.4, 11, Abilities.RATTLED, Abilities.STATIC, Abilities.KLUTZ, 242, 40, 38, 35, 54, 35, 40, 75, 50, 48, GrowthRate.MEDIUM_SLOW, 50, false),
|
||||
new PokemonSpecies(Species.TOXTRICITY, 8, false, false, false, "Punk Pokémon", Type.ELECTRIC, Type.POISON, 1.6, 40, Abilities.PUNK_ROCK, Abilities.PLUS, Abilities.TECHNICIAN, 502, 75, 98, 70, 114, 70, 75, 45, 50, 176, GrowthRate.MEDIUM_SLOW, 50, false, true,
|
||||
new PokemonForm("Amped Form", "amped", Type.ELECTRIC, Type.POISON, 1.6, 40, Abilities.PUNK_ROCK, Abilities.PLUS, Abilities.TECHNICIAN, 502, 75, 98, 70, 114, 70, 75, 45, 50, 176, false, "", true),
|
||||
new PokemonForm("Low-Key Form", "lowkey", Type.ELECTRIC, Type.POISON, 1.6, 40, Abilities.PUNK_ROCK, Abilities.MINUS, Abilities.TECHNICIAN, 502, 75, 98, 70, 114, 70, 75, 45, 50, 176, true),
|
||||
new PokemonForm("Low-Key Form", "lowkey", Type.ELECTRIC, Type.POISON, 1.6, 40, Abilities.PUNK_ROCK, Abilities.MINUS, Abilities.TECHNICIAN, 502, 75, 98, 70, 114, 70, 75, 45, 50, 176, false, "lowkey", true),
|
||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.ELECTRIC, Type.POISON, 24, 40, Abilities.PUNK_ROCK, Abilities.MINUS, Abilities.TECHNICIAN, 602, 95, 118, 80, 144, 80, 85, 45, 50, 176),
|
||||
),
|
||||
new PokemonSpecies(Species.SIZZLIPEDE, 8, false, false, false, "Radiator Pokémon", Type.FIRE, Type.BUG, 0.7, 1, Abilities.FLASH_FIRE, Abilities.WHITE_SMOKE, Abilities.FLAME_BODY, 305, 50, 65, 45, 50, 50, 45, 190, 50, 61, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
@ -2355,11 +2357,11 @@ export function initSpecies() {
|
||||
new PokemonSpecies(Species.DRAKLOAK, 8, false, false, false, "Caretaker Pokémon", Type.DRAGON, Type.GHOST, 1.4, 11, Abilities.CLEAR_BODY, Abilities.INFILTRATOR, Abilities.CURSED_BODY, 410, 68, 80, 50, 60, 50, 102, 45, 50, 144, GrowthRate.SLOW, 50, false),
|
||||
new PokemonSpecies(Species.DRAGAPULT, 8, false, false, false, "Stealth Pokémon", Type.DRAGON, Type.GHOST, 3, 50, Abilities.CLEAR_BODY, Abilities.INFILTRATOR, Abilities.CURSED_BODY, 600, 88, 120, 75, 100, 75, 142, 45, 50, 300, GrowthRate.SLOW, 50, false),
|
||||
new PokemonSpecies(Species.ZACIAN, 8, false, true, false, "Warrior Pokémon", Type.FAIRY, null, 2.8, 110, Abilities.INTREPID_SWORD, Abilities.NONE, Abilities.NONE, 660, 92, 120, 115, 80, 115, 138, 10, 0, 335, GrowthRate.SLOW, null, false, false,
|
||||
new PokemonForm("Hero of Many Battles", "hero", Type.FAIRY, null, 2.8, 110, Abilities.INTREPID_SWORD, Abilities.NONE, Abilities.NONE, 660, 92, 120, 115, 80, 115, 138, 10, 0, 335, false, "", true),
|
||||
new PokemonForm("Hero of Many Battles", "hero-of-many-battles", Type.FAIRY, null, 2.8, 110, Abilities.INTREPID_SWORD, Abilities.NONE, Abilities.NONE, 660, 92, 120, 115, 80, 115, 138, 10, 0, 335, false, "", true),
|
||||
new PokemonForm("Crowned", "crowned", Type.FAIRY, Type.STEEL, 2.8, 355, Abilities.INTREPID_SWORD, Abilities.NONE, Abilities.NONE, 700, 92, 150, 115, 80, 115, 148, 10, 0, 335),
|
||||
),
|
||||
new PokemonSpecies(Species.ZAMAZENTA, 8, false, true, false, "Warrior Pokémon", Type.FIGHTING, null, 2.9, 210, Abilities.DAUNTLESS_SHIELD, Abilities.NONE, Abilities.NONE, 660, 92, 120, 115, 80, 115, 138, 10, 0, 335, GrowthRate.SLOW, null, false, false,
|
||||
new PokemonForm("Hero of Many Battles", "hero", Type.FIGHTING, null, 2.9, 210, Abilities.DAUNTLESS_SHIELD, Abilities.NONE, Abilities.NONE, 660, 92, 120, 115, 80, 115, 138, 10, 0, 335, false, "", true),
|
||||
new PokemonForm("Hero of Many Battles", "hero-of-many-battles", Type.FIGHTING, null, 2.9, 210, Abilities.DAUNTLESS_SHIELD, Abilities.NONE, Abilities.NONE, 660, 92, 120, 115, 80, 115, 138, 10, 0, 335, false, "", true),
|
||||
new PokemonForm("Crowned", "crowned", Type.FIGHTING, Type.STEEL, 2.9, 785, Abilities.DAUNTLESS_SHIELD, Abilities.NONE, Abilities.NONE, 700, 92, 120, 140, 80, 140, 128, 10, 0, 335),
|
||||
),
|
||||
new PokemonSpecies(Species.ETERNATUS, 8, false, true, false, "Gigantic Pokémon", Type.POISON, Type.DRAGON, 20, 950, Abilities.PRESSURE, Abilities.NONE, Abilities.NONE, 690, 140, 85, 95, 145, 95, 130, 255, 0, 345, GrowthRate.SLOW, null, false, true,
|
||||
@ -2468,9 +2470,9 @@ export function initSpecies() {
|
||||
new PokemonSpecies(Species.WUGTRIO, 9, false, false, false, "Garden Eel Pokémon", Type.WATER, null, 1.2, 5.4, Abilities.GOOEY, Abilities.RATTLED, Abilities.SAND_VEIL, 425, 35, 100, 50, 50, 70, 120, 50, 50, 149, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(Species.BOMBIRDIER, 9, false, false, false, "Item Drop Pokémon", Type.FLYING, Type.DARK, 1.5, 42.9, Abilities.BIG_PECKS, Abilities.KEEN_EYE, Abilities.ROCKY_PAYLOAD, 485, 70, 103, 85, 60, 85, 82, 25, 50, 243, GrowthRate.SLOW, 50, false),
|
||||
new PokemonSpecies(Species.FINIZEN, 9, false, false, false, "Dolphin Pokémon", Type.WATER, null, 1.3, 60.2, Abilities.WATER_VEIL, Abilities.NONE, Abilities.NONE, 315, 70, 45, 40, 45, 40, 75, 200, 50, 63, GrowthRate.SLOW, 50, false),
|
||||
new PokemonSpecies(Species.PALAFIN, 9, false, false, false, "Dolphin Pokémon", Type.WATER, null, 1.3, 60.2, Abilities.ZERO_TO_HERO, Abilities.NONE, Abilities.NONE, 457, 100, 70, 72, 53, 62, 100, 45, 50, 160, GrowthRate.SLOW, 50, false, false,
|
||||
new PokemonSpecies(Species.PALAFIN, 9, false, false, false, "Dolphin Pokémon", Type.WATER, null, 1.3, 60.2, Abilities.ZERO_TO_HERO, Abilities.NONE, Abilities.NONE, 457, 100, 70, 72, 53, 62, 100, 45, 50, 160, GrowthRate.SLOW, 50, false, true,
|
||||
new PokemonForm("Zero Form", "zero", Type.WATER, null, 1.3, 60.2, Abilities.ZERO_TO_HERO, Abilities.NONE, Abilities.ZERO_TO_HERO, 457, 100, 70, 72, 53, 62, 100, 45, 50, 160, false, null, true),
|
||||
new PokemonForm("Hero Form", "hero", Type.WATER, null, 1.8, 97.4, Abilities.ZERO_TO_HERO, Abilities.NONE, Abilities.ZERO_TO_HERO, 650, 100, 160, 97, 106, 87, 100, 45, 50, 160, false, null),
|
||||
new PokemonForm("Hero Form", "hero", Type.WATER, null, 1.8, 97.4, Abilities.ZERO_TO_HERO, Abilities.NONE, Abilities.ZERO_TO_HERO, 650, 100, 160, 97, 106, 87, 100, 45, 50, 160),
|
||||
),
|
||||
new PokemonSpecies(Species.VAROOM, 9, false, false, false, "Single-Cyl Pokémon", Type.STEEL, Type.POISON, 1, 35, Abilities.OVERCOAT, Abilities.NONE, Abilities.SLOW_START, 300, 45, 70, 63, 30, 45, 47, 190, 50, 60, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(Species.REVAVROOM, 9, false, false, false, "Multi-Cyl Pokémon", Type.STEEL, Type.POISON, 1.8, 120, Abilities.OVERCOAT, Abilities.NONE, Abilities.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
|
@ -989,6 +989,8 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerType.DEPOT_AGENT]: new TrainerConfig(++t).setMoneyMultiplier(1.45).setEncounterBgm(TrainerType.CLERK),
|
||||
[TrainerType.DOCTOR]: new TrainerConfig(++t).setHasGenders("Nurse", "lass").setHasDouble("Medical Team").setMoneyMultiplier(3).setEncounterBgm(TrainerType.CLERK)
|
||||
.setSpeciesFilter(s => !!s.getLevelMoves().find(plm => plm[1] === Moves.HEAL_PULSE)),
|
||||
[TrainerType.FIREBREATHER]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.ROUGHNECK)
|
||||
.setSpeciesFilter(s => !!s.getLevelMoves().find(plm => plm[1] === Moves.SMOG) || s.isOfType(Type.FIRE)),
|
||||
[TrainerType.FISHERMAN]: new TrainerConfig(++t).setMoneyMultiplier(1.25).setEncounterBgm(TrainerType.BACKPACKER).setSpecialtyTypes(Type.WATER)
|
||||
.setPartyTemplates(trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.THREE_WEAK_SAME, trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.SIX_WEAKER)
|
||||
.setSpeciesPools({
|
||||
|
@ -36,6 +36,7 @@ const trainerNameConfigs: TrainerNameConfigs = {
|
||||
[TrainerType.DANCER]: new TrainerNameConfig(TrainerType.DANCER),
|
||||
[TrainerType.DEPOT_AGENT]: new TrainerNameConfig(TrainerType.DEPOT_AGENT),
|
||||
[TrainerType.DOCTOR]: new TrainerNameConfig(TrainerType.DOCTOR).hasGenderVariant("Nurse"),
|
||||
[TrainerType.FIREBREATHER]: new TrainerNameConfig(TrainerType.FIREBREATHER),
|
||||
[TrainerType.FISHERMAN]: new TrainerNameConfig(TrainerType.FISHERMAN),
|
||||
[TrainerType.GUITARIST]: new TrainerNameConfig(TrainerType.GUITARIST),
|
||||
[TrainerType.HARLEQUIN]: new TrainerNameConfig(TrainerType.HARLEQUIN),
|
||||
@ -87,6 +88,7 @@ export const trainerNamePools = {
|
||||
[TrainerType.DANCER]: ["Brian","Davey","Dirk","Edmond","Mickey","Raymond","Cara","Julia","Maika","Mireille","Ronda","Zoe"],
|
||||
[TrainerType.DEPOT_AGENT]: ["Josh","Hank","Vincent"],
|
||||
[TrainerType.DOCTOR]: [["Hank","Jerry","Jules","Logan","Wayne","Braid","Derek","Heath","Julius","Kit","Graham"],["Kirsten","Sachiko","Shery","Carol","Dixie","Mariah"]],
|
||||
[TrainerType.FIREBREATHER]: ["Bill","Burt","Cliff","Dick","Lyle","Ned","Otis","Ray","Richard","Walt"],
|
||||
[TrainerType.FISHERMAN]: ["Andre","Arnold","Barney","Chris","Edgar","Henry","Jonah","Justin","Kyle","Martin","Marvin","Ralph","Raymond","Scott","Stephen","Wilton","Tully","Andrew","Barny","Carter","Claude","Dale","Elliot","Eugene","Ivan","Ned","Nolan","Roger","Ronald","Wade","Wayne","Darian","Kai","Chip","Hank","Kaden","Tommy","Tylor","Alec","Brett","Cameron","Cody","Cole","Cory","Erick","George","Joseph","Juan","Kenneth","Luc","Miguel","Travis","Walter","Zachary","Josh","Gideon","Kyler","Liam","Murphy","Bruce","Damon","Devon","Hubert","Jones","Lydon","Mick","Pete","Sean","Sid","Vince","Bucky","Dean","Eustace","Kenzo","Leroy","Mack","Ryder","Ewan","Finn","Murray","Seward","Shad","Wharton","Finley","Fisher","Fisk","River","Sheaffer","Timin","Carl","Ernest","Hal","Herbert","Hisato","Mike","Vernon","Harriet","Marina","Chase"],
|
||||
[TrainerType.GUITARIST]: ["Anna","Beverly","January","Tina","Alicia","Claudia","Julia","Lidia","Mireia","Noelia","Sara","Sheila","Tatiana"],
|
||||
[TrainerType.HARLEQUIN]: ["Charley","Ian","Jack","Kerry","Louis","Pat","Paul","Rick","Anders","Clarence","Gary"],
|
||||
|
@ -14,30 +14,51 @@ import { EggTier } from "./data/enums/egg-type";
|
||||
import PokemonInfoContainer from "./ui/pokemon-info-container";
|
||||
import EggsToHatchCountContainer from "./ui/eggs-to-hatch-count-container";
|
||||
|
||||
/**
|
||||
* Class that represents egg hatching
|
||||
*/
|
||||
export class EggHatchPhase extends Phase {
|
||||
/** The egg that is hatching */
|
||||
private egg: Egg;
|
||||
|
||||
/** The number of eggs that are hatching */
|
||||
private eggsToHatchCount: integer;
|
||||
/** The container that lists how many eggs are hatching */
|
||||
private eggsToHatchCountContainer: EggsToHatchCountContainer;
|
||||
|
||||
/** The scene handler for egg hatching */
|
||||
private eggHatchHandler: EggHatchSceneHandler;
|
||||
/** The phaser gameobject container that holds everything */
|
||||
private eggHatchContainer: Phaser.GameObjects.Container;
|
||||
/** The phaser image that is the background */
|
||||
private eggHatchBg: Phaser.GameObjects.Image;
|
||||
/** The phaser rectangle that overlays during the scene */
|
||||
private eggHatchOverlay: Phaser.GameObjects.Rectangle;
|
||||
/** The phaser container that holds the egg */
|
||||
private eggContainer: Phaser.GameObjects.Container;
|
||||
/** The phaser sprite of the egg */
|
||||
private eggSprite: Phaser.GameObjects.Sprite;
|
||||
/** The phaser sprite of the cracks in an egg */
|
||||
private eggCrackSprite: Phaser.GameObjects.Sprite;
|
||||
/** The phaser sprite that represents the overlaid light rays */
|
||||
private eggLightraysOverlay: Phaser.GameObjects.Sprite;
|
||||
/** The phaser sprite of the hatched Pokemon */
|
||||
private pokemonSprite: Phaser.GameObjects.Sprite;
|
||||
/** The phaser sprite for shiny sparkles */
|
||||
private pokemonShinySparkle: Phaser.GameObjects.Sprite;
|
||||
|
||||
/** The {@link PokemonInfoContainer} of the newly hatched Pokemon */
|
||||
private infoContainer: PokemonInfoContainer;
|
||||
|
||||
/** The newly hatched {@link PlayerPokemon} */
|
||||
private pokemon: PlayerPokemon;
|
||||
/** The index of which egg move is unlocked. 0-2 is common, 3 is rare */
|
||||
private eggMoveIndex: integer;
|
||||
/** Internal booleans representing if the egg is hatched, able to be skipped, or skipped */
|
||||
private hatched: boolean;
|
||||
private canSkip: boolean;
|
||||
private skipped: boolean;
|
||||
/** The sound effect being played when the egg is hatched */
|
||||
private evolutionBgm: AnySound;
|
||||
|
||||
constructor(scene: BattleScene, egg: Egg, eggsToHatchCount: integer) {
|
||||
@ -117,6 +138,7 @@ export class EggHatchPhase extends Phase {
|
||||
|
||||
this.eggHatchContainer.add(this.infoContainer);
|
||||
|
||||
// The game will try to unfuse any Pokemon even though eggs should not generate fused Pokemon in the first place
|
||||
const pokemon = this.generatePokemon();
|
||||
if (pokemon.fusionSpecies) {
|
||||
pokemon.clearFusionSpecies();
|
||||
@ -187,6 +209,13 @@ export class EggHatchPhase extends Phase {
|
||||
super.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that animates egg shaking
|
||||
* @param intensity of horizontal shaking. Doubled on the first call (where count is 0)
|
||||
* @param repeatCount the number of times this function should be called (asynchronous recursion?!?)
|
||||
* @param count the current number of times this function has been called.
|
||||
* @returns nothing since it's a Promise<void>
|
||||
*/
|
||||
doEggShake(intensity: number, repeatCount?: integer, count?: integer): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (repeatCount === undefined) {
|
||||
@ -226,6 +255,10 @@ export class EggHatchPhase extends Phase {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to skip the hatching animation
|
||||
* @returns false if cannot be skipped or already skipped. True otherwise
|
||||
*/
|
||||
trySkip(): boolean {
|
||||
if (!this.canSkip || this.skipped) {
|
||||
return false;
|
||||
@ -239,6 +272,9 @@ export class EggHatchPhase extends Phase {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the animation of an egg hatch
|
||||
*/
|
||||
doHatch(): void {
|
||||
this.canSkip = false;
|
||||
this.hatched = true;
|
||||
@ -268,6 +304,9 @@ export class EggHatchPhase extends Phase {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to do the logic and animation of completing a hatch and revealing the Pokemon
|
||||
*/
|
||||
doReveal(): void {
|
||||
// Update/reduce count of hatching eggs when revealed if count is at least 1
|
||||
// If count is 0, hide eggsToHatchCountContainer instead
|
||||
@ -333,10 +372,21 @@ export class EggHatchPhase extends Phase {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to generate sine. (Why is this not a Utils?!?)
|
||||
* @param index random number from 0-7 being passed in to scale pi/128
|
||||
* @param amplitude Scaling
|
||||
* @returns a number
|
||||
*/
|
||||
sin(index: integer, amplitude: integer): number {
|
||||
return amplitude * Math.sin(index * (Math.PI / 128));
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates spraying
|
||||
* @param intensity number of times this is repeated (this is a badly named variable)
|
||||
* @param offsetY how much to offset the Y coordinates
|
||||
*/
|
||||
doSpray(intensity: integer, offsetY?: number) {
|
||||
this.scene.tweens.addCounter({
|
||||
repeat: intensity,
|
||||
@ -347,6 +397,11 @@ export class EggHatchPhase extends Phase {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates a particle used in the spray animation
|
||||
* @param trigIndex Used to modify the particle's vertical speed, is a random number from 0-7
|
||||
* @param offsetY how much to offset the Y coordinate
|
||||
*/
|
||||
doSprayParticle(trigIndex: integer, offsetY: number) {
|
||||
const initialX = this.eggHatchBg.displayWidth / 2;
|
||||
const initialY = this.eggHatchBg.displayHeight / 2 + offsetY;
|
||||
@ -387,12 +442,22 @@ export class EggHatchPhase extends Phase {
|
||||
updateParticle();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a Pokemon to be hatched by the egg
|
||||
* @returns the hatched PlayerPokemon
|
||||
*/
|
||||
generatePokemon(): PlayerPokemon {
|
||||
let ret: PlayerPokemon;
|
||||
let speciesOverride: Species;
|
||||
let speciesOverride: Species; // SpeciesOverride should probably be a passed in parameter for future species-eggs
|
||||
|
||||
this.scene.executeWithSeedOffset(() => {
|
||||
|
||||
/**
|
||||
* Manaphy eggs have a 1/8 chance of being Manaphy and 7/8 chance of being Phione
|
||||
* Legendary eggs pulled from the legendary gacha have a 50% of being converted into
|
||||
* the species that was the legendary focus at the time
|
||||
*/
|
||||
if (this.egg.isManaphyEgg()) {
|
||||
const rand = Utils.randSeedInt(8);
|
||||
|
||||
@ -437,6 +502,18 @@ export class EggHatchPhase extends Phase {
|
||||
.map(s => parseInt(s) as Species)
|
||||
.filter(s => !pokemonPrevolutions.hasOwnProperty(s) && getPokemonSpecies(s).isObtainable() && ignoredSpecies.indexOf(s) === -1);
|
||||
|
||||
/**
|
||||
* Pokemon that are cheaper in their tier get a weight boost. Regionals get a weight penalty
|
||||
* 1 cost mons get 2x
|
||||
* 2 cost mons get 1.5x
|
||||
* 4, 6, 8 cost mons get 1.75x
|
||||
* 3, 5, 7, 9 cost mons get 1x
|
||||
* Alolan, Galarian, and Paldean mons get 0.5x
|
||||
* Hisui mons get 0.125x
|
||||
*
|
||||
* The total weight is also being calculated EACH time there is an egg hatch instead of being generated once
|
||||
* and being the same each time
|
||||
*/
|
||||
let totalWeight = 0;
|
||||
const speciesWeights = [];
|
||||
for (const speciesId of speciesPool) {
|
||||
@ -464,6 +541,16 @@ export class EggHatchPhase extends Phase {
|
||||
ret = this.scene.addPlayerPokemon(pokemonSpecies, 1, undefined, undefined, undefined, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Non Shiny gacha Pokemon have a 1/128 chance of being shiny
|
||||
* Shiny gacha Pokemon have a 1/64 chance of being shiny
|
||||
* IVs are rolled twice and the higher of each stat's IV is taken
|
||||
* The egg move gacha doubles the rate of rare egg moves but the base rates are
|
||||
* Common: 1/48
|
||||
* Rare: 1/24
|
||||
* Epic: 1/12
|
||||
* Legendary: 1/6
|
||||
*/
|
||||
ret.trySetShiny(this.egg.gachaType === GachaType.SHINY ? 1024 : 512);
|
||||
ret.variant = ret.shiny ? ret.generateVariant() : 0;
|
||||
|
||||
|
77
src/field/arena-events.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import { ArenaTagSide } from "#app/data/arena-tag.js";
|
||||
import { ArenaTagType } from "#app/data/enums/arena-tag-type.js";
|
||||
import { TerrainType } from "#app/data/terrain.js";
|
||||
import { WeatherType } from "#app/data/weather.js";
|
||||
|
||||
/** Alias for all {@linkcode ArenaEvent} type strings */
|
||||
export enum ArenaEventType {
|
||||
/** Triggers when a {@linkcode WeatherType} is added, overlapped, or removed */
|
||||
WEATHER_CHANGED = "onWeatherChanged",
|
||||
/** Triggers when a {@linkcode TerrainType} is added, overlapped, or removed */
|
||||
TERRAIN_CHANGED = "onTerrainChanged",
|
||||
|
||||
/** Triggers when a {@linkcode ArenaTagType} is added or removed */
|
||||
TAG_CHANGED = "onTagChanged",
|
||||
}
|
||||
|
||||
/**
|
||||
* Base container class for all {@linkcode ArenaEventType} events
|
||||
* @extends Event
|
||||
*/
|
||||
export class ArenaEvent extends Event {
|
||||
/** The total duration of the {@linkcode ArenaEventType} */
|
||||
public duration: number;
|
||||
constructor(eventType: ArenaEventType, duration: number) {
|
||||
super(eventType);
|
||||
|
||||
this.duration = duration;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Container class for {@linkcode ArenaEventType.WEATHER_CHANGED} events
|
||||
* @extends ArenaEvent
|
||||
*/
|
||||
export class WeatherChangedEvent extends ArenaEvent {
|
||||
/** The {@linkcode WeatherType} being overridden */
|
||||
public oldWeatherType: WeatherType;
|
||||
/** The {@linkcode WeatherType} being set */
|
||||
public newWeatherType: WeatherType;
|
||||
constructor(oldWeatherType: WeatherType, newWeatherType: WeatherType, duration: number) {
|
||||
super(ArenaEventType.WEATHER_CHANGED, duration);
|
||||
|
||||
this.oldWeatherType = oldWeatherType;
|
||||
this.newWeatherType = newWeatherType;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Container class for {@linkcode ArenaEventType.TERRAIN_CHANGED} events
|
||||
* @extends ArenaEvent
|
||||
*/
|
||||
export class TerrainChangedEvent extends ArenaEvent {
|
||||
/** The {@linkcode TerrainType} being overridden */
|
||||
public oldTerrainType: TerrainType;
|
||||
/** The {@linkcode TerrainType} being set */
|
||||
public newTerrainType: TerrainType;
|
||||
constructor(oldTerrainType: TerrainType, newTerrainType: TerrainType, duration: number) {
|
||||
super(ArenaEventType.TERRAIN_CHANGED, duration);
|
||||
|
||||
this.oldTerrainType = oldTerrainType;
|
||||
this.newTerrainType = newTerrainType;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Container class for {@linkcode ArenaEventType.TAG_CHANGED} events
|
||||
* @extends ArenaEvent
|
||||
*/
|
||||
export class TagChangedEvent extends ArenaEvent {
|
||||
/** The {@linkcode ArenaTagType} being set */
|
||||
public arenaTagType: ArenaTagType;
|
||||
/** The {@linkcode ArenaTagSide} the tag is being placed on */
|
||||
public arenaTagSide: ArenaTagSide;
|
||||
constructor(arenaTagType: ArenaTagType, arenaTagSide: ArenaTagSide, duration: number) {
|
||||
super(ArenaEventType.TAG_CHANGED, duration);
|
||||
|
||||
this.arenaTagType = arenaTagType;
|
||||
this.arenaTagSide = arenaTagSide;
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ import { Terrain, TerrainType } from "../data/terrain";
|
||||
import { PostTerrainChangeAbAttr, PostWeatherChangeAbAttr, applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs } from "../data/ability";
|
||||
import Pokemon from "./pokemon";
|
||||
import * as Overrides from "../overrides";
|
||||
import { WeatherChangedEvent, TerrainChangedEvent, TagChangedEvent } from "./arena-events";
|
||||
|
||||
export class Arena {
|
||||
public scene: BattleScene;
|
||||
@ -34,6 +35,8 @@ export class Arena {
|
||||
private pokemonPool: PokemonPools;
|
||||
private trainerPool: BiomeTierTrainerPools;
|
||||
|
||||
public readonly eventTarget: EventTarget = new EventTarget();
|
||||
|
||||
constructor(scene: BattleScene, biome: Biome, bgm: string) {
|
||||
this.scene = scene;
|
||||
this.biomeType = biome;
|
||||
@ -300,6 +303,7 @@ export class Arena {
|
||||
const oldWeatherType = this.weather?.weatherType || WeatherType.NONE;
|
||||
|
||||
this.weather = weather ? new Weather(weather, hasPokemonSource ? 5 : 0) : null;
|
||||
this.eventTarget.dispatchEvent(new WeatherChangedEvent(oldWeatherType, this.weather?.weatherType, this.weather?.turnsLeft));
|
||||
|
||||
if (this.weather) {
|
||||
this.scene.unshiftPhase(new CommonAnimPhase(this.scene, undefined, undefined, CommonAnim.SUNNY + (weather - 1)));
|
||||
@ -324,6 +328,7 @@ export class Arena {
|
||||
const oldTerrainType = this.terrain?.terrainType || TerrainType.NONE;
|
||||
|
||||
this.terrain = terrain ? new Terrain(terrain, hasPokemonSource ? 5 : 0) : null;
|
||||
this.eventTarget.dispatchEvent(new TerrainChangedEvent(oldTerrainType,this.terrain?.terrainType, this.terrain?.turnsLeft));
|
||||
|
||||
if (this.terrain) {
|
||||
if (!ignoreAnim) {
|
||||
@ -545,6 +550,8 @@ export class Arena {
|
||||
this.tags.push(newTag);
|
||||
newTag.onAdd(this);
|
||||
|
||||
this.eventTarget.dispatchEvent(new TagChangedEvent(newTag.tagType, newTag.side, newTag.turnCount));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -978,7 +978,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
if (this.isOnField() && !ability.hasAttr(SuppressFieldAbilitiesAbAttr)) {
|
||||
const suppressed = new Utils.BooleanHolder(false);
|
||||
this.scene.getField(true).map(p => {
|
||||
this.scene.getField(true).filter(p => p !== this).map(p => {
|
||||
if (p.getAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility()) {
|
||||
p.getAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, false, suppressed, [ability]));
|
||||
}
|
||||
@ -1222,7 +1222,22 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that tries to set a Pokemon shiny based on the trainer's trainer ID and secret ID
|
||||
* Endless Pokemon in the end biome are unable to be set to shiny
|
||||
*
|
||||
* The exact mechanic is that it calculates E as the XOR of the player's trainer ID and secret ID
|
||||
* F is calculated as the XOR of the first 16 bits of the Pokemon's ID with the last 16 bits
|
||||
* The XOR of E and F are then compared to the thresholdOverride (default case 32) to see whether or not to generate a shiny
|
||||
* @param thresholdOverride number that is divided by 2^16 (65536) to get the shiny chance
|
||||
* @returns true if the Pokemon has been set as a shiny, false otherwise
|
||||
*/
|
||||
trySetShiny(thresholdOverride?: integer): boolean {
|
||||
// Shiny Pokemon should not spawn in the end biome in endless
|
||||
if (this.scene.gameMode.isEndless && this.scene.arena.biomeType === Biome.END) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const rand1 = Utils.binToDec(Utils.decToBin(this.id).substring(0, 16));
|
||||
const rand2 = Utils.binToDec(Utils.decToBin(this.id).substring(16, 32));
|
||||
|
||||
@ -1250,18 +1265,25 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return this.shiny;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a variant
|
||||
* Has a 10% of returning 2 (epic variant)
|
||||
* And a 30% of returning 1 (rare variant)
|
||||
* Returns 0 (basic shiny) if there is no variant or 60% of the time otherwise
|
||||
* @returns the shiny variant
|
||||
*/
|
||||
generateVariant(): Variant {
|
||||
if (!this.shiny || !variantData.hasOwnProperty(this.species.speciesId)) {
|
||||
return 0;
|
||||
}
|
||||
const rand = Utils.randSeedInt(10);
|
||||
if (rand > 3) {
|
||||
return 0;
|
||||
if (rand >= 4) {
|
||||
return 0; // 6/10
|
||||
} else if (rand >= 1) {
|
||||
return 1; // 3/10
|
||||
} else {
|
||||
return 2; // 1/10
|
||||
}
|
||||
if (rand) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
generateFusionSpecies(forStarter?: boolean): void {
|
||||
@ -3167,7 +3189,7 @@ export class PlayerPokemon extends Pokemon {
|
||||
&& (m as PokemonHeldItemModifier).pokemonId === pokemon.id, true) as PokemonHeldItemModifier[];
|
||||
const transferModifiers: Promise<boolean>[] = [];
|
||||
for (const modifier of fusedPartyMemberHeldModifiers) {
|
||||
transferModifiers.push(this.scene.tryTransferHeldItemModifier(modifier, this, true, false, true, true));
|
||||
transferModifiers.push(this.scene.tryTransferHeldItemModifier(modifier, this, false, modifier.getStackCount(), true, true));
|
||||
}
|
||||
Promise.allSettled(transferModifiers).then(() => {
|
||||
this.scene.updateModifiers(true, true).then(() => {
|
||||
|
@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{pokemonName}} wurde durch {{abilityName}}\nvor Rückstoß geschützt!",
|
||||
"badDreams": "{{pokemonName}} ist in einem Alptraum gefangen!",
|
||||
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
|
||||
} as const;
|
||||
|
@ -367,6 +367,18 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
1: "Ich werde für das nächste Rennen tunen."
|
||||
},
|
||||
},
|
||||
"firebreather": {
|
||||
"encounter": {
|
||||
1: "My flames shall devour you!",
|
||||
2: "My soul is on fire. I'll show you how hot it burns!",
|
||||
3: "Step right up and take a look!"
|
||||
},
|
||||
"victory": {
|
||||
1: "I burned down to ashes...",
|
||||
2: "Yow! That's hot!",
|
||||
3: "Ow! I scorched the tip of my nose!"
|
||||
},
|
||||
},
|
||||
"brock": {
|
||||
"encounter": {
|
||||
1: "Meine Expertise in Bezug auf Gesteins-Pokémon wird dich besiegen! Komm schon!",
|
||||
@ -516,7 +528,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"victory": {
|
||||
1: "Oh, es scheint, als hätte ich verloren.",
|
||||
2: "Es scheint, als hätte ich noch so viel mehr zu lernen, wenn es um den Kämpfe geht.",
|
||||
2: "Es scheint, als hätte ich noch so viel mehr zu lernen, wenn es um Kämpfe geht.",
|
||||
3: "Ich werde mir zu Herzen nehmen, was ich heute gelernt habe."
|
||||
},
|
||||
"defeat": {
|
||||
@ -775,7 +787,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"marshal": {
|
||||
"encounter": {
|
||||
1: `Mein Mentor, Lauro, sieht sieht Potential in dir. Ich werde dich testen,
|
||||
1: `Mein Mentor, Lauro, sieht Potential in dir. Ich werde dich testen,
|
||||
$dich an die Grenzen deiner Stärke bringen. Kiai!`,
|
||||
2: "Ein Sieg, ein entscheidender Sieg, das ist mein Ziel! Herausforderer, hier komme ich!",
|
||||
3: "Ich selber suche die Stärke eines Kämpfers zu entwickeln und jede Schwäche in mir zu brechen!"
|
||||
@ -930,7 +942,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"lacey": {
|
||||
"encounter": {
|
||||
1: "Ich werde dir mit meiner gewohnten Team, als Mitglied der Top Vier gegenüberstehen."
|
||||
1: "Ich werde dir mit meinem gewohnten Team, als Mitglied der Top Vier gegenüberstehen."
|
||||
},
|
||||
"victory": {
|
||||
1: "Das war ein großartiger Kampf!"
|
||||
@ -1025,7 +1037,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"cress": {
|
||||
"encounter": {
|
||||
1: "Das ist korrekt! Ich und meine geschätzten Wasser-Typen werden deine Gegner im Kampf sein!"
|
||||
1: "Das ist korrekt! Ich und meine geschätzten Wasser-Pokémon werden deine Gegner im Kampf sein!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Verlieren? Ich? Das glaube ich nicht."
|
||||
@ -1234,8 +1246,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"bugsy": {
|
||||
"encounter": {
|
||||
1: `Wow, erstaunlich! Du bist ein Experte für Pokémon!
|
||||
$Meine Forschung ist noch nicht abgeschlossen. OK, du gewinnst.`,
|
||||
1: "Ich bin Kai, der Arenaleiter von Azalea City. Ich bin ein großer Fan von Käfer-Pokémon.",
|
||||
},
|
||||
"victory": {
|
||||
1: `Wow, erstaunlich! Du bist ein Experte für Pokémon!
|
||||
|
@ -48,6 +48,7 @@ export const trainerClasses: SimpleTranslationEntries = {
|
||||
"depot_agent": "Bahnangestellter",
|
||||
"doctor": "Arzt",
|
||||
"doctor_female": "Ärztin",
|
||||
"firebreather": "Feuerspucker",
|
||||
"fisherman": "Angler",
|
||||
"fisherman_female": "Angler", // Seems to be the same in german but exists in other languages like italian
|
||||
"gentleman": "Gentleman",
|
||||
|
@ -3,5 +3,7 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!",
|
||||
"badDreams": "{{pokemonName}} is tormented!",
|
||||
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
|
||||
"perishBody": "{{pokemonName}}'s {{abilityName}}\nwill faint both pokemon in 3 turns!",
|
||||
"poisonHeal": "{{pokemonName}}'s {{abilityName}}\nrestored its HP a little!"
|
||||
} as const;
|
||||
|
@ -359,6 +359,18 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
1: "I'll tune up for the next race."
|
||||
},
|
||||
},
|
||||
"firebreather": {
|
||||
"encounter": {
|
||||
1: "My flames shall devour you!",
|
||||
2: "My soul is on fire. I'll show you how hot it burns!",
|
||||
3: "Step right up and take a look!"
|
||||
},
|
||||
"victory": {
|
||||
1: "I burned down to ashes...",
|
||||
2: "Yow! That's hot!",
|
||||
3: "Ow! I scorched the tip of my nose!"
|
||||
},
|
||||
},
|
||||
"brock": {
|
||||
"encounter": {
|
||||
1: "My expertise on Rock-type Pokémon will take you down! Come on!",
|
||||
@ -1203,8 +1215,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"bugsy": {
|
||||
"encounter": {
|
||||
1: `Whoa, amazing! You're an expert on Pokémon!
|
||||
$My research isn't complete yet. OK, you win.`,
|
||||
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."
|
||||
|
@ -209,6 +209,9 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
||||
"LEFTOVERS": { name: "Leftovers", description: "Heals 1/16 of a Pokémon's maximum HP every turn" },
|
||||
"SHELL_BELL": { name: "Shell Bell", description: "Heals 1/8 of a Pokémon's dealt damage" },
|
||||
|
||||
"TOXIC_ORB": { name: "Toxic Orb", description: "Badly poisons its holder at the end of the turn if they do not have a status condition already" },
|
||||
"FLAME_ORB": { name: "Flame Orb", description: "Burns its holder at the end of the turn if they do not have a status condition already" },
|
||||
|
||||
"BATON": { name: "Baton", description: "Allows passing along effects when switching Pokémon, which also bypasses traps" },
|
||||
|
||||
"SHINY_CHARM": { name: "Shiny Charm", description: "Dramatically increases the chance of a wild Pokémon being Shiny" },
|
||||
|
@ -48,6 +48,7 @@ export const trainerClasses: SimpleTranslationEntries = {
|
||||
"depot_agent": "Depot Agent",
|
||||
"doctor": "Doctor",
|
||||
"doctor_female": "Doctor",
|
||||
"firebreather": "Firebreather",
|
||||
"fisherman": "Fisherman",
|
||||
"fisherman_female": "Fisherman",
|
||||
"gentleman": "Gentleman",
|
||||
|
@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "¡{{abilityName}} de {{pokemonName}}\nlo protegió del daño de retroceso!",
|
||||
"badDreams": "¡{{pokemonName}} está atormentado!"
|
||||
"badDreams": "¡{{pokemonName}} está atormentado!",
|
||||
"windPowerCharged": "¡{{pokemonName}} se ha cargado de electricidad gracias a {{moveName}}!",
|
||||
} as const;
|
||||
|
@ -359,6 +359,18 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
1: "I'll tune up for the next race."
|
||||
},
|
||||
},
|
||||
"firebreather": {
|
||||
"encounter": {
|
||||
1: "My flames shall devour you!",
|
||||
2: "My soul is on fire. I'll show you how hot it burns!",
|
||||
3: "Step right up and take a look!"
|
||||
},
|
||||
"victory": {
|
||||
1: "I burned down to ashes...",
|
||||
2: "Yow! That's hot!",
|
||||
3: "Ow! I scorched the tip of my nose!"
|
||||
},
|
||||
},
|
||||
"brock": {
|
||||
"encounter": {
|
||||
1: "My expertise on Rock-type Pokémon will take you down! Come on!",
|
||||
@ -1203,8 +1215,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"bugsy": {
|
||||
"encounter": {
|
||||
1: `Whoa, amazing! You're an expert on Pokémon!
|
||||
$My research isn't complete yet. OK, you win.`,
|
||||
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."
|
||||
|
@ -48,6 +48,7 @@ export const trainerClasses: SimpleTranslationEntries = {
|
||||
"depot_agent": "Ferroviario",
|
||||
"doctor": "Enfermero",
|
||||
"doctor_female": "Enfermera",
|
||||
"firebreather": "Comefuegos",
|
||||
"fisherman": "Pescador",
|
||||
"fisherman_female": "Pescadora",
|
||||
"gentleman": "Aristócrata",
|
||||
|
@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{abilityName}}\nde {{pokemonName}} le protège du contrecoup !",
|
||||
"badDreams": "{{pokemonName}} a le sommeil agité !"
|
||||
"badDreams": "{{pokemonName}} a le sommeil agité !",
|
||||
"windPowerCharged": "{{pokemonName}} a été touché par la capacité {{moveName}} et se charge en électricité !"
|
||||
} as const;
|
||||
|
@ -359,6 +359,18 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
1: "I'll tune up for the next race."
|
||||
},
|
||||
},
|
||||
"firebreather": {
|
||||
"encounter": {
|
||||
1: "My flames shall devour you!",
|
||||
2: "My soul is on fire. I'll show you how hot it burns!",
|
||||
3: "Step right up and take a look!"
|
||||
},
|
||||
"victory": {
|
||||
1: "I burned down to ashes...",
|
||||
2: "Yow! That's hot!",
|
||||
3: "Ow! I scorched the tip of my nose!"
|
||||
},
|
||||
},
|
||||
"brock": {
|
||||
"encounter": {
|
||||
1: "My expertise on Rock-type Pokémon will take you down! Come on!",
|
||||
@ -1203,8 +1215,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"bugsy": {
|
||||
"encounter": {
|
||||
1: `Whoa, amazing! You're an expert on Pokémon!
|
||||
$My research isn't complete yet. OK, you win.`,
|
||||
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."
|
||||
|
@ -48,6 +48,7 @@ export const trainerClasses: SimpleTranslationEntries = {
|
||||
"depot_agent": "Cheminot",
|
||||
"doctor": "Docteur",
|
||||
"doctor_female": "Docteure",
|
||||
"firebreather": "Firebreather",
|
||||
"fisherman": "Pêcheur",
|
||||
"fisherman_female": "Pêcheuse",
|
||||
"gentleman": "Gentleman",
|
||||
|
@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{abilityName}} di {{pokemonName}}\nl'ha protetto dal contraccolpo!",
|
||||
"badDreams": "{{pokemonName}} è tormentato!",
|
||||
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
|
||||
} as const;
|
||||
|
@ -359,6 +359,18 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
1: "I'll tune up for the next race."
|
||||
},
|
||||
},
|
||||
"firebreather": {
|
||||
"encounter": {
|
||||
1: "My flames shall devour you!",
|
||||
2: "My soul is on fire. I'll show you how hot it burns!",
|
||||
3: "Step right up and take a look!"
|
||||
},
|
||||
"victory": {
|
||||
1: "I burned down to ashes...",
|
||||
2: "Yow! That's hot!",
|
||||
3: "Ow! I scorched the tip of my nose!"
|
||||
},
|
||||
},
|
||||
"brock": {
|
||||
"encounter": {
|
||||
1: "My expertise on Rock-type Pokémon will take you down! Come on!",
|
||||
@ -1203,8 +1215,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"bugsy": {
|
||||
"encounter": {
|
||||
1: `Whoa, amazing! You're an expert on Pokémon!
|
||||
$My research isn't complete yet. OK, you win.`,
|
||||
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."
|
||||
|
@ -48,6 +48,7 @@ export const trainerClasses: SimpleTranslationEntries = {
|
||||
"depot_agent": "Depot Agent",
|
||||
"doctor": "Doctor",
|
||||
"doctor_female": "Doctor",
|
||||
"firebreather": "Firebreather",
|
||||
"fisherman": "Fisherman",
|
||||
"fisherman_female": "Fisherman",
|
||||
"gentleman": "Gentleman",
|
||||
|
@ -2,5 +2,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{pokemonName}}(는)은 {{abilityName}} 때문에\n반동 데미지를 받지 않는다!",
|
||||
"badDreams": "{{pokemonName}} is tormented!",
|
||||
"badDreams": "{{pokemonName}}(는)은\n나이트메어 때문에 시달리고 있다!",
|
||||
} as const;
|
||||
|
@ -15,7 +15,7 @@ export const battle: SimpleTranslationEntries = {
|
||||
"trainerDefeated": "{{trainerName}}과(와)의\n승부에서 이겼다!",
|
||||
"moneyWon": "상금으로\n₽{{moneyAmount}}을 손에 넣었다!",
|
||||
"pokemonCaught": "신난다-!\n{{pokemonName}}(를)을 잡았다!",
|
||||
"partyFull": "지닌 포켓몬이 가득 찼습니다. {{pokemonName}}(를)\n대신해 포켓몬을 놓아주시겠습니까?",
|
||||
"partyFull": "지닌 포켓몬이 가득 찼습니다. {{pokemonName}}를(을)\n대신해 포켓몬을 놓아주시겠습니까?",
|
||||
"pokemon": "포켓몬",
|
||||
"sendOutPokemon": "가랏! {{pokemonName}}!",
|
||||
"hitResultCriticalHit": "급소에 맞았다!",
|
||||
|
@ -359,6 +359,18 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
1: "I'll tune up for the next race."
|
||||
},
|
||||
},
|
||||
"firebreather": {
|
||||
"encounter": {
|
||||
1: "My flames shall devour you!",
|
||||
2: "My soul is on fire. I'll show you how hot it burns!",
|
||||
3: "Step right up and take a look!"
|
||||
},
|
||||
"victory": {
|
||||
1: "I burned down to ashes...",
|
||||
2: "Yow! That's hot!",
|
||||
3: "Ow! I scorched the tip of my nose!"
|
||||
},
|
||||
},
|
||||
"brock": {
|
||||
"encounter": {
|
||||
1: "My expertise on Rock-type Pokémon will take you down! Come on!",
|
||||
@ -1203,8 +1215,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"bugsy": {
|
||||
"encounter": {
|
||||
1: `Whoa, amazing! You're an expert on Pokémon!
|
||||
$My research isn't complete yet. OK, you win.`,
|
||||
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."
|
||||
@ -2086,127 +2097,125 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"rival": {
|
||||
"encounter": {
|
||||
1: `@c{smile}Hey, I was looking for you! I knew you were eager to get going but I expected at least a goodbye…
|
||||
$@c{smile_eclosed}So you're really pursuing your dream after all?\n I almost can't believe it.
|
||||
$@c{serious_smile_fists}Since we're here, how about a battle?\nAfter all, I want to make sure you're ready.
|
||||
$@c{serious_mopen_fists}Don't hold back, I want you to give me everything you've got!`
|
||||
1: `@c{smile}오, 찾았다! 떠나려는 건 알고 있었지만\n인사정도는 해줄 줄 알았는데…
|
||||
$@c{smile_eclosed}그러니까 정말로 꿈을 좇겠다는 거지?\n듣고도 못 믿었다니까.
|
||||
$@c{serious_smile_fists}여기까지 온 김에, 배틀은 어때?\n준비가 됐나 보자구.
|
||||
$@c{serious_mopen_fists}망설이지 말고,\n너의 진면목을 보여봐!`
|
||||
},
|
||||
"victory": {
|
||||
1: `@c{shock}Wow… You cleaned me out.\nAre you actually a beginner?
|
||||
$@c{smile}Maybe it was a bit of luck but…\nWho knows you might just be able to go all the way.
|
||||
$By the way, the professor asked me to give you these items. They look pretty cool.
|
||||
$@c{serious_smile_fists}Good luck out there!`
|
||||
1: `@c{shock}와… 정말 깔끔하게 당했네.\n초보자 맞아?
|
||||
$@c{smile}운이 따른 건지도 모르겠지만…\n그래도 정말 꿈을 이룰 지도.
|
||||
$그나저나, 박사님께서 이걸 전해달라고 하시더라.\n좋아 보이던데.
|
||||
$@c{serious_smile_fists}아무튼, 힘 내는거야!`
|
||||
},
|
||||
},
|
||||
"rival_female": {
|
||||
"encounter": {
|
||||
1: `@c{smile_wave}There you are! I've been looking everywhere for you!\n@c{angry_mopen}Did you forget to say goodbye to your best friend?
|
||||
$@c{smile_ehalf}You're going after your dream, huh?\nThat day is really today isn't it…
|
||||
$@c{smile}Anyway, I'll forgive you for forgetting me, but on one condition. @c{smile_wave_wink}You have to battle me!
|
||||
$@c{angry_mopen}Give it your all! Wouldn't want your adventure to be over before it started, right?`
|
||||
1: `@c{smile_wave}여깄구나! 찾고 있었어!\n@c{angry_mopen}절친한테 작별인사도 안 하는거야?
|
||||
$@c{smile_ehalf}꿈을 향해 떠나는거구나. 그렇지?\n이런 날이 오긴 하네…
|
||||
$@c{smile}아무튼, 날 까먹고 가버린 건 용서해주겠어.\n@c{smile_wave_wink}배틀을 해준다면 말야!
|
||||
$@c{angry_mopen}최선을 다 해 봐.\n모험을 시작과 동시에 끝내고 싶지 않다면!`
|
||||
},
|
||||
"victory": {
|
||||
1: `@c{shock}You just started and you're already this strong?!@d{96}\n@c{angry}You totally cheated, didn't you?
|
||||
$@c{smile_wave_wink}Just kidding!@d{64} @c{smile_eclosed}I lost fair and square… I have a feeling you're going to do really well out there.
|
||||
$@c{smile}By the way, the professor wanted me to give you some items. Hopefully they're helpful!
|
||||
$@c{smile_wave}Do your best like always! I believe in you!`
|
||||
1: `@c{shock}왜 벌써 이렇게 센 건데?!@d{96}\n@c{angry}아니면 뭔가 속임수, 그런 거?
|
||||
$@c{smile_wave_wink}농담, 농담!@d{64} @c{smile_eclosed}내가 진 거 맞아…\n너 정말 앞으로도 잘 하겠는데.
|
||||
$@c{smile}아 그래, 박사님께서 전해달라던 물건.\n도움이 되면 좋겠어!
|
||||
$@c{smile_wave}항상 최선을 다 하라구! 믿고 있을게!`
|
||||
},
|
||||
},
|
||||
"rival_2": {
|
||||
"encounter": {
|
||||
1: `@c{smile}Hey, you're here too?\n@c{smile_eclosed}Still a perfect record, huh…?
|
||||
$@c{serious_mopen_fists}I know it kind of looks like I followed you here, but that's mostly not true.
|
||||
$@c{serious_smile_fists}Honestly though, I've been itching for a rematch since you beat me back at home.
|
||||
$I've been doing a lot of my own training so I'll definitely put up a fight this time.
|
||||
$@c{serious_mopen_fists}Don't hold back, just like before!\nLet's go!`
|
||||
1: `@c{smile}어라, 너 여깄었구나?\n@c{smile_eclosed}아직도 전승 중이라, 이거지…?
|
||||
$@c{serious_mopen_fists}널 쫓아서 온 것 같아 보이겠지만, 오해야.
|
||||
$@c{serious_smile_fists}그래도 솔직히 그 때부터 쭉 재대결이 간절했어.
|
||||
$그 동안의 훈련도 있겠다 마침 좋은 기회같지?
|
||||
$@c{serious_mopen_fists}자, 전처럼!\n배틀이야!`
|
||||
},
|
||||
"victory": {
|
||||
1: `@c{neutral_eclosed}Oh. I guess I was overconfident.
|
||||
$@c{smile}That's alright, though. I figured this might happen.\n@c{serious_mopen_fists}It just means I need to try harder for next time!\n
|
||||
$@c{smile}Oh, not that you really need the help, but I had an extra one of these lying around and figured you might want it.\n
|
||||
$@c{serious_smile_fists}Don't expect another one after this, though!\nI can't keep giving my opponent an advantage after all.
|
||||
$@c{smile}Anyway, take care!`
|
||||
1: `@c{neutral_eclosed}이런. 자신감이 과했나봐.
|
||||
$@c{smile}그래, 또 지고 말았네.\n@c{serious_mopen_fists}좀 더 열심히 훈련을 해야겠어!\n
|
||||
$@c{smile}너한테 도움이 필요할 것 같지는 않지만, 이거.\n남는 게 있어서 말이야.
|
||||
$@c{serious_smile_fists}물론 이번이 마지막이야, 알겠지?\n공평하게 하지 않으면 그게 내 핑계거리가 되고 말거야.
|
||||
$@c{smile}이제 갈게. 앞으로도 조심하고!`
|
||||
},
|
||||
},
|
||||
"rival_2_female": {
|
||||
"encounter": {
|
||||
1: `@c{smile_wave}Oh, fancy meeting you here. Looks like you're still undefeated. @c{angry_mopen}Huh… Not bad!
|
||||
$@c{angry_mopen}I know what you're thinking, and no, I wasn't creeping on you. @c{smile_eclosed}I just happened to be in the area.
|
||||
$@c{smile_ehalf}I'm happy for you but I just want to let you know that it's OK to lose sometimes.
|
||||
$@c{smile}We learn from our mistakes, often more than we would if we kept succeeding.
|
||||
$@c{angry_mopen}In any case, I've been training hard for our rematch, so you'd better give it your all!`
|
||||
1: `@c{smile_wave}우연이네, 이런 곳에서 만나고.\n아직 연전연승이구나? @c{angry_mopen}나쁘지 않아!
|
||||
$@c{angry_mopen}무슨 생각하고있는지 알겠어, 하지만 아냐.\n@c{smile_eclosed}우연히 근처에 있었을 뿐이라구.
|
||||
$@c{smile_ehalf}그래도 마침, 가끔은 지는것도 괜찮다고 알려주고 싶었는데.
|
||||
$@c{smile}우린 실수를 통해서도 성장할 수 있잖아.\n때로는 성공을 반복할 때보다도 더 많이 말야.
|
||||
$@c{angry_mopen}어쨌든간에, 나도 이런 때를 위해 훈련해왔으니까,\n너도 최선을 다 하는게 좋을 거야!`
|
||||
},
|
||||
"victory": {
|
||||
1: `@c{neutral}I… wasn't supposed to lose that time…
|
||||
$@c{smile}Aw well. That just means I'll have to train even harder for next time!
|
||||
$@c{smile_wave}I also got you another one of these!\n@c{smile_wave_wink}No need to thank me~.
|
||||
$@c{angry_mopen}This is the last one, though! You won't be getting anymore freebies from me after this!
|
||||
$@c{smile_wave}Keep at it!`
|
||||
1: `@c{neutral}이… 번에도 져버릴 줄이야…
|
||||
$@c{smile}으, 그래. 더 열심히 훈련하면 되겠지!
|
||||
$@c{smile_wave}이것도 하나 더 챙겨왔으니 받아!\n@c{smile_wave_wink}감사 인사는 됐다구~.
|
||||
$@c{angry_mopen}하지만, 마지막이야!\n또 이렇게 공짜로 나눠주진 않을 테니까!
|
||||
$@c{smile_wave}그럼!`
|
||||
},
|
||||
"defeat": {
|
||||
1: "It's OK to lose sometimes…"
|
||||
1: "가끔은 지는 것도 괜찮아…"
|
||||
}
|
||||
},
|
||||
"rival_3": {
|
||||
"encounter": {
|
||||
1: `@c{smile}Hey, look who it is! It's been a while.\n@c{neutral}You're… still undefeated? Huh.
|
||||
$@c{neutral_eclosed}Things have been kind of… strange.\nIt's not the same back home without you.
|
||||
$@c{serious}I know it's selfish, but I need to get this off my chest.\n@c{neutral_eclosed}I think you're in over your head here.
|
||||
$@c{serious}Never losing once is just unrealistic.\nWe need to lose sometimes in order to grow.
|
||||
$@c{neutral_eclosed}You've had a great run but there's still so much ahead, and it only gets harder. @c{neutral}Are you prepared for that?
|
||||
$@c{serious_mopen_fists}If so, prove it to me.`
|
||||
1: `@c{smile}이게 누구야! 오랜만이야.\n@c{neutral}역시나… 쭉 이기고 있었구나?
|
||||
$@c{neutral_eclosed}상황이 좀… 그렇더라. \n혼자 마을로 돌아가봤자 너 없인 예전같아질 수 없겠지.
|
||||
$@c{serious}이기적인 이야기란건 알지만 말해야겠어.\n@c{neutral_eclosed}너 지금 좀 아닌 것 같아.
|
||||
$@c{serious}계속 이기기만 하겠다는 건 너무 비현실적이야.\n사람은 원래 꺾여가며 성장하는 거라고.
|
||||
$@c{neutral_eclosed}물론 지금까지는 잘 해왔다고 생각하겠지만,\n갈 길이 멀지. @c{neutral}대비는 되어 있어?
|
||||
$@c{serious_mopen_fists}그렇다면, 내게 증명해 줘.`
|
||||
},
|
||||
"victory": {
|
||||
1: "@c{angry_mhalf}This is ridiculous… I've hardly stopped training…\nHow are we still so far apart?"
|
||||
1: "@c{angry_mhalf}말도 안 돼… 한시도 쉬지 않고 훈련했는데…\n어째서 전혀 닿을 수 없는거야?"
|
||||
},
|
||||
},
|
||||
"rival_3_female": {
|
||||
"encounter": {
|
||||
1: `@c{smile_wave}Long time no see! Still haven't lost, huh.\n@c{angry}You're starting to get on my nerves. @c{smile_wave_wink}Just kidding!
|
||||
$@c{smile_ehalf}But really, don't you miss home by now? Or… me?\nI… I mean, we've really missed you.
|
||||
$@c{smile_eclosed}I support you in your dream and everything, but the reality is you're going to lose sooner or later.
|
||||
$@c{smile}And when you do, I'll be there for you like always.\n@c{angry_mopen}Now, let me show you how strong I've become!`
|
||||
1: `@c{smile_wave}오랜만이야! 아직도 안 졌구나.\n@c{angry}거슬리게 말야. @c{smile_wave_wink}농담이야!
|
||||
$@c{smile_ehalf}하지만 진짜, 고향이 그립진 않아? 집이나… 나는?\n나… 나는, 네가 정말 그리웠어.
|
||||
$@c{smile_eclosed}난 너의 꿈과 모든 것을 응원하지만,\n넌 언젠가 패배를 겪게 될 거야.
|
||||
$@c{smile}그 땐 언제나처럼 내가 곁에 있어줄게.\n@c{angry_mopen}내가 얼마나 강해졌는지도, 지금 보여 줄 테니까!`
|
||||
},
|
||||
"victory": {
|
||||
1: "@c{shock}After all that… it wasn't enough…?\nYou'll never come back at this rate…"
|
||||
|
||||
1: "@c{shock}이렇게까지 했는데도… 모자랐던 거야…?\n이러면 정말로 너는 이제 영영…"
|
||||
},
|
||||
"defeat": {
|
||||
1: "You gave it your best, now let's go home."
|
||||
1: "최선을 다 했지.\n집에 갈 시간이야."
|
||||
}
|
||||
},
|
||||
"rival_4": {
|
||||
"encounter": {
|
||||
1: `@c{neutral}Hey.
|
||||
$I won't mince words or pleasantries with you.\n@c{neutral_eclosed}I'm here to win, plain and simple.
|
||||
$@c{serious_mhalf_fists}I've learned to maximize my potential by putting all my time into training.
|
||||
$@c{smile}You get a lot of extra time when you cut out the unnecessary sleep and social interaction.
|
||||
$@c{serious_mopen_fists}None of that matters anymore, not until I win.
|
||||
$@c{neutral_eclosed}I've even reached the point where I don't lose anymore.\n@c{smile_eclosed}I suppose your philosophy wasn't so wrong after all.
|
||||
$@c{angry_mhalf}Losing is for the weak, and I'm not weak anymore.
|
||||
$@c{serious_mopen_fists}Prepare yourself.`
|
||||
1: `@c{neutral}안녕.
|
||||
$잡담은 넘어가자.\n@c{neutral_eclosed}너에게 이기기 위해 찾아왔어. 간단하지.
|
||||
$@c{serious_mhalf_fists}이제 잠재력을 끌어내는 법은 확실히 알겠어.
|
||||
$@c{smile}잠이나 사회적인 활동들.\n줄일 수 있는 불필요한 시간이 아주 많더라.
|
||||
$@c{serious_mopen_fists}오직 승리 뿐이야.\n이제 아무것도 중요하지 않아.
|
||||
$@c{neutral_eclosed}나도 이제 더 이상은 지지 않게 됐어.\n@c{smile_eclosed}네 그 철학이 완전히 틀린 건 아니었나봐.
|
||||
$@c{angry_mhalf}패배는 약자에게 주어지는 것이고, 난 더 이상 약하지 않아.
|
||||
$@c{serious_mopen_fists}준비해.`
|
||||
},
|
||||
"victory": {
|
||||
1: "@c{neutral}What…@d{64} What are you?"
|
||||
1: "@c{neutral}너…@d{64} 너 대체 뭐야?"
|
||||
},
|
||||
},
|
||||
"rival_4_female": {
|
||||
"encounter": {
|
||||
1: `@c{neutral}It's me! You didn't forget about me again… did you?
|
||||
$@c{smile}You should be proud of how far you made it. Congrats!\nBut it looks like it's the end of your journey.
|
||||
$@c{smile_eclosed}You've awoken something in me I never knew was there.\nIt seems like all I do now is train.
|
||||
$@c{smile_ehalf}I hardly even eat or sleep now, I just train my Pokémon all day, getting stronger every time.
|
||||
$@c{neutral}In fact, I… hardly recognize myself.
|
||||
$And now, I've finally reached peak performance.\nI don't think anyone could beat me now.
|
||||
$And you know what? It's all because of you.\n@c{smile_ehalf}I don't know whether to thank you or hate you.
|
||||
$@c{angry_mopen}Prepare yourself.`
|
||||
1: `@c{neutral}나야! 날 잊어버리고 있던 건… 아니지?
|
||||
$@c{smile}네 업적에 자랑스러워 할 때가 됐어. 축하해!\n하지만 네 여행도 여기까지야.
|
||||
$@c{smile_eclosed}너는 나도 모르던 내 안의 무언가를 일깨웠어.\n이제 훈련 말고는 아무것도 하지 않아.
|
||||
$@c{smile_ehalf}먹지도 자지도 않고, 그저 하루종일.\n더 강해지고 있어.
|
||||
$@c{neutral}사실, 나… 이제 내가 뭔지도 잘 모르겠어.
|
||||
$그렇지만 기량만은, 정점에 다다랐지.\n아무도 내게 이길 수 없을거야.
|
||||
$그거 알아? 이게 전부 네 덕이야.\n@c{smile_ehalf}감사해야할지 증오해야할지 모르겠네.
|
||||
$@c{angry_mopen}준비해.`
|
||||
},
|
||||
"victory": {
|
||||
1: "@c{neutral}What…@d{64} What are you?"
|
||||
|
||||
1: "@c{neutral}너…@d{64} 너 대체 뭐야?"
|
||||
},
|
||||
"defeat": {
|
||||
1: "$@c{smile}You should be proud of how far you made it."
|
||||
1: "$@c{smile}네가 키운 상대야. 자랑스럽지?"
|
||||
}
|
||||
},
|
||||
"rival_5": {
|
||||
@ -2231,47 +2240,46 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"rival_6": {
|
||||
"encounter": {
|
||||
1: `@c{smile_eclosed}We meet again.
|
||||
$@c{neutral}I've had some time to reflect on all this.\nThere's a reason this all seems so strange.
|
||||
$@c{neutral_eclosed}Your dream, my drive to beat you…\nIt's all a part of something greater.
|
||||
$@c{serious}This isn't about me, or about you… This is about the world, @c{serious_mhalf_fists}and it's my purpose to push you to your limits.
|
||||
$@c{neutral_eclosed}Whether I've fulfilled that purpose I can't say, but I've done everything in my power.
|
||||
$@c{neutral}This place we ended up in is terrifying… Yet somehow I feel unphased, like I've been here before.
|
||||
$@c{serious_mhalf_fists}You feel the same, don't you?
|
||||
$@c{serious}…and it's like something here is speaking to me.\nThis is all the world's known for a long time now.
|
||||
$Those times we cherished together that seem so recent are nothing but a distant memory.
|
||||
$@c{neutral_eclosed}Who can say whether they were ever even real in the first place.
|
||||
$@c{serious_mopen_fists}You need to keep pushing, because if you don't, it will never end. You're the only one who can do this.
|
||||
$@c{serious_smile_fists}I hardly know what any of this means, I just know that it's true.
|
||||
$@c{serious_mopen_fists}If you can't defeat me here and now, you won't stand a chance.`
|
||||
1: `@c{smile_eclosed}다시 만났구나.
|
||||
$@c{neutral}모든 걸 되짚어 봤어.\n이 기이함에도 이유가 있더라.
|
||||
$@c{neutral_eclosed}널 이기고자 하는 욕구, 아니면 네 꿈…\n이건 그저 더 큰 무언가의 일부일 뿐이었어.
|
||||
$@c{serious}개인의 문제가 아니라 세계 전체가 엮인 일이었고…\n@c{serious_mhalf_fists}난 널 한계까지 밀어붙이기 위한 도구였던 거지.
|
||||
$@c{neutral_eclosed}내가 잘 쓰였는진 모르겠지만 어쨌든 최선을 다 했고.
|
||||
$@c{neutral}끝끝내 도착한 이곳은 끔찍하지만…\n언젠가 와 본 것 같아.
|
||||
$@c{serious_mhalf_fists}너도 그렇게 느끼지?
|
||||
$@c{serious}…그리고 무언가가 이야기하고 있어.\n오랫동안 세상에 알려져온 무언가가.
|
||||
$우리가 함께했던 소중한 시간들은 이제 그저 아득해.
|
||||
$@c{neutral_eclosed}실제로 일어난 일이긴 할까?
|
||||
$@c{serious_mopen_fists}너는 계속 나아가야 해. 그렇지 않으면 끝나지 않아.\n오직 너만이 할 수 있어.
|
||||
$@c{serious_smile_fists}잘 모르겠지만, 하나만은 확실해.
|
||||
$@c{serious_mopen_fists}여기서 날 쓰러뜨리지 못한다면, 너에게 기회는 없을거란걸.`
|
||||
},
|
||||
"victory": {
|
||||
1: `@c{smile_eclosed}It looks like my work is done here.
|
||||
$I want you to promise me one thing.\n@c{smile}After you heal the world, please come home.`
|
||||
1: `@c{smile_eclosed}내 역할은 여기까진 것 같아.
|
||||
$하나만 약속해 줘.\n@c{smile}세상을 원래대로 되돌리고 나면, 집으로 돌아오는거야.`
|
||||
},
|
||||
},
|
||||
"rival_6_female": {
|
||||
"encounter": {
|
||||
1: `@c{smile_ehalf}So it's just us again.
|
||||
$@c{smile_eclosed}You know, I keep going around and around in my head…
|
||||
$@c{smile_ehalf}There's something to all this, why everything seems so strange now…
|
||||
$@c{smile}You have your dream, and I have this ambition in me…
|
||||
$I just can't help but feel there's a greater purpose to all this, to what we're doing, you and I.
|
||||
$@c{smile_eclosed}I think I'm supposed to push you… to your limits.
|
||||
$@c{smile_ehalf}I'm not sure if I've been doing a good job at that, but I've tried my best up to now.
|
||||
$It's something about this strange and dreadful place… Everything seems so clear…
|
||||
$This… is all the world's known for a long time now.
|
||||
$@c{smile_eclosed}It's like I can barely remember the memories we cherished together.
|
||||
$@c{smile_ehalf}Were they even real? They seem so far away now…
|
||||
$@c{angry_mopen}You need to keep pushing, because if you don't, it will never end. You're the only one who can do this.
|
||||
$@c{smile_ehalf}I… don't know what all this means… but I feel it's true.
|
||||
$@c{neutral}If you can't defeat me here and now, you won't stand a chance.`
|
||||
1: `@c{smile_ehalf}또 이렇게 만났네.
|
||||
$@c{smile_eclosed}나 머릿속이 빙글빙글 도는 것 같아…
|
||||
$@c{smile_ehalf}모든 것이 이상하게 보이는 이유.\n분명 뭔가가 있어…
|
||||
$@c{smile}너는 너의 꿈이 있고,\n나는 나의 야망이 있지…
|
||||
$이 모든것, 우리가 하고 있는 모든 일들이\n더 큰 무언가를 위한 것임을 느낄 수밖에 없어.
|
||||
$@c{smile_eclosed}나는 아마 너를…\n한계까지 몰아붙여야 하는 거야.
|
||||
$@c{smile_ehalf}잘 해왔는지는 모르겠는데, 최선은 다 했어.
|
||||
$이 이상하고 무서운 곳…\n모든게 선명하게 보이고…
|
||||
$이건… 오래전부터 세상에 알려져온 전부.
|
||||
$@c{smile_eclosed}우리가 함께해온 추억들이, 이제는 거의 떠오르지 않아.
|
||||
$@c{smile_ehalf}실제로 일어났던 일일까? 너무 멀게만 느껴지는데…
|
||||
$@c{angry_mopen}계속 나아가야 해. 안 그러면, 영원히 끝나지 않을 거야. \n오직 너만이 할 수 있어.
|
||||
$@c{smile_ehalf}난… 이 모든게 무슨 의미가 있는지는 잘 모르겠지만…\n이거 하나는 느끼고 있어.
|
||||
$@c{neutral}여기서 날 쓰러뜨리지 못한다면, 너에게 기회는 없을거란걸.`
|
||||
},
|
||||
"victory": {
|
||||
1: `@c{smile_ehalf}I… I think I fulfilled my purpose…
|
||||
$@c{smile_eclosed}Promise me… After you heal the world… Please… come home safe.
|
||||
$@c{smile_ehalf}…Thank you.`
|
||||
|
||||
1: `@c{smile_ehalf}나… 내 소임을 다 한 기분이야…
|
||||
$@c{smile_eclosed}약속해 줘… 세상을 원래대로 되돌리고서… \n집으로… 무사히 돌아오는 거야.
|
||||
$@c{smile_ehalf}…고마워.`
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -2282,17 +2290,17 @@ export const PGFdialogue: DialogueTranslationEntries = PGMdialogue;
|
||||
|
||||
// Dialogue of the endboss of the game when the player character is male (Or unset)
|
||||
export const PGMbattleSpecDialogue: SimpleTranslationEntries = {
|
||||
"encounter": `It appears the time has finally come once again.\nYou know why you have come here, do you not?
|
||||
$You were drawn here, because you have been here before.\nCountless times.
|
||||
$Though, perhaps it can be counted.\nTo be precise, this is in fact your 5,643,853rd cycle.
|
||||
$Each cycle your mind reverts to its former state.\nEven so, somehow, remnants of your former selves remain.
|
||||
$Until now you have yet to succeed, but I sense a different presence in you this time.\n
|
||||
$You are the only one here, though it is as if there is… another.
|
||||
$Will you finally prove a formidable challenge to me?\nThe challenge I have longed for for millennia?
|
||||
$We begin.`,
|
||||
"firstStageWin": `I see. The presence I felt was indeed real.\nIt appears I no longer need to hold back.
|
||||
$Do not disappoint me.`,
|
||||
"secondStageWin": "…Magnificent."
|
||||
"encounter": `드디어 때가 다시 도래했다.\n당도한 연유를 아는가?
|
||||
$이미 도달한 적이 있기에 이 자리에 있다.\n셀 수도 없이 많이.
|
||||
$아니, 사실 셀 수는 있지.\n정확히 너의 5,643,853번째다.
|
||||
$매 번 태초의 정신으로 되돌아갔을 뿐.\n하지만 어떻게든, 흔적은 남는다.
|
||||
$실패만을 반복했을 뿐이지만,\n지금은 네 안에 무언가가 있구나.\n
|
||||
$홀로 선 것처럼 보이나, 무언가 이질적인…
|
||||
$마침내 그간의 갈망을 해소해주는가?\n수천 년 간 기다려온 도전을?
|
||||
$시작하지.`,
|
||||
"firstStageWin": `그렇군. 정말로 있었어.\n이제 주저할 필요는 없다.
|
||||
$실망시키지 않도록.`,
|
||||
"secondStageWin": "…고무적이군."
|
||||
};
|
||||
|
||||
// Dialogue of the endboss of the game when the player character is female. For languages that do not have gendered pronouns, this can be set to PGMbattleSpecDialogue.
|
||||
@ -2301,22 +2309,22 @@ export const PGFbattleSpecDialogue: SimpleTranslationEntries = PGMbattleSpecDial
|
||||
// Dialogue that does not fit into any other category (e.g. tutorial messages, or the end of the game). For when the player character is male
|
||||
export const PGMmiscDialogue: SimpleTranslationEntries = {
|
||||
"ending":
|
||||
`@c{smile}Oh? You won?@d{96} @c{smile_eclosed}I guess I should've known.\nBut, you're back now.
|
||||
$@c{smile}It's over.@d{64} You ended the loop.
|
||||
$@c{serious_smile_fists}You fulfilled your dream too, didn't you?\nYou didn't lose even once.
|
||||
$@c{neutral}I'm the only one who'll remember what you did.@d{96}\nI guess that's okay, isn't it?
|
||||
$@c{serious_smile_fists}Your legend will always live on in our hearts.
|
||||
$@c{smile_eclosed}Anyway, I've had about enough of this place, haven't you? Let's head home.
|
||||
$@c{serious_smile_fists}Maybe when we get back, we can have another battle?\nIf you're up to it.`,
|
||||
`@c{smile}오? 이긴거야?@d{96} @c{smile_eclosed}진즉 알았어야 했는데.\n아무튼, 돌아왔구나.
|
||||
$@c{smile}다 끝난거야.@d{64} 네가 굴레를 끝장냈어.
|
||||
$@c{serious_smile_fists}네 꿈도 이뤄졌고말야.\n진짜로 한 번도 안 졌잖아.
|
||||
$@c{neutral}기억하는 건 우리들 뿐일 모양이지만.@d{96}\n그래도, 괜찮지?
|
||||
$@c{serious_smile_fists}오늘의 일은\n너와 나의 마음 속에 항상 함께할 거야.
|
||||
$@c{smile_eclosed}여기 구경도 충분히 했으니\n이제 집에 가자.
|
||||
$@c{serious_smile_fists}되돌아가서, 다시 배틀을 할 수도 있지 않을까?\n네가 원한다면 말야.`,
|
||||
"ending_female":
|
||||
`@c{shock}You're back?@d{32} Does that mean…@d{96} you won?!\n@c{smile_ehalf}I should have known you had it in you.
|
||||
$@c{smile_eclosed}Of course… I always had that feeling.\n@c{smile}It's over now, right? You ended the loop.
|
||||
$@c{smile_ehalf}You fulfilled your dream too, didn't you?\nYou didn't lose even once.
|
||||
$I'll be the only one to remember what you did.\n@c{angry_mopen}I'll try not to forget!
|
||||
$@c{smile_wave_wink}Just kidding!@d{64} @c{smile}I'd never forget.@d{32}\nYour legend will live on in our hearts.
|
||||
$@c{smile_wave}Anyway,@d{64} it's getting late…@d{96} I think?\nIt's hard to tell in this place.
|
||||
$Let's go home. @c{smile_wave_wink}Maybe tomorrow, we can have another battle, for old time's sake?`,
|
||||
"ending_endless": "Congratulations on reaching the current end!\nMore content is coming soon.",
|
||||
`@c{shock}돌아왔구나?@d{32} 그 말은…@d{96} 이겼어?!\n@c{smile_ehalf}그럴 줄 알았다니까.
|
||||
$@c{smile_eclosed}물론… 언제나 느껴왔지.\n@c{smile}끝난 거, 맞지? 이 굴레를 말이야.
|
||||
$@c{smile_ehalf}네 꿈도 이뤘고 말이야.\n어떻게 한번도 안 졌대?
|
||||
$네가 한 일은 나만 기억하게 될 모양이지만.\n@c{angry_mopen}나, 안 까먹어볼 테니까!
|
||||
$@c{smile_wave_wink}농담이야!@d{64} @c{smile}절대로 안 잊어버릴 거야.@d{32}\n오늘 일은 우리의 마음 속에서 살아갈 야.
|
||||
$@c{smile_wave}어쨌든,@d{64} 시간이 좀 늦었어…@d{96}\n이런 곳에서 할 말은 아닌가?
|
||||
$집에 가자. @c{smile_wave_wink}아마 내일은,\n추억을 되짚어보기 위한 배틀을 해볼 수 있을 거야.`,
|
||||
"ending_endless": "끝에 도달하신 것을 축하드립니다!\n더 많은 컨텐츠를 기다려주세요.",
|
||||
"ending_name": "Devs"
|
||||
};
|
||||
// Dialogue that does not fit into any other category (e.g. tutorial messages, or the end of the game). For when the player character is female. For languages that do not have gendered pronouns, this can be set to PGMmiscDialogue.
|
||||
|
@ -11,6 +11,7 @@ export const menu: SimpleTranslationEntries = {
|
||||
"dailyRun": "데일리 런 (베타)",
|
||||
"loadGame": "불러오기",
|
||||
"newGame": "새 게임",
|
||||
"settings": "설정",
|
||||
"selectGameMode": "게임 모드를 선택해주세요.",
|
||||
"logInOrCreateAccount": "로그인 또는 등록을 해 주세요. 개인정보를 요구하지 않습니다!",
|
||||
"username": "이름",
|
||||
|
@ -48,6 +48,7 @@ export const trainerClasses: SimpleTranslationEntries = {
|
||||
"depot_agent": "역무원",
|
||||
"doctor": "의사",
|
||||
"doctor_female": "간호사", // doctor_f.png 파일이 간호사
|
||||
"firebreather": "Firebreather",
|
||||
"fisherman": "낚시꾼",
|
||||
"fisherman_female": "낚시꾼",
|
||||
"gentleman": "신사",
|
||||
|
@ -12,7 +12,7 @@ export const tutorial: SimpleTranslationEntries = {
|
||||
$설정에서 게임 속도, 윈도우 스타일 및 기타 옵션을 변경할 수 있습니다.
|
||||
$여기에는 다양한 다른 기능도 있으니 꼭 확인해보세요!`,
|
||||
|
||||
starterSelect: `이 화면에서 스타팅을 선택할 수 있습니다.\n이들은 당신의 첫 번째 파티 멤버들입니다.
|
||||
starterSelect: `이 화면에서 Z나 스페이스바로 스타팅을 선택할 수 있습니다.\n이들은 당신의 첫 번째 파티 멤버들입니다.
|
||||
$최대 6마리의 파티로 시작할 수 있지만\n포켓몬에 따라 코스트가 있어 총합 10을 넘겨선 안 됩니다.
|
||||
$계속 잡거나 부화시켜서\n선택할 수 있는 성별, 특성, 폼 등의 폭을 넓힐 수 있습니다.
|
||||
$개체값도 점점 누적되어 높아지므로,\n같은 포켓몬을 많이 잡아보세요!`,
|
||||
@ -22,7 +22,8 @@ export const tutorial: SimpleTranslationEntries = {
|
||||
|
||||
statChange: `포켓몬은 교체하지 않으면 다음 전투에서도 능력치 변화가 유지됩니다.
|
||||
$대신 트레이너 배틀이나 새로운 바이옴 입장 직전에 자동으로 들여보내지게 됩니다.
|
||||
$C 또는 Shift를 꾹 눌러 현재 포켓몬의 능력치 변화를 볼 수도 있습니다.`,
|
||||
$C 또는 Shift를 꾹 눌러 현재 포켓몬의 능력치 변화를 볼 수도 있습니다.
|
||||
$V를 눌러 상대방이 사용했던 기술도 확인하여 전투를 유리하게 이끌어봅시다.`,
|
||||
|
||||
selectItem: `전투가 끝날때마다 무작위 아이템 3개 중 하나를 선택하여 얻습니다.
|
||||
$종류는 소모품, 포켓몬의 지닌 도구, 영구적 패시브 아이템에 이르기까지 다양합니다.
|
||||
|
@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{abilityName}} de {{pokemonName}}\nprotegeu-o do dano de recuo!",
|
||||
"badDreams": "{{pokemonName}} está tendo pesadelos!",
|
||||
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!"
|
||||
} as const;
|
||||
|
@ -359,6 +359,18 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
1: "I'll tune up for the next race."
|
||||
},
|
||||
},
|
||||
"firebreather": {
|
||||
"encounter": {
|
||||
1: "My flames shall devour you!",
|
||||
2: "My soul is on fire. I'll show you how hot it burns!",
|
||||
3: "Step right up and take a look!"
|
||||
},
|
||||
"victory": {
|
||||
1: "I burned down to ashes...",
|
||||
2: "Yow! That's hot!",
|
||||
3: "Ow! I scorched the tip of my nose!"
|
||||
},
|
||||
},
|
||||
"brock": {
|
||||
"encounter": {
|
||||
1: "My expertise on Rock-type Pokémon will take you down! Come on!",
|
||||
@ -1203,8 +1215,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"bugsy": {
|
||||
"encounter": {
|
||||
1: `Whoa, amazing! You're an expert on Pokémon!
|
||||
$My research isn't complete yet. OK, you win.`,
|
||||
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."
|
||||
|
@ -48,6 +48,7 @@ export const trainerClasses: SimpleTranslationEntries = {
|
||||
"depot_agent": "Ferroviário",
|
||||
"doctor": "Doutor",
|
||||
"doctor_female": "Doutora",
|
||||
"firebreather": "Firebreather",
|
||||
"fishermen": "Pescador",
|
||||
"fishermen_female": "Pescadora",
|
||||
"gentleman": "Cavalheiro",
|
||||
|
@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力!",
|
||||
"badDreams": "{{pokemonName}} 被折磨着!"
|
||||
"badDreams": "{{pokemonName}} 被折磨着!",
|
||||
"windPowerCharged": "受 {{moveName}} 的影响, {{pokemonName}} 提升了能力!"
|
||||
} as const;
|
||||
|
@ -359,6 +359,18 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
1: "I'll tune up for the next race."
|
||||
},
|
||||
},
|
||||
"firebreather": {
|
||||
"encounter": {
|
||||
1: "My flames shall devour you!",
|
||||
2: "My soul is on fire. I'll show you how hot it burns!",
|
||||
3: "Step right up and take a look!"
|
||||
},
|
||||
"victory": {
|
||||
1: "I burned down to ashes...",
|
||||
2: "Yow! That's hot!",
|
||||
3: "Ow! I scorched the tip of my nose!"
|
||||
},
|
||||
},
|
||||
"brock": {
|
||||
"encounter": {
|
||||
1: "My expertise on Rock-type Pokémon will take you down! Come on!",
|
||||
@ -1203,8 +1215,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"bugsy": {
|
||||
"encounter": {
|
||||
1: `Whoa, amazing! You're an expert on Pokémon!
|
||||
$My research isn't complete yet. OK, you win.`,
|
||||
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."
|
||||
|
@ -48,6 +48,7 @@ export const trainerClasses: SimpleTranslationEntries = {
|
||||
"depot_agent": "铁路员工",
|
||||
"doctor": "医生",
|
||||
"doctor_female": "医生",
|
||||
"firebreather": "Firebreather",
|
||||
"fisherman": "垂钓者",
|
||||
"fisherman_female": "垂钓者",
|
||||
"gentleman": "绅士",
|
||||
|
@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力!",
|
||||
"badDreams": "{{pokemonName}} 被折磨着!",
|
||||
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!"
|
||||
} as const;
|
||||
|
@ -359,6 +359,18 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
1: "I'll tune up for the next race."
|
||||
},
|
||||
},
|
||||
"firebreather": {
|
||||
"encounter": {
|
||||
1: "My flames shall devour you!",
|
||||
2: "My soul is on fire. I'll show you how hot it burns!",
|
||||
3: "Step right up and take a look!"
|
||||
},
|
||||
"victory": {
|
||||
1: "I burned down to ashes...",
|
||||
2: "Yow! That's hot!",
|
||||
3: "Ow! I scorched the tip of my nose!"
|
||||
},
|
||||
},
|
||||
"brock": {
|
||||
"encounter": {
|
||||
1: "My expertise on Rock-type Pokémon will take you down! Come on!",
|
||||
@ -1203,8 +1215,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
},
|
||||
"bugsy": {
|
||||
"encounter": {
|
||||
1: `Whoa, amazing! You're an expert on Pokémon!
|
||||
$My research isn't complete yet. OK, you win.`,
|
||||
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."
|
||||
|
@ -48,6 +48,7 @@ export const trainerClasses: SimpleTranslationEntries = {
|
||||
"depot_agent": "鐵路員工",
|
||||
"doctor": "醫生",
|
||||
"doctor_female": "醫生",
|
||||
"firebreather": "Firebreather",
|
||||
"fisherman": "垂釣者",
|
||||
"fisherman_female": "垂釣者",
|
||||
"gentleman": "紳士",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import * as Modifiers from "./modifier";
|
||||
import { AttackMove, allMoves } from "../data/move";
|
||||
import { Moves } from "../data/enums/moves";
|
||||
import { Abilities } from "../data/enums/abilities";
|
||||
import { PokeballType, getPokeballCatchMultiplier, getPokeballName } from "../data/pokeball";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "../field/pokemon";
|
||||
import { EvolutionItem, pokemonEvolutions } from "../data/pokemon-evolutions";
|
||||
@ -756,14 +757,23 @@ export class EvolutionItemModifierType extends PokemonModifierType implements Ge
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that represents form changing items
|
||||
*/
|
||||
export class FormChangeItemModifierType extends PokemonModifierType implements GeneratedPersistentModifierType {
|
||||
public formChangeItem: FormChangeItem;
|
||||
|
||||
constructor(formChangeItem: FormChangeItem) {
|
||||
super("", FormChangeItem[formChangeItem].toLowerCase(), (_type, args) => new Modifiers.PokemonFormChangeItemModifier(this, (args[0] as PlayerPokemon).id, formChangeItem, true),
|
||||
(pokemon: PlayerPokemon) => {
|
||||
if (pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId) && !!pokemonFormChanges[pokemon.species.speciesId].find(fc => fc.trigger.hasTriggerType(SpeciesFormChangeItemTrigger)
|
||||
&& (fc.trigger as SpeciesFormChangeItemTrigger).item === this.formChangeItem)) {
|
||||
// Make sure the Pokemon has alternate forms
|
||||
if (pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId)
|
||||
// Get all form changes for this species with an item trigger, including any compound triggers
|
||||
&& pokemonFormChanges[pokemon.species.speciesId].filter(fc => fc.trigger.hasTriggerType(SpeciesFormChangeItemTrigger))
|
||||
// Returns true if any form changes match this item
|
||||
.map(fc => fc.findTrigger(SpeciesFormChangeItemTrigger) as SpeciesFormChangeItemTrigger)
|
||||
.flat().flatMap(fc => fc.item).includes(this.formChangeItem)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -1182,6 +1192,9 @@ export const modifierTypes = {
|
||||
LEFTOVERS: () => new PokemonHeldItemModifierType("modifierType:ModifierType.LEFTOVERS", "leftovers", (type, args) => new Modifiers.TurnHealModifier(type, (args[0] as Pokemon).id)),
|
||||
SHELL_BELL: () => new PokemonHeldItemModifierType("modifierType:ModifierType.SHELL_BELL", "shell_bell", (type, args) => new Modifiers.HitHealModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
TOXIC_ORB: () => new PokemonHeldItemModifierType("modifierType:ModifierType.TOXIC_ORB", "toxic_orb", (type, args) => new Modifiers.TurnStatusEffectModifier(type, (args[0] as Pokemon).id)),
|
||||
FLAME_ORB: () => new PokemonHeldItemModifierType("modifierType:ModifierType.FLAME_ORB", "flame_orb", (type, args) => new Modifiers.TurnStatusEffectModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
BATON: () => new PokemonHeldItemModifierType("modifierType:ModifierType.BATON", "stick", (type, args) => new Modifiers.SwitchEffectTransferModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
SHINY_CHARM: () => new ModifierType("modifierType:ModifierType.SHINY_CHARM", "shiny_charm", (type, _args) => new Modifiers.ShinyRateBoosterModifier(type)),
|
||||
@ -1247,7 +1260,12 @@ const modifierPool: ModifierPool = {
|
||||
[ModifierTier.GREAT]: [
|
||||
new WeightedModifierType(modifierTypes.GREAT_BALL, 6),
|
||||
new WeightedModifierType(modifierTypes.FULL_HEAL, (party: Pokemon[]) => {
|
||||
const statusEffectPartyMemberCount = Math.min(party.filter(p => p.hp && !!p.status).length, 3);
|
||||
const statusEffectPartyMemberCount = Math.min(party.filter(p => p.hp && !!p.status && !p.getHeldItems().some(i => {
|
||||
if (i instanceof Modifiers.TurnStatusEffectModifier) {
|
||||
return (i as Modifiers.TurnStatusEffectModifier).getStatusEffect() === p.status.effect;
|
||||
}
|
||||
return false;
|
||||
})).length, 3);
|
||||
return statusEffectPartyMemberCount * 6;
|
||||
}, 18),
|
||||
new WeightedModifierType(modifierTypes.REVIVE, (party: Pokemon[]) => {
|
||||
@ -1270,7 +1288,12 @@ const modifierPool: ModifierPool = {
|
||||
return thresholdPartyMemberCount;
|
||||
}, 3),
|
||||
new WeightedModifierType(modifierTypes.FULL_RESTORE, (party: Pokemon[]) => {
|
||||
const statusEffectPartyMemberCount = Math.min(party.filter(p => p.hp && !!p.status).length, 3);
|
||||
const statusEffectPartyMemberCount = Math.min(party.filter(p => p.hp && !!p.status && !p.getHeldItems().some(i => {
|
||||
if (i instanceof Modifiers.TurnStatusEffectModifier) {
|
||||
return (i as Modifiers.TurnStatusEffectModifier).getStatusEffect() === p.status.effect;
|
||||
}
|
||||
return false;
|
||||
})).length, 3);
|
||||
const thresholdPartyMemberCount = Math.floor((Math.min(party.filter(p => (p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5) && !p.isFainted()).length, 3) + statusEffectPartyMemberCount) / 2);
|
||||
return thresholdPartyMemberCount;
|
||||
}, 3),
|
||||
@ -1312,6 +1335,40 @@ const modifierPool: ModifierPool = {
|
||||
new WeightedModifierType(modifierTypes.MINT, 4),
|
||||
new WeightedModifierType(modifierTypes.RARE_EVOLUTION_ITEM, (party: Pokemon[]) => Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 15) * 4, 32), 32),
|
||||
new WeightedModifierType(modifierTypes.AMULET_COIN, 3),
|
||||
new WeightedModifierType(modifierTypes.TOXIC_ORB, (party: Pokemon[]) => {
|
||||
let weight = 0;
|
||||
const filteredParty = party.filter(p => (p.status?.effect === StatusEffect.TOXIC || p.canSetStatus(StatusEffect.TOXIC, true, true))
|
||||
&& !p.hasAbility(Abilities.FLARE_BOOST)
|
||||
&& !p.getHeldItems().some(i => i instanceof Modifiers.TurnStatusEffectModifier));
|
||||
if (filteredParty.some(p => p.hasAbility(Abilities.TOXIC_BOOST) || p.hasAbility(Abilities.POISON_HEAL))) {
|
||||
weight = 4;
|
||||
} else if (filteredParty.some(p => p.hasAbility(Abilities.GUTS) || p.hasAbility(Abilities.QUICK_FEET) || p.hasAbility(Abilities.MARVEL_SCALE))) {
|
||||
weight = 2;
|
||||
} else {
|
||||
const moveList = [Moves.FACADE, Moves.TRICK, Moves.FLING, Moves.SWITCHEROO, Moves.PSYCHO_SHIFT];
|
||||
if (filteredParty.some(p => p.getMoveset().some(m => moveList.includes(m.moveId)))) {
|
||||
weight = 1;
|
||||
}
|
||||
}
|
||||
return Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 15) * weight, 8 * weight);
|
||||
}, 32),
|
||||
new WeightedModifierType(modifierTypes.FLAME_ORB, (party: Pokemon[]) => {
|
||||
let weight = 0;
|
||||
const filteredParty = party.filter(p => (p.status?.effect === StatusEffect.BURN || p.canSetStatus(StatusEffect.BURN, true, true))
|
||||
&& !p.hasAbility(Abilities.TOXIC_BOOST) && !p.hasAbility(Abilities.POISON_HEAL)
|
||||
&& !p.getHeldItems().some(i => i instanceof Modifiers.TurnStatusEffectModifier));
|
||||
if (filteredParty.some(p => p.hasAbility(Abilities.FLARE_BOOST))) {
|
||||
weight = 4;
|
||||
} else if (filteredParty.some(p => p.hasAbility(Abilities.GUTS) || p.hasAbility(Abilities.QUICK_FEET) || p.hasAbility(Abilities.MARVEL_SCALE))) {
|
||||
weight = 2;
|
||||
} else {
|
||||
const moveList = [Moves.FACADE, Moves.TRICK, Moves.FLING, Moves.SWITCHEROO, Moves.PSYCHO_SHIFT];
|
||||
if (filteredParty.some(p => p.getMoveset().some(m => moveList.includes(m.moveId)))) {
|
||||
weight = 1;
|
||||
}
|
||||
}
|
||||
return Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 15) * weight, 8 * weight);
|
||||
}, 32),
|
||||
new WeightedModifierType(modifierTypes.REVIVER_SEED, 4),
|
||||
new WeightedModifierType(modifierTypes.CANDY_JAR, 5),
|
||||
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10),
|
||||
|
@ -851,6 +851,66 @@ export class TurnHealModifier extends PokemonHeldItemModifier {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifier used for held items, namely Toxic Orb and Flame Orb, that apply a
|
||||
* set {@linkcode StatusEffect} at the end of a turn.
|
||||
* @extends PokemonHeldItemModifier
|
||||
* @see {@linkcode apply}
|
||||
*/
|
||||
export class TurnStatusEffectModifier extends PokemonHeldItemModifier {
|
||||
/** The status effect to be applied by the held item */
|
||||
private effect: StatusEffect;
|
||||
|
||||
constructor (type: ModifierType, pokemonId: integer, stackCount?: integer) {
|
||||
super(type, pokemonId, stackCount);
|
||||
|
||||
switch (type.id) {
|
||||
case "TOXIC_ORB":
|
||||
this.effect = StatusEffect.TOXIC;
|
||||
break;
|
||||
case "FLAME_ORB":
|
||||
this.effect = StatusEffect.BURN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if {@linkcode modifier} is an instance of this class,
|
||||
* intentionally ignoring potentially different {@linkcode effect}s
|
||||
* to prevent held item stockpiling since the item obtained first
|
||||
* would be the only item able to {@linkcode apply} successfully.
|
||||
* @override
|
||||
* @param modifier {@linkcode Modifier} being type tested
|
||||
* @return true if {@linkcode modifier} is an instance of
|
||||
* TurnStatusEffectModifier, false otherwise
|
||||
*/
|
||||
matchType(modifier: Modifier): boolean {
|
||||
return modifier instanceof TurnStatusEffectModifier;
|
||||
}
|
||||
|
||||
clone() {
|
||||
return new TurnStatusEffectModifier(this.type, this.pokemonId, this.stackCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to inflicts the holder with the associated {@linkcode StatusEffect}.
|
||||
* @param args [0] {@linkcode Pokemon} that holds the held item
|
||||
* @returns true if the status effect was applied successfully, false if
|
||||
* otherwise
|
||||
*/
|
||||
apply(args: any[]): boolean {
|
||||
return (args[0] as Pokemon).trySetStatus(this.effect, true, undefined, undefined, this.type.name);
|
||||
}
|
||||
|
||||
getMaxHeldItemCount(pokemon: Pokemon): integer {
|
||||
return 1;
|
||||
}
|
||||
|
||||
getStatusEffect(): StatusEffect {
|
||||
return this.effect;
|
||||
}
|
||||
}
|
||||
|
||||
export class HitHealModifier extends PokemonHeldItemModifier {
|
||||
constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) {
|
||||
super(type, pokemonId, stackCount);
|
||||
@ -1868,7 +1928,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier {
|
||||
}
|
||||
const randItemIndex = pokemon.randSeedInt(itemModifiers.length);
|
||||
const randItem = itemModifiers[randItemIndex];
|
||||
heldItemTransferPromises.push(pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, false, false).then(success => {
|
||||
heldItemTransferPromises.push(pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, false).then(success => {
|
||||
if (success) {
|
||||
transferredModifierTypes.push(randItem.type);
|
||||
itemModifiers.splice(randItemIndex, 1);
|
||||
|
@ -14,6 +14,7 @@ import { PokeballType } from "./data/pokeball";
|
||||
import {TimeOfDay} from "#app/data/enums/time-of-day";
|
||||
import { Gender } from "./data/gender";
|
||||
import { StatusEffect } from "./data/status-effect";
|
||||
import { modifierTypes } from "./modifier/modifier-type";
|
||||
|
||||
/**
|
||||
* Overrides for testing different in game situations
|
||||
@ -100,7 +101,7 @@ export const OPP_VARIANT_OVERRIDE: Variant = 0;
|
||||
* - BerryType is for BERRY
|
||||
*/
|
||||
interface ModifierOverride {
|
||||
name: string,
|
||||
name: keyof typeof modifierTypes & string,
|
||||
count?: integer
|
||||
type?: TempBattleStat|Stat|Nature|Type|BerryType
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMov
|
||||
import { Mode } from "./ui/ui";
|
||||
import { Command } from "./ui/command-ui-handler";
|
||||
import { Stat } from "./data/pokemon-stat";
|
||||
import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier, overrideModifiers, overrideHeldItems, BypassSpeedChanceModifier } from "./modifier/modifier";
|
||||
import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier, overrideModifiers, overrideHeldItems, BypassSpeedChanceModifier, TurnStatusEffectModifier } from "./modifier/modifier";
|
||||
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
|
||||
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball";
|
||||
import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims";
|
||||
@ -1513,7 +1513,7 @@ export class SwitchSummonPhase extends SummonPhase {
|
||||
const batonPassModifier = this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier
|
||||
&& (m as SwitchEffectTransferModifier).pokemonId === this.lastPokemon.id) as SwitchEffectTransferModifier;
|
||||
if (batonPassModifier && !this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === switchedPokemon.id)) {
|
||||
this.scene.tryTransferHeldItemModifier(batonPassModifier, switchedPokemon, false, false);
|
||||
this.scene.tryTransferHeldItemModifier(batonPassModifier, switchedPokemon, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1548,11 +1548,16 @@ export class SwitchSummonPhase extends SummonPhase {
|
||||
super.onEnd();
|
||||
|
||||
const pokemon = this.getPokemon();
|
||||
const moveId = pokemon.scene.currentBattle.turnCommands[this.fieldIndex]?.move?.move;
|
||||
|
||||
const moveId = this.lastPokemon?.scene.currentBattle.lastMove;
|
||||
const lastUsedMove = moveId ? allMoves[moveId] : undefined;
|
||||
|
||||
const currentCommand = pokemon.scene.currentBattle.turnCommands[this.fieldIndex]?.command;
|
||||
const lastPokemonIsForceSwitchedAndNotFainted = !!lastUsedMove?.findAttr(attr => attr instanceof ForceSwitchOutAttr) && !this.lastPokemon.isFainted();
|
||||
|
||||
// Compensate for turn spent summoning
|
||||
if (pokemon.scene.currentBattle.turnCommands[this.fieldIndex]?.command === Command.POKEMON || !!lastUsedMove?.findAttr(attr => attr instanceof ForceSwitchOutAttr)) { //check if hard switch OR pivot move was used
|
||||
// Or compensate for force switch move if switched out pokemon is not fainted
|
||||
if (currentCommand === Command.POKEMON || lastPokemonIsForceSwitchedAndNotFainted) {
|
||||
pokemon.battleSummonData.turnCount--;
|
||||
}
|
||||
|
||||
@ -2284,6 +2289,8 @@ export class TurnEndPhase extends FieldPhase {
|
||||
|
||||
applyPostTurnAbAttrs(PostTurnAbAttr, pokemon);
|
||||
|
||||
this.scene.applyModifiers(TurnStatusEffectModifier, pokemon.isPlayer(), pokemon);
|
||||
|
||||
this.scene.applyModifiers(TurnHeldItemTransferModifier, pokemon.isPlayer(), pokemon);
|
||||
|
||||
pokemon.battleSummonData.turnCount++;
|
||||
@ -4895,14 +4902,12 @@ export class SelectModifierPhase extends BattlePhase {
|
||||
this.scene.playSound("buy");
|
||||
}
|
||||
} else if (cursor === 1) {
|
||||
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, toSlotIndex: integer) => {
|
||||
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer) => {
|
||||
if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) {
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers)).then(() => {
|
||||
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[];
|
||||
const itemModifier = itemModifiers[itemIndex];
|
||||
this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, true);
|
||||
});
|
||||
this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity);
|
||||
} else {
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers));
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import { allMoves } from "../data/move";
|
||||
import { TrainerVariant } from "../field/trainer";
|
||||
import { OutdatedPhase, ReloadSessionPhase } from "#app/phases";
|
||||
import { Variant, variantData } from "#app/data/variant";
|
||||
import { TerrainChangedEvent, WeatherChangedEvent } from "#app/field/arena-events.js";
|
||||
|
||||
const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet necessary
|
||||
|
||||
@ -740,6 +741,10 @@ export class GameData {
|
||||
});
|
||||
|
||||
scene.arena.weather = sessionData.arena.weather;
|
||||
scene.arena.eventTarget.dispatchEvent(new WeatherChangedEvent(null, scene.arena.weather?.weatherType, scene.arena.weather?.turnsLeft));
|
||||
|
||||
scene.arena.terrain = sessionData.arena.terrain;
|
||||
scene.arena.eventTarget.dispatchEvent(new TerrainChangedEvent(null, scene.arena.terrain?.terrainType, scene.arena.terrain?.turnsLeft));
|
||||
// TODO
|
||||
//scene.arena.tags = sessionData.arena.tags;
|
||||
|
||||
|
@ -57,7 +57,7 @@ export enum PartyOption {
|
||||
}
|
||||
|
||||
export type PartySelectCallback = (cursor: integer, option: PartyOption) => void;
|
||||
export type PartyModifierTransferSelectCallback = (fromCursor: integer, index: integer, toCursor?: integer) => void;
|
||||
export type PartyModifierTransferSelectCallback = (fromCursor: integer, index: integer, itemQuantity?: integer, toCursor?: integer) => void;
|
||||
export type PartyModifierSpliceSelectCallback = (fromCursor: integer, toCursor?: integer) => void;
|
||||
export type PokemonSelectFilter = (pokemon: PlayerPokemon) => string;
|
||||
export type PokemonModifierTransferSelectFilter = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => string;
|
||||
@ -87,6 +87,10 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
private transferMode: boolean;
|
||||
private transferOptionCursor: integer;
|
||||
private transferCursor: integer;
|
||||
/** Current quantity selection for every item held by the pokemon selected for the transfer */
|
||||
private transferQuantities: integer[];
|
||||
/** Stack size of every item that the selected pokemon is holding */
|
||||
private transferQuantitiesMax: integer[];
|
||||
|
||||
private lastCursor: integer = 0;
|
||||
private selectCallback: PartySelectCallback | PartyModifierTransferSelectCallback;
|
||||
@ -231,8 +235,8 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
let success = false;
|
||||
|
||||
if (this.optionsMode) {
|
||||
if (button === Button.ACTION) {
|
||||
const option = this.options[this.optionsCursor];
|
||||
if (button === Button.ACTION) {
|
||||
const pokemon = this.scene.getParty()[this.cursor];
|
||||
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER && !this.transferMode && option !== PartyOption.CANCEL) {
|
||||
this.startTransfer();
|
||||
@ -270,7 +274,9 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
}
|
||||
if (this.selectCallback) {
|
||||
if (option === PartyOption.TRANSFER) {
|
||||
(this.selectCallback as PartyModifierTransferSelectCallback)(this.transferCursor, this.transferOptionCursor, this.cursor);
|
||||
if (this.transferCursor !== this.cursor) {
|
||||
(this.selectCallback as PartyModifierTransferSelectCallback)(this.transferCursor, this.transferOptionCursor, this.transferQuantities[this.transferOptionCursor], this.cursor);
|
||||
}
|
||||
this.clearTransfer();
|
||||
} else if (this.partyUiMode === PartyUiMode.SPLICE) {
|
||||
if (option === PartyOption.SPLICE) {
|
||||
@ -369,17 +375,50 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
return true;
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.LEFT:
|
||||
/** Decrease quantity for the current item and update UI */
|
||||
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
|
||||
this.transferQuantities[option] = this.transferQuantities[option] === 1 ? this.transferQuantitiesMax[option] : this.transferQuantities[option] - 1;
|
||||
this.updateOptions();
|
||||
success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */
|
||||
}
|
||||
break;
|
||||
case Button.RIGHT:
|
||||
/** Increase quantity for the current item and update UI */
|
||||
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
|
||||
this.transferQuantities[option] = this.transferQuantities[option] === this.transferQuantitiesMax[option] ? 1 : this.transferQuantities[option] + 1;
|
||||
this.updateOptions();
|
||||
success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */
|
||||
}
|
||||
break;
|
||||
case Button.UP:
|
||||
success = this.setCursor(this.optionsCursor ? this.optionsCursor - 1 : this.options.length - 1);
|
||||
/** If currently selecting items to transfer, reset quantity selection */
|
||||
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
|
||||
this.transferQuantities[option] = this.transferQuantitiesMax[option];
|
||||
this.updateOptions();
|
||||
}
|
||||
success = this.setCursor(this.optionsCursor ? this.optionsCursor - 1 : this.options.length - 1); /** Move cursor */
|
||||
break;
|
||||
case Button.DOWN:
|
||||
success = this.setCursor(this.optionsCursor < this.options.length - 1 ? this.optionsCursor + 1 : 0);
|
||||
/** If currently selecting items to transfer, reset quantity selection */
|
||||
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
|
||||
this.transferQuantities[option] = this.transferQuantitiesMax[option];
|
||||
this.updateOptions();
|
||||
}
|
||||
success = this.setCursor(this.optionsCursor < this.options.length - 1 ? this.optionsCursor + 1 : 0); /** Move cursor */
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (button === Button.ACTION) {
|
||||
if (this.cursor < 6) {
|
||||
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER && !this.transferMode) {
|
||||
/** Initialize item quantities for the selected Pokemon */
|
||||
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === this.scene.getParty()[this.cursor].id) as PokemonHeldItemModifier[];
|
||||
this.transferQuantities = itemModifiers.map(item => item.getStackCount());
|
||||
this.transferQuantitiesMax = itemModifiers.map(item => item.getStackCount());
|
||||
}
|
||||
this.showOptions();
|
||||
ui.playSelect();
|
||||
} else if (this.partyUiMode === PartyUiMode.FAINT_SWITCH || this.partyUiMode === PartyUiMode.REVIVAL_BLESSING) {
|
||||
@ -555,7 +594,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
break;
|
||||
case PartyUiMode.MODIFIER_TRANSFER:
|
||||
if (!this.transferMode) {
|
||||
optionsMessage = "Select a held item to transfer.";
|
||||
optionsMessage = "Select a held item to transfer.\nUse < and > to change the quantity.";
|
||||
}
|
||||
break;
|
||||
case PartyUiMode.SPLICE:
|
||||
@ -569,7 +608,12 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
|
||||
this.updateOptions();
|
||||
|
||||
/** When an item is being selected for transfer, the message box is taller as the message occupies two lines */
|
||||
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
|
||||
this.partyMessageBox.setSize(262 - Math.max(this.optionsBg.displayWidth - 56, 0), 42);
|
||||
} else {
|
||||
this.partyMessageBox.setSize(262 - Math.max(this.optionsBg.displayWidth - 56, 0), 30);
|
||||
}
|
||||
|
||||
this.setCursor(0);
|
||||
}
|
||||
@ -741,8 +785,9 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
} else {
|
||||
const itemModifier = itemModifiers[option];
|
||||
optionName = itemModifier.type.name;
|
||||
if (itemModifier.stackCount > 1) {
|
||||
optionName += ` (${itemModifier.stackCount})`;
|
||||
/** For every item that has stack bigger than 1, display the current quantity selection */
|
||||
if (this.transferQuantitiesMax[option] > 1) {
|
||||
optionName += ` (${this.transferQuantities[option]})`;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1339,11 +1339,27 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
case Button.UP:
|
||||
if (row) {
|
||||
success = this.setCursor(this.cursor - 9);
|
||||
} else {
|
||||
// when strictly opposite starter based on rows length
|
||||
// does not exits, set cursor on the second to last row
|
||||
if (this.cursor + (rows - 1) * 9 > genStarters - 1) {
|
||||
success = this.setCursor(this.cursor + (rows - 2) * 9);
|
||||
} else {
|
||||
success = this.setCursor(this.cursor + (rows - 1) * 9);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (row < rows - 2 || (row < rows - 1 && this.cursor % 9 <= (genStarters - 1) % 9)) {
|
||||
success = this.setCursor(this.cursor + 9);
|
||||
} else {
|
||||
// if there is no starter below while being on the second to
|
||||
// last row, adjust cursor position with one line less
|
||||
if (row === rows - 2 && this.cursor + 9 > genStarters - 1) {
|
||||
success = this.setCursor(this.cursor - (rows - 2) * 9);
|
||||
} else {
|
||||
success = this.setCursor(this.cursor - (rows - 1) * 9);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Button.LEFT:
|
||||
|
@ -68,7 +68,14 @@ export class StatsContainer extends Phaser.GameObjects.Container {
|
||||
this.statsIvsCache = ivChartData.slice(0);
|
||||
|
||||
this.ivStatValueTexts.map((t: BBCodeText, i: integer) => {
|
||||
let label = ivs[i].toString();
|
||||
let label = "";
|
||||
|
||||
// Check to see if IVs are 31, if so change the text style to gold, otherwise leave them be.
|
||||
if (ivs[i] === 31) {
|
||||
label += `[color=${getTextColor(TextStyle.SUMMARY_GOLD, false, (this.scene as BattleScene).uiTheme)}][shadow]${ivs[i].toString()}[/shadow][/color]`;
|
||||
} else {
|
||||
label = ivs[i].toString();
|
||||
}
|
||||
if (this.showDiff && originalIvs) {
|
||||
if (originalIvs[i] < ivs[i]) {
|
||||
label += ` ([color=${getTextColor(TextStyle.SUMMARY_BLUE, false, (this.scene as BattleScene).uiTheme)}][shadow=${getTextColor(TextStyle.SUMMARY_BLUE, true, (this.scene as BattleScene).uiTheme)}]+${ivs[i] - originalIvs[i]}[/shadow][/color])`;
|
||||
|
@ -407,6 +407,7 @@ export function verifyLang(lang?: string): boolean {
|
||||
case "zh_CN":
|
||||
case "zh_TW":
|
||||
case "pt_BR":
|
||||
case "ko":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
11
src/vite.env.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_BYPASS_LOGIN?: string;
|
||||
readonly VITE_BYPASS_TUTORIAL?: string;
|
||||
readonly VITE_API_BASE_URL?: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv
|
||||
}
|
@ -16,5 +16,10 @@
|
||||
},
|
||||
"outDir": "./build",
|
||||
"noEmit": true
|
||||
},
|
||||
"typedocOptions": {
|
||||
"entryPoints": ["src/"],
|
||||
"entryPointStrategy": "expand",
|
||||
"out": "typedoc",
|
||||
}
|
||||
}
|
11
vite.env.d.ts
vendored
@ -1,11 +0,0 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_BYPASS_LOGIN: string;
|
||||
readonly VITE_BYPASS_TUTORIAL: string;
|
||||
readonly VITE_API_BASE_URL: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|