diff --git a/package-lock.json b/package-lock.json index da89f87b0bd..66400b14459 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pokemon-rogue-battle", - "version": "1.9.2", + "version": "1.9.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pokemon-rogue-battle", - "version": "1.9.2", + "version": "1.9.4", "hasInstallScript": true, "dependencies": { "@material/material-color-utilities": "^0.2.7", diff --git a/package.json b/package.json index d5eb1138776..7d1ba35154a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.9.2", + "version": "1.9.4", "type": "module", "scripts": { "start": "vite", diff --git a/public/battle-anims/common-sandstorm.json b/public/battle-anims/common-sandstorm.json index b5b2d29f54c..fba90a08645 100644 --- a/public/battle-anims/common-sandstorm.json +++ b/public/battle-anims/common-sandstorm.json @@ -542,6 +542,79 @@ "volume": 100, "pitch": 55, "eventType": "AnimTimedSoundEvent" + }, + { + "frameIndex": 0, + "resourceName": "PRAS- Sandstorm", + "bgX": -50, + "bgY": 0, + "opacity": 0, + "duration": 5, + "eventType": "AnimTimedAddBgEvent" + }, + { + "frameIndex": 0, + "resourceName": "", + "bgX": -50, + "bgY": 0, + "opacity": 96, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "3": [ + { + "frameIndex": 3, + "resourceName": "", + "bgX": -25, + "bgY": 0, + "opacity": 128, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "6": [ + { + "frameIndex": 6, + "resourceName": "", + "bgX": 0, + "bgY": 0, + "opacity": 192, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "9": [ + { + "frameIndex": 9, + "resourceName": "", + "bgX": 25, + "bgY": 0, + "opacity": 128, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "12": [ + { + "frameIndex": 12, + "resourceName": "", + "bgX": 50, + "bgY": 0, + "opacity": 96, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "15": [ + { + "frameIndex": 15, + "resourceName": "", + "bgX": 50, + "bgY": 0, + "opacity": 0, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" } ] }, diff --git a/public/exp-sprites.json b/public/exp-sprites.json index 2595b5a7983..5580bb5cb7d 100644 --- a/public/exp-sprites.json +++ b/public/exp-sprites.json @@ -179,8 +179,6 @@ "483-origin", "484-origin", "484-origin", - "487-origin", - "487-origin", "531-mega", "531-mega", "569-gigantamax", @@ -1293,8 +1291,6 @@ "483b-origin", "484b-origin", "484b-origin", - "487b-origin", - "487b-origin", "531b-mega", "531b-mega", "569b-gigantamax", @@ -2407,8 +2403,6 @@ "483sb-origin", "484sb-origin", "484sb-origin", - "487sb-origin", - "487sb-origin", "531sb-mega", "531sb-mega", "569sb-gigantamax", @@ -3526,8 +3520,6 @@ "483s-origin", "484s-origin", "484s-origin", - "487s-origin", - "487s-origin", "531s-mega", "531s-mega", "569s-gigantamax", diff --git a/public/images/pokemon/exp/487-origin.json b/public/images/pokemon/exp/487-origin.json deleted file mode 100644 index a146f68d70d..00000000000 --- a/public/images/pokemon/exp/487-origin.json +++ /dev/null @@ -1,566 +0,0 @@ -{ - "textures": [ - { - "image": "487-origin.png", - "format": "RGBA8888", - "size": { - "w": 318, - "h": 318 - }, - "scale": 1, - "frames": [ - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 8, - "w": 91, - "h": 77 - }, - "frame": { - "x": 0, - "y": 0, - "w": 91, - "h": 77 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 8, - "w": 91, - "h": 77 - }, - "frame": { - "x": 0, - "y": 0, - "w": 91, - "h": 77 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 9, - "w": 91, - "h": 74 - }, - "frame": { - "x": 91, - "y": 0, - "w": 91, - "h": 74 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 10, - "w": 91, - "h": 74 - }, - "frame": { - "x": 91, - "y": 0, - "w": 91, - "h": 74 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 10, - "w": 91, - "h": 74 - }, - "frame": { - "x": 91, - "y": 0, - "w": 91, - "h": 74 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 6, - "w": 89, - "h": 75 - }, - "frame": { - "x": 182, - "y": 0, - "w": 89, - "h": 75 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 7, - "w": 89, - "h": 75 - }, - "frame": { - "x": 182, - "y": 0, - "w": 89, - "h": 75 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 7, - "w": 89, - "h": 75 - }, - "frame": { - "x": 182, - "y": 0, - "w": 89, - "h": 75 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 7, - "w": 86, - "h": 79 - }, - "frame": { - "x": 91, - "y": 74, - "w": 86, - "h": 79 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 8, - "w": 86, - "h": 79 - }, - "frame": { - "x": 91, - "y": 74, - "w": 86, - "h": 79 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 1, - "w": 85, - "h": 83 - }, - "frame": { - "x": 0, - "y": 77, - "w": 85, - "h": 83 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 85, - "h": 83 - }, - "frame": { - "x": 0, - "y": 77, - "w": 85, - "h": 83 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 85, - "h": 82 - }, - "frame": { - "x": 177, - "y": 75, - "w": 85, - "h": 82 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 83, - "h": 83 - }, - "frame": { - "x": 85, - "y": 153, - "w": 83, - "h": 83 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 4, - "y": 1, - "w": 83, - "h": 83 - }, - "frame": { - "x": 85, - "y": 153, - "w": 83, - "h": 83 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 80, - "h": 82 - }, - "frame": { - "x": 0, - "y": 236, - "w": 80, - "h": 82 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 80, - "h": 82 - }, - "frame": { - "x": 0, - "y": 236, - "w": 80, - "h": 82 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 6, - "y": 3, - "w": 80, - "h": 82 - }, - "frame": { - "x": 0, - "y": 236, - "w": 80, - "h": 82 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 83, - "h": 76 - }, - "frame": { - "x": 0, - "y": 160, - "w": 83, - "h": 76 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 2, - "y": 5, - "w": 83, - "h": 76 - }, - "frame": { - "x": 0, - "y": 160, - "w": 83, - "h": 76 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 81, - "h": 81 - }, - "frame": { - "x": 80, - "y": 236, - "w": 81, - "h": 81 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 81, - "h": 80 - }, - "frame": { - "x": 161, - "y": 236, - "w": 81, - "h": 80 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 81, - "h": 80 - }, - "frame": { - "x": 161, - "y": 236, - "w": 81, - "h": 80 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 3, - "w": 81, - "h": 79 - }, - "frame": { - "x": 168, - "y": 157, - "w": 81, - "h": 79 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 81, - "h": 79 - }, - "frame": { - "x": 168, - "y": 157, - "w": 81, - "h": 79 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 81, - "h": 79 - }, - "frame": { - "x": 168, - "y": 157, - "w": 81, - "h": 79 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:f669baef18fc6ae83124ad81c9b726f9:b705ee5bfe7dc7d92c348ffa4a4d6ce2:5d19509f6557fe13b0b6311434ba7e2d$" - } -} diff --git a/public/images/pokemon/exp/487-origin.png b/public/images/pokemon/exp/487-origin.png deleted file mode 100644 index 370ddf89173..00000000000 Binary files a/public/images/pokemon/exp/487-origin.png and /dev/null differ diff --git a/public/images/pokemon/exp/back/487-origin.json b/public/images/pokemon/exp/back/487-origin.json deleted file mode 100644 index 72f5e4d4dc4..00000000000 --- a/public/images/pokemon/exp/back/487-origin.json +++ /dev/null @@ -1,566 +0,0 @@ -{ - "textures": [ - { - "image": "487-origin.png", - "format": "RGBA8888", - "size": { - "w": 326, - "h": 326 - }, - "scale": 1, - "frames": [ - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 95, - "h": 84 - }, - "frame": { - "x": 0, - "y": 0, - "w": 95, - "h": 84 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 95, - "h": 84 - }, - "frame": { - "x": 0, - "y": 0, - "w": 95, - "h": 84 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 97, - "h": 79 - }, - "frame": { - "x": 0, - "y": 84, - "w": 97, - "h": 79 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 97, - "h": 79 - }, - "frame": { - "x": 0, - "y": 84, - "w": 97, - "h": 79 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 97, - "h": 78 - }, - "frame": { - "x": 95, - "y": 0, - "w": 97, - "h": 78 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 97, - "h": 78 - }, - "frame": { - "x": 95, - "y": 0, - "w": 97, - "h": 78 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 97, - "h": 78 - }, - "frame": { - "x": 95, - "y": 0, - "w": 97, - "h": 78 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 4, - "w": 94, - "h": 84 - }, - "frame": { - "x": 97, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 94, - "h": 84 - }, - "frame": { - "x": 97, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 94, - "h": 84 - }, - "frame": { - "x": 97, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 6, - "w": 95, - "h": 81 - }, - "frame": { - "x": 97, - "y": 162, - "w": 95, - "h": 81 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 7, - "w": 95, - "h": 81 - }, - "frame": { - "x": 97, - "y": 162, - "w": 95, - "h": 81 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 1, - "w": 94, - "h": 84 - }, - "frame": { - "x": 191, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 94, - "h": 84 - }, - "frame": { - "x": 191, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 94, - "h": 77 - }, - "frame": { - "x": 192, - "y": 0, - "w": 94, - "h": 77 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 94, - "h": 77 - }, - "frame": { - "x": 192, - "y": 0, - "w": 94, - "h": 77 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 94, - "h": 77 - }, - "frame": { - "x": 192, - "y": 0, - "w": 94, - "h": 77 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 94, - "h": 83 - }, - "frame": { - "x": 0, - "y": 163, - "w": 94, - "h": 83 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 92, - "h": 83 - }, - "frame": { - "x": 192, - "y": 162, - "w": 92, - "h": 83 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 0, - "y": 6, - "w": 92, - "h": 82 - }, - "frame": { - "x": 94, - "y": 243, - "w": 92, - "h": 82 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 0, - "y": 6, - "w": 92, - "h": 82 - }, - "frame": { - "x": 94, - "y": 243, - "w": 92, - "h": 82 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 90, - "h": 78 - }, - "frame": { - "x": 0, - "y": 246, - "w": 90, - "h": 78 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 90, - "h": 78 - }, - "frame": { - "x": 0, - "y": 246, - "w": 90, - "h": 78 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 91, - "h": 81 - }, - "frame": { - "x": 186, - "y": 245, - "w": 91, - "h": 81 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 91, - "h": 81 - }, - "frame": { - "x": 186, - "y": 245, - "w": 91, - "h": 81 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 91, - "h": 81 - }, - "frame": { - "x": 186, - "y": 245, - "w": 91, - "h": 81 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:d1a63c2aac4c99e778e6efb9fa120e53:11f49886c328fc8474daefc2533a7f5d:5d19509f6557fe13b0b6311434ba7e2d$" - } -} diff --git a/public/images/pokemon/exp/back/487-origin.png b/public/images/pokemon/exp/back/487-origin.png deleted file mode 100644 index ec3dfd6c8f8..00000000000 Binary files a/public/images/pokemon/exp/back/487-origin.png and /dev/null differ diff --git a/public/images/pokemon/exp/back/shiny/487-origin.json b/public/images/pokemon/exp/back/shiny/487-origin.json deleted file mode 100644 index 8da21992405..00000000000 --- a/public/images/pokemon/exp/back/shiny/487-origin.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "textures": [ - { - "image": "487-origin.png", - "format": "RGBA8888", - "size": { - "w": 326, - "h": 326 - }, - "scale": 1, - "frames": [ - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 2, - "y": 2, - "w": 95, - "h": 84 - }, - "frame": { - "x": 0, - "y": 0, - "w": 95, - "h": 84 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 2, - "y": 7, - "w": 97, - "h": 79 - }, - "frame": { - "x": 0, - "y": 84, - "w": 97, - "h": 79 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 97, - "h": 78 - }, - "frame": { - "x": 95, - "y": 0, - "w": 97, - "h": 78 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 94, - "h": 84 - }, - "frame": { - "x": 97, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 1, - "y": 6, - "w": 95, - "h": 81 - }, - "frame": { - "x": 97, - "y": 162, - "w": 95, - "h": 81 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 1, - "w": 94, - "h": 84 - }, - "frame": { - "x": 191, - "y": 78, - "w": 94, - "h": 84 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 94, - "h": 77 - }, - "frame": { - "x": 192, - "y": 0, - "w": 94, - "h": 77 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 94, - "h": 77 - }, - "frame": { - "x": 192, - "y": 0, - "w": 94, - "h": 77 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 94, - "h": 83 - }, - "frame": { - "x": 0, - "y": 163, - "w": 94, - "h": 83 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 92, - "h": 83 - }, - "frame": { - "x": 192, - "y": 162, - "w": 92, - "h": 83 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 0, - "y": 6, - "w": 92, - "h": 82 - }, - "frame": { - "x": 94, - "y": 243, - "w": 92, - "h": 82 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 90, - "h": 78 - }, - "frame": { - "x": 0, - "y": 246, - "w": 90, - "h": 78 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 101, - "h": 88 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 91, - "h": 81 - }, - "frame": { - "x": 186, - "y": 245, - "w": 91, - "h": 81 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:47e13c1a7a77825c7cf7e9fb039c2587:68949a6c55126e61a0a82829cd6ac5a8:5d19509f6557fe13b0b6311434ba7e2d$" - } -} diff --git a/public/images/pokemon/exp/back/shiny/487-origin.png b/public/images/pokemon/exp/back/shiny/487-origin.png deleted file mode 100644 index 95bee551e5d..00000000000 Binary files a/public/images/pokemon/exp/back/shiny/487-origin.png and /dev/null differ diff --git a/public/images/pokemon/exp/shiny/487-origin.json b/public/images/pokemon/exp/shiny/487-origin.json deleted file mode 100644 index d770a34a1b8..00000000000 --- a/public/images/pokemon/exp/shiny/487-origin.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "textures": [ - { - "image": "487-origin.png", - "format": "RGBA8888", - "size": { - "w": 318, - "h": 318 - }, - "scale": 1, - "frames": [ - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 8, - "w": 91, - "h": 77 - }, - "frame": { - "x": 0, - "y": 0, - "w": 91, - "h": 77 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 10, - "w": 91, - "h": 74 - }, - "frame": { - "x": 91, - "y": 0, - "w": 91, - "h": 74 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 6, - "w": 89, - "h": 75 - }, - "frame": { - "x": 182, - "y": 0, - "w": 89, - "h": 75 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 0, - "y": 7, - "w": 89, - "h": 75 - }, - "frame": { - "x": 182, - "y": 0, - "w": 89, - "h": 75 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 7, - "w": 86, - "h": 79 - }, - "frame": { - "x": 91, - "y": 74, - "w": 86, - "h": 79 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 1, - "w": 85, - "h": 83 - }, - "frame": { - "x": 0, - "y": 77, - "w": 85, - "h": 83 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 85, - "h": 82 - }, - "frame": { - "x": 177, - "y": 75, - "w": 85, - "h": 82 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 83, - "h": 83 - }, - "frame": { - "x": 85, - "y": 153, - "w": 83, - "h": 83 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 80, - "h": 82 - }, - "frame": { - "x": 0, - "y": 236, - "w": 80, - "h": 82 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 83, - "h": 76 - }, - "frame": { - "x": 0, - "y": 160, - "w": 83, - "h": 76 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 81, - "h": 81 - }, - "frame": { - "x": 80, - "y": 236, - "w": 81, - "h": 81 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 81, - "h": 80 - }, - "frame": { - "x": 161, - "y": 236, - "w": 81, - "h": 80 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 91, - "h": 87 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 81, - "h": 79 - }, - "frame": { - "x": 168, - "y": 157, - "w": 81, - "h": 79 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:00abebb007c47ada81d4e754581d7146:4691e19364eb9392dbee1ee37d737c8b:5d19509f6557fe13b0b6311434ba7e2d$" - } -} diff --git a/public/images/pokemon/exp/shiny/487-origin.png b/public/images/pokemon/exp/shiny/487-origin.png deleted file mode 100644 index d0f0fdb6b9b..00000000000 Binary files a/public/images/pokemon/exp/shiny/487-origin.png and /dev/null differ diff --git a/public/images/pokemon/shiny/890.json b/public/images/pokemon/shiny/890.json index 15d4be50370..527f9bbf500 100644 --- a/public/images/pokemon/shiny/890.json +++ b/public/images/pokemon/shiny/890.json @@ -4,30 +4,1815 @@ "image": "890.png", "format": "RGBA8888", "size": { - "w": 92, - "h": 88 + "w": 539, + "h": 539 }, "scale": 1, "frames": [ + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 19, + "w": 96, + "h": 66 + }, + "frame": { + "x": 0, + "y": 0, + "w": 96, + "h": 66 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 19, + "w": 96, + "h": 66 + }, + "frame": { + "x": 96, + "y": 0, + "w": 96, + "h": 66 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 19, + "w": 96, + "h": 66 + }, + "frame": { + "x": 192, + "y": 0, + "w": 96, + "h": 66 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 19, + "w": 96, + "h": 67 + }, + "frame": { + "x": 288, + "y": 0, + "w": 96, + "h": 67 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 1, + "y": 19, + "w": 95, + "h": 67 + }, + "frame": { + "x": 384, + "y": 0, + "w": 95, + "h": 67 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 19, + "w": 96, + "h": 68 + }, + "frame": { + "x": 0, + "y": 66, + "w": 96, + "h": 68 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 19, + "w": 96, + "h": 68 + }, + "frame": { + "x": 96, + "y": 66, + "w": 96, + "h": 68 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 19, + "w": 96, + "h": 68 + }, + "frame": { + "x": 192, + "y": 66, + "w": 96, + "h": 68 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 18, + "w": 96, + "h": 68 + }, + "frame": { + "x": 288, + "y": 67, + "w": 96, + "h": 68 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 19, + "w": 96, + "h": 69 + }, + "frame": { + "x": 384, + "y": 67, + "w": 96, + "h": 69 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 19, + "w": 96, + "h": 69 + }, + "frame": { + "x": 0, + "y": 134, + "w": 96, + "h": 69 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 19, + "w": 96, + "h": 69 + }, + "frame": { + "x": 96, + "y": 134, + "w": 96, + "h": 69 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 0, + "y": 16, + "w": 96, + "h": 71 + }, + "frame": { + "x": 192, + "y": 134, + "w": 96, + "h": 71 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 6, + "y": 10, + "w": 88, + "h": 73 + }, + "frame": { + "x": 288, + "y": 135, + "w": 88, + "h": 73 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 16, + "w": 92, + "h": 73 + }, + "frame": { + "x": 376, + "y": 136, + "w": 92, + "h": 73 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 1, + "y": 13, + "w": 95, + "h": 74 + }, + "frame": { + "x": 0, + "y": 203, + "w": 95, + "h": 74 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 1, + "y": 13, + "w": 94, + "h": 76 + }, + "frame": { + "x": 95, + "y": 203, + "w": 94, + "h": 76 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 1, + "y": 13, + "w": 94, + "h": 76 + }, + "frame": { + "x": 95, + "y": 203, + "w": 94, + "h": 76 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 1, + "y": 13, + "w": 94, + "h": 76 + }, + "frame": { + "x": 95, + "y": 203, + "w": 94, + "h": 76 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 1, + "y": 13, + "w": 94, + "h": 76 + }, + "frame": { + "x": 95, + "y": 203, + "w": 94, + "h": 76 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 12, + "w": 89, + "h": 77 + }, + "frame": { + "x": 189, + "y": 205, + "w": 89, + "h": 77 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 12, + "w": 89, + "h": 77 + }, + "frame": { + "x": 189, + "y": 205, + "w": 89, + "h": 77 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 12, + "w": 89, + "h": 77 + }, + "frame": { + "x": 189, + "y": 205, + "w": 89, + "h": 77 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 12, + "w": 89, + "h": 77 + }, + "frame": { + "x": 189, + "y": 205, + "w": 89, + "h": 77 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 11, + "w": 94, + "h": 77 + }, + "frame": { + "x": 278, + "y": 208, + "w": 94, + "h": 77 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 11, + "w": 94, + "h": 77 + }, + "frame": { + "x": 278, + "y": 208, + "w": 94, + "h": 77 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 11, + "w": 94, + "h": 77 + }, + "frame": { + "x": 278, + "y": 208, + "w": 94, + "h": 77 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 11, + "w": 94, + "h": 77 + }, + "frame": { + "x": 278, + "y": 208, + "w": 94, + "h": 77 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 1, + "y": 9, + "w": 95, + "h": 77 + }, + "frame": { + "x": 372, + "y": 209, + "w": 95, + "h": 77 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 11, + "w": 86, + "h": 78 + }, + "frame": { + "x": 0, + "y": 277, + "w": 86, + "h": 78 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 11, + "w": 86, + "h": 78 + }, + "frame": { + "x": 0, + "y": 277, + "w": 86, + "h": 78 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 11, + "w": 86, + "h": 78 + }, + "frame": { + "x": 0, + "y": 277, + "w": 86, + "h": 78 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 11, + "w": 86, + "h": 78 + }, + "frame": { + "x": 0, + "y": 277, + "w": 86, + "h": 78 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, + "w": 92, + "h": 78 + }, + "frame": { + "x": 86, + "y": 279, + "w": 92, + "h": 78 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, + "w": 92, + "h": 78 + }, + "frame": { + "x": 86, + "y": 279, + "w": 92, + "h": 78 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, + "w": 92, + "h": 78 + }, + "frame": { + "x": 86, + "y": 279, + "w": 92, + "h": 78 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, + "w": 92, + "h": 78 + }, + "frame": { + "x": 86, + "y": 279, + "w": 92, + "h": 78 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 91, + "h": 78 + }, + "frame": { + "x": 178, + "y": 282, + "w": 91, + "h": 78 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 91, + "h": 78 + }, + "frame": { + "x": 178, + "y": 282, + "w": 91, + "h": 78 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 91, + "h": 78 + }, + "frame": { + "x": 178, + "y": 282, + "w": 91, + "h": 78 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 91, + "h": 78 + }, + "frame": { + "x": 178, + "y": 282, + "w": 91, + "h": 78 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 4, + "w": 91, + "h": 78 + }, + "frame": { + "x": 269, + "y": 285, + "w": 91, + "h": 78 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 4, + "w": 91, + "h": 78 + }, + "frame": { + "x": 269, + "y": 285, + "w": 91, + "h": 78 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 4, + "w": 91, + "h": 78 + }, + "frame": { + "x": 269, + "y": 285, + "w": 91, + "h": 78 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 4, + "w": 91, + "h": 78 + }, + "frame": { + "x": 269, + "y": 285, + "w": 91, + "h": 78 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 86, + "h": 78 + }, + "frame": { + "x": 360, + "y": 286, + "w": 86, + "h": 78 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 9, + "w": 86, + "h": 79 + }, + "frame": { + "x": 446, + "y": 286, + "w": 86, + "h": 79 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 9, + "w": 86, + "h": 79 + }, + "frame": { + "x": 446, + "y": 286, + "w": 86, + "h": 79 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 9, + "w": 86, + "h": 79 + }, + "frame": { + "x": 446, + "y": 286, + "w": 86, + "h": 79 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 9, + "w": 86, + "h": 79 + }, + "frame": { + "x": 446, + "y": 286, + "w": 86, + "h": 79 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 3, + "y": 6, + "w": 85, + "h": 80 + }, + "frame": { + "x": 0, + "y": 355, + "w": 85, + "h": 80 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 3, + "y": 6, + "w": 85, + "h": 80 + }, + "frame": { + "x": 0, + "y": 355, + "w": 85, + "h": 80 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 3, + "y": 6, + "w": 85, + "h": 80 + }, + "frame": { + "x": 0, + "y": 355, + "w": 85, + "h": 80 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 3, + "y": 6, + "w": 85, + "h": 80 + }, + "frame": { + "x": 0, + "y": 355, + "w": 85, + "h": 80 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 2, + "y": 6, + "w": 93, + "h": 79 + }, + "frame": { + "x": 85, + "y": 357, + "w": 93, + "h": 79 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 90, + "h": 80 + }, + "frame": { + "x": 178, + "y": 360, + "w": 90, + "h": 80 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 90, + "h": 80 + }, + "frame": { + "x": 178, + "y": 360, + "w": 90, + "h": 80 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 90, + "h": 80 + }, + "frame": { + "x": 178, + "y": 360, + "w": 90, + "h": 80 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 90, + "h": 80 + }, + "frame": { + "x": 178, + "y": 360, + "w": 90, + "h": 80 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 86, + "h": 81 + }, + "frame": { + "x": 268, + "y": 363, + "w": 86, + "h": 81 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 86, + "h": 81 + }, + "frame": { + "x": 268, + "y": 363, + "w": 86, + "h": 81 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 86, + "h": 81 + }, + "frame": { + "x": 268, + "y": 363, + "w": 86, + "h": 81 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 3, + "y": 4, + "w": 86, + "h": 81 + }, + "frame": { + "x": 268, + "y": 363, + "w": 86, + "h": 81 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 88, + "h": 82 + }, + "frame": { + "x": 354, + "y": 364, + "w": 88, + "h": 82 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 88, + "h": 82 + }, + "frame": { + "x": 354, + "y": 364, + "w": 88, + "h": 82 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 88, + "h": 82 + }, + "frame": { + "x": 354, + "y": 364, + "w": 88, + "h": 82 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 88, + "h": 82 + }, + "frame": { + "x": 354, + "y": 364, + "w": 88, + "h": 82 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 87, + "h": 82 + }, + "frame": { + "x": 442, + "y": 365, + "w": 87, + "h": 82 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 87, + "h": 82 + }, + "frame": { + "x": 442, + "y": 365, + "w": 87, + "h": 82 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 87, + "h": 82 + }, + "frame": { + "x": 442, + "y": 365, + "w": 87, + "h": 82 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 87, + "h": 82 + }, + "frame": { + "x": 442, + "y": 365, + "w": 87, + "h": 82 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 91, + "h": 82 + }, + "frame": { + "x": 0, + "y": 436, + "w": 91, + "h": 82 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 91, + "h": 82 + }, + "frame": { + "x": 0, + "y": 436, + "w": 91, + "h": 82 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 91, + "h": 82 + }, + "frame": { + "x": 0, + "y": 436, + "w": 91, + "h": 82 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 1, + "w": 91, + "h": 82 + }, + "frame": { + "x": 0, + "y": 436, + "w": 91, + "h": 82 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 88, + "h": 82 + }, + "frame": { + "x": 91, + "y": 440, + "w": 88, + "h": 82 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 89, + "h": 85 + }, + "frame": { + "x": 179, + "y": 440, + "w": 89, + "h": 85 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 91, + "h": 82 + }, + "frame": { + "x": 268, + "y": 446, + "w": 91, + "h": 82 + } + }, { "filename": "0001.png", "rotated": false, "trimmed": true, "sourceSize": { "w": 96, - "h": 96 + "h": 89 }, "spriteSourceSize": { - "x": 2, - "y": 4, - "w": 92, - "h": 88 + "x": 4, + "y": 0, + "w": 90, + "h": 84 }, "frame": { - "x": 0, + "x": 359, + "y": 447, + "w": 90, + "h": 84 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, "y": 0, - "w": 92, - "h": 88 + "w": 90, + "h": 84 + }, + "frame": { + "x": 359, + "y": 447, + "w": 90, + "h": 84 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 90, + "h": 84 + }, + "frame": { + "x": 359, + "y": 447, + "w": 90, + "h": 84 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 90, + "h": 84 + }, + "frame": { + "x": 359, + "y": 447, + "w": 90, + "h": 84 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 90, + "h": 84 + }, + "frame": { + "x": 449, + "y": 447, + "w": 90, + "h": 84 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 90, + "h": 84 + }, + "frame": { + "x": 449, + "y": 447, + "w": 90, + "h": 84 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 90, + "h": 84 + }, + "frame": { + "x": 449, + "y": 447, + "w": 90, + "h": 84 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 96, + "h": 89 + }, + "spriteSourceSize": { + "x": 4, + "y": 0, + "w": 90, + "h": 84 + }, + "frame": { + "x": 449, + "y": 447, + "w": 90, + "h": 84 } } ] @@ -36,6 +1821,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:15403e46a7a5b364c2a2147d4eb7d7c3:2e867b4ea704cf035cb5af056c17a9c3:cedd2711a12bbacba5623505fe88bd92$" + "smartupdate": "$TexturePacker:SmartUpdate:fa96c0e3d65728e89186519f4cb67c52:fea71255f53302925c1d757e4cf5549f:cedd2711a12bbacba5623505fe88bd92$" } } diff --git a/public/images/pokemon/shiny/890.png b/public/images/pokemon/shiny/890.png index d59419ca66c..98e82b38b21 100644 Binary files a/public/images/pokemon/shiny/890.png and b/public/images/pokemon/shiny/890.png differ diff --git a/public/locales b/public/locales index f4b8b7b737e..42cd5cf577f 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit f4b8b7b737e47eaf7e7231855d0b59f8c7c7c0f8 +Subproject commit 42cd5cf577f475c22bc82d55e7ca358eb4f3184f diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 39bd1dd64cf..5835ee08af5 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1045,7 +1045,7 @@ export default class BattleScene extends SceneBase { y: number, originX = 0.5, originY = 0.5, - ignoreOverride = false, + ignoreOverride = true, useIllusion = false, ): Phaser.GameObjects.Container { const container = this.add.container(x, y); @@ -1053,9 +1053,9 @@ export default class BattleScene extends SceneBase { const icon = this.add.sprite(0, 0, pokemon.getIconAtlasKey(ignoreOverride, useIllusion)); icon.setName(`sprite-${pokemon.name}-icon`); - icon.setFrame(pokemon.getIconId(true, useIllusion)); + icon.setFrame(pokemon.getIconId(ignoreOverride, useIllusion)); // Temporary fix to show pokemon's default icon if variant icon doesn't exist - if (icon.frame.name !== pokemon.getIconId(true, useIllusion)) { + if (icon.frame.name !== pokemon.getIconId(ignoreOverride, useIllusion)) { console.log(`${pokemon.name}'s variant icon does not exist. Replacing with default.`); const temp = pokemon.shiny; pokemon.shiny = false; @@ -1071,7 +1071,7 @@ export default class BattleScene extends SceneBase { const fusionIcon = this.add.sprite(0, 0, pokemon.getFusionIconAtlasKey(ignoreOverride, useIllusion)); fusionIcon.setName("sprite-fusion-icon"); fusionIcon.setOrigin(0.5, 0); - fusionIcon.setFrame(pokemon.getFusionIconId(true, useIllusion)); + fusionIcon.setFrame(pokemon.getFusionIconId(ignoreOverride, useIllusion)); const originalWidth = icon.width; const originalHeight = icon.height; @@ -2921,7 +2921,10 @@ export default class BattleScene extends SceneBase { instant?: boolean, cost?: number, ): boolean { - if (!modifier) { + // We check against modifier.type to stop a bug related to loading in a pokemon that has a form change item, which prior to some patch + // that changed form change modifiers worked, had previously set the `type` field to null. + // TODO: This is not the right place to check for this; it should ideally go in a session migrator. + if (!modifier || !modifier.type) { return false; } let success = false; diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index 4609ff6ec1a..ff86937622b 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -850,14 +850,14 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { } override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; return move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && !attacker.status - && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) + && (this.chance === -1 || pokemon.randBattleSeedInt(100) < this.chance) && attacker.canSetStatus(effect, true, false, pokemon); } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; attacker.trySetStatus(effect, true, pokemon); } } @@ -891,7 +891,7 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { } override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { - return move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && pokemon.randSeedInt(100) < this.chance + return move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && pokemon.randBattleSeedInt(100) < this.chance && attacker.canAddTag(this.tagType); } @@ -1068,7 +1068,7 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr { override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { return attacker.getTag(BattlerTagType.DISABLED) === null - && move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance); + && move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon}) && (this.chance === -1 || pokemon.randBattleSeedInt(100) < this.chance); } override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { @@ -1741,7 +1741,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { const heldItems = this.getTargetHeldItems(defender).filter((i) => i.isTransferable); if (heldItems.length) { // Ensure that the stolen item in testing is the same as when the effect is applied - this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; + this.stolenItem = heldItems[pokemon.randBattleSeedInt(heldItems.length)]; if (globalScene.canTransferHeldItemModifier(this.stolenItem, pokemon)) { return true; } @@ -1762,7 +1762,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { ): void { const heldItems = this.getTargetHeldItems(defender).filter((i) => i.isTransferable); if (!this.stolenItem) { - this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; + this.stolenItem = heldItems[pokemon.randBattleSeedInt(heldItems.length)]; } if (globalScene.tryTransferHeldItemModifier(this.stolenItem, pokemon, false)) { globalScene.queueMessage( @@ -1799,9 +1799,9 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { if ( super.canApplyPostAttack(pokemon, passive, simulated, attacker, move, hitResult, args) && (simulated || !attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker - && (!this.contactRequired || move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon})) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) + && (!this.contactRequired || move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon})) && pokemon.randBattleSeedInt(100) < this.chance && !pokemon.status) ) { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; return simulated || attacker.canSetStatus(effect, true, false, pokemon); } @@ -1809,7 +1809,7 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { } applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): void { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; attacker.trySetStatus(effect, true, pokemon); } } @@ -1839,12 +1839,12 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr { return super.canApplyPostAttack(pokemon, passive, simulated, attacker, move, hitResult, args) && !attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker && (!this.contactRequired || move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon})) && - pokemon.randSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status; + pokemon.randBattleSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status; } override applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): void { if (!simulated) { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; attacker.addTag(effect); } } @@ -1868,7 +1868,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { ) { const heldItems = this.getTargetHeldItems(attacker).filter((i) => i.isTransferable); if (heldItems.length) { - this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; + this.stolenItem = heldItems[pokemon.randBattleSeedInt(heldItems.length)]; if (globalScene.canTransferHeldItemModifier(this.stolenItem, pokemon)) { return true; } @@ -1889,7 +1889,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { const heldItems = this.getTargetHeldItems(attacker).filter((i) => i.isTransferable); if (!this.stolenItem) { - this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; + this.stolenItem = heldItems[pokemon.randBattleSeedInt(heldItems.length)]; } if (globalScene.tryTransferHeldItemModifier(this.stolenItem, pokemon, false)) { globalScene.queueMessage( @@ -3171,7 +3171,7 @@ export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr { */ override applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): void { if (!simulated) { - defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedIntRange(2, 5), move.id, defender.id); + defender.addTag(BattlerTagType.CONFUSED, pokemon.randBattleSeedIntRange(2, 5), move.id, defender.id); } } } @@ -4235,12 +4235,12 @@ export class MoodyAbAttr extends PostTurnAbAttr { if (!simulated) { if (canRaise.length > 0) { - const raisedStat = canRaise[pokemon.randSeedInt(canRaise.length)]; + const raisedStat = canRaise[pokemon.randBattleSeedInt(canRaise.length)]; canLower = canRaise.filter(s => s !== raisedStat); globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ raisedStat ], 2)); } if (canLower.length > 0) { - const loweredStat = canLower[pokemon.randSeedInt(canLower.length)]; + const loweredStat = canLower[pokemon.randBattleSeedInt(canLower.length)]; globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ loweredStat ], -1)); } } @@ -5349,7 +5349,7 @@ export class BypassSpeedChanceAbAttr extends AbAttr { const isCommandFight = turnCommand?.command === Command.FIGHT; const move = turnCommand?.move?.move ? allMoves[turnCommand.move.move] : null; const isDamageMove = move?.category === MoveCategory.PHYSICAL || move?.category === MoveCategory.SPECIAL; - return !simulated && !bypassSpeed.value && pokemon.randSeedInt(100) < this.chance && isCommandFight && isDamageMove; + return !simulated && !bypassSpeed.value && pokemon.randBattleSeedInt(100) < this.chance && isCommandFight && isDamageMove; } /** diff --git a/src/data/balance/signature-species.ts b/src/data/balance/signature-species.ts index fb8f33d4435..04749a67521 100644 --- a/src/data/balance/signature-species.ts +++ b/src/data/balance/signature-species.ts @@ -8,11 +8,11 @@ export type SignatureSpecies = { * The signature species for each Gym Leader, Elite Four member, and Champion. * The key is the trainer type, and the value is an array of Species or Species arrays. * This is in a separate const so it can be accessed from other places and not just the trainerConfigs - * + * * @remarks - * The `Proxy` object allows us to define a handler that will intercept + * The `Proxy` object allows us to define a handler that will intercept * the property access and return an empty array if the property does not exist in the object. - * + * * This means that accessing `signatureSpecies` will not throw an error if the property does not exist, * but instead default to an empty array. */ diff --git a/src/data/balance/tms.ts b/src/data/balance/tms.ts index 69aef9b135d..06d191c3b2a 100644 --- a/src/data/balance/tms.ts +++ b/src/data/balance/tms.ts @@ -19057,8 +19057,15 @@ export const tmSpecies: TmSpecies = { Species.SLAKING, Species.HARIYAMA, Species.NOSEPASS, + Species.ARON, + Species.LAIRON, + Species.AGGRON, + Species.ELECTRIKE, + Species.MANECTRIC, Species.GULPIN, Species.SWALOT, + Species.WAILMER, + Species.WAILORD, Species.NUMEL, Species.CAMERUPT, Species.TORKOAL, @@ -19067,18 +19074,28 @@ export const tmSpecies: TmSpecies = { Species.ZANGOOSE, Species.SEVIPER, Species.WHISCASH, + Species.LILEEP, + Species.CRADILY, + Species.ANORITH, + Species.ARMALDO, Species.SHUPPET, Species.BANETTE, Species.DUSKULL, Species.DUSCLOPS, Species.TROPIUS, Species.CHIMECHO, + Species.ABSOL, + Species.SPHEAL, + Species.SEALEO, + Species.WALREIN, Species.REGIROCK, Species.REGICE, Species.REGISTEEL, Species.TURTWIG, Species.GROTLE, Species.TORTERRA, + Species.BIDOOF, + Species.BIBAREL, Species.CRANIDOS, Species.RAMPARDOS, Species.SHIELDON, @@ -19120,6 +19137,11 @@ export const tmSpecies: TmSpecies = { Species.TEPIG, Species.PIGNITE, Species.EMBOAR, + Species.MUNNA, + Species.MUSHARNA, + Species.ROGGENROLA, + Species.BOLDORE, + Species.GIGALITH, Species.DRILBUR, Species.EXCADRILL, Species.TIMBURR, @@ -19128,28 +19150,44 @@ export const tmSpecies: TmSpecies = { Species.SANDILE, Species.KROKOROK, Species.KROOKODILE, + Species.DWEBBLE, + Species.CRUSTLE, Species.SCRAGGY, Species.SCRAFTY, Species.YAMASK, - Species.COFAGRIGUS, + Species.COFAGRIGUS, + Species.TRUBBISH, + Species.GARBODOR, Species.SAWSBUCK, + Species.FERROSEED, + Species.FERROTHORN, Species.LITWICK, Species.LAMPENT, Species.CHANDELURE, Species.BEARTIC, + Species.SHELMET, + Species.ACCELGOR, + Species.STUNFISK, Species.GOLETT, Species.GOLURK, + Species.HEATMOR, Species.CHESPIN, Species.QUILLADIN, Species.CHESNAUGHT, + Species.TYRUNT, + Species.TYRANTRUM, Species.SYLVEON, Species.GOOMY, Species.SLIGGOO, Species.GOODRA, Species.PHANTUMP, Species.TREVENANT, + Species.PUMPKABOO, + Species.GOURGEIST, Species.BERGMITE, Species.AVALUGG, + Species.ROWLET, + Species.DARTRIX, Species.DECIDUEYE, Species.GUMSHOOS, Species.MUDBRAY, @@ -19157,7 +19195,9 @@ export const tmSpecies: TmSpecies = { Species.PASSIMIAN, Species.SANDYGAST, Species.PALOSSAND, + Species.PYUKUMUKU, Species.KOMALA, + Species.TURTONATOR, Species.MIMIKYU, Species.SKWOVET, Species.GREEDENT, @@ -19169,6 +19209,7 @@ export const tmSpecies: TmSpecies = { Species.SINISTEA, Species.POLTEAGEIST, Species.PERRSERKER, + Species.CURSOLA, Species.RUNERIGUS, Species.PINCURCHIN, Species.STONJOURNER, @@ -19236,6 +19277,7 @@ export const tmSpecies: TmSpecies = { Species.GALAR_WEEZING, Species.GALAR_SLOWKING, Species.GALAR_YAMASK, + Species.GALAR_STUNFISK, Species.HISUI_ELECTRODE, Species.HISUI_TYPHLOSION, Species.HISUI_QWILFISH, @@ -67062,7 +67104,7 @@ export const tmSpecies: TmSpecies = { Species.CHEWTLE, Species.DREDNAW, Species.YAMPER, - Species.BOLTUND, + Species.BOLTUND, Species.ROLYCOLY, Species.CARKOL, Species.COALOSSAL, @@ -67079,7 +67121,7 @@ export const tmSpecies: TmSpecies = { Species.SIZZLIPEDE, Species.CENTISKORCH, Species.CLOBBOPUS, - Species.GRAPPLOCT, + Species.GRAPPLOCT, Species.SINISTEA, Species.POLTEAGEIST, Species.HATENNA, diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 8a512f3c16c..34fdd5409c8 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -766,11 +766,11 @@ export class ConfusedTag extends BattlerTag { globalScene.unshiftPhase(new CommonAnimPhase(pokemon.getBattlerIndex(), undefined, CommonAnim.CONFUSION)); // 1/3 chance of hitting self with a 40 base power move - if (pokemon.randSeedInt(3) === 0 || Overrides.CONFUSION_ACTIVATION_OVERRIDE === true) { + if (pokemon.randBattleSeedInt(3) === 0 || Overrides.CONFUSION_ACTIVATION_OVERRIDE === true) { const atk = pokemon.getEffectiveStat(Stat.ATK); const def = pokemon.getEffectiveStat(Stat.DEF); const damage = toDmgValue( - ((((2 * pokemon.level) / 5 + 2) * 40 * atk) / def / 50 + 2) * (pokemon.randSeedIntRange(85, 100) / 100), + ((((2 * pokemon.level) / 5 + 2) * 40 * atk) / def / 50 + 2) * (pokemon.randBattleSeedIntRange(85, 100) / 100), ); // Intentionally don't increment rage fist's hitCount globalScene.queueMessage(i18next.t("battlerTags:confusedLapseHurtItself")); @@ -890,7 +890,7 @@ export class InfatuatedTag extends BattlerTag { ); globalScene.unshiftPhase(new CommonAnimPhase(pokemon.getBattlerIndex(), undefined, CommonAnim.ATTRACT)); - if (pokemon.randSeedInt(2)) { + if (pokemon.randBattleSeedInt(2)) { globalScene.queueMessage( i18next.t("battlerTags:infatuatedLapseImmobilize", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), @@ -1119,7 +1119,7 @@ export class FrenzyTag extends BattlerTag { if (this.turnCount < 2) { // Only add CONFUSED tag if a disruption occurs on the final confusion-inducing turn of FRENZY - pokemon.addTag(BattlerTagType.CONFUSED, pokemon.randSeedIntRange(2, 4)); + pokemon.addTag(BattlerTagType.CONFUSED, pokemon.randBattleSeedIntRange(2, 4)); } } } diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 3ef70fd75be..71807288abc 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -1591,7 +1591,7 @@ export class RandomLevelDamageAttr extends FixedDamageAttr { } getDamage(user: Pokemon, target: Pokemon, move: Move): number { - return toDmgValue(user.level * (user.randSeedIntRange(50, 150) * 0.01)); + return toDmgValue(user.level * (user.randBattleSeedIntRange(50, 150) * 0.01)); } } @@ -2352,7 +2352,7 @@ export class MultiHitAttr extends MoveAttr { switch (this.multiHitType) { case MultiHitType._2_TO_5: { - const rand = user.randSeedInt(20); + const rand = user.randBattleSeedInt(20); const hitValue = new NumberHolder(rand); applyAbAttrs(MaxMultiHitAbAttr, user, null, false, hitValue); if (hitValue.value >= 13) { @@ -2453,7 +2453,7 @@ export class StatusEffectAttr extends MoveEffectAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); - const statusCheck = moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance; + const statusCheck = moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance; const quiet = move.category !== MoveCategory.STATUS; if (statusCheck) { const pokemon = this.selfTarget ? user : target; @@ -2560,7 +2560,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr { const poolType = target.isPlayer() ? ModifierPoolType.PLAYER : target.hasTrainer() ? ModifierPoolType.TRAINER : ModifierPoolType.WILD; const highestItemTier = heldItems.map((m) => m.type.getOrInferTier(poolType)).reduce((highestTier, tier) => Math.max(tier!, highestTier), 0); // TODO: is the bang after tier correct? const tierHeldItems = heldItems.filter((m) => m.type.getOrInferTier(poolType) === highestItemTier); - const stolenItem = tierHeldItems[user.randSeedInt(tierHeldItems.length)]; + const stolenItem = tierHeldItems[user.randBattleSeedInt(tierHeldItems.length)]; if (!globalScene.tryTransferHeldItemModifier(stolenItem, user, false)) { return false; } @@ -2636,7 +2636,7 @@ export class RemoveHeldItemAttr extends MoveEffectAttr { return false; } - const removedItem = heldItems[user.randSeedInt(heldItems.length)]; + const removedItem = heldItems[user.randBattleSeedInt(heldItems.length)]; // Decrease item amount and update icon target.loseHeldItem(removedItem); @@ -2697,7 +2697,7 @@ export class EatBerryAttr extends MoveEffectAttr { } // pick a random berry to gobble and check if we preserve it - this.chosenBerry = heldBerries[user.randSeedInt(heldBerries.length)]; + this.chosenBerry = heldBerries[user.randBattleSeedInt(heldBerries.length)]; const preserve = new BooleanHolder(false); // check for berry pouch preservation globalScene.applyModifiers(PreserveBerryModifier, pokemon.isPlayer(), pokemon, preserve); @@ -2774,7 +2774,7 @@ export class StealEatBerryAttr extends EatBerryAttr { } // pick a random berry and eat it - this.chosenBerry = heldBerries[user.randSeedInt(heldBerries.length)]; + this.chosenBerry = heldBerries[user.randBattleSeedInt(heldBerries.length)]; applyPostItemLostAbAttrs(PostItemLostAbAttr, target, false); const message = i18next.t("battle:stealEatBerry", { pokemonName: user.name, targetName: target.name, berryName: this.chosenBerry.type.name }); globalScene.queueMessage(message); @@ -3205,7 +3205,7 @@ export class StatStageChangeAttr extends MoveEffectAttr { } const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); - if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { + if (moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance) { const stages = this.getLevels(user); globalScene.unshiftPhase(new StatStageChangePhase((this.selfTarget ? user : target).getBattlerIndex(), this.selfTarget, this.stats, stages, this.showMessage)); return true; @@ -3431,7 +3431,7 @@ export class AcupressureStatStageChangeAttr extends MoveEffectAttr { override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const randStats = BATTLE_STATS.filter((s) => target.getStatStage(s) < 6); if (randStats.length > 0) { - const boostStat = [ randStats[user.randSeedInt(randStats.length)] ]; + const boostStat = [ randStats[user.randBattleSeedInt(randStats.length)] ]; globalScene.unshiftPhase(new StatStageChangePhase(target.getBattlerIndex(), this.selfTarget, boostStat, 2)); return true; } @@ -4823,7 +4823,7 @@ export class ShellSideArmCategoryAttr extends VariableMoveCategoryAttr { if (predictedPhysDmg > predictedSpecDmg) { category.value = MoveCategory.PHYSICAL; return true; - } else if (predictedPhysDmg === predictedSpecDmg && user.randSeedInt(2) === 0) { + } else if (predictedPhysDmg === predictedSpecDmg && user.randBattleSeedInt(2) === 0) { category.value = MoveCategory.PHYSICAL; return true; } @@ -5404,7 +5404,7 @@ export class FrenzyAttr extends MoveEffectAttr { } if (!user.getTag(BattlerTagType.FRENZY) && !user.getMoveQueue().length) { - const turnCount = user.randSeedIntRange(1, 2); + const turnCount = user.randBattleSeedIntRange(1, 2); new Array(turnCount).fill(null).map(() => user.getMoveQueue().push({ move: move.id, targets: [ target.getBattlerIndex() ], ignorePP: true })); user.addTag(BattlerTagType.FRENZY, turnCount, move.id, user.id); } else { @@ -5485,8 +5485,8 @@ export class AddBattlerTagAttr extends MoveEffectAttr { } const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); - if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { - return (this.selfTarget ? user : target).addTag(this.tagType, user.randSeedIntRange(this.turnCountMin, this.turnCountMax), move.id, user.id); + if (moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance) { + return (this.selfTarget ? user : target).addTag(this.tagType, user.randBattleSeedIntRange(this.turnCountMin, this.turnCountMax), move.id, user.id); } return false; @@ -5654,7 +5654,7 @@ export class JawLockAttr extends AddBattlerTagAttr { } const moveChance = this.getMoveChance(user, target, move, this.selfTarget); - if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { + if (moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance) { /** * Add the tag to both the user and the target. * The target's tag source is considered to be the user and vice versa @@ -5792,7 +5792,7 @@ export class ProtectAttr extends AddBattlerTagAttr { timesUsed++; } if (timesUsed) { - return !user.randSeedInt(Math.pow(3, timesUsed)); + return !user.randBattleSeedInt(Math.pow(3, timesUsed)); } return true; }); @@ -5916,7 +5916,7 @@ export class AddArenaTagAttr extends MoveEffectAttr { return false; } - if ((move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { + if ((move.chance < 0 || move.chance === 100 || user.randBattleSeedInt(100) < move.chance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { const side = ((this.selfSideTarget ? user : target).isPlayer() !== (move.hasAttr(AddArenaTrapTagAttr) && target === user)) ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; globalScene.arena.addTag(this.tagType, this.turnCount, move.id, user.id, side); return true; @@ -5992,7 +5992,7 @@ export class AddArenaTrapTagHitAttr extends AddArenaTagAttr { const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const tag = globalScene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; - if ((moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { + if ((moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { globalScene.arena.addTag(this.tagType, 0, move.id, user.id, side); if (!tag) { return true; @@ -6167,7 +6167,7 @@ export class RevivalBlessingAttr extends MoveEffectAttr { // If used by an enemy trainer with at least one fainted non-boss Pokemon, this // revives one of said Pokemon selected at random. const faintedPokemon = globalScene.getEnemyParty().filter((p) => p.isFainted() && !p.isBoss()); - const pokemon = faintedPokemon[user.randSeedInt(faintedPokemon.length)]; + const pokemon = faintedPokemon[user.randBattleSeedInt(faintedPokemon.length)]; const slotIndex = globalScene.getEnemyParty().findIndex((p) => pokemon.id === p.id); pokemon.resetStatus(true, false, false, true); pokemon.heal(Math.min(toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp())); @@ -6263,7 +6263,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { if (switchOutTarget.hp > 0) { if (this.switchType === SwitchType.FORCE_SWITCH) { switchOutTarget.leaveField(true); - const slotIndex = eligibleNewIndices[user.randSeedInt(eligibleNewIndices.length)]; + const slotIndex = eligibleNewIndices[user.randBattleSeedInt(eligibleNewIndices.length)]; globalScene.prependToPhase( new SwitchSummonPhase( this.switchType, @@ -6306,7 +6306,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { if (switchOutTarget.hp > 0) { if (this.switchType === SwitchType.FORCE_SWITCH) { switchOutTarget.leaveField(true); - const slotIndex = eligibleNewIndices[user.randSeedInt(eligibleNewIndices.length)]; + const slotIndex = eligibleNewIndices[user.randBattleSeedInt(eligibleNewIndices.length)]; globalScene.prependToPhase( new SwitchSummonPhase( this.switchType, @@ -6390,8 +6390,23 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { return (user, target, move) => { const switchOutTarget = (this.selfSwitch ? user : target); const player = switchOutTarget instanceof PlayerPokemon; + const forceSwitchAttr = move.getAttrs(ForceSwitchOutAttr).find(attr => attr.switchType === SwitchType.FORCE_SWITCH); if (!this.selfSwitch) { + if (move.hitsSubstitute(user, target)) { + return false; + } + + // Check if the move is Roar or Whirlwind and if there is a trainer with only Pokémon left. + if (forceSwitchAttr && globalScene.currentBattle.trainer) { + const enemyParty = globalScene.getEnemyParty(); + // Filter out any Pokémon that are not allowed in battle (e.g. fainted ones) + const remainingPokemon = enemyParty.filter(p => p.hp > 0 && p.isAllowedInBattle()); + if (remainingPokemon.length <= 1) { + return false; + } + } + // Dondozo with an allied Tatsugiri in its mouth cannot be forced out const commandedTag = switchOutTarget.getTag(BattlerTagType.COMMANDED); if (commandedTag?.getSourcePokemon()?.isActive(true)) { @@ -6725,7 +6740,7 @@ class CallMoveAttr extends OverrideMoveEffectAttr { } const targets = moveTargets.multiple || moveTargets.targets.length === 1 ? moveTargets.targets - : [ this.hasTarget ? target.getBattlerIndex() : moveTargets.targets[user.randSeedInt(moveTargets.targets.length)] ]; // account for Mirror Move having a target already + : [ this.hasTarget ? target.getBattlerIndex() : moveTargets.targets[user.randBattleSeedInt(moveTargets.targets.length)] ]; // account for Mirror Move having a target already user.getMoveQueue().push({ move: move.id, targets: targets, virtual: true, ignorePP: true }); globalScene.unshiftPhase(new LoadMoveAnimPhase(move.id)); globalScene.unshiftPhase(new MovePhase(user, targets, new PokemonMove(move.id, 0, 0, true), true, true)); @@ -6765,7 +6780,7 @@ export class RandomMoveAttr extends CallMoveAttr { const moveIds = getEnumValues(Moves).map(m => !this.invalidMoves.has(m) && !allMoves[m].name.endsWith(" (N)") ? m : Moves.NONE); let moveId: Moves = Moves.NONE; do { - moveId = this.getMoveOverride() ?? moveIds[user.randSeedInt(moveIds.length)]; + moveId = this.getMoveOverride() ?? moveIds[user.randBattleSeedInt(moveIds.length)]; } while (moveId === Moves.NONE); return super.apply(user, target, allMoves[moveId], args); @@ -6817,7 +6832,7 @@ export class RandomMovesetMoveAttr extends CallMoveAttr { return false; } - this.moveId = moves[user.randSeedInt(moves.length)]!.moveId; + this.moveId = moves[user.randBattleSeedInt(moves.length)]!.moveId; return true; }; } @@ -7900,7 +7915,7 @@ const phaseForcedSlower = (phase: MovePhase, target: Pokemon, trickRoom: boolean let slower: boolean; // quashed pokemon still have speed ties if (phase.pokemon.getEffectiveStat(Stat.SPD) === target.getEffectiveStat(Stat.SPD)) { - slower = !!target.randSeedInt(2); + slower = !!target.randBattleSeedInt(2); } else { slower = !trickRoom ? phase.pokemon.getEffectiveStat(Stat.SPD) < target.getEffectiveStat(Stat.SPD) : phase.pokemon.getEffectiveStat(Stat.SPD) > target.getEffectiveStat(Stat.SPD); } @@ -8052,10 +8067,10 @@ export class UpperHandCondition extends MoveCondition { } } -export class hitsSameTypeAttr extends VariableMoveTypeMultiplierAttr { +export class HitsSameTypeAttr extends VariableMoveTypeMultiplierAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const multiplier = args[0] as NumberHolder; - if (!user.getTypes().some(type => target.getTypes().includes(type))) { + if (!user.getTypes(true).some(type => target.getTypes(true).includes(type))) { multiplier.value = 0; return true; } @@ -8103,7 +8118,7 @@ export class ResistLastMoveTypeAttr extends MoveEffectAttr { if (!validTypes.length) { return false; } - const type = validTypes[user.randSeedInt(validTypes.length)]; + const type = validTypes[user.randBattleSeedInt(validTypes.length)]; user.summonData.types = [ type ]; globalScene.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: toReadableString(PokemonType[type]) })); user.updateInfo(); @@ -8218,7 +8233,7 @@ export function getMoveTargets(user: Pokemon, move: Moves, replaceTarget?: MoveT multiple = moveTarget !== MoveTarget.NEAR_ENEMY; break; case MoveTarget.RANDOM_NEAR_ENEMY: - set = [ opponents[user.randSeedInt(opponents.length)] ]; + set = [ opponents[user.randBattleSeedInt(opponents.length)] ]; break; case MoveTarget.ATTACKER: return { targets: [ -1 as BattlerIndex ], multiple: false }; @@ -9756,7 +9771,7 @@ export function initMoves() { new AttackMove(Moves.SYNCHRONOISE, PokemonType.PSYCHIC, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 5) .target(MoveTarget.ALL_NEAR_OTHERS) .condition(unknownTypeCondition) - .attr(hitsSameTypeAttr), + .attr(HitsSameTypeAttr), new AttackMove(Moves.ELECTRO_BALL, PokemonType.ELECTRIC, MoveCategory.SPECIAL, -1, 100, 10, -1, 0, 5) .attr(ElectroBallPowerAttr) .ballBombMove(), diff --git a/src/data/trainers/trainer-config.ts b/src/data/trainers/trainer-config.ts index 50acf84efa6..839a1cdc0cc 100644 --- a/src/data/trainers/trainer-config.ts +++ b/src/data/trainers/trainer-config.ts @@ -1,7 +1,7 @@ import { globalScene } from "#app/global-scene"; import { modifierTypes } from "#app/modifier/modifier-type"; import { PokemonMove } from "#app/field/pokemon"; -import { toReadableString, isNullOrUndefined, randSeedItem, randSeedInt } from "#app/utils/common"; +import { toReadableString, isNullOrUndefined, randSeedItem, randSeedInt, randSeedIntRange } from "#app/utils/common"; import { pokemonEvolutions, pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { tmSpecies } from "#app/data/balance/tms"; @@ -2856,21 +2856,29 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["LORELEI"], false, PokemonType.ICE, 2) .setBattleBgm("battle_kanto_gym") .setMixedBattleBgm("battle_kanto_gym") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.DEWGONG], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.DEWGONG], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 0; // Thick Fat p.generateAndPopulateMoveset(); }), ) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SLOWBRO, Species.GALAR_SLOWBRO], TrainerSlot.TRAINER, true, p => { // Tera Ice Slowbro/G-Slowbro + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.SLOWBRO, Species.GALAR_SLOWBRO], TrainerSlot.TRAINER, true, p => { + // Tera Ice Slowbro/G-Slowbro p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.ICE_BEAM)) { // Check if Ice Beam is in the moveset, if not, replace the third move with Ice Beam. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.ICE_BEAM)) { + // Check if Ice Beam is in the moveset, if not, replace the third move with Ice Beam. p.moveset[2] = new PokemonMove(Moves.ICE_BEAM); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.JYNX])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CLOYSTER, Species.ALOLA_SANDSLASH])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.LAPRAS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.LAPRAS], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2880,9 +2888,13 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_kanto_gym") .setMixedBattleBgm("battle_kanto_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.HITMONLEE, Species.HITMONCHAN, Species.HITMONTOP])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.STEELIX], TrainerSlot.TRAINER, true, p => { // Tera Fighting Steelix + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.STEELIX], TrainerSlot.TRAINER, true, p => { + // Tera Fighting Steelix p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.BODY_PRESS)) { // Check if Body Press is in the moveset, if not, replace the third move with Body Press. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.BODY_PRESS)) { + // Check if Body Press is in the moveset, if not, replace the third move with Body Press. p.moveset[2] = new PokemonMove(Moves.BODY_PRESS); } }), @@ -2901,16 +2913,22 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_kanto_gym") .setMixedBattleBgm("battle_kanto_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.MISMAGIUS])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.ARBOK, Species.WEEZING], TrainerSlot.TRAINER, true, p => { // Tera Ghost Arbok/Weezing + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.ARBOK, Species.WEEZING], TrainerSlot.TRAINER, true, p => { + // Tera Ghost Arbok/Weezing p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.ALOLA_MAROWAK])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CURSOLA])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2921,16 +2939,22 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_kanto_gym") .setMixedBattleBgm("battle_kanto_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.KINGDRA])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GYARADOS, Species.AERODACTYL], TrainerSlot.TRAINER, true, p => { // Tera Dragon Gyarados/Aerodactyl + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.GYARADOS, Species.AERODACTYL], TrainerSlot.TRAINER, true, p => { + // Tera Dragon Gyarados/Aerodactyl p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.ALOLA_EXEGGUTOR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SALAMENCE])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DRAGONITE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DRAGONITE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2943,7 +2967,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SLOWKING, Species.GALAR_SLOWKING])) // Tera Psychic Slowking/G-Slowking .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.EXEGGUTOR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.WYRDEER, Species.FARIGIRAF])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.XATU], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.XATU], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2952,7 +2978,9 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["KOGA"], true, PokemonType.POISON, 2) .setBattleBgm("battle_johto_gym") .setMixedBattleBgm("battle_johto_gym") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.VENOMOTH], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.VENOMOTH], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Tinted Lens p.generateAndPopulateMoveset(); }), @@ -2960,7 +2988,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.MUK, Species.WEEZING])) // Tera Poison Muk/Weezing .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TENTACRUEL])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SNEASLER, Species.OVERQWIL])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CROBAT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CROBAT], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2970,16 +3000,22 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_johto_gym") .setMixedBattleBgm("battle_johto_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.UMBREON])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { // Tera Dark Gengar + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { + // Tera Dark Gengar p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.DARK_PULSE)) { // Check if Dark Pulse is in the moveset, if not, replace the third move with Dark Pulse. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.DARK_PULSE)) { + // Check if Dark Pulse is in the moveset, if not, replace the third move with Dark Pulse. p.moveset[2] = new PokemonMove(Moves.DARK_PULSE); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.HONCHKROW])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.WEAVILE])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.HOUNDOOM], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.HOUNDOOM], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -2987,7 +3023,9 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.SIDNEY]: new TrainerConfig(++t) .initForEliteFour(signatureSpecies["SIDNEY"], true, PokemonType.DARK, 2) .setMixedBattleBgm("battle_hoenn_elite") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.MIGHTYENA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.MIGHTYENA], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 0; // Intimidate p.generateAndPopulateMoveset(); }), @@ -3008,12 +3046,16 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SABLEYE])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.BANETTE])) // Tera Ghost Banette .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.DRIFBLIM, Species.MISMAGIUS])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ORICORIO, Species.ALOLA_MAROWAK], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.ORICORIO, Species.ALOLA_MAROWAK], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.formIndex = p.species.speciesId === Species.ORICORIO ? 3 : 0; // Oricorio-Sensu }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DUSKNOIR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DUSKNOIR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3021,7 +3063,9 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.GLACIA]: new TrainerConfig(++t) .initForEliteFour(signatureSpecies["GLACIA"], false, PokemonType.ICE, 2) .setMixedBattleBgm("battle_hoenn_elite") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ABOMASNOW], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.ABOMASNOW], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 0; // Snow Warning p.generateAndPopulateMoveset(); }), @@ -3029,7 +3073,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GLALIE])) // Tera Ice Glalie .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.FROSLASS])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ALOLA_NINETALES])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.WALREIN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.WALREIN], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3038,16 +3084,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["DRAKE"], true, PokemonType.DRAGON, 2) .setMixedBattleBgm("battle_hoenn_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALTARIA])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.DHELMISE], TrainerSlot.TRAINER, true, p => { // Tera Dragon Dhelmise + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.DHELMISE], TrainerSlot.TRAINER, true, p => { + // Tera Dragon Dhelmise p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.FLYGON])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.KINGDRA])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.SALAMENCE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.SALAMENCE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3060,11 +3112,15 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.HERACROSS])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.VESPIQUEN])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SCIZOR, Species.KLEAVOR])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DRAPION], TrainerSlot.TRAINER, true, p => { // Tera Bug Drapion + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DRAPION], TrainerSlot.TRAINER, true, p => { + // Tera Bug Drapion p.setBoss(true, 2); p.abilityIndex = 1; // Sniper p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.X_SCISSOR)) { // Check if X-Scissor is in the moveset, if not, replace the third move with X-Scissor. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.X_SCISSOR)) { + // Check if X-Scissor is in the moveset, if not, replace the third move with X-Scissor. p.moveset[2] = new PokemonMove(Moves.X_SCISSOR); } }), @@ -3074,14 +3130,19 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_sinnoh_gym") .setMixedBattleBgm("battle_sinnoh_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.WHISCASH])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.HIPPOWDON], TrainerSlot.TRAINER, true, p => { // Tera Ground Hippowdon + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.HIPPOWDON], TrainerSlot.TRAINER, true, p => { + // Tera Ground Hippowdon p.abilityIndex = 0; // Sand Stream p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GLISCOR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MAMOSWINE, Species.URSALUNA])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.RHYPERIOR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.RHYPERIOR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.abilityIndex = 1; // Solid Rock p.generateAndPopulateMoveset(); @@ -3092,16 +3153,22 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_sinnoh_gym") .setMixedBattleBgm("battle_sinnoh_gym") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.RAPIDASH])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.STEELIX, Species.LOPUNNY], TrainerSlot.TRAINER, true, p => { // Tera Fire Steelix/Lopunny + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.STEELIX, Species.LOPUNNY], TrainerSlot.TRAINER, true, p => { + // Tera Fire Steelix/Lopunny p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.INFERNAPE])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ARCANINE, Species.HISUI_ARCANINE])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.MAGMORTAR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.MAGMORTAR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3114,7 +3181,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.FARIGIRAF])) // Tera Psychic Farigiraf .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.BRONZONG])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MR_RIME, Species.HISUI_BRAVIARY])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GALLADE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GALLADE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.abilityIndex = 1; // Sharpness p.generateAndPopulateMoveset(); @@ -3126,8 +3195,10 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.COFAGRIGUS])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GOLURK])) // Tera Ghost Golurk .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.JELLICENT])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MISMAGIUS, Species.FROSLASS ])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CHANDELURE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MISMAGIUS, Species.FROSLASS])) + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CHANDELURE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3139,7 +3210,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.MIENSHAO])) // Tera Fighting Mienshao .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.EMBOAR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.BRELOOM, Species.TOXICROAK])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CONKELDURR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CONKELDURR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3151,7 +3224,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.KROOKODILE])) // Tera Dark Krookodile .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SCRAFTY])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ZOROARK, Species.HISUI_SAMUROTT])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.KINGAMBIT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.KINGAMBIT], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3161,7 +3236,9 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_unova_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.MUSHARNA])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.REUNICLUS])) // Tera Psychic Reuniclus - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GALLADE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.GALLADE], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Sharpness p.generateAndPopulateMoveset(); }), @@ -3177,19 +3254,25 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.MALVA]: new TrainerConfig(++t) .initForEliteFour(signatureSpecies["MALVA"], false, PokemonType.FIRE, 2) .setMixedBattleBgm("battle_kalos_elite") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PYROAR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.PYROAR], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.FEMALE; }), ) .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.HOUNDOOM])) // Tera Fire Houndoom - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TORKOAL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.TORKOAL], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Drought p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CHANDELURE, Species.DELPHOX])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.TALONFLAME], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.TALONFLAME], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3201,7 +3284,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GYARADOS])) // Tera Water Gyarados .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.STARMIE])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.BLASTOISE, Species.DONDOZO])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.BARBARACLE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.BARBARACLE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.abilityIndex = 1; // Tough Claws p.generateAndPopulateMoveset(); @@ -3211,16 +3296,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["WIKSTROM"], true, PokemonType.STEEL, 2) .setMixedBattleBgm("battle_kalos_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.KLEFKI])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.CERULEDGE], TrainerSlot.TRAINER, true, p => { // Tera Steel Ceruledge + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.CERULEDGE], TrainerSlot.TRAINER, true, p => { + // Tera Steel Ceruledge p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.IRON_HEAD)) { // Check if Iron Head is in the moveset, if not, replace the third move with Iron Head. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.IRON_HEAD)) { + // Check if Iron Head is in the moveset, if not, replace the third move with Iron Head. p.moveset[2] = new PokemonMove(Moves.IRON_HEAD); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SCIZOR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CORVIKNIGHT])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.AEGISLASH], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.AEGISLASH], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3232,7 +3323,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GARCHOMP])) // Tera Dragon Garchomp .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.ALTARIA])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.DRUDDIGON])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.NOIVERN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.NOIVERN], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3241,16 +3334,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["HALA"], true, PokemonType.FIGHTING, 2) .setMixedBattleBgm("battle_alola_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.HARIYAMA])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.INCINEROAR], TrainerSlot.TRAINER, true, p => { // Tera Fighting Incineroar + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.INCINEROAR], TrainerSlot.TRAINER, true, p => { + // Tera Fighting Incineroar p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.CROSS_CHOP)) { // Check if Cross Chop is in the moveset, if not, replace the third move with Cross Chop. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.CROSS_CHOP)) { + // Check if Cross Chop is in the moveset, if not, replace the third move with Cross Chop. p.moveset[2] = new PokemonMove(Moves.CROSS_CHOP); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.BEWEAR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.POLIWRATH, Species.ANNIHILAPE])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CRABOMINABLE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CRABOMINABLE], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3262,7 +3361,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.ALOLA_SANDSLASH])) // Tera Steel A-Sandslash .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.MAGNEZONE])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.METAGROSS, Species.KINGAMBIT])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.ALOLA_DUGTRIO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.ALOLA_DUGTRIO], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3270,7 +3371,9 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.OLIVIA]: new TrainerConfig(++t) .initForEliteFour(signatureSpecies["OLIVIA"], false, PokemonType.ROCK, 2) .setMixedBattleBgm("battle_alola_elite") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GIGALITH], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.GIGALITH], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Sand Stream p.generateAndPopulateMoveset(); }), @@ -3278,7 +3381,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.PROBOPASS])) // Tera Rock Probopass .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.ALOLA_GOLEM])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.RELICANTH, Species.CARBINK])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.formIndex = 1; p.generateAndPopulateMoveset(); @@ -3291,7 +3396,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.MIMIKYU])) // Tera Ghost Mimikyu .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.DHELMISE])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.FROSLASS])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.PALOSSAND], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.PALOSSAND], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3300,16 +3407,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["KAHILI"], false, PokemonType.FLYING, 2) .setMixedBattleBgm("battle_alola_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.HAWLUCHA])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.DECIDUEYE], TrainerSlot.TRAINER, true, p => { // Tera Flying Decidueye + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.DECIDUEYE], TrainerSlot.TRAINER, true, p => { + // Tera Flying Decidueye p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.BRAVE_BIRD)) { // Check if Brave Bird is in the moveset, if not, replace the third move with Brave Bird. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.BRAVE_BIRD)) { + // Check if Brave Bird is in the moveset, if not, replace the third move with Brave Bird. p.moveset[2] = new PokemonMove(Moves.BRAVE_BIRD); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.BRAVIARY, Species.MANDIBUZZ])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ORICORIO])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.TOUCANNON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.TOUCANNON], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3319,7 +3432,10 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["MARNIE_ELITE"], false, PokemonType.DARK, 2) .setMixedBattleBgm("battle_galar_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.LIEPARD])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.TOXICROAK], TrainerSlot.TRAINER, true, p => { // Tera Dark Toxicroak + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.TOXICROAK], TrainerSlot.TRAINER, true, p => { + // Tera Dark Toxicroak p.generateAndPopulateMoveset(); if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.SUCKER_PUNCH)) { // Check if Sucker Punch is in the moveset, if not, replace the third move with Sucker Punch. @@ -3329,7 +3445,9 @@ export const trainerConfigs: TrainerConfigs = { ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SCRAFTY, Species.PANGORO])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MORPEKO])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GRIMMSNARL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GRIMMSNARL], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3339,20 +3457,28 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["NESSA_ELITE"], false, PokemonType.WATER, 2) .setMixedBattleBgm("battle_galar_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GOLISOPOD])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.EISCUE], TrainerSlot.TRAINER, true, p => { // Tera Water Eiscue + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.EISCUE], TrainerSlot.TRAINER, true, p => { + // Tera Water Eiscue p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.LIQUIDATION)) { // Check if Liquidation is in the moveset, if not, replace the third move with Liquidation. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.LIQUIDATION)) { + // Check if Liquidation is in the moveset, if not, replace the third move with Liquidation. p.moveset[2] = new PokemonMove(Moves.LIQUIDATION); } }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Drizzle p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.TOXAPEX])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DREDNAW], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DREDNAW], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3365,7 +3491,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SIRFETCHD])) // Tera Fighting Sirfetch'd .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GRAPPLOCT, Species.FALINKS])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.HITMONTOP])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.MACHAMP], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.MACHAMP], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3378,7 +3506,9 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.RUNERIGUS])) // Tera Ghost Runerigus .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.POLTEAGEIST, Species.SINISTCHA])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CURSOLA])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GENGAR], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3388,17 +3518,23 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["RAIHAN_ELITE"], true, PokemonType.DRAGON, 2) .setMixedBattleBgm("battle_galar_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.FLYGON])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.TORKOAL], TrainerSlot.TRAINER, true, p => { // Tera Dragon Torkoal + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.TORKOAL], TrainerSlot.TRAINER, true, p => { + // Tera Dragon Torkoal p.abilityIndex = 1; // Drought p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GOODRA])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.TURTONATOR])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.ARCHALUDON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.ARCHALUDON], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3410,7 +3546,10 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.DONPHAN])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SWAMPERT, Species.TORTERRA])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CAMERUPT])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CLODSIRE], TrainerSlot.TRAINER, true, p => { // Tera Ground Clodsire + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CLODSIRE], TrainerSlot.TRAINER, true, p => { + // Tera Ground Clodsire p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3420,13 +3559,18 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_paldea_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.COPPERAJAH])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.MAGNEZONE])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.BRONZONG, Species.CORVIKNIGHT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.BRONZONG, Species.CORVIKNIGHT], TrainerSlot.TRAINER, true, p => { p.abilityIndex = p.species.speciesId === Species.BRONZONG ? 0 : 1; // Levitate Bronzong, Unnerve Corviknight p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.STEELIX])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.TINKATON], TrainerSlot.TRAINER, true, p => { // Tera Steel Tinkaton + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.TINKATON], TrainerSlot.TRAINER, true, p => { + // Tera Steel Tinkaton p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3439,7 +3583,10 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.BOMBIRDIER])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TROPIUS])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.STARAPTOR])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.FLAMIGO], TrainerSlot.TRAINER, true, p => { // Tera Flying Flamigo + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.FLAMIGO], TrainerSlot.TRAINER, true, p => { + // Tera Flying Flamigo p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3451,7 +3598,10 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.DRAGALGE])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.FLAPPLE, Species.APPLETUN, Species.HYDRAPPLE])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.HAXORUS])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.BAXCALIBUR], TrainerSlot.TRAINER, true, p => { // Tera Dragon Baxcalibur + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.BAXCALIBUR], TrainerSlot.TRAINER, true, p => { + // Tera Dragon Baxcalibur p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3459,27 +3609,38 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.CRISPIN]: new TrainerConfig(++t) .initForEliteFour(signatureSpecies["CRISPIN"], true, PokemonType.FIRE, 2) .setMixedBattleBgm("battle_bb_elite") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ROTOM], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.ROTOM], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Heat Rotom p.generateAndPopulateMoveset(); }), ) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.EXEGGUTOR], TrainerSlot.TRAINER, true, p => { // Tera Fire Exeggutor + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.EXEGGUTOR], TrainerSlot.TRAINER, true, p => { + // Tera Fire Exeggutor p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TALONFLAME], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.TALONFLAME], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.SUNNY_DAY)) { // Check if Sunny Day is in the moveset, if not, replace the third move with Sunny Day. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.SUNNY_DAY)) { + // Check if Sunny Day is in the moveset, if not, replace the third move with Sunny Day. p.moveset[2] = new PokemonMove(Moves.SUNNY_DAY); } }), ) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.MAGMORTAR])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.BLAZIKEN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.BLAZIKEN], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3488,16 +3649,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["AMARYS"], false, PokemonType.STEEL, 2) .setMixedBattleBgm("battle_bb_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SKARMORY])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.REUNICLUS], TrainerSlot.TRAINER, true, p => { // Tera Steel Reuniclus + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.REUNICLUS], TrainerSlot.TRAINER, true, p => { + // Tera Steel Reuniclus p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.FLASH_CANNON)) { // Check if Flash Cannon is in the moveset, if not, replace the third move with Flash Cannon. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.FLASH_CANNON)) { + // Check if Flash Cannon is in the moveset, if not, replace the third move with Flash Cannon. p.moveset[2] = new PokemonMove(Moves.FLASH_CANNON); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.EMPOLEON])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SCIZOR])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.METAGROSS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.METAGROSS], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3509,10 +3676,14 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.PRIMARINA])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GRANBULL])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ALCREMIE])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.EXCADRILL], TrainerSlot.TRAINER, true, p => { // Tera Fairy Excadrill + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.EXCADRILL], TrainerSlot.TRAINER, true, p => { + // Tera Fairy Excadrill p.setBoss(true, 2); p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. p.moveset[2] = new PokemonMove(Moves.TERA_BLAST); } }), @@ -3521,16 +3692,22 @@ export const trainerConfigs: TrainerConfigs = { .initForEliteFour(signatureSpecies["DRAYTON"], true, PokemonType.DRAGON, 2) .setMixedBattleBgm("battle_bb_elite") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.DRAGONITE])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SCEPTILE], TrainerSlot.TRAINER, true, p => { // Tera Dragon Sceptile + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.SCEPTILE], TrainerSlot.TRAINER, true, p => { + // Tera Dragon Sceptile p.generateAndPopulateMoveset(); - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.DUAL_CHOP)) { // Check if Dual Chop is in the moveset, if not, replace the third move with Dual Chop. + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.DUAL_CHOP)) { + // Check if Dual Chop is in the moveset, if not, replace the third move with Dual Chop. p.moveset[2] = new PokemonMove(Moves.DUAL_CHOP); } }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.HAXORUS])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.KINGDRA, Species.DRACOVISH])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.ARCHALUDON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.ARCHALUDON], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); }), @@ -3545,18 +3722,29 @@ export const trainerConfigs: TrainerConfigs = { .setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALAKAZAM])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.MACHAMP])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.HO_OH], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.HO_OH], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.RHYPERIOR, Species.ELECTIVIRE])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ARCANINE, Species.EXEGGUTOR, Species.GYARADOS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc( + [Species.ARCANINE, Species.EXEGGUTOR, Species.GYARADOS], + TrainerSlot.TRAINER, + true, + p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); - }), + }, + ), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.PIDGEOT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.PIDGEOT], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Pidgeot p.generateAndPopulateMoveset(); p.generateName(); @@ -3571,7 +3759,9 @@ export const trainerConfigs: TrainerConfigs = { .setHasDouble("red_blue_double") .setDoubleTrainerType(TrainerType.BLUE) .setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PIKACHU], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.PIKACHU], TrainerSlot.TRAINER, true, p => { p.formIndex = 8; // G-Max Pikachu p.generateAndPopulateMoveset(); p.generateName(); @@ -3579,24 +3769,34 @@ export const trainerConfigs: TrainerConfigs = { }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.ESPEON, Species.UMBREON, Species.SYLVEON])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.LUGIA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.LUGIA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SNORLAX], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.SNORLAX], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc( - [Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc( + [Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE], + TrainerSlot.TRAINER, + true, + p => { p.formIndex = 1; // Mega Venusaur, Mega Charizard X, or Mega Blastoise p.generateAndPopulateMoveset(); p.generateName(); p.gender = Gender.MALE; - }), + }, + ), ) .setInstantTera(3), // Tera Grass Meganium / Fire Typhlosion / Water Feraligatr [TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t) @@ -3606,20 +3806,26 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_johto_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GYARADOS, Species.KINGDRA])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.AERODACTYL])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SALAMENCE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.SALAMENCE], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Salamence p.generateAndPopulateMoveset(); p.generateName(); }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.CHARIZARD])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.TYRANITAR, Species.GARCHOMP, Species.KOMMO_O], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.TYRANITAR, Species.GARCHOMP, Species.KOMMO_O], TrainerSlot.TRAINER, true, p => { p.teraType = PokemonType.DRAGON; p.generateAndPopulateMoveset(); p.abilityIndex = p.species.speciesId === Species.KOMMO_O ? 1 : 2; // Soundproof Kommo-o, Unnerve Tyranitar, Rough Skin Garchomp }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DRAGONITE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DRAGONITE], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); @@ -3635,18 +3841,24 @@ export const trainerConfigs: TrainerConfigs = { .setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SKARMORY])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.CRADILY, Species.ARMALDO])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.AGGRON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.AGGRON], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GOLURK, Species.RUNERIGUS])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.REGIROCK, Species.REGICE, Species.REGISTEEL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.REGIROCK, Species.REGICE, Species.REGISTEEL], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.METAGROSS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.METAGROSS], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Metagross p.generateAndPopulateMoveset(); p.generateName(); @@ -3660,13 +3872,17 @@ export const trainerConfigs: TrainerConfigs = { .setHasDouble("wallace_steven_double") .setDoubleTrainerType(TrainerType.STEVEN) .setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Drizzle p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.LUDICOLO])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.LATIAS, Species.LATIOS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.LATIAS, Species.LATIOS], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Latios or Mega Latias p.generateAndPopulateMoveset(); p.generateName(); @@ -3674,12 +3890,16 @@ export const trainerConfigs: TrainerConfigs = { }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SWAMPERT, Species.GASTRODON, Species.SEISMITOAD])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.REGIELEKI, Species.REGIDRAGO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.REGIELEKI, Species.REGIDRAGO], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.MILOTIC], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.MILOTIC], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.FEMALE; p.setBoss(true, 2); @@ -3692,22 +3912,35 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_sinnoh_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SPIRITOMB])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.LUCARIO])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GIRATINA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.GIRATINA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.MILOTIC, Species.ROSERADE, Species.HISUI_ARCANINE], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.teraType = p.species.type1; - }), + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc( + [Species.MILOTIC, Species.ROSERADE, Species.HISUI_ARCANINE], + TrainerSlot.TRAINER, + true, + p => { + p.generateAndPopulateMoveset(); + p.teraType = p.species.type1; + }, + ), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.TOGEKISS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.TOGEKISS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GARCHOMP], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GARCHOMP], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Garchomp p.generateAndPopulateMoveset(); p.generateName(); @@ -3723,28 +3956,47 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_champion_alder") .setMixedBattleBgm("battle_champion_alder") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BOUFFALANT, Species.BRAVIARY])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.HISUI_LILLIGANT, Species.HISUI_ZOROARK, Species.BASCULEGION], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 1, + getRandomPartyMemberFunc( + [Species.HISUI_LILLIGANT, Species.HISUI_ZOROARK, Species.BASCULEGION], + TrainerSlot.TRAINER, + true, + p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ROGUE_BALL; - }), + }, + ), ) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.ZEKROM], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.ZEKROM], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.KELDEO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.KELDEO], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc( - [Species.CHANDELURE, Species.KROOKODILE, Species.REUNICLUS, Species.CONKELDURR], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.teraType = p.species.speciesId === Species.KROOKODILE ? PokemonType.DARK : p.species.type1; - }), + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc( + [Species.CHANDELURE, Species.KROOKODILE, Species.REUNICLUS, Species.CONKELDURR], + TrainerSlot.TRAINER, + true, + p => { + p.generateAndPopulateMoveset(); + p.teraType = p.species.speciesId === Species.KROOKODILE ? PokemonType.DARK : p.species.type1; + }, + ), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.VOLCARONA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.VOLCARONA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); @@ -3760,23 +4012,36 @@ export const trainerConfigs: TrainerConfigs = { .setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.DRUDDIGON])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.ARCHEOPS])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.RESHIRAM], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.RESHIRAM], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.SALAMENCE, Species.HYDREIGON, Species.ARCHALUDON], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.teraType = PokemonType.DRAGON; - }), + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc( + [Species.SALAMENCE, Species.HYDREIGON, Species.ARCHALUDON], + TrainerSlot.TRAINER, + true, + p => { + p.generateAndPopulateMoveset(); + p.teraType = PokemonType.DRAGON; + }, + ), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.LAPRAS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.LAPRAS], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // G-Max Lapras p.generateAndPopulateMoveset(); p.generateName(); }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.HAXORUS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.HAXORUS], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Mold Breaker p.generateAndPopulateMoveset(); p.gender = Gender.FEMALE; @@ -3787,28 +4052,38 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.DIANTHA]: new TrainerConfig(++t) .initForChampion(false) .setMixedBattleBgm("battle_kalos_champion") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.HAWLUCHA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.HAWLUCHA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.TREVENANT, Species.GOURGEIST])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.XERNEAS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.XERNEAS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TYRANTRUM, Species.AURORUS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.TYRANTRUM, Species.AURORUS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = 2; // Rock Head Tyrantrum, Snow Warning Aurorus p.teraType = p.species.type2!; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.GOODRA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.GOODRA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GARDEVOIR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.GARDEVOIR], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Gardevoir p.generateAndPopulateMoveset(); p.generateName(); @@ -3819,29 +4094,45 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.KUKUI]: new TrainerConfig(++t) .initForChampion(true) .setMixedBattleBgm("battle_champion_kukui") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.formIndex = 2; // Dusk Lycanroc }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.MAGNEZONE, Species.ALOLA_NINETALES])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.TORNADUS, Species.THUNDURUS, Species.LANDORUS], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Therian Formes + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc( + [Species.TORNADUS, Species.THUNDURUS, Species.LANDORUS], + TrainerSlot.TRAINER, + true, + p => { + p.formIndex = 1; // Therian Formes p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; - }), + }, + ), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TAPU_KOKO, Species.TAPU_FINI], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.TAPU_KOKO, Species.TAPU_FINI], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SNORLAX], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.SNORLAX], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.formIndex = 1; // G-Max Snorlax }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.INCINEROAR, Species.HISUI_DECIDUEYE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.INCINEROAR, Species.HISUI_DECIDUEYE], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.teraType = p.species.type2!; @@ -3853,24 +4144,32 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_alola_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALOLA_RAICHU])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.NOIVERN])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SOLGALEO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.SOLGALEO], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TAPU_LELE, Species.TAPU_BULU], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.TAPU_LELE, Species.TAPU_BULU], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.teraType = p.species.type1; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ZYGARDE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.ZYGARDE], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Zygarde 10% forme, Aura Break p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ROGUE_BALL; }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DECIDUEYE, Species.PRIMARINA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.DECIDUEYE, Species.PRIMARINA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); p.gender = p.species.speciesId === Species.PRIMARINA ? Gender.FEMALE : Gender.MALE; @@ -3882,18 +4181,29 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_galar_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.AEGISLASH])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.RHYPERIOR, Species.SEISMITOAD, Species.MR_RIME])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.ZACIAN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.ZACIAN], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.DRAGAPULT])) - .setPartyMemberFunc(4,getRandomPartyMemberFunc([Species.RILLABOOM, Species.CINDERACE, Species.INTELEON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc( + [Species.RILLABOOM, Species.CINDERACE, Species.INTELEON], + TrainerSlot.TRAINER, + true, + p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); - }), + }, + ), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CHARIZARD], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.CHARIZARD], TrainerSlot.TRAINER, true, p => { p.formIndex = 3; // G-Max Charizard p.generateAndPopulateMoveset(); p.generateName(); @@ -3904,35 +4214,47 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.MUSTARD]: new TrainerConfig(++t) .initForChampion(true) .setMixedBattleBgm("battle_mustard") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.CORVIKNIGHT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.CORVIKNIGHT], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.KOMMO_O], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 1, + getRandomPartyMemberFunc([Species.KOMMO_O], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.GALAR_SLOWBRO, Species.GALAR_SLOWKING], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.GALAR_SLOWBRO, Species.GALAR_SLOWKING], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.teraType = p.species.type1; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GALAR_DARMANITAN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.GALAR_DARMANITAN], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.BLASTOISE, Species.VENUSAUR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.BLASTOISE, Species.VENUSAUR], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.setBoss(true, 2); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.URSHIFU], TrainerSlot.TRAINER, true, p => { - p.formIndex = randSeedInt(2, 2); // Random G-Max Urshifu + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.URSHIFU], TrainerSlot.TRAINER, true, p => { + p.formIndex = randSeedIntRange(2, 3); // Random G-Max Urshifu p.generateAndPopulateMoveset(); p.generateName(); p.gender = Gender.MALE; @@ -3943,21 +4265,27 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.GEETA]: new TrainerConfig(++t) .initForChampion(false) .setMixedBattleBgm("battle_champion_geeta") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GLIMMORA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.GLIMMORA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.ESPATHRA, Species.VELUZA])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.MIRAIDON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.MIRAIDON], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.BAXCALIBUR])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.KINGAMBIT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.KINGAMBIT], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === Moves.TERA_BLAST)) { // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. @@ -3971,50 +4299,71 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.NEMONA]: new TrainerConfig(++t) .initForChampion(false) .setMixedBattleBgm("battle_champion_nemona") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 0, + getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { p.formIndex = 0; // Midday form p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PAWMOT])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.KORAIDON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.KORAIDON], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GHOLDENGO])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.ARMAROUGE, Species.CERULEDGE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.ARMAROUGE, Species.CERULEDGE], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.teraType = p.species.type2!; }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc( + [Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], + TrainerSlot.TRAINER, + true, + p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); - }), + }, + ), ) .setInstantTera(4), // Tera Psychic Armarouge / Ghost Ceruledge [TrainerType.KIERAN]: new TrainerConfig(++t) .initForChampion(true) .setMixedBattleBgm("battle_champion_kieran") .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.POLIWRATH, Species.POLITOED])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.INCINEROAR, Species.GRIMMSNARL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 1, + getRandomPartyMemberFunc([Species.INCINEROAR, Species.GRIMMSNARL], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = p.species.speciesId === Species.INCINEROAR ? 2 : 0; // Intimidate Incineroar, Prankster Grimmsnarl }), ) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.TERAPAGOS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([Species.TERAPAGOS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.URSALUNA, Species.BLOODMOON_URSALUNA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([Species.URSALUNA, Species.BLOODMOON_URSALUNA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.OGERPON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([Species.OGERPON], TrainerSlot.TRAINER, true, p => { p.formIndex = randSeedInt(4); // Random Ogerpon Tera Mask p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; @@ -4024,7 +4373,9 @@ export const trainerConfigs: TrainerConfigs = { } }), ) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.HYDRAPPLE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc( + 5, + getRandomPartyMemberFunc([Species.HYDRAPPLE], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 042d4b7492c..edf45362dfe 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -54,7 +54,7 @@ import { getStarterValueFriendshipCap, speciesStarterCosts, } from "#app/data/balance/starters"; -import { NumberHolder, randSeedInt, getIvsFromId, BooleanHolder, randSeedItem, isNullOrUndefined, getEnumValues, toDmgValue, fixedInt, rgbaToInt, rgbHexToRgba, rgbToHsv, deltaRgb, isBetween, type nil, type Constructor } from "#app/utils/common"; +import { NumberHolder, randSeedInt, getIvsFromId, BooleanHolder, randSeedItem, isNullOrUndefined, getEnumValues, toDmgValue, fixedInt, rgbaToInt, rgbHexToRgba, rgbToHsv, deltaRgb, isBetween, type nil, type Constructor, randSeedIntRange } from "#app/utils/common"; import type { TypeDamageMultiplier } from "#app/data/type"; import { getTypeDamageMultiplier, getTypeRgb } from "#app/data/type"; import { PokemonType } from "#enums/pokemon-type"; @@ -909,19 +909,22 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const originalWarn = console.warn; // Ignore warnings for missing frames, because there will be a lot console.warn = () => {}; - const battleFrameNames = globalScene.anims.generateFrameNames(this.getBattleSpriteKey(), { + const battleSpriteKey = this.getBattleSpriteKey(this.isPlayer(), ignoreOverride); + const battleFrameNames = globalScene.anims.generateFrameNames(battleSpriteKey, { zeroPad: 4, suffix: ".png", start: 1, end: 400, }); console.warn = originalWarn; - globalScene.anims.create({ - key: this.getBattleSpriteKey(), - frames: battleFrameNames, - frameRate: 10, - repeat: -1, - }); + if (!globalScene.anims.exists(battleSpriteKey)) { + globalScene.anims.create({ + key: battleSpriteKey, + frames: battleFrameNames, + frameRate: 10, + repeat: -1, + }); + } } // With everything loaded, now begin playing the animation. this.playAnim(); @@ -3486,11 +3489,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } let weight = levelMove[0]; // Evolution Moves - if (weight === 0) { + if (weight === EVOLVE_MOVE) { weight = 50; } - // Assume level 1 moves with 80+ BP are "move reminder" moves and bump their weight - if (weight === 1 && allMoves[levelMove[1]].power >= 80) { + // Assume level 1 moves with 80+ BP are "move reminder" moves and bump their weight. Trainers use actual relearn moves. + if (weight === 1 && allMoves[levelMove[1]].power >= 80 || weight === RELEARN_MOVE && this.hasTrainer()) { weight = 40; } if ( @@ -3595,9 +3598,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // Bosses never get self ko moves or Pain Split if (this.isBoss()) { - movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttr)); - movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(HpSplitAttr)); + movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttr) && !allMoves[m[0]].hasAttr(HpSplitAttr)); } + // No one gets Memento or Final Gambit movePool = movePool.filter( m => !allMoves[m[0]].hasAttr(SacrificialAttrOnHit), ); @@ -3609,10 +3612,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { m[0], m[1] * (allMoves[m[0]].hasAttr(SacrificialAttr) ? 0.5 : 1), ]); - movePool = movePool.map(m => [ - m[0], - m[1] * (allMoves[m[0]].hasAttr(SacrificialAttrOnHit) ? 0.5 : 1), - ]); // Trainers get a weight bump to stat buffing moves movePool = movePool.map(m => [ m[0], @@ -3673,10 +3672,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ]); /** The higher this is the more the game weights towards higher level moves. At `0` all moves are equal weight. */ - let weightMultiplier = 0.9; - if (this.hasTrainer()) { - weightMultiplier += 0.7; - } + let weightMultiplier = 1.6; if (this.isBoss()) { weightMultiplier += 0.4; } @@ -3685,37 +3681,21 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { Math.ceil(Math.pow(m[1], weightMultiplier) * 100), ]); - // Trainers and bosses always force a stab move - if (this.hasTrainer() || this.isBoss()) { - const stabMovePool = baseWeights.filter( - m => - allMoves[m[0]].category !== MoveCategory.STATUS && - this.isOfType(allMoves[m[0]].type), - ); + // All Pokemon force a STAB move first + const stabMovePool = baseWeights.filter( + m => + allMoves[m[0]].category !== MoveCategory.STATUS && + this.isOfType(allMoves[m[0]].type), + ); - if (stabMovePool.length) { - const totalWeight = stabMovePool.reduce((v, m) => v + m[1], 0); - let rand = randSeedInt(totalWeight); - let index = 0; - while (rand > stabMovePool[index][1]) { - rand -= stabMovePool[index++][1]; - } - this.moveset.push(new PokemonMove(stabMovePool[index][0], 0, 0)); - } - } else { - // Normal wild pokemon just force a random damaging move - const attackMovePool = baseWeights.filter( - m => allMoves[m[0]].category !== MoveCategory.STATUS, - ); - if (attackMovePool.length) { - const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0); - let rand = randSeedInt(totalWeight); - let index = 0; - while (rand > attackMovePool[index][1]) { - rand -= attackMovePool[index++][1]; - } - this.moveset.push(new PokemonMove(attackMovePool[index][0], 0, 0)); + if (stabMovePool.length) { + const totalWeight = stabMovePool.reduce((v, m) => v + m[1], 0); + let rand = randSeedInt(totalWeight); + let index = 0; + while (rand > stabMovePool[index][1]) { + rand -= stabMovePool[index++][1]; } + this.moveset.push(new PokemonMove(stabMovePool[index][0], 0, 0)); } while ( @@ -3727,7 +3707,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // Other damaging moves 2x weight if 0-1 damaging moves, 0.5x if 2, 0.125x if 3. These weights get 20x if STAB. // Status moves remain unchanged on weight, this encourages 1-2 movePool = baseWeights - .filter(m => !this.moveset.some(mo => m[0] === mo.moveId)) + .filter(m => !this.moveset.some( + mo => + m[0] === mo.moveId || + (allMoves[m[0]].hasAttr(SacrificialAttr) && mo.getMove().hasAttr(SacrificialAttr)) // Only one self-KO move allowed + )) .map(m => { let ret: number; if ( @@ -3758,7 +3742,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { }); } else { // Non-trainer pokemon just use normal weights - movePool = baseWeights.filter(m => !this.moveset.some(mo => m[0] === mo.moveId)); + movePool = baseWeights.filter(m => !this.moveset.some( + mo => + m[0] === mo.moveId || + (allMoves[m[0]].hasAttr(SacrificialAttr) && mo.getMove().hasAttr(SacrificialAttr)) // Only one self-KO move allowed + )); } const totalWeight = movePool.reduce((v, m) => v + m[1], 0); let rand = randSeedInt(totalWeight); @@ -4471,7 +4459,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { */ const randomMultiplier = simulated ? 1 - : this.randSeedIntRange(85, 100) / 100; + : this.randBattleSeedIntRange(85, 100) / 100; /** A damage multiplier for when the attack is of the attacker's type and/or Tera type. */ @@ -5615,7 +5603,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { let sleepTurnsRemaining: NumberHolder; if (effect === StatusEffect.SLEEP) { - sleepTurnsRemaining = new NumberHolder(this.randSeedIntRange(2, 4)); + sleepTurnsRemaining = new NumberHolder(this.randBattleSeedIntRange(2, 4)); this.setFrameRate(4); @@ -5664,7 +5652,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { /** * Performs the action of clearing a Pokemon's status - * + * * This is a helper to {@linkcode resetStatus}, which should be called directly instead of this method */ public clearStatus(confusion: boolean, reloadAssets: boolean) { @@ -5707,17 +5695,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } /** - * Reset this Pokemon's {@linkcode PokemonSummonData | SummonData} and {@linkcode PokemonTempSummonData | TempSummonData} - * in preparation for switching pokemon, as well as removing any relevant on-switch tags. + * Performs miscellaneous setup for when the Pokemon is summoned, like generating the substitute sprite + * @param resetSummonData - Whether to additionally reset the Pokemon's summon data (default: `false`) */ - resetSummonData(): void { - const illusion: IllusionData | null = this.summonData.illusion; - if (this.summonData.speciesForm) { - this.summonData.speciesForm = null; - this.updateFusionPalette(); - } - this.summonData = new PokemonSummonData(); - this.tempSummonData = new PokemonTempSummonData(); + public fieldSetup(resetSummonData?: boolean): void { this.setSwitchOutStatus(false); if (globalScene) { globalScene.triggerPokemonFormChange( @@ -5726,7 +5707,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { true, ); } - // If this Pokemon has a Substitute when loading in, play an animation to add its sprite if (this.getTag(SubstituteTag)) { globalScene.triggerPokemonBattleAnim( @@ -5744,6 +5724,24 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ) { this.setVisible(false); } + + if (resetSummonData) { + this.resetSummonData(); + } + } + + /** + * Reset this Pokemon's {@linkcode PokemonSummonData | SummonData} and {@linkcode PokemonTempSummonData | TempSummonData} + * in preparation for switching pokemon, as well as removing any relevant on-switch tags. + */ + resetSummonData(): void { + const illusion: IllusionData | null = this.summonData.illusion; + if (this.summonData.speciesForm) { + this.summonData.speciesForm = null; + this.updateFusionPalette(); + } + this.summonData = new PokemonSummonData(); + this.tempSummonData = new PokemonTempSummonData(); this.summonData.illusion = illusion this.updateInfo(); } @@ -6268,7 +6266,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param min The minimum integer to pick, default `0` * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) */ - randSeedInt(range: number, min = 0): number { + randBattleSeedInt(range: number, min = 0): number { return globalScene.currentBattle ? globalScene.randBattleSeedInt(range, min) : randSeedInt(range, min); @@ -6280,8 +6278,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param max The maximum integer to generate * @returns a random integer between {@linkcode min} and {@linkcode max} inclusive */ - randSeedIntRange(min: number, max: number): number { - return this.randSeedInt(max - min + 1, min); + randBattleSeedIntRange(min: number, max: number): number { + return globalScene.currentBattle + ? globalScene.randBattleSeedInt(max - min + 1, min) + : randSeedIntRange(min, max); } /** @@ -7078,7 +7078,6 @@ export class EnemyPokemon extends Pokemon { if (!dataSource) { this.generateAndPopulateMoveset(); - if (shinyLock || Overrides.OPP_SHINY_OVERRIDE === false) { this.shiny = false; } else { @@ -7119,7 +7118,7 @@ export class EnemyPokemon extends Pokemon { const { waveIndex } = globalScene.currentBattle; const ivs: number[] = []; while (ivs.length < 6) { - ivs.push(this.randSeedIntRange(Math.floor(waveIndex / 10), 31)); + ivs.push(randSeedIntRange(Math.floor(waveIndex / 10), 31)); } this.ivs = ivs; } @@ -7851,7 +7850,7 @@ export class PokemonSummonData { } if (key === "moveset") { - this.moveset = value.map((m: any) => PokemonMove.loadMove(m)); + this.moveset = value?.map((m: any) => PokemonMove.loadMove(m)); continue; } diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 763b40c8555..94bb0e3419a 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1548,7 +1548,7 @@ export class SurviveDamageModifier extends PokemonHeldItemModifier { * @returns `true` if the survive damage has been applied */ override apply(pokemon: Pokemon, surviveDamage: BooleanHolder): boolean { - if (!surviveDamage.value && pokemon.randSeedInt(10) < this.getStackCount()) { + if (!surviveDamage.value && pokemon.randBattleSeedInt(10) < this.getStackCount()) { surviveDamage.value = true; globalScene.queueMessage( @@ -1594,7 +1594,7 @@ export class BypassSpeedChanceModifier extends PokemonHeldItemModifier { * @returns `true` if {@linkcode BypassSpeedChanceModifier} has been applied */ override apply(pokemon: Pokemon, doBypassSpeed: BooleanHolder): boolean { - if (!doBypassSpeed.value && pokemon.randSeedInt(10) < this.getStackCount()) { + if (!doBypassSpeed.value && pokemon.randBattleSeedInt(10) < this.getStackCount()) { doBypassSpeed.value = true; const isCommandFight = globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]?.command === Command.FIGHT; @@ -1658,7 +1658,7 @@ export class FlinchChanceModifier extends PokemonHeldItemModifier { override apply(pokemon: Pokemon, flinched: BooleanHolder): boolean { // The check for pokemon.summonData is to ensure that a crash doesn't occur when a Pokemon with King's Rock procs a flinch // TODO: Since summonData is always defined now, we can probably remove this - if (pokemon.summonData && !flinched.value && pokemon.randSeedInt(100) < this.getStackCount() * this.chance) { + if (pokemon.summonData && !flinched.value && pokemon.randBattleSeedInt(100) < this.getStackCount() * this.chance) { flinched.value = true; return true; } @@ -1927,7 +1927,7 @@ export class PreserveBerryModifier extends PersistentModifier { * @returns always `true` */ override apply(pokemon: Pokemon, doPreserve: BooleanHolder): boolean { - doPreserve.value ||= pokemon.randSeedInt(10) < this.getStackCount() * 3; + doPreserve.value ||= pokemon.randBattleSeedInt(10) < this.getStackCount() * 3; return true; } @@ -3240,7 +3240,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier { return false; } - const targetPokemon = opponents[pokemon.randSeedInt(opponents.length)]; + const targetPokemon = opponents[pokemon.randBattleSeedInt(opponents.length)]; const transferredItemCount = this.getTransferredItemCount(); if (!transferredItemCount) { @@ -3272,7 +3272,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier { break; } } - const randItemIndex = pokemon.randSeedInt(itemModifiers.length); + const randItemIndex = pokemon.randBattleSeedInt(itemModifiers.length); const randItem = itemModifiers[randItemIndex]; if (globalScene.tryTransferHeldItemModifier(randItem, pokemon, false)) { transferredModifierTypes.push(randItem.type); @@ -3731,7 +3731,7 @@ export class EnemyEndureChanceModifier extends EnemyPersistentModifier { * @returns `true` if {@linkcode Pokemon} endured */ override apply(target: Pokemon): boolean { - if (target.waveData.endured || target.randSeedInt(100) >= this.chance * this.getStackCount()) { + if (target.waveData.endured || target.randBattleSeedInt(100) >= this.chance * this.getStackCount()) { return false; } diff --git a/src/phases/attempt-capture-phase.ts b/src/phases/attempt-capture-phase.ts index 795aa7010e1..8592cd98508 100644 --- a/src/phases/attempt-capture-phase.ts +++ b/src/phases/attempt-capture-phase.ts @@ -63,7 +63,7 @@ export class AttemptCapturePhase extends PokemonPhase { const modifiedCatchRate = Math.round((((_3m - _2h) * catchRate * pokeballMultiplier) / _3m) * statusMultiplier); const shakeProbability = Math.round(65536 / Math.pow(255 / modifiedCatchRate, 0.1875)); // Formula taken from gen 6 const criticalCaptureChance = getCriticalCaptureChance(modifiedCatchRate); - const isCritical = pokemon.randSeedInt(256) < criticalCaptureChance; + const isCritical = pokemon.randBattleSeedInt(256) < criticalCaptureChance; const fpOffset = pokemon.getFieldPositionOffset(); const pokeballAtlasKey = getPokeballAtlasKey(this.pokeballType); @@ -135,14 +135,14 @@ export class AttemptCapturePhase extends PokemonPhase { pokeballMultiplier === -1 || isCritical || modifiedCatchRate >= 255 || - pokemon.randSeedInt(65536) < shakeProbability + pokemon.randBattleSeedInt(65536) < shakeProbability ) { globalScene.playSound("se/pb_move"); } else { shakeCounter.stop(); this.failCatch(shakeCount); } - } else if (isCritical && pokemon.randSeedInt(65536) >= shakeProbability) { + } else if (isCritical && pokemon.randBattleSeedInt(65536) >= shakeProbability) { // Above, perform the one shake check for critical captures after the ball shakes once shakeCounter.stop(); this.failCatch(shakeCount); diff --git a/src/phases/attempt-run-phase.ts b/src/phases/attempt-run-phase.ts index 274d3c40576..15c521c01fc 100644 --- a/src/phases/attempt-run-phase.ts +++ b/src/phases/attempt-run-phase.ts @@ -34,7 +34,7 @@ export class AttemptRunPhase extends PokemonPhase { applyAbAttrs(RunSuccessAbAttr, playerPokemon, null, false, escapeChance); - if (playerPokemon.randSeedInt(100) < escapeChance.value && !this.forceFailEscape) { + if (playerPokemon.randBattleSeedInt(100) < escapeChance.value && !this.forceFailEscape) { enemyField.forEach(enemyPokemon => applyPreLeaveFieldAbAttrs(PreLeaveFieldAbAttr, enemyPokemon)); globalScene.playSound("se/flee"); diff --git a/src/phases/encounter-phase.ts b/src/phases/encounter-phase.ts index 5b799bd9316..3cfd2b9a901 100644 --- a/src/phases/encounter-phase.ts +++ b/src/phases/encounter-phase.ts @@ -146,7 +146,7 @@ export class EncounterPhase extends BattlePhase { const enemyPokemon = globalScene.getEnemyParty()[e]; if (e < (battle.double ? 2 : 1)) { enemyPokemon.setX(-66 + enemyPokemon.getFieldPositionOffset()[0]); - enemyPokemon.resetSummonData(); + enemyPokemon.fieldSetup(true); } if (!this.loaded) { diff --git a/src/phases/message-phase.ts b/src/phases/message-phase.ts index f6777579857..b277d67de82 100644 --- a/src/phases/message-phase.ts +++ b/src/phases/message-phase.ts @@ -35,20 +35,22 @@ export class MessagePhase extends Phase { this.text = this.text.split(pokename[p]).join(repname[p]); } const pageIndex = this.text.indexOf("$"); - for (let p = 0; p < globalScene.getPlayerField().length; p++) { - this.text = this.text.split(repname[p]).join(pokename[p]); - } if (pageIndex !== -1) { + let page0 = this.text.slice(0, pageIndex); + let page1 = this.text.slice(pageIndex + 1); + // Pokemon names must be re-inserted _after_ the split, otherwise the index will be wrong + for (let p = 0; p < globalScene.getPlayerField().length; p++) { + page0 = page0.split(repname[p]).join(pokename[p]); + page1 = page1.split(repname[p]).join(pokename[p]); + } globalScene.unshiftPhase( - new MessagePhase( - this.text.slice(pageIndex + 1), - this.callbackDelay, - this.prompt, - this.promptDelay, - this.speaker, - ), + new MessagePhase(page1, this.callbackDelay, this.prompt, this.promptDelay, this.speaker), ); - this.text = this.text.slice(0, pageIndex).trim(); + this.text = page0.trim(); + } else { + for (let p = 0; p < globalScene.getPlayerField().length; p++) { + this.text = this.text.split(repname[p]).join(pokename[p]); + } } } diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index c65e8e15271..e3773952214 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -206,11 +206,13 @@ export class MoveEffectPhase extends PokemonPhase { * @throws Error if there was an unexpected hit check result */ private applyToTargets(user: Pokemon, targets: Pokemon[]): void { + let firstHit = true; for (const [i, target] of targets.entries()) { const [hitCheckResult, effectiveness] = this.hitChecks[i]; switch (hitCheckResult) { case HitCheckResult.HIT: - this.applyMoveEffects(target, effectiveness); + this.applyMoveEffects(target, effectiveness, firstHit); + firstHit = false; if (isFieldTargeted(this.move)) { // Stop processing other targets if the move is a field move return; @@ -352,8 +354,8 @@ export class MoveEffectPhase extends PokemonPhase { move.id as Moves, user, firstTarget?.getBattlerIndex() ?? BattlerIndex.ATTACKER, - // Field moves and some moves used in mystery encounters should be played even on an empty field - fieldMove || (globalScene.currentBattle?.mysteryEncounter?.hasBattleAnimationsWithoutTargets ?? false), + // Some moves used in mystery encounters should be played even on an empty field + globalScene.currentBattle?.mysteryEncounter?.hasBattleAnimationsWithoutTargets ?? false, ).play(move.hitsSubstitute(user, firstTarget), () => this.postAnimCallback(user, targets)); return; @@ -592,7 +594,7 @@ export class MoveEffectPhase extends PokemonPhase { } const accuracyMultiplier = user.getAccuracyMultiplier(target, this.move); - const rand = user.randSeedInt(100); + const rand = user.randBattleSeedInt(100); if (rand < moveAccuracy * accuracyMultiplier) { return [HitCheckResult.HIT, effectiveness]; @@ -763,15 +765,12 @@ export class MoveEffectPhase extends PokemonPhase { * - Invoking {@linkcode applyOnTargetEffects} if the move does not hit a substitute * - Triggering form changes and emergency exit / wimp out if this is the last hit * - * @param target the {@linkcode Pokemon} hit by this phase's move. - * @param effectiveness the effectiveness of the move (as previously evaluated in {@linkcode hitCheck}) + * @param target - the {@linkcode Pokemon} hit by this phase's move. + * @param effectiveness - The effectiveness of the move (as previously evaluated in {@linkcode hitCheck}) + * @param firstTarget - Whether this is the first target successfully struck by the move */ - protected applyMoveEffects(target: Pokemon, effectiveness: TypeDamageMultiplier): void { + protected applyMoveEffects(target: Pokemon, effectiveness: TypeDamageMultiplier, firstTarget: boolean): void { const user = this.getUserPokemon(); - - /** The first target hit by the move */ - const firstTarget = target === this.getTargets().find((_, i) => this.hitChecks[i][1] > 0); - if (isNullOrUndefined(user)) { return; } @@ -905,6 +904,14 @@ export class MoveEffectPhase extends PokemonPhase { target.destroySubstitute(); target.lapseTag(BattlerTagType.COMMANDED); + + // Force `lastHit` to be true if this is a multi hit move with hits left + // `hitsLeft` must be left as-is in order for the message displaying the number of hits + // to display the proper number. + // Note: When Dragon Darts' smart targeting is implemented, this logic may need to be adjusted. + if (!this.lastHit && user.turnData.hitsLeft > 1) { + this.lastHit = true; + } } /** diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index e704b040d20..5d63fe6efea 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -232,7 +232,7 @@ export class MovePhase extends BattlePhase { switch (this.pokemon.status.effect) { case StatusEffect.PARALYSIS: activated = - (!this.pokemon.randSeedInt(4) || Overrides.STATUS_ACTIVATION_OVERRIDE === true) && + (!this.pokemon.randBattleSeedInt(4) || Overrides.STATUS_ACTIVATION_OVERRIDE === true) && Overrides.STATUS_ACTIVATION_OVERRIDE !== false; break; case StatusEffect.SLEEP: { @@ -258,7 +258,7 @@ export class MovePhase extends BattlePhase { .findAttr( attr => attr instanceof HealStatusEffectAttr && attr.selfTarget && attr.isOfEffect(StatusEffect.FREEZE), ) || - (!this.pokemon.randSeedInt(5) && Overrides.STATUS_ACTIVATION_OVERRIDE !== true) || + (!this.pokemon.randBattleSeedInt(5) && Overrides.STATUS_ACTIVATION_OVERRIDE !== true) || Overrides.STATUS_ACTIVATION_OVERRIDE === false; activated = !healed; diff --git a/src/phases/summon-phase.ts b/src/phases/summon-phase.ts index fef9b356348..c217583f163 100644 --- a/src/phases/summon-phase.ts +++ b/src/phases/summon-phase.ts @@ -196,6 +196,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { onComplete: () => { pokemon.cry(pokemon.getHpRatio() > 0.25 ? undefined : { rate: 0.85 }); pokemon.getSprite().clearTint(); + pokemon.fieldSetup(); // necessary to stay transformed during wild waves if (pokemon.summonData.speciesForm) { pokemon.loadAssets(false); @@ -261,6 +262,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { onComplete: () => { pokemon.cry(pokemon.getHpRatio() > 0.25 ? undefined : { rate: 0.85 }); pokemon.getSprite().clearTint(); + pokemon.fieldSetup(); globalScene.updateFieldScale(); globalScene.time.delayedCall(1000, () => this.end()); }, diff --git a/src/phases/switch-summon-phase.ts b/src/phases/switch-summon-phase.ts index bb31f87cc3d..a063b6e6863 100644 --- a/src/phases/switch-summon-phase.ts +++ b/src/phases/switch-summon-phase.ts @@ -193,7 +193,7 @@ export class SwitchSummonPhase extends SummonPhase { switchedInPokemon.setAlpha(0.5); } } else { - switchedInPokemon.resetSummonData(); + switchedInPokemon.fieldSetup(true); } this.summon(); }; diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 51e488210be..0c5e0b349ed 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -1110,7 +1110,7 @@ export class GameData { for (const p of sessionData.party) { const pokemon = p.toPokemon() as PlayerPokemon; pokemon.setVisible(false); - loadPokemonAssets.push(pokemon.loadAssets()); + loadPokemonAssets.push(pokemon.loadAssets(false)); party.push(pokemon); } diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index 8d4fd7c05df..00169678ed0 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -188,7 +188,7 @@ export default class PokemonData { // when loading from saved session, recover summonData.speciesFrom and form index species object // used to stay transformed on reload session if (this.summonData.speciesForm) { - this.summonData.speciesForm = getPokemonSpeciesForm( + ret.summonData.speciesForm = getPokemonSpeciesForm( this.summonData.speciesForm.speciesId, this.summonDataSpeciesFormIndex, ); diff --git a/src/ui/ball-ui-handler.ts b/src/ui/ball-ui-handler.ts index abb106a6553..eb7c208662a 100644 --- a/src/ui/ball-ui-handler.ts +++ b/src/ui/ball-ui-handler.ts @@ -7,6 +7,7 @@ import { addWindow } from "./ui-theme"; import { Button } from "#enums/buttons"; import type { CommandPhase } from "#app/phases/command-phase"; import { globalScene } from "#app/global-scene"; +import i18next from "i18next"; export default class BallUiHandler extends UiHandler { private pokeballSelectContainer: Phaser.GameObjects.Container; @@ -31,7 +32,7 @@ export default class BallUiHandler extends UiHandler { for (let pb = 0; pb < Object.keys(globalScene.pokeballCounts).length; pb++) { optionsTextContent += `${getPokeballName(pb)}\n`; } - optionsTextContent += "Cancel"; + optionsTextContent += i18next.t("pokeball:cancel"); const optionsText = addTextObject(0, 0, optionsTextContent, TextStyle.WINDOW, { align: "right", maxLines: 6 }); const optionsTextWidth = optionsText.displayWidth; this.pokeballSelectContainer = globalScene.add.container( diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index 5377cf3d283..1bb7124d935 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -108,7 +108,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { let pokemonIconX = -20; let pokemonIconY = 6; - if (["de", "es-ES", "fr", "ko", "pt-BR"].includes(currentLanguage)) { + if (["de", "es-ES", "es-MX", "fr", "ko", "pt-BR"].includes(currentLanguage)) { gachaTextStyle = TextStyle.SMALLER_WINDOW_ALT; gachaX = 2; gachaY = 2; @@ -116,7 +116,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { let legendaryLabelX = gachaX; let legendaryLabelY = gachaY; - if (["de", "es-ES"].includes(currentLanguage)) { + if (["de", "es-ES", "es-MX"].includes(currentLanguage)) { pokemonIconX = -25; pokemonIconY = 10; legendaryLabelX = -6; diff --git a/src/ui/pokedex-page-ui-handler.ts b/src/ui/pokedex-page-ui-handler.ts index ddc16ab5a88..051d267259f 100644 --- a/src/ui/pokedex-page-ui-handler.ts +++ b/src/ui/pokedex-page-ui-handler.ts @@ -1888,7 +1888,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler { if (!(passiveAttr & PassiveAttr.UNLOCKED)) { const passiveCost = getPassiveCandyCount(speciesStarterCosts[this.starterId]); options.push({ - label: `x${passiveCost} ${i18next.t("pokedexUiHandler:unlockPassive")} (${allAbilities[this.passive].name})`, + label: `x${passiveCost} ${i18next.t("pokedexUiHandler:unlockPassive")}`, handler: () => { if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= passiveCost) { starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED; diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 09d7322cb75..f24a3ff9265 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -145,12 +145,16 @@ const languageSettings: { [key: string]: LanguageSetting } = { starterInfoXPos: 33, }, ko: { - starterInfoTextSize: "52px", + starterInfoTextSize: "60px", instructionTextSize: "38px", + starterInfoYOffset: -0.5, + starterInfoXPos: 30, }, ja: { - starterInfoTextSize: "51px", + starterInfoTextSize: "62px", instructionTextSize: "38px", + starterInfoYOffset: 0.5, + starterInfoXPos: 33, }, "ca-ES": { starterInfoTextSize: "52px", @@ -2180,7 +2184,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { if (!(passiveAttr & PassiveAttr.UNLOCKED)) { const passiveCost = getPassiveCandyCount(speciesStarterCosts[this.lastSpecies.speciesId]); options.push({ - label: `x${passiveCost} ${i18next.t("starterSelectUiHandler:unlockPassive")} (${allAbilities[this.lastSpecies.getPassiveAbility()].name})`, + label: `x${passiveCost} ${i18next.t("starterSelectUiHandler:unlockPassive")}`, handler: () => { if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= passiveCost) { starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED; diff --git a/src/utils/common.ts b/src/utils/common.ts index 4cf7ceccff2..b9111578e2f 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -99,6 +99,16 @@ export function randSeedInt(range: number, min = 0): number { return Phaser.Math.RND.integerInRange(min, range - 1 + min); } +/** + * Generates a random number using the global seed + * @param min The minimum integer to generate + * @param max The maximum integer to generate + * @returns a random integer between {@linkcode min} and {@linkcode max} inclusive + */ +export function randSeedIntRange(min: number, max: number): number { + return randSeedInt(max - min + 1, min); +} + /** * Returns a random integer between min and max (non-inclusive) * @param min The lowest number diff --git a/test/abilities/cud_chew.test.ts b/test/abilities/cud_chew.test.ts index f99060cb744..2f65ac5fd97 100644 --- a/test/abilities/cud_chew.test.ts +++ b/test/abilities/cud_chew.test.ts @@ -111,7 +111,7 @@ describe("Abilities - Cud Chew", () => { it("can store multiple berries across 2 turns with teatime", async () => { // always eat first berry for stuff cheeks & company - vi.spyOn(Pokemon.prototype, "randSeedInt").mockReturnValue(0); + vi.spyOn(Pokemon.prototype, "randBattleSeedInt").mockReturnValue(0); game.override .startingHeldItems([ { name: "BERRY", type: BerryType.PETAYA, count: 3 }, diff --git a/test/abilities/desolate-land.test.ts b/test/abilities/desolate-land.test.ts index d6f01f7aa5e..697bd0a4c48 100644 --- a/test/abilities/desolate-land.test.ts +++ b/test/abilities/desolate-land.test.ts @@ -139,7 +139,7 @@ describe("Abilities - Desolate Land", () => { await game.classicMode.startBattle([Species.MAGIKARP]); expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.HARSH_SUN); - vi.spyOn(game.scene.getPlayerPokemon()!, "randSeedInt").mockReturnValue(0); + vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0); const commandPhase = game.scene.getCurrentPhase() as CommandPhase; commandPhase.handleCommand(Command.RUN, 0); diff --git a/test/abilities/neutralizing_gas.test.ts b/test/abilities/neutralizing_gas.test.ts index 32c61b72e4d..979583b7d97 100644 --- a/test/abilities/neutralizing_gas.test.ts +++ b/test/abilities/neutralizing_gas.test.ts @@ -164,7 +164,7 @@ describe("Abilities - Neutralizing Gas", () => { await game.classicMode.startBattle([Species.MAGIKARP]); expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeDefined(); - vi.spyOn(game.scene.getPlayerPokemon()!, "randSeedInt").mockReturnValue(0); + vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0); const commandPhase = game.scene.getCurrentPhase() as CommandPhase; commandPhase.handleCommand(Command.RUN, 0); diff --git a/test/items/reviver_seed.test.ts b/test/items/reviver_seed.test.ts index c109794d3d2..3c67481a904 100644 --- a/test/items/reviver_seed.test.ts +++ b/test/items/reviver_seed.test.ts @@ -73,7 +73,7 @@ describe("Items - Reviver Seed", () => { const reviverSeed = player.getHeldItems()[0] as PokemonInstantReviveModifier; vi.spyOn(reviverSeed, "apply"); - vi.spyOn(player, "randSeedInt").mockReturnValue(0); // Force confusion self-hit + vi.spyOn(player, "randBattleSeedInt").mockReturnValue(0); // Force confusion self-hit game.move.select(Moves.TACKLE); await game.phaseInterceptor.to("BerryPhase"); diff --git a/test/moves/synchronoise.test.ts b/test/moves/synchronoise.test.ts new file mode 100644 index 00000000000..0f59bce26b4 --- /dev/null +++ b/test/moves/synchronoise.test.ts @@ -0,0 +1,47 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { PokemonType } from "#enums/pokemon-type"; +import { Species } from "#enums/species"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Moves - Synchronoise", () => { + 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.SYNCHRONOISE]) + .ability(Abilities.BALL_FETCH) + .battleStyle("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should consider the user's tera type if it is terastallized", async () => { + await game.classicMode.startBattle([Species.BIDOOF]); + const playerPokemon = game.scene.getPlayerPokemon()!; + const enemyPokemon = game.scene.getEnemyPokemon()!; + + // force the player to be terastallized + playerPokemon.teraType = PokemonType.WATER; + playerPokemon.isTerastallized = true; + game.move.select(Moves.SYNCHRONOISE); + await game.phaseInterceptor.to("BerryPhase"); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); + }); +}); diff --git a/test/moves/u_turn.test.ts b/test/moves/u_turn.test.ts index 4ceb6865be0..9dca29414a1 100644 --- a/test/moves/u_turn.test.ts +++ b/test/moves/u_turn.test.ts @@ -74,7 +74,7 @@ describe("Moves - U-turn", () => { // arrange game.override.enemyAbility(Abilities.POISON_POINT); await game.classicMode.startBattle([Species.RAICHU, Species.SHUCKLE]); - vi.spyOn(game.scene.getEnemyPokemon()!, "randSeedInt").mockReturnValue(0); + vi.spyOn(game.scene.getEnemyPokemon()!, "randBattleSeedInt").mockReturnValue(0); // act game.move.select(Moves.U_TURN); diff --git a/test/moves/whirlwind.test.ts b/test/moves/whirlwind.test.ts index 6b5133ec7b1..67ffb77612c 100644 --- a/test/moves/whirlwind.test.ts +++ b/test/moves/whirlwind.test.ts @@ -10,6 +10,7 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { Status } from "#app/data/status-effect"; import { StatusEffect } from "#enums/status-effect"; +import { globalScene } from "#app/global-scene"; import { BattlerIndex } from "#app/battle"; import { BattleType } from "#enums/battle-type"; import { TrainerType } from "#enums/trainer-type"; @@ -161,6 +162,37 @@ describe("Moves - Whirlwind", () => { expect(eevee.isOnField()).toBe(false); }); + it("should fail when player uses Whirlwind against an opponent with only one available Pokémon", async () => { + // Set up the battle scenario with the player knowing Whirlwind + game.override.startingWave(5).enemySpecies(Species.PIDGEY).moveset([Moves.WHIRLWIND]); + await game.classicMode.startBattle(); + + const enemyParty = game.scene.getEnemyParty(); + + // Ensure the opponent has only one available Pokémon + if (enemyParty.length > 1) { + enemyParty.slice(1).forEach(p => { + p.hp = 0; + p.status = new Status(StatusEffect.FAINT); + }); + } + const eligibleEnemy = enemyParty.filter(p => p.hp > 0 && p.isAllowedInBattle()); + expect(eligibleEnemy.length).toBe(1); + + // Spy on the queueMessage function + const queueSpy = vi.spyOn(globalScene, "queueMessage"); + + // Player uses Whirlwind; opponent uses Splash + game.move.select(Moves.WHIRLWIND); + await game.forceEnemyMove(Moves.SPLASH); + await game.toNextTurn(); + + // Verify that the failure message is displayed for Whirlwind + expect(queueSpy).toHaveBeenCalledWith(expect.stringContaining("But it failed")); + // Verify the opponent's Splash message + expect(queueSpy).toHaveBeenCalledWith(expect.stringContaining("But nothing happened!")); + }); + it("should not pull in the other trainer's pokemon in a partner trainer battle", async () => { game.override .startingWave(2)