diff --git a/package-lock.json b/package-lock.json index 52cc628872a..9531244a42d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pokemon-rogue-battle", - "version": "1.4.3", + "version": "1.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pokemon-rogue-battle", - "version": "1.4.3", + "version": "1.5.0", "hasInstallScript": true, "dependencies": { "@material/material-color-utilities": "^0.2.7", diff --git a/package.json b/package.json index e52c5928da7..9d8adb8c1c0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.4.3", + "version": "1.5.0", "type": "module", "scripts": { "start": "vite", 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/pokemon/3-gigantamax.png b/public/images/pokemon/3-gigantamax.png index 4036c641327..d551638c880 100644 Binary files a/public/images/pokemon/3-gigantamax.png and b/public/images/pokemon/3-gigantamax.png differ diff --git a/public/images/pokemon/3-mega.png b/public/images/pokemon/3-mega.png index 9f867c8e13d..c15a9cac092 100644 Binary files a/public/images/pokemon/3-mega.png and b/public/images/pokemon/3-mega.png differ diff --git a/public/images/pokemon/3.png b/public/images/pokemon/3.png index b9239f3096e..534a48fdfa6 100644 Binary files a/public/images/pokemon/3.png and b/public/images/pokemon/3.png differ diff --git a/public/images/pokemon/back/3-gigantamax.png b/public/images/pokemon/back/3-gigantamax.png index a368c97741e..278cb58b765 100644 Binary files a/public/images/pokemon/back/3-gigantamax.png and b/public/images/pokemon/back/3-gigantamax.png differ diff --git a/public/images/pokemon/back/3-mega.png b/public/images/pokemon/back/3-mega.png index 0c8512cb91b..5f4986de090 100644 Binary files a/public/images/pokemon/back/3-mega.png and b/public/images/pokemon/back/3-mega.png differ diff --git a/public/images/pokemon/back/3.png b/public/images/pokemon/back/3.png index 4312bfbce2c..9f833c7d122 100644 Binary files a/public/images/pokemon/back/3.png and b/public/images/pokemon/back/3.png differ diff --git a/public/images/pokemon/back/987.png b/public/images/pokemon/back/987.png index 64a47fbf0ea..ab4e628de28 100644 Binary files a/public/images/pokemon/back/987.png and b/public/images/pokemon/back/987.png differ diff --git a/public/images/pokemon/back/female/3.png b/public/images/pokemon/back/female/3.png index 0fdbf4e9be2..ef103db8ce0 100644 Binary files a/public/images/pokemon/back/female/3.png and b/public/images/pokemon/back/female/3.png differ diff --git a/public/images/pokemon/back/shiny/3-gigantamax.png b/public/images/pokemon/back/shiny/3-gigantamax.png index e3402e164a6..24b79e4211e 100644 Binary files a/public/images/pokemon/back/shiny/3-gigantamax.png and b/public/images/pokemon/back/shiny/3-gigantamax.png differ diff --git a/public/images/pokemon/back/shiny/3.png b/public/images/pokemon/back/shiny/3.png index a80c363723b..890fce10821 100644 Binary files a/public/images/pokemon/back/shiny/3.png and b/public/images/pokemon/back/shiny/3.png differ diff --git a/public/images/pokemon/back/shiny/987.png b/public/images/pokemon/back/shiny/987.png index 8022d2f900a..8c4c0c8b62a 100644 Binary files a/public/images/pokemon/back/shiny/987.png and b/public/images/pokemon/back/shiny/987.png differ diff --git a/public/images/pokemon/back/shiny/female/3.png b/public/images/pokemon/back/shiny/female/3.png index 706a6c33f14..dff72d5b6e5 100644 Binary files a/public/images/pokemon/back/shiny/female/3.png and b/public/images/pokemon/back/shiny/female/3.png differ diff --git a/public/images/pokemon/exp/back/382-primal.png b/public/images/pokemon/exp/back/382-primal.png index 55c73cf877e..7bf840bcf24 100644 Binary files a/public/images/pokemon/exp/back/382-primal.png and b/public/images/pokemon/exp/back/382-primal.png differ diff --git a/public/images/pokemon/exp/back/987.png b/public/images/pokemon/exp/back/987.png index 1da8db869dc..4956b630d3e 100644 Binary files a/public/images/pokemon/exp/back/987.png and b/public/images/pokemon/exp/back/987.png differ diff --git a/public/images/pokemon/exp/back/shiny/987.png b/public/images/pokemon/exp/back/shiny/987.png index d829e1a2d11..f62bb9f3ecc 100644 Binary files a/public/images/pokemon/exp/back/shiny/987.png and b/public/images/pokemon/exp/back/shiny/987.png differ diff --git a/public/images/pokemon/female/3.png b/public/images/pokemon/female/3.png index 646157beb32..e21b53dfd57 100644 Binary files a/public/images/pokemon/female/3.png and b/public/images/pokemon/female/3.png differ diff --git a/public/images/pokemon/shiny/3-gigantamax.png b/public/images/pokemon/shiny/3-gigantamax.png index ee4705de701..acc57a41671 100644 Binary files a/public/images/pokemon/shiny/3-gigantamax.png and b/public/images/pokemon/shiny/3-gigantamax.png differ diff --git a/public/images/pokemon/shiny/3.png b/public/images/pokemon/shiny/3.png index fb4545e3019..4afd3847484 100644 Binary files a/public/images/pokemon/shiny/3.png and b/public/images/pokemon/shiny/3.png differ diff --git a/public/images/pokemon/shiny/female/3.png b/public/images/pokemon/shiny/female/3.png index aeacf461779..ec5a9849e60 100644 Binary files a/public/images/pokemon/shiny/female/3.png and b/public/images/pokemon/shiny/female/3.png differ diff --git a/public/images/pokemon/variant/3-gigantamax.json b/public/images/pokemon/variant/3-gigantamax.json index 7b341b367aa..9b74b1131ba 100644 --- a/public/images/pokemon/variant/3-gigantamax.json +++ b/public/images/pokemon/variant/3-gigantamax.json @@ -4,6 +4,8 @@ "ffee52": "37d6de", "debd29": "078a8f", "833100": "002112", + "830009": "23033b", + "189d87": "c2247b", "ff7b73": "712f8f", "de4141": "3f1375", "ffbdbd": "a266b0", @@ -11,6 +13,7 @@ "107b6a": "9e1976", "105241": "4f2800", "83de7b": "a37707", + "2e5529": "38001c", "5a9c39": "705207", "20b49c": "de3592", "fdfdfd": "fdfdfd", @@ -21,14 +24,17 @@ "ffee52": "f75ea8", "debd29": "a30a66", "833100": "0b2e01", + "830009": "154205", + "189d87": "f17f05", "ff7b73": "9db042", "de4141": "3c8227", "ffbdbd": "e7e385", "101010": "101010", "107b6a": "d44300", - "105241": "030129", - "83de7b": "433d99", - "5a9c39": "19164f", + "105241": "381601", + "83de7b": "80ced9", + "2e5519": "011c38", + "5a9c39": "446b94", "20b49c": "fa8405", "fdfdfd": "fdfdfd", "5ad5c5": "faa405" diff --git a/public/images/pokemon/variant/3-mega_2.png b/public/images/pokemon/variant/3-mega_2.png index ddc2bd976ad..54ca687d1c3 100644 Binary files a/public/images/pokemon/variant/3-mega_2.png and b/public/images/pokemon/variant/3-mega_2.png differ diff --git a/public/images/pokemon/variant/3-mega_3.png b/public/images/pokemon/variant/3-mega_3.png index 56945d383e6..07ddb5ae7ed 100644 Binary files a/public/images/pokemon/variant/3-mega_3.png and b/public/images/pokemon/variant/3-mega_3.png differ diff --git a/public/images/pokemon/variant/3.json b/public/images/pokemon/variant/3.json index 83a13fdca0e..bdcc30edcbf 100644 --- a/public/images/pokemon/variant/3.json +++ b/public/images/pokemon/variant/3.json @@ -1,6 +1,7 @@ { "1": { "843100": "033b22", + "830009": "23033b", "ff7b73": "712f8f", "ffbdbd": "a266b0", "debd29": "078a8f", @@ -13,11 +14,13 @@ "5a9c3a": "b34952", "84de7b": "ff745e", "5ad6c5": "f062a4", + "2e5519": "38001c", "21b59c": "de3592", "ffffff": "ffffff" }, "2": { "843100": "420514", + "830009": "154205", "ff7b73": "9db042", "ffbdbd": "e7e385", "debd29": "a30a66", @@ -30,6 +33,7 @@ "5a9c3a": "446b94", "84de7b": "80ced9", "5ad6c5": "faa405", + "2e5519": "011c38", "21b59c": "fa8405", "ffffff": "ffffff" } diff --git a/public/images/pokemon/variant/_masterlist.json b/public/images/pokemon/variant/_masterlist.json index 3c5aedf2084..87c9816b8cb 100644 --- a/public/images/pokemon/variant/_masterlist.json +++ b/public/images/pokemon/variant/_masterlist.json @@ -835,7 +835,7 @@ "6713": [0, 1, 1], "8901": [1, 1, 1], "female": { - "3": [0, 2, 1], + "3": [0, 1, 1], "19": [0, 1, 1], "20": [0, 1, 1], "25": [0, 1, 1], diff --git a/public/images/pokemon/variant/back/3-gigantamax.json b/public/images/pokemon/variant/back/3-gigantamax.json index a8cd61c3419..b618abecbcc 100644 --- a/public/images/pokemon/variant/back/3-gigantamax.json +++ b/public/images/pokemon/variant/back/3-gigantamax.json @@ -1,6 +1,7 @@ { "1": { "833100": "180136", + "830009": "23033b", "bd6a31": "012729", "ffee52": "37d6de", "debd29": "078a8f", @@ -8,15 +9,18 @@ "de4141": "3f1375", "ff7b73": "712f8f", "ffbdbd": "a266b0", - "5a9c39": "705207", - "105241": "4f2800", - "83de7b": "a37707", + "e8a3a3": "91579e", + "5a9c39": "b34952", + "105241": "190038", + "2e5519": "38001c", + "83de7b": "ff745e", "107b6a": "b80479", "20b49c": "de3592", "fdfdfd": "fdfdfd" }, "2": { "833100": "0b2e01", + "830009": "154205", "bd6a31": "420514", "ffee52": "f75ea8", "debd29": "a30a66", @@ -24,9 +28,11 @@ "de4141": "3c8227", "ff7b73": "9db042", "ffbdbd": "e7e385", - "5a9c39": "19164f", - "105241": "030129", - "83de7b": "433d99", + "e8a3a3": "ced76f", + "5a9c39": "446b94", + "105241": "381601", + "2e5519": "011c38", + "83de7b": "80ced9", "107b6a": "d15d04", "20b49c": "fa8405", "fdfdfd": "fdfdfd" diff --git a/public/images/pokemon/variant/back/3-mega_2.png b/public/images/pokemon/variant/back/3-mega_2.png index 7bb201ef984..90eeb6d84f2 100644 Binary files a/public/images/pokemon/variant/back/3-mega_2.png and b/public/images/pokemon/variant/back/3-mega_2.png differ diff --git a/public/images/pokemon/variant/back/3-mega_3.png b/public/images/pokemon/variant/back/3-mega_3.png index 5d7fb8ad798..77d6c7f12fa 100644 Binary files a/public/images/pokemon/variant/back/3-mega_3.png and b/public/images/pokemon/variant/back/3-mega_3.png differ diff --git a/public/images/pokemon/variant/back/3.json b/public/images/pokemon/variant/back/3.json index 616efac7d3c..0c179dd5e4a 100644 --- a/public/images/pokemon/variant/back/3.json +++ b/public/images/pokemon/variant/back/3.json @@ -1,6 +1,7 @@ { "1": { "843100": "033b22", + "830009": "23033b", "ffbdbd": "a266b0", "ff7b73": "712f8f", "debd29": "078a8f", @@ -11,6 +12,7 @@ "105242": "190038", "107b6b": "c21f7e", "5a9c3a": "b34952", + "2e5519": "38001c", "5ad6c5": "f062a4", "21b59c": "de3592", "84de7b": "ff745e", @@ -18,6 +20,7 @@ }, "2": { "843100": "420514", + "830009": "154205", "ffbdbd": "e7e385", "ff7b73": "9db042", "debd29": "a30a66", @@ -25,7 +28,8 @@ "de4242": "3c8227", "101010": "101010", "ffef52": "f75ea8", - "105242": "001a33", + "105242": "381601", + "2e5519": "011c38", "107b6b": "d15d04", "5a9c3a": "446b94", "5ad6c5": "faa405", diff --git a/public/images/pokemon/variant/back/987.json b/public/images/pokemon/variant/back/987.json index 1773ba70c36..e28a34d5435 100644 --- a/public/images/pokemon/variant/back/987.json +++ b/public/images/pokemon/variant/back/987.json @@ -9,7 +9,7 @@ "de62a4": "ffc668", "4a83a4": "387fa7", "314a62": "244260", - "70bbb4": "f8d371", + "548e88": "2d60bb", "a4295a": "cc762f" }, "1": { @@ -22,7 +22,7 @@ "de62a4": "ffdf90", "4a83a4": "a1c8db", "314a62": "7396b4", - "70bbb4": "70bbb4", + "548e88": "a9c0c6", "a4295a": "e28c27" }, "2": { @@ -35,7 +35,7 @@ "de62a4": "e25038", "4a83a4": "e6aa47", "314a62": "b56f2a", - "70bbb4": "f8d371", + "548e88": "e0b544", "a4295a": "a62a21" } } \ No newline at end of file diff --git a/public/images/pokemon/variant/back/female/3.json b/public/images/pokemon/variant/back/female/3.json index 567479d58d0..49fe726b084 100644 --- a/public/images/pokemon/variant/back/female/3.json +++ b/public/images/pokemon/variant/back/female/3.json @@ -1,6 +1,7 @@ { "1": { "843100": "033b22", + "830009": "23033b", "ffbdbd": "a266b0", "ffef52": "37d6de", "debd29": "078a8f", @@ -10,6 +11,7 @@ "101010": "101010", "105242": "190038", "107b6b": "9e1976", + "2e5519": "38001c", "5a9c3a": "b34952", "5ad6c5": "f062a4", "21b59c": "de3592", @@ -18,6 +20,7 @@ }, "2": { "843100": "420514", + "830009": "154205", "ffbdbd": "e7e385", "ffef52": "f75ea8", "debd29": "a30a66", @@ -27,6 +30,7 @@ "101010": "101010", "105242": "381601", "107b6b": "d15d04", + "2e5519": "011c38", "5a9c3a": "446b94", "5ad6c5": "faa405", "21b59c": "fa8405", diff --git a/public/images/pokemon/variant/exp/back/987.json b/public/images/pokemon/variant/exp/back/987.json index 385a9eeb29f..5fb59f6979d 100644 --- a/public/images/pokemon/variant/exp/back/987.json +++ b/public/images/pokemon/variant/exp/back/987.json @@ -8,7 +8,7 @@ "0f0f0f": "0f0f0f", "314a62": "244260", "621841": "71370f", - "70bbb4": "f8d371", + "548e88": "2d60bb", "de62a4": "ffc668", "a4295a": "cc762f" }, @@ -21,7 +21,7 @@ "0f0f0f": "0f0f0f", "314a62": "7396b4", "621841": "7b3c08", - "70bbb4": "70bbb4", + "548e88": "a9c0c6", "de62a4": "ffdf90", "a4295a": "e28c27" }, @@ -34,7 +34,7 @@ "0f0f0f": "0f0f0f", "314a62": "b56f2a", "621841": "5a0a05", - "70bbb4": "f8d371", + "548e88": "e0b544", "de62a4": "e25038", "a4295a": "a62a21" } diff --git a/public/images/pokemon/variant/female/3.json b/public/images/pokemon/variant/female/3.json index 515cd2e93e5..de2c52f6003 100644 --- a/public/images/pokemon/variant/female/3.json +++ b/public/images/pokemon/variant/female/3.json @@ -1,19 +1,41 @@ { + "1": { + "843100": "033b22", + "830009": "23033b", + "ffbdbd": "a266b0", + "ffef52": "37d6de", + "debd29": "078a8f", + "ff7b73": "712f8f", + "bd6b31": "168a69", + "de4242": "3f1375", + "101010": "101010", + "105242": "190038", + "107b6b": "9e1976", + "2e5519": "38001c", + "5a9c3a": "b34952", + "5ad6c5": "f062a4", + "21b59c": "de3592", + "84de7b": "ff745e", + "ffffff": "ffffff" + }, "2": { "843100": "420514", - "ff7b73": "9db042", + "830009": "154205", "ffbdbd": "e7e385", "ffef52": "f75ea8", "debd29": "a30a66", + "ff7b73": "9db042", "bd6b31": "852a41", "de4242": "3c8227", "101010": "101010", "105242": "381601", - "107b6b": "d44300", + "107b6b": "d15d04", + "2e5519": "011c38", "5a9c3a": "446b94", - "84de7b": "80ced9", "5ad6c5": "faa405", "21b59c": "fa8405", - "ffffff": "ffffff" + "84de7b": "80ced9", + "ffffff": "ffffff", + "2f561a": "011b34" } } \ No newline at end of file diff --git a/public/images/pokemon/variant/female/3_2.json b/public/images/pokemon/variant/female/3_2.json deleted file mode 100644 index 8c89faed762..00000000000 --- a/public/images/pokemon/variant/female/3_2.json +++ /dev/null @@ -1,4136 +0,0 @@ -{ - "textures": [ - { - "image": "3_2.png", - "format": "RGBA8888", - "size": { - "w": 569, - "h": 569 - }, - "scale": 1, - "frames": [ - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 0, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 0, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 0, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 0, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 81, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 81, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 81, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 81, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 81, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 162, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 162, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 162, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 81, - "h": 66 - }, - "frame": { - "x": 162, - "y": 0, - "w": 81, - "h": 66 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 243, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 243, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 243, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 243, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 243, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 324, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 324, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 324, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 324, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 405, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 405, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 486, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 486, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 67 - }, - "frame": { - "x": 486, - "y": 0, - "w": 81, - "h": 67 - } - }, - { - "filename": "0172.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 67 - }, - "frame": { - "x": 0, - "y": 66, - "w": 81, - "h": 67 - } - }, - { - "filename": "0173.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 67 - }, - "frame": { - "x": 0, - "y": 66, - "w": 81, - "h": 67 - } - }, - { - "filename": "0190.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 84, - "h": 67 - }, - "frame": { - "x": 81, - "y": 66, - "w": 84, - "h": 67 - } - }, - { - "filename": "0191.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 84, - "h": 67 - }, - "frame": { - "x": 81, - "y": 66, - "w": 84, - "h": 67 - } - }, - { - "filename": "0192.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 84, - "h": 67 - }, - "frame": { - "x": 81, - "y": 66, - "w": 84, - "h": 67 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 165, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 165, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 165, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 165, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 165, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 246, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 246, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 246, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 246, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 246, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 327, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 327, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 327, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 327, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 408, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 408, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 408, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 408, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 408, - "y": 67, - "w": 81, - "h": 68 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 80, - "h": 68 - }, - "frame": { - "x": 489, - "y": 67, - "w": 80, - "h": 68 - } - }, - { - "filename": "0145.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 80, - "h": 68 - }, - "frame": { - "x": 489, - "y": 67, - "w": 80, - "h": 68 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 0, - "y": 133, - "w": 81, - "h": 68 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 0, - "y": 133, - "w": 81, - "h": 68 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 0, - "y": 133, - "w": 81, - "h": 68 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 0, - "y": 133, - "w": 81, - "h": 68 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 0, - "y": 133, - "w": 81, - "h": 68 - } - }, - { - "filename": "0153.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 84, - "h": 68 - }, - "frame": { - "x": 81, - "y": 133, - "w": 84, - "h": 68 - } - }, - { - "filename": "0154.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 84, - "h": 68 - }, - "frame": { - "x": 81, - "y": 133, - "w": 84, - "h": 68 - } - }, - { - "filename": "0155.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 84, - "h": 68 - }, - "frame": { - "x": 165, - "y": 135, - "w": 84, - "h": 68 - } - }, - { - "filename": "0156.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 84, - "h": 68 - }, - "frame": { - "x": 165, - "y": 135, - "w": 84, - "h": 68 - } - }, - { - "filename": "0157.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 84, - "h": 68 - }, - "frame": { - "x": 165, - "y": 135, - "w": 84, - "h": 68 - } - }, - { - "filename": "0174.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 249, - "y": 135, - "w": 81, - "h": 68 - } - }, - { - "filename": "0175.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 81, - "h": 68 - }, - "frame": { - "x": 249, - "y": 135, - "w": 81, - "h": 68 - } - }, - { - "filename": "0188.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 84, - "h": 68 - }, - "frame": { - "x": 330, - "y": 135, - "w": 84, - "h": 68 - } - }, - { - "filename": "0189.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 84, - "h": 68 - }, - "frame": { - "x": 330, - "y": 135, - "w": 84, - "h": 68 - } - }, - { - "filename": "0193.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 83, - "h": 68 - }, - "frame": { - "x": 414, - "y": 135, - "w": 83, - "h": 68 - } - }, - { - "filename": "0194.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 83, - "h": 68 - }, - "frame": { - "x": 414, - "y": 135, - "w": 83, - "h": 68 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 0, - "y": 201, - "w": 81, - "h": 69 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 0, - "y": 201, - "w": 81, - "h": 69 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 0, - "y": 201, - "w": 81, - "h": 69 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 0, - "y": 201, - "w": 81, - "h": 69 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 0, - "y": 201, - "w": 81, - "h": 69 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 81, - "y": 201, - "w": 81, - "h": 69 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 81, - "y": 201, - "w": 81, - "h": 69 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 81, - "y": 201, - "w": 81, - "h": 69 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 81, - "y": 201, - "w": 81, - "h": 69 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 81, - "y": 201, - "w": 81, - "h": 69 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 162, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 162, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 162, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 162, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 162, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 243, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 243, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 243, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 243, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 243, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 324, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 324, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 324, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 324, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 324, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 405, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 405, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 405, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 405, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 69 - }, - "frame": { - "x": 486, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 69 - }, - "frame": { - "x": 486, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 69 - }, - "frame": { - "x": 486, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 69 - }, - "frame": { - "x": 486, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 81, - "h": 69 - }, - "frame": { - "x": 486, - "y": 203, - "w": 81, - "h": 69 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 0, - "y": 270, - "w": 81, - "h": 69 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 0, - "y": 270, - "w": 81, - "h": 69 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 0, - "y": 270, - "w": 81, - "h": 69 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 0, - "y": 270, - "w": 81, - "h": 69 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 0, - "y": 270, - "w": 81, - "h": 69 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 81, - "y": 270, - "w": 81, - "h": 69 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 81, - "h": 69 - }, - "frame": { - "x": 81, - "y": 270, - "w": 81, - "h": 69 - } - }, - { - "filename": "0146.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 80, - "h": 69 - }, - "frame": { - "x": 162, - "y": 272, - "w": 80, - "h": 69 - } - }, - { - "filename": "0147.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 80, - "h": 69 - }, - "frame": { - "x": 162, - "y": 272, - "w": 80, - "h": 69 - } - }, - { - "filename": "0151.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 83, - "h": 69 - }, - "frame": { - "x": 242, - "y": 272, - "w": 83, - "h": 69 - } - }, - { - "filename": "0152.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 83, - "h": 69 - }, - "frame": { - "x": 242, - "y": 272, - "w": 83, - "h": 69 - } - }, - { - "filename": "0167.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 80, - "h": 69 - }, - "frame": { - "x": 325, - "y": 272, - "w": 80, - "h": 69 - } - }, - { - "filename": "0168.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 80, - "h": 69 - }, - "frame": { - "x": 325, - "y": 272, - "w": 80, - "h": 69 - } - }, - { - "filename": "0169.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 81, - "h": 69 - }, - "frame": { - "x": 405, - "y": 272, - "w": 81, - "h": 69 - } - }, - { - "filename": "0170.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 81, - "h": 69 - }, - "frame": { - "x": 405, - "y": 272, - "w": 81, - "h": 69 - } - }, - { - "filename": "0171.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 81, - "h": 69 - }, - "frame": { - "x": 405, - "y": 272, - "w": 81, - "h": 69 - } - }, - { - "filename": "0176.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 80, - "h": 69 - }, - "frame": { - "x": 486, - "y": 272, - "w": 80, - "h": 69 - } - }, - { - "filename": "0177.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 80, - "h": 69 - }, - "frame": { - "x": 486, - "y": 272, - "w": 80, - "h": 69 - } - }, - { - "filename": "0178.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 80, - "h": 69 - }, - "frame": { - "x": 486, - "y": 272, - "w": 80, - "h": 69 - } - }, - { - "filename": "0195.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 82, - "h": 69 - }, - "frame": { - "x": 0, - "y": 339, - "w": 82, - "h": 69 - } - }, - { - "filename": "0196.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 82, - "h": 69 - }, - "frame": { - "x": 0, - "y": 339, - "w": 82, - "h": 69 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 80, - "h": 70 - }, - "frame": { - "x": 82, - "y": 339, - "w": 80, - "h": 70 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 80, - "h": 70 - }, - "frame": { - "x": 82, - "y": 339, - "w": 80, - "h": 70 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 80, - "h": 70 - }, - "frame": { - "x": 82, - "y": 339, - "w": 80, - "h": 70 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 243, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 243, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 243, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 243, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 324, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 324, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 324, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 324, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 405, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 405, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 405, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 405, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 405, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 486, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 486, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 486, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 486, - "y": 341, - "w": 81, - "h": 70 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 0, - "y": 408, - "w": 81, - "h": 70 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 0, - "y": 408, - "w": 81, - "h": 70 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 0, - "y": 408, - "w": 81, - "h": 70 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 0, - "y": 408, - "w": 81, - "h": 70 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 0, - "y": 408, - "w": 81, - "h": 70 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 81, - "y": 409, - "w": 81, - "h": 70 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 81, - "y": 409, - "w": 81, - "h": 70 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 81, - "y": 409, - "w": 81, - "h": 70 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 81, - "y": 409, - "w": 81, - "h": 70 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 81, - "y": 409, - "w": 81, - "h": 70 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 243, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 243, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 243, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 243, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 70 - }, - "frame": { - "x": 324, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 70 - }, - "frame": { - "x": 324, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 70 - }, - "frame": { - "x": 324, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 70 - }, - "frame": { - "x": 324, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 81, - "h": 70 - }, - "frame": { - "x": 324, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0148.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 405, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0149.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 405, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0150.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 405, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0181.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 405, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0182.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 405, - "y": 411, - "w": 81, - "h": 70 - } - }, - { - "filename": "0160.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 83, - "h": 70 - }, - "frame": { - "x": 486, - "y": 411, - "w": 83, - "h": 70 - } - }, - { - "filename": "0161.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 83, - "h": 70 - }, - "frame": { - "x": 486, - "y": 411, - "w": 83, - "h": 70 - } - }, - { - "filename": "0165.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 0, - "y": 478, - "w": 81, - "h": 70 - } - }, - { - "filename": "0166.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 81, - "h": 70 - }, - "frame": { - "x": 0, - "y": 478, - "w": 81, - "h": 70 - } - }, - { - "filename": "0179.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 80, - "h": 70 - }, - "frame": { - "x": 81, - "y": 479, - "w": 80, - "h": 70 - } - }, - { - "filename": "0180.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 80, - "h": 70 - }, - "frame": { - "x": 81, - "y": 479, - "w": 80, - "h": 70 - } - }, - { - "filename": "0158.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 84, - "h": 70 - }, - "frame": { - "x": 161, - "y": 481, - "w": 84, - "h": 70 - } - }, - { - "filename": "0159.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 84, - "h": 70 - }, - "frame": { - "x": 161, - "y": 481, - "w": 84, - "h": 70 - } - }, - { - "filename": "0162.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 82, - "h": 70 - }, - "frame": { - "x": 245, - "y": 481, - "w": 82, - "h": 70 - } - }, - { - "filename": "0163.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 82, - "h": 70 - }, - "frame": { - "x": 245, - "y": 481, - "w": 82, - "h": 70 - } - }, - { - "filename": "0164.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 82, - "h": 70 - }, - "frame": { - "x": 245, - "y": 481, - "w": 82, - "h": 70 - } - }, - { - "filename": "0183.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 83, - "h": 70 - }, - "frame": { - "x": 327, - "y": 481, - "w": 83, - "h": 70 - } - }, - { - "filename": "0184.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 83, - "h": 70 - }, - "frame": { - "x": 327, - "y": 481, - "w": 83, - "h": 70 - } - }, - { - "filename": "0185.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 83, - "h": 70 - }, - "frame": { - "x": 327, - "y": 481, - "w": 83, - "h": 70 - } - }, - { - "filename": "0186.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 84, - "h": 70 - }, - "frame": { - "x": 410, - "y": 481, - "w": 84, - "h": 70 - } - }, - { - "filename": "0187.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 71 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 84, - "h": 70 - }, - "frame": { - "x": 410, - "y": 481, - "w": 84, - "h": 70 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:45b1919b351dad733f7b88701725e98a:30341f5f924f3632d0e938277cc51026:4e25ec866a209ce3a44bf419a5862c0c$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/female/3_2.png b/public/images/pokemon/variant/female/3_2.png deleted file mode 100644 index 8e955e2c82f..00000000000 Binary files a/public/images/pokemon/variant/female/3_2.png and /dev/null differ diff --git a/public/images/trainer/shelly.png b/public/images/trainer/shelly.png index 505dce1b110..2885fbde48e 100644 Binary files a/public/images/trainer/shelly.png and b/public/images/trainer/shelly.png differ diff --git a/public/locales b/public/locales index 6c6f0af398a..e07ab625f20 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit 6c6f0af398ae11f8d96c6ac064f171d927812c85 +Subproject commit e07ab625f2080afe36b61fad291b0ec5eff4000c diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 6849aae9576..a0022d15fc6 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -112,7 +112,7 @@ import { ExpGainsSpeed } from "#enums/exp-gains-speed"; import { BattlerTagType } from "#enums/battler-tag-type"; import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters"; import { StatusEffect } from "#enums/status-effect"; -import { globalScene, initGlobalScene } from "#app/global-scene"; +import { initGlobalScene } from "#app/global-scene"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; @@ -394,10 +394,10 @@ export default class BattleScene extends SceneBase { const originalRealInRange = Phaser.Math.RND.realInRange; Phaser.Math.RND.realInRange = function (min: number, max: number): number { const ret = originalRealInRange.apply(this, [ min, max ]); - const args = [ "RNG", ++globalScene.rngCounter, ret / (max - min), `min: ${min} / max: ${max}` ]; - args.push(`seed: ${globalScene.rngSeedOverride || globalScene.waveSeed || globalScene.seed}`); - if (globalScene.rngOffset) { - args.push(`offset: ${globalScene.rngOffset}`); + const args = [ "RNG", ++this.rngCounter, ret / (max - min), `min: ${min} / max: ${max}` ]; + args.push(`seed: ${this.rngSeedOverride || this.waveSeed || this.seed}`); + if (this.rngOffset) { + args.push(`offset: ${this.rngOffset}`); } console.log(...args); return ret; @@ -410,7 +410,7 @@ export default class BattleScene extends SceneBase { } create() { - globalScene.scene.remove(LoadingScene.KEY); + this.scene.remove(LoadingScene.KEY); initGameSpeed.apply(this); this.inputController = new InputsController(); this.uiInputs = new UiInputs(this.inputController); @@ -1849,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; @@ -2960,7 +2962,7 @@ export default class BattleScene extends SceneBase { */ applyShuffledModifiers(modifierType: Constructor, player: boolean = true, ...args: Parameters): T[] { let modifiers = (player ? this.modifiers : this.enemyModifiers).filter((m): m is T => m instanceof modifierType && m.shouldApply(...args)); - globalScene.executeWithSeedOffset(() => { + this.executeWithSeedOffset(() => { const shuffleModifiers = mods => { if (mods.length < 1) { return mods; @@ -2969,7 +2971,7 @@ export default class BattleScene extends SceneBase { return [ mods[rand], ...shuffleModifiers(mods.filter((_, i) => i !== rand)) ]; }; modifiers = shuffleModifiers(modifiers); - }, globalScene.currentBattle.turn << 4, globalScene.waveSeed); + }, this.currentBattle.turn << 4, this.waveSeed); return this.applyModifiersInternal(modifiers, player, args); } @@ -3394,7 +3396,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 @@ -3403,7 +3406,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/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/balance/starters.ts b/src/data/balance/starters.ts index ec66401675b..ee33142e981 100644 --- a/src/data/balance/starters.ts +++ b/src/data/balance/starters.ts @@ -51,9 +51,7 @@ export const speciesStarterCosts = { [Species.SANDSHREW]: 2, [Species.NIDORAN_F]: 3, [Species.NIDORAN_M]: 3, - [Species.CLEFAIRY]: 3, [Species.VULPIX]: 3, - [Species.JIGGLYPUFF]: 2, [Species.ZUBAT]: 3, [Species.ODDISH]: 3, [Species.PARAS]: 2, @@ -84,22 +82,15 @@ export const speciesStarterCosts = { [Species.VOLTORB]: 2, [Species.EXEGGCUTE]: 3, [Species.CUBONE]: 3, - [Species.HITMONLEE]: 4, - [Species.HITMONCHAN]: 4, [Species.LICKITUNG]: 3, [Species.KOFFING]: 2, [Species.RHYHORN]: 4, - [Species.CHANSEY]: 3, [Species.TANGELA]: 3, [Species.KANGASKHAN]: 4, [Species.HORSEA]: 3, [Species.GOLDEEN]: 2, [Species.STARYU]: 3, - [Species.MR_MIME]: 3, [Species.SCYTHER]: 5, - [Species.JYNX]: 4, - [Species.ELECTABUZZ]: 4, - [Species.MAGMAR]: 4, [Species.PINSIR]: 4, [Species.TAUROS]: 4, [Species.MAGIKARP]: 4, @@ -110,7 +101,6 @@ export const speciesStarterCosts = { [Species.OMANYTE]: 3, [Species.KABUTO]: 3, [Species.AERODACTYL]: 5, - [Species.SNORLAX]: 5, [Species.ARTICUNO]: 5, [Species.ZAPDOS]: 6, [Species.MOLTRES]: 6, @@ -132,8 +122,6 @@ export const speciesStarterCosts = { [Species.TOGEPI]: 3, [Species.NATU]: 2, [Species.MAREEP]: 2, - [Species.MARILL]: 4, - [Species.SUDOWOODO]: 3, [Species.HOPPIP]: 2, [Species.AIPOM]: 2, [Species.SUNKERN]: 1, @@ -142,7 +130,6 @@ export const speciesStarterCosts = { [Species.MURKROW]: 3, [Species.MISDREAVUS]: 2, [Species.UNOWN]: 1, - [Species.WOBBUFFET]: 2, [Species.GIRAFARIG]: 3, [Species.PINECO]: 2, [Species.DUNSPARCE]: 3, @@ -158,7 +145,6 @@ export const speciesStarterCosts = { [Species.CORSOLA]: 2, [Species.REMORAID]: 2, [Species.DELIBIRD]: 2, - [Species.MANTINE]: 3, [Species.SKARMORY]: 4, [Species.HOUNDOUR]: 3, [Species.PHANPY]: 3, @@ -206,7 +192,6 @@ export const speciesStarterCosts = { [Species.MINUN]: 2, [Species.VOLBEAT]: 2, [Species.ILLUMISE]: 2, - [Species.ROSELIA]: 3, [Species.GULPIN]: 1, [Species.CARVANHA]: 3, [Species.WAILMER]: 2, @@ -232,7 +217,6 @@ export const speciesStarterCosts = { [Species.SHUPPET]: 2, [Species.DUSKULL]: 3, [Species.TROPIUS]: 3, - [Species.CHIMECHO]: 3, [Species.ABSOL]: 4, [Species.WYNAUT]: 2, [Species.SNORUNT]: 2, @@ -543,7 +527,6 @@ export const speciesStarterCosts = { [Species.GALAR_PONYTA]: 2, [Species.GALAR_SLOWPOKE]: 3, [Species.GALAR_FARFETCHD]: 3, - [Species.GALAR_MR_MIME]: 3, [Species.GALAR_ARTICUNO]: 6, [Species.GALAR_ZAPDOS]: 6, [Species.GALAR_MOLTRES]: 6, 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/custom-pokemon-data.ts b/src/data/custom-pokemon-data.ts index 1c3bbbc3180..4a5eb89aeed 100644 --- a/src/data/custom-pokemon-data.ts +++ b/src/data/custom-pokemon-data.ts @@ -5,7 +5,8 @@ import type { Nature } from "#enums/nature"; /** * Data that can customize a Pokemon in non-standard ways from its Species - * Currently only used by Mystery Encounters and Mints. + * Used by Mystery Encounters and Mints + * Also used as a counter how often a Pokemon got hit until new arena encounter */ export class CustomPokemonData { public spriteScale: number; @@ -13,6 +14,8 @@ export class CustomPokemonData { public passive: Abilities | -1; public nature: Nature | -1; public types: Type[]; + /** `hitsReceivedCount` aka `hitsRecCount` saves how often the pokemon got hit until a new arena encounter (used for Rage Fist) */ + public hitsRecCount: number; constructor(data?: CustomPokemonData | Partial) { if (!isNullOrUndefined(data)) { @@ -24,5 +27,10 @@ export class CustomPokemonData { this.passive = this.passive ?? -1; this.nature = this.nature ?? -1; this.types = this.types ?? []; + this.hitsRecCount = this.hitsRecCount ?? 0; + } + + resetHitReceivedCount(): void { + this.hitsRecCount = 0; } } diff --git a/src/data/move.ts b/src/data/move.ts index a7ce2b98954..f6a8f72ebab 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3993,12 +3993,32 @@ export class FriendshipPowerAttr extends VariablePowerAttr { } } -export class HitCountPowerAttr extends VariablePowerAttr { +/** + * This Attribute calculates the current power of {@linkcode Moves.RAGE_FIST}. + * The counter for power calculation does not reset on every wave but on every new arena encounter + */ +export class RageFistPowerAttr extends VariablePowerAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - (args[0] as Utils.NumberHolder).value += Math.min(user.battleData.hitCount, 6) * 50; + const { hitCount, prevHitCount } = user.battleData; + const basePower: Utils.NumberHolder = args[0]; + + this.updateHitReceivedCount(user, hitCount, prevHitCount); + + basePower.value = 50 + (Math.min(user.customPokemonData.hitsRecCount, 6) * 50); return true; } + + /** + * Updates the number of hits the Pokemon has taken in battle + * @param user Pokemon calling Rage Fist + * @param hitCount The number of received hits this battle + * @param previousHitCount The number of received hits this battle since last time Rage Fist was used + */ + protected updateHitReceivedCount(user: Pokemon, hitCount: number, previousHitCount: number): void { + user.customPokemonData.hitsRecCount += (hitCount - previousHitCount); + user.battleData.prevHitCount = hitCount; + } } /** @@ -11008,8 +11028,8 @@ export function initMoves() { new AttackMove(Moves.TWIN_BEAM, Type.PSYCHIC, MoveCategory.SPECIAL, 40, 100, 10, -1, 0, 9) .attr(MultiHitAttr, MultiHitType._2), new AttackMove(Moves.RAGE_FIST, Type.GHOST, MoveCategory.PHYSICAL, 50, 100, 10, -1, 0, 9) - .partial() // Counter resets every wave instead of on arena reset - .attr(HitCountPowerAttr) + .edgeCase() // Counter incorrectly increases on confusion self-hits + .attr(RageFistPowerAttr) .punchingMove(), new AttackMove(Moves.ARMOR_CANNON, Type.FIRE, MoveCategory.SPECIAL, 120, 100, 5, -1, 0, 9) .attr(StatStageChangeAttr, [ Stat.DEF, Stat.SPDEF ], -1, true), 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/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/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index 8768fb06b37..a144b1ac5c5 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, !isNullOrUndefined(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/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/pokemon.ts b/src/field/pokemon.ts index 56c724ef51a..1b987ba34f6 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -10,7 +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 { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters"; import { starterPassiveAbilities } from "#app/data/balance/passives"; import type { Constructor } from "#app/utils"; import { isNullOrUndefined, randSeedInt, type nil } from "#app/utils"; @@ -1956,7 +1956,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; @@ -1968,7 +1968,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(); @@ -2059,6 +2059,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()) { @@ -2392,8 +2424,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)) { @@ -3607,6 +3644,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!this.canSetStatus(effect, asPhase, false, sourcePokemon)) { return false; } + if (this.isFainted() && effect !== StatusEffect.FAINT) { + return false; + } /** * If this Pokemon falls asleep or freezes in the middle of a multi-hit attack, @@ -4321,10 +4361,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 @@ -5283,7 +5320,10 @@ export class PokemonSummonData { } export class PokemonBattleData { + /** counts the hits the pokemon received */ public hitCount: number = 0; + /** used for {@linkcode Moves.RAGE_FIST} in order to save hit Counts received before Rage Fist is applied */ + public prevHitCount: number = 0; public endured: boolean = false; public berriesEaten: BerryType[] = []; public abilitiesApplied: Abilities[] = []; 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/modifier/modifier.ts b/src/modifier/modifier.ts index 37f88deea7f..c51fa129efe 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -3183,12 +3183,12 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier { break; } } - const randItemIndex = pokemon.randSeedInt(itemModifiers.length); - const randItem = itemModifiers[randItemIndex]; + const randItemIndex = pokemon.randSeedInt(tierItemModifiers.length); + const randItem = tierItemModifiers[randItemIndex]; heldItemTransferPromises.push(globalScene.tryTransferHeldItemModifier(randItem, pokemon, false).then(success => { if (success) { transferredModifierTypes.push(randItem.type); - itemModifiers.splice(randItemIndex, 1); + tierItemModifiers.splice(randItemIndex, 1); } })); } diff --git a/src/overrides.ts b/src/overrides.ts index 9d4d7af02fb..06ad619a074 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -1,19 +1,20 @@ +/* eslint-disable @typescript-eslint/consistent-type-imports */ import { type PokeballCounts } from "#app/battle-scene"; -import type { Gender } from "#app/data/gender"; -import type { Variant } from "#app/data/variant"; +import { Gender } from "#app/data/gender"; +import { Variant } from "#app/data/variant"; import { type ModifierOverride } from "#app/modifier/modifier-type"; -import type { Unlockables } from "#app/system/unlockables"; +import { Unlockables } from "#app/system/unlockables"; import { Abilities } from "#enums/abilities"; import { Biome } from "#enums/biome"; -import type { EggTier } from "#enums/egg-type"; -import type { Moves } from "#enums/moves"; -import type { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; -import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; +import { EggTier } from "#enums/egg-type"; +import { Moves } from "#enums/moves"; +import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; +import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { PokeballType } from "#enums/pokeball"; -import type { Species } from "#enums/species"; +import { Species } from "#enums/species"; import { StatusEffect } from "#enums/status-effect"; -import type { TimeOfDay } from "#enums/time-of-day"; -import type { VariantTier } from "#enums/variant-tier"; +import { TimeOfDay } from "#enums/time-of-day"; +import { VariantTier } from "#enums/variant-tier"; import { WeatherType } from "#enums/weather-type"; /** @@ -62,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/encounter-phase.ts b/src/phases/encounter-phase.ts index 6dae7dff8f9..353dd6681cb 100644 --- a/src/phases/encounter-phase.ts +++ b/src/phases/encounter-phase.ts @@ -104,6 +104,12 @@ export class EncounterPhase extends BattlePhase { } if (!this.loaded) { if (battle.battleType === BattleType.TRAINER) { + //resets hitRecCount during Trainer ecnounter + for (const pokemon of globalScene.getPlayerParty()) { + if (pokemon) { + pokemon.customPokemonData.resetHitReceivedCount(); + } + } battle.enemyParty[e] = battle.trainer?.genPartyMember(e)!; // TODO:: is the bang correct here? } else { let enemySpecies = globalScene.randomSpecies(battle.waveIndex, level, true); diff --git a/src/phases/new-biome-encounter-phase.ts b/src/phases/new-biome-encounter-phase.ts index be6815333e5..2de9a4300c5 100644 --- a/src/phases/new-biome-encounter-phase.ts +++ b/src/phases/new-biome-encounter-phase.ts @@ -14,6 +14,7 @@ export class NewBiomeEncounterPhase extends NextEncounterPhase { for (const pokemon of globalScene.getPlayerParty()) { if (pokemon) { pokemon.resetBattleData(); + pokemon.customPokemonData.resetHitReceivedCount(); } } diff --git a/src/phases/trainer-victory-phase.ts b/src/phases/trainer-victory-phase.ts index 3fa7209751a..9722e9c4197 100644 --- a/src/phases/trainer-victory-phase.ts +++ b/src/phases/trainer-victory-phase.ts @@ -29,7 +29,7 @@ export class TrainerVictoryPhase extends BattlePhase { globalScene.unshiftPhase(new ModifierRewardPhase(modifierRewardFunc)); } - if (globalScene.eventManager.isEventActive()) { + if (globalScene.eventManager.getShinyMultiplier() > 1) { //If a shiny boosting event is active for (const rewardFunc of globalScene.currentBattle.trainer?.config.eventRewardFuncs!) { globalScene.unshiftPhase(new ModifierRewardPhase(rewardFunc)); } @@ -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 845739dfcac..cc798bc8585 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/achv.ts b/src/system/achv.ts index a2777101186..e0c9f0cf052 100644 --- a/src/system/achv.ts +++ b/src/system/achv.ts @@ -292,7 +292,6 @@ export function getAchievementDescription(localizationKey: string): string { } - export const achvs = { _10K_MONEY: new MoneyAchv("10K_MONEY", "", 10000, "nugget", 10), _100K_MONEY: new MoneyAchv("100K_MONEY", "", 100000, "big_nugget", 25).setSecret(true), @@ -365,7 +364,7 @@ export const achvs = { FRESH_START: new ChallengeAchv("FRESH_START", "", "FRESH_START.description", "reviver_seed", 100, (c) => c instanceof FreshStartChallenge && c.value > 0 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)), INVERSE_BATTLE: new ChallengeAchv("INVERSE_BATTLE", "", "INVERSE_BATTLE.description", "inverse", 100, (c) => c instanceof InverseBattleChallenge && c.value > 0), FLIP_STATS: new ChallengeAchv("FLIP_STATS", "", "FLIP_STATS.description", "dubious_disc", 100, (c) => c instanceof FlipStatChallenge && c.value > 0), - FLIP_INVERSE: new ChallengeAchv("FLIP_INVERSE", "", "FLIP_INVERSE.description", "cracked_pot", 100, (c) => c instanceof FlipStatChallenge && c.value > 0 && globalScene.gameMode.challenges.every(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)).setSecret(), + FLIP_INVERSE: new ChallengeAchv("FLIP_INVERSE", "", "FLIP_INVERSE.description", "cracked_pot", 100, (c) => c instanceof FlipStatChallenge && c.value > 0 && globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)).setSecret(), BREEDERS_IN_SPACE: new Achv("BREEDERS_IN_SPACE", "", "BREEDERS_IN_SPACE.description", "moon_stone", 50).setSecret(), }; diff --git a/src/test/data/status-effect.test.ts b/src/test/data/status_effect.test.ts similarity index 92% rename from src/test/data/status-effect.test.ts rename to src/test/data/status_effect.test.ts index 4831e8de5de..7948549b8e8 100644 --- a/src/test/data/status-effect.test.ts +++ b/src/test/data/status_effect.test.ts @@ -400,4 +400,42 @@ describe("Status Effects", () => { expect(player.getLastXMoves(1)[0].result).toBe(MoveResult.SUCCESS); }); }); + + describe("Behavior", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([ Moves.SPLASH ]) + .ability(Abilities.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.NUZZLE) + .enemyLevel(2000); + }); + + it("should not inflict a 0 HP mon with a status", async () => { + await game.classicMode.startBattle([ Species.FEEBAS, Species.MILOTIC ]); + + const player = game.scene.getPlayerPokemon()!; + player.hp = 0; + + expect(player.trySetStatus(StatusEffect.BURN)).toBe(false); + expect(player.status?.effect).not.toBe(StatusEffect.BURN); + }); + }); }); diff --git a/src/test/moves/rage_fist.test.ts b/src/test/moves/rage_fist.test.ts new file mode 100644 index 00000000000..a85be5a88d9 --- /dev/null +++ b/src/test/moves/rage_fist.test.ts @@ -0,0 +1,143 @@ +import { BattlerIndex } from "#app/battle"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { allMoves } from "#app/data/move"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +describe("Moves - Rage Fist", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + const move = allMoves[Moves.RAGE_FIST]; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .battleType("single") + .moveset([ Moves.RAGE_FIST, Moves.SPLASH, Moves.SUBSTITUTE ]) + .startingLevel(100) + .enemyLevel(1) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.DOUBLE_KICK); + + vi.spyOn(move, "calculateBattlePower"); + }); + + it("should have 100 more power if hit twice before calling Rage Fist", async () => { + game.override + .enemySpecies(Species.MAGIKARP); + + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + game.move.select(Moves.RAGE_FIST); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(move.calculateBattlePower).toHaveLastReturnedWith(150); + }); + + it("should maintain its power during next battle if it is within the same arena encounter", async () => { + game.override + .enemySpecies(Species.MAGIKARP) + .startingWave(1); + + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + game.move.select(Moves.RAGE_FIST); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.toNextWave(); + + game.move.select(Moves.RAGE_FIST); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.phaseInterceptor.to("BerryPhase", false); + + expect(move.calculateBattlePower).toHaveLastReturnedWith(250); + }); + + it("should reset the hitRecCounter if we enter new trainer battle", async () => { + game.override + .enemySpecies(Species.MAGIKARP) + .startingWave(4); + + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + game.move.select(Moves.RAGE_FIST); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.toNextWave(); + + game.move.select(Moves.RAGE_FIST); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.phaseInterceptor.to("BerryPhase", false); + + expect(move.calculateBattlePower).toHaveLastReturnedWith(150); + }); + + it("should not increase the hitCounter if Substitute is hit", async () => { + game.override + .enemySpecies(Species.MAGIKARP) + .startingWave(4); + + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + game.move.select(Moves.SUBSTITUTE); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + await game.phaseInterceptor.to("MoveEffectPhase"); + + expect(game.scene.getPlayerPokemon()?.customPokemonData.hitsRecCount).toBe(0); + }); + + it("should reset the hitRecCounter if we enter new biome", async () => { + game.override + .enemySpecies(Species.MAGIKARP) + .startingWave(10); + + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + game.move.select(Moves.RAGE_FIST); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.toNextTurn(); + + game.move.select(Moves.RAGE_FIST); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.phaseInterceptor.to("BerryPhase", false); + + expect(move.calculateBattlePower).toHaveLastReturnedWith(150); + }); + + it("should not reset the hitRecCounter if switched out", async () => { + game.override + .enemySpecies(Species.MAGIKARP) + .startingWave(1) + .enemyMoveset(Moves.TACKLE); + + await game.classicMode.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); + + game.move.select(Moves.SPLASH); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.toNextTurn(); + + game.doSwitchPokemon(1); + await game.toNextTurn(); + + game.doSwitchPokemon(1); + await game.toNextTurn(); + + game.move.select(Moves.RAGE_FIST); + await game.phaseInterceptor.to("MoveEndPhase"); + + expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(Species.CHARIZARD); + expect(move.calculateBattlePower).toHaveLastReturnedWith(150); + }); +}); 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/utils/helpers/moveHelper.ts b/src/test/utils/helpers/moveHelper.ts index 02f9d1ef3b3..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"; @@ -91,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 e4faa838d91..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 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..8633460d98c 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: [], + 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/dropdown.ts b/src/ui/dropdown.ts index ec124312e14..8c318b29d64 100644 --- a/src/ui/dropdown.ts +++ b/src/ui/dropdown.ts @@ -7,7 +7,9 @@ export enum DropDownState { ON = 0, OFF = 1, EXCLUDE = 2, - UNLOCKABLE = 3 + UNLOCKABLE = 3, + ONE = 4, + TWO = 5 } export enum DropDownType { @@ -27,7 +29,9 @@ export enum SortCriteria { COST = 1, CANDY = 2, IV = 3, - NAME = 4 + NAME = 4, + CAUGHT = 5, + HATCHED = 6 } export class DropDownLabel { @@ -55,6 +59,8 @@ export class DropDownOption extends Phaser.GameObjects.Container { private offColor = 0x272727; private excludeColor = 0xff5555; private unlockableColor = 0xffff00; + private oneColor = 0x33bbff; + private twoColor = 0x33bbff; constructor(val: any, labels: DropDownLabel | DropDownLabel[]) { super(globalScene); @@ -126,6 +132,12 @@ export class DropDownOption extends Phaser.GameObjects.Container { case DropDownState.UNLOCKABLE: this.toggle.setTint(this.unlockableColor); break; + case DropDownState.ONE: + this.toggle.setTint(this.oneColor); + break; + case DropDownState.TWO: + this.toggle.setTint(this.twoColor); + break; } } diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 40325d24af7..dd427802083 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -450,6 +450,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const costReductionLabels = [ new DropDownLabel(i18next.t("filterBar:costReduction"), undefined, DropDownState.OFF), new DropDownLabel(i18next.t("filterBar:costReductionUnlocked"), undefined, DropDownState.ON), + new DropDownLabel(i18next.t("filterBar:costReductionUnlockedOne"), undefined, DropDownState.ONE), + new DropDownLabel(i18next.t("filterBar:costReductionUnlockedTwo"), undefined, DropDownState.TWO), new DropDownLabel(i18next.t("filterBar:costReductionUnlockable"), undefined, DropDownState.UNLOCKABLE), new DropDownLabel(i18next.t("filterBar:costReductionLocked"), undefined, DropDownState.EXCLUDE), ]; @@ -500,7 +502,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler { new DropDownOption(SortCriteria.COST, new DropDownLabel(i18next.t("filterBar:sortByCost"))), new DropDownOption(SortCriteria.CANDY, new DropDownLabel(i18next.t("filterBar:sortByCandies"))), new DropDownOption(SortCriteria.IV, new DropDownLabel(i18next.t("filterBar:sortByIVs"))), - new DropDownOption(SortCriteria.NAME, new DropDownLabel(i18next.t("filterBar:sortByName"))) + new DropDownOption(SortCriteria.NAME, new DropDownLabel(i18next.t("filterBar:sortByName"))), + new DropDownOption(SortCriteria.CAUGHT, new DropDownLabel(i18next.t("filterBar:sortByNumCaught"))), + new DropDownOption(SortCriteria.HATCHED, new DropDownLabel(i18next.t("filterBar:sortByNumHatched"))) ]; this.filterBar.addFilter(DropDownColumn.SORT, i18next.t("filterBar:sortFilter"), new DropDown(0, 0, sortOptions, this.updateStarters, DropDownType.SINGLE)); this.filterBarContainer.add(this.filterBar); @@ -2585,13 +2589,18 @@ export default class StarterSelectUiHandler extends MessageUiHandler { }); // Cost Reduction Filter - const isCostReduced = starterData.valueReduction > 0; + const isCostReducedByOne = starterData.valueReduction === 1; + const isCostReducedByTwo = starterData.valueReduction === 2; const isCostReductionUnlockable = this.isValueReductionAvailable(container.species.speciesId); const fitsCostReduction = this.filterBar.getVals(DropDownColumn.UNLOCKS).some(unlocks => { if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.ON) { - return isCostReduced; + return isCostReducedByOne || isCostReducedByTwo; + } else if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.ONE) { + return isCostReducedByOne; + } else if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.TWO) { + return isCostReducedByTwo; } else if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.EXCLUDE) { - return isStarterProgressable && !isCostReduced; + return isStarterProgressable && !(isCostReducedByOne || isCostReducedByTwo); } else if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.UNLOCKABLE) { return isCostReductionUnlockable; } else if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.OFF) { @@ -2691,6 +2700,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler { return (avgIVsA - avgIVsB) * -sort.dir; case SortCriteria.NAME: return a.species.name.localeCompare(b.species.name) * -sort.dir; + case SortCriteria.CAUGHT: + return (globalScene.gameData.dexData[a.species.speciesId].caughtCount - globalScene.gameData.dexData[b.species.speciesId].caughtCount) * -sort.dir; + case SortCriteria.HATCHED: + return (globalScene.gameData.dexData[a.species.speciesId].hatchedCount - globalScene.gameData.dexData[b.species.speciesId].hatchedCount) * -sort.dir; } return 0; }); diff --git a/src/utils.ts b/src/utils.ts index be0aec84ecd..2235fb69633 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -349,14 +349,14 @@ export class IntegerHolder extends NumberHolder { } } -/** @deprecated Use {@linkcode NumberHolder}*/ -export class FixedInt extends IntegerHolder { - constructor(value: integer) { - super(value); +export class FixedInt { + public readonly value: number; + + constructor(value: number) { + this.value = value; } } -/** @deprecated */ export function fixedInt(value: integer): integer { return new FixedInt(value) as unknown as integer; }