diff --git a/public/images/pokemon/variant/890-eternamax_2.png b/public/images/pokemon/variant/890-eternamax_2.png index 30c8333a431..b5aab00c241 100644 Binary files a/public/images/pokemon/variant/890-eternamax_2.png and b/public/images/pokemon/variant/890-eternamax_2.png differ diff --git a/public/images/pokemon/variant/890-eternamax_3.png b/public/images/pokemon/variant/890-eternamax_3.png index 48cd4dbe14a..29a3d84c0d6 100644 Binary files a/public/images/pokemon/variant/890-eternamax_3.png and b/public/images/pokemon/variant/890-eternamax_3.png differ diff --git a/public/images/pokemon/variant/exp/890-eternamax_2.json b/public/images/pokemon/variant/exp/890-eternamax_2.json new file mode 100644 index 00000000000..895a2f27841 --- /dev/null +++ b/public/images/pokemon/variant/exp/890-eternamax_2.json @@ -0,0 +1,755 @@ +{ + "textures": [ + { + "image": "890-eternamax_2.png", + "format": "RGBA8888", + "size": { + "w": 579, + "h": 579 + }, + "scale": 1, + "frames": [ + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 9, + "w": 100, + "h": 98 + }, + "frame": { + "x": 0, + "y": 0, + "w": 100, + "h": 98 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 95, + "h": 100 + }, + "frame": { + "x": 100, + "y": 0, + "w": 95, + "h": 100 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 8, + "w": 91, + "h": 100 + }, + "frame": { + "x": 0, + "y": 98, + "w": 91, + "h": 100 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 9, + "w": 96, + "h": 98 + }, + "frame": { + "x": 91, + "y": 100, + "w": 96, + "h": 98 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 9, + "w": 95, + "h": 99 + }, + "frame": { + "x": 187, + "y": 100, + "w": 95, + "h": 99 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 9, + "y": 10, + "w": 91, + "h": 98 + }, + "frame": { + "x": 0, + "y": 198, + "w": 91, + "h": 98 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 10, + "w": 88, + "h": 98 + }, + "frame": { + "x": 91, + "y": 198, + "w": 88, + "h": 98 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 10, + "w": 95, + "h": 97 + }, + "frame": { + "x": 195, + "y": 0, + "w": 95, + "h": 97 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 11, + "w": 95, + "h": 97 + }, + "frame": { + "x": 179, + "y": 199, + "w": 95, + "h": 97 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 11, + "w": 95, + "h": 97 + }, + "frame": { + "x": 274, + "y": 199, + "w": 95, + "h": 97 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 11, + "w": 95, + "h": 97 + }, + "frame": { + "x": 290, + "y": 0, + "w": 95, + "h": 97 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 11, + "w": 94, + "h": 96 + }, + "frame": { + "x": 282, + "y": 97, + "w": 94, + "h": 96 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 11, + "w": 90, + "h": 97 + }, + "frame": { + "x": 369, + "y": 193, + "w": 90, + "h": 97 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 13, + "w": 93, + "h": 95 + }, + "frame": { + "x": 385, + "y": 0, + "w": 93, + "h": 95 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 13, + "y": 9, + "w": 91, + "h": 96 + }, + "frame": { + "x": 385, + "y": 95, + "w": 91, + "h": 96 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 87, + "h": 97 + }, + "frame": { + "x": 369, + "y": 290, + "w": 87, + "h": 97 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 12, + "w": 90, + "h": 96 + }, + "frame": { + "x": 456, + "y": 290, + "w": 90, + "h": 96 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 8, + "w": 90, + "h": 96 + }, + "frame": { + "x": 459, + "y": 191, + "w": 90, + "h": 96 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 13, + "y": 8, + "w": 90, + "h": 95 + }, + "frame": { + "x": 476, + "y": 95, + "w": 90, + "h": 95 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 89, + "h": 95 + }, + "frame": { + "x": 478, + "y": 0, + "w": 89, + "h": 95 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 12, + "w": 89, + "h": 96 + }, + "frame": { + "x": 456, + "y": 386, + "w": 89, + "h": 96 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 11, + "w": 89, + "h": 95 + }, + "frame": { + "x": 0, + "y": 296, + "w": 89, + "h": 95 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 9, + "y": 14, + "w": 89, + "h": 94 + }, + "frame": { + "x": 89, + "y": 296, + "w": 89, + "h": 94 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 88, + "h": 95 + }, + "frame": { + "x": 178, + "y": 296, + "w": 88, + "h": 95 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 87, + "h": 95 + }, + "frame": { + "x": 89, + "y": 390, + "w": 87, + "h": 95 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 12, + "w": 89, + "h": 94 + }, + "frame": { + "x": 0, + "y": 391, + "w": 89, + "h": 94 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 14, + "w": 89, + "h": 93 + }, + "frame": { + "x": 266, + "y": 387, + "w": 89, + "h": 93 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 16, + "y": 13, + "w": 85, + "h": 91 + }, + "frame": { + "x": 266, + "y": 296, + "w": 85, + "h": 91 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 13, + "w": 88, + "h": 94 + }, + "frame": { + "x": 176, + "y": 391, + "w": 88, + "h": 94 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 13, + "w": 87, + "h": 94 + }, + "frame": { + "x": 355, + "y": 387, + "w": 87, + "h": 94 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 16, + "y": 11, + "w": 87, + "h": 94 + }, + "frame": { + "x": 264, + "y": 480, + "w": 87, + "h": 94 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 14, + "w": 89, + "h": 93 + }, + "frame": { + "x": 351, + "y": 481, + "w": 89, + "h": 93 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 87, + "h": 93 + }, + "frame": { + "x": 440, + "y": 482, + "w": 87, + "h": 93 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 13, + "y": 10, + "w": 86, + "h": 94 + }, + "frame": { + "x": 0, + "y": 485, + "w": 86, + "h": 94 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 13, + "y": 14, + "w": 85, + "h": 91 + }, + "frame": { + "x": 86, + "y": 485, + "w": 85, + "h": 91 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:8fd9e1830200ec8e4aac8571cc2d27a6:c966e3efce03c7bae43d7bca6d6dfa62:cedd2711a12bbacba5623505fe88bd92$" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/exp/890-eternamax_3.json b/public/images/pokemon/variant/exp/890-eternamax_3.json new file mode 100644 index 00000000000..ecc084c689f --- /dev/null +++ b/public/images/pokemon/variant/exp/890-eternamax_3.json @@ -0,0 +1,755 @@ +{ + "textures": [ + { + "image": "890-eternamax_3.png", + "format": "RGBA8888", + "size": { + "w": 579, + "h": 579 + }, + "scale": 1, + "frames": [ + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 9, + "w": 100, + "h": 98 + }, + "frame": { + "x": 0, + "y": 0, + "w": 100, + "h": 98 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 95, + "h": 100 + }, + "frame": { + "x": 100, + "y": 0, + "w": 95, + "h": 100 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 8, + "w": 91, + "h": 100 + }, + "frame": { + "x": 0, + "y": 98, + "w": 91, + "h": 100 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 9, + "w": 96, + "h": 98 + }, + "frame": { + "x": 91, + "y": 100, + "w": 96, + "h": 98 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 9, + "w": 95, + "h": 99 + }, + "frame": { + "x": 187, + "y": 100, + "w": 95, + "h": 99 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 9, + "y": 10, + "w": 91, + "h": 98 + }, + "frame": { + "x": 0, + "y": 198, + "w": 91, + "h": 98 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 10, + "w": 88, + "h": 98 + }, + "frame": { + "x": 91, + "y": 198, + "w": 88, + "h": 98 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 10, + "w": 95, + "h": 97 + }, + "frame": { + "x": 195, + "y": 0, + "w": 95, + "h": 97 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 11, + "w": 95, + "h": 97 + }, + "frame": { + "x": 179, + "y": 199, + "w": 95, + "h": 97 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 11, + "w": 95, + "h": 97 + }, + "frame": { + "x": 274, + "y": 199, + "w": 95, + "h": 97 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 11, + "w": 95, + "h": 97 + }, + "frame": { + "x": 290, + "y": 0, + "w": 95, + "h": 97 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 11, + "w": 94, + "h": 96 + }, + "frame": { + "x": 282, + "y": 97, + "w": 94, + "h": 96 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 11, + "w": 90, + "h": 97 + }, + "frame": { + "x": 369, + "y": 193, + "w": 90, + "h": 97 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 8, + "y": 13, + "w": 93, + "h": 95 + }, + "frame": { + "x": 385, + "y": 0, + "w": 93, + "h": 95 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 13, + "y": 9, + "w": 91, + "h": 96 + }, + "frame": { + "x": 385, + "y": 95, + "w": 91, + "h": 96 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 87, + "h": 97 + }, + "frame": { + "x": 369, + "y": 290, + "w": 87, + "h": 97 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 12, + "w": 90, + "h": 96 + }, + "frame": { + "x": 456, + "y": 290, + "w": 90, + "h": 96 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 8, + "w": 90, + "h": 96 + }, + "frame": { + "x": 459, + "y": 191, + "w": 90, + "h": 96 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 13, + "y": 8, + "w": 90, + "h": 95 + }, + "frame": { + "x": 476, + "y": 95, + "w": 90, + "h": 95 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 89, + "h": 95 + }, + "frame": { + "x": 478, + "y": 0, + "w": 89, + "h": 95 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 12, + "w": 89, + "h": 96 + }, + "frame": { + "x": 456, + "y": 386, + "w": 89, + "h": 96 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 11, + "w": 89, + "h": 95 + }, + "frame": { + "x": 0, + "y": 296, + "w": 89, + "h": 95 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 9, + "y": 14, + "w": 89, + "h": 94 + }, + "frame": { + "x": 89, + "y": 296, + "w": 89, + "h": 94 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 88, + "h": 95 + }, + "frame": { + "x": 178, + "y": 296, + "w": 88, + "h": 95 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 87, + "h": 95 + }, + "frame": { + "x": 89, + "y": 390, + "w": 87, + "h": 95 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 12, + "w": 89, + "h": 94 + }, + "frame": { + "x": 0, + "y": 391, + "w": 89, + "h": 94 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 14, + "w": 89, + "h": 93 + }, + "frame": { + "x": 266, + "y": 387, + "w": 89, + "h": 93 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 16, + "y": 13, + "w": 85, + "h": 91 + }, + "frame": { + "x": 266, + "y": 296, + "w": 85, + "h": 91 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 13, + "w": 88, + "h": 94 + }, + "frame": { + "x": 176, + "y": 391, + "w": 88, + "h": 94 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 13, + "w": 87, + "h": 94 + }, + "frame": { + "x": 355, + "y": 387, + "w": 87, + "h": 94 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 16, + "y": 11, + "w": 87, + "h": 94 + }, + "frame": { + "x": 264, + "y": 480, + "w": 87, + "h": 94 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 11, + "y": 14, + "w": 89, + "h": 93 + }, + "frame": { + "x": 351, + "y": 481, + "w": 89, + "h": 93 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 87, + "h": 93 + }, + "frame": { + "x": 440, + "y": 482, + "w": 87, + "h": 93 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 13, + "y": 10, + "w": 86, + "h": 94 + }, + "frame": { + "x": 0, + "y": 485, + "w": 86, + "h": 94 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 112, + "h": 112 + }, + "spriteSourceSize": { + "x": 13, + "y": 14, + "w": 85, + "h": 91 + }, + "frame": { + "x": 86, + "y": 485, + "w": 85, + "h": 91 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:8fd9e1830200ec8e4aac8571cc2d27a6:c966e3efce03c7bae43d7bca6d6dfa62:cedd2711a12bbacba5623505fe88bd92$" + } +} \ No newline at end of file diff --git a/src/battle.ts b/src/battle.ts index 580bad9a508..601cbeb9cb6 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -11,6 +11,7 @@ import { BattleSpec } from "./enums/battle-spec"; import { PlayerGender } from "./system/game-data"; import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier"; import { MoneyAchv } from "./system/achv"; +import { PokeballType } from "./data/pokeball"; export enum BattleType { WILD, @@ -61,6 +62,7 @@ export default class Battle { public battleSeed: string; private battleSeedState: string; public moneyScattered: number; + public lastUsedPokeball: PokeballType; private rngCounter: integer = 0; @@ -86,6 +88,7 @@ export default class Battle { this.battleSeed = Utils.randomString(16, true); this.battleSeedState = null; this.moneyScattered = 0; + this.lastUsedPokeball = null; } private initBattleSpec(): void { diff --git a/src/data/ability.ts b/src/data/ability.ts index a257525efd0..2c472871bab 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -22,6 +22,7 @@ import i18next, { Localizable } from "#app/plugins/i18n.js"; import { Command } from "../ui/command-ui-handler"; import Battle from "#app/battle.js"; import { ability } from "#app/locales/en/ability.js"; +import { PokeballType, getPokeballName } from "./pokeball"; export class Ability implements Localizable { public id: Abilities; @@ -1822,6 +1823,36 @@ export class MultCritAbAttr extends AbAttr { } } +/** + * Guarantees a critical hit according to the given condition, except if target prevents critical hits. ie. Merciless + * @extends AbAttr + * @see {@linkcode apply} + */ +export class ConditionalCritAbAttr extends AbAttr { + private condition: PokemonAttackCondition; + + constructor(condition: PokemonAttackCondition, checkUser?: Boolean) { + super(); + + this.condition = condition; + } + + /** + * @param pokemon {@linkcode Pokemon} user. + * @param args [0] {@linkcode Utils.BooleanHolder} If true critical hit is guaranteed. + * [1] {@linkcode Pokemon} Target. + * [2] {@linkcode Move} used by ability user. + */ + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const target = (args[1] as Pokemon); + const move = (args[2] as Move); + if(!this.condition(pokemon,target,move)) + return false; + + (args[0] as Utils.BooleanHolder).value = true; + return true; + } +} export class BlockNonDirectDamageAbAttr extends AbAttr { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { @@ -2246,6 +2277,33 @@ export class PostTurnFormChangeAbAttr extends PostTurnAbAttr { } } +/** + * Grabs the last failed Pokeball used + * @extends PostTurnAbAttr + * @see {@linkcode applyPostTurn} */ +export class FetchBallAbAttr extends PostTurnAbAttr { + constructor() { + super(); + } + /** + * Adds the last used Pokeball back into the player's inventory + * @param pokemon {@linkcode Pokemon} with this ability + * @param passive N/A + * @param args N/A + * @returns true if player has used a pokeball and this pokemon is owned by the player + */ + applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { + let lastUsed = pokemon.scene.currentBattle.lastUsedPokeball; + if(lastUsed != null && pokemon.isPlayer) { + pokemon.scene.pokeballCounts[lastUsed]++; + pokemon.scene.currentBattle.lastUsedPokeball = null; + pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` found a\n${getPokeballName(lastUsed)}!`)); + return true; + } + return false; + } +} + export class PostBiomeChangeAbAttr extends AbAttr { } export class PostBiomeChangeWeatherChangeAbAttr extends PostBiomeChangeAbAttr { @@ -2338,18 +2396,42 @@ export class RunSuccessAbAttr extends AbAttr { } } +/** + * Base class for checking if a Pokemon is trapped by arena trap + * @extends AbAttr + * @see {@linkcode applyCheckTrapped} + */ export class CheckTrappedAbAttr extends AbAttr { constructor() { super(false); } - - applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, args: any[]): boolean | Promise { + + applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, args: any[]): boolean | Promise { return false; } } +/** + * Determines whether a Pokemon is blocked from switching/running away + * because of a trapping ability or move. + * @extends CheckTrappedAbAttr + * @see {@linkcode applyCheckTrapped} + */ export class ArenaTrapAbAttr extends CheckTrappedAbAttr { - applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, args: any[]): boolean { + /** + * Checks if enemy Pokemon is trapped by an Arena Trap-esque ability + * @param pokemon The {@link Pokemon} with this {@link AbAttr} + * @param passive N/A + * @param trapped {@link Utils.BooleanHolder} indicating whether the other Pokemon is trapped or not + * @param otherPokemon The {@link Pokemon} that is affected by an Arena Trap ability + * @param args N/A + * @returns if enemy Pokemon is trapped or not + */ + applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, args: any[]): boolean { + if (otherPokemon.getTypes().includes(Type.GHOST)){ + trapped.value = false; + return false; + } trapped.value = true; return true; } @@ -2614,7 +2696,6 @@ export class SuppressFieldAbilitiesAbAttr extends AbAttr { } } - export class AlwaysHitAbAttr extends AbAttr { } export class UncopiableAbilityAbAttr extends AbAttr { @@ -2859,8 +2940,8 @@ export function applyPostTerrainChangeAbAttrs(attrType: { new(...args: any[]): P } export function applyCheckTrappedAbAttrs(attrType: { new(...args: any[]): CheckTrappedAbAttr }, - pokemon: Pokemon, trapped: Utils.BooleanHolder, ...args: any[]): Promise { - return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyCheckTrapped(pokemon, passive, trapped, args), args, true); + pokemon: Pokemon, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyCheckTrapped(pokemon, passive, trapped, otherPokemon, args), args, true); } export function applyPostBattleAbAttrs(attrType: { new(...args: any[]): PostBattleAbAttr }, @@ -3442,7 +3523,7 @@ export function initAbilities() { new Ability(Abilities.WATER_COMPACTION, 7) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.WATER && move.category !== MoveCategory.STATUS, BattleStat.DEF, 2), new Ability(Abilities.MERCILESS, 7) - .unimplemented(), + .attr(ConditionalCritAbAttr, (user, target, move) => target.status?.effect === StatusEffect.TOXIC || target.status?.effect === StatusEffect.POISON), new Ability(Abilities.SHIELDS_DOWN, 7) .attr(PostBattleInitFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) .attr(PostSummonFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) @@ -3597,7 +3678,8 @@ export function initAbilities() { new Ability(Abilities.LIBERO, 8) .unimplemented(), new Ability(Abilities.BALL_FETCH, 8) - .unimplemented(), + .attr(FetchBallAbAttr) + .condition(getOncePerBattleCondition(Abilities.BALL_FETCH)), new Ability(Abilities.COTTON_DOWN, 8) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattleStat.SPD, -1, false, true) .bypassFaint(), diff --git a/src/data/move.ts b/src/data/move.ts index 6849a0fe7ce..d71edda691d 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -58,7 +58,8 @@ export enum MoveTarget { /** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Entry_hazard-creating_moves Entry hazard-creating moves} */ ENEMY_SIDE, BOTH_SIDES, - PARTY + PARTY, + CURSE } export enum MoveFlags { @@ -916,6 +917,7 @@ export enum MultiHitType { _3, _3_INCR, _1_TO_10, + BEAT_UP, } /** @@ -1233,6 +1235,11 @@ export class MultiHitAttr extends MoveAttr { hitTimes = 10; } break; + case MultiHitType.BEAT_UP: + // No status means the ally pokemon can contribute to Beat Up + hitTimes = user.scene.getParty().reduce((total, pokemon) => { + return total + (pokemon.id === user.id ? 1 : pokemon?.status && pokemon.status.effect !== StatusEffect.NONE ? 0 : 1) + }, 0); } (args[0] as Utils.IntegerHolder).value = hitTimes; return true; @@ -2034,6 +2041,46 @@ export class VariablePowerAttr extends MoveAttr { } } +export class LessPPMorePowerAttr extends VariablePowerAttr { + /** + * Power up moves when less PP user has + * @param user {@linkcode Pokemon} using this move + * @param target {@linkcode Pokemon} target of this move + * @param move {@linkcode Move} being used + * @param args [0] {@linkcode Utils.NumberHolder} of power + * @returns true if the function succeeds + */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const ppMax = move.pp; + let ppUsed = user.moveset.find((m) => m.moveId === move.id).ppUsed; + + let ppRemains = ppMax - ppUsed; + /** Reduce to 0 to avoid negative numbers if user has 1PP before attack and target has Ability.PRESSURE */ + if(ppRemains < 0) ppRemains = 0; + + const power = args[0] as Utils.NumberHolder; + + switch (ppRemains) { + case 0: + power.value = 200; + break; + case 1: + power.value = 80; + break; + case 2: + power.value = 60; + break; + case 3: + power.value = 50; + break; + default: + power.value = 40; + break; + } + return true; + } +} + export class MovePowerMultiplierAttr extends VariablePowerAttr { private powerMultiplierFunc: (user: Pokemon, target: Pokemon, move: Move) => number; @@ -2051,6 +2098,45 @@ export class MovePowerMultiplierAttr extends VariablePowerAttr { } } +/** + * Helper function to calculate the the base power of an ally's hit when using Beat Up. + * @param user The Pokemon that used Beat Up. + * @param allyIndex The party position of the ally contributing to Beat Up. + * @returns The base power of the Beat Up hit. + */ +const beatUpFunc = (user: Pokemon, allyIndex: number): number => { + const party = user.scene.getParty(); + + for (let i = allyIndex; i < party.length; i++) { + const pokemon = party[i]; + + // The user contributes to Beat Up regardless of status condition. + // Allies can contribute only if they do not have a non-volatile status condition. + if (pokemon.id !== user.id && pokemon?.status && pokemon.status.effect !== StatusEffect.NONE) { + continue; + } + return (pokemon.species.getBaseStat(Stat.ATK) / 10) + 5; + } +} + +export class BeatUpAttr extends VariablePowerAttr { + + /** + * Gets the next party member to contribute to a Beat Up hit, and calculates the base power for it. + * @param user Pokemon that used the move + * @param _target N/A + * @param _move Move with this attribute + * @param args N/A + * @returns true if the function succeeds + */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const power = args[0] as Utils.NumberHolder; + const allyIndex = user.turnData.hitCount - user.turnData.hitsLeft; + power.value = beatUpFunc(user, allyIndex); + return true; + } +} + const doublePowerChanceMessageFunc = (user: Pokemon, target: Pokemon, move: Move) => { let message: string = null; user.scene.executeWithSeedOffset(() => { @@ -2778,6 +2864,47 @@ export class WeatherBallTypeAttr extends VariableMoveTypeAttr { } } +/** + * Changes the move's type to match the current terrain. + * Has no effect if the user is not grounded. + * @extends VariableMoveTypeAttr + * @see {@linkcode apply} + */ +export class TerrainPulseTypeAttr extends VariableMoveTypeAttr { + /** + * @param user {@linkcode Pokemon} using this move + * @param target N/A + * @param move N/A + * @param args [0] {@linkcode Utils.IntegerHolder} The move's type to be modified + * @returns true if the function succeeds + */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + if(!user.isGrounded) + return false; + + const currentTerrain = user.scene.arena.getTerrainType(); + const type = (args[0] as Utils.IntegerHolder); + + switch (currentTerrain) { + case TerrainType.MISTY: + type.value = Type.FAIRY; + break; + case TerrainType.ELECTRIC: + type.value = Type.ELECTRIC; + break; + case TerrainType.GRASSY: + type.value = Type.GRASS; + break; + case TerrainType.PSYCHIC: + type.value = Type.PSYCHIC; + break; + default: + return false; + } + return true; + } +} + export class HiddenPowerTypeAttr extends VariableMoveTypeAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const type = (args[0] as Utils.IntegerHolder); @@ -4375,7 +4502,7 @@ export function getMoveTargets(user: Pokemon, move: Moves): MoveTargetSet { switch (moveTarget) { case MoveTarget.USER: case MoveTarget.PARTY: - set = [ user]; + set = [ user ]; break; case MoveTarget.NEAR_OTHER: case MoveTarget.OTHER: @@ -4411,6 +4538,9 @@ export function getMoveTargets(user: Pokemon, move: Moves): MoveTargetSet { set = [ user, user.getAlly() ].concat(opponents); multiple = true; break; + case MoveTarget.CURSE: + set = user.getTypes(true).includes(Type.GHOST) ? (opponents.concat([ user.getAlly() ])) : [ user ]; + break; } return { targets: set.filter(p => p?.isActive(true)).map(p => p.getBattlerIndex()).filter(t => t !== undefined), multiple }; @@ -4897,7 +5027,8 @@ export function initMoves() { .soundBased(), new StatusMove(Moves.CURSE, Type.GHOST, -1, 10, -1, 0, 2) .attr(CurseAttr) - .ignoresProtect(true), + .ignoresProtect(true) + .target(MoveTarget.CURSE), new AttackMove(Moves.FLAIL, Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 15, -1, 0, 2) .attr(LowHpPowerAttr), new StatusMove(Moves.CONVERSION_2, Type.NORMAL, -1, 30, -1, 0, 2) @@ -5115,8 +5246,9 @@ export function initMoves() { .attr(TrapAttr, BattlerTagType.WHIRLPOOL) .attr(HitsTagAttr, BattlerTagType.UNDERWATER, true), new AttackMove(Moves.BEAT_UP, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 2) - .makesContact(false) - .unimplemented(), + .attr(MultiHitAttr, MultiHitType.BEAT_UP) + .attr(BeatUpAttr) + .makesContact(false), new AttackMove(Moves.FAKE_OUT, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 10, 100, 3, 3) .attr(FlinchAttr) .condition(new FirstMoveCondition()), @@ -5460,7 +5592,7 @@ export function initMoves() { ), new AttackMove(Moves.TRUMP_CARD, Type.NORMAL, MoveCategory.SPECIAL, -1, -1, 5, -1, 0, 4) .makesContact() - .unimplemented(), + .attr(LessPPMorePowerAttr), new StatusMove(Moves.HEAL_BLOCK, Type.PSYCHIC, 100, 15, -1, 0, 4) .target(MoveTarget.ALL_NEAR_ENEMIES) .unimplemented(), @@ -6691,14 +6823,16 @@ export function initMoves() { .attr(SacrificialAttr) .target(MoveTarget.ALL_NEAR_OTHERS) .attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.MISTY && user.isGrounded() ? 1.5 : 1) - .condition(failIfDampCondition), + .condition(failIfDampCondition) + .makesContact(false), new AttackMove(Moves.GRASSY_GLIDE, Type.GRASS, MoveCategory.PHYSICAL, 55, 100, 20, -1, 0, 8) .partial(), new AttackMove(Moves.RISING_VOLTAGE, Type.ELECTRIC, MoveCategory.SPECIAL, 70, 100, 20, -1, 0, 8) .attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.ELECTRIC && target.isGrounded() ? 2 : 1), new AttackMove(Moves.TERRAIN_PULSE, Type.NORMAL, MoveCategory.SPECIAL, 50, 100, 10, -1, 0, 8) - .pulseMove() - .partial(), + .attr(TerrainPulseTypeAttr) + .attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() !== TerrainType.NONE && user.isGrounded() ? 2 : 1) + .pulseMove(), new AttackMove(Moves.SKITTER_SMACK, Type.BUG, MoveCategory.PHYSICAL, 70, 90, 10, 100, 0, 8) .attr(StatChangeAttr, BattleStat.SPATK, -1), new AttackMove(Moves.BURNING_JEALOUSY, Type.FIRE, MoveCategory.SPECIAL, 70, 100, 5, 100, 0, 8) @@ -7158,7 +7292,10 @@ export function initMoves() { new AttackMove(Moves.PSYCHIC_NOISE, Type.PSYCHIC, MoveCategory.SPECIAL, 75, 100, 10, -1, 0, 9) .soundBased() .partial(), - new AttackMove(Moves.UPPER_HAND, Type.FIGHTING, MoveCategory.PHYSICAL, 65, 100, 15, -1, 3, 9) + new AttackMove(Moves.UPPER_HAND, Type.FIGHTING, MoveCategory.PHYSICAL, 65, 100, 15, 100, 3, 9) + .attr(FlinchAttr) + .condition((user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.FIGHT && !target.turnData.acted && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()].move.move].category !== MoveCategory.STATUS && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()].move.move].priority > 0 ) + //TODO: Should also apply when target move priority increased by ability ex. gale wings .partial(), new AttackMove(Moves.MALIGNANT_CHAIN, Type.POISON, MoveCategory.SPECIAL, 100, 100, 5, 50, 0, 9) .attr(StatusEffectAttr, StatusEffect.TOXIC) diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 218423d3232..5032bd0dfbc 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -16,6 +16,7 @@ import { GameMode } from '../game-mode'; import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities"; import { VariantSet } from './variant'; import i18next, { Localizable } from '../plugins/i18n'; +import { Stat } from "./pokemon-stat"; export enum Region { NORMAL, @@ -192,6 +193,15 @@ export abstract class PokemonSpeciesForm { return false; } + /** + * Gets the species' base stat amount for the given stat. + * @param stat The desired stat. + * @returns The species' base stat amount. + */ + getBaseStat(stat: Stat): integer { + return this.baseStats[stat] + } + getBaseExp(): integer { let ret = this.baseExp; switch (this.getFormSpriteKey()) { diff --git a/src/data/tms.ts b/src/data/tms.ts index 1eff9102c4c..0b2c2c93bc8 100644 --- a/src/data/tms.ts +++ b/src/data/tms.ts @@ -43762,6 +43762,7 @@ export const tmSpecies: TmSpecies = { Species.TAUROS, Species.MEW, Species.SNUBBULL, + Species.GRANBULL, Species.SCIZOR, Species.HERACROSS, Species.TEDDIURSA, @@ -43785,11 +43786,14 @@ export const tmSpecies: TmSpecies = { Species.LUCARIO, Species.TOXICROAK, Species.GALLADE, + Species.PIGNITE, + Species.EMBOAR, Species.TIMBURR, Species.GURDURR, Species.CONKELDURR, Species.SAWK, Species.KROOKODILE, + Species.SCRAGGY, Species.SCRAFTY, Species.ESCAVALIER, Species.EELEKTROSS, diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 685662a2114..0abd153ff25 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -235,11 +235,10 @@ export class TrainerConfig { if (!getIsInitialized()) { initI18n(); } + // This is only the male name, because the female name is handled in a different function (setHasGenders) if (name === 'Finn') { name = i18next.t('trainerNames:rival'); } - - } this.name = name; return this; @@ -254,6 +253,7 @@ export class TrainerConfig { // Make the title lowercase and replace spaces with underscores title = title.toLowerCase().replace(/\s/g, '_'); + // Get the title from the i18n file this.title = i18next.t(`titles:${title}`); @@ -281,21 +281,40 @@ export class TrainerConfig { return trainerType; } + /** + * Sets the configuration for trainers with genders, including the female name and encounter background music (BGM). + * @param {string} [nameFemale] - The name of the female trainer. If 'Ivy', a localized name will be assigned. + * @param {TrainerType | string} [femaleEncounterBgm] - The encounter BGM for the female trainer, which can be a TrainerType or a string. + * @returns {TrainerConfig} - The updated TrainerConfig instance. + **/ setHasGenders(nameFemale?: string, femaleEncounterBgm?: TrainerType | string): TrainerConfig { + // If the female name is 'Ivy' (the rival), assign a localized name. if (nameFemale === 'Ivy') { - // Give the rival a localized name - // First check if i18n is initialized + // Check if the internationalization (i18n) system is initialized. if (!getIsInitialized()) { + // Initialize the i18n system if it is not already initialized. initI18n(); } - this.nameFemale = i18next.t('trainerNames:rival_female'); - } else { + // Set the localized name for the female rival. + this.nameFemale = i18next.t('trainerNames:rival_female'); + } else { + // Otherwise, assign the provided female name. this.nameFemale = nameFemale; } + // Indicate that this trainer configuration includes genders. this.hasGenders = true; - if (femaleEncounterBgm) - this.femaleEncounterBgm = typeof femaleEncounterBgm === 'number' ? TrainerType[femaleEncounterBgm].toString().replace(/\_/g, ' ').toLowerCase() : femaleEncounterBgm; + + // If a female encounter BGM is provided. + if (femaleEncounterBgm) { + // If the BGM is a TrainerType (number), convert it to a string, replace underscores with spaces, and convert to lowercase. + // Otherwise, assign the provided string as the BGM. + this.femaleEncounterBgm = typeof femaleEncounterBgm === 'number' + ? TrainerType[femaleEncounterBgm].toString().replace(/_/g, ' ').toLowerCase() + : femaleEncounterBgm; + } + + // Return the updated TrainerConfig instance. return this; } @@ -398,29 +417,44 @@ export class TrainerConfig { return this; } + /** + * Initializes the trainer configuration for a Gym Leader. + * @param {Species | Species[]} signatureSpecies - The signature species for the Gym Leader. + * @param {Type[]} specialtyTypes - The specialty types for the Gym Leader. + * @returns {TrainerConfig} - The updated TrainerConfig instance. + * **/ initForGymLeader(signatureSpecies: (Species | Species[])[], ...specialtyTypes: Type[]): TrainerConfig { + // Check if the internationalization (i18n) system is initialized. if (!getIsInitialized()) { initI18n(); } + // Set the function to generate the Gym Leader's party template. this.setPartyTemplateFunc(getGymLeaderPartyTemplate); + + // Set up party members with their corresponding species. signatureSpecies.forEach((speciesPool, s) => { + // Ensure speciesPool is an array. if (!Array.isArray(speciesPool)) speciesPool = [speciesPool]; + // Set a function to get a random party member from the species pool. this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); }); + + // If specialty types are provided, set species filter and specialty types. if (specialtyTypes.length) { this.setSpeciesFilter(p => specialtyTypes.find(t => p.isOfType(t)) !== undefined); this.setSpecialtyTypes(...specialtyTypes); } - // Handle name by checking this.name - making it lowercase and replacing spaces with underscores and then calling i18next.t with the name + // Localize the trainer's name by converting it to lowercase and replacing spaces with underscores. const nameForCall = this.name.toLowerCase().replace(/\s/g, '_'); this.name = i18next.t(`trainerNames:${nameForCall}`); + // Set the title to "gym_leader". (this is the key in the i18n file) + this.setTitle('gym_leader'); - - this.setTitle("gym_leader"); + // Configure various properties for the Gym Leader. this.setMoneyMultiplier(2.5); this.setBoss(); this.setStaticParty(); @@ -430,75 +464,125 @@ export class TrainerConfig { const waveIndex = party[0].scene.currentBattle.waveIndex; return getRandomTeraModifiers(party, waveIndex >= 100 ? 1 : 0, specialtyTypes.length ? specialtyTypes : null); }); + return this; } + /** + * Initializes the trainer configuration for an Elite Four member. + * @param {Species | Species[]} signatureSpecies - The signature species for the Elite Four member. + * @param {Type[]} specialtyTypes - The specialty types for the Elite Four member. + * @returns {TrainerConfig} - The updated TrainerConfig instance. + **/ initForEliteFour(signatureSpecies: (Species | Species[])[], ...specialtyTypes: Type[]): TrainerConfig { + // Check if the internationalization (i18n) system is initialized. if (!getIsInitialized()) { initI18n(); } + // Set the party templates for the Elite Four. this.setPartyTemplates(trainerPartyTemplates.ELITE_FOUR); + + // Set up party members with their corresponding species. signatureSpecies.forEach((speciesPool, s) => { + // Ensure speciesPool is an array. if (!Array.isArray(speciesPool)) speciesPool = [speciesPool]; + // Set a function to get a random party member from the species pool. this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); }); + + // Set species filter and specialty types if provided, otherwise filter by base total. if (specialtyTypes.length) { this.setSpeciesFilter(p => specialtyTypes.find(t => p.isOfType(t)) && p.baseTotal >= 450); this.setSpecialtyTypes(...specialtyTypes); - } else + } else { this.setSpeciesFilter(p => p.baseTotal >= 450); - // Handle name by checking this.name - making it lowercase and replacing spaces with underscores and then calling i18next.t with the name + } + + // Localize the trainer's name by converting it to lowercase and replacing spaces with underscores. const nameForCall = this.name.toLowerCase().replace(/\s/g, '_'); this.name = i18next.t(`trainerNames:${nameForCall}`); - this.setTitle("elite_four"); + // Set the title to "elite_four". (this is the key in the i18n file) + this.setTitle('elite_four'); + + // Configure various properties for the Elite Four member. this.setMoneyMultiplier(3.25); this.setBoss(); this.setStaticParty(); this.setBattleBgm('battle_elite'); this.setVictoryBgm('victory_gym'); this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 2, specialtyTypes.length ? specialtyTypes : null)); + return this; } + /** + * Initializes the trainer configuration for a Champion. + * @param {Species | Species[]} signatureSpecies - The signature species for the Champion. + * @returns {TrainerConfig} - The updated TrainerConfig instance. + **/ initForChampion(signatureSpecies: (Species | Species[])[]): TrainerConfig { + // Check if the internationalization (i18n) system is initialized. if (!getIsInitialized()) { initI18n(); } + + // Set the party templates for the Champion. this.setPartyTemplates(trainerPartyTemplates.CHAMPION); + + // Set up party members with their corresponding species. signatureSpecies.forEach((speciesPool, s) => { + // Ensure speciesPool is an array. if (!Array.isArray(speciesPool)) speciesPool = [speciesPool]; + // Set a function to get a random party member from the species pool. this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); }); + + // Set species filter to only include species with a base total of 470 or higher. this.setSpeciesFilter(p => p.baseTotal >= 470); - // Handle name by checking this.name - making it lowercase and replacing spaces with underscores and then calling i18next.t with the name + + // Localize the trainer's name by converting it to lowercase and replacing spaces with underscores. const nameForCall = this.name.toLowerCase().replace(/\s/g, '_'); this.name = i18next.t(`trainerNames:${nameForCall}`); - this.setTitle("champion"); + + // Set the title to "champion". (this is the key in the i18n file) + this.setTitle('champion'); + + // Configure various properties for the Champion. this.setMoneyMultiplier(10); this.setBoss(); this.setStaticParty(); this.setBattleBgm('battle_champion_alder'); this.setVictoryBgm('victory_champion'); this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 3)); + return this; } + /** + * Retrieves the title for the trainer based on the provided trainer slot and variant. + * @param {TrainerSlot} trainerSlot - The slot to determine which title to use. Defaults to TrainerSlot.NONE. + * @param {TrainerVariant} variant - The variant of the trainer to determine the specific title. + * @returns {string} - The title of the trainer. + **/ getTitle(trainerSlot: TrainerSlot = TrainerSlot.NONE, variant: TrainerVariant): string { let ret = this.name; + // Check if the variant is double and the name for double exists if (!trainerSlot && variant === TrainerVariant.DOUBLE && this.nameDouble) return this.nameDouble; + // Female variant if (this.hasGenders) { + // If the name is already set if (this.nameFemale) { + // Check if the variant is either female or this is for the partner in a double battle if (variant === TrainerVariant.FEMALE || (variant === TrainerVariant.DOUBLE && trainerSlot === TrainerSlot.TRAINER_PARTNER)) return this.nameFemale; } else - // Check if !variant is true, if so return the name, else return the name with _female appended if (variant) { if (!getIsInitialized()) { @@ -603,12 +687,12 @@ function getRandomTeraModifiers(party: EnemyPokemon[], count: integer, types?: T export const trainerConfigs: TrainerConfigs = { [TrainerType.UNKNOWN]: new TrainerConfig(0).setHasGenders(), - [TrainerType.ACE_TRAINER]: new TrainerConfig(++t).setHasGenders().setHasDouble('Ace Duo').setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.ACE_TRAINER) + [TrainerType.ACE_TRAINER]: new TrainerConfig(++t).setHasGenders('Ace Trainer Female').setHasDouble('Ace Duo').setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.ACE_TRAINER) .setPartyTemplateFunc(scene => getWavePartyTemplate(scene, trainerPartyTemplates.THREE_WEAK_BALANCED, trainerPartyTemplates.FOUR_WEAK_BALANCED, trainerPartyTemplates.FIVE_WEAK_BALANCED, trainerPartyTemplates.SIX_WEAK_BALANCED)), [TrainerType.ARTIST]: new TrainerConfig(++t).setEncounterBgm(TrainerType.RICH).setPartyTemplates(trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.THREE_AVG) .setSpeciesPools([ Species.SMEARGLE ]), - [TrainerType.BACKERS]: new TrainerConfig(++t).setHasGenders().setDoubleOnly().setEncounterBgm(TrainerType.CYCLIST), - [TrainerType.BACKPACKER]: new TrainerConfig(++t).setHasGenders().setHasDouble('Backpackers').setSpeciesFilter(s => s.isOfType(Type.FLYING) || s.isOfType(Type.ROCK)).setEncounterBgm(TrainerType.BACKPACKER) + [TrainerType.BACKERS]: new TrainerConfig(++t).setHasGenders("Backers").setDoubleOnly().setEncounterBgm(TrainerType.CYCLIST), + [TrainerType.BACKPACKER]: new TrainerConfig(++t).setHasGenders("Backpacker Female").setHasDouble('Backpackers').setSpeciesFilter(s => s.isOfType(Type.FLYING) || s.isOfType(Type.ROCK)).setEncounterBgm(TrainerType.BACKPACKER) .setPartyTemplates(trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.ONE_WEAK_ONE_STRONG, trainerPartyTemplates.ONE_AVG_ONE_STRONG) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.RHYHORN, Species.AIPOM, Species.MAKUHITA, Species.MAWILE, Species.NUMEL, Species.LILLIPUP, Species.SANDILE, Species.WOOLOO ], @@ -628,17 +712,17 @@ export const trainerConfigs: TrainerConfigs = { [TrainerPoolTier.SUPER_RARE]: [ Species.HITMONTOP, Species.INFERNAPE, Species.GALLADE, Species.HAWLUCHA, Species.HAKAMO_O ], [TrainerPoolTier.ULTRA_RARE]: [ Species.KUBFU ] }), - [TrainerType.BREEDER]: new TrainerConfig(++t).setMoneyMultiplier(1.325).setEncounterBgm(TrainerType.POKEFAN).setHasGenders().setHasDouble('Breeders') + [TrainerType.BREEDER]: new TrainerConfig(++t).setMoneyMultiplier(1.325).setEncounterBgm(TrainerType.POKEFAN).setHasGenders("Breeder Female").setHasDouble('Breeders') .setPartyTemplateFunc(scene => getWavePartyTemplate(scene, trainerPartyTemplates.FOUR_WEAKER, trainerPartyTemplates.FIVE_WEAKER, trainerPartyTemplates.SIX_WEAKER)) .setSpeciesFilter(s => s.baseTotal < 450), - [TrainerType.CLERK]: new TrainerConfig(++t).setHasGenders().setHasDouble('Colleagues').setEncounterBgm(TrainerType.CLERK) + [TrainerType.CLERK]: new TrainerConfig(++t).setHasGenders("Clerk Female").setHasDouble('Colleagues').setEncounterBgm(TrainerType.CLERK) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.THREE_WEAK, trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_ONE_AVG) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.MEOWTH, Species.PSYDUCK, Species.BUDEW, Species.PIDOVE, Species.CINCCINO, Species.LITLEO ], [TrainerPoolTier.UNCOMMON]: [ Species.JIGGLYPUFF, Species.MAGNEMITE, Species.MARILL, Species.COTTONEE, Species.SKIDDO ], [TrainerPoolTier.RARE]: [ Species.BUIZEL, Species.SNEASEL, Species.KLEFKI, Species.INDEEDEE ] }), - [TrainerType.CYCLIST]: new TrainerConfig(++t).setMoneyMultiplier(1.3).setHasGenders().setHasDouble('Cyclists').setEncounterBgm(TrainerType.CYCLIST) + [TrainerType.CYCLIST]: new TrainerConfig(++t).setMoneyMultiplier(1.3).setHasGenders("Cyclist Female").setHasDouble('Cyclists').setEncounterBgm(TrainerType.CYCLIST) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.ONE_AVG) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.PICHU, Species.STARLY, Species.TAILLOW, Species.BOLTUND ], @@ -697,9 +781,9 @@ export const trainerConfigs: TrainerConfigs = { }), [TrainerType.PARASOL_LADY]: new TrainerConfig(++t).setMoneyMultiplier(1.55).setEncounterBgm(TrainerType.PARASOL_LADY).setSpeciesFilter(s => s.isOfType(Type.WATER)), [TrainerType.PILOT]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK).setSpeciesFilter(s => tmSpecies[Moves.FLY].indexOf(s.speciesId) > -1), - [TrainerType.POKEFAN]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setName('Poké Fan').setHasGenders().setHasDouble('Poké Fan Family').setEncounterBgm(TrainerType.POKEFAN) + [TrainerType.POKEFAN]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setName('PokéFan').setHasGenders("PokéFan Female").setHasDouble('PokéFan Family').setEncounterBgm(TrainerType.POKEFAN) .setPartyTemplates(trainerPartyTemplates.SIX_WEAKER, trainerPartyTemplates.FOUR_WEAK, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.FOUR_WEAK_SAME, trainerPartyTemplates.FIVE_WEAK, trainerPartyTemplates.SIX_WEAKER_SAME), - [TrainerType.PRESCHOOLER]: new TrainerConfig(++t).setMoneyMultiplier(0.2).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders(undefined, 'lass').setHasDouble('Preschoolers') + [TrainerType.PRESCHOOLER]: new TrainerConfig(++t).setMoneyMultiplier(0.2).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders("Preschooler Female", 'lass').setHasDouble('Preschoolers') .setPartyTemplates(trainerPartyTemplates.THREE_WEAK, trainerPartyTemplates.FOUR_WEAKER, trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, trainerPartyTemplates.FIVE_WEAKER) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.CATERPIE, Species.PICHU, Species.SANDSHREW, Species.LEDYBA, Species.BUDEW, Species.BURMY, Species.WOOLOO, Species.PAWMI, Species.SMOLIV ], @@ -707,7 +791,7 @@ export const trainerConfigs: TrainerConfigs = { [TrainerPoolTier.RARE]: [ Species.RALTS, Species.RIOLU, Species.JOLTIK, Species.TANDEMAUS ], [TrainerPoolTier.SUPER_RARE]: [ Species.DARUMAKA, Species.TINKATINK ], }), - [TrainerType.PSYCHIC]: new TrainerConfig(++t).setHasGenders().setHasDouble('Psychics').setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.PSYCHIC) + [TrainerType.PSYCHIC]: new TrainerConfig(++t).setHasGenders("Psychic Female").setHasDouble('Psychics').setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.PSYCHIC) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, trainerPartyTemplates.TWO_WEAK_SAME_TWO_WEAK_SAME, trainerPartyTemplates.ONE_STRONGER) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.ABRA, Species.DROWZEE, Species.RALTS, Species.SPOINK, Species.GOTHITA, Species.SOLOSIS, Species.BLIPBUG, Species.ESPURR, Species.HATENNA ], @@ -715,7 +799,7 @@ export const trainerConfigs: TrainerConfigs = { [TrainerPoolTier.RARE]: [ Species.ELGYEM, Species.SIGILYPH, Species.BALTOY, Species.GIRAFARIG, Species.MEOWSTIC ], [TrainerPoolTier.SUPER_RARE]: [ Species.BELDUM, Species.ESPEON, Species.STANTLER ], }), - [TrainerType.RANGER]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setName('Pokémon Ranger').setEncounterBgm(TrainerType.BACKPACKER).setHasGenders().setHasDouble('Pokémon Rangers') + [TrainerType.RANGER]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setName('Pokémon Ranger').setEncounterBgm(TrainerType.BACKPACKER).setHasGenders("Pokémon Ranger Female").setHasDouble('Pokémon Rangers') .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.PICHU, Species.GROWLITHE, Species.PONYTA, Species.ZIGZAGOON, Species.SEEDOT, Species.BIDOOF, Species.RIOLU, Species.SEWADDLE, Species.SKIDDO, Species.SALANDIT, Species.YAMPER ], [TrainerPoolTier.UNCOMMON]: [ Species.AZURILL, Species.TAUROS, Species.MAREEP, Species.FARFETCHD, Species.TEDDIURSA, Species.SHROOMISH, Species.ELECTRIKE, Species.BUDEW, Species.BUIZEL, Species.MUDBRAY, Species.STUFFUL ], @@ -725,7 +809,7 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.RICH]: new TrainerConfig(++t).setMoneyMultiplier(5).setName('Gentleman').setHasGenders('Madame').setHasDouble('Rich Couple'), [TrainerType.RICH_KID]: new TrainerConfig(++t).setMoneyMultiplier(3.75).setName('Rich Boy').setHasGenders('Lady').setHasDouble('Rich Kids').setEncounterBgm(TrainerType.RICH), [TrainerType.ROUGHNECK]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.DARK)), - [TrainerType.SCIENTIST]: new TrainerConfig(++t).setHasGenders().setHasDouble('Scientists').setMoneyMultiplier(1.7).setEncounterBgm(TrainerType.SCIENTIST) + [TrainerType.SCIENTIST]: new TrainerConfig(++t).setHasGenders("Scientist Female").setHasDouble('Scientists').setMoneyMultiplier(1.7).setEncounterBgm(TrainerType.SCIENTIST) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.MAGNEMITE, Species.GRIMER, Species.DROWZEE, Species.VOLTORB, Species.KOFFING ], [TrainerPoolTier.UNCOMMON]: [ Species.BALTOY, Species.BRONZOR, Species.FERROSEED, Species.KLINK, Species.CHARJABUG, Species.BLIPBUG, Species.HELIOPTILE ], @@ -734,29 +818,29 @@ export const trainerConfigs: TrainerConfigs = { [TrainerPoolTier.ULTRA_RARE]: [ Species.ROTOM, Species.MELTAN ] }), [TrainerType.SMASHER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), - [TrainerType.SNOW_WORKER]: new TrainerConfig(++t).setName('Worker').setHasGenders().setHasDouble('Workers').setMoneyMultiplier(1.7).setEncounterBgm(TrainerType.CLERK).setSpeciesFilter(s => s.isOfType(Type.ICE) || s.isOfType(Type.STEEL)), + [TrainerType.SNOW_WORKER]: new TrainerConfig(++t).setName('Worker').setHasGenders("Worker Female").setHasDouble('Workers').setMoneyMultiplier(1.7).setEncounterBgm(TrainerType.CLERK).setSpeciesFilter(s => s.isOfType(Type.ICE) || s.isOfType(Type.STEEL)), [TrainerType.STRIKER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), - [TrainerType.SCHOOL_KID]: new TrainerConfig(++t).setMoneyMultiplier(0.75).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders(undefined, 'lass').setHasDouble('School Kids') + [TrainerType.SCHOOL_KID]: new TrainerConfig(++t).setMoneyMultiplier(0.75).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders("School Kid Female", 'lass').setHasDouble('School Kids') .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.ODDISH, Species.EXEGGCUTE, Species.TEDDIURSA, Species.WURMPLE, Species.RALTS, Species.SHROOMISH, Species.FLETCHLING ], [TrainerPoolTier.UNCOMMON]: [ Species.VOLTORB, Species.WHISMUR, Species.MEDITITE, Species.MIME_JR, Species.NYMBLE ], [TrainerPoolTier.RARE]: [ Species.TANGELA, Species.EEVEE, Species.YANMA ], [TrainerPoolTier.SUPER_RARE]: [ Species.TADBULB ] }), - [TrainerType.SWIMMER]: new TrainerConfig(++t).setMoneyMultiplier(1.3).setEncounterBgm(TrainerType.PARASOL_LADY).setHasGenders().setHasDouble('Swimmers').setSpecialtyTypes(Type.WATER).setSpeciesFilter(s => s.isOfType(Type.WATER)), + [TrainerType.SWIMMER]: new TrainerConfig(++t).setMoneyMultiplier(1.3).setEncounterBgm(TrainerType.PARASOL_LADY).setHasGenders("Swimmer Female").setHasDouble('Swimmers').setSpecialtyTypes(Type.WATER).setSpeciesFilter(s => s.isOfType(Type.WATER)), [TrainerType.TWINS]: new TrainerConfig(++t).setDoubleOnly().setMoneyMultiplier(0.65).setUseSameSeedForAllMembers() .setPartyTemplateFunc(scene => getWavePartyTemplate(scene, trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_STRONG)) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PLUSLE, Species.VOLBEAT, Species.PACHIRISU, Species.SILCOON, Species.METAPOD, Species.IGGLYBUFF, Species.PETILIL, Species.EEVEE ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MINUN, Species.ILLUMISE, Species.EMOLGA, Species.CASCOON, Species.KAKUNA, Species.CLEFFA, Species.COTTONEE, Species.EEVEE ], TrainerSlot.TRAINER_PARTNER)) .setEncounterBgm(TrainerType.TWINS), - [TrainerType.VETERAN]: new TrainerConfig(++t).setHasGenders().setHasDouble('Veteran Duo').setMoneyMultiplier(2.5).setEncounterBgm(TrainerType.ACE_TRAINER).setSpeciesFilter(s => s.isOfType(Type.DRAGON)), + [TrainerType.VETERAN]: new TrainerConfig(++t).setHasGenders("Veteran Female").setHasDouble('Veteran Duo').setMoneyMultiplier(2.5).setEncounterBgm(TrainerType.ACE_TRAINER).setSpeciesFilter(s => s.isOfType(Type.DRAGON)), [TrainerType.WAITER]: new TrainerConfig(++t).setHasGenders('Waitress').setHasDouble('Restaurant Staff').setMoneyMultiplier(1.5).setEncounterBgm(TrainerType.CLERK) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.CLEFFA, Species.CHATOT, Species.PANSAGE, Species.PANSEAR, Species.PANPOUR, Species.MINCCINO ], [TrainerPoolTier.UNCOMMON]: [ Species.TROPIUS, Species.PETILIL, Species.BOUNSWEET, Species.INDEEDEE ], [TrainerPoolTier.RARE]: [ Species.APPLIN, Species.SINISTEA, Species.POLTCHAGEIST ] }), - [TrainerType.WORKER]: new TrainerConfig(++t).setHasGenders().setHasDouble('Workers').setEncounterBgm(TrainerType.CLERK).setMoneyMultiplier(1.7).setSpeciesFilter(s => s.isOfType(Type.ROCK) || s.isOfType(Type.STEEL)), + [TrainerType.WORKER]: new TrainerConfig(++t).setHasGenders("Worker Female").setHasDouble('Workers').setEncounterBgm(TrainerType.CLERK).setMoneyMultiplier(1.7).setSpeciesFilter(s => s.isOfType(Type.ROCK) || s.isOfType(Type.STEEL)), [TrainerType.YOUNGSTER]: new TrainerConfig(++t).setMoneyMultiplier(0.5).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders('Lass', 'lass').setHasDouble('Beginners').setPartyTemplates(trainerPartyTemplates.TWO_WEAKER) .setSpeciesPools( [ Species.CATERPIE, Species.WEEDLE, Species.RATTATA, Species.SENTRET, Species.POOCHYENA, Species.ZIGZAGOON, Species.WURMPLE, Species.BIDOOF, Species.PATRAT, Species.LILLIPUP ] diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index e25fbe5fa71..a1347bcd256 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -27,7 +27,7 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr } from '../data/ability'; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import Battle, { BattlerIndex } from '../battle'; @@ -1523,6 +1523,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const critOnly = new Utils.BooleanHolder(false); const critAlways = source.getTag(BattlerTagType.ALWAYS_CRIT); applyMoveAttrs(CritOnlyAttr, source, this, move, critOnly); + applyAbAttrs(ConditionalCritAbAttr, source, null, critOnly, this, move); if (critOnly.value || critAlways) isCritical = true; else { @@ -1538,12 +1539,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { critLevel.value += 2; const critChance = [24, 8, 2, 1][Math.max(0, Math.min(critLevel.value, 3))]; isCritical = !source.getTag(BattlerTagType.NO_CRIT) && (critChance === 1 || !this.scene.randBattleSeedInt(critChance)); - if (isCritical) { - const blockCrit = new Utils.BooleanHolder(false); - applyAbAttrs(BlockCritAbAttr, this, null, blockCrit); - if (blockCrit.value) - isCritical = false; - } + } + if (isCritical) { + const blockCrit = new Utils.BooleanHolder(false); + applyAbAttrs(BlockCritAbAttr, this, null, blockCrit); + if (blockCrit.value) + isCritical = false; } const sourceAtk = new Utils.IntegerHolder(source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK, this, null, isCritical)); const targetDef = new Utils.IntegerHolder(this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, isCritical)); diff --git a/src/field/trainer.ts b/src/field/trainer.ts index 60497239488..8cd06cac12f 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -96,30 +96,54 @@ export default class Trainer extends Phaser.GameObjects.Container { return this.config.getSpriteKey(this.variant === TrainerVariant.FEMALE || forceFemale); } + /** + * Returns the name of the trainer based on the provided trainer slot and the option to include a title. + * @param {TrainerSlot} trainerSlot - The slot to determine which name to use. Defaults to TrainerSlot.NONE. + * @param {boolean} includeTitle - Whether to include the title in the returned name. Defaults to false. + * @returns {string} - The formatted name of the trainer. + **/ getName(trainerSlot: TrainerSlot = TrainerSlot.NONE, includeTitle: boolean = false): string { + // Get the base title based on the trainer slot and variant. let name = this.config.getTitle(trainerSlot, this.variant); + + // Determine the title to include based on the configuration and includeTitle flag. let title = includeTitle && this.config.title ? this.config.title : null; - + // If the trainer has a name (not null or undefined). if (this.name) { - if (includeTitle) - - // Check if i18n is initialized + // If the title should be included. + if (includeTitle) { + // Check if the internationalization (i18n) system is initialized. if (!getIsInitialized()) { - initI18n() + // Initialize the i18n system if it is not already initialized. + initI18n(); } + // Get the localized trainer class name from the i18n file and set it as the title. + // This is used for trainer class names, not titles like "Elite Four, Champion, etc." title = i18next.t(`trainerClasses:${name.toLowerCase().replace(/\s/g, '_')}`); + } + + // If no specific trainer slot is set. if (!trainerSlot) { + // Use the trainer's name. name = this.name; - if (this.partnerName) + // If there is a partner name, concatenate it with the trainer's name using "&". + if (this.partnerName) { name = `${name} & ${this.partnerName}`; - } else + } + } else { + // Assign the name based on the trainer slot: + // Use 'this.name' if 'trainerSlot' is TRAINER. + // Otherwise, use 'this.partnerName' if it exists, or 'this.name' if it doesn't. name = trainerSlot === TrainerSlot.TRAINER ? this.name : this.partnerName || this.name; + } } + // Return the formatted name, including the title if it is set. return title ? `${title} ${name}` : name; } + isDouble(): boolean { return this.config.doubleOnly || this.variant === TrainerVariant.DOUBLE; } diff --git a/src/locales/de/trainers.ts b/src/locales/de/trainers.ts index 11e8d914842..93eb04cca67 100644 --- a/src/locales/de/trainers.ts +++ b/src/locales/de/trainers.ts @@ -68,8 +68,9 @@ export const trainerClasses: SimpleTranslationEntries = { "officer": "Polizist", "parasol_lady": "Schirmdame", "pilot": "Pilot", - "pokefan": "Pokéfan", - "pokefan_family": "Pokéfan-Pärchen", + "pokéfan": "Pokéfan", + "pokéfan_female": "Pokéfan", + "pokéfan_family": "Pokéfan-Pärchen", "preschooler": "Vorschüler", "preschooler_female": "Vorschülerin", "preschoolers": "Vorschüler", @@ -77,6 +78,7 @@ export const trainerClasses: SimpleTranslationEntries = { "psychic_female": "Seherin", "psychics": "Seher", "pokémon_ranger": "Pokémon-Ranger", + "pokémon_ranger_female": "Pokémon-Ranger", "pokémon_rangers": "Pokémon-Ranger", "ranger": "Ranger", "restaurant_staff": "Restaurant Angestellte", diff --git a/src/locales/en/trainers.ts b/src/locales/en/trainers.ts index 03c3e22c12c..1eff742e23a 100644 --- a/src/locales/en/trainers.ts +++ b/src/locales/en/trainers.ts @@ -68,8 +68,9 @@ export const trainerClasses: SimpleTranslationEntries = { "officer": "Officer", "parasol_lady": "Parasol Lady", "pilot": "Pilot", - "pokefan": "Poké Fan", - "pokefan_family": "Poké Fan Family", + "pokéfan": "Poké Fan", + "pokéfan_female": "Poké Fan", + "pokéfan_family": "Poké Fan Family", "preschooler": "Preschooler", "preschooler_female": "Preschooler", "preschoolers": "Preschoolers", @@ -77,6 +78,7 @@ export const trainerClasses: SimpleTranslationEntries = { "psychic_female": "Psychic", "psychics": "Psychics", "pokémon_ranger": "Pokémon Ranger", + "pokémon_ranger_female": "Pokémon Ranger", "pokémon_rangers": "Pokémon Ranger", "ranger": "Ranger", "restaurant_staff": "Restaurant Staff", diff --git a/src/locales/es/trainers.ts b/src/locales/es/trainers.ts index 916ef8fb838..e0af5aac1c4 100644 --- a/src/locales/es/trainers.ts +++ b/src/locales/es/trainers.ts @@ -68,8 +68,9 @@ export const trainerClasses: SimpleTranslationEntries = { "officer": "Officer", "parasol_lady": "Parasol Lady", "pilot": "Pilot", - "pokefan": "Poké Fan", - "pokefan_family": "Poké Fan Family", + "pokéfan": "Poké Fan", + "pokéfan_female": "Poké Fan", + "pokéfan_family": "Poké Fan Family", "preschooler": "Preschooler", "preschooler_female": "Preschooler", "preschoolers": "Preschoolers", diff --git a/src/locales/fr/modifier-type.ts b/src/locales/fr/modifier-type.ts index f8697c04259..4c3725117a2 100644 --- a/src/locales/fr/modifier-type.ts +++ b/src/locales/fr/modifier-type.ts @@ -52,16 +52,16 @@ export const modifierType: ModifierTypeTranslationEntries = { description: "Double les chances de tomber sur un combat double pendant {{battleCount}} combats", }, "TempBattleStatBoosterModifierType": { - description: "Augmente d’1 cran {{tempBattleStatName}} pour toute l’équipe pendant 5 combats", + description: "Augmente d’un cran {{tempBattleStatName}} pour toute l’équipe pendant 5 combats", }, "AttackTypeBoosterModifierType": { description: "Augmente de 20% la puissance des capacités de type {{moveType}} d’un Pokémon", }, "PokemonLevelIncrementModifierType": { - description: "Fait monter un Pokémon d’1 niveau", + description: "Fait monter un Pokémon d’un niveau", }, "AllPokemonLevelIncrementModifierType": { - description: "Fait monter toute l’équipe d’1 niveau", + description: "Fait monter toute l’équipe d’un niveau", }, "PokemonBaseStatBoosterModifierType": { description: "Augmente de 10% {{statName}} de base de son porteur. Plus les IV sont hauts, plus il peut en porter.", @@ -214,13 +214,13 @@ export const modifierType: ModifierTypeTranslationEntries = { "SHINY_CHARM": { name: "Charme Chroma", description: "Augmente énormément les chances de rencontrer un Pokémon sauvage chromatique" }, "ABILITY_CHARM": { name: "Charme Talent", description: "Augmente énormément les chances de rencontrer un Pokémon sauvage avec un Talent Caché" }, - "IV_SCANNER": { name: "Scanner d’IV", description: "Scanne les IV d’un Pokémon sauvage. 2 IV sont révélés par Scanner. Les meilleurs sont montrés en 1er." }, + "IV_SCANNER": { name: "Scanner d’IV", description: "Révèle la qualité de deux IV d’un Pokémon sauvage par scanner possédé. Les meilleurs IV sont révélés en priorité." }, "DNA_SPLICERS": { name: "Pointeau ADN" }, "MINI_BLACK_HOLE": { name: "Mini Trou Noir" }, - "GOLDEN_POKEBALL": { name: "Poké Ball Dorée", description: "Ajoute 1 choix d’objet à la fin de chaque combat" }, + "GOLDEN_POKEBALL": { name: "Poké Ball Dorée", description: "Ajoute un choix d’objet à la fin de chaque combat" }, "ENEMY_DAMAGE_BOOSTER": { name: "Jeton Dégâts", description: "Augmente les dégâts de 5%" }, "ENEMY_DAMAGE_REDUCTION": { name: "Jeton Protection", description: "Diminue les dégâts reçus de 2,5%" }, diff --git a/src/locales/fr/trainers.ts b/src/locales/fr/trainers.ts index 3d22b00f89e..bfc77b5a8cf 100644 --- a/src/locales/fr/trainers.ts +++ b/src/locales/fr/trainers.ts @@ -68,8 +68,9 @@ export const trainerClasses: SimpleTranslationEntries = { "officer": "Policier", "parasol_lady": "Sœur Parasol", "pilot": "Pilote", - "pokefan": "Poké Fan", - "pokefan_family": "Couple de Pokéfans", + "pokéfan": "Poké Fan", + "pokéfan_female": "Poké Fan", + "pokéfan_family": "Couple de Pokéfans", "preschooler": "Petit", "preschooler_female": "Petite", "preschoolers": "Petits", @@ -77,6 +78,7 @@ export const trainerClasses: SimpleTranslationEntries = { "psychic_female": "Kinésiste", "psychics": "Kinésistes", "pokémon_ranger": "Pokémon Ranger", + "pokémon_ranger_female": "Pokémon Ranger", "pokémon_rangers": "Pokémon Rangers", "ranger": "Ranger", "restaurant_staff": "Serveurs", diff --git a/src/locales/it/trainers.ts b/src/locales/it/trainers.ts index 24c40acdac4..6fcd157a0f1 100644 --- a/src/locales/it/trainers.ts +++ b/src/locales/it/trainers.ts @@ -68,8 +68,9 @@ export const trainerClasses: SimpleTranslationEntries = { "officer": "Officer", "parasol_lady": "Parasol Lady", "pilot": "Pilot", - "pokefan": "Poké Fan", - "pokefan_family": "Poké Fan Family", + "pokéfan": "Poké Fan", + "pokéfan_female": "Poké Fan", + "pokéfan_family": "Poké Fan Family", "preschooler": "Preschooler", "preschooler_female": "Preschooler", "preschoolers": "Preschoolers", @@ -77,6 +78,7 @@ export const trainerClasses: SimpleTranslationEntries = { "psychic_female": "Psychic", "psychics": "Psychics", "pokémon_ranger": "Pokémon Ranger", + "pokémon_ranger_female": "Pokémon Ranger", "pokémon_rangers": "Pokémon Ranger", "ranger": "Ranger", "restaurant_staff": "Restaurant Staff", diff --git a/src/locales/pt_BR/trainers.ts b/src/locales/pt_BR/trainers.ts index bc79f98b41b..96dc7d1934e 100644 --- a/src/locales/pt_BR/trainers.ts +++ b/src/locales/pt_BR/trainers.ts @@ -68,8 +68,9 @@ export const trainerClasses: SimpleTranslationEntries = { "officer": "Policial", "parasol_lady": "Moça de Sombrinha", "pilot": "Piloto", - "poké_fan": "Pokefã", - "poké_fan_family": "Família Pokefã", + "pokéfan": "Pokefã", + "pokéfan_female": "Pokéfã", + "pokéfan_family": "Família Pokefã", "preschooler": "Menino do Prezinho", "preschooler_female": "Menina do Prezinho", "preschoolers": "Alunos do Prezinho", @@ -77,6 +78,7 @@ export const trainerClasses: SimpleTranslationEntries = { "psychic_female": "Médium", "psychics": "Médiuns", "pokémon_ranger": "Guarda Pokémon", + "pokémon_ranger_female": "Guarda Pokémon", "pokémon_rangers": "Guardas Pokémon", "ranger": "Guarda", "restaurant_staff": "Equipe do Restaurante", diff --git a/src/locales/zh_CN/trainers.ts b/src/locales/zh_CN/trainers.ts index 2dd10d49ef4..7fa16d87fad 100644 --- a/src/locales/zh_CN/trainers.ts +++ b/src/locales/zh_CN/trainers.ts @@ -68,8 +68,9 @@ export const trainerClasses: SimpleTranslationEntries = { "officer": "警察", "parasol_lady": "阳伞姐姐", "pilot": "飞行员", - "poké_fan": "发烧友俱乐部", - "poké_fan_family": "同好夫妇", + "pokéfan": "发烧友俱乐部", + "pokéfan_female": "发烧友俱乐部", + "pokéfan_family": "同好夫妇", "preschooler": "幼儿园小朋友", "preschooler_female": "幼儿园小朋友", "preschoolers": "幼儿园小朋友组合", @@ -77,6 +78,7 @@ export const trainerClasses: SimpleTranslationEntries = { "psychic_female": "超能力者", "psychics": "超能力者组合", "pokémon_ranger": "宝可梦巡护员", + "pokémon_ranger_female": "宝可梦巡护员", "pokémon_rangers": "宝可梦巡护员组合", "ranger": "巡护员", "restaurant_staff": "服务生组合", diff --git a/src/phases.ts b/src/phases.ts index f70fe9e857a..a6df54c4cea 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -906,7 +906,7 @@ export class EncounterPhase extends BattlePhase { const showDialogueAndSummon = () => { let message: string; this.scene.executeWithSeedOffset(() => message = Utils.randSeedItem(encounterMessages), this.scene.currentBattle.waveIndex); - this.scene.ui.showDialogue(message, trainer.getName(), null, () => { + this.scene.ui.showDialogue(message, trainer.getName(TrainerSlot.NONE,true), null, () => { this.scene.charSprite.hide().then(() => this.scene.hideFieldOverlay(250).then(() => doSummon())); }); }; @@ -1809,7 +1809,7 @@ export class CommandPhase extends FieldPhase { const trapped = new Utils.BooleanHolder(false); const batonPass = isSwitch && args[0] as boolean; if (!batonPass) - enemyField.forEach(enemyPokemon => applyCheckTrappedAbAttrs(CheckTrappedAbAttr, enemyPokemon, trapped)); + enemyField.forEach(enemyPokemon => applyCheckTrappedAbAttrs(CheckTrappedAbAttr, enemyPokemon, trapped, playerPokemon)); if (batonPass || (!trapTag && !trapped.value)) { this.scene.currentBattle.turnCommands[this.fieldIndex] = isSwitch ? { command: Command.POKEMON, cursor: cursor, args: args } @@ -1914,7 +1914,7 @@ export class EnemyCommandPhase extends FieldPhase { const trapTag = enemyPokemon.findTag(t => t instanceof TrappedTag) as TrappedTag; const trapped = new Utils.BooleanHolder(false); - opponents.forEach(playerPokemon => applyCheckTrappedAbAttrs(CheckTrappedAbAttr, playerPokemon, trapped)); + opponents.forEach(playerPokemon => applyCheckTrappedAbAttrs(CheckTrappedAbAttr, playerPokemon, trapped, enemyPokemon)); if (!trapTag && !trapped.value) { const partyMemberScores = trainer.getPartyMemberMatchupScores(enemyPokemon.trainerSlot, true); @@ -3045,7 +3045,8 @@ export class PostTurnStatusEffectPhase extends PokemonPhase { break; } if (damage) { - this.scene.damageNumberHandler.add(this.getPokemon(), pokemon.damage(damage)); + // Set preventEndure flag to avoid pokemon surviving thanks to focus band, sturdy, endure ... + this.scene.damageNumberHandler.add(this.getPokemon(), pokemon.damage(damage, false, true)); pokemon.updateInfo(); } new CommonBattleAnim(CommonAnim.POISON + (pokemon.status.effect - 1), pokemon).play(this.scene, () => this.end()); @@ -4349,6 +4350,7 @@ export class AttemptCapturePhase extends PokemonPhase { scale: 1 }); + this.scene.currentBattle.lastUsedPokeball = this.pokeballType; this.removePb(); this.end(); } diff --git a/src/system/settings.ts b/src/system/settings.ts index 15c1f19aa04..aa2f4f5c682 100644 --- a/src/system/settings.ts +++ b/src/system/settings.ts @@ -178,11 +178,17 @@ export function setSetting(scene: BattleScene, setting: Setting, value: integer) scene.ui.revertMode(); (scene.ui.getHandler() as SettingsUiHandler).setOptionCursor(Object.values(Setting).indexOf(Setting.Language), 0, true); }; - const changeLocaleHandler = (locale: string) => { - i18next.changeLanguage(locale); - localStorage.setItem('prLang', locale); - cancelHandler(); - scene.reset(true, false, true); + const changeLocaleHandler = (locale: string): boolean => { + try { + i18next.changeLanguage(locale); + localStorage.setItem('prLang', locale); + cancelHandler(); + scene.reset(true, false, true); + return true; + } catch (error) { + console.error('Error changing locale:', error); + return false; + } }; scene.ui.setOverlayMode(Mode.OPTION_SELECT, { options: [ diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index a20f3a3647f..c3681651964 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -271,6 +271,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler { // The font size should be set per language // currentLanguage is already defined switch (currentLanguage) { + case 'fr': + starterInfoTextSize = '54px'; + break; case 'pt_BR': starterInfoTextSize = '47px'; break; diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index 943679cae39..0655880d271 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -494,20 +494,16 @@ export default class SummaryUiHandler extends UiHandler { } break; case Button.LEFT: - if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) - break; if (this.cursor) success = this.setCursor(this.cursor - 1); break; case Button.RIGHT: - if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { - this.setCursor(Page.MOVES); - this.moveSelect = true; - success = true; - break; - } - if (this.cursor < pages.length - 1) + if (this.cursor < pages.length - 1) { success = this.setCursor(this.cursor + 1); + if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE && this.cursor === Page.MOVES) { + this.moveSelect = true; + } + } break; } } @@ -614,13 +610,7 @@ export default class SummaryUiHandler extends UiHandler { onComplete: () => { if (forward){ this.populatePageContainer(this.summaryPageContainer); - if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { - this.moveCursorObj = null; - this.extraMoveRowContainer.setVisible(true); - this.setCursor(0, true); - this.showMoveEffect(); - } - else if (this.cursor===Page.MOVES) { + if (this.cursor===Page.MOVES) { this.moveCursorObj = null; this.showMoveSelect(); this.showMoveEffect();