diff --git a/public/images/mystery-encounters/safari_zone.json b/public/images/mystery-encounters/safari_zone.json new file mode 100644 index 00000000000..f0c23d43f5a --- /dev/null +++ b/public/images/mystery-encounters/safari_zone.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "safarizone.png", + "format": "RGBA8888", + "size": { + "w": 105, + "h": 83 + }, + "scale": 1, + "frames": [ + { + "filename": "safarizone.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 103, + "h": 81 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 103, + "h": 81 + }, + "frame": { + "x": 1, + "y": 1, + "w": 103, + "h": 81 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:f07e2d44900011048b658765e193a86c:3d91036b9c3943256dd1e4712042ec59:d467a15bea042bd0d310f1cce7d9791f$" + } +} diff --git a/public/images/mystery-encounters/safari_zone.png b/public/images/mystery-encounters/safari_zone.png new file mode 100644 index 00000000000..03c32d1b955 Binary files /dev/null and b/public/images/mystery-encounters/safari_zone.png differ diff --git a/public/images/trainer/buck.json b/public/images/trainer/buck.json new file mode 100644 index 00000000000..2088fa084f1 --- /dev/null +++ b/public/images/trainer/buck.json @@ -0,0 +1,272 @@ +{ + "textures": [ + { + "image": "buck.png", + "format": "RGBA8888", + "size": { + "w": 120, + "h": 78 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 33, + "y": 4, + "w": 35, + "h": 76 + }, + "frame": { + "x": 1, + "y": 1, + "w": 35, + "h": 76 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 33, + "y": 4, + "w": 35, + "h": 76 + }, + "frame": { + "x": 1, + "y": 1, + "w": 35, + "h": 76 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 33, + "y": 4, + "w": 35, + "h": 76 + }, + "frame": { + "x": 1, + "y": 1, + "w": 35, + "h": 76 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 33, + "y": 4, + "w": 35, + "h": 76 + }, + "frame": { + "x": 1, + "y": 1, + "w": 35, + "h": 76 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 18, + "y": 8, + "w": 44, + "h": 72 + }, + "frame": { + "x": 38, + "y": 1, + "w": 44, + "h": 72 + } + }, + { + "filename": "00010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 15, + "y": 8, + "w": 44, + "h": 72 + }, + "frame": { + "x": 38, + "y": 1, + "w": 44, + "h": 72 + } + }, + { + "filename": "00011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 13, + "y": 8, + "w": 44, + "h": 72 + }, + "frame": { + "x": 38, + "y": 1, + "w": 44, + "h": 72 + } + }, + { + "filename": "0000.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 34, + "y": 5, + "w": 35, + "h": 75 + }, + "frame": { + "x": 84, + "y": 1, + "w": 35, + "h": 75 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 34, + "y": 5, + "w": 35, + "h": 75 + }, + "frame": { + "x": 84, + "y": 1, + "w": 35, + "h": 75 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 34, + "y": 5, + "w": 35, + "h": 75 + }, + "frame": { + "x": 84, + "y": 1, + "w": 35, + "h": 75 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 34, + "y": 5, + "w": 35, + "h": 75 + }, + "frame": { + "x": 84, + "y": 1, + "w": 35, + "h": 75 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 34, + "y": 5, + "w": 35, + "h": 75 + }, + "frame": { + "x": 84, + "y": 1, + "w": 35, + "h": 75 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:bedd2f8769ba9b1430dc6479e53194f2:49cc02f839fd834c23053d7c92ce9e20:3347efe478119141b0e3e6eccdecd0f5$" + } +} diff --git a/public/images/trainer/buck.png b/public/images/trainer/buck.png new file mode 100644 index 00000000000..2384fb42a33 Binary files /dev/null and b/public/images/trainer/buck.png differ diff --git a/public/images/trainer/cheryl.json b/public/images/trainer/cheryl.json new file mode 100644 index 00000000000..e00e6773c5c --- /dev/null +++ b/public/images/trainer/cheryl.json @@ -0,0 +1,398 @@ +{ + "textures": [ + { + "image": "cheryll.png", + "format": "RGBA8888", + "size": { + "w": 154, + "h": 83 + }, + "scale": 1, + "frames": [ + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 25, + "y": 0, + "w": 41, + "h": 81 + }, + "frame": { + "x": 1, + "y": 1, + "w": 41, + "h": 81 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 25, + "y": 0, + "w": 41, + "h": 81 + }, + "frame": { + "x": 1, + "y": 1, + "w": 41, + "h": 81 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 26, + "y": 0, + "w": 41, + "h": 81 + }, + "frame": { + "x": 1, + "y": 1, + "w": 41, + "h": 81 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 26, + "y": 0, + "w": 41, + "h": 81 + }, + "frame": { + "x": 1, + "y": 1, + "w": 41, + "h": 81 + } + }, + { + "filename": "00010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 27, + "y": 0, + "w": 41, + "h": 81 + }, + "frame": { + "x": 44, + "y": 1, + "w": 41, + "h": 81 + } + }, + { + "filename": "00011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 27, + "y": 0, + "w": 41, + "h": 81 + }, + "frame": { + "x": 44, + "y": 1, + "w": 41, + "h": 81 + } + }, + { + "filename": "00012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 24, + "y": 0, + "w": 41, + "h": 81 + }, + "frame": { + "x": 44, + "y": 1, + "w": 41, + "h": 81 + } + }, + { + "filename": "00013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 24, + "y": 0, + "w": 41, + "h": 81 + }, + "frame": { + "x": 44, + "y": 1, + "w": 41, + "h": 81 + } + }, + { + "filename": "00014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 27, + "y": 0, + "w": 33, + "h": 81 + }, + "frame": { + "x": 87, + "y": 1, + "w": 33, + "h": 81 + } + }, + { + "filename": "00015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 27, + "y": 0, + "w": 33, + "h": 81 + }, + "frame": { + "x": 87, + "y": 1, + "w": 33, + "h": 81 + } + }, + { + "filename": "00016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 26, + "y": 0, + "w": 33, + "h": 81 + }, + "frame": { + "x": 87, + "y": 1, + "w": 33, + "h": 81 + } + }, + { + "filename": "00017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 26, + "y": 0, + "w": 33, + "h": 81 + }, + "frame": { + "x": 87, + "y": 1, + "w": 33, + "h": 81 + } + }, + { + "filename": "0000.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 20, + "y": 0, + "w": 31, + "h": 81 + }, + "frame": { + "x": 122, + "y": 1, + "w": 31, + "h": 81 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 20, + "y": 0, + "w": 31, + "h": 81 + }, + "frame": { + "x": 122, + "y": 1, + "w": 31, + "h": 81 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 20, + "y": 0, + "w": 31, + "h": 81 + }, + "frame": { + "x": 122, + "y": 1, + "w": 31, + "h": 81 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 20, + "y": 0, + "w": 31, + "h": 81 + }, + "frame": { + "x": 122, + "y": 1, + "w": 31, + "h": 81 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 21, + "y": 0, + "w": 31, + "h": 81 + }, + "frame": { + "x": 122, + "y": 1, + "w": 31, + "h": 81 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 81 + }, + "spriteSourceSize": { + "x": 21, + "y": 0, + "w": 31, + "h": 81 + }, + "frame": { + "x": 122, + "y": 1, + "w": 31, + "h": 81 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:dfcf7aedbd588c4e42427a2e17c171bf:206549943a0e3325d20a017ef01eefee:a233cd27590422717866c66e366b68fb$" + } +} diff --git a/public/images/trainer/cheryl.png b/public/images/trainer/cheryl.png new file mode 100644 index 00000000000..c46505f6b25 Binary files /dev/null and b/public/images/trainer/cheryl.png differ diff --git a/public/images/trainer/marley.json b/public/images/trainer/marley.json new file mode 100644 index 00000000000..fcb94459942 --- /dev/null +++ b/public/images/trainer/marley.json @@ -0,0 +1,104 @@ +{ + "textures": [ + { + "image": "marley.png", + "format": "RGBA8888", + "size": { + "w": 102, + "h": 82 + }, + "scale": 1, + "frames": [ + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 27, + "y": 0, + "w": 30, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 30, + "h": 80 + } + }, + { + "filename": "0000.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 27, + "y": 1, + "w": 33, + "h": 79 + }, + "frame": { + "x": 33, + "y": 1, + "w": 33, + "h": 79 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 27, + "y": 1, + "w": 33, + "h": 79 + }, + "frame": { + "x": 33, + "y": 1, + "w": 33, + "h": 79 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 25, + "y": 1, + "w": 33, + "h": 79 + }, + "frame": { + "x": 68, + "y": 1, + "w": 33, + "h": 79 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:4b2edf4443e93acdceffb1d86ae96a96:1019efd49d236cd477b7e9d786d99ffe:d7dbd866d03c506dac6716ab23e62168$" + } +} diff --git a/public/images/trainer/marley.png b/public/images/trainer/marley.png new file mode 100644 index 00000000000..1344574a97c Binary files /dev/null and b/public/images/trainer/marley.png differ diff --git a/public/images/trainer/mira.json b/public/images/trainer/mira.json new file mode 100644 index 00000000000..79f54c49614 --- /dev/null +++ b/public/images/trainer/mira.json @@ -0,0 +1,482 @@ +{ + "textures": [ + { + "image": "mira.png", + "format": "RGBA8888", + "size": { + "w": 57, + "h": 205 + }, + "scale": 1, + "frames": [ + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 20, + "y": 10, + "w": 55, + "h": 65 + }, + "frame": { + "x": 1, + "y": 1, + "w": 55, + "h": 65 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 20, + "y": 11, + "w": 55, + "h": 65 + }, + "frame": { + "x": 1, + "y": 1, + "w": 55, + "h": 65 + } + }, + { + "filename": "00011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 20, + "y": 10, + "w": 55, + "h": 65 + }, + "frame": { + "x": 1, + "y": 1, + "w": 55, + "h": 65 + } + }, + { + "filename": "00012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 20, + "y": 11, + "w": 55, + "h": 65 + }, + "frame": { + "x": 1, + "y": 1, + "w": 55, + "h": 65 + } + }, + { + "filename": "00018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 20, + "y": 10, + "w": 55, + "h": 65 + }, + "frame": { + "x": 1, + "y": 1, + "w": 55, + "h": 65 + } + }, + { + "filename": "00019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 20, + "y": 11, + "w": 55, + "h": 65 + }, + "frame": { + "x": 1, + "y": 1, + "w": 55, + "h": 65 + } + }, + { + "filename": "0000.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 22, + "y": 13, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 68, + "w": 46, + "h": 67 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 22, + "y": 13, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 68, + "w": 46, + "h": 67 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 21, + "y": 12, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 68, + "w": 46, + "h": 67 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 20, + "y": 10, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 68, + "w": 46, + "h": 67 + } + }, + { + "filename": "00013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 20, + "y": 10, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 68, + "w": 46, + "h": 67 + } + }, + { + "filename": "00014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 21, + "y": 12, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 68, + "w": 46, + "h": 67 + } + }, + { + "filename": "00015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 22, + "y": 13, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 68, + "w": 46, + "h": 67 + } + }, + { + "filename": "00016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 21, + "y": 12, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 68, + "w": 46, + "h": 67 + } + }, + { + "filename": "00017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 20, + "y": 10, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 68, + "w": 46, + "h": 67 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 10, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 137, + "w": 46, + "h": 67 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 11, + "y": 12, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 137, + "w": 46, + "h": 67 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 10, + "y": 13, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 137, + "w": 46, + "h": 67 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 11, + "y": 12, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 137, + "w": 46, + "h": 67 + } + }, + { + "filename": "00010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 10, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 137, + "w": 46, + "h": 67 + } + }, + { + "filename": "00020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 10, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 137, + "w": 46, + "h": 67 + } + }, + { + "filename": "00021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 11, + "y": 12, + "w": 46, + "h": 67 + }, + "frame": { + "x": 1, + "y": 137, + "w": 46, + "h": 67 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:fa0a6e132823f8a832e4a5a4f7f22e71:0662a4931405bc13b67679afcad37bac:f9bd0c7364e7f214bd64723bef0b3fe9$" + } +} diff --git a/public/images/trainer/mira.png b/public/images/trainer/mira.png new file mode 100644 index 00000000000..0ddddf90e47 Binary files /dev/null and b/public/images/trainer/mira.png differ diff --git a/public/images/trainer/riley.json b/public/images/trainer/riley.json new file mode 100644 index 00000000000..e29f6e02e24 --- /dev/null +++ b/public/images/trainer/riley.json @@ -0,0 +1,461 @@ +{ + "textures": [ + { + "image": "riley.png", + "format": "RGBA8888", + "size": { + "w": 59, + "h": 246 + }, + "scale": 1, + "frames": [ + { + "filename": "0000.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 57, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 57, + "h": 80 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 9, + "y": 0, + "w": 57, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 57, + "h": 80 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 57, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 57, + "h": 80 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 57, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 57, + "h": 80 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 57, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 57, + "h": 80 + } + }, + { + "filename": "00010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 57, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 57, + "h": 80 + } + }, + { + "filename": "00012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 57, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 57, + "h": 80 + } + }, + { + "filename": "00014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 57, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 57, + "h": 80 + } + }, + { + "filename": "00016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 57, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 57, + "h": 80 + } + }, + { + "filename": "00018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 57, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 57, + "h": 80 + } + }, + { + "filename": "00020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 57, + "h": 80 + }, + "frame": { + "x": 1, + "y": 1, + "w": 57, + "h": 80 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 11, + "y": 0, + "w": 56, + "h": 80 + }, + "frame": { + "x": 1, + "y": 83, + "w": 56, + "h": 80 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 11, + "y": 0, + "w": 56, + "h": 80 + }, + "frame": { + "x": 1, + "y": 83, + "w": 56, + "h": 80 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 11, + "y": 0, + "w": 56, + "h": 80 + }, + "frame": { + "x": 1, + "y": 83, + "w": 56, + "h": 80 + } + }, + { + "filename": "00011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 11, + "y": 0, + "w": 56, + "h": 80 + }, + "frame": { + "x": 1, + "y": 83, + "w": 56, + "h": 80 + } + }, + { + "filename": "00013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 11, + "y": 0, + "w": 56, + "h": 80 + }, + "frame": { + "x": 1, + "y": 83, + "w": 56, + "h": 80 + } + }, + { + "filename": "00015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 11, + "y": 0, + "w": 56, + "h": 80 + }, + "frame": { + "x": 1, + "y": 83, + "w": 56, + "h": 80 + } + }, + { + "filename": "00017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 11, + "y": 0, + "w": 56, + "h": 80 + }, + "frame": { + "x": 1, + "y": 83, + "w": 56, + "h": 80 + } + }, + { + "filename": "00019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 11, + "y": 0, + "w": 56, + "h": 80 + }, + "frame": { + "x": 1, + "y": 83, + "w": 56, + "h": 80 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 30, + "y": 0, + "w": 39, + "h": 80 + }, + "frame": { + "x": 1, + "y": 165, + "w": 39, + "h": 80 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 29, + "y": 0, + "w": 39, + "h": 80 + }, + "frame": { + "x": 1, + "y": 165, + "w": 39, + "h": 80 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:d0f27c1a776dc776dbc730ec409fafad:7a665e1bfee26403e5d49912c4dad042:cb98d9ba5e960a1d670368dad1073434$" + } +} diff --git a/public/images/trainer/riley.png b/public/images/trainer/riley.png new file mode 100644 index 00000000000..dd5d3bdd8c9 Binary files /dev/null and b/public/images/trainer/riley.png differ diff --git a/src/data/dialogue.ts b/src/data/dialogue.ts index ec3358b1a77..5d4bea542de 100644 --- a/src/data/dialogue.ts +++ b/src/data/dialogue.ts @@ -665,6 +665,76 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { ] } ], + [TrainerType.BUCK]: [ + { + encounter: [ + "dialogue:stat_trainer_buck.encounter.1", + "dialogue:stat_trainer_buck.encounter.2" + ], + victory: [ + "dialogue:stat_trainer_buck.victory.1" + ], + defeat: [ + "dialogue:stat_trainer_buck.defeat.1" + ] + } + ], + [TrainerType.CHERYL]: [ + { + encounter: [ + "dialogue:stat_trainer_cheryl.encounter.1", + "dialogue:stat_trainer_cheryl.encounter.2" + ], + victory: [ + "dialogue:stat_trainer_cheryl.victory.1" + ], + defeat: [ + "dialogue:stat_trainer_cheryl.defeat.1" + ] + } + ], + [TrainerType.MARLEY]: [ + { + encounter: [ + "dialogue:stat_trainer_marley.encounter.1", + "dialogue:stat_trainer_marley.encounter.2" + ], + victory: [ + "dialogue:stat_trainer_marley.victory.1" + ], + defeat: [ + "dialogue:stat_trainer_marley.defeat.1" + ] + } + ], + [TrainerType.MIRA]: [ + { + encounter: [ + "dialogue:stat_trainer_mira.encounter.1", + "dialogue:stat_trainer_mira.encounter.2" + ], + victory: [ + "dialogue:stat_trainer_mira.victory.1" + ], + defeat: [ + "dialogue:stat_trainer_mira.defeat.1" + ] + } + ], + [TrainerType.RILEY]: [ + { + encounter: [ + "dialogue:stat_trainer_riley.encounter.1", + "dialogue:stat_trainer_riley.encounter.2" + ], + victory: [ + "dialogue:stat_trainer_riley.victory.1" + ], + defeat: [ + "dialogue:stat_trainer_riley.defeat.1" + ] + } + ], [TrainerType.BROCK]: { encounter: [ "dialogue:brock.encounter.1", diff --git a/src/data/mystery-encounters/encounters/a-trainers-test-encounter.ts b/src/data/mystery-encounters/encounters/a-trainers-test-encounter.ts new file mode 100644 index 00000000000..c2cd13690f9 --- /dev/null +++ b/src/data/mystery-encounters/encounters/a-trainers-test-encounter.ts @@ -0,0 +1,168 @@ +import { EnemyPartyConfig, initBattleWithEnemyConfig, setEncounterRewards, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { trainerConfigs, } from "#app/data/trainer-config"; +import { ModifierTier } from "#app/modifier/modifier-tier"; +import { modifierTypes } from "#app/modifier/modifier-type"; +import { MysteryEncounterType } from "#enums/mystery-encounter-type"; +import BattleScene from "#app/battle-scene"; +import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter"; +import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; +import { TrainerType } from "#enums/trainer-type"; +import { Species } from "#enums/species"; +import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; +import { randSeedInt } from "#app/utils"; + +/** the i18n namespace for the encounter */ +const namespace = "mysteryEncounter:aTrainersTest"; + +/** + * A Trainer's Test encounter. + * @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/115 | GitHub Issue #115} + * @see For biome requirements check {@linkcode mysteryEncountersByBiome} + */ +export const ATrainersTestEncounter: IMysteryEncounter = + MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.A_TRAINERS_TEST) + .withEncounterTier(MysteryEncounterTier.ROGUE) + .withSceneWaveRangeRequirement(10, 180) // waves 10 to 180 + .withIntroSpriteConfigs([]) // These are set in onInit() + .withIntroDialogue([ + { + text: `${namespace}:intro`, + }, + ]) + .withOnInit((scene: BattleScene) => { + const encounter = scene.currentBattle.mysteryEncounter; + + // Randomly pick from 1 of the 5 stat trainers to spawn + let trainerType: TrainerType; + let spriteKeys; + switch (randSeedInt(5)) { + default: + case 0: + trainerType = TrainerType.BUCK; + spriteKeys = getSpriteKeysFromSpecies(Species.CLAYDOL); + break; + case 1: + trainerType = TrainerType.CHERYL; + spriteKeys = getSpriteKeysFromSpecies(Species.BLISSEY); + break; + case 2: + trainerType = TrainerType.MARLEY; + spriteKeys = getSpriteKeysFromSpecies(Species.ARCANINE); + break; + case 3: + trainerType = TrainerType.MIRA; + spriteKeys = getSpriteKeysFromSpecies(Species.ALAKAZAM, false, 1); + break; + case 4: + trainerType = TrainerType.RILEY; + spriteKeys = getSpriteKeysFromSpecies(Species.LUCARIO, false, 1); + break; + } + + encounter.misc = { trainerType }; + const trainerConfig = trainerConfigs[trainerType].copy(); + const trainerSpriteKey = trainerConfig.getSpriteKey(); + encounter.enemyPartyConfigs.push({ + levelAdditiveMultiplier: 1, + trainerConfig: trainerConfig + }); + + encounter.spriteConfigs = [ + { + spriteKey: spriteKeys.spriteKey, + fileRoot: spriteKeys.fileRoot, + hasShadow: true, + repeat: true, + isPokemon: true + }, + { + spriteKey: trainerSpriteKey, + fileRoot: "trainer", + hasShadow: true, + disableAnimation: true + } + ]; + + return true; + }) + .withTitle(`${namespace}:title`) + .withDescription(`${namespace}:description`) + .withQuery(`${namespace}:query`) + .withSimpleOption( + { + buttonLabel: `${namespace}:option:1:label`, + buttonTooltip: `${namespace}:option:1:tooltip`, + selected: [ + { + text: `${namespace}:option:selected`, + }, + ], + }, + async (scene: BattleScene) => { + const encounter = scene.currentBattle.mysteryEncounter; + // Spawn standard trainer battle with memory mushroom reward + const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0]; + + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM], fillRemaining: true }); + return initBattleWithEnemyConfig(scene, config); + } + ) + .withSimpleOption( + { + buttonLabel: `${namespace}:option:2:label`, + buttonTooltip: `${namespace}:option:2:tooltip`, + selected: [ + { + text: `${namespace}:option:selected`, + }, + ], + }, + async (scene: BattleScene) => { + const encounter = scene.currentBattle.mysteryEncounter; + // Spawn hard fight with ULTRA/GREAT reward (can improve with luck) + const config: EnemyPartyConfig = encounter.enemyPartyConfigs[1]; + + setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], fillRemaining: true }); + + // Seed offsets to remove possibility of different trainers having exact same teams + let ret; + scene.executeWithSeedOffset(() => { + ret = initBattleWithEnemyConfig(scene, config); + }, scene.currentBattle.waveIndex * 100); + return ret; + } + ) + .withSimpleOption( + { + buttonLabel: `${namespace}:option:3:label`, + buttonTooltip: `${namespace}:option:3:tooltip`, + selected: [ + { + text: `${namespace}:option:selected`, + }, + ], + }, + async (scene: BattleScene) => { + const encounter = scene.currentBattle.mysteryEncounter; + // Spawn brutal fight with ROGUE/ULTRA/GREAT reward (can improve with luck) + const config: EnemyPartyConfig = encounter.enemyPartyConfigs[2]; + + // To avoid player level snowballing from picking this option + encounter.expMultiplier = 0.9; + + setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT], fillRemaining: true }); + + // Seed offsets to remove possibility of different trainers having exact same teams + let ret; + scene.executeWithSeedOffset(() => { + ret = initBattleWithEnemyConfig(scene, config); + }, scene.currentBattle.waveIndex * 1000); + return ret; + } + ) + .withOutroDialogue([ + { + text: `${namespace}:outro`, + }, + ]) + .build(); diff --git a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts index 2b379bdba86..bd39c586ad9 100644 --- a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts +++ b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts @@ -1,5 +1,5 @@ import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; -import Pokemon, { PokemonMove } from "#app/field/pokemon"; +import Pokemon, { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; import { BerryModifierType, modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { Species } from "#enums/species"; @@ -37,18 +37,20 @@ export const AbsoluteAvariceEncounter: IMysteryEncounter = .withSceneRequirement(new PersistentModifierRequirement("BerryModifier", 4)) // Must have at least 4 berries to spawn .withIntroSpriteConfigs([ { - spriteKey: Species.GREEDENT.toString(), - fileRoot: "pokemon", - hasShadow: false, + // This sprite has the shadow + spriteKey: null, + fileRoot: null, + species: Species.GREEDENT, + hasShadow: true, + alpha: 0.001, repeat: true, x: -5 }, { - // This sprite has the shadow - spriteKey: Species.GREEDENT.toString(), - fileRoot: "pokemon", - hasShadow: true, - alpha: 0.001, + spriteKey: null, + fileRoot: null, + species: Species.GREEDENT, + hasShadow: false, repeat: true, x: -5 }, @@ -328,7 +330,7 @@ export const AbsoluteAvariceEncounter: IMysteryEncounter = // Let it have the food // Greedent joins the team, level equal to 2 below highest party member const level = getHighestLevelPlayerPokemon(scene).level - 2; - const greedent = scene.addEnemyPokemon(getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false); + const greedent = new EnemyPokemon(scene, getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false, null); greedent.moveset = [new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF)]; greedent.passive = true; @@ -344,7 +346,7 @@ function doGreedentSpriteSteal(scene: BattleScene) { const shakeDelay = 50; const slideDelay = 500; - const greedentSprites = scene.currentBattle.mysteryEncounter.introVisuals.getSpriteAtIndex(0); + const greedentSprites = scene.currentBattle.mysteryEncounter.introVisuals.getSpriteAtIndex(1); scene.playSound("Follow Me"); scene.tweens.chain({ @@ -418,7 +420,7 @@ function doGreedentSpriteSteal(scene: BattleScene) { } function doGreedentEatBerries(scene: BattleScene) { - const greedentSprites = scene.currentBattle.mysteryEncounter.introVisuals.getSpriteAtIndex(0); + const greedentSprites = scene.currentBattle.mysteryEncounter.introVisuals.getSpriteAtIndex(1); let index = 1; scene.tweens.add({ targets: greedentSprites, @@ -452,7 +454,7 @@ function doBerrySpritePile(scene: BattleScene, isEat: boolean = false) { } const encounter = scene.currentBattle.mysteryEncounter; animationOrder.forEach((berry, i) => { - const introVisualsIndex = encounter.spriteConfigs.findIndex(config => config.spriteKey.includes(berry)); + const introVisualsIndex = encounter.spriteConfigs.findIndex(config => config.spriteKey?.includes(berry)); const [ sprite, tintSprite ] = encounter.introVisuals.getSpriteAtIndex(introVisualsIndex); scene.time.delayedCall(berryAddDelay * i + 400, () => { if (sprite) { diff --git a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts index c1c3fb8c3c8..7d1e7a61035 100644 --- a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts +++ b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts @@ -47,23 +47,26 @@ export const DelibirdyEncounter: IMysteryEncounter = )) .withIntroSpriteConfigs([ { - spriteKey: Species.DELIBIRD.toString(), - fileRoot: "pokemon", + spriteKey: null, + fileRoot: null, + species: Species.DELIBIRD, hasShadow: true, repeat: true, startFrame: 38, scale: 0.94 }, { - spriteKey: Species.DELIBIRD.toString(), - fileRoot: "pokemon", + spriteKey: null, + fileRoot: null, + species: Species.DELIBIRD, hasShadow: true, repeat: true, scale: 1.06 }, { - spriteKey: Species.DELIBIRD.toString(), - fileRoot: "pokemon", + spriteKey: null, + fileRoot: null, + species: Species.DELIBIRD, hasShadow: true, repeat: true, startFrame: 65, diff --git a/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts b/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts index 610b836ef9e..65873941bd5 100644 --- a/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts +++ b/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts @@ -32,8 +32,9 @@ export const DepartmentStoreSaleEncounter: IMysteryEncounter = x: -20, }, { - spriteKey: Species.FURFROU.toString(), - fileRoot: "pokemon", + spriteKey: null, + fileRoot: null, + species: Species.FURFROU, hasShadow: true, repeat: true, x: 30, diff --git a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts index c7933129ff9..20d113bf940 100644 --- a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts +++ b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts @@ -1,5 +1,5 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; -import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, initCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, loadCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { AttackTypeBoosterModifierType, modifierTypes, } from "#app/modifier/modifier-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import BattleScene from "#app/battle-scene"; @@ -75,8 +75,9 @@ export const FieryFalloutEncounter: IMysteryEncounter = // Load hidden Volcarona sprites encounter.spriteConfigs = [ { - spriteKey: volcaronaSpecies.getSpriteId(false), - fileRoot: "pokemon", + spriteKey: null, + fileRoot: null, + species: Species.VOLCARONA, repeat: true, hidden: true, hasShadow: true, @@ -84,8 +85,9 @@ export const FieryFalloutEncounter: IMysteryEncounter = startFrame: 20 }, { - spriteKey: volcaronaSpecies.getSpriteId(true ), - fileRoot: "pokemon", + spriteKey: null, + fileRoot: null, + species: Species.VOLCARONA, repeat: true, hidden: true, hasShadow: true, @@ -94,7 +96,7 @@ export const FieryFalloutEncounter: IMysteryEncounter = ]; // Load animations/sfx for Volcarona moves - initCustomMovesForEncounter(scene, [Moves.FIRE_SPIN, Moves.QUIVER_DANCE]); + loadCustomMovesForEncounter(scene, [Moves.FIRE_SPIN, Moves.QUIVER_DANCE]); scene.arena.trySetWeather(WeatherType.SUNNY, true); diff --git a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts index 77ef97ace84..55e31406cdb 100644 --- a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts +++ b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts @@ -7,7 +7,7 @@ import { setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups"; -import Pokemon from "#app/field/pokemon"; +import Pokemon, { EnemyPokemon } from "#app/field/pokemon"; import { ModifierTier } from "#app/modifier/modifier-tier"; import { getPartyLuckValue, @@ -27,6 +27,9 @@ import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-enco import { getPokemonNameWithAffix } from "#app/messages"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; +import { TrainerSlot } from "#app/data/trainer-config"; +import { getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; +import PokemonData from "#app/system/pokemon-data"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounter:fightOrFlight"; @@ -53,9 +56,14 @@ export const FightOrFlightEncounter: IMysteryEncounter = // Calculate boss mon const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, scene.currentBattle.waveIndex, 0, getPartyLuckValue(scene.getParty()), true); + const bossPokemon = new EnemyPokemon(scene, bossSpecies, scene.currentBattle.waveIndex, TrainerSlot.NONE, true, null); const config: EnemyPartyConfig = { levelAdditiveMultiplier: 1, - pokemonConfigs: [{ species: bossSpecies, isBoss: true }], + pokemonConfigs: [{ + species: bossSpecies, + dataSource: new PokemonData(bossPokemon), + isBoss: true + }], }; encounter.enemyPartyConfigs = [config]; @@ -74,7 +82,7 @@ export const FightOrFlightEncounter: IMysteryEncounter = encounter.setDialogueToken("itemName", item.type.name); encounter.misc = item; - const bossSpriteKey = bossSpecies.getSpriteId(false, bossSpecies.forms ? 0 : null, false, bossSpecies.hasVariants() ? 0 : null); + const { spriteKey, fileRoot } = getSpriteKeysFromPokemon(bossPokemon); encounter.spriteConfigs = [ { spriteKey: item.type.iconImage, @@ -87,12 +95,13 @@ export const FightOrFlightEncounter: IMysteryEncounter = disableAnimation: true }, { - spriteKey: bossSpriteKey, - fileRoot: "pokemon", + spriteKey: spriteKey, + fileRoot: fileRoot, hasShadow: true, tint: 0.25, x: -5, repeat: true, + isPokemon: true }, ]; diff --git a/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts b/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts index a4e47311f43..40c913584bd 100644 --- a/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts +++ b/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts @@ -31,8 +31,8 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with .withSceneWaveRangeRequirement(11, 179) .withIntroSpriteConfigs([ { - fileRoot: "mystery-encounters", spriteKey: "buoy", + fileRoot: "mystery-encounters", hasShadow: false, x: 20, y: 3, diff --git a/src/data/mystery-encounters/encounters/pokemon-salesman-encounter.ts b/src/data/mystery-encounters/encounters/pokemon-salesman-encounter.ts index d1750119add..b0cbb454042 100644 --- a/src/data/mystery-encounters/encounters/pokemon-salesman-encounter.ts +++ b/src/data/mystery-encounters/encounters/pokemon-salesman-encounter.ts @@ -4,7 +4,7 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import BattleScene from "#app/battle-scene"; import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter"; import { MoneyRequirement } from "../mystery-encounter-requirements"; -import { catchPokemon, getRandomSpeciesByStarterTier } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; +import { catchPokemon, getRandomSpeciesByStarterTier, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species"; import { Species } from "#enums/species"; import { PokeballType } from "#app/data/pokeball"; @@ -66,17 +66,16 @@ export const PokemonSalesmanEncounter: IMysteryEncounter = // If no HA mon found or you roll 1%, give shiny Magikarp species = getPokemonSpecies(Species.MAGIKARP); const hiddenIndex = species.ability2 ? 2 : 1; - pokemon = scene.addPlayerPokemon(species, 5, hiddenIndex, species.formIndex, null, true); + pokemon = new PlayerPokemon(scene, species, 5, hiddenIndex, species.formIndex, null, true, null, null, null, null); } else { const hiddenIndex = species.ability2 ? 2 : 1; - pokemon = scene.addPlayerPokemon(species, 5, hiddenIndex, species.formIndex); + pokemon = new PlayerPokemon(scene, species, 5, hiddenIndex, species.formIndex, null, null, null, null, null, null); } - const spriteKey = pokemon.getSpriteId(); - const spriteRoot = pokemon.getSpriteAtlasPath(); + const { spriteKey, fileRoot } = getSpriteKeysFromPokemon(pokemon); encounter.spriteConfigs.push({ spriteKey: spriteKey, - fileRoot: spriteRoot, + fileRoot: fileRoot, hasShadow: true, repeat: true, isPokemon: true diff --git a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts index 7ca2e991305..d193b5a5d00 100644 --- a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts +++ b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts @@ -36,12 +36,11 @@ export const SafariZoneEncounter: IMysteryEncounter = .withSceneRequirement(new MoneyRequirement(0, 2.75)) // Cost equal to 1 Max Revive .withIntroSpriteConfigs([ { - spriteKey: "chest_blue", + spriteKey: "safari_zone", fileRoot: "mystery-encounters", - hasShadow: true, + hasShadow: false, x: 4, - y: 10, - yShadow: 3 + y: 6 }, ]) .withIntroDialogue([ @@ -52,6 +51,11 @@ export const SafariZoneEncounter: IMysteryEncounter = .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) + // .withEnterIntroVisualsFromRight(true) + // .withOnVisualsStart((scene: BattleScene) => { + // scene.setFieldScale(0.9); + // return true; + // }) .withOption(new MysteryEncounterOptionBuilder() .withOptionMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT) .withSceneRequirement(new MoneyRequirement(0, 2.75)) // Cost equal to 1 Max Revive diff --git a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts index 316416e3809..dd3a2057502 100644 --- a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts +++ b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts @@ -7,7 +7,7 @@ import { StatusEffect } from "#app/data/status-effect"; import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter"; import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option"; import { MoveRequirement } from "../mystery-encounter-requirements"; -import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, initCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, } from "../utils/encounter-phase-utils"; +import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, loadCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, } from "../utils/encounter-phase-utils"; import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { Moves } from "#enums/moves"; import { BattlerIndex } from "#app/battle"; @@ -66,7 +66,7 @@ export const SlumberingSnorlaxEncounter: IMysteryEncounter = encounter.enemyPartyConfigs = [config]; // Load animations/sfx for Snorlax fight start moves - initCustomMovesForEncounter(scene, [Moves.SNORE]); + loadCustomMovesForEncounter(scene, [Moves.SNORE]); return true; }) diff --git a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts index 34967112a72..f92e33683d6 100644 --- a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts @@ -1,4 +1,4 @@ -import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, initCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, loadCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { modifierTypes, PokemonHeldItemModifierType, } from "#app/modifier/modifier-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import BattleScene from "#app/battle-scene"; @@ -91,7 +91,7 @@ export const TheStrongStuffEncounter: IMysteryEncounter = encounter.enemyPartyConfigs = [config]; - initCustomMovesForEncounter(scene, [Moves.GASTRO_ACID, Moves.STEALTH_ROCK]); + loadCustomMovesForEncounter(scene, [Moves.GASTRO_ACID, Moves.STEALTH_ROCK]); return true; }) diff --git a/src/data/mystery-encounters/mystery-encounter.ts b/src/data/mystery-encounters/mystery-encounter.ts index 502d84d9124..8eababcfdeb 100644 --- a/src/data/mystery-encounters/mystery-encounter.ts +++ b/src/data/mystery-encounters/mystery-encounter.ts @@ -47,6 +47,7 @@ export default interface IMysteryEncounter { encounterAnimations?: EncounterAnim[]; hideBattleIntroMessage?: boolean; autoHideIntroVisuals?: boolean; + enterIntroVisualsFromRight?: boolean; catchAllowed?: boolean; maxAllowedEncounters?: number; @@ -159,14 +160,15 @@ export default class IMysteryEncounter implements IMysteryEncounter { if (!isNullOrUndefined(encounter)) { Object.assign(this, encounter); } - this.encounterTier = !isNullOrUndefined(this.encounterTier) ? this.encounterTier : MysteryEncounterTier.COMMON; + this.encounterTier = this.encounterTier ?? MysteryEncounterTier.COMMON; this.dialogue = this.dialogue ?? {}; // Default max is 1 for ROGUE encounters, 3 for others this.maxAllowedEncounters = this.maxAllowedEncounters ?? this.encounterTier === MysteryEncounterTier.ROGUE ? 1 : 3; this.encounterMode = MysteryEncounterMode.DEFAULT; this.requirements = this.requirements ? this.requirements : []; - this.hideBattleIntroMessage = !isNullOrUndefined(this.hideBattleIntroMessage) ? this.hideBattleIntroMessage : false; - this.autoHideIntroVisuals = !isNullOrUndefined(this.autoHideIntroVisuals) ? this.autoHideIntroVisuals : true; + this.hideBattleIntroMessage = this.hideBattleIntroMessage ?? false; + this.autoHideIntroVisuals = this.autoHideIntroVisuals ?? true; + this.enterIntroVisualsFromRight = this.enterIntroVisualsFromRight ?? false; // Reset any dirty flags or encounter data this.startOfBattleEffectsComplete = false; @@ -414,6 +416,7 @@ export class MysteryEncounterBuilder implements Partial { hideBattleIntroMessage?: boolean; hideIntroVisuals?: boolean; + enterIntroVisualsFromRight?: boolean; enemyPartyConfigs?: EnemyPartyConfig[] = []; /** @@ -717,6 +720,15 @@ export class MysteryEncounterBuilder implements Partial { return Object.assign(this, { autoHideIntroVisuals: autoHideIntroVisuals }); } + /** + * @param enterIntroVisualsFromRight - If true, will slide in intro visuals from the right side of the screen. If false, slides in from left, as normal + * Default false + * @returns + */ + withEnterIntroVisualsFromRight(enterIntroVisualsFromRight: boolean): this & Required> { + return Object.assign(this, { enterIntroVisualsFromRight: enterIntroVisualsFromRight }); + } + /** * Add a title for the encounter * diff --git a/src/data/mystery-encounters/mystery-encounters.ts b/src/data/mystery-encounters/mystery-encounters.ts index c41fd8dfe53..68f01220793 100644 --- a/src/data/mystery-encounters/mystery-encounters.ts +++ b/src/data/mystery-encounters/mystery-encounters.ts @@ -18,6 +18,7 @@ import { PokemonSalesmanEncounter } from "#app/data/mystery-encounters/encounter import { OfferYouCantRefuseEncounter } from "#app/data/mystery-encounters/encounters/offer-you-cant-refuse-encounter"; import { DelibirdyEncounter } from "#app/data/mystery-encounters/encounters/delibirdy-encounter"; import { AbsoluteAvariceEncounter } from "#app/data/mystery-encounters/encounters/absolute-avarice-encounter"; +import { ATrainersTestEncounter } from "#app/data/mystery-encounters/encounters/a-trainers-test-encounter"; // Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * ) / 256 export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 1; @@ -154,6 +155,7 @@ const anyBiomeEncounters: MysteryEncounterType[] = [ MysteryEncounterType.MYSTERIOUS_CHEST, MysteryEncounterType.TRAINING_SESSION, MysteryEncounterType.DELIBIRDY, + MysteryEncounterType.A_TRAINERS_TEST ]; /** @@ -240,6 +242,7 @@ export function initMysteryEncounters() { allMysteryEncounters[MysteryEncounterType.OFFER_YOU_CANT_REFUSE] = OfferYouCantRefuseEncounter; allMysteryEncounters[MysteryEncounterType.DELIBIRDY] = DelibirdyEncounter; allMysteryEncounters[MysteryEncounterType.ABSOLUTE_AVARICE] = AbsoluteAvariceEncounter; + allMysteryEncounters[MysteryEncounterType.A_TRAINERS_TEST] = ATrainersTestEncounter; // Add extreme encounters to biome map extremeBiomeEncounters.forEach(encounter => { diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index 9fa24106417..21f54059828 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -305,7 +305,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig: * @param scene * @param moves */ -export function initCustomMovesForEncounter(scene: BattleScene, moves: Moves | Moves[]) { +export function loadCustomMovesForEncounter(scene: BattleScene, moves: Moves | Moves[]) { moves = Array.isArray(moves) ? moves : [moves]; return Promise.all(moves.map(move => initMoveAnim(scene, move))) .then(() => loadMoveAnimAssets(scene, moves)); diff --git a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts index edfb72e6611..e3dd3106aeb 100644 --- a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts @@ -3,7 +3,7 @@ import i18next from "i18next"; import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { PokemonHeldItemModifier } from "#app/modifier/modifier"; import { VictoryPhase } from "#app/phases"; -import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; +import Pokemon, { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "#app/data/pokeball"; import { PlayerGender } from "#enums/player-gender"; import { addPokeballCaptureStars, addPokeballOpenParticles } from "#app/field/anims"; @@ -18,11 +18,25 @@ import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "#app/data/po import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getPokemonNameWithAffix } from "#app/messages"; import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; +import { Gender } from "#app/data/gender"; export interface MysteryEncounterPokemonData { spriteScale?: number } +export function getSpriteKeysFromSpecies(species: Species, female?: boolean, formIndex?: integer, shiny?: boolean, variant?: integer): { spriteKey: string, fileRoot: string } { + const spriteKey = getPokemonSpecies(species).getSpriteKey(female ?? false, formIndex ?? 0, shiny ?? false, variant ?? 0); + const fileRoot = getPokemonSpecies(species).getSpriteAtlasPath(female ?? false, formIndex ?? 0, shiny ?? false, variant ?? 0); + return { spriteKey, fileRoot }; +} + +export function getSpriteKeysFromPokemon(pokemon: Pokemon): { spriteKey: string, fileRoot: string } { + const spriteKey = pokemon.getSpeciesForm().getSpriteKey(pokemon.getGender() === Gender.FEMALE, pokemon.formIndex, pokemon.shiny, pokemon.variant); + const fileRoot = pokemon.getSpeciesForm().getSpriteAtlasPath(pokemon.getGender() === Gender.FEMALE, pokemon.formIndex, pokemon.shiny, pokemon.variant); + + return { spriteKey, fileRoot }; +} + /** * * Will never remove the player's last non-fainted Pokemon (if they only have 1) diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 8b251d59de9..f3e6009e02e 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -1,16 +1,16 @@ -import BattleScene, {startingWave} from "../battle-scene"; -import {ModifierTypeFunc, modifierTypes} from "../modifier/modifier-type"; -import {EnemyPokemon} from "../field/pokemon"; +import BattleScene, { startingWave } from "../battle-scene"; +import { ModifierTypeFunc, modifierTypes } from "../modifier/modifier-type"; +import { EnemyPokemon } from "../field/pokemon"; import * as Utils from "../utils"; -import {PokeballType} from "./pokeball"; -import {pokemonEvolutions, pokemonPrevolutions} from "./pokemon-evolutions"; -import PokemonSpecies, {getPokemonSpecies, PokemonSpeciesFilter} from "./pokemon-species"; -import {tmSpecies} from "./tms"; -import {Type} from "./type"; -import {doubleBattleDialogue} from "./dialogue"; -import {PersistentModifier} from "../modifier/modifier"; -import {TrainerVariant} from "../field/trainer"; -import {getIsInitialized, initI18n} from "#app/plugins/i18n"; +import { PokeballType } from "./pokeball"; +import { pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions"; +import PokemonSpecies, { getPokemonSpecies, PokemonSpeciesFilter } from "./pokemon-species"; +import { tmSpecies } from "./tms"; +import { Type } from "./type"; +import { doubleBattleDialogue } from "./dialogue"; +import { PersistentModifier } from "../modifier/modifier"; +import { TrainerVariant } from "../field/trainer"; +import { getIsInitialized, initI18n } from "#app/plugins/i18n"; import i18next from "i18next"; import { Moves } from "#enums/moves"; import { PartyMemberStrength } from "#enums/party-member-strength"; @@ -527,6 +527,44 @@ export class TrainerConfig { return this; } + /** + * Initializes the trainer configuration for a Stat Trainer, as part of the Trainer's Test Mystery Encounter. + * @param {Species | Species[]} signatureSpecies - The signature species for the Elite Four member. + * @param {Type[]} specialtyTypes - The specialty types for the Stat Trainer. + * @param isMale - Whether the Elite Four Member is Male or Female (for localization of the title). + * @returns {TrainerConfig} - The updated TrainerConfig instance. + **/ + initForStatTrainer(signatureSpecies: (Species | Species[])[], isMale: boolean, ...specialtyTypes: Type[]): TrainerConfig { + if (!getIsInitialized()) { + initI18n(); + } + + this.setPartyTemplates(trainerPartyTemplates.ELITE_FOUR); + + signatureSpecies.forEach((speciesPool, s) => { + if (!Array.isArray(speciesPool)) { + speciesPool = [speciesPool]; + } + this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); + }); + if (specialtyTypes.length) { + this.setSpeciesFilter(p => specialtyTypes.find(t => p.isOfType(t)) !== undefined); + this.setSpecialtyTypes(...specialtyTypes); + } + const nameForCall = this.name.toLowerCase().replace(/\s/g, "_"); + this.name = i18next.t(`trainerNames:${nameForCall}`); + // this.setTitle(title); + this.setMoneyMultiplier(2); + this.setBoss(); + this.setStaticParty(); + + // TODO: replace with more suitable music? + this.setBattleBgm("battle_trainer"); + this.setVictoryBgm("victory_trainer"); + + return this; + } + /** * Initializes the trainer configuration for an evil team leader. Temporarily hardcoding evil leader teams though. * @param {Species | Species[]} signatureSpecies - The signature species for the evil team leader. @@ -1787,4 +1825,137 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; })), + // TODO: use signature species? + [TrainerType.BUCK]: new TrainerConfig(++t).setName("Buck").initForStatTrainer([], true) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CLAYDOL ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 3); + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.COALOSSAL ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.GREAT_BALL; + if (p.species.speciesId === Species.VENUSAUR) { + p.formIndex = 2; // Gmax + p.abilityIndex = 2; // Venusaur gets Chlorophyll + } else { + p.formIndex = 1; // Gmax + } + p.generateName(); + })) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.AGGRON ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.formIndex = 1; // Mega + p.generateName(); + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TORKOAL ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.abilityIndex = 1; // Drought + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GREAT_TUSK ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.HEATRAN ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })), + [TrainerType.CHERYL]: new TrainerConfig(++t).setName("Cheryl").initForStatTrainer([], false) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BLISSEY ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 3); + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.SNORLAX, Species.LAPRAS ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.GREAT_BALL; + p.formIndex = 1; // Gmax + p.generateName(); + })) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.AUDINO ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.formIndex = 1; // Mega + p.generateName(); + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GOODRA ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.IRON_HANDS ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.CRESSELIA, Species.ENAMORUS ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + if (p.species.speciesId === Species.ENAMORUS) { + p.formIndex = 1; // Therian + p.generateName(); + } + p.pokeball = PokeballType.MASTER_BALL; + })), + [TrainerType.MARLEY]: new TrainerConfig(++t).setName("Marley").initForStatTrainer([], false) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ARCANINE ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 3); + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CINDERACE, Species.INTELEON ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.GREAT_BALL; + p.formIndex = 1; // Gmax + p.generateName(); + })) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.AERODACTYL ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.formIndex = 1; // Mega + p.generateName(); + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.DRAGAPULT ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.IRON_BUNDLE ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.REGIELEKI ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })), + [TrainerType.MIRA]: new TrainerConfig(++t).setName("Mira").initForStatTrainer([], false) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ALAKAZAM ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + p.formIndex = 1; + p.pokeball = PokeballType.ULTRA_BALL; + p.generateName(); + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.GENGAR, Species.HATTERENE ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.GREAT_BALL; + p.formIndex = p.species.speciesId === Species.GENGAR ? 2 : 1; // Gmax + p.generateName(); + })) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.FLUTTER_MANE ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.HYDREIGON ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.MAGNEZONE ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.LATIOS, Species.LATIAS ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })), + [TrainerType.RILEY]: new TrainerConfig(++t).setName("Riley").initForStatTrainer([], true) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LUCARIO ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + p.formIndex = 1; + p.pokeball = PokeballType.ULTRA_BALL; + p.generateName(); + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.RILLABOOM, Species.CENTISKORCH ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.GREAT_BALL; + p.formIndex = 1; // Gmax + p.generateName(); + })) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.TYRANITAR ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.ROARING_MOON ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.URSALUNA ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.REGIGIGAS, Species.LANDORUS ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + if (p.species.speciesId === Species.LANDORUS) { + p.formIndex = 1; // Therian + p.generateName(); + } + p.pokeball = PokeballType.MASTER_BALL; + })), }; diff --git a/src/enums/mystery-encounter-type.ts b/src/enums/mystery-encounter-type.ts index 95283e63b36..3bb204ab9d8 100644 --- a/src/enums/mystery-encounter-type.ts +++ b/src/enums/mystery-encounter-type.ts @@ -15,5 +15,6 @@ export enum MysteryEncounterType { POKEMON_SALESMAN, OFFER_YOU_CANT_REFUSE, DELIBIRDY, - ABSOLUTE_AVARICE + ABSOLUTE_AVARICE, + A_TRAINERS_TEST } diff --git a/src/enums/trainer-type.ts b/src/enums/trainer-type.ts index 6bd8f567acb..0d3a0771604 100644 --- a/src/enums/trainer-type.ts +++ b/src/enums/trainer-type.ts @@ -70,6 +70,11 @@ export enum TrainerType { GHETSIS_2, LYSANDRE, LYSANDRE_2, + BUCK, + CHERYL, + MARLEY, + MIRA, + RILEY, BROCK = 200, MISTY, diff --git a/src/field/mystery-encounter-intro.ts b/src/field/mystery-encounter-intro.ts index 467d44c23cd..7055d29d45c 100644 --- a/src/field/mystery-encounter-intro.ts +++ b/src/field/mystery-encounter-intro.ts @@ -1,10 +1,11 @@ import { GameObjects } from "phaser"; import BattleScene from "../battle-scene"; import IMysteryEncounter from "../data/mystery-encounters/mystery-encounter"; +import { Species } from "#enums/species"; +import { isNullOrUndefined } from "#app/utils"; +import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; type KnownFileRoot = - | "trainer" - | "pokemon" | "arenas" | "battle_anims" | "cg" @@ -33,6 +34,8 @@ export class MysteryEncounterSpriteConfig { spriteKey: string; /** Refer to [/public/images](../../public/images) directorty for all folder names */ fileRoot: KnownFileRoot & string | string; + /** Optional replacement for `spriteKey`/`fileRoot`. Just know this defaults to male/genderless, form 0, no shiny */ + species?: Species; /** Enable shadow. Defaults to `false` */ hasShadow?: boolean = false; /** Disable animation. Defaults to `false` */ @@ -69,15 +72,26 @@ export class MysteryEncounterSpriteConfig { export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Container { public encounter: IMysteryEncounter; public spriteConfigs: MysteryEncounterSpriteConfig[]; + public enterFromRight: boolean; constructor(scene: BattleScene, encounter: IMysteryEncounter) { super(scene, -72, 76); this.encounter = encounter; + this.enterFromRight = encounter.enterIntroVisualsFromRight ?? false; // Shallow copy configs to allow visual config updates at runtime without dirtying master copy of Encounter this.spriteConfigs = encounter.spriteConfigs.map(config => { - return { + const result = { ...config }; + + if (!isNullOrUndefined(result.species)) { + const keys = getSpriteKeysFromSpecies(result.species); + result.spriteKey = keys.spriteKey; + result.fileRoot = keys.fileRoot; + result.isPokemon = true; + } + + return result; }); if (!this.spriteConfigs) { return; @@ -90,9 +104,10 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con return ret; }; - const getItemSprite = (spriteKey: string) => { + const getItemSprite = (spriteKey: string, hasShadow?: boolean, yShadow?: number) => { const icon = this.scene.add.sprite(-19, 2, "items", spriteKey); icon.setOrigin(0.5, 1); + icon.setPipeline(this.scene.spritePipeline, { tone: [0.0, 0.0, 0.0, 0.0], hasShadow: !!hasShadow, yShadowOffset: yShadow ?? 0 }); return icon; }; @@ -114,7 +129,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con sprite = getSprite(spriteKey, hasShadow, yShadow); tintSprite = getSprite(spriteKey); } else { - sprite = getItemSprite(spriteKey); + sprite = getItemSprite(spriteKey, hasShadow, yShadow); tintSprite = getItemSprite(spriteKey); } diff --git a/src/locales/en/dialogue.ts b/src/locales/en/dialogue.ts index dda8891b788..50dee033782 100644 --- a/src/locales/en/dialogue.ts +++ b/src/locales/en/dialogue.ts @@ -566,6 +566,67 @@ export const PGMdialogue: DialogueTranslationEntries = { 1: "Fools with no vision will continue to befoul this beautiful world." } }, + "stat_trainer_buck": { + "encounter": { + 1: "...I'm telling you right now. I'm seriously tough. Act surprised!", + 2: "I can feel my Pokémon shivering inside their Pokéballs!" + }, + "victory": { + 1: "Heeheehee!\nSo hot, you!" + }, + "defeat": { + 1: "Whoa! You're all out of gas, I guess." + } + }, + "stat_trainer_cheryl": { + "encounter": { + 1: "My Pokémon have been itching for a battle.", + 2: "I should warn you, my Pokémon can be quite rambunctious." + }, + "victory": { + 1: "Striking the right balance of offense and defense... It's not easy to do." + }, + "defeat": { + 1: "Do your Pokémon need any healing?" + } + }, + "stat_trainer_marley": { + "encounter": { + 1: "... OK.\nI'll do my best.", + 2: "... OK.\nI... won't lose...!" + }, + "victory": { + 1: "... Awww." + }, + "defeat": { + 1: "... Goodbye." + } + }, + "stat_trainer_mira": { + "encounter": { + 1: "You will be shocked by Mira!", + 2: "Mira will show you that Mira doesn't get lost anymore!" + }, + "victory": { + 1: "Mira wonders if she can get very far in this land." + }, + "defeat": { + 1: "Mira knew she would win!" + } + }, + "stat_trainer_riley": { + "encounter": { + 1: "Battling is our way of greeting!", + 2: "We're pulling out all the stops to put your Pokémon down.", + }, + "victory": { + 1: `At times we battle, and sometimes we team up... + $It's great how Trainers can interact.` + }, + "defeat": { + 1: "You put up quite the display.\nBetter luck next time." + } + }, "brock": { "encounter": { 1: "My expertise on Rock-type Pokémon will take you down! Come on!", diff --git a/src/locales/en/trainers.ts b/src/locales/en/trainers.ts index b59cfdc4fda..0581a6698de 100644 --- a/src/locales/en/trainers.ts +++ b/src/locales/en/trainers.ts @@ -270,6 +270,11 @@ export const trainerNames: SimpleTranslationEntries = { "cyrus": "Cyrus", "ghetsis": "Ghetsis", "lysandre": "Lysandre", + "buck": "Buck", + "cheryl": "Cheryl", + "marley": "Marley", + "mira": "Mira", + "riley": "Riley", // Double Names "blue_red_double": "Blue & Red", diff --git a/src/overrides.ts b/src/overrides.ts index 1196797fac0..ff833564899 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -127,9 +127,9 @@ class DefaultOverrides { // ------------------------- // 1 to 256, set to null to ignore - readonly MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = null; + readonly MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = 256; readonly MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null; - readonly MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = null; + readonly MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.A_TRAINERS_TEST; // ------------------------- // MODIFIER / ITEM OVERRIDES diff --git a/src/phases.ts b/src/phases.ts index 7f2933a738a..b0bfc739ae8 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1002,8 +1002,8 @@ export class EncounterPhase extends BattlePhase { const enemyField = this.scene.getEnemyField(); this.scene.tweens.add({ - targets: [this.scene.arenaEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.currentBattle?.mysteryEncounter?.introVisuals, this.scene.arenaPlayer, this.scene.trainer].flat(), - x: (_target, _key, value, fieldIndex: integer) => fieldIndex < 3 + (enemyField.length) ? value + 300 : value - 300, + targets: [this.scene.arenaEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.arenaPlayer, this.scene.trainer].flat(), + x: (_target, _key, value, fieldIndex: integer) => fieldIndex < 2 + (enemyField.length) ? value + 300 : value - 300, duration: 2000, onComplete: () => { if (!this.tryOverrideForBattleSpec()) { @@ -1011,6 +1011,19 @@ export class EncounterPhase extends BattlePhase { } } }); + + const encounterIntroVisuals = this.scene.currentBattle?.mysteryEncounter?.introVisuals; + if (encounterIntroVisuals) { + const enterFromRight = encounterIntroVisuals.enterFromRight; + if (enterFromRight) { + encounterIntroVisuals.x += 500; + } + this.scene.tweens.add({ + targets: encounterIntroVisuals, + x: enterFromRight ? "-=200" : "+=300", + duration: 2000 + }); + } } getEncounterMessage(): string { @@ -1106,8 +1119,6 @@ export class EncounterPhase extends BattlePhase { } const doEncounter = () => { - this.scene.playBgm(undefined); - const doShowEncounterOptions = () => { this.scene.ui.clearText(); this.scene.ui.getMessageHandler().hideNameText(); @@ -1264,7 +1275,17 @@ export class NextEncounterPhase extends EncounterPhase { } const nextEncounterVisuals = this.scene.currentBattle?.mysteryEncounter?.introVisuals; if (nextEncounterVisuals) { - moveTargets.push(nextEncounterVisuals); + const enterFromRight = nextEncounterVisuals.enterFromRight; + if (enterFromRight) { + nextEncounterVisuals.x += 500; + this.scene.tweens.add({ + targets: nextEncounterVisuals, + x: "-=200", + duration: 2000 + }); + } else { + moveTargets.push(nextEncounterVisuals); + } } this.scene.tweens.add({ targets: moveTargets.flat(),