diff --git a/package-lock.json b/package-lock.json index 52cc628872a..676539af79e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pokemon-rogue-battle", - "version": "1.4.3", + "version": "1.5.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pokemon-rogue-battle", - "version": "1.4.3", + "version": "1.5.2", "hasInstallScript": true, "dependencies": { "@material/material-color-utilities": "^0.2.7", diff --git a/package.json b/package.json index e52c5928da7..81f01e1d482 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.4.3", + "version": "1.5.2", "type": "module", "scripts": { "start": "vite", diff --git a/public/audio/bgm/title.mp3 b/public/audio/bgm/title.mp3 index 86d4be0da35..8ad451a52a9 100644 Binary files a/public/audio/bgm/title.mp3 and b/public/audio/bgm/title.mp3 differ diff --git a/public/fonts/pokemon-emerald-pro.ttf b/public/fonts/pokemon-emerald-pro.ttf index e4ee49dbff3..758130172c7 100644 Binary files a/public/fonts/pokemon-emerald-pro.ttf and b/public/fonts/pokemon-emerald-pro.ttf differ diff --git a/public/images/events/yearofthesnakeevent-de.png b/public/images/events/yearofthesnakeevent-de.png new file mode 100644 index 00000000000..f5e684bbcd5 Binary files /dev/null and b/public/images/events/yearofthesnakeevent-de.png differ diff --git a/public/images/events/yearofthesnakeevent-en.png b/public/images/events/yearofthesnakeevent-en.png new file mode 100644 index 00000000000..ddd34023b94 Binary files /dev/null and b/public/images/events/yearofthesnakeevent-en.png differ diff --git a/public/images/events/yearofthesnakeevent-es-ES.png b/public/images/events/yearofthesnakeevent-es-ES.png new file mode 100644 index 00000000000..76474c475c5 Binary files /dev/null and b/public/images/events/yearofthesnakeevent-es-ES.png differ diff --git a/public/images/events/yearofthesnakeevent-fr.png b/public/images/events/yearofthesnakeevent-fr.png new file mode 100644 index 00000000000..88ad3e770ca Binary files /dev/null and b/public/images/events/yearofthesnakeevent-fr.png differ diff --git a/public/images/events/yearofthesnakeevent-it.png b/public/images/events/yearofthesnakeevent-it.png new file mode 100644 index 00000000000..a02e7048d2a Binary files /dev/null and b/public/images/events/yearofthesnakeevent-it.png differ diff --git a/public/images/events/yearofthesnakeevent-ja.png b/public/images/events/yearofthesnakeevent-ja.png new file mode 100644 index 00000000000..ba13b5d281f Binary files /dev/null and b/public/images/events/yearofthesnakeevent-ja.png differ diff --git a/public/images/events/yearofthesnakeevent-ko.png b/public/images/events/yearofthesnakeevent-ko.png new file mode 100644 index 00000000000..dca6bcbbd15 Binary files /dev/null and b/public/images/events/yearofthesnakeevent-ko.png differ diff --git a/public/images/events/yearofthesnakeevent-pt-BR.png b/public/images/events/yearofthesnakeevent-pt-BR.png new file mode 100644 index 00000000000..a535aec2aa5 Binary files /dev/null and b/public/images/events/yearofthesnakeevent-pt-BR.png differ diff --git a/public/images/events/yearofthesnakeevent-zh-CN.png b/public/images/events/yearofthesnakeevent-zh-CN.png new file mode 100644 index 00000000000..3ab4fc565a7 Binary files /dev/null and b/public/images/events/yearofthesnakeevent-zh-CN.png differ diff --git a/public/images/pokemon/back/249.json b/public/images/pokemon/back/249.json index 52784b825f8..7f126e8c62c 100644 --- a/public/images/pokemon/back/249.json +++ b/public/images/pokemon/back/249.json @@ -1,2540 +1,686 @@ -{ - "textures": [ - { - "image": "249.png", - "format": "RGBA8888", - "size": { - "w": 610, - "h": 610 - }, - "scale": 1, - "frames": [ - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 25, - "y": 5, - "w": 99, - "h": 88 - }, - "frame": { - "x": 230, - "y": 137, - "w": 99, - "h": 88 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 5, - "w": 99, - "h": 88 - }, - "frame": { - "x": 329, - "y": 141, - "w": 99, - "h": 88 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 26, - "y": 0, - "w": 84, - "h": 97 - }, - "frame": { - "x": 526, - "y": 141, - "w": 84, - "h": 97 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 27, - "y": 4, - "w": 96, - "h": 89 - }, - "frame": { - "x": 0, - "y": 216, - "w": 96, - "h": 89 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 25, - "y": 4, - "w": 96, - "h": 89 - }, - "frame": { - "x": 96, - "y": 222, - "w": 96, - "h": 89 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 7, - "w": 95, - "h": 90 - }, - "frame": { - "x": 290, - "y": 229, - "w": 95, - "h": 90 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 7, - "w": 95, - "h": 90 - }, - "frame": { - "x": 290, - "y": 229, - "w": 95, - "h": 90 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 4, - "w": 95, - "h": 90 - }, - "frame": { - "x": 385, - "y": 230, - "w": 95, - "h": 90 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 6, - "w": 95, - "h": 91 - }, - "frame": { - "x": 95, - "y": 311, - "w": 95, - "h": 91 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 32, - "y": 2, - "w": 92, - "h": 91 - }, - "frame": { - "x": 190, - "y": 315, - "w": 92, - "h": 91 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 32, - "y": 2, - "w": 92, - "h": 91 - }, - "frame": { - "x": 190, - "y": 315, - "w": 92, - "h": 91 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 16, - "y": 5, - "w": 101, - "h": 91 - }, - "frame": { - "x": 282, - "y": 319, - "w": 101, - "h": 91 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 5, - "w": 94, - "h": 92 - }, - "frame": { - "x": 383, - "y": 320, - "w": 94, - "h": 92 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 16, - "y": 4, - "w": 100, - "h": 92 - }, - "frame": { - "x": 477, - "y": 329, - "w": 100, - "h": 92 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 94, - "h": 92 - }, - "frame": { - "x": 0, - "y": 396, - "w": 94, - "h": 92 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 29, - "y": 2, - "w": 91, - "h": 92 - }, - "frame": { - "x": 94, - "y": 402, - "w": 91, - "h": 92 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 29, - "y": 2, - "w": 91, - "h": 92 - }, - "frame": { - "x": 94, - "y": 402, - "w": 91, - "h": 92 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 2, - "w": 92, - "h": 92 - }, - "frame": { - "x": 185, - "y": 406, - "w": 92, - "h": 92 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 6, - "w": 96, - "h": 92 - }, - "frame": { - "x": 277, - "y": 410, - "w": 96, - "h": 92 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 2, - "w": 92, - "h": 93 - }, - "frame": { - "x": 465, - "y": 421, - "w": 92, - "h": 93 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 4, - "w": 93, - "h": 94 - }, - "frame": { - "x": 0, - "y": 488, - "w": 93, - "h": 94 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 1, - "w": 90, - "h": 95 - }, - "frame": { - "x": 93, - "y": 494, - "w": 90, - "h": 95 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 1, - "w": 90, - "h": 95 - }, - "frame": { - "x": 93, - "y": 494, - "w": 90, - "h": 95 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 3, - "w": 93, - "h": 95 - }, - "frame": { - "x": 183, - "y": 498, - "w": 93, - "h": 95 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 0, - "w": 86, - "h": 96 - }, - "frame": { - "x": 276, - "y": 502, - "w": 86, - "h": 96 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 0, - "w": 86, - "h": 96 - }, - "frame": { - "x": 276, - "y": 502, - "w": 86, - "h": 96 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 1, - "w": 90, - "h": 96 - }, - "frame": { - "x": 362, - "y": 505, - "w": 90, - "h": 96 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 2, - "w": 90, - "h": 96 - }, - "frame": { - "x": 452, - "y": 514, - "w": 90, - "h": 96 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:d1fca3cca7f334c5072e6d9eac438f12:ad4656a8607db0b15f07d4c8860395b7:25c89a8ec37b43392b53a70993acdff3$" - } +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 284, "y": 81, "w": 96, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 11, "w": 96, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0002.png", + "frame": { "x": 690, "y": 66, "w": 103, "h": 86 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 18, "y": 14, "w": 103, "h": 86 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0003.png", + "frame": { "x": 554, "y": 0, "w": 136, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 33, "w": 136, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0004.png", + "frame": { "x": 143, "y": 69, "w": 141, "h": 63 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 40, "w": 141, "h": 63 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0005.png", + "frame": { "x": 409, "y": 0, "w": 145, "h": 65 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 38, "w": 145, "h": 65 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0006.png", + "frame": { "x": 143, "y": 0, "w": 144, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 33, "w": 144, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0007.png", + "frame": { "x": 0, "y": 0, "w": 143, "h": 71 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 30, "w": 143, "h": 71 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0008.png", + "frame": { "x": 409, "y": 65, "w": 131, "h": 68 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 32, "w": 131, "h": 68 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0009.png", + "frame": { "x": 540, "y": 69, "w": 134, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 33, "w": 134, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0010.png", + "frame": { "x": 690, "y": 0, "w": 139, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 32, "w": 139, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0011.png", + "frame": { "x": 287, "y": 0, "w": 122, "h": 81 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 122, "h": 81 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0012.png", + "frame": { "x": 380, "y": 133, "w": 96, "h": 87 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 10, "w": 96, "h": 87 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0013.png", + "frame": { "x": 573, "y": 135, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 7, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0014.png", + "frame": { "x": 653, "y": 242, "w": 90, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 7, "w": 90, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0015.png", + "frame": { "x": 665, "y": 152, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 8, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0016.png", + "frame": { "x": 284, "y": 81, "w": 96, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 11, "w": 96, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0017.png", + "frame": { "x": 690, "y": 66, "w": 103, "h": 86 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 18, "y": 14, "w": 103, "h": 86 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0018.png", + "frame": { "x": 554, "y": 0, "w": 136, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 33, "w": 136, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0019.png", + "frame": { "x": 143, "y": 69, "w": 141, "h": 63 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 40, "w": 141, "h": 63 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0020.png", + "frame": { "x": 409, "y": 0, "w": 145, "h": 65 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 38, "w": 145, "h": 65 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0021.png", + "frame": { "x": 143, "y": 0, "w": 144, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 33, "w": 144, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0022.png", + "frame": { "x": 0, "y": 0, "w": 143, "h": 71 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 30, "w": 143, "h": 71 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0023.png", + "frame": { "x": 409, "y": 65, "w": 131, "h": 68 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 32, "w": 131, "h": 68 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0024.png", + "frame": { "x": 540, "y": 69, "w": 134, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 33, "w": 134, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0025.png", + "frame": { "x": 690, "y": 0, "w": 139, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 32, "w": 139, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0026.png", + "frame": { "x": 287, "y": 0, "w": 122, "h": 81 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 122, "h": 81 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0027.png", + "frame": { "x": 380, "y": 133, "w": 96, "h": 87 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 10, "w": 96, "h": 87 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0028.png", + "frame": { "x": 573, "y": 135, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 7, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0029.png", + "frame": { "x": 653, "y": 242, "w": 90, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 7, "w": 90, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0030.png", + "frame": { "x": 665, "y": 152, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 8, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0031.png", + "frame": { "x": 284, "y": 81, "w": 96, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 11, "w": 96, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0032.png", + "frame": { "x": 690, "y": 66, "w": 103, "h": 86 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 18, "y": 14, "w": 103, "h": 86 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0033.png", + "frame": { "x": 554, "y": 0, "w": 136, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 33, "w": 136, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0034.png", + "frame": { "x": 143, "y": 69, "w": 141, "h": 63 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 40, "w": 141, "h": 63 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0035.png", + "frame": { "x": 409, "y": 0, "w": 145, "h": 65 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 38, "w": 145, "h": 65 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0036.png", + "frame": { "x": 143, "y": 0, "w": 144, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 33, "w": 144, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0037.png", + "frame": { "x": 0, "y": 0, "w": 143, "h": 71 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 30, "w": 143, "h": 71 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0038.png", + "frame": { "x": 409, "y": 65, "w": 131, "h": 68 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 32, "w": 131, "h": 68 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0039.png", + "frame": { "x": 540, "y": 69, "w": 134, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 33, "w": 134, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0040.png", + "frame": { "x": 690, "y": 0, "w": 139, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 32, "w": 139, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0041.png", + "frame": { "x": 287, "y": 0, "w": 122, "h": 81 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 122, "h": 81 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0042.png", + "frame": { "x": 380, "y": 133, "w": 96, "h": 87 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 10, "w": 96, "h": 87 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0043.png", + "frame": { "x": 573, "y": 135, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 7, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0044.png", + "frame": { "x": 653, "y": 242, "w": 90, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 7, "w": 90, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0045.png", + "frame": { "x": 665, "y": 152, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 8, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0046.png", + "frame": { "x": 284, "y": 81, "w": 96, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 11, "w": 96, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + }, + { + "filename": "0047.png", + "frame": { "x": 0, "y": 161, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 9, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0048.png", + "frame": { "x": 374, "y": 220, "w": 93, "h": 89 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 10, "w": 93, "h": 89 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0049.png", + "frame": { "x": 832, "y": 275, "w": 89, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 8, "w": 89, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0050.png", + "frame": { "x": 282, "y": 169, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 9, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0051.png", + "frame": { "x": 191, "y": 132, "w": 91, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 8, "w": 91, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0052.png", + "frame": { "x": 0, "y": 71, "w": 98, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 17, "y": 8, "w": 98, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0053.png", + "frame": { "x": 829, "y": 0, "w": 97, "h": 92 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 17, "y": 6, "w": 97, "h": 92 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0054.png", + "frame": { "x": 92, "y": 222, "w": 90, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 6, "w": 90, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0055.png", + "frame": { "x": 926, "y": 0, "w": 89, "h": 92 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 5, "w": 89, "h": 92 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + }, + { + "filename": "0056.png", + "frame": { "x": 90, "y": 313, "w": 88, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 30, "y": 5, "w": 88, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + }, + { + "filename": "0057.png", + "frame": { "x": 0, "y": 251, "w": 90, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 30, "y": 6, "w": 90, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0058.png", + "frame": { "x": 743, "y": 271, "w": 89, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 33, "y": 4, "w": 89, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0059.png", + "frame": { "x": 98, "y": 132, "w": 93, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 31, "y": 5, "w": 93, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0060.png", + "frame": { "x": 182, "y": 223, "w": 93, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 28, "y": 7, "w": 93, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0061.png", + "frame": { "x": 793, "y": 92, "w": 97, "h": 87 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 8, "w": 97, "h": 87 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0062.png", + "frame": { "x": 476, "y": 135, "w": 97, "h": 86 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 9, "w": 97, "h": 86 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0063.png", + "frame": { "x": 560, "y": 225, "w": 93, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 7, "w": 93, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0064.png", + "frame": { "x": 467, "y": 221, "w": 93, "h": 89 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 7, "w": 93, "h": 89 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0065.png", + "frame": { "x": 275, "y": 259, "w": 89, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 25, "y": 5, "w": 89, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + }, + { + "filename": "0066.png", + "frame": { "x": 921, "y": 275, "w": 87, "h": 93 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 4, "w": 87, "h": 93 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + }, + { + "filename": "0067.png", + "frame": { "x": 536, "y": 313, "w": 83, "h": 95 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 2, "w": 83, "h": 95 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0068.png", + "frame": { "x": 182, "y": 311, "w": 84, "h": 96 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 1, "w": 84, "h": 96 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0069.png", + "frame": { "x": 0, "y": 341, "w": 80, "h": 97 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 80, "h": 97 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0070.png", + "frame": { "x": 619, "y": 332, "w": 81, "h": 96 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 27, "y": 2, "w": 81, "h": 96 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0071.png", + "frame": { "x": 364, "y": 309, "w": 86, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 4, "w": 86, "h": 94 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0072.png", + "frame": { "x": 450, "y": 310, "w": 86, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 25, "y": 5, "w": 86, "h": 94 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0073.png", + "frame": { "x": 757, "y": 179, "w": 90, "h": 92 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 7, "w": 90, "h": 92 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0074.png", + "frame": { "x": 847, "y": 183, "w": 90, "h": 92 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 7, "w": 90, "h": 92 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0075.png", + "frame": { "x": 890, "y": 92, "w": 92, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 8, "w": 92, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.9.2-x64", + "image": "249.png", + "format": "I8", + "size": { "w": 1015, "h": 438 }, + "scale": "1" + } } diff --git a/public/images/pokemon/back/249.png b/public/images/pokemon/back/249.png index e08ce361804..181c7076e5d 100644 Binary files a/public/images/pokemon/back/249.png and b/public/images/pokemon/back/249.png differ diff --git a/public/images/pokemon/back/shiny/249.json b/public/images/pokemon/back/shiny/249.json index 7512f163c15..7f126e8c62c 100644 --- a/public/images/pokemon/back/shiny/249.json +++ b/public/images/pokemon/back/shiny/249.json @@ -1,2540 +1,686 @@ -{ - "textures": [ - { - "image": "249.png", - "format": "RGBA8888", - "size": { - "w": 610, - "h": 610 - }, - "scale": 1, - "frames": [ - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 36, - "w": 143, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 143, - "h": 64 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 35, - "w": 146, - "h": 65 - }, - "frame": { - "x": 143, - "y": 0, - "w": 146, - "h": 65 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 30, - "w": 132, - "h": 67 - }, - "frame": { - "x": 289, - "y": 0, - "w": 132, - "h": 67 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 28, - "w": 140, - "h": 68 - }, - "frame": { - "x": 421, - "y": 0, - "w": 140, - "h": 68 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 2, - "y": 30, - "w": 138, - "h": 70 - }, - "frame": { - "x": 0, - "y": 64, - "w": 138, - "h": 70 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 0, - "y": 30, - "w": 146, - "h": 70 - }, - "frame": { - "x": 138, - "y": 65, - "w": 146, - "h": 70 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 10, - "y": 28, - "w": 130, - "h": 70 - }, - "frame": { - "x": 284, - "y": 67, - "w": 130, - "h": 70 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 1, - "y": 26, - "w": 145, - "h": 73 - }, - "frame": { - "x": 414, - "y": 68, - "w": 145, - "h": 73 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 7, - "y": 13, - "w": 124, - "h": 82 - }, - "frame": { - "x": 0, - "y": 134, - "w": 124, - "h": 82 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 17, - "y": 11, - "w": 106, - "h": 87 - }, - "frame": { - "x": 124, - "y": 135, - "w": 106, - "h": 87 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 25, - "y": 5, - "w": 99, - "h": 88 - }, - "frame": { - "x": 230, - "y": 137, - "w": 99, - "h": 88 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 5, - "w": 99, - "h": 88 - }, - "frame": { - "x": 329, - "y": 141, - "w": 99, - "h": 88 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 6, - "w": 98, - "h": 89 - }, - "frame": { - "x": 428, - "y": 141, - "w": 98, - "h": 89 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 26, - "y": 0, - "w": 84, - "h": 97 - }, - "frame": { - "x": 526, - "y": 141, - "w": 84, - "h": 97 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 27, - "y": 4, - "w": 96, - "h": 89 - }, - "frame": { - "x": 0, - "y": 216, - "w": 96, - "h": 89 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 25, - "y": 4, - "w": 96, - "h": 89 - }, - "frame": { - "x": 96, - "y": 222, - "w": 96, - "h": 89 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 20, - "y": 7, - "w": 98, - "h": 90 - }, - "frame": { - "x": 192, - "y": 225, - "w": 98, - "h": 90 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 7, - "w": 95, - "h": 90 - }, - "frame": { - "x": 290, - "y": 229, - "w": 95, - "h": 90 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 7, - "w": 95, - "h": 90 - }, - "frame": { - "x": 290, - "y": 229, - "w": 95, - "h": 90 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 4, - "w": 95, - "h": 90 - }, - "frame": { - "x": 385, - "y": 230, - "w": 95, - "h": 90 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 4, - "w": 95, - "h": 91 - }, - "frame": { - "x": 480, - "y": 238, - "w": 95, - "h": 91 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 95, - "h": 91 - }, - "frame": { - "x": 0, - "y": 305, - "w": 95, - "h": 91 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 6, - "w": 95, - "h": 91 - }, - "frame": { - "x": 95, - "y": 311, - "w": 95, - "h": 91 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 32, - "y": 2, - "w": 92, - "h": 91 - }, - "frame": { - "x": 190, - "y": 315, - "w": 92, - "h": 91 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 32, - "y": 2, - "w": 92, - "h": 91 - }, - "frame": { - "x": 190, - "y": 315, - "w": 92, - "h": 91 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 16, - "y": 5, - "w": 101, - "h": 91 - }, - "frame": { - "x": 282, - "y": 319, - "w": 101, - "h": 91 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 5, - "w": 94, - "h": 92 - }, - "frame": { - "x": 383, - "y": 320, - "w": 94, - "h": 92 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 16, - "y": 4, - "w": 100, - "h": 92 - }, - "frame": { - "x": 477, - "y": 329, - "w": 100, - "h": 92 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 94, - "h": 92 - }, - "frame": { - "x": 0, - "y": 396, - "w": 94, - "h": 92 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 29, - "y": 2, - "w": 91, - "h": 92 - }, - "frame": { - "x": 94, - "y": 402, - "w": 91, - "h": 92 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 29, - "y": 2, - "w": 91, - "h": 92 - }, - "frame": { - "x": 94, - "y": 402, - "w": 91, - "h": 92 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 2, - "w": 92, - "h": 92 - }, - "frame": { - "x": 185, - "y": 406, - "w": 92, - "h": 92 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 6, - "w": 96, - "h": 92 - }, - "frame": { - "x": 277, - "y": 410, - "w": 96, - "h": 92 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 3, - "w": 92, - "h": 93 - }, - "frame": { - "x": 373, - "y": 412, - "w": 92, - "h": 93 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 2, - "w": 92, - "h": 93 - }, - "frame": { - "x": 465, - "y": 421, - "w": 92, - "h": 93 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 4, - "w": 93, - "h": 94 - }, - "frame": { - "x": 0, - "y": 488, - "w": 93, - "h": 94 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 1, - "w": 90, - "h": 95 - }, - "frame": { - "x": 93, - "y": 494, - "w": 90, - "h": 95 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 1, - "w": 90, - "h": 95 - }, - "frame": { - "x": 93, - "y": 494, - "w": 90, - "h": 95 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 22, - "y": 3, - "w": 93, - "h": 95 - }, - "frame": { - "x": 183, - "y": 498, - "w": 93, - "h": 95 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 0, - "w": 86, - "h": 96 - }, - "frame": { - "x": 276, - "y": 502, - "w": 86, - "h": 96 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 0, - "w": 86, - "h": 96 - }, - "frame": { - "x": 276, - "y": 502, - "w": 86, - "h": 96 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 23, - "y": 1, - "w": 90, - "h": 96 - }, - "frame": { - "x": 362, - "y": 505, - "w": 90, - "h": 96 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 146, - "h": 100 - }, - "spriteSourceSize": { - "x": 24, - "y": 2, - "w": 90, - "h": 96 - }, - "frame": { - "x": 452, - "y": 514, - "w": 90, - "h": 96 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:d7da4020739cd4d93722302e0d6f99c6:d519731f31735f11bbba940400858c46:25c89a8ec37b43392b53a70993acdff3$" - } +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 284, "y": 81, "w": 96, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 11, "w": 96, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0002.png", + "frame": { "x": 690, "y": 66, "w": 103, "h": 86 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 18, "y": 14, "w": 103, "h": 86 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0003.png", + "frame": { "x": 554, "y": 0, "w": 136, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 33, "w": 136, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0004.png", + "frame": { "x": 143, "y": 69, "w": 141, "h": 63 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 40, "w": 141, "h": 63 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0005.png", + "frame": { "x": 409, "y": 0, "w": 145, "h": 65 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 38, "w": 145, "h": 65 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0006.png", + "frame": { "x": 143, "y": 0, "w": 144, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 33, "w": 144, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0007.png", + "frame": { "x": 0, "y": 0, "w": 143, "h": 71 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 30, "w": 143, "h": 71 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0008.png", + "frame": { "x": 409, "y": 65, "w": 131, "h": 68 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 32, "w": 131, "h": 68 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0009.png", + "frame": { "x": 540, "y": 69, "w": 134, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 33, "w": 134, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0010.png", + "frame": { "x": 690, "y": 0, "w": 139, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 32, "w": 139, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0011.png", + "frame": { "x": 287, "y": 0, "w": 122, "h": 81 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 122, "h": 81 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0012.png", + "frame": { "x": 380, "y": 133, "w": 96, "h": 87 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 10, "w": 96, "h": 87 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0013.png", + "frame": { "x": 573, "y": 135, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 7, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0014.png", + "frame": { "x": 653, "y": 242, "w": 90, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 7, "w": 90, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0015.png", + "frame": { "x": 665, "y": 152, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 8, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0016.png", + "frame": { "x": 284, "y": 81, "w": 96, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 11, "w": 96, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0017.png", + "frame": { "x": 690, "y": 66, "w": 103, "h": 86 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 18, "y": 14, "w": 103, "h": 86 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0018.png", + "frame": { "x": 554, "y": 0, "w": 136, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 33, "w": 136, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0019.png", + "frame": { "x": 143, "y": 69, "w": 141, "h": 63 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 40, "w": 141, "h": 63 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0020.png", + "frame": { "x": 409, "y": 0, "w": 145, "h": 65 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 38, "w": 145, "h": 65 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0021.png", + "frame": { "x": 143, "y": 0, "w": 144, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 33, "w": 144, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0022.png", + "frame": { "x": 0, "y": 0, "w": 143, "h": 71 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 30, "w": 143, "h": 71 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0023.png", + "frame": { "x": 409, "y": 65, "w": 131, "h": 68 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 32, "w": 131, "h": 68 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0024.png", + "frame": { "x": 540, "y": 69, "w": 134, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 33, "w": 134, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0025.png", + "frame": { "x": 690, "y": 0, "w": 139, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 32, "w": 139, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0026.png", + "frame": { "x": 287, "y": 0, "w": 122, "h": 81 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 122, "h": 81 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0027.png", + "frame": { "x": 380, "y": 133, "w": 96, "h": 87 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 10, "w": 96, "h": 87 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0028.png", + "frame": { "x": 573, "y": 135, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 7, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0029.png", + "frame": { "x": 653, "y": 242, "w": 90, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 7, "w": 90, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0030.png", + "frame": { "x": 665, "y": 152, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 8, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0031.png", + "frame": { "x": 284, "y": 81, "w": 96, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 11, "w": 96, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0032.png", + "frame": { "x": 690, "y": 66, "w": 103, "h": 86 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 18, "y": 14, "w": 103, "h": 86 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0033.png", + "frame": { "x": 554, "y": 0, "w": 136, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 3, "y": 33, "w": 136, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0034.png", + "frame": { "x": 143, "y": 69, "w": 141, "h": 63 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 40, "w": 141, "h": 63 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0035.png", + "frame": { "x": 409, "y": 0, "w": 145, "h": 65 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 38, "w": 145, "h": 65 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0036.png", + "frame": { "x": 143, "y": 0, "w": 144, "h": 69 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 1, "y": 33, "w": 144, "h": 69 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0037.png", + "frame": { "x": 0, "y": 0, "w": 143, "h": 71 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 30, "w": 143, "h": 71 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0038.png", + "frame": { "x": 409, "y": 65, "w": 131, "h": 68 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 32, "w": 131, "h": 68 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0039.png", + "frame": { "x": 540, "y": 69, "w": 134, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 33, "w": 134, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0040.png", + "frame": { "x": 690, "y": 0, "w": 139, "h": 66 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 32, "w": 139, "h": 66 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0041.png", + "frame": { "x": 287, "y": 0, "w": 122, "h": 81 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 122, "h": 81 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0042.png", + "frame": { "x": 380, "y": 133, "w": 96, "h": 87 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 10, "w": 96, "h": 87 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0043.png", + "frame": { "x": 573, "y": 135, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 7, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0044.png", + "frame": { "x": 653, "y": 242, "w": 90, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 7, "w": 90, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0045.png", + "frame": { "x": 665, "y": 152, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 8, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 100 + }, + { + "filename": "0046.png", + "frame": { "x": 284, "y": 81, "w": 96, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 21, "y": 11, "w": 96, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + }, + { + "filename": "0047.png", + "frame": { "x": 0, "y": 161, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 9, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0048.png", + "frame": { "x": 374, "y": 220, "w": 93, "h": 89 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 10, "w": 93, "h": 89 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0049.png", + "frame": { "x": 832, "y": 275, "w": 89, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 8, "w": 89, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0050.png", + "frame": { "x": 282, "y": 169, "w": 92, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 9, "w": 92, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0051.png", + "frame": { "x": 191, "y": 132, "w": 91, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 8, "w": 91, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0052.png", + "frame": { "x": 0, "y": 71, "w": 98, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 17, "y": 8, "w": 98, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0053.png", + "frame": { "x": 829, "y": 0, "w": 97, "h": 92 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 17, "y": 6, "w": 97, "h": 92 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0054.png", + "frame": { "x": 92, "y": 222, "w": 90, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 6, "w": 90, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0055.png", + "frame": { "x": 926, "y": 0, "w": 89, "h": 92 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 5, "w": 89, "h": 92 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + }, + { + "filename": "0056.png", + "frame": { "x": 90, "y": 313, "w": 88, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 30, "y": 5, "w": 88, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + }, + { + "filename": "0057.png", + "frame": { "x": 0, "y": 251, "w": 90, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 30, "y": 6, "w": 90, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0058.png", + "frame": { "x": 743, "y": 271, "w": 89, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 33, "y": 4, "w": 89, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0059.png", + "frame": { "x": 98, "y": 132, "w": 93, "h": 90 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 31, "y": 5, "w": 93, "h": 90 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0060.png", + "frame": { "x": 182, "y": 223, "w": 93, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 28, "y": 7, "w": 93, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0061.png", + "frame": { "x": 793, "y": 92, "w": 97, "h": 87 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 8, "w": 97, "h": 87 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0062.png", + "frame": { "x": 476, "y": 135, "w": 97, "h": 86 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 9, "w": 97, "h": 86 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0063.png", + "frame": { "x": 560, "y": 225, "w": 93, "h": 88 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 7, "w": 93, "h": 88 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0064.png", + "frame": { "x": 467, "y": 221, "w": 93, "h": 89 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 7, "w": 93, "h": 89 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0065.png", + "frame": { "x": 275, "y": 259, "w": 89, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 25, "y": 5, "w": 89, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + }, + { + "filename": "0066.png", + "frame": { "x": 921, "y": 275, "w": 87, "h": 93 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 4, "w": 87, "h": 93 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + }, + { + "filename": "0067.png", + "frame": { "x": 536, "y": 313, "w": 83, "h": 95 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 2, "w": 83, "h": 95 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0068.png", + "frame": { "x": 182, "y": 311, "w": 84, "h": 96 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 1, "w": 84, "h": 96 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0069.png", + "frame": { "x": 0, "y": 341, "w": 80, "h": 97 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 80, "h": 97 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0070.png", + "frame": { "x": 619, "y": 332, "w": 81, "h": 96 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 27, "y": 2, "w": 81, "h": 96 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0071.png", + "frame": { "x": 364, "y": 309, "w": 86, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 4, "w": 86, "h": 94 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 50 + }, + { + "filename": "0072.png", + "frame": { "x": 450, "y": 310, "w": 86, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 25, "y": 5, "w": 86, "h": 94 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 30 + }, + { + "filename": "0073.png", + "frame": { "x": 757, "y": 179, "w": 90, "h": 92 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 7, "w": 90, "h": 92 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 70 + }, + { + "filename": "0074.png", + "frame": { "x": 847, "y": 183, "w": 90, "h": 92 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 24, "y": 7, "w": 90, "h": 92 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 20 + }, + { + "filename": "0075.png", + "frame": { "x": 890, "y": 92, "w": 92, "h": 91 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 23, "y": 8, "w": 92, "h": 91 }, + "sourceSize": { "w": 146, "h": 103 }, + "duration": 80 + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.9.2-x64", + "image": "249.png", + "format": "I8", + "size": { "w": 1015, "h": 438 }, + "scale": "1" + } } diff --git a/public/images/pokemon/back/shiny/249.png b/public/images/pokemon/back/shiny/249.png index bf37f724613..066a38999e0 100644 Binary files a/public/images/pokemon/back/shiny/249.png and b/public/images/pokemon/back/shiny/249.png differ diff --git a/public/locales b/public/locales index e07ab625f20..5ef993b95fa 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit e07ab625f2080afe36b61fad291b0ec5eff4000c +Subproject commit 5ef993b95fa8248adc0fb7d9489baccf546bf8e3 diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 65ec6a844ee..d042d2c0b12 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -869,6 +869,12 @@ export default class BattleScene extends SceneBase { return party.slice(0, Math.min(party.length, this.currentBattle?.double ? 2 : 1)); } + /** + * Returns an array of Pokemon on both sides of the battle - player first, then enemy. + * Does not actually check if the pokemon are on the field or not, and always has length 4 regardless of battle type. + * @param activeOnly Whether to consider only active pokemon + * @returns array of {@linkcode Pokemon} + */ public getField(activeOnly: boolean = false): Pokemon[] { const ret = new Array(4).fill(null); const playerField = this.getPlayerField(); @@ -1843,8 +1849,10 @@ export default class BattleScene extends SceneBase { this.currentBattle.battleScore += Math.ceil(scoreIncrease); } - getMaxExpLevel(ignoreLevelCap?: boolean): integer { - if (ignoreLevelCap) { + getMaxExpLevel(ignoreLevelCap: boolean = false): integer { + if (Overrides.LEVEL_CAP_OVERRIDE > 0) { + return Overrides.LEVEL_CAP_OVERRIDE; + } else if (ignoreLevelCap || Overrides.LEVEL_CAP_OVERRIDE < 0) { return Number.MAX_SAFE_INTEGER; } const waveIndex = Math.ceil((this.currentBattle?.waveIndex || 1) / 10) * 10; @@ -2082,8 +2090,11 @@ export default class BattleScene extends SceneBase { return sound; } + /** The loop point of any given battle, mystery encounter, or title track, read as seconds and milliseconds. */ getBgmLoopPoint(bgmName: string): number { switch (bgmName) { + case "title": //Firel PokéRogue Title + return 46.500; case "battle_kanto_champion": //B2W2 Kanto Champion Battle return 13.950; case "battle_johto_champion": //B2W2 Johto Champion Battle @@ -3388,7 +3399,8 @@ export default class BattleScene extends SceneBase { const previousEncounter = this.mysteryEncounterSaveData.encounteredEvents.length > 0 ? this.mysteryEncounterSaveData.encounteredEvents[this.mysteryEncounterSaveData.encounteredEvents.length - 1].type : null; - const biomeMysteryEncounters = mysteryEncountersByBiome.get(this.arena.biomeType) ?? []; + const disabledEncounters = this.eventManager.getEventMysteryEncountersDisabled(); + const biomeMysteryEncounters = mysteryEncountersByBiome.get(this.arena.biomeType)?.filter(enc => !disabledEncounters.includes(enc)) ?? []; // If no valid encounters exist at tier, checks next tier down, continuing until there are some encounters available while (availableEncounters.length === 0 && tier !== null) { availableEncounters = biomeMysteryEncounters @@ -3397,7 +3409,7 @@ export default class BattleScene extends SceneBase { if (!encounterCandidate) { return false; } - if (encounterCandidate.encounterTier !== tier) { + if (this.eventManager.getMysteryEncounterTierForEvent(encounterType, encounterCandidate.encounterTier) !== tier) { return false; } const disallowedGameModes = encounterCandidate.disallowedGameModes; diff --git a/src/battle.ts b/src/battle.ts index b1196bb0139..287a981f83d 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -24,9 +24,26 @@ import { ModifierTier } from "#app/modifier/modifier-tier"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; export enum ClassicFixedBossWaves { - // TODO: other fixed wave battles should be added here + TOWN_YOUNGSTER = 5, + RIVAL_1 = 8, + RIVAL_2 = 25, + EVIL_GRUNT_1 = 35, + RIVAL_3 = 55, + EVIL_GRUNT_2 = 62, + EVIL_GRUNT_3 = 64, + EVIL_ADMIN_1 = 66, + RIVAL_4 = 95, + EVIL_GRUNT_4 = 112, + EVIL_ADMIN_2 = 114, EVIL_BOSS_1 = 115, + RIVAL_5 = 145, EVIL_BOSS_2 = 165, + ELITE_FOUR_1 = 182, + ELITE_FOUR_2 = 184, + ELITE_FOUR_3 = 186, + ELITE_FOUR_4 = 188, + CHAMPION = 190, + RIVAL_6 = 195, } export enum BattleType { @@ -500,7 +517,7 @@ export class FixedBattleConfig { * @param seedOffset the seed offset to use for the random generation of the trainer * @returns the generated trainer */ -function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], randomGender: boolean = false, seedOffset: number = 0): GetTrainerFunc { +export function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], randomGender: boolean = false, seedOffset: number = 0): GetTrainerFunc { return () => { const rand = Utils.randSeedInt(trainerPool.length); const trainerTypes: TrainerType[] = []; @@ -544,51 +561,51 @@ export interface FixedBattleConfigs { * Champion on 190 */ export const classicFixedBattles: FixedBattleConfigs = { - [5]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) + [ClassicFixedBossWaves.TOWN_YOUNGSTER]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(() => new Trainer(TrainerType.YOUNGSTER, Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), - [8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) + [ClassicFixedBossWaves.RIVAL_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(() => new Trainer(TrainerType.RIVAL, globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), - [25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) + [ClassicFixedBossWaves.RIVAL_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(() => new Trainer(TrainerType.RIVAL_2, globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }), - [35]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) + [ClassicFixedBossWaves.EVIL_GRUNT_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), - [55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) + [ClassicFixedBossWaves.RIVAL_3]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(() => new Trainer(TrainerType.RIVAL_3, globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }), - [62]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) + [ClassicFixedBossWaves.EVIL_GRUNT_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), - [64]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) + [ClassicFixedBossWaves.EVIL_GRUNT_3]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), - [66]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) + [ClassicFixedBossWaves.EVIL_ADMIN_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true)), - [95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) + [ClassicFixedBossWaves.RIVAL_4]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(() => new Trainer(TrainerType.RIVAL_4, globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }), - [112]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) + [ClassicFixedBossWaves.EVIL_GRUNT_4]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), - [114]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) + [ClassicFixedBossWaves.EVIL_ADMIN_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true, 1)), - [ClassicFixedBossWaves.EVIL_BOSS_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) + [ClassicFixedBossWaves.EVIL_BOSS_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE, TrainerType.PENNY ])) .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }), - [145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) + [ClassicFixedBossWaves.RIVAL_5]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(() => new Trainer(TrainerType.RIVAL_5, globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }), - [ClassicFixedBossWaves.EVIL_BOSS_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) + [ClassicFixedBossWaves.EVIL_BOSS_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2, TrainerType.LUSAMINE_2, TrainerType.GUZMA_2, TrainerType.ROSE_2, TrainerType.PENNY_2 ])) .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }), - [182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) + [ClassicFixedBossWaves.ELITE_FOUR_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])), - [184]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182) + [ClassicFixedBossWaves.ELITE_FOUR_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY, TrainerType.AMARYS ])), - [186]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182) + [ClassicFixedBossWaves.ELITE_FOUR_3]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, [ TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE ], TrainerType.LARRY_ELITE, TrainerType.LACEY ])), - [188]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182) + [ClassicFixedBossWaves.ELITE_FOUR_4]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL, TrainerType.DRAYTON ])), - [190]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182) + [ClassicFixedBossWaves.CHAMPION]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN ])), - [195]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) + [ClassicFixedBossWaves.RIVAL_6]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(() => new Trainer(TrainerType.RIVAL_6, globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }) }; diff --git a/src/data/ability.ts b/src/data/ability.ts index 0e8b3c2392d..5e5231176b5 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -16,7 +16,7 @@ import type { ArenaTrapTag } from "./arena-tag"; import { ArenaTagSide } from "./arena-tag"; import { BerryModifier, HitHealModifier, PokemonHeldItemModifier } from "../modifier/modifier"; import { TerrainType } from "./terrain"; -import { SpeciesFormChangeManualTrigger, SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "./pokemon-forms"; +import { SpeciesFormChangeAbilityTrigger, SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "./pokemon-forms"; import i18next from "i18next"; import type { Localizable } from "#app/interfaces/locales"; import { Command } from "../ui/command-ui-handler"; @@ -232,7 +232,7 @@ export class PostBattleInitFormChangeAbAttr extends PostBattleInitAbAttr { applyPostBattleInit(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex && !simulated) { - return globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); + return globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); } return false; @@ -1875,7 +1875,7 @@ export class PostVictoryFormChangeAbAttr extends PostVictoryAbAttr { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { if (!simulated) { - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); } return true; } @@ -2306,7 +2306,7 @@ export class PostSummonFormChangeAbAttr extends PostSummonAbAttr { applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { - return simulated || globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); + return simulated || globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); } return false; @@ -2734,7 +2734,7 @@ export class PreSwitchOutFormChangeAbAttr extends PreSwitchOutAbAttr { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { if (!simulated) { - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); } return true; } @@ -3704,7 +3704,7 @@ export class PostTurnFormChangeAbAttr extends PostTurnAbAttr { const formIndex = this.formFunc(pokemon); if (formIndex !== pokemon.formIndex) { if (!simulated) { - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); } return true; diff --git a/src/data/balance/passives.ts b/src/data/balance/passives.ts index 3a8285b4586..60b50c7909c 100644 --- a/src/data/balance/passives.ts +++ b/src/data/balance/passives.ts @@ -2,581 +2,581 @@ import { Abilities } from "#app/enums/abilities"; import { Species } from "#app/enums/species"; export const starterPassiveAbilities = { - [Species.BULBASAUR]: Abilities.GRASSY_SURGE, - [Species.CHARMANDER]: Abilities.BEAST_BOOST, - [Species.SQUIRTLE]: Abilities.STURDY, - [Species.CATERPIE]: Abilities.MAGICIAN, - [Species.WEEDLE]: Abilities.TINTED_LENS, - [Species.PIDGEY]: Abilities.SHEER_FORCE, - [Species.RATTATA]: Abilities.STRONG_JAW, - [Species.SPEAROW]: Abilities.MOXIE, - [Species.EKANS]: Abilities.REGENERATOR, - [Species.SANDSHREW]: Abilities.TOUGH_CLAWS, - [Species.NIDORAN_F]: Abilities.FLARE_BOOST, - [Species.NIDORAN_M]: Abilities.GUTS, - [Species.VULPIX]: Abilities.FUR_COAT, - [Species.ZUBAT]: Abilities.INTIMIDATE, - [Species.ODDISH]: Abilities.TRIAGE, - [Species.PARAS]: Abilities.TRIAGE, - [Species.VENONAT]: Abilities.SIMPLE, - [Species.DIGLETT]: Abilities.STURDY, - [Species.MEOWTH]: Abilities.TOUGH_CLAWS, - [Species.PSYDUCK]: Abilities.SIMPLE, - [Species.MANKEY]: Abilities.IRON_FIST, - [Species.GROWLITHE]: Abilities.FLUFFY, - [Species.POLIWAG]: Abilities.NO_GUARD, - [Species.ABRA]: Abilities.MAGICIAN, - [Species.MACHOP]: Abilities.QUICK_FEET, - [Species.BELLSPROUT]: Abilities.FLOWER_GIFT, - [Species.TENTACOOL]: Abilities.TOXIC_CHAIN, - [Species.GEODUDE]: Abilities.DRY_SKIN, - [Species.PONYTA]: Abilities.MAGIC_GUARD, - [Species.SLOWPOKE]: Abilities.UNAWARE, - [Species.MAGNEMITE]: Abilities.LEVITATE, - [Species.FARFETCHD]: Abilities.SNIPER, - [Species.DODUO]: Abilities.PARENTAL_BOND, - [Species.SEEL]: Abilities.WATER_BUBBLE, - [Species.GRIMER]: Abilities.WATER_ABSORB, - [Species.SHELLDER]: Abilities.ICE_SCALES, - [Species.GASTLY]: Abilities.SHADOW_SHIELD, - [Species.ONIX]: Abilities.ROCKY_PAYLOAD, - [Species.DROWZEE]: Abilities.MAGICIAN, - [Species.KRABBY]: Abilities.UNBURDEN, - [Species.VOLTORB]: Abilities.TRANSISTOR, - [Species.EXEGGCUTE]: Abilities.RIPEN, - [Species.CUBONE]: Abilities.PARENTAL_BOND, - [Species.LICKITUNG]: Abilities.CHEEK_POUCH, - [Species.KOFFING]: Abilities.PARENTAL_BOND, - [Species.RHYHORN]: Abilities.FILTER, - [Species.TANGELA]: Abilities.SEED_SOWER, - [Species.KANGASKHAN]: Abilities.GUTS, - [Species.HORSEA]: Abilities.DRAGONS_MAW, - [Species.GOLDEEN]: Abilities.MULTISCALE, - [Species.STARYU]: Abilities.REGENERATOR, - [Species.SCYTHER]: Abilities.TINTED_LENS, - [Species.PINSIR]: Abilities.TINTED_LENS, - [Species.TAUROS]: Abilities.STAMINA, - [Species.MAGIKARP]: Abilities.MULTISCALE, - [Species.LAPRAS]: Abilities.LIGHTNING_ROD, - [Species.DITTO]: Abilities.ADAPTABILITY, - [Species.EEVEE]: Abilities.PICKUP, - [Species.PORYGON]: Abilities.PROTEAN, - [Species.OMANYTE]: Abilities.STURDY, - [Species.KABUTO]: Abilities.TOUGH_CLAWS, - [Species.AERODACTYL]: Abilities.ORICHALCUM_PULSE, - [Species.ARTICUNO]: Abilities.SNOW_WARNING, - [Species.ZAPDOS]: Abilities.DRIZZLE, - [Species.MOLTRES]: Abilities.DROUGHT, - [Species.DRATINI]: Abilities.AERILATE, - [Species.MEWTWO]: Abilities.NEUROFORCE, - [Species.MEW]: Abilities.PROTEAN, + [Species.BULBASAUR]: { 0: Abilities.GRASSY_SURGE }, + [Species.CHARMANDER]: { 0: Abilities.BEAST_BOOST }, + [Species.SQUIRTLE]: { 0: Abilities.STURDY }, + [Species.CATERPIE]: { 0: Abilities.MAGICIAN }, + [Species.WEEDLE]: { 0: Abilities.TINTED_LENS }, + [Species.PIDGEY]: { 0: Abilities.SHEER_FORCE }, + [Species.RATTATA]: { 0: Abilities.STRONG_JAW }, + [Species.SPEAROW]: { 0: Abilities.MOXIE }, + [Species.EKANS]: { 0: Abilities.REGENERATOR }, + [Species.SANDSHREW]: { 0: Abilities.TOUGH_CLAWS }, + [Species.NIDORAN_F]: { 0: Abilities.FLARE_BOOST }, + [Species.NIDORAN_M]: { 0: Abilities.GUTS }, + [Species.VULPIX]: { 0: Abilities.FUR_COAT }, + [Species.ZUBAT]: { 0: Abilities.INTIMIDATE }, + [Species.ODDISH]: { 0: Abilities.TRIAGE }, + [Species.PARAS]: { 0: Abilities.TRIAGE }, + [Species.VENONAT]: { 0: Abilities.SIMPLE }, + [Species.DIGLETT]: { 0: Abilities.STURDY }, + [Species.MEOWTH]: { 0: Abilities.TOUGH_CLAWS }, + [Species.PSYDUCK]: { 0: Abilities.SIMPLE }, + [Species.MANKEY]: { 0: Abilities.IRON_FIST }, + [Species.GROWLITHE]: { 0: Abilities.FLUFFY }, + [Species.POLIWAG]: { 0: Abilities.NO_GUARD }, + [Species.ABRA]: { 0: Abilities.MAGICIAN }, + [Species.MACHOP]: { 0: Abilities.QUICK_FEET }, + [Species.BELLSPROUT]: { 0: Abilities.FLOWER_GIFT }, + [Species.TENTACOOL]: { 0: Abilities.TOXIC_CHAIN }, + [Species.GEODUDE]: { 0: Abilities.DRY_SKIN }, + [Species.PONYTA]: { 0: Abilities.MAGIC_GUARD }, + [Species.SLOWPOKE]: { 0: Abilities.UNAWARE }, + [Species.MAGNEMITE]: { 0: Abilities.LEVITATE }, + [Species.FARFETCHD]: { 0: Abilities.SNIPER }, + [Species.DODUO]: { 0: Abilities.PARENTAL_BOND }, + [Species.SEEL]: { 0: Abilities.WATER_BUBBLE }, + [Species.GRIMER]: { 0: Abilities.WATER_ABSORB }, + [Species.SHELLDER]: { 0: Abilities.ICE_SCALES }, + [Species.GASTLY]: { 0: Abilities.SHADOW_SHIELD }, + [Species.ONIX]: { 0: Abilities.ROCKY_PAYLOAD }, + [Species.DROWZEE]: { 0: Abilities.MAGICIAN }, + [Species.KRABBY]: { 0: Abilities.UNBURDEN }, + [Species.VOLTORB]: { 0: Abilities.TRANSISTOR }, + [Species.EXEGGCUTE]: { 0: Abilities.RIPEN }, + [Species.CUBONE]: { 0: Abilities.PARENTAL_BOND }, + [Species.LICKITUNG]: { 0: Abilities.CHEEK_POUCH }, + [Species.KOFFING]: { 0: Abilities.PARENTAL_BOND }, + [Species.RHYHORN]: { 0: Abilities.FILTER }, + [Species.TANGELA]: { 0: Abilities.SEED_SOWER }, + [Species.KANGASKHAN]: { 0: Abilities.GUTS }, + [Species.HORSEA]: { 0: Abilities.DRAGONS_MAW }, + [Species.GOLDEEN]: { 0: Abilities.MULTISCALE }, + [Species.STARYU]: { 0: Abilities.REGENERATOR }, + [Species.SCYTHER]: { 0: Abilities.TINTED_LENS }, + [Species.PINSIR]: { 0: Abilities.TINTED_LENS }, + [Species.TAUROS]: { 0: Abilities.STAMINA }, + [Species.MAGIKARP]: { 0: Abilities.MULTISCALE }, + [Species.LAPRAS]: { 0: Abilities.LIGHTNING_ROD }, + [Species.DITTO]: { 0: Abilities.ADAPTABILITY }, + [Species.EEVEE]: { 0: Abilities.PICKUP }, + [Species.PORYGON]: { 0: Abilities.PROTEAN }, + [Species.OMANYTE]: { 0: Abilities.STURDY }, + [Species.KABUTO]: { 0: Abilities.TOUGH_CLAWS }, + [Species.AERODACTYL]: { 0: Abilities.ORICHALCUM_PULSE }, + [Species.ARTICUNO]: { 0: Abilities.SNOW_WARNING }, + [Species.ZAPDOS]: { 0: Abilities.DRIZZLE }, + [Species.MOLTRES]: { 0: Abilities.DROUGHT }, + [Species.DRATINI]: { 0: Abilities.AERILATE }, + [Species.MEWTWO]: { 0: Abilities.NEUROFORCE }, + [Species.MEW]: { 0: Abilities.PROTEAN }, - [Species.CHIKORITA]: Abilities.THICK_FAT, - [Species.CYNDAQUIL]: Abilities.DROUGHT, - [Species.TOTODILE]: Abilities.TOUGH_CLAWS, - [Species.SENTRET]: Abilities.PICKUP, - [Species.HOOTHOOT]: Abilities.AERILATE, - [Species.LEDYBA]: Abilities.PRANKSTER, - [Species.SPINARAK]: Abilities.PRANKSTER, - [Species.CHINCHOU]: Abilities.REGENERATOR, - [Species.PICHU]: Abilities.ELECTRIC_SURGE, - [Species.CLEFFA]: Abilities.ANALYTIC, - [Species.IGGLYBUFF]: Abilities.HUGE_POWER, - [Species.TOGEPI]: Abilities.PIXILATE, - [Species.NATU]: Abilities.SHEER_FORCE, - [Species.MAREEP]: Abilities.ELECTROMORPHOSIS, - [Species.HOPPIP]: Abilities.FLUFFY, - [Species.AIPOM]: Abilities.SCRAPPY, - [Species.SUNKERN]: Abilities.DROUGHT, - [Species.YANMA]: Abilities.SHEER_FORCE, - [Species.WOOPER]: Abilities.COMATOSE, - [Species.MURKROW]: Abilities.DARK_AURA, - [Species.MISDREAVUS]: Abilities.BEADS_OF_RUIN, - [Species.UNOWN]: Abilities.PICKUP, - [Species.GIRAFARIG]: Abilities.PARENTAL_BOND, - [Species.PINECO]: Abilities.IRON_BARBS, - [Species.DUNSPARCE]: Abilities.UNAWARE, - [Species.GLIGAR]: Abilities.TOXIC_BOOST, - [Species.SNUBBULL]: Abilities.PIXILATE, - [Species.QWILFISH]: Abilities.TOXIC_DEBRIS, - [Species.SHUCKLE]: Abilities.HARVEST, - [Species.HERACROSS]: Abilities.TECHNICIAN, - [Species.SNEASEL]: Abilities.TOUGH_CLAWS, - [Species.TEDDIURSA]: Abilities.THICK_FAT, - [Species.SLUGMA]: Abilities.DESOLATE_LAND, - [Species.SWINUB]: Abilities.SLUSH_RUSH, - [Species.CORSOLA]: Abilities.STORM_DRAIN, - [Species.REMORAID]: Abilities.SIMPLE, - [Species.DELIBIRD]: Abilities.HUGE_POWER, - [Species.SKARMORY]: Abilities.LIGHTNING_ROD, - [Species.HOUNDOUR]: Abilities.LIGHTNING_ROD, - [Species.PHANPY]: Abilities.SPEED_BOOST, - [Species.STANTLER]: Abilities.SPEED_BOOST, - [Species.SMEARGLE]: Abilities.PRANKSTER, - [Species.TYROGUE]: Abilities.MOXIE, - [Species.SMOOCHUM]: Abilities.PSYCHIC_SURGE, - [Species.ELEKID]: Abilities.SHEER_FORCE, - [Species.MAGBY]: Abilities.SHEER_FORCE, - [Species.MILTANK]: Abilities.STAMINA, - [Species.RAIKOU]: Abilities.BEAST_BOOST, - [Species.ENTEI]: Abilities.BEAST_BOOST, - [Species.SUICUNE]: Abilities.BEAST_BOOST, - [Species.LARVITAR]: Abilities.SAND_RUSH, - [Species.LUGIA]: Abilities.DELTA_STREAM, - [Species.HO_OH]: Abilities.MAGIC_GUARD, - [Species.CELEBI]: Abilities.PSYCHIC_SURGE, + [Species.CHIKORITA]: { 0: Abilities.THICK_FAT }, + [Species.CYNDAQUIL]: { 0: Abilities.DROUGHT }, + [Species.TOTODILE]: { 0: Abilities.TOUGH_CLAWS }, + [Species.SENTRET]: { 0: Abilities.PICKUP }, + [Species.HOOTHOOT]: { 0: Abilities.AERILATE }, + [Species.LEDYBA]: { 0: Abilities.PRANKSTER }, + [Species.SPINARAK]: { 0: Abilities.PRANKSTER }, + [Species.CHINCHOU]: { 0: Abilities.REGENERATOR }, + [Species.PICHU]: { 0: Abilities.ELECTRIC_SURGE }, + [Species.CLEFFA]: { 0: Abilities.ANALYTIC }, + [Species.IGGLYBUFF]: { 0: Abilities.HUGE_POWER }, + [Species.TOGEPI]: { 0: Abilities.PIXILATE }, + [Species.NATU]: { 0: Abilities.SHEER_FORCE }, + [Species.MAREEP]: { 0: Abilities.ELECTROMORPHOSIS }, + [Species.HOPPIP]: { 0: Abilities.FLUFFY }, + [Species.AIPOM]: { 0: Abilities.SCRAPPY }, + [Species.SUNKERN]: { 0: Abilities.DROUGHT }, + [Species.YANMA]: { 0: Abilities.SHEER_FORCE }, + [Species.WOOPER]: { 0: Abilities.COMATOSE }, + [Species.MURKROW]: { 0: Abilities.DARK_AURA }, + [Species.MISDREAVUS]: { 0: Abilities.BEADS_OF_RUIN }, + [Species.UNOWN]: { 0: Abilities.PICKUP }, + [Species.GIRAFARIG]: { 0: Abilities.PARENTAL_BOND }, + [Species.PINECO]: { 0: Abilities.IRON_BARBS }, + [Species.DUNSPARCE]: { 0: Abilities.UNAWARE }, + [Species.GLIGAR]: { 0: Abilities.TOXIC_BOOST }, + [Species.SNUBBULL]: { 0: Abilities.PIXILATE }, + [Species.QWILFISH]: { 0: Abilities.TOXIC_DEBRIS }, + [Species.SHUCKLE]: { 0: Abilities.HARVEST }, + [Species.HERACROSS]: { 0: Abilities.TECHNICIAN }, + [Species.SNEASEL]: { 0: Abilities.TOUGH_CLAWS }, + [Species.TEDDIURSA]: { 0: Abilities.THICK_FAT }, + [Species.SLUGMA]: { 0: Abilities.DESOLATE_LAND }, + [Species.SWINUB]: { 0: Abilities.SLUSH_RUSH }, + [Species.CORSOLA]: { 0: Abilities.STORM_DRAIN }, + [Species.REMORAID]: { 0: Abilities.SIMPLE }, + [Species.DELIBIRD]: { 0: Abilities.HUGE_POWER }, + [Species.SKARMORY]: { 0: Abilities.LIGHTNING_ROD }, + [Species.HOUNDOUR]: { 0: Abilities.LIGHTNING_ROD }, + [Species.PHANPY]: { 0: Abilities.SPEED_BOOST }, + [Species.STANTLER]: { 0: Abilities.SPEED_BOOST }, + [Species.SMEARGLE]: { 0: Abilities.PRANKSTER }, + [Species.TYROGUE]: { 0: Abilities.MOXIE }, + [Species.SMOOCHUM]: { 0: Abilities.PSYCHIC_SURGE }, + [Species.ELEKID]: { 0: Abilities.SHEER_FORCE }, + [Species.MAGBY]: { 0: Abilities.SHEER_FORCE }, + [Species.MILTANK]: { 0: Abilities.STAMINA }, + [Species.RAIKOU]: { 0: Abilities.BEAST_BOOST }, + [Species.ENTEI]: { 0: Abilities.BEAST_BOOST }, + [Species.SUICUNE]: { 0: Abilities.BEAST_BOOST }, + [Species.LARVITAR]: { 0: Abilities.SAND_RUSH }, + [Species.LUGIA]: { 0: Abilities.DELTA_STREAM }, + [Species.HO_OH]: { 0: Abilities.MAGIC_GUARD }, + [Species.CELEBI]: { 0: Abilities.PSYCHIC_SURGE }, - [Species.TREECKO]: Abilities.TINTED_LENS, - [Species.TORCHIC]: Abilities.DEFIANT, - [Species.MUDKIP]: Abilities.DRIZZLE, - [Species.POOCHYENA]: Abilities.TOUGH_CLAWS, - [Species.ZIGZAGOON]: Abilities.RUN_AWAY, - [Species.WURMPLE]: Abilities.SIMPLE, - [Species.LOTAD]: Abilities.DRIZZLE, - [Species.SEEDOT]: Abilities.SHARPNESS, - [Species.TAILLOW]: Abilities.AERILATE, - [Species.WINGULL]: Abilities.SWIFT_SWIM, - [Species.RALTS]: Abilities.PSYCHIC_SURGE, - [Species.SURSKIT]: Abilities.WATER_BUBBLE, - [Species.SHROOMISH]: Abilities.GUTS, - [Species.SLAKOTH]: Abilities.GUTS, - [Species.NINCADA]: Abilities.MAGIC_GUARD, - [Species.WHISMUR]: Abilities.PUNK_ROCK, - [Species.MAKUHITA]: Abilities.STAMINA, - [Species.AZURILL]: Abilities.MISTY_SURGE, - [Species.NOSEPASS]: Abilities.LEVITATE, - [Species.SKITTY]: Abilities.SCRAPPY, - [Species.SABLEYE]: Abilities.UNNERVE, - [Species.MAWILE]: Abilities.UNNERVE, - [Species.ARON]: Abilities.EARTH_EATER, - [Species.MEDITITE]: Abilities.MINDS_EYE, - [Species.ELECTRIKE]: Abilities.FLASH_FIRE, - [Species.PLUSLE]: Abilities.POWER_SPOT, - [Species.MINUN]: Abilities.POWER_SPOT, - [Species.VOLBEAT]: Abilities.HONEY_GATHER, - [Species.ILLUMISE]: Abilities.HONEY_GATHER, - [Species.GULPIN]: Abilities.EARTH_EATER, - [Species.CARVANHA]: Abilities.SHEER_FORCE, - [Species.WAILMER]: Abilities.LEVITATE, - [Species.NUMEL]: Abilities.FUR_COAT, - [Species.TORKOAL]: Abilities.ANALYTIC, - [Species.SPOINK]: Abilities.PSYCHIC_SURGE, - [Species.SPINDA]: Abilities.SIMPLE, - [Species.TRAPINCH]: Abilities.ADAPTABILITY, - [Species.CACNEA]: Abilities.SAND_RUSH, - [Species.SWABLU]: Abilities.FLUFFY, - [Species.ZANGOOSE]: Abilities.POISON_HEAL, - [Species.SEVIPER]: Abilities.MULTISCALE, - [Species.LUNATONE]: Abilities.SHADOW_SHIELD, - [Species.SOLROCK]: Abilities.DROUGHT, - [Species.BARBOACH]: Abilities.SIMPLE, - [Species.CORPHISH]: Abilities.TOUGH_CLAWS, - [Species.BALTOY]: Abilities.WELL_BAKED_BODY, - [Species.LILEEP]: Abilities.SEED_SOWER, - [Species.ANORITH]: Abilities.WATER_ABSORB, - [Species.FEEBAS]: Abilities.MAGIC_GUARD, - [Species.CASTFORM]: Abilities.ADAPTABILITY, - [Species.KECLEON]: Abilities.ADAPTABILITY, - [Species.SHUPPET]: Abilities.SHADOW_SHIELD, - [Species.DUSKULL]: Abilities.UNNERVE, - [Species.TROPIUS]: Abilities.RIPEN, - [Species.ABSOL]: Abilities.SHARPNESS, - [Species.WYNAUT]: Abilities.STURDY, - [Species.SNORUNT]: Abilities.SNOW_WARNING, - [Species.SPHEAL]: Abilities.UNAWARE, - [Species.CLAMPERL]: Abilities.ARENA_TRAP, - [Species.RELICANTH]: Abilities.PRIMORDIAL_SEA, - [Species.LUVDISC]: Abilities.MULTISCALE, - [Species.BAGON]: Abilities.MOLD_BREAKER, - [Species.BELDUM]: Abilities.LEVITATE, - [Species.REGIROCK]: Abilities.SAND_STREAM, - [Species.REGICE]: Abilities.SNOW_WARNING, - [Species.REGISTEEL]: Abilities.STEELY_SPIRIT, - [Species.LATIAS]: Abilities.PRISM_ARMOR, - [Species.LATIOS]: Abilities.TINTED_LENS, - [Species.KYOGRE]: Abilities.MOLD_BREAKER, - [Species.GROUDON]: Abilities.TURBOBLAZE, - [Species.RAYQUAZA]: Abilities.UNNERVE, - [Species.JIRACHI]: Abilities.COMATOSE, - [Species.DEOXYS]: Abilities.PROTEAN, + [Species.TREECKO]: { 0: Abilities.TINTED_LENS }, + [Species.TORCHIC]: { 0: Abilities.DEFIANT }, + [Species.MUDKIP]: { 0: Abilities.DRIZZLE }, + [Species.POOCHYENA]: { 0: Abilities.TOUGH_CLAWS }, + [Species.ZIGZAGOON]: { 0: Abilities.RUN_AWAY }, + [Species.WURMPLE]: { 0: Abilities.SIMPLE }, + [Species.LOTAD]: { 0: Abilities.DRIZZLE }, + [Species.SEEDOT]: { 0: Abilities.SHARPNESS }, + [Species.TAILLOW]: { 0: Abilities.AERILATE }, + [Species.WINGULL]: { 0: Abilities.SWIFT_SWIM }, + [Species.RALTS]: { 0: Abilities.PSYCHIC_SURGE }, + [Species.SURSKIT]: { 0: Abilities.WATER_BUBBLE }, + [Species.SHROOMISH]: { 0: Abilities.GUTS }, + [Species.SLAKOTH]: { 0: Abilities.GUTS }, + [Species.NINCADA]: { 0: Abilities.MAGIC_GUARD }, + [Species.WHISMUR]: { 0: Abilities.PUNK_ROCK }, + [Species.MAKUHITA]: { 0: Abilities.STAMINA }, + [Species.AZURILL]: { 0: Abilities.MISTY_SURGE }, + [Species.NOSEPASS]: { 0: Abilities.LEVITATE }, + [Species.SKITTY]: { 0: Abilities.SCRAPPY }, + [Species.SABLEYE]: { 0: Abilities.UNNERVE }, + [Species.MAWILE]: { 0: Abilities.UNNERVE }, + [Species.ARON]: { 0: Abilities.EARTH_EATER }, + [Species.MEDITITE]: { 0: Abilities.MINDS_EYE }, + [Species.ELECTRIKE]: { 0: Abilities.FLASH_FIRE }, + [Species.PLUSLE]: { 0: Abilities.POWER_SPOT }, + [Species.MINUN]: { 0: Abilities.POWER_SPOT }, + [Species.VOLBEAT]: { 0: Abilities.HONEY_GATHER }, + [Species.ILLUMISE]: { 0: Abilities.HONEY_GATHER }, + [Species.GULPIN]: { 0: Abilities.EARTH_EATER }, + [Species.CARVANHA]: { 0: Abilities.SHEER_FORCE }, + [Species.WAILMER]: { 0: Abilities.LEVITATE }, + [Species.NUMEL]: { 0: Abilities.FUR_COAT }, + [Species.TORKOAL]: { 0: Abilities.ANALYTIC }, + [Species.SPOINK]: { 0: Abilities.PSYCHIC_SURGE }, + [Species.SPINDA]: { 0: Abilities.SIMPLE }, + [Species.TRAPINCH]: { 0: Abilities.ADAPTABILITY }, + [Species.CACNEA]: { 0: Abilities.SAND_RUSH }, + [Species.SWABLU]: { 0: Abilities.FLUFFY }, + [Species.ZANGOOSE]: { 0: Abilities.POISON_HEAL }, + [Species.SEVIPER]: { 0: Abilities.MULTISCALE }, + [Species.LUNATONE]: { 0: Abilities.SHADOW_SHIELD }, + [Species.SOLROCK]: { 0: Abilities.DROUGHT }, + [Species.BARBOACH]: { 0: Abilities.SIMPLE }, + [Species.CORPHISH]: { 0: Abilities.TOUGH_CLAWS }, + [Species.BALTOY]: { 0: Abilities.WELL_BAKED_BODY }, + [Species.LILEEP]: { 0: Abilities.SEED_SOWER }, + [Species.ANORITH]: { 0: Abilities.WATER_ABSORB }, + [Species.FEEBAS]: { 0: Abilities.MAGIC_GUARD }, + [Species.CASTFORM]: { 0: Abilities.ADAPTABILITY }, + [Species.KECLEON]: { 0: Abilities.ADAPTABILITY }, + [Species.SHUPPET]: { 0: Abilities.SHADOW_SHIELD }, + [Species.DUSKULL]: { 0: Abilities.UNNERVE }, + [Species.TROPIUS]: { 0: Abilities.RIPEN }, + [Species.ABSOL]: { 0: Abilities.SHARPNESS }, + [Species.WYNAUT]: { 0: Abilities.STURDY }, + [Species.SNORUNT]: { 0: Abilities.SNOW_WARNING }, + [Species.SPHEAL]: { 0: Abilities.UNAWARE }, + [Species.CLAMPERL]: { 0: Abilities.ARENA_TRAP }, + [Species.RELICANTH]: { 0: Abilities.PRIMORDIAL_SEA }, + [Species.LUVDISC]: { 0: Abilities.MULTISCALE }, + [Species.BAGON]: { 0: Abilities.MOLD_BREAKER }, + [Species.BELDUM]: { 0: Abilities.LEVITATE }, + [Species.REGIROCK]: { 0: Abilities.SAND_STREAM }, + [Species.REGICE]: { 0: Abilities.SNOW_WARNING }, + [Species.REGISTEEL]: { 0: Abilities.STEELY_SPIRIT }, + [Species.LATIAS]: { 0: Abilities.PRISM_ARMOR }, + [Species.LATIOS]: { 0: Abilities.TINTED_LENS }, + [Species.KYOGRE]: { 0: Abilities.MOLD_BREAKER }, + [Species.GROUDON]: { 0: Abilities.TURBOBLAZE }, + [Species.RAYQUAZA]: { 0: Abilities.UNNERVE }, + [Species.JIRACHI]: { 0: Abilities.COMATOSE }, + [Species.DEOXYS]: { 0: Abilities.PROTEAN }, - [Species.TURTWIG]: Abilities.THICK_FAT, - [Species.CHIMCHAR]: Abilities.BEAST_BOOST, - [Species.PIPLUP]: Abilities.DRIZZLE, - [Species.STARLY]: Abilities.ROCK_HEAD, - [Species.BIDOOF]: Abilities.SAP_SIPPER, - [Species.KRICKETOT]: Abilities.SHARPNESS, - [Species.SHINX]: Abilities.SPEED_BOOST, - [Species.BUDEW]: Abilities.GRASSY_SURGE, - [Species.CRANIDOS]: Abilities.ROCK_HEAD, - [Species.SHIELDON]: Abilities.EARTH_EATER, - [Species.BURMY]: Abilities.STURDY, - [Species.COMBEE]: Abilities.INTIMIDATE, - [Species.PACHIRISU]: Abilities.HONEY_GATHER, - [Species.BUIZEL]: Abilities.MOXIE, - [Species.CHERUBI]: Abilities.ORICHALCUM_PULSE, - [Species.SHELLOS]: Abilities.REGENERATOR, - [Species.DRIFLOON]: Abilities.MAGIC_GUARD, - [Species.BUNEARY]: Abilities.ADAPTABILITY, - [Species.GLAMEOW]: Abilities.INTIMIDATE, - [Species.CHINGLING]: Abilities.PUNK_ROCK, - [Species.STUNKY]: Abilities.NEUTRALIZING_GAS, - [Species.BRONZOR]: Abilities.MIRROR_ARMOR, - [Species.BONSLY]: Abilities.SAP_SIPPER, - [Species.MIME_JR]: Abilities.PRANKSTER, - [Species.HAPPINY]: Abilities.FUR_COAT, - [Species.CHATOT]: Abilities.PUNK_ROCK, - [Species.SPIRITOMB]: Abilities.VESSEL_OF_RUIN, - [Species.GIBLE]: Abilities.SAND_STREAM, - [Species.MUNCHLAX]: Abilities.RIPEN, - [Species.RIOLU]: Abilities.MINDS_EYE, - [Species.HIPPOPOTAS]: Abilities.UNAWARE, - [Species.SKORUPI]: Abilities.SUPER_LUCK, - [Species.CROAGUNK]: Abilities.MOXIE, - [Species.CARNIVINE]: Abilities.ARENA_TRAP, - [Species.FINNEON]: Abilities.WATER_BUBBLE, - [Species.MANTYKE]: Abilities.UNAWARE, - [Species.SNOVER]: Abilities.GRASSY_SURGE, - [Species.ROTOM]: Abilities.HADRON_ENGINE, - [Species.UXIE]: Abilities.UNAWARE, - [Species.MESPRIT]: Abilities.MOODY, - [Species.AZELF]: Abilities.NEUROFORCE, - [Species.DIALGA]: Abilities.LEVITATE, - [Species.PALKIA]: Abilities.SPEED_BOOST, - [Species.HEATRAN]: Abilities.EARTH_EATER, - [Species.REGIGIGAS]: Abilities.SCRAPPY, - [Species.GIRATINA]: Abilities.SHADOW_SHIELD, - [Species.CRESSELIA]: Abilities.SHADOW_SHIELD, - [Species.PHIONE]: Abilities.SIMPLE, - [Species.MANAPHY]: Abilities.PRIMORDIAL_SEA, - [Species.DARKRAI]: Abilities.UNNERVE, - [Species.SHAYMIN]: Abilities.WIND_RIDER, - [Species.ARCEUS]: Abilities.ADAPTABILITY, + [Species.TURTWIG]: { 0: Abilities.THICK_FAT }, + [Species.CHIMCHAR]: { 0: Abilities.BEAST_BOOST }, + [Species.PIPLUP]: { 0: Abilities.DRIZZLE }, + [Species.STARLY]: { 0: Abilities.ROCK_HEAD }, + [Species.BIDOOF]: { 0: Abilities.SAP_SIPPER }, + [Species.KRICKETOT]: { 0: Abilities.SHARPNESS }, + [Species.SHINX]: { 0: Abilities.SPEED_BOOST }, + [Species.BUDEW]: { 0: Abilities.GRASSY_SURGE }, + [Species.CRANIDOS]: { 0: Abilities.ROCK_HEAD }, + [Species.SHIELDON]: { 0: Abilities.EARTH_EATER }, + [Species.BURMY]: { 0: Abilities.STURDY }, + [Species.COMBEE]: { 0: Abilities.INTIMIDATE }, + [Species.PACHIRISU]: { 0: Abilities.HONEY_GATHER }, + [Species.BUIZEL]: { 0: Abilities.MOXIE }, + [Species.CHERUBI]: { 0: Abilities.ORICHALCUM_PULSE }, + [Species.SHELLOS]: { 0: Abilities.REGENERATOR }, + [Species.DRIFLOON]: { 0: Abilities.MAGIC_GUARD }, + [Species.BUNEARY]: { 0: Abilities.ADAPTABILITY }, + [Species.GLAMEOW]: { 0: Abilities.INTIMIDATE }, + [Species.CHINGLING]: { 0: Abilities.PUNK_ROCK }, + [Species.STUNKY]: { 0: Abilities.NEUTRALIZING_GAS }, + [Species.BRONZOR]: { 0: Abilities.MIRROR_ARMOR }, + [Species.BONSLY]: { 0: Abilities.SAP_SIPPER }, + [Species.MIME_JR]: { 0: Abilities.PRANKSTER }, + [Species.HAPPINY]: { 0: Abilities.FUR_COAT }, + [Species.CHATOT]: { 0: Abilities.PUNK_ROCK }, + [Species.SPIRITOMB]: { 0: Abilities.VESSEL_OF_RUIN }, + [Species.GIBLE]: { 0: Abilities.SAND_STREAM }, + [Species.MUNCHLAX]: { 0: Abilities.RIPEN }, + [Species.RIOLU]: { 0: Abilities.MINDS_EYE }, + [Species.HIPPOPOTAS]: { 0: Abilities.UNAWARE }, + [Species.SKORUPI]: { 0: Abilities.SUPER_LUCK }, + [Species.CROAGUNK]: { 0: Abilities.MOXIE }, + [Species.CARNIVINE]: { 0: Abilities.ARENA_TRAP }, + [Species.FINNEON]: { 0: Abilities.WATER_BUBBLE }, + [Species.MANTYKE]: { 0: Abilities.UNAWARE }, + [Species.SNOVER]: { 0: Abilities.GRASSY_SURGE }, + [Species.ROTOM]: { 0: Abilities.HADRON_ENGINE }, + [Species.UXIE]: { 0: Abilities.UNAWARE }, + [Species.MESPRIT]: { 0: Abilities.MOODY }, + [Species.AZELF]: { 0: Abilities.NEUROFORCE }, + [Species.DIALGA]: { 0: Abilities.LEVITATE }, + [Species.PALKIA]: { 0: Abilities.SPEED_BOOST }, + [Species.HEATRAN]: { 0: Abilities.EARTH_EATER }, + [Species.REGIGIGAS]: { 0: Abilities.SCRAPPY }, + [Species.GIRATINA]: { 0: Abilities.SHADOW_SHIELD }, + [Species.CRESSELIA]: { 0: Abilities.SHADOW_SHIELD }, + [Species.PHIONE]: { 0: Abilities.SIMPLE }, + [Species.MANAPHY]: { 0: Abilities.PRIMORDIAL_SEA }, + [Species.DARKRAI]: { 0: Abilities.UNNERVE }, + [Species.SHAYMIN]: { 0: Abilities.WIND_RIDER }, + [Species.ARCEUS]: { 0: Abilities.ADAPTABILITY }, - [Species.VICTINI]: Abilities.SHEER_FORCE, - [Species.SNIVY]: Abilities.MULTISCALE, - [Species.TEPIG]: Abilities.ROCK_HEAD, - [Species.OSHAWOTT]: Abilities.INTREPID_SWORD, - [Species.PATRAT]: Abilities.NO_GUARD, - [Species.LILLIPUP]: Abilities.FUR_COAT, - [Species.PURRLOIN]: Abilities.PICKUP, - [Species.PANSAGE]: Abilities.WELL_BAKED_BODY, - [Species.PANSEAR]: Abilities.WATER_ABSORB, - [Species.PANPOUR]: Abilities.SAP_SIPPER, - [Species.MUNNA]: Abilities.NEUTRALIZING_GAS, - [Species.PIDOVE]: Abilities.SNIPER, - [Species.BLITZLE]: Abilities.ELECTRIC_SURGE, - [Species.ROGGENROLA]: Abilities.SOLID_ROCK, - [Species.WOOBAT]: Abilities.OPPORTUNIST, - [Species.DRILBUR]: Abilities.STURDY, - [Species.AUDINO]: Abilities.FRIEND_GUARD, - [Species.TIMBURR]: Abilities.ROCKY_PAYLOAD, - [Species.TYMPOLE]: Abilities.POISON_HEAL, - [Species.THROH]: Abilities.STAMINA, - [Species.SAWK]: Abilities.SCRAPPY, - [Species.SEWADDLE]: Abilities.SHARPNESS, - [Species.VENIPEDE]: Abilities.STAMINA, - [Species.COTTONEE]: Abilities.FLUFFY, - [Species.PETILIL]: Abilities.SIMPLE, - [Species.BASCULIN]: Abilities.SUPREME_OVERLORD, - [Species.SANDILE]: Abilities.TOUGH_CLAWS, - [Species.DARUMAKA]: Abilities.GORILLA_TACTICS, - [Species.MARACTUS]: Abilities.WELL_BAKED_BODY, - [Species.DWEBBLE]: Abilities.ROCKY_PAYLOAD, - [Species.SCRAGGY]: Abilities.PROTEAN, - [Species.SIGILYPH]: Abilities.FLARE_BOOST, - [Species.YAMASK]: Abilities.PURIFYING_SALT, - [Species.TIRTOUGA]: Abilities.WATER_ABSORB, - [Species.ARCHEN]: Abilities.MULTISCALE, - [Species.TRUBBISH]: Abilities.NEUTRALIZING_GAS, - [Species.ZORUA]: Abilities.DARK_AURA, - [Species.MINCCINO]: Abilities.FUR_COAT, - [Species.GOTHITA]: Abilities.UNNERVE, - [Species.SOLOSIS]: Abilities.PSYCHIC_SURGE, - [Species.DUCKLETT]: Abilities.DRIZZLE, - [Species.VANILLITE]: Abilities.SLUSH_RUSH, - [Species.DEERLING]: Abilities.FUR_COAT, - [Species.EMOLGA]: Abilities.SERENE_GRACE, - [Species.KARRABLAST]: Abilities.QUICK_DRAW, - [Species.FOONGUS]: Abilities.THICK_FAT, - [Species.FRILLISH]: Abilities.POISON_HEAL, - [Species.ALOMOMOLA]: Abilities.MULTISCALE, - [Species.JOLTIK]: Abilities.TRANSISTOR, - [Species.FERROSEED]: Abilities.ROUGH_SKIN, - [Species.KLINK]: Abilities.STEELY_SPIRIT, - [Species.TYNAMO]: Abilities.POISON_HEAL, - [Species.ELGYEM]: Abilities.BEADS_OF_RUIN, - [Species.LITWICK]: Abilities.SHADOW_TAG, - [Species.AXEW]: Abilities.DRAGONS_MAW, - [Species.CUBCHOO]: Abilities.FUR_COAT, - [Species.CRYOGONAL]: Abilities.SNOW_WARNING, - [Species.SHELMET]: Abilities.PROTEAN, - [Species.STUNFISK]: Abilities.STORM_DRAIN, - [Species.MIENFOO]: Abilities.NO_GUARD, - [Species.DRUDDIGON]: Abilities.INTIMIDATE, - [Species.GOLETT]: Abilities.SHADOW_SHIELD, - [Species.PAWNIARD]: Abilities.SWORD_OF_RUIN, - [Species.BOUFFALANT]: Abilities.ROCK_HEAD, - [Species.RUFFLET]: Abilities.SPEED_BOOST, - [Species.VULLABY]: Abilities.THICK_FAT, - [Species.HEATMOR]: Abilities.CONTRARY, - [Species.DURANT]: Abilities.COMPOUND_EYES, - [Species.DEINO]: Abilities.PARENTAL_BOND, - [Species.LARVESTA]: Abilities.DROUGHT, - [Species.COBALION]: Abilities.INTREPID_SWORD, - [Species.TERRAKION]: Abilities.ROCKY_PAYLOAD, - [Species.VIRIZION]: Abilities.SHARPNESS, - [Species.TORNADUS]: Abilities.DRIZZLE, - [Species.THUNDURUS]: Abilities.DRIZZLE, - [Species.RESHIRAM]: Abilities.ORICHALCUM_PULSE, - [Species.ZEKROM]: Abilities.HADRON_ENGINE, - [Species.LANDORUS]: Abilities.STORM_DRAIN, - [Species.KYUREM]: Abilities.SNOW_WARNING, - [Species.KELDEO]: Abilities.GRIM_NEIGH, - [Species.MELOETTA]: Abilities.MINDS_EYE, - [Species.GENESECT]: Abilities.PROTEAN, + [Species.VICTINI]: { 0: Abilities.SHEER_FORCE }, + [Species.SNIVY]: { 0: Abilities.MULTISCALE }, + [Species.TEPIG]: { 0: Abilities.ROCK_HEAD }, + [Species.OSHAWOTT]: { 0: Abilities.INTREPID_SWORD }, + [Species.PATRAT]: { 0: Abilities.NO_GUARD }, + [Species.LILLIPUP]: { 0: Abilities.FUR_COAT }, + [Species.PURRLOIN]: { 0: Abilities.PICKUP }, + [Species.PANSAGE]: { 0: Abilities.WELL_BAKED_BODY }, + [Species.PANSEAR]: { 0: Abilities.WATER_ABSORB }, + [Species.PANPOUR]: { 0: Abilities.SAP_SIPPER }, + [Species.MUNNA]: { 0: Abilities.NEUTRALIZING_GAS }, + [Species.PIDOVE]: { 0: Abilities.SNIPER }, + [Species.BLITZLE]: { 0: Abilities.ELECTRIC_SURGE }, + [Species.ROGGENROLA]: { 0: Abilities.SOLID_ROCK }, + [Species.WOOBAT]: { 0: Abilities.OPPORTUNIST }, + [Species.DRILBUR]: { 0: Abilities.STURDY }, + [Species.AUDINO]: { 0: Abilities.FRIEND_GUARD }, + [Species.TIMBURR]: { 0: Abilities.ROCKY_PAYLOAD }, + [Species.TYMPOLE]: { 0: Abilities.POISON_HEAL }, + [Species.THROH]: { 0: Abilities.STAMINA }, + [Species.SAWK]: { 0: Abilities.SCRAPPY }, + [Species.SEWADDLE]: { 0: Abilities.SHARPNESS }, + [Species.VENIPEDE]: { 0: Abilities.STAMINA }, + [Species.COTTONEE]: { 0: Abilities.FLUFFY }, + [Species.PETILIL]: { 0: Abilities.SIMPLE }, + [Species.BASCULIN]: { 0: Abilities.SUPREME_OVERLORD }, + [Species.SANDILE]: { 0: Abilities.TOUGH_CLAWS }, + [Species.DARUMAKA]: { 0: Abilities.GORILLA_TACTICS }, + [Species.MARACTUS]: { 0: Abilities.WELL_BAKED_BODY }, + [Species.DWEBBLE]: { 0: Abilities.ROCKY_PAYLOAD }, + [Species.SCRAGGY]: { 0: Abilities.PROTEAN }, + [Species.SIGILYPH]: { 0: Abilities.FLARE_BOOST }, + [Species.YAMASK]: { 0: Abilities.PURIFYING_SALT }, + [Species.TIRTOUGA]: { 0: Abilities.WATER_ABSORB }, + [Species.ARCHEN]: { 0: Abilities.MULTISCALE }, + [Species.TRUBBISH]: { 0: Abilities.NEUTRALIZING_GAS }, + [Species.ZORUA]: { 0: Abilities.DARK_AURA }, + [Species.MINCCINO]: { 0: Abilities.FUR_COAT }, + [Species.GOTHITA]: { 0: Abilities.UNNERVE }, + [Species.SOLOSIS]: { 0: Abilities.PSYCHIC_SURGE }, + [Species.DUCKLETT]: { 0: Abilities.DRIZZLE }, + [Species.VANILLITE]: { 0: Abilities.SLUSH_RUSH }, + [Species.DEERLING]: { 0: Abilities.FUR_COAT }, + [Species.EMOLGA]: { 0: Abilities.SERENE_GRACE }, + [Species.KARRABLAST]: { 0: Abilities.QUICK_DRAW }, + [Species.FOONGUS]: { 0: Abilities.THICK_FAT }, + [Species.FRILLISH]: { 0: Abilities.POISON_HEAL }, + [Species.ALOMOMOLA]: { 0: Abilities.MULTISCALE }, + [Species.JOLTIK]: { 0: Abilities.TRANSISTOR }, + [Species.FERROSEED]: { 0: Abilities.ROUGH_SKIN }, + [Species.KLINK]: { 0: Abilities.STEELY_SPIRIT }, + [Species.TYNAMO]: { 0: Abilities.POISON_HEAL }, + [Species.ELGYEM]: { 0: Abilities.BEADS_OF_RUIN }, + [Species.LITWICK]: { 0: Abilities.SHADOW_TAG }, + [Species.AXEW]: { 0: Abilities.DRAGONS_MAW }, + [Species.CUBCHOO]: { 0: Abilities.FUR_COAT }, + [Species.CRYOGONAL]: { 0: Abilities.SNOW_WARNING }, + [Species.SHELMET]: { 0: Abilities.PROTEAN }, + [Species.STUNFISK]: { 0: Abilities.STORM_DRAIN }, + [Species.MIENFOO]: { 0: Abilities.NO_GUARD }, + [Species.DRUDDIGON]: { 0: Abilities.INTIMIDATE }, + [Species.GOLETT]: { 0: Abilities.SHADOW_SHIELD }, + [Species.PAWNIARD]: { 0: Abilities.SWORD_OF_RUIN }, + [Species.BOUFFALANT]: { 0: Abilities.ROCK_HEAD }, + [Species.RUFFLET]: { 0: Abilities.SPEED_BOOST }, + [Species.VULLABY]: { 0: Abilities.THICK_FAT }, + [Species.HEATMOR]: { 0: Abilities.CONTRARY }, + [Species.DURANT]: { 0: Abilities.COMPOUND_EYES }, + [Species.DEINO]: { 0: Abilities.PARENTAL_BOND }, + [Species.LARVESTA]: { 0: Abilities.DROUGHT }, + [Species.COBALION]: { 0: Abilities.INTREPID_SWORD }, + [Species.TERRAKION]: { 0: Abilities.ROCKY_PAYLOAD }, + [Species.VIRIZION]: { 0: Abilities.SHARPNESS }, + [Species.TORNADUS]: { 0: Abilities.DRIZZLE }, + [Species.THUNDURUS]: { 0: Abilities.DRIZZLE }, + [Species.RESHIRAM]: { 0: Abilities.ORICHALCUM_PULSE }, + [Species.ZEKROM]: { 0: Abilities.HADRON_ENGINE }, + [Species.LANDORUS]: { 0: Abilities.STORM_DRAIN }, + [Species.KYUREM]: { 0: Abilities.SNOW_WARNING }, + [Species.KELDEO]: { 0: Abilities.GRIM_NEIGH }, + [Species.MELOETTA]: { 0: Abilities.MINDS_EYE }, + [Species.GENESECT]: { 0: Abilities.PROTEAN }, - [Species.CHESPIN]: Abilities.DAUNTLESS_SHIELD, - [Species.FENNEKIN]: Abilities.PSYCHIC_SURGE, - [Species.FROAKIE]: Abilities.STAKEOUT, - [Species.BUNNELBY]: Abilities.GUTS, - [Species.FLETCHLING]: Abilities.MAGIC_GUARD, - [Species.SCATTERBUG]: Abilities.PRANKSTER, - [Species.LITLEO]: Abilities.BEAST_BOOST, - [Species.FLABEBE]: Abilities.GRASSY_SURGE, - [Species.SKIDDO]: Abilities.SEED_SOWER, - [Species.PANCHAM]: Abilities.FUR_COAT, - [Species.FURFROU]: Abilities.FLUFFY, - [Species.ESPURR]: Abilities.FUR_COAT, - [Species.HONEDGE]: Abilities.SHARPNESS, - [Species.SPRITZEE]: Abilities.FUR_COAT, - [Species.SWIRLIX]: Abilities.RIPEN, - [Species.INKAY]: Abilities.UNNERVE, - [Species.BINACLE]: Abilities.SAP_SIPPER, - [Species.SKRELP]: Abilities.DRAGONS_MAW, - [Species.CLAUNCHER]: Abilities.PROTEAN, - [Species.HELIOPTILE]: Abilities.PROTEAN, - [Species.TYRUNT]: Abilities.RECKLESS, - [Species.AMAURA]: Abilities.ICE_SCALES, - [Species.HAWLUCHA]: Abilities.MOXIE, - [Species.DEDENNE]: Abilities.PIXILATE, - [Species.CARBINK]: Abilities.SOLID_ROCK, - [Species.GOOMY]: Abilities.REGENERATOR, - [Species.KLEFKI]: Abilities.LEVITATE, - [Species.PHANTUMP]: Abilities.SHADOW_TAG, - [Species.PUMPKABOO]: Abilities.WELL_BAKED_BODY, - [Species.BERGMITE]: Abilities.ICE_SCALES, - [Species.NOIBAT]: Abilities.PUNK_ROCK, - [Species.XERNEAS]: Abilities.HARVEST, - [Species.YVELTAL]: Abilities.SOUL_HEART, - [Species.ZYGARDE]: Abilities.ADAPTABILITY, - [Species.DIANCIE]: Abilities.PRISM_ARMOR, - [Species.HOOPA]: Abilities.OPPORTUNIST, - [Species.VOLCANION]: Abilities.FILTER, - [Species.ETERNAL_FLOETTE]: Abilities.MAGIC_GUARD, + [Species.CHESPIN]: { 0: Abilities.DAUNTLESS_SHIELD }, + [Species.FENNEKIN]: { 0: Abilities.PSYCHIC_SURGE }, + [Species.FROAKIE]: { 0: Abilities.STAKEOUT }, + [Species.BUNNELBY]: { 0: Abilities.GUTS }, + [Species.FLETCHLING]: { 0: Abilities.MAGIC_GUARD }, + [Species.SCATTERBUG]: { 0: Abilities.PRANKSTER }, + [Species.LITLEO]: { 0: Abilities.BEAST_BOOST }, + [Species.FLABEBE]: { 0: Abilities.GRASSY_SURGE }, + [Species.SKIDDO]: { 0: Abilities.SEED_SOWER }, + [Species.PANCHAM]: { 0: Abilities.FUR_COAT }, + [Species.FURFROU]: { 0: Abilities.FLUFFY }, + [Species.ESPURR]: { 0: Abilities.FUR_COAT }, + [Species.HONEDGE]: { 0: Abilities.SHARPNESS }, + [Species.SPRITZEE]: { 0: Abilities.FUR_COAT }, + [Species.SWIRLIX]: { 0: Abilities.RIPEN }, + [Species.INKAY]: { 0: Abilities.UNNERVE }, + [Species.BINACLE]: { 0: Abilities.SAP_SIPPER }, + [Species.SKRELP]: { 0: Abilities.DRAGONS_MAW }, + [Species.CLAUNCHER]: { 0: Abilities.PROTEAN }, + [Species.HELIOPTILE]: { 0: Abilities.PROTEAN }, + [Species.TYRUNT]: { 0: Abilities.RECKLESS }, + [Species.AMAURA]: { 0: Abilities.ICE_SCALES }, + [Species.HAWLUCHA]: { 0: Abilities.MOXIE }, + [Species.DEDENNE]: { 0: Abilities.PIXILATE }, + [Species.CARBINK]: { 0: Abilities.SOLID_ROCK }, + [Species.GOOMY]: { 0: Abilities.REGENERATOR }, + [Species.KLEFKI]: { 0: Abilities.LEVITATE }, + [Species.PHANTUMP]: { 0: Abilities.SHADOW_TAG }, + [Species.PUMPKABOO]: { 0: Abilities.WELL_BAKED_BODY }, + [Species.BERGMITE]: { 0: Abilities.ICE_SCALES }, + [Species.NOIBAT]: { 0: Abilities.PUNK_ROCK }, + [Species.XERNEAS]: { 0: Abilities.HARVEST }, + [Species.YVELTAL]: { 0: Abilities.SOUL_HEART }, + [Species.ZYGARDE]: { 0: Abilities.ADAPTABILITY }, + [Species.DIANCIE]: { 0: Abilities.PRISM_ARMOR }, + [Species.HOOPA]: { 0: Abilities.OPPORTUNIST }, + [Species.VOLCANION]: { 0: Abilities.FILTER }, + [Species.ETERNAL_FLOETTE]: { 0: Abilities.MAGIC_GUARD }, - [Species.ROWLET]: Abilities.SNIPER, - [Species.LITTEN]: Abilities.OPPORTUNIST, - [Species.POPPLIO]: Abilities.PUNK_ROCK, - [Species.PIKIPEK]: Abilities.TECHNICIAN, - [Species.YUNGOOS]: Abilities.TOUGH_CLAWS, - [Species.GRUBBIN]: Abilities.SPEED_BOOST, - [Species.CRABRAWLER]: Abilities.WATER_BUBBLE, - [Species.ORICORIO]: Abilities.ADAPTABILITY, - [Species.CUTIEFLY]: Abilities.TINTED_LENS, - [Species.ROCKRUFF]: Abilities.ROCKY_PAYLOAD, - [Species.WISHIWASHI]: Abilities.REGENERATOR, - [Species.MAREANIE]: Abilities.TOXIC_DEBRIS, - [Species.MUDBRAY]: Abilities.CUD_CHEW, - [Species.DEWPIDER]: Abilities.TINTED_LENS, - [Species.FOMANTIS]: Abilities.SHARPNESS, - [Species.MORELULL]: Abilities.TRIAGE, - [Species.SALANDIT]: Abilities.DRAGONS_MAW, - [Species.STUFFUL]: Abilities.SCRAPPY, - [Species.BOUNSWEET]: Abilities.MOXIE, - [Species.COMFEY]: Abilities.FRIEND_GUARD, - [Species.ORANGURU]: Abilities.POWER_SPOT, - [Species.PASSIMIAN]: Abilities.LIBERO, - [Species.WIMPOD]: Abilities.REGENERATOR, - [Species.SANDYGAST]: Abilities.SAND_SPIT, - [Species.PYUKUMUKU]: Abilities.PURIFYING_SALT, - [Species.TYPE_NULL]: Abilities.ADAPTABILITY, - [Species.MINIOR]: Abilities.STURDY, - [Species.KOMALA]: Abilities.GUTS, - [Species.TURTONATOR]: Abilities.DAUNTLESS_SHIELD, - [Species.TOGEDEMARU]: Abilities.ROUGH_SKIN, - [Species.MIMIKYU]: Abilities.TOUGH_CLAWS, - [Species.BRUXISH]: Abilities.MULTISCALE, - [Species.DRAMPA]: Abilities.THICK_FAT, - [Species.DHELMISE]: Abilities.WATER_BUBBLE, - [Species.JANGMO_O]: Abilities.DAUNTLESS_SHIELD, - [Species.TAPU_KOKO]: Abilities.DAUNTLESS_SHIELD, - [Species.TAPU_LELE]: Abilities.SHEER_FORCE, - [Species.TAPU_BULU]: Abilities.TRIAGE, - [Species.TAPU_FINI]: Abilities.FAIRY_AURA, - [Species.COSMOG]: Abilities.BEAST_BOOST, - [Species.NIHILEGO]: Abilities.LEVITATE, - [Species.BUZZWOLE]: Abilities.MOXIE, - [Species.PHEROMOSA]: Abilities.TINTED_LENS, - [Species.XURKITREE]: Abilities.TRANSISTOR, - [Species.CELESTEELA]: Abilities.HEATPROOF, - [Species.KARTANA]: Abilities.LONG_REACH, - [Species.GUZZLORD]: Abilities.POISON_HEAL, - [Species.NECROZMA]: Abilities.BEAST_BOOST, - [Species.MAGEARNA]: Abilities.STEELY_SPIRIT, - [Species.MARSHADOW]: Abilities.IRON_FIST, - [Species.POIPOLE]: Abilities.LEVITATE, - [Species.STAKATAKA]: Abilities.SOLID_ROCK, - [Species.BLACEPHALON]: Abilities.MAGIC_GUARD, - [Species.ZERAORA]: Abilities.TOUGH_CLAWS, - [Species.MELTAN]: Abilities.HEATPROOF, - [Species.ALOLA_RATTATA]: Abilities.ADAPTABILITY, - [Species.ALOLA_SANDSHREW]: Abilities.ICE_SCALES, - [Species.ALOLA_VULPIX]: Abilities.SHEER_FORCE, - [Species.ALOLA_DIGLETT]: Abilities.STURDY, - [Species.ALOLA_MEOWTH]: Abilities.DARK_AURA, - [Species.ALOLA_GEODUDE]: Abilities.DRY_SKIN, - [Species.ALOLA_GRIMER]: Abilities.TOXIC_DEBRIS, + [Species.ROWLET]: { 0: Abilities.SNIPER }, + [Species.LITTEN]: { 0: Abilities.OPPORTUNIST }, + [Species.POPPLIO]: { 0: Abilities.PUNK_ROCK }, + [Species.PIKIPEK]: { 0: Abilities.TECHNICIAN }, + [Species.YUNGOOS]: { 0: Abilities.TOUGH_CLAWS }, + [Species.GRUBBIN]: { 0: Abilities.SPEED_BOOST }, + [Species.CRABRAWLER]: { 0: Abilities.WATER_BUBBLE }, + [Species.ORICORIO]: { 0: Abilities.ADAPTABILITY }, + [Species.CUTIEFLY]: { 0: Abilities.TINTED_LENS }, + [Species.ROCKRUFF]: { 0: Abilities.ROCKY_PAYLOAD }, + [Species.WISHIWASHI]: { 0: Abilities.REGENERATOR }, + [Species.MAREANIE]: { 0: Abilities.TOXIC_DEBRIS }, + [Species.MUDBRAY]: { 0: Abilities.CUD_CHEW }, + [Species.DEWPIDER]: { 0: Abilities.TINTED_LENS }, + [Species.FOMANTIS]: { 0: Abilities.SHARPNESS }, + [Species.MORELULL]: { 0: Abilities.TRIAGE }, + [Species.SALANDIT]: { 0: Abilities.DRAGONS_MAW }, + [Species.STUFFUL]: { 0: Abilities.SCRAPPY }, + [Species.BOUNSWEET]: { 0: Abilities.MOXIE }, + [Species.COMFEY]: { 0: Abilities.FRIEND_GUARD }, + [Species.ORANGURU]: { 0: Abilities.POWER_SPOT }, + [Species.PASSIMIAN]: { 0: Abilities.LIBERO }, + [Species.WIMPOD]: { 0: Abilities.REGENERATOR }, + [Species.SANDYGAST]: { 0: Abilities.SAND_SPIT }, + [Species.PYUKUMUKU]: { 0: Abilities.PURIFYING_SALT }, + [Species.TYPE_NULL]: { 0: Abilities.ADAPTABILITY }, + [Species.MINIOR]: { 0: Abilities.STURDY }, + [Species.KOMALA]: { 0: Abilities.GUTS }, + [Species.TURTONATOR]: { 0: Abilities.DAUNTLESS_SHIELD }, + [Species.TOGEDEMARU]: { 0: Abilities.ROUGH_SKIN }, + [Species.MIMIKYU]: { 0: Abilities.TOUGH_CLAWS }, + [Species.BRUXISH]: { 0: Abilities.MULTISCALE }, + [Species.DRAMPA]: { 0: Abilities.THICK_FAT }, + [Species.DHELMISE]: { 0: Abilities.WATER_BUBBLE }, + [Species.JANGMO_O]: { 0: Abilities.DAUNTLESS_SHIELD }, + [Species.TAPU_KOKO]: { 0: Abilities.DAUNTLESS_SHIELD }, + [Species.TAPU_LELE]: { 0: Abilities.SHEER_FORCE }, + [Species.TAPU_BULU]: { 0: Abilities.TRIAGE }, + [Species.TAPU_FINI]: { 0: Abilities.FAIRY_AURA }, + [Species.COSMOG]: { 0: Abilities.BEAST_BOOST }, + [Species.NIHILEGO]: { 0: Abilities.LEVITATE }, + [Species.BUZZWOLE]: { 0: Abilities.MOXIE }, + [Species.PHEROMOSA]: { 0: Abilities.TINTED_LENS }, + [Species.XURKITREE]: { 0: Abilities.TRANSISTOR }, + [Species.CELESTEELA]: { 0: Abilities.HEATPROOF }, + [Species.KARTANA]: { 0: Abilities.LONG_REACH }, + [Species.GUZZLORD]: { 0: Abilities.POISON_HEAL }, + [Species.NECROZMA]: { 0: Abilities.BEAST_BOOST }, + [Species.MAGEARNA]: { 0: Abilities.STEELY_SPIRIT }, + [Species.MARSHADOW]: { 0: Abilities.IRON_FIST }, + [Species.POIPOLE]: { 0: Abilities.LEVITATE }, + [Species.STAKATAKA]: { 0: Abilities.SOLID_ROCK }, + [Species.BLACEPHALON]: { 0: Abilities.MAGIC_GUARD }, + [Species.ZERAORA]: { 0: Abilities.TOUGH_CLAWS }, + [Species.MELTAN]: { 0: Abilities.HEATPROOF }, + [Species.ALOLA_RATTATA]: { 0: Abilities.ADAPTABILITY }, + [Species.ALOLA_SANDSHREW]: { 0: Abilities.ICE_SCALES }, + [Species.ALOLA_VULPIX]: { 0: Abilities.SHEER_FORCE }, + [Species.ALOLA_DIGLETT]: { 0: Abilities.STURDY }, + [Species.ALOLA_MEOWTH]: { 0: Abilities.DARK_AURA }, + [Species.ALOLA_GEODUDE]: { 0: Abilities.DRY_SKIN }, + [Species.ALOLA_GRIMER]: { 0: Abilities.TOXIC_DEBRIS }, - [Species.GROOKEY]: Abilities.GRASS_PELT, - [Species.SCORBUNNY]: Abilities.NO_GUARD, - [Species.SOBBLE]: Abilities.SUPER_LUCK, - [Species.SKWOVET]: Abilities.HARVEST, - [Species.ROOKIDEE]: Abilities.IRON_BARBS, - [Species.BLIPBUG]: Abilities.PSYCHIC_SURGE, - [Species.NICKIT]: Abilities.MAGICIAN, - [Species.GOSSIFLEUR]: Abilities.GRASSY_SURGE, - [Species.WOOLOO]: Abilities.SCRAPPY, - [Species.CHEWTLE]: Abilities.ROCKY_PAYLOAD, - [Species.YAMPER]: Abilities.SHEER_FORCE, - [Species.ROLYCOLY]: Abilities.SOLID_ROCK, - [Species.APPLIN]: Abilities.DRAGONS_MAW, - [Species.SILICOBRA]: Abilities.SAND_RUSH, - [Species.CRAMORANT]: Abilities.LIGHTNING_ROD, - [Species.ARROKUDA]: Abilities.INTIMIDATE, - [Species.TOXEL]: Abilities.ELECTRIC_SURGE, - [Species.SIZZLIPEDE]: Abilities.SPEED_BOOST, - [Species.CLOBBOPUS]: Abilities.WATER_BUBBLE, - [Species.SINISTEA]: Abilities.SHADOW_SHIELD, - [Species.HATENNA]: Abilities.FAIRY_AURA, - [Species.IMPIDIMP]: Abilities.INTIMIDATE, - [Species.MILCERY]: Abilities.REGENERATOR, - [Species.FALINKS]: Abilities.PARENTAL_BOND, - [Species.PINCURCHIN]: Abilities.ELECTROMORPHOSIS, - [Species.SNOM]: Abilities.SNOW_WARNING, - [Species.STONJOURNER]: Abilities.STURDY, - [Species.EISCUE]: Abilities.ICE_SCALES, - [Species.INDEEDEE]: Abilities.FRIEND_GUARD, - [Species.MORPEKO]: Abilities.MOODY, - [Species.CUFANT]: Abilities.EARTH_EATER, - [Species.DRACOZOLT]: Abilities.NO_GUARD, - [Species.ARCTOZOLT]: Abilities.WATER_ABSORB, - [Species.DRACOVISH]: Abilities.SWIFT_SWIM, - [Species.ARCTOVISH]: Abilities.STRONG_JAW, - [Species.DURALUDON]: Abilities.STEELWORKER, - [Species.DREEPY]: Abilities.PARENTAL_BOND, - [Species.ZACIAN]: Abilities.UNNERVE, - [Species.ZAMAZENTA]: Abilities.UNNERVE, - [Species.ETERNATUS]: Abilities.NEUTRALIZING_GAS, - [Species.KUBFU]: Abilities.IRON_FIST, - [Species.ZARUDE]: Abilities.TOUGH_CLAWS, - [Species.REGIELEKI]: Abilities.ELECTRIC_SURGE, - [Species.REGIDRAGO]: Abilities.MULTISCALE, - [Species.GLASTRIER]: Abilities.FILTER, - [Species.SPECTRIER]: Abilities.SHADOW_SHIELD, - [Species.CALYREX]: Abilities.HARVEST, - [Species.ENAMORUS]: Abilities.FAIRY_AURA, - [Species.GALAR_MEOWTH]: Abilities.UNBURDEN, - [Species.GALAR_PONYTA]: Abilities.CHILLING_NEIGH, - [Species.GALAR_SLOWPOKE]: Abilities.UNAWARE, - [Species.GALAR_FARFETCHD]: Abilities.INTREPID_SWORD, - [Species.GALAR_ARTICUNO]: Abilities.SERENE_GRACE, - [Species.GALAR_ZAPDOS]: Abilities.TOUGH_CLAWS, - [Species.GALAR_MOLTRES]: Abilities.DARK_AURA, - [Species.GALAR_CORSOLA]: Abilities.SHADOW_SHIELD, - [Species.GALAR_ZIGZAGOON]: Abilities.POISON_HEAL, - [Species.GALAR_DARUMAKA]: Abilities.FLASH_FIRE, - [Species.GALAR_YAMASK]: Abilities.TABLETS_OF_RUIN, - [Species.GALAR_STUNFISK]: Abilities.ARENA_TRAP, - [Species.HISUI_GROWLITHE]: Abilities.RECKLESS, - [Species.HISUI_VOLTORB]: Abilities.TRANSISTOR, - [Species.HISUI_QWILFISH]: Abilities.MERCILESS, - [Species.HISUI_SNEASEL]: Abilities.SCRAPPY, - [Species.HISUI_ZORUA]: Abilities.ADAPTABILITY, + [Species.GROOKEY]: { 0: Abilities.GRASS_PELT }, + [Species.SCORBUNNY]: { 0: Abilities.NO_GUARD }, + [Species.SOBBLE]: { 0: Abilities.SUPER_LUCK }, + [Species.SKWOVET]: { 0: Abilities.HARVEST }, + [Species.ROOKIDEE]: { 0: Abilities.IRON_BARBS }, + [Species.BLIPBUG]: { 0: Abilities.PSYCHIC_SURGE }, + [Species.NICKIT]: { 0: Abilities.MAGICIAN }, + [Species.GOSSIFLEUR]: { 0: Abilities.GRASSY_SURGE }, + [Species.WOOLOO]: { 0: Abilities.SCRAPPY }, + [Species.CHEWTLE]: { 0: Abilities.ROCKY_PAYLOAD }, + [Species.YAMPER]: { 0: Abilities.SHEER_FORCE }, + [Species.ROLYCOLY]: { 0: Abilities.SOLID_ROCK }, + [Species.APPLIN]: { 0: Abilities.DRAGONS_MAW }, + [Species.SILICOBRA]: { 0: Abilities.SAND_RUSH }, + [Species.CRAMORANT]: { 0: Abilities.LIGHTNING_ROD }, + [Species.ARROKUDA]: { 0: Abilities.INTIMIDATE }, + [Species.TOXEL]: { 0: Abilities.ELECTRIC_SURGE }, + [Species.SIZZLIPEDE]: { 0: Abilities.SPEED_BOOST }, + [Species.CLOBBOPUS]: { 0: Abilities.WATER_BUBBLE }, + [Species.SINISTEA]: { 0: Abilities.SHADOW_SHIELD }, + [Species.HATENNA]: { 0: Abilities.FAIRY_AURA }, + [Species.IMPIDIMP]: { 0: Abilities.INTIMIDATE }, + [Species.MILCERY]: { 0: Abilities.REGENERATOR }, + [Species.FALINKS]: { 0: Abilities.PARENTAL_BOND }, + [Species.PINCURCHIN]: { 0: Abilities.ELECTROMORPHOSIS }, + [Species.SNOM]: { 0: Abilities.SNOW_WARNING }, + [Species.STONJOURNER]: { 0: Abilities.STURDY }, + [Species.EISCUE]: { 0: Abilities.ICE_SCALES }, + [Species.INDEEDEE]: { 0: Abilities.FRIEND_GUARD }, + [Species.MORPEKO]: { 0: Abilities.MOODY }, + [Species.CUFANT]: { 0: Abilities.EARTH_EATER }, + [Species.DRACOZOLT]: { 0: Abilities.NO_GUARD }, + [Species.ARCTOZOLT]: { 0: Abilities.WATER_ABSORB }, + [Species.DRACOVISH]: { 0: Abilities.SWIFT_SWIM }, + [Species.ARCTOVISH]: { 0: Abilities.STRONG_JAW }, + [Species.DURALUDON]: { 0: Abilities.STEELWORKER }, + [Species.DREEPY]: { 0: Abilities.PARENTAL_BOND }, + [Species.ZACIAN]: { 0: Abilities.UNNERVE }, + [Species.ZAMAZENTA]: { 0: Abilities.UNNERVE }, + [Species.ETERNATUS]: { 0: Abilities.NEUTRALIZING_GAS }, + [Species.KUBFU]: { 0: Abilities.IRON_FIST }, + [Species.ZARUDE]: { 0: Abilities.TOUGH_CLAWS }, + [Species.REGIELEKI]: { 0: Abilities.ELECTRIC_SURGE }, + [Species.REGIDRAGO]: { 0: Abilities.MULTISCALE }, + [Species.GLASTRIER]: { 0: Abilities.FILTER }, + [Species.SPECTRIER]: { 0: Abilities.SHADOW_SHIELD }, + [Species.CALYREX]: { 0: Abilities.HARVEST }, + [Species.ENAMORUS]: { 0: Abilities.FAIRY_AURA }, + [Species.GALAR_MEOWTH]: { 0: Abilities.UNBURDEN }, + [Species.GALAR_PONYTA]: { 0: Abilities.CHILLING_NEIGH }, + [Species.GALAR_SLOWPOKE]: { 0: Abilities.UNAWARE }, + [Species.GALAR_FARFETCHD]: { 0: Abilities.INTREPID_SWORD }, + [Species.GALAR_ARTICUNO]: { 0: Abilities.SERENE_GRACE }, + [Species.GALAR_ZAPDOS]: { 0: Abilities.TOUGH_CLAWS }, + [Species.GALAR_MOLTRES]: { 0: Abilities.DARK_AURA }, + [Species.GALAR_CORSOLA]: { 0: Abilities.SHADOW_SHIELD }, + [Species.GALAR_ZIGZAGOON]: { 0: Abilities.POISON_HEAL }, + [Species.GALAR_DARUMAKA]: { 0: Abilities.FLASH_FIRE }, + [Species.GALAR_YAMASK]: { 0: Abilities.TABLETS_OF_RUIN }, + [Species.GALAR_STUNFISK]: { 0: Abilities.ARENA_TRAP }, + [Species.HISUI_GROWLITHE]: { 0: Abilities.RECKLESS }, + [Species.HISUI_VOLTORB]: { 0: Abilities.TRANSISTOR }, + [Species.HISUI_QWILFISH]: { 0: Abilities.MERCILESS }, + [Species.HISUI_SNEASEL]: { 0: Abilities.SCRAPPY }, + [Species.HISUI_ZORUA]: { 0: Abilities.ADAPTABILITY }, - [Species.SPRIGATITO]: Abilities.MAGICIAN, - [Species.FUECOCO]: Abilities.PUNK_ROCK, - [Species.QUAXLY]: Abilities.OPPORTUNIST, - [Species.LECHONK]: Abilities.SIMPLE, - [Species.TAROUNTULA]: Abilities.HONEY_GATHER, - [Species.NYMBLE]: Abilities.GUTS, - [Species.PAWMI]: Abilities.TRANSISTOR, - [Species.TANDEMAUS]: Abilities.SCRAPPY, - [Species.FIDOUGH]: Abilities.WATER_ABSORB, - [Species.SMOLIV]: Abilities.RIPEN, - [Species.SQUAWKABILLY]: Abilities.MOXIE, - [Species.NACLI]: Abilities.SOLID_ROCK, - [Species.CHARCADET]: Abilities.PRISM_ARMOR, - [Species.TADBULB]: Abilities.STAMINA, - [Species.WATTREL]: Abilities.SHEER_FORCE, - [Species.MASCHIFF]: Abilities.STRONG_JAW, - [Species.SHROODLE]: Abilities.CORROSION, - [Species.BRAMBLIN]: Abilities.SHADOW_SHIELD, - [Species.TOEDSCOOL]: Abilities.PRANKSTER, - [Species.KLAWF]: Abilities.WATER_ABSORB, - [Species.CAPSAKID]: Abilities.PARENTAL_BOND, - [Species.RELLOR]: Abilities.PRANKSTER, - [Species.FLITTLE]: Abilities.DAZZLING, - [Species.TINKATINK]: Abilities.STEELWORKER, - [Species.WIGLETT]: Abilities.STURDY, - [Species.BOMBIRDIER]: Abilities.UNBURDEN, - [Species.FINIZEN]: Abilities.IRON_FIST, - [Species.VAROOM]: Abilities.LEVITATE, - [Species.CYCLIZAR]: Abilities.PROTEAN, - [Species.ORTHWORM]: Abilities.REGENERATOR, - [Species.GLIMMET]: Abilities.LEVITATE, - [Species.GREAVARD]: Abilities.UNAWARE, - [Species.FLAMIGO]: Abilities.MOXIE, - [Species.CETODDLE]: Abilities.REFRIGERATE, - [Species.VELUZA]: Abilities.SUPER_LUCK, - [Species.DONDOZO]: Abilities.DRAGONS_MAW, - [Species.TATSUGIRI]: Abilities.FLUFFY, - [Species.GREAT_TUSK]: Abilities.INTIMIDATE, - [Species.SCREAM_TAIL]: Abilities.UNAWARE, - [Species.BRUTE_BONNET]: Abilities.CHLOROPHYLL, - [Species.FLUTTER_MANE]: Abilities.DAZZLING, - [Species.SLITHER_WING]: Abilities.SCRAPPY, - [Species.SANDY_SHOCKS]: Abilities.ELECTRIC_SURGE, - [Species.IRON_TREADS]: Abilities.STEELY_SPIRIT, - [Species.IRON_BUNDLE]: Abilities.SNOW_WARNING, - [Species.IRON_HANDS]: Abilities.IRON_FIST, - [Species.IRON_JUGULIS]: Abilities.LIGHTNING_ROD, - [Species.IRON_MOTH]: Abilities.LEVITATE, - [Species.IRON_THORNS]: Abilities.SAND_STREAM, - [Species.FRIGIBAX]: Abilities.INTIMIDATE, - [Species.GIMMIGHOUL]: Abilities.HONEY_GATHER, - [Species.WO_CHIEN]: Abilities.VESSEL_OF_RUIN, - [Species.CHIEN_PAO]: Abilities.INTIMIDATE, - [Species.TING_LU]: Abilities.STAMINA, - [Species.CHI_YU]: Abilities.BERSERK, - [Species.ROARING_MOON]: Abilities.TOUGH_CLAWS, - [Species.IRON_VALIANT]: Abilities.NEUROFORCE, - [Species.KORAIDON]: Abilities.OPPORTUNIST, - [Species.MIRAIDON]: Abilities.OPPORTUNIST, - [Species.WALKING_WAKE]: Abilities.BEAST_BOOST, - [Species.IRON_LEAVES]: Abilities.SHARPNESS, - [Species.POLTCHAGEIST]: Abilities.TRIAGE, - [Species.OKIDOGI]: Abilities.DARK_AURA, - [Species.MUNKIDORI]: Abilities.MAGICIAN, - [Species.FEZANDIPITI]: Abilities.PIXILATE, - [Species.OGERPON]: Abilities.OPPORTUNIST, - [Species.GOUGING_FIRE]: Abilities.BEAST_BOOST, - [Species.RAGING_BOLT]: Abilities.BEAST_BOOST, - [Species.IRON_BOULDER]: Abilities.SHARPNESS, - [Species.IRON_CROWN]: Abilities.SHARPNESS, - [Species.TERAPAGOS]: Abilities.SOUL_HEART, - [Species.PECHARUNT]: Abilities.TOXIC_CHAIN, - [Species.PALDEA_TAUROS]: Abilities.ADAPTABILITY, - [Species.PALDEA_WOOPER]: Abilities.THICK_FAT, - [Species.BLOODMOON_URSALUNA]: Abilities.BERSERK + [Species.SPRIGATITO]: { 0: Abilities.MAGICIAN }, + [Species.FUECOCO]: { 0: Abilities.PUNK_ROCK }, + [Species.QUAXLY]: { 0: Abilities.OPPORTUNIST }, + [Species.LECHONK]: { 0: Abilities.SIMPLE }, + [Species.TAROUNTULA]: { 0: Abilities.HONEY_GATHER }, + [Species.NYMBLE]: { 0: Abilities.GUTS }, + [Species.PAWMI]: { 0: Abilities.TRANSISTOR }, + [Species.TANDEMAUS]: { 0: Abilities.SCRAPPY }, + [Species.FIDOUGH]: { 0: Abilities.WATER_ABSORB }, + [Species.SMOLIV]: { 0: Abilities.RIPEN }, + [Species.SQUAWKABILLY]: { 0: Abilities.MOXIE }, + [Species.NACLI]: { 0: Abilities.SOLID_ROCK }, + [Species.CHARCADET]: { 0: Abilities.PRISM_ARMOR }, + [Species.TADBULB]: { 0: Abilities.STAMINA }, + [Species.WATTREL]: { 0: Abilities.SHEER_FORCE }, + [Species.MASCHIFF]: { 0: Abilities.STRONG_JAW }, + [Species.SHROODLE]: { 0: Abilities.CORROSION }, + [Species.BRAMBLIN]: { 0: Abilities.SHADOW_SHIELD }, + [Species.TOEDSCOOL]: { 0: Abilities.PRANKSTER }, + [Species.KLAWF]: { 0: Abilities.WATER_ABSORB }, + [Species.CAPSAKID]: { 0: Abilities.PARENTAL_BOND }, + [Species.RELLOR]: { 0: Abilities.PRANKSTER }, + [Species.FLITTLE]: { 0: Abilities.DAZZLING }, + [Species.TINKATINK]: { 0: Abilities.STEELWORKER }, + [Species.WIGLETT]: { 0: Abilities.STURDY }, + [Species.BOMBIRDIER]: { 0: Abilities.UNBURDEN }, + [Species.FINIZEN]: { 0: Abilities.IRON_FIST }, + [Species.VAROOM]: { 0: Abilities.LEVITATE }, + [Species.CYCLIZAR]: { 0: Abilities.PROTEAN }, + [Species.ORTHWORM]: { 0: Abilities.REGENERATOR }, + [Species.GLIMMET]: { 0: Abilities.LEVITATE }, + [Species.GREAVARD]: { 0: Abilities.UNAWARE }, + [Species.FLAMIGO]: { 0: Abilities.MOXIE }, + [Species.CETODDLE]: { 0: Abilities.REFRIGERATE }, + [Species.VELUZA]: { 0: Abilities.SUPER_LUCK }, + [Species.DONDOZO]: { 0: Abilities.DRAGONS_MAW }, + [Species.TATSUGIRI]: { 0: Abilities.FLUFFY }, + [Species.GREAT_TUSK]: { 0: Abilities.INTIMIDATE }, + [Species.SCREAM_TAIL]: { 0: Abilities.UNAWARE }, + [Species.BRUTE_BONNET]: { 0: Abilities.CHLOROPHYLL }, + [Species.FLUTTER_MANE]: { 0: Abilities.DAZZLING }, + [Species.SLITHER_WING]: { 0: Abilities.SCRAPPY }, + [Species.SANDY_SHOCKS]: { 0: Abilities.ELECTRIC_SURGE }, + [Species.IRON_TREADS]: { 0: Abilities.STEELY_SPIRIT }, + [Species.IRON_BUNDLE]: { 0: Abilities.SNOW_WARNING }, + [Species.IRON_HANDS]: { 0: Abilities.IRON_FIST }, + [Species.IRON_JUGULIS]: { 0: Abilities.LIGHTNING_ROD }, + [Species.IRON_MOTH]: { 0: Abilities.LEVITATE }, + [Species.IRON_THORNS]: { 0: Abilities.SAND_STREAM }, + [Species.FRIGIBAX]: { 0: Abilities.INTIMIDATE }, + [Species.GIMMIGHOUL]: { 0: Abilities.HONEY_GATHER }, + [Species.WO_CHIEN]: { 0: Abilities.VESSEL_OF_RUIN }, + [Species.CHIEN_PAO]: { 0: Abilities.INTIMIDATE }, + [Species.TING_LU]: { 0: Abilities.STAMINA }, + [Species.CHI_YU]: { 0: Abilities.BERSERK }, + [Species.ROARING_MOON]: { 0: Abilities.TOUGH_CLAWS }, + [Species.IRON_VALIANT]: { 0: Abilities.NEUROFORCE }, + [Species.KORAIDON]: { 0: Abilities.OPPORTUNIST }, + [Species.MIRAIDON]: { 0: Abilities.OPPORTUNIST }, + [Species.WALKING_WAKE]: { 0: Abilities.BEAST_BOOST }, + [Species.IRON_LEAVES]: { 0: Abilities.SHARPNESS }, + [Species.POLTCHAGEIST]: { 0: Abilities.TRIAGE }, + [Species.OKIDOGI]: { 0: Abilities.DARK_AURA }, + [Species.MUNKIDORI]: { 0: Abilities.MAGICIAN }, + [Species.FEZANDIPITI]: { 0: Abilities.PIXILATE }, + [Species.OGERPON]: { 0: Abilities.OPPORTUNIST }, + [Species.GOUGING_FIRE]: { 0: Abilities.BEAST_BOOST }, + [Species.RAGING_BOLT]: { 0: Abilities.BEAST_BOOST }, + [Species.IRON_BOULDER]: { 0: Abilities.SHARPNESS }, + [Species.IRON_CROWN]: { 0: Abilities.SHARPNESS }, + [Species.TERAPAGOS]: { 0: Abilities.SOUL_HEART }, + [Species.PECHARUNT]: { 0: Abilities.TOXIC_CHAIN }, + [Species.PALDEA_TAUROS]: { 0: Abilities.ADAPTABILITY }, + [Species.PALDEA_WOOPER]: { 0: Abilities.THICK_FAT }, + [Species.BLOODMOON_URSALUNA]: { 0: Abilities.BERSERK } }; diff --git a/src/data/balance/pokemon-evolutions.ts b/src/data/balance/pokemon-evolutions.ts index bf34b5122dc..a8fe3b5f4ab 100644 --- a/src/data/balance/pokemon-evolutions.ts +++ b/src/data/balance/pokemon-evolutions.ts @@ -12,6 +12,8 @@ import { Species } from "#enums/species"; import { TimeOfDay } from "#enums/time-of-day"; import { DamageMoneyRewardModifier, ExtraModifierModifier, MoneyMultiplierModifier, TempExtraModifierModifier } from "#app/modifier/modifier"; import { SpeciesFormKey } from "#enums/species-form-key"; +import { speciesStarterCosts } from "./starters"; +import i18next from "i18next"; export enum SpeciesWildEvolutionDelay { @@ -120,17 +122,214 @@ export class FusionSpeciesFormEvolution extends SpeciesFormEvolution { export class SpeciesEvolutionCondition { public predicate: EvolutionConditionPredicate; - public enforceFunc: EvolutionConditionEnforceFunc | undefined; + public enforceFunc?: EvolutionConditionEnforceFunc; + public description: string; constructor(predicate: EvolutionConditionPredicate, enforceFunc?: EvolutionConditionEnforceFunc) { this.predicate = predicate; this.enforceFunc = enforceFunc; + this.description = ""; } } -export class SpeciesFriendshipEvolutionCondition extends SpeciesEvolutionCondition { - constructor(friendshipAmount: integer, predicate?: EvolutionConditionPredicate, enforceFunc?: EvolutionConditionEnforceFunc) { - super(p => p.friendship >= friendshipAmount && (!predicate || predicate(p)), enforceFunc); +class GenderEvolutionCondition extends SpeciesEvolutionCondition { + public gender: Gender; + constructor(gender: Gender) { + super(p => p.gender === gender, p => p.gender = gender); + this.gender = gender; + this.description = i18next.t("pokemonEvolutions:gender", { gender: i18next.t(`pokemonEvolutions:${Gender[gender]}`) }); + } +} + +class TimeOfDayEvolutionCondition extends SpeciesEvolutionCondition { + public timesOfDay: TimeOfDay[]; + constructor(tod: "day" | "night") { + if (tod === "day") { + super(() => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY); + this.timesOfDay = [ TimeOfDay.DAWN, TimeOfDay.DAY ]; + } else if (tod === "night") { + super(() => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT); + this.timesOfDay = [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]; + } else { + super(() => false); + this.timesOfDay = []; + } + this.description = i18next.t("pokemonEvolutions:timeOfDay", { tod: i18next.t(`pokemonEvolutions:${tod}`) }); + } +} + +class MoveEvolutionCondition extends SpeciesEvolutionCondition { + public move: Moves; + constructor(move: Moves) { + super(p => p.moveset.filter(m => m?.moveId === move).length > 0); + this.move = move; + const moveKey = Moves[this.move].split("_").filter(f => f).map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join(""); + this.description = i18next.t("pokemonEvolutions:move", { move: i18next.t(`move:${moveKey}.name`) }); + } +} + +class FriendshipEvolutionCondition extends SpeciesEvolutionCondition { + public amount: integer; + constructor(amount: number) { + super(p => p.friendship >= amount); + this.amount = amount; + this.description = i18next.t("pokemonEvolutions:friendship"); + } +} + +class FriendshipTimeOfDayEvolutionCondition extends SpeciesEvolutionCondition { + public amount: integer; + public timesOfDay: TimeOfDay[]; + constructor(amount: number, tod: "day" | "night") { + if (tod === "day") { + super(p => p.friendship >= amount && (globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)); + this.timesOfDay = [ TimeOfDay.DAWN, TimeOfDay.DAY ]; + } else if (tod === "night") { + super(p => p.friendship >= amount && (globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)); + this.timesOfDay = [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]; + } else { + super(p => false); + this.timesOfDay = []; + } + this.amount = amount; + this.description = i18next.t("pokemonEvolutions:friendshipTimeOfDay", { tod: i18next.t(`pokemonEvolutions:${tod}`) }); + } +} + +class FriendshipMoveTypeEvolutionCondition extends SpeciesEvolutionCondition { + public amount: integer; + public type: Type; + constructor(amount: number, type: Type) { + super(p => p.friendship >= amount && !!p.getMoveset().find(m => m?.getMove().type === type)); + this.amount = amount; + this.type = type; + this.description = i18next.t("pokemonEvolutions:friendshipMoveType", { type: i18next.t(`pokemonInfo:Type.${Type[this.type]}`) }); + } +} + +class ShedinjaEvolutionCondition extends SpeciesEvolutionCondition { + constructor() { + super(() => globalScene.getPlayerParty().length < 6 && globalScene.pokeballCounts[PokeballType.POKEBALL] > 0); + this.description = i18next.t("pokemonEvolutions:shedinja"); + } +} + +class PartyTypeEvolutionCondition extends SpeciesEvolutionCondition { + public type: Type; + constructor(type: Type) { + super(() => !!globalScene.getPlayerParty().find(p => p.getTypes(false, false, true).indexOf(type) > -1)); + this.type = type; + this.description = i18next.t("pokemonEvolutions:partyType", { type: i18next.t(`pokemonInfo:Type.${Type[this.type]}`) }); + } +} + +class CaughtEvolutionCondition extends SpeciesEvolutionCondition { + public species: Species; + constructor(species: Species) { + super(() => !!globalScene.gameData.dexData[species].caughtAttr); + this.species = species; + this.description = i18next.t("pokemonEvolutions:caught", { species: i18next.t(`pokemon:${Species[this.species].toLowerCase()}`) }); + } +} + +class WeatherEvolutionCondition extends SpeciesEvolutionCondition { + public weatherTypes: WeatherType[]; + constructor(weatherTypes: WeatherType[]) { + super(() => weatherTypes.indexOf(globalScene.arena.weather?.weatherType || WeatherType.NONE) > -1); + this.weatherTypes = weatherTypes; + } +} + +class MoveTypeEvolutionCondition extends SpeciesEvolutionCondition { + public type: Type; + constructor(type: Type) { + super(p => p.moveset.filter(m => m?.getMove().type === type).length > 0); + this.type = type; + this.description = i18next.t("pokemonEvolutions:moveType", { type: i18next.t(`pokemonInfo:Type.${Type[this.type]}`) }); + } +} + +class TreasureEvolutionCondition extends SpeciesEvolutionCondition { + constructor() { + super(p => p.evoCounter + + p.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length + + globalScene.findModifiers(m => m instanceof MoneyMultiplierModifier + || m instanceof ExtraModifierModifier || m instanceof TempExtraModifierModifier).length > 9); + this.description = i18next.t("pokemonEvolutions:treasure"); + } +} + +class TyrogueEvolutionCondition extends SpeciesEvolutionCondition { + public move: Moves; + constructor(move: Moves) { + super(p => + p.getMoveset(true).find(m => m && [ Moves.LOW_SWEEP, Moves.MACH_PUNCH, Moves.RAPID_SPIN ].includes(m?.moveId))?.moveId === move); + this.move = move; + const moveKey = Moves[this.move].split("_").filter(f => f).map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join(""); + this.description = i18next.t("pokemonEvolutions:move", { move: i18next.t(`move:${moveKey}.name`) }); + } +} + +class NatureEvolutionCondition extends SpeciesEvolutionCondition { + public natures: Nature[]; + constructor(natures: Nature[]) { + super(p => natures.indexOf(p.getNature()) > -1); + this.natures = natures; + this.description = i18next.t("pokemonEvolutions:nature"); + } +} + +class MoveTimeOfDayEvolutionCondition extends SpeciesEvolutionCondition { + public move: Moves; + public timesOfDay: TimeOfDay[]; + constructor(move: Moves, tod: "day" | "night") { + if (tod === "day") { + super(p => p.moveset.filter(m => m?.moveId === move).length > 0 && (globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)); + this.move = move; + this.timesOfDay = [ TimeOfDay.DAWN, TimeOfDay.DAY ]; + } else if (tod === "night") { + super(p => p.moveset.filter(m => m?.moveId === move).length > 0 && (globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)); + this.move = move; + this.timesOfDay = [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]; + } else { + super(() => false); + this.timesOfDay = []; + } + const moveKey = Moves[this.move].split("_").filter(f => f).map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join(""); + this.description = i18next.t("pokemonEvolutions:moveTimeOfDay", { move: i18next.t(`move:${moveKey}.name`), tod: i18next.t(`pokemonEvolutions:${tod}`) }); + } +} + +class BiomeEvolutionCondition extends SpeciesEvolutionCondition { + public biomes: Biome[]; + constructor(biomes: Biome[]) { + super(() => biomes.filter(b => b === globalScene.arena.biomeType).length > 0); + this.biomes = biomes; + this.description = i18next.t("pokemonEvolutions:biome"); + } +} + +class DunsparceEvolutionCondition extends SpeciesEvolutionCondition { + constructor() { + super(p => { + let ret = false; + if (p.moveset.filter(m => m?.moveId === Moves.HYPER_DRILL).length > 0) { + globalScene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4), p.id); + } + return ret; + }); + const moveKey = Moves[Moves.HYPER_DRILL].split("_").filter(f => f).map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join(""); + this.description = i18next.t("pokemonEvolutions:move", { move: i18next.t(`move:${moveKey}.name`) }); + } +} + +class TandemausEvolutionCondition extends SpeciesEvolutionCondition { + constructor() { + super(p => { + let ret = false; + globalScene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4), p.id); + return ret; + }); } } @@ -267,8 +466,8 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.ELECTRODE, 30, null, null) ], [Species.CUBONE]: [ - new SpeciesEvolution(Species.ALOLA_MAROWAK, 28, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)), - new SpeciesEvolution(Species.MAROWAK, 28, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)) + new SpeciesEvolution(Species.ALOLA_MAROWAK, 28, null, new TimeOfDayEvolutionCondition("night")), + new SpeciesEvolution(Species.MAROWAK, 28, null, new TimeOfDayEvolutionCondition("day")) ], [Species.TYROGUE]: [ /** @@ -277,19 +476,13 @@ export const pokemonEvolutions: PokemonEvolutions = { * If Tyrogue knows multiple of these moves, its evolution is based on * the first qualifying move in its moveset. */ - new SpeciesEvolution(Species.HITMONLEE, 20, null, new SpeciesEvolutionCondition(p => - p.getMoveset(true).find(move => move && [ Moves.LOW_SWEEP, Moves.MACH_PUNCH, Moves.RAPID_SPIN ].includes(move?.moveId))?.moveId === Moves.LOW_SWEEP - )), - new SpeciesEvolution(Species.HITMONCHAN, 20, null, new SpeciesEvolutionCondition(p => - p.getMoveset(true).find(move => move && [ Moves.LOW_SWEEP, Moves.MACH_PUNCH, Moves.RAPID_SPIN ].includes(move?.moveId))?.moveId === Moves.MACH_PUNCH - )), - new SpeciesEvolution(Species.HITMONTOP, 20, null, new SpeciesEvolutionCondition(p => - p.getMoveset(true).find(move => move && [ Moves.LOW_SWEEP, Moves.MACH_PUNCH, Moves.RAPID_SPIN ].includes(move?.moveId))?.moveId === Moves.RAPID_SPIN - )), + new SpeciesEvolution(Species.HITMONLEE, 20, null, new TyrogueEvolutionCondition(Moves.LOW_SWEEP)), + new SpeciesEvolution(Species.HITMONCHAN, 20, null, new TyrogueEvolutionCondition(Moves.MACH_PUNCH)), + new SpeciesEvolution(Species.HITMONTOP, 20, null, new TyrogueEvolutionCondition(Moves.RAPID_SPIN)), ], [Species.KOFFING]: [ - new SpeciesEvolution(Species.GALAR_WEEZING, 35, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)), - new SpeciesEvolution(Species.WEEZING, 35, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)) + new SpeciesEvolution(Species.GALAR_WEEZING, 35, null, new TimeOfDayEvolutionCondition("night")), + new SpeciesEvolution(Species.WEEZING, 35, null, new TimeOfDayEvolutionCondition("day")) ], [Species.RHYHORN]: [ new SpeciesEvolution(Species.RHYDON, 42, null, null) @@ -334,8 +527,8 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.QUILAVA, 14, null, null) ], [Species.QUILAVA]: [ - new SpeciesEvolution(Species.HISUI_TYPHLOSION, 36, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)), - new SpeciesEvolution(Species.TYPHLOSION, 36, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)) + new SpeciesEvolution(Species.HISUI_TYPHLOSION, 36, null, new TimeOfDayEvolutionCondition("night")), + new SpeciesEvolution(Species.TYPHLOSION, 36, null, new TimeOfDayEvolutionCondition("day")) ], [Species.TOTODILE]: [ new SpeciesEvolution(Species.CROCONAW, 18, null, null) @@ -437,8 +630,8 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.LINOONE, 20, null, null) ], [Species.WURMPLE]: [ - new SpeciesEvolution(Species.SILCOON, 7, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)), - new SpeciesEvolution(Species.CASCOON, 7, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)) + new SpeciesEvolution(Species.SILCOON, 7, null, new TimeOfDayEvolutionCondition("day")), + new SpeciesEvolution(Species.CASCOON, 7, null, new TimeOfDayEvolutionCondition("night")) ], [Species.SILCOON]: [ new SpeciesEvolution(Species.BEAUTIFLY, 10, null, null) @@ -462,8 +655,8 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.KIRLIA, 20, null, null) ], [Species.KIRLIA]: [ - new SpeciesEvolution(Species.GARDEVOIR, 30, null, new SpeciesEvolutionCondition(p => p.gender === Gender.FEMALE, p => p.gender = Gender.FEMALE)), - new SpeciesEvolution(Species.GALLADE, 30, null, new SpeciesEvolutionCondition(p => p.gender === Gender.MALE, p => p.gender = Gender.MALE)) + new SpeciesEvolution(Species.GARDEVOIR, 30, null, new GenderEvolutionCondition(Gender.FEMALE)), + new SpeciesEvolution(Species.GALLADE, 30, null, new GenderEvolutionCondition(Gender.MALE)) ], [Species.SURSKIT]: [ new SpeciesEvolution(Species.MASQUERAIN, 22, null, null) @@ -479,7 +672,7 @@ export const pokemonEvolutions: PokemonEvolutions = { ], [Species.NINCADA]: [ new SpeciesEvolution(Species.NINJASK, 20, null, null), - new SpeciesEvolution(Species.SHEDINJA, 20, null, new SpeciesEvolutionCondition(p => globalScene.getPlayerParty().length < 6 && globalScene.pokeballCounts[PokeballType.POKEBALL] > 0)) + new SpeciesEvolution(Species.SHEDINJA, 20, null, new ShedinjaEvolutionCondition()) ], [Species.WHISMUR]: [ new SpeciesEvolution(Species.LOUDRED, 20, null, null) @@ -551,8 +744,8 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.DUSCLOPS, 37, null, null) ], [Species.SNORUNT]: [ - new SpeciesEvolution(Species.GLALIE, 42, null, new SpeciesEvolutionCondition(p => p.gender === Gender.MALE, p => p.gender = Gender.MALE)), - new SpeciesEvolution(Species.FROSLASS, 42, null, new SpeciesEvolutionCondition(p => p.gender === Gender.FEMALE, p => p.gender = Gender.FEMALE)) + new SpeciesEvolution(Species.GLALIE, 42, null, new GenderEvolutionCondition(Gender.MALE)), + new SpeciesEvolution(Species.FROSLASS, 42, null, new GenderEvolutionCondition(Gender.FEMALE)) ], [Species.SPHEAL]: [ new SpeciesEvolution(Species.SEALEO, 32, null, null) @@ -615,11 +808,11 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.BASTIODON, 30, null, null) ], [Species.BURMY]: [ - new SpeciesEvolution(Species.MOTHIM, 20, null, new SpeciesEvolutionCondition(p => p.gender === Gender.MALE, p => p.gender = Gender.MALE)), - new SpeciesEvolution(Species.WORMADAM, 20, null, new SpeciesEvolutionCondition(p => p.gender === Gender.FEMALE, p => p.gender = Gender.FEMALE)) + new SpeciesEvolution(Species.MOTHIM, 20, null, new GenderEvolutionCondition(Gender.MALE)), + new SpeciesEvolution(Species.WORMADAM, 20, null, new GenderEvolutionCondition(Gender.FEMALE)) ], [Species.COMBEE]: [ - new SpeciesEvolution(Species.VESPIQUEN, 21, null, new SpeciesEvolutionCondition(p => p.gender === Gender.FEMALE, p => p.gender = Gender.FEMALE)) + new SpeciesEvolution(Species.VESPIQUEN, 21, null, new GenderEvolutionCondition(Gender.FEMALE)) ], [Species.BUIZEL]: [ new SpeciesEvolution(Species.FLOATZEL, 26, null, null) @@ -661,7 +854,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.LUMINEON, 31, null, null) ], [Species.MANTYKE]: [ - new SpeciesEvolution(Species.MANTINE, 32, null, new SpeciesEvolutionCondition(p => !!globalScene.gameData.dexData[Species.REMORAID].caughtAttr), SpeciesWildEvolutionDelay.MEDIUM) + new SpeciesEvolution(Species.MANTINE, 32, null, new CaughtEvolutionCondition(Species.REMORAID), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.SNOVER]: [ new SpeciesEvolution(Species.ABOMASNOW, 40, null, null) @@ -682,8 +875,8 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.DEWOTT, 17, null, null) ], [Species.DEWOTT]: [ - new SpeciesEvolution(Species.HISUI_SAMUROTT, 36, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)), - new SpeciesEvolution(Species.SAMUROTT, 36, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)) + new SpeciesEvolution(Species.HISUI_SAMUROTT, 36, null, new TimeOfDayEvolutionCondition("night")), + new SpeciesEvolution(Species.SAMUROTT, 36, null, new TimeOfDayEvolutionCondition("day")) ], [Species.PATRAT]: [ new SpeciesEvolution(Species.WATCHOG, 20, null, null) @@ -833,8 +1026,8 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.KINGAMBIT, 1, EvolutionItem.LEADERS_CREST, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.RUFFLET]: [ - new SpeciesEvolution(Species.HISUI_BRAVIARY, 54, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)), - new SpeciesEvolution(Species.BRAVIARY, 54, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)) + new SpeciesEvolution(Species.HISUI_BRAVIARY, 54, null, new TimeOfDayEvolutionCondition("night")), + new SpeciesEvolution(Species.BRAVIARY, 54, null, new TimeOfDayEvolutionCondition("day")) ], [Species.VULLABY]: [ new SpeciesEvolution(Species.MANDIBUZZ, 54, null, null) @@ -891,11 +1084,11 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.GOGOAT, 32, null, null) ], [Species.PANCHAM]: [ - new SpeciesEvolution(Species.PANGORO, 32, null, new SpeciesEvolutionCondition(p => !!globalScene.getPlayerParty().find(p => p.getTypes(false, false, true).indexOf(Type.DARK) > -1)), SpeciesWildEvolutionDelay.MEDIUM) + new SpeciesEvolution(Species.PANGORO, 32, null, new PartyTypeEvolutionCondition(Type.DARK), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.ESPURR]: [ - new SpeciesFormEvolution(Species.MEOWSTIC, "", "female", 25, null, new SpeciesEvolutionCondition(p => p.gender === Gender.FEMALE, p => p.gender = Gender.FEMALE)), - new SpeciesFormEvolution(Species.MEOWSTIC, "", "", 25, null, new SpeciesEvolutionCondition(p => p.gender === Gender.MALE, p => p.gender = Gender.MALE)) + new SpeciesFormEvolution(Species.MEOWSTIC, "", "female", 25, null, new GenderEvolutionCondition(Gender.FEMALE)), + new SpeciesFormEvolution(Species.MEOWSTIC, "", "", 25, null, new GenderEvolutionCondition(Gender.MALE)) ], [Species.HONEDGE]: [ new SpeciesEvolution(Species.DOUBLADE, 35, null, null) @@ -913,21 +1106,21 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.CLAWITZER, 37, null, null) ], [Species.TYRUNT]: [ - new SpeciesEvolution(Species.TYRANTRUM, 39, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)) + new SpeciesEvolution(Species.TYRANTRUM, 39, null, new TimeOfDayEvolutionCondition("day")) ], [Species.AMAURA]: [ - new SpeciesEvolution(Species.AURORUS, 39, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)) + new SpeciesEvolution(Species.AURORUS, 39, null, new TimeOfDayEvolutionCondition("night")) ], [Species.GOOMY]: [ - new SpeciesEvolution(Species.HISUI_SLIGGOO, 40, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)), - new SpeciesEvolution(Species.SLIGGOO, 40, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)) + new SpeciesEvolution(Species.HISUI_SLIGGOO, 40, null, new TimeOfDayEvolutionCondition("night")), + new SpeciesEvolution(Species.SLIGGOO, 40, null, new TimeOfDayEvolutionCondition("day")) ], [Species.SLIGGOO]: [ - new SpeciesEvolution(Species.GOODRA, 50, null, new SpeciesEvolutionCondition(p => [ WeatherType.RAIN, WeatherType.FOG, WeatherType.HEAVY_RAIN ].indexOf(globalScene.arena.weather?.weatherType || WeatherType.NONE) > -1), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.GOODRA, 50, null, new WeatherEvolutionCondition([ WeatherType.RAIN, WeatherType.FOG, WeatherType.HEAVY_RAIN ]), SpeciesWildEvolutionDelay.LONG) ], [Species.BERGMITE]: [ - new SpeciesEvolution(Species.HISUI_AVALUGG, 37, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)), - new SpeciesEvolution(Species.AVALUGG, 37, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)) + new SpeciesEvolution(Species.HISUI_AVALUGG, 37, null, new TimeOfDayEvolutionCondition("night")), + new SpeciesEvolution(Species.AVALUGG, 37, null, new TimeOfDayEvolutionCondition("day")) ], [Species.NOIBAT]: [ new SpeciesEvolution(Species.NOIVERN, 48, null, null) @@ -936,8 +1129,8 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.DARTRIX, 17, null, null) ], [Species.DARTRIX]: [ - new SpeciesEvolution(Species.HISUI_DECIDUEYE, 36, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)), - new SpeciesEvolution(Species.DECIDUEYE, 34, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)) + new SpeciesEvolution(Species.HISUI_DECIDUEYE, 36, null, new TimeOfDayEvolutionCondition("night")), + new SpeciesEvolution(Species.DECIDUEYE, 34, null, new TimeOfDayEvolutionCondition("day")) ], [Species.LITTEN]: [ new SpeciesEvolution(Species.TORRACAT, 17, null, null) @@ -958,7 +1151,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.TOUCANNON, 28, null, null) ], [Species.YUNGOOS]: [ - new SpeciesEvolution(Species.GUMSHOOS, 20, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)) + new SpeciesEvolution(Species.GUMSHOOS, 20, null, new TimeOfDayEvolutionCondition("day")) ], [Species.GRUBBIN]: [ new SpeciesEvolution(Species.CHARJABUG, 20, null, null) @@ -976,13 +1169,13 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.ARAQUANID, 22, null, null) ], [Species.FOMANTIS]: [ - new SpeciesEvolution(Species.LURANTIS, 34, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)) + new SpeciesEvolution(Species.LURANTIS, 34, null, new TimeOfDayEvolutionCondition("day")) ], [Species.MORELULL]: [ new SpeciesEvolution(Species.SHIINOTIC, 24, null, null) ], [Species.SALANDIT]: [ - new SpeciesEvolution(Species.SALAZZLE, 33, null, new SpeciesEvolutionCondition(p => p.gender === Gender.FEMALE, p => p.gender = Gender.FEMALE)) + new SpeciesEvolution(Species.SALAZZLE, 33, null, new GenderEvolutionCondition(Gender.FEMALE)) ], [Species.STUFFUL]: [ new SpeciesEvolution(Species.BEWEAR, 27, null, null) @@ -1013,7 +1206,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.MELMETAL, 48, null, null) ], [Species.ALOLA_RATTATA]: [ - new SpeciesEvolution(Species.ALOLA_RATICATE, 20, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)) + new SpeciesEvolution(Species.ALOLA_RATICATE, 20, null, new TimeOfDayEvolutionCondition("night")) ], [Species.ALOLA_DIGLETT]: [ new SpeciesEvolution(Species.ALOLA_DUGTRIO, 26, null, null) @@ -1086,7 +1279,8 @@ export const pokemonEvolutions: PokemonEvolutions = { ], [Species.TOXEL]: [ new SpeciesFormEvolution(Species.TOXTRICITY, "", "lowkey", 30, null, - new SpeciesEvolutionCondition(p => [ Nature.LONELY, Nature.BOLD, Nature.RELAXED, Nature.TIMID, Nature.SERIOUS, Nature.MODEST, Nature.MILD, Nature.QUIET, Nature.BASHFUL, Nature.CALM, Nature.GENTLE, Nature.CAREFUL ].indexOf(p.getNature()) > -1)), + new NatureEvolutionCondition([ Nature.LONELY, Nature.BOLD, Nature.RELAXED, Nature.TIMID, Nature.SERIOUS, Nature.MODEST, Nature.MILD, Nature.QUIET, Nature.BASHFUL, Nature.CALM, Nature.GENTLE, Nature.CAREFUL ]) + ), new SpeciesFormEvolution(Species.TOXTRICITY, "", "amped", 30, null, null) ], [Species.SIZZLIPEDE]: [ @@ -1136,7 +1330,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.GALAR_LINOONE, 20, null, null) ], [Species.GALAR_LINOONE]: [ - new SpeciesEvolution(Species.OBSTAGOON, 35, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)) + new SpeciesEvolution(Species.OBSTAGOON, 35, null, new TimeOfDayEvolutionCondition("night")) ], [Species.GALAR_YAMASK]: [ new SpeciesEvolution(Species.RUNERIGUS, 34, null, null) @@ -1145,7 +1339,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.HISUI_ZOROARK, 30, null, null) ], [Species.HISUI_SLIGGOO]: [ - new SpeciesEvolution(Species.HISUI_GOODRA, 50, null, new SpeciesEvolutionCondition(p => [ WeatherType.RAIN, WeatherType.FOG, WeatherType.HEAVY_RAIN ].indexOf(globalScene.arena.weather?.weatherType || WeatherType.NONE) > -1), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.HISUI_GOODRA, 50, null, new WeatherEvolutionCondition([ WeatherType.RAIN, WeatherType.FOG, WeatherType.HEAVY_RAIN ]), SpeciesWildEvolutionDelay.LONG) ], [Species.SPRIGATITO]: [ new SpeciesEvolution(Species.FLORAGATO, 16, null, null) @@ -1166,8 +1360,8 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.QUAQUAVAL, 36, null, null) ], [Species.LECHONK]: [ - new SpeciesFormEvolution(Species.OINKOLOGNE, "", "female", 18, null, new SpeciesEvolutionCondition(p => p.gender === Gender.FEMALE, p => p.gender = Gender.FEMALE)), - new SpeciesFormEvolution(Species.OINKOLOGNE, "", "", 18, null, new SpeciesEvolutionCondition(p => p.gender === Gender.MALE, p => p.gender = Gender.MALE)) + new SpeciesFormEvolution(Species.OINKOLOGNE, "", "female", 18, null, new GenderEvolutionCondition(Gender.FEMALE)), + new SpeciesFormEvolution(Species.OINKOLOGNE, "", "", 18, null, new GenderEvolutionCondition(Gender.MALE)) ], [Species.TAROUNTULA]: [ new SpeciesEvolution(Species.SPIDOPS, 15, null, null) @@ -1182,11 +1376,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.PAWMOT, 32, null, null) ], [Species.TANDEMAUS]: [ - new SpeciesFormEvolution(Species.MAUSHOLD, "", "three", 25, null, new SpeciesEvolutionCondition(p => { - let ret = false; - globalScene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4), p.id); - return ret; - })), + new SpeciesFormEvolution(Species.MAUSHOLD, "", "three", 25, null, new TandemausEvolutionCondition()), new SpeciesEvolution(Species.MAUSHOLD, 25, null, null) ], [Species.FIDOUGH]: [ @@ -1244,7 +1434,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.GLIMMORA, 35, null, null) ], [Species.GREAVARD]: [ - new SpeciesEvolution(Species.HOUNDSTONE, 30, null, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)) + new SpeciesEvolution(Species.HOUNDSTONE, 30, null, new TimeOfDayEvolutionCondition("night")) ], [Species.FRIGIBAX]: [ new SpeciesEvolution(Species.ARCTIBAX, 35, null, null) @@ -1301,21 +1491,21 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.EXEGGUTOR, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.TANGELA]: [ - new SpeciesEvolution(Species.TANGROWTH, 34, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.ANCIENT_POWER).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.TANGROWTH, 34, null, new MoveEvolutionCondition(Moves.ANCIENT_POWER), SpeciesWildEvolutionDelay.LONG) ], [Species.LICKITUNG]: [ - new SpeciesEvolution(Species.LICKILICKY, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.ROLLOUT).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.LICKILICKY, 32, null, new MoveEvolutionCondition(Moves.ROLLOUT), SpeciesWildEvolutionDelay.LONG) ], [Species.STARYU]: [ new SpeciesEvolution(Species.STARMIE, 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.EEVEE]: [ - new SpeciesFormEvolution(Species.SYLVEON, "", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => !!p.getMoveset().find(m => m?.getMove().type === Type.FAIRY)), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.SYLVEON, "partner", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => !!p.getMoveset().find(m => m?.getMove().type === Type.FAIRY)), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.ESPEON, "", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAY), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.ESPEON, "partner", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAY), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.UMBREON, "", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.UMBREON, "partner", "", 1, null, new SpeciesFriendshipEvolutionCondition(120, p => globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT), SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.SYLVEON, "", "", 1, null, new FriendshipMoveTypeEvolutionCondition(120, Type.FAIRY), SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.SYLVEON, "partner", "", 1, null, new FriendshipMoveTypeEvolutionCondition(120, Type.FAIRY), SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.ESPEON, "", "", 1, null, new FriendshipTimeOfDayEvolutionCondition(120, "day"), SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.ESPEON, "partner", "", 1, null, new FriendshipTimeOfDayEvolutionCondition(120, "day"), SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.UMBREON, "", "", 1, null, new FriendshipTimeOfDayEvolutionCondition(120, "night"), SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.UMBREON, "partner", "", 1, null, new FriendshipTimeOfDayEvolutionCondition(120, "night"), SpeciesWildEvolutionDelay.LONG), new SpeciesFormEvolution(Species.VAPOREON, "", "", 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.LONG), new SpeciesFormEvolution(Species.VAPOREON, "partner", "", 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.LONG), new SpeciesFormEvolution(Species.JOLTEON, "", "", 1, EvolutionItem.THUNDER_STONE, null, SpeciesWildEvolutionDelay.LONG), @@ -1331,13 +1521,13 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.TOGEKISS, 1, EvolutionItem.SHINY_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.AIPOM]: [ - new SpeciesEvolution(Species.AMBIPOM, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.DOUBLE_HIT).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.AMBIPOM, 32, null, new MoveEvolutionCondition(Moves.DOUBLE_HIT), SpeciesWildEvolutionDelay.LONG) ], [Species.SUNKERN]: [ new SpeciesEvolution(Species.SUNFLORA, 1, EvolutionItem.SUN_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.YANMA]: [ - new SpeciesEvolution(Species.YANMEGA, 33, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.ANCIENT_POWER).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.YANMEGA, 33, null, new MoveEvolutionCondition(Moves.ANCIENT_POWER), SpeciesWildEvolutionDelay.LONG) ], [Species.MURKROW]: [ new SpeciesEvolution(Species.HONCHKROW, 1, EvolutionItem.DUSK_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG) @@ -1346,32 +1536,26 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.MISMAGIUS, 1, EvolutionItem.DUSK_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.GIRAFARIG]: [ - new SpeciesEvolution(Species.FARIGIRAF, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.TWIN_BEAM).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.FARIGIRAF, 32, null, new MoveEvolutionCondition(Moves.TWIN_BEAM), SpeciesWildEvolutionDelay.LONG) ], [Species.DUNSPARCE]: [ - new SpeciesFormEvolution(Species.DUDUNSPARCE, "", "three-segment", 32, null, new SpeciesEvolutionCondition(p => { - let ret = false; - if (p.moveset.filter(m => m?.moveId === Moves.HYPER_DRILL).length > 0) { - globalScene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4), p.id); - } - return ret; - }), SpeciesWildEvolutionDelay.LONG), - new SpeciesEvolution(Species.DUDUNSPARCE, 32, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.HYPER_DRILL).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesFormEvolution(Species.DUDUNSPARCE, "", "three-segment", 32, null, new DunsparceEvolutionCondition(), SpeciesWildEvolutionDelay.LONG), + new SpeciesEvolution(Species.DUDUNSPARCE, 32, null, new MoveEvolutionCondition(Moves.HYPER_DRILL), SpeciesWildEvolutionDelay.LONG) ], [Species.GLIGAR]: [ - new SpeciesEvolution(Species.GLISCOR, 1, EvolutionItem.RAZOR_FANG, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT /* Razor fang at night*/), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.GLISCOR, 1, EvolutionItem.RAZOR_FANG, new TimeOfDayEvolutionCondition("night") /* Razor fang at night*/, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.SNEASEL]: [ - new SpeciesEvolution(Species.WEAVILE, 1, EvolutionItem.RAZOR_CLAW, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT /* Razor claw at night*/), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.WEAVILE, 1, EvolutionItem.RAZOR_CLAW, new TimeOfDayEvolutionCondition("night") /* Razor claw at night*/, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.URSARING]: [ new SpeciesEvolution(Species.URSALUNA, 1, EvolutionItem.PEAT_BLOCK, null, SpeciesWildEvolutionDelay.VERY_LONG) //Ursaring does not evolve into Bloodmoon Ursaluna ], [Species.PILOSWINE]: [ - new SpeciesEvolution(Species.MAMOSWINE, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.ANCIENT_POWER).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.MAMOSWINE, 1, null, new MoveEvolutionCondition(Moves.ANCIENT_POWER), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.STANTLER]: [ - new SpeciesEvolution(Species.WYRDEER, 25, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.PSYSHIELD_BASH).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.WYRDEER, 25, null, new MoveEvolutionCondition(Moves.PSYSHIELD_BASH), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.LOMBRE]: [ new SpeciesEvolution(Species.LUDICOLO, 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.LONG) @@ -1389,11 +1573,11 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.ROSERADE, 1, EvolutionItem.SHINY_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.BONSLY]: [ - new SpeciesEvolution(Species.SUDOWOODO, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.MIMIC).length > 0), SpeciesWildEvolutionDelay.MEDIUM) + new SpeciesEvolution(Species.SUDOWOODO, 1, null, new MoveEvolutionCondition(Moves.MIMIC), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.MIME_JR]: [ - new SpeciesEvolution(Species.GALAR_MR_MIME, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.MIMIC).length > 0 && (globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT)), SpeciesWildEvolutionDelay.MEDIUM), - new SpeciesEvolution(Species.MR_MIME, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.MIMIC).length > 0 && (globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY)), SpeciesWildEvolutionDelay.MEDIUM) + new SpeciesEvolution(Species.GALAR_MR_MIME, 1, null, new MoveTimeOfDayEvolutionCondition(Moves.MIMIC, "night"), SpeciesWildEvolutionDelay.MEDIUM), + new SpeciesEvolution(Species.MR_MIME, 1, null, new MoveTimeOfDayEvolutionCondition(Moves.MIMIC, "day"), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.PANSAGE]: [ new SpeciesEvolution(Species.SIMISAGE, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG) @@ -1415,8 +1599,8 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.LILLIGANT, 1, EvolutionItem.SUN_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.BASCULIN]: [ - new SpeciesFormEvolution(Species.BASCULEGION, "white-striped", "female", 40, null, new SpeciesEvolutionCondition(p => p.gender === Gender.FEMALE, p => p.gender = Gender.FEMALE), SpeciesWildEvolutionDelay.VERY_LONG), - new SpeciesFormEvolution(Species.BASCULEGION, "white-striped", "male", 40, null, new SpeciesEvolutionCondition(p => p.gender === Gender.MALE, p => p.gender = Gender.MALE), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesFormEvolution(Species.BASCULEGION, "white-striped", "female", 40, null, new GenderEvolutionCondition(Gender.FEMALE), SpeciesWildEvolutionDelay.VERY_LONG), + new SpeciesFormEvolution(Species.BASCULEGION, "white-striped", "male", 40, null, new GenderEvolutionCondition(Gender.MALE), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.MINCCINO]: [ new SpeciesEvolution(Species.CINCCINO, 1, EvolutionItem.SHINY_STONE, null, SpeciesWildEvolutionDelay.LONG) @@ -1443,15 +1627,15 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.CRABOMINABLE, 1, EvolutionItem.ICE_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.ROCKRUFF]: [ - new SpeciesFormEvolution(Species.LYCANROC, "", "midday", 25, null, new SpeciesEvolutionCondition(p => (globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY) && (p.formIndex === 0))), - new SpeciesFormEvolution(Species.LYCANROC, "own-tempo", "dusk", 25, null, new SpeciesEvolutionCondition(p => p.formIndex === 1)), - new SpeciesFormEvolution(Species.LYCANROC, "", "midnight", 25, null, new SpeciesEvolutionCondition(p => (globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT) && (p.formIndex === 0))) + new SpeciesFormEvolution(Species.LYCANROC, "own-tempo", "dusk", 25, null, null), + new SpeciesFormEvolution(Species.LYCANROC, "", "midday", 25, null, new TimeOfDayEvolutionCondition("day")), + new SpeciesFormEvolution(Species.LYCANROC, "", "midnight", 25, null, new TimeOfDayEvolutionCondition("night")) ], [Species.STEENEE]: [ - new SpeciesEvolution(Species.TSAREENA, 28, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.STOMP).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.TSAREENA, 28, null, new MoveEvolutionCondition(Moves.STOMP), SpeciesWildEvolutionDelay.LONG) ], [Species.POIPOLE]: [ - new SpeciesEvolution(Species.NAGANADEL, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.DRAGON_PULSE).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.NAGANADEL, 1, null, new MoveEvolutionCondition(Moves.DRAGON_PULSE), SpeciesWildEvolutionDelay.LONG) ], [Species.ALOLA_SANDSHREW]: [ new SpeciesEvolution(Species.ALOLA_SANDSLASH, 1, EvolutionItem.ICE_STONE, null, SpeciesWildEvolutionDelay.LONG) @@ -1465,22 +1649,40 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.APPLETUN, 1, EvolutionItem.SWEET_APPLE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.CLOBBOPUS]: [ - new SpeciesEvolution(Species.GRAPPLOCT, 35, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.TAUNT).length > 0)/*Once Taunt is implemented, change evo level to 1 and delay to LONG*/) + new SpeciesEvolution(Species.GRAPPLOCT, 35, null, new MoveEvolutionCondition(Moves.TAUNT)/*Once Taunt is implemented, change evo level to 1 and delay to LONG*/) ], [Species.SINISTEA]: [ new SpeciesFormEvolution(Species.POLTEAGEIST, "phony", "phony", 1, EvolutionItem.CRACKED_POT, null, SpeciesWildEvolutionDelay.LONG), new SpeciesFormEvolution(Species.POLTEAGEIST, "antique", "antique", 1, EvolutionItem.CHIPPED_POT, null, SpeciesWildEvolutionDelay.LONG) ], [Species.MILCERY]: [ - new SpeciesFormEvolution(Species.ALCREMIE, "", "vanilla-cream", 1, EvolutionItem.STRAWBERRY_SWEET, new SpeciesEvolutionCondition(p => globalScene.arena.biomeType === Biome.TOWN || globalScene.arena.biomeType === Biome.PLAINS || globalScene.arena.biomeType === Biome.GRASS || globalScene.arena.biomeType === Biome.TALL_GRASS || globalScene.arena.biomeType === Biome.METROPOLIS), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.ALCREMIE, "", "ruby-cream", 1, EvolutionItem.STRAWBERRY_SWEET, new SpeciesEvolutionCondition(p => globalScene.arena.biomeType === Biome.BADLANDS || globalScene.arena.biomeType === Biome.VOLCANO || globalScene.arena.biomeType === Biome.GRAVEYARD || globalScene.arena.biomeType === Biome.FACTORY || globalScene.arena.biomeType === Biome.SLUM), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.ALCREMIE, "", "matcha-cream", 1, EvolutionItem.STRAWBERRY_SWEET, new SpeciesEvolutionCondition(p => globalScene.arena.biomeType === Biome.FOREST || globalScene.arena.biomeType === Biome.SWAMP || globalScene.arena.biomeType === Biome.MEADOW || globalScene.arena.biomeType === Biome.JUNGLE), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.ALCREMIE, "", "mint-cream", 1, EvolutionItem.STRAWBERRY_SWEET, new SpeciesEvolutionCondition(p => globalScene.arena.biomeType === Biome.SEA || globalScene.arena.biomeType === Biome.BEACH || globalScene.arena.biomeType === Biome.LAKE || globalScene.arena.biomeType === Biome.SEABED), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.ALCREMIE, "", "lemon-cream", 1, EvolutionItem.STRAWBERRY_SWEET, new SpeciesEvolutionCondition(p => globalScene.arena.biomeType === Biome.DESERT || globalScene.arena.biomeType === Biome.POWER_PLANT || globalScene.arena.biomeType === Biome.DOJO || globalScene.arena.biomeType === Biome.RUINS || globalScene.arena.biomeType === Biome.CONSTRUCTION_SITE), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.ALCREMIE, "", "salted-cream", 1, EvolutionItem.STRAWBERRY_SWEET, new SpeciesEvolutionCondition(p => globalScene.arena.biomeType === Biome.MOUNTAIN || globalScene.arena.biomeType === Biome.CAVE || globalScene.arena.biomeType === Biome.ICE_CAVE || globalScene.arena.biomeType === Biome.FAIRY_CAVE || globalScene.arena.biomeType === Biome.SNOWY_FOREST), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.ALCREMIE, "", "ruby-swirl", 1, EvolutionItem.STRAWBERRY_SWEET, new SpeciesEvolutionCondition(p => globalScene.arena.biomeType === Biome.WASTELAND || globalScene.arena.biomeType === Biome.LABORATORY), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.ALCREMIE, "", "caramel-swirl", 1, EvolutionItem.STRAWBERRY_SWEET, new SpeciesEvolutionCondition(p => globalScene.arena.biomeType === Biome.TEMPLE || globalScene.arena.biomeType === Biome.ISLAND), SpeciesWildEvolutionDelay.LONG), - new SpeciesFormEvolution(Species.ALCREMIE, "", "rainbow-swirl", 1, EvolutionItem.STRAWBERRY_SWEET, new SpeciesEvolutionCondition(p => globalScene.arena.biomeType === Biome.ABYSS || globalScene.arena.biomeType === Biome.SPACE || globalScene.arena.biomeType === Biome.END), SpeciesWildEvolutionDelay.LONG) + new SpeciesFormEvolution(Species.ALCREMIE, "", "vanilla-cream", 1, EvolutionItem.STRAWBERRY_SWEET, + new BiomeEvolutionCondition([ Biome.TOWN, Biome.PLAINS, Biome.GRASS, Biome.TALL_GRASS, Biome.METROPOLIS ]), + SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.ALCREMIE, "", "ruby-cream", 1, EvolutionItem.STRAWBERRY_SWEET, + new BiomeEvolutionCondition([ Biome.BADLANDS, Biome.VOLCANO, Biome.GRAVEYARD, Biome.FACTORY, Biome.SLUM ]), + SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.ALCREMIE, "", "matcha-cream", 1, EvolutionItem.STRAWBERRY_SWEET, + new BiomeEvolutionCondition([ Biome.FOREST, Biome.SWAMP, Biome.MEADOW, Biome.JUNGLE ]), + SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.ALCREMIE, "", "mint-cream", 1, EvolutionItem.STRAWBERRY_SWEET, + new BiomeEvolutionCondition([ Biome.SEA, Biome.BEACH, Biome.LAKE, Biome.SEABED ]), + SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.ALCREMIE, "", "lemon-cream", 1, EvolutionItem.STRAWBERRY_SWEET, + new BiomeEvolutionCondition([ Biome.DESERT, Biome.POWER_PLANT, Biome.DOJO, Biome.RUINS, Biome.CONSTRUCTION_SITE ]), + SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.ALCREMIE, "", "salted-cream", 1, EvolutionItem.STRAWBERRY_SWEET, + new BiomeEvolutionCondition([ Biome.MOUNTAIN, Biome.CAVE, Biome.ICE_CAVE, Biome.FAIRY_CAVE, Biome.SNOWY_FOREST ]), + SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.ALCREMIE, "", "ruby-swirl", 1, EvolutionItem.STRAWBERRY_SWEET, + new BiomeEvolutionCondition([ Biome.WASTELAND, Biome.LABORATORY ]), + SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.ALCREMIE, "", "caramel-swirl", 1, EvolutionItem.STRAWBERRY_SWEET, + new BiomeEvolutionCondition([ Biome.TEMPLE, Biome.ISLAND ]), + SpeciesWildEvolutionDelay.LONG), + new SpeciesFormEvolution(Species.ALCREMIE, "", "rainbow-swirl", 1, EvolutionItem.STRAWBERRY_SWEET, + new BiomeEvolutionCondition([ Biome.ABYSS, Biome.SPACE, Biome.END ]), + SpeciesWildEvolutionDelay.LONG) ], [Species.DURALUDON]: [ new SpeciesFormEvolution(Species.ARCHALUDON, "", "", 1, EvolutionItem.METAL_ALLOY, null, SpeciesWildEvolutionDelay.VERY_LONG) @@ -1499,10 +1701,10 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.HISUI_ELECTRODE, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.HISUI_QWILFISH]: [ - new SpeciesEvolution(Species.OVERQWIL, 28, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.BARB_BARRAGE).length > 0), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.OVERQWIL, 28, null, new MoveEvolutionCondition(Moves.BARB_BARRAGE), SpeciesWildEvolutionDelay.LONG) ], [Species.HISUI_SNEASEL]: [ - new SpeciesEvolution(Species.SNEASLER, 1, EvolutionItem.RAZOR_CLAW, new SpeciesEvolutionCondition(p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY /* Razor claw at day*/), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.SNEASLER, 1, EvolutionItem.RAZOR_CLAW, new TimeOfDayEvolutionCondition("day") /* Razor claw at day*/, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.CHARCADET]: [ new SpeciesEvolution(Species.ARMAROUGE, 1, EvolutionItem.AUSPICIOUS_ARMOR, null, SpeciesWildEvolutionDelay.LONG), @@ -1522,7 +1724,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesFormEvolution(Species.SINISTCHA, "artisan", "masterpiece", 1, EvolutionItem.MASTERPIECE_TEACUP, null, SpeciesWildEvolutionDelay.LONG) ], [Species.DIPPLIN]: [ - new SpeciesEvolution(Species.HYDRAPPLE, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.DRAGON_CHEER).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.HYDRAPPLE, 1, null, new MoveEvolutionCondition(Moves.DRAGON_CHEER), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.KADABRA]: [ new SpeciesEvolution(Species.ALAKAZAM, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG) @@ -1537,9 +1739,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.GENGAR, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.ONIX]: [ - new SpeciesEvolution(Species.STEELIX, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition( - p => p.moveset.filter(m => m?.getMove().type === Type.STEEL).length > 0), - SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.STEELIX, 1, EvolutionItem.LINKING_CORD, new MoveTypeEvolutionCondition(Type.STEEL), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.RHYDON]: [ new SpeciesEvolution(Species.RHYPERIOR, 1, EvolutionItem.PROTECTOR, null, SpeciesWildEvolutionDelay.VERY_LONG) @@ -1548,9 +1748,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.KINGDRA, 1, EvolutionItem.DRAGON_SCALE, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.SCYTHER]: [ - new SpeciesEvolution(Species.SCIZOR, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition( - p => p.moveset.filter(m => m?.getMove().type === Type.STEEL).length > 0), - SpeciesWildEvolutionDelay.VERY_LONG), + new SpeciesEvolution(Species.SCIZOR, 1, EvolutionItem.LINKING_CORD, new MoveTypeEvolutionCondition(Type.STEEL), SpeciesWildEvolutionDelay.VERY_LONG), new SpeciesEvolution(Species.KLEAVOR, 1, EvolutionItem.BLACK_AUGURITE, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.ELECTABUZZ]: [ @@ -1572,8 +1770,8 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.DUSKNOIR, 1, EvolutionItem.REAPER_CLOTH, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.CLAMPERL]: [ - new SpeciesEvolution(Species.HUNTAIL, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition(p => p.gender === Gender.MALE, p => p.gender = Gender.MALE /* Deep Sea Tooth */), SpeciesWildEvolutionDelay.VERY_LONG), - new SpeciesEvolution(Species.GOREBYSS, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition(p => p.gender === Gender.FEMALE, p => p.gender = Gender.FEMALE /* Deep Sea Scale */), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.HUNTAIL, 1, EvolutionItem.LINKING_CORD, new GenderEvolutionCondition(Gender.MALE /* Deep Sea Tooth */), SpeciesWildEvolutionDelay.VERY_LONG), + new SpeciesEvolution(Species.GOREBYSS, 1, EvolutionItem.LINKING_CORD, new GenderEvolutionCondition(Gender.FEMALE /* Deep Sea Scale */), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.BOLDORE]: [ new SpeciesEvolution(Species.GIGALITH, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG) @@ -1582,10 +1780,10 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.CONKELDURR, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.KARRABLAST]: [ - new SpeciesEvolution(Species.ESCAVALIER, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition(p => !!globalScene.gameData.dexData[Species.SHELMET].caughtAttr), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.ESCAVALIER, 1, EvolutionItem.LINKING_CORD, new CaughtEvolutionCondition(Species.SHELMET), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.SHELMET]: [ - new SpeciesEvolution(Species.ACCELGOR, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition(p => !!globalScene.gameData.dexData[Species.KARRABLAST].caughtAttr), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.ACCELGOR, 1, EvolutionItem.LINKING_CORD, new CaughtEvolutionCondition(Species.KARRABLAST), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.SPRITZEE]: [ new SpeciesEvolution(Species.AROMATISSE, 1, EvolutionItem.SACHET, null, SpeciesWildEvolutionDelay.VERY_LONG) @@ -1603,72 +1801,66 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.ALOLA_GOLEM, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.PRIMEAPE]: [ - new SpeciesEvolution(Species.ANNIHILAPE, 35, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m?.moveId === Moves.RAGE_FIST).length > 0), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.ANNIHILAPE, 35, null, new MoveEvolutionCondition(Moves.RAGE_FIST), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.GOLBAT]: [ - new SpeciesEvolution(Species.CROBAT, 1, null, new SpeciesFriendshipEvolutionCondition(120), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesEvolution(Species.CROBAT, 1, null, new FriendshipEvolutionCondition(120), SpeciesWildEvolutionDelay.VERY_LONG) ], [Species.CHANSEY]: [ - new SpeciesEvolution(Species.BLISSEY, 1, null, new SpeciesFriendshipEvolutionCondition(200), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.BLISSEY, 1, null, new FriendshipEvolutionCondition(200), SpeciesWildEvolutionDelay.LONG) ], [Species.PICHU]: [ - new SpeciesFormEvolution(Species.PIKACHU, "spiky", "partner", 1, null, new SpeciesFriendshipEvolutionCondition(90), SpeciesWildEvolutionDelay.SHORT), - new SpeciesFormEvolution(Species.PIKACHU, "", "", 1, null, new SpeciesFriendshipEvolutionCondition(90), SpeciesWildEvolutionDelay.SHORT), + new SpeciesFormEvolution(Species.PIKACHU, "spiky", "partner", 1, null, new FriendshipEvolutionCondition(90), SpeciesWildEvolutionDelay.SHORT), + new SpeciesFormEvolution(Species.PIKACHU, "", "", 1, null, new FriendshipEvolutionCondition(90), SpeciesWildEvolutionDelay.SHORT), ], [Species.CLEFFA]: [ - new SpeciesEvolution(Species.CLEFAIRY, 1, null, new SpeciesFriendshipEvolutionCondition(160), SpeciesWildEvolutionDelay.SHORT) + new SpeciesEvolution(Species.CLEFAIRY, 1, null, new FriendshipEvolutionCondition(160), SpeciesWildEvolutionDelay.SHORT) ], [Species.IGGLYBUFF]: [ - new SpeciesEvolution(Species.JIGGLYPUFF, 1, null, new SpeciesFriendshipEvolutionCondition(70), SpeciesWildEvolutionDelay.SHORT) + new SpeciesEvolution(Species.JIGGLYPUFF, 1, null, new FriendshipEvolutionCondition(70), SpeciesWildEvolutionDelay.SHORT) ], [Species.TOGEPI]: [ - new SpeciesEvolution(Species.TOGETIC, 1, null, new SpeciesFriendshipEvolutionCondition(70), SpeciesWildEvolutionDelay.SHORT) + new SpeciesEvolution(Species.TOGETIC, 1, null, new FriendshipEvolutionCondition(70), SpeciesWildEvolutionDelay.SHORT) ], [Species.AZURILL]: [ - new SpeciesEvolution(Species.MARILL, 1, null, new SpeciesFriendshipEvolutionCondition(70), SpeciesWildEvolutionDelay.SHORT) + new SpeciesEvolution(Species.MARILL, 1, null, new FriendshipEvolutionCondition(70), SpeciesWildEvolutionDelay.SHORT) ], [Species.BUDEW]: [ - new SpeciesEvolution(Species.ROSELIA, 1, null, new SpeciesFriendshipEvolutionCondition(70, p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY), SpeciesWildEvolutionDelay.SHORT) + new SpeciesEvolution(Species.ROSELIA, 1, null, new FriendshipTimeOfDayEvolutionCondition(70, "day"), SpeciesWildEvolutionDelay.SHORT) ], [Species.BUNEARY]: [ - new SpeciesEvolution(Species.LOPUNNY, 1, null, new SpeciesFriendshipEvolutionCondition(70), SpeciesWildEvolutionDelay.MEDIUM) + new SpeciesEvolution(Species.LOPUNNY, 1, null, new FriendshipEvolutionCondition(70), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.CHINGLING]: [ - new SpeciesEvolution(Species.CHIMECHO, 1, null, new SpeciesFriendshipEvolutionCondition(90, p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT), SpeciesWildEvolutionDelay.MEDIUM) + new SpeciesEvolution(Species.CHIMECHO, 1, null, new FriendshipTimeOfDayEvolutionCondition(90, "night"), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.HAPPINY]: [ - new SpeciesEvolution(Species.CHANSEY, 1, null, new SpeciesFriendshipEvolutionCondition(160), SpeciesWildEvolutionDelay.SHORT) + new SpeciesEvolution(Species.CHANSEY, 1, null, new FriendshipEvolutionCondition(160), SpeciesWildEvolutionDelay.SHORT) ], [Species.MUNCHLAX]: [ - new SpeciesEvolution(Species.SNORLAX, 1, null, new SpeciesFriendshipEvolutionCondition(120), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.SNORLAX, 1, null, new FriendshipEvolutionCondition(120), SpeciesWildEvolutionDelay.LONG) ], [Species.RIOLU]: [ - new SpeciesEvolution(Species.LUCARIO, 1, null, new SpeciesFriendshipEvolutionCondition(120, p => globalScene.arena.getTimeOfDay() === TimeOfDay.DAWN || globalScene.arena.getTimeOfDay() === TimeOfDay.DAY), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.LUCARIO, 1, null, new FriendshipTimeOfDayEvolutionCondition(120, "day"), SpeciesWildEvolutionDelay.LONG) ], [Species.WOOBAT]: [ - new SpeciesEvolution(Species.SWOOBAT, 1, null, new SpeciesFriendshipEvolutionCondition(90), SpeciesWildEvolutionDelay.MEDIUM) + new SpeciesEvolution(Species.SWOOBAT, 1, null, new FriendshipEvolutionCondition(90), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.SWADLOON]: [ - new SpeciesEvolution(Species.LEAVANNY, 1, null, new SpeciesFriendshipEvolutionCondition(120), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.LEAVANNY, 1, null, new FriendshipEvolutionCondition(120), SpeciesWildEvolutionDelay.LONG) ], [Species.TYPE_NULL]: [ - new SpeciesEvolution(Species.SILVALLY, 1, null, new SpeciesFriendshipEvolutionCondition(100), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.SILVALLY, 1, null, new FriendshipEvolutionCondition(100), SpeciesWildEvolutionDelay.LONG) ], [Species.ALOLA_MEOWTH]: [ - new SpeciesEvolution(Species.ALOLA_PERSIAN, 1, null, new SpeciesFriendshipEvolutionCondition(120), SpeciesWildEvolutionDelay.LONG) + new SpeciesEvolution(Species.ALOLA_PERSIAN, 1, null, new FriendshipEvolutionCondition(120), SpeciesWildEvolutionDelay.LONG) ], [Species.SNOM]: [ - new SpeciesEvolution(Species.FROSMOTH, 1, null, new SpeciesFriendshipEvolutionCondition(90, p => globalScene.arena.getTimeOfDay() === TimeOfDay.DUSK || globalScene.arena.getTimeOfDay() === TimeOfDay.NIGHT), SpeciesWildEvolutionDelay.MEDIUM) + new SpeciesEvolution(Species.FROSMOTH, 1, null, new FriendshipTimeOfDayEvolutionCondition(90, "night"), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.GIMMIGHOUL]: [ - new SpeciesFormEvolution(Species.GHOLDENGO, "chest", "", 1, null, new SpeciesEvolutionCondition(p => p.evoCounter - + p.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length - + globalScene.findModifiers(m => m instanceof MoneyMultiplierModifier - || m instanceof ExtraModifierModifier || m instanceof TempExtraModifierModifier).length > 9), SpeciesWildEvolutionDelay.VERY_LONG), - new SpeciesFormEvolution(Species.GHOLDENGO, "roaming", "", 1, null, new SpeciesEvolutionCondition(p => p.evoCounter - + p.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length - + globalScene.findModifiers(m => m instanceof MoneyMultiplierModifier - || m instanceof ExtraModifierModifier || m instanceof TempExtraModifierModifier).length > 9), SpeciesWildEvolutionDelay.VERY_LONG) + new SpeciesFormEvolution(Species.GHOLDENGO, "chest", "", 1, null, new TreasureEvolutionCondition(), SpeciesWildEvolutionDelay.VERY_LONG), + new SpeciesFormEvolution(Species.GHOLDENGO, "roaming", "", 1, null, new TreasureEvolutionCondition(), SpeciesWildEvolutionDelay.VERY_LONG) ] }; @@ -1691,3 +1883,19 @@ export function initPokemonPrevolutions(): void { } }); } + + +// TODO: This may cause funny business for double starters such as Pichu/Pikachu +export const pokemonStarters: PokemonPrevolutions = {}; + +export function initPokemonStarters(): void { + const starterKeys = Object.keys(pokemonPrevolutions); + starterKeys.forEach(pk => { + const prevolution = pokemonPrevolutions[pk]; + if (speciesStarterCosts.hasOwnProperty(prevolution)) { + pokemonStarters[pk] = prevolution; + } else { + pokemonStarters[pk] = pokemonPrevolutions[prevolution]; + } + }); +} diff --git a/src/data/balance/pokemon-level-moves.ts b/src/data/balance/pokemon-level-moves.ts index 8e28300eb8a..8fe61da35c0 100644 --- a/src/data/balance/pokemon-level-moves.ts +++ b/src/data/balance/pokemon-level-moves.ts @@ -19718,6 +19718,44 @@ export const pokemonFormLevelMoves: PokemonSpeciesFormLevelMoves = { [ 48, Moves.CLOSE_COMBAT ], [ 52, Moves.FOCUS_PUNCH ], ], + 2: [ + [ EVOLVE_MOVE, Moves.WICKED_BLOW ], + [ 1, Moves.LEER ], + [ 1, Moves.FOCUS_ENERGY ], + [ 1, Moves.ENDURE ], + [ 1, Moves.ROCK_SMASH ], + [ 1, Moves.SUCKER_PUNCH ], + [ 12, Moves.AERIAL_ACE ], + [ 16, Moves.SCARY_FACE ], + [ 20, Moves.HEADBUTT ], + [ 24, Moves.BRICK_BREAK ], + [ 28, Moves.DETECT ], + [ 32, Moves.BULK_UP ], + [ 36, Moves.IRON_HEAD ], + [ 40, Moves.DYNAMIC_PUNCH ], + [ 44, Moves.COUNTER ], + [ 48, Moves.CLOSE_COMBAT ], + [ 52, Moves.FOCUS_PUNCH ], + ], + 3: [ + [ EVOLVE_MOVE, Moves.SURGING_STRIKES ], + [ 1, Moves.LEER ], + [ 1, Moves.FOCUS_ENERGY ], + [ 1, Moves.ENDURE ], + [ 1, Moves.ROCK_SMASH ], + [ 1, Moves.AQUA_JET ], + [ 12, Moves.AERIAL_ACE ], + [ 16, Moves.SCARY_FACE ], + [ 20, Moves.HEADBUTT ], + [ 24, Moves.BRICK_BREAK ], + [ 28, Moves.DETECT ], + [ 32, Moves.BULK_UP ], + [ 36, Moves.IRON_HEAD ], + [ 40, Moves.DYNAMIC_PUNCH ], + [ 44, Moves.COUNTER ], + [ 48, Moves.CLOSE_COMBAT ], + [ 52, Moves.FOCUS_PUNCH ], + ], }, [Species.CALYREX]: { 1: [ diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 3a58ff4a99d..4c68de5abc5 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -18,7 +18,7 @@ import { MoveFlags, StatusCategoryOnAllyAttr } from "#app/data/move"; -import { SpeciesFormChangeManualTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeAbilityTrigger } from "#app/data/pokemon-forms"; import { getStatusEffectHealText } from "#app/data/status-effect"; import { TerrainType } from "#app/data/terrain"; import { Type } from "#enums/type"; @@ -2149,7 +2149,7 @@ export class FormBlockDamageTag extends BattlerTag { super.onAdd(pokemon); if (pokemon.formIndex !== 0) { - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger); + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger); } } @@ -2161,7 +2161,7 @@ export class FormBlockDamageTag extends BattlerTag { onRemove(pokemon: Pokemon): void { super.onRemove(pokemon); - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger); + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger); } } /** Provides the additional weather-based effects of the Ice Face ability */ @@ -2361,12 +2361,12 @@ export class GulpMissileTag extends BattlerTag { onAdd(pokemon: Pokemon): void { super.onAdd(pokemon); - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger); + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger); } onRemove(pokemon: Pokemon): void { super.onRemove(pokemon); - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger); + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger); } } diff --git a/src/data/challenge.ts b/src/data/challenge.ts index a01ceab8aa3..fab5196601c 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -8,7 +8,7 @@ import { speciesStarterCosts } from "#app/data/balance/starters"; import type Pokemon from "#app/field/pokemon"; import { PokemonMove } from "#app/field/pokemon"; import type { FixedBattleConfig } from "#app/battle"; -import { BattleType } from "#app/battle"; +import { ClassicFixedBossWaves, BattleType, getRandomTrainerFunc } from "#app/battle"; import Trainer, { TrainerVariant } from "#app/field/trainer"; import type { GameMode } from "#app/game-mode"; import { Type } from "#enums/type"; @@ -20,6 +20,7 @@ import type { Moves } from "#enums/moves"; import { TypeColor, TypeShadow } from "#enums/color"; import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonFormChanges } from "#app/data/pokemon-forms"; +import { ModifierTier } from "#app/modifier/modifier-tier"; /** A constant for the default max cost of the starting party before a run */ const DEFAULT_PARTY_MAX_COST = 10; @@ -464,30 +465,64 @@ export class SingleGenerationChallenge extends Challenge { return false; } - applyFixedBattle(waveIndex: Number, battleConfig: FixedBattleConfig): boolean { - let trainerTypes: TrainerType[] = []; + applyFixedBattle(waveIndex: number, battleConfig: FixedBattleConfig): boolean { + let trainerTypes: (TrainerType | TrainerType[])[] = []; + const evilTeamWaves: number[] = [ ClassicFixedBossWaves.EVIL_GRUNT_1, ClassicFixedBossWaves.EVIL_GRUNT_2, ClassicFixedBossWaves.EVIL_GRUNT_3, ClassicFixedBossWaves.EVIL_ADMIN_1, ClassicFixedBossWaves.EVIL_GRUNT_4, ClassicFixedBossWaves.EVIL_ADMIN_2, ClassicFixedBossWaves.EVIL_BOSS_1, ClassicFixedBossWaves.EVIL_BOSS_2 ]; + const evilTeamGrunts = [[ TrainerType.ROCKET_GRUNT ], [ TrainerType.ROCKET_GRUNT ], [ TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT ], [ TrainerType.GALACTIC_GRUNT ], [ TrainerType.PLASMA_GRUNT ], [ TrainerType.FLARE_GRUNT ], [ TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT ], [ TrainerType.MACRO_GRUNT ], [ TrainerType.STAR_GRUNT ]]; + const evilTeamAdmins = [[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [[ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ]], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], [ TrainerType.FABA, TrainerType.PLUMERIA ], [ TrainerType.OLEANA ], [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]]; + const evilTeamBosses = [[ TrainerType.ROCKET_BOSS_GIOVANNI_1 ], [ TrainerType.ROCKET_BOSS_GIOVANNI_1 ], [ TrainerType.MAXIE, TrainerType.ARCHIE ], [ TrainerType.CYRUS ], [ TrainerType.GHETSIS ], [ TrainerType.LYSANDRE ], [ TrainerType.LUSAMINE, TrainerType.GUZMA ], [ TrainerType.ROSE ], [ TrainerType.PENNY ]]; + const evilTeamBossRematches = [[ TrainerType.ROCKET_BOSS_GIOVANNI_2 ], [ TrainerType.ROCKET_BOSS_GIOVANNI_2 ], [ TrainerType.MAXIE_2, TrainerType.ARCHIE_2 ], [ TrainerType.CYRUS_2 ], [ TrainerType.GHETSIS_2 ], [ TrainerType.LYSANDRE_2 ], [ TrainerType.LUSAMINE_2, TrainerType.GUZMA_2 ], [ TrainerType.ROSE_2 ], [ TrainerType.PENNY_2 ]]; switch (waveIndex) { - case 182: + case ClassicFixedBossWaves.EVIL_GRUNT_1: + trainerTypes = evilTeamGrunts[this.value - 1]; + battleConfig.setBattleType(BattleType.TRAINER).setGetTrainerFunc(getRandomTrainerFunc(trainerTypes, true)); + return true; + case ClassicFixedBossWaves.EVIL_GRUNT_2: + case ClassicFixedBossWaves.EVIL_GRUNT_3: + case ClassicFixedBossWaves.EVIL_GRUNT_4: + trainerTypes = evilTeamGrunts[this.value - 1]; + break; + case ClassicFixedBossWaves.EVIL_ADMIN_1: + case ClassicFixedBossWaves.EVIL_ADMIN_2: + trainerTypes = evilTeamAdmins[this.value - 1]; + break; + case ClassicFixedBossWaves.EVIL_BOSS_1: + trainerTypes = evilTeamBosses[this.value - 1]; + battleConfig.setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1).setGetTrainerFunc(getRandomTrainerFunc(trainerTypes, true)) + .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }); + return true; + case ClassicFixedBossWaves.EVIL_BOSS_2: + trainerTypes = evilTeamBossRematches[this.value - 1]; + battleConfig.setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1).setGetTrainerFunc(getRandomTrainerFunc(trainerTypes, true)) + .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }); + return true; + case ClassicFixedBossWaves.ELITE_FOUR_1: trainerTypes = [ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, Utils.randSeedItem([ TrainerType.HALA, TrainerType.MOLAYNE ]), TrainerType.MARNIE_ELITE, TrainerType.RIKA ]; break; - case 184: + case ClassicFixedBossWaves.ELITE_FOUR_2: trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ]; break; - case 186: + case ClassicFixedBossWaves.ELITE_FOUR_3: trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([ TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE ]), TrainerType.LARRY_ELITE ]; break; - case 188: + case ClassicFixedBossWaves.ELITE_FOUR_4: trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ]; break; - case 190: + case ClassicFixedBossWaves.CHAMPION: trainerTypes = [ TrainerType.BLUE, Utils.randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), Utils.randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, Utils.randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, Utils.randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ]; break; } if (trainerTypes.length === 0) { return false; - } else { - battleConfig.setBattleType(BattleType.TRAINER).setGetTrainerFunc(() => new Trainer(trainerTypes[this.value - 1], TrainerVariant.DEFAULT)); + } else if (evilTeamWaves.includes(waveIndex)) { + battleConfig.setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1).setGetTrainerFunc(getRandomTrainerFunc(trainerTypes, true)); return true; + } else if (waveIndex >= ClassicFixedBossWaves.ELITE_FOUR_1 && waveIndex <= ClassicFixedBossWaves.CHAMPION) { + const ttypes = trainerTypes as TrainerType[]; + battleConfig.setBattleType(BattleType.TRAINER).setGetTrainerFunc(() => new Trainer(ttypes[this.value - 1], TrainerVariant.DEFAULT)); + return true; + } else { + return false; } } diff --git a/src/data/move.ts b/src/data/move.ts index 06f3c85e9c4..2d2da38cce7 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1380,8 +1380,10 @@ export class UserHpDamageAttr extends FixedDamageAttr { } export class TargetHalfHpDamageAttr extends FixedDamageAttr { - // the initial amount of hp the target had before the first hit - // used for multi lens + /** + * The initial amount of hp the target had before the first hit. + * Used for calculating multi lens damage. + */ private initialHp: number; constructor() { super(0); @@ -1405,12 +1407,10 @@ export class TargetHalfHpDamageAttr extends FixedDamageAttr { // multi lens added hit; use initialHp tracker to ensure correct damage (args[0] as Utils.NumberHolder).value = Utils.toDmgValue(this.initialHp / 2); return true; - break; case lensCount + 1: // parental bond added hit; calc damage as normal (args[0] as Utils.NumberHolder).value = Utils.toDmgValue(target.hp / 2); return true; - break; } } @@ -6129,7 +6129,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { return false; } - // Don't allow wild mons to flee with U-turn et al + // Don't allow wild mons to flee with U-turn et al. if (this.selfSwitch && !user.isPlayer() && move.category !== MoveCategory.STATUS) { return false; } @@ -7084,7 +7084,25 @@ export class RepeatMoveAttr extends MoveEffectAttr { // get the last move used (excluding status based failures) as well as the corresponding moveset slot const lastMove = target.getLastXMoves(-1).find(m => m.move !== Moves.NONE)!; const movesetMove = target.getMoveset().find(m => m?.moveId === lastMove.move)!; - const moveTargets = lastMove.targets ?? []; + // If the last move used can hit more than one target or has variable targets, + // re-compute the targets for the attack + // (mainly for alternating double/single battle shenanigans) + // Rampaging moves (e.g. Outrage) are not included due to being incompatible with Instruct + // TODO: Fix this once dragon darts gets smart targeting + let moveTargets = movesetMove.getMove().isMultiTarget() ? getMoveTargets(target, lastMove.move).targets : lastMove.targets; + + /** In the event the instructed move's only target is a fainted opponent, redirect it to an alive ally if possible + Normally, all yet-unexecuted move phases would swap over when the enemy in question faints + (see `redirectPokemonMoves` in `battle-scene.ts`), + but since instruct adds a new move phase pre-emptively, we need to handle this interaction manually. + */ + const firstTarget = globalScene.getField()[moveTargets[0]]; + if (globalScene.currentBattle.double && moveTargets.length === 1 && firstTarget.isFainted() && firstTarget !== target.getAlly()) { + const ally = firstTarget.getAlly(); + if (ally.isActive()) { // ally exists, is not dead and can sponge the blast + moveTargets = [ ally.getBattlerIndex() ]; + } + } globalScene.queueMessage(i18next.t("moveTriggers:instructingMove", { userPokemonName: getPokemonNameWithAffix(user), @@ -7098,12 +7116,9 @@ export class RepeatMoveAttr extends MoveEffectAttr { getCondition(): MoveConditionFunc { return (user, target, move) => { - // TODO: Confirm behavior of instructing move known by target but called by another move const lastMove = target.getLastXMoves(-1).find(m => m.move !== Moves.NONE); const movesetMove = target.getMoveset().find(m => m?.moveId === lastMove?.move); - const moveTargets = lastMove?.targets ?? []; - // TODO: Add a way of adding moves to list procedurally rather than a pre-defined blacklist - const unrepeatablemoves = [ + const uninstructableMoves = [ // Locking/Continually Executed moves Moves.OUTRAGE, Moves.RAGING_FURY, @@ -7158,11 +7173,11 @@ export class RepeatMoveAttr extends MoveEffectAttr { // TODO: Add Max/G-Move blockage if or when they are implemented ]; - if (!movesetMove // called move not in target's moveset (dancer, forgetting the move, etc.) + if (!lastMove?.move // no move to instruct + || !movesetMove // called move not in target's moveset (forgetting the move, etc.) || movesetMove.ppUsed === movesetMove.getMovePp() // move out of pp - || allMoves[lastMove?.move ?? Moves.NONE].isChargingMove() // called move is a charging/recharging move - || !moveTargets.length // called move has no targets - || unrepeatablemoves.includes(lastMove?.move ?? Moves.NONE)) { // called move is explicitly in the banlist + || allMoves[lastMove.move].isChargingMove() // called move is a charging/recharging move + || uninstructableMoves.includes(lastMove.move)) { // called move is in the banlist return false; } return true; @@ -7170,7 +7185,7 @@ export class RepeatMoveAttr extends MoveEffectAttr { } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { - // TODO: Make the AI acutally use instruct + // TODO: Make the AI actually use instruct /* Ideally, the AI would score instruct based on the scorings of the on-field pokemons' * last used moves at the time of using Instruct (by the time the instructor gets to act) * with respect to the user's side. @@ -10279,7 +10294,10 @@ export function initMoves() { new StatusMove(Moves.INSTRUCT, Type.PSYCHIC, -1, 15, -1, 0, 7) .ignoresSubstitute() .attr(RepeatMoveAttr) - .edgeCase(), // incorrect interactions with Gigaton Hammer, Blood Moon & Torment + // incorrect interactions with Gigaton Hammer, Blood Moon & Torment + // Also has incorrect interactions with Dancer due to the latter + // erroneously adding copied moves to move history. + .edgeCase(), new AttackMove(Moves.BEAK_BLAST, Type.FLYING, MoveCategory.PHYSICAL, 100, 100, 15, -1, -3, 7) .attr(BeakBlastHeaderAttr) .ballBombMove() diff --git a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts index 20179f4c618..550d9bd4f13 100644 --- a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts +++ b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts @@ -4,6 +4,7 @@ import type { import { generateModifierType, generateModifierTypeOption, + getRandomEncounterSpecies, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterExp, @@ -11,17 +12,15 @@ import { } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import type { PlayerPokemon } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; -import { EnemyPokemon } from "#app/field/pokemon"; import type { BerryModifierType, ModifierTypeOption } from "#app/modifier/modifier-type"; import { - getPartyLuckValue, ModifierPoolType, modifierTypes, regenerateModifierPoolThresholds, } from "#app/modifier/modifier-type"; -import { randSeedInt, randSeedItem } from "#app/utils"; +import { randSeedInt } from "#app/utils"; import { BattlerTagType } from "#enums/battler-tag-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { globalScene } from "#app/global-scene"; @@ -31,7 +30,6 @@ import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-enco import { getPokemonNameWithAffix } from "#app/messages"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; -import { TrainerSlot } from "#app/data/trainer-config"; import { applyModifierTypeToPlayerPokemon, getEncounterPokemonLevelForWave, getHighestStatPlayerPokemon, getSpriteKeysFromPokemon, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import PokemonData from "#app/system/pokemon-data"; import { BerryModifier } from "#app/modifier/modifier"; @@ -40,8 +38,6 @@ import { BerryType } from "#enums/berry-type"; import { PERMANENT_STATS, Stat } from "#enums/stat"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; -import type PokemonSpecies from "#app/data/pokemon-species"; -import { getPokemonSpecies } from "#app/data/pokemon-species"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounters/berriesAbound"; @@ -69,20 +65,12 @@ export const BerriesAboundEncounter: MysteryEncounter = // Calculate boss mon const level = getEncounterPokemonLevelForWave(STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER); - let bossSpecies: PokemonSpecies; - if (globalScene.eventManager.isEventActive() && globalScene.eventManager.activeEvent()?.uncommonBreedEncounters && randSeedInt(2) === 1) { - const eventEncounter = randSeedItem(globalScene.eventManager.activeEvent()!.uncommonBreedEncounters!); - const levelSpecies = getPokemonSpecies(eventEncounter.species).getWildSpeciesForLevel(level, eventEncounter.allowEvolution ?? false, true, globalScene.gameMode); - bossSpecies = getPokemonSpecies( levelSpecies ); - } else { - bossSpecies = globalScene.arena.randomSpecies(globalScene.currentBattle.waveIndex, level, 0, getPartyLuckValue(globalScene.getPlayerParty()), true); - } - const bossPokemon = new EnemyPokemon(bossSpecies, level, TrainerSlot.NONE, true); + const bossPokemon = getRandomEncounterSpecies(level, true); encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon)); const config: EnemyPartyConfig = { pokemonConfigs: [{ level: level, - species: bossSpecies, + species: bossPokemon.species, dataSource: new PokemonData(bossPokemon), isBoss: true }], diff --git a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts index d710dffab8c..f382f130540 100644 --- a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts +++ b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts @@ -41,7 +41,7 @@ const OPTION_3_DISALLOWED_MODIFIERS = [ const DELIBIRDY_MONEY_PRICE_MULTIPLIER = 2; const doEventReward = () => { - const event_buff = globalScene.eventManager.activeEvent()?.delibirdyBuff ?? []; + const event_buff = globalScene.eventManager.getDelibirdyBuff(); if (event_buff.length > 0) { const candidates = event_buff.filter((c => { const mtype = generateModifierType(modifierTypes[c]); diff --git a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts index fc6f163010b..1667a15e7c9 100644 --- a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts +++ b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts @@ -2,6 +2,7 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/myst import type { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { + getRandomEncounterSpecies, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterExp, @@ -9,12 +10,10 @@ import { } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups"; import type Pokemon from "#app/field/pokemon"; -import { EnemyPokemon } from "#app/field/pokemon"; import { ModifierTier } from "#app/modifier/modifier-tier"; import type { ModifierTypeOption } from "#app/modifier/modifier-type"; import { - getPartyLuckValue, getPlayerModifierTypeOptions, ModifierPoolType, regenerateModifierPoolThresholds, @@ -26,16 +25,13 @@ import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-en import { MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; -import { TrainerSlot } from "#app/data/trainer-config"; import { getEncounterPokemonLevelForWave, getSpriteKeysFromPokemon, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import PokemonData from "#app/system/pokemon-data"; import { BattlerTagType } from "#enums/battler-tag-type"; import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; -import { randSeedInt, randSeedItem } from "#app/utils"; +import { randSeedInt } from "#app/utils"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; -import type PokemonSpecies from "#app/data/pokemon-species"; -import { getPokemonSpecies } from "#app/data/pokemon-species"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounters/fightOrFlight"; @@ -63,20 +59,12 @@ export const FightOrFlightEncounter: MysteryEncounter = // Calculate boss mon const level = getEncounterPokemonLevelForWave(STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER); - let bossSpecies: PokemonSpecies; - if (globalScene.eventManager.isEventActive() && globalScene.eventManager.activeEvent()?.uncommonBreedEncounters && randSeedInt(2) === 1) { - const eventEncounter = randSeedItem(globalScene.eventManager.activeEvent()!.uncommonBreedEncounters!); - const levelSpecies = getPokemonSpecies(eventEncounter.species).getWildSpeciesForLevel(level, eventEncounter.allowEvolution ?? false, true, globalScene.gameMode); - bossSpecies = getPokemonSpecies( levelSpecies ); - } else { - bossSpecies = globalScene.arena.randomSpecies(globalScene.currentBattle.waveIndex, level, 0, getPartyLuckValue(globalScene.getPlayerParty()), true); - } - const bossPokemon = new EnemyPokemon(bossSpecies, level, TrainerSlot.NONE, true); + const bossPokemon = getRandomEncounterSpecies(level, true); encounter.setDialogueToken("enemyPokemon", bossPokemon.getNameToRender()); const config: EnemyPartyConfig = { pokemonConfigs: [{ level: level, - species: bossSpecies, + species: bossPokemon.species, dataSource: new PokemonData(bossPokemon), isBoss: true, tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ], diff --git a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts index b50ced69918..65bbab16603 100644 --- a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts +++ b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts @@ -449,7 +449,7 @@ function getPokemonTradeOptions(): Map { }); tradeOptionsMap.set(pokemon.id, tradeOptions); } else { - const originalBst = pokemon.calculateBaseStats().reduce((a, b) => a + b, 0); + const originalBst = pokemon.getSpeciesForm().getBaseStatTotal(); const tradeOptions: PokemonSpecies[] = []; for (let i = 0; i < 3; i++) { diff --git a/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts b/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts index 702d8262cb6..5e87a40d952 100644 --- a/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts @@ -452,7 +452,7 @@ function getSpeciesFromPool(speciesPool: (Species | BreederSpeciesEvolution)[][] } function calculateEggRewardsForPokemon(pokemon: PlayerPokemon): [number, number] { - const bst = pokemon.calculateBaseStats().reduce((a, b) => a + b, 0); + const bst = pokemon.getSpeciesForm().getBaseStatTotal(); // 1 point for every 20 points below 680 BST the pokemon is, (max 18, min 1) const pointsFromBst = Math.min(Math.max(Math.floor((680 - bst) / 20), 1), 18); diff --git a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts index 6748d133d67..9e94e87938e 100644 --- a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts @@ -147,8 +147,8 @@ export const TheStrongStuffEncounter: MysteryEncounter = // Sort party by bst const sortedParty = globalScene.getPlayerParty().slice(0) .sort((pokemon1, pokemon2) => { - const pokemon1Bst = pokemon1.calculateBaseStats().reduce((a, b) => a + b, 0); - const pokemon2Bst = pokemon2.calculateBaseStats().reduce((a, b) => a + b, 0); + const pokemon1Bst = pokemon1.getSpeciesForm().getBaseStatTotal(); + const pokemon2Bst = pokemon2.getSpeciesForm().getBaseStatTotal(); return pokemon2Bst - pokemon1Bst; }); diff --git a/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts b/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts index d0a44504763..ca6b384cfbb 100644 --- a/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts @@ -16,7 +16,7 @@ import { Nature } from "#enums/nature"; import { Type } from "#enums/type"; import { BerryType } from "#enums/berry-type"; import { Stat } from "#enums/stat"; -import { SpeciesFormChangeManualTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeAbilityTrigger } from "#app/data/pokemon-forms"; import { applyPostBattleInitAbAttrs, PostBattleInitAbAttr } from "#app/data/ability"; import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; @@ -198,7 +198,7 @@ function endTrainerBattleAndShowDialogue(): Promise { // Only trigger form change when Eiscue is in Noice form // Hardcoded Eiscue for now in case it is fused with another pokemon if (pokemon.species.speciesId === Species.EISCUE && pokemon.hasAbility(Abilities.ICE_FACE) && pokemon.formIndex === 1) { - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger); + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger); } pokemon.resetBattleData(); diff --git a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts index 39297ab95b6..6e6381888f1 100644 --- a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts +++ b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts @@ -1,10 +1,10 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import type { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; -import { initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { getRandomEncounterSpecies, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { CHARMING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups"; import type Pokemon from "#app/field/pokemon"; -import { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; -import { getPartyLuckValue } from "#app/modifier/modifier-type"; +import type { EnemyPokemon } from "#app/field/pokemon"; +import { PokemonMove } from "#app/field/pokemon"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { globalScene } from "#app/global-scene"; import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; @@ -12,10 +12,9 @@ import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-en import { MoveRequirement, PersistentModifierRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; -import { TrainerSlot } from "#app/data/trainer-config"; import { catchPokemon, getHighestLevelPlayerPokemon, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import PokemonData from "#app/system/pokemon-data"; -import { isNullOrUndefined, randSeedInt, randSeedItem } from "#app/utils"; +import { isNullOrUndefined, randSeedInt } from "#app/utils"; import type { Moves } from "#enums/moves"; import { BattlerIndex } from "#app/battle"; import { SelfStatusMove } from "#app/data/move"; @@ -26,8 +25,6 @@ import { BerryModifier } from "#app/modifier/modifier"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { Stat } from "#enums/stat"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; -import type PokemonSpecies from "#app/data/pokemon-species"; -import { getPokemonSpecies } from "#app/data/pokemon-species"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounters/uncommonBreed"; @@ -56,15 +53,7 @@ export const UncommonBreedEncounter: MysteryEncounter = // Calculate boss mon // Level equal to 2 below highest party member const level = getHighestLevelPlayerPokemon(false, true).level - 2; - let species: PokemonSpecies; - if (globalScene.eventManager.isEventActive() && globalScene.eventManager.activeEvent()?.uncommonBreedEncounters && randSeedInt(2) === 1) { - const eventEncounter = randSeedItem(globalScene.eventManager.activeEvent()!.uncommonBreedEncounters!); - const levelSpecies = getPokemonSpecies(eventEncounter.species).getWildSpeciesForLevel(level, eventEncounter.allowEvolution ?? false, true, globalScene.gameMode); - species = getPokemonSpecies( levelSpecies ); - } else { - species = globalScene.arena.randomSpecies(globalScene.currentBattle.waveIndex, level, 0, getPartyLuckValue(globalScene.getPlayerParty()), true); - } - const pokemon = new EnemyPokemon(species, level, TrainerSlot.NONE, true); + const pokemon = getRandomEncounterSpecies(level, true, true); // Pokemon will always have one of its egg moves in its moveset const eggMoves = pokemon.getEggMoves(); @@ -92,7 +81,7 @@ export const UncommonBreedEncounter: MysteryEncounter = const config: EnemyPartyConfig = { pokemonConfigs: [{ level: level, - species: species, + species: pokemon.species, dataSource: new PokemonData(pokemon), isBoss: false, tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ], diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index 392a963e639..e8a4c405d5f 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -360,7 +360,7 @@ function getTeamTransformations(): PokemonTransformation[] { const index = pokemonTransformations.findIndex(p => p.previousPokemon.id === removed.id); pokemonTransformations[index].heldItems = removed.getHeldItems().filter(m => !(m instanceof PokemonFormChangeItemModifier)); - const bst = removed.calculateBaseStats().reduce((a, b) => a + b, 0); + const bst = removed.getSpeciesForm().getBaseStatTotal(); let newBstRange: [number, number]; if (i < 2) { newBstRange = HIGH_BST_TRANSFORM_BASE_VALUES; diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index 8768fb06b37..8e7c67fae84 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -6,9 +6,9 @@ import { AVERAGE_ENCOUNTERS_PER_RUN_TARGET, WEIGHT_INCREMENT_ON_SPAWN_MISS } fro import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import type { AiType, PlayerPokemon } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; -import { FieldPosition, PokemonMove, PokemonSummonData } from "#app/field/pokemon"; +import { EnemyPokemon, FieldPosition, PokemonMove, PokemonSummonData } from "#app/field/pokemon"; import type { CustomModifierSettings, ModifierType } from "#app/modifier/modifier-type"; -import { ModifierPoolType, ModifierTypeGenerator, ModifierTypeOption, modifierTypes, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type"; +import { getPartyLuckValue, ModifierPoolType, ModifierTypeGenerator, ModifierTypeOption, modifierTypes, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type"; import { MysteryEncounterBattlePhase, MysteryEncounterBattleStartCleanupPhase, MysteryEncounterPhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phases"; import type PokemonData from "#app/system/pokemon-data"; import type { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; @@ -16,7 +16,7 @@ import type { PartyOption, PokemonSelectFilter } from "#app/ui/party-ui-handler" import { PartyUiMode } from "#app/ui/party-ui-handler"; import { Mode } from "#app/ui/ui"; import * as Utils from "#app/utils"; -import { isNullOrUndefined } from "#app/utils"; +import { isNullOrUndefined, randSeedInt, randSeedItem } from "#app/utils"; import type { BattlerTagType } from "#enums/battler-tag-type"; import { Biome } from "#enums/biome"; import type { TrainerType } from "#enums/trainer-type"; @@ -45,6 +45,7 @@ import { PartyExpPhase } from "#app/phases/party-exp-phase"; import type { Variant } from "#app/data/variant"; import { StatusEffect } from "#enums/status-effect"; import { globalScene } from "#app/global-scene"; +import { getPokemonSpecies } from "#app/data/pokemon-species"; /** * Animates exclamation sprite over trainer's head at start of encounter @@ -874,6 +875,41 @@ export function handleMysteryEncounterTurnStartEffects(): boolean { return false; } +/** + * Helper function for encounters such as {@linkcode UncommonBreedEncounter} which call for a random species including event encounters. + * If the mon is from the event encounter list, it will do an extra shiny roll. + * @param level the level of the mon, which differs between MEs + * @param isBoss whether the mon should be a Boss + * @param rerollHidden whether the mon should get an extra roll for Hidden Ability + * @returns {@linkcode EnemyPokemon} for the requested encounter + */ +export function getRandomEncounterSpecies(level: number, isBoss: boolean = false, rerollHidden: boolean = false): EnemyPokemon { + let bossSpecies: PokemonSpecies; + let isEventEncounter = false; + const eventEncounters = globalScene.eventManager.getEventEncounters(); + + if (eventEncounters.length > 0 && randSeedInt(2) === 1) { + const eventEncounter = randSeedItem(eventEncounters); + const levelSpecies = getPokemonSpecies(eventEncounter.species).getWildSpeciesForLevel(level, !eventEncounter.blockEvolution, isBoss, globalScene.gameMode); + isEventEncounter = true; + bossSpecies = getPokemonSpecies(levelSpecies); + } else { + bossSpecies = globalScene.arena.randomSpecies(globalScene.currentBattle.waveIndex, level, 0, getPartyLuckValue(globalScene.getPlayerParty()), isBoss); + } + const ret = new EnemyPokemon(bossSpecies, level, TrainerSlot.NONE, isBoss); + + //Reroll shiny for event encounters + if (isEventEncounter && !ret.shiny) { + ret.trySetShinySeed(); + } + //Reroll hidden ability + if (rerollHidden && ret.abilityIndex !== 2 && ret.species.abilityHidden) { + ret.tryRerollHiddenAbilitySeed(); + } + + return ret; +} + /** * TODO: remove once encounter spawn rate is finalized * Just a helper function to calculate aggregate stats for MEs in a Classic run diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index b1c3db47768..035cd6f1369 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -212,6 +212,8 @@ export class SpeciesFormChangeCondition { } export abstract class SpeciesFormChangeTrigger { + public description: string = ""; + canChange(pokemon: Pokemon): boolean { return true; } @@ -222,16 +224,19 @@ export abstract class SpeciesFormChangeTrigger { } export class SpeciesFormChangeManualTrigger extends SpeciesFormChangeTrigger { - canChange(pokemon: Pokemon): boolean { - return true; - } +} + +export class SpeciesFormChangeAbilityTrigger extends SpeciesFormChangeTrigger { + public description: string = i18next.t("pokemonEvolutions:Forms.ability"); } export class SpeciesFormChangeCompoundTrigger { + public description: string = ""; public triggers: SpeciesFormChangeTrigger[]; constructor(...triggers: SpeciesFormChangeTrigger[]) { this.triggers = triggers; + this.description = this.triggers.filter(trigger => trigger?.description?.length > 0).map(trigger => trigger.description).join(", "); } canChange(pokemon: Pokemon): boolean { @@ -257,6 +262,9 @@ export class SpeciesFormChangeItemTrigger extends SpeciesFormChangeTrigger { super(); this.item = item; this.active = active; + this.description = this.active ? + i18next.t("pokemonEvolutions:Forms.item", { item: i18next.t(`modifierType:FormChangeItem.${FormChangeItem[this.item]}`) }) : + i18next.t("pokemonEvolutions:Forms.deactivateItem", { item: i18next.t(`modifierType:FormChangeItem.${FormChangeItem[this.item]}`) }); } canChange(pokemon: Pokemon): boolean { @@ -270,6 +278,7 @@ export class SpeciesFormChangeTimeOfDayTrigger extends SpeciesFormChangeTrigger constructor(...timesOfDay: TimeOfDay[]) { super(); this.timesOfDay = timesOfDay; + this.description = i18next.t("pokemonEvolutions:Forms.timeOfDay"); } canChange(pokemon: Pokemon): boolean { @@ -283,6 +292,7 @@ export class SpeciesFormChangeActiveTrigger extends SpeciesFormChangeTrigger { constructor(active: boolean = false) { super(); this.active = active; + this.description = this.active ? i18next.t("pokemonEvolutions:Forms.enter") : i18next.t("pokemonEvolutions:Forms.leave"); } canChange(pokemon: Pokemon): boolean { @@ -301,6 +311,7 @@ export class SpeciesFormChangeStatusEffectTrigger extends SpeciesFormChangeTrigg } this.statusEffects = statusEffects; this.invert = invert; + this.description = i18next.t("pokemonEvolutions:Forms.statusEffect"); } canChange(pokemon: Pokemon): boolean { @@ -316,6 +327,8 @@ export class SpeciesFormChangeMoveLearnedTrigger extends SpeciesFormChangeTrigge super(); this.move = move; this.known = known; + const moveKey = Moves[this.move].split("_").filter(f => f).map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join("") as unknown as string; + this.description = i18next.t("pokemonEvolutions:Forms.moveLearned", { move: i18next.t(`move:${moveKey}.name`) }); } canChange(pokemon: Pokemon): boolean { @@ -335,6 +348,8 @@ export abstract class SpeciesFormChangeMoveTrigger extends SpeciesFormChangeTrig } export class SpeciesFormChangePreMoveTrigger extends SpeciesFormChangeMoveTrigger { + description = i18next.t("pokemonEvolutions:Forms.preMove"); + canChange(pokemon: Pokemon): boolean { const command = globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]; return !!command?.move && this.movePredicate(command.move.move) === this.used; @@ -342,6 +357,8 @@ export class SpeciesFormChangePreMoveTrigger extends SpeciesFormChangeMoveTrigge } export class SpeciesFormChangePostMoveTrigger extends SpeciesFormChangeMoveTrigger { + description = i18next.t("pokemonEvolutions:Forms.postMove"); + canChange(pokemon: Pokemon): boolean { return pokemon.summonData && !!pokemon.getLastXMoves(1).filter(m => this.movePredicate(m.move)).length === this.used; } @@ -367,6 +384,7 @@ export class SpeciesDefaultFormMatchTrigger extends SpeciesFormChangeTrigger { constructor(formKey: string) { super(); this.formKey = formKey; + this.description = ""; } canChange(pokemon: Pokemon): boolean { @@ -386,6 +404,7 @@ export class SpeciesFormChangeTeraTrigger extends SpeciesFormChangeTrigger { constructor(teraType: Type) { super(); this.teraType = teraType; + this.description = i18next.t("pokemonEvolutions:Forms.tera", { teraType: i18next.t(`pokemonInfo:Type.${Type[this.teraType]}`) }); } /** @@ -404,6 +423,8 @@ export class SpeciesFormChangeTeraTrigger extends SpeciesFormChangeTrigger { * @extends SpeciesFormChangeTrigger */ export class SpeciesFormChangeLapseTeraTrigger extends SpeciesFormChangeTrigger { + description = i18next.t("pokemonEvolutions:Forms.teraLapse"); + canChange(pokemon: Pokemon): boolean { return !!globalScene.findModifier(m => m instanceof TerastallizeModifier && m.pokemonId === pokemon.id); } @@ -424,6 +445,7 @@ export class SpeciesFormChangeWeatherTrigger extends SpeciesFormChangeTrigger { super(); this.ability = ability; this.weathers = weathers; + this.description = i18next.t("pokemonEvolutions:Forms.weather"); } /** @@ -457,6 +479,7 @@ export class SpeciesFormChangeRevertWeatherFormTrigger extends SpeciesFormChange super(); this.ability = ability; this.weathers = weathers; + this.description = i18next.t("pokemonEvolutions:Forms.weatherRevert"); } /** @@ -751,8 +774,8 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.ARCEUS, "normal", "fairy", new SpeciesFormChangeItemTrigger(FormChangeItem.PIXIE_PLATE)) ], [Species.DARMANITAN]: [ - new SpeciesFormChange(Species.DARMANITAN, "", "zen", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.DARMANITAN, "zen", "", new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.DARMANITAN, "", "zen", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.DARMANITAN, "zen", "", new SpeciesFormChangeAbilityTrigger(), true) ], [Species.GARBODOR]: [ new SpeciesFormChange(Species.GARBODOR, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) @@ -785,12 +808,12 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.GENESECT, "", "douse", new SpeciesFormChangeItemTrigger(FormChangeItem.DOUSE_DRIVE)) ], [Species.GRENINJA]: [ - new SpeciesFormChange(Species.GRENINJA, "battle-bond", "ash", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.GRENINJA, "ash", "battle-bond", new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.GRENINJA, "battle-bond", "ash", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.GRENINJA, "ash", "battle-bond", new SpeciesFormChangeAbilityTrigger(), true) ], [Species.PALAFIN] : [ - new SpeciesFormChange(Species.PALAFIN, "zero", "hero", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.PALAFIN, "hero", "zero", new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.PALAFIN, "zero", "hero", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.PALAFIN, "hero", "zero", new SpeciesFormChangeAbilityTrigger(), true) ], [Species.AEGISLASH]: [ new SpeciesFormChange(Species.AEGISLASH, "blade", "shield", new SpeciesFormChangePreMoveTrigger(Moves.KINGS_SHIELD), true, new SpeciesFormChangeCondition(p => p.hasAbility(Abilities.STANCE_CHANGE))), @@ -802,10 +825,10 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.XERNEAS, "active", "neutral", new SpeciesFormChangeActiveTrigger(false), true) ], [Species.ZYGARDE]: [ - new SpeciesFormChange(Species.ZYGARDE, "50-pc", "complete", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.ZYGARDE, "complete", "50-pc", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.ZYGARDE, "10-pc", "10-complete", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.ZYGARDE, "10-complete", "10-pc", new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.ZYGARDE, "50-pc", "complete", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.ZYGARDE, "complete", "50-pc", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.ZYGARDE, "10-pc", "10-complete", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.ZYGARDE, "10-complete", "10-pc", new SpeciesFormChangeAbilityTrigger(), true) ], [Species.DIANCIE]: [ new SpeciesFormChange(Species.DIANCIE, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.DIANCITE)) @@ -814,8 +837,8 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.HOOPA, "", "unbound", new SpeciesFormChangeItemTrigger(FormChangeItem.PRISON_BOTTLE)) ], [Species.WISHIWASHI]: [ - new SpeciesFormChange(Species.WISHIWASHI, "", "school", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.WISHIWASHI, "school", "", new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.WISHIWASHI, "", "school", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.WISHIWASHI, "school", "", new SpeciesFormChangeAbilityTrigger(), true) ], [Species.SILVALLY]: [ new SpeciesFormChange(Species.SILVALLY, "normal", "fighting", new SpeciesFormChangeItemTrigger(FormChangeItem.FIGHTING_MEMORY)), @@ -837,24 +860,24 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.SILVALLY, "normal", "fairy", new SpeciesFormChangeItemTrigger(FormChangeItem.FAIRY_MEMORY)) ], [Species.MINIOR]: [ - new SpeciesFormChange(Species.MINIOR, "red-meteor", "red", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "red", "red-meteor", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "orange-meteor", "orange", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "orange", "orange-meteor", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "yellow-meteor", "yellow", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "yellow", "yellow-meteor", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "green-meteor", "green", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "green", "green-meteor", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "blue-meteor", "blue", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "blue", "blue-meteor", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "indigo-meteor", "indigo", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "indigo", "indigo-meteor", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "violet-meteor", "violet", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MINIOR, "violet", "violet-meteor", new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.MINIOR, "red-meteor", "red", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "red", "red-meteor", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "orange-meteor", "orange", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "orange", "orange-meteor", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "yellow-meteor", "yellow", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "yellow", "yellow-meteor", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "green-meteor", "green", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "green", "green-meteor", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "blue-meteor", "blue", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "blue", "blue-meteor", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "indigo-meteor", "indigo", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "indigo", "indigo-meteor", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "violet-meteor", "violet", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MINIOR, "violet", "violet-meteor", new SpeciesFormChangeAbilityTrigger(), true) ], [Species.MIMIKYU]: [ - new SpeciesFormChange(Species.MIMIKYU, "disguised", "busted", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MIMIKYU, "busted", "disguised", new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.MIMIKYU, "disguised", "busted", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MIMIKYU, "busted", "disguised", new SpeciesFormChangeAbilityTrigger(), true) ], [Species.NECROZMA]: [ new SpeciesFormChange(Species.NECROZMA, "", "dawn-wings", new SpeciesFormChangeItemTrigger(FormChangeItem.N_LUNARIZER), false, getSpeciesDependentFormChangeCondition(Species.LUNALA)), @@ -896,10 +919,10 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.SANDACONDA, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) ], [Species.CRAMORANT]: [ - new SpeciesFormChange(Species.CRAMORANT, "", "gulping", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() >= .5)), - new SpeciesFormChange(Species.CRAMORANT, "", "gorging", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() < .5)), - new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeManualTrigger, true), - new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeManualTrigger, true), + new SpeciesFormChange(Species.CRAMORANT, "", "gulping", new SpeciesFormChangeAbilityTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() >= .5)), + new SpeciesFormChange(Species.CRAMORANT, "", "gorging", new SpeciesFormChangeAbilityTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() < .5)), + new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeAbilityTrigger, true), + new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeAbilityTrigger, true), new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeActiveTrigger(false), true), new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeActiveTrigger(false), true) ], @@ -930,12 +953,12 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.ALCREMIE, "rainbow-swirl", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) ], [Species.EISCUE]: [ - new SpeciesFormChange(Species.EISCUE, "", "no-ice", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.EISCUE, "no-ice", "", new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.EISCUE, "", "no-ice", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.EISCUE, "no-ice", "", new SpeciesFormChangeAbilityTrigger(), true) ], [Species.MORPEKO]: [ - new SpeciesFormChange(Species.MORPEKO, "full-belly", "hangry", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.MORPEKO, "hangry", "full-belly", new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.MORPEKO, "full-belly", "hangry", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.MORPEKO, "hangry", "full-belly", new SpeciesFormChangeAbilityTrigger(), true) ], [Species.COPPERAJAH]: [ new SpeciesFormChange(Species.COPPERAJAH, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) @@ -978,13 +1001,13 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.OGERPON, "cornerstone-mask-tera", "cornerstone-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.ROCK)) ], [Species.TERAPAGOS]: [ - new SpeciesFormChange(Species.TERAPAGOS, "", "terastal", new SpeciesFormChangeManualTrigger(), true), + new SpeciesFormChange(Species.TERAPAGOS, "", "terastal", new SpeciesFormChangeAbilityTrigger(), true), new SpeciesFormChange(Species.TERAPAGOS, "terastal", "stellar", new SpeciesFormChangeTeraTrigger(Type.STELLAR)), new SpeciesFormChange(Species.TERAPAGOS, "stellar", "terastal", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.STELLAR)) ], [Species.GALAR_DARMANITAN]: [ - new SpeciesFormChange(Species.GALAR_DARMANITAN, "", "zen", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.GALAR_DARMANITAN, "zen", "", new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.GALAR_DARMANITAN, "", "zen", new SpeciesFormChangeAbilityTrigger(), true), + new SpeciesFormChange(Species.GALAR_DARMANITAN, "zen", "", new SpeciesFormChangeAbilityTrigger(), true) ], }; @@ -1002,3 +1025,4 @@ export function initPokemonForms() { formChanges.push(...newFormChanges); }); } + diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 574c2a67f65..f2ab2f6520f 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -22,6 +22,7 @@ import type { Variant, VariantSet } from "#app/data/variant"; import { variantData } from "#app/data/variant"; import { speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters"; import { SpeciesFormKey } from "#enums/species-form-key"; +import { starterPassiveAbilities } from "#app/data/balance/passives"; export enum Region { NORMAL, @@ -230,6 +231,31 @@ export abstract class PokemonSpeciesForm { return ret; } + /** + * Method to get the passive ability of a Pokemon species + * @param formIndex The form index to use, defaults to form for this species instance + * @returns The id of the ability + */ + getPassiveAbility(formIndex?: number): Abilities { + if (Utils.isNullOrUndefined(formIndex)) { + formIndex = this.formIndex; + } + let starterSpeciesId = this.speciesId; + while (!(starterSpeciesId in starterPassiveAbilities) || !(formIndex in starterPassiveAbilities[starterSpeciesId])) { + if (pokemonPrevolutions.hasOwnProperty(starterSpeciesId)) { + starterSpeciesId = pokemonPrevolutions[starterSpeciesId]; + } else { // If we've reached the base species and still haven't found a matching ability, use form 0 if possible + if (0 in starterPassiveAbilities[starterSpeciesId]) { + return starterPassiveAbilities[starterSpeciesId][0]; + } else { + console.log("No passive ability found for %s, using run away", this.speciesId); + return Abilities.RUN_AWAY; + } + } + } + return starterPassiveAbilities[starterSpeciesId][formIndex]; + } + getLevelMoves(): LevelMoves { if (pokemonSpeciesFormLevelMoves.hasOwnProperty(this.speciesId) && pokemonSpeciesFormLevelMoves[this.speciesId].hasOwnProperty(this.formIndex)) { return pokemonSpeciesFormLevelMoves[this.speciesId][this.formIndex].slice(0); diff --git a/src/data/status-effect.ts b/src/data/status-effect.ts index 3c085bdd099..35a956cbb93 100644 --- a/src/data/status-effect.ts +++ b/src/data/status-effect.ts @@ -162,7 +162,7 @@ export function getNonVolatileStatusEffects():Array { } /** - * Returns whether a statuss effect is non volatile. + * Returns whether a status effect is non volatile. * Non-volatile status condition is a status that remains after being switched out. * @param status The status to check */ diff --git a/src/data/weather.ts b/src/data/weather.ts index d971f726543..7bba698f9b4 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -375,8 +375,8 @@ export function getRandomWeatherType(arena: Arena): WeatherType { break; } - if (arena.biomeType === Biome.TOWN && globalScene.eventManager.isEventActive() && (globalScene.eventManager.activeEvent()?.weather?.length ?? 0) > 0) { - globalScene.eventManager.activeEvent()?.weather?.map(w => weatherPool.push(w)); + if (arena.biomeType === Biome.TOWN && globalScene.eventManager.isEventActive()) { + globalScene.eventManager.getWeather()?.map(w => weatherPool.push(w)); } if (weatherPool.length > 1) { diff --git a/src/field/arena.ts b/src/field/arena.ts index 71966b97775..deeb261a491 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -695,6 +695,7 @@ export class Arena { globalScene.loadBgm(this.bgm); } + /** The loop point of any given biome track, read as seconds and milliseconds. */ getBgmLoopPoint(): number { switch (this.biomeType) { case Biome.TOWN: diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index a4b8603cbb0..5b7cafeefb8 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -10,8 +10,7 @@ import type Move from "#app/data/move"; import { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget, CombinedPledgeStabBoostAttr, VariableMoveTypeChartAttr } from "#app/data/move"; import type { PokemonSpeciesForm } from "#app/data/pokemon-species"; import { default as PokemonSpecies, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; -import { CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER, getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters"; -import { starterPassiveAbilities } from "#app/data/balance/passives"; +import { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters"; import type { Constructor } from "#app/utils"; import { isNullOrUndefined, randSeedInt, type nil } from "#app/utils"; import * as Utils from "#app/utils"; @@ -1108,6 +1107,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.getStat(Stat.HP); } + /** Returns the amount of hp currently missing from this {@linkcode Pokemon} (max - current) */ getInverseHp(): integer { return this.getMaxHp() - this.hp; } @@ -1400,11 +1400,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return allAbilities[this.customPokemonData.passive]; } - let starterSpeciesId = this.species.speciesId; - while (pokemonPrevolutions.hasOwnProperty(starterSpeciesId)) { - starterSpeciesId = pokemonPrevolutions[starterSpeciesId]; - } - return allAbilities[starterPassiveAbilities[starterSpeciesId]]; + return allAbilities[this.species.getPassiveAbility(this.formIndex)]; } /** @@ -1955,7 +1951,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param thresholdOverride number that is divided by 2^16 (65536) to get the shiny chance, overrides {@linkcode shinyThreshold} if set (bypassing shiny rate modifiers such as Shiny Charm) * @returns true if the Pokemon has been set as a shiny, false otherwise */ - trySetShiny(thresholdOverride?: integer): boolean { + trySetShiny(thresholdOverride?: number): boolean { // Shiny Pokemon should not spawn in the end biome in endless if (globalScene.gameMode.isEndless && globalScene.arena.biomeType === Biome.END) { return false; @@ -1967,7 +1963,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const E = globalScene.gameData.trainerId ^ globalScene.gameData.secretId; const F = rand1 ^ rand2; - const shinyThreshold = new Utils.IntegerHolder(BASE_SHINY_CHANCE); + const shinyThreshold = new Utils.NumberHolder(BASE_SHINY_CHANCE); if (thresholdOverride === undefined) { if (globalScene.eventManager.isEventActive()) { shinyThreshold.value *= globalScene.eventManager.getShinyMultiplier(); @@ -2058,6 +2054,38 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } + /** + * Function that tries to set a Pokemon to have its hidden ability based on seed, if it exists. + * For manual use only, usually to roll a Pokemon's hidden ability chance a second time. + * + * The base hidden ability odds are {@linkcode BASE_HIDDEN_ABILITY_CHANCE} / `65536` + * @param thresholdOverride number that is divided by `2^16` (`65536`) to get the HA chance, overrides {@linkcode haThreshold} if set (bypassing HA rate modifiers such as Ability Charm) + * @param applyModifiersToOverride If {@linkcode thresholdOverride} is set and this is true, will apply Ability Charm to {@linkcode thresholdOverride} + * @returns `true` if the Pokemon has been set to have its hidden ability, `false` otherwise + */ + public tryRerollHiddenAbilitySeed(thresholdOverride?: number, applyModifiersToOverride?: boolean): boolean { + if (!this.species.abilityHidden) { + return false; + } + const haThreshold = new Utils.NumberHolder(BASE_HIDDEN_ABILITY_CHANCE); + if (thresholdOverride === undefined || applyModifiersToOverride) { + if (thresholdOverride !== undefined && applyModifiersToOverride) { + haThreshold.value = thresholdOverride; + } + if (!this.hasTrainer()) { + globalScene.applyModifiers(HiddenAbilityRateBoosterModifier, true, haThreshold); + } + } else { + haThreshold.value = thresholdOverride; + } + + if (randSeedInt(65536) < haThreshold.value) { + this.abilityIndex = 2; + } + + return this.abilityIndex === 2; + } + public generateFusionSpecies(forStarter?: boolean): void { const hiddenAbilityChance = new Utils.NumberHolder(BASE_HIDDEN_ABILITY_CHANCE); if (!this.hasTrainer()) { @@ -2391,8 +2419,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.battleInfo.toggleFlyout(visible); } - addExp(exp: integer) { - const maxExpLevel = globalScene.getMaxExpLevel(); + /** + * Adds experience to this PlayerPokemon, subject to wave based level caps. + * @param exp The amount of experience to add + * @param ignoreLevelCap Whether to ignore level caps when adding experience (defaults to false) + */ + addExp(exp: integer, ignoreLevelCap: boolean = false) { + const maxExpLevel = globalScene.getMaxExpLevel(ignoreLevelCap); const initialExp = this.exp; this.exp += exp; while (this.level < maxExpLevel && this.exp >= getLevelTotalExp(this.level + 1, this.species.growthRate)) { @@ -4323,10 +4356,7 @@ export class PlayerPokemon extends Pokemon { ].filter(d => !!d); const amount = new Utils.NumberHolder(friendship); globalScene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount); - let candyFriendshipMultiplier = CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER; - if (globalScene.eventManager.isEventActive()) { - candyFriendshipMultiplier *= globalScene.eventManager.getFriendshipMultiplier(); - } + const candyFriendshipMultiplier = globalScene.eventManager.getClassicFriendshipMultiplier(); const starterAmount = new Utils.NumberHolder(Math.floor(amount.value * (globalScene.gameMode.isClassic ? candyFriendshipMultiplier : 1) / (fusionStarterSpeciesId ? 2 : 1))); // Add friendship to this PlayerPokemon diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 40b6417f9f2..023f907a30d 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -246,9 +246,9 @@ export class LoadingScene extends SceneBase { } const availableLangs = [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ]; if (lang && availableLangs.includes(lang)) { - this.loadImage("winter_holidays2024-event-" + lang, "events"); + this.loadImage("yearofthesnakeevent-" + lang, "events"); } else { - this.loadImage("winter_holidays2024-event-en", "events"); + this.loadImage("yearofthesnakeevent-en", "events"); } this.loadAtlas("statuses", ""); diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 9c844596abc..f531e96d641 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -2537,9 +2537,10 @@ export function getPartyLuckValue(party: Pokemon[]): integer { }, 0, globalScene.seed); return DailyLuck.value; } - const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? p.getLuck() : 0) + const eventSpecies = globalScene.eventManager.getEventLuckBoostedSpecies(); + const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? p.getLuck() + (eventSpecies.includes(p.species.speciesId) ? 1 : 0) : 0) .reduce((total: integer, value: integer) => total += value, 0), 0, 14); - return luck ?? 0; + return Math.min(globalScene.eventManager.getEventLuckBoost() + (luck ?? 0), 14); } export function getLuckString(luckValue: integer): string { diff --git a/src/overrides.ts b/src/overrides.ts index 1f8601b7659..06ad619a074 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -22,7 +22,7 @@ import { WeatherType } from "#enums/weather-type"; * * Any override added here will be used instead of the value in {@linkcode DefaultOverrides} * - * If an override name starts with "STARTING", it will apply when a new run begins + * If an override name starts with "STARTING", it will only apply when a new run begins. * * @example * ``` @@ -39,7 +39,7 @@ const overrides = {} satisfies Partial>; * --- * Defaults for Overrides that are used when testing different in game situations * - * If an override name starts with "STARTING", it will apply when a new run begins + * If an override name starts with "STARTING", it will only apply when a new run begins. */ class DefaultOverrides { // ----------------- @@ -63,8 +63,11 @@ class DefaultOverrides { readonly STARTING_WAVE_OVERRIDE: number = 0; readonly STARTING_BIOME_OVERRIDE: Biome = Biome.TOWN; 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; + /** Sets the level cap to this number during experience gain calculations. Set to `0` to disable override & use normal wave-based level caps, + or any negative number to set it to 9 quadrillion (effectively disabling it). */ + readonly LEVEL_CAP_OVERRIDE: number = 0; readonly NEVER_CRIT_OVERRIDE: boolean = false; /** default 1000 */ readonly STARTING_MONEY_OVERRIDE: number = 0; diff --git a/src/phases/learn-move-phase.ts b/src/phases/learn-move-phase.ts index 6f10022d1fc..a11b797c574 100644 --- a/src/phases/learn-move-phase.ts +++ b/src/phases/learn-move-phase.ts @@ -26,7 +26,7 @@ export enum LearnMoveType { export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { private moveId: Moves; private messageMode: Mode; - private learnMoveType; + private learnMoveType: LearnMoveType; private cost: number; constructor(partyMemberIndex: integer, moveId: Moves, learnMoveType: LearnMoveType = LearnMoveType.LEARN_MOVE, cost: number = -1) { diff --git a/src/phases/trainer-victory-phase.ts b/src/phases/trainer-victory-phase.ts index 3fa7209751a..e2617f598da 100644 --- a/src/phases/trainer-victory-phase.ts +++ b/src/phases/trainer-victory-phase.ts @@ -39,7 +39,11 @@ export class TrainerVictoryPhase extends BattlePhase { // Validate Voucher for boss trainers if (vouchers.hasOwnProperty(TrainerType[trainerType])) { if (!globalScene.validateVoucher(vouchers[TrainerType[trainerType]]) && globalScene.currentBattle.trainer?.config.isBoss) { - globalScene.unshiftPhase(new ModifierRewardPhase([ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType])); + if (globalScene.eventManager.getUpgradeUnlockedVouchers()) { + globalScene.unshiftPhase(new ModifierRewardPhase([ modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType])); + } else { + globalScene.unshiftPhase(new ModifierRewardPhase([ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType])); + } } } // Breeders in Space achievement diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 6a7a36dbca5..ac99490e640 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -204,6 +204,7 @@ export async function initI18n(): Promise { "nature", "pokeball", "pokemon", + "pokemonEvolutions", "pokemonForm", "pokemonInfo", "pokemonInfoContainer", diff --git a/src/system/settings/settings.ts b/src/system/settings/settings.ts index 5f90b932377..5c598a0ea5a 100644 --- a/src/system/settings/settings.ts +++ b/src/system/settings/settings.ts @@ -166,7 +166,7 @@ export const SettingKeys = { Field_Volume: "FIELD_VOLUME", SE_Volume: "SE_VOLUME", UI_Volume: "UI_SOUND_EFFECTS", - Music_Preference: "MUSIC_PREFERENCE", + Battle_Music: "BATTLE_MUSIC", Show_BGM_Bar: "SHOW_BGM_BAR", Move_Touch_Controls: "MOVE_TOUCH_CONTROLS", Shop_Overlay_Opacity: "SHOP_OVERLAY_OPACITY" @@ -577,8 +577,8 @@ export const Setting: Array = [ label: i18next.t("settings:consistent") }, { - value: "Mixed Animated", - label: i18next.t("settings:mixedAnimated") + value: "Experimental", + label: i18next.t("settings:experimental") } ], default: 0, @@ -658,11 +658,11 @@ export const Setting: Array = [ type: SettingType.AUDIO }, { - key: SettingKeys.Music_Preference, - label: i18next.t("settings:musicPreference"), + key: SettingKeys.Battle_Music, + label: i18next.t("settings:battleMusic"), options: [ { - value: "Gen V + PMD", + value: "Gen V", label: i18next.t("settings:musicGenFive") }, { @@ -741,7 +741,7 @@ export function setSetting(setting: string, value: integer): boolean { case SettingKeys.UI_Volume: globalScene.uiVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; break; - case SettingKeys.Music_Preference: + case SettingKeys.Battle_Music: globalScene.musicPreference = value; break; case SettingKeys.Damage_Numbers: diff --git a/src/test/abilities/dancer.test.ts b/src/test/abilities/dancer.test.ts index 842b2196441..3a480316c96 100644 --- a/src/test/abilities/dancer.test.ts +++ b/src/test/abilities/dancer.test.ts @@ -7,7 +7,6 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Abilities - Dancer", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -24,20 +23,21 @@ describe("Abilities - Dancer", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override - .battleType("double") - .moveset([ Moves.SWORDS_DANCE, Moves.SPLASH ]) - .enemySpecies(Species.MAGIKARP) - .enemyAbility(Abilities.DANCER) - .enemyMoveset([ Moves.VICTORY_DANCE ]); + game.override.battleType("double"); }); // Reference Link: https://bulbapedia.bulbagarden.net/wiki/Dancer_(Ability) it("triggers when dance moves are used, doesn't consume extra PP", async () => { + game.override + .enemyAbility(Abilities.DANCER) + .enemySpecies(Species.MAGIKARP) + .enemyMoveset(Moves.VICTORY_DANCE); await game.classicMode.startBattle([ Species.ORICORIO, Species.FEEBAS ]); - const [ oricorio ] = game.scene.getPlayerField(); + const [ oricorio, feebas ] = game.scene.getPlayerField(); + game.move.changeMoveset(oricorio, [ Moves.SWORDS_DANCE, Moves.VICTORY_DANCE, Moves.SPLASH ]); + game.move.changeMoveset(feebas, [ Moves.SWORDS_DANCE, Moves.SPLASH ]); game.move.select(Moves.SPLASH); game.move.select(Moves.SWORDS_DANCE, 1); @@ -59,5 +59,44 @@ describe("Abilities - Dancer", () => { // doesn't use PP if copied move is also in moveset expect(oricorio.moveset[0]?.ppUsed).toBe(0); + expect(oricorio.moveset[1]?.ppUsed).toBe(0); + }); + + // TODO: Enable after Dancer rework to not push to move history + it.todo("should not count as the last move used for mirror move/instruct", async () => { + game.override + .moveset([ Moves.FIERY_DANCE, Moves.REVELATION_DANCE ]) + .enemyMoveset([ Moves.INSTRUCT, Moves.MIRROR_MOVE, Moves.SPLASH ]) + .enemySpecies(Species.SHUCKLE) + .enemyLevel(10); + await game.classicMode.startBattle([ Species.ORICORIO, Species.FEEBAS ]); + + const [ oricorio ] = game.scene.getPlayerField(); + const [ , shuckle2 ] = game.scene.getEnemyField(); + + game.move.select(Moves.REVELATION_DANCE, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2); + game.move.select(Moves.FIERY_DANCE, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2); + await game.forceEnemyMove(Moves.INSTRUCT, BattlerIndex.PLAYER); + await game.forceEnemyMove(Moves.MIRROR_MOVE, BattlerIndex.PLAYER); + 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"); // Feebas fiery dance + await game.phaseInterceptor.to("MovePhase"); // Oricorio fiery dance (from dancer) + await game.phaseInterceptor.to("MoveEndPhase", false); + // dancer copied move doesn't appear in move history + expect(oricorio.getLastXMoves(-1)[0].move).toBe(Moves.REVELATION_DANCE); + + await game.phaseInterceptor.to("MovePhase"); // shuckle 2 mirror moves oricorio + await game.phaseInterceptor.to("MovePhase"); // calls instructed rev dance + let currentPhase = game.scene.getCurrentPhase() as MovePhase; + expect(currentPhase.pokemon).toBe(shuckle2); + expect(currentPhase.move.moveId).toBe(Moves.REVELATION_DANCE); + + await game.phaseInterceptor.to("MovePhase"); // shuckle 1 instructs oricorio + await game.phaseInterceptor.to("MovePhase"); + currentPhase = game.scene.getCurrentPhase() as MovePhase; + expect(currentPhase.pokemon).toBe(oricorio); + expect(currentPhase.move.moveId).toBe(Moves.REVELATION_DANCE); + }); }); diff --git a/src/test/moves/instruct.test.ts b/src/test/moves/instruct.test.ts index 0e227ef6a3f..13f0c83c784 100644 --- a/src/test/moves/instruct.test.ts +++ b/src/test/moves/instruct.test.ts @@ -1,6 +1,7 @@ import { BattlerIndex } from "#app/battle"; import type Pokemon from "#app/field/pokemon"; import { MoveResult } from "#app/field/pokemon"; +import type { MovePhase } from "#app/phases/move-phase"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; @@ -12,10 +13,10 @@ describe("Moves - Instruct", () => { let phaserGame: Phaser.Game; let game: GameManager; - function instructSuccess(pokemon: Pokemon, move: Moves): void { - expect(pokemon.getLastXMoves(-1)[0].move).toBe(move); - expect(pokemon.getLastXMoves(-1)[1].move).toBe(pokemon.getLastXMoves()[0].move); - expect(pokemon.getMoveset().find(m => m?.moveId === move)?.ppUsed).toBe(2); + function instructSuccess(target: Pokemon, move: Moves): void { + expect(target.getLastXMoves(-1)[0].move).toBe(move); + expect(target.getLastXMoves(-1)[1].move).toBe(target.getLastXMoves()[0].move); + expect(target.getMoveset().find(m => m?.moveId === move)?.ppUsed).toBe(2); } beforeAll(() => { @@ -36,27 +37,40 @@ describe("Moves - Instruct", () => { .enemyAbility(Abilities.NO_GUARD) .enemyLevel(100) .startingLevel(100) - .ability(Abilities.BALL_FETCH) - .moveset([ Moves.INSTRUCT, Moves.SONIC_BOOM, Moves.SPLASH, Moves.TORMENT ]) .disableCrits(); }); - it("should repeat enemy's attack move when moving last", async () => { + it("should repeat target's last used move", async () => { + game.override + .moveset(Moves.INSTRUCT) + .enemyLevel(1000); // ensures shuckle no die await game.classicMode.startBattle([ Species.AMOONGUSS ]); const enemy = game.scene.getEnemyPokemon()!; game.move.changeMoveset(enemy, Moves.SONIC_BOOM); - game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER, BattlerIndex.ENEMY); - await game.forceEnemyMove(Moves.SONIC_BOOM, BattlerIndex.PLAYER); + game.move.select(Moves.INSTRUCT); + await game.forceEnemyMove(Moves.SONIC_BOOM); await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + + await game.phaseInterceptor.to("MovePhase"); // enemy attacks us + await game.phaseInterceptor.to("MovePhase", false); // instruct + let currentPhase = game.scene.getCurrentPhase() as MovePhase; + expect(currentPhase.pokemon).toBe(game.scene.getPlayerPokemon()); + await game.phaseInterceptor.to("MoveEndPhase"); + + await game.phaseInterceptor.to("MovePhase", false); // enemy repeats move + currentPhase = game.scene.getCurrentPhase() as MovePhase; + expect(currentPhase.pokemon).toBe(enemy); + expect(currentPhase.move.moveId).toBe(Moves.SONIC_BOOM); await game.phaseInterceptor.to("TurnEndPhase", false); - expect(game.scene.getPlayerPokemon()?.getInverseHp()).toBe(40); instructSuccess(enemy, Moves.SONIC_BOOM); + expect(game.scene.getPlayerPokemon()?.getInverseHp()).toBe(40); }); it("should repeat enemy's move through substitute", async () => { + game.override.moveset([ Moves.INSTRUCT, Moves.SPLASH ]); await game.classicMode.startBattle([ Species.AMOONGUSS ]); const enemy = game.scene.getEnemyPokemon()!; @@ -72,75 +86,94 @@ describe("Moves - Instruct", () => { await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnEndPhase", false); - expect(game.scene.getPlayerPokemon()?.getInverseHp()).toBe(40); instructSuccess(game.scene.getEnemyPokemon()!, Moves.SONIC_BOOM); + expect(game.scene.getPlayerPokemon()?.getInverseHp()).toBe(40); }); it("should repeat ally's attack on enemy", async () => { game.override .battleType("double") - .moveset([]); + .enemyMoveset(Moves.SPLASH); await game.classicMode.startBattle([ Species.AMOONGUSS, Species.SHUCKLE ]); const [ amoonguss, shuckle ] = game.scene.getPlayerField(); - game.move.changeMoveset(amoonguss, Moves.INSTRUCT); - game.move.changeMoveset(shuckle, Moves.SONIC_BOOM); + game.move.changeMoveset(amoonguss, [ Moves.INSTRUCT, Moves.SONIC_BOOM ]); + game.move.changeMoveset(shuckle, [ Moves.INSTRUCT, Moves.SONIC_BOOM ]); game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2); game.move.select(Moves.SONIC_BOOM, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY); - await game.forceEnemyMove(Moves.SPLASH); - await game.forceEnemyMove(Moves.SPLASH); await game.setTurnOrder([ BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("TurnEndPhase", false); - expect(game.scene.getEnemyField()[0].getInverseHp()).toBe(40); instructSuccess(shuckle, Moves.SONIC_BOOM); + expect(game.scene.getEnemyField()[0].getInverseHp()).toBe(40); }); - // TODO: Enable test case once gigaton hammer (and blood moon) is fixed + // TODO: Enable test case once gigaton hammer (and blood moon) are reworked it.todo("should repeat enemy's Gigaton Hammer", async () => { game.override + .moveset(Moves.INSTRUCT) .enemyLevel(5); await game.classicMode.startBattle([ Species.AMOONGUSS ]); const enemy = game.scene.getEnemyPokemon()!; - game.move.changeMoveset(enemy, Moves.GIGATON_HAMMER); + game.move.changeMoveset(enemy, [ Moves.GIGATON_HAMMER, Moves.BLOOD_MOON ]); game.move.select(Moves.INSTRUCT); await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); - await game.phaseInterceptor.to("TurnEndPhase", false); + await game.phaseInterceptor.to("BerryPhase"); instructSuccess(enemy, Moves.GIGATON_HAMMER); + expect(game.scene.getPlayerPokemon()!.turnData.attacksReceived.length).toBe(2); + }); + + it("should add moves to move queue for copycat", async () => { + game.override + .battleType("double") + .moveset(Moves.INSTRUCT) + .enemyLevel(5); + await game.classicMode.startBattle([ Species.AMOONGUSS ]); + + const [ enemy1, enemy2 ] = game.scene.getEnemyField()!; + game.move.changeMoveset(enemy1, Moves.WATER_GUN); + game.move.changeMoveset(enemy2, Moves.COPYCAT); + + game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER, BattlerIndex.ENEMY); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2 ]); + await game.phaseInterceptor.to("BerryPhase"); + + instructSuccess(enemy1, Moves.WATER_GUN); + // amoonguss gets hit by water gun thrice; once by original attack, once by instructed use and once by copycat + expect(game.scene.getPlayerPokemon()!.turnData.attacksReceived.length).toBe(3); }); it("should respect enemy's status condition", async () => { game.override - .moveset([ Moves.THUNDER_WAVE, Moves.INSTRUCT ]) - .enemyMoveset([ Moves.SPLASH, Moves.SONIC_BOOM ]); + .moveset([ Moves.INSTRUCT, Moves.THUNDER_WAVE ]) + .enemyMoveset(Moves.SONIC_BOOM); await game.classicMode.startBattle([ Species.AMOONGUSS ]); game.move.select(Moves.THUNDER_WAVE); - await game.forceEnemyMove(Moves.SONIC_BOOM); await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); game.move.select(Moves.INSTRUCT); - await game.forceEnemyMove(Moves.SPLASH); - await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); - await game.move.forceStatusActivation(true); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MovePhase"); + // force enemy's instructed move to bork and then immediately thaw out + await game.move.forceStatusActivation(true); await game.move.forceStatusActivation(false); await game.phaseInterceptor.to("TurnEndPhase", false); - const moveHistory = game.scene.getEnemyPokemon()!.getMoveHistory(); - expect(moveHistory.length).toBe(3); - expect(moveHistory[0].move).toBe(Moves.SONIC_BOOM); - expect(moveHistory[1].move).toBe(Moves.NONE); - expect(moveHistory[2].move).toBe(Moves.SONIC_BOOM); + const moveHistory = game.scene.getEnemyPokemon()?.getLastXMoves(-1)!; + expect(moveHistory.map(m => m.move)).toEqual([ Moves.SONIC_BOOM, Moves.NONE, Moves.SONIC_BOOM ]); + expect(game.scene.getPlayerPokemon()?.getInverseHp()).toBe(40); }); it("should not repeat enemy's out of pp move", async () => { - game.override.enemySpecies(Species.UNOWN); + game.override + .moveset(Moves.INSTRUCT) + .enemySpecies(Species.UNOWN); await game.classicMode.startBattle([ Species.AMOONGUSS ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -153,13 +186,85 @@ describe("Moves - Instruct", () => { await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnEndPhase", false); - const playerMove = game.scene.getPlayerPokemon()!.getLastXMoves()!; - expect(playerMove[0].result).toBe(MoveResult.FAIL); + const playerMoves = game.scene.getPlayerPokemon()!.getLastXMoves(-1)!; + expect(playerMoves[0].result).toBe(MoveResult.FAIL); expect(enemyPokemon.getMoveHistory().length).toBe(1); }); + it("should redirect attacking moves if enemy faints", async () => { + game.override + .battleType("double") + .enemyMoveset(Moves.SPLASH) + .enemySpecies(Species.MAGIKARP) + .enemyLevel(1); + await game.classicMode.startBattle([ Species.HISUI_ELECTRODE, Species.KOMMO_O ]); + + const [ electrode, kommo_o ] = game.scene.getPlayerField()!; + game.move.changeMoveset(electrode, Moves.CHLOROBLAST); + game.move.changeMoveset(kommo_o, Moves.INSTRUCT); + + game.move.select(Moves.CHLOROBLAST, BattlerIndex.PLAYER, BattlerIndex.ENEMY); + game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + await game.phaseInterceptor.to("BerryPhase"); + + // Chloroblast always deals 50% max HP% recoil UNLESS you whiff + // due to lack of targets or similar, + // so all we have to do is check whether electrode fainted or not. + // Naturally, both karps should also be dead as well. + expect(electrode.isFainted()).toBe(true); + const [ karp1, karp2 ] = game.scene.getEnemyField()!; + expect(karp1.isFainted()).toBe(true); + expect(karp2.isFainted()).toBe(true); + }), + + it("should allow for dancer copying of instructed dance move", async () => { + game.override + .battleType("double") + .enemyMoveset([ Moves.INSTRUCT, Moves.SPLASH ]); + await game.classicMode.startBattle([ Species.ORICORIO, Species.VOLCARONA ]); + + const [ oricorio, volcarona ] = game.scene.getPlayerField(); + game.move.changeMoveset(oricorio, Moves.SPLASH); + game.move.changeMoveset(volcarona, Moves.FIERY_DANCE); + + game.move.select(Moves.SPLASH, BattlerIndex.PLAYER); + game.move.select(Moves.FIERY_DANCE, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY); + await game.forceEnemyMove(Moves.INSTRUCT, BattlerIndex.PLAYER_2); + await game.forceEnemyMove(Moves.SPLASH); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + await game.phaseInterceptor.to("BerryPhase"); + + // fiery dance triggered dancer successfully for a total of 4 hits + // Volcarona fiery dance has a _small_ chance to 3HKO a shuckle in worst case, so we add the hit count of both + // foes to account for spillover + instructSuccess(volcarona, Moves.FIERY_DANCE); + expect(game.scene.getEnemyField()[0].turnData.attacksReceived.length + + game.scene.getEnemyField()[1].turnData.attacksReceived.length).toBe(4); + }); + + it("should not repeat move when switching out", async () => { + game.override + .enemyMoveset(Moves.INSTRUCT) + .enemySpecies(Species.UNOWN); + await game.classicMode.startBattle([ Species.AMOONGUSS, Species.TOXICROAK ]); + + const amoonguss = game.scene.getPlayerPokemon()!; + game.move.changeMoveset(amoonguss, Moves.SEED_BOMB); + + amoonguss.battleSummonData.moveHistory = [{ move: Moves.SEED_BOMB, targets: [ BattlerIndex.ENEMY ], result: MoveResult.SUCCESS }]; + + game.doSwitchPokemon(1); + await game.phaseInterceptor.to("TurnEndPhase", false); + + const enemyMoves = game.scene.getEnemyPokemon()!.getLastXMoves(-1)!; + expect(enemyMoves[0].result).toBe(MoveResult.FAIL); + }); + it("should fail if no move has yet been used by target", async () => { - game.override.enemyMoveset(Moves.SPLASH); + game.override + .moveset(Moves.INSTRUCT) + .enemyMoveset(Moves.SPLASH); await game.classicMode.startBattle([ Species.AMOONGUSS ]); game.move.select(Moves.INSTRUCT); @@ -183,48 +288,46 @@ describe("Moves - Instruct", () => { game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER, BattlerIndex.ENEMY); game.move.select(Moves.DISABLE, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY); await game.forceEnemyMove(Moves.SONIC_BOOM, BattlerIndex.PLAYER); - await game.forceEnemyMove(Moves.SPLASH); await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("TurnEndPhase", false); expect(game.scene.getPlayerField()[0].getLastXMoves()[0].result).toBe(MoveResult.SUCCESS); - const enemyMove = game.scene.getEnemyPokemon()!.getLastXMoves()[0]; + const enemyMove = game.scene.getEnemyField()[0]!.getLastXMoves()[0]; expect(enemyMove.result).toBe(MoveResult.FAIL); - expect(game.scene.getEnemyPokemon()!.getMoveset().find(m => m?.moveId === Moves.SONIC_BOOM)?.ppUsed).toBe(1); - + expect(game.scene.getEnemyField()[0].getMoveset().find(m => m?.moveId === Moves.SONIC_BOOM)?.ppUsed).toBe(1); }); it("should not repeat enemy's move through protect", async () => { + game.override.moveset([ Moves.INSTRUCT ]); await game.classicMode.startBattle([ Species.AMOONGUSS ]); - const MoveToUse = Moves.PROTECT; - const enemyPokemon = game.scene.getEnemyPokemon()!; - game.move.changeMoveset(enemyPokemon, MoveToUse); + const enemy = game.scene.getEnemyPokemon()!; + game.move.changeMoveset(enemy, Moves.PROTECT); game.move.select(Moves.INSTRUCT); - await game.forceEnemyMove(Moves.PROTECT); await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnEndPhase", false); - expect(enemyPokemon.getLastXMoves(-1)[0].move).toBe(Moves.PROTECT); - expect(enemyPokemon.getLastXMoves(-1)[1]).toBeUndefined(); // undefined because protect failed - expect(enemyPokemon.getMoveset().find(m => m?.moveId === Moves.PROTECT)?.ppUsed).toBe(1); + expect(enemy.getLastXMoves(-1)[0].move).toBe(Moves.PROTECT); + expect(enemy.getLastXMoves(-1)[1]).toBeUndefined(); // undefined because instruct failed and didn't repeat + expect(enemy.getMoveset().find(m => m?.moveId === Moves.PROTECT)?.ppUsed).toBe(1); }); it("should not repeat enemy's charging move", async () => { game.override - .enemyMoveset([ Moves.SONIC_BOOM, Moves.HYPER_BEAM ]) - .enemyLevel(5); + .moveset([ Moves.INSTRUCT ]) + .enemyMoveset([ Moves.SONIC_BOOM, Moves.HYPER_BEAM ]); await game.classicMode.startBattle([ Species.SHUCKLE ]); const player = game.scene.getPlayerPokemon()!; - const enemyPokemon = game.scene.getEnemyPokemon()!; - enemyPokemon.battleSummonData.moveHistory = [{ move: Moves.SONIC_BOOM, targets: [ BattlerIndex.PLAYER ], result: MoveResult.SUCCESS, virtual: false }]; + const enemy = game.scene.getEnemyPokemon()!; + enemy.battleSummonData.moveHistory = [{ move: Moves.SONIC_BOOM, targets: [ BattlerIndex.PLAYER ], result: MoveResult.SUCCESS, virtual: false }]; game.move.select(Moves.INSTRUCT); await game.forceEnemyMove(Moves.HYPER_BEAM); await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); + // instruct fails at copying last move due to charging turn (rather than instructing sonic boom) expect(player.getLastXMoves()[0].result).toBe(MoveResult.FAIL); game.move.select(Moves.INSTRUCT); @@ -234,31 +337,162 @@ describe("Moves - Instruct", () => { expect(player.getLastXMoves()[0].result).toBe(MoveResult.FAIL); }); - it("should not repeat dance move not known by target", async () => { + it("should not repeat move since forgotten by target", async () => { game.override - .battleType("double") - .moveset([ Moves.INSTRUCT, Moves.FIERY_DANCE ]) - .enemyMoveset(Moves.SPLASH) - .enemyAbility(Abilities.DANCER); - await game.classicMode.startBattle([ Species.SHUCKLE, Species.SHUCKLE ]); + .enemyLevel(5) + .xpMultiplier(0) + .enemySpecies(Species.WURMPLE) + .enemyMoveset(Moves.INSTRUCT); + await game.classicMode.startBattle([ Species.REGIELEKI ]); - game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER, BattlerIndex.ENEMY); - game.move.select(Moves.FIERY_DANCE, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY); + const regieleki = game.scene.getPlayerPokemon()!; + // fill out moveset with random moves + game.move.changeMoveset(regieleki, [ Moves.ELECTRO_DRIFT, Moves.SPLASH, Moves.ICE_BEAM, Moves.ANCIENT_POWER ]); + + game.move.select(Moves.ELECTRO_DRIFT); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + await game.phaseInterceptor.to("FaintPhase"); + await game.move.learnMove(Moves.ELECTROWEB); + await game.toNextWave(); + + game.move.select(Moves.SPLASH); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.phaseInterceptor.to("TurnEndPhase", false); + expect(game.scene.getEnemyField()[0].getLastXMoves()[0].result).toBe(MoveResult.FAIL); + }); + + it("should disregard priority of instructed move on use", async () => { + game.override + .enemyMoveset([ Moves.SPLASH, Moves.WHIRLWIND ]) + .moveset(Moves.INSTRUCT); + await game.classicMode.startBattle([ Species.LUCARIO, Species.BANETTE ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + enemyPokemon.battleSummonData.moveHistory = [{ move: Moves.WHIRLWIND, targets: [ BattlerIndex.PLAYER ], result: MoveResult.SUCCESS, virtual: false }]; + + game.move.select(Moves.INSTRUCT); await game.forceEnemyMove(Moves.SPLASH); + await game.phaseInterceptor.to("TurnEndPhase", false); + + // lucario instructed enemy whirlwind at 0 priority to switch itself out + const instructedMove = enemyPokemon.getLastXMoves(-1)[1]; + expect(instructedMove.result).toBe(MoveResult.SUCCESS); + expect(instructedMove.move).toBe(Moves.WHIRLWIND); + expect(game.scene.getPlayerPokemon()?.species.speciesId).toBe(Species.BANETTE); + }); + + it("should respect moves' original priority for psychic terrain", async () => { + game.override. + battleType("double") + .moveset([ Moves.QUICK_ATTACK, Moves.SPLASH, Moves.INSTRUCT ]) + .enemyMoveset([ Moves.SPLASH, Moves.PSYCHIC_TERRAIN ]); + await game.classicMode.startBattle([ Species.BANETTE, Species.KLEFKI ]); + + game.move.select(Moves.QUICK_ATTACK, BattlerIndex.PLAYER, BattlerIndex.ENEMY); // succeeds due to terrain no + game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2); await game.forceEnemyMove(Moves.SPLASH); + await game.forceEnemyMove(Moves.PSYCHIC_TERRAIN); + await game.toNextTurn(); + + game.move.select(Moves.SPLASH, BattlerIndex.PLAYER); + game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER); await game.setTurnOrder([ BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("TurnEndPhase", false); - expect(game.scene.getPlayerField()[0].getLastXMoves()[0].result).toBe(MoveResult.FAIL); + // quick attack failed when instructed + const banette = game.scene.getPlayerPokemon()!; + expect(banette.getLastXMoves(-1)[1].move).toBe(Moves.QUICK_ATTACK); + expect(banette.getLastXMoves(-1)[1].result).toBe(MoveResult.FAIL); + }); + + it("should still work w/ prankster in psychic terrain", async () => { + game.override. + battleType("double") + .enemyMoveset([ Moves.SPLASH, Moves.PSYCHIC_TERRAIN ]); + await game.classicMode.startBattle([ Species.BANETTE, Species.KLEFKI ]); + + const [ banette, klefki ] = game.scene.getPlayerField()!; + game.move.changeMoveset(banette, [ Moves.VINE_WHIP, Moves.SPLASH ]); + game.move.changeMoveset(klefki, [ Moves.INSTRUCT, Moves.SPLASH ]); + + game.move.select(Moves.VINE_WHIP, BattlerIndex.PLAYER, BattlerIndex.ENEMY); + game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2); + await game.forceEnemyMove(Moves.SPLASH); + await game.forceEnemyMove(Moves.PSYCHIC_TERRAIN); + await game.toNextTurn(); + + game.move.select(Moves.SPLASH, BattlerIndex.PLAYER); + game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER); // copies vine whip + await game.setTurnOrder([ BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + await game.phaseInterceptor.to("TurnEndPhase", false); + expect(banette.getLastXMoves(-1)[1].move).toBe(Moves.VINE_WHIP); + expect(banette.getLastXMoves(-1)[2].move).toBe(Moves.VINE_WHIP); + expect(banette.getMoveset().find(m => m?.moveId === Moves.VINE_WHIP )?.ppUsed).toBe(2); + }); + + it("should cause spread moves to correctly hit targets in doubles after singles", async () => { + game.override + .battleType("even-doubles") + .moveset([ Moves.BREAKING_SWIPE, Moves.INSTRUCT, Moves.SPLASH ]) + .enemyMoveset(Moves.SONIC_BOOM) + .enemySpecies(Species.AXEW) + .startingLevel(500); + await game.classicMode.startBattle([ Species.KORAIDON, Species.KLEFKI ]); + + const koraidon = game.scene.getPlayerField()[0]!; + + game.move.select(Moves.BREAKING_SWIPE); + await game.phaseInterceptor.to("TurnEndPhase", false); + expect(koraidon.getInverseHp()).toBe(0); + expect(koraidon.getLastXMoves(-1)[0].targets).toEqual([ BattlerIndex.ENEMY ]); + await game.toNextWave(); + + game.move.select(Moves.SPLASH, BattlerIndex.PLAYER); + game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER); + await game.setTurnOrder([ BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + await game.phaseInterceptor.to("TurnEndPhase", false); + // did not take damage since enemies died beforehand; + // last move used hit both enemies + expect(koraidon.getInverseHp()).toBe(0); + expect(koraidon.getLastXMoves(-1)[1].targets?.sort()).toEqual([ BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + }); + + it("should cause AoE moves to correctly hit everyone in doubles after singles", async () => { + game.override + .battleType("even-doubles") + .moveset([ Moves.BRUTAL_SWING, Moves.INSTRUCT, Moves.SPLASH ]) + .enemySpecies(Species.AXEW) + .enemyMoveset(Moves.SONIC_BOOM) + .startingLevel(500); + await game.classicMode.startBattle([ Species.KORAIDON, Species.KLEFKI ]); + + const koraidon = game.scene.getPlayerField()[0]!; + + game.move.select(Moves.BRUTAL_SWING); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + await game.phaseInterceptor.to("TurnEndPhase", false); + expect(koraidon.getInverseHp()).toBe(0); + expect(koraidon.getLastXMoves(-1)[0].targets).toEqual([ BattlerIndex.ENEMY ]); + await game.toNextWave(); + + game.move.select(Moves.SPLASH, BattlerIndex.PLAYER); + game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER); + await game.setTurnOrder([ BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + await game.phaseInterceptor.to("TurnEndPhase", false); + // did not take damage since enemies died beforehand; + // last move used hit everything around it + expect(koraidon.getInverseHp()).toBe(0); + expect(koraidon.getLastXMoves(-1)[1].targets?.sort()).toEqual([ BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); }); it("should cause multi-hit moves to hit the appropriate number of times in singles", async () => { game.override .enemyAbility(Abilities.SKILL_LINK) + .moveset([ Moves.SPLASH, Moves.INSTRUCT ]) .enemyMoveset(Moves.BULLET_SEED); await game.classicMode.startBattle([ Species.BULBASAUR ]); - const player = game.scene.getPlayerPokemon()!; + const bulbasaur = game.scene.getPlayerPokemon()!; game.move.select(Moves.SPLASH); await game.toNextTurn(); @@ -267,34 +501,35 @@ describe("Moves - Instruct", () => { await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("BerryPhase"); - expect(player.turnData.attacksReceived.length).toBe(10); + expect(bulbasaur.turnData.attacksReceived.length).toBe(10); await game.toNextTurn(); game.move.select(Moves.INSTRUCT); await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("BerryPhase"); - expect(player.turnData.attacksReceived.length).toBe(10); + expect(bulbasaur.turnData.attacksReceived.length).toBe(10); }); it("should cause multi-hit moves to hit the appropriate number of times in doubles", async () => { game.override .battleType("double") .enemyAbility(Abilities.SKILL_LINK) + .moveset([ Moves.SPLASH, Moves.INSTRUCT ]) .enemyMoveset([ Moves.BULLET_SEED, Moves.SPLASH ]) .enemyLevel(5); await game.classicMode.startBattle([ Species.BULBASAUR, Species.IVYSAUR ]); const [ , ivysaur ] = game.scene.getPlayerField(); - game.move.select(Moves.SPLASH); - game.move.select(Moves.SPLASH, 1); + game.move.select(Moves.SPLASH, BattlerIndex.PLAYER); + game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2); await game.forceEnemyMove(Moves.BULLET_SEED, BattlerIndex.PLAYER_2); await game.forceEnemyMove(Moves.SPLASH); await game.toNextTurn(); - game.move.select(Moves.INSTRUCT, 0, BattlerIndex.ENEMY); - game.move.select(Moves.INSTRUCT, 1, BattlerIndex.ENEMY); + game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER, BattlerIndex.ENEMY); + game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY); await game.forceEnemyMove(Moves.BULLET_SEED, BattlerIndex.PLAYER_2); await game.forceEnemyMove(Moves.SPLASH); await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); @@ -303,8 +538,8 @@ describe("Moves - Instruct", () => { expect(ivysaur.turnData.attacksReceived.length).toBe(15); await game.toNextTurn(); - game.move.select(Moves.INSTRUCT, 0, BattlerIndex.ENEMY); - game.move.select(Moves.INSTRUCT, 1, BattlerIndex.ENEMY); + game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER, BattlerIndex.ENEMY); + game.move.select(Moves.INSTRUCT, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY); await game.forceEnemyMove(Moves.BULLET_SEED, BattlerIndex.PLAYER_2); await game.forceEnemyMove(Moves.SPLASH); await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2 ]); diff --git a/src/test/phases/learn-move-phase.test.ts b/src/test/phases/learn-move-phase.test.ts index c4fa0e8bf45..3a3d111f551 100644 --- a/src/test/phases/learn-move-phase.test.ts +++ b/src/test/phases/learn-move-phase.test.ts @@ -4,6 +4,8 @@ import GameManager from "#test/utils/gameManager"; import { Species } from "#enums/species"; import { Moves } from "#enums/moves"; import { LearnMovePhase } from "#app/phases/learn-move-phase"; +import { Mode } from "#app/ui/ui"; +import { Button } from "#app/enums/buttons"; describe("Learn Move Phase", () => { let phaserGame: Phaser.Game; @@ -26,7 +28,7 @@ describe("Learn Move Phase", () => { it("If Pokemon has less than 4 moves, its newest move will be added to the lowest empty index", async () => { game.override.moveset([ Moves.SPLASH ]); - await game.startBattle([ Species.BULBASAUR ]); + await game.classicMode.startBattle([ Species.BULBASAUR ]); const pokemon = game.scene.getPlayerPokemon()!; const newMovePos = pokemon?.getMoveset().length; game.move.select(Moves.SPLASH); @@ -36,12 +38,113 @@ describe("Learn Move Phase", () => { const levelReq = levelMove[0]; const levelMoveId = levelMove[1]; expect(pokemon.level).toBeGreaterThanOrEqual(levelReq); - expect(pokemon?.getMoveset()[newMovePos]?.moveId).toBe(levelMoveId); + expect(pokemon?.moveset[newMovePos]?.moveId).toBe(levelMoveId); + }); + + it("If a pokemon has 4 move slots filled, the chosen move will be deleted and replaced", async () => { + await game.classicMode.startBattle([ Species.BULBASAUR ]); + const bulbasaur = game.scene.getPlayerPokemon()!; + const prevMoveset = [ Moves.SPLASH, Moves.ABSORB, Moves.ACID, Moves.VINE_WHIP ]; + const moveSlotNum = 3; + + game.move.changeMoveset(bulbasaur, prevMoveset); + game.move.select(Moves.SPLASH); + await game.doKillOpponents(); + + // queue up inputs to confirm dialog boxes + game.onNextPrompt("LearnMovePhase", Mode.CONFIRM, () => { + game.scene.ui.processInput(Button.ACTION); + }); + game.onNextPrompt("LearnMovePhase", Mode.SUMMARY, () => { + for (let x = 0; x < moveSlotNum; x++) { + game.scene.ui.processInput(Button.DOWN); + } + game.scene.ui.processInput(Button.ACTION); + }); + await game.phaseInterceptor.to(LearnMovePhase); + + const levelMove = bulbasaur.getLevelMoves(5)[0]; + const levelReq = levelMove[0]; + const levelMoveId = levelMove[1]; + expect(bulbasaur.level).toBeGreaterThanOrEqual(levelReq); + // Check each of mr mime's moveslots to make sure the changed move (and ONLY the changed move) is different + bulbasaur.getMoveset().forEach((move, index) => { + const expectedMove: Moves = (index === moveSlotNum ? levelMoveId : prevMoveset[index]); + expect(move?.moveId).toBe(expectedMove); + }); + }); + + it("selecting the newly deleted move will reject it and keep old moveset", async () => { + await game.classicMode.startBattle([ Species.BULBASAUR ]); + const bulbasaur = game.scene.getPlayerPokemon()!; + const prevMoveset = [ Moves.SPLASH, Moves.ABSORB, Moves.ACID, Moves.VINE_WHIP ]; + + game.move.changeMoveset(bulbasaur, [ Moves.SPLASH, Moves.ABSORB, Moves.ACID, Moves.VINE_WHIP ]); + game.move.select(Moves.SPLASH); + await game.doKillOpponents(); + + // queue up inputs to confirm dialog boxes + game.onNextPrompt("LearnMovePhase", Mode.CONFIRM, () => { + game.scene.ui.processInput(Button.ACTION); + }); + game.onNextPrompt("LearnMovePhase", Mode.SUMMARY, () => { + for (let x = 0; x < 4; x++) { + game.scene.ui.processInput(Button.DOWN); // moves down 4 times to the 5th move slot + } + game.scene.ui.processInput(Button.ACTION); + }); + game.onNextPrompt("LearnMovePhase", Mode.CONFIRM, () => { + game.scene.ui.processInput(Button.ACTION); + }); + await game.phaseInterceptor.to(LearnMovePhase); + + const levelReq = bulbasaur.getLevelMoves(5)[0][0]; + expect(bulbasaur.level).toBeGreaterThanOrEqual(levelReq); + expect(bulbasaur.getMoveset().map(m => m?.moveId)).toEqual(prevMoveset); + }); + + it("macro should add moves in free slots normally", async () => { + await game.classicMode.startBattle([ Species.BULBASAUR ]); + const bulbasaur = game.scene.getPlayerPokemon()!; + + game.move.changeMoveset(bulbasaur, [ Moves.SPLASH, Moves.ABSORB, Moves.ACID ]); + game.move.select(Moves.SPLASH); + await game.move.learnMove(Moves.SACRED_FIRE, 0, 1); + expect(bulbasaur.getMoveset().map(m => m?.moveId)).toEqual([ Moves.SPLASH, Moves.ABSORB, Moves.ACID, Moves.SACRED_FIRE ]); + + }); + + it("macro should replace moves", async () => { + await game.classicMode.startBattle([ Species.BULBASAUR ]); + const bulbasaur = game.scene.getPlayerPokemon()!; + + game.move.changeMoveset(bulbasaur, [ Moves.SPLASH, Moves.ABSORB, Moves.ACID, Moves.VINE_WHIP ]); + game.move.select(Moves.SPLASH); + await game.move.learnMove(Moves.SACRED_FIRE, 0, 1); + expect(bulbasaur.getMoveset().map(m => m?.moveId)).toEqual([ Moves.SPLASH, Moves.SACRED_FIRE, Moves.ACID, Moves.VINE_WHIP ]); + + }); + + it("macro should allow for cancelling move learning", async () => { + await game.classicMode.startBattle([ Species.BULBASAUR ]); + const bulbasaur = game.scene.getPlayerPokemon()!; + + game.move.changeMoveset(bulbasaur, [ Moves.SPLASH, Moves.ABSORB, Moves.ACID, Moves.VINE_WHIP ]); + game.move.select(Moves.SPLASH); + await game.move.learnMove(Moves.SACRED_FIRE, 0, 4); + expect(bulbasaur.getMoveset().map(m => m?.moveId)).toEqual([ Moves.SPLASH, Moves.ABSORB, Moves.ACID, Moves.VINE_WHIP ]); + + }); + + it("macro works on off-field party members", async () => { + await game.classicMode.startBattle([ Species.BULBASAUR, Species.SQUIRTLE ]); + const squirtle = game.scene.getPlayerParty()[1]!; + + game.move.changeMoveset(squirtle, [ Moves.SPLASH, Moves.WATER_GUN, Moves.FREEZE_DRY, Moves.GROWL ]); + game.move.select(Moves.TACKLE); + await game.move.learnMove(Moves.SHELL_SMASH, 1, 0); + expect(squirtle.getMoveset().map(m => m?.moveId)).toEqual([ Moves.SHELL_SMASH, Moves.WATER_GUN, Moves.FREEZE_DRY, Moves.GROWL ]); + }); - /** - * Future Tests: - * If a Pokemon has four moves, the user can specify an old move to be forgotten and a new move will take its place. - * If a Pokemon has four moves, the user can reject the new move, keeping the moveset the same. - */ }); diff --git a/src/test/ui/starter-select.test.ts b/src/test/ui/starter-select.test.ts index f80990f6dc3..15b5f643539 100644 --- a/src/test/ui/starter-select.test.ts +++ b/src/test/ui/starter-select.test.ts @@ -362,8 +362,9 @@ describe("UI - Starter select", () => { const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; handler.processInput(Button.RIGHT); handler.processInput(Button.LEFT); - handler.processInput(Button.V); - handler.processInput(Button.V); + handler.processInput(Button.CYCLE_SHINY); + handler.processInput(Button.CYCLE_SHINY); + handler.processInput(Button.CYCLE_SHINY); handler.processInput(Button.ACTION); game.phaseInterceptor.unlock(); }); @@ -423,7 +424,8 @@ describe("UI - Starter select", () => { const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; handler.processInput(Button.RIGHT); handler.processInput(Button.LEFT); - handler.processInput(Button.V); + handler.processInput(Button.CYCLE_SHINY); + handler.processInput(Button.CYCLE_SHINY); handler.processInput(Button.ACTION); game.phaseInterceptor.unlock(); }); diff --git a/src/test/utils/gameManager.ts b/src/test/utils/gameManager.ts index 9fda3afa56e..8e595212898 100644 --- a/src/test/utils/gameManager.ts +++ b/src/test/utils/gameManager.ts @@ -129,9 +129,10 @@ export default class GameManager { /** * Adds an action to be executed on the next prompt. + * This can be used to (among other things) simulate inputs or run functions mid-phase. * @param phaseTarget - The target phase. * @param mode - The mode to wait for. - * @param callback - The callback to execute. + * @param callback - The callback function to execute on next prompt. * @param expireFn - Optional function to determine if the prompt has expired. */ onNextPrompt(phaseTarget: string, mode: Mode, callback: () => void, expireFn?: () => void, awaitingActionInput: boolean = false) { @@ -400,6 +401,11 @@ export default class GameManager { return updateUserInfo(); } + /** + * Faints a player or enemy pokemon instantly by setting their HP to 0. + * @param pokemon The player/enemy pokemon being fainted + * @returns A promise that resolves once the fainted pokemon's FaintPhase finishes running. + */ async killPokemon(pokemon: PlayerPokemon | EnemyPokemon) { return new Promise(async (resolve, reject) => { pokemon.hp = 0; @@ -453,8 +459,9 @@ export default class GameManager { } /** - * Intercepts `TurnStartPhase` and mocks the getSpeedOrder's return value {@linkcode TurnStartPhase.getSpeedOrder} - * Used to modify the turn order. + * Intercepts `TurnStartPhase` and mocks {@linkcode TurnStartPhase.getSpeedOrder}'s return value. + * Used to manually modify Pokemon turn order. + * Note: This *DOES NOT* account for priority, only speed. * @param {BattlerIndex[]} order The turn order to set * @example * ```ts @@ -468,7 +475,7 @@ export default class GameManager { } /** - * Removes all held items from enemy pokemon + * Removes all held items from enemy pokemon. */ removeEnemyHeldItems(): void { this.scene.clearEnemyHeldItemModifiers(); diff --git a/src/test/utils/helpers/moveHelper.ts b/src/test/utils/helpers/moveHelper.ts index 4b2069ee881..ad39755b556 100644 --- a/src/test/utils/helpers/moveHelper.ts +++ b/src/test/utils/helpers/moveHelper.ts @@ -1,8 +1,10 @@ import type { BattlerIndex } from "#app/battle"; +import { Button } from "#app/enums/buttons"; import type Pokemon from "#app/field/pokemon"; import { PokemonMove } from "#app/field/pokemon"; import Overrides from "#app/overrides"; import type { CommandPhase } from "#app/phases/command-phase"; +import { LearnMovePhase } from "#app/phases/learn-move-phase"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { Command } from "#app/ui/command-ui-handler"; import { Mode } from "#app/ui/ui"; @@ -75,9 +77,10 @@ export class MoveHelper extends GameManagerHelper { } /** - * Used when the normal moveset override can't be used (such as when it's necessary to check updated properties of the moveset). - * @param pokemon - The pokemon being modified - * @param moveset - The moveset to use + * Changes a pokemon's moveset to the given move(s). + * Used when the normal moveset override can't be used (such as when it's necessary to check or update properties of the moveset). + * @param pokemon - The {@linkcode Pokemon} being modified + * @param moveset - The {@linkcode Moves} (single or array) to change the Pokemon's moveset to */ public changeMoveset(pokemon: Pokemon, moveset: Moves | Moves[]): void { if (!Array.isArray(moveset)) { @@ -90,4 +93,40 @@ export class MoveHelper extends GameManagerHelper { const movesetStr = moveset.map((moveId) => Moves[moveId]).join(", "); console.log(`Pokemon ${pokemon.species.name}'s moveset manually set to ${movesetStr} (=[${moveset.join(", ")}])!`); } + + /** + * Simulates learning a move for a player pokemon. + * @param move The {@linkcode Moves} being learnt + * @param partyIndex The party position of the {@linkcode PlayerPokemon} learning the move (defaults to 0) + * @param moveSlotIndex The INDEX (0-4) of the move slot to replace if existent move slots are full; + * defaults to 0 (first slot) and 4 aborts the procedure + * @returns a promise that resolves once the move has been successfully learnt + */ + public async learnMove(move: Moves | integer, partyIndex: integer = 0, moveSlotIndex: integer = 0) { + return new Promise(async (resolve, reject) => { + this.game.scene.pushPhase(new LearnMovePhase(partyIndex, move)); + + // if slots are full, queue up inputs to replace existing moves + if (this.game.scene.getPlayerParty()[partyIndex].moveset.filter(m => m).length === 4) { + this.game.onNextPrompt("LearnMovePhase", Mode.CONFIRM, () => { + this.game.scene.ui.processInput(Button.ACTION); // "Should a move be forgotten and replaced with XXX?" + }); + this.game.onNextPrompt("LearnMovePhase", Mode.SUMMARY, () => { + for (let x = 0; x < (moveSlotIndex ?? 0); x++) { + this.game.scene.ui.processInput(Button.DOWN); // Scrolling in summary pane to move position + } + this.game.scene.ui.processInput(Button.ACTION); + if (moveSlotIndex === 4) { + this.game.onNextPrompt("LearnMovePhase", Mode.CONFIRM, () => { + this.game.scene.ui.processInput(Button.ACTION); // "Give up on learning XXX?" + }); + } + }); + } + + await this.game.phaseInterceptor.to(LearnMovePhase).catch(e => reject(e)); + resolve(); + }); + } + } diff --git a/src/test/utils/helpers/overridesHelper.ts b/src/test/utils/helpers/overridesHelper.ts index 9af811561b7..822c42163b1 100644 --- a/src/test/utils/helpers/overridesHelper.ts +++ b/src/test/utils/helpers/overridesHelper.ts @@ -71,6 +71,26 @@ export class OverridesHelper extends GameManagerHelper { return this; } + /** + * Override the wave level cap + * @param cap the level cap value to set; 0 uses normal level caps and negative values + * disable it completely + * @returns `this` + */ + public levelCap(cap: number): this { + vi.spyOn(Overrides, "LEVEL_CAP_OVERRIDE", "get").mockReturnValue(cap); + let capStr: string; + if (cap > 0) { + capStr = `Level cap set to ${cap}!`; + } else if (cap < 0) { + capStr = "Level cap disabled!"; + } else { + capStr = "Level cap reset to default value for wave."; + } + this.log(capStr); + return this; + } + /** * Override the player (pokemon) starting held items * @param items the items to hold @@ -140,7 +160,7 @@ export class OverridesHelper extends GameManagerHelper { } /** - * Override the player (pokemon) {@linkcode Abilities | ability} + * Override the player (pokemon) {@linkcode Abilities | ability}. * @param ability the (pokemon) {@linkcode Abilities | ability} to set * @returns `this` */ diff --git a/src/test/utils/mocks/mockTimedEventManager.ts b/src/test/utils/mocks/mockTimedEventManager.ts index b44729996a7..10f32fd4c8b 100644 --- a/src/test/utils/mocks/mockTimedEventManager.ts +++ b/src/test/utils/mocks/mockTimedEventManager.ts @@ -1,3 +1,4 @@ +import { CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER } from "#app/data/balance/starters"; import { TimedEventManager } from "#app/timed-event-manager"; /** Mock TimedEventManager so that ongoing events don't impact tests */ @@ -8,8 +9,8 @@ export class MockTimedEventManager extends TimedEventManager { override isEventActive(): boolean { return false; } - override getFriendshipMultiplier(): number { - return 1; + override getClassicFriendshipMultiplier(): number { + return CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER; } override getShinyMultiplier(): number { return 1; diff --git a/src/timed-event-manager.ts b/src/timed-event-manager.ts index 216900e8f58..7a9f0e59993 100644 --- a/src/timed-event-manager.ts +++ b/src/timed-event-manager.ts @@ -1,14 +1,19 @@ import { globalScene } from "#app/global-scene"; import { TextStyle, addTextObject } from "#app/ui/text"; import type { nil } from "#app/utils"; +import { isNullOrUndefined } from "#app/utils"; import i18next from "i18next"; import { Species } from "#enums/species"; import type { WeatherPoolEntry } from "#app/data/weather"; import { WeatherType } from "#enums/weather-type"; +import { CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER } from "./data/balance/starters"; +import { MysteryEncounterType } from "./enums/mystery-encounter-type"; +import { MysteryEncounterTier } from "./enums/mystery-encounter-tier"; export enum EventType { SHINY, - NO_TIMER_DISPLAY + NO_TIMER_DISPLAY, + LUCK } interface EventBanner { @@ -21,19 +26,29 @@ interface EventBanner { interface EventEncounter { species: Species; - allowEvolution?: boolean; + blockEvolution?: boolean; +} + +interface EventMysteryEncounterTier { + mysteryEncounter: MysteryEncounterType; + tier?: MysteryEncounterTier; + disable?: boolean; } interface TimedEvent extends EventBanner { name: string; eventType: EventType; shinyMultiplier?: number; - friendshipMultiplier?: number; + classicFriendshipMultiplier?: number; + luckBoost?: number; + upgradeUnlockedVouchers?: boolean; startDate: Date; endDate: Date; - uncommonBreedEncounters?: EventEncounter[]; + eventEncounters?: EventEncounter[]; delibirdyBuff?: string[]; weather?: WeatherPoolEntry[]; + mysteryEncounterTierChanges?: EventMysteryEncounterTier[]; + luckBoostedSpecies?: Species[]; } const timedEvents: TimedEvent[] = [ @@ -41,36 +56,94 @@ const timedEvents: TimedEvent[] = [ name: "Winter Holiday Update", eventType: EventType.SHINY, shinyMultiplier: 2, - friendshipMultiplier: 1, + upgradeUnlockedVouchers: true, startDate: new Date(Date.UTC(2024, 11, 21, 0)), endDate: new Date(Date.UTC(2025, 0, 4, 0)), bannerKey: "winter_holidays2024-event-", scale: 0.21, availableLangs: [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ], - uncommonBreedEncounters: [ - { species: Species.GIMMIGHOUL }, + eventEncounters: [ + { species: Species.GIMMIGHOUL, blockEvolution: true }, { species: Species.DELIBIRD }, - { species: Species.STANTLER, allowEvolution: true }, - { species: Species.CYNDAQUIL, allowEvolution: true }, - { species: Species.PIPLUP, allowEvolution: true }, - { species: Species.CHESPIN, allowEvolution: true }, - { species: Species.BALTOY, allowEvolution: true }, - { species: Species.SNOVER, allowEvolution: true }, - { species: Species.CHINGLING, allowEvolution: true }, - { species: Species.LITWICK, allowEvolution: true }, - { species: Species.CUBCHOO, allowEvolution: true }, - { species: Species.SWIRLIX, allowEvolution: true }, - { species: Species.AMAURA, allowEvolution: true }, - { species: Species.MUDBRAY, allowEvolution: true }, - { species: Species.ROLYCOLY, allowEvolution: true }, - { species: Species.MILCERY, allowEvolution: true }, - { species: Species.SMOLIV, allowEvolution: true }, - { species: Species.ALOLA_VULPIX, allowEvolution: true }, - { species: Species.GALAR_DARUMAKA, allowEvolution: true }, + { species: Species.STANTLER }, + { species: Species.CYNDAQUIL }, + { species: Species.PIPLUP }, + { species: Species.CHESPIN }, + { species: Species.BALTOY }, + { species: Species.SNOVER }, + { species: Species.CHINGLING }, + { species: Species.LITWICK }, + { species: Species.CUBCHOO }, + { species: Species.SWIRLIX }, + { species: Species.AMAURA }, + { species: Species.MUDBRAY }, + { species: Species.ROLYCOLY }, + { species: Species.MILCERY }, + { species: Species.SMOLIV }, + { species: Species.ALOLA_VULPIX }, + { species: Species.GALAR_DARUMAKA }, { species: Species.IRON_BUNDLE } ], delibirdyBuff: [ "CATCHING_CHARM", "SHINY_CHARM", "ABILITY_CHARM", "EXP_CHARM", "SUPER_EXP_CHARM", "HEALING_CHARM" ], - weather: [{ weatherType: WeatherType.SNOW, weight: 1 }] + weather: [{ weatherType: WeatherType.SNOW, weight: 1 }], + mysteryEncounterTierChanges: [ + { mysteryEncounter: MysteryEncounterType.DELIBIRDY, tier: MysteryEncounterTier.COMMON }, + { mysteryEncounter: MysteryEncounterType.PART_TIMER, disable: true }, + { mysteryEncounter: MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, disable: true }, + { mysteryEncounter: MysteryEncounterType.FIELD_TRIP, disable: true }, + { mysteryEncounter: MysteryEncounterType.DEPARTMENT_STORE_SALE, disable: true } + ] + }, + { + name: "Year of the Snake", + eventType: EventType.LUCK, + luckBoost: 1, + startDate: new Date(Date.UTC(2025, 0, 29, 0)), + endDate: new Date(Date.UTC(2025, 1, 3, 0)), + bannerKey: "yearofthesnakeevent-", + scale: 0.21, + availableLangs: [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ], + eventEncounters: [ + { species: Species.EKANS }, + { species: Species.ONIX }, + { species: Species.DRATINI }, + { species: Species.CLEFFA }, + { species: Species.UMBREON }, + { species: Species.DUNSPARCE }, + { species: Species.TEDDIURSA }, + { species: Species.SEVIPER }, + { species: Species.LUNATONE }, + { species: Species.CHINGLING }, + { species: Species.SNIVY }, + { species: Species.DARUMAKA }, + { species: Species.DRAMPA }, + { species: Species.SILICOBRA }, + { species: Species.BLOODMOON_URSALUNA } + ], + luckBoostedSpecies: [ + Species.EKANS, Species.ARBOK, + Species.ONIX, Species.STEELIX, + Species.DRATINI, Species.DRAGONAIR, Species.DRAGONITE, + Species.CLEFFA, Species.CLEFAIRY, Species.CLEFABLE, + Species.UMBREON, + Species.DUNSPARCE, Species.DUDUNSPARCE, + Species.TEDDIURSA, Species.URSARING, Species.URSALUNA, + Species.SEVIPER, + Species.LUNATONE, + Species.RAYQUAZA, + Species.CHINGLING, Species.CHIMECHO, + Species.CRESSELIA, + Species.DARKRAI, + Species.SNIVY, Species.SERVINE, Species.SERPERIOR, + Species.DARUMAKA, Species.DARMANITAN, + Species.ZYGARDE, + Species.DRAMPA, + Species.LUNALA, + Species.BLACEPHALON, + Species.SILICOBRA, Species.SANDACONDA, + Species.ROARING_MOON, + Species.BLOODMOON_URSALUNA + ] } ]; @@ -97,16 +170,6 @@ export class TimedEventManager { return activeEvents.length > 0; } - getFriendshipMultiplier(): number { - let multiplier = 1; - const friendshipEvents = timedEvents.filter((te) => this.isActive(te)); - friendshipEvents.forEach((fe) => { - multiplier *= fe.friendshipMultiplier ?? 1; - }); - - return multiplier; - } - getShinyMultiplier(): number { let multiplier = 1; const shinyEvents = timedEvents.filter((te) => te.eventType === EventType.SHINY && this.isActive(te)); @@ -120,6 +183,120 @@ export class TimedEventManager { getEventBannerFilename(): string { return timedEvents.find((te: TimedEvent) => this.isActive(te))?.bannerKey ?? ""; } + + getEventEncounters(): EventEncounter[] { + const ret: EventEncounter[] = []; + timedEvents.filter((te) => this.isActive(te)).map((te) => { + if (!isNullOrUndefined(te.eventEncounters)) { + ret.push(...te.eventEncounters); + } + }); + return ret; + } + + /** + * For events that change the classic candy friendship multiplier + * @returns The highest classic friendship multiplier among the active events, or the default CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER + */ + getClassicFriendshipMultiplier(): number { + let multiplier = CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER; + const classicFriendshipEvents = timedEvents.filter((te) => this.isActive(te)); + classicFriendshipEvents.forEach((fe) => { + if (!isNullOrUndefined(fe.classicFriendshipMultiplier) && fe.classicFriendshipMultiplier > multiplier) { + multiplier = fe.classicFriendshipMultiplier; + } + }); + return multiplier; + } + + /** + * For events where defeated bosses (Gym Leaders, E4 etc) give out Voucher Plus even if they were defeated before + * @returns Whether vouchers should be upgraded + */ + getUpgradeUnlockedVouchers(): boolean { + return timedEvents.some((te) => this.isActive(te) && (te.upgradeUnlockedVouchers ?? false)); + } + + /** + * For events where Delibirdy gives extra items + * @returns list of ids of {@linkcode ModifierType}s that Delibirdy hands out as a bonus + */ + getDelibirdyBuff(): string[] { + const ret: string[] = []; + timedEvents.filter((te) => this.isActive(te)).map((te) => { + if (!isNullOrUndefined(te.delibirdyBuff)) { + ret.push(...te.delibirdyBuff); + } + }); + return ret; + } + + /** + * For events where there's a set weather for town biome (other biomes are hard) + * @returns Event weathers for town + */ + getWeather(): WeatherPoolEntry[] { + const ret: WeatherPoolEntry[] = []; + timedEvents.filter((te) => this.isActive(te)).map((te) => { + if (!isNullOrUndefined(te.weather)) { + ret.push(...te.weather); + } + }); + return ret; + } + + getAllMysteryEncounterChanges(): EventMysteryEncounterTier[] { + const ret: EventMysteryEncounterTier[] = []; + timedEvents.filter((te) => this.isActive(te)).map((te) => { + if (!isNullOrUndefined(te.mysteryEncounterTierChanges)) { + ret.push(...te.mysteryEncounterTierChanges); + } + }); + return ret; + } + + getEventMysteryEncountersDisabled(): MysteryEncounterType[] { + const ret: MysteryEncounterType[] = []; + timedEvents.filter((te) => this.isActive(te) && !isNullOrUndefined(te.mysteryEncounterTierChanges)).map((te) => { + te.mysteryEncounterTierChanges?.map((metc) => { + if (metc.disable) { + ret.push(metc.mysteryEncounter); + } + }); + }); + return ret; + } + + getMysteryEncounterTierForEvent(encounterType: MysteryEncounterType, normal: MysteryEncounterTier): MysteryEncounterTier { + let ret = normal; + timedEvents.filter((te) => this.isActive(te) && !isNullOrUndefined(te.mysteryEncounterTierChanges)).map((te) => { + te.mysteryEncounterTierChanges?.map((metc) => { + if (metc.mysteryEncounter === encounterType) { + ret = metc.tier ?? normal; + } + }); + }); + return ret; + } + + getEventLuckBoost(): number { + let ret = 0; + const luckEvents = timedEvents.filter((te) => this.isActive(te) && !isNullOrUndefined(te.luckBoost)); + luckEvents.forEach((le) => { + ret += le.luckBoost!; + }); + return ret; + } + + getEventLuckBoostedSpecies(): Species[] { + const ret: Species[] = []; + timedEvents.filter((te) => this.isActive(te)).map((te) => { + if (!isNullOrUndefined(te.luckBoostedSpecies)) { + ret.push(...te.luckBoostedSpecies.filter(s => !ret.includes(s))); + } + }); + return ret; + } } export class TimedEventDisplay extends Phaser.GameObjects.Container { diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index bb950f328e8..7ea8dbe7a4e 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -111,7 +111,7 @@ export default class MenuUiHandler extends MessageUiHandler { render() { const ui = this.getUi(); this.excludedMenus = () => [ - { condition: globalScene.getCurrentPhase() instanceof SelectModifierPhase, options: [ MenuOptions.EGG_GACHA, MenuOptions.EGG_LIST ]}, + { condition: globalScene.getCurrentPhase() instanceof SelectModifierPhase, options: [ MenuOptions.EGG_GACHA ]}, { condition: bypassLogin, options: [ MenuOptions.LOG_OUT ]} ]; diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 0539477ad36..0ea14fd47e0 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -20,7 +20,6 @@ import { pokemonFormLevelMoves, pokemonSpeciesLevelMoves } from "#app/data/balan import type PokemonSpecies from "#app/data/pokemon-species"; import { allSpecies, getPokemonSpeciesForm, getPokerusStarters } from "#app/data/pokemon-species"; import { getStarterValueFriendshipCap, speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters"; -import { starterPassiveAbilities } from "#app/data/balance/passives"; import { Type } from "#enums/type"; import { GameModes } from "#app/game-mode"; import type { DexAttrProps, DexEntry, StarterMoveset, StarterAttributes, StarterPreferences } from "#app/system/game-data"; @@ -276,14 +275,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private abilityIconElement: Phaser.GameObjects.Sprite; private genderIconElement: Phaser.GameObjects.Sprite; private natureIconElement: Phaser.GameObjects.Sprite; - private variantIconElement: Phaser.GameObjects.Sprite; private goFilterIconElement: Phaser.GameObjects.Sprite; private shinyLabel: Phaser.GameObjects.Text; private formLabel: Phaser.GameObjects.Text; private genderLabel: Phaser.GameObjects.Text; private abilityLabel: Phaser.GameObjects.Text; private natureLabel: Phaser.GameObjects.Text; - private variantLabel: Phaser.GameObjects.Text; private goFilterLabel: Phaser.GameObjects.Text; private starterSelectMessageBox: Phaser.GameObjects.NineSlice; @@ -319,7 +316,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private canCycleGender: boolean; private canCycleAbility: boolean; private canCycleNature: boolean; - private canCycleVariant: boolean; private assetLoadCancelled: BooleanHolder | null; public cursorObj: Phaser.GameObjects.Image; @@ -875,13 +871,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.natureLabel = addTextObject(this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, i18next.t("starterSelectUiHandler:cycleNature"), TextStyle.PARTY, { fontSize: instructionTextSize }); this.natureLabel.setName("text-nature-label"); - this.variantIconElement = new Phaser.GameObjects.Sprite(globalScene, this.instructionRowX, this.instructionRowY, "keyboard", "V.png"); - this.variantIconElement.setName("sprite-variant-icon-element"); - this.variantIconElement.setScale(0.675); - this.variantIconElement.setOrigin(0.0, 0.0); - this.variantLabel = addTextObject(this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, i18next.t("starterSelectUiHandler:cycleVariant"), TextStyle.PARTY, { fontSize: instructionTextSize }); - this.variantLabel.setName("text-variant-label"); - this.goFilterIconElement = new Phaser.GameObjects.Sprite(globalScene, this.filterInstructionRowX, this.filterInstructionRowY, "keyboard", "C.png"); this.goFilterIconElement.setName("sprite-goFilter-icon-element"); this.goFilterIconElement.setScale(0.675); @@ -1858,7 +1847,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { if (!(passiveAttr & PassiveAttr.UNLOCKED)) { const passiveCost = getPassiveCandyCount(speciesStarterCosts[this.lastSpecies.speciesId]); options.push({ - label: `x${passiveCost} ${i18next.t("starterSelectUiHandler:unlockPassive")} (${allAbilities[starterPassiveAbilities[this.lastSpecies.speciesId]].name})`, + label: `x${passiveCost} ${i18next.t("starterSelectUiHandler:unlockPassive")} (${allAbilities[this.lastSpecies.getPassiveAbility()].name})`, handler: () => { if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= passiveCost) { starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED; @@ -2003,53 +1992,56 @@ export default class StarterSelectUiHandler extends MessageUiHandler { switch (button) { case Button.CYCLE_SHINY: if (this.canCycleShiny) { - starterAttributes.shiny = starterAttributes.shiny !== undefined ? !starterAttributes.shiny : false; - - if (starterAttributes.shiny) { - // Change to shiny, we need to get the proper default variant + if (starterAttributes.shiny === false) { + // If not shiny, we change to shiny and get the proper default variant const newProps = globalScene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId)); const newVariant = starterAttributes.variant ? starterAttributes.variant as Variant : newProps.variant; this.setSpeciesDetails(this.lastSpecies, { shiny: true, variant: newVariant }); globalScene.playSound("se/sparkle"); - // Set the variant label to the shiny tint + // Cycle tint based on current sprite tint const tint = getVariantTint(newVariant); this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant)); this.pokemonShinyIcon.setTint(tint); this.pokemonShinyIcon.setVisible(true); + + starterAttributes.shiny = true; } else { - this.setSpeciesDetails(this.lastSpecies, { shiny: false, variant: 0 }); - this.pokemonShinyIcon.setVisible(false); - success = true; - } - } - break; - case Button.V: - if (this.canCycleVariant) { - let newVariant = props.variant; - do { - newVariant = (newVariant + 1) % 3; - if (newVariant === 0) { - if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.DEFAULT_VARIANT) { // TODO: is this bang correct? - break; - } - } else if (newVariant === 1) { - if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_2) { // TODO: is this bang correct? - break; + // If shiny, we update the variant + let newVariant = props.variant; + do { + newVariant = (newVariant + 1) % 3; + if (newVariant === 0) { + if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.DEFAULT_VARIANT) { // TODO: is this bang correct? + break; + } + } else if (newVariant === 1) { + if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_2) { // TODO: is this bang correct? + break; + } + } else { + if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_3) { // TODO: is this bang correct? + break; + } } + } while (newVariant !== props.variant); + starterAttributes.variant = newVariant; // store the selected variant + // If going to a higher variant, display that + if (newVariant > props.variant) { + this.setSpeciesDetails(this.lastSpecies, { variant: newVariant as Variant }); + // Cycle tint based on current sprite tint + const tint = getVariantTint(newVariant as Variant); + this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant as Variant)); + this.pokemonShinyIcon.setTint(tint); + success = true; + // If we have run out of variants, go back to non shiny } else { - if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_3) { // TODO: is this bang correct? - break; - } + this.setSpeciesDetails(this.lastSpecies, { shiny: false, variant: 0 }); + this.pokemonShinyIcon.setVisible(false); + success = true; + starterAttributes.shiny = false; } - } while (newVariant !== props.variant); - starterAttributes.variant = newVariant; // store the selected variant - this.setSpeciesDetails(this.lastSpecies, { variant: newVariant as Variant }); - // Cycle tint based on current sprite tint - const tint = getVariantTint(newVariant as Variant); - this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant as Variant)); - this.pokemonShinyIcon.setTint(tint); - success = true; + } } break; case Button.CYCLE_FORM: @@ -2376,9 +2368,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { case SettingKeyboard.Button_Cycle_Nature: iconPath = "N.png"; break; - case SettingKeyboard.Button_Cycle_Variant: - iconPath = "V.png"; - break; case SettingKeyboard.Button_Stats: iconPath = "C.png"; break; @@ -2459,9 +2448,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { if (this.canCycleNature) { this.updateButtonIcon(SettingKeyboard.Button_Cycle_Nature, gamepadType, this.natureIconElement, this.natureLabel); } - if (this.canCycleVariant) { - this.updateButtonIcon(SettingKeyboard.Button_Cycle_Variant, gamepadType, this.variantIconElement, this.variantLabel); - } } // if filter mode is inactivated and gamepadType is not undefined, update the button icons @@ -3266,12 +3252,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const isNonShinyCaught = !!(caughtAttr & DexAttr.NON_SHINY); const isShinyCaught = !!(caughtAttr & DexAttr.SHINY); - const isVariant1Caught = isShinyCaught && !!(caughtAttr & DexAttr.DEFAULT_VARIANT); - const isVariant2Caught = isShinyCaught && !!(caughtAttr & DexAttr.VARIANT_2); - const isVariant3Caught = isShinyCaught && !!(caughtAttr & DexAttr.VARIANT_3); this.canCycleShiny = isNonShinyCaught && isShinyCaught; - this.canCycleVariant = !!shiny && [ isVariant1Caught, isVariant2Caught, isVariant3Caught ].filter(v => v).length > 1; const isMaleCaught = !!(caughtAttr & DexAttr.MALE); const isFemaleCaught = !!(caughtAttr & DexAttr.FEMALE); @@ -3316,7 +3298,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonAbilityText.setShadowColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD, true)); const passiveAttr = globalScene.gameData.starterData[species.speciesId].passiveAttr; - const passiveAbility = allAbilities[starterPassiveAbilities[this.lastSpecies.speciesId]]; + const passiveAbility = allAbilities[this.lastSpecies.getPassiveAbility(formIndex)]; if (this.pokemonAbilityText.visible) { if (this.activeTooltip === "ABILITY") { @@ -3830,8 +3812,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.abilityLabel.setVisible(false); this.natureIconElement.setVisible(false); this.natureLabel.setVisible(false); - this.variantIconElement.setVisible(false); - this.variantLabel.setVisible(false); this.goFilterIconElement.setVisible(false); this.goFilterLabel.setVisible(false); } diff --git a/src/ui/ui.ts b/src/ui/ui.ts index 9e8c52b1d24..682ef836765 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -269,7 +269,7 @@ export default class UI extends Phaser.GameObjects.Container { return false; } - if ([ Mode.CONFIRM, Mode.COMMAND, Mode.FIGHT, Mode.MESSAGE ].includes(this.mode)) { + if ([ Mode.CONFIRM, Mode.COMMAND, Mode.FIGHT, Mode.MESSAGE, Mode.TARGET_SELECT ].includes(this.mode)) { globalScene?.processInfoButton(pressed); return true; } @@ -277,6 +277,11 @@ export default class UI extends Phaser.GameObjects.Container { return true; } + /** + * Process a player input of a button (delivering it to the current UI handler for processing) + * @param button The {@linkcode Button} being inputted + * @returns true if the input attempt succeeds + */ processInput(button: Button): boolean { if (this.overlayActive) { return false;