Merge branch 'beta' into hebrew-pr

This commit is contained in:
Lugiad 2025-05-31 01:58:08 +02:00 committed by GitHub
commit 638a318048
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
208 changed files with 5255 additions and 2179 deletions

View File

@ -1,7 +1,8 @@
all: all:
- "src/**" # Negations syntax from https://github.com/dorny/paths-filter/issues/184#issuecomment-2786521554
- "test/**" - "src/**/!(*.{md,py,sh,gitkeep,gitignore})"
- "public/**" - "test/**/!(*.{md,py,sh,gitkeep,gitignore})"
- "public/**/!(*.{md,py,sh,gitkeep,gitignore})"
# Workflows that can impact tests # Workflows that can impact tests
- ".github/workflows/test*.yml" - ".github/workflows/test*.yml"
- ".github/test-filters.yml" - ".github/test-filters.yml"
@ -11,9 +12,4 @@ all:
- "vite*" # vite.config.ts, vite.vitest.config.ts, vitest.workspace.ts - "vite*" # vite.config.ts, vite.vitest.config.ts, vitest.workspace.ts
- "tsconfig*.json" # tsconfig.json tweaking can impact compilation - "tsconfig*.json" # tsconfig.json tweaking can impact compilation
- "global.d.ts" - "global.d.ts"
- ".env*" - ".env*"
# Blanket negations for files that cannot impact tests
- "!**/*.py" # No .py files
- "!**/*.sh" # No .sh files
- "!**/*.md" # No .md files
- "!**/.git*" # .gitkeep and family

View File

@ -19,19 +19,20 @@ on:
jobs: jobs:
test: test:
name: Shard ${{ inputs.shard }} of ${{ inputs.totalShards }} # We can't use dynmically named jobs until https://github.com/orgs/community/discussions/13261 is implemented
name: Shard
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ !inputs.skip }} if: ${{ !inputs.skip }}
steps: steps:
- name: Check out Git repository - name: Check out Git repository
uses: actions/checkout@v4.2.2 uses: actions/checkout@v4.2.2
with: with:
submodules: 'recursive' submodules: "recursive"
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: ".nvmrc"
cache: 'npm' cache: "npm"
- name: Install Node.js dependencies - name: Install Node.js dependencies
run: npm ci run: npm ci
- name: Run tests - name: Run tests

View File

@ -25,6 +25,7 @@ jobs:
- name: checkout - name: checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36
id: filter
with: with:
filters: .github/test-filters.yml filters: .github/test-filters.yml
@ -33,10 +34,10 @@ jobs:
needs: check-path-change-filter needs: check-path-change-filter
strategy: strategy:
matrix: matrix:
shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] shard: [1, 2, 3, 4, 5]
uses: ./.github/workflows/test-shard-template.yml uses: ./.github/workflows/test-shard-template.yml
with: with:
project: main project: main
shard: ${{ matrix.shard }} shard: ${{ matrix.shard }}
totalShards: 10 totalShards: 5
skip: ${{ needs.check-path-change-filter.outputs.all == 'false'}} skip: ${{ needs.check-path-change-filter.outputs.all != 'true'}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -1,34 +1,36 @@
{ {
"1": { "1": {
"319452": "831a1f",
"4a7310": "982443",
"7ba563": "b44040",
"bdef84": "ec8c8c",
"8cbd63": "c54b4b", "8cbd63": "c54b4b",
"215200": "710f2e", "a5d670": "df5252",
"4aa552": "9f2f2c",
"a5d674": "e16363", "a5d674": "e16363",
"196b21": "891222", "7aa953": "c54b4b",
"7ba563": "b44040",
"215200": "710f2e",
"f7ce00": "7aa1df", "f7ce00": "7aa1df",
"525252": "123a5a", "525252": "123a5a",
"63b56b": "b2332f",
"a5d673": "df5252",
"8c6b3a": "448bc3", "8c6b3a": "448bc3",
"4aa552": "9f2f2c" "bdef84": "ec8c8c",
"63b56b": "b2332f",
"319452": "831a1f",
"196b21": "891222",
"4a7310": "982443"
}, },
"2": { "2": {
"319452": "b08d72",
"4a7310": "4f3956",
"7ba563": "704e7e",
"bdef84": "a779ba",
"8cbd63": "e3d7a6", "8cbd63": "e3d7a6",
"215200": "583823", "a5d670": "d7cda7",
"4aa552": "c5a77f",
"a5d674": "8c669b", "a5d674": "8c669b",
"196b21": "78582c", "7aa953": "704e7e",
"7ba563": "704e7e",
"215200": "583823",
"f7ce00": "f2aacd", "f7ce00": "f2aacd",
"525252": "a53b6f", "525252": "a53b6f",
"63b56b": "cfc191",
"a5d673": "d7cda7",
"8c6b3a": "df87bb", "8c6b3a": "df87bb",
"4aa552": "c5a77f" "bdef84": "a779ba",
"63b56b": "cfc191",
"319452": "b08d72",
"196b21": "78582c",
"4a7310": "4f3956"
} }
} }

View File

@ -1,28 +1,28 @@
{ {
"1": { "1": {
"196b21": "831a1f",
"7ba563": "b44040",
"215201": "630d28",
"215200": "710f2f",
"a5d674": "df5252",
"8cbd63": "c54b4b",
"63b56b": "b2332f",
"a5d670": "e16363",
"319452": "831a1f", "319452": "831a1f",
"4aa552": "9f2f2c", "4aa552": "9f2f2c",
"7ba563": "b44040", "4a7310": "982443"
"8cbd63": "c54b4b",
"215200": "710f2f",
"196b21": "831a1f",
"a5d674": "df5252",
"4a7310": "982443",
"a5d673": "e16363",
"63b56b": "b2332f",
"215201": "630d28"
}, },
"2": { "2": {
"196b21": "b08d72",
"7ba563": "704e7e",
"215201": "583823",
"215200": "3f3249",
"a5d674": "d7cda7",
"8cbd63": "e3d7a6",
"63b56b": "cfc191",
"a5d670": "8c669b",
"319452": "b08d72", "319452": "b08d72",
"4aa552": "c5a77f", "4aa552": "c5a77f",
"7ba563": "704e7e", "4a7310": "4f3956"
"8cbd63": "e3d7a6",
"215200": "3f3249",
"196b21": "b08d72",
"a5d674": "d7cda7",
"4a7310": "4f3956",
"a5d673": "8c669b",
"63b56b": "cfc191",
"215201": "583823"
} }
} }

View File

@ -1,28 +1,28 @@
{ {
"1": { "1": {
"196b21": "780d4a",
"7ba563": "b44040",
"215201": "710f2e",
"215200": "710f2f",
"a5d674": "de5b6f",
"8cbd63": "bf3d64",
"63b56b": "9e2056",
"a5d670": "e16363",
"319452": "780d4a", "319452": "780d4a",
"4aa552": "8a1652", "4aa552": "8a1652",
"7ba563": "b44040", "4a7310": "982443"
"8cbd63": "bf3d64",
"215200": "710f2f",
"196b21": "780d4a",
"a5d674": "de5b6f",
"4a7310": "982443",
"a5d673": "e16363",
"63b56b": "9e2056",
"215201": "710f2e"
}, },
"2": { "2": {
"196b21": "b59c72",
"7ba563": "805a9c",
"215201": "694d37",
"215200": "41334d",
"a5d674": "f6f7df",
"8cbd63": "ebe9ca",
"63b56b": "e3ddb8",
"a5d670": "a473ba",
"319452": "b59c72", "319452": "b59c72",
"4aa552": "c9b991", "4aa552": "c9b991",
"7ba563": "805a9c", "4a7310": "4f3956"
"8cbd63": "ebe9ca",
"215200": "41334d",
"196b21": "b59c72",
"a5d674": "f6f7df",
"4a7310": "4f3956",
"a5d673": "a473ba",
"63b56b": "e3ddb8",
"215201": "694d37"
} }
} }

View File

@ -1,34 +1,36 @@
{ {
"1": { "1": {
"319452": "780d4a",
"4a7310": "982443",
"7ba563": "b44040",
"bdef84": "ec8c8c",
"8cbd63": "bf3d64", "8cbd63": "bf3d64",
"215200": "710f2e", "a5d670": "de5b6f",
"4aa552": "8a1652",
"a5d674": "e16363", "a5d674": "e16363",
"196b21": "7d1157", "7aa953": "bf3d64",
"7ba563": "b44040",
"215200": "710f2e",
"f7ce00": "5bcfc3", "f7ce00": "5bcfc3",
"525252": "20668c", "525252": "20668c",
"63b56b": "9e2056",
"a5d673": "de5b6f",
"8c6b3a": "33a3b0", "8c6b3a": "33a3b0",
"4aa552": "8a1652" "bdef84": "ec8c8c",
"63b56b": "9e2056",
"319452": "780d4a",
"196b21": "7d1157",
"4a7310": "982443"
}, },
"2": { "2": {
"319452": "b59c72",
"4a7310": "4f3956",
"7ba563": "805a9c",
"bdef84": "c193cf",
"8cbd63": "f6f7df", "8cbd63": "f6f7df",
"215200": "694d37", "a5d670": "ebe9ca",
"4aa552": "c9b991",
"a5d674": "a473ba", "a5d674": "a473ba",
"196b21": "9c805f", "7aa953": "805a9c",
"7ba563": "805a9c",
"215200": "694d37",
"f7ce00": "f2aab6", "f7ce00": "f2aab6",
"525252": "983364", "525252": "983364",
"63b56b": "e3ddb8",
"a5d673": "ebe9ca",
"8c6b3a": "df879f", "8c6b3a": "df879f",
"4aa552": "c9b991" "bdef84": "c193cf",
"63b56b": "e3ddb8",
"319452": "b59c72",
"196b21": "9c805f",
"4a7310": "4f3956"
} }
} }

View File

@ -1,7 +1,7 @@
{ {
"textures": [ "textures": [
{ {
"image": "statuses_ca_ES.png", "image": "statuses_ca.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": { "size": {
"w": 22, "w": 22,

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,188 @@
{
"textures": [
{
"image": "statuses_da.png",
"format": "RGBA8888",
"size": {
"w": 22,
"h": 64
},
"scale": 1,
"frames": [
{
"filename": "pokerus",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 22,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 22,
"h": 8
},
"frame": {
"x": 0,
"y": 0,
"w": 22,
"h": 8
}
},
{
"filename": "burn",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 8,
"w": 20,
"h": 8
}
},
{
"filename": "faint",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 16,
"w": 20,
"h": 8
}
},
{
"filename": "freeze",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 24,
"w": 20,
"h": 8
}
},
{
"filename": "paralysis",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 32,
"w": 20,
"h": 8
}
},
{
"filename": "poison",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 40,
"w": 20,
"h": 8
}
},
{
"filename": "sleep",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 48,
"w": 20,
"h": 8
}
},
{
"filename": "toxic",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 56,
"w": 20,
"h": 8
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,188 @@
{
"textures": [
{
"image": "statuses_ro.png",
"format": "RGBA8888",
"size": {
"w": 22,
"h": 64
},
"scale": 1,
"frames": [
{
"filename": "pokerus",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 22,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 22,
"h": 8
},
"frame": {
"x": 0,
"y": 0,
"w": 22,
"h": 8
}
},
{
"filename": "burn",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 8,
"w": 20,
"h": 8
}
},
{
"filename": "faint",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 16,
"w": 20,
"h": 8
}
},
{
"filename": "freeze",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 24,
"w": 20,
"h": 8
}
},
{
"filename": "paralysis",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 32,
"w": 20,
"h": 8
}
},
{
"filename": "poison",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 40,
"w": 20,
"h": 8
}
},
{
"filename": "sleep",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 48,
"w": 20,
"h": 8
}
},
{
"filename": "toxic",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 56,
"w": 20,
"h": 8
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,188 @@
{
"textures": [
{
"image": "statuses_ru.png",
"format": "RGBA8888",
"size": {
"w": 22,
"h": 64
},
"scale": 1,
"frames": [
{
"filename": "pokerus",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 22,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 22,
"h": 8
},
"frame": {
"x": 0,
"y": 0,
"w": 22,
"h": 8
}
},
{
"filename": "burn",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 8,
"w": 20,
"h": 8
}
},
{
"filename": "faint",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 16,
"w": 20,
"h": 8
}
},
{
"filename": "freeze",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 24,
"w": 20,
"h": 8
}
},
{
"filename": "paralysis",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 32,
"w": 20,
"h": 8
}
},
{
"filename": "poison",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 40,
"w": 20,
"h": 8
}
},
{
"filename": "sleep",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 48,
"w": 20,
"h": 8
}
},
{
"filename": "toxic",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 56,
"w": 20,
"h": 8
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,188 @@
{
"textures": [
{
"image": "statuses_tr.png",
"format": "RGBA8888",
"size": {
"w": 22,
"h": 64
},
"scale": 1,
"frames": [
{
"filename": "pokerus",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 22,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 22,
"h": 8
},
"frame": {
"x": 0,
"y": 0,
"w": 22,
"h": 8
}
},
{
"filename": "burn",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 8,
"w": 20,
"h": 8
}
},
{
"filename": "faint",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 16,
"w": 20,
"h": 8
}
},
{
"filename": "freeze",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 24,
"w": 20,
"h": 8
}
},
{
"filename": "paralysis",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 32,
"w": 20,
"h": 8
}
},
{
"filename": "poison",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 40,
"w": 20,
"h": 8
}
},
{
"filename": "sleep",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 48,
"w": 20,
"h": 8
}
},
{
"filename": "toxic",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 20,
"h": 8
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 20,
"h": 8
},
"frame": {
"x": 0,
"y": 56,
"w": 20,
"h": 8
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

View File

@ -1,7 +1,7 @@
{ {
"textures": [ "textures": [
{ {
"image": "types_ca-ES.png", "image": "types_ca.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": { "size": {
"w": 32, "w": 32,

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

440
public/images/types_da.json Normal file
View File

@ -0,0 +1,440 @@
{
"textures": [
{
"image": "types_da.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_da.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

440
public/images/types_ro.json Normal file
View File

@ -0,0 +1,440 @@
{
"textures": [
{
"image": "types_ro.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_ro.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

440
public/images/types_ru.json Normal file
View File

@ -0,0 +1,440 @@
{
"textures": [
{
"image": "types_ru.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_ru.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

440
public/images/types_tr.json Normal file
View File

@ -0,0 +1,440 @@
{
"textures": [
{
"image": "types_tr.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_tr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

@ -1 +1 @@
Subproject commit 42cd5cf577f475c22bc82d55e7ca358eb4f3184f Subproject commit 88c60b6f8d5babfb0c157b31ceff22486712295c

View File

@ -7425,7 +7425,12 @@ export function initAbilities() {
.uncopiable() .uncopiable()
.attr(NoTransformAbilityAbAttr), .attr(NoTransformAbilityAbAttr),
new Ability(Abilities.GOOD_AS_GOLD, 9) new Ability(Abilities.GOOD_AS_GOLD, 9)
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.category === MoveCategory.STATUS && ![ MoveTarget.ENEMY_SIDE, MoveTarget.BOTH_SIDES, MoveTarget.USER_SIDE ].includes(move.moveTarget)) .attr(MoveImmunityAbAttr, (pokemon, attacker, move) =>
pokemon !== attacker
&& move.category === MoveCategory.STATUS
&& ![ MoveTarget.ENEMY_SIDE, MoveTarget.BOTH_SIDES, MoveTarget.USER_SIDE ].includes(move.moveTarget)
)
.edgeCase() // Heal Bell should not cure the status of a Pokemon with Good As Gold
.ignorable(), .ignorable(),
new Ability(Abilities.VESSEL_OF_RUIN, 9) new Ability(Abilities.VESSEL_OF_RUIN, 9)
.attr(FieldMultiplyStatAbAttr, Stat.SPATK, 0.75) .attr(FieldMultiplyStatAbAttr, Stat.SPATK, 0.75)

View File

@ -1697,8 +1697,8 @@ export function initSpecies() {
new PokemonSpecies(Species.CHINCHOU, 2, false, false, false, "Angler Pokémon", PokemonType.WATER, PokemonType.ELECTRIC, 0.5, 12, Abilities.VOLT_ABSORB, Abilities.ILLUMINATE, Abilities.WATER_ABSORB, 330, 75, 38, 38, 56, 56, 67, 190, 50, 66, GrowthRate.SLOW, 50, false), new PokemonSpecies(Species.CHINCHOU, 2, false, false, false, "Angler Pokémon", PokemonType.WATER, PokemonType.ELECTRIC, 0.5, 12, Abilities.VOLT_ABSORB, Abilities.ILLUMINATE, Abilities.WATER_ABSORB, 330, 75, 38, 38, 56, 56, 67, 190, 50, 66, GrowthRate.SLOW, 50, false),
new PokemonSpecies(Species.LANTURN, 2, false, false, false, "Light Pokémon", PokemonType.WATER, PokemonType.ELECTRIC, 1.2, 22.5, Abilities.VOLT_ABSORB, Abilities.ILLUMINATE, Abilities.WATER_ABSORB, 460, 125, 58, 58, 76, 76, 67, 75, 50, 161, GrowthRate.SLOW, 50, false), new PokemonSpecies(Species.LANTURN, 2, false, false, false, "Light Pokémon", PokemonType.WATER, PokemonType.ELECTRIC, 1.2, 22.5, Abilities.VOLT_ABSORB, Abilities.ILLUMINATE, Abilities.WATER_ABSORB, 460, 125, 58, 58, 76, 76, 67, 75, 50, 161, GrowthRate.SLOW, 50, false),
new PokemonSpecies(Species.PICHU, 2, false, false, false, "Tiny Mouse Pokémon", PokemonType.ELECTRIC, null, 0.3, 2, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 205, 20, 40, 15, 35, 35, 60, 190, 70, 41, GrowthRate.MEDIUM_FAST, 50, false, false, new PokemonSpecies(Species.PICHU, 2, false, false, false, "Tiny Mouse Pokémon", PokemonType.ELECTRIC, null, 0.3, 2, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 205, 20, 40, 15, 35, 35, 60, 190, 70, 41, GrowthRate.MEDIUM_FAST, 50, false, false,
new PokemonForm("Normal", "", PokemonType.ELECTRIC, null, 1.4, 61.5, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 205, 20, 40, 15, 35, 35, 60, 190, 70, 41, false, null, true), new PokemonForm("Normal", "", PokemonType.ELECTRIC, null, 1.4, 2, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 205, 20, 40, 15, 35, 35, 60, 190, 70, 41, false, null, true),
new PokemonForm("Spiky-Eared", "spiky", PokemonType.ELECTRIC, null, 1.4, 61.5, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 205, 20, 40, 15, 35, 35, 60, 190, 70, 41, false, null, true), new PokemonForm("Spiky-Eared", "spiky", PokemonType.ELECTRIC, null, 1.4, 2, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 205, 20, 40, 15, 35, 35, 60, 190, 70, 41, false, null, true),
), ),
new PokemonSpecies(Species.CLEFFA, 2, false, false, false, "Star Shape Pokémon", PokemonType.FAIRY, null, 0.3, 3, Abilities.CUTE_CHARM, Abilities.MAGIC_GUARD, Abilities.FRIEND_GUARD, 218, 50, 25, 28, 45, 55, 15, 150, 140, 44, GrowthRate.FAST, 25, false), new PokemonSpecies(Species.CLEFFA, 2, false, false, false, "Star Shape Pokémon", PokemonType.FAIRY, null, 0.3, 3, Abilities.CUTE_CHARM, Abilities.MAGIC_GUARD, Abilities.FRIEND_GUARD, 218, 50, 25, 28, 45, 55, 15, 150, 140, 44, GrowthRate.FAST, 25, false),
new PokemonSpecies(Species.IGGLYBUFF, 2, false, false, false, "Balloon Pokémon", PokemonType.NORMAL, PokemonType.FAIRY, 0.3, 1, Abilities.CUTE_CHARM, Abilities.COMPETITIVE, Abilities.FRIEND_GUARD, 210, 90, 30, 15, 40, 20, 15, 170, 50, 42, GrowthRate.FAST, 25, false), new PokemonSpecies(Species.IGGLYBUFF, 2, false, false, false, "Balloon Pokémon", PokemonType.NORMAL, PokemonType.FAIRY, 0.3, 1, Abilities.CUTE_CHARM, Abilities.COMPETITIVE, Abilities.FRIEND_GUARD, 210, 90, 30, 15, 40, 20, 15, 170, 50, 42, GrowthRate.FAST, 25, false),
@ -3121,7 +3121,7 @@ export function initSpecies() {
), ),
new PokemonSpecies(Species.WALKING_WAKE, 9, false, false, false, "Paradox Pokémon", PokemonType.WATER, PokemonType.DRAGON, 3.5, 280, Abilities.PROTOSYNTHESIS, Abilities.NONE, Abilities.NONE, 590, 99, 83, 91, 125, 83, 109, 10, 0, 295, GrowthRate.SLOW, null, false), //Custom Catchrate, matching Gouging Fire and Raging Bolt new PokemonSpecies(Species.WALKING_WAKE, 9, false, false, false, "Paradox Pokémon", PokemonType.WATER, PokemonType.DRAGON, 3.5, 280, Abilities.PROTOSYNTHESIS, Abilities.NONE, Abilities.NONE, 590, 99, 83, 91, 125, 83, 109, 10, 0, 295, GrowthRate.SLOW, null, false), //Custom Catchrate, matching Gouging Fire and Raging Bolt
new PokemonSpecies(Species.IRON_LEAVES, 9, false, false, false, "Paradox Pokémon", PokemonType.GRASS, PokemonType.PSYCHIC, 1.5, 125, Abilities.QUARK_DRIVE, Abilities.NONE, Abilities.NONE, 590, 90, 130, 88, 70, 108, 104, 10, 0, 295, GrowthRate.SLOW, null, false), //Custom Catchrate, matching Iron Boulder and Iron Crown new PokemonSpecies(Species.IRON_LEAVES, 9, false, false, false, "Paradox Pokémon", PokemonType.GRASS, PokemonType.PSYCHIC, 1.5, 125, Abilities.QUARK_DRIVE, Abilities.NONE, Abilities.NONE, 590, 90, 130, 88, 70, 108, 104, 10, 0, 295, GrowthRate.SLOW, null, false), //Custom Catchrate, matching Iron Boulder and Iron Crown
new PokemonSpecies(Species.DIPPLIN, 9, false, false, false, "Candy Apple Pokémon", PokemonType.GRASS, PokemonType.DRAGON, 0.4, 9.7, Abilities.SUPERSWEET_SYRUP, Abilities.GLUTTONY, Abilities.STICKY_HOLD, 485, 80, 80, 110, 95, 80, 40, 45, 50, 170, GrowthRate.ERRATIC, 50, false), new PokemonSpecies(Species.DIPPLIN, 9, false, false, false, "Candy Apple Pokémon", PokemonType.GRASS, PokemonType.DRAGON, 0.4, 4.4, Abilities.SUPERSWEET_SYRUP, Abilities.GLUTTONY, Abilities.STICKY_HOLD, 485, 80, 80, 110, 95, 80, 40, 45, 50, 170, GrowthRate.ERRATIC, 50, false),
new PokemonSpecies(Species.POLTCHAGEIST, 9, false, false, false, "Matcha Pokémon", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, GrowthRate.SLOW, null, false, false, new PokemonSpecies(Species.POLTCHAGEIST, 9, false, false, false, "Matcha Pokémon", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, GrowthRate.SLOW, null, false, false,
new PokemonForm("Counterfeit Form", "counterfeit", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, null, true), new PokemonForm("Counterfeit Form", "counterfeit", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, null, true),
new PokemonForm("Artisan Form", "artisan", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, null, false, true), new PokemonForm("Artisan Form", "artisan", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, null, false, true),

View File

@ -0,0 +1,9 @@
export enum DropDownColumn {
GEN,
TYPES,
BIOME,
CAUGHT,
UNLOCKS,
MISC,
SORT
}

View File

@ -5,7 +5,9 @@ import { globalScene } from "#app/global-scene";
import type { Variant } from "#app/sprites/variant"; import type { Variant } from "#app/sprites/variant";
import { populateVariantColors, variantColorCache } from "#app/sprites/variant"; import { populateVariantColors, variantColorCache } from "#app/sprites/variant";
import { variantData } from "#app/sprites/variant"; import { variantData } from "#app/sprites/variant";
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "#app/ui/battle-info"; import BattleInfo from "#app/ui/battle-info/battle-info";
import { EnemyBattleInfo } from "#app/ui/battle-info/enemy-battle-info";
import { PlayerBattleInfo } from "#app/ui/battle-info/player-battle-info";
import type Move from "#app/data/moves/move"; import type Move from "#app/data/moves/move";
import { import {
HighCritAttr, HighCritAttr,
@ -3347,22 +3349,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return this.battleInfo.updateInfo(this, instant); return this.battleInfo.updateInfo(this, instant);
} }
/**
* Show or hide the type effectiveness multiplier window
* Passing undefined will hide the window
*/
updateEffectiveness(effectiveness?: string) {
this.battleInfo.updateEffectiveness(effectiveness);
}
toggleStats(visible: boolean): void { toggleStats(visible: boolean): void {
this.battleInfo.toggleStats(visible); this.battleInfo.toggleStats(visible);
} }
toggleFlyout(visible: boolean): void {
this.battleInfo.toggleFlyout(visible);
}
/** /**
* Adds experience to this PlayerPokemon, subject to wave based level caps. * Adds experience to this PlayerPokemon, subject to wave based level caps.
* @param exp The amount of experience to add * @param exp The amount of experience to add
@ -5518,6 +5508,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
export class PlayerPokemon extends Pokemon { export class PlayerPokemon extends Pokemon {
protected battleInfo: PlayerBattleInfo;
public compatibleTms: Moves[]; public compatibleTms: Moves[];
constructor( constructor(
@ -6038,6 +6029,7 @@ export class PlayerPokemon extends Pokemon {
} }
export class EnemyPokemon extends Pokemon { export class EnemyPokemon extends Pokemon {
protected battleInfo: EnemyBattleInfo;
public trainerSlot: TrainerSlot; public trainerSlot: TrainerSlot;
public aiType: AiType; public aiType: AiType;
public bossSegments: number; public bossSegments: number;
@ -6709,6 +6701,19 @@ export class EnemyPokemon extends Pokemon {
return ret; return ret;
} }
/**
* Show or hide the type effectiveness multiplier window
* Passing undefined will hide the window
*/
updateEffectiveness(effectiveness?: string) {
this.battleInfo.updateEffectiveness(effectiveness);
}
toggleFlyout(visible: boolean): void {
this.battleInfo.toggleFlyout(visible);
}
} }
/** /**

View File

@ -7,7 +7,7 @@ import type PokemonSpecies from "./data/pokemon-species";
import { allSpecies } from "./data/pokemon-species"; import { allSpecies } from "./data/pokemon-species";
import type { Arena } from "./field/arena"; import type { Arena } from "./field/arena";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import { randSeedInt, randSeedItem } from "#app/utils/common"; import { isNullOrUndefined, randSeedInt, randSeedItem } from "#app/utils/common";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { Challenges } from "./enums/challenges"; import { Challenges } from "./enums/challenges";
@ -124,16 +124,20 @@ export class GameMode implements GameModeConfig {
/** /**
* @returns either: * @returns either:
* - random biome for Daily mode
* - override from overrides.ts * - override from overrides.ts
* - random biome for Daily mode
* - Town * - Town
*/ */
getStartingBiome(): Biome { getStartingBiome(): Biome {
if (!isNullOrUndefined(Overrides.STARTING_BIOME_OVERRIDE)) {
return Overrides.STARTING_BIOME_OVERRIDE;
}
switch (this.modeId) { switch (this.modeId) {
case GameModes.DAILY: case GameModes.DAILY:
return getDailyStartingBiome(); return getDailyStartingBiome();
default: default:
return Overrides.STARTING_BIOME_OVERRIDE || Biome.TOWN; return Biome.TOWN;
} }
} }

View File

@ -29,7 +29,7 @@ window.addEventListener("unhandledrejection", event => {
const setPositionRelative = function (guideObject: Phaser.GameObjects.GameObject, x: number, y: number) { const setPositionRelative = function (guideObject: Phaser.GameObjects.GameObject, x: number, y: number) {
const offsetX = guideObject.width * (-0.5 + (0.5 - guideObject.originX)); const offsetX = guideObject.width * (-0.5 + (0.5 - guideObject.originX));
const offsetY = guideObject.height * (-0.5 + (0.5 - guideObject.originY)); const offsetY = guideObject.height * (-0.5 + (0.5 - guideObject.originY));
this.setPosition(guideObject.x + offsetX + x, guideObject.y + offsetY + y); return this.setPosition(guideObject.x + offsetX + x, guideObject.y + offsetY + y);
}; };
Phaser.GameObjects.Container.prototype.setPositionRelative = setPositionRelative; Phaser.GameObjects.Container.prototype.setPositionRelative = setPositionRelative;

View File

@ -73,7 +73,7 @@ class DefaultOverrides {
*/ */
readonly BATTLE_STYLE_OVERRIDE: BattleStyle | null = null; readonly BATTLE_STYLE_OVERRIDE: BattleStyle | null = null;
readonly STARTING_WAVE_OVERRIDE: number = 0; readonly STARTING_WAVE_OVERRIDE: number = 0;
readonly STARTING_BIOME_OVERRIDE: Biome = Biome.TOWN; readonly STARTING_BIOME_OVERRIDE: Biome | null = null;
readonly ARENA_TINT_OVERRIDE: TimeOfDay | null = null; readonly ARENA_TINT_OVERRIDE: TimeOfDay | null = null;
/** Multiplies XP gained by this value including 0. Set to null to ignore the override. */ /** Multiplies XP gained by this value including 0. Set to null to ignore the override. */
readonly XP_MULTIPLIER_OVERRIDE: number | null = null; readonly XP_MULTIPLIER_OVERRIDE: number | null = null;

View File

@ -125,6 +125,12 @@ export class SwitchSummonPhase extends SummonPhase {
const switchedInPokemon: Pokemon | undefined = party[this.slotIndex]; const switchedInPokemon: Pokemon | undefined = party[this.slotIndex];
this.lastPokemon = this.getPokemon(); this.lastPokemon = this.getPokemon();
// Defensive programming: Overcome the bug where the summon data has somehow not been reset
// prior to switching in a new Pokemon.
// Force the switch to occur and load the assets for the new pokemon, ignoring override.
switchedInPokemon.resetSummonData();
switchedInPokemon.loadAssets(true);
applyPreSummonAbAttrs(PreSummonAbAttr, switchedInPokemon); applyPreSummonAbAttrs(PreSummonAbAttr, switchedInPokemon);
applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, this.lastPokemon); applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, this.lastPokemon);
if (!switchedInPokemon) { if (!switchedInPokemon) {
@ -132,6 +138,7 @@ export class SwitchSummonPhase extends SummonPhase {
return; return;
} }
if (this.switchType === SwitchType.BATON_PASS) { if (this.switchType === SwitchType.BATON_PASS) {
// If switching via baton pass, update opposing tags coming from the prior pokemon // If switching via baton pass, update opposing tags coming from the prior pokemon
(this.player ? globalScene.getEnemyField() : globalScene.getPlayerField()).forEach((enemyPokemon: Pokemon) => (this.player ? globalScene.getEnemyField() : globalScene.getPlayerField()).forEach((enemyPokemon: Pokemon) =>

View File

@ -65,14 +65,14 @@ const fonts: Array<LoadingFontFaceProperty> = [
unicodeRange: rangesByLanguage.chinese, unicodeRange: rangesByLanguage.chinese,
}), }),
extraOptions: { sizeAdjust: "70%", format: "woff2" }, extraOptions: { sizeAdjust: "70%", format: "woff2" },
only: ["en", "es", "fr", "it", "de", "zh", "pt", "ko", "ca", "he"], only: ["en", "es", "fr", "it", "de", "zh", "pt", "ko", "ca", "da", "tr", "ro", "ru", "he"],
}, },
{ {
face: new FontFace("pkmnems", "url(./fonts/unifont-15.1.05.subset.woff2)", { face: new FontFace("pkmnems", "url(./fonts/unifont-15.1.05.subset.woff2)", {
unicodeRange: rangesByLanguage.chinese, unicodeRange: rangesByLanguage.chinese,
}), }),
extraOptions: { format: "woff2" }, extraOptions: { format: "woff2" },
only: ["en", "es", "fr", "it", "de", "zh", "pt", "ko", "ca", "he"], only: ["en", "es", "fr", "it", "de", "zh", "pt", "ko", "ca", "da", "tr", "ro", "ru", "he"],
}, },
// japanese // japanese
{ {
@ -174,7 +174,7 @@ export async function initI18n(): Promise<void> {
"es-MX": ["es-ES", "en"], "es-MX": ["es-ES", "en"],
default: ["en"], default: ["en"],
}, },
supportedLngs: ["en", "es-ES", "es-MX", "fr", "it", "de", "zh-CN", "zh-TW", "pt-BR", "ko", "ja", "ca-ES", "he"], supportedLngs: ["en", "es-ES", "es-MX", "fr", "it", "de", "zh-CN", "zh-TW", "pt-BR", "ko", "ja", "ca", "da", "tr", "ro", "ru", "he"],
backend: { backend: {
loadPath(lng: string, [ns]: string[]) { loadPath(lng: string, [ns]: string[]) {
let fileName: string; let fileName: string;

View File

@ -921,10 +921,6 @@ export function setSetting(setting: string, value: number): boolean {
label: "Español (LATAM)", label: "Español (LATAM)",
handler: () => changeLocaleHandler("es-MX"), handler: () => changeLocaleHandler("es-MX"),
}, },
{
label: "Italiano",
handler: () => changeLocaleHandler("it"),
},
{ {
label: "Français", label: "Français",
handler: () => changeLocaleHandler("fr"), handler: () => changeLocaleHandler("fr"),
@ -933,18 +929,14 @@ export function setSetting(setting: string, value: number): boolean {
label: "Deutsch", label: "Deutsch",
handler: () => changeLocaleHandler("de"), handler: () => changeLocaleHandler("de"),
}, },
{
label: "Italiano",
handler: () => changeLocaleHandler("it"),
},
{ {
label: "Português (BR)", label: "Português (BR)",
handler: () => changeLocaleHandler("pt-BR"), handler: () => changeLocaleHandler("pt-BR"),
}, },
{
label: "简体中文",
handler: () => changeLocaleHandler("zh-CN"),
},
{
label: "繁體中文",
handler: () => changeLocaleHandler("zh-TW"),
},
{ {
label: "한국어", label: "한국어",
handler: () => changeLocaleHandler("ko"), handler: () => changeLocaleHandler("ko"),
@ -954,8 +946,32 @@ export function setSetting(setting: string, value: number): boolean {
handler: () => changeLocaleHandler("ja"), handler: () => changeLocaleHandler("ja"),
}, },
{ {
label: "Català", label: "简体中文",
handler: () => changeLocaleHandler("ca-ES"), handler: () => changeLocaleHandler("zh-CN"),
},
{
label: "繁體中文",
handler: () => changeLocaleHandler("zh-TW"),
},
{
label: "Català (Needs Help)",
handler: () => changeLocaleHandler("ca"),
},
{
label: "Türkçe (Needs Help)",
handler: () => changeLocaleHandler("tr")
},
{
label: "Русский (Needs Help)",
handler: () => changeLocaleHandler("ru"),
},
{
label: "Dansk (Needs Help)",
handler: () => changeLocaleHandler("da")
},
{
label: "Română (Needs Help)",
handler: () => changeLocaleHandler("ro")
}, },
{ {
label: "עברית", label: "עברית",

View File

@ -20,37 +20,37 @@ declare module "phaser" {
/** /**
* Sets this object's position relative to another object with a given offset * Sets this object's position relative to another object with a given offset
*/ */
setPositionRelative(guideObject: any, x: number, y: number): void; setPositionRelative(guideObject: any, x: number, y: number): this;
} }
interface Sprite { interface Sprite {
/** /**
* Sets this object's position relative to another object with a given offset * Sets this object's position relative to another object with a given offset
*/ */
setPositionRelative(guideObject: any, x: number, y: number): void; setPositionRelative(guideObject: any, x: number, y: number): this;
} }
interface Image { interface Image {
/** /**
* Sets this object's position relative to another object with a given offset * Sets this object's position relative to another object with a given offset
*/ */
setPositionRelative(guideObject: any, x: number, y: number): void; setPositionRelative(guideObject: any, x: number, y: number): this;
} }
interface NineSlice { interface NineSlice {
/** /**
* Sets this object's position relative to another object with a given offset * Sets this object's position relative to another object with a given offset
*/ */
setPositionRelative(guideObject: any, x: number, y: number): void; setPositionRelative(guideObject: any, x: number, y: number): this;
} }
interface Text { interface Text {
/** /**
* Sets this object's position relative to another object with a given offset * Sets this object's position relative to another object with a given offset
*/ */
setPositionRelative(guideObject: any, x: number, y: number): void; setPositionRelative(guideObject: any, x: number, y: number): this;
} }
interface Rectangle { interface Rectangle {
/** /**
* Sets this object's position relative to another object with a given offset * Sets this object's position relative to another object with a given offset
*/ */
setPositionRelative(guideObject: any, x: number, y: number): void; setPositionRelative(guideObject: any, x: number, y: number): this;
} }
} }

View File

@ -161,7 +161,7 @@ export class UiInputs {
buttonInfo(pressed = true): void { buttonInfo(pressed = true): void {
if (globalScene.showMovesetFlyout) { if (globalScene.showMovesetFlyout) {
for (const p of globalScene.getField().filter(p => p?.isActive(true))) { for (const p of globalScene.getEnemyField().filter(p => p?.isActive(true))) {
p.toggleFlyout(pressed); p.toggleFlyout(pressed);
} }
} }

View File

@ -1,4 +1,4 @@
import type { default as Pokemon } from "../field/pokemon"; import type { EnemyPokemon, default as Pokemon } from "../field/pokemon";
import { addTextObject, TextStyle } from "./text"; import { addTextObject, TextStyle } from "./text";
import { fixedInt } from "#app/utils/common"; import { fixedInt } from "#app/utils/common";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
@ -126,7 +126,7 @@ export default class BattleFlyout extends Phaser.GameObjects.Container {
* Links the given {@linkcode Pokemon} and subscribes to the {@linkcode BattleSceneEventType.MOVE_USED} event * Links the given {@linkcode Pokemon} and subscribes to the {@linkcode BattleSceneEventType.MOVE_USED} event
* @param pokemon {@linkcode Pokemon} to link to this flyout * @param pokemon {@linkcode Pokemon} to link to this flyout
*/ */
initInfo(pokemon: Pokemon) { initInfo(pokemon: EnemyPokemon) {
this.pokemon = pokemon; this.pokemon = pokemon;
this.name = `Flyout ${getPokemonNameWithAffix(this.pokemon)}`; this.name = `Flyout ${getPokemonNameWithAffix(this.pokemon)}`;

View File

@ -1,986 +0,0 @@
import type { EnemyPokemon, default as Pokemon } from "../field/pokemon";
import { getLevelTotalExp, getLevelRelExp } from "../data/exp";
import { getLocalizedSpriteKey, fixedInt } from "#app/utils/common";
import { addTextObject, TextStyle } from "./text";
import { getGenderSymbol, getGenderColor, Gender } from "../data/gender";
import { StatusEffect } from "#enums/status-effect";
import { globalScene } from "#app/global-scene";
import { getTypeRgb } from "#app/data/type";
import { PokemonType } from "#enums/pokemon-type";
import { getVariantTint } from "#app/sprites/variant";
import { Stat } from "#enums/stat";
import BattleFlyout from "./battle-flyout";
import { WindowVariant, addWindow } from "./ui-theme";
import i18next from "i18next";
import { ExpGainsSpeed } from "#app/enums/exp-gains-speed";
export default class BattleInfo extends Phaser.GameObjects.Container {
public static readonly EXP_GAINS_DURATION_BASE = 1650;
private baseY: number;
private player: boolean;
private mini: boolean;
private boss: boolean;
private bossSegments: number;
private offset: boolean;
private lastName: string | null;
private lastTeraType: PokemonType;
private lastStatus: StatusEffect;
private lastHp: number;
private lastMaxHp: number;
private lastHpFrame: string | null;
private lastExp: number;
private lastLevelExp: number;
private lastLevel: number;
private lastLevelCapped: boolean;
private lastStats: string;
private box: Phaser.GameObjects.Sprite;
private nameText: Phaser.GameObjects.Text;
private genderText: Phaser.GameObjects.Text;
private ownedIcon: Phaser.GameObjects.Sprite;
private championRibbon: Phaser.GameObjects.Sprite;
private teraIcon: Phaser.GameObjects.Sprite;
private shinyIcon: Phaser.GameObjects.Sprite;
private fusionShinyIcon: Phaser.GameObjects.Sprite;
private splicedIcon: Phaser.GameObjects.Sprite;
private statusIndicator: Phaser.GameObjects.Sprite;
private levelContainer: Phaser.GameObjects.Container;
private hpBar: Phaser.GameObjects.Image;
private hpBarSegmentDividers: Phaser.GameObjects.Rectangle[];
private levelNumbersContainer: Phaser.GameObjects.Container;
private hpNumbersContainer: Phaser.GameObjects.Container;
private type1Icon: Phaser.GameObjects.Sprite;
private type2Icon: Phaser.GameObjects.Sprite;
private type3Icon: Phaser.GameObjects.Sprite;
private expBar: Phaser.GameObjects.Image;
// #region Type effectiveness hint objects
private effectivenessContainer: Phaser.GameObjects.Container;
private effectivenessWindow: Phaser.GameObjects.NineSlice;
private effectivenessText: Phaser.GameObjects.Text;
private currentEffectiveness?: string;
// #endregion
public expMaskRect: Phaser.GameObjects.Graphics;
private statsContainer: Phaser.GameObjects.Container;
private statsBox: Phaser.GameObjects.Sprite;
private statValuesContainer: Phaser.GameObjects.Container;
private statNumbers: Phaser.GameObjects.Sprite[];
public flyoutMenu?: BattleFlyout;
private statOrder: Stat[];
private readonly statOrderPlayer = [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.ACC, Stat.EVA, Stat.SPD];
private readonly statOrderEnemy = [Stat.HP, Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.ACC, Stat.EVA, Stat.SPD];
constructor(x: number, y: number, player: boolean) {
super(globalScene, x, y);
this.baseY = y;
this.player = player;
this.mini = !player;
this.boss = false;
this.offset = false;
this.lastName = null;
this.lastTeraType = PokemonType.UNKNOWN;
this.lastStatus = StatusEffect.NONE;
this.lastHp = -1;
this.lastMaxHp = -1;
this.lastHpFrame = null;
this.lastExp = -1;
this.lastLevelExp = -1;
this.lastLevel = -1;
// Initially invisible and shown via Pokemon.showInfo
this.setVisible(false);
this.box = globalScene.add.sprite(0, 0, this.getTextureName());
this.box.setName("box");
this.box.setOrigin(1, 0.5);
this.add(this.box);
this.nameText = addTextObject(player ? -115 : -124, player ? -15.2 : -11.2, "", TextStyle.BATTLE_INFO);
this.nameText.setName("text_name");
this.nameText.setOrigin(0, 0);
this.add(this.nameText);
this.genderText = addTextObject(0, 0, "", TextStyle.BATTLE_INFO);
this.genderText.setName("text_gender");
this.genderText.setOrigin(0, 0);
this.genderText.setPositionRelative(this.nameText, 0, 2);
this.add(this.genderText);
if (!this.player) {
this.ownedIcon = globalScene.add.sprite(0, 0, "icon_owned");
this.ownedIcon.setName("icon_owned");
this.ownedIcon.setVisible(false);
this.ownedIcon.setOrigin(0, 0);
this.ownedIcon.setPositionRelative(this.nameText, 0, 11.75);
this.add(this.ownedIcon);
this.championRibbon = globalScene.add.sprite(0, 0, "champion_ribbon");
this.championRibbon.setName("icon_champion_ribbon");
this.championRibbon.setVisible(false);
this.championRibbon.setOrigin(0, 0);
this.championRibbon.setPositionRelative(this.nameText, 8, 11.75);
this.add(this.championRibbon);
}
this.teraIcon = globalScene.add.sprite(0, 0, "icon_tera");
this.teraIcon.setName("icon_tera");
this.teraIcon.setVisible(false);
this.teraIcon.setOrigin(0, 0);
this.teraIcon.setScale(0.5);
this.teraIcon.setPositionRelative(this.nameText, 0, 2);
this.teraIcon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 12, 15), Phaser.Geom.Rectangle.Contains);
this.add(this.teraIcon);
this.shinyIcon = globalScene.add.sprite(0, 0, "shiny_star");
this.shinyIcon.setName("icon_shiny");
this.shinyIcon.setVisible(false);
this.shinyIcon.setOrigin(0, 0);
this.shinyIcon.setScale(0.5);
this.shinyIcon.setPositionRelative(this.nameText, 0, 2);
this.shinyIcon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 12, 15), Phaser.Geom.Rectangle.Contains);
this.add(this.shinyIcon);
this.fusionShinyIcon = globalScene.add.sprite(0, 0, "shiny_star_2");
this.fusionShinyIcon.setName("icon_fusion_shiny");
this.fusionShinyIcon.setVisible(false);
this.fusionShinyIcon.setOrigin(0, 0);
this.fusionShinyIcon.setScale(0.5);
this.fusionShinyIcon.setPosition(this.shinyIcon.x, this.shinyIcon.y);
this.add(this.fusionShinyIcon);
this.splicedIcon = globalScene.add.sprite(0, 0, "icon_spliced");
this.splicedIcon.setName("icon_spliced");
this.splicedIcon.setVisible(false);
this.splicedIcon.setOrigin(0, 0);
this.splicedIcon.setScale(0.5);
this.splicedIcon.setPositionRelative(this.nameText, 0, 2);
this.splicedIcon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 12, 15), Phaser.Geom.Rectangle.Contains);
this.add(this.splicedIcon);
this.statusIndicator = globalScene.add.sprite(0, 0, getLocalizedSpriteKey("statuses"));
this.statusIndicator.setName("icon_status");
this.statusIndicator.setVisible(false);
this.statusIndicator.setOrigin(0, 0);
this.statusIndicator.setPositionRelative(this.nameText, 0, 11.5);
this.add(this.statusIndicator);
this.levelContainer = globalScene.add.container(player ? -41 : -50, player ? -10 : -5);
this.levelContainer.setName("container_level");
this.add(this.levelContainer);
const levelOverlay = globalScene.add.image(0, 0, "overlay_lv");
this.levelContainer.add(levelOverlay);
this.hpBar = globalScene.add.image(player ? -61 : -71, player ? -1 : 4.5, "overlay_hp");
this.hpBar.setName("hp_bar");
this.hpBar.setOrigin(0);
this.add(this.hpBar);
this.hpBarSegmentDividers = [];
this.levelNumbersContainer = globalScene.add.container(9.5, globalScene.uiTheme ? 0 : -0.5);
this.levelNumbersContainer.setName("container_level");
this.levelContainer.add(this.levelNumbersContainer);
if (this.player) {
this.hpNumbersContainer = globalScene.add.container(-15, 10);
this.hpNumbersContainer.setName("container_hp");
this.add(this.hpNumbersContainer);
const expBar = globalScene.add.image(-98, 18, "overlay_exp");
expBar.setName("overlay_exp");
expBar.setOrigin(0);
this.add(expBar);
const expMaskRect = globalScene.make.graphics({});
expMaskRect.setScale(6);
expMaskRect.fillStyle(0xffffff);
expMaskRect.beginPath();
expMaskRect.fillRect(127, 126, 85, 2);
const expMask = expMaskRect.createGeometryMask();
expBar.setMask(expMask);
this.expBar = expBar;
this.expMaskRect = expMaskRect;
}
this.statsContainer = globalScene.add.container(0, 0);
this.statsContainer.setName("container_stats");
this.statsContainer.setAlpha(0);
this.add(this.statsContainer);
this.statsBox = globalScene.add.sprite(0, 0, `${this.getTextureName()}_stats`);
this.statsBox.setName("box_stats");
this.statsBox.setOrigin(1, 0.5);
this.statsContainer.add(this.statsBox);
const statLabels: Phaser.GameObjects.Sprite[] = [];
this.statNumbers = [];
this.statValuesContainer = globalScene.add.container(0, 0);
this.statsContainer.add(this.statValuesContainer);
// this gives us a different starting location from the left of the label and padding between stats for a player vs enemy
// since the player won't have HP to show, it doesn't need to change from the current version
const startingX = this.player ? -this.statsBox.width + 8 : -this.statsBox.width + 5;
const paddingX = this.player ? 4 : 2;
const statOverflow = this.player ? 1 : 0;
this.statOrder = this.player ? this.statOrderPlayer : this.statOrderEnemy; // this tells us whether or not to use the player or enemy battle stat order
this.statOrder.map((s, i) => {
// we do a check for i > statOverflow to see when the stat labels go onto the next column
// For enemies, we have HP (i=0) by itself then a new column, so we check for i > 0
// For players, we don't have HP, so we start with i = 0 and i = 1 for our first column, and so need to check for i > 1
const statX =
i > statOverflow
? this.statNumbers[Math.max(i - 2, 0)].x + this.statNumbers[Math.max(i - 2, 0)].width + paddingX
: startingX; // we have the Math.max(i - 2, 0) in there so for i===1 to not return a negative number; since this is now based on anything >0 instead of >1, we need to allow for i-2 < 0
const baseY = -this.statsBox.height / 2 + 4; // this is the baseline for the y-axis
let statY: number; // this will be the y-axis placement for the labels
if (this.statOrder[i] === Stat.SPD || this.statOrder[i] === Stat.HP) {
statY = baseY + 5;
} else {
statY = baseY + (!!(i % 2) === this.player ? 10 : 0); // we compare i % 2 against this.player to tell us where to place the label; because this.battleStatOrder for enemies has HP, this.battleStatOrder[1]=ATK, but for players this.battleStatOrder[0]=ATK, so this comparing i % 2 to this.player fixes this issue for us
}
const statLabel = globalScene.add.sprite(statX, statY, "pbinfo_stat", Stat[s]);
statLabel.setName("icon_stat_label_" + i.toString());
statLabel.setOrigin(0, 0);
statLabels.push(statLabel);
this.statValuesContainer.add(statLabel);
const statNumber = globalScene.add.sprite(
statX + statLabel.width,
statY,
"pbinfo_stat_numbers",
this.statOrder[i] !== Stat.HP ? "3" : "empty",
);
statNumber.setName("icon_stat_number_" + i.toString());
statNumber.setOrigin(0, 0);
this.statNumbers.push(statNumber);
this.statValuesContainer.add(statNumber);
if (this.statOrder[i] === Stat.HP) {
statLabel.setVisible(false);
statNumber.setVisible(false);
}
});
if (!this.player) {
this.flyoutMenu = new BattleFlyout(this.player);
this.add(this.flyoutMenu);
this.moveBelow<Phaser.GameObjects.GameObject>(this.flyoutMenu, this.box);
}
this.type1Icon = globalScene.add.sprite(
player ? -139 : -15,
player ? -17 : -15.5,
`pbinfo_${player ? "player" : "enemy"}_type1`,
);
this.type1Icon.setName("icon_type_1");
this.type1Icon.setOrigin(0, 0);
this.add(this.type1Icon);
this.type2Icon = globalScene.add.sprite(
player ? -139 : -15,
player ? -1 : -2.5,
`pbinfo_${player ? "player" : "enemy"}_type2`,
);
this.type2Icon.setName("icon_type_2");
this.type2Icon.setOrigin(0, 0);
this.add(this.type2Icon);
this.type3Icon = globalScene.add.sprite(
player ? -154 : 0,
player ? -17 : -15.5,
`pbinfo_${player ? "player" : "enemy"}_type`,
);
this.type3Icon.setName("icon_type_3");
this.type3Icon.setOrigin(0, 0);
this.add(this.type3Icon);
if (!this.player) {
this.effectivenessContainer = globalScene.add.container(0, 0);
this.effectivenessContainer.setPositionRelative(this.type1Icon, 22, 4);
this.effectivenessContainer.setVisible(false);
this.add(this.effectivenessContainer);
this.effectivenessText = addTextObject(5, 4.5, "", TextStyle.BATTLE_INFO);
this.effectivenessWindow = addWindow(0, 0, 0, 20, undefined, false, undefined, undefined, WindowVariant.XTHIN);
this.effectivenessContainer.add(this.effectivenessWindow);
this.effectivenessContainer.add(this.effectivenessText);
}
}
getStatsValueContainer(): Phaser.GameObjects.Container {
return this.statValuesContainer;
}
initInfo(pokemon: Pokemon) {
this.updateNameText(pokemon);
const nameTextWidth = this.nameText.displayWidth;
this.name = pokemon.getNameToRender();
this.box.name = pokemon.getNameToRender();
this.flyoutMenu?.initInfo(pokemon);
this.genderText.setText(getGenderSymbol(pokemon.gender));
this.genderText.setColor(getGenderColor(pokemon.gender));
this.genderText.setPositionRelative(this.nameText, nameTextWidth, 0);
this.lastTeraType = pokemon.getTeraType();
this.teraIcon.setPositionRelative(this.nameText, nameTextWidth + this.genderText.displayWidth + 1, 2);
this.teraIcon.setVisible(pokemon.isTerastallized);
this.teraIcon.on("pointerover", () => {
if (pokemon.isTerastallized) {
globalScene.ui.showTooltip(
"",
i18next.t("fightUiHandler:teraHover", {
type: i18next.t(`pokemonInfo:Type.${PokemonType[this.lastTeraType]}`),
}),
);
}
});
this.teraIcon.on("pointerout", () => globalScene.ui.hideTooltip());
const isFusion = pokemon.isFusion(true);
this.splicedIcon.setPositionRelative(
this.nameText,
nameTextWidth + this.genderText.displayWidth + 1 + (this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0),
2.5,
);
this.splicedIcon.setVisible(isFusion);
if (this.splicedIcon.visible) {
this.splicedIcon.on("pointerover", () =>
globalScene.ui.showTooltip(
"",
`${pokemon.species.getName(pokemon.formIndex)}/${pokemon.fusionSpecies?.getName(pokemon.fusionFormIndex)}`,
),
);
this.splicedIcon.on("pointerout", () => globalScene.ui.hideTooltip());
}
const doubleShiny = isFusion && pokemon.shiny && pokemon.fusionShiny;
const baseVariant = !doubleShiny ? pokemon.getVariant(true) : pokemon.variant;
this.shinyIcon.setPositionRelative(
this.nameText,
nameTextWidth +
this.genderText.displayWidth +
1 +
(this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0) +
(this.splicedIcon.visible ? this.splicedIcon.displayWidth + 1 : 0),
2.5,
);
this.shinyIcon.setTexture(`shiny_star${doubleShiny ? "_1" : ""}`);
this.shinyIcon.setVisible(pokemon.isShiny());
this.shinyIcon.setTint(getVariantTint(baseVariant));
if (this.shinyIcon.visible) {
const shinyDescriptor =
doubleShiny || baseVariant
? `${baseVariant === 2 ? i18next.t("common:epicShiny") : baseVariant === 1 ? i18next.t("common:rareShiny") : i18next.t("common:commonShiny")}${doubleShiny ? `/${pokemon.fusionVariant === 2 ? i18next.t("common:epicShiny") : pokemon.fusionVariant === 1 ? i18next.t("common:rareShiny") : i18next.t("common:commonShiny")}` : ""}`
: "";
this.shinyIcon.on("pointerover", () =>
globalScene.ui.showTooltip(
"",
`${i18next.t("common:shinyOnHover")}${shinyDescriptor ? ` (${shinyDescriptor})` : ""}`,
),
);
this.shinyIcon.on("pointerout", () => globalScene.ui.hideTooltip());
}
this.fusionShinyIcon.setPosition(this.shinyIcon.x, this.shinyIcon.y);
this.fusionShinyIcon.setVisible(doubleShiny);
if (isFusion) {
this.fusionShinyIcon.setTint(getVariantTint(pokemon.fusionVariant));
}
if (!this.player) {
if (this.nameText.visible) {
this.nameText.on("pointerover", () =>
globalScene.ui.showTooltip(
"",
i18next.t("battleInfo:generation", {
generation: i18next.t(`starterSelectUiHandler:gen${pokemon.species.generation}`),
}),
),
);
this.nameText.on("pointerout", () => globalScene.ui.hideTooltip());
}
const dexEntry = globalScene.gameData.dexData[pokemon.species.speciesId];
this.ownedIcon.setVisible(!!dexEntry.caughtAttr);
const opponentPokemonDexAttr = pokemon.getDexAttr();
if (globalScene.gameMode.isClassic) {
if (
globalScene.gameData.starterData[pokemon.species.getRootSpeciesId()].classicWinCount > 0 &&
globalScene.gameData.starterData[pokemon.species.getRootSpeciesId(true)].classicWinCount > 0
) {
this.championRibbon.setVisible(true);
}
}
// Check if Player owns all genders and forms of the Pokemon
const missingDexAttrs = (dexEntry.caughtAttr & opponentPokemonDexAttr) < opponentPokemonDexAttr;
const ownedAbilityAttrs = globalScene.gameData.starterData[pokemon.species.getRootSpeciesId()].abilityAttr;
// Check if the player owns ability for the root form
const playerOwnsThisAbility = pokemon.checkIfPlayerHasAbilityOfStarter(ownedAbilityAttrs);
if (missingDexAttrs || !playerOwnsThisAbility) {
this.ownedIcon.setTint(0x808080);
}
if (this.boss) {
this.updateBossSegmentDividers(pokemon as EnemyPokemon);
}
}
this.hpBar.setScale(pokemon.getHpRatio(true), 1);
this.lastHpFrame = this.hpBar.scaleX > 0.5 ? "high" : this.hpBar.scaleX > 0.25 ? "medium" : "low";
this.hpBar.setFrame(this.lastHpFrame);
if (this.player) {
this.setHpNumbers(pokemon.hp, pokemon.getMaxHp());
}
this.lastHp = pokemon.hp;
this.lastMaxHp = pokemon.getMaxHp();
this.setLevel(pokemon.level);
this.lastLevel = pokemon.level;
this.shinyIcon.setVisible(pokemon.isShiny());
const types = pokemon.getTypes(true, false, undefined, true);
this.type1Icon.setTexture(`pbinfo_${this.player ? "player" : "enemy"}_type${types.length > 1 ? "1" : ""}`);
this.type1Icon.setFrame(PokemonType[types[0]].toLowerCase());
this.type2Icon.setVisible(types.length > 1);
this.type3Icon.setVisible(types.length > 2);
if (types.length > 1) {
this.type2Icon.setFrame(PokemonType[types[1]].toLowerCase());
}
if (types.length > 2) {
this.type3Icon.setFrame(PokemonType[types[2]].toLowerCase());
}
if (this.player) {
this.expMaskRect.x = (pokemon.levelExp / getLevelTotalExp(pokemon.level, pokemon.species.growthRate)) * 510;
this.lastExp = pokemon.exp;
this.lastLevelExp = pokemon.levelExp;
this.statValuesContainer.setPosition(8, 7);
}
const stats = this.statOrder.map(() => 0);
this.lastStats = stats.join("");
this.updateStats(stats);
}
getTextureName(): string {
return `pbinfo_${this.player ? "player" : "enemy"}${!this.player && this.boss ? "_boss" : this.mini ? "_mini" : ""}`;
}
setMini(mini: boolean): void {
if (this.mini === mini) {
return;
}
this.mini = mini;
this.box.setTexture(this.getTextureName());
this.statsBox.setTexture(`${this.getTextureName()}_stats`);
if (this.player) {
this.y -= 12 * (mini ? 1 : -1);
this.baseY = this.y;
}
const offsetElements = [
this.nameText,
this.genderText,
this.teraIcon,
this.splicedIcon,
this.shinyIcon,
this.statusIndicator,
this.levelContainer,
];
offsetElements.forEach(el => (el.y += 1.5 * (mini ? -1 : 1)));
[this.type1Icon, this.type2Icon, this.type3Icon].forEach(el => {
el.x += 4 * (mini ? 1 : -1);
el.y += -8 * (mini ? 1 : -1);
});
this.statValuesContainer.x += 2 * (mini ? 1 : -1);
this.statValuesContainer.y += -7 * (mini ? 1 : -1);
const toggledElements = [this.hpNumbersContainer, this.expBar];
toggledElements.forEach(el => el.setVisible(!mini));
}
toggleStats(visible: boolean): void {
globalScene.tweens.add({
targets: this.statsContainer,
duration: fixedInt(125),
ease: "Sine.easeInOut",
alpha: visible ? 1 : 0,
});
}
updateBossSegments(pokemon: EnemyPokemon): void {
const boss = !!pokemon.bossSegments;
if (boss !== this.boss) {
this.boss = boss;
[
this.nameText,
this.genderText,
this.teraIcon,
this.splicedIcon,
this.shinyIcon,
this.ownedIcon,
this.championRibbon,
this.statusIndicator,
this.statValuesContainer,
].map(e => (e.x += 48 * (boss ? -1 : 1)));
this.hpBar.x += 38 * (boss ? -1 : 1);
this.hpBar.y += 2 * (this.boss ? -1 : 1);
this.levelContainer.x += 2 * (boss ? -1 : 1);
this.hpBar.setTexture(`overlay_hp${boss ? "_boss" : ""}`);
this.box.setTexture(this.getTextureName());
this.statsBox.setTexture(`${this.getTextureName()}_stats`);
}
this.bossSegments = boss ? pokemon.bossSegments : 0;
this.updateBossSegmentDividers(pokemon);
}
updateBossSegmentDividers(pokemon: EnemyPokemon): void {
while (this.hpBarSegmentDividers.length) {
this.hpBarSegmentDividers.pop()?.destroy();
}
if (this.boss && this.bossSegments > 1) {
const uiTheme = globalScene.uiTheme;
const maxHp = pokemon.getMaxHp();
for (let s = 1; s < this.bossSegments; s++) {
const dividerX = (Math.round((maxHp / this.bossSegments) * s) / maxHp) * this.hpBar.width;
const divider = globalScene.add.rectangle(
0,
0,
1,
this.hpBar.height - (uiTheme ? 0 : 1),
pokemon.bossSegmentIndex >= s ? 0xffffff : 0x404040,
);
divider.setOrigin(0.5, 0);
divider.setName("hpBar_divider_" + s.toString());
this.add(divider);
this.moveBelow(divider as Phaser.GameObjects.GameObject, this.statsContainer);
divider.setPositionRelative(this.hpBar, dividerX, uiTheme ? 0 : 1);
this.hpBarSegmentDividers.push(divider);
}
}
}
setOffset(offset: boolean): void {
if (this.offset === offset) {
return;
}
this.offset = offset;
this.x += 10 * (this.offset === this.player ? 1 : -1);
this.y += 27 * (this.offset ? 1 : -1);
this.baseY = this.y;
}
updateInfo(pokemon: Pokemon, instant?: boolean): Promise<void> {
return new Promise(resolve => {
if (!globalScene) {
return resolve();
}
const gender = pokemon.summonData.illusion?.gender ?? pokemon.gender;
this.genderText.setText(getGenderSymbol(gender));
this.genderText.setColor(getGenderColor(gender));
const nameUpdated = this.lastName !== pokemon.getNameToRender();
if (nameUpdated) {
this.updateNameText(pokemon);
this.genderText.setPositionRelative(this.nameText, this.nameText.displayWidth, 0);
}
const teraType = pokemon.isTerastallized ? pokemon.getTeraType() : PokemonType.UNKNOWN;
const teraTypeUpdated = this.lastTeraType !== teraType;
if (teraTypeUpdated) {
this.teraIcon.setVisible(teraType !== PokemonType.UNKNOWN);
this.teraIcon.setPositionRelative(
this.nameText,
this.nameText.displayWidth + this.genderText.displayWidth + 1,
2,
);
this.teraIcon.setTintFill(Phaser.Display.Color.GetColor(...getTypeRgb(teraType)));
this.lastTeraType = teraType;
}
const isFusion = pokemon.isFusion(true);
if (nameUpdated || teraTypeUpdated) {
this.splicedIcon.setVisible(isFusion);
this.teraIcon.setPositionRelative(
this.nameText,
this.nameText.displayWidth + this.genderText.displayWidth + 1,
2,
);
this.splicedIcon.setPositionRelative(
this.nameText,
this.nameText.displayWidth +
this.genderText.displayWidth +
1 +
(this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0),
1.5,
);
this.shinyIcon.setPositionRelative(
this.nameText,
this.nameText.displayWidth +
this.genderText.displayWidth +
1 +
(this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0) +
(this.splicedIcon.visible ? this.splicedIcon.displayWidth + 1 : 0),
2.5,
);
}
if (this.lastStatus !== (pokemon.status?.effect || StatusEffect.NONE)) {
this.lastStatus = pokemon.status?.effect || StatusEffect.NONE;
if (this.lastStatus !== StatusEffect.NONE) {
this.statusIndicator.setFrame(StatusEffect[this.lastStatus].toLowerCase());
}
const offsetX = !this.player ? (this.ownedIcon.visible ? 8 : 0) + (this.championRibbon.visible ? 8 : 0) : 0;
this.statusIndicator.setPositionRelative(this.nameText, offsetX, 11.5);
this.statusIndicator.setVisible(!!this.lastStatus);
}
const types = pokemon.getTypes(true, false, undefined, true);
this.type1Icon.setTexture(`pbinfo_${this.player ? "player" : "enemy"}_type${types.length > 1 ? "1" : ""}`);
this.type1Icon.setFrame(PokemonType[types[0]].toLowerCase());
this.type2Icon.setVisible(types.length > 1);
this.type3Icon.setVisible(types.length > 2);
if (types.length > 1) {
this.type2Icon.setFrame(PokemonType[types[1]].toLowerCase());
}
if (types.length > 2) {
this.type3Icon.setFrame(PokemonType[types[2]].toLowerCase());
}
const updateHpFrame = () => {
const hpFrame = this.hpBar.scaleX > 0.5 ? "high" : this.hpBar.scaleX > 0.25 ? "medium" : "low";
if (hpFrame !== this.lastHpFrame) {
this.hpBar.setFrame(hpFrame);
this.lastHpFrame = hpFrame;
}
};
const updatePokemonHp = () => {
let duration = !instant ? Phaser.Math.Clamp(Math.abs(this.lastHp - pokemon.hp) * 5, 250, 5000) : 0;
const speed = globalScene.hpBarSpeed;
if (speed) {
duration = speed >= 3 ? 0 : duration / Math.pow(2, speed);
}
globalScene.tweens.add({
targets: this.hpBar,
ease: "Sine.easeOut",
scaleX: pokemon.getHpRatio(true),
duration: duration,
onUpdate: () => {
if (this.player && this.lastHp !== pokemon.hp) {
const tweenHp = Math.ceil(this.hpBar.scaleX * pokemon.getMaxHp());
this.setHpNumbers(tweenHp, pokemon.getMaxHp());
this.lastHp = tweenHp;
}
updateHpFrame();
},
onComplete: () => {
updateHpFrame();
// If, after tweening, the hp is different from the original (due to rounding), force the hp number display
// to update to the correct value.
if (this.player && this.lastHp !== pokemon.hp) {
this.setHpNumbers(pokemon.hp, pokemon.getMaxHp());
this.lastHp = pokemon.hp;
}
resolve();
},
});
if (!this.player) {
this.lastHp = pokemon.hp;
}
this.lastMaxHp = pokemon.getMaxHp();
};
if (this.player) {
const isLevelCapped = pokemon.level >= globalScene.getMaxExpLevel();
if (this.lastExp !== pokemon.exp || this.lastLevel !== pokemon.level) {
const originalResolve = resolve;
const durationMultipler = Math.max(
Phaser.Tweens.Builders.GetEaseFunction("Cubic.easeIn")(
1 - Math.min(pokemon.level - this.lastLevel, 10) / 10,
),
0.1,
);
resolve = () => this.updatePokemonExp(pokemon, false, durationMultipler).then(() => originalResolve());
} else if (isLevelCapped !== this.lastLevelCapped) {
this.setLevel(pokemon.level);
}
this.lastLevelCapped = isLevelCapped;
}
if (this.lastHp !== pokemon.hp || this.lastMaxHp !== pokemon.getMaxHp()) {
return updatePokemonHp();
}
if (!this.player && this.lastLevel !== pokemon.level) {
this.setLevel(pokemon.level);
this.lastLevel = pokemon.level;
}
const stats = pokemon.getStatStages();
const statsStr = stats.join("");
if (this.lastStats !== statsStr) {
this.updateStats(stats);
this.lastStats = statsStr;
}
this.shinyIcon.setVisible(pokemon.isShiny(true));
const doubleShiny = isFusion && pokemon.shiny && pokemon.fusionShiny;
const baseVariant = !doubleShiny ? pokemon.getVariant(true) : pokemon.variant;
this.shinyIcon.setTint(getVariantTint(baseVariant));
this.fusionShinyIcon.setVisible(doubleShiny);
if (isFusion) {
this.fusionShinyIcon.setTint(getVariantTint(pokemon.fusionVariant));
}
this.fusionShinyIcon.setPosition(this.shinyIcon.x, this.shinyIcon.y);
resolve();
});
}
updateNameText(pokemon: Pokemon): void {
let displayName = pokemon.getNameToRender().replace(/[♂♀]/g, "");
let nameTextWidth: number;
const nameSizeTest = addTextObject(0, 0, displayName, TextStyle.BATTLE_INFO);
nameTextWidth = nameSizeTest.displayWidth;
const gender = pokemon.summonData.illusion?.gender ?? pokemon.gender;
while (
nameTextWidth >
(this.player || !this.boss ? 60 : 98) -
((gender !== Gender.GENDERLESS ? 6 : 0) +
(pokemon.fusionSpecies ? 8 : 0) +
(pokemon.isShiny() ? 8 : 0) +
(Math.min(pokemon.level.toString().length, 3) - 3) * 8)
) {
displayName = `${displayName.slice(0, displayName.endsWith(".") ? -2 : -1).trimEnd()}.`;
nameSizeTest.setText(displayName);
nameTextWidth = nameSizeTest.displayWidth;
}
nameSizeTest.destroy();
this.nameText.setText(displayName);
this.lastName = pokemon.getNameToRender();
if (this.nameText.visible) {
this.nameText.setInteractive(
new Phaser.Geom.Rectangle(0, 0, this.nameText.width, this.nameText.height),
Phaser.Geom.Rectangle.Contains,
);
}
}
updatePokemonExp(pokemon: Pokemon, instant?: boolean, levelDurationMultiplier = 1): Promise<void> {
return new Promise(resolve => {
const levelUp = this.lastLevel < pokemon.level;
const relLevelExp = getLevelRelExp(this.lastLevel + 1, pokemon.species.growthRate);
const levelExp = levelUp ? relLevelExp : pokemon.levelExp;
let ratio = relLevelExp ? levelExp / relLevelExp : 0;
if (this.lastLevel >= globalScene.getMaxExpLevel(true)) {
if (levelUp) {
ratio = 1;
} else {
ratio = 0;
}
instant = true;
}
const durationMultiplier = Phaser.Tweens.Builders.GetEaseFunction("Sine.easeIn")(
1 - Math.max(this.lastLevel - 100, 0) / 150,
);
let duration =
this.visible && !instant
? ((levelExp - this.lastLevelExp) / relLevelExp) *
BattleInfo.EXP_GAINS_DURATION_BASE *
durationMultiplier *
levelDurationMultiplier
: 0;
const speed = globalScene.expGainsSpeed;
if (speed && speed >= ExpGainsSpeed.DEFAULT) {
duration = speed >= ExpGainsSpeed.SKIP ? ExpGainsSpeed.DEFAULT : duration / Math.pow(2, speed);
}
if (ratio === 1) {
this.lastLevelExp = 0;
this.lastLevel++;
} else {
this.lastExp = pokemon.exp;
this.lastLevelExp = pokemon.levelExp;
}
if (duration) {
globalScene.playSound("se/exp");
}
globalScene.tweens.add({
targets: this.expMaskRect,
ease: "Sine.easeIn",
x: ratio * 510,
duration: duration,
onComplete: () => {
if (!globalScene) {
return resolve();
}
if (duration) {
globalScene.sound.stopByKey("se/exp");
}
if (ratio === 1) {
globalScene.playSound("se/level_up");
this.setLevel(this.lastLevel);
globalScene.time.delayedCall(500 * levelDurationMultiplier, () => {
this.expMaskRect.x = 0;
this.updateInfo(pokemon, instant).then(() => resolve());
});
return;
}
resolve();
},
});
});
}
setLevel(level: number): void {
const isCapped = level >= globalScene.getMaxExpLevel();
this.levelNumbersContainer.removeAll(true);
const levelStr = level.toString();
for (let i = 0; i < levelStr.length; i++) {
this.levelNumbersContainer.add(
globalScene.add.image(i * 8, 0, `numbers${isCapped && this.player ? "_red" : ""}`, levelStr[i]),
);
}
this.levelContainer.setX((this.player ? -41 : -50) - 8 * Math.max(levelStr.length - 3, 0));
}
setHpNumbers(hp: number, maxHp: number): void {
if (!this.player || !globalScene) {
return;
}
this.hpNumbersContainer.removeAll(true);
const hpStr = hp.toString();
const maxHpStr = maxHp.toString();
let offset = 0;
for (let i = maxHpStr.length - 1; i >= 0; i--) {
this.hpNumbersContainer.add(globalScene.add.image(offset++ * -8, 0, "numbers", maxHpStr[i]));
}
this.hpNumbersContainer.add(globalScene.add.image(offset++ * -8, 0, "numbers", "/"));
for (let i = hpStr.length - 1; i >= 0; i--) {
this.hpNumbersContainer.add(globalScene.add.image(offset++ * -8, 0, "numbers", hpStr[i]));
}
}
updateStats(stats: number[]): void {
this.statOrder.map((s, i) => {
if (s !== Stat.HP) {
this.statNumbers[i].setFrame(stats[s - 1].toString());
}
});
}
/**
* Request the flyoutMenu to toggle if available and hides or shows the effectiveness window where necessary
*/
toggleFlyout(visible: boolean): void {
this.flyoutMenu?.toggleFlyout(visible);
if (visible) {
this.effectivenessContainer?.setVisible(false);
} else {
this.updateEffectiveness(this.currentEffectiveness);
}
}
/**
* Show or hide the type effectiveness multiplier window
* Passing undefined will hide the window
*/
updateEffectiveness(effectiveness?: string) {
if (this.player) {
return;
}
this.currentEffectiveness = effectiveness;
if (!globalScene.typeHints || effectiveness === undefined || this.flyoutMenu?.flyoutVisible) {
this.effectivenessContainer.setVisible(false);
return;
}
this.effectivenessText.setText(effectiveness);
this.effectivenessWindow.width = 10 + this.effectivenessText.displayWidth;
this.effectivenessContainer.setVisible(true);
}
getBaseY(): number {
return this.baseY;
}
resetY(): void {
this.y = this.baseY;
}
}
export class PlayerBattleInfo extends BattleInfo {
constructor() {
super(Math.floor(globalScene.game.canvas.width / 6) - 10, -72, true);
}
}
export class EnemyBattleInfo extends BattleInfo {
constructor() {
super(140, -141, false);
}
setMini(_mini: boolean): void {} // Always mini
}

View File

@ -0,0 +1,688 @@
import type { default as Pokemon } from "../../field/pokemon";
import { getLocalizedSpriteKey, fixedInt, getShinyDescriptor } from "#app/utils/common";
import { addTextObject, TextStyle } from "../text";
import { getGenderSymbol, getGenderColor, Gender } from "../../data/gender";
import { StatusEffect } from "#enums/status-effect";
import { globalScene } from "#app/global-scene";
import { getTypeRgb } from "#app/data/type";
import { PokemonType } from "#enums/pokemon-type";
import { getVariantTint } from "#app/sprites/variant";
import { Stat } from "#enums/stat";
import i18next from "i18next";
/**
* Parameters influencing the position of elements within the battle info container
*/
export type BattleInfoParamList = {
/** X offset for the name text*/
nameTextX: number;
/** Y offset for the name text */
nameTextY: number;
/** X offset for the level container */
levelContainerX: number;
/** Y offset for the level container */
levelContainerY: number;
/** X offset for the hp bar */
hpBarX: number;
/** Y offset for the hp bar */
hpBarY: number;
/** Parameters for the stat box container */
statBox: {
/** The starting offset from the left of the label for the entries in the stat box */
xOffset: number;
/** The X padding between each number column */
paddingX: number;
/** The index of the stat entries at which paddingX is used instead of startingX */
statOverflow: number;
};
};
export default abstract class BattleInfo extends Phaser.GameObjects.Container {
public static readonly EXP_GAINS_DURATION_BASE = 1650;
protected baseY: number;
protected baseLvContainerX: number;
protected player: boolean;
protected mini: boolean;
protected boss: boolean;
protected bossSegments: number;
protected offset: boolean;
protected lastName: string | null;
protected lastTeraType: PokemonType;
protected lastStatus: StatusEffect;
protected lastHp: number;
protected lastMaxHp: number;
protected lastHpFrame: string | null;
protected lastExp: number;
protected lastLevelExp: number;
protected lastLevel: number;
protected lastLevelCapped: boolean;
protected lastStats: string;
protected box: Phaser.GameObjects.Sprite;
protected nameText: Phaser.GameObjects.Text;
protected genderText: Phaser.GameObjects.Text;
protected teraIcon: Phaser.GameObjects.Sprite;
protected shinyIcon: Phaser.GameObjects.Sprite;
protected fusionShinyIcon: Phaser.GameObjects.Sprite;
protected splicedIcon: Phaser.GameObjects.Sprite;
protected statusIndicator: Phaser.GameObjects.Sprite;
protected levelContainer: Phaser.GameObjects.Container;
protected hpBar: Phaser.GameObjects.Image;
protected levelNumbersContainer: Phaser.GameObjects.Container;
protected type1Icon: Phaser.GameObjects.Sprite;
protected type2Icon: Phaser.GameObjects.Sprite;
protected type3Icon: Phaser.GameObjects.Sprite;
protected expBar: Phaser.GameObjects.Image;
public expMaskRect: Phaser.GameObjects.Graphics;
protected statsContainer: Phaser.GameObjects.Container;
protected statsBox: Phaser.GameObjects.Sprite;
protected statValuesContainer: Phaser.GameObjects.Container;
protected statNumbers: Phaser.GameObjects.Sprite[];
get statOrder(): Stat[] {
return [];
}
/** Helper method used by the constructor to create the tera and shiny icons next to the name */
private constructIcons() {
const hitArea = new Phaser.Geom.Rectangle(0, 0, 12, 15);
const hitCallback = Phaser.Geom.Rectangle.Contains;
this.teraIcon = globalScene.add
.sprite(0, 0, "icon_tera")
.setName("icon_tera")
.setVisible(false)
.setOrigin(0)
.setScale(0.5)
.setInteractive(hitArea, hitCallback)
.setPositionRelative(this.nameText, 0, 2);
this.shinyIcon = globalScene.add
.sprite(0, 0, "shiny_star")
.setName("icon_shiny")
.setVisible(false)
.setOrigin(0)
.setScale(0.5)
.setInteractive(hitArea, hitCallback)
.setPositionRelative(this.nameText, 0, 2);
this.fusionShinyIcon = globalScene.add
.sprite(0, 0, "shiny_star_2")
.setName("icon_fusion_shiny")
.setVisible(false)
.setOrigin(0)
.setScale(0.5)
.copyPosition(this.shinyIcon);
this.splicedIcon = globalScene.add
.sprite(0, 0, "icon_spliced")
.setName("icon_spliced")
.setVisible(false)
.setOrigin(0)
.setScale(0.5)
.setInteractive(hitArea, hitCallback)
.setPositionRelative(this.nameText, 0, 2);
this.add([this.teraIcon, this.shinyIcon, this.fusionShinyIcon, this.splicedIcon]);
}
/**
* Submethod of the constructor that creates and adds the stats container to the battle info
*/
protected constructStatContainer({ xOffset, paddingX, statOverflow }: BattleInfoParamList["statBox"]): void {
this.statsContainer = globalScene.add.container(0, 0).setName("container_stats").setAlpha(0);
this.add(this.statsContainer);
this.statsBox = globalScene.add
.sprite(0, 0, `${this.getTextureName()}_stats`)
.setName("box_stats")
.setOrigin(1, 0.5);
this.statsContainer.add(this.statsBox);
const statLabels: Phaser.GameObjects.Sprite[] = [];
this.statNumbers = [];
this.statValuesContainer = globalScene.add.container();
this.statsContainer.add(this.statValuesContainer);
const startingX = -this.statsBox.width + xOffset;
// this gives us a different starting location from the left of the label and padding between stats for a player vs enemy
// since the player won't have HP to show, it doesn't need to change from the current version
for (const [i, s] of this.statOrder.entries()) {
const isHp = s === Stat.HP;
// we do a check for i > statOverflow to see when the stat labels go onto the next column
// For enemies, we have HP (i=0) by itself then a new column, so we check for i > 0
// For players, we don't have HP, so we start with i = 0 and i = 1 for our first column, and so need to check for i > 1
const statX =
i > statOverflow
? this.statNumbers[Math.max(i - 2, 0)].x + this.statNumbers[Math.max(i - 2, 0)].width + paddingX
: startingX; // we have the Math.max(i - 2, 0) in there so for i===1 to not return a negative number; since this is now based on anything >0 instead of >1, we need to allow for i-2 < 0
let statY = -this.statsBox.height / 2 + 4; // this is the baseline for the y-axis
if (isHp || s === Stat.SPD) {
statY += 5;
} else if (this.player === !!(i % 2)) {
// we compare i % 2 against this.player to tell us where to place the label
// because this.battleStatOrder for enemies has HP, this.battleStatOrder[1]=ATK, but for players
// this.battleStatOrder[0]=ATK, so this comparing i % 2 to this.player fixes this issue for us
statY += 10;
}
const statLabel = globalScene.add
.sprite(statX, statY, "pbinfo_stat", Stat[s])
.setName("icon_stat_label_" + i.toString())
.setOrigin(0);
statLabels.push(statLabel);
this.statValuesContainer.add(statLabel);
const statNumber = globalScene.add
.sprite(statX + statLabel.width, statY, "pbinfo_stat_numbers", !isHp ? "3" : "empty")
.setName("icon_stat_number_" + i.toString())
.setOrigin(0);
this.statNumbers.push(statNumber);
this.statValuesContainer.add(statNumber);
if (isHp) {
statLabel.setVisible(false);
statNumber.setVisible(false);
}
}
}
/**
* Submethod of the constructor that creates and adds the pokemon type icons to the battle info
*/
protected abstract constructTypeIcons(): void;
/**
* @param x - The x position of the battle info container
* @param y - The y position of the battle info container
* @param player - Whether this battle info belongs to a player or an enemy
* @param posParams - The parameters influencing the position of elements within the battle info container
*/
constructor(x: number, y: number, player: boolean, posParams: BattleInfoParamList) {
super(globalScene, x, y);
this.baseY = y;
this.player = player;
this.mini = !player;
this.boss = false;
this.offset = false;
this.lastName = null;
this.lastTeraType = PokemonType.UNKNOWN;
this.lastStatus = StatusEffect.NONE;
this.lastHp = -1;
this.lastMaxHp = -1;
this.lastHpFrame = null;
this.lastExp = -1;
this.lastLevelExp = -1;
this.lastLevel = -1;
this.baseLvContainerX = posParams.levelContainerX;
// Initially invisible and shown via Pokemon.showInfo
this.setVisible(false);
this.box = globalScene.add.sprite(0, 0, this.getTextureName()).setName("box").setOrigin(1, 0.5);
this.add(this.box);
this.nameText = addTextObject(posParams.nameTextX, posParams.nameTextY, "", TextStyle.BATTLE_INFO)
.setName("text_name")
.setOrigin(0);
this.add(this.nameText);
this.genderText = addTextObject(0, 0, "", TextStyle.BATTLE_INFO)
.setName("text_gender")
.setOrigin(0)
.setPositionRelative(this.nameText, 0, 2);
this.add(this.genderText);
this.constructIcons();
this.statusIndicator = globalScene.add
.sprite(0, 0, getLocalizedSpriteKey("statuses"))
.setName("icon_status")
.setVisible(false)
.setOrigin(0)
.setPositionRelative(this.nameText, 0, 11.5);
this.add(this.statusIndicator);
this.levelContainer = globalScene.add
.container(posParams.levelContainerX, posParams.levelContainerY)
.setName("container_level");
this.add(this.levelContainer);
const levelOverlay = globalScene.add.image(0, 0, "overlay_lv");
this.levelContainer.add(levelOverlay);
this.hpBar = globalScene.add.image(posParams.hpBarX, posParams.hpBarY, "overlay_hp").setName("hp_bar").setOrigin(0);
this.add(this.hpBar);
this.levelNumbersContainer = globalScene.add
.container(9.5, globalScene.uiTheme ? 0 : -0.5)
.setName("container_level");
this.levelContainer.add(this.levelNumbersContainer);
this.constructStatContainer(posParams.statBox);
this.constructTypeIcons();
}
getStatsValueContainer(): Phaser.GameObjects.Container {
return this.statValuesContainer;
}
//#region Initialization methods
initSplicedIcon(pokemon: Pokemon, baseWidth: number) {
this.splicedIcon.setPositionRelative(
this.nameText,
baseWidth + this.genderText.displayWidth + 1 + (this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0),
2.5,
);
this.splicedIcon.setVisible(pokemon.isFusion(true));
if (!this.splicedIcon.visible) {
return;
}
this.splicedIcon
.on("pointerover", () =>
globalScene.ui.showTooltip(
"",
`${pokemon.species.getName(pokemon.formIndex)}/${pokemon.fusionSpecies?.getName(pokemon.fusionFormIndex)}`,
),
)
.on("pointerout", () => globalScene.ui.hideTooltip());
}
/**
* Called by {@linkcode initInfo} to initialize the shiny icon
* @param pokemon - The pokemon object attached to this battle info
* @param baseXOffset - The x offset to use for the shiny icon
* @param doubleShiny - Whether the pokemon is shiny and its fusion species is also shiny
*/
protected initShinyIcon(pokemon: Pokemon, xOffset: number, doubleShiny: boolean) {
const baseVariant = !doubleShiny ? pokemon.getVariant(true) : pokemon.variant;
this.shinyIcon.setPositionRelative(
this.nameText,
xOffset +
this.genderText.displayWidth +
1 +
(this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0) +
(this.splicedIcon.visible ? this.splicedIcon.displayWidth + 1 : 0),
2.5,
);
this.shinyIcon
.setTexture(`shiny_star${doubleShiny ? "_1" : ""}`)
.setVisible(pokemon.isShiny())
.setTint(getVariantTint(baseVariant));
if (!this.shinyIcon.visible) {
return;
}
let shinyDescriptor = "";
if (doubleShiny || baseVariant) {
shinyDescriptor = " (" + getShinyDescriptor(baseVariant);
if (doubleShiny) {
shinyDescriptor += "/" + getShinyDescriptor(pokemon.fusionVariant);
}
shinyDescriptor += ")";
}
this.shinyIcon
.on("pointerover", () => globalScene.ui.showTooltip("", i18next.t("common:shinyOnHover") + shinyDescriptor))
.on("pointerout", () => globalScene.ui.hideTooltip());
}
initInfo(pokemon: Pokemon) {
this.updateNameText(pokemon);
const nameTextWidth = this.nameText.displayWidth;
this.name = pokemon.getNameToRender();
this.box.name = pokemon.getNameToRender();
this.genderText
.setText(getGenderSymbol(pokemon.gender))
.setColor(getGenderColor(pokemon.gender))
.setPositionRelative(this.nameText, nameTextWidth, 0);
this.lastTeraType = pokemon.getTeraType();
this.teraIcon
.setVisible(pokemon.isTerastallized)
.on("pointerover", () => {
if (pokemon.isTerastallized) {
globalScene.ui.showTooltip(
"",
i18next.t("fightUiHandler:teraHover", {
type: i18next.t(`pokemonInfo:Type.${PokemonType[this.lastTeraType]}`),
}),
);
}
})
.on("pointerout", () => globalScene.ui.hideTooltip())
.setPositionRelative(this.nameText, nameTextWidth + this.genderText.displayWidth + 1, 2);
const isFusion = pokemon.isFusion(true);
this.initSplicedIcon(pokemon, nameTextWidth);
const doubleShiny = isFusion && pokemon.shiny && pokemon.fusionShiny;
this.initShinyIcon(pokemon, nameTextWidth, doubleShiny);
this.fusionShinyIcon.setVisible(doubleShiny).copyPosition(this.shinyIcon);
if (isFusion) {
this.fusionShinyIcon.setTint(getVariantTint(pokemon.fusionVariant));
}
this.hpBar.setScale(pokemon.getHpRatio(true), 1);
this.lastHpFrame = this.hpBar.scaleX > 0.5 ? "high" : this.hpBar.scaleX > 0.25 ? "medium" : "low";
this.hpBar.setFrame(this.lastHpFrame);
this.lastHp = pokemon.hp;
this.lastMaxHp = pokemon.getMaxHp();
this.setLevel(pokemon.level);
this.lastLevel = pokemon.level;
this.shinyIcon.setVisible(pokemon.isShiny());
this.setTypes(pokemon.getTypes(true, false, undefined, true));
const stats = this.statOrder.map(() => 0);
this.lastStats = stats.join("");
this.updateStats(stats);
}
//#endregion
/**
* Return the texture name of the battle info box
*/
abstract getTextureName(): string;
setMini(_mini: boolean): void {}
toggleStats(visible: boolean): void {
globalScene.tweens.add({
targets: this.statsContainer,
duration: fixedInt(125),
ease: "Sine.easeInOut",
alpha: visible ? 1 : 0,
});
}
setOffset(offset: boolean): void {
if (this.offset === offset) {
return;
}
this.offset = offset;
this.x += 10 * (this.offset === this.player ? 1 : -1);
this.y += 27 * (this.offset ? 1 : -1);
this.baseY = this.y;
}
//#region Update methods and helpers
/**
* Update the status icon to match the pokemon's current status
* @param pokemon - The pokemon object attached to this battle info
* @param xOffset - The offset from the name text
*/
updateStatusIcon(pokemon: Pokemon, xOffset = 0) {
if (this.lastStatus !== (pokemon.status?.effect || StatusEffect.NONE)) {
this.lastStatus = pokemon.status?.effect || StatusEffect.NONE;
if (this.lastStatus !== StatusEffect.NONE) {
this.statusIndicator.setFrame(StatusEffect[this.lastStatus].toLowerCase());
}
this.statusIndicator.setVisible(!!this.lastStatus).setPositionRelative(this.nameText, xOffset, 11.5);
}
}
/** Update the pokemon name inside the container */
protected updateName(name: string): boolean {
if (this.lastName === name) {
return false;
}
this.nameText.setText(name).setPositionRelative(this.box, -this.nameText.displayWidth, 0);
this.lastName = name;
return true;
}
protected updateTeraType(ty: PokemonType): boolean {
if (this.lastTeraType === ty) {
return false;
}
this.teraIcon
.setVisible(ty !== PokemonType.UNKNOWN)
.setTintFill(Phaser.Display.Color.GetColor(...getTypeRgb(ty)))
.setPositionRelative(this.nameText, this.nameText.displayWidth + this.genderText.displayWidth + 1, 2);
this.lastTeraType = ty;
return true;
}
/**
* Update the type icons to match the pokemon's types
*/
setTypes(types: PokemonType[]): void {
this.type1Icon
.setTexture(`pbinfo_${this.player ? "player" : "enemy"}_type${types.length > 1 ? "1" : ""}`)
.setFrame(PokemonType[types[0]].toLowerCase());
this.type2Icon.setVisible(types.length > 1);
this.type3Icon.setVisible(types.length > 2);
if (types.length > 1) {
this.type2Icon.setFrame(PokemonType[types[1]].toLowerCase());
}
if (types.length > 2) {
this.type3Icon.setFrame(PokemonType[types[2]].toLowerCase());
}
}
/**
* Called by {@linkcode updateInfo} to update the position of the tera, spliced, and shiny icons
* @param isFusion - Whether the pokemon is a fusion or not
*/
protected updateIconDisplay(isFusion: boolean): void {
this.teraIcon.setPositionRelative(this.nameText, this.nameText.displayWidth + this.genderText.displayWidth + 1, 2);
this.splicedIcon
.setVisible(isFusion)
.setPositionRelative(
this.nameText,
this.nameText.displayWidth +
this.genderText.displayWidth +
1 +
(this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0),
1.5,
);
this.shinyIcon.setPositionRelative(
this.nameText,
this.nameText.displayWidth +
this.genderText.displayWidth +
1 +
(this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0) +
(this.splicedIcon.visible ? this.splicedIcon.displayWidth + 1 : 0),
2.5,
);
}
//#region Hp Bar Display handling
/**
* Called every time the hp frame is updated by the tween
* @param pokemon - The pokemon object attached to this battle info
*/
protected updateHpFrame(): void {
const hpFrame = this.hpBar.scaleX > 0.5 ? "high" : this.hpBar.scaleX > 0.25 ? "medium" : "low";
if (hpFrame !== this.lastHpFrame) {
this.hpBar.setFrame(hpFrame);
this.lastHpFrame = hpFrame;
}
}
/**
* Called by every frame in the hp animation tween created in {@linkcode updatePokemonHp}
* @param _pokemon - The pokemon the battle-info bar belongs to
*/
protected onHpTweenUpdate(_pokemon: Pokemon): void {
this.updateHpFrame();
}
/** Update the pokemonHp bar */
protected updatePokemonHp(pokemon: Pokemon, resolve: (r: void | PromiseLike<void>) => void, instant?: boolean): void {
let duration = !instant ? Phaser.Math.Clamp(Math.abs(this.lastHp - pokemon.hp) * 5, 250, 5000) : 0;
const speed = globalScene.hpBarSpeed;
if (speed) {
duration = speed >= 3 ? 0 : duration / Math.pow(2, speed);
}
globalScene.tweens.add({
targets: this.hpBar,
ease: "Sine.easeOut",
scaleX: pokemon.getHpRatio(true),
duration: duration,
onUpdate: () => {
this.onHpTweenUpdate(pokemon);
},
onComplete: () => {
this.updateHpFrame();
resolve();
},
});
this.lastMaxHp = pokemon.getMaxHp();
}
//#endregion
async updateInfo(pokemon: Pokemon, instant?: boolean): Promise<void> {
let resolve: (r: void | PromiseLike<void>) => void = () => {};
const promise = new Promise<void>(r => (resolve = r));
if (!globalScene) {
return resolve();
}
const gender: Gender = pokemon.summonData?.illusion?.gender ?? pokemon.gender;
this.genderText.setText(getGenderSymbol(gender)).setColor(getGenderColor(gender));
const nameUpdated = this.updateName(pokemon.getNameToRender());
const teraTypeUpdated = this.updateTeraType(pokemon.isTerastallized ? pokemon.getTeraType() : PokemonType.UNKNOWN);
const isFusion = pokemon.isFusion(true);
if (nameUpdated || teraTypeUpdated) {
this.updateIconDisplay(isFusion);
}
this.updateStatusIcon(pokemon);
if (this.lastHp !== pokemon.hp || this.lastMaxHp !== pokemon.getMaxHp()) {
return this.updatePokemonHp(pokemon, resolve, instant);
}
if (!this.player && this.lastLevel !== pokemon.level) {
this.setLevel(pokemon.level);
this.lastLevel = pokemon.level;
}
const stats = pokemon.getStatStages();
const statsStr = stats.join("");
if (this.lastStats !== statsStr) {
this.updateStats(stats);
this.lastStats = statsStr;
}
this.shinyIcon.setVisible(pokemon.isShiny(true));
const doubleShiny = isFusion && pokemon.shiny && pokemon.fusionShiny;
const baseVariant = !doubleShiny ? pokemon.getVariant(true) : pokemon.variant;
this.shinyIcon.setTint(getVariantTint(baseVariant));
this.fusionShinyIcon.setVisible(doubleShiny).setPosition(this.shinyIcon.x, this.shinyIcon.y);
if (isFusion) {
this.fusionShinyIcon.setTint(getVariantTint(pokemon.fusionVariant));
}
resolve();
await promise;
}
//#endregion
updateNameText(pokemon: Pokemon): void {
let displayName = pokemon.getNameToRender().replace(/[♂♀]/g, "");
let nameTextWidth: number;
const nameSizeTest = addTextObject(0, 0, displayName, TextStyle.BATTLE_INFO);
nameTextWidth = nameSizeTest.displayWidth;
const gender = pokemon.summonData.illusion?.gender ?? pokemon.gender;
while (
nameTextWidth >
(this.player || !this.boss ? 60 : 98) -
((gender !== Gender.GENDERLESS ? 6 : 0) +
(pokemon.fusionSpecies ? 8 : 0) +
(pokemon.isShiny() ? 8 : 0) +
(Math.min(pokemon.level.toString().length, 3) - 3) * 8)
) {
displayName = `${displayName.slice(0, displayName.endsWith(".") ? -2 : -1).trimEnd()}.`;
nameSizeTest.setText(displayName);
nameTextWidth = nameSizeTest.displayWidth;
}
nameSizeTest.destroy();
this.nameText.setText(displayName);
this.lastName = pokemon.getNameToRender();
if (this.nameText.visible) {
this.nameText.setInteractive(
new Phaser.Geom.Rectangle(0, 0, this.nameText.width, this.nameText.height),
Phaser.Geom.Rectangle.Contains,
);
}
}
/**
* Set the level numbers container to display the provided level
*
* @remarks
* The numbers in the pokemon's level uses images for each number rather than a text object with a special font.
* This method sets the images for each digit of the level number and then positions the level container based
* on the number of digits.
*
* @param level - The level to display
* @param textureKey - The texture key for the level numbers
*/
setLevel(level: number, textureKey: "numbers" | "numbers_red" = "numbers"): void {
this.levelNumbersContainer.removeAll(true);
const levelStr = level.toString();
for (let i = 0; i < levelStr.length; i++) {
this.levelNumbersContainer.add(globalScene.add.image(i * 8, 0, textureKey, levelStr[i]));
}
this.levelContainer.setX(this.baseLvContainerX - 8 * Math.max(levelStr.length - 3, 0));
}
updateStats(stats: number[]): void {
for (const [i, s] of this.statOrder.entries()) {
if (s !== Stat.HP) {
this.statNumbers[i].setFrame(stats[s - 1].toString());
}
}
}
getBaseY(): number {
return this.baseY;
}
resetY(): void {
this.y = this.baseY;
}
}

View File

@ -0,0 +1,235 @@
import { globalScene } from "#app/global-scene";
import BattleFlyout from "../battle-flyout";
import { addTextObject, TextStyle } from "#app/ui/text";
import { addWindow, WindowVariant } from "#app/ui/ui-theme";
import { Stat } from "#enums/stat";
import i18next from "i18next";
import type { EnemyPokemon } from "#app/field/pokemon";
import type { GameObjects } from "phaser";
import BattleInfo from "./battle-info";
import type { BattleInfoParamList } from "./battle-info";
export class EnemyBattleInfo extends BattleInfo {
protected player: false = false;
protected championRibbon: Phaser.GameObjects.Sprite;
protected ownedIcon: Phaser.GameObjects.Sprite;
protected flyoutMenu: BattleFlyout;
protected hpBarSegmentDividers: GameObjects.Rectangle[] = [];
// #region Type effectiveness hint objects
protected effectivenessContainer: Phaser.GameObjects.Container;
protected effectivenessWindow: Phaser.GameObjects.NineSlice;
protected effectivenessText: Phaser.GameObjects.Text;
protected currentEffectiveness?: string;
// #endregion
override get statOrder(): Stat[] {
return [Stat.HP, Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.ACC, Stat.EVA, Stat.SPD];
}
override getTextureName(): string {
return this.boss ? "pbinfo_enemy_boss" : "pbinfo_enemy_mini";
}
override constructTypeIcons(): void {
this.type1Icon = globalScene.add.sprite(-15, -15.5, "pbinfo_enemy_type1").setName("icon_type_1").setOrigin(0);
this.type2Icon = globalScene.add.sprite(-15, -2.5, "pbinfo_enemy_type2").setName("icon_type_2").setOrigin(0);
this.type3Icon = globalScene.add.sprite(0, 15.5, "pbinfo_enemy_type3").setName("icon_type_3").setOrigin(0);
this.add([this.type1Icon, this.type2Icon, this.type3Icon]);
}
constructor() {
const posParams: BattleInfoParamList = {
nameTextX: -124,
nameTextY: -11.2,
levelContainerX: -50,
levelContainerY: -5,
hpBarX: -71,
hpBarY: 4.5,
statBox: {
xOffset: 5,
paddingX: 2,
statOverflow: 0,
},
};
super(140, -141, false, posParams);
this.ownedIcon = globalScene.add
.sprite(0, 0, "icon_owned")
.setName("icon_owned")
.setVisible(false)
.setOrigin(0, 0)
.setPositionRelative(this.nameText, 0, 11.75);
this.championRibbon = globalScene.add
.sprite(0, 0, "champion_ribbon")
.setName("icon_champion_ribbon")
.setVisible(false)
.setOrigin(0, 0)
.setPositionRelative(this.nameText, 8, 11.75);
// Ensure these two icons are positioned below the stats container
this.addAt([this.ownedIcon, this.championRibbon], this.getIndex(this.statsContainer));
this.flyoutMenu = new BattleFlyout(this.player);
this.add(this.flyoutMenu);
this.moveBelow<Phaser.GameObjects.GameObject>(this.flyoutMenu, this.box);
this.effectivenessContainer = globalScene.add
.container(0, 0)
.setVisible(false)
.setPositionRelative(this.type1Icon, 22, 4);
this.add(this.effectivenessContainer);
this.effectivenessText = addTextObject(5, 4.5, "", TextStyle.BATTLE_INFO);
this.effectivenessWindow = addWindow(0, 0, 0, 20, undefined, false, undefined, undefined, WindowVariant.XTHIN);
this.effectivenessContainer.add([this.effectivenessWindow, this.effectivenessText]);
}
override initInfo(pokemon: EnemyPokemon): void {
this.flyoutMenu.initInfo(pokemon);
super.initInfo(pokemon);
if (this.nameText.visible) {
this.nameText
.on("pointerover", () =>
globalScene.ui.showTooltip(
"",
i18next.t("battleInfo:generation", {
generation: i18next.t(`starterSelectUiHandler:gen${pokemon.species.generation}`),
}),
),
)
.on("pointerout", () => globalScene.ui.hideTooltip());
}
const dexEntry = globalScene.gameData.dexData[pokemon.species.speciesId];
this.ownedIcon.setVisible(!!dexEntry.caughtAttr);
const opponentPokemonDexAttr = pokemon.getDexAttr();
if (
globalScene.gameMode.isClassic &&
globalScene.gameData.starterData[pokemon.species.getRootSpeciesId()].classicWinCount > 0 &&
globalScene.gameData.starterData[pokemon.species.getRootSpeciesId(true)].classicWinCount > 0
) {
this.championRibbon.setVisible(true);
}
// Check if Player owns all genders and forms of the Pokemon
const missingDexAttrs = (dexEntry.caughtAttr & opponentPokemonDexAttr) < opponentPokemonDexAttr;
const ownedAbilityAttrs = globalScene.gameData.starterData[pokemon.species.getRootSpeciesId()].abilityAttr;
// Check if the player owns ability for the root form
const playerOwnsThisAbility = pokemon.checkIfPlayerHasAbilityOfStarter(ownedAbilityAttrs);
if (missingDexAttrs || !playerOwnsThisAbility) {
this.ownedIcon.setTint(0x808080);
}
if (this.boss) {
this.updateBossSegmentDividers(pokemon as EnemyPokemon);
}
}
/**
* Show or hide the type effectiveness multiplier window
* Passing undefined will hide the window
*/
updateEffectiveness(effectiveness?: string) {
this.currentEffectiveness = effectiveness;
if (!globalScene.typeHints || effectiveness === undefined || this.flyoutMenu.flyoutVisible) {
this.effectivenessContainer.setVisible(false);
return;
}
this.effectivenessText.setText(effectiveness);
this.effectivenessWindow.width = 10 + this.effectivenessText.displayWidth;
this.effectivenessContainer.setVisible(true);
}
/**
* Request the flyoutMenu to toggle if available and hides or shows the effectiveness window where necessary
*/
toggleFlyout(visible: boolean): void {
this.flyoutMenu.toggleFlyout(visible);
if (visible) {
this.effectivenessContainer.setVisible(false);
} else {
this.updateEffectiveness(this.currentEffectiveness);
}
}
updateBossSegments(pokemon: EnemyPokemon): void {
const boss = !!pokemon.bossSegments;
if (boss !== this.boss) {
this.boss = boss;
[
this.nameText,
this.genderText,
this.teraIcon,
this.splicedIcon,
this.shinyIcon,
this.ownedIcon,
this.championRibbon,
this.statusIndicator,
this.levelContainer,
this.statValuesContainer,
].map(e => (e.x += 48 * (boss ? -1 : 1)));
this.hpBar.x += 38 * (boss ? -1 : 1);
this.hpBar.y += 2 * (this.boss ? -1 : 1);
this.hpBar.setTexture(`overlay_hp${boss ? "_boss" : ""}`);
this.box.setTexture(this.getTextureName());
this.statsBox.setTexture(`${this.getTextureName()}_stats`);
}
this.bossSegments = boss ? pokemon.bossSegments : 0;
this.updateBossSegmentDividers(pokemon);
}
updateBossSegmentDividers(pokemon: EnemyPokemon): void {
while (this.hpBarSegmentDividers.length) {
this.hpBarSegmentDividers.pop()?.destroy();
}
if (this.boss && this.bossSegments > 1) {
const uiTheme = globalScene.uiTheme;
const maxHp = pokemon.getMaxHp();
for (let s = 1; s < this.bossSegments; s++) {
const dividerX = (Math.round((maxHp / this.bossSegments) * s) / maxHp) * this.hpBar.width;
const divider = globalScene.add.rectangle(
0,
0,
1,
this.hpBar.height - (uiTheme ? 0 : 1),
pokemon.bossSegmentIndex >= s ? 0xffffff : 0x404040,
);
divider.setOrigin(0.5, 0).setName("hpBar_divider_" + s.toString());
this.add(divider);
this.moveBelow(divider as Phaser.GameObjects.GameObject, this.statsContainer);
divider.setPositionRelative(this.hpBar, dividerX, uiTheme ? 0 : 1);
this.hpBarSegmentDividers.push(divider);
}
}
}
override updateStatusIcon(pokemon: EnemyPokemon): void {
super.updateStatusIcon(pokemon, (this.ownedIcon.visible ? 8 : 0) + (this.championRibbon.visible ? 8 : 0));
}
protected override updatePokemonHp(
pokemon: EnemyPokemon,
resolve: (r: void | PromiseLike<void>) => void,
instant?: boolean,
): void {
super.updatePokemonHp(pokemon, resolve, instant);
this.lastHp = pokemon.hp;
}
}

View File

@ -0,0 +1,242 @@
import { getLevelRelExp, getLevelTotalExp } from "#app/data/exp";
import type { PlayerPokemon } from "#app/field/pokemon";
import { globalScene } from "#app/global-scene";
import { ExpGainsSpeed } from "#enums/exp-gains-speed";
import { Stat } from "#enums/stat";
import BattleInfo from "./battle-info";
import type { BattleInfoParamList } from "./battle-info";
export class PlayerBattleInfo extends BattleInfo {
protected player: true = true;
protected hpNumbersContainer: Phaser.GameObjects.Container;
override get statOrder(): Stat[] {
return [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.ACC, Stat.EVA, Stat.SPD];
}
override getTextureName(): string {
return this.mini ? "pbinfo_player_mini" : "pbinfo_player";
}
override constructTypeIcons(): void {
this.type1Icon = globalScene.add.sprite(-139, -17, "pbinfo_player_type1").setName("icon_type_1").setOrigin(0);
this.type2Icon = globalScene.add.sprite(-139, -1, "pbinfo_player_type2").setName("icon_type_2").setOrigin(0);
this.type3Icon = globalScene.add.sprite(-154, -17, "pbinfo_player_type3").setName("icon_type_3").setOrigin(0);
this.add([this.type1Icon, this.type2Icon, this.type3Icon]);
}
constructor() {
const posParams: BattleInfoParamList = {
nameTextX: -115,
nameTextY: -15.2,
levelContainerX: -41,
levelContainerY: -10,
hpBarX: -61,
hpBarY: -1,
statBox: {
xOffset: 8,
paddingX: 4,
statOverflow: 1,
},
};
super(Math.floor(globalScene.game.canvas.width / 6) - 10, -72, true, posParams);
this.hpNumbersContainer = globalScene.add.container(-15, 10).setName("container_hp");
// hp number container must be beneath the stat container for overlay to display properly
this.addAt(this.hpNumbersContainer, this.getIndex(this.statsContainer));
const expBar = globalScene.add.image(-98, 18, "overlay_exp").setName("overlay_exp").setOrigin(0);
this.add(expBar);
const expMaskRect = globalScene.make
.graphics({})
.setScale(6)
.fillStyle(0xffffff)
.beginPath()
.fillRect(127, 126, 85, 2);
const expMask = expMaskRect.createGeometryMask();
expBar.setMask(expMask);
this.expBar = expBar;
this.expMaskRect = expMaskRect;
}
override initInfo(pokemon: PlayerPokemon): void {
super.initInfo(pokemon);
this.setHpNumbers(pokemon.hp, pokemon.getMaxHp());
this.expMaskRect.x = (pokemon.levelExp / getLevelTotalExp(pokemon.level, pokemon.species.growthRate)) * 510;
this.lastExp = pokemon.exp;
this.lastLevelExp = pokemon.levelExp;
this.statValuesContainer.setPosition(8, 7);
}
override setMini(mini: boolean): void {
if (this.mini === mini) {
return;
}
this.mini = mini;
this.box.setTexture(this.getTextureName());
this.statsBox.setTexture(`${this.getTextureName()}_stats`);
if (this.player) {
this.y -= 12 * (mini ? 1 : -1);
this.baseY = this.y;
}
const offsetElements = [
this.nameText,
this.genderText,
this.teraIcon,
this.splicedIcon,
this.shinyIcon,
this.statusIndicator,
this.levelContainer,
];
offsetElements.forEach(el => (el.y += 1.5 * (mini ? -1 : 1)));
[this.type1Icon, this.type2Icon, this.type3Icon].forEach(el => {
el.x += 4 * (mini ? 1 : -1);
el.y += -8 * (mini ? 1 : -1);
});
this.statValuesContainer.x += 2 * (mini ? 1 : -1);
this.statValuesContainer.y += -7 * (mini ? 1 : -1);
const toggledElements = [this.hpNumbersContainer, this.expBar];
toggledElements.forEach(el => el.setVisible(!mini));
}
/**
* Updates the Hp Number text (that is the "HP/Max HP" text that appears below the player's health bar)
* while the health bar is tweening.
* @param pokemon - The Pokemon the health bar belongs to.
*/
protected override onHpTweenUpdate(pokemon: PlayerPokemon): void {
const tweenHp = Math.ceil(this.hpBar.scaleX * pokemon.getMaxHp());
this.setHpNumbers(tweenHp, pokemon.getMaxHp());
this.lastHp = tweenHp;
this.updateHpFrame();
}
updatePokemonExp(pokemon: PlayerPokemon, instant?: boolean, levelDurationMultiplier = 1): Promise<void> {
const levelUp = this.lastLevel < pokemon.level;
const relLevelExp = getLevelRelExp(this.lastLevel + 1, pokemon.species.growthRate);
const levelExp = levelUp ? relLevelExp : pokemon.levelExp;
let ratio = relLevelExp ? levelExp / relLevelExp : 0;
if (this.lastLevel >= globalScene.getMaxExpLevel(true)) {
ratio = levelUp ? 1 : 0;
instant = true;
}
const durationMultiplier = Phaser.Tweens.Builders.GetEaseFunction("Sine.easeIn")(
1 - Math.max(this.lastLevel - 100, 0) / 150,
);
let duration =
this.visible && !instant
? ((levelExp - this.lastLevelExp) / relLevelExp) *
BattleInfo.EXP_GAINS_DURATION_BASE *
durationMultiplier *
levelDurationMultiplier
: 0;
const speed = globalScene.expGainsSpeed;
if (speed && speed >= ExpGainsSpeed.DEFAULT) {
duration = speed >= ExpGainsSpeed.SKIP ? ExpGainsSpeed.DEFAULT : duration / Math.pow(2, speed);
}
if (ratio === 1) {
this.lastLevelExp = 0;
this.lastLevel++;
} else {
this.lastExp = pokemon.exp;
this.lastLevelExp = pokemon.levelExp;
}
if (duration) {
globalScene.playSound("se/exp");
}
return new Promise(resolve => {
globalScene.tweens.add({
targets: this.expMaskRect,
ease: "Sine.easeIn",
x: ratio * 510,
duration: duration,
onComplete: () => {
if (!globalScene) {
return resolve();
}
if (duration) {
globalScene.sound.stopByKey("se/exp");
}
if (ratio === 1) {
globalScene.playSound("se/level_up");
this.setLevel(this.lastLevel);
globalScene.time.delayedCall(500 * levelDurationMultiplier, () => {
this.expMaskRect.x = 0;
this.updateInfo(pokemon, instant).then(() => resolve());
});
return;
}
resolve();
},
});
});
}
/**
* Updates the info on the info bar.
*
* In addition to performing all the steps of {@linkcode BattleInfo.updateInfo},
* it also updates the EXP Bar
*/
override async updateInfo(pokemon: PlayerPokemon, instant?: boolean): Promise<void> {
await super.updateInfo(pokemon, instant);
const isLevelCapped = pokemon.level >= globalScene.getMaxExpLevel();
const oldLevelCapped = this.lastLevelCapped;
this.lastLevelCapped = isLevelCapped;
if (this.lastExp !== pokemon.exp || this.lastLevel !== pokemon.level) {
const durationMultipler = Math.max(
Phaser.Tweens.Builders.GetEaseFunction("Cubic.easeIn")(1 - Math.min(pokemon.level - this.lastLevel, 10) / 10),
0.1,
);
await this.updatePokemonExp(pokemon, false, durationMultipler);
} else if (isLevelCapped !== oldLevelCapped) {
this.setLevel(pokemon.level);
}
}
/**
* Set the HP numbers text, that is the "HP/Max HP" text that appears below the player's health bar.
* @param hp - The current HP of the player.
* @param maxHp - The maximum HP of the player.
*/
setHpNumbers(hp: number, maxHp: number): void {
if (!globalScene) {
return;
}
this.hpNumbersContainer.removeAll(true);
const hpStr = hp.toString();
const maxHpStr = maxHp.toString();
let offset = 0;
for (let i = maxHpStr.length - 1; i >= 0; i--) {
this.hpNumbersContainer.add(globalScene.add.image(offset++ * -8, 0, "numbers", maxHpStr[i]));
}
this.hpNumbersContainer.add(globalScene.add.image(offset++ * -8, 0, "numbers", "/"));
for (let i = hpStr.length - 1; i >= 0; i--) {
this.hpNumbersContainer.add(globalScene.add.image(offset++ * -8, 0, "numbers", hpStr[i]));
}
}
/**
* Set the level numbers container to display the provided level
*
* Overrides the default implementation to handle displaying level capped numbers in red.
* @param level - The level to display
*/
override setLevel(level: number): void {
super.setLevel(level, level >= globalScene.getMaxExpLevel() ? "numbers_red" : "numbers");
}
}

View File

@ -43,14 +43,13 @@ export default class EggCounterContainer extends Phaser.GameObjects.Container {
this.add(this.eggCountWindow); this.add(this.eggCountWindow);
const eggSprite = globalScene.add.sprite(19, 18, "egg", "egg_0"); const eggSprite = globalScene.add.sprite(19, 18, "egg", "egg_0").setScale(0.32);
eggSprite.setScale(0.32);
this.eggCountText = addTextObject(28, 13, `${this.eggCount}`, TextStyle.MESSAGE, { fontSize: "66px" }); this.eggCountText = addTextObject(28, 13, `${this.eggCount}`, TextStyle.MESSAGE, { fontSize: "66px" }).setName(
this.eggCountText.setName("text-egg-count"); "text-egg-count",
);
this.add(eggSprite); this.add([eggSprite, this.eggCountText]);
this.add(this.eggCountText);
} }
/** /**

View File

@ -22,18 +22,12 @@ export default class EvolutionSceneHandler extends MessageUiHandler {
const ui = this.getUi(); const ui = this.getUi();
this.evolutionContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6); this.evolutionContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6);
ui.add(this.evolutionContainer);
const messageBg = globalScene.add.sprite(0, 0, "bg", globalScene.windowType); const messageBg = globalScene.add.sprite(0, 0, "bg", globalScene.windowType).setOrigin(0, 1).setVisible(false);
messageBg.setOrigin(0, 1);
messageBg.setVisible(false);
ui.add(messageBg);
this.messageBg = messageBg; this.messageBg = messageBg;
this.messageContainer = globalScene.add.container(12, -39); this.messageContainer = globalScene.add.container(12, -39).setVisible(false);
this.messageContainer.setVisible(false);
ui.add(this.messageContainer);
const message = addTextObject(0, 0, "", TextStyle.MESSAGE, { const message = addTextObject(0, 0, "", TextStyle.MESSAGE, {
maxLines: 2, maxLines: 2,
@ -43,6 +37,8 @@ export default class EvolutionSceneHandler extends MessageUiHandler {
}); });
this.messageContainer.add(message); this.messageContainer.add(message);
ui.add([this.evolutionContainer, this.messageBg, this.messageContainer]);
this.message = message; this.message = message;
this.initPromptSprite(this.messageContainer); this.initPromptSprite(this.messageContainer);
@ -52,10 +48,8 @@ export default class EvolutionSceneHandler extends MessageUiHandler {
super.show(_args); super.show(_args);
globalScene.ui.bringToTop(this.evolutionContainer); globalScene.ui.bringToTop(this.evolutionContainer);
globalScene.ui.bringToTop(this.messageBg); globalScene.ui.bringToTop(this.messageBg.setVisible(true));
globalScene.ui.bringToTop(this.messageContainer); globalScene.ui.bringToTop(this.messageContainer.setVisible(true));
this.messageBg.setVisible(true);
this.messageContainer.setVisible(true);
return true; return true;
} }

View File

@ -10,7 +10,7 @@ import { getLocalizedSpriteKey, fixedInt, padInt } from "#app/utils/common";
import { MoveCategory } from "#enums/MoveCategory"; import { MoveCategory } from "#enums/MoveCategory";
import i18next from "i18next"; import i18next from "i18next";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import type { PokemonMove } from "#app/field/pokemon"; import type { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import type { CommandPhase } from "#app/phases/command-phase"; import type { CommandPhase } from "#app/phases/command-phase";
import MoveInfoOverlay from "./move-info-overlay"; import MoveInfoOverlay from "./move-info-overlay";
@ -279,7 +279,7 @@ export default class FightUiHandler extends UiHandler implements InfoToggle {
this.moveInfoOverlay.show(pokemonMove.getMove()); this.moveInfoOverlay.show(pokemonMove.getMove());
pokemon.getOpponents().forEach(opponent => { pokemon.getOpponents().forEach(opponent => {
opponent.updateEffectiveness(this.getEffectivenessText(pokemon, opponent, pokemonMove)); (opponent as EnemyPokemon).updateEffectiveness(this.getEffectivenessText(pokemon, opponent, pokemonMove));
}); });
} }
@ -391,7 +391,7 @@ export default class FightUiHandler extends UiHandler implements InfoToggle {
const opponents = (globalScene.getCurrentPhase() as CommandPhase).getPokemon().getOpponents(); const opponents = (globalScene.getCurrentPhase() as CommandPhase).getPokemon().getOpponents();
opponents.forEach(opponent => { opponents.forEach(opponent => {
opponent.updateEffectiveness(undefined); (opponent as EnemyPokemon).updateEffectiveness();
}); });
} }

View File

@ -5,16 +5,7 @@ import { addTextObject, getTextColor, TextStyle } from "./text";
import type { UiTheme } from "#enums/ui-theme"; import type { UiTheme } from "#enums/ui-theme";
import { addWindow, WindowVariant } from "./ui-theme"; import { addWindow, WindowVariant } from "./ui-theme";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import type { DropDownColumn } from "#enums/drop-down-column";
export enum DropDownColumn {
GEN,
TYPES,
BIOME,
CAUGHT,
UNLOCKS,
MISC,
SORT,
}
export class FilterBar extends Phaser.GameObjects.Container { export class FilterBar extends Phaser.GameObjects.Container {
private window: Phaser.GameObjects.NineSlice; private window: Phaser.GameObjects.NineSlice;
@ -49,13 +40,9 @@ export class FilterBar extends Phaser.GameObjects.Container {
this.cursorOffset = cursorOffset; this.cursorOffset = cursorOffset;
this.window = addWindow(0, 0, width, height, false, false, undefined, undefined, WindowVariant.THIN); this.window = addWindow(0, 0, width, height, false, false, undefined, undefined, WindowVariant.THIN);
this.add(this.window);
this.cursorObj = globalScene.add.image(1, 1, "cursor"); this.cursorObj = globalScene.add.image(1, 1, "cursor").setScale(0.5).setVisible(false).setOrigin(0);
this.cursorObj.setScale(0.5); this.add([this.window, this.cursorObj]);
this.cursorObj.setVisible(false);
this.cursorObj.setOrigin(0, 0);
this.add(this.cursorObj);
} }
/** /**

View File

@ -23,7 +23,8 @@ import type { Species } from "#enums/species";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "#app/ui/dropdown"; import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "#app/ui/dropdown";
import { PokedexMonContainer } from "#app/ui/pokedex-mon-container"; import { PokedexMonContainer } from "#app/ui/pokedex-mon-container";
import { DropDownColumn, FilterBar } from "#app/ui/filter-bar"; import { FilterBar } from "#app/ui/filter-bar";
import { DropDownColumn } from "#enums/drop-down-column";
import { ScrollBar } from "#app/ui/scroll-bar"; import { ScrollBar } from "#app/ui/scroll-bar";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { import {

View File

@ -8,7 +8,7 @@ import type Pokemon from "../field/pokemon";
import i18next from "i18next"; import i18next from "i18next";
import type { DexEntry, StarterDataEntry } from "../system/game-data"; import type { DexEntry, StarterDataEntry } from "../system/game-data";
import { DexAttr } from "../system/game-data"; import { DexAttr } from "../system/game-data";
import { fixedInt } from "#app/utils/common"; import { fixedInt, getShinyDescriptor } from "#app/utils/common";
import ConfirmUiHandler from "./confirm-ui-handler"; import ConfirmUiHandler from "./confirm-ui-handler";
import { StatsContainer } from "./stats-container"; import { StatsContainer } from "./stats-container";
import { TextStyle, addBBCodeTextObject, addTextObject, getTextColor } from "./text"; import { TextStyle, addBBCodeTextObject, addTextObject, getTextColor } from "./text";
@ -343,18 +343,19 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
this.pokemonShinyIcon.setVisible(pokemon.isShiny()); this.pokemonShinyIcon.setVisible(pokemon.isShiny());
this.pokemonShinyIcon.setTint(getVariantTint(baseVariant)); this.pokemonShinyIcon.setTint(getVariantTint(baseVariant));
if (this.pokemonShinyIcon.visible) { if (this.pokemonShinyIcon.visible) {
const shinyDescriptor = let shinyDescriptor = "";
doubleShiny || baseVariant if (doubleShiny || baseVariant) {
? `${baseVariant === 2 ? i18next.t("common:epicShiny") : baseVariant === 1 ? i18next.t("common:rareShiny") : i18next.t("common:commonShiny")}${doubleShiny ? `/${pokemon.fusionVariant === 2 ? i18next.t("common:epicShiny") : pokemon.fusionVariant === 1 ? i18next.t("common:rareShiny") : i18next.t("common:commonShiny")}` : ""}` shinyDescriptor = " (" + getShinyDescriptor(baseVariant);
: ""; if (doubleShiny) {
this.pokemonShinyIcon.on("pointerover", () => shinyDescriptor += "/" + getShinyDescriptor(pokemon.fusionVariant);
globalScene.ui.showTooltip( }
"", shinyDescriptor += ")";
`${i18next.t("common:shinyOnHover")}${shinyDescriptor ? ` (${shinyDescriptor})` : ""}`, }
true, this.pokemonShinyIcon
), .on("pointerover", () =>
); globalScene.ui.showTooltip("", i18next.t("common:shinyOnHover") + shinyDescriptor, true),
this.pokemonShinyIcon.on("pointerout", () => globalScene.ui.hideTooltip()); )
.on("pointerout", () => globalScene.ui.hideTooltip());
const newShiny = BigInt(1 << (pokemon.shiny ? 1 : 0)); const newShiny = BigInt(1 << (pokemon.shiny ? 1 : 0));
const newVariant = BigInt(1 << (pokemon.variant + 4)); const newVariant = BigInt(1 << (pokemon.variant + 4));

View File

@ -39,12 +39,6 @@ export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler
label: "Español (LATAM)", label: "Español (LATAM)",
}; };
break; break;
case "it":
this.settings[languageIndex].options[0] = {
value: "Italiano",
label: "Italiano",
};
break;
case "fr": case "fr":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "Français", value: "Français",
@ -57,24 +51,18 @@ export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler
label: "Deutsch", label: "Deutsch",
}; };
break; break;
case "it":
this.settings[languageIndex].options[0] = {
value: "Italiano",
label: "Italiano",
};
break;
case "pt-BR": case "pt-BR":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "Português (BR)", value: "Português (BR)",
label: "Português (BR)", label: "Português (BR)",
}; };
break; break;
case "zh-CN":
this.settings[languageIndex].options[0] = {
value: "简体中文",
label: "简体中文",
};
break;
case "zh-TW":
this.settings[languageIndex].options[0] = {
value: "繁體中文",
label: "繁體中文",
};
break;
case "ko": case "ko":
case "ko-KR": case "ko-KR":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
@ -88,10 +76,46 @@ export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler
label: "日本語", label: "日本語",
}; };
break; break;
case "ca-ES": case "zh-CN":
this.settings[languageIndex].options[0] = {
value: "简体中文",
label: "简体中文",
};
break;
case "zh-TW":
this.settings[languageIndex].options[0] = {
value: "繁體中文",
label: "繁體中文",
};
break;
case "ca":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "Català", value: "Català",
label: "Català", label: "Català (Needs Help)",
};
break;
case "tr":
this.settings[languageIndex].options[0] = {
value: "Türkçe",
label: "Türkçe (Needs Help)",
};
break;
case "ru":
this.settings[languageIndex].options[0] = {
value: "Русский",
label: "Русский (Needs Help)",
};
break;
case "da":
this.settings[languageIndex].options[0] = {
value: "Dansk",
label: "Dansk (Needs Help)",
};
break;
case "ro":
this.settings[languageIndex].options[0] = {
value: "Română",
label: "Română (Needs Help)",
}; };
break; break;
case "he": case "he":

View File

@ -53,7 +53,8 @@ import { Button } from "#enums/buttons";
import { EggSourceType } from "#enums/egg-source-types"; import { EggSourceType } from "#enums/egg-source-types";
import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "#app/ui/dropdown"; import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "#app/ui/dropdown";
import { StarterContainer } from "#app/ui/starter-container"; import { StarterContainer } from "#app/ui/starter-container";
import { DropDownColumn, FilterBar } from "#app/ui/filter-bar"; import { FilterBar } from "#app/ui/filter-bar";
import { DropDownColumn } from "#enums/drop-down-column";
import { ScrollBar } from "#app/ui/scroll-bar"; import { ScrollBar } from "#app/ui/scroll-bar";
import { SelectChallengePhase } from "#app/phases/select-challenge-phase"; import { SelectChallengePhase } from "#app/phases/select-challenge-phase";
import { EncounterPhase } from "#app/phases/encounter-phase"; import { EncounterPhase } from "#app/phases/encounter-phase";
@ -161,7 +162,25 @@ const languageSettings: { [key: string]: LanguageSetting } = {
starterInfoYOffset: 0.5, starterInfoYOffset: 0.5,
starterInfoXPos: 29, starterInfoXPos: 29,
}, },
"he":{ da:{
starterInfoTextSize: "56px",
instructionTextSize: "38px",
},
tr:{
starterInfoTextSize: "56px",
instructionTextSize: "38px",
},
ro:{
starterInfoTextSize: "56px",
instructionTextSize: "38px",
},
ru: {
starterInfoTextSize: "46px",
instructionTextSize: "38px",
starterInfoYOffset: 0.5,
starterInfoXPos: 26,
},
he:{
starterInfoTextSize: "56px", starterInfoTextSize: "56px",
instructionTextSize: "38px", instructionTextSize: "38px",
}, },

View File

@ -11,6 +11,7 @@ import {
isNullOrUndefined, isNullOrUndefined,
toReadableString, toReadableString,
formatStat, formatStat,
getShinyDescriptor,
} from "#app/utils/common"; } from "#app/utils/common";
import type { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import type { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters"; import { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters";
@ -444,18 +445,19 @@ export default class SummaryUiHandler extends UiHandler {
this.shinyIcon.setVisible(this.pokemon.isShiny(false)); this.shinyIcon.setVisible(this.pokemon.isShiny(false));
this.shinyIcon.setTint(getVariantTint(baseVariant)); this.shinyIcon.setTint(getVariantTint(baseVariant));
if (this.shinyIcon.visible) { if (this.shinyIcon.visible) {
const shinyDescriptor = let shinyDescriptor = "";
doubleShiny || baseVariant if (doubleShiny || baseVariant) {
? `${baseVariant === 2 ? i18next.t("common:epicShiny") : baseVariant === 1 ? i18next.t("common:rareShiny") : i18next.t("common:commonShiny")}${doubleShiny ? `/${this.pokemon.fusionVariant === 2 ? i18next.t("common:epicShiny") : this.pokemon.fusionVariant === 1 ? i18next.t("common:rareShiny") : i18next.t("common:commonShiny")}` : ""}` shinyDescriptor = " (" + getShinyDescriptor(baseVariant);
: ""; if (doubleShiny) {
this.shinyIcon.on("pointerover", () => shinyDescriptor += "/" + getShinyDescriptor(this.pokemon.fusionVariant);
globalScene.ui.showTooltip( }
"", shinyDescriptor += ")";
`${i18next.t("common:shinyOnHover")}${shinyDescriptor ? ` (${shinyDescriptor})` : ""}`, }
true, this.shinyIcon
), .on("pointerover", () =>
); globalScene.ui.showTooltip("", i18next.t("common:shinyOnHover") + shinyDescriptor, true),
this.shinyIcon.on("pointerout", () => globalScene.ui.hideTooltip()); )
.on("pointerout", () => globalScene.ui.hideTooltip());
} }
this.fusionShinyIcon.setPosition(this.shinyIcon.x, this.shinyIcon.y); this.fusionShinyIcon.setPosition(this.shinyIcon.x, this.shinyIcon.y);

View File

@ -2,6 +2,7 @@ import { MoneyFormat } from "#enums/money-format";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import i18next from "i18next"; import i18next from "i18next";
import { pokerogueApi } from "#app/plugins/api/pokerogue-api"; import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
import type { Variant } from "#app/sprites/variant";
export type nil = null | undefined; export type nil = null | undefined;
@ -434,15 +435,19 @@ export function hasAllLocalizedSprites(lang?: string): boolean {
case "es-ES": case "es-ES":
case "es-MX": case "es-MX":
case "fr": case "fr":
case "da":
case "de": case "de":
case "he": case "he":
case "it": case "it":
case "zh-CN": case "zh-CN":
case "zh-TW": case "zh-TW":
case "pt-BR": case "pt-BR":
case "ro":
case "tr":
case "ko": case "ko":
case "ja": case "ja":
case "ca-ES": case "ca":
case "ru":
return true; return true;
default: default:
return false; return false;
@ -577,3 +582,18 @@ export function animationFileName(move: Moves): string {
export function camelCaseToKebabCase(str: string): string { export function camelCaseToKebabCase(str: string): string {
return str.replace(/[A-Z]+(?![a-z])|[A-Z]/g, (s, o) => (o ? "-" : "") + s.toLowerCase()); return str.replace(/[A-Z]+(?![a-z])|[A-Z]/g, (s, o) => (o ? "-" : "") + s.toLowerCase());
} }
/** Get the localized shiny descriptor for the provided variant
* @param variant - The variant to get the shiny descriptor for
* @returns The localized shiny descriptor
*/
export function getShinyDescriptor(variant: Variant): string {
switch (variant) {
case 2:
return i18next.t("common:epicShiny");
case 1:
return i18next.t("common:rareShiny");
case 0:
return i18next.t("common:commonShiny");
}
}

View File

@ -40,7 +40,7 @@ describe("Moves - Aroma Veil", () => {
game.move.select(Moves.GROWL); game.move.select(Moves.GROWL);
game.move.select(Moves.GROWL); game.move.select(Moves.GROWL);
await game.forceEnemyMove(Moves.HEAL_BLOCK); await game.move.selectEnemyMove(Moves.HEAL_BLOCK);
await game.toNextTurn(); await game.toNextTurn();
party.forEach(p => { party.forEach(p => {
expect(p.getTag(BattlerTagType.HEAL_BLOCK)).toBeUndefined(); expect(p.getTag(BattlerTagType.HEAL_BLOCK)).toBeUndefined();
@ -54,8 +54,8 @@ describe("Moves - Aroma Veil", () => {
game.move.select(Moves.GROWL); game.move.select(Moves.GROWL);
game.move.select(Moves.GROWL, 1); game.move.select(Moves.GROWL, 1);
await game.forceEnemyMove(Moves.IMPRISON, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.IMPRISON, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
expect(game.scene.arena.getTag(ArenaTagType.IMPRISON)).toBeDefined(); expect(game.scene.arena.getTag(ArenaTagType.IMPRISON)).toBeDefined();
party.forEach(p => { party.forEach(p => {

View File

@ -39,7 +39,7 @@ describe("Abilities - Battery", () => {
vi.spyOn(moveToCheck, "calculateBattlePower"); vi.spyOn(moveToCheck, "calculateBattlePower");
await game.startBattle([Species.PIKACHU, Species.CHARJABUG]); await game.classicMode.startBattle([Species.PIKACHU, Species.CHARJABUG]);
game.move.select(Moves.DAZZLING_GLEAM); game.move.select(Moves.DAZZLING_GLEAM);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
@ -54,7 +54,7 @@ describe("Abilities - Battery", () => {
vi.spyOn(moveToCheck, "calculateBattlePower"); vi.spyOn(moveToCheck, "calculateBattlePower");
await game.startBattle([Species.PIKACHU, Species.CHARJABUG]); await game.classicMode.startBattle([Species.PIKACHU, Species.CHARJABUG]);
game.move.select(Moves.BREAKING_SWIPE); game.move.select(Moves.BREAKING_SWIPE);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
@ -69,7 +69,7 @@ describe("Abilities - Battery", () => {
vi.spyOn(moveToCheck, "calculateBattlePower"); vi.spyOn(moveToCheck, "calculateBattlePower");
await game.startBattle([Species.CHARJABUG, Species.PIKACHU]); await game.classicMode.startBattle([Species.CHARJABUG, Species.PIKACHU]);
game.move.select(Moves.DAZZLING_GLEAM); game.move.select(Moves.DAZZLING_GLEAM);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);

View File

@ -59,8 +59,8 @@ describe("Abilities - Commander", () => {
expect(game.scene.currentBattle.turnCommands[0]?.skip).toBeTruthy(); expect(game.scene.currentBattle.turnCommands[0]?.skip).toBeTruthy();
// Force both enemies to target the Tatsugiri // Force both enemies to target the Tatsugiri
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER);
await game.phaseInterceptor.to("BerryPhase", false); await game.phaseInterceptor.to("BerryPhase", false);
game.scene.getEnemyField().forEach(enemy => expect(enemy.getLastXMoves(1)[0].result).toBe(MoveResult.MISS)); game.scene.getEnemyField().forEach(enemy => expect(enemy.getLastXMoves(1)[0].result).toBe(MoveResult.MISS));
@ -100,8 +100,8 @@ describe("Abilities - Commander", () => {
expect(game.scene.currentBattle.turnCommands[0]?.skip).toBeTruthy(); expect(game.scene.currentBattle.turnCommands[0]?.skip).toBeTruthy();
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER);
await game.setTurnOrder([BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER]);
@ -183,8 +183,8 @@ describe("Abilities - Commander", () => {
expect(game.scene.currentBattle.turnCommands[0]?.skip).toBeTruthy(); expect(game.scene.currentBattle.turnCommands[0]?.skip).toBeTruthy();
await game.forceEnemyMove(Moves.WHIRLWIND, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(Moves.WHIRLWIND, BattlerIndex.PLAYER_2);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
// Test may time out here if Whirlwind forced out a Pokemon // Test may time out here if Whirlwind forced out a Pokemon
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");

View File

@ -33,7 +33,7 @@ describe("Abilities - COSTAR", () => {
test("ability copies positive stat stages", async () => { test("ability copies positive stat stages", async () => {
game.override.enemyAbility(Abilities.BALL_FETCH); game.override.enemyAbility(Abilities.BALL_FETCH);
await game.startBattle([Species.MAGIKARP, Species.MAGIKARP, Species.FLAMIGO]); await game.classicMode.startBattle([Species.MAGIKARP, Species.MAGIKARP, Species.FLAMIGO]);
let [leftPokemon, rightPokemon] = game.scene.getPlayerField(); let [leftPokemon, rightPokemon] = game.scene.getPlayerField();
@ -58,7 +58,7 @@ describe("Abilities - COSTAR", () => {
test("ability copies negative stat stages", async () => { test("ability copies negative stat stages", async () => {
game.override.enemyAbility(Abilities.INTIMIDATE); game.override.enemyAbility(Abilities.INTIMIDATE);
await game.startBattle([Species.MAGIKARP, Species.MAGIKARP, Species.FLAMIGO]); await game.classicMode.startBattle([Species.MAGIKARP, Species.MAGIKARP, Species.FLAMIGO]);
let [leftPokemon, rightPokemon] = game.scene.getPlayerField(); let [leftPokemon, rightPokemon] = game.scene.getPlayerField();

View File

@ -76,7 +76,7 @@ describe("Abilities - Cud Chew", () => {
farigiraf.hp = farigiraf.getMaxHp() / 2 - 1; farigiraf.hp = farigiraf.getMaxHp() / 2 - 1;
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
// doesn't trigger since cud chew hasn't eaten berry yet // doesn't trigger since cud chew hasn't eaten berry yet
@ -86,7 +86,7 @@ describe("Abilities - Cud Chew", () => {
// get heal pulsed back to full before the cud chew proc // get heal pulsed back to full before the cud chew proc
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.HEAL_PULSE); await game.move.selectEnemyMove(Moves.HEAL_PULSE);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
// globalScene.queueAbilityDisplay should be called twice: // globalScene.queueAbilityDisplay should be called twice:

View File

@ -77,8 +77,8 @@ describe("Abilities - Dancer", () => {
game.move.select(Moves.REVELATION_DANCE, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2); game.move.select(Moves.REVELATION_DANCE, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2);
game.move.select(Moves.FIERY_DANCE, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2); game.move.select(Moves.FIERY_DANCE, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2);
await game.forceEnemyMove(Moves.INSTRUCT, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.INSTRUCT, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.MIRROR_MOVE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.MIRROR_MOVE, BattlerIndex.PLAYER);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2, BattlerIndex.ENEMY]); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2, BattlerIndex.ENEMY]);
await game.phaseInterceptor.to("MovePhase"); // Oricorio rev dance await game.phaseInterceptor.to("MovePhase"); // Oricorio rev dance
await game.phaseInterceptor.to("MovePhase"); // Feebas fiery dance await game.phaseInterceptor.to("MovePhase"); // Feebas fiery dance

View File

@ -50,8 +50,8 @@ describe("Abilities - Desolate Land", () => {
game.move.select(Moves.SPLASH, 0, 2); game.move.select(Moves.SPLASH, 0, 2);
game.move.select(Moves.SPLASH, 1, 2); game.move.select(Moves.SPLASH, 1, 2);
await game.forceEnemyMove(Moves.ROAR, 0); await game.move.selectEnemyMove(Moves.ROAR, 0);
await game.forceEnemyMove(Moves.SPLASH, 1); await game.move.selectEnemyMove(Moves.SPLASH, 1);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
@ -66,8 +66,8 @@ describe("Abilities - Desolate Land", () => {
game.move.select(Moves.SPLASH, 0, 2); game.move.select(Moves.SPLASH, 0, 2);
game.move.select(Moves.SPLASH, 1, 2); game.move.select(Moves.SPLASH, 1, 2);
await game.forceEnemyMove(Moves.ROAR, 1); await game.move.selectEnemyMove(Moves.ROAR, 1);
await game.forceEnemyMove(Moves.SPLASH, 0); await game.move.selectEnemyMove(Moves.SPLASH, 0);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
@ -103,8 +103,8 @@ describe("Abilities - Desolate Land", () => {
game.move.select(Moves.SPLASH, 0, 2); game.move.select(Moves.SPLASH, 0, 2);
game.move.select(Moves.SPLASH, 1, 2); game.move.select(Moves.SPLASH, 1, 2);
await game.forceEnemyMove(Moves.MEMENTO, 0); await game.move.selectEnemyMove(Moves.MEMENTO, 0);
await game.forceEnemyMove(Moves.MEMENTO, 1); await game.move.selectEnemyMove(Moves.MEMENTO, 1);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");

View File

@ -67,8 +67,8 @@ describe("Abilities - Flower Gift", () => {
// turn 1 // turn 1
game.move.select(Moves.SUNNY_DAY, 0); game.move.select(Moves.SUNNY_DAY, 0);
game.move.select(ally_move, 1, ally_target); game.move.select(ally_move, 1, ally_target);
await game.forceEnemyMove(enemy_move, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(enemy_move, BattlerIndex.PLAYER_2);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
// Ensure sunny day is used last. // Ensure sunny day is used last.
await game.setTurnOrder([attacker_index, target_index, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER]); await game.setTurnOrder([attacker_index, target_index, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER]);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
@ -79,8 +79,8 @@ describe("Abilities - Flower Gift", () => {
// turn 2. Make target use recover to reset hp calculation. // turn 2. Make target use recover to reset hp calculation.
game.move.select(Moves.SPLASH, 0, target_index); game.move.select(Moves.SPLASH, 0, target_index);
game.move.select(ally_move, 1, ally_target); game.move.select(ally_move, 1, ally_target);
await game.forceEnemyMove(enemy_move, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(enemy_move, BattlerIndex.PLAYER_2);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, target_index, attacker_index]); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, target_index, attacker_index]);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
const damageWithGift = initialHp - target.hp; const damageWithGift = initialHp - target.hp;

View File

@ -49,7 +49,7 @@ describe("Abilities - Flower Veil", () => {
await game.classicMode.startBattle([Species.BULBASAUR]); await game.classicMode.startBattle([Species.BULBASAUR]);
const user = game.scene.getPlayerPokemon()!; const user = game.scene.getPlayerPokemon()!;
game.move.select(Moves.REST); game.move.select(Moves.REST);
await game.forceEnemyMove(Moves.TACKLE); await game.move.selectEnemyMove(Moves.TACKLE);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.toNextTurn(); await game.toNextTurn();
expect(user.status?.effect).toBe(StatusEffect.SLEEP); expect(user.status?.effect).toBe(StatusEffect.SLEEP);
@ -57,7 +57,7 @@ describe("Abilities - Flower Veil", () => {
// remove sleep status so we can get burn from the orb // remove sleep status so we can get burn from the orb
user.resetStatus(); user.resetStatus();
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
expect(user.status?.effect).toBe(StatusEffect.BURN); expect(user.status?.effect).toBe(StatusEffect.BURN);
}); });
@ -71,8 +71,8 @@ describe("Abilities - Flower Veil", () => {
vi.spyOn(ally, "getAbility").mockReturnValue(allAbilities[Abilities.BALL_FETCH]); vi.spyOn(ally, "getAbility").mockReturnValue(allAbilities[Abilities.BALL_FETCH]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.YAWN, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.YAWN, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.YAWN, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(Moves.YAWN, BattlerIndex.PLAYER_2);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
const user = game.scene.getPlayerPokemon()!; const user = game.scene.getPlayerPokemon()!;
@ -86,7 +86,7 @@ describe("Abilities - Flower Veil", () => {
await game.classicMode.startBattle([Species.BULBASAUR]); await game.classicMode.startBattle([Species.BULBASAUR]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.THUNDER_WAVE); await game.move.selectEnemyMove(Moves.THUNDER_WAVE);
await game.toNextTurn(); await game.toNextTurn();
expect(game.scene.getPlayerPokemon()!.status).toBeUndefined(); expect(game.scene.getPlayerPokemon()!.status).toBeUndefined();
vi.spyOn(allMoves[Moves.THUNDER_WAVE], "accuracy", "get").mockClear(); vi.spyOn(allMoves[Moves.THUNDER_WAVE], "accuracy", "get").mockClear();
@ -101,8 +101,8 @@ describe("Abilities - Flower Veil", () => {
vi.spyOn(ally, "getAbility").mockReturnValue(allAbilities[Abilities.BALL_FETCH]); vi.spyOn(ally, "getAbility").mockReturnValue(allAbilities[Abilities.BALL_FETCH]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.THUNDER_WAVE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.THUNDER_WAVE, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.THUNDER_WAVE, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(Moves.THUNDER_WAVE, BattlerIndex.PLAYER_2);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
expect(user.status?.effect).toBe(StatusEffect.PARALYSIS); expect(user.status?.effect).toBe(StatusEffect.PARALYSIS);
expect(ally.status?.effect).toBe(StatusEffect.PARALYSIS); expect(ally.status?.effect).toBe(StatusEffect.PARALYSIS);

View File

@ -30,7 +30,7 @@ describe("Abilities - Forecast", () => {
*/ */
const testWeatherFormChange = async (game: GameManager, weather: WeatherType, form: number, initialForm?: number) => { const testWeatherFormChange = async (game: GameManager, weather: WeatherType, form: number, initialForm?: number) => {
game.override.weather(weather).starterForms({ [Species.CASTFORM]: initialForm }); game.override.weather(weather).starterForms({ [Species.CASTFORM]: initialForm });
await game.startBattle([Species.CASTFORM]); await game.classicMode.startBattle([Species.CASTFORM]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
@ -44,7 +44,7 @@ describe("Abilities - Forecast", () => {
*/ */
const testRevertFormAgainstAbility = async (game: GameManager, ability: Abilities) => { const testRevertFormAgainstAbility = async (game: GameManager, ability: Abilities) => {
game.override.starterForms({ [Species.CASTFORM]: SUNNY_FORM }).enemyAbility(ability); game.override.starterForms({ [Species.CASTFORM]: SUNNY_FORM }).enemyAbility(ability);
await game.startBattle([Species.CASTFORM]); await game.classicMode.startBattle([Species.CASTFORM]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
@ -81,7 +81,7 @@ describe("Abilities - Forecast", () => {
[Species.GROUDON]: 1, [Species.GROUDON]: 1,
[Species.RAYQUAZA]: 1, [Species.RAYQUAZA]: 1,
}); });
await game.startBattle([ await game.classicMode.startBattle([
Species.CASTFORM, Species.CASTFORM,
Species.FEEBAS, Species.FEEBAS,
Species.KYOGRE, Species.KYOGRE,
@ -201,7 +201,7 @@ describe("Abilities - Forecast", () => {
it("has no effect on Pokémon other than Castform", async () => { it("has no effect on Pokémon other than Castform", async () => {
game.override.enemyAbility(Abilities.FORECAST).enemySpecies(Species.SHUCKLE); game.override.enemyAbility(Abilities.FORECAST).enemySpecies(Species.SHUCKLE);
await game.startBattle([Species.CASTFORM]); await game.classicMode.startBattle([Species.CASTFORM]);
game.move.select(Moves.RAIN_DANCE); game.move.select(Moves.RAIN_DANCE);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
@ -212,7 +212,7 @@ describe("Abilities - Forecast", () => {
it("reverts to Normal Form when Forecast is suppressed, changes form to match the weather when it regains it", async () => { it("reverts to Normal Form when Forecast is suppressed, changes form to match the weather when it regains it", async () => {
game.override.enemyMoveset([Moves.GASTRO_ACID]).weather(WeatherType.RAIN); game.override.enemyMoveset([Moves.GASTRO_ACID]).weather(WeatherType.RAIN);
await game.startBattle([Species.CASTFORM, Species.PIKACHU]); await game.classicMode.startBattle([Species.CASTFORM, Species.PIKACHU]);
const castform = game.scene.getPlayerPokemon()!; const castform = game.scene.getPlayerPokemon()!;
expect(castform.formIndex).toBe(RAINY_FORM); expect(castform.formIndex).toBe(RAINY_FORM);
@ -243,7 +243,7 @@ describe("Abilities - Forecast", () => {
it("does not change Castform's form until after Stealth Rock deals damage", async () => { it("does not change Castform's form until after Stealth Rock deals damage", async () => {
game.override.weather(WeatherType.RAIN).enemyMoveset([Moves.STEALTH_ROCK]); game.override.weather(WeatherType.RAIN).enemyMoveset([Moves.STEALTH_ROCK]);
await game.startBattle([Species.PIKACHU, Species.CASTFORM]); await game.classicMode.startBattle([Species.PIKACHU, Species.CASTFORM]);
// First turn - set up stealth rock // First turn - set up stealth rock
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
@ -267,7 +267,7 @@ describe("Abilities - Forecast", () => {
it("should be in Normal Form after the user is switched out", async () => { it("should be in Normal Form after the user is switched out", async () => {
game.override.weather(WeatherType.RAIN); game.override.weather(WeatherType.RAIN);
await game.startBattle([Species.CASTFORM, Species.MAGIKARP]); await game.classicMode.startBattle([Species.CASTFORM, Species.MAGIKARP]);
const castform = game.scene.getPlayerPokemon()!; const castform = game.scene.getPlayerPokemon()!;
expect(castform.formIndex).toBe(RAINY_FORM); expect(castform.formIndex).toBe(RAINY_FORM);

View File

@ -43,8 +43,8 @@ describe("Moves - Friend Guard", () => {
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
// Get the last return value from `getAttackDamage` // Get the last return value from `getAttackDamage`
@ -60,8 +60,8 @@ describe("Moves - Friend Guard", () => {
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
// Get the last return value from `getAttackDamage` // Get the last return value from `getAttackDamage`
@ -83,8 +83,8 @@ describe("Moves - Friend Guard", () => {
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER_2);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
const turn1Damage = spy.mock.results[spy.mock.results.length - 1].value.damage; const turn1Damage = spy.mock.results[spy.mock.results.length - 1].value.damage;
@ -93,8 +93,8 @@ describe("Moves - Friend Guard", () => {
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER_2);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
const turn2Damage = spy.mock.results[spy.mock.results.length - 1].value.damage; const turn2Damage = spy.mock.results[spy.mock.results.length - 1].value.damage;
@ -109,8 +109,8 @@ describe("Moves - Friend Guard", () => {
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.DRAGON_RAGE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.DRAGON_RAGE, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
const turn1Damage = spy.mock.results[spy.mock.results.length - 1].value.damage; const turn1Damage = spy.mock.results[spy.mock.results.length - 1].value.damage;
@ -120,8 +120,8 @@ describe("Moves - Friend Guard", () => {
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.DRAGON_RAGE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.DRAGON_RAGE, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
const turn2Damage = spy.mock.results[spy.mock.results.length - 1].value.damage; const turn2Damage = spy.mock.results[spy.mock.results.length - 1].value.damage;

View File

@ -1,6 +1,6 @@
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { allAbilities } from "#app/data/data-lists";
import { ArenaTagSide } from "#app/data/arena-tag"; import { ArenaTagSide } from "#app/data/arena-tag";
import { allAbilities } from "#app/data/data-lists";
import { ArenaTagType } from "#app/enums/arena-tag-type"; import { ArenaTagType } from "#app/enums/arena-tag-type";
import { BattlerTagType } from "#app/enums/battler-tag-type"; import { BattlerTagType } from "#app/enums/battler-tag-type";
import { Stat } from "#app/enums/stat"; import { Stat } from "#app/enums/stat";
@ -74,8 +74,8 @@ describe("Abilities - Good As Gold", () => {
game.move.select(Moves.SWORDS_DANCE, 0); game.move.select(Moves.SWORDS_DANCE, 0);
game.move.select(Moves.SAFEGUARD, 1); game.move.select(Moves.SAFEGUARD, 1);
await game.forceEnemyMove(Moves.STEALTH_ROCK); await game.move.selectEnemyMove(Moves.STEALTH_ROCK);
await game.forceEnemyMove(Moves.HAZE); await game.move.selectEnemyMove(Moves.HAZE);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
expect(good_as_gold.getAbility().id).toBe(Abilities.GOOD_AS_GOLD); expect(good_as_gold.getAbility().id).toBe(Abilities.GOOD_AS_GOLD);
@ -107,35 +107,33 @@ describe("Abilities - Good As Gold", () => {
expect(game.scene.getPlayerField()[1].getTag(BattlerTagType.HELPING_HAND)).toBeUndefined(); expect(game.scene.getPlayerField()[1].getTag(BattlerTagType.HELPING_HAND)).toBeUndefined();
}); });
it("should block the ally's heal bell, but only if the good as gold user is on the field", async () => { // TODO: re-enable when heal bell is fixed
game.override.battleStyle("double"); it.todo("should block the ally's heal bell, but only if the good as gold user is on the field", async () => {
game.override.moveset([Moves.HEAL_BELL, Moves.SPLASH]); game.override.battleStyle("double").statusEffect(StatusEffect.BURN);
game.override.statusEffect(StatusEffect.BURN); await game.classicMode.startBattle([Species.MILOTIC, Species.FEEBAS, Species.ABRA]);
await game.classicMode.startBattle([Species.MAGIKARP, Species.FEEBAS, Species.ABRA]); const [milotic, feebas, abra] = game.scene.getPlayerParty();
const [good_as_gold, ball_fetch] = game.scene.getPlayerField(); game.field.mockAbility(milotic, Abilities.GOOD_AS_GOLD);
game.field.mockAbility(feebas, Abilities.BALL_FETCH);
// Force second pokemon to have ball fetch to isolate to a single mon. game.field.mockAbility(abra, Abilities.BALL_FETCH);
vi.spyOn(ball_fetch, "getAbility").mockReturnValue(allAbilities[Abilities.BALL_FETCH]);
// turn 1 // turn 1
game.move.select(Moves.SPLASH, 0); game.move.use(Moves.SPLASH, 0);
game.move.select(Moves.HEAL_BELL, 1); game.move.use(Moves.HEAL_BELL, 1);
await game.toNextTurn(); await game.toNextTurn();
expect(good_as_gold.status?.effect).toBe(StatusEffect.BURN); expect(milotic.status?.effect).toBe(StatusEffect.BURN);
game.doSwitchPokemon(2); game.doSwitchPokemon(2);
game.move.select(Moves.HEAL_BELL, 0); game.move.use(Moves.HEAL_BELL, 1);
await game.toNextTurn(); await game.toNextTurn();
expect(good_as_gold.status?.effect).toBeUndefined(); expect(milotic.status?.effect).toBeUndefined();
}); });
it("should not block field targeted effects like rain dance", async () => { it("should not block field targeted effects like rain dance", async () => {
game.override.battleStyle("single"); game.override.battleStyle("single");
game.override.enemyMoveset([Moves.RAIN_DANCE]); game.override.enemyMoveset([Moves.RAIN_DANCE]);
game.override.weather(WeatherType.NONE);
await game.classicMode.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
game.move.select(Moves.SPLASH, 0); game.move.use(Moves.SPLASH, 0);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.RAIN); expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.RAIN);

View File

@ -39,7 +39,7 @@ describe("Abilities - Gorilla Tactics", () => {
const initialAtkStat = darmanitan.getStat(Stat.ATK); const initialAtkStat = darmanitan.getStat(Stat.ATK);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
@ -57,13 +57,13 @@ describe("Abilities - Gorilla Tactics", () => {
// First turn, lock move to Growl // First turn, lock move to Growl
game.move.select(Moves.GROWL); game.move.select(Moves.GROWL);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
// Second turn, Growl is interrupted by Disable // Second turn, Growl is interrupted by Disable
await game.toNextTurn(); await game.toNextTurn();
game.move.select(Moves.GROWL); game.move.select(Moves.GROWL);
await game.forceEnemyMove(Moves.DISABLE); await game.move.selectEnemyMove(Moves.DISABLE);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");

View File

@ -241,13 +241,13 @@ describe("Abilities - Gulp Missile", () => {
await game.classicMode.startBattle([Species.CRAMORANT]); await game.classicMode.startBattle([Species.CRAMORANT]);
game.move.select(Moves.SURF); game.move.select(Moves.SURF);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
expect(game.scene.getPlayerPokemon()!.formIndex).toBe(GULPING_FORM); expect(game.scene.getPlayerPokemon()!.formIndex).toBe(GULPING_FORM);
game.move.select(Moves.SUBSTITUTE); game.move.select(Moves.SUBSTITUTE);
await game.forceEnemyMove(Moves.POWER_TRIP); await game.move.selectEnemyMove(Moves.POWER_TRIP);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
await game.toNextTurn(); await game.toNextTurn();

View File

@ -61,7 +61,7 @@ describe("Abilities - Harvest", () => {
await game.classicMode.startBattle([Species.FEEBAS]); await game.classicMode.startBattle([Species.FEEBAS]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.NUZZLE); await game.move.selectEnemyMove(Moves.NUZZLE);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
expect(getPlayerBerries()).toHaveLength(0); expect(getPlayerBerries()).toHaveLength(0);
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toHaveLength(1); expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toHaveLength(1);
@ -87,7 +87,7 @@ describe("Abilities - Harvest", () => {
// Chug a few berries without harvest (should get tracked) // Chug a few berries without harvest (should get tracked)
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.NUZZLE); await game.move.selectEnemyMove(Moves.NUZZLE);
await game.toNextTurn(); await game.toNextTurn();
expect(milotic.battleData.berriesEaten).toEqual(expect.arrayContaining([BerryType.ENIGMA, BerryType.LUM])); expect(milotic.battleData.berriesEaten).toEqual(expect.arrayContaining([BerryType.ENIGMA, BerryType.LUM]));
@ -98,7 +98,7 @@ describe("Abilities - Harvest", () => {
vi.spyOn(PostTurnRestoreBerryAbAttr.prototype, "canApplyPostTurn").mockReturnValueOnce(false); vi.spyOn(PostTurnRestoreBerryAbAttr.prototype, "canApplyPostTurn").mockReturnValueOnce(false);
game.override.ability(Abilities.HARVEST); game.override.ability(Abilities.HARVEST);
game.move.select(Moves.GASTRO_ACID); game.move.select(Moves.GASTRO_ACID);
await game.forceEnemyMove(Moves.NUZZLE); await game.move.selectEnemyMove(Moves.NUZZLE);
await game.toNextTurn(); await game.toNextTurn();
@ -109,7 +109,7 @@ describe("Abilities - Harvest", () => {
// proc a high roll and we _should_ get a berry back! // proc a high roll and we _should_ get a berry back!
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
expect(milotic.battleData.berriesEaten).toHaveLength(3); expect(milotic.battleData.berriesEaten).toHaveLength(3);
@ -126,7 +126,7 @@ describe("Abilities - Harvest", () => {
regieleki.hp = 1; regieleki.hp = 1;
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.doKillOpponents(); await game.doKillOpponents();
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
@ -154,7 +154,7 @@ describe("Abilities - Harvest", () => {
regieleki.hp = regieleki.getMaxHp() / 4 + 1; regieleki.hp = regieleki.getMaxHp() / 4 + 1;
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SUPER_FANG); await game.move.selectEnemyMove(Moves.SUPER_FANG);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.toNextTurn(); await game.toNextTurn();
@ -165,7 +165,7 @@ describe("Abilities - Harvest", () => {
// heal up so harvest doesn't proc and kill enemy // heal up so harvest doesn't proc and kill enemy
game.move.select(Moves.EARTHQUAKE); game.move.select(Moves.EARTHQUAKE);
await game.forceEnemyMove(Moves.HEAL_PULSE); await game.move.selectEnemyMove(Moves.HEAL_PULSE);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.toNextWave(); await game.toNextWave();
@ -191,7 +191,7 @@ describe("Abilities - Harvest", () => {
feebas.battleData.berriesEaten = [BerryType.LUM, BerryType.STARF]; feebas.battleData.berriesEaten = [BerryType.LUM, BerryType.STARF];
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
// Force RNG roll to hit the first berry we find that matches. // Force RNG roll to hit the first berry we find that matches.
@ -219,7 +219,7 @@ describe("Abilities - Harvest", () => {
player.battleData.berriesEaten = [BerryType.LUM, BerryType.STARF]; player.battleData.berriesEaten = [BerryType.LUM, BerryType.STARF];
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
expectBerriesContaining(...initBerries); expectBerriesContaining(...initBerries);
@ -231,7 +231,7 @@ describe("Abilities - Harvest", () => {
await game.classicMode.startBattle([Species.FEEBAS]); await game.classicMode.startBattle([Species.FEEBAS]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.INCINERATE); await game.move.selectEnemyMove(Moves.INCINERATE);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toEqual([]); expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toEqual([]);
@ -242,7 +242,7 @@ describe("Abilities - Harvest", () => {
await game.classicMode.startBattle([Species.FEEBAS]); await game.classicMode.startBattle([Species.FEEBAS]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.KNOCK_OFF); await game.move.selectEnemyMove(Moves.KNOCK_OFF);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toEqual([]); expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toEqual([]);
@ -308,7 +308,7 @@ describe("Abilities - Harvest", () => {
// steal a sitrus and immediately consume it // steal a sitrus and immediately consume it
game.move.select(Moves.FALSE_SWIPE); game.move.select(Moves.FALSE_SWIPE);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
expect(player.battleData.berriesEaten).toEqual([BerryType.SITRUS]); expect(player.battleData.berriesEaten).toEqual([BerryType.SITRUS]);

View File

@ -38,7 +38,7 @@ describe("Abilities - Heatproof", () => {
}); });
it("reduces Fire type damage by half", async () => { it("reduces Fire type damage by half", async () => {
await game.startBattle(); await game.classicMode.startBattle();
const enemy = game.scene.getEnemyPokemon()!; const enemy = game.scene.getEnemyPokemon()!;
const initialHP = 1000; const initialHP = 1000;
@ -61,7 +61,7 @@ describe("Abilities - Heatproof", () => {
it("reduces Burn damage by half", async () => { it("reduces Burn damage by half", async () => {
game.override.enemyStatusEffect(StatusEffect.BURN).enemySpecies(Species.ABRA); game.override.enemyStatusEffect(StatusEffect.BURN).enemySpecies(Species.ABRA);
await game.startBattle(); await game.classicMode.startBattle();
const enemy = game.scene.getEnemyPokemon()!; const enemy = game.scene.getEnemyPokemon()!;

View File

@ -34,7 +34,7 @@ describe("Abilities - Hyper Cutter", () => {
// Reference Link: https://bulbapedia.bulbagarden.net/wiki/Hyper_Cutter_(Ability) // Reference Link: https://bulbapedia.bulbagarden.net/wiki/Hyper_Cutter_(Ability)
it("only prevents ATK drops", async () => { it("only prevents ATK drops", async () => {
await game.startBattle(); await game.classicMode.startBattle();
const enemy = game.scene.getEnemyPokemon()!; const enemy = game.scene.getEnemyPokemon()!;

View File

@ -39,7 +39,7 @@ describe("Abilities - Libero", () => {
test("ability applies and changes a pokemon's type", async () => { test("ability applies and changes a pokemon's type", async () => {
game.override.moveset([Moves.SPLASH]); game.override.moveset([Moves.SPLASH]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -54,7 +54,7 @@ describe("Abilities - Libero", () => {
test.skip("ability applies only once per switch in", async () => { test.skip("ability applies only once per switch in", async () => {
game.override.moveset([Moves.SPLASH, Moves.AGILITY]); game.override.moveset([Moves.SPLASH, Moves.AGILITY]);
await game.startBattle([Species.MAGIKARP, Species.BULBASAUR]); await game.classicMode.startBattle([Species.MAGIKARP, Species.BULBASAUR]);
let leadPokemon = game.scene.getPlayerPokemon()!; let leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -90,7 +90,7 @@ describe("Abilities - Libero", () => {
test("ability applies correctly even if the pokemon's move has a variable type", async () => { test("ability applies correctly even if the pokemon's move has a variable type", async () => {
game.override.moveset([Moves.WEATHER_BALL]); game.override.moveset([Moves.WEATHER_BALL]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -110,7 +110,7 @@ describe("Abilities - Libero", () => {
game.override.moveset([Moves.TACKLE]); game.override.moveset([Moves.TACKLE]);
game.override.passiveAbility(Abilities.REFRIGERATE); game.override.passiveAbility(Abilities.REFRIGERATE);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -128,7 +128,7 @@ describe("Abilities - Libero", () => {
test("ability applies correctly even if the pokemon's move calls another move", async () => { test("ability applies correctly even if the pokemon's move calls another move", async () => {
game.override.moveset([Moves.NATURE_POWER]); game.override.moveset([Moves.NATURE_POWER]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -143,7 +143,7 @@ describe("Abilities - Libero", () => {
test("ability applies correctly even if the pokemon's move is delayed / charging", async () => { test("ability applies correctly even if the pokemon's move is delayed / charging", async () => {
game.override.moveset([Moves.DIG]); game.override.moveset([Moves.DIG]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -158,7 +158,7 @@ describe("Abilities - Libero", () => {
game.override.moveset([Moves.TACKLE]); game.override.moveset([Moves.TACKLE]);
game.override.enemyMoveset(Moves.SPLASH); game.override.enemyMoveset(Moves.SPLASH);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -176,7 +176,7 @@ describe("Abilities - Libero", () => {
game.override.moveset([Moves.TACKLE]); game.override.moveset([Moves.TACKLE]);
game.override.enemyMoveset([Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT]); game.override.enemyMoveset([Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -191,7 +191,7 @@ describe("Abilities - Libero", () => {
game.override.moveset([Moves.TACKLE]); game.override.moveset([Moves.TACKLE]);
game.override.enemySpecies(Species.GASTLY); game.override.enemySpecies(Species.GASTLY);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -205,7 +205,7 @@ describe("Abilities - Libero", () => {
test("ability is not applied if pokemon's type is the same as the move's type", async () => { test("ability is not applied if pokemon's type is the same as the move's type", async () => {
game.override.moveset([Moves.SPLASH]); game.override.moveset([Moves.SPLASH]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -220,7 +220,7 @@ describe("Abilities - Libero", () => {
test("ability is not applied if pokemon is terastallized", async () => { test("ability is not applied if pokemon is terastallized", async () => {
game.override.moveset([Moves.SPLASH]); game.override.moveset([Moves.SPLASH]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -236,7 +236,7 @@ describe("Abilities - Libero", () => {
test("ability is not applied if pokemon uses struggle", async () => { test("ability is not applied if pokemon uses struggle", async () => {
game.override.moveset([Moves.STRUGGLE]); game.override.moveset([Moves.STRUGGLE]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -250,7 +250,7 @@ describe("Abilities - Libero", () => {
test("ability is not applied if the pokemon's move fails", async () => { test("ability is not applied if the pokemon's move fails", async () => {
game.override.moveset([Moves.BURN_UP]); game.override.moveset([Moves.BURN_UP]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -265,7 +265,7 @@ describe("Abilities - Libero", () => {
game.override.moveset([Moves.TRICK_OR_TREAT]); game.override.moveset([Moves.TRICK_OR_TREAT]);
game.override.enemySpecies(Species.GASTLY); game.override.enemySpecies(Species.GASTLY);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -279,7 +279,7 @@ describe("Abilities - Libero", () => {
test("ability applies correctly and the pokemon curses itself", async () => { test("ability applies correctly and the pokemon curses itself", async () => {
game.override.moveset([Moves.CURSE]); game.override.moveset([Moves.CURSE]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);

View File

@ -52,7 +52,7 @@ describe("Abilities - Magic Bounce", () => {
game.override.enemyMoveset([Moves.FLY]); game.override.enemyMoveset([Moves.FLY]);
game.move.select(Moves.GROWL); game.move.select(Moves.GROWL);
await game.forceEnemyMove(Moves.FLY); await game.move.selectEnemyMove(Moves.FLY);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
@ -183,7 +183,7 @@ describe("Abilities - Magic Bounce", () => {
// turn 1 // turn 1
game.move.select(Moves.ENCORE); game.move.select(Moves.ENCORE);
await game.forceEnemyMove(Moves.TACKLE); await game.move.selectEnemyMove(Moves.TACKLE);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.toNextTurn(); await game.toNextTurn();
expect(enemyPokemon.getTag(BattlerTagType.ENCORE)!["moveId"]).toBe(Moves.TACKLE); expect(enemyPokemon.getTag(BattlerTagType.ENCORE)!["moveId"]).toBe(Moves.TACKLE);
@ -209,7 +209,7 @@ describe("Abilities - Magic Bounce", () => {
// turn 1 // turn 1
game.move.select(Moves.GROWL); game.move.select(Moves.GROWL);
await game.forceEnemyMove(Moves.TACKLE); await game.move.selectEnemyMove(Moves.TACKLE);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.toNextTurn(); await game.toNextTurn();
@ -218,7 +218,7 @@ describe("Abilities - Magic Bounce", () => {
// turn 2 // turn 2
game.move.select(Moves.ENCORE); game.move.select(Moves.ENCORE);
await game.forceEnemyMove(Moves.TACKLE); await game.move.selectEnemyMove(Moves.TACKLE);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
expect(enemyPokemon.getTag(BattlerTagType.ENCORE)!["moveId"]).toBe(Moves.TACKLE); expect(enemyPokemon.getTag(BattlerTagType.ENCORE)!["moveId"]).toBe(Moves.TACKLE);
@ -254,7 +254,7 @@ describe("Abilities - Magic Bounce", () => {
vi.spyOn(stomping_tantrum, "calculateBattlePower"); vi.spyOn(stomping_tantrum, "calculateBattlePower");
game.move.select(Moves.SPORE); game.move.select(Moves.SPORE);
await game.forceEnemyMove(Moves.CHARM); await game.move.selectEnemyMove(Moves.CHARM);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
expect(enemy.getLastXMoves(1)[0].result).toBe("success"); expect(enemy.getLastXMoves(1)[0].result).toBe("success");
@ -346,7 +346,7 @@ describe("Abilities - Magic Bounce", () => {
game.override.moveset([Moves.TOXIC, Moves.CHARM]); game.override.moveset([Moves.TOXIC, Moves.CHARM]);
await game.classicMode.startBattle([Species.BULBASAUR]); await game.classicMode.startBattle([Species.BULBASAUR]);
game.move.select(Moves.TOXIC); game.move.select(Moves.TOXIC);
await game.forceEnemyMove(Moves.FLY); await game.move.selectEnemyMove(Moves.FLY);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.TOXIC); expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.TOXIC);

View File

@ -46,7 +46,7 @@ describe("Abilities - Magic Guard", () => {
it("ability should prevent damage caused by weather", async () => { it("ability should prevent damage caused by weather", async () => {
game.override.weather(WeatherType.SANDSTORM); game.override.weather(WeatherType.SANDSTORM);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -70,7 +70,7 @@ describe("Abilities - Magic Guard", () => {
//Toxic keeps track of the turn counters -> important that Magic Guard keeps track of post-Toxic turns //Toxic keeps track of the turn counters -> important that Magic Guard keeps track of post-Toxic turns
game.override.statusEffect(StatusEffect.POISON); game.override.statusEffect(StatusEffect.POISON);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -91,7 +91,7 @@ describe("Abilities - Magic Guard", () => {
game.override.enemyMoveset([Moves.WORRY_SEED, Moves.WORRY_SEED, Moves.WORRY_SEED, Moves.WORRY_SEED]); game.override.enemyMoveset([Moves.WORRY_SEED, Moves.WORRY_SEED, Moves.WORRY_SEED, Moves.WORRY_SEED]);
game.override.statusEffect(StatusEffect.POISON); game.override.statusEffect(StatusEffect.POISON);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -110,7 +110,7 @@ describe("Abilities - Magic Guard", () => {
game.override.enemyStatusEffect(StatusEffect.BURN); game.override.enemyStatusEffect(StatusEffect.BURN);
game.override.enemyAbility(Abilities.MAGIC_GUARD); game.override.enemyAbility(Abilities.MAGIC_GUARD);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
@ -132,7 +132,7 @@ describe("Abilities - Magic Guard", () => {
game.override.enemyStatusEffect(StatusEffect.TOXIC); game.override.enemyStatusEffect(StatusEffect.TOXIC);
game.override.enemyAbility(Abilities.MAGIC_GUARD); game.override.enemyAbility(Abilities.MAGIC_GUARD);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
@ -159,7 +159,7 @@ describe("Abilities - Magic Guard", () => {
const newTag = getArenaTag(ArenaTagType.SPIKES, 5, Moves.SPIKES, 0, 0, ArenaTagSide.BOTH)!; const newTag = getArenaTag(ArenaTagType.SPIKES, 5, Moves.SPIKES, 0, 0, ArenaTagSide.BOTH)!;
game.scene.arena.tags.push(newTag); game.scene.arena.tags.push(newTag);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
@ -184,7 +184,7 @@ describe("Abilities - Magic Guard", () => {
game.scene.arena.tags.push(playerTag); game.scene.arena.tags.push(playerTag);
game.scene.arena.tags.push(enemyTag); game.scene.arena.tags.push(enemyTag);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
@ -206,7 +206,7 @@ describe("Abilities - Magic Guard", () => {
}); });
it("Magic Guard prevents against damage from volatile status effects", async () => { it("Magic Guard prevents against damage from volatile status effects", async () => {
await game.startBattle([Species.DUSKULL]); await game.classicMode.startBattle([Species.DUSKULL]);
game.override.moveset([Moves.CURSE]); game.override.moveset([Moves.CURSE]);
game.override.enemyAbility(Abilities.MAGIC_GUARD); game.override.enemyAbility(Abilities.MAGIC_GUARD);
@ -231,7 +231,7 @@ describe("Abilities - Magic Guard", () => {
it("Magic Guard prevents crash damage", async () => { it("Magic Guard prevents crash damage", async () => {
game.override.moveset([Moves.HIGH_JUMP_KICK]); game.override.moveset([Moves.HIGH_JUMP_KICK]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -249,7 +249,7 @@ describe("Abilities - Magic Guard", () => {
it("Magic Guard prevents damage from recoil", async () => { it("Magic Guard prevents damage from recoil", async () => {
game.override.moveset([Moves.TAKE_DOWN]); game.override.moveset([Moves.TAKE_DOWN]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -266,7 +266,7 @@ describe("Abilities - Magic Guard", () => {
it("Magic Guard does not prevent damage from Struggle's recoil", async () => { it("Magic Guard does not prevent damage from Struggle's recoil", async () => {
game.override.moveset([Moves.STRUGGLE]); game.override.moveset([Moves.STRUGGLE]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -284,7 +284,7 @@ describe("Abilities - Magic Guard", () => {
//This tests different move attributes than the recoil tests above //This tests different move attributes than the recoil tests above
it("Magic Guard prevents self-damage from attacking moves", async () => { it("Magic Guard prevents self-damage from attacking moves", async () => {
game.override.moveset([Moves.STEEL_BEAM]); game.override.moveset([Moves.STEEL_BEAM]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -301,7 +301,7 @@ describe("Abilities - Magic Guard", () => {
/* /*
it("Magic Guard does not prevent self-damage from confusion", async () => { it("Magic Guard does not prevent self-damage from confusion", async () => {
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
game.move.select(Moves.CHARM); game.move.select(Moves.CHARM);
@ -311,7 +311,7 @@ describe("Abilities - Magic Guard", () => {
it("Magic Guard does not prevent self-damage from non-attacking moves", async () => { it("Magic Guard does not prevent self-damage from non-attacking moves", async () => {
game.override.moveset([Moves.BELLY_DRUM]); game.override.moveset([Moves.BELLY_DRUM]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -333,7 +333,7 @@ describe("Abilities - Magic Guard", () => {
game.override.enemyMoveset([Moves.SPORE, Moves.SPORE, Moves.SPORE, Moves.SPORE]); game.override.enemyMoveset([Moves.SPORE, Moves.SPORE, Moves.SPORE, Moves.SPORE]);
game.override.enemyAbility(Abilities.BAD_DREAMS); game.override.enemyAbility(Abilities.BAD_DREAMS);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -355,7 +355,7 @@ describe("Abilities - Magic Guard", () => {
game.override.moveset([Moves.TACKLE]); game.override.moveset([Moves.TACKLE]);
game.override.enemyAbility(Abilities.AFTERMATH); game.override.enemyAbility(Abilities.AFTERMATH);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -379,7 +379,7 @@ describe("Abilities - Magic Guard", () => {
game.override.moveset([Moves.TACKLE]); game.override.moveset([Moves.TACKLE]);
game.override.enemyAbility(Abilities.IRON_BARBS); game.override.enemyAbility(Abilities.IRON_BARBS);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -402,7 +402,7 @@ describe("Abilities - Magic Guard", () => {
game.override.moveset([Moves.ABSORB]); game.override.moveset([Moves.ABSORB]);
game.override.enemyAbility(Abilities.LIQUID_OOZE); game.override.enemyAbility(Abilities.LIQUID_OOZE);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
@ -425,7 +425,7 @@ describe("Abilities - Magic Guard", () => {
game.override.passiveAbility(Abilities.SOLAR_POWER); game.override.passiveAbility(Abilities.SOLAR_POWER);
game.override.weather(WeatherType.SUNNY); game.override.weather(WeatherType.SUNNY);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);

View File

@ -55,7 +55,7 @@ describe("Abilities - Mimicry", () => {
const playerPokemon = game.scene.getPlayerPokemon(); const playerPokemon = game.scene.getPlayerPokemon();
game.move.select(Moves.TRANSFORM); game.move.select(Moves.TRANSFORM);
await game.forceEnemyMove(Moves.PSYCHIC_TERRAIN); await game.move.selectEnemyMove(Moves.PSYCHIC_TERRAIN);
await game.toNextTurn(); await game.toNextTurn();
expect(playerPokemon?.getTypes().includes(PokemonType.PSYCHIC)).toBe(true); expect(playerPokemon?.getTypes().includes(PokemonType.PSYCHIC)).toBe(true);
@ -64,7 +64,7 @@ describe("Abilities - Mimicry", () => {
} }
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
expect(playerPokemon?.getTypes().includes(PokemonType.ELECTRIC)).toBe(true); expect(playerPokemon?.getTypes().includes(PokemonType.ELECTRIC)).toBe(true);
}); });
@ -75,13 +75,13 @@ describe("Abilities - Mimicry", () => {
const playerPokemon = game.scene.getPlayerPokemon(); const playerPokemon = game.scene.getPlayerPokemon();
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.FORESTS_CURSE); await game.move.selectEnemyMove(Moves.FORESTS_CURSE);
await game.toNextTurn(); await game.toNextTurn();
expect(playerPokemon?.summonData.addedType).toBe(PokemonType.GRASS); expect(playerPokemon?.summonData.addedType).toBe(PokemonType.GRASS);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.GRASSY_TERRAIN); await game.move.selectEnemyMove(Moves.GRASSY_TERRAIN);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
expect(playerPokemon?.summonData.addedType).toBeNull(); expect(playerPokemon?.summonData.addedType).toBeNull();

View File

@ -46,7 +46,7 @@ describe("Ability - Mirror Armor", () => {
// Enemy has intimidate, enemy should lose -1 atk // Enemy has intimidate, enemy should lose -1 atk
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER);
await game.toNextTurn(); await game.toNextTurn();
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1); expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1);
@ -63,7 +63,7 @@ describe("Ability - Mirror Armor", () => {
// Enemy has intimidate, enemy should lose -1 atk // Enemy has intimidate, enemy should lose -1 atk
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER);
await game.toNextTurn(); await game.toNextTurn();
expect(userPokemon.getStatStage(Stat.ATK)).toBe(-1); expect(userPokemon.getStatStage(Stat.ATK)).toBe(-1);
@ -82,8 +82,8 @@ describe("Ability - Mirror Armor", () => {
// Enemy has intimidate, enemy should lose -2 atk each // Enemy has intimidate, enemy should lose -2 atk each
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2);
await game.toNextTurn(); await game.toNextTurn();
expect(enemy1.getStatStage(Stat.ATK)).toBe(-2); expect(enemy1.getStatStage(Stat.ATK)).toBe(-2);
@ -104,8 +104,8 @@ describe("Ability - Mirror Armor", () => {
// Enemy has intimidate, enemy should lose -1 atk // Enemy has intimidate, enemy should lose -1 atk
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2);
await game.toNextTurn(); await game.toNextTurn();
expect(enemy1.getStatStage(Stat.ATK)).toBe(0); expect(enemy1.getStatStage(Stat.ATK)).toBe(0);
@ -124,7 +124,7 @@ describe("Ability - Mirror Armor", () => {
// Enemy has intimidate and uses tickle, enemy receives -2 atk and -1 defense // Enemy has intimidate and uses tickle, enemy receives -2 atk and -1 defense
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER);
await game.toNextTurn(); await game.toNextTurn();
expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(-1); expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(-1);
@ -144,8 +144,8 @@ describe("Ability - Mirror Armor", () => {
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER_2);
await game.toNextTurn(); await game.toNextTurn();
expect(player1.getStatStage(Stat.ATK)).toBe(0); expect(player1.getStatStage(Stat.ATK)).toBe(0);
@ -168,7 +168,7 @@ describe("Ability - Mirror Armor", () => {
// Enemy has intimidate and uses tickle, enemy receives -2 atk and -1 defense // Enemy has intimidate and uses tickle, enemy receives -2 atk and -1 defense
game.move.select(Moves.TICKLE); game.move.select(Moves.TICKLE);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER);
await game.toNextTurn(); await game.toNextTurn();
expect(userPokemon.getStatStage(Stat.DEF)).toBe(-1); expect(userPokemon.getStatStage(Stat.DEF)).toBe(-1);
@ -187,7 +187,7 @@ describe("Ability - Mirror Armor", () => {
// Enemy has intimidate and uses tickle, enemy has white smoke, no one loses stats // Enemy has intimidate and uses tickle, enemy has white smoke, no one loses stats
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.TICKLE, BattlerIndex.PLAYER);
await game.toNextTurn(); await game.toNextTurn();
expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0); expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0);
@ -206,7 +206,7 @@ describe("Ability - Mirror Armor", () => {
// Enemy has intimidate and uses tickle, enemy has white smoke, no one loses stats // Enemy has intimidate and uses tickle, enemy has white smoke, no one loses stats
game.move.select(Moves.TICKLE); game.move.select(Moves.TICKLE);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER);
await game.toNextTurn(); await game.toNextTurn();
expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0); expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0);
@ -224,7 +224,7 @@ describe("Ability - Mirror Armor", () => {
// Enemy uses octolock, player loses stats at end of turn // Enemy uses octolock, player loses stats at end of turn
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.OCTOLOCK, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.OCTOLOCK, BattlerIndex.PLAYER);
await game.toNextTurn(); await game.toNextTurn();
expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0); expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0);
@ -242,7 +242,7 @@ describe("Ability - Mirror Armor", () => {
// Player uses octolock, enemy loses stats at end of turn // Player uses octolock, enemy loses stats at end of turn
game.move.select(Moves.OCTOLOCK); game.move.select(Moves.OCTOLOCK);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER);
await game.toNextTurn(); await game.toNextTurn();
expect(userPokemon.getStatStage(Stat.DEF)).toBe(0); expect(userPokemon.getStatStage(Stat.DEF)).toBe(0);
@ -261,7 +261,7 @@ describe("Ability - Mirror Armor", () => {
const userPokemon = game.scene.getPlayerPokemon()!; const userPokemon = game.scene.getPlayerPokemon()!;
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER);
await game.toNextTurn(); await game.toNextTurn();
expect(userPokemon.getStatStage(Stat.ATK)).toBe(-1); expect(userPokemon.getStatStage(Stat.ATK)).toBe(-1);
@ -276,11 +276,11 @@ describe("Ability - Mirror Armor", () => {
const userPokemon = game.scene.getPlayerPokemon()!; const userPokemon = game.scene.getPlayerPokemon()!;
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.STICKY_WEB, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.STICKY_WEB, BattlerIndex.PLAYER);
await game.toNextTurn(); await game.toNextTurn();
game.doSwitchPokemon(1); game.doSwitchPokemon(1);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER);
await game.toNextTurn(); await game.toNextTurn();
expect(userPokemon.getStatStage(Stat.SPD)).toBe(0); expect(userPokemon.getStatStage(Stat.SPD)).toBe(0);
@ -297,14 +297,14 @@ describe("Ability - Mirror Armor", () => {
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.STICKY_WEB, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.STICKY_WEB, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2);
await game.toNextTurn(); await game.toNextTurn();
game.doSwitchPokemon(2); game.doSwitchPokemon(2);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(Moves.SPLASH, BattlerIndex.PLAYER_2);
await game.toNextTurn(); await game.toNextTurn();
expect(enemy1.getStatStage(Stat.SPD)).toBe(-1); expect(enemy1.getStatStage(Stat.SPD)).toBe(-1);

View File

@ -38,7 +38,7 @@ describe("Abilities - Moxie", () => {
it("should raise ATK stat stage by 1 when winning a battle", async () => { it("should raise ATK stat stage by 1 when winning a battle", async () => {
const moveToUse = Moves.AERIAL_ACE; const moveToUse = Moves.AERIAL_ACE;
await game.startBattle([Species.MIGHTYENA, Species.MIGHTYENA]); await game.classicMode.startBattle([Species.MIGHTYENA, Species.MIGHTYENA]);
const playerPokemon = game.scene.getPlayerPokemon()!; const playerPokemon = game.scene.getPlayerPokemon()!;
@ -56,7 +56,7 @@ describe("Abilities - Moxie", () => {
async () => { async () => {
game.override.battleStyle("double"); game.override.battleStyle("double");
const moveToUse = Moves.AERIAL_ACE; const moveToUse = Moves.AERIAL_ACE;
await game.startBattle([Species.MIGHTYENA, Species.MIGHTYENA]); await game.classicMode.startBattle([Species.MIGHTYENA, Species.MIGHTYENA]);
const [firstPokemon, secondPokemon] = game.scene.getPlayerField(); const [firstPokemon, secondPokemon] = game.scene.getPlayerField();

View File

@ -41,7 +41,7 @@ describe("Abilities - Mycelium Might", () => {
**/ **/
it("will move last in its priority bracket and ignore protective abilities", async () => { it("will move last in its priority bracket and ignore protective abilities", async () => {
await game.startBattle([Species.REGIELEKI]); await game.classicMode.startBattle([Species.REGIELEKI]);
const enemyPokemon = game.scene.getEnemyPokemon(); const enemyPokemon = game.scene.getEnemyPokemon();
const playerIndex = game.scene.getPlayerPokemon()?.getBattlerIndex(); const playerIndex = game.scene.getPlayerPokemon()?.getBattlerIndex();
@ -65,7 +65,7 @@ describe("Abilities - Mycelium Might", () => {
it("will still go first if a status move that is in a higher priority bracket than the opponent's move is used", async () => { it("will still go first if a status move that is in a higher priority bracket than the opponent's move is used", async () => {
game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
await game.startBattle([Species.REGIELEKI]); await game.classicMode.startBattle([Species.REGIELEKI]);
const enemyPokemon = game.scene.getEnemyPokemon(); const enemyPokemon = game.scene.getEnemyPokemon();
const playerIndex = game.scene.getPlayerPokemon()?.getBattlerIndex(); const playerIndex = game.scene.getPlayerPokemon()?.getBattlerIndex();
@ -87,7 +87,7 @@ describe("Abilities - Mycelium Might", () => {
}, 20000); }, 20000);
it("will not affect non-status moves", async () => { it("will not affect non-status moves", async () => {
await game.startBattle([Species.REGIELEKI]); await game.classicMode.startBattle([Species.REGIELEKI]);
const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();

View File

@ -110,16 +110,16 @@ describe("Abilities - Neutralizing Gas", () => {
await game.classicMode.startBattle([Species.ACCELGOR, Species.ACCELGOR]); await game.classicMode.startBattle([Species.ACCELGOR, Species.ACCELGOR]);
game.move.select(Moves.SPLASH, 0); game.move.select(Moves.SPLASH, 0);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.ENTRAINMENT, BattlerIndex.PLAYER); await game.move.selectEnemyMove(Moves.ENTRAINMENT, BattlerIndex.PLAYER);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeDefined(); // Now one neut gas user is left expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeDefined(); // Now one neut gas user is left
game.move.select(Moves.SPLASH, 0); game.move.select(Moves.SPLASH, 0);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.forceEnemyMove(Moves.ENTRAINMENT, BattlerIndex.PLAYER_2); await game.move.selectEnemyMove(Moves.ENTRAINMENT, BattlerIndex.PLAYER_2);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeUndefined(); // No neut gas users are left expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeUndefined(); // No neut gas users are left

View File

@ -34,7 +34,7 @@ describe("Abilities - Pastel Veil", () => {
}); });
it("prevents the user and its allies from being afflicted by poison", async () => { it("prevents the user and its allies from being afflicted by poison", async () => {
await game.startBattle([Species.MAGIKARP, Species.GALAR_PONYTA]); await game.classicMode.startBattle([Species.MAGIKARP, Species.GALAR_PONYTA]);
const ponyta = game.scene.getPlayerField()[1]; const ponyta = game.scene.getPlayerField()[1];
const magikarp = game.scene.getPlayerField()[0]; const magikarp = game.scene.getPlayerField()[0];
ponyta.abilityIndex = 1; ponyta.abilityIndex = 1;
@ -50,7 +50,7 @@ describe("Abilities - Pastel Veil", () => {
}); });
it("it heals the poisoned status condition of allies if user is sent out into battle", async () => { it("it heals the poisoned status condition of allies if user is sent out into battle", async () => {
await game.startBattle([Species.MAGIKARP, Species.FEEBAS, Species.GALAR_PONYTA]); await game.classicMode.startBattle([Species.MAGIKARP, Species.FEEBAS, Species.GALAR_PONYTA]);
const ponyta = game.scene.getPlayerParty()[2]; const ponyta = game.scene.getPlayerParty()[2];
const magikarp = game.scene.getPlayerField()[0]; const magikarp = game.scene.getPlayerField()[0];
ponyta.abilityIndex = 1; ponyta.abilityIndex = 1;

View File

@ -64,14 +64,14 @@ describe("Abilities - Perish Song", () => {
const magikarp = game.scene.getEnemyPokemon(); const magikarp = game.scene.getEnemyPokemon();
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.PERISH_SONG); await game.move.selectEnemyMove(Moves.PERISH_SONG);
await game.toNextTurn(); await game.toNextTurn();
expect(feebas?.summonData.tags[0].turnCount).toBe(3); expect(feebas?.summonData.tags[0].turnCount).toBe(3);
expect(magikarp?.summonData.tags[0].turnCount).toBe(3); expect(magikarp?.summonData.tags[0].turnCount).toBe(3);
game.doSwitchPokemon(1); game.doSwitchPokemon(1);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
const cursola = game.scene.getPlayerPokemon(); const cursola = game.scene.getPlayerPokemon();
@ -79,7 +79,7 @@ describe("Abilities - Perish Song", () => {
expect(magikarp?.summonData.tags[0].turnCount).toBe(2); expect(magikarp?.summonData.tags[0].turnCount).toBe(2);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.AQUA_JET); await game.move.selectEnemyMove(Moves.AQUA_JET);
await game.toNextTurn(); await game.toNextTurn();
expect(cursola?.summonData.tags.length).toBe(0); expect(cursola?.summonData.tags.length).toBe(0);
@ -94,7 +94,7 @@ describe("Abilities - Perish Song", () => {
const cursola = game.scene.getPlayerPokemon(); const cursola = game.scene.getPlayerPokemon();
game.move.select(Moves.WHIRLWIND); game.move.select(Moves.WHIRLWIND);
await game.forceEnemyMove(Moves.PERISH_SONG); await game.move.selectEnemyMove(Moves.PERISH_SONG);
await game.toNextTurn(); await game.toNextTurn();
const magikarp = game.scene.getEnemyPokemon(); const magikarp = game.scene.getEnemyPokemon();
@ -102,7 +102,7 @@ describe("Abilities - Perish Song", () => {
expect(magikarp?.summonData.tags.length).toBe(0); expect(magikarp?.summonData.tags.length).toBe(0);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.AQUA_JET); await game.move.selectEnemyMove(Moves.AQUA_JET);
await game.toNextTurn(); await game.toNextTurn();
expect(cursola?.summonData.tags[0].turnCount).toBe(2); expect(cursola?.summonData.tags[0].turnCount).toBe(2);

View File

@ -39,7 +39,7 @@ describe("Abilities - Power Spot", () => {
vi.spyOn(moveToCheck, "calculateBattlePower"); vi.spyOn(moveToCheck, "calculateBattlePower");
await game.startBattle([Species.REGIELEKI, Species.STONJOURNER]); await game.classicMode.startBattle([Species.REGIELEKI, Species.STONJOURNER]);
game.move.select(Moves.DAZZLING_GLEAM); game.move.select(Moves.DAZZLING_GLEAM);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to(MoveEffectPhase); await game.phaseInterceptor.to(MoveEffectPhase);
@ -53,7 +53,7 @@ describe("Abilities - Power Spot", () => {
vi.spyOn(moveToCheck, "calculateBattlePower"); vi.spyOn(moveToCheck, "calculateBattlePower");
await game.startBattle([Species.REGIELEKI, Species.STONJOURNER]); await game.classicMode.startBattle([Species.REGIELEKI, Species.STONJOURNER]);
game.move.select(Moves.BREAKING_SWIPE); game.move.select(Moves.BREAKING_SWIPE);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to(MoveEffectPhase); await game.phaseInterceptor.to(MoveEffectPhase);
@ -67,7 +67,7 @@ describe("Abilities - Power Spot", () => {
vi.spyOn(moveToCheck, "calculateBattlePower"); vi.spyOn(moveToCheck, "calculateBattlePower");
await game.startBattle([Species.STONJOURNER, Species.REGIELEKI]); await game.classicMode.startBattle([Species.STONJOURNER, Species.REGIELEKI]);
game.move.select(Moves.BREAKING_SWIPE); game.move.select(Moves.BREAKING_SWIPE);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);

View File

@ -39,7 +39,7 @@ describe("Abilities - Protean", () => {
test("ability applies and changes a pokemon's type", async () => { test("ability applies and changes a pokemon's type", async () => {
game.override.moveset([Moves.SPLASH]); game.override.moveset([Moves.SPLASH]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -54,7 +54,7 @@ describe("Abilities - Protean", () => {
test.skip("ability applies only once per switch in", async () => { test.skip("ability applies only once per switch in", async () => {
game.override.moveset([Moves.SPLASH, Moves.AGILITY]); game.override.moveset([Moves.SPLASH, Moves.AGILITY]);
await game.startBattle([Species.MAGIKARP, Species.BULBASAUR]); await game.classicMode.startBattle([Species.MAGIKARP, Species.BULBASAUR]);
let leadPokemon = game.scene.getPlayerPokemon()!; let leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -90,7 +90,7 @@ describe("Abilities - Protean", () => {
test("ability applies correctly even if the pokemon's move has a variable type", async () => { test("ability applies correctly even if the pokemon's move has a variable type", async () => {
game.override.moveset([Moves.WEATHER_BALL]); game.override.moveset([Moves.WEATHER_BALL]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -110,7 +110,7 @@ describe("Abilities - Protean", () => {
game.override.moveset([Moves.TACKLE]); game.override.moveset([Moves.TACKLE]);
game.override.passiveAbility(Abilities.REFRIGERATE); game.override.passiveAbility(Abilities.REFRIGERATE);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -128,7 +128,7 @@ describe("Abilities - Protean", () => {
test("ability applies correctly even if the pokemon's move calls another move", async () => { test("ability applies correctly even if the pokemon's move calls another move", async () => {
game.override.moveset([Moves.NATURE_POWER]); game.override.moveset([Moves.NATURE_POWER]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -143,7 +143,7 @@ describe("Abilities - Protean", () => {
test("ability applies correctly even if the pokemon's move is delayed / charging", async () => { test("ability applies correctly even if the pokemon's move is delayed / charging", async () => {
game.override.moveset([Moves.DIG]); game.override.moveset([Moves.DIG]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -158,7 +158,7 @@ describe("Abilities - Protean", () => {
game.override.moveset([Moves.TACKLE]); game.override.moveset([Moves.TACKLE]);
game.override.enemyMoveset(Moves.SPLASH); game.override.enemyMoveset(Moves.SPLASH);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -176,7 +176,7 @@ describe("Abilities - Protean", () => {
game.override.moveset([Moves.TACKLE]); game.override.moveset([Moves.TACKLE]);
game.override.enemyMoveset([Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT]); game.override.enemyMoveset([Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -191,7 +191,7 @@ describe("Abilities - Protean", () => {
game.override.moveset([Moves.TACKLE]); game.override.moveset([Moves.TACKLE]);
game.override.enemySpecies(Species.GASTLY); game.override.enemySpecies(Species.GASTLY);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -205,7 +205,7 @@ describe("Abilities - Protean", () => {
test("ability is not applied if pokemon's type is the same as the move's type", async () => { test("ability is not applied if pokemon's type is the same as the move's type", async () => {
game.override.moveset([Moves.SPLASH]); game.override.moveset([Moves.SPLASH]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -220,7 +220,7 @@ describe("Abilities - Protean", () => {
test("ability is not applied if pokemon is terastallized", async () => { test("ability is not applied if pokemon is terastallized", async () => {
game.override.moveset([Moves.SPLASH]); game.override.moveset([Moves.SPLASH]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -236,7 +236,7 @@ describe("Abilities - Protean", () => {
test("ability is not applied if pokemon uses struggle", async () => { test("ability is not applied if pokemon uses struggle", async () => {
game.override.moveset([Moves.STRUGGLE]); game.override.moveset([Moves.STRUGGLE]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -250,7 +250,7 @@ describe("Abilities - Protean", () => {
test("ability is not applied if the pokemon's move fails", async () => { test("ability is not applied if the pokemon's move fails", async () => {
game.override.moveset([Moves.BURN_UP]); game.override.moveset([Moves.BURN_UP]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -265,7 +265,7 @@ describe("Abilities - Protean", () => {
game.override.moveset([Moves.TRICK_OR_TREAT]); game.override.moveset([Moves.TRICK_OR_TREAT]);
game.override.enemySpecies(Species.GASTLY); game.override.enemySpecies(Species.GASTLY);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);
@ -279,7 +279,7 @@ describe("Abilities - Protean", () => {
test("ability applies correctly and the pokemon curses itself", async () => { test("ability applies correctly and the pokemon curses itself", async () => {
game.override.moveset([Moves.CURSE]); game.override.moveset([Moves.CURSE]);
await game.startBattle([Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP]);
const leadPokemon = game.scene.getPlayerPokemon()!; const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined); expect(leadPokemon).not.toBe(undefined);

View File

@ -41,7 +41,7 @@ describe("Abilities - Quick Draw", () => {
}); });
test("makes pokemon going first in its priority bracket", async () => { test("makes pokemon going first in its priority bracket", async () => {
await game.startBattle(); await game.classicMode.startBattle();
const pokemon = game.scene.getPlayerPokemon()!; const pokemon = game.scene.getPlayerPokemon()!;
const enemy = game.scene.getEnemyPokemon()!; const enemy = game.scene.getEnemyPokemon()!;
@ -63,7 +63,7 @@ describe("Abilities - Quick Draw", () => {
retry: 5, retry: 5,
}, },
async () => { async () => {
await game.startBattle(); await game.classicMode.startBattle();
const pokemon = game.scene.getPlayerPokemon()!; const pokemon = game.scene.getPlayerPokemon()!;
const enemy = game.scene.getEnemyPokemon()!; const enemy = game.scene.getEnemyPokemon()!;
@ -83,7 +83,7 @@ describe("Abilities - Quick Draw", () => {
test("does not increase priority", async () => { test("does not increase priority", async () => {
game.override.enemyMoveset([Moves.EXTREME_SPEED]); game.override.enemyMoveset([Moves.EXTREME_SPEED]);
await game.startBattle(); await game.classicMode.startBattle();
const pokemon = game.scene.getPlayerPokemon()!; const pokemon = game.scene.getPlayerPokemon()!;
const enemy = game.scene.getEnemyPokemon()!; const enemy = game.scene.getEnemyPokemon()!;

View File

@ -38,7 +38,7 @@ describe("Abilities - Sand Veil", () => {
}); });
test("ability should increase the evasiveness of the source", async () => { test("ability should increase the evasiveness of the source", async () => {
await game.startBattle([Species.SNORLAX, Species.BLISSEY]); await game.classicMode.startBattle([Species.SNORLAX, Species.BLISSEY]);
const leadPokemon = game.scene.getPlayerField(); const leadPokemon = game.scene.getPlayerField();

View File

@ -39,7 +39,7 @@ describe("Abilities - SCHOOLING", () => {
[Species.WISHIWASHI]: schoolForm, [Species.WISHIWASHI]: schoolForm,
}); });
await game.startBattle([Species.MAGIKARP, Species.WISHIWASHI]); await game.classicMode.startBattle([Species.MAGIKARP, Species.WISHIWASHI]);
const wishiwashi = game.scene.getPlayerParty().find(p => p.species.speciesId === Species.WISHIWASHI)!; const wishiwashi = game.scene.getPlayerParty().find(p => p.species.speciesId === Species.WISHIWASHI)!;
expect(wishiwashi).not.toBe(undefined); expect(wishiwashi).not.toBe(undefined);

View File

@ -33,7 +33,7 @@ describe("Abilities - Screen Cleaner", () => {
game.override.moveset([Moves.HAIL]); game.override.moveset([Moves.HAIL]);
game.override.enemyMoveset([Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL]); game.override.enemyMoveset([Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL]);
await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP, Species.MAGIKARP]);
game.move.select(Moves.HAIL); game.move.select(Moves.HAIL);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
@ -50,7 +50,7 @@ describe("Abilities - Screen Cleaner", () => {
it("removes Light Screen", async () => { it("removes Light Screen", async () => {
game.override.enemyMoveset([Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN]); game.override.enemyMoveset([Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN]);
await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP, Species.MAGIKARP]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
@ -67,7 +67,7 @@ describe("Abilities - Screen Cleaner", () => {
it("removes Reflect", async () => { it("removes Reflect", async () => {
game.override.enemyMoveset([Moves.REFLECT, Moves.REFLECT, Moves.REFLECT, Moves.REFLECT]); game.override.enemyMoveset([Moves.REFLECT, Moves.REFLECT, Moves.REFLECT, Moves.REFLECT]);
await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); await game.classicMode.startBattle([Species.MAGIKARP, Species.MAGIKARP]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);

View File

@ -76,7 +76,7 @@ describe("Abilities - SHIELDS DOWN", () => {
await game.classicMode.startBattle([Species.MINIOR]); await game.classicMode.startBattle([Species.MINIOR]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.SPORE); await game.move.selectEnemyMove(Moves.SPORE);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
expect(game.scene.getPlayerPokemon()!.status).toBe(undefined); expect(game.scene.getPlayerPokemon()!.status).toBe(undefined);
@ -115,12 +115,12 @@ describe("Abilities - SHIELDS DOWN", () => {
// turn 1 // turn 1
game.move.select(Moves.GRAVITY); game.move.select(Moves.GRAVITY);
await game.forceEnemyMove(Moves.TOXIC_SPIKES); await game.move.selectEnemyMove(Moves.TOXIC_SPIKES);
await game.toNextTurn(); await game.toNextTurn();
// turn 2 // turn 2
game.doSwitchPokemon(1); game.doSwitchPokemon(1);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(Species.MINIOR); expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(Species.MINIOR);
@ -134,7 +134,7 @@ describe("Abilities - SHIELDS DOWN", () => {
await game.classicMode.startBattle([Species.MAGIKARP, Species.MINIOR]); await game.classicMode.startBattle([Species.MAGIKARP, Species.MINIOR]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.YAWN); await game.move.selectEnemyMove(Moves.YAWN);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
expect(game.scene.getPlayerPokemon()!.findTag(tag => tag.tagType === BattlerTagType.DROWSY)).toBe(undefined); expect(game.scene.getPlayerPokemon()!.findTag(tag => tag.tagType === BattlerTagType.DROWSY)).toBe(undefined);
@ -146,7 +146,7 @@ describe("Abilities - SHIELDS DOWN", () => {
await game.classicMode.startBattle([Species.MINIOR]); await game.classicMode.startBattle([Species.MINIOR]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.CONFUSE_RAY); await game.move.selectEnemyMove(Moves.CONFUSE_RAY);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
@ -162,7 +162,7 @@ describe("Abilities - SHIELDS DOWN", () => {
await game.classicMode.startBattle([Species.MINIOR]); await game.classicMode.startBattle([Species.MINIOR]);
game.move.select(Moves.SPORE); game.move.select(Moves.SPORE);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.SLEEP); expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.SLEEP);

View File

@ -31,7 +31,7 @@ describe("Abilities - Simple", () => {
}); });
it("should double stat changes when applied", async () => { it("should double stat changes when applied", async () => {
await game.startBattle([Species.SLOWBRO]); await game.classicMode.startBattle([Species.SLOWBRO]);
const enemyPokemon = game.scene.getEnemyPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!;

View File

@ -42,7 +42,7 @@ describe("Abilities - Stakeout", () => {
const [enemy1] = game.scene.getEnemyParty(); const [enemy1] = game.scene.getEnemyParty();
game.move.select(Moves.SURF); game.move.select(Moves.SURF);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
const damage1 = enemy1.getInverseHp(); const damage1 = enemy1.getInverseHp();
enemy1.hp = enemy1.getMaxHp(); enemy1.hp = enemy1.getMaxHp();
@ -65,17 +65,17 @@ describe("Abilities - Stakeout", () => {
const [enemy1] = game.scene.getEnemyParty(); const [enemy1] = game.scene.getEnemyParty();
game.move.select(Moves.SURF); game.move.select(Moves.SURF);
await game.forceEnemyMove(Moves.SPLASH); await game.move.selectEnemyMove(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
const damage1 = enemy1.getInverseHp(); const damage1 = enemy1.getInverseHp();
enemy1.hp = enemy1.getMaxHp(); enemy1.hp = enemy1.getMaxHp();
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.forceEnemyMove(Moves.FLIP_TURN); await game.move.selectEnemyMove(Moves.FLIP_TURN);
await game.toNextTurn(); await game.toNextTurn();
game.move.select(Moves.SURF); game.move.select(Moves.SURF);
await game.forceEnemyMove(Moves.FLIP_TURN); await game.move.selectEnemyMove(Moves.FLIP_TURN);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.toNextTurn(); await game.toNextTurn();

View File

@ -37,7 +37,7 @@ describe("Abilities - Stall", () => {
**/ **/
it("Pokemon with Stall should move last in its priority bracket regardless of speed", async () => { it("Pokemon with Stall should move last in its priority bracket regardless of speed", async () => {
await game.startBattle([Species.SHUCKLE]); await game.classicMode.startBattle([Species.SHUCKLE]);
const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
@ -55,7 +55,7 @@ describe("Abilities - Stall", () => {
}, 20000); }, 20000);
it("Pokemon with Stall will go first if a move that is in a higher priority bracket than the opponent's move is used", async () => { it("Pokemon with Stall will go first if a move that is in a higher priority bracket than the opponent's move is used", async () => {
await game.startBattle([Species.SHUCKLE]); await game.classicMode.startBattle([Species.SHUCKLE]);
const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
@ -74,7 +74,7 @@ describe("Abilities - Stall", () => {
it("If both Pokemon have stall and use the same move, speed is used to determine who goes first.", async () => { it("If both Pokemon have stall and use the same move, speed is used to determine who goes first.", async () => {
game.override.ability(Abilities.STALL); game.override.ability(Abilities.STALL);
await game.startBattle([Species.SHUCKLE]); await game.classicMode.startBattle([Species.SHUCKLE]);
const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();

View File

@ -36,14 +36,14 @@ describe("Abilities - Sturdy", () => {
}); });
test("Sturdy activates when user is at full HP", async () => { test("Sturdy activates when user is at full HP", async () => {
await game.startBattle(); await game.classicMode.startBattle();
game.move.select(Moves.CLOSE_COMBAT); game.move.select(Moves.CLOSE_COMBAT);
await game.phaseInterceptor.to(MoveEndPhase); await game.phaseInterceptor.to(MoveEndPhase);
expect(game.scene.getEnemyParty()[0].hp).toBe(1); expect(game.scene.getEnemyParty()[0].hp).toBe(1);
}); });
test("Sturdy doesn't activate when user is not at full HP", async () => { test("Sturdy doesn't activate when user is not at full HP", async () => {
await game.startBattle(); await game.classicMode.startBattle();
const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0];
enemyPokemon.hp = enemyPokemon.getMaxHp() - 1; enemyPokemon.hp = enemyPokemon.getMaxHp() - 1;
@ -56,7 +56,7 @@ describe("Abilities - Sturdy", () => {
}); });
test("Sturdy pokemon should be immune to OHKO moves", async () => { test("Sturdy pokemon should be immune to OHKO moves", async () => {
await game.startBattle(); await game.classicMode.startBattle();
game.move.select(Moves.FISSURE); game.move.select(Moves.FISSURE);
await game.phaseInterceptor.to(MoveEndPhase); await game.phaseInterceptor.to(MoveEndPhase);
@ -67,7 +67,7 @@ describe("Abilities - Sturdy", () => {
test("Sturdy is ignored by pokemon with `Abilities.MOLD_BREAKER`", async () => { test("Sturdy is ignored by pokemon with `Abilities.MOLD_BREAKER`", async () => {
game.override.ability(Abilities.MOLD_BREAKER); game.override.ability(Abilities.MOLD_BREAKER);
await game.startBattle(); await game.classicMode.startBattle();
game.move.select(Moves.CLOSE_COMBAT); game.move.select(Moves.CLOSE_COMBAT);
await game.phaseInterceptor.to(DamageAnimPhase); await game.phaseInterceptor.to(DamageAnimPhase);

View File

@ -44,7 +44,7 @@ describe("Abilities - Supreme Overlord", () => {
}); });
it("should increase Power by 20% if 2 Pokemon are fainted in the party", async () => { it("should increase Power by 20% if 2 Pokemon are fainted in the party", async () => {
await game.startBattle([Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE]); await game.classicMode.startBattle([Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE]);
game.move.select(Moves.EXPLOSION); game.move.select(Moves.EXPLOSION);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);

View File

@ -33,7 +33,7 @@ describe("Abilities - Sweet Veil", () => {
}); });
it("prevents the user and its allies from falling asleep", async () => { it("prevents the user and its allies from falling asleep", async () => {
await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]); await game.classicMode.startBattle([Species.SWIRLIX, Species.MAGIKARP]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
@ -45,7 +45,7 @@ describe("Abilities - Sweet Veil", () => {
it("causes Rest to fail when used by the user or its allies", async () => { it("causes Rest to fail when used by the user or its allies", async () => {
game.override.enemyMoveset(Moves.SPLASH); game.override.enemyMoveset(Moves.SPLASH);
await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]); await game.classicMode.startBattle([Species.SWIRLIX, Species.MAGIKARP]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.REST, 1); game.move.select(Moves.REST, 1);
@ -57,7 +57,7 @@ describe("Abilities - Sweet Veil", () => {
it("causes Yawn to fail if used on the user or its allies", async () => { it("causes Yawn to fail if used on the user or its allies", async () => {
game.override.enemyMoveset([Moves.YAWN, Moves.YAWN, Moves.YAWN, Moves.YAWN]); game.override.enemyMoveset([Moves.YAWN, Moves.YAWN, Moves.YAWN, Moves.YAWN]);
await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]); await game.classicMode.startBattle([Species.SWIRLIX, Species.MAGIKARP]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1); game.move.select(Moves.SPLASH, 1);
@ -73,7 +73,7 @@ describe("Abilities - Sweet Veil", () => {
game.override.startingLevel(5); game.override.startingLevel(5);
game.override.enemyMoveset(Moves.SPLASH); game.override.enemyMoveset(Moves.SPLASH);
await game.startBattle([Species.SHUCKLE, Species.SHUCKLE, Species.SWIRLIX]); await game.classicMode.startBattle([Species.SHUCKLE, Species.SHUCKLE, Species.SWIRLIX]);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
game.move.select(Moves.YAWN, 1, BattlerIndex.PLAYER); game.move.select(Moves.YAWN, 1, BattlerIndex.PLAYER);

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