diff --git a/.gitignore b/.gitignore index 0ae49fe9e1c3..c22d0b2ce4c1 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,5 @@ coverage # Local Documentation /typedoc -/dependency-graph.svg \ No newline at end of file +/dependency-graph.svg +/.vs diff --git a/README.md b/README.md index ac4ed05b0ae1..ade4adc2c592 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,7 @@ Check out [Github Issues](https://github.com/pagefaultgames/pokerogue/issues) to - mangalos810 - Involuntary-Twitch - selstar + - koda_want_to_sleep ### 🎨 Move Animations - Pokémon Reborn diff --git a/public/images/items.json b/public/images/items.json index 7f8eaf31e0bb..91d9ed7c65ca 100644 --- a/public/images/items.json +++ b/public/images/items.json @@ -4,8 +4,8 @@ "image": "items.png", "format": "RGBA8888", "size": { - "w": 415, - "h": 415 + "w": 423, + "h": 423 }, "scale": 1, "frames": [ @@ -72,6 +72,48 @@ "h": 28 } }, + { + "filename": "ribbon_gen4", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 30, + "h": 28 + }, + "frame": { + "x": 29, + "y": 27, + "w": 30, + "h": 28 + } + }, + { + "filename": "ribbon_gen2", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 2, + "y": 2, + "w": 28, + "h": 28 + }, + "frame": { + "x": 0, + "y": 58, + "w": 28, + "h": 28 + } + }, { "filename": "bronze_ribbon", "rotated": false, @@ -87,8 +129,8 @@ "h": 31 }, "frame": { - "x": 29, - "y": 27, + "x": 0, + "y": 86, "w": 22, "h": 31 } @@ -109,7 +151,7 @@ }, "frame": { "x": 0, - "y": 58, + "y": 117, "w": 22, "h": 31 } @@ -151,7 +193,7 @@ }, "frame": { "x": 0, - "y": 89, + "y": 148, "w": 22, "h": 31 } @@ -171,8 +213,8 @@ "h": 31 }, "frame": { - "x": 22, - "y": 58, + "x": 0, + "y": 179, "w": 22, "h": 31 } @@ -193,11 +235,74 @@ }, "frame": { "x": 0, - "y": 120, + "y": 210, "w": 22, "h": 31 } }, + { + "filename": "ribbon_gen3", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 22, + "h": 29 + }, + "frame": { + "x": 0, + "y": 241, + "w": 22, + "h": 29 + } + }, + { + "filename": "ribbon_gen7", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 22, + "h": 29 + }, + "frame": { + "x": 0, + "y": 270, + "w": 22, + "h": 29 + } + }, + { + "filename": "ribbon_gen9", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 22, + "h": 29 + }, + "frame": { + "x": 0, + "y": 299, + "w": 22, + "h": 29 + } + }, { "filename": "cornerstone_mask", "rotated": false, @@ -219,6 +324,69 @@ "h": 26 } }, + { + "filename": "ribbon_gen1", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 22, + "h": 28 + }, + "frame": { + "x": 0, + "y": 328, + "w": 22, + "h": 28 + } + }, + { + "filename": "ribbon_gen5", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 22, + "h": 28 + }, + "frame": { + "x": 0, + "y": 356, + "w": 22, + "h": 28 + } + }, + { + "filename": "ribbon_gen6", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 22, + "h": 28 + }, + "frame": { + "x": 0, + "y": 384, + "w": 22, + "h": 28 + } + }, { "filename": "ability_charm", "rotated": false, @@ -388,7 +556,7 @@ } }, { - "filename": "exp_charm", + "filename": "chipped_pot", "rotated": false, "trimmed": true, "sourceSize": { @@ -396,20 +564,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 17, - "h": 31 + "x": 3, + "y": 6, + "w": 26, + "h": 20 }, "frame": { - "x": 22, - "y": 89, - "w": 17, - "h": 31 + "x": 330, + "y": 0, + "w": 26, + "h": 20 } }, { - "filename": "golden_exp_charm", + "filename": "cracked_pot", "rotated": false, "trimmed": true, "sourceSize": { @@ -417,20 +585,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 17, - "h": 31 + "x": 3, + "y": 6, + "w": 26, + "h": 20 }, "frame": { - "x": 0, - "y": 151, - "w": 17, - "h": 31 + "x": 356, + "y": 0, + "w": 26, + "h": 20 } }, { - "filename": "super_exp_charm", + "filename": "legend_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -438,20 +606,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 17, - "h": 31 + "x": 3, + "y": 6, + "w": 25, + "h": 20 }, "frame": { - "x": 22, - "y": 120, - "w": 17, - "h": 31 + "x": 382, + "y": 0, + "w": 25, + "h": 20 } }, { - "filename": "black_augurite", + "filename": "calcium", "rotated": false, "trimmed": true, "sourceSize": { @@ -459,20 +627,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 3, - "w": 22, - "h": 25 + "x": 8, + "y": 4, + "w": 16, + "h": 24 }, "frame": { - "x": 17, - "y": 151, - "w": 22, - "h": 25 + "x": 407, + "y": 0, + "w": 16, + "h": 24 } }, { - "filename": "prison_bottle", + "filename": "relic_gold", "rotated": false, "trimmed": true, "sourceSize": { @@ -480,20 +648,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 17, - "h": 30 + "x": 9, + "y": 11, + "w": 15, + "h": 11 }, "frame": { "x": 0, - "y": 182, - "w": 17, - "h": 30 + "y": 412, + "w": 15, + "h": 11 } }, { - "filename": "big_root", + "filename": "exp_charm", "rotated": false, "trimmed": true, "sourceSize": { @@ -501,20 +669,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 4, - "w": 23, - "h": 24 + "x": 7, + "y": 1, + "w": 17, + "h": 31 }, "frame": { - "x": 17, - "y": 176, - "w": 23, - "h": 24 + "x": 22, + "y": 86, + "w": 17, + "h": 31 } }, { - "filename": "chipped_pot", + "filename": "golden_exp_charm", "rotated": false, "trimmed": true, "sourceSize": { @@ -522,20 +690,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 3, - "y": 6, - "w": 26, - "h": 20 + "x": 7, + "y": 1, + "w": 17, + "h": 31 }, "frame": { - "x": 330, - "y": 0, - "w": 26, - "h": 20 + "x": 22, + "y": 117, + "w": 17, + "h": 31 } }, { - "filename": "cracked_pot", + "filename": "super_exp_charm", "rotated": false, "trimmed": true, "sourceSize": { @@ -543,20 +711,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 3, - "y": 6, - "w": 26, - "h": 20 + "x": 7, + "y": 1, + "w": 17, + "h": 31 }, "frame": { - "x": 356, - "y": 0, - "w": 26, - "h": 20 + "x": 22, + "y": 148, + "w": 17, + "h": 31 } }, { - "filename": "legend_plate", + "filename": "prison_bottle", "rotated": false, "trimmed": true, "sourceSize": { @@ -564,20 +732,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 3, - "y": 6, - "w": 25, - "h": 20 + "x": 7, + "y": 1, + "w": 17, + "h": 30 }, "frame": { - "x": 382, - "y": 0, - "w": 25, - "h": 20 + "x": 22, + "y": 179, + "w": 17, + "h": 30 } }, { - "filename": "blank_plate", + "filename": "ribbon_gen8", "rotated": false, "trimmed": true, "sourceSize": { @@ -585,20 +753,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 4, - "w": 24, - "h": 24 + "x": 5, + "y": 2, + "w": 22, + "h": 28 }, "frame": { - "x": 0, - "y": 212, - "w": 24, - "h": 24 + "x": 22, + "y": 209, + "w": 22, + "h": 28 } }, { - "filename": "choice_scarf", + "filename": "black_augurite", "rotated": false, "trimmed": true, "sourceSize": { @@ -606,20 +774,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 4, - "w": 24, - "h": 24 + "x": 5, + "y": 3, + "w": 22, + "h": 25 }, "frame": { - "x": 0, - "y": 236, - "w": 24, - "h": 24 + "x": 22, + "y": 237, + "w": 22, + "h": 25 } }, { - "filename": "draco_plate", + "filename": "big_root", "rotated": false, "trimmed": true, "sourceSize": { @@ -629,18 +797,18 @@ "spriteSourceSize": { "x": 4, "y": 4, - "w": 24, + "w": 23, "h": 24 }, "frame": { - "x": 0, - "y": 260, - "w": 24, + "x": 22, + "y": 262, + "w": 23, "h": 24 } }, { - "filename": "dread_plate", + "filename": "blank_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -654,14 +822,14 @@ "h": 24 }, "frame": { - "x": 0, - "y": 284, + "x": 22, + "y": 286, "w": 24, "h": 24 } }, { - "filename": "earth_plate", + "filename": "choice_scarf", "rotated": false, "trimmed": true, "sourceSize": { @@ -675,14 +843,14 @@ "h": 24 }, "frame": { - "x": 0, - "y": 308, + "x": 22, + "y": 310, "w": 24, "h": 24 } }, { - "filename": "fist_plate", + "filename": "draco_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -696,14 +864,14 @@ "h": 24 }, "frame": { - "x": 0, - "y": 332, + "x": 22, + "y": 334, "w": 24, "h": 24 } }, { - "filename": "flame_plate", + "filename": "dread_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -717,14 +885,14 @@ "h": 24 }, "frame": { - "x": 0, - "y": 356, + "x": 22, + "y": 358, "w": 24, "h": 24 } }, { - "filename": "focus_band", + "filename": "earth_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -738,14 +906,14 @@ "h": 24 }, "frame": { - "x": 0, - "y": 380, + "x": 22, + "y": 382, "w": 24, "h": 24 } }, { - "filename": "relic_gold", + "filename": "black_glasses", "rotated": false, "trimmed": true, "sourceSize": { @@ -753,20 +921,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 15, - "h": 11 + "x": 4, + "y": 8, + "w": 23, + "h": 17 }, "frame": { - "x": 0, - "y": 404, - "w": 15, - "h": 11 + "x": 22, + "y": 406, + "w": 23, + "h": 17 } }, { - "filename": "calcium", + "filename": "burn_drive", "rotated": false, "trimmed": true, "sourceSize": { @@ -774,20 +942,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 + "x": 4, + "y": 8, + "w": 23, + "h": 17 }, "frame": { - "x": 51, - "y": 27, - "w": 16, - "h": 24 + "x": 45, + "y": 406, + "w": 23, + "h": 17 } }, { - "filename": "golden_punch", + "filename": "ability_capsule", "rotated": false, "trimmed": true, "sourceSize": { @@ -796,19 +964,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, + "y": 9, "w": 24, - "h": 24 + "h": 14 }, "frame": { - "x": 67, - "y": 26, + "x": 135, + "y": 22, "w": 24, - "h": 24 + "h": 14 } }, { - "filename": "gracidea", + "filename": "choice_specs", "rotated": false, "trimmed": true, "sourceSize": { @@ -817,19 +985,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, + "y": 8, "w": 24, - "h": 24 + "h": 18 }, "frame": { - "x": 91, - "y": 26, + "x": 29, + "y": 55, "w": 24, - "h": 24 + "h": 18 } }, { - "filename": "catching_charm", + "filename": "carbos", "rotated": false, "trimmed": true, "sourceSize": { @@ -837,20 +1005,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 8, "y": 4, - "w": 21, + "w": 16, "h": 24 }, "frame": { - "x": 115, - "y": 26, - "w": 21, + "x": 59, + "y": 27, + "w": 16, "h": 24 } }, { - "filename": "grip_claw", + "filename": "fist_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -864,14 +1032,14 @@ "h": 24 }, "frame": { - "x": 136, - "y": 22, + "x": 75, + "y": 26, "w": 24, "h": 24 } }, { - "filename": "carbos", + "filename": "flame_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -879,20 +1047,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, + "x": 4, "y": 4, - "w": 16, + "w": 24, "h": 24 }, "frame": { - "x": 44, - "y": 58, - "w": 16, + "x": 99, + "y": 26, + "w": 24, "h": 24 } }, { - "filename": "elixir", + "filename": "revive", "rotated": false, "trimmed": true, "sourceSize": { @@ -900,20 +1068,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 18, - "h": 24 + "x": 10, + "y": 8, + "w": 12, + "h": 17 }, "frame": { - "x": 39, - "y": 89, - "w": 18, - "h": 24 + "x": 123, + "y": 26, + "w": 12, + "h": 17 } }, { - "filename": "ether", + "filename": "clefairy_doll", "rotated": false, "trimmed": true, "sourceSize": { @@ -921,20 +1089,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 18, - "h": 24 + "x": 4, + "y": 5, + "w": 24, + "h": 23 }, "frame": { - "x": 39, - "y": 113, - "w": 18, - "h": 24 + "x": 135, + "y": 36, + "w": 24, + "h": 23 } }, { - "filename": "full_restore", + "filename": "catching_charm", "rotated": false, "trimmed": true, "sourceSize": { @@ -942,20 +1110,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, + "x": 5, "y": 4, - "w": 18, + "w": 21, "h": 24 }, "frame": { - "x": 39, - "y": 137, - "w": 18, + "x": 159, + "y": 22, + "w": 21, "h": 24 } }, { - "filename": "silver_powder", + "filename": "focus_band", "rotated": false, "trimmed": true, "sourceSize": { @@ -964,19 +1132,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 11, + "y": 4, "w": 24, - "h": 15 + "h": 24 }, "frame": { - "x": 39, - "y": 161, + "x": 180, + "y": 21, "w": 24, - "h": 15 + "h": 24 } }, { - "filename": "icicle_plate", + "filename": "golden_punch", "rotated": false, "trimmed": true, "sourceSize": { @@ -990,14 +1158,14 @@ "h": 24 }, "frame": { - "x": 40, - "y": 176, + "x": 204, + "y": 21, "w": 24, "h": 24 } }, { - "filename": "insect_plate", + "filename": "gracidea", "rotated": false, "trimmed": true, "sourceSize": { @@ -1011,14 +1179,14 @@ "h": 24 }, "frame": { - "x": 24, - "y": 200, - "w": 24, + "x": 228, + "y": 21, + "w": 24, "h": 24 } }, { - "filename": "iron_plate", + "filename": "grip_claw", "rotated": false, "trimmed": true, "sourceSize": { @@ -1032,14 +1200,14 @@ "h": 24 }, "frame": { - "x": 24, - "y": 224, + "x": 252, + "y": 21, "w": 24, "h": 24 } }, { - "filename": "lucky_punch", + "filename": "icicle_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1053,14 +1221,14 @@ "h": 24 }, "frame": { - "x": 24, - "y": 248, + "x": 276, + "y": 21, "w": 24, "h": 24 } }, { - "filename": "lucky_punch_great", + "filename": "insect_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1074,14 +1242,14 @@ "h": 24 }, "frame": { - "x": 24, - "y": 272, + "x": 300, + "y": 21, "w": 24, "h": 24 } }, { - "filename": "lucky_punch_master", + "filename": "adamant_crystal", "rotated": false, "trimmed": true, "sourceSize": { @@ -1090,19 +1258,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, - "w": 24, - "h": 24 + "y": 6, + "w": 23, + "h": 21 }, "frame": { - "x": 24, - "y": 296, - "w": 24, - "h": 24 + "x": 159, + "y": 46, + "w": 23, + "h": 21 } }, { - "filename": "lucky_punch_ultra", + "filename": "coin_case", "rotated": false, "trimmed": true, "sourceSize": { @@ -1111,19 +1279,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, + "y": 5, "w": 24, - "h": 24 + "h": 23 }, "frame": { - "x": 24, - "y": 320, + "x": 182, + "y": 45, "w": 24, - "h": 24 + "h": 23 } }, { - "filename": "lustrous_globe", + "filename": "expert_belt", "rotated": false, "trimmed": true, "sourceSize": { @@ -1134,17 +1302,17 @@ "x": 4, "y": 4, "w": 24, - "h": 24 + "h": 23 }, "frame": { - "x": 24, - "y": 344, + "x": 206, + "y": 45, "w": 24, - "h": 24 + "h": 23 } }, { - "filename": "meadow_plate", + "filename": "hearthflame_mask", "rotated": false, "trimmed": true, "sourceSize": { @@ -1155,17 +1323,17 @@ "x": 4, "y": 4, "w": 24, - "h": 24 + "h": 23 }, "frame": { - "x": 24, - "y": 368, + "x": 230, + "y": 45, "w": 24, - "h": 24 + "h": 23 } }, { - "filename": "clefairy_doll", + "filename": "iron_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1174,19 +1342,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 5, + "y": 4, "w": 24, - "h": 23 + "h": 24 }, "frame": { - "x": 24, - "y": 392, + "x": 254, + "y": 45, "w": 24, - "h": 23 + "h": 24 } }, { - "filename": "hp_up", + "filename": "lucky_punch", "rotated": false, "trimmed": true, "sourceSize": { @@ -1194,20 +1362,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, + "x": 4, "y": 4, - "w": 16, + "w": 24, "h": 24 }, "frame": { - "x": 48, - "y": 200, - "w": 16, + "x": 278, + "y": 45, + "w": 24, "h": 24 } }, { - "filename": "iron", + "filename": "kings_rock", "rotated": false, "trimmed": true, "sourceSize": { @@ -1215,20 +1383,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, + "x": 5, "y": 4, - "w": 16, + "w": 23, "h": 24 }, "frame": { - "x": 48, - "y": 224, - "w": 16, + "x": 302, + "y": 45, + "w": 23, "h": 24 } }, { - "filename": "kings_rock", + "filename": "elixir", "rotated": false, "trimmed": true, "sourceSize": { @@ -1236,20 +1404,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 7, "y": 4, - "w": 23, + "w": 18, "h": 24 }, "frame": { - "x": 48, - "y": 248, - "w": 23, + "x": 324, + "y": 21, + "w": 18, "h": 24 } }, { - "filename": "mind_plate", + "filename": "lucky_punch_great", "rotated": false, "trimmed": true, "sourceSize": { @@ -1263,14 +1431,14 @@ "h": 24 }, "frame": { - "x": 48, - "y": 272, + "x": 342, + "y": 20, "w": 24, "h": 24 } }, { - "filename": "muscle_band", + "filename": "lucky_punch_master", "rotated": false, "trimmed": true, "sourceSize": { @@ -1284,14 +1452,14 @@ "h": 24 }, "frame": { - "x": 48, - "y": 296, + "x": 366, + "y": 20, "w": 24, "h": 24 } }, { - "filename": "pixie_plate", + "filename": "lure", "rotated": false, "trimmed": true, "sourceSize": { @@ -1299,20 +1467,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, + "x": 8, "y": 4, - "w": 24, + "w": 17, "h": 24 }, "frame": { - "x": 48, - "y": 320, - "w": 24, + "x": 390, + "y": 20, + "w": 17, "h": 24 } }, { - "filename": "salac_berry", + "filename": "hp_up", "rotated": false, "trimmed": true, "sourceSize": { @@ -1320,20 +1488,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, + "x": 8, "y": 4, - "w": 24, + "w": 16, "h": 24 }, "frame": { - "x": 48, - "y": 344, - "w": 24, + "x": 407, + "y": 24, + "w": 16, "h": 24 } }, { - "filename": "scanner", + "filename": "ether", "rotated": false, "trimmed": true, "sourceSize": { @@ -1341,20 +1509,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, + "x": 7, "y": 4, - "w": 24, + "w": 18, "h": 24 }, "frame": { - "x": 48, - "y": 368, - "w": 24, + "x": 325, + "y": 45, + "w": 18, "h": 24 } }, { - "filename": "coin_case", + "filename": "lucky_punch_ultra", "rotated": false, "trimmed": true, "sourceSize": { @@ -1363,19 +1531,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 5, + "y": 4, "w": 24, - "h": 23 + "h": 24 }, "frame": { - "x": 48, - "y": 392, + "x": 343, + "y": 44, "w": 24, - "h": 23 + "h": 24 } }, { - "filename": "ability_capsule", + "filename": "lustrous_globe", "rotated": false, "trimmed": true, "sourceSize": { @@ -1384,19 +1552,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 9, + "y": 4, "w": 24, - "h": 14 + "h": 24 }, "frame": { - "x": 136, - "y": 46, + "x": 367, + "y": 44, "w": 24, - "h": 14 + "h": 24 } }, { - "filename": "lure", + "filename": "iron", "rotated": false, "trimmed": true, "sourceSize": { @@ -1406,18 +1574,18 @@ "spriteSourceSize": { "x": 8, "y": 4, - "w": 17, + "w": 16, "h": 24 }, "frame": { - "x": 160, - "y": 22, - "w": 17, + "x": 391, + "y": 44, + "w": 16, "h": 24 } }, { - "filename": "silk_scarf", + "filename": "max_repel", "rotated": false, "trimmed": true, "sourceSize": { @@ -1425,20 +1593,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, + "x": 8, "y": 4, - "w": 24, + "w": 16, "h": 24 }, "frame": { - "x": 177, - "y": 21, - "w": 24, + "x": 407, + "y": 48, + "w": 16, "h": 24 } }, { - "filename": "sky_plate", + "filename": "dragon_scale", "rotated": false, "trimmed": true, "sourceSize": { @@ -1447,19 +1615,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, + "y": 8, "w": 24, - "h": 24 + "h": 18 }, "frame": { - "x": 201, - "y": 21, + "x": 75, + "y": 50, "w": 24, - "h": 24 + "h": 18 } }, { - "filename": "splash_plate", + "filename": "exp_balance", "rotated": false, "trimmed": true, "sourceSize": { @@ -1468,19 +1636,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, + "y": 5, "w": 24, - "h": 24 + "h": 22 }, "frame": { - "x": 225, - "y": 21, + "x": 99, + "y": 50, "w": 24, - "h": 24 + "h": 22 } }, { - "filename": "spooky_plate", + "filename": "black_belt", "rotated": false, "trimmed": true, "sourceSize": { @@ -1488,20 +1656,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, + "x": 5, "y": 4, - "w": 24, - "h": 24 + "w": 22, + "h": 23 }, "frame": { - "x": 249, - "y": 21, - "w": 24, - "h": 24 + "x": 53, + "y": 55, + "w": 22, + "h": 23 } }, { - "filename": "stone_plate", + "filename": "exp_share", "rotated": false, "trimmed": true, "sourceSize": { @@ -1510,19 +1678,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, + "y": 5, "w": 24, - "h": 24 + "h": 22 }, "frame": { - "x": 273, - "y": 21, + "x": 75, + "y": 68, "w": 24, - "h": 24 + "h": 22 } }, { - "filename": "sun_stone", + "filename": "icy_reins_of_unity", "rotated": false, "trimmed": true, "sourceSize": { @@ -1531,19 +1699,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, + "y": 7, "w": 24, - "h": 24 + "h": 20 }, "frame": { - "x": 297, - "y": 21, + "x": 99, + "y": 72, "w": 24, - "h": 24 + "h": 20 } }, { - "filename": "max_elixir", + "filename": "meadow_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1551,20 +1719,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, + "x": 4, "y": 4, - "w": 18, + "w": 24, "h": 24 }, "frame": { - "x": 321, - "y": 21, - "w": 18, + "x": 123, + "y": 59, + "w": 24, "h": 24 } }, { - "filename": "toxic_plate", + "filename": "leppa_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -1573,19 +1741,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, + "y": 5, "w": 24, - "h": 24 + "h": 23 }, "frame": { - "x": 339, - "y": 20, + "x": 123, + "y": 83, "w": 24, - "h": 24 + "h": 23 } }, { - "filename": "zap_plate", + "filename": "mind_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1599,14 +1767,14 @@ "h": 24 }, "frame": { - "x": 363, - "y": 20, + "x": 147, + "y": 67, "w": 24, "h": 24 } }, { - "filename": "max_revive", + "filename": "metal_powder", "rotated": false, "trimmed": true, "sourceSize": { @@ -1614,20 +1782,41 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 4, - "w": 22, - "h": 24 + "x": 4, + "y": 6, + "w": 24, + "h": 20 }, "frame": { - "x": 387, - "y": 20, - "w": 22, + "x": 147, + "y": 91, + "w": 24, + "h": 20 + } + }, + { + "filename": "muscle_band", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 171, + "y": 68, + "w": 24, "h": 24 } }, { - "filename": "adamant_crystal", + "filename": "pixie_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1636,19 +1825,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 6, - "w": 23, - "h": 21 + "y": 4, + "w": 24, + "h": 24 }, "frame": { - "x": 160, - "y": 46, - "w": 23, - "h": 21 + "x": 195, + "y": 68, + "w": 24, + "h": 24 } }, { - "filename": "exp_balance", + "filename": "salac_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -1657,19 +1846,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 5, + "y": 4, "w": 24, - "h": 22 + "h": 24 }, "frame": { - "x": 183, - "y": 45, + "x": 219, + "y": 68, "w": 24, - "h": 22 + "h": 24 } }, { - "filename": "exp_share", + "filename": "peat_block", "rotated": false, "trimmed": true, "sourceSize": { @@ -1683,14 +1872,14 @@ "h": 22 }, "frame": { - "x": 207, - "y": 45, + "x": 171, + "y": 92, "w": 24, "h": 22 } }, { - "filename": "expert_belt", + "filename": "scanner", "rotated": false, "trimmed": true, "sourceSize": { @@ -1701,17 +1890,17 @@ "x": 4, "y": 4, "w": 24, - "h": 23 + "h": 24 }, "frame": { - "x": 231, - "y": 45, + "x": 195, + "y": 92, "w": 24, - "h": 23 + "h": 24 } }, { - "filename": "hearthflame_mask", + "filename": "silk_scarf", "rotated": false, "trimmed": true, "sourceSize": { @@ -1722,17 +1911,17 @@ "x": 4, "y": 4, "w": 24, - "h": 23 + "h": 24 }, "frame": { - "x": 255, - "y": 45, + "x": 219, + "y": 92, "w": 24, - "h": 23 + "h": 24 } }, { - "filename": "leppa_berry", + "filename": "sky_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1741,19 +1930,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 5, + "y": 4, "w": 24, - "h": 23 + "h": 24 }, "frame": { - "x": 279, - "y": 45, + "x": 243, + "y": 69, "w": 24, - "h": 23 + "h": 24 } }, { - "filename": "scope_lens", + "filename": "splash_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1762,19 +1951,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 5, + "y": 4, "w": 24, - "h": 23 + "h": 24 }, "frame": { - "x": 303, - "y": 45, + "x": 267, + "y": 69, "w": 24, - "h": 23 + "h": 24 } }, { - "filename": "berry_pouch", + "filename": "spooky_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1783,19 +1972,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 5, - "w": 23, - "h": 23 + "y": 4, + "w": 24, + "h": 24 }, "frame": { - "x": 327, - "y": 45, - "w": 23, - "h": 23 + "x": 291, + "y": 69, + "w": 24, + "h": 24 } }, { - "filename": "reveal_glass", + "filename": "stone_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1805,18 +1994,18 @@ "spriteSourceSize": { "x": 4, "y": 4, - "w": 23, + "w": 24, "h": 24 }, "frame": { - "x": 350, - "y": 44, - "w": 23, + "x": 315, + "y": 69, + "w": 24, "h": 24 } }, { - "filename": "twisted_spoon", + "filename": "scope_lens", "rotated": false, "trimmed": true, "sourceSize": { @@ -1830,14 +2019,14 @@ "h": 23 }, "frame": { - "x": 373, - "y": 44, + "x": 243, + "y": 93, "w": 24, "h": 23 } }, { - "filename": "max_ether", + "filename": "sun_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -1845,20 +2034,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, + "x": 4, "y": 4, - "w": 18, + "w": 24, "h": 24 }, "frame": { - "x": 397, - "y": 44, - "w": 18, + "x": 267, + "y": 93, + "w": 24, "h": 24 } }, { - "filename": "choice_specs", + "filename": "toxic_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1867,19 +2056,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 8, + "y": 4, "w": 24, - "h": 18 + "h": 24 }, "frame": { - "x": 373, - "y": 67, + "x": 291, + "y": 93, "w": 24, - "h": 18 + "h": 24 } }, { - "filename": "max_potion", + "filename": "zap_plate", "rotated": false, "trimmed": true, "sourceSize": { @@ -1887,20 +2076,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, + "x": 4, "y": 4, - "w": 18, + "w": 24, "h": 24 }, "frame": { - "x": 397, - "y": 68, - "w": 18, + "x": 315, + "y": 93, + "w": 24, "h": 24 } }, { - "filename": "dragon_scale", + "filename": "full_restore", "rotated": false, "trimmed": true, "sourceSize": { @@ -1908,20 +2097,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 24, - "h": 18 + "x": 7, + "y": 4, + "w": 18, + "h": 24 }, "frame": { - "x": 67, - "y": 50, - "w": 24, - "h": 18 + "x": 339, + "y": 69, + "w": 18, + "h": 24 } }, { - "filename": "icy_reins_of_unity", + "filename": "reveal_glass", "rotated": false, "trimmed": true, "sourceSize": { @@ -1930,19 +2119,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 7, - "w": 24, - "h": 20 + "y": 4, + "w": 23, + "h": 24 }, "frame": { - "x": 91, - "y": 50, - "w": 24, - "h": 20 + "x": 357, + "y": 68, + "w": 23, + "h": 24 } }, { - "filename": "dragon_fang", + "filename": "twisted_spoon", "rotated": false, "trimmed": true, "sourceSize": { @@ -1950,20 +2139,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 4, "y": 5, - "w": 21, + "w": 24, "h": 23 }, "frame": { - "x": 115, - "y": 50, - "w": 21, + "x": 380, + "y": 68, + "w": 24, "h": 23 } }, { - "filename": "metal_powder", + "filename": "lock_capsule", "rotated": false, "trimmed": true, "sourceSize": { @@ -1971,20 +2160,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 24, - "h": 20 + "x": 7, + "y": 5, + "w": 19, + "h": 22 }, "frame": { - "x": 136, - "y": 60, - "w": 24, - "h": 20 + "x": 404, + "y": 72, + "w": 19, + "h": 22 } }, { - "filename": "peat_block", + "filename": "max_elixir", "rotated": false, "trimmed": true, "sourceSize": { @@ -1992,20 +2181,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 24, - "h": 22 + "x": 7, + "y": 4, + "w": 18, + "h": 24 }, "frame": { - "x": 160, - "y": 67, - "w": 24, - "h": 22 + "x": 339, + "y": 93, + "w": 18, + "h": 24 } }, { - "filename": "dynamax_band", + "filename": "berry_pouch", "rotated": false, "trimmed": true, "sourceSize": { @@ -2014,19 +2203,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, + "y": 5, "w": 23, "h": 23 }, "frame": { - "x": 184, - "y": 67, + "x": 357, + "y": 92, "w": 23, "h": 23 } }, { - "filename": "griseous_core", + "filename": "quick_powder", "rotated": false, "trimmed": true, "sourceSize": { @@ -2034,20 +2223,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 23, - "h": 23 + "x": 4, + "y": 6, + "w": 24, + "h": 20 }, "frame": { - "x": 207, - "y": 67, - "w": 23, - "h": 23 + "x": 380, + "y": 91, + "w": 24, + "h": 20 } }, { - "filename": "healing_charm", + "filename": "metal_coat", "rotated": false, "trimmed": true, "sourceSize": { @@ -2055,20 +2244,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 6, "y": 5, - "w": 23, + "w": 19, "h": 22 }, "frame": { - "x": 230, - "y": 68, - "w": 23, + "x": 404, + "y": 94, + "w": 19, "h": 22 } }, { - "filename": "leek", + "filename": "rusted_shield", "rotated": false, "trimmed": true, "sourceSize": { @@ -2077,19 +2266,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 5, - "w": 23, - "h": 23 + "y": 6, + "w": 24, + "h": 20 }, "frame": { - "x": 253, - "y": 68, - "w": 23, - "h": 23 + "x": 380, + "y": 111, + "w": 24, + "h": 20 } }, { - "filename": "rare_candy", + "filename": "quick_claw", "rotated": false, "trimmed": true, "sourceSize": { @@ -2097,20 +2286,41 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, + "x": 6, + "y": 6, + "w": 19, + "h": 21 + }, + "frame": { + "x": 404, + "y": 116, + "w": 19, + "h": 21 + } + }, + { + "filename": "amulet_coin", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, "y": 5, "w": 23, - "h": 23 + "h": 21 }, "frame": { - "x": 276, - "y": 68, + "x": 357, + "y": 115, "w": 23, - "h": 23 + "h": 21 } }, { - "filename": "rarer_candy", + "filename": "sacred_ash", "rotated": false, "trimmed": true, "sourceSize": { @@ -2119,19 +2329,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 5, - "w": 23, - "h": 23 + "y": 7, + "w": 24, + "h": 20 }, "frame": { - "x": 299, - "y": 68, - "w": 23, - "h": 23 + "x": 380, + "y": 131, + "w": 24, + "h": 20 } }, { - "filename": "black_belt", + "filename": "spell_tag", "rotated": false, "trimmed": true, "sourceSize": { @@ -2139,20 +2349,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 4, - "w": 22, - "h": 23 + "x": 7, + "y": 6, + "w": 19, + "h": 21 }, "frame": { - "x": 322, - "y": 68, - "w": 22, - "h": 23 + "x": 404, + "y": 137, + "w": 19, + "h": 21 } }, { - "filename": "bug_tera_shard", + "filename": "dynamax_band", "rotated": false, "trimmed": true, "sourceSize": { @@ -2160,20 +2370,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, + "x": 4, "y": 4, - "w": 22, + "w": 23, "h": 23 }, "frame": { - "x": 344, - "y": 68, - "w": 22, + "x": 39, + "y": 78, + "w": 23, "h": 23 } }, { - "filename": "quick_powder", + "filename": "griseous_core", "rotated": false, "trimmed": true, "sourceSize": { @@ -2181,20 +2391,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 24, - "h": 20 + "x": 5, + "y": 5, + "w": 23, + "h": 23 }, "frame": { - "x": 60, - "y": 68, - "w": 24, - "h": 20 + "x": 39, + "y": 101, + "w": 23, + "h": 23 } }, { - "filename": "dark_tera_shard", + "filename": "leek", "rotated": false, "trimmed": true, "sourceSize": { @@ -2202,20 +2412,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, + "x": 4, + "y": 5, + "w": 23, "h": 23 }, "frame": { - "x": 57, - "y": 88, - "w": 22, + "x": 39, + "y": 124, + "w": 23, "h": 23 } }, { - "filename": "dragon_tera_shard", + "filename": "max_revive", "rotated": false, "trimmed": true, "sourceSize": { @@ -2223,20 +2433,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, + "x": 5, "y": 4, "w": 22, - "h": 23 + "h": 24 }, "frame": { - "x": 57, - "y": 111, + "x": 39, + "y": 147, "w": 22, - "h": 23 + "h": 24 } }, { - "filename": "electric_tera_shard", + "filename": "bug_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -2250,14 +2460,14 @@ "h": 23 }, "frame": { - "x": 57, - "y": 134, + "x": 39, + "y": 171, "w": 22, "h": 23 } }, { - "filename": "rusted_shield", + "filename": "silver_powder", "rotated": false, "trimmed": true, "sourceSize": { @@ -2266,19 +2476,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 6, + "y": 11, "w": 24, - "h": 20 + "h": 15 }, "frame": { - "x": 84, - "y": 70, + "x": 39, + "y": 194, "w": 24, - "h": 20 + "h": 15 } }, { - "filename": "fairy_tera_shard", + "filename": "oval_charm", "rotated": false, "trimmed": true, "sourceSize": { @@ -2288,18 +2498,18 @@ "spriteSourceSize": { "x": 6, "y": 4, - "w": 22, - "h": 23 + "w": 21, + "h": 24 }, "frame": { - "x": 79, - "y": 90, - "w": 22, - "h": 23 + "x": 44, + "y": 209, + "w": 21, + "h": 24 } }, { - "filename": "fighting_tera_shard", + "filename": "shiny_charm", "rotated": false, "trimmed": true, "sourceSize": { @@ -2309,18 +2519,18 @@ "spriteSourceSize": { "x": 6, "y": 4, - "w": 22, - "h": 23 + "w": 21, + "h": 24 }, "frame": { - "x": 79, - "y": 113, - "w": 22, - "h": 23 + "x": 44, + "y": 233, + "w": 21, + "h": 24 } }, { - "filename": "amulet_coin", + "filename": "red_orb", "rotated": false, "trimmed": true, "sourceSize": { @@ -2329,19 +2539,19 @@ }, "spriteSourceSize": { "x": 6, - "y": 5, - "w": 23, - "h": 21 + "y": 4, + "w": 20, + "h": 24 }, "frame": { - "x": 79, - "y": 136, - "w": 23, - "h": 21 + "x": 45, + "y": 257, + "w": 20, + "h": 24 } }, { - "filename": "coupon", + "filename": "dark_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -2349,20 +2559,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 19 + "x": 6, + "y": 4, + "w": 22, + "h": 23 }, "frame": { - "x": 63, - "y": 157, - "w": 23, - "h": 19 + "x": 46, + "y": 281, + "w": 22, + "h": 23 } }, { - "filename": "fire_stone", + "filename": "dragon_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -2370,20 +2580,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, + "x": 6, + "y": 4, "w": 22, "h": 23 }, "frame": { - "x": 64, - "y": 176, + "x": 46, + "y": 304, "w": 22, "h": 23 } }, { - "filename": "fire_tera_shard", + "filename": "electric_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -2397,14 +2607,14 @@ "h": 23 }, "frame": { - "x": 64, - "y": 199, + "x": 46, + "y": 327, "w": 22, "h": 23 } }, { - "filename": "flying_tera_shard", + "filename": "fairy_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -2418,14 +2628,14 @@ "h": 23 }, "frame": { - "x": 64, - "y": 222, + "x": 46, + "y": 350, "w": 22, "h": 23 } }, { - "filename": "max_lure", + "filename": "fighting_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -2433,20 +2643,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, + "x": 6, "y": 4, - "w": 17, - "h": 24 + "w": 22, + "h": 23 }, "frame": { - "x": 86, - "y": 157, - "w": 17, - "h": 24 + "x": 46, + "y": 373, + "w": 22, + "h": 23 } }, { - "filename": "oval_charm", + "filename": "rare_candy", "rotated": false, "trimmed": true, "sourceSize": { @@ -2454,20 +2664,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 21, - "h": 24 + "x": 4, + "y": 5, + "w": 23, + "h": 23 }, "frame": { - "x": 86, - "y": 181, - "w": 21, - "h": 24 + "x": 62, + "y": 90, + "w": 23, + "h": 23 } }, { - "filename": "shiny_charm", + "filename": "rarer_candy", "rotated": false, "trimmed": true, "sourceSize": { @@ -2475,17 +2685,17 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 21, - "h": 24 + "x": 4, + "y": 5, + "w": 23, + "h": 23 }, "frame": { - "x": 86, - "y": 205, - "w": 21, - "h": 24 - } + "x": 62, + "y": 113, + "w": 23, + "h": 23 + } }, { "filename": "auspicious_armor", @@ -2502,14 +2712,14 @@ "h": 21 }, "frame": { - "x": 86, - "y": 229, + "x": 62, + "y": 136, "w": 23, "h": 21 } }, { - "filename": "full_heal", + "filename": "fire_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -2517,20 +2727,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 9, - "y": 4, - "w": 15, + "x": 5, + "y": 5, + "w": 22, "h": 23 }, "frame": { - "x": 71, - "y": 245, - "w": 15, + "x": 61, + "y": 157, + "w": 22, "h": 23 } }, { - "filename": "binding_band", + "filename": "fire_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -2538,20 +2748,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 23, - "h": 20 + "x": 6, + "y": 4, + "w": 22, + "h": 23 }, "frame": { - "x": 86, - "y": 250, - "w": 23, - "h": 20 + "x": 85, + "y": 92, + "w": 22, + "h": 23 } }, { - "filename": "sacred_ash", + "filename": "pp_max", "rotated": false, "trimmed": true, "sourceSize": { @@ -2559,20 +2769,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 24, - "h": 20 + "x": 8, + "y": 4, + "w": 16, + "h": 24 }, "frame": { - "x": 108, - "y": 73, - "w": 24, - "h": 20 + "x": 107, + "y": 92, + "w": 16, + "h": 24 } }, { - "filename": "focus_sash", + "filename": "flying_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -2580,20 +2790,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 6, "y": 4, "w": 22, "h": 23 }, "frame": { - "x": 101, - "y": 93, + "x": 85, + "y": 115, "w": 22, "h": 23 } }, { - "filename": "deep_sea_scale", + "filename": "binding_band", "rotated": false, "trimmed": true, "sourceSize": { @@ -2603,18 +2813,18 @@ "spriteSourceSize": { "x": 5, "y": 6, - "w": 22, + "w": 23, "h": 20 }, "frame": { - "x": 101, - "y": 116, - "w": 22, + "x": 85, + "y": 138, + "w": 23, "h": 20 } }, { - "filename": "deep_sea_tooth", + "filename": "healing_charm", "rotated": false, "trimmed": true, "sourceSize": { @@ -2623,61 +2833,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 6, - "w": 22, - "h": 21 - }, - "frame": { - "x": 102, - "y": 136, - "w": 22, - "h": 21 - } - }, - { - "filename": "red_orb", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 20, - "h": 24 - }, - "frame": { - "x": 103, - "y": 157, - "w": 20, - "h": 24 - } - }, - { - "filename": "max_repel", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 + "y": 5, + "w": 23, + "h": 22 }, "frame": { - "x": 107, - "y": 181, - "w": 16, - "h": 24 + "x": 83, + "y": 158, + "w": 23, + "h": 22 } }, { - "filename": "pp_max", + "filename": "berry_pot", "rotated": false, "trimmed": true, "sourceSize": { @@ -2685,20 +2853,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 + "x": 7, + "y": 5, + "w": 18, + "h": 22 }, "frame": { "x": 107, - "y": 205, - "w": 16, - "h": 24 + "y": 116, + "w": 18, + "h": 22 } }, { - "filename": "pp_up", + "filename": "focus_sash", "rotated": false, "trimmed": true, "sourceSize": { @@ -2706,20 +2874,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, + "x": 5, "y": 4, - "w": 16, - "h": 24 + "w": 22, + "h": 23 }, "frame": { - "x": 109, - "y": 229, - "w": 16, - "h": 24 + "x": 125, + "y": 106, + "w": 22, + "h": 23 } }, { - "filename": "apicot_berry", + "filename": "shadow_reins_of_unity", "rotated": false, "trimmed": true, "sourceSize": { @@ -2727,62 +2895,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 19, + "x": 4, + "y": 7, + "w": 24, "h": 20 }, "frame": { - "x": 109, - "y": 253, - "w": 19, + "x": 147, + "y": 111, + "w": 24, "h": 20 } }, { - "filename": "protein", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 123, - "y": 93, - "w": 16, - "h": 24 - } - }, - { - "filename": "lansat_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 4, - "w": 21, - "h": 23 - }, - "frame": { - "x": 139, - "y": 80, - "w": 21, - "h": 23 - } - }, - { - "filename": "shadow_reins_of_unity", + "filename": "soft_sand", "rotated": false, "trimmed": true, "sourceSize": { @@ -2796,14 +2922,14 @@ "h": 20 }, "frame": { - "x": 160, - "y": 89, + "x": 171, + "y": 114, "w": 24, "h": 20 } }, { - "filename": "soft_sand", + "filename": "coupon", "rotated": false, "trimmed": true, "sourceSize": { @@ -2813,18 +2939,18 @@ "spriteSourceSize": { "x": 4, "y": 7, - "w": 24, - "h": 20 + "w": 23, + "h": 19 }, "frame": { - "x": 184, - "y": 90, - "w": 24, - "h": 20 + "x": 195, + "y": 116, + "w": 23, + "h": 19 } }, { - "filename": "moon_stone", + "filename": "golden_mystic_ticket", "rotated": false, "trimmed": true, "sourceSize": { @@ -2833,19 +2959,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 6, + "y": 7, "w": 23, - "h": 21 + "h": 19 }, "frame": { - "x": 208, - "y": 90, + "x": 218, + "y": 116, "w": 23, - "h": 21 + "h": 19 } }, { - "filename": "blank_memory", + "filename": "moon_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -2853,16 +2979,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 4, + "y": 6, + "w": 23, + "h": 21 }, "frame": { - "x": 231, - "y": 90, - "w": 22, - "h": 22 + "x": 241, + "y": 116, + "w": 23, + "h": 21 } }, { @@ -2880,8 +3006,8 @@ "h": 21 }, "frame": { - "x": 253, - "y": 91, + "x": 264, + "y": 117, "w": 23, "h": 21 } @@ -2901,8 +3027,8 @@ "h": 21 }, "frame": { - "x": 276, - "y": 91, + "x": 287, + "y": 117, "w": 23, "h": 21 } @@ -2922,14 +3048,14 @@ "h": 22 }, "frame": { - "x": 299, - "y": 91, + "x": 310, + "y": 117, "w": 23, "h": 22 } }, { - "filename": "bug_memory", + "filename": "blank_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -2943,14 +3069,14 @@ "h": 22 }, "frame": { - "x": 322, - "y": 91, + "x": 333, + "y": 117, "w": 22, "h": 22 } }, { - "filename": "charcoal", + "filename": "apicot_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -2958,20 +3084,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 6, + "y": 6, + "w": 19, + "h": 20 }, "frame": { - "x": 344, - "y": 91, - "w": 22, - "h": 22 + "x": 108, + "y": 138, + "w": 19, + "h": 20 } }, { - "filename": "dusk_stone", + "filename": "bug_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -2979,20 +3105,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 21, - "h": 21 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 139, - "y": 103, - "w": 21, - "h": 21 + "x": 106, + "y": 158, + "w": 22, + "h": 22 } }, { - "filename": "mystery_egg", + "filename": "mystic_water", "rotated": false, "trimmed": true, "sourceSize": { @@ -3000,20 +3126,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 18 + "x": 6, + "y": 5, + "w": 20, + "h": 23 }, "frame": { - "x": 123, - "y": 117, - "w": 16, - "h": 18 + "x": 127, + "y": 129, + "w": 20, + "h": 23 } }, { - "filename": "black_glasses", + "filename": "wellspring_mask", "rotated": false, "trimmed": true, "sourceSize": { @@ -3022,19 +3148,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 8, + "y": 5, "w": 23, - "h": 17 + "h": 21 }, "frame": { - "x": 160, - "y": 109, + "x": 147, + "y": 131, "w": 23, - "h": 17 + "h": 21 } }, { - "filename": "burn_drive", + "filename": "mystic_ticket", "rotated": false, "trimmed": true, "sourceSize": { @@ -3043,15 +3169,15 @@ }, "spriteSourceSize": { "x": 4, - "y": 8, + "y": 7, "w": 23, - "h": 17 + "h": 19 }, "frame": { - "x": 183, - "y": 110, + "x": 170, + "y": 134, "w": 23, - "h": 17 + "h": 19 } }, { @@ -3069,14 +3195,14 @@ "h": 23 }, "frame": { - "x": 366, - "y": 85, + "x": 128, + "y": 152, "w": 22, "h": 23 } }, { - "filename": "chill_drive", + "filename": "hard_meteorite", "rotated": false, "trimmed": true, "sourceSize": { @@ -3084,20 +3210,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 23, - "h": 17 + "x": 7, + "y": 5, + "w": 20, + "h": 22 }, "frame": { - "x": 206, - "y": 111, - "w": 23, - "h": 17 + "x": 150, + "y": 152, + "w": 20, + "h": 22 } }, { - "filename": "douse_drive", + "filename": "charcoal", "rotated": false, "trimmed": true, "sourceSize": { @@ -3105,20 +3231,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 23, - "h": 17 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 229, - "y": 112, - "w": 23, - "h": 17 + "x": 170, + "y": 153, + "w": 22, + "h": 22 } }, { - "filename": "golden_mystic_ticket", + "filename": "pair_of_tickets", "rotated": false, "trimmed": true, "sourceSize": { @@ -3132,14 +3258,14 @@ "h": 19 }, "frame": { - "x": 252, - "y": 112, + "x": 193, + "y": 135, "w": 23, "h": 19 } }, { - "filename": "mystic_ticket", + "filename": "dark_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -3147,20 +3273,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 19 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 275, - "y": 112, - "w": 23, - "h": 19 + "x": 192, + "y": 154, + "w": 22, + "h": 22 } }, { - "filename": "pair_of_tickets", + "filename": "reviver_seed", "rotated": false, "trimmed": true, "sourceSize": { @@ -3168,20 +3294,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 7, + "x": 5, + "y": 8, "w": 23, - "h": 19 + "h": 20 }, "frame": { - "x": 298, - "y": 113, + "x": 216, + "y": 135, "w": 23, - "h": 19 + "h": 20 } }, { - "filename": "reviver_seed", + "filename": "deep_sea_tooth", "rotated": false, "trimmed": true, "sourceSize": { @@ -3190,19 +3316,40 @@ }, "spriteSourceSize": { "x": 5, - "y": 8, + "y": 6, + "w": 22, + "h": 21 + }, + "frame": { + "x": 214, + "y": 155, + "w": 22, + "h": 21 + } + }, + { + "filename": "relic_crown", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 7, "w": 23, - "h": 20 + "h": 18 }, "frame": { - "x": 321, - "y": 113, + "x": 239, + "y": 137, "w": 23, - "h": 20 + "h": 18 } }, { - "filename": "dark_memory", + "filename": "dire_hit", "rotated": false, "trimmed": true, "sourceSize": { @@ -3216,14 +3363,14 @@ "h": 22 }, "frame": { - "x": 344, - "y": 113, + "x": 236, + "y": 155, "w": 22, "h": 22 } }, { - "filename": "grass_tera_shard", + "filename": "chill_drive", "rotated": false, "trimmed": true, "sourceSize": { @@ -3231,20 +3378,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 + "x": 4, + "y": 8, + "w": 23, + "h": 17 }, "frame": { - "x": 366, - "y": 108, - "w": 22, - "h": 23 + "x": 262, + "y": 138, + "w": 23, + "h": 17 } }, { - "filename": "berry_pot", + "filename": "dna_splicers", "rotated": false, "trimmed": true, "sourceSize": { @@ -3252,20 +3399,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, + "x": 5, "y": 5, - "w": 18, + "w": 22, "h": 22 }, "frame": { - "x": 124, - "y": 135, - "w": 18, + "x": 258, + "y": 155, + "w": 22, "h": 22 } }, { - "filename": "ground_tera_shard", + "filename": "douse_drive", "rotated": false, "trimmed": true, "sourceSize": { @@ -3273,20 +3420,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 + "x": 4, + "y": 8, + "w": 23, + "h": 17 }, "frame": { - "x": 123, - "y": 157, - "w": 22, - "h": 23 + "x": 285, + "y": 138, + "w": 23, + "h": 17 } }, { - "filename": "ice_tera_shard", + "filename": "dragon_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -3294,20 +3441,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, + "x": 5, + "y": 5, "w": 22, - "h": 23 + "h": 22 }, "frame": { - "x": 123, - "y": 180, + "x": 280, + "y": 155, "w": 22, - "h": 23 + "h": 22 } }, { - "filename": "never_melt_ice", + "filename": "shell_bell", "rotated": false, "trimmed": true, "sourceSize": { @@ -3316,19 +3463,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 5, - "w": 22, - "h": 23 + "y": 7, + "w": 23, + "h": 20 }, "frame": { - "x": 123, - "y": 203, - "w": 22, - "h": 23 + "x": 308, + "y": 139, + "w": 23, + "h": 20 } }, { - "filename": "leaf_stone", + "filename": "deep_sea_scale", "rotated": false, "trimmed": true, "sourceSize": { @@ -3337,19 +3484,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 5, - "w": 21, - "h": 23 + "y": 6, + "w": 22, + "h": 20 }, "frame": { - "x": 125, - "y": 226, - "w": 21, - "h": 23 + "x": 331, + "y": 139, + "w": 22, + "h": 20 } }, { - "filename": "mystic_water", + "filename": "blunder_policy", "rotated": false, "trimmed": true, "sourceSize": { @@ -3357,41 +3504,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 20, - "h": 23 + "x": 5, + "y": 6, + "w": 22, + "h": 19 }, "frame": { - "x": 128, - "y": 249, - "w": 20, - "h": 23 - } - }, - { - "filename": "normal_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 388, - "y": 92, + "x": 302, + "y": 159, "w": 22, - "h": 23 + "h": 19 } }, { - "filename": "blunder_policy", + "filename": "dubious_disc", "rotated": false, "trimmed": true, "sourceSize": { @@ -3400,19 +3526,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 6, + "y": 7, "w": 22, "h": 19 }, "frame": { - "x": 388, - "y": 115, + "x": 324, + "y": 159, "w": 22, "h": 19 } }, { - "filename": "sachet", + "filename": "grass_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3422,18 +3548,18 @@ "spriteSourceSize": { "x": 6, "y": 4, - "w": 18, + "w": 22, "h": 23 }, "frame": { - "x": 142, - "y": 124, - "w": 18, + "x": 63, + "y": 180, + "w": 22, "h": 23 } }, { - "filename": "wellspring_mask", + "filename": "ground_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3441,20 +3567,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 23, - "h": 21 + "x": 6, + "y": 4, + "w": 22, + "h": 23 }, "frame": { - "x": 160, - "y": 126, - "w": 23, - "h": 21 + "x": 85, + "y": 180, + "w": 22, + "h": 23 } }, { - "filename": "shell_bell", + "filename": "dragon_fang", "rotated": false, "trimmed": true, "sourceSize": { @@ -3463,19 +3589,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 7, - "w": 23, - "h": 20 + "y": 5, + "w": 21, + "h": 23 }, "frame": { - "x": 183, - "y": 127, - "w": 23, - "h": 20 + "x": 107, + "y": 180, + "w": 21, + "h": 23 } }, { - "filename": "relic_crown", + "filename": "ice_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3483,20 +3609,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 18 + "x": 6, + "y": 4, + "w": 22, + "h": 23 }, "frame": { - "x": 206, - "y": 128, - "w": 23, - "h": 18 + "x": 128, + "y": 175, + "w": 22, + "h": 23 } }, { - "filename": "shock_drive", + "filename": "sitrus_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -3504,20 +3630,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 23, - "h": 17 + "x": 6, + "y": 5, + "w": 20, + "h": 22 }, "frame": { - "x": 229, - "y": 129, - "w": 23, - "h": 17 + "x": 150, + "y": 174, + "w": 20, + "h": 22 } }, { - "filename": "wise_glasses", + "filename": "electirizer", "rotated": false, "trimmed": true, "sourceSize": { @@ -3525,20 +3651,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 23, - "h": 17 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 252, - "y": 131, - "w": 23, - "h": 17 + "x": 170, + "y": 175, + "w": 22, + "h": 22 } }, { - "filename": "dire_hit", + "filename": "electric_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -3552,14 +3678,14 @@ "h": 22 }, "frame": { - "x": 275, - "y": 131, + "x": 192, + "y": 176, "w": 22, "h": 22 } }, { - "filename": "dna_splicers", + "filename": "enigma_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -3573,14 +3699,14 @@ "h": 22 }, "frame": { - "x": 297, - "y": 132, + "x": 214, + "y": 176, "w": 22, "h": 22 } }, { - "filename": "dragon_memory", + "filename": "fairy_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -3594,14 +3720,14 @@ "h": 22 }, "frame": { - "x": 319, - "y": 133, + "x": 236, + "y": 177, "w": 22, "h": 22 } }, { - "filename": "electirizer", + "filename": "fighting_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -3615,14 +3741,14 @@ "h": 22 }, "frame": { - "x": 341, - "y": 135, + "x": 258, + "y": 177, "w": 22, "h": 22 } }, { - "filename": "petaya_berry", + "filename": "fire_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -3633,17 +3759,17 @@ "x": 5, "y": 5, "w": 22, - "h": 23 + "h": 22 }, "frame": { - "x": 145, - "y": 147, + "x": 280, + "y": 177, "w": 22, - "h": 23 + "h": 22 } }, { - "filename": "poison_tera_shard", + "filename": "flying_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -3651,20 +3777,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, + "x": 5, + "y": 5, "w": 22, - "h": 23 + "h": 22 }, "frame": { - "x": 167, - "y": 147, + "x": 302, + "y": 178, "w": 22, - "h": 23 + "h": 22 } }, { - "filename": "psychic_tera_shard", + "filename": "ganlon_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -3672,20 +3798,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, + "x": 5, + "y": 5, "w": 22, - "h": 23 + "h": 22 }, "frame": { - "x": 145, - "y": 170, + "x": 324, + "y": 178, "w": 22, - "h": 23 + "h": 22 } }, { - "filename": "reaper_cloth", + "filename": "never_melt_ice", "rotated": false, "trimmed": true, "sourceSize": { @@ -3699,14 +3825,14 @@ "h": 23 }, "frame": { - "x": 145, - "y": 193, + "x": 65, + "y": 203, "w": 22, "h": 23 } }, { - "filename": "rock_tera_shard", + "filename": "normal_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3720,14 +3846,14 @@ "h": 23 }, "frame": { - "x": 167, - "y": 170, + "x": 87, + "y": 203, "w": 22, "h": 23 } }, { - "filename": "steel_tera_shard", + "filename": "petaya_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -3735,20 +3861,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, + "x": 5, + "y": 5, "w": 22, "h": 23 }, "frame": { - "x": 167, - "y": 193, + "x": 65, + "y": 226, "w": 22, "h": 23 } }, { - "filename": "super_lure", + "filename": "poison_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3756,20 +3882,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, + "x": 6, "y": 4, - "w": 17, - "h": 24 + "w": 22, + "h": 23 }, "frame": { - "x": 189, - "y": 147, - "w": 17, - "h": 24 + "x": 87, + "y": 226, + "w": 22, + "h": 23 } }, { - "filename": "stellar_tera_shard", + "filename": "psychic_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3783,14 +3909,14 @@ "h": 23 }, "frame": { - "x": 206, - "y": 146, + "x": 65, + "y": 249, "w": 22, "h": 23 } }, { - "filename": "water_tera_shard", + "filename": "reaper_cloth", "rotated": false, "trimmed": true, "sourceSize": { @@ -3798,20 +3924,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, + "x": 5, + "y": 5, "w": 22, "h": 23 }, "frame": { - "x": 228, - "y": 146, + "x": 87, + "y": 249, "w": 22, "h": 23 } }, { - "filename": "electric_memory", + "filename": "lansat_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -3820,19 +3946,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 5, - "w": 22, - "h": 22 + "y": 4, + "w": 21, + "h": 23 }, "frame": { - "x": 250, - "y": 148, - "w": 22, - "h": 22 + "x": 109, + "y": 203, + "w": 21, + "h": 23 } }, { - "filename": "hyper_potion", + "filename": "leaf_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -3840,20 +3966,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, + "x": 5, "y": 5, - "w": 17, + "w": 21, "h": 23 }, "frame": { - "x": 189, - "y": 171, - "w": 17, + "x": 109, + "y": 226, + "w": 21, "h": 23 } }, { - "filename": "wide_lens", + "filename": "rock_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3861,20 +3987,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 6, "y": 4, "w": 22, "h": 23 }, "frame": { - "x": 206, - "y": 169, + "x": 109, + "y": 249, "w": 22, "h": 23 } }, { - "filename": "enigma_berry", + "filename": "sharp_beak", "rotated": false, "trimmed": true, "sourceSize": { @@ -3884,18 +4010,18 @@ "spriteSourceSize": { "x": 5, "y": 5, - "w": 22, - "h": 22 + "w": 21, + "h": 23 }, "frame": { - "x": 228, - "y": 169, - "w": 22, - "h": 22 + "x": 130, + "y": 198, + "w": 21, + "h": 23 } }, { - "filename": "fairy_memory", + "filename": "steel_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3903,62 +4029,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 250, - "y": 170, - "w": 22, - "h": 22 - } - }, - { - "filename": "fighting_memory", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 272, - "y": 153, - "w": 22, - "h": 22 - } - }, - { - "filename": "fire_memory", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, + "x": 6, + "y": 4, "w": 22, - "h": 22 + "h": 23 }, "frame": { - "x": 294, - "y": 154, + "x": 130, + "y": 221, "w": 22, - "h": 22 + "h": 23 } }, { - "filename": "dubious_disc", + "filename": "max_ether", "rotated": false, "trimmed": true, "sourceSize": { @@ -3966,20 +4050,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 22, - "h": 19 + "x": 7, + "y": 4, + "w": 18, + "h": 24 }, "frame": { - "x": 272, - "y": 175, - "w": 22, - "h": 19 + "x": 151, + "y": 196, + "w": 18, + "h": 24 } }, { - "filename": "fairy_feather", + "filename": "stellar_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3987,20 +4071,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 7, + "x": 6, + "y": 4, "w": 22, - "h": 20 + "h": 23 }, "frame": { - "x": 294, - "y": 176, + "x": 169, + "y": 197, "w": 22, - "h": 20 + "h": 23 } }, { - "filename": "flying_memory", + "filename": "water_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -4008,20 +4092,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, + "x": 6, + "y": 4, "w": 22, - "h": 22 + "h": 23 }, "frame": { - "x": 316, - "y": 155, + "x": 152, + "y": 220, "w": 22, - "h": 22 + "h": 23 } }, { - "filename": "ganlon_berry", + "filename": "ghost_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -4035,14 +4119,14 @@ "h": 22 }, "frame": { - "x": 316, - "y": 177, + "x": 191, + "y": 198, "w": 22, "h": 22 } }, { - "filename": "ghost_memory", + "filename": "wide_lens", "rotated": false, "trimmed": true, "sourceSize": { @@ -4051,15 +4135,15 @@ }, "spriteSourceSize": { "x": 5, - "y": 5, + "y": 4, "w": 22, - "h": 22 + "h": 23 }, "frame": { - "x": 338, - "y": 157, + "x": 174, + "y": 220, "w": 22, - "h": 22 + "h": 23 } }, { @@ -4077,8 +4161,8 @@ "h": 22 }, "frame": { - "x": 338, - "y": 179, + "x": 213, + "y": 198, "w": 22, "h": 22 } @@ -4098,33 +4182,12 @@ "h": 22 }, "frame": { - "x": 189, - "y": 194, + "x": 196, + "y": 220, "w": 22, "h": 22 } }, - { - "filename": "potion", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 17, - "h": 23 - }, - "frame": { - "x": 211, - "y": 192, - "w": 17, - "h": 23 - } - }, { "filename": "guard_spec", "rotated": false, @@ -4140,8 +4203,8 @@ "h": 22 }, "frame": { - "x": 228, - "y": 191, + "x": 235, + "y": 199, "w": 22, "h": 22 } @@ -4161,8 +4224,8 @@ "h": 22 }, "frame": { - "x": 250, - "y": 192, + "x": 257, + "y": 199, "w": 22, "h": 22 } @@ -4182,8 +4245,8 @@ "h": 22 }, "frame": { - "x": 272, - "y": 194, + "x": 279, + "y": 199, "w": 22, "h": 22 } @@ -4203,8 +4266,8 @@ "h": 21 }, "frame": { - "x": 294, - "y": 196, + "x": 301, + "y": 200, "w": 22, "h": 21 } @@ -4224,14 +4287,14 @@ "h": 22 }, "frame": { - "x": 316, - "y": 199, + "x": 323, + "y": 200, "w": 22, "h": 22 } }, { - "filename": "malicious_armor", + "filename": "hyper_potion", "rotated": false, "trimmed": true, "sourceSize": { @@ -4239,16 +4302,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 20 + "x": 8, + "y": 5, + "w": 17, + "h": 23 }, "frame": { - "x": 338, - "y": 201, - "w": 22, - "h": 20 + "x": 218, + "y": 220, + "w": 17, + "h": 23 } }, { @@ -4266,8 +4329,8 @@ "h": 22 }, "frame": { - "x": 146, - "y": 216, + "x": 235, + "y": 221, "w": 22, "h": 22 } @@ -4287,8 +4350,8 @@ "h": 22 }, "frame": { - "x": 168, - "y": 216, + "x": 257, + "y": 221, "w": 22, "h": 22 } @@ -4308,14 +4371,14 @@ "h": 22 }, "frame": { - "x": 190, - "y": 216, + "x": 279, + "y": 221, "w": 22, "h": 22 } }, { - "filename": "repel", + "filename": "psychic_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -4323,20 +4386,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 212, - "y": 215, - "w": 16, - "h": 24 + "x": 301, + "y": 221, + "w": 22, + "h": 22 } }, { - "filename": "psychic_memory", + "filename": "rock_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -4350,14 +4413,14 @@ "h": 22 }, "frame": { - "x": 228, - "y": 213, + "x": 323, + "y": 222, "w": 22, "h": 22 } }, { - "filename": "rock_memory", + "filename": "whipped_dream", "rotated": false, "trimmed": true, "sourceSize": { @@ -4366,15 +4429,15 @@ }, "spriteSourceSize": { "x": 5, - "y": 5, - "w": 22, - "h": 22 + "y": 4, + "w": 21, + "h": 23 }, "frame": { - "x": 250, - "y": 214, - "w": 22, - "h": 22 + "x": 131, + "y": 244, + "w": 21, + "h": 23 } }, { @@ -4392,8 +4455,8 @@ "h": 22 }, "frame": { - "x": 272, - "y": 216, + "x": 152, + "y": 243, "w": 22, "h": 22 } @@ -4413,8 +4476,8 @@ "h": 22 }, "frame": { - "x": 294, - "y": 217, + "x": 174, + "y": 243, "w": 22, "h": 22 } @@ -4434,8 +4497,8 @@ "h": 22 }, "frame": { - "x": 316, - "y": 221, + "x": 196, + "y": 242, "w": 22, "h": 22 } @@ -4455,14 +4518,14 @@ "h": 22 }, "frame": { - "x": 338, - "y": 221, + "x": 218, + "y": 243, "w": 22, "h": 22 } }, { - "filename": "sharp_beak", + "filename": "steel_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -4472,18 +4535,18 @@ "spriteSourceSize": { "x": 5, "y": 5, - "w": 21, - "h": 23 + "w": 22, + "h": 22 }, "frame": { - "x": 148, - "y": 238, - "w": 21, - "h": 23 + "x": 240, + "y": 243, + "w": 22, + "h": 22 } }, { - "filename": "steel_memory", + "filename": "thick_club", "rotated": false, "trimmed": true, "sourceSize": { @@ -4497,14 +4560,14 @@ "h": 22 }, "frame": { - "x": 169, - "y": 238, + "x": 262, + "y": 243, "w": 22, "h": 22 } }, { - "filename": "whipped_dream", + "filename": "thunder_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -4513,40 +4576,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 4, - "w": 21, - "h": 23 - }, - "frame": { - "x": 191, - "y": 238, - "w": 21, - "h": 23 - } - }, - { - "filename": "hard_meteorite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, "y": 5, - "w": 20, + "w": 22, "h": 22 }, "frame": { - "x": 212, - "y": 239, - "w": 20, + "x": 284, + "y": 243, + "w": 22, "h": 22 } }, { - "filename": "super_potion", + "filename": "max_lure", "rotated": false, "trimmed": true, "sourceSize": { @@ -4555,19 +4597,19 @@ }, "spriteSourceSize": { "x": 8, - "y": 5, + "y": 4, "w": 17, - "h": 23 + "h": 24 }, "frame": { - "x": 232, - "y": 235, + "x": 306, + "y": 243, "w": 17, - "h": 23 + "h": 24 } }, { - "filename": "thick_club", + "filename": "tm_bug", "rotated": false, "trimmed": true, "sourceSize": { @@ -4581,14 +4623,14 @@ "h": 22 }, "frame": { - "x": 249, - "y": 236, + "x": 323, + "y": 244, "w": 22, "h": 22 } }, { - "filename": "sweet_apple", + "filename": "tm_dark", "rotated": false, "trimmed": true, "sourceSize": { @@ -4597,19 +4639,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 6, + "y": 5, "w": 22, - "h": 21 + "h": 22 }, "frame": { - "x": 271, - "y": 238, + "x": 68, + "y": 272, "w": 22, - "h": 21 + "h": 22 } }, { - "filename": "syrupy_apple", + "filename": "tm_dragon", "rotated": false, "trimmed": true, "sourceSize": { @@ -4618,19 +4660,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 6, + "y": 5, "w": 22, - "h": 21 + "h": 22 }, "frame": { - "x": 293, - "y": 239, + "x": 68, + "y": 294, "w": 22, - "h": 21 + "h": 22 } }, { - "filename": "tart_apple", + "filename": "tm_electric", "rotated": false, "trimmed": true, "sourceSize": { @@ -4639,19 +4681,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 6, + "y": 5, "w": 22, - "h": 21 + "h": 22 }, "frame": { - "x": 315, - "y": 243, + "x": 90, + "y": 272, "w": 22, - "h": 21 + "h": 22 } }, { - "filename": "thunder_stone", + "filename": "tm_fairy", "rotated": false, "trimmed": true, "sourceSize": { @@ -4665,35 +4707,14 @@ "h": 22 }, "frame": { - "x": 337, - "y": 243, + "x": 68, + "y": 316, "w": 22, "h": 22 } }, { - "filename": "masterpiece_teacup", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 21, - "h": 18 - }, - "frame": { - "x": 148, - "y": 261, - "w": 21, - "h": 18 - } - }, - { - "filename": "tera_orb", + "filename": "tm_fighting", "rotated": false, "trimmed": true, "sourceSize": { @@ -4702,19 +4723,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 6, + "y": 5, "w": 22, - "h": 20 + "h": 22 }, "frame": { - "x": 169, - "y": 260, + "x": 90, + "y": 294, "w": 22, - "h": 20 + "h": 22 } }, { - "filename": "tm_bug", + "filename": "tm_fire", "rotated": false, "trimmed": true, "sourceSize": { @@ -4728,14 +4749,14 @@ "h": 22 }, "frame": { - "x": 191, - "y": 261, + "x": 68, + "y": 338, "w": 22, "h": 22 } }, { - "filename": "lock_capsule", + "filename": "tm_flying", "rotated": false, "trimmed": true, "sourceSize": { @@ -4743,20 +4764,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, + "x": 5, "y": 5, - "w": 19, + "w": 22, "h": 22 }, "frame": { - "x": 213, - "y": 261, - "w": 19, + "x": 90, + "y": 316, + "w": 22, "h": 22 } }, { - "filename": "tm_dark", + "filename": "tm_ghost", "rotated": false, "trimmed": true, "sourceSize": { @@ -4770,14 +4791,14 @@ "h": 22 }, "frame": { - "x": 232, - "y": 258, + "x": 68, + "y": 360, "w": 22, "h": 22 } }, { - "filename": "metronome", + "filename": "tm_grass", "rotated": false, "trimmed": true, "sourceSize": { @@ -4785,20 +4806,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, + "x": 5, "y": 5, - "w": 17, + "w": 22, "h": 22 }, "frame": { - "x": 254, - "y": 258, - "w": 17, + "x": 90, + "y": 338, + "w": 22, "h": 22 } }, { - "filename": "tm_dragon", + "filename": "tm_ground", "rotated": false, "trimmed": true, "sourceSize": { @@ -4812,14 +4833,14 @@ "h": 22 }, "frame": { - "x": 271, - "y": 259, + "x": 90, + "y": 360, "w": 22, "h": 22 } }, { - "filename": "tm_electric", + "filename": "max_potion", "rotated": false, "trimmed": true, "sourceSize": { @@ -4827,20 +4848,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 7, + "y": 4, + "w": 18, + "h": 24 }, "frame": { - "x": 293, - "y": 260, - "w": 22, - "h": 22 + "x": 112, + "y": 272, + "w": 18, + "h": 24 } }, { - "filename": "tm_fairy", + "filename": "sachet", "rotated": false, "trimmed": true, "sourceSize": { @@ -4848,20 +4869,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 6, + "y": 4, + "w": 18, + "h": 23 }, "frame": { - "x": 315, - "y": 264, - "w": 22, - "h": 22 + "x": 112, + "y": 296, + "w": 18, + "h": 23 } }, { - "filename": "tm_fighting", + "filename": "super_lure", "rotated": false, "trimmed": true, "sourceSize": { @@ -4869,20 +4890,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 8, + "y": 4, + "w": 17, + "h": 24 }, "frame": { - "x": 337, - "y": 265, - "w": 22, - "h": 22 + "x": 112, + "y": 319, + "w": 17, + "h": 24 } }, { - "filename": "tm_fire", + "filename": "potion", "rotated": false, "trimmed": true, "sourceSize": { @@ -4890,20 +4911,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 8, "y": 5, - "w": 22, - "h": 22 + "w": 17, + "h": 23 }, "frame": { - "x": 366, - "y": 131, - "w": 22, - "h": 22 + "x": 112, + "y": 343, + "w": 17, + "h": 23 } }, { - "filename": "tm_flying", + "filename": "shock_drive", "rotated": false, "trimmed": true, "sourceSize": { @@ -4911,20 +4932,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 4, + "y": 8, + "w": 23, + "h": 17 }, "frame": { - "x": 388, - "y": 134, - "w": 22, - "h": 22 + "x": 68, + "y": 382, + "w": 23, + "h": 17 } }, { - "filename": "big_nugget", + "filename": "pp_up", "rotated": false, "trimmed": true, "sourceSize": { @@ -4932,20 +4953,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 + "x": 8, + "y": 4, + "w": 16, + "h": 24 }, "frame": { - "x": 128, - "y": 272, - "w": 20, - "h": 20 + "x": 68, + "y": 399, + "w": 16, + "h": 24 } }, { - "filename": "metal_alloy", + "filename": "protein", "rotated": false, "trimmed": true, "sourceSize": { @@ -4953,20 +4974,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 21, - "h": 19 + "x": 8, + "y": 4, + "w": 16, + "h": 24 }, "frame": { - "x": 148, - "y": 279, - "w": 21, - "h": 19 + "x": 84, + "y": 399, + "w": 16, + "h": 24 } }, { - "filename": "tm_ghost", + "filename": "wise_glasses", "rotated": false, "trimmed": true, "sourceSize": { @@ -4974,20 +4995,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 4, + "y": 8, + "w": 23, + "h": 17 }, "frame": { - "x": 169, - "y": 280, - "w": 22, - "h": 22 + "x": 91, + "y": 382, + "w": 23, + "h": 17 } }, { - "filename": "tm_grass", + "filename": "repel", "rotated": false, "trimmed": true, "sourceSize": { @@ -4995,20 +5016,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 8, + "y": 4, + "w": 16, + "h": 24 }, "frame": { - "x": 191, - "y": 283, - "w": 22, - "h": 22 + "x": 100, + "y": 399, + "w": 16, + "h": 24 } }, { - "filename": "metal_coat", + "filename": "mega_bracelet", "rotated": false, "trimmed": true, "sourceSize": { @@ -5017,19 +5038,19 @@ }, "spriteSourceSize": { "x": 6, - "y": 5, - "w": 19, - "h": 22 + "y": 8, + "w": 20, + "h": 16 }, "frame": { - "x": 213, - "y": 283, - "w": 19, - "h": 22 + "x": 112, + "y": 366, + "w": 20, + "h": 16 } }, { - "filename": "tm_ground", + "filename": "everstone", "rotated": false, "trimmed": true, "sourceSize": { @@ -5037,41 +5058,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 232, - "y": 280, - "w": 22, - "h": 22 - } - }, - { - "filename": "soothe_bell", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 17, - "h": 22 + "x": 6, + "y": 8, + "w": 20, + "h": 17 }, "frame": { - "x": 254, - "y": 280, - "w": 17, - "h": 22 + "x": 114, + "y": 382, + "w": 20, + "h": 17 } }, { - "filename": "tm_ice", + "filename": "super_repel", "rotated": false, "trimmed": true, "sourceSize": { @@ -5079,20 +5079,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 8, + "y": 4, + "w": 16, + "h": 24 }, "frame": { - "x": 271, - "y": 281, - "w": 22, - "h": 22 + "x": 116, + "y": 399, + "w": 16, + "h": 24 } }, { - "filename": "tm_normal", + "filename": "unknown", "rotated": false, "trimmed": true, "sourceSize": { @@ -5100,20 +5100,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 8, + "y": 4, + "w": 16, + "h": 24 }, "frame": { - "x": 293, - "y": 282, - "w": 22, - "h": 22 + "x": 132, + "y": 399, + "w": 16, + "h": 24 } }, { - "filename": "tm_poison", + "filename": "zinc", "rotated": false, "trimmed": true, "sourceSize": { @@ -5121,20 +5121,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 8, + "y": 4, + "w": 16, + "h": 24 }, "frame": { - "x": 315, - "y": 286, - "w": 22, - "h": 22 + "x": 346, + "y": 159, + "w": 16, + "h": 24 } }, { - "filename": "tm_psychic", + "filename": "baton", "rotated": false, "trimmed": true, "sourceSize": { @@ -5142,20 +5142,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 7, + "y": 7, + "w": 18, + "h": 18 }, "frame": { - "x": 337, - "y": 287, - "w": 22, - "h": 22 + "x": 362, + "y": 136, + "w": 18, + "h": 18 } }, { - "filename": "tm_rock", + "filename": "super_potion", "rotated": false, "trimmed": true, "sourceSize": { @@ -5163,20 +5163,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 8, "y": 5, - "w": 22, - "h": 22 + "w": 17, + "h": 23 }, "frame": { - "x": 72, - "y": 270, - "w": 22, - "h": 22 + "x": 362, + "y": 154, + "w": 17, + "h": 23 } }, { - "filename": "tm_steel", + "filename": "big_mushroom", "rotated": false, "trimmed": true, "sourceSize": { @@ -5184,20 +5184,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 6, + "y": 6, + "w": 19, + "h": 19 }, "frame": { - "x": 72, - "y": 292, - "w": 22, - "h": 22 + "x": 346, + "y": 183, + "w": 19, + "h": 19 } }, { - "filename": "tm_water", + "filename": "tm_ice", "rotated": false, "trimmed": true, "sourceSize": { @@ -5211,14 +5211,14 @@ "h": 22 }, "frame": { - "x": 72, - "y": 314, + "x": 345, + "y": 202, "w": 22, "h": 22 } }, { - "filename": "water_memory", + "filename": "tm_normal", "rotated": false, "trimmed": true, "sourceSize": { @@ -5232,14 +5232,14 @@ "h": 22 }, "frame": { - "x": 72, - "y": 336, + "x": 345, + "y": 224, "w": 22, "h": 22 } }, { - "filename": "water_stone", + "filename": "fairy_feather", "rotated": false, "trimmed": true, "sourceSize": { @@ -5248,19 +5248,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 5, + "y": 7, "w": 22, - "h": 22 + "h": 20 }, "frame": { - "x": 72, - "y": 358, + "x": 345, + "y": 246, "w": 22, - "h": 22 + "h": 20 } }, { - "filename": "x_accuracy", + "filename": "full_heal", "rotated": false, "trimmed": true, "sourceSize": { @@ -5268,16 +5268,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 9, + "y": 4, + "w": 15, + "h": 23 }, "frame": { - "x": 72, - "y": 380, - "w": 22, - "h": 22 + "x": 365, + "y": 177, + "w": 15, + "h": 23 } }, { @@ -5295,14 +5295,14 @@ "h": 22 }, "frame": { - "x": 94, - "y": 270, + "x": 367, + "y": 200, "w": 15, "h": 22 } }, { - "filename": "big_mushroom", + "filename": "metronome", "rotated": false, "trimmed": true, "sourceSize": { @@ -5310,20 +5310,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 19, - "h": 19 + "x": 7, + "y": 5, + "w": 17, + "h": 22 }, "frame": { - "x": 109, - "y": 273, - "w": 19, - "h": 19 + "x": 367, + "y": 222, + "w": 17, + "h": 22 } }, { - "filename": "x_attack", + "filename": "soothe_bell", "rotated": false, "trimmed": true, "sourceSize": { @@ -5331,20 +5331,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 8, "y": 5, - "w": 22, + "w": 17, "h": 22 }, "frame": { - "x": 94, - "y": 292, - "w": 22, + "x": 367, + "y": 244, + "w": 17, "h": 22 } }, { - "filename": "x_defense", + "filename": "malicious_armor", "rotated": false, "trimmed": true, "sourceSize": { @@ -5353,19 +5353,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 5, + "y": 6, "w": 22, - "h": 22 + "h": 20 }, "frame": { - "x": 116, - "y": 292, + "x": 382, + "y": 151, "w": 22, - "h": 22 + "h": 20 } }, { - "filename": "x_sp_atk", + "filename": "candy_jar", "rotated": false, "trimmed": true, "sourceSize": { @@ -5373,20 +5373,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 6, + "y": 6, + "w": 19, + "h": 20 }, "frame": { - "x": 94, - "y": 314, - "w": 22, - "h": 22 + "x": 404, + "y": 158, + "w": 19, + "h": 20 } }, { - "filename": "x_sp_def", + "filename": "tm_poison", "rotated": false, "trimmed": true, "sourceSize": { @@ -5400,14 +5400,14 @@ "h": 22 }, "frame": { - "x": 94, - "y": 336, + "x": 380, + "y": 171, "w": 22, "h": 22 } }, { - "filename": "x_speed", + "filename": "dusk_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -5415,20 +5415,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 6, + "y": 6, + "w": 21, + "h": 21 }, "frame": { - "x": 116, - "y": 314, - "w": 22, - "h": 22 + "x": 402, + "y": 178, + "w": 21, + "h": 21 } }, { - "filename": "poison_barb", + "filename": "dawn_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -5436,20 +5436,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 6, "y": 6, - "w": 21, + "w": 20, "h": 21 }, "frame": { - "x": 94, - "y": 358, - "w": 21, + "x": 382, + "y": 193, + "w": 20, "h": 21 } }, { - "filename": "shiny_stone", + "filename": "poison_barb", "rotated": false, "trimmed": true, "sourceSize": { @@ -5463,14 +5463,14 @@ "h": 21 }, "frame": { - "x": 116, - "y": 336, + "x": 402, + "y": 199, "w": 21, "h": 21 } }, { - "filename": "sitrus_berry", + "filename": "razor_fang", "rotated": false, "trimmed": true, "sourceSize": { @@ -5478,20 +5478,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 20, - "h": 22 + "x": 7, + "y": 6, + "w": 18, + "h": 20 }, "frame": { - "x": 94, - "y": 379, - "w": 20, - "h": 22 + "x": 384, + "y": 214, + "w": 18, + "h": 20 } }, { - "filename": "zoom_lens", + "filename": "shiny_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -5505,14 +5505,77 @@ "h": 21 }, "frame": { - "x": 138, - "y": 298, + "x": 402, + "y": 220, "w": 21, "h": 21 } }, { - "filename": "sharp_meteorite", + "filename": "oval_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 18, + "h": 19 + }, + "frame": { + "x": 384, + "y": 234, + "w": 18, + "h": 19 + } + }, + { + "filename": "zoom_lens", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 21, + "h": 21 + }, + "frame": { + "x": 402, + "y": 241, + "w": 21, + "h": 21 + } + }, + { + "filename": "candy", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 11, + "w": 18, + "h": 18 + }, + "frame": { + "x": 384, + "y": 253, + "w": 18, + "h": 18 + } + }, + { + "filename": "metal_alloy", "rotated": false, "trimmed": true, "sourceSize": { @@ -5521,19 +5584,40 @@ }, "spriteSourceSize": { "x": 6, - "y": 8, + "y": 7, + "w": 21, + "h": 19 + }, + "frame": { + "x": 402, + "y": 262, + "w": 21, + "h": 19 + } + }, + { + "filename": "masterpiece_teacup", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, "w": 21, "h": 18 }, "frame": { - "x": 138, - "y": 319, + "x": 131, + "y": 267, "w": 21, "h": 18 } }, { - "filename": "upgrade", + "filename": "tm_psychic", "rotated": false, "trimmed": true, "sourceSize": { @@ -5542,19 +5626,19 @@ }, "spriteSourceSize": { "x": 5, - "y": 7, + "y": 5, "w": 22, - "h": 19 + "h": 22 }, "frame": { - "x": 137, - "y": 337, + "x": 130, + "y": 285, "w": 22, - "h": 19 + "h": 22 } }, { - "filename": "dawn_stone", + "filename": "tm_rock", "rotated": false, "trimmed": true, "sourceSize": { @@ -5562,20 +5646,83 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 152, + "y": 265, + "w": 22, + "h": 22 + } + }, + { + "filename": "tm_steel", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 174, + "y": 265, + "w": 22, + "h": 22 + } + }, + { + "filename": "tm_water", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 196, + "y": 264, + "w": 22, + "h": 22 + } + }, + { + "filename": "sweet_apple", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, "y": 6, - "w": 20, + "w": 22, "h": 21 }, "frame": { - "x": 159, - "y": 302, - "w": 20, + "x": 218, + "y": 265, + "w": 22, "h": 21 } }, { - "filename": "blue_orb", + "filename": "syrupy_apple", "rotated": false, "trimmed": true, "sourceSize": { @@ -5583,20 +5730,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, + "x": 5, "y": 6, - "w": 20, - "h": 20 + "w": 22, + "h": 21 }, "frame": { - "x": 159, - "y": 323, - "w": 20, - "h": 20 + "x": 240, + "y": 265, + "w": 22, + "h": 21 } }, { - "filename": "everstone", + "filename": "tart_apple", "rotated": false, "trimmed": true, "sourceSize": { @@ -5604,20 +5751,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 17 + "x": 5, + "y": 6, + "w": 22, + "h": 21 }, "frame": { - "x": 159, - "y": 343, - "w": 20, - "h": 17 + "x": 262, + "y": 265, + "w": 22, + "h": 21 } }, { - "filename": "revive", + "filename": "water_memory", "rotated": false, "trimmed": true, "sourceSize": { @@ -5625,20 +5772,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 12, - "h": 17 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 179, - "y": 302, - "w": 12, - "h": 17 + "x": 284, + "y": 265, + "w": 22, + "h": 22 } }, { - "filename": "super_repel", + "filename": "tera_orb", "rotated": false, "trimmed": true, "sourceSize": { @@ -5646,41 +5793,41 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 + "x": 5, + "y": 6, + "w": 22, + "h": 20 }, "frame": { - "x": 179, - "y": 319, - "w": 16, - "h": 24 + "x": 152, + "y": 287, + "w": 22, + "h": 20 } }, { - "filename": "baton", + "filename": "water_stone", "rotated": false, - "trimmed": false, + "trimmed": true, "sourceSize": { - "w": 18, - "h": 18 + "w": 32, + "h": 32 }, "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 18, - "h": 18 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 179, - "y": 343, - "w": 18, - "h": 18 + "x": 174, + "y": 287, + "w": 22, + "h": 22 } }, { - "filename": "unknown", + "filename": "x_accuracy", "rotated": false, "trimmed": true, "sourceSize": { @@ -5688,20 +5835,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 360, - "y": 157, - "w": 16, - "h": 24 + "x": 196, + "y": 286, + "w": 22, + "h": 22 } }, { - "filename": "zinc", + "filename": "x_attack", "rotated": false, "trimmed": true, "sourceSize": { @@ -5709,20 +5856,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 360, - "y": 181, - "w": 16, - "h": 24 + "x": 218, + "y": 286, + "w": 22, + "h": 22 } }, { - "filename": "quick_claw", + "filename": "x_defense", "rotated": false, "trimmed": true, "sourceSize": { @@ -5730,20 +5877,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 19, - "h": 21 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 360, - "y": 205, - "w": 19, - "h": 21 + "x": 240, + "y": 286, + "w": 22, + "h": 22 } }, { - "filename": "candy_jar", + "filename": "x_sp_atk", "rotated": false, "trimmed": true, "sourceSize": { @@ -5751,20 +5898,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 19, - "h": 20 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 360, - "y": 226, - "w": 19, - "h": 20 + "x": 262, + "y": 286, + "w": 22, + "h": 22 } }, { - "filename": "gb", + "filename": "x_sp_def", "rotated": false, "trimmed": true, "sourceSize": { @@ -5772,20 +5919,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 359, - "y": 246, - "w": 20, - "h": 20 + "x": 284, + "y": 287, + "w": 22, + "h": 22 } }, { - "filename": "magnet", + "filename": "x_speed", "rotated": false, "trimmed": true, "sourceSize": { @@ -5793,20 +5940,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 + "x": 5, + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 359, - "y": 266, - "w": 20, - "h": 20 + "x": 306, + "y": 267, + "w": 22, + "h": 22 } }, { - "filename": "mb", + "filename": "upgrade", "rotated": false, "trimmed": true, "sourceSize": { @@ -5814,20 +5961,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 + "x": 5, + "y": 7, + "w": 22, + "h": 19 }, "frame": { - "x": 359, - "y": 286, - "w": 20, - "h": 20 + "x": 306, + "y": 289, + "w": 22, + "h": 19 } }, { - "filename": "pb", + "filename": "big_nugget", "rotated": false, "trimmed": true, "sourceSize": { @@ -5841,14 +5988,14 @@ "h": 20 }, "frame": { - "x": 376, - "y": 156, + "x": 328, + "y": 266, "w": 20, "h": 20 } }, { - "filename": "spell_tag", + "filename": "blue_orb", "rotated": false, "trimmed": true, "sourceSize": { @@ -5856,20 +6003,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, + "x": 6, "y": 6, - "w": 19, - "h": 21 + "w": 20, + "h": 20 }, "frame": { - "x": 396, - "y": 156, - "w": 19, - "h": 21 + "x": 348, + "y": 266, + "w": 20, + "h": 20 } }, { - "filename": "pb_gold", + "filename": "gb", "rotated": false, "trimmed": true, "sourceSize": { @@ -5883,14 +6030,14 @@ "h": 20 }, "frame": { - "x": 376, - "y": 176, + "x": 328, + "y": 286, "w": 20, "h": 20 } }, { - "filename": "hard_stone", + "filename": "magnet", "rotated": false, "trimmed": true, "sourceSize": { @@ -5900,18 +6047,18 @@ "spriteSourceSize": { "x": 6, "y": 6, - "w": 19, + "w": 20, "h": 20 }, "frame": { - "x": 396, - "y": 177, - "w": 19, + "x": 348, + "y": 286, + "w": 20, "h": 20 } }, { - "filename": "golden_egg", + "filename": "mystery_egg", "rotated": false, "trimmed": true, "sourceSize": { @@ -5919,20 +6066,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 17, - "h": 20 + "x": 8, + "y": 8, + "w": 16, + "h": 18 }, "frame": { - "x": 379, - "y": 196, - "w": 17, - "h": 20 + "x": 368, + "y": 266, + "w": 16, + "h": 18 } }, { - "filename": "miracle_seed", + "filename": "dark_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -5940,20 +6087,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, + "x": 7, "y": 7, - "w": 19, - "h": 19 + "w": 18, + "h": 18 }, "frame": { - "x": 396, - "y": 197, - "w": 19, - "h": 19 + "x": 384, + "y": 271, + "w": 18, + "h": 18 } }, { - "filename": "rb", + "filename": "sharp_meteorite", "rotated": false, "trimmed": true, "sourceSize": { @@ -5962,15 +6109,15 @@ }, "spriteSourceSize": { "x": 6, - "y": 6, - "w": 20, - "h": 20 + "y": 8, + "w": 21, + "h": 18 }, "frame": { - "x": 379, - "y": 216, - "w": 20, - "h": 20 + "x": 402, + "y": 281, + "w": 21, + "h": 18 } }, { @@ -5988,14 +6135,14 @@ "h": 16 }, "frame": { - "x": 399, - "y": 216, + "x": 368, + "y": 284, "w": 16, "h": 16 } }, { - "filename": "smooth_meteorite", + "filename": "flame_orb", "rotated": false, "trimmed": true, "sourceSize": { @@ -6004,19 +6151,19 @@ }, "spriteSourceSize": { "x": 7, - "y": 6, - "w": 20, - "h": 20 + "y": 7, + "w": 18, + "h": 18 }, "frame": { - "x": 379, - "y": 236, - "w": 20, - "h": 20 + "x": 384, + "y": 289, + "w": 18, + "h": 18 } }, { - "filename": "absolite", + "filename": "unremarkable_teacup", "rotated": false, "trimmed": true, "sourceSize": { @@ -6024,20 +6171,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 + "x": 5, + "y": 7, + "w": 21, + "h": 18 }, "frame": { - "x": 399, - "y": 232, - "w": 16, - "h": 16 + "x": 402, + "y": 299, + "w": 21, + "h": 18 } }, { - "filename": "aerodactylite", + "filename": "lum_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -6045,20 +6192,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 + "x": 6, + "y": 7, + "w": 20, + "h": 19 }, "frame": { - "x": 399, - "y": 248, - "w": 16, - "h": 16 + "x": 130, + "y": 307, + "w": 20, + "h": 19 } }, { - "filename": "strange_ball", + "filename": "mb", "rotated": false, "trimmed": true, "sourceSize": { @@ -6072,14 +6219,14 @@ "h": 20 }, "frame": { - "x": 379, - "y": 256, + "x": 129, + "y": 326, "w": 20, "h": 20 } }, { - "filename": "aggronite", + "filename": "pb", "rotated": false, "trimmed": true, "sourceSize": { @@ -6087,20 +6234,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 + "x": 6, + "y": 6, + "w": 20, + "h": 20 }, "frame": { - "x": 399, - "y": 264, - "w": 16, - "h": 16 + "x": 129, + "y": 346, + "w": 20, + "h": 20 } }, { - "filename": "ub", + "filename": "pb_gold", "rotated": false, "trimmed": true, "sourceSize": { @@ -6114,14 +6261,14 @@ "h": 20 }, "frame": { - "x": 379, - "y": 276, + "x": 150, + "y": 307, "w": 20, "h": 20 } }, { - "filename": "alakazite", + "filename": "rb", "rotated": false, "trimmed": true, "sourceSize": { @@ -6129,20 +6276,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 + "x": 6, + "y": 6, + "w": 20, + "h": 20 }, "frame": { - "x": 399, - "y": 280, - "w": 16, - "h": 16 + "x": 149, + "y": 327, + "w": 20, + "h": 20 } }, { - "filename": "unremarkable_teacup", + "filename": "razor_claw", "rotated": false, "trimmed": true, "sourceSize": { @@ -6150,62 +6297,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 6, "y": 7, - "w": 21, - "h": 18 - }, - "frame": { - "x": 379, - "y": 296, - "w": 21, - "h": 18 - } - }, - { - "filename": "eviolite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 15, - "h": 15 - }, - "frame": { - "x": 400, - "y": 296, - "w": 15, - "h": 15 - } - }, - { - "filename": "prism_scale", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 9, - "y": 8, - "w": 15, - "h": 15 + "w": 20, + "h": 19 }, "frame": { - "x": 400, - "y": 311, - "w": 15, - "h": 15 + "x": 149, + "y": 347, + "w": 20, + "h": 19 } }, { - "filename": "lum_berry", + "filename": "relic_band", "rotated": false, "trimmed": true, "sourceSize": { @@ -6213,20 +6318,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 20, - "h": 19 + "x": 7, + "y": 9, + "w": 17, + "h": 16 }, "frame": { - "x": 359, - "y": 306, - "w": 20, - "h": 19 + "x": 132, + "y": 366, + "w": 17, + "h": 16 } }, { - "filename": "mega_bracelet", + "filename": "smooth_meteorite", "rotated": false, "trimmed": true, "sourceSize": { @@ -6234,20 +6339,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 8, + "x": 7, + "y": 6, "w": 20, - "h": 16 + "h": 20 }, "frame": { - "x": 379, - "y": 314, + "x": 149, + "y": 366, "w": 20, - "h": 16 + "h": 20 } }, { - "filename": "altarianite", + "filename": "eviolite", "rotated": false, "trimmed": true, "sourceSize": { @@ -6257,18 +6362,18 @@ "spriteSourceSize": { "x": 8, "y": 8, - "w": 16, - "h": 16 + "w": 15, + "h": 15 }, "frame": { - "x": 399, - "y": 326, - "w": 16, - "h": 16 + "x": 134, + "y": 382, + "w": 15, + "h": 15 } }, { - "filename": "razor_claw", + "filename": "strange_ball", "rotated": false, "trimmed": true, "sourceSize": { @@ -6277,19 +6382,19 @@ }, "spriteSourceSize": { "x": 6, - "y": 7, + "y": 6, "w": 20, - "h": 19 + "h": 20 }, "frame": { - "x": 195, - "y": 305, + "x": 170, + "y": 309, "w": 20, - "h": 19 + "h": 20 } }, { - "filename": "oval_stone", + "filename": "ub", "rotated": false, "trimmed": true, "sourceSize": { @@ -6297,20 +6402,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 19 + "x": 6, + "y": 6, + "w": 20, + "h": 20 }, "frame": { - "x": 195, - "y": 324, - "w": 18, - "h": 19 + "x": 169, + "y": 329, + "w": 20, + "h": 20 } }, { - "filename": "lucky_egg", + "filename": "hard_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -6318,20 +6423,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, + "x": 6, "y": 6, - "w": 17, + "w": 19, "h": 20 }, "frame": { - "x": 215, - "y": 305, - "w": 17, + "x": 169, + "y": 349, + "w": 19, "h": 20 } }, { - "filename": "razor_fang", + "filename": "miracle_seed", "rotated": false, "trimmed": true, "sourceSize": { @@ -6339,16 +6444,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 18, - "h": 20 + "x": 6, + "y": 7, + "w": 19, + "h": 19 }, "frame": { - "x": 232, - "y": 302, - "w": 18, - "h": 20 + "x": 169, + "y": 369, + "w": 19, + "h": 19 } }, { @@ -6366,8 +6471,8 @@ "h": 18 }, "frame": { - "x": 250, - "y": 302, + "x": 149, + "y": 386, "w": 20, "h": 18 } @@ -6387,8 +6492,8 @@ "h": 18 }, "frame": { - "x": 270, - "y": 303, + "x": 148, + "y": 404, "w": 20, "h": 18 } @@ -6408,14 +6513,14 @@ "h": 18 }, "frame": { - "x": 213, - "y": 325, + "x": 169, + "y": 388, "w": 20, "h": 18 } }, { - "filename": "wl_burn_heal", + "filename": "absolite", "rotated": false, "trimmed": true, "sourceSize": { @@ -6423,20 +6528,41 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, + "x": 8, "y": 8, - "w": 20, - "h": 18 + "w": 16, + "h": 16 }, "frame": { - "x": 197, - "y": 343, - "w": 20, - "h": 18 + "x": 168, + "y": 406, + "w": 16, + "h": 16 } }, { - "filename": "candy", + "filename": "aerodactylite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 368, + "y": 300, + "w": 16, + "h": 16 + } + }, + { + "filename": "light_ball", "rotated": false, "trimmed": true, "sourceSize": { @@ -6445,19 +6571,19 @@ }, "spriteSourceSize": { "x": 7, - "y": 11, + "y": 7, "w": 18, "h": 18 }, "frame": { - "x": 217, - "y": 343, + "x": 384, + "y": 307, "w": 18, "h": 18 } }, { - "filename": "wl_custom_spliced", + "filename": "wl_burn_heal", "rotated": false, "trimmed": true, "sourceSize": { @@ -6471,14 +6597,14 @@ "h": 18 }, "frame": { - "x": 290, - "y": 304, + "x": 402, + "y": 317, "w": 20, "h": 18 } }, { - "filename": "dark_stone", + "filename": "golden_egg", "rotated": false, "trimmed": true, "sourceSize": { @@ -6487,19 +6613,19 @@ }, "spriteSourceSize": { "x": 7, - "y": 7, - "w": 18, - "h": 18 + "y": 6, + "w": 17, + "h": 20 }, "frame": { - "x": 233, - "y": 322, - "w": 18, - "h": 18 + "x": 190, + "y": 309, + "w": 17, + "h": 20 } }, { - "filename": "flame_orb", + "filename": "lucky_egg", "rotated": false, "trimmed": true, "sourceSize": { @@ -6508,19 +6634,19 @@ }, "spriteSourceSize": { "x": 7, - "y": 7, - "w": 18, - "h": 18 + "y": 6, + "w": 17, + "h": 20 }, "frame": { - "x": 251, - "y": 320, - "w": 18, - "h": 18 + "x": 189, + "y": 329, + "w": 17, + "h": 20 } }, { - "filename": "wl_custom_thief", + "filename": "wl_custom_spliced", "rotated": false, "trimmed": true, "sourceSize": { @@ -6534,14 +6660,14 @@ "h": 18 }, "frame": { - "x": 269, - "y": 321, + "x": 207, + "y": 308, "w": 20, "h": 18 } }, { - "filename": "wl_elixir", + "filename": "wl_custom_thief", "rotated": false, "trimmed": true, "sourceSize": { @@ -6555,14 +6681,14 @@ "h": 18 }, "frame": { - "x": 289, - "y": 322, + "x": 227, + "y": 308, "w": 20, "h": 18 } }, { - "filename": "light_ball", + "filename": "wl_elixir", "rotated": false, "trimmed": true, "sourceSize": { @@ -6570,20 +6696,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, + "x": 6, + "y": 8, + "w": 20, "h": 18 }, "frame": { - "x": 235, - "y": 340, - "w": 18, + "x": 247, + "y": 308, + "w": 20, "h": 18 } }, { - "filename": "ampharosite", + "filename": "light_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -6591,20 +6717,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 + "x": 7, + "y": 7, + "w": 18, + "h": 18 }, "frame": { - "x": 253, - "y": 338, - "w": 16, - "h": 16 + "x": 188, + "y": 349, + "w": 18, + "h": 18 } }, { - "filename": "wl_ether", + "filename": "toxic_orb", "rotated": false, "trimmed": true, "sourceSize": { @@ -6612,20 +6738,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, + "x": 7, + "y": 7, + "w": 18, "h": 18 }, "frame": { - "x": 269, - "y": 339, - "w": 20, + "x": 188, + "y": 367, + "w": 18, "h": 18 } }, { - "filename": "wl_full_heal", + "filename": "aggronite", "rotated": false, "trimmed": true, "sourceSize": { @@ -6633,20 +6759,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, + "x": 8, "y": 8, - "w": 20, - "h": 18 + "w": 16, + "h": 16 }, "frame": { - "x": 289, - "y": 340, - "w": 20, - "h": 18 + "x": 267, + "y": 308, + "w": 16, + "h": 16 } }, { - "filename": "wl_full_restore", + "filename": "wl_ether", "rotated": false, "trimmed": true, "sourceSize": { @@ -6660,14 +6786,14 @@ "h": 18 }, "frame": { - "x": 310, - "y": 308, + "x": 283, + "y": 309, "w": 20, "h": 18 } }, { - "filename": "wl_guard_spec", + "filename": "wl_full_heal", "rotated": false, "trimmed": true, "sourceSize": { @@ -6681,14 +6807,14 @@ "h": 18 }, "frame": { - "x": 309, - "y": 326, + "x": 189, + "y": 385, "w": 20, "h": 18 } }, { - "filename": "wl_hyper_potion", + "filename": "wl_full_restore", "rotated": false, "trimmed": true, "sourceSize": { @@ -6702,14 +6828,14 @@ "h": 18 }, "frame": { - "x": 309, - "y": 344, + "x": 189, + "y": 403, "w": 20, "h": 18 } }, { - "filename": "wl_ice_heal", + "filename": "wl_guard_spec", "rotated": false, "trimmed": true, "sourceSize": { @@ -6723,14 +6849,14 @@ "h": 18 }, "frame": { - "x": 330, - "y": 309, + "x": 207, + "y": 326, "w": 20, "h": 18 } }, { - "filename": "wl_item_drop", + "filename": "wl_hyper_potion", "rotated": false, "trimmed": true, "sourceSize": { @@ -6744,14 +6870,14 @@ "h": 18 }, "frame": { - "x": 329, - "y": 327, + "x": 227, + "y": 326, "w": 20, "h": 18 } }, { - "filename": "wl_item_urge", + "filename": "wl_ice_heal", "rotated": false, "trimmed": true, "sourceSize": { @@ -6765,14 +6891,14 @@ "h": 18 }, "frame": { - "x": 329, - "y": 345, + "x": 247, + "y": 326, "w": 20, "h": 18 } }, { - "filename": "audinite", + "filename": "wl_item_drop", "rotated": false, "trimmed": true, "sourceSize": { @@ -6780,20 +6906,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, + "x": 6, "y": 8, - "w": 16, - "h": 16 + "w": 20, + "h": 18 }, "frame": { - "x": 253, - "y": 354, - "w": 16, - "h": 16 + "x": 206, + "y": 344, + "w": 20, + "h": 18 } }, { - "filename": "wl_max_elixir", + "filename": "wl_item_urge", "rotated": false, "trimmed": true, "sourceSize": { @@ -6807,14 +6933,14 @@ "h": 18 }, "frame": { - "x": 269, - "y": 357, + "x": 206, + "y": 362, "w": 20, "h": 18 } }, { - "filename": "wl_max_ether", + "filename": "wl_max_elixir", "rotated": false, "trimmed": true, "sourceSize": { @@ -6828,14 +6954,14 @@ "h": 18 }, "frame": { - "x": 289, - "y": 358, + "x": 226, + "y": 344, "w": 20, "h": 18 } }, { - "filename": "wl_max_potion", + "filename": "wl_max_ether", "rotated": false, "trimmed": true, "sourceSize": { @@ -6849,14 +6975,14 @@ "h": 18 }, "frame": { - "x": 309, + "x": 226, "y": 362, "w": 20, "h": 18 } }, { - "filename": "wl_max_revive", + "filename": "wl_max_potion", "rotated": false, "trimmed": true, "sourceSize": { @@ -6870,14 +6996,14 @@ "h": 18 }, "frame": { - "x": 329, - "y": 363, + "x": 246, + "y": 344, "w": 20, "h": 18 } }, { - "filename": "light_stone", + "filename": "wl_max_revive", "rotated": false, "trimmed": true, "sourceSize": { @@ -6885,20 +7011,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, + "x": 6, + "y": 8, + "w": 20, "h": 18 }, "frame": { - "x": 235, - "y": 358, - "w": 18, + "x": 246, + "y": 362, + "w": 20, "h": 18 } }, { - "filename": "banettite", + "filename": "alakazite", "rotated": false, "trimmed": true, "sourceSize": { @@ -6912,8 +7038,8 @@ "h": 16 }, "frame": { - "x": 253, - "y": 370, + "x": 267, + "y": 324, "w": 16, "h": 16 } @@ -6933,8 +7059,8 @@ "h": 18 }, "frame": { - "x": 269, - "y": 375, + "x": 209, + "y": 380, "w": 20, "h": 18 } @@ -6954,8 +7080,8 @@ "h": 18 }, "frame": { - "x": 289, - "y": 376, + "x": 209, + "y": 398, "w": 20, "h": 18 } @@ -6975,7 +7101,7 @@ "h": 18 }, "frame": { - "x": 309, + "x": 229, "y": 380, "w": 20, "h": 18 @@ -6996,8 +7122,8 @@ "h": 18 }, "frame": { - "x": 329, - "y": 381, + "x": 229, + "y": 398, "w": 20, "h": 18 } @@ -7017,14 +7143,14 @@ "h": 18 }, "frame": { - "x": 116, - "y": 357, + "x": 249, + "y": 380, "w": 20, "h": 18 } }, { - "filename": "toxic_orb", + "filename": "altarianite", "rotated": false, "trimmed": true, "sourceSize": { @@ -7032,20 +7158,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 18 + "x": 8, + "y": 8, + "w": 16, + "h": 16 }, "frame": { - "x": 115, - "y": 375, - "w": 18, - "h": 18 + "x": 249, + "y": 398, + "w": 16, + "h": 16 } }, { - "filename": "relic_band", + "filename": "ampharosite", "rotated": false, "trimmed": true, "sourceSize": { @@ -7053,15 +7179,57 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 17, + "x": 8, + "y": 8, + "w": 16, "h": 16 }, "frame": { - "x": 114, - "y": 393, - "w": 17, + "x": 283, + "y": 327, + "w": 16, + "h": 16 + } + }, + { + "filename": "audinite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 267, + "y": 340, + "w": 16, + "h": 16 + } + }, + { + "filename": "banettite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 266, + "y": 356, + "w": 16, "h": 16 } }, @@ -7080,8 +7248,8 @@ "h": 16 }, "frame": { - "x": 131, - "y": 399, + "x": 283, + "y": 343, "w": 16, "h": 16 } @@ -7101,8 +7269,8 @@ "h": 16 }, "frame": { - "x": 147, - "y": 399, + "x": 282, + "y": 359, "w": 16, "h": 16 } @@ -7122,8 +7290,8 @@ "h": 16 }, "frame": { - "x": 163, - "y": 399, + "x": 265, + "y": 398, "w": 16, "h": 16 } @@ -7143,8 +7311,8 @@ "h": 16 }, "frame": { - "x": 179, - "y": 399, + "x": 299, + "y": 327, "w": 16, "h": 16 } @@ -7164,8 +7332,8 @@ "h": 16 }, "frame": { - "x": 195, - "y": 399, + "x": 299, + "y": 343, "w": 16, "h": 16 } @@ -7185,8 +7353,8 @@ "h": 16 }, "frame": { - "x": 211, - "y": 399, + "x": 298, + "y": 359, "w": 16, "h": 16 } @@ -7206,8 +7374,8 @@ "h": 16 }, "frame": { - "x": 227, - "y": 399, + "x": 303, + "y": 309, "w": 16, "h": 16 } @@ -7227,8 +7395,8 @@ "h": 16 }, "frame": { - "x": 243, - "y": 399, + "x": 319, + "y": 308, "w": 16, "h": 16 } @@ -7248,8 +7416,8 @@ "h": 16 }, "frame": { - "x": 259, - "y": 399, + "x": 335, + "y": 306, "w": 16, "h": 16 } @@ -7269,14 +7437,14 @@ "h": 16 }, "frame": { - "x": 275, - "y": 399, + "x": 351, + "y": 306, "w": 16, "h": 16 } }, { - "filename": "gengarite", + "filename": "candy_overlay", "rotated": false, "trimmed": true, "sourceSize": { @@ -7285,19 +7453,19 @@ }, "spriteSourceSize": { "x": 8, - "y": 8, + "y": 12, "w": 16, - "h": 16 + "h": 15 }, "frame": { - "x": 291, - "y": 399, + "x": 367, + "y": 316, "w": 16, - "h": 16 + "h": 15 } }, { - "filename": "glalitite", + "filename": "gengarite", "rotated": false, "trimmed": true, "sourceSize": { @@ -7311,14 +7479,14 @@ "h": 16 }, "frame": { - "x": 307, - "y": 399, + "x": 383, + "y": 325, "w": 16, "h": 16 } }, { - "filename": "gyaradosite", + "filename": "glalitite", "rotated": false, "trimmed": true, "sourceSize": { @@ -7332,14 +7500,14 @@ "h": 16 }, "frame": { - "x": 323, - "y": 399, + "x": 399, + "y": 335, "w": 16, "h": 16 } }, { - "filename": "heracronite", + "filename": "gyaradosite", "rotated": false, "trimmed": true, "sourceSize": { @@ -7353,14 +7521,14 @@ "h": 16 }, "frame": { - "x": 339, - "y": 399, + "x": 315, + "y": 325, "w": 16, "h": 16 } }, { - "filename": "houndoominite", + "filename": "heracronite", "rotated": false, "trimmed": true, "sourceSize": { @@ -7374,14 +7542,14 @@ "h": 16 }, "frame": { - "x": 133, - "y": 375, + "x": 315, + "y": 341, "w": 16, "h": 16 } }, { - "filename": "candy_overlay", + "filename": "houndoominite", "rotated": false, "trimmed": true, "sourceSize": { @@ -7390,15 +7558,15 @@ }, "spriteSourceSize": { "x": 8, - "y": 12, + "y": 8, "w": 16, - "h": 15 + "h": 16 }, "frame": { - "x": 136, - "y": 360, + "x": 331, + "y": 324, "w": 16, - "h": 15 + "h": 16 } }, { @@ -7416,8 +7584,8 @@ "h": 16 }, "frame": { - "x": 152, - "y": 360, + "x": 331, + "y": 340, "w": 16, "h": 16 } @@ -7437,8 +7605,8 @@ "h": 16 }, "frame": { - "x": 149, - "y": 376, + "x": 347, + "y": 322, "w": 16, "h": 16 } @@ -7458,8 +7626,8 @@ "h": 16 }, "frame": { - "x": 168, - "y": 361, + "x": 347, + "y": 338, "w": 16, "h": 16 } @@ -7479,8 +7647,8 @@ "h": 16 }, "frame": { - "x": 184, - "y": 361, + "x": 363, + "y": 331, "w": 16, "h": 16 } @@ -7500,8 +7668,8 @@ "h": 16 }, "frame": { - "x": 200, - "y": 361, + "x": 363, + "y": 347, "w": 16, "h": 16 } @@ -7521,8 +7689,8 @@ "h": 16 }, "frame": { - "x": 216, - "y": 361, + "x": 379, + "y": 341, "w": 16, "h": 16 } @@ -7542,8 +7710,8 @@ "h": 16 }, "frame": { - "x": 165, - "y": 377, + "x": 347, + "y": 354, "w": 16, "h": 16 } @@ -7563,8 +7731,8 @@ "h": 16 }, "frame": { - "x": 181, - "y": 377, + "x": 331, + "y": 356, "w": 16, "h": 16 } @@ -7584,8 +7752,8 @@ "h": 16 }, "frame": { - "x": 197, - "y": 377, + "x": 315, + "y": 357, "w": 16, "h": 16 } @@ -7605,8 +7773,8 @@ "h": 16 }, "frame": { - "x": 213, - "y": 377, + "x": 363, + "y": 363, "w": 16, "h": 16 } @@ -7626,8 +7794,8 @@ "h": 16 }, "frame": { - "x": 229, - "y": 377, + "x": 379, + "y": 357, "w": 16, "h": 16 } @@ -7647,8 +7815,8 @@ "h": 16 }, "frame": { - "x": 349, - "y": 327, + "x": 395, + "y": 351, "w": 16, "h": 16 } @@ -7668,8 +7836,8 @@ "h": 16 }, "frame": { - "x": 349, - "y": 343, + "x": 347, + "y": 370, "w": 16, "h": 16 } @@ -7689,8 +7857,8 @@ "h": 16 }, "frame": { - "x": 349, - "y": 359, + "x": 331, + "y": 372, "w": 16, "h": 16 } @@ -7710,8 +7878,8 @@ "h": 16 }, "frame": { - "x": 349, - "y": 375, + "x": 363, + "y": 379, "w": 16, "h": 16 } @@ -7731,8 +7899,8 @@ "h": 16 }, "frame": { - "x": 365, - "y": 330, + "x": 379, + "y": 373, "w": 16, "h": 16 } @@ -7752,8 +7920,8 @@ "h": 16 }, "frame": { - "x": 381, - "y": 330, + "x": 395, + "y": 367, "w": 16, "h": 16 } @@ -7773,8 +7941,8 @@ "h": 16 }, "frame": { - "x": 365, - "y": 346, + "x": 347, + "y": 386, "w": 16, "h": 16 } @@ -7794,8 +7962,8 @@ "h": 16 }, "frame": { - "x": 365, - "y": 362, + "x": 363, + "y": 395, "w": 16, "h": 16 } @@ -7815,8 +7983,8 @@ "h": 16 }, "frame": { - "x": 381, - "y": 346, + "x": 379, + "y": 389, "w": 16, "h": 16 } @@ -7836,8 +8004,8 @@ "h": 16 }, "frame": { - "x": 381, - "y": 362, + "x": 395, + "y": 383, "w": 16, "h": 16 } @@ -7857,8 +8025,8 @@ "h": 16 }, "frame": { - "x": 397, - "y": 342, + "x": 379, + "y": 405, "w": 16, "h": 16 } @@ -7878,8 +8046,8 @@ "h": 16 }, "frame": { - "x": 397, - "y": 358, + "x": 395, + "y": 399, "w": 16, "h": 16 } @@ -7899,8 +8067,8 @@ "h": 16 }, "frame": { - "x": 365, - "y": 378, + "x": 314, + "y": 373, "w": 16, "h": 16 } @@ -7920,8 +8088,8 @@ "h": 16 }, "frame": { - "x": 381, - "y": 378, + "x": 330, + "y": 388, "w": 16, "h": 16 } @@ -7941,8 +8109,8 @@ "h": 16 }, "frame": { - "x": 397, - "y": 374, + "x": 346, + "y": 402, "w": 16, "h": 16 } @@ -7962,11 +8130,32 @@ "h": 16 }, "frame": { - "x": 397, - "y": 390, + "x": 281, + "y": 375, "w": 16, "h": 16 } + }, + { + "filename": "prism_scale", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 9, + "y": 8, + "w": 15, + "h": 15 + }, + "frame": { + "x": 297, + "y": 375, + "w": 15, + "h": 15 + } } ] } @@ -7974,6 +8163,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:d3848d1a2f1d71413dd485f5f629a4eb:a418dc4833fcd357930c1512c8417df7:110e074689c9edd2c54833ce2e4d9270$" + "smartupdate": "$TexturePacker:SmartUpdate:7ddaa91855ce79db7a72977126d431b4:c362d5547935cdfe138ac39e53b02773:110e074689c9edd2c54833ce2e4d9270$" } } diff --git a/public/images/items.png b/public/images/items.png index d9efd889f1fd..ddad2bad9d8e 100644 Binary files a/public/images/items.png and b/public/images/items.png differ diff --git a/public/images/items/baton.png b/public/images/items/baton.png index 43ec2b8a4568..8e9ebfae06d5 100644 Binary files a/public/images/items/baton.png and b/public/images/items/baton.png differ diff --git a/public/images/items/ribbon-gen1.png b/public/images/items/ribbon-gen1.png new file mode 100644 index 000000000000..a9774d18ad0b Binary files /dev/null and b/public/images/items/ribbon-gen1.png differ diff --git a/public/images/items/ribbon-gen2.png b/public/images/items/ribbon-gen2.png new file mode 100644 index 000000000000..a04f6a32a621 Binary files /dev/null and b/public/images/items/ribbon-gen2.png differ diff --git a/public/images/items/ribbon-gen3.png b/public/images/items/ribbon-gen3.png new file mode 100644 index 000000000000..0cf20ed92eed Binary files /dev/null and b/public/images/items/ribbon-gen3.png differ diff --git a/public/images/items/ribbon-gen4.png b/public/images/items/ribbon-gen4.png new file mode 100644 index 000000000000..aa24433b71b1 Binary files /dev/null and b/public/images/items/ribbon-gen4.png differ diff --git a/public/images/items/ribbon-gen5.png b/public/images/items/ribbon-gen5.png new file mode 100644 index 000000000000..7bb7800671f3 Binary files /dev/null and b/public/images/items/ribbon-gen5.png differ diff --git a/public/images/items/ribbon-gen6.png b/public/images/items/ribbon-gen6.png new file mode 100644 index 000000000000..e466eb78842b Binary files /dev/null and b/public/images/items/ribbon-gen6.png differ diff --git a/public/images/items/ribbon-gen7.png b/public/images/items/ribbon-gen7.png new file mode 100644 index 000000000000..9c156ebd1c60 Binary files /dev/null and b/public/images/items/ribbon-gen7.png differ diff --git a/public/images/items/ribbon-gen8.png b/public/images/items/ribbon-gen8.png new file mode 100644 index 000000000000..86b3748e348c Binary files /dev/null and b/public/images/items/ribbon-gen8.png differ diff --git a/public/images/items/ribbon-gen9.png b/public/images/items/ribbon-gen9.png new file mode 100644 index 000000000000..e9609daf3cd6 Binary files /dev/null and b/public/images/items/ribbon-gen9.png differ diff --git a/public/images/items/ribbon_gen1.png b/public/images/items/ribbon_gen1.png new file mode 100644 index 000000000000..a9774d18ad0b Binary files /dev/null and b/public/images/items/ribbon_gen1.png differ diff --git a/public/images/items/ribbon_gen2.png b/public/images/items/ribbon_gen2.png new file mode 100644 index 000000000000..a04f6a32a621 Binary files /dev/null and b/public/images/items/ribbon_gen2.png differ diff --git a/public/images/items/ribbon_gen3.png b/public/images/items/ribbon_gen3.png new file mode 100644 index 000000000000..0cf20ed92eed Binary files /dev/null and b/public/images/items/ribbon_gen3.png differ diff --git a/public/images/items/ribbon_gen4.png b/public/images/items/ribbon_gen4.png new file mode 100644 index 000000000000..aa24433b71b1 Binary files /dev/null and b/public/images/items/ribbon_gen4.png differ diff --git a/public/images/items/ribbon_gen5.png b/public/images/items/ribbon_gen5.png new file mode 100644 index 000000000000..7bb7800671f3 Binary files /dev/null and b/public/images/items/ribbon_gen5.png differ diff --git a/public/images/items/ribbon_gen6.png b/public/images/items/ribbon_gen6.png new file mode 100644 index 000000000000..e466eb78842b Binary files /dev/null and b/public/images/items/ribbon_gen6.png differ diff --git a/public/images/items/ribbon_gen7.png b/public/images/items/ribbon_gen7.png new file mode 100644 index 000000000000..9c156ebd1c60 Binary files /dev/null and b/public/images/items/ribbon_gen7.png differ diff --git a/public/images/items/ribbon_gen8.png b/public/images/items/ribbon_gen8.png new file mode 100644 index 000000000000..86b3748e348c Binary files /dev/null and b/public/images/items/ribbon_gen8.png differ diff --git a/public/images/items/ribbon_gen9.png b/public/images/items/ribbon_gen9.png new file mode 100644 index 000000000000..e9609daf3cd6 Binary files /dev/null and b/public/images/items/ribbon_gen9.png differ diff --git a/public/images/pokemon/802-zenith.png b/public/images/pokemon/802-zenith.png index b6db4621a0bb..17d2831a50ce 100644 Binary files a/public/images/pokemon/802-zenith.png and b/public/images/pokemon/802-zenith.png differ diff --git a/public/images/pokemon/back/700.png b/public/images/pokemon/back/700.png index cfd4063921b9..229c786c67eb 100644 Binary files a/public/images/pokemon/back/700.png and b/public/images/pokemon/back/700.png differ diff --git a/public/images/pokemon/back/802-zenith.png b/public/images/pokemon/back/802-zenith.png index 4158e0c1ed24..e38e295be753 100644 Binary files a/public/images/pokemon/back/802-zenith.png and b/public/images/pokemon/back/802-zenith.png differ diff --git a/public/images/pokemon/back/shiny/715.png b/public/images/pokemon/back/shiny/715.png index e71e12f74453..dfd07126e592 100644 Binary files a/public/images/pokemon/back/shiny/715.png and b/public/images/pokemon/back/shiny/715.png differ diff --git a/public/images/pokemon/back/shiny/802-zenith.png b/public/images/pokemon/back/shiny/802-zenith.png index 4158e0c1ed24..8e71dd7c7622 100644 Binary files a/public/images/pokemon/back/shiny/802-zenith.png and b/public/images/pokemon/back/shiny/802-zenith.png differ diff --git a/public/images/pokemon/back/shiny/982-three-segment.png b/public/images/pokemon/back/shiny/982-three-segment.png index 13d150bcdc72..11f855f93663 100644 Binary files a/public/images/pokemon/back/shiny/982-three-segment.png and b/public/images/pokemon/back/shiny/982-three-segment.png differ diff --git a/public/images/pokemon/back/shiny/982.png b/public/images/pokemon/back/shiny/982.png index df537fd151ce..3f72e2a644fc 100644 Binary files a/public/images/pokemon/back/shiny/982.png and b/public/images/pokemon/back/shiny/982.png differ diff --git a/public/images/pokemon/exp/380-mega.png b/public/images/pokemon/exp/380-mega.png index 50be5e401f3e..2a0cfa8797bc 100644 Binary files a/public/images/pokemon/exp/380-mega.png and b/public/images/pokemon/exp/380-mega.png differ diff --git a/public/images/pokemon/exp/381-mega.png b/public/images/pokemon/exp/381-mega.png index cf9addd7b12a..a40e3eb8655a 100644 Binary files a/public/images/pokemon/exp/381-mega.png and b/public/images/pokemon/exp/381-mega.png differ diff --git a/public/images/pokemon/female/6215.png b/public/images/pokemon/female/6215.png index 0bfb2114c0f4..c98bc4847b77 100644 Binary files a/public/images/pokemon/female/6215.png and b/public/images/pokemon/female/6215.png differ diff --git a/public/images/pokemon/shiny/802-zenith.png b/public/images/pokemon/shiny/802-zenith.png index b6db4621a0bb..28c5a5e68d9a 100644 Binary files a/public/images/pokemon/shiny/802-zenith.png and b/public/images/pokemon/shiny/802-zenith.png differ diff --git a/public/images/pokemon/variant/133-partner.json b/public/images/pokemon/variant/133-partner.json new file mode 100644 index 000000000000..1939d16ec225 --- /dev/null +++ b/public/images/pokemon/variant/133-partner.json @@ -0,0 +1,24 @@ +{ + "1": { + "a5634a": "5982b7", + "734a4a": "334b7d", + "d69c4a": "90c1f1", + "000000": "000000", + "523121": "13235c", + "e6c594": "9db5d8", + "bd9c7b": "5f6f94", + "ffffff": "ffffff", + "ffe6ad": "d7ebff" + }, + "2": { + "a5634a": "915ea3", + "734a4a": "5e3372", + "d69c4a": "bf88cb", + "000000": "000000", + "523121": "461144", + "e6c594": "d7b8ba", + "bd9c7b": "a07c83", + "ffffff": "ffffff", + "ffe6ad": "f3e6e3" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/169.json b/public/images/pokemon/variant/169.json index 3824fc5e3510..751102ef4a0a 100644 --- a/public/images/pokemon/variant/169.json +++ b/public/images/pokemon/variant/169.json @@ -1,19 +1,4 @@ { - "0": { - "7b4a9c": "d684ce", - "63197b": "9c528c", - "a55ace": "ffb5f7", - "101010": "101010", - "b57bce": "ffd6ef", - "08426b": "638400", - "ce0021": "940821", - "ffd600": "ffd600", - "d69400": "d69400", - "216b94": "8ca508", - "ffffff": "ffffff", - "a5a5a5": "a5a5a5", - "6b6b6b": "6b6b6b" - }, "1": { "7b4a9c": "2f2a5f", "63197b": "14093b", diff --git a/public/images/pokemon/variant/169_1.png b/public/images/pokemon/variant/169_1.png deleted file mode 100644 index 1baf868c278e..000000000000 Binary files a/public/images/pokemon/variant/169_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/41.json b/public/images/pokemon/variant/41.json index d3af6fbd948d..99ab116de024 100644 --- a/public/images/pokemon/variant/41.json +++ b/public/images/pokemon/variant/41.json @@ -1,28 +1,14 @@ { - "0": { - "101010": "101010", - "637bb5": "398422", - "4a427b": "084a00", - "bdceff": "99e870", - "8cb5ef": "5caf3b", - "b5529c": "bd9273", - "73215a": "a5785e", - "d673bd": "efd69c", - "ffffff": "ffffff", - "d6d6d6": "d6d6d6", - "636363": "636363" - }, "1": { "101010": "101010", - "637bb5": "37326f", + "637bb5": "12325c", "4a427b": "14093b", "bdceff": "868ecc", - "8cb5ef": "4e538f", - "b5529c": "cc7b32", - "73215a": "aa4c18", + "8cb5ef": "205182", + "b5529c": "d58e41", + "73215a": "b6591e", "d673bd": "f0ad57", "ffffff": "ffffff", - "d6d6d6": "d6d6d6", "636363": "636363" }, "2": { @@ -35,7 +21,6 @@ "73215a": "670f10", "d673bd": "bc3b1d", "ffffff": "ffffff", - "d6d6d6": "d6d6d6", "636363": "636363" } } \ No newline at end of file diff --git a/public/images/pokemon/variant/41_1.png b/public/images/pokemon/variant/41_1.png deleted file mode 100644 index 003d45e55918..000000000000 Binary files a/public/images/pokemon/variant/41_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/41_2.png b/public/images/pokemon/variant/41_2.png deleted file mode 100644 index 59605d5265a8..000000000000 Binary files a/public/images/pokemon/variant/41_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/41_3.png b/public/images/pokemon/variant/41_3.png deleted file mode 100644 index cd8c4542d2c5..000000000000 Binary files a/public/images/pokemon/variant/41_3.png and /dev/null differ diff --git a/public/images/pokemon/variant/42.json b/public/images/pokemon/variant/42.json index 74311a59fb22..af784a0fd2c7 100644 --- a/public/images/pokemon/variant/42.json +++ b/public/images/pokemon/variant/42.json @@ -1,31 +1,17 @@ { - "0": { - "3a3a7b": "142557", - "5aadef": "6265b4", - "6384ce": "323f81", - "631052": "093263", - "ce6bb5": "61b6da", - "adceff": "99a3ee", - "000000": "000000", - "ad52ad": "348cc1", - "636363": "636363", - "ffffff": "ffffff", - "d6d6d6": "d6d6d6", - "943a7b": "175990" - }, "1": { - "3a3a7b": "084a00", - "5aadef": "6b9c29", - "6384ce": "317300", - "631052": "c52931", - "ce6bb5": "ffada5", - "adceff": "84d64a", + "3a3a7b": "14093b", + "5aadef": "204882", + "6384ce": "12245c", + "631052": "892d03", + "ce6bb5": "f1a139", + "adceff": "3c74b1", "000000": "000000", - "ad52ad": "e6737b", + "ad52ad": "d5711b", "636363": "636363", "ffffff": "ffffff", "d6d6d6": "d6d6d6", - "943a7b": "d6525a" + "943a7b": "af4e0c" }, "2": { "3a3a7b": "3d2349", diff --git a/public/images/pokemon/variant/42_2.png b/public/images/pokemon/variant/42_2.png deleted file mode 100644 index 629e3a926f4d..000000000000 Binary files a/public/images/pokemon/variant/42_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/42_3.png b/public/images/pokemon/variant/42_3.png deleted file mode 100644 index 6fcfcbf1859d..000000000000 Binary files a/public/images/pokemon/variant/42_3.png and /dev/null differ diff --git a/public/images/pokemon/variant/622.json b/public/images/pokemon/variant/622.json index e43817498e77..9d3d631c473d 100644 --- a/public/images/pokemon/variant/622.json +++ b/public/images/pokemon/variant/622.json @@ -1,20 +1,4 @@ { - "0": { - "106b63": "0d1e10", - "004a52": "102c16", - "84cece": "758076", - "191921": "191921", - "29848c": "224427", - "298c8c": "1c3820", - "5aada5": "3e5d43", - "106b7b": "102c16", - "ffefa5": "ff9942", - "dece94": "e46424", - "bdad73": "cb3000", - "6b4200": "54190e", - "c59c52": "a65c3f", - "9c7329": "763826" - }, "1": { "106b63": "732d02", "004a52": "4c1b11", diff --git a/public/images/pokemon/variant/622_1.png b/public/images/pokemon/variant/622_1.png deleted file mode 100644 index 615a9a629ae1..000000000000 Binary files a/public/images/pokemon/variant/622_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/622_2.png b/public/images/pokemon/variant/622_2.png deleted file mode 100644 index 1ce1c3e9f0eb..000000000000 Binary files a/public/images/pokemon/variant/622_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/623.json b/public/images/pokemon/variant/623.json index d4a00ad94ba2..2a9f0774f9ae 100644 --- a/public/images/pokemon/variant/623.json +++ b/public/images/pokemon/variant/623.json @@ -1,19 +1,4 @@ { - "0": { - "297b8c": "152c18", - "105263": "041408", - "5aa5a5": "2b3c2d", - "195a7b": "051b0a", - "84c5ce": "3f4a3f", - "003a52": "020e06", - "191921": "191921", - "ffefa5": "ff9942", - "bdad73": "e46424", - "dece94": "cb3000", - "6b4200": "5e1c0b", - "c59c52": "ad5735", - "9c7329": "943b21" - }, "1": { "297b8c": "6b2808", "105263": "8b2a05", diff --git a/public/images/pokemon/variant/623_1.json b/public/images/pokemon/variant/623_1.json deleted file mode 100644 index 3a12266f1027..000000000000 --- a/public/images/pokemon/variant/623_1.json +++ /dev/null @@ -1,3590 +0,0 @@ -{ - "textures": [ - { - "image": "623_1.png", - "format": "RGBA8888", - "size": { - "w": 401, - "h": 401 - }, - "scale": 1, - "frames": [ - { - "filename": "0121.png", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 83, - "h": 80 - }, - "frame": { - "x": 0, - "y": 0, - "w": 83, - "h": 80 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 83, - "h": 80 - }, - "frame": { - "x": 0, - "y": 0, - "w": 83, - "h": 80 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 83, - "h": 80 - }, - "frame": { - "x": 0, - "y": 80, - "w": 83, - "h": 80 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 83, - "h": 80 - }, - "frame": { - "x": 0, - "y": 80, - "w": 83, - "h": 80 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 83, - "h": 80 - }, - "frame": { - "x": 83, - "y": 0, - "w": 83, - "h": 80 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 83, - "h": 80 - }, - "frame": { - "x": 83, - "y": 0, - "w": 83, - "h": 80 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 83, - "h": 79 - }, - "frame": { - "x": 0, - "y": 160, - "w": 83, - "h": 79 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 83, - "h": 79 - }, - "frame": { - "x": 0, - "y": 160, - "w": 83, - "h": 79 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 83, - "h": 79 - }, - "frame": { - "x": 83, - "y": 80, - "w": 83, - "h": 79 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 83, - "h": 79 - }, - "frame": { - "x": 83, - "y": 80, - "w": 83, - "h": 79 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 83, - "h": 79 - }, - "frame": { - "x": 166, - "y": 0, - "w": 83, - "h": 79 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 83, - "h": 79 - }, - "frame": { - "x": 166, - "y": 0, - "w": 83, - "h": 79 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 81, - "h": 80 - }, - "frame": { - "x": 0, - "y": 239, - "w": 81, - "h": 80 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 81, - "h": 80 - }, - "frame": { - "x": 0, - "y": 239, - "w": 81, - "h": 80 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 81, - "h": 80 - }, - "frame": { - "x": 83, - "y": 159, - "w": 81, - "h": 80 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 81, - "h": 80 - }, - "frame": { - "x": 83, - "y": 159, - "w": 81, - "h": 80 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 81, - "h": 80 - }, - "frame": { - "x": 166, - "y": 79, - "w": 81, - "h": 80 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 81, - "h": 80 - }, - "frame": { - "x": 166, - "y": 79, - "w": 81, - "h": 80 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0169.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0170.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 0, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0167.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0168.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 81, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 164, - "y": 159, - "w": 79, - "h": 80 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 164, - "y": 159, - "w": 79, - "h": 80 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 164, - "y": 159, - "w": 79, - "h": 80 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 164, - "y": 159, - "w": 79, - "h": 80 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 79, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 79, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 160, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 160, - "y": 239, - "w": 79, - "h": 80 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 158, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 158, - "y": 319, - "w": 79, - "h": 80 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0165.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0166.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 249, - "y": 0, - "w": 79, - "h": 79 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 247, - "y": 79, - "w": 79, - "h": 80 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 80 - }, - "frame": { - "x": 247, - "y": 79, - "w": 79, - "h": 80 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0163.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0164.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 79, - "h": 79 - }, - "frame": { - "x": 243, - "y": 159, - "w": 79, - "h": 79 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0145.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0146.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0161.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0162.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 79, - "h": 78 - }, - "frame": { - "x": 322, - "y": 159, - "w": 79, - "h": 78 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0147.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0148.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0159.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0160.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 3, - "w": 79, - "h": 77 - }, - "frame": { - "x": 322, - "y": 237, - "w": 79, - "h": 77 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0149.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0150.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0157.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0158.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 77 - }, - "frame": { - "x": 239, - "y": 239, - "w": 81, - "h": 77 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0151.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0152.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0155.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0156.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 81, - "h": 76 - }, - "frame": { - "x": 320, - "y": 314, - "w": 81, - "h": 76 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 82, - "h": 75 - }, - "frame": { - "x": 237, - "y": 319, - "w": 82, - "h": 75 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 82, - "h": 75 - }, - "frame": { - "x": 237, - "y": 319, - "w": 82, - "h": 75 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 82, - "h": 75 - }, - "frame": { - "x": 237, - "y": 319, - "w": 82, - "h": 75 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 82, - "h": 75 - }, - "frame": { - "x": 237, - "y": 319, - "w": 82, - "h": 75 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 82, - "h": 75 - }, - "frame": { - "x": 237, - "y": 319, - "w": 82, - "h": 75 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 82, - "h": 75 - }, - "frame": { - "x": 237, - "y": 319, - "w": 82, - "h": 75 - } - }, - { - "filename": "0153.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 82, - "h": 75 - }, - "frame": { - "x": 237, - "y": 319, - "w": 82, - "h": 75 - } - }, - { - "filename": "0154.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 83, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 5, - "w": 82, - "h": 75 - }, - "frame": { - "x": 237, - "y": 319, - "w": 82, - "h": 75 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:76e8001e2d30637bbf46d66a3c01cc86:32d4799151bd0a494e1cc16c07cc1afb:869abf8e0bcb859d5abfb33d03e5db07$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/623_1.png b/public/images/pokemon/variant/623_1.png deleted file mode 100644 index 836f46d459f2..000000000000 Binary files a/public/images/pokemon/variant/623_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/623_2.png b/public/images/pokemon/variant/623_2.png deleted file mode 100644 index fc7de7bdccbd..000000000000 Binary files a/public/images/pokemon/variant/623_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/802.json b/public/images/pokemon/variant/802.json index 841bb430fad5..95a92d8babc6 100644 --- a/public/images/pokemon/variant/802.json +++ b/public/images/pokemon/variant/802.json @@ -24,9 +24,9 @@ "f2a455": "ff9a50" }, "2": { - "2c3e30": "5a0423", - "6a806d": "ce3e63", - "536155": "97123b", + "2c3e30": "508294", + "6a806d": "a7eaee", + "536155": "82b7c3", "101010": "101010", "2d3137": "5a0423", "747778": "ce3e63", diff --git a/public/images/pokemon/variant/_masterlist.json b/public/images/pokemon/variant/_masterlist.json index 744c5ebf7198..c936fc8d0a1c 100644 --- a/public/images/pokemon/variant/_masterlist.json +++ b/public/images/pokemon/variant/_masterlist.json @@ -125,12 +125,12 @@ 1 ], "41": [ - 1, + 0, 1, 1 ], "42": [ - 1, + 0, 1, 1 ], @@ -364,6 +364,11 @@ 1, 1 ], + "133-partner": [ + 0, + 1, + 1 + ], "134": [ 0, 1, @@ -480,7 +485,7 @@ 2 ], "169": [ - 1, + 0, 1, 1 ], @@ -1895,12 +1900,12 @@ 1 ], "622": [ - 1, + 0, 1, 1 ], "623": [ - 2, + 0, 1, 1 ], @@ -1939,36 +1944,6 @@ 1, 1 ], - "641-incarnate": [ - 0, - 0, - 0 - ], - "641-therian": [ - 0, - 0, - 0 - ], - "642-incarnate": [ - 0, - 0, - 0 - ], - "642-therian": [ - 0, - 0, - 0 - ], - "645-incarnate": [ - 0, - 0, - 0 - ], - "645-therian": [ - 0, - 0, - 0 - ], "647-resolute": [ 0, 1, @@ -3389,6 +3364,11 @@ 1, 1, 1 + ], + "6215": [ + 0, + 1, + 1 ] }, "back": { @@ -3518,12 +3498,12 @@ 1 ], "41": [ - 1, + 0, 1, 1 ], "42": [ - 1, + 0, 1, 1 ], @@ -3757,6 +3737,11 @@ 1, 1 ], + "133-partner": [ + 0, + 1, + 1 + ], "134": [ 0, 1, @@ -3873,7 +3858,7 @@ 1 ], "169": [ - 1, + 0, 1, 1 ], @@ -5288,12 +5273,12 @@ 1 ], "622": [ - 1, + 0, 1, 1 ], "623": [ - 2, + 0, 1, 1 ], @@ -6772,6 +6757,11 @@ 1, 1, 1 + ], + "6215": [ + 0, + 1, + 1 ] } }, diff --git a/public/images/pokemon/variant/back/133-partner.json b/public/images/pokemon/variant/back/133-partner.json new file mode 100644 index 000000000000..d48eaad4364a --- /dev/null +++ b/public/images/pokemon/variant/back/133-partner.json @@ -0,0 +1,22 @@ +{ + "1": { + "734a4a": "13235c", + "523121": "0b1145", + "d69c4a": "90c1f1", + "a5634a": "5982b7", + "000000": "000000", + "ffe6ad": "d7ebff", + "bd9c7b": "5f6f94", + "e6c594": "8ca8d2" + }, + "2": { + "734a4a": "5e3372", + "523121": "461144", + "d69c4a": "bf88cb", + "a5634a": "915ea3", + "000000": "000000", + "ffe6ad": "f3e6e3", + "bd9c7b": "a07c83", + "e6c594": "cfa7a9" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/169.json b/public/images/pokemon/variant/back/169.json index b66c1c82caa4..34cfabeb5736 100644 --- a/public/images/pokemon/variant/back/169.json +++ b/public/images/pokemon/variant/back/169.json @@ -1,27 +1,18 @@ { - "0": { - "63197b": "142557", - "a55ace": "6265b4", - "7b4a9c": "323f81", - "b57bce": "99a3ee", - "101010": "101010", - "08426b": "206f9e", - "216b94": "4aa6ce" - }, "1": { - "63197b": "9c528c", - "a55ace": "ffb5f7", - "7b4a9c": "d684ce", - "b57bce": "ffd6ef", + "63197b": "14093b", + "a55ace": "3d4381", + "7b4a9c": "2f2a5f", + "b57bce": "666fb4", "101010": "101010", - "08426b": "638400", - "216b94": "8ca508" + "08426b": "b06130", + "216b94": "ffb049" }, "2": { "63197b": "3c1e39", - "a55ace": "b5a3b3", - "7b4a9c": "958093", - "b57bce": "d4c3d1", + "a55ace": "b49db2", + "7b4a9c": "80607b", + "b57bce": "c8b6c2", "101010": "101010", "08426b": "901606", "216b94": "b52c0c" diff --git a/public/images/pokemon/variant/back/41.json b/public/images/pokemon/variant/back/41.json index 6a75080db165..42283672198c 100644 --- a/public/images/pokemon/variant/back/41.json +++ b/public/images/pokemon/variant/back/41.json @@ -1,16 +1,4 @@ { - "0": { - "101010": "101010", - "8cb5ef": "6569c0", - "4a427b": "142557", - "637bb5": "323f81", - "73215a": "196297", - "b5529c": "61b6da", - "bdceff": "959ee9", - "ffffff": "ffffff", - "636363": "636363", - "d6d6d6": "d6d6d6" - }, "1": { "101010": "101010", "8cb5ef": "205182", @@ -25,12 +13,12 @@ }, "2": { "101010": "101010", - "8cb5ef": "c1aec0", + "8cb5ef": "cbabca", "4a427b": "4d3259", - "637bb5": "866881", + "637bb5": "916c8b", "73215a": "670f10", "b5529c": "94241c", - "bdceff": "dfcddd", + "bdceff": "e8d2e6", "ffffff": "ffffff", "636363": "636363", "d6d6d6": "d6d6d6" diff --git a/public/images/pokemon/variant/back/41_1.png b/public/images/pokemon/variant/back/41_1.png deleted file mode 100644 index 6943a2eddb47..000000000000 Binary files a/public/images/pokemon/variant/back/41_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/back/42.json b/public/images/pokemon/variant/back/42.json index 54417a7af59a..df3cf67d3ef3 100644 --- a/public/images/pokemon/variant/back/42.json +++ b/public/images/pokemon/variant/back/42.json @@ -1,15 +1,4 @@ { - "0": { - "3a3a7b": "142557", - "6384ce": "323f81", - "adceff": "99a3ee", - "5aadef": "6265b4", - "631052": "093263", - "000000": "000000", - "ce6bb5": "61b6da", - "ad52ad": "348cc1", - "943a7b": "348cc1" - }, "1": { "3a3a7b": "14093b", "6384ce": "12245c", @@ -22,10 +11,10 @@ "943a7b": "af4e0c" }, "2": { - "3a3a7b": "584055", - "6384ce": "866881", + "3a3a7b": "3d2349", + "6384ce": "916c8b", "adceff": "dfcddd", - "5aadef": "c1aec0", + "5aadef": "cbabca", "631052": "54070c", "000000": "000000", "ce6bb5": "bc3b1d", diff --git a/public/images/pokemon/variant/back/42_1.png b/public/images/pokemon/variant/back/42_1.png deleted file mode 100644 index 2f649cdc6490..000000000000 Binary files a/public/images/pokemon/variant/back/42_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/back/445.json b/public/images/pokemon/variant/back/445.json index c5b10066d10c..7bf76d032123 100644 --- a/public/images/pokemon/variant/back/445.json +++ b/public/images/pokemon/variant/back/445.json @@ -1,8 +1,8 @@ { "0": { - "292952": "091f4e", - "5a63ad": "33719e", - "42428c": "1e4b77", + "292952": "0a1347", + "5a63ad": "226596", + "42428c": "264074", "7b7bce": "65a2d5", "101010": "101010", "c59410": "3aadc5", diff --git a/public/images/pokemon/variant/back/622.json b/public/images/pokemon/variant/back/622.json index 9ad7426a9d7c..97f38954babc 100644 --- a/public/images/pokemon/variant/back/622.json +++ b/public/images/pokemon/variant/back/622.json @@ -1,20 +1,4 @@ { - "0": { - "298c8c": "427373", - "5aada5": "6b9c94", - "84cece": "94bdbd", - "004a52": "192121", - "106b63": "21524a", - "191921": "191921", - "106b7b": "293a42", - "29848c": "424a5a", - "6b4200": "523a10", - "c59c52": "b59463", - "9c7329": "846b3a", - "dece94": "b5de21", - "ffefa5": "d6ff42", - "bdad73": "94bd00" - }, "1": { "298c8c": "793907", "5aada5": "9d5915", diff --git a/public/images/pokemon/variant/back/622_1.png b/public/images/pokemon/variant/back/622_1.png deleted file mode 100644 index 8caa7b15ac00..000000000000 Binary files a/public/images/pokemon/variant/back/622_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/back/622_2.png b/public/images/pokemon/variant/back/622_2.png deleted file mode 100644 index 9e57b6fd73ad..000000000000 Binary files a/public/images/pokemon/variant/back/622_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/back/623.json b/public/images/pokemon/variant/back/623.json index 56017b98f59c..7c3429ecb261 100644 --- a/public/images/pokemon/variant/back/623.json +++ b/public/images/pokemon/variant/back/623.json @@ -1,16 +1,4 @@ { - "0": { - "003a52": "020e06", - "195a7b": "051b0a", - "191921": "191921", - "297b8c": "152c18", - "84c5ce": "3f4a3f", - "5aa5a5": "2b3c2d", - "105263": "041408", - "6b4200": "54190e", - "9c7329": "763826", - "c59c52": "a65c3f" - }, "1": { "003a52": "471205", "195a7b": "4d0a00", diff --git a/public/images/pokemon/variant/back/623_1.json b/public/images/pokemon/variant/back/623_1.json deleted file mode 100644 index 893fe66c597f..000000000000 --- a/public/images/pokemon/variant/back/623_1.json +++ /dev/null @@ -1,3590 +0,0 @@ -{ - "textures": [ - { - "image": "623_1.png", - "format": "RGBA8888", - "size": { - "w": 392, - "h": 392 - }, - "scale": 1, - "frames": [ - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 78, - "h": 79 - }, - "frame": { - "x": 0, - "y": 0, - "w": 78, - "h": 79 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 78, - "h": 79 - }, - "frame": { - "x": 0, - "y": 0, - "w": 78, - "h": 79 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 78, - "h": 78 - }, - "frame": { - "x": 0, - "y": 79, - "w": 78, - "h": 78 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 78, - "h": 78 - }, - "frame": { - "x": 0, - "y": 79, - "w": 78, - "h": 78 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 78, - "h": 78 - }, - "frame": { - "x": 78, - "y": 0, - "w": 78, - "h": 78 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 78, - "h": 78 - }, - "frame": { - "x": 78, - "y": 0, - "w": 78, - "h": 78 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 78, - "h": 78 - }, - "frame": { - "x": 78, - "y": 0, - "w": 78, - "h": 78 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 78, - "h": 78 - }, - "frame": { - "x": 78, - "y": 0, - "w": 78, - "h": 78 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 78, - "h": 78 - }, - "frame": { - "x": 0, - "y": 157, - "w": 78, - "h": 78 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 78, - "h": 78 - }, - "frame": { - "x": 0, - "y": 157, - "w": 78, - "h": 78 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 77, - "h": 79 - }, - "frame": { - "x": 78, - "y": 78, - "w": 77, - "h": 79 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 77, - "h": 79 - }, - "frame": { - "x": 78, - "y": 78, - "w": 77, - "h": 79 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 76, - "h": 80 - }, - "frame": { - "x": 0, - "y": 235, - "w": 76, - "h": 80 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 76, - "h": 80 - }, - "frame": { - "x": 0, - "y": 235, - "w": 76, - "h": 80 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0151.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0152.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0155.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0156.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 74, - "h": 77 - }, - "frame": { - "x": 0, - "y": 315, - "w": 74, - "h": 77 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 75, - "h": 79 - }, - "frame": { - "x": 156, - "y": 0, - "w": 75, - "h": 79 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 75, - "h": 79 - }, - "frame": { - "x": 156, - "y": 0, - "w": 75, - "h": 79 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 74, - "h": 80 - }, - "frame": { - "x": 231, - "y": 0, - "w": 74, - "h": 80 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 74, - "h": 80 - }, - "frame": { - "x": 231, - "y": 0, - "w": 74, - "h": 80 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0169.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0170.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 305, - "y": 0, - "w": 73, - "h": 80 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0149.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0150.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0157.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0158.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 2, - "w": 74, - "h": 78 - }, - "frame": { - "x": 78, - "y": 157, - "w": 74, - "h": 78 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 76, - "y": 235, - "w": 73, - "h": 80 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 73, - "h": 80 - }, - "frame": { - "x": 76, - "y": 235, - "w": 73, - "h": 80 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 75, - "h": 76 - }, - "frame": { - "x": 74, - "y": 315, - "w": 75, - "h": 76 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 75, - "h": 76 - }, - "frame": { - "x": 74, - "y": 315, - "w": 75, - "h": 76 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 75, - "h": 76 - }, - "frame": { - "x": 74, - "y": 315, - "w": 75, - "h": 76 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 75, - "h": 76 - }, - "frame": { - "x": 74, - "y": 315, - "w": 75, - "h": 76 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 75, - "h": 76 - }, - "frame": { - "x": 74, - "y": 315, - "w": 75, - "h": 76 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 75, - "h": 76 - }, - "frame": { - "x": 74, - "y": 315, - "w": 75, - "h": 76 - } - }, - { - "filename": "0153.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 75, - "h": 76 - }, - "frame": { - "x": 74, - "y": 315, - "w": 75, - "h": 76 - } - }, - { - "filename": "0154.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 75, - "h": 76 - }, - "frame": { - "x": 74, - "y": 315, - "w": 75, - "h": 76 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0167.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0168.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 155, - "y": 79, - "w": 72, - "h": 80 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0165.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0166.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 227, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0163.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0164.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 299, - "y": 80, - "w": 72, - "h": 80 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0145.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0146.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0161.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0162.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 72, - "h": 79 - }, - "frame": { - "x": 152, - "y": 159, - "w": 72, - "h": 79 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 149, - "y": 238, - "w": 72, - "h": 80 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 149, - "y": 238, - "w": 72, - "h": 80 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 149, - "y": 238, - "w": 72, - "h": 80 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 149, - "y": 238, - "w": 72, - "h": 80 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0147.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0148.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0159.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0160.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 2, - "w": 72, - "h": 78 - }, - "frame": { - "x": 224, - "y": 160, - "w": 72, - "h": 78 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 221, - "y": 238, - "w": 72, - "h": 80 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 221, - "y": 238, - "w": 72, - "h": 80 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 296, - "y": 160, - "w": 72, - "h": 80 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 72, - "h": 80 - }, - "frame": { - "x": 296, - "y": 160, - "w": 72, - "h": 80 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 71, - "h": 80 - }, - "frame": { - "x": 293, - "y": 240, - "w": 71, - "h": 80 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 78, - "h": 80 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 71, - "h": 80 - }, - "frame": { - "x": 293, - "y": 240, - "w": 71, - "h": 80 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:d2a0b4f8d67951bad9facc61ed8ecd29:029ea763f8f267a92908e8da6c5b70c9:869abf8e0bcb859d5abfb33d03e5db07$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/623_1.png b/public/images/pokemon/variant/back/623_1.png deleted file mode 100644 index b02cc7645022..000000000000 Binary files a/public/images/pokemon/variant/back/623_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/back/623_2.png b/public/images/pokemon/variant/back/623_2.png deleted file mode 100644 index 456f439cd860..000000000000 Binary files a/public/images/pokemon/variant/back/623_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/back/female/6215.json b/public/images/pokemon/variant/back/female/6215.json new file mode 100644 index 000000000000..741d6ddc0bbb --- /dev/null +++ b/public/images/pokemon/variant/back/female/6215.json @@ -0,0 +1,32 @@ +{ + "1": { + "724ca2": "12968b", + "503678": "0f5d6d", + "956cbe": "31dabb", + "9c9bce": "ae8976", + "514a80": "402010", + "dcdbf7": "d0b3a4", + "080808": "080808", + "28234b": "220d0a", + "7d6ca4": "853a36", + "584d80": "562627", + "f6f6ff": "f6f6ff", + "bdbdc5": "bdbdc5", + "c52973": "ea903f" + }, + "2": { + "724ca2": "982e33", + "503678": "601522", + "956cbe": "cc5427", + "9c9bce": "3c8775", + "514a80": "14273a", + "dcdbf7": "60ae7e", + "080808": "080808", + "28234b": "0a191e", + "7d6ca4": "395962", + "584d80": "1c3942", + "f6f6ff": "f6f6ff", + "bdbdc5": "bdbdc5", + "c52973": "f49633" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/exp/380-mega.json b/public/images/pokemon/variant/exp/380-mega.json index 8774aec6dcdf..aedcc39909c6 100644 --- a/public/images/pokemon/variant/exp/380-mega.json +++ b/public/images/pokemon/variant/exp/380-mega.json @@ -9,8 +9,8 @@ "ffffff": "fafafa", "7b73a4": "b48f79", "cdcdee": "f3e6df", - "ff005a": "6734bf", - "62004a": "97440c", + "ffcd5a": "9b75ff", + "cda44a": "6734bf", "cd4a52": "6734bf" }, "2": { @@ -23,8 +23,8 @@ "ffffff": "fafafa", "7b73a4": "c78ac4", "cdcdee": "eedaea", - "ff005a": "dd6800", - "62004a": "2393a2", + "ffcd5a": "e88a00", + "cda44a": "dd6800", "cd4a52": "dd6800" } -} \ No newline at end of file +} diff --git a/public/images/pokemon/variant/exp/381-mega.json b/public/images/pokemon/variant/exp/381-mega.json index 5b4d0638c6d6..bb5b7cffd0b8 100644 --- a/public/images/pokemon/variant/exp/381-mega.json +++ b/public/images/pokemon/variant/exp/381-mega.json @@ -9,8 +9,8 @@ "ffffff": "fafafa", "7b73a4": "b673ad", "cdcdee": "f9cfed", - "ffcd5a": "f78232", - "cda44a": "f78232", + "ff005a": "f78232", + "62004a": "f78232", "cd4a52": "d05718" }, "2": { @@ -23,8 +23,8 @@ "ffffff": "fafafa", "7b73a4": "d086ac", "cdcdee": "f7d9ec", - "ffcd5a": "9344b8", - "cda44a": "9344b8", + "ff005a": "9344b8", + "62004a": "9344b8", "cd4a52": "70309f" } -} \ No newline at end of file +} diff --git a/public/images/pokemon/variant/female/118.json b/public/images/pokemon/variant/female/118.json index 659fcbf17d3b..ba5a9377fdb7 100644 --- a/public/images/pokemon/variant/female/118.json +++ b/public/images/pokemon/variant/female/118.json @@ -1,22 +1,5 @@ { "1": { - "52525a": "2e5453", - "ffffff": "f0fff8", - "101010": "101010", - "8c8c94": "4c867a", - "d6d6de": "9cd8c4", - "efefef": "c3f0dd", - "ceb57b": "65aaae", - "ffc57b": "5addc9", - "ef7b42": "4cb5b1", - "d64210": "2a7580", - "ad1000": "174a5a", - "006b63": "8c3824", - "42ada5": "af704f", - "ad5273": "1f562f", - "f7848c": "5e9964" - }, - "2": { "52525a": "5b3856", "ffffff": "fff9fc", "101010": "101010", @@ -32,5 +15,22 @@ "42ada5": "ffdf5b", "ad5273": "762066", "f7848c": "c450a5" + }, + "2": { + "52525a": "2e5453", + "ffffff": "f0fff8", + "101010": "101010", + "8c8c94": "4c867a", + "d6d6de": "9cd8c4", + "efefef": "c3f0dd", + "ceb57b": "65aaae", + "ffc57b": "5addc9", + "ef7b42": "4cb5b1", + "d64210": "2a7580", + "ad1000": "174a5a", + "006b63": "8c3824", + "42ada5": "af704f", + "ad5273": "1f562f", + "f7848c": "5e9964" } } \ No newline at end of file diff --git a/public/images/pokemon/variant/female/41_2.png b/public/images/pokemon/variant/female/41_2.png deleted file mode 100644 index 9ef30a5e98e3..000000000000 Binary files a/public/images/pokemon/variant/female/41_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/female/41_3.png b/public/images/pokemon/variant/female/41_3.png deleted file mode 100644 index cbc73b705154..000000000000 Binary files a/public/images/pokemon/variant/female/41_3.png and /dev/null differ diff --git a/public/images/pokemon/variant/female/42_2.png b/public/images/pokemon/variant/female/42_2.png deleted file mode 100644 index a8183eaf60be..000000000000 Binary files a/public/images/pokemon/variant/female/42_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/female/42_3.png b/public/images/pokemon/variant/female/42_3.png deleted file mode 100644 index a0029ba8548e..000000000000 Binary files a/public/images/pokemon/variant/female/42_3.png and /dev/null differ diff --git a/public/images/pokemon/variant/female/6215.json b/public/images/pokemon/variant/female/6215.json new file mode 100644 index 000000000000..99e0c880142e --- /dev/null +++ b/public/images/pokemon/variant/female/6215.json @@ -0,0 +1,36 @@ +{ + "1": { + "503678": "0f5d6d", + "080808": "080808", + "514a80": "402010", + "956cbe": "31dabb", + "9c9bce": "ae8976", + "724ca2": "12968b", + "dcdbf7": "d0b3a4", + "7d6ca4": "853a36", + "c58b08": "6e6f6f", + "ffde7b": "a7a7a7", + "584d80": "562627", + "28234b": "220d0a", + "c52973": "ea903f", + "bdbdc5": "bdbdc5", + "f6f6ff": "f6f6ff" + }, + "2": { + "503678": "601522", + "080808": "080808", + "514a80": "14273a", + "956cbe": "cc5427", + "9c9bce": "3c8775", + "724ca2": "982e33", + "dcdbf7": "60ae7e", + "7d6ca4": "395962", + "c58b08": "ffa341", + "ffde7b": "ffe07e", + "584d80": "1c3942", + "28234b": "0a191e", + "c52973": "f49633", + "bdbdc5": "bdbdc5", + "f6f6ff": "f6f6ff" + } +} \ No newline at end of file diff --git a/public/images/ui/legacy/scroll_bar.png b/public/images/ui/legacy/scroll_bar.png new file mode 100644 index 000000000000..e4e5eb34dd2c Binary files /dev/null and b/public/images/ui/legacy/scroll_bar.png differ diff --git a/public/images/ui/legacy/scroll_bar_handle.png b/public/images/ui/legacy/scroll_bar_handle.png new file mode 100644 index 000000000000..95a1726b3bad Binary files /dev/null and b/public/images/ui/legacy/scroll_bar_handle.png differ diff --git a/public/images/ui/legacy/starter_container_bg.png b/public/images/ui/legacy/starter_container_bg.png new file mode 100644 index 000000000000..5b60fcf551e5 Binary files /dev/null and b/public/images/ui/legacy/starter_container_bg.png differ diff --git a/public/images/ui/scroll_bar.png b/public/images/ui/scroll_bar.png new file mode 100644 index 000000000000..e4e5eb34dd2c Binary files /dev/null and b/public/images/ui/scroll_bar.png differ diff --git a/public/images/ui/scroll_bar_handle.png b/public/images/ui/scroll_bar_handle.png new file mode 100644 index 000000000000..95a1726b3bad Binary files /dev/null and b/public/images/ui/scroll_bar_handle.png differ diff --git a/public/images/ui/starter_container_bg.png b/public/images/ui/starter_container_bg.png new file mode 100644 index 000000000000..5b60fcf551e5 Binary files /dev/null and b/public/images/ui/starter_container_bg.png differ diff --git a/public/images/ui/starter_select_bg.png b/public/images/ui/starter_select_bg.png index f02182fe1409..8b11f55a9636 100644 Binary files a/public/images/ui/starter_select_bg.png and b/public/images/ui/starter_select_bg.png differ diff --git a/src/battle-scene.ts b/src/battle-scene.ts index e9f5414caff8..390b5acd90d5 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -180,11 +180,16 @@ export default class BattleScene extends SceneBase { public gameData: GameData; public sessionSlotId: integer; + /** PhaseQueue: dequeue/remove the first element to get the next phase */ public phaseQueue: Phase[]; public conditionalQueue: Array<[() => boolean, Phase]>; + /** PhaseQueuePrepend: is a temp storage of what will be added to PhaseQueue */ private phaseQueuePrepend: Phase[]; + + /** overrides default of inserting phases to end of phaseQueuePrepend array, useful or inserting Phases "out of order" */ private phaseQueuePrependSpliceIndex: integer; private nextCommandPhaseQueue: Phase[]; + private currentPhase: Phase; private standbyPhase: Phase; public field: Phaser.GameObjects.Container; @@ -1073,11 +1078,11 @@ export default class BattleScene extends SceneBase { newDouble = !!double; } - if (Overrides.DOUBLE_BATTLE_OVERRIDE) { + if (Overrides.BATTLE_TYPE_OVERRIDE === "double") { newDouble = true; } /* Override battles into single only if not fighting with trainers */ - if (newBattleType !== BattleType.TRAINER && Overrides.SINGLE_BATTLE_OVERRIDE) { + if (newBattleType !== BattleType.TRAINER && Overrides.BATTLE_TYPE_OVERRIDE === "single") { newDouble = false; } @@ -1973,6 +1978,7 @@ export default class BattleScene extends SceneBase { return this.standbyPhase; } + /** * Adds a phase to the conditional queue and ensures it is executed only when the specified condition is met. * @@ -1987,11 +1993,19 @@ export default class BattleScene extends SceneBase { this.conditionalQueue.push([condition, phase]); } - + /** + * Adds a phase to nextCommandPhaseQueue, as long as boolean passed in is false + * @param phase {@linkcode Phase} the phase to add + * @param defer boolean on which queue to add to, defaults to false, and adds to phaseQueue + */ pushPhase(phase: Phase, defer: boolean = false): void { (!defer ? this.phaseQueue : this.nextCommandPhaseQueue).push(phase); } + /** + * Adds Phase to the end of phaseQueuePrepend, or at phaseQueuePrependSpliceIndex + * @param phase {@linkcode Phase} the phase to add + */ unshiftPhase(phase: Phase): void { if (this.phaseQueuePrependSpliceIndex === -1) { this.phaseQueuePrepend.push(phase); @@ -2000,18 +2014,32 @@ export default class BattleScene extends SceneBase { } } + /** + * Clears the phaseQueue + */ clearPhaseQueue(): void { this.phaseQueue.splice(0, this.phaseQueue.length); } + /** + * Used by function unshiftPhase(), sets index to start inserting at current length instead of the end of the array, useful if phaseQueuePrepend gets longer with Phases + */ setPhaseQueueSplice(): void { this.phaseQueuePrependSpliceIndex = this.phaseQueuePrepend.length; } + /** + * Resets phaseQueuePrependSpliceIndex to -1, implies that calls to unshiftPhase will insert at end of phaseQueuePrepend + */ clearPhaseQueueSplice(): void { this.phaseQueuePrependSpliceIndex = -1; } + /** + * Is called by each Phase implementations "end()" by default + * We dump everything from phaseQueuePrepend to the start of of phaseQueue + * then removes first Phase and starts it + */ shiftPhase(): void { if (this.standbyPhase) { this.currentPhase = this.standbyPhase; @@ -2029,7 +2057,7 @@ export default class BattleScene extends SceneBase { } if (!this.phaseQueue.length) { this.populatePhaseQueue(); - // clear the conditionalQueue if there are no phases left in the phaseQueue + // Clear the conditionalQueue if there are no phases left in the phaseQueue this.conditionalQueue = []; } this.currentPhase = this.phaseQueue.shift(); @@ -2040,8 +2068,8 @@ export default class BattleScene extends SceneBase { const conditionalPhase = this.conditionalQueue.shift(); // Evaluate the condition associated with the phase if (conditionalPhase[0]()) { - // If the condition is met, add the phase to the front of the phase queue - this.unshiftPhase(conditionalPhase[1]); + // If the condition is met, add the phase to the phase queue + this.pushPhase(conditionalPhase[1]); } else { // If the condition is not met, re-add the phase back to the front of the conditional queue this.conditionalQueue.unshift(conditionalPhase); @@ -2114,15 +2142,28 @@ export default class BattleScene extends SceneBase { } } + /** + * Adds a MessagePhase, either to PhaseQueuePrepend or nextCommandPhaseQueue + * @param message string for MessagePhase + * @param callbackDelay optional param for MessagePhase constructor + * @param prompt optional param for MessagePhase constructor + * @param promptDelay optional param for MessagePhase constructor + * @param defer boolean for which queue to add it to, false -> add to PhaseQueuePrepend, true -> nextCommandPhaseQueue + */ queueMessage(message: string, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer, defer?: boolean) { const phase = new MessagePhase(this, message, callbackDelay, prompt, promptDelay); if (!defer) { + // adds to the end of PhaseQueuePrepend this.unshiftPhase(phase); } else { + //remember that pushPhase adds it to nextCommandPhaseQueue this.pushPhase(phase); } } + /** + * Moves everything from nextCommandPhaseQueue to phaseQueue (keeping order) + */ populatePhaseQueue(): void { if (this.nextCommandPhaseQueue.length) { this.phaseQueue.push(...this.nextCommandPhaseQueue); diff --git a/src/battle.ts b/src/battle.ts index 474d33819236..3ba635d47f44 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -294,9 +294,20 @@ export default class Battle { if (pokemon.species.speciesId === Species.TAPU_KOKO || pokemon.species.speciesId === Species.TAPU_LELE || pokemon.species.speciesId === Species.TAPU_BULU || pokemon.species.speciesId === Species.TAPU_FINI) { return "battle_legendary_tapu"; } - if (pokemon.species.speciesId === Species.COSMOG || pokemon.species.speciesId === Species.COSMOEM || pokemon.species.speciesId === Species.SOLGALEO || pokemon.species.speciesId === Species.LUNALA || pokemon.species.speciesId === Species.NECROZMA) { + if (pokemon.species.speciesId === Species.COSMOG || pokemon.species.speciesId === Species.COSMOEM || pokemon.species.speciesId === Species.SOLGALEO || pokemon.species.speciesId === Species.LUNALA) { return "battle_legendary_sol_lun"; } + if (pokemon.species.speciesId === Species.NECROZMA) { + if (pokemon.getFormKey() === "") { + return "battle_legendary_sol_lun"; + } + if (pokemon.getFormKey() === "dusk-mane" || pokemon.getFormKey() === "dawn-wings") { + return "battle_legendary_dusk_dawn"; + } + if (pokemon.getFormKey() === "ultra") { + return "battle_legendary_ultra_nec"; + } + } if (pokemon.species.speciesId === Species.NIHILEGO || pokemon.species.speciesId === Species.BUZZWOLE || pokemon.species.speciesId === Species.PHEROMOSA || pokemon.species.speciesId === Species.XURKITREE || pokemon.species.speciesId === Species.CELESTEELA || pokemon.species.speciesId === Species.KARTANA || pokemon.species.speciesId === Species.GUZZLORD || pokemon.species.speciesId === Species.POIPOLE || pokemon.species.speciesId === Species.NAGANADEL || pokemon.species.speciesId === Species.STAKATAKA || pokemon.species.speciesId === Species.BLACEPHALON) { return "battle_legendary_ub"; } diff --git a/src/data/ability.ts b/src/data/ability.ts index e02c2afd4f53..40461f72e971 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -266,7 +266,7 @@ export class PreDefendFormChangeAbAttr extends PreDefendAbAttr { } export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr { applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (pokemon.hp === pokemon.getMaxHp() && + if (pokemon.isFullHp() && pokemon.getMaxHp() > 1 && //Checks if pokemon has wonder_guard (which forces 1hp) (args[0] as Utils.NumberHolder).value >= pokemon.hp) { //Damage >= hp return pokemon.addTag(BattlerTagType.STURDY, 1); @@ -400,7 +400,7 @@ export class TypeImmunityHealAbAttr extends TypeImmunityAbAttr { const ret = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (ret) { - if (pokemon.getHpRatio() < 1) { + if (!pokemon.isFullHp()) { const simulated = args.length > 1 && args[1]; if (!simulated) { const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; @@ -752,7 +752,7 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr { if (this.condition(pokemon, attacker, move)) { if (!pokemon.getTag(this.tagType)) { pokemon.addTag(this.tagType, undefined, undefined, pokemon.id); - pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: move.name })); + pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name })); } return true; } @@ -1083,7 +1083,9 @@ export class MoveEffectChanceMultiplierAbAttr extends AbAttr { * [1]: {@linkcode Moves } Move used by the ability user. */ apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - + //Disable showAbility during getTargetBenefitScore + const showAbility = args[4]; + this.showAbility = showAbility; if ((args[0] as Utils.NumberHolder).value <= 0 || (args[1] as Move).id === Moves.ORDER_UP) { return false; } @@ -2281,7 +2283,7 @@ export class PreSwitchOutClearWeatherAbAttr extends PreSwitchOutAbAttr { export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr { applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { - if (pokemon.getHpRatio() < 1 ) { + if (!pokemon.isFullHp()) { const healAmount = Math.floor(pokemon.getMaxHp() * 0.33); pokemon.heal(healAmount); pokemon.updateInfo(); @@ -2838,7 +2840,7 @@ export class PostWeatherLapseHealAbAttr extends PostWeatherLapseAbAttr { } applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, weather: Weather, args: any[]): boolean { - if (pokemon.getHpRatio() < 1) { + if (!pokemon.isFullHp()) { const scene = pokemon.scene; const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), @@ -2932,11 +2934,11 @@ export class PostTurnStatusHealAbAttr extends PostTurnAbAttr { */ applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { if (this.effects.includes(pokemon.status?.effect)) { - if (pokemon.getMaxHp() !== pokemon.hp) { + if (!pokemon.isFullHp()) { const scene = pokemon.scene; const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), - Math.max(Math.floor(pokemon.getMaxHp() / 8), 1), i18next.t("abilityTriggers:poisonHeal", { pokemonName: pokemon.name, abilityName: abilityName}), true)); + Math.max(Math.floor(pokemon.getMaxHp() / 8), 1), i18next.t("abilityTriggers:poisonHeal", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName}), true)); return true; } } @@ -3029,7 +3031,11 @@ export class PostTurnLootAbAttr extends PostTurnAbAttr { ) as BerryModifier | undefined; if (!berryModifier) { - pokemon.scene.addModifier(new BerryModifier(chosenBerry, pokemon.id, chosenBerryType, 1)); + if (pokemon.isPlayer()) { + pokemon.scene.addModifier(new BerryModifier(chosenBerry, pokemon.id, chosenBerryType, 1)); + } else { + pokemon.scene.addEnemyModifier(new BerryModifier(chosenBerry, pokemon.id, chosenBerryType, 1)); + } } else if (berryModifier.stackCount < berryModifier.getMaxHeldItemCount(pokemon)) { berryModifier.stackCount++; } @@ -3085,7 +3091,7 @@ export class PostTurnStatChangeAbAttr extends PostTurnAbAttr { export class PostTurnHealAbAttr extends PostTurnAbAttr { applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { - if (pokemon.getHpRatio() < 1) { + if (!pokemon.isFullHp()) { const scene = pokemon.scene; const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), @@ -3912,7 +3918,7 @@ export class IceFaceBlockPhysicalAbAttr extends ReceivedMoveDamageMultiplierAbAt * @returns {string} - The trigger message. */ getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return i18next.t("abilityTriggers:iceFaceAvoidedDamage", { pokemonName: pokemon.name, abilityName: abilityName }); + return i18next.t("abilityTriggers:iceFaceAvoidedDamage", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName }); } } @@ -4218,7 +4224,8 @@ export function initAbilities() { .attr(IntimidateImmunityAbAttr) .ignorable(), new Ability(Abilities.CLOUD_NINE, 3) - .attr(SuppressWeatherEffectAbAttr, true), + .attr(SuppressWeatherEffectAbAttr, true) + .attr(PostSummonUnnamedMessageAbAttr, "The effects of the weather disappeared."), new Ability(Abilities.COMPOUND_EYES, 3) .attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 1.3), new Ability(Abilities.INSOMNIA, 3) @@ -4350,7 +4357,7 @@ export function initAbilities() { new Ability(Abilities.TRUANT, 3) .attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.TRUANT, 1, false), new Ability(Abilities.HUSTLE, 3) - .attr(BattleStatMultiplierAbAttr, BattleStat.ATK, 1.5, (user, target, move) => move.category === MoveCategory.PHYSICAL) + .attr(BattleStatMultiplierAbAttr, BattleStat.ATK, 1.5) .attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 0.8, (user, target, move) => move.category === MoveCategory.PHYSICAL), new Ability(Abilities.CUTE_CHARM, 3) .attr(PostDefendContactApplyTagChanceAbAttr, 30, BattlerTagType.INFATUATED), @@ -4591,7 +4598,7 @@ export function initAbilities() { .attr(WeightMultiplierAbAttr, 0.5) .ignorable(), new Ability(Abilities.MULTISCALE, 5) - .attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getHpRatio() === 1, 0.5) + .attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.isFullHp(), 0.5) .ignorable(), new Ability(Abilities.TOXIC_BOOST, 5) .attr(MovePowerBoostAbAttr, (user, target, move) => move.category === MoveCategory.PHYSICAL && (user.status?.effect === StatusEffect.POISON || user.status?.effect === StatusEffect.TOXIC), 1.5), @@ -4722,7 +4729,7 @@ export function initAbilities() { .attr(UnsuppressableAbilityAbAttr) .attr(NoFusionAbilityAbAttr), new Ability(Abilities.GALE_WINGS, 6) - .attr(IncrementMovePriorityAbAttr, (pokemon, move) => pokemon.getHpRatio() === 1 && move.type === Type.FLYING), + .attr(IncrementMovePriorityAbAttr, (pokemon, move) => pokemon.isFullHp() && move.type === Type.FLYING), new Ability(Abilities.MEGA_LAUNCHER, 6) .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.PULSE_MOVE), 1.5), new Ability(Abilities.GRASS_PELT, 6) @@ -4927,7 +4934,7 @@ export function initAbilities() { new Ability(Abilities.FULL_METAL_BODY, 7) .attr(ProtectStatAbAttr), new Ability(Abilities.SHADOW_SHIELD, 7) - .attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getHpRatio() === 1, 0.5), + .attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.isFullHp(), 0.5), new Ability(Abilities.PRISM_ARMOR, 7) .attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2, 0.75), new Ability(Abilities.NEUROFORCE, 7) diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 28d38daffb4e..2676826ff634 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -2,7 +2,7 @@ import { Arena } from "../field/arena"; import { Type } from "./type"; import * as Utils from "../utils"; import { MoveCategory, allMoves, MoveTarget } from "./move"; -import { getPokemonMessage } from "../messages"; +import { getPokemonMessage, getPokemonNameWithAffix } from "../messages"; import Pokemon, { HitResult, PokemonMove } from "../field/pokemon"; import { MoveEffectPhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../phases"; import { StatusEffect } from "./status-effect"; @@ -635,7 +635,7 @@ class StealthRockTag extends ArenaTrapTag { if (damageHpRatio) { const damage = Math.ceil(pokemon.getMaxHp() * damageHpRatio); - pokemon.scene.queueMessage(`Pointed stones dug into\n${pokemon.name}!`); + pokemon.scene.queueMessage(`Pointed stones dug into\n${getPokemonNameWithAffix(pokemon)}!`); pokemon.damageAndUpdate(damage, HitResult.OTHER); if (pokemon.turnData) { pokemon.turnData.damageTaken += damage; @@ -677,7 +677,7 @@ class StickyWebTag extends ArenaTrapTag { const cancelled = new Utils.BooleanHolder(false); applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled); if (!cancelled.value) { - pokemon.scene.queueMessage(`The opposing ${pokemon.name} was caught in a sticky web!`); + pokemon.scene.queueMessage(`The opposing ${getPokemonNameWithAffix(pokemon)} was caught in a sticky web!`); const statLevels = new Utils.NumberHolder(-1); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [BattleStat.SPD], statLevels.value)); } @@ -759,7 +759,7 @@ class TailwindTag extends ArenaTag { // Apply the CHARGED tag to party members with the WIND_POWER ability if (pokemon.hasAbility(Abilities.WIND_POWER) && !pokemon.getTag(BattlerTagType.CHARGED)) { pokemon.addTag(BattlerTagType.CHARGED); - pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: this.getMoveName() })); + pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: this.getMoveName() })); } // Raise attack by one stage if party member has WIND_RIDER ability if (pokemon.hasAbility(Abilities.WIND_RIDER)) { diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index a664ac1e2bf8..2755fd0bbbed 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -1,5 +1,5 @@ import { CommonAnim, CommonBattleAnim } from "./battle-anims"; -import { CommonAnimPhase, MoveEffectPhase, MovePhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../phases"; +import { CommonAnimPhase, MoveEffectPhase, MovePhase, PokemonHealPhase, ShowAbilityPhase, StatChangeCallback, StatChangePhase } from "../phases"; import { getPokemonNameWithAffix } from "../messages"; import Pokemon, { MoveResult, HitResult } from "../field/pokemon"; import { Stat, getStatName } from "./pokemon-stat"; @@ -32,11 +32,11 @@ export enum BattlerTagLapseType { export class BattlerTag { public tagType: BattlerTagType; public lapseType: BattlerTagLapseType[]; - public turnCount: integer; + public turnCount: number; public sourceMove: Moves; - public sourceId?: integer; + public sourceId?: number; - constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType | BattlerTagLapseType[], turnCount: integer, sourceMove: Moves, sourceId?: integer) { + constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType | BattlerTagLapseType[], turnCount: number, sourceMove: Moves, sourceId?: number) { this.tagType = tagType; this.lapseType = typeof lapseType === "number" ? [ lapseType ] : lapseType; this.turnCount = turnCount; @@ -92,30 +92,34 @@ export interface TerrainBattlerTag { terrainTypes: TerrainType[]; } +/** + * BattlerTag that represents the "recharge" effects of moves like Hyper Beam. + */ export class RechargingTag extends BattlerTag { constructor(sourceMove: Moves) { - super(BattlerTagType.RECHARGING, BattlerTagLapseType.PRE_MOVE, 1, sourceMove); + super(BattlerTagType.RECHARGING, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.TURN_END ], 2, sourceMove); } onAdd(pokemon: Pokemon): void { super.onAdd(pokemon); + // Queue a placeholder move for the Pokemon to "use" next turn pokemon.getMoveQueue().push({ move: Moves.NONE, targets: [] }); } + /** Cancels the source's move this turn and queues a "__ must recharge!" message */ lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { - super.lapse(pokemon, lapseType); - - pokemon.scene.queueMessage(i18next.t("battle:battlerTagsRechargingLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); - (pokemon.scene.getCurrentPhase() as MovePhase).cancel(); - pokemon.getMoveQueue().shift(); - - return true; + if (lapseType === BattlerTagLapseType.PRE_MOVE) { + pokemon.scene.queueMessage(i18next.t("battle:battlerTagsRechargingLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); + (pokemon.scene.getCurrentPhase() as MovePhase).cancel(); + pokemon.getMoveQueue().shift(); + } + return super.lapse(pokemon, lapseType); } } export class TrappedTag extends BattlerTag { - constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, turnCount: integer, sourceMove: Moves, sourceId: integer) { + constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, turnCount: number, sourceMove: Moves, sourceId: number) { super(tagType, lapseType, turnCount, sourceMove, sourceId); } @@ -218,7 +222,7 @@ export class InterruptedTag extends BattlerTag { * BattlerTag that represents the {@link https://bulbapedia.bulbagarden.net/wiki/Confusion_(status_condition) Confusion} status condition */ export class ConfusedTag extends BattlerTag { - constructor(turnCount: integer, sourceMove: Moves) { + constructor(turnCount: number, sourceMove: Moves) { super(BattlerTagType.CONFUSED, BattlerTagLapseType.MOVE, turnCount, sourceMove); } @@ -278,7 +282,7 @@ export class ConfusedTag extends BattlerTag { * @see {@linkcode apply} */ export class DestinyBondTag extends BattlerTag { - constructor(sourceMove: Moves, sourceId: integer) { + constructor(sourceMove: Moves, sourceId: number) { super(BattlerTagType.DESTINY_BOND, BattlerTagLapseType.PRE_MOVE, 1, sourceMove, sourceId); } @@ -321,7 +325,7 @@ export class DestinyBondTag extends BattlerTag { } export class InfatuatedTag extends BattlerTag { - constructor(sourceMove: integer, sourceId: integer) { + constructor(sourceMove: number, sourceId: number) { super(BattlerTagType.INFATUATED, BattlerTagLapseType.MOVE, 1, sourceMove, sourceId); } @@ -335,7 +339,7 @@ export class InfatuatedTag extends BattlerTag { pokemon.scene.queueMessage( i18next.t("battle:battlerTagsInfatuatedOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - sourcePokemonName: pokemon.scene.getPokemonById(this.sourceId).name + sourcePokemonName: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)) }) ); } @@ -353,7 +357,7 @@ export class InfatuatedTag extends BattlerTag { pokemon.scene.queueMessage( i18next.t("battle:battlerTagsInfatuatedLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - sourcePokemonName: pokemon.scene.getPokemonById(this.sourceId).name + sourcePokemonName: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)) }) ); pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), undefined, CommonAnim.ATTRACT)); @@ -383,9 +387,9 @@ export class InfatuatedTag extends BattlerTag { } export class SeedTag extends BattlerTag { - private sourceIndex: integer; + private sourceIndex: number; - constructor(sourceId: integer) { + constructor(sourceId: number) { super(BattlerTagType.SEEDED, BattlerTagLapseType.TURN_END, 1, Moves.LEECH_SEED, sourceId); } @@ -480,19 +484,21 @@ export class NightmareTag extends BattlerTag { } export class FrenzyTag extends BattlerTag { - constructor(sourceMove: Moves, sourceId: integer) { - super(BattlerTagType.FRENZY, BattlerTagLapseType.CUSTOM, 1, sourceMove, sourceId); + constructor(turnCount: number, sourceMove: Moves, sourceId: number) { + super(BattlerTagType.FRENZY, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); } onRemove(pokemon: Pokemon): void { super.onRemove(pokemon); - pokemon.addTag(BattlerTagType.CONFUSED, pokemon.randSeedIntRange(2, 4)); + 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)); + } } } export class ChargingTag extends BattlerTag { - constructor(sourceMove: Moves, sourceId: integer) { + constructor(sourceMove: Moves, sourceId: number) { super(BattlerTagType.CHARGING, BattlerTagLapseType.CUSTOM, 1, sourceMove, sourceId); } } @@ -500,7 +506,7 @@ export class ChargingTag extends BattlerTag { export class EncoreTag extends BattlerTag { public moveId: Moves; - constructor(sourceId: integer) { + constructor(sourceId: number) { super(BattlerTagType.ENCORE, BattlerTagLapseType.AFTER_MOVE, 3, Moves.ENCORE, sourceId); } @@ -573,7 +579,7 @@ export class EncoreTag extends BattlerTag { } export class HelpingHandTag extends BattlerTag { - constructor(sourceId: integer) { + constructor(sourceId: number) { super(BattlerTagType.HELPING_HAND, BattlerTagLapseType.TURN_END, 1, Moves.HELPING_HAND, sourceId); } @@ -581,7 +587,7 @@ export class HelpingHandTag extends BattlerTag { pokemon.scene.queueMessage( i18next.t("battle:battlerTagsHelpingHandOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)), - pokemonName: pokemon.name + pokemonName: getPokemonNameWithAffix(pokemon) }) ); } @@ -592,7 +598,7 @@ export class HelpingHandTag extends BattlerTag { * @extends TrappedTag */ export class IngrainTag extends TrappedTag { - constructor(sourceId: integer) { + constructor(sourceId: number) { super(BattlerTagType.INGRAIN, BattlerTagLapseType.TURN_END, 1, Moves.INGRAIN, sourceId); } @@ -682,7 +688,7 @@ export class AquaRingTag extends BattlerTag { Math.floor(pokemon.getMaxHp() / 16), i18next.t("battle:battlerTagsAquaRingLapse", { moveName: this.getMoveName(), - pokemonName: pokemon.name + pokemonName: getPokemonNameWithAffix(pokemon) }), true)); } @@ -750,7 +756,7 @@ export class DrowsyTag extends BattlerTag { export abstract class DamagingTrapTag extends TrappedTag { private commonAnim: CommonAnim; - constructor(tagType: BattlerTagType, commonAnim: CommonAnim, turnCount: integer, sourceMove: Moves, sourceId: integer) { + constructor(tagType: BattlerTagType, commonAnim: CommonAnim, turnCount: number, sourceMove: Moves, sourceId: number) { super(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove, sourceId); this.commonAnim = commonAnim; @@ -794,34 +800,34 @@ export abstract class DamagingTrapTag extends TrappedTag { } export class BindTag extends DamagingTrapTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(BattlerTagType.BIND, CommonAnim.BIND, turnCount, Moves.BIND, sourceId); } getTrapMessage(pokemon: Pokemon): string { return i18next.t("battle:battlerTagsBindOnTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - sourcePokemonName: pokemon.scene.getPokemonById(this.sourceId).name, + sourcePokemonName: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)), moveName: this.getMoveName() }); } } export class WrapTag extends DamagingTrapTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(BattlerTagType.WRAP, CommonAnim.WRAP, turnCount, Moves.WRAP, sourceId); } getTrapMessage(pokemon: Pokemon): string { return i18next.t("battle:battlerTagsWrapOnTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - sourcePokemonName: pokemon.scene.getPokemonById(this.sourceId).name + sourcePokemonName: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)) }); } } export abstract class VortexTrapTag extends DamagingTrapTag { - constructor(tagType: BattlerTagType, commonAnim: CommonAnim, turnCount: integer, sourceMove: Moves, sourceId: integer) { + constructor(tagType: BattlerTagType, commonAnim: CommonAnim, turnCount: number, sourceMove: Moves, sourceId: number) { super(tagType, commonAnim, turnCount, sourceMove, sourceId); } @@ -831,32 +837,32 @@ export abstract class VortexTrapTag extends DamagingTrapTag { } export class FireSpinTag extends VortexTrapTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(BattlerTagType.FIRE_SPIN, CommonAnim.FIRE_SPIN, turnCount, Moves.FIRE_SPIN, sourceId); } } export class WhirlpoolTag extends VortexTrapTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(BattlerTagType.WHIRLPOOL, CommonAnim.WHIRLPOOL, turnCount, Moves.WHIRLPOOL, sourceId); } } export class ClampTag extends DamagingTrapTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(BattlerTagType.CLAMP, CommonAnim.CLAMP, turnCount, Moves.CLAMP, sourceId); } getTrapMessage(pokemon: Pokemon): string { return i18next.t("battle:battlerTagsClampOnTrap", { sourcePokemonNameWithAffix: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)), - pokemonName: pokemon.name, + pokemonName: getPokemonNameWithAffix(pokemon), }); } } export class SandTombTag extends DamagingTrapTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(BattlerTagType.SAND_TOMB, CommonAnim.SAND_TOMB, turnCount, Moves.SAND_TOMB, sourceId); } @@ -869,7 +875,7 @@ export class SandTombTag extends DamagingTrapTag { } export class MagmaStormTag extends DamagingTrapTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(BattlerTagType.MAGMA_STORM, CommonAnim.MAGMA_STORM, turnCount, Moves.MAGMA_STORM, sourceId); } @@ -879,7 +885,7 @@ export class MagmaStormTag extends DamagingTrapTag { } export class SnapTrapTag extends DamagingTrapTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(BattlerTagType.SNAP_TRAP, CommonAnim.SNAP_TRAP, turnCount, Moves.SNAP_TRAP, sourceId); } @@ -889,7 +895,7 @@ export class SnapTrapTag extends DamagingTrapTag { } export class ThunderCageTag extends DamagingTrapTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(BattlerTagType.THUNDER_CAGE, CommonAnim.THUNDER_CAGE, turnCount, Moves.THUNDER_CAGE, sourceId); } @@ -902,7 +908,7 @@ export class ThunderCageTag extends DamagingTrapTag { } export class InfestationTag extends DamagingTrapTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(BattlerTagType.INFESTATION, CommonAnim.INFESTATION, turnCount, Moves.INFESTATION, sourceId); } @@ -944,9 +950,9 @@ export class ProtectedTag extends BattlerTag { } export class ContactDamageProtectedTag extends ProtectedTag { - private damageRatio: integer; + private damageRatio: number; - constructor(sourceMove: Moves, damageRatio: integer) { + constructor(sourceMove: Moves, damageRatio: number) { super(sourceMove, BattlerTagType.SPIKY_SHIELD); this.damageRatio = damageRatio; @@ -980,9 +986,9 @@ export class ContactDamageProtectedTag extends ProtectedTag { export class ContactStatChangeProtectedTag extends ProtectedTag { private stat: BattleStat; - private levels: integer; + private levels: number; - constructor(sourceMove: Moves, tagType: BattlerTagType, stat: BattleStat, levels: integer) { + constructor(sourceMove: Moves, tagType: BattlerTagType, stat: BattleStat, levels: number) { super(sourceMove, tagType); this.stat = stat; @@ -1091,7 +1097,7 @@ export class SturdyTag extends BattlerTag { } export class PerishSongTag extends BattlerTag { - constructor(turnCount: integer) { + constructor(turnCount: number) { super(BattlerTagType.PERISH_SONG, BattlerTagLapseType.TURN_END, turnCount, Moves.PERISH_SONG); } @@ -1147,7 +1153,7 @@ export class CenterOfAttentionTag extends BattlerTag { export class AbilityBattlerTag extends BattlerTag { public ability: Abilities; - constructor(tagType: BattlerTagType, ability: Abilities, lapseType: BattlerTagLapseType, turnCount: integer) { + constructor(tagType: BattlerTagType, ability: Abilities, lapseType: BattlerTagLapseType, turnCount: number) { super(tagType, lapseType, turnCount, undefined); this.ability = ability; @@ -1235,7 +1241,7 @@ export class HighestStatBoostTag extends AbilityBattlerTag { const stats = [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ]; let highestStat: Stat; - stats.map(s => pokemon.getBattleStat(s)).reduce((highestValue: integer, value: integer, i: integer) => { + stats.map(s => pokemon.getBattleStat(s)).reduce((highestValue: number, value: number, i: number) => { if (value > highestValue) { highestStat = stats[i]; return value; @@ -1301,7 +1307,7 @@ export class TerrainHighestStatBoostTag extends HighestStatBoostTag implements T } export class SemiInvulnerableTag extends BattlerTag { - constructor(tagType: BattlerTagType, turnCount: integer, sourceMove: Moves) { + constructor(tagType: BattlerTagType, turnCount: number, sourceMove: Moves) { super(tagType, BattlerTagLapseType.MOVE_EFFECT, turnCount, sourceMove); } @@ -1420,10 +1426,22 @@ export class IgnoreAccuracyTag extends BattlerTag { } } +export class AlwaysGetHitTag extends BattlerTag { + constructor(sourceMove: Moves) { + super(BattlerTagType.ALWAYS_GET_HIT, BattlerTagLapseType.PRE_MOVE, 1, sourceMove); + } +} + +export class ReceiveDoubleDamageTag extends BattlerTag { + constructor(sourceMove: Moves) { + super(BattlerTagType.RECEIVE_DOUBLE_DAMAGE, BattlerTagLapseType.PRE_MOVE, 1, sourceMove); + } +} + export class SaltCuredTag extends BattlerTag { - private sourceIndex: integer; + private sourceIndex: number; - constructor(sourceId: integer) { + constructor(sourceId: number) { super(BattlerTagType.SALT_CURED, BattlerTagLapseType.TURN_END, 1, Moves.SALT_CURE, sourceId); } @@ -1470,9 +1488,9 @@ export class SaltCuredTag extends BattlerTag { } export class CursedTag extends BattlerTag { - private sourceIndex: integer; + private sourceIndex: number; - constructor(sourceId: integer) { + constructor(sourceId: number) { super(BattlerTagType.CURSED, BattlerTagLapseType.TURN_END, 1, Moves.CURSE, sourceId); } @@ -1571,7 +1589,96 @@ export class IceFaceTag extends BattlerTag { } } -export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourceMove: Moves, sourceId: integer): BattlerTag { + +/** + * Battler tag enabling the Stockpile mechanic. This tag handles: + * - Stack tracking, including max limit enforcement (which is replicated in Stockpile for redundancy). + * + * - Stat changes on adding a stack. Adding a stockpile stack attempts to raise the pokemon's DEF and SPDEF by +1. + * + * - Stat changes on removal of (all) stacks. + * - Removing stacks decreases DEF and SPDEF, independently, by one stage for each stack that successfully changed + * the stat when added. + */ +export class StockpilingTag extends BattlerTag { + public stockpiledCount: number = 0; + public statChangeCounts: { [BattleStat.DEF]: number; [BattleStat.SPDEF]: number } = { + [BattleStat.DEF]: 0, + [BattleStat.SPDEF]: 0 + }; + + constructor(sourceMove: Moves = Moves.NONE) { + super(BattlerTagType.STOCKPILING, BattlerTagLapseType.CUSTOM, 1, sourceMove); + } + + private onStatsChanged: StatChangeCallback = (_, statsChanged, statChanges) => { + const defChange = statChanges[statsChanged.indexOf(BattleStat.DEF)] ?? 0; + const spDefChange = statChanges[statsChanged.indexOf(BattleStat.SPDEF)] ?? 0; + + if (defChange) { + this.statChangeCounts[BattleStat.DEF]++; + } + + if (spDefChange) { + this.statChangeCounts[BattleStat.SPDEF]++; + } + }; + + loadTag(source: BattlerTag | any): void { + super.loadTag(source); + this.stockpiledCount = source.stockpiledCount || 0; + this.statChangeCounts = { + [BattleStat.DEF]: source.statChangeCounts?.[BattleStat.DEF] || 0, + [BattleStat.SPDEF]: source.statChangeCounts?.[BattleStat.SPDEF] || 0, + }; + } + + /** + * Adds a stockpile stack to a pokemon, up to a maximum of 3 stacks. Note that onOverlap defers to this method. + * + * If a stack is added, a message is displayed and the pokemon's DEF and SPDEF are increased by 1. + * For each stat, an internal counter is incremented (by 1) if the stat was successfully changed. + */ + onAdd(pokemon: Pokemon): void { + if (this.stockpiledCount < 3) { + this.stockpiledCount++; + + pokemon.scene.queueMessage(i18next.t("battle:battlerTagsStockpilingOnAdd", { + pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), + stockpiledCount: this.stockpiledCount + })); + + // Attempt to increase DEF and SPDEF by one stage, keeping track of successful changes. + pokemon.scene.unshiftPhase(new StatChangePhase( + pokemon.scene, pokemon.getBattlerIndex(), true, + [BattleStat.SPDEF, BattleStat.DEF], 1, true, false, true, this.onStatsChanged + )); + } + } + + onOverlap(pokemon: Pokemon): void { + this.onAdd(pokemon); + } + + /** + * Removing the tag removes all stacks, and the pokemon's DEF and SPDEF are decreased by + * one stage for each stack which had successfully changed that particular stat during onAdd. + */ + onRemove(pokemon: Pokemon): void { + const defChange = this.statChangeCounts[BattleStat.DEF]; + const spDefChange = this.statChangeCounts[BattleStat.SPDEF]; + + if (defChange) { + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.DEF], -defChange, true, false, true)); + } + + if (spDefChange) { + pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.SPDEF], -spDefChange, true, false, true)); + } + } +} + +export function getBattlerTag(tagType: BattlerTagType, turnCount: number, sourceMove: Moves, sourceId: number): BattlerTag { switch (tagType) { case BattlerTagType.RECHARGING: return new RechargingTag(sourceMove); @@ -1588,7 +1695,7 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc case BattlerTagType.NIGHTMARE: return new NightmareTag(); case BattlerTagType.FRENZY: - return new FrenzyTag(sourceMove, sourceId); + return new FrenzyTag(turnCount, sourceMove, sourceId); case BattlerTagType.CHARGING: return new ChargingTag(sourceMove, sourceId); case BattlerTagType.ENCORE: @@ -1668,6 +1775,10 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new BattlerTag(tagType, BattlerTagLapseType.AFTER_MOVE, turnCount, sourceMove); case BattlerTagType.IGNORE_ACCURACY: return new IgnoreAccuracyTag(sourceMove); + case BattlerTagType.ALWAYS_GET_HIT: + return new AlwaysGetHitTag(sourceMove); + case BattlerTagType.RECEIVE_DOUBLE_DAMAGE: + return new ReceiveDoubleDamageTag(sourceMove); case BattlerTagType.BYPASS_SLEEP: return new BattlerTag(BattlerTagType.BYPASS_SLEEP, BattlerTagLapseType.TURN_END, turnCount, sourceMove); case BattlerTagType.IGNORE_FLYING: @@ -1688,6 +1799,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new DestinyBondTag(sourceMove, sourceId); case BattlerTagType.ICE_FACE: return new IceFaceTag(sourceMove); + case BattlerTagType.STOCKPILING: + return new StockpilingTag(sourceMove); case BattlerTagType.OCTOLOCK: return new OctolockTag(sourceId); case BattlerTagType.NONE: diff --git a/src/data/challenge.ts b/src/data/challenge.ts index 9035c7e7a3fd..eda97e9cdadb 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -270,9 +270,11 @@ export abstract class Challenge { * @param valid {@link Utils.BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed. * @param dexAttr {@link DexAttrProps} The dex attributes of the pokemon. * @param soft {@link boolean} If true, allow it if it could become a valid pokemon. + * @param checkEvolutions {@link boolean} If true, check the pokemon's future evolutions + * @param checkForms {@link boolean} If true, check the pokemon's alternative forms * @returns {@link boolean} Whether this function did anything. */ - applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean { + applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false, checkEvolutions?: boolean, checkForms?: boolean): boolean { return false; } @@ -400,7 +402,7 @@ export class SingleGenerationChallenge extends Challenge { super(Challenges.SINGLE_GENERATION, 9); } - applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean { + applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false, checkEvolutions?: boolean): boolean { /** * We have special code below for victini because it is classed as a generation 4 pokemon in the code * despite being a generation 5 pokemon. This is due to UI constraints, the starter select screen has @@ -409,11 +411,12 @@ export class SingleGenerationChallenge extends Challenge { */ const starterGeneration = pokemon.speciesId === Species.VICTINI ? 5 : pokemon.generation; const generations = [starterGeneration]; + const checkPokemonEvolutions = checkEvolutions ?? true as boolean; if (soft) { const speciesToCheck = [pokemon.speciesId]; while (speciesToCheck.length) { const checking = speciesToCheck.pop(); - if (pokemonEvolutions.hasOwnProperty(checking)) { + if (pokemonEvolutions.hasOwnProperty(checking) && checkPokemonEvolutions) { pokemonEvolutions[checking].forEach(e => { speciesToCheck.push(e.speciesId); generations.push(getPokemonSpecies(e.speciesId).generation); @@ -534,20 +537,22 @@ export class SingleTypeChallenge extends Challenge { super(Challenges.SINGLE_TYPE, 18); } - applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean { + applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false, checkEvolutions?: boolean, checkForms?: boolean): boolean { const speciesForm = getPokemonSpeciesForm(pokemon.speciesId, dexAttr.formIndex); const types = [speciesForm.type1, speciesForm.type2]; + const checkPokemonEvolutions = checkEvolutions ?? true as boolean; + const checkPokemonForms = checkForms ?? true as boolean; if (soft) { const speciesToCheck = [pokemon.speciesId]; while (speciesToCheck.length) { const checking = speciesToCheck.pop(); - if (pokemonEvolutions.hasOwnProperty(checking)) { + if (pokemonEvolutions.hasOwnProperty(checking) && checkPokemonEvolutions) { pokemonEvolutions[checking].forEach(e => { speciesToCheck.push(e.speciesId); types.push(getPokemonSpecies(e.speciesId).type1, getPokemonSpecies(e.speciesId).type2); }); } - if (pokemonFormChanges.hasOwnProperty(checking)) { + if (pokemonFormChanges.hasOwnProperty(checking) && checkPokemonForms) { pokemonFormChanges[checking].forEach(f1 => { getPokemonSpecies(checking).forms.forEach(f2 => { if (f1.formKey === f2.formKey) { @@ -743,7 +748,7 @@ export class LowerStarterPointsChallenge extends Challenge { * @param soft {@link boolean} If true, allow it if it could become a valid pokemon. * @returns True if any challenge was successfully applied. */ -export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_CHOICE, pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean): boolean; +export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_CHOICE, pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean, checkEvolutions?: boolean, checkForms?: boolean): boolean; /** * Apply all challenges that modify available total starter points. * @param gameMode {@link GameMode} The current gameMode @@ -851,7 +856,7 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType if (c.value !== 0) { switch (challengeType) { case ChallengeType.STARTER_CHOICE: - ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3]); + ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3], args[4], args[5]); break; case ChallengeType.STARTER_POINTS: ret ||= c.applyStarterPoints(args[0]); diff --git a/src/data/egg.ts b/src/data/egg.ts index 4cbb7afbaf64..b8ed28c892ac 100644 --- a/src/data/egg.ts +++ b/src/data/egg.ts @@ -2,7 +2,7 @@ import BattleScene from "../battle-scene"; import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species"; import { VariantTier } from "../enums/variant-tiers"; import * as Utils from "../utils"; -import Overrides from "../overrides"; +import Overrides from "#app/overrides"; import { pokemonPrevolutions } from "./pokemon-evolutions"; import { PlayerPokemon } from "#app/field/pokemon"; import i18next from "i18next"; diff --git a/src/data/move.ts b/src/data/move.ts index 4a77d89f9f1a..64aed985d575 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1,7 +1,7 @@ import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims"; import { BattleEndPhase, MoveEndPhase, MovePhase, NewBattlePhase, PartyStatusCurePhase, PokemonHealPhase, StatChangePhase, SwitchSummonPhase } from "../phases"; import { BattleStat, getBattleStatName } from "./battle-stat"; -import { EncoreTag, HelpingHandTag, SemiInvulnerableTag, TypeBoostTag } from "./battler-tags"; +import { EncoreTag, HelpingHandTag, SemiInvulnerableTag, StockpilingTag, TypeBoostTag } from "./battler-tags"; import { getPokemonMessage, getPokemonNameWithAffix } from "../messages"; import Pokemon, { AttackMoveResult, EnemyPokemon, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../field/pokemon"; import { StatusEffect, getStatusEffectHealText, isNonVolatileStatusEffect, getNonVolatileStatusEffects} from "./status-effect"; @@ -10,9 +10,9 @@ import { Constructor } from "#app/utils"; import * as Utils from "../utils"; import { WeatherType } from "./weather"; import { ArenaTagSide, ArenaTrapTag, WeakenMoveTypeTag } from "./arena-tag"; -import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr, HealFromBerryUseAbAttr, IgnoreProtectOnContactAbAttr, IgnoreMoveEffectsAbAttr, applyPreDefendAbAttrs, MoveEffectChanceMultiplierAbAttr, applyPreAttackAbAttrs, MoveTypeChangeAttr, UserFieldMoveTypePowerBoostAbAttr, FieldMoveTypePowerBoostAbAttr, AllyMoveCategoryPowerBoostAbAttr, VariableMovePowerAbAttr } from "./ability"; +import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr, HealFromBerryUseAbAttr, IgnoreProtectOnContactAbAttr, IgnoreMoveEffectsAbAttr, applyPreDefendAbAttrs, MoveEffectChanceMultiplierAbAttr, WonderSkinAbAttr, applyPreAttackAbAttrs, MoveTypeChangeAttr, UserFieldMoveTypePowerBoostAbAttr, FieldMoveTypePowerBoostAbAttr, AllyMoveCategoryPowerBoostAbAttr, VariableMovePowerAbAttr } from "./ability"; import { allAbilities } from "./ability"; -import { PokemonHeldItemModifier, BerryModifier, PreserveBerryModifier, AttackTypeBoosterModifier, PokemonMultiHitModifier } from "../modifier/modifier"; +import { PokemonHeldItemModifier, BerryModifier, PreserveBerryModifier, PokemonMoveAccuracyBoosterModifier, AttackTypeBoosterModifier, PokemonMultiHitModifier } from "../modifier/modifier"; import { BattlerIndex } from "../battle"; import { Stat } from "./pokemon-stat"; import { TerrainType } from "./terrain"; @@ -656,6 +656,44 @@ export default class Move implements Localizable { return score; } + /** + * Calculates the accuracy of a move in battle based on various conditions and attributes. + * + * @param user {@linkcode Pokemon} The Pokémon using the move. + * @param target {@linkcode Pokemon} The Pokémon being targeted by the move. + * @returns The calculated accuracy of the move. + */ + calculateBattleAccuracy(user: Pokemon, target: Pokemon) { + const moveAccuracy = new Utils.NumberHolder(this.accuracy); + + applyMoveAttrs(VariableAccuracyAttr, user, target, this, moveAccuracy); + applyPreDefendAbAttrs(WonderSkinAbAttr, target, user, this, { value: false }, moveAccuracy); + + if (moveAccuracy.value === -1) { + return moveAccuracy.value; + } + + const isOhko = this.hasAttr(OneHitKOAccuracyAttr); + + if (!isOhko) { + user.scene.applyModifiers(PokemonMoveAccuracyBoosterModifier, user.isPlayer(), user, moveAccuracy); + } + + if (user.scene.arena.weather?.weatherType === WeatherType.FOG) { + /** + * The 0.9 multiplier is PokeRogue-only implementation, Bulbapedia uses 3/5 + * See Fog {@link https://bulbapedia.bulbagarden.net/wiki/Fog} + */ + moveAccuracy.value = Math.floor(moveAccuracy.value * 0.9); + } + + if (!isOhko && user.scene.arena.getTag(ArenaTagType.GRAVITY)) { + moveAccuracy.value = Math.floor(moveAccuracy.value * 1.67); + } + + return moveAccuracy.value; + } + /** * Calculates the power of a move in battle based on various conditions and attributes. * @@ -917,9 +955,9 @@ export class MoveEffectAttr extends MoveAttr { * @param selfEffect {@linkcode Boolean} if move targets user. * @returns Move chance value. */ - getMoveChance(user: Pokemon, target: Pokemon, move: Move, selfEffect?: Boolean): integer { + getMoveChance(user: Pokemon, target: Pokemon, move: Move, selfEffect?: Boolean, showAbility?: Boolean): integer { const moveChance = new Utils.NumberHolder(move.chance); - applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, moveChance, move, target, selfEffect); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, moveChance, move, target, selfEffect, showAbility); applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr,target,user,null,null, moveChance); return moveChance.value; } @@ -1576,11 +1614,11 @@ export class HitHealAttr extends MoveEffectAttr { if (this.healStat) { // Strength Sap formula healAmount = target.getBattleStat(this.healStat); - message = i18next.t("battle:drainMessage", {pokemonName: target.name}); + message = i18next.t("battle:drainMessage", {pokemonName: getPokemonNameWithAffix(target)}); } else { // Default healing formula used by draining moves like Absorb, Draining Kiss, Bitter Blade, etc. healAmount = Math.max(Math.floor(user.turnData.currDamageDealt * this.healRatio), 1); - message = i18next.t("battle:regainHealth", {pokemonName: user.name}); + message = i18next.t("battle:regainHealth", {pokemonName: getPokemonNameWithAffix(user)}); } if (reverseDrain) { user.turnData.damageTaken += healAmount; @@ -1681,6 +1719,7 @@ export class MultiHitAttr extends MoveAttr { } else { const hitType = new Utils.IntegerHolder(this.multiHitType); applyMoveAttrs(ChangeMultiHitTypeAttr, user, target, move, hitType); + this.multiHitType = hitType.value; hitTimes = this.getHitCount(user, target); } @@ -1767,7 +1806,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); + const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); const statusCheck = moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance; if (statusCheck) { const pokemon = this.selfTarget ? user : target; @@ -1788,7 +1827,7 @@ export class StatusEffectAttr extends MoveEffectAttr { } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { - const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + const moveChance = this.getMoveChance(user, target, move, this.selfTarget, false); return !(this.selfTarget ? user : target).status && (this.selfTarget ? user : target).canSetStatus(this.effect, true, false, user) ? Math.floor(moveChance * -0.1) : 0; } } @@ -1808,7 +1847,7 @@ export class MultiStatusEffectAttr extends StatusEffectAttr { } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { - const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + const moveChance = this.getMoveChance(user, target, move, this.selfTarget, false); return !(this.selfTarget ? user : target).status && (this.selfTarget ? user : target).canSetStatus(this.effect, true, false, user) ? Math.floor(moveChance * -0.1) : 0; } } @@ -2378,7 +2417,7 @@ export class DelayedAttackAttr extends OverrideMoveEffectAttr { if (args.length < 2 || !args[1]) { new MoveChargeAnim(this.chargeAnim, move.id, user).play(user.scene, () => { (args[0] as Utils.BooleanHolder).value = true; - user.scene.queueMessage(getPokemonMessage(user, ` ${this.chargeText.replace("{TARGET}", target.name)}`)); + user.scene.queueMessage(getPokemonMessage(user, ` ${this.chargeText.replace("{TARGET}", getPokemonNameWithAffix(target))}`)); user.pushMoveHistory({ move: move.id, targets: [ target.getBattlerIndex() ], result: MoveResult.OTHER }); user.scene.arena.addTag(this.tagType, 3, move.id, user.id, ArenaTagSide.BOTH, false, target.getBattlerIndex()); @@ -2412,7 +2451,7 @@ export class StatChangeAttr extends MoveEffectAttr { return false; } - const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { const levels = this.getLevels(user); user.scene.unshiftPhase(new StatChangePhase(user.scene, (this.selfTarget ? user : target).getBattlerIndex(), this.selfTarget, this.stats, levels, this.showMessage)); @@ -3257,6 +3296,62 @@ export class WaterShurikenPowerAttr extends VariablePowerAttr { } } +/** + * Attribute used to calculate the power of attacks that scale with Stockpile stacks (i.e. Spit Up). + */ +export class SpitUpPowerAttr extends VariablePowerAttr { + private multiplier: number = 0; + + constructor(multiplier: number) { + super(); + this.multiplier = multiplier; + } + + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const stockpilingTag = user.getTag(StockpilingTag); + + if (stockpilingTag?.stockpiledCount > 0) { + const power = args[0] as Utils.IntegerHolder; + power.value = this.multiplier * stockpilingTag.stockpiledCount; + return true; + } + + return false; + } +} + +/** + * Attribute used to apply Swallow's healing, which scales with Stockpile stacks. + * Does NOT remove stockpiled stacks. + */ +export class SwallowHealAttr extends HealAttr { + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const stockpilingTag = user.getTag(StockpilingTag); + + if (stockpilingTag?.stockpiledCount > 0) { + const stockpiled = stockpilingTag.stockpiledCount; + let healRatio: number; + + if (stockpiled === 1) { + healRatio = 0.25; + } else if (stockpiled === 2) { + healRatio = 0.50; + } else { // stockpiled >= 3 + healRatio = 1.00; + } + + if (healRatio) { + this.addHealPhase(user, healRatio); + return true; + } + } + + return false; + } +} + +const hasStockpileStacksCondition: MoveConditionFunc = (user) => user.getTag(StockpilingTag)?.stockpiledCount > 0; + /** * Attribute used for multi-hit moves that increase power in increments of the * move's base power for each hit, namely Triple Kick and Triple Axel. @@ -3965,19 +4060,16 @@ export class FrenzyAttr extends MoveEffectAttr { return false; } - if (!user.getMoveQueue().length) { - if (!user.getTag(BattlerTagType.FRENZY)) { - const turnCount = user.randSeedIntRange(1, 2); - new Array(turnCount).fill(null).map(() => user.getMoveQueue().push({ move: move.id, targets: [ target.getBattlerIndex() ], ignorePP: true })); - user.addTag(BattlerTagType.FRENZY, 1, move.id, user.id); - } else { - applyMoveAttrs(AddBattlerTagAttr, user, target, move, args); - user.lapseTag(BattlerTagType.FRENZY); - } - return true; + if (!user.getTag(BattlerTagType.FRENZY) && !user.getMoveQueue().length) { + const turnCount = user.randSeedIntRange(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 { + applyMoveAttrs(AddBattlerTagAttr, user, target, move, args); + user.lapseTag(BattlerTagType.FRENZY); // if FRENZY is already in effect (moveQueue.length > 0), lapse the tag } - return false; + return true; } } @@ -3985,7 +4077,7 @@ export const frenzyMissFunc: UserMoveConditionFunc = (user: Pokemon, move: Move) while (user.getMoveQueue().length && user.getMoveQueue()[0].move === move.id) { user.getMoveQueue().shift(); } - user.lapseTag(BattlerTagType.FRENZY); + user.removeTag(BattlerTagType.FRENZY); // FRENZY tag should be disrupted on miss/no effect return true; }; @@ -4010,7 +4102,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr { return false; } - const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + 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.randSeedInt(this.turnCountMax - this.turnCountMin, this.turnCountMin), move.id, user.id); } @@ -4069,7 +4161,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr { } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { - let moveChance = this.getMoveChance(user,target,move,this.selfTarget); + let moveChance = this.getMoveChance(user,target,move,this.selfTarget, false); if (moveChance < 0) { moveChance = 100; } @@ -4090,7 +4182,7 @@ export class CurseAttr extends MoveEffectAttr { user.scene.queueMessage( i18next.t("battle:battlerTagsCursedOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(user), - pokemonName: target.name + pokemonName: getPokemonNameWithAffix(target) }) ); @@ -4220,9 +4312,9 @@ export class IgnoreAccuracyAttr extends AddBattlerTagAttr { } } -export class AlwaysCritsAttr extends AddBattlerTagAttr { +export class AlwaysGetHitAttr extends AddBattlerTagAttr { constructor() { - super(BattlerTagType.ALWAYS_CRIT, true, false, 2); + super(BattlerTagType.ALWAYS_GET_HIT, true, false, 0, 0, true); } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { @@ -4230,7 +4322,19 @@ export class AlwaysCritsAttr extends AddBattlerTagAttr { return false; } - user.scene.queueMessage(getPokemonMessage(user, ` took aim\nat ${target.name}!`)); + return true; + } +} + +export class ReceiveDoubleDamageAttr extends AddBattlerTagAttr { + constructor() { + super(BattlerTagType.RECEIVE_DOUBLE_DAMAGE, true, false, 0, 0, true); + } + + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + if (!super.apply(user, target, move, args)) { + return false; + } return true; } @@ -4366,7 +4470,7 @@ export class AddArenaTrapTagHitAttr extends AddArenaTagAttr { * @param move {@linkcode Move} being used */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + const moveChance = this.getMoveChance(user,target,move,this.selfTarget, true); const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; if ((moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance)) { @@ -4486,7 +4590,7 @@ export class SwapArenaTagsAttr extends MoveEffectAttr { } - user.scene.queueMessage( `${user.name} swapped the battle effects affecting each side of the field!`); + user.scene.queueMessage( `${getPokemonNameWithAffix(user)} swapped the battle effects affecting each side of the field!`); return true; } } @@ -4527,7 +4631,7 @@ export class RevivalBlessingAttr extends MoveEffectAttr { const slotIndex = user.scene.getEnemyParty().findIndex(p => pokemon.id === p.id); pokemon.resetStatus(); pokemon.heal(Math.min(Math.max(Math.ceil(Math.floor(0.5 * pokemon.getMaxHp())), 1), pokemon.getMaxHp())); - user.scene.queueMessage(`${pokemon.name} was revived!`,0,true); + user.scene.queueMessage(`${getPokemonNameWithAffix(pokemon)} was revived!`,0,true); if (user.scene.currentBattle.double && user.scene.getEnemyParty().length > 1) { const allyPokemon = user.getAlly(); @@ -4718,7 +4822,7 @@ export class CopyTypeAttr extends MoveEffectAttr { user.summonData.types = target.getTypes(true); user.updateInfo(); - user.scene.queueMessage(getPokemonMessage(user, `'s type\nchanged to match ${target.name}'s!`)); + user.scene.queueMessage(getPokemonMessage(user, `'s type\nchanged to match ${getPokemonNameWithAffix(target)}'s!`)); return true; } @@ -5100,7 +5204,7 @@ export class ReducePpMoveAttr extends MoveEffectAttr { const lastPpUsed = movesetMove.ppUsed; movesetMove.ppUsed = Math.min(movesetMove.ppUsed + this.reduction, movesetMove.getMovePp()); - const message = i18next.t("battle:ppReduced", {targetName: target.name, moveName: movesetMove.getName(), reduction: movesetMove.ppUsed - lastPpUsed}); + const message = i18next.t("battle:ppReduced", {targetName: getPokemonNameWithAffix(target), moveName: movesetMove.getName(), reduction: movesetMove.ppUsed - lastPpUsed}); user.scene.queueMessage(message); @@ -5873,6 +5977,7 @@ export function initMoves() { new AttackMove(Moves.THRASH, Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 10, -1, 0, 1) .attr(FrenzyAttr) .attr(MissEffectAttr, frenzyMissFunc) + .attr(NoEffectAttr, frenzyMissFunc) .target(MoveTarget.RANDOM_NEAR_ENEMY), new AttackMove(Moves.DOUBLE_EDGE, Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, -1, 0, 1) .attr(RecoilAttr, false, 0.33) @@ -5991,6 +6096,7 @@ export function initMoves() { new AttackMove(Moves.PETAL_DANCE, Type.GRASS, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 1) .attr(FrenzyAttr) .attr(MissEffectAttr, frenzyMissFunc) + .attr(NoEffectAttr, frenzyMissFunc) .makesContact() .danceMove() .target(MoveTarget.RANDOM_NEAR_ENEMY), @@ -6199,7 +6305,7 @@ export function initMoves() { new SelfStatusMove(Moves.REST, Type.PSYCHIC, -1, 5, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.SLEEP, true, 3, true) .attr(HealAttr, 1, true) - .condition((user, target, move) => user.getHpRatio() < 1 && user.canSetStatus(StatusEffect.SLEEP, true, true)) + .condition((user, target, move) => !user.isFullHp() && user.canSetStatus(StatusEffect.SLEEP, true, true)) .triageMove(), new AttackMove(Moves.ROCK_SLIDE, Type.ROCK, MoveCategory.PHYSICAL, 75, 90, 10, 30, 0, 1) .attr(FlinchAttr) @@ -6261,6 +6367,7 @@ export function initMoves() { .attr(ResistLastMoveTypeAttr) .partial(), // Checks the move's original typing and not if its type is changed through some other means new AttackMove(Moves.AEROBLAST, Type.FLYING, MoveCategory.SPECIAL, 100, 95, 5, -1, 0, 2) + .windMove() .attr(HighCritAttr), new StatusMove(Moves.COTTON_SPORE, Type.GRASS, 100, 40, -1, 0, 2) .attr(StatChangeAttr, BattleStat.SPD, -2) @@ -6323,6 +6430,7 @@ export function initMoves() { new AttackMove(Moves.OUTRAGE, Type.DRAGON, MoveCategory.PHYSICAL, 120, 100, 10, -1, 0, 2) .attr(FrenzyAttr) .attr(MissEffectAttr, frenzyMissFunc) + .attr(NoEffectAttr, frenzyMissFunc) .target(MoveTarget.RANDOM_NEAR_ENEMY), new StatusMove(Moves.SANDSTORM, Type.ROCK, -1, 10, -1, 0, 2) .attr(WeatherChangeAttr, WeatherType.SANDSTORM) @@ -6485,12 +6593,17 @@ export function initMoves() { .target(MoveTarget.RANDOM_NEAR_ENEMY) .partial(), new SelfStatusMove(Moves.STOCKPILE, Type.NORMAL, -1, 20, -1, 0, 3) - .unimplemented(), - new AttackMove(Moves.SPIT_UP, Type.NORMAL, MoveCategory.SPECIAL, -1, 100, 10, -1, 0, 3) - .unimplemented(), + .condition(user => (user.getTag(StockpilingTag)?.stockpiledCount ?? 0) < 3) + .attr(AddBattlerTagAttr, BattlerTagType.STOCKPILING, true), + new AttackMove(Moves.SPIT_UP, Type.NORMAL, MoveCategory.SPECIAL, -1, -1, 10, -1, 0, 3) + .condition(hasStockpileStacksCondition) + .attr(SpitUpPowerAttr, 100) + .attr(RemoveBattlerTagAttr, [BattlerTagType.STOCKPILING], true), new SelfStatusMove(Moves.SWALLOW, Type.NORMAL, -1, 10, -1, 0, 3) - .triageMove() - .unimplemented(), + .condition(hasStockpileStacksCondition) + .attr(SwallowHealAttr) + .attr(RemoveBattlerTagAttr, [BattlerTagType.STOCKPILING], true) + .triageMove(), new AttackMove(Moves.HEAT_WAVE, Type.FIRE, MoveCategory.SPECIAL, 95, 90, 10, 10, 0, 3) .attr(HealStatusEffectAttr, true, StatusEffect.FREEZE) .attr(StatusEffectAttr, StatusEffect.BURN) @@ -7481,6 +7594,7 @@ export function initMoves() { .attr(NeutralDamageAgainstFlyingTypeMultiplierAttr) .attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 1, 1, true) .attr(HitsTagAttr, BattlerTagType.FLYING, false) + .attr(HitsTagAttr, BattlerTagType.MAGNET_RISEN, false) .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN]) .makesContact(false) @@ -7895,7 +8009,7 @@ export function initMoves() { .attr(EatBerryAttr) .attr(StatChangeAttr, BattleStat.DEF, 2, true) .condition((user) => { - const userBerries = user.scene.findModifiers(m => m instanceof BerryModifier); + const userBerries = user.scene.findModifiers(m => m instanceof BerryModifier, user.isPlayer()); return userBerries.length > 0; }) .partial(), @@ -8118,8 +8232,9 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.BURN), new StatusMove(Moves.JUNGLE_HEALING, Type.GRASS, -1, 10, -1, 0, 8) .attr(HealAttr, 0.25, true, false) - .target(MoveTarget.USER_AND_ALLIES) - .partial(), + .attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN, StatusEffect.SLEEP) + .attr(HealStatusEffectAttr, false, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN, StatusEffect.SLEEP) + .target(MoveTarget.USER_AND_ALLIES), new AttackMove(Moves.WICKED_BLOW, Type.DARK, MoveCategory.PHYSICAL, 75, 100, 5, -1, 0, 8) .attr(CritOnlyAttr) .punchingMove(), @@ -8166,6 +8281,7 @@ export function initMoves() { .makesContact(false) .attr(FrenzyAttr) .attr(MissEffectAttr, frenzyMissFunc) + .attr(NoEffectAttr, frenzyMissFunc) .target(MoveTarget.RANDOM_NEAR_ENEMY), new AttackMove(Moves.WAVE_CRASH, Type.WATER, MoveCategory.PHYSICAL, 120, 100, 10, -1, 0, 8) .attr(RecoilAttr, false, 0.33) @@ -8221,9 +8337,10 @@ export function initMoves() { .target(MoveTarget.ALL_NEAR_ENEMIES), new StatusMove(Moves.LUNAR_BLESSING, Type.PSYCHIC, -1, 5, -1, 0, 8) .attr(HealAttr, 0.25) + .attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN, StatusEffect.SLEEP) + .attr(HealStatusEffectAttr, false, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN, StatusEffect.SLEEP) .target(MoveTarget.USER_AND_ALLIES) - .triageMove() - .partial(), + .triageMove(), new SelfStatusMove(Moves.TAKE_HEART, Type.PSYCHIC, -1, 10, -1, 0, 8) .attr(StatChangeAttr, [ BattleStat.SPATK, BattleStat.SPDEF ], 1, true) .attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN, StatusEffect.SLEEP), @@ -8360,7 +8477,8 @@ export function initMoves() { new AttackMove(Moves.ICE_SPINNER, Type.ICE, MoveCategory.PHYSICAL, 80, 100, 15, -1, 0, 9) .attr(ClearTerrainAttr), new AttackMove(Moves.GLAIVE_RUSH, Type.DRAGON, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 9) - .partial(), + .attr(AlwaysGetHitAttr) + .attr(ReceiveDoubleDamageAttr), new StatusMove(Moves.REVIVAL_BLESSING, Type.NORMAL, -1, 1, -1, 0, 9) .triageMove() .attr(RevivalBlessingAttr) diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index ae1532f0be01..2c2d637c6f02 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -8,6 +8,7 @@ import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import { TimeOfDay } from "#enums/time-of-day"; +import { getPokemonNameWithAffix } from "#app/messages.js"; export enum FormChangeItem { NONE, @@ -369,7 +370,7 @@ export function getSpeciesFormChangeMessage(pokemon: Pokemon, formChange: Specie return `${prefix}${preName} Eternamaxed\ninto ${pokemon.name}!`; } if (isRevert) { - return `${prefix}${pokemon.name} reverted\nto its original form!`; + return `${prefix}${getPokemonNameWithAffix(pokemon)} reverted\nto its original form!`; } return `${prefix}${preName} changed form!`; } diff --git a/src/data/pokemon-level-moves.ts b/src/data/pokemon-level-moves.ts index 53272ed5bebc..2ba8ccdf4636 100644 --- a/src/data/pokemon-level-moves.ts +++ b/src/data/pokemon-level-moves.ts @@ -587,28 +587,28 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 48, Moves.HEALING_WISH ], ], [Species.CLEFABLE]: [ + [ RELEARN_MOVE, Moves.POUND ], + [ RELEARN_MOVE, Moves.GROWL ], + [ RELEARN_MOVE, Moves.SING ], + [ RELEARN_MOVE, Moves.DEFENSE_CURL ], + [ RELEARN_MOVE, Moves.SPLASH ], + [ RELEARN_MOVE, Moves.SWEET_KISS ], + [ RELEARN_MOVE, Moves.CHARM ], + [ RELEARN_MOVE, Moves.ENCORE ], + [ RELEARN_MOVE, Moves.MOONLIGHT ], + [ RELEARN_MOVE, Moves.FOLLOW_ME ], + [ RELEARN_MOVE, Moves.COSMIC_POWER ], + [ RELEARN_MOVE, Moves.GRAVITY ], + [ RELEARN_MOVE, Moves.HEALING_WISH ], + [ RELEARN_MOVE, Moves.COPYCAT ], + [ RELEARN_MOVE, Moves.AFTER_YOU ], + [ RELEARN_MOVE, Moves.STORED_POWER ], + [ RELEARN_MOVE, Moves.DISARMING_VOICE ], [ 1, Moves.METRONOME ], [ 1, Moves.METEOR_MASH ], [ 1, Moves.MOONBLAST ], [ 1, Moves.LIFE_DEW ], - [ 1, Moves.POUND ], - [ 1, Moves.GROWL ], - [ 1, Moves.SING ], - [ 1, Moves.DEFENSE_CURL ], - [ 1, Moves.SPLASH ], - [ 1, Moves.SWEET_KISS ], - [ 1, Moves.CHARM ], - [ 1, Moves.ENCORE ], - [ 1, Moves.MOONLIGHT ], - [ 1, Moves.FOLLOW_ME ], - [ 1, Moves.COSMIC_POWER ], - [ 1, Moves.GRAVITY ], - [ 1, Moves.HEALING_WISH ], - [ 1, Moves.COPYCAT ], - [ 1, Moves.AFTER_YOU ], - [ 1, Moves.STORED_POWER ], [ 1, Moves.SPOTLIGHT ], - [ 1, Moves.DISARMING_VOICE ], ], [Species.VULPIX]: [ [ 1, Moves.TAIL_WHIP ], @@ -628,22 +628,22 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 52, Moves.FIRE_BLAST ], ], [Species.NINETALES]: [ + [ RELEARN_MOVE, Moves.DISABLE ], + [ RELEARN_MOVE, Moves.EMBER ], + [ RELEARN_MOVE, Moves.FIRE_SPIN ], + [ RELEARN_MOVE, Moves.CONFUSE_RAY ], + [ RELEARN_MOVE, Moves.FIRE_BLAST ], + [ RELEARN_MOVE, Moves.SPITE ], + [ RELEARN_MOVE, Moves.SAFEGUARD ], + [ RELEARN_MOVE, Moves.WILL_O_WISP ], + [ RELEARN_MOVE, Moves.IMPRISON ], + [ RELEARN_MOVE, Moves.EXTRASENSORY ], + [ RELEARN_MOVE, Moves.NASTY_PLOT ], + [ RELEARN_MOVE, Moves.INCINERATE ], + [ RELEARN_MOVE, Moves.INFERNO ], [ 1, Moves.FLAMETHROWER ], [ 1, Moves.TAIL_WHIP ], [ 1, Moves.QUICK_ATTACK ], - [ 1, Moves.DISABLE ], - [ 1, Moves.EMBER ], - [ 1, Moves.FIRE_SPIN ], - [ 1, Moves.CONFUSE_RAY ], - [ 1, Moves.FIRE_BLAST ], - [ 1, Moves.SPITE ], - [ 1, Moves.SAFEGUARD ], - [ 1, Moves.WILL_O_WISP ], - [ 1, Moves.IMPRISON ], - [ 1, Moves.EXTRASENSORY ], - [ 1, Moves.NASTY_PLOT ], - [ 1, Moves.INCINERATE ], - [ 1, Moves.INFERNO ], ], [Species.JIGGLYPUFF]: [ [ 1, Moves.POUND ], @@ -1047,16 +1047,16 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.BUBBLE_BEAM ], [ 1, Moves.BODY_SLAM ], [ 1, Moves.HYPNOSIS ], - [ 1, Moves.POUND ], - [ 1, Moves.DOUBLE_EDGE ], - [ 1, Moves.WATER_GUN ], [ 1, Moves.WATER_SPORT ], - [ 1, Moves.HYDRO_PUMP ], - [ 1, Moves.BELLY_DRUM ], - [ 1, Moves.RAIN_DANCE ], - [ 1, Moves.MUD_SHOT ], - [ 1, Moves.EARTH_POWER ], - [ 1, Moves.CIRCLE_THROW ], + [ RELEARN_MOVE, Moves.POUND ], + [ RELEARN_MOVE, Moves.DOUBLE_EDGE ], + [ RELEARN_MOVE, Moves.WATER_GUN ], + [ RELEARN_MOVE, Moves.HYDRO_PUMP ], + [ RELEARN_MOVE, Moves.BELLY_DRUM ], + [ RELEARN_MOVE, Moves.RAIN_DANCE ], + [ RELEARN_MOVE, Moves.MUD_SHOT ], + [ RELEARN_MOVE, Moves.EARTH_POWER ], + [ RELEARN_MOVE, Moves.CIRCLE_THROW ], ], [Species.ABRA]: [ [ 1, Moves.TELEPORT ], @@ -1181,15 +1181,15 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.VICTREEBEL]: [ [ EVOLVE_MOVE, Moves.LEAF_STORM ], + [ RELEARN_MOVE, Moves.STOCKPILE ], + [ RELEARN_MOVE, Moves.SWALLOW ], + [ RELEARN_MOVE, Moves.SPIT_UP ], + [ RELEARN_MOVE, Moves.GASTRO_ACID ], + [ RELEARN_MOVE, Moves.POWER_WHIP ], [ 1, Moves.VINE_WHIP ], [ 1, Moves.SLEEP_POWDER ], [ 1, Moves.SWEET_SCENT ], [ 1, Moves.RAZOR_LEAF ], - [ 1, Moves.STOCKPILE ], - [ 1, Moves.SWALLOW ], - [ 1, Moves.SPIT_UP ], - [ 1, Moves.GASTRO_ACID ], - [ 1, Moves.POWER_WHIP ], [ 44, Moves.LEAF_BLADE ], ], [Species.TENTACOOL]: [ @@ -1328,6 +1328,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 45, Moves.HEAL_PULSE ], ], [Species.SLOWBRO]: [ + [ RELEARN_MOVE, Moves.FUTURE_SIGHT ], [ 1, Moves.TACKLE ], [ 1, Moves.GROWL ], [ 1, Moves.WATER_GUN ], @@ -1745,6 +1746,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.EXEGGUTOR]: [ [ EVOLVE_MOVE, Moves.STOMP ], + [ RELEARN_MOVE, Moves.GROWTH ], [ 1, Moves.BARRAGE ], [ 1, Moves.SEED_BOMB ], [ 1, Moves.PSYSHOCK ], @@ -1763,7 +1765,6 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.HYPNOSIS ], [ 1, Moves.REFLECT ], [ 1, Moves.LEECH_SEED ], - [ 1, Moves.GROWTH ], ], [Species.CUBONE]: [ [ 1, Moves.GROWL ], @@ -3206,20 +3207,20 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.POLITOED]: [ [ EVOLVE_MOVE, Moves.BOUNCE ], + [ RELEARN_MOVE, Moves.BODY_SLAM ], + [ RELEARN_MOVE, Moves.DOUBLE_EDGE ], + [ RELEARN_MOVE, Moves.WATER_GUN ], + [ RELEARN_MOVE, Moves.BUBBLE_BEAM ], + [ RELEARN_MOVE, Moves.HYPNOSIS ], + [ RELEARN_MOVE, Moves.PERISH_SONG ], + [ RELEARN_MOVE, Moves.SWAGGER ], + [ RELEARN_MOVE, Moves.HYPER_VOICE ], + [ RELEARN_MOVE, Moves.MUD_SHOT ], + [ RELEARN_MOVE, Moves.EARTH_POWER ], [ 1, Moves.RAIN_DANCE ], [ 1, Moves.HYDRO_PUMP ], [ 1, Moves.BELLY_DRUM ], [ 1, Moves.POUND ], - [ 1, Moves.BODY_SLAM ], - [ 1, Moves.DOUBLE_EDGE ], - [ 1, Moves.WATER_GUN ], - [ 1, Moves.BUBBLE_BEAM ], - [ 1, Moves.HYPNOSIS ], - [ 1, Moves.PERISH_SONG ], - [ 1, Moves.SWAGGER ], - [ 1, Moves.HYPER_VOICE ], - [ 1, Moves.MUD_SHOT ], - [ 1, Moves.EARTH_POWER ], ], [Species.HOPPIP]: [ [ 1, Moves.TACKLE ], @@ -3448,6 +3449,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 60, Moves.QUASH ], ], [Species.SLOWKING]: [ + [ RELEARN_MOVE, Moves.FUTURE_SIGHT ], + [ RELEARN_MOVE, Moves.CHILLY_RECEPTION ], [ 1, Moves.POWER_GEM ], [ 1, Moves.NASTY_PLOT ], [ 1, Moves.SWAGGER ], @@ -3455,8 +3458,6 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.CURSE ], [ 1, Moves.GROWL ], [ 1, Moves.WATER_GUN ], - [ 1, Moves.FUTURE_SIGHT ], - [ 1, Moves.CHILLY_RECEPTION ], [ 9, Moves.YAWN ], [ 12, Moves.CONFUSION ], [ 15, Moves.DISABLE ], @@ -4214,12 +4215,12 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 78, Moves.ZAP_CANNON ], ], [Species.ENTEI]: [ + [ RELEARN_MOVE, Moves.SACRED_FIRE ], + [ RELEARN_MOVE, Moves.EXTREME_SPEED ], [ 1, Moves.STOMP ], [ 1, Moves.LEER ], [ 1, Moves.EMBER ], [ 1, Moves.SMOKESCREEN ], - [ 1, Moves.SACRED_FIRE ], - [ 1, Moves.EXTREME_SPEED ], [ 6, Moves.FLAME_WHEEL ], [ 12, Moves.BITE ], [ 18, Moves.CALM_MIND ], @@ -4235,12 +4236,12 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 78, Moves.ERUPTION ], ], [Species.SUICUNE]: [ + [ RELEARN_MOVE, Moves.EXTREME_SPEED ], + [ RELEARN_MOVE, Moves.SHEER_COLD ], [ 1, Moves.GUST ], [ 1, Moves.LEER ], [ 1, Moves.MIST ], [ 1, Moves.WATER_GUN ], - [ 1, Moves.EXTREME_SPEED ], - [ 1, Moves.SHEER_COLD ], [ 6, Moves.WATER_PULSE ], [ 12, Moves.BITE ], [ 18, Moves.CALM_MIND ], @@ -4317,11 +4318,11 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 59, Moves.GIGA_IMPACT ], ], [Species.LUGIA]: [ + [ RELEARN_MOVE, Moves.DRAGON_RUSH ], [ 1, Moves.GUST ], [ 1, Moves.WHIRLWIND ], [ 1, Moves.ANCIENT_POWER ], [ 1, Moves.WEATHER_BALL ], - [ 1, Moves.DRAGON_RUSH ], [ 9, Moves.MIST ], [ 18, Moves.SAFEGUARD ], [ 27, Moves.CALM_MIND ], @@ -4383,14 +4384,14 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 39, Moves.LEAF_STORM ], ], [Species.GROVYLE]: [ + [ RELEARN_MOVE, Moves.FALSE_SWIPE ], + [ RELEARN_MOVE, Moves.FURY_CUTTER ], + [ RELEARN_MOVE, Moves.X_SCISSOR ], + [ RELEARN_MOVE, Moves.ENERGY_BALL ], [ 1, Moves.POUND ], [ 1, Moves.LEER ], [ 1, Moves.LEAFAGE ], [ 1, Moves.QUICK_ATTACK ], - [ 1, Moves.FALSE_SWIPE ], - [ 1, Moves.FURY_CUTTER ], - [ 1, Moves.X_SCISSOR ], - [ 1, Moves.ENERGY_BALL ], [ 9, Moves.MEGA_DRAIN ], [ 12, Moves.DETECT ], [ 15, Moves.QUICK_GUARD ], @@ -4405,15 +4406,15 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.SCEPTILE]: [ [ EVOLVE_MOVE, Moves.LEAF_BLADE ], + [ RELEARN_MOVE, Moves.FALSE_SWIPE ], + [ RELEARN_MOVE, Moves.FURY_CUTTER ], + [ RELEARN_MOVE, Moves.X_SCISSOR ], + [ RELEARN_MOVE, Moves.ENERGY_BALL ], + [ RELEARN_MOVE, Moves.SHED_TAIL ], [ 1, Moves.POUND ], [ 1, Moves.LEER ], [ 1, Moves.LEAFAGE ], [ 1, Moves.QUICK_ATTACK ], - [ 1, Moves.FALSE_SWIPE ], - [ 1, Moves.FURY_CUTTER ], - [ 1, Moves.X_SCISSOR ], - [ 1, Moves.ENERGY_BALL ], - [ 1, Moves.SHED_TAIL ], [ 1, Moves.DUAL_CHOP ], [ 5, Moves.MEGA_DRAIN ], [ 12, Moves.DETECT ], @@ -4445,12 +4446,12 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.COMBUSKEN]: [ [ EVOLVE_MOVE, Moves.DOUBLE_KICK ], + [ RELEARN_MOVE, Moves.FLAMETHROWER ], + [ RELEARN_MOVE, Moves.FEATHER_DANCE ], [ 1, Moves.SCRATCH ], [ 1, Moves.GROWL ], [ 1, Moves.EMBER ], [ 1, Moves.QUICK_ATTACK ], - [ 1, Moves.FLAMETHROWER ], - [ 1, Moves.FEATHER_DANCE ], [ 9, Moves.FLAME_CHARGE ], [ 12, Moves.DETECT ], [ 15, Moves.SAND_ATTACK ], @@ -4465,14 +4466,14 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.BLAZIKEN]: [ [ EVOLVE_MOVE, Moves.BLAZE_KICK ], + [ RELEARN_MOVE, Moves.FIRE_PUNCH ], + [ RELEARN_MOVE, Moves.EMBER ], + [ RELEARN_MOVE, Moves.FLAMETHROWER ], + [ RELEARN_MOVE, Moves.FEATHER_DANCE ], [ 1, Moves.DOUBLE_KICK ], [ 1, Moves.SCRATCH ], [ 1, Moves.GROWL ], [ 1, Moves.QUICK_ATTACK ], - [ 1, Moves.FIRE_PUNCH ], - [ 1, Moves.EMBER ], - [ 1, Moves.FLAMETHROWER ], - [ 1, Moves.FEATHER_DANCE ], [ 9, Moves.FLAME_CHARGE ], [ 12, Moves.DETECT ], [ 15, Moves.SAND_ATTACK ], @@ -4504,10 +4505,10 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.MARSHTOMP]: [ [ EVOLVE_MOVE, Moves.MUD_SHOT ], + [ RELEARN_MOVE, Moves.ROCK_SMASH ], [ 1, Moves.TACKLE ], [ 1, Moves.GROWL ], [ 1, Moves.WATER_GUN ], - [ 1, Moves.ROCK_SMASH ], [ 9, Moves.ROCK_THROW ], [ 12, Moves.PROTECT ], [ 15, Moves.SUPERSONIC ], @@ -4521,14 +4522,14 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 55, Moves.HYDRO_PUMP ], ], [Species.SWAMPERT]: [ + [ RELEARN_MOVE, Moves.SURF ], + [ RELEARN_MOVE, Moves.EARTHQUAKE ], + [ RELEARN_MOVE, Moves.ROCK_SMASH ], + [ RELEARN_MOVE, Moves.HAMMER_ARM ], [ 1, Moves.MUD_SHOT ], [ 1, Moves.TACKLE ], [ 1, Moves.GROWL ], [ 1, Moves.WATER_GUN ], - [ 1, Moves.SURF ], - [ 1, Moves.EARTHQUAKE ], - [ 1, Moves.ROCK_SMASH ], - [ 1, Moves.HAMMER_ARM ], [ 9, Moves.ROCK_THROW ], [ 12, Moves.PROTECT ], [ 15, Moves.SUPERSONIC ], @@ -4706,22 +4707,22 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 64, Moves.HYDRO_PUMP ], ], [Species.LUDICOLO]: [ + [ RELEARN_MOVE, Moves.GROWL ], + [ RELEARN_MOVE, Moves.MIST ], + [ RELEARN_MOVE, Moves.WATER_GUN ], + [ RELEARN_MOVE, Moves.HYDRO_PUMP ], + [ RELEARN_MOVE, Moves.ABSORB ], + [ RELEARN_MOVE, Moves.MEGA_DRAIN ], + [ RELEARN_MOVE, Moves.FURY_SWIPES ], + [ RELEARN_MOVE, Moves.FLAIL ], + [ RELEARN_MOVE, Moves.KNOCK_OFF ], + [ RELEARN_MOVE, Moves.TEETER_DANCE ], + [ RELEARN_MOVE, Moves.ASTONISH ], + [ RELEARN_MOVE, Moves.ENERGY_BALL ], + [ RELEARN_MOVE, Moves.ZEN_HEADBUTT ], [ 1, Moves.FAKE_OUT ], [ 1, Moves.BUBBLE_BEAM ], [ 1, Moves.RAIN_DANCE ], - [ 1, Moves.GROWL ], - [ 1, Moves.MIST ], - [ 1, Moves.WATER_GUN ], - [ 1, Moves.HYDRO_PUMP ], - [ 1, Moves.ABSORB ], - [ 1, Moves.MEGA_DRAIN ], - [ 1, Moves.FURY_SWIPES ], - [ 1, Moves.FLAIL ], - [ 1, Moves.KNOCK_OFF ], - [ 1, Moves.TEETER_DANCE ], - [ 1, Moves.ASTONISH ], - [ 1, Moves.ENERGY_BALL ], - [ 1, Moves.ZEN_HEADBUTT ], ], [Species.SEEDOT]: [ [ 1, Moves.TACKLE ], @@ -4762,27 +4763,27 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.SHIFTRY]: [ [ EVOLVE_MOVE, Moves.LEAF_BLADE ], + [ RELEARN_MOVE, Moves.WHIRLWIND ], + [ RELEARN_MOVE, Moves.TACKLE ], + [ RELEARN_MOVE, Moves.ABSORB ], + [ RELEARN_MOVE, Moves.MEGA_DRAIN ], + [ RELEARN_MOVE, Moves.GROWTH ], + [ RELEARN_MOVE, Moves.RAZOR_LEAF ], + [ RELEARN_MOVE, Moves.HARDEN ], + [ RELEARN_MOVE, Moves.EXPLOSION ], + [ RELEARN_MOVE, Moves.ROLLOUT ], + [ RELEARN_MOVE, Moves.SWAGGER ], + [ RELEARN_MOVE, Moves.SYNTHESIS ], + [ RELEARN_MOVE, Moves.BEAT_UP ], + [ RELEARN_MOVE, Moves.FAKE_OUT ], + [ RELEARN_MOVE, Moves.TORMENT ], + [ RELEARN_MOVE, Moves.ASTONISH ], + [ RELEARN_MOVE, Moves.EXTRASENSORY ], + [ RELEARN_MOVE, Moves.SUCKER_PUNCH ], [ 1, Moves.AIR_CUTTER ], [ 1, Moves.HURRICANE ], [ 1, Moves.PAYBACK ], [ 1, Moves.SUNNY_DAY ], - [ 1, Moves.WHIRLWIND ], - [ 1, Moves.TACKLE ], - [ 1, Moves.ABSORB ], - [ 1, Moves.MEGA_DRAIN ], - [ 1, Moves.GROWTH ], - [ 1, Moves.RAZOR_LEAF ], - [ 1, Moves.HARDEN ], - [ 1, Moves.EXPLOSION ], - [ 1, Moves.ROLLOUT ], - [ 1, Moves.SWAGGER ], - [ 1, Moves.SYNTHESIS ], - [ 1, Moves.BEAT_UP ], - [ 1, Moves.FAKE_OUT ], - [ 1, Moves.TORMENT ], - [ 1, Moves.ASTONISH ], - [ 1, Moves.EXTRASENSORY ], - [ 1, Moves.SUCKER_PUNCH ], ], [Species.TAILLOW]: [ [ 1, Moves.PECK ], @@ -4952,6 +4953,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.BRELOOM]: [ [ EVOLVE_MOVE, Moves.MACH_PUNCH ], + [ RELEARN_MOVE, Moves.SPORE ], [ 1, Moves.POISON_POWDER ], [ 1, Moves.GROWTH ], [ 1, Moves.TOXIC ], @@ -5388,11 +5390,11 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 60, Moves.ELECTRIC_TERRAIN ], ], [Species.PLUSLE]: [ + [ RELEARN_MOVE, Moves.NUZZLE ], [ 1, Moves.PLAY_NICE ], [ 1, Moves.GROWL ], [ 1, Moves.THUNDER_WAVE ], [ 1, Moves.QUICK_ATTACK ], - [ 1, Moves.NUZZLE ], [ 4, Moves.HELPING_HAND ], [ 7, Moves.SPARK ], [ 10, Moves.ENCORE ], @@ -5410,11 +5412,11 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 49, Moves.ENTRAINMENT ], ], [Species.MINUN]: [ + [ RELEARN_MOVE, Moves.NUZZLE ], [ 1, Moves.PLAY_NICE ], [ 1, Moves.GROWL ], [ 1, Moves.THUNDER_WAVE ], [ 1, Moves.QUICK_ATTACK ], - [ 1, Moves.NUZZLE ], [ 4, Moves.HELPING_HAND ], [ 7, Moves.SPARK ], [ 10, Moves.ENCORE ], @@ -5712,15 +5714,15 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.VIBRAVA]: [ [ EVOLVE_MOVE, Moves.DRAGON_BREATH ], + [ RELEARN_MOVE, Moves.SUPERSONIC ], + [ RELEARN_MOVE, Moves.FISSURE ], + [ RELEARN_MOVE, Moves.CRUNCH ], + [ RELEARN_MOVE, Moves.SUPERPOWER ], + [ RELEARN_MOVE, Moves.ASTONISH ], + [ RELEARN_MOVE, Moves.BULLDOZE ], [ 1, Moves.DIG ], [ 1, Moves.SAND_ATTACK ], [ 1, Moves.BITE ], - [ 1, Moves.SUPERSONIC ], - [ 1, Moves.FISSURE ], - [ 1, Moves.CRUNCH ], - [ 1, Moves.SUPERPOWER ], - [ 1, Moves.ASTONISH ], - [ 1, Moves.BULLDOZE ], [ 1, Moves.BIDE ], [ 1, Moves.FEINT_ATTACK ], [ 12, Moves.MUD_SLAP ], @@ -5737,18 +5739,18 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.FLYGON]: [ [ EVOLVE_MOVE, Moves.DRAGON_CLAW ], + [ RELEARN_MOVE, Moves.BITE ], + [ RELEARN_MOVE, Moves.FISSURE ], + [ RELEARN_MOVE, Moves.DIG ], + [ RELEARN_MOVE, Moves.CRUNCH ], + [ RELEARN_MOVE, Moves.SUPERPOWER ], + [ RELEARN_MOVE, Moves.ASTONISH ], + [ RELEARN_MOVE, Moves.DRAGON_DANCE ], + [ RELEARN_MOVE, Moves.FEINT ], [ 1, Moves.DRAGON_BREATH ], [ 1, Moves.BULLDOZE ], [ 1, Moves.SAND_ATTACK ], [ 1, Moves.SUPERSONIC ], - [ 1, Moves.BITE ], - [ 1, Moves.FISSURE ], - [ 1, Moves.DIG ], - [ 1, Moves.CRUNCH ], - [ 1, Moves.SUPERPOWER ], - [ 1, Moves.ASTONISH ], - [ 1, Moves.DRAGON_DANCE ], - [ 1, Moves.FEINT ], [ 1, Moves.BIDE ], [ 1, Moves.FEINT_ATTACK ], [ 12, Moves.MUD_SLAP ], @@ -6526,12 +6528,12 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.METAGROSS]: [ [ EVOLVE_MOVE, Moves.HAMMER_ARM ], + [ RELEARN_MOVE, Moves.EXPLOSION ], + [ RELEARN_MOVE, Moves.HONE_CLAWS ], [ 1, Moves.CONFUSION ], [ 1, Moves.METAL_CLAW ], [ 1, Moves.BULLET_PUNCH ], [ 1, Moves.TACKLE ], - [ 1, Moves.EXPLOSION ], - [ 1, Moves.HONE_CLAWS ], [ 6, Moves.ZEN_HEADBUTT ], [ 12, Moves.MAGNET_RISE ], [ 16, Moves.FLASH_CANNON ], @@ -6796,6 +6798,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.INFERNAPE]: [ [ EVOLVE_MOVE, Moves.CLOSE_COMBAT ], + [ RELEARN_MOVE, Moves.TAUNT ], + [ RELEARN_MOVE, Moves.SLACK_OFF ], [ 1, Moves.SCRATCH ], [ 1, Moves.LEER ], [ 1, Moves.EMBER ], @@ -7082,6 +7086,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.BASTIODON]: [ [ EVOLVE_MOVE, Moves.BLOCK ], + [ RELEARN_MOVE, Moves.WIDE_GUARD ], [ 1, Moves.TACKLE ], [ 1, Moves.PROTECT ], [ 1, Moves.TAUNT ], @@ -8066,6 +8071,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.LIFE_DEW ], ], [Species.YANMEGA]: [ + [ RELEARN_MOVE, Moves.HYPNOSIS ], [ 1, Moves.TACKLE ], [ 1, Moves.DOUBLE_TEAM ], [ 1, Moves.NIGHT_SLASH ], @@ -8311,6 +8317,16 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 55, Moves.UPROAR ], ], [Species.UXIE]: [ + [ RELEARN_MOVE, Moves.TRI_ATTACK ], + [ RELEARN_MOVE, Moves.SNORE ], + [ RELEARN_MOVE, Moves.SAFEGUARD ], + [ RELEARN_MOVE, Moves.IRON_TAIL ], + [ RELEARN_MOVE, Moves.PSYCHO_CUT ], + [ RELEARN_MOVE, Moves.WONDER_ROOM ], + [ RELEARN_MOVE, Moves.MAGIC_ROOM ], + [ RELEARN_MOVE, Moves.ROUND ], + [ RELEARN_MOVE, Moves.ALLY_SWITCH ], + [ RELEARN_MOVE, Moves.EXPANDING_FORCE ], [ 1, Moves.CONFUSION ], [ 1, Moves.REST ], [ 7, Moves.SWIFT ], @@ -8327,6 +8343,16 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 84, Moves.MYSTICAL_POWER ], ], [Species.MESPRIT]: [ + [ RELEARN_MOVE, Moves.TRI_ATTACK ], + [ RELEARN_MOVE, Moves.SNORE ], + [ RELEARN_MOVE, Moves.SAFEGUARD ], + [ RELEARN_MOVE, Moves.IRON_TAIL ], + [ RELEARN_MOVE, Moves.PSYCHO_CUT ], + [ RELEARN_MOVE, Moves.WONDER_ROOM ], + [ RELEARN_MOVE, Moves.MAGIC_ROOM ], + [ RELEARN_MOVE, Moves.ROUND ], + [ RELEARN_MOVE, Moves.ALLY_SWITCH ], + [ RELEARN_MOVE, Moves.EXPANDING_FORCE ], [ 1, Moves.CONFUSION ], [ 1, Moves.REST ], [ 7, Moves.SWIFT ], @@ -8343,6 +8369,19 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 84, Moves.MYSTICAL_POWER ], ], [Species.AZELF]: [ + [ RELEARN_MOVE, Moves.SELF_DESTRUCT ], + [ RELEARN_MOVE, Moves.TRI_ATTACK ], + [ RELEARN_MOVE, Moves.SNORE ], + [ RELEARN_MOVE, Moves.SAFEGUARD ], + [ RELEARN_MOVE, Moves.IRON_TAIL ], + [ RELEARN_MOVE, Moves.PAYBACK ], + [ RELEARN_MOVE, Moves.ASSURANCE ], + [ RELEARN_MOVE, Moves.PSYCHO_CUT ], + [ RELEARN_MOVE, Moves.WONDER_ROOM ], + [ RELEARN_MOVE, Moves.MAGIC_ROOM ], + [ RELEARN_MOVE, Moves.ROUND ], + [ RELEARN_MOVE, Moves.ALLY_SWITCH ], + [ RELEARN_MOVE, Moves.EXPANDING_FORCE ], [ 1, Moves.CONFUSION ], [ 1, Moves.REST ], [ 7, Moves.SWIFT ], @@ -8633,12 +8672,12 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 52, Moves.FLARE_BLITZ ], ], [Species.EMBOAR]: [ + [ RELEARN_MOVE, Moves.ENDURE ], + [ RELEARN_MOVE, Moves.HAMMER_ARM ], [ 1, Moves.TACKLE ], [ 1, Moves.TAIL_WHIP ], [ 1, Moves.EMBER ], [ 1, Moves.ARM_THRUST ], - [ 1, Moves.ENDURE ], - [ 1, Moves.HAMMER_ARM ], [ 13, Moves.DEFENSE_CURL ], [ 15, Moves.FLAME_CHARGE ], [ 20, Moves.SMOG ], @@ -9300,6 +9339,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.LEAVANNY]: [ [ EVOLVE_MOVE, Moves.SLASH ], + [ RELEARN_MOVE, Moves.BUG_BITE ], [ 1, Moves.TACKLE ], [ 1, Moves.RAZOR_LEAF ], [ 1, Moves.STRING_SHOT ], @@ -9864,21 +9904,21 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.CINCCINO]: [ [ EVOLVE_MOVE, Moves.TAIL_SLAP ], + [ RELEARN_MOVE, Moves.SLAM ], + [ RELEARN_MOVE, Moves.SWIFT ], + [ RELEARN_MOVE, Moves.ENCORE ], + [ RELEARN_MOVE, Moves.HELPING_HAND ], + [ RELEARN_MOVE, Moves.HYPER_VOICE ], + [ RELEARN_MOVE, Moves.TICKLE ], + [ RELEARN_MOVE, Moves.ROCK_BLAST ], + [ RELEARN_MOVE, Moves.LAST_RESORT ], + [ RELEARN_MOVE, Moves.AFTER_YOU ], + [ RELEARN_MOVE, Moves.ECHOED_VOICE ], + [ RELEARN_MOVE, Moves.BABY_DOLL_EYES ], [ 1, Moves.BULLET_SEED ], [ 1, Moves.SING ], [ 1, Moves.CHARM ], [ 1, Moves.POUND ], - [ 1, Moves.SLAM ], - [ 1, Moves.SWIFT ], - [ 1, Moves.ENCORE ], - [ 1, Moves.HELPING_HAND ], - [ 1, Moves.HYPER_VOICE ], - [ 1, Moves.TICKLE ], - [ 1, Moves.ROCK_BLAST ], - [ 1, Moves.LAST_RESORT ], - [ 1, Moves.AFTER_YOU ], - [ 1, Moves.ECHOED_VOICE ], - [ 1, Moves.BABY_DOLL_EYES ], ], [Species.GOTHITA]: [ [ 1, Moves.POUND ], @@ -10738,10 +10778,10 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 56, Moves.DYNAMIC_PUNCH ], ], [Species.GOLURK]: [ + [ RELEARN_MOVE, Moves.MUD_SLAP ], + [ RELEARN_MOVE, Moves.FOCUS_PUNCH ], [ 1, Moves.POUND ], [ 1, Moves.DEFENSE_CURL ], - [ 1, Moves.MUD_SLAP ], - [ 1, Moves.FOCUS_PUNCH ], [ 1, Moves.ASTONISH ], [ 1, Moves.HIGH_HORSEPOWER ], [ 12, Moves.SHADOW_PUNCH ], @@ -11045,6 +11085,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 70, Moves.CLOSE_COMBAT ], ], [Species.VIRIZION]: [ + [ RELEARN_MOVE, Moves.TAKE_DOWN ], [ 1, Moves.LEER ], [ 1, Moves.QUICK_ATTACK ], [ 1, Moves.HELPING_HAND ], @@ -12543,13 +12584,13 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.INCINEROAR]: [ [ EVOLVE_MOVE, Moves.DARKEST_LARIAT ], - [ 1, Moves.SCRATCH ], - [ 1, Moves.GROWL ], + [ RELEARN_MOVE, Moves.SCRATCH ], + [ RELEARN_MOVE, Moves.GROWL ], + [ RELEARN_MOVE, Moves.THROAT_CHOP ], [ 1, Moves.EMBER ], [ 1, Moves.LICK ], [ 1, Moves.CROSS_CHOP ], [ 1, Moves.BULK_UP ], - [ 1, Moves.THROAT_CHOP ], [ 9, Moves.ROAR ], [ 12, Moves.FURY_SWIPES ], [ 15, Moves.BITE ], @@ -12626,11 +12667,11 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 37, Moves.HYPER_VOICE ], ], [Species.TRUMBEAK]: [ + [ RELEARN_MOVE, Moves.ECHOED_VOICE ], [ 1, Moves.GROWL ], [ 1, Moves.PECK ], [ 1, Moves.ROCK_SMASH ], [ 1, Moves.ROCK_BLAST ], - [ 1, Moves.ECHOED_VOICE ], [ 13, Moves.SUPERSONIC ], [ 16, Moves.PLUCK ], [ 21, Moves.ROOST ], @@ -12720,16 +12761,16 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.VIKAVOLT]: [ [ EVOLVE_MOVE, Moves.THUNDERBOLT ], + [ RELEARN_MOVE, Moves.VISE_GRIP ], + [ RELEARN_MOVE, Moves.DIG ], + [ RELEARN_MOVE, Moves.MUD_SLAP ], + [ RELEARN_MOVE, Moves.IRON_DEFENSE ], + [ RELEARN_MOVE, Moves.X_SCISSOR ], + [ RELEARN_MOVE, Moves.BUG_BITE ], [ 1, Moves.CHARGE ], [ 1, Moves.CRUNCH ], [ 1, Moves.DISCHARGE ], [ 1, Moves.STRING_SHOT ], - [ 1, Moves.VISE_GRIP ], - [ 1, Moves.DIG ], - [ 1, Moves.MUD_SLAP ], - [ 1, Moves.IRON_DEFENSE ], - [ 1, Moves.X_SCISSOR ], - [ 1, Moves.BUG_BITE ], [ 15, Moves.BITE ], [ 23, Moves.SPARK ], [ 29, Moves.STICKY_WEB ], @@ -13473,6 +13514,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.KOMMO_O]: [ [ EVOLVE_MOVE, Moves.CLANGING_SCALES ], + [ RELEARN_MOVE, Moves.BELLY_DRUM ], [ 1, Moves.TACKLE ], [ 1, Moves.LEER ], [ 1, Moves.PROTECT ], @@ -14411,6 +14453,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 51, Moves.SAND_TOMB ], ], [Species.CRAMORANT]: [ + [ RELEARN_MOVE, Moves.BELCH ], [ 1, Moves.PECK ], [ 1, Moves.STOCKPILE ], [ 1, Moves.SPIT_UP ], @@ -15437,6 +15480,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.MEOWSCARADA]: [ [ EVOLVE_MOVE, Moves.FLOWER_TRICK ], + [ RELEARN_MOVE, Moves.DOUBLE_TEAM ], + [ RELEARN_MOVE, Moves.TRICK ], [ 1, Moves.SCRATCH ], [ 1, Moves.TAIL_WHIP ], [ 1, Moves.LEAFAGE ], @@ -15487,6 +15532,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.SKELEDIRGE]: [ [ EVOLVE_MOVE, Moves.TORCH_SONG ], + [ RELEARN_MOVE, Moves.SING ], + [ RELEARN_MOVE, Moves.YAWN ], [ 1, Moves.TACKLE ], [ 1, Moves.LEER ], [ 1, Moves.EMBER ], @@ -15538,6 +15585,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.QUAQUAVAL]: [ [ EVOLVE_MOVE, Moves.AQUA_STEP ], + [ RELEARN_MOVE, Moves.COUNTER ], [ 1, Moves.POUND ], [ 1, Moves.GROWL ], [ 1, Moves.WATER_GUN ], @@ -15937,13 +15985,13 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.CERULEDGE]: [ [ EVOLVE_MOVE, Moves.SHADOW_CLAW ], + [ RELEARN_MOVE, Moves.NIGHT_SLASH ], + [ RELEARN_MOVE, Moves.SHADOW_SNEAK ], + [ RELEARN_MOVE, Moves.QUICK_GUARD ], + [ RELEARN_MOVE, Moves.SOLAR_BLADE ], [ 1, Moves.EMBER ], [ 1, Moves.LEER ], [ 1, Moves.ASTONISH ], - [ 1, Moves.NIGHT_SLASH ], - [ 1, Moves.SHADOW_SNEAK ], - [ 1, Moves.QUICK_GUARD ], - [ 1, Moves.SOLAR_BLADE ], [ 8, Moves.CLEAR_SMOG ], [ 12, Moves.FIRE_SPIN ], [ 16, Moves.WILL_O_WISP ], @@ -16224,6 +16272,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.RABSCA]: [ [ EVOLVE_MOVE, Moves.REVIVAL_BLESSING ], + [ RELEARN_MOVE, Moves.SAFEGUARD ], + [ RELEARN_MOVE, Moves.PSYCH_UP ], [ 1, Moves.TACKLE ], [ 1, Moves.CONFUSION ], [ 1, Moves.DEFENSE_CURL ], @@ -16756,6 +16806,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.HEADLONG_RUSH ], ], [Species.SCREAM_TAIL]: [ + [ RELEARN_MOVE, Moves.SUNNY_DAY ], [ 1, Moves.POUND ], [ 1, Moves.SING ], [ 1, Moves.DISABLE ], @@ -16774,6 +16825,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.BOOMBURST ], ], [Species.BRUTE_BONNET]: [ + [ RELEARN_MOVE, Moves.SUNNY_DAY ], [ 1, Moves.ABSORB ], [ 1, Moves.GROWTH ], [ 1, Moves.ASTONISH ], @@ -16791,6 +16843,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.SOLAR_BEAM ], ], [Species.FLUTTER_MANE]: [ + [ RELEARN_MOVE, Moves.SUNNY_DAY ], [ 1, Moves.CONFUSE_RAY ], [ 1, Moves.SPITE ], [ 1, Moves.ASTONISH ], @@ -16809,6 +16862,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.PERISH_SONG ], ], [Species.SLITHER_WING]: [ + [ RELEARN_MOVE, Moves.SUNNY_DAY ], [ 1, Moves.GUST ], [ 1, Moves.EMBER ], [ 1, Moves.BUG_BITE ], @@ -16828,6 +16882,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.THRASH ], ], [Species.SANDY_SHOCKS]: [ + [ RELEARN_MOVE, Moves.SUNNY_DAY ], [ 1, Moves.SUPERSONIC ], [ 1, Moves.THUNDER_SHOCK ], [ 1, Moves.THUNDER_WAVE ], @@ -16865,6 +16920,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.STEEL_ROLLER ], ], [Species.IRON_BUNDLE]: [ + [ RELEARN_MOVE, Moves.ELECTRIC_TERRAIN ], [ 1, Moves.PRESENT ], [ 1, Moves.WATER_GUN ], //Custom [ 7, Moves.POWDER_SNOW ], @@ -16882,6 +16938,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.BLIZZARD ], ], [Species.IRON_HANDS]: [ + [ RELEARN_MOVE, Moves.ELECTRIC_TERRAIN ], [ 1, Moves.SAND_ATTACK ], [ 1, Moves.TACKLE ], [ 1, Moves.FOCUS_ENERGY ], @@ -16901,6 +16958,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.FOCUS_PUNCH ], ], [Species.IRON_JUGULIS]: [ + [ RELEARN_MOVE, Moves.ELECTRIC_TERRAIN ], [ 1, Moves.FOCUS_ENERGY ], [ 1, Moves.TRI_ATTACK ], [ 1, Moves.AIR_CUTTER ], @@ -16920,6 +16978,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.HYPER_BEAM ], ], [Species.IRON_MOTH]: [ + [ RELEARN_MOVE, Moves.ELECTRIC_TERRAIN ], [ 1, Moves.GUST ], [ 1, Moves.WHIRLWIND ], [ 1, Moves.EMBER ], @@ -16939,6 +16998,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.OVERHEAT ], ], [Species.IRON_THORNS]: [ + [ RELEARN_MOVE, Moves.ELECTRIC_TERRAIN ], [ 1, Moves.ROCK_THROW ], [ 1, Moves.IRON_DEFENSE ], [ 1, Moves.THUNDER_FANG ], @@ -17106,6 +17166,10 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 75, Moves.OVERHEAT ], ], [Species.ROARING_MOON]: [ + [ RELEARN_MOVE, Moves.SUNNY_DAY ], + [ RELEARN_MOVE, Moves.JAW_LOCK ], + [ RELEARN_MOVE, Moves.BREAKING_SWIPE ], + [ RELEARN_MOVE, Moves.SCALE_SHOT ], [ 1, Moves.LEER ], [ 1, Moves.BITE ], [ 1, Moves.FOCUS_ENERGY ], @@ -17125,6 +17189,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 91, Moves.DOUBLE_EDGE ], ], [Species.IRON_VALIANT]: [ + [ RELEARN_MOVE, Moves.ELECTRIC_TERRAIN ], [ 1, Moves.DISABLE ], [ 1, Moves.DOUBLE_TEAM ], [ 1, Moves.FURY_CUTTER ], @@ -17222,11 +17287,11 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.DIPPLIN]: [ [ EVOLVE_MOVE, Moves.DOUBLE_HIT ], + [ RELEARN_MOVE, Moves.INFESTATION ], [ 1, Moves.WITHDRAW ], [ 1, Moves.SWEET_SCENT ], [ 1, Moves.RECYCLE ], [ 1, Moves.ASTONISH ], - [ 1, Moves.INFESTATION ], [ 4, Moves.DRAGON_TAIL ], [ 8, Moves.GROWTH ], [ 12, Moves.DRAGON_BREATH ], @@ -17315,6 +17380,10 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 72, Moves.MOONBLAST ], ], [Species.OGERPON]: [ + [ RELEARN_MOVE, Moves.DOUBLE_KICK ], + [ RELEARN_MOVE, Moves.COUNTER ], + [ RELEARN_MOVE, Moves.RETALIATE ], + [ RELEARN_MOVE, Moves.HORN_LEECH ], [ 1, Moves.VINE_WHIP ], [ 1, Moves.LEECH_SEED ], [ 1, Moves.QUICK_ATTACK ], @@ -17349,13 +17418,13 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.HYDRAPPLE]: [ [ EVOLVE_MOVE, Moves.FICKLE_BEAM ], + [ RELEARN_MOVE, Moves.YAWN ], + [ RELEARN_MOVE, Moves.DOUBLE_HIT ], + [ RELEARN_MOVE, Moves.INFESTATION ], [ 1, Moves.WITHDRAW ], [ 1, Moves.SWEET_SCENT ], [ 1, Moves.RECYCLE ], [ 1, Moves.ASTONISH ], - [ 1, Moves.YAWN ], - [ 1, Moves.DOUBLE_HIT ], - [ 1, Moves.INFESTATION ], [ 4, Moves.DRAGON_TAIL ], [ 8, Moves.GROWTH ], [ 12, Moves.DRAGON_BREATH ], @@ -17463,6 +17532,9 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 90, Moves.GYRO_BALL ], ], [Species.PECHARUNT]: [ + [ RELEARN_MOVE, Moves.DEFENSE_CURL ], + [ RELEARN_MOVE, Moves.ROLLOUT ], + [ RELEARN_MOVE, Moves.MEAN_LOOK ], [ 1, Moves.SMOG ], [ 1, Moves.POISON_GAS ], [ 1, Moves.MEMENTO ], @@ -17555,25 +17627,25 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.ALOLA_SANDSLASH]: [ [ EVOLVE_MOVE, Moves.ICICLE_SPEAR ], + [ RELEARN_MOVE, Moves.SCRATCH ], + [ RELEARN_MOVE, Moves.MIST ], + [ RELEARN_MOVE, Moves.BLIZZARD ], + [ RELEARN_MOVE, Moves.DEFENSE_CURL ], + [ RELEARN_MOVE, Moves.SWIFT ], + [ RELEARN_MOVE, Moves.FURY_SWIPES ], + [ RELEARN_MOVE, Moves.POWDER_SNOW ], + [ RELEARN_MOVE, Moves.ROLLOUT ], + [ RELEARN_MOVE, Moves.FURY_CUTTER ], + [ RELEARN_MOVE, Moves.RAPID_SPIN ], + [ RELEARN_MOVE, Moves.IRON_DEFENSE ], + [ RELEARN_MOVE, Moves.GYRO_BALL ], + [ RELEARN_MOVE, Moves.METAL_BURST ], + [ RELEARN_MOVE, Moves.IRON_HEAD ], + [ RELEARN_MOVE, Moves.SNOWSCAPE ], [ 1, Moves.ICICLE_CRASH ], [ 1, Moves.METAL_CLAW ], [ 1, Moves.SLASH ], [ 1, Moves.SWORDS_DANCE ], - [ 1, Moves.SCRATCH ], - [ 1, Moves.MIST ], - [ 1, Moves.BLIZZARD ], - [ 1, Moves.DEFENSE_CURL ], - [ 1, Moves.SWIFT ], - [ 1, Moves.FURY_SWIPES ], - [ 1, Moves.POWDER_SNOW ], - [ 1, Moves.ROLLOUT ], - [ 1, Moves.FURY_CUTTER ], - [ 1, Moves.RAPID_SPIN ], - [ 1, Moves.IRON_DEFENSE ], - [ 1, Moves.GYRO_BALL ], - [ 1, Moves.METAL_BURST ], - [ 1, Moves.IRON_HEAD ], - [ 1, Moves.SNOWSCAPE ], [ 1, Moves.ICE_BALL ], ], [Species.ALOLA_VULPIX]: [ @@ -17595,22 +17667,22 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.ALOLA_NINETALES]: [ [ EVOLVE_MOVE, Moves.DAZZLING_GLEAM ], + [ RELEARN_MOVE, Moves.DISABLE ], + [ RELEARN_MOVE, Moves.MIST ], + [ RELEARN_MOVE, Moves.ICE_BEAM ], + [ RELEARN_MOVE, Moves.AURORA_BEAM ], + [ RELEARN_MOVE, Moves.CONFUSE_RAY ], + [ RELEARN_MOVE, Moves.SPITE ], + [ RELEARN_MOVE, Moves.POWDER_SNOW ], + [ RELEARN_MOVE, Moves.EXTRASENSORY ], + [ RELEARN_MOVE, Moves.NASTY_PLOT ], + [ RELEARN_MOVE, Moves.ICE_SHARD ], + [ RELEARN_MOVE, Moves.FREEZE_DRY ], + [ RELEARN_MOVE, Moves.AURORA_VEIL ], [ 1, Moves.ICY_WIND ], [ 1, Moves.IMPRISON ], [ 1, Moves.BLIZZARD ], [ 1, Moves.TAIL_WHIP ], - [ 1, Moves.DISABLE ], - [ 1, Moves.MIST ], - [ 1, Moves.ICE_BEAM ], - [ 1, Moves.AURORA_BEAM ], - [ 1, Moves.CONFUSE_RAY ], - [ 1, Moves.SPITE ], - [ 1, Moves.POWDER_SNOW ], - [ 1, Moves.EXTRASENSORY ], - [ 1, Moves.NASTY_PLOT ], - [ 1, Moves.ICE_SHARD ], - [ 1, Moves.FREEZE_DRY ], - [ 1, Moves.AURORA_VEIL ], ], [Species.ALOLA_DIGLETT]: [ [ 1, Moves.SAND_ATTACK ], @@ -17771,6 +17843,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.ALOLA_EXEGGUTOR]: [ [ EVOLVE_MOVE, Moves.DRAGON_HAMMER ], + [ RELEARN_MOVE, Moves.GROWTH ], [ 1, Moves.BARRAGE ], [ 1, Moves.SEED_BOMB ], [ 1, Moves.PSYSHOCK ], @@ -17789,7 +17862,6 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.HYPNOSIS ], [ 1, Moves.REFLECT ], [ 1, Moves.LEECH_SEED ], - [ 1, Moves.GROWTH ], ], [Species.ALOLA_MAROWAK]: [ [ EVOLVE_MOVE, Moves.SHADOW_BONE ], @@ -18043,6 +18115,9 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.GALAR_SLOWKING]: [ [ EVOLVE_MOVE, Moves.EERIE_SPELL ], + [ RELEARN_MOVE, Moves.FUTURE_SIGHT ], + [ RELEARN_MOVE, Moves.CHILLY_RECEPTION ], + [ RELEARN_MOVE, Moves.TOXIC ], [ 1, Moves.POWER_GEM ], [ 1, Moves.NASTY_PLOT ], [ 1, Moves.SWAGGER ], @@ -18050,9 +18125,6 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.CURSE ], [ 1, Moves.GROWL ], [ 1, Moves.ACID ], - [ 1, Moves.TOXIC ], - [ 1, Moves.FUTURE_SIGHT ], - [ 1, Moves.CHILLY_RECEPTION ], [ 9, Moves.YAWN ], [ 12, Moves.CONFUSION ], [ 15, Moves.DISABLE ], @@ -18523,11 +18595,11 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 40, Moves.EARTHQUAKE ], ], [Species.BLOODMOON_URSALUNA]: [ + [ RELEARN_MOVE, Moves.MOONLIGHT ], [ 1, Moves.HEADLONG_RUSH ], [ 1, Moves.SCRATCH ], [ 1, Moves.LEER ], [ 1, Moves.LICK ], - [ 1, Moves.MOONLIGHT ], [ 8, Moves.FURY_SWIPES ], [ 13, Moves.PAYBACK ], [ 17, Moves.HARDEN ], diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 2b488f330c45..e0fc8df823cc 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -177,12 +177,40 @@ export abstract class PokemonSpeciesForm { return this.type1 === type || (this.type2 !== null && this.type2 === type); } + /** + * Method to get the total number of abilities a Pokemon species has. + * @returns Number of abilities + */ getAbilityCount(): integer { - return this.ability2 ? this.abilityHidden ? 3 : 2 : this.abilityHidden ? 2 : 1; + let count = 1; + if (this.ability2 !== Abilities.NONE) { + count += 1; + } + if (this.abilityHidden !== Abilities.NONE) { + count += 1; + } + return count; } + /** + * Method to get the ability of a Pokemon species. + * @param abilityIndex Which ability to get (should only be 0-2) + * @returns The id of the Ability + */ getAbility(abilityIndex: integer): Abilities { - return !abilityIndex ? this.ability1 : abilityIndex === 1 && this.ability2 ? this.ability2 : this.abilityHidden; + let ret: Abilities; + if (abilityIndex === 0) { + ret = this.ability1; + } else if (abilityIndex === 1) { + if (this.ability2 !== Abilities.NONE) { + ret = this.ability2; + } else { + ret = this.abilityHidden; + } + } else { + ret = this.abilityHidden; + } + return ret; } getLevelMoves(): LevelMoves { @@ -597,20 +625,24 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali getName(formIndex?: integer): string { if (formIndex !== undefined && this.forms.length) { const form = this.forms[formIndex]; + let key: string; switch (form.formKey) { case SpeciesFormKey.MEGA: case SpeciesFormKey.PRIMAL: case SpeciesFormKey.ETERNAMAX: - return `${form.formName} ${this.name}`; case SpeciesFormKey.MEGA_X: - return `Mega ${this.name} X`; case SpeciesFormKey.MEGA_Y: - return `Mega ${this.name} Y`; + key = form.formKey; + break; default: if (form.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1) { - return `G-Max ${this.name}`; + key = "gigantamax"; } } + + if (key) { + return i18next.t(`pokemonForm:${key}`, {pokemonName: this.name}); + } } return this.name; } diff --git a/src/data/tms.ts b/src/data/tms.ts index a0359a5d526a..761dcdf6be47 100644 --- a/src/data/tms.ts +++ b/src/data/tms.ts @@ -282,9 +282,13 @@ export const tmSpecies: TmSpecies = { Species.MEWTWO, Species.MEW, Species.HOPPIP, + Species.SKIPLOOM, + Species.JUMPLUFF, Species.ESPEON, Species.UMBREON, Species.SLOWKING, + Species.SKITTY, + Species.DELCATTY, Species.MUNCHLAX, Species.RHYPERIOR, Species.LEAFEON, @@ -301,6 +305,7 @@ export const tmSpecies: TmSpecies = { Species.PERRSERKER, Species.INDEEDEE, Species.CALYREX, + Species.ANNIHILAPE, Species.ALOLA_RAICHU, Species.ALOLA_MEOWTH, Species.ALOLA_PERSIAN, @@ -400,11 +405,7 @@ export const tmSpecies: TmSpecies = { Species.REGIROCK, Species.GROUDON, Species.JIRACHI, - [ - Species.DEOXYS, - "", - "speed", - ], + Species.DEOXYS, Species.CHIMCHAR, Species.MONFERNO, Species.INFERNAPE, @@ -459,6 +460,10 @@ export const tmSpecies: TmSpecies = { Species.HOOPA, Species.INCINEROAR, Species.GUMSHOOS, + [ + Species.LYCANROC, + "midnight", + ], Species.KOMMO_O, Species.MARSHADOW, Species.BLACEPHALON, @@ -603,11 +608,7 @@ export const tmSpecies: TmSpecies = { Species.REGICE, Species.REGISTEEL, Species.JIRACHI, - [ - Species.DEOXYS, - "", - "speed", - ], + Species.DEOXYS, Species.BUIZEL, Species.FLOATZEL, Species.AMBIPOM, @@ -807,11 +808,7 @@ export const tmSpecies: TmSpecies = { Species.REGISTEEL, Species.GROUDON, Species.JIRACHI, - [ - Species.DEOXYS, - "", - "speed", - ], + Species.DEOXYS, Species.CHIMCHAR, Species.MONFERNO, Species.INFERNAPE, @@ -877,6 +874,10 @@ export const tmSpecies: TmSpecies = { Species.CRABOMINABLE, Species.STUFFUL, Species.BEWEAR, + [ + Species.LYCANROC, + "midnight", + ], Species.KOMMO_O, Species.TAPU_KOKO, Species.BUZZWOLE, @@ -954,6 +955,8 @@ export const tmSpecies: TmSpecies = { Species.EXEGGUTOR, Species.CUBONE, Species.MAROWAK, + Species.HITMONLEE, + Species.HITMONCHAN, Species.LICKITUNG, Species.RHYHORN, Species.RHYDON, @@ -1078,6 +1081,7 @@ export const tmSpecies: TmSpecies = { Species.LILLIGANT, Species.DWEBBLE, Species.CRUSTLE, + Species.SCRAFTY, Species.ZORUA, Species.ZOROARK, Species.SAWSBUCK, @@ -2026,6 +2030,7 @@ export const tmSpecies: TmSpecies = { Species.PUPITAR, Species.TYRANITAR, Species.LUGIA, + Species.HO_OH, Species.TREECKO, Species.GROVYLE, Species.SCEPTILE, @@ -2146,6 +2151,7 @@ export const tmSpecies: TmSpecies = { Species.LUXRAY, Species.ROSERADE, Species.SHIELDON, + Species.BASTIODON, Species.FLOATZEL, Species.SHELLOS, Species.GASTRODON, @@ -2188,8 +2194,15 @@ export const tmSpecies: TmSpecies = { Species.GIRATINA, Species.CRESSELIA, Species.ARCEUS, + Species.SERPERIOR, Species.TEPIG, + Species.PIGNITE, + Species.EMBOAR, Species.SAMUROTT, + Species.BLITZLE, + Species.ZEBSTRIKA, + Species.DRILBUR, + Species.EXCADRILL, Species.AUDINO, Species.CONKELDURR, Species.THROH, @@ -2197,11 +2210,13 @@ export const tmSpecies: TmSpecies = { Species.KROKOROK, Species.KROOKODILE, Species.DARMANITAN, + Species.SCRAFTY, Species.TIRTOUGA, Species.CARRACOSTA, Species.GARBODOR, Species.ZOROARK, Species.GOTHITELLE, + Species.REUNICLUS, Species.DEERLING, Species.SAWSBUCK, Species.FOONGUS, @@ -2216,6 +2231,7 @@ export const tmSpecies: TmSpecies = { Species.SHELMET, Species.ACCELGOR, Species.DRUDDIGON, + Species.GOLETT, Species.GOLURK, Species.BOUFFALANT, Species.RUFFLET, @@ -2226,9 +2242,15 @@ export const tmSpecies: TmSpecies = { Species.HYDREIGON, Species.LARVESTA, Species.VOLCARONA, + Species.COBALION, + Species.TERRAKION, + Species.VIRIZION, Species.TORNADUS, Species.THUNDURUS, + Species.RESHIRAM, + Species.ZEKROM, Species.LANDORUS, + Species.KYUREM, Species.CHESPIN, Species.QUILLADIN, Species.CHESNAUGHT, @@ -2261,18 +2283,17 @@ export const tmSpecies: TmSpecies = { Species.LITTEN, Species.TORRACAT, Species.INCINEROAR, + Species.BRIONNE, + Species.PRIMARINA, Species.GUMSHOOS, Species.CRABRAWLER, Species.CRABOMINABLE, Species.ROCKRUFF, - [ - Species.LYCANROC, - "midday", - "midnight", - ], + Species.LYCANROC, Species.TOXAPEX, Species.MUDBRAY, Species.MUDSDALE, + Species.ARAQUANID, Species.SALAZZLE, Species.BEWEAR, Species.ORANGURU, @@ -2283,10 +2304,12 @@ export const tmSpecies: TmSpecies = { Species.JANGMO_O, Species.HAKAMO_O, Species.KOMMO_O, + Species.SOLGALEO, Species.NIHILEGO, Species.BUZZWOLE, Species.CELESTEELA, Species.GUZZLORD, + Species.NECROZMA, Species.MAGEARNA, Species.STAKATAKA, Species.MELMETAL, @@ -3648,6 +3671,7 @@ export const tmSpecies: TmSpecies = { Species.SPINARAK, Species.ARIADOS, Species.PINECO, + Species.FORRETRESS, Species.QWILFISH, Species.HERACROSS, Species.ZIGZAGOON, @@ -4258,6 +4282,7 @@ export const tmSpecies: TmSpecies = { Species.DEWOTT, Species.SAMUROTT, Species.PANPOUR, + Species.SIMIPOUR, Species.DRILBUR, Species.EXCADRILL, Species.TYMPOLE, @@ -4288,6 +4313,7 @@ export const tmSpecies: TmSpecies = { Species.WISHIWASHI, Species.MAREANIE, Species.TOXAPEX, + Species.DEWPIDER, Species.ARAQUANID, Species.BRUXISH, Species.DRAMPA, @@ -4328,7 +4354,10 @@ export const tmSpecies: TmSpecies = { Species.ROARING_MOON, Species.WALKING_WAKE, Species.HYDRAPPLE, - Species.ROTOM, + [ + Species.ROTOM, + "wash", + ], Species.GALAR_SLOWPOKE, Species.GALAR_SLOWBRO, Species.GALAR_SLOWKING, @@ -5148,7 +5177,10 @@ export const tmSpecies: TmSpecies = { Species.ARCTIBAX, Species.BAXCALIBUR, Species.CHIEN_PAO, - Species.ROTOM, + [ + Species.ROTOM, + "frost", + ], Species.ALOLA_RATTATA, Species.ALOLA_RATICATE, Species.ALOLA_SANDSHREW, @@ -5909,6 +5941,8 @@ export const tmSpecies: TmSpecies = { Species.MACHAMP, Species.PONYTA, Species.RAPIDASH, + Species.DODUO, + Species.DODRIO, Species.DROWZEE, Species.HYPNO, Species.EXEGGUTOR, @@ -7108,6 +7142,7 @@ export const tmSpecies: TmSpecies = { Species.HEATRAN, Species.VICTINI, Species.PANSEAR, + Species.SIMISEAR, Species.DARUMAKA, Species.DARMANITAN, Species.LITWICK, @@ -10173,6 +10208,8 @@ export const tmSpecies: TmSpecies = { Species.ZORUA, Species.ZOROARK, Species.SOLOSIS, + Species.DUOSION, + Species.REUNICLUS, Species.FRILLISH, Species.JELLICENT, Species.LITWICK, @@ -10184,6 +10221,7 @@ export const tmSpecies: TmSpecies = { Species.PHANTUMP, Species.TREVENANT, Species.ROWLET, + Species.DARTRIX, Species.DECIDUEYE, Species.SANDYGAST, Species.PALOSSAND, @@ -10226,6 +10264,7 @@ export const tmSpecies: TmSpecies = { Species.HISUI_ZORUA, Species.HISUI_ZOROARK, Species.HISUI_BRAVIARY, + Species.HISUI_DECIDUEYE, ], [Moves.SCREECH]: [ Species.RATTATA, @@ -11532,6 +11571,7 @@ export const tmSpecies: TmSpecies = { Species.PSYDUCK, Species.GOLDUCK, Species.TENTACOOL, + Species.TENTACRUEL, Species.MAGNEMITE, Species.MAGNETON, Species.GRIMER, @@ -11587,6 +11627,9 @@ export const tmSpecies: TmSpecies = { Species.DUSKULL, Species.DUSCLOPS, Species.CLAMPERL, + Species.HUNTAIL, + Species.GOREBYSS, + Species.JIRACHI, Species.SHINX, Species.LUXIO, Species.LUXRAY, @@ -11598,6 +11641,7 @@ export const tmSpecies: TmSpecies = { Species.MIME_JR, Species.SPIRITOMB, Species.SKORUPI, + Species.DRAPION, Species.FINNEON, Species.LUMINEON, Species.MANTYKE, @@ -11612,17 +11656,23 @@ export const tmSpecies: TmSpecies = { Species.REGIGIGAS, Species.GIRATINA, Species.CRESSELIA, + Species.DARKRAI, Species.ARCEUS, Species.WATCHOG, Species.ZORUA, Species.ZOROARK, Species.SOLOSIS, + Species.DUOSION, + Species.REUNICLUS, Species.FRILLISH, + Species.JELLICENT, Species.EELEKTROSS, Species.LITWICK, Species.LAMPENT, Species.CHANDELURE, Species.CRYOGONAL, + Species.GOLETT, + Species.GOLURK, Species.DELPHOX, Species.VIVILLON, Species.PHANTUMP, @@ -11630,6 +11680,7 @@ export const tmSpecies: TmSpecies = { Species.PUMPKABOO, Species.GOURGEIST, Species.ROWLET, + Species.DARTRIX, Species.DECIDUEYE, Species.MORELULL, Species.SHIINOTIC, @@ -11643,7 +11694,11 @@ export const tmSpecies: TmSpecies = { Species.ORBEETLE, Species.SINISTEA, Species.POLTEAGEIST, + Species.CURSOLA, + Species.MR_RIME, Species.DREEPY, + Species.DRAKLOAK, + Species.DRAGAPULT, Species.ETERNATUS, Species.SPECTRIER, Species.WYRDEER, @@ -11688,6 +11743,7 @@ export const tmSpecies: TmSpecies = { Species.HISUI_ZORUA, Species.HISUI_ZOROARK, Species.HISUI_BRAVIARY, + Species.HISUI_DECIDUEYE, ], [Moves.LIGHT_SCREEN]: [ Species.BULBASAUR, @@ -13875,6 +13931,7 @@ export const tmSpecies: TmSpecies = { Species.MAMOSWINE, Species.UXIE, Species.PANSEAR, + Species.SIMISEAR, Species.MUNNA, Species.MUSHARNA, Species.WOOBAT, @@ -19142,6 +19199,7 @@ export const tmSpecies: TmSpecies = { ], [Moves.REVERSAL]: [ Species.RATTATA, + Species.RATICATE, Species.PIKACHU, Species.RAICHU, Species.DIGLETT, @@ -19155,6 +19213,7 @@ export const tmSpecies: TmSpecies = { Species.MACHOKE, Species.MACHAMP, Species.HITMONLEE, + Species.HITMONCHAN, Species.RHYHORN, Species.RHYDON, Species.KANGASKHAN, @@ -19172,6 +19231,8 @@ export const tmSpecies: TmSpecies = { Species.YANMA, Species.PINECO, Species.FORRETRESS, + Species.SNUBBULL, + Species.GRANBULL, Species.QWILFISH, Species.SCIZOR, Species.SHUCKLE, @@ -19180,8 +19241,10 @@ export const tmSpecies: TmSpecies = { Species.SWINUB, Species.PILOSWINE, Species.DELIBIRD, + Species.SKARMORY, Species.HOUNDOUR, Species.HOUNDOOM, + Species.HITMONTOP, Species.MILTANK, Species.ENTEI, Species.TORCHIC, @@ -19210,11 +19273,14 @@ export const tmSpecies: TmSpecies = { Species.LUCARIO, Species.CROAGUNK, Species.TOXICROAK, + Species.WEAVILE, Species.RHYPERIOR, Species.YANMEGA, Species.MAMOSWINE, Species.GALLADE, Species.VICTINI, + Species.PIGNITE, + Species.EMBOAR, Species.LILLIPUP, Species.HERDIER, Species.STOUTLAND, @@ -19225,6 +19291,7 @@ export const tmSpecies: TmSpecies = { Species.SAWK, Species.BASCULIN, Species.DARMANITAN, + Species.SCRAFTY, Species.ESCAVALIER, Species.AXEW, Species.FRAXURE, @@ -19256,6 +19323,11 @@ export const tmSpecies: TmSpecies = { Species.CRABRAWLER, Species.CRABOMINABLE, Species.ORICORIO, + [ + Species.LYCANROC, + "midnight", + "dusk", + ], Species.BEWEAR, Species.PASSIMIAN, Species.SILVALLY, @@ -19312,6 +19384,7 @@ export const tmSpecies: TmSpecies = { Species.OGERPON, Species.GOUGING_FIRE, Species.ALOLA_RATTATA, + Species.ALOLA_RATICATE, Species.ALOLA_RAICHU, Species.ALOLA_DIGLETT, Species.ALOLA_DUGTRIO, @@ -25824,7 +25897,100 @@ export const tmSpecies: TmSpecies = { Species.DRAGAPULT, Species.KUBFU, Species.URSHIFU, + Species.WYRDEER, + Species.KLEAVOR, + Species.URSALUNA, + Species.BASCULEGION, + Species.SNEASLER, + Species.OVERQWIL, + Species.ENAMORUS, + Species.SPRIGATITO, + Species.FLORAGATO, + Species.MEOWSCARADA, + Species.FUECOCO, + Species.CROCALOR, + Species.SKELEDIRGE, + Species.QUAXLY, + Species.QUAXWELL, + Species.QUAQUAVAL, + Species.LECHONK, + Species.OINKOLOGNE, + Species.TAROUNTULA, + Species.SPIDOPS, + Species.NYMBLE, + Species.LOKIX, + Species.PAWMI, + Species.PAWMO, + Species.PAWMOT, + Species.FIDOUGH, + Species.DACHSBUN, + Species.SMOLIV, + Species.DOLLIV, + Species.ARBOLIVA, + Species.SQUAWKABILLY, + Species.NACLI, + Species.NACLSTACK, + Species.GARGANACL, + Species.CHARCADET, + Species.ARMAROUGE, + Species.CERULEDGE, + Species.TADBULB, + Species.BELLIBOLT, + Species.WATTREL, + Species.KILOWATTREL, + Species.MASCHIFF, + Species.MABOSSTIFF, + Species.SHROODLE, + Species.GRAFAIAI, + Species.BRAMBLIN, + Species.BRAMBLEGHAST, + Species.TOEDSCOOL, + Species.TOEDSCRUEL, + Species.KLAWF, + Species.CAPSAKID, + Species.SCOVILLAIN, + Species.RELLOR, + Species.RABSCA, + Species.FLITTLE, + Species.ESPATHRA, + Species.TINKATINK, + Species.TINKATUFF, + Species.TINKATON, + Species.WIGLETT, + Species.WUGTRIO, + Species.BOMBIRDIER, + Species.FINIZEN, + Species.PALAFIN, + Species.VAROOM, + Species.REVAVROOM, + Species.CYCLIZAR, + Species.ORTHWORM, + Species.GLIMMET, + Species.GLIMMORA, + Species.GREAVARD, + Species.HOUNDSTONE, + Species.FLAMIGO, + Species.CETODDLE, + Species.CETITAN, + Species.VELUZA, + Species.DONDOZO, + Species.TATSUGIRI, + Species.ANNIHILAPE, + Species.CLODSIRE, + Species.FARIGIRAF, + Species.DUDUNSPARCE, + Species.KINGAMBIT, + Species.FRIGIBAX, + Species.ARCTIBAX, + Species.BAXCALIBUR, + Species.DIPPLIN, + Species.OKIDOGI, + Species.MUNKIDORI, Species.FEZANDIPITI, + Species.OGERPON, + Species.ARCHALUDON, + Species.HYDRAPPLE, + Species.TERAPAGOS, Species.ALOLA_RATTATA, Species.ALOLA_RATICATE, Species.ALOLA_RAICHU, @@ -25860,6 +26026,23 @@ export const tmSpecies: TmSpecies = { Species.GALAR_DARMANITAN, Species.GALAR_YAMASK, Species.GALAR_STUNFISK, + Species.HISUI_GROWLITHE, + Species.HISUI_ARCANINE, + Species.HISUI_TYPHLOSION, + Species.HISUI_QWILFISH, + Species.HISUI_SNEASEL, + Species.HISUI_SAMUROTT, + Species.HISUI_LILLIGANT, + Species.HISUI_ZORUA, + Species.HISUI_ZOROARK, + Species.HISUI_BRAVIARY, + Species.HISUI_SLIGGOO, + Species.HISUI_GOODRA, + Species.HISUI_AVALUGG, + Species.HISUI_DECIDUEYE, + Species.PALDEA_TAUROS, + Species.PALDEA_WOOPER, + Species.BLOODMOON_URSALUNA, ], [Moves.SLEEP_TALK]: [ Species.BULBASAUR, @@ -26757,6 +26940,8 @@ export const tmSpecies: TmSpecies = { Species.FUECOCO, Species.CROCALOR, Species.SKELEDIRGE, + Species.QUAXLY, + Species.QUAXWELL, Species.QUAQUAVAL, Species.LECHONK, Species.OINKOLOGNE, @@ -26833,10 +27018,12 @@ export const tmSpecies: TmSpecies = { Species.FLUTTER_MANE, Species.SLITHER_WING, Species.SANDY_SHOCKS, + Species.IRON_TREADS, Species.IRON_BUNDLE, Species.IRON_HANDS, Species.IRON_JUGULIS, Species.IRON_MOTH, + Species.IRON_THORNS, Species.FRIGIBAX, Species.ARCTIBAX, Species.BAXCALIBUR, @@ -29618,6 +29805,7 @@ export const tmSpecies: TmSpecies = { Species.GREAT_TUSK, Species.IRON_TREADS, Species.IRON_LEAVES, + Species.IRON_BOULDER, Species.GALAR_RAPIDASH, [ Species.CALYREX, @@ -29840,17 +30028,20 @@ export const tmSpecies: TmSpecies = { Species.GENGAR, Species.DROWZEE, Species.HYPNO, + Species.HITMONCHAN, Species.MR_MIME, Species.JYNX, Species.SNORLAX, Species.DRAGONITE, Species.MEW, Species.LEDYBA, + Species.LEDIAN, Species.PICHU, Species.CLEFFA, Species.IGGLYBUFF, Species.TOGEPI, Species.TOGETIC, + Species.BELLOSSOM, Species.MARILL, Species.AZUMARILL, Species.POLITOED, @@ -29862,6 +30053,8 @@ export const tmSpecies: TmSpecies = { Species.WOOPER, Species.QUAGSIRE, Species.WOBBUFFET, + Species.SNUBBULL, + Species.GRANBULL, Species.SHUCKLE, Species.PHANPY, Species.DONPHAN, @@ -29925,6 +30118,8 @@ export const tmSpecies: TmSpecies = { Species.LILLIGANT, Species.DARUMAKA, Species.DARMANITAN, + Species.SCRAGGY, + Species.SCRAFTY, Species.ZORUA, Species.ZOROARK, Species.MINCCINO, @@ -29951,6 +30146,7 @@ export const tmSpecies: TmSpecies = { Species.POPPLIO, Species.BRIONNE, Species.PRIMARINA, + Species.TOUCANNON, Species.SALAZZLE, Species.COMFEY, Species.ORANGURU, @@ -29961,10 +30157,14 @@ export const tmSpecies: TmSpecies = { Species.TOXTRICITY, Species.MR_RIME, Species.ALCREMIE, - Species.INDEEDEE, + [ + Species.INDEEDEE, + "male", + ], Species.ZARUDE, Species.CALYREX, Species.FUECOCO, + Species.CROCALOR, Species.SKELEDIRGE, Species.QUAXLY, Species.QUAXWELL, @@ -30307,8 +30507,13 @@ export const tmSpecies: TmSpecies = { Species.ZACIAN, Species.ZAMAZENTA, Species.ZARUDE, + Species.WYRDEER, + Species.SNEASLER, Species.CYCLIZAR, Species.ORTHWORM, + Species.ANNIHILAPE, + Species.FARIGIRAF, + Species.DUDUNSPARCE, Species.ALOLA_RATTATA, Species.ALOLA_RATICATE, Species.ALOLA_RAICHU, @@ -30328,6 +30533,10 @@ export const tmSpecies: TmSpecies = { Species.GALAR_SLOWKING, Species.GALAR_ZIGZAGOON, Species.GALAR_LINOONE, + Species.HISUI_GROWLITHE, + Species.HISUI_ARCANINE, + Species.HISUI_TYPHLOSION, + Species.HISUI_SLIGGOO, Species.HISUI_GOODRA, ], [Moves.METAL_CLAW]: [ @@ -33185,8 +33394,11 @@ export const tmSpecies: TmSpecies = { Species.HERDIER, Species.STOUTLAND, Species.PANSAGE, + Species.SIMISAGE, Species.PANSEAR, + Species.SIMISAGE, Species.PANPOUR, + Species.SIMIPOUR, Species.BASCULIN, Species.SANDILE, Species.KROKOROK, @@ -34575,6 +34787,7 @@ export const tmSpecies: TmSpecies = { Species.LOTAD, Species.LOMBRE, Species.LUDICOLO, + Species.WINGULL, Species.PELIPPER, Species.EXPLOUD, Species.MAKUHITA, @@ -34624,17 +34837,25 @@ export const tmSpecies: TmSpecies = { Species.PHIONE, Species.MANAPHY, Species.ARCEUS, + Species.OSHAWOTT, + Species.DEWOTT, + Species.SAMUROTT, Species.BASCULIN, Species.TIRTOUGA, Species.CARRACOSTA, + Species.DUCKLETT, + Species.SWANNA, Species.FRILLISH, Species.JELLICENT, Species.ALOMOMOLA, Species.BARBARACLE, + Species.SKRELP, + Species.DRAGALGE, Species.POPPLIO, Species.BRIONNE, Species.PRIMARINA, Species.WISHIWASHI, + Species.BRUXISH, Species.DHELMISE, Species.TAPU_FINI, Species.SOBBLE, @@ -34651,7 +34872,16 @@ export const tmSpecies: TmSpecies = { Species.EISCUE, Species.DRACOVISH, Species.ARCTOVISH, + Species.BASCULEGION, + Species.QUAXLY, + Species.QUAXWELL, + Species.QUAQUAVAL, + Species.WIGLETT, + Species.WUGTRIO, + Species.PALAFIN, + Species.TATSUGIRI, Species.IRON_BUNDLE, + Species.WALKING_WAKE, Species.GALAR_SLOWPOKE, Species.GALAR_SLOWBRO, Species.GALAR_SLOWKING, @@ -34662,12 +34892,18 @@ export const tmSpecies: TmSpecies = { Species.URSHIFU, "rapid-strike", ], + Species.HISUI_SAMUROTT, + [ + Species.PALDEA_TAUROS, + "aqua", + ], ], [Moves.BEAT_UP]: [ Species.CHARMANDER, Species.CHARMELEON, Species.CHARIZARD, Species.EKANS, + Species.ARBOK, Species.NIDORAN_F, Species.NIDORINA, Species.NIDOQUEEN, @@ -34677,6 +34913,7 @@ export const tmSpecies: TmSpecies = { Species.DIGLETT, Species.DUGTRIO, Species.MANKEY, + Species.PRIMEAPE, Species.KANGASKHAN, Species.MEW, Species.AIPOM, @@ -34720,6 +34957,10 @@ export const tmSpecies: TmSpecies = { Species.TANDEMAUS, Species.MAUSHOLD, Species.BRAMBLIN, + Species.BRAMBLEGHAST, + Species.ANNIHILAPE, + Species.FARIGIRAF, + Species.KINGAMBIT, Species.FEZANDIPITI, Species.PIKACHU, Species.ALOLA_DIGLETT, @@ -36894,6 +37135,7 @@ export const tmSpecies: TmSpecies = { Species.SCEPTILE, Species.COMBUSKEN, Species.BLAZIKEN, + Species.MARSHTOMP, Species.SWAMPERT, Species.LUDICOLO, Species.SHROOMISH, @@ -36984,6 +37226,7 @@ export const tmSpecies: TmSpecies = { Species.GOLETT, Species.GOLURK, Species.HEATMOR, + Species.ZEKROM, Species.MELOETTA, Species.CHESPIN, Species.QUILLADIN, @@ -37010,9 +37253,11 @@ export const tmSpecies: TmSpecies = { Species.ZERAORA, Species.RILLABOOM, Species.GRIMMSNARL, + Species.MR_RIME, Species.KUBFU, Species.URSHIFU, Species.ZARUDE, + Species.URSALUNA, Species.SNEASLER, Species.PAWMO, Species.PAWMOT, @@ -37035,7 +37280,9 @@ export const tmSpecies: TmSpecies = { Species.LYCANROC, "midnight", ], + Species.GALAR_MR_MIME, Species.GALAR_DARUMAKA, + Species.GALAR_DARMANITAN, Species.HISUI_TYPHLOSION, Species.HISUI_SNEASEL, Species.HISUI_ZORUA, @@ -37184,12 +37431,18 @@ export const tmSpecies: TmSpecies = { Species.TAPU_FINI, Species.XURKITREE, Species.GROOKEY, + Species.THWACKEY, + Species.RILLABOOM, + Species.CURSOLA, Species.ALOLA_GEODUDE, Species.ALOLA_GRAVELER, Species.ALOLA_GOLEM, Species.ALOLA_EXEGGUTOR, Species.ETERNAL_FLOETTE, Species.GALAR_CORSOLA, + Species.HISUI_TYPHLOSION, + Species.HISUI_LILLIGANT, + Species.HISUI_DECIDUEYE, ], [Moves.CHARGE]: [ Species.PIKACHU, @@ -38709,7 +38962,9 @@ export const tmSpecies: TmSpecies = { ], [Moves.REVENGE]: [ Species.RATTATA, + Species.RATICATE, Species.MANKEY, + Species.PRIMEAPE, Species.MACHOP, Species.MACHOKE, Species.MACHAMP, @@ -38721,6 +38976,7 @@ export const tmSpecies: TmSpecies = { Species.MEW, Species.AIPOM, Species.PINECO, + Species.FORRETRESS, Species.QWILFISH, Species.HERACROSS, Species.HITMONTOP, @@ -38729,12 +38985,16 @@ export const tmSpecies: TmSpecies = { Species.BLAZIKEN, Species.SHIFTRY, Species.MAKUHITA, + Species.HARIYAMA, Species.CACTURNE, Species.ZANGOOSE, Species.CRAWDAUNT, Species.DUSKULL, Species.DUSCLOPS, Species.STARLY, + Species.STARAVIA, + Species.STARAPTOR, + Species.AMBIPOM, Species.VESPIQUEN, Species.RIOLU, Species.LUCARIO, @@ -38750,6 +39010,7 @@ export const tmSpecies: TmSpecies = { Species.DEWOTT, Species.SAMUROTT, Species.PATRAT, + Species.WATCHOG, Species.TIMBURR, Species.GURDURR, Species.CONKELDURR, @@ -38785,6 +39046,7 @@ export const tmSpecies: TmSpecies = { Species.TORRACAT, Species.INCINEROAR, Species.YUNGOOS, + Species.GUMSHOOS, Species.MUDSDALE, Species.BEWEAR, Species.PASSIMIAN, @@ -38817,13 +39079,18 @@ export const tmSpecies: TmSpecies = { Species.KUBFU, Species.URSHIFU, Species.ZARUDE, + Species.BASCULEGION, + Species.ANNIHILAPE, + Species.KINGAMBIT, Species.ALOLA_RATTATA, + Species.ALOLA_RATICATE, [ Species.LYCANROC, "midnight", ], Species.GALAR_FARFETCHD, Species.GALAR_ZAPDOS, + Species.HISUI_SAMUROTT, Species.GALAR_STUNFISK, ], [Moves.BRICK_BREAK]: [ @@ -40317,6 +40584,7 @@ export const tmSpecies: TmSpecies = { Species.XATU, Species.MURKROW, Species.DELIBIRD, + Species.LUGIA, Species.TORCHIC, Species.COMBUSKEN, Species.BLAZIKEN, @@ -40373,6 +40641,8 @@ export const tmSpecies: TmSpecies = { Species.COMBUSKEN, Species.BLAZIKEN, Species.CHIMCHAR, + Species.MONFERNO, + Species.INFERNAPE, Species.RIOLU, Species.LUCARIO, Species.VICTINI, @@ -40913,6 +41183,7 @@ export const tmSpecies: TmSpecies = { ], [Moves.AIR_CUTTER]: [ Species.CHARMANDER, + Species.CHARMELEON, Species.CHARIZARD, Species.BUTTERFREE, Species.BEEDRILL, @@ -40968,6 +41239,8 @@ export const tmSpecies: TmSpecies = { Species.ALTARIA, Species.TROPIUS, Species.SALAMENCE, + Species.LATIAS, + Species.LATIOS, Species.EMPOLEON, Species.STARLY, Species.STARAVIA, @@ -41008,6 +41281,9 @@ export const tmSpecies: TmSpecies = { Species.ROWLET, Species.DARTRIX, Species.DECIDUEYE, + Species.PIKIPEK, + Species.TRUMBEAK, + Species.TOUCANNON, Species.ORICORIO, Species.KARTANA, Species.NAGANADEL, @@ -41134,7 +41410,10 @@ export const tmSpecies: TmSpecies = { Species.KORAIDON, Species.MIRAIDON, Species.GOUGING_FIRE, - Species.ROTOM, + [ + Species.ROTOM, + "heat", + ], Species.GALAR_WEEZING, Species.GALAR_DARUMAKA, Species.GALAR_DARMANITAN, @@ -41644,6 +41923,7 @@ export const tmSpecies: TmSpecies = { Species.NATU, Species.XATU, Species.SKITTY, + Species.DELCATTY, Species.LUNATONE, Species.SOLROCK, Species.BALTOY, @@ -41674,6 +41954,7 @@ export const tmSpecies: TmSpecies = { Species.NECROZMA, Species.ETERNATUS, Species.RELLOR, + Species.RABSCA, ], [Moves.SIGNAL_BEAM]: [ Species.BLASTOISE, @@ -42161,7 +42442,9 @@ export const tmSpecies: TmSpecies = { Species.SHAYMIN, Species.ARCEUS, Species.PATRAT, + Species.WATCHOG, Species.PANSAGE, + Species.SIMISAGE, Species.LEAVANNY, Species.PETILIL, Species.LILLIGANT, @@ -42591,6 +42874,7 @@ export const tmSpecies: TmSpecies = { ], [Moves.ICICLE_SPEAR]: [ Species.SEEL, + Species.DEWGONG, Species.SHELLDER, Species.CLOYSTER, Species.JYNX, @@ -43018,6 +43302,7 @@ export const tmSpecies: TmSpecies = { Species.MACHAMP, Species.HITMONLEE, Species.HITMONCHAN, + Species.ELECTABUZZ, Species.PINSIR, Species.MEWTWO, Species.MEW, @@ -43051,10 +43336,12 @@ export const tmSpecies: TmSpecies = { Species.LUCARIO, Species.CROAGUNK, Species.TOXICROAK, + Species.ELECTIVIRE, Species.GALLADE, Species.DIALGA, Species.PALKIA, Species.ARCEUS, + Species.PIGNITE, Species.EMBOAR, Species.TIMBURR, Species.GURDURR, @@ -44239,6 +44526,8 @@ export const tmSpecies: TmSpecies = { Species.DRAGONITE, Species.MEW, Species.TOTODILE, + Species.CROCONAW, + Species.FERALIGATR, Species.STEELIX, Species.KINGDRA, Species.LARVITAR, @@ -44341,6 +44630,7 @@ export const tmSpecies: TmSpecies = { Species.GROUDON, Species.TORTERRA, Species.SHIELDON, + Species.BASTIODON, Species.GASTRODON, Species.BRONZOR, Species.BRONZONG, @@ -44374,6 +44664,7 @@ export const tmSpecies: TmSpecies = { Species.TRUMBEAK, Species.TOUCANNON, Species.LYCANROC, + Species.MINIOR, Species.NECROZMA, Species.STAKATAKA, Species.BLACEPHALON, @@ -44400,6 +44691,7 @@ export const tmSpecies: TmSpecies = { Species.GLIMMET, Species.GLIMMORA, Species.IRON_THORNS, + Species.IRON_BOULDER, [ Species.WORMADAM, "sandy", @@ -48382,7 +48674,10 @@ export const tmSpecies: TmSpecies = { Species.IRON_BOULDER, Species.IRON_CROWN, Species.SHAYMIN, - Species.ROTOM, + [ + Species.ROTOM, + "fan", + ], Species.GALAR_ARTICUNO, Species.GALAR_MOLTRES, Species.HISUI_SAMUROTT, @@ -52277,6 +52572,9 @@ export const tmSpecies: TmSpecies = { Species.BULBASAUR, Species.IVYSAUR, Species.VENUSAUR, + Species.ODDISH, + Species.GLOOM, + Species.VILEPLUME, Species.BELLSPROUT, Species.WEEPINBELL, Species.VICTREEBEL, @@ -52285,6 +52583,8 @@ export const tmSpecies: TmSpecies = { Species.TANGELA, Species.MEW, Species.CHIKORITA, + Species.BAYLEEF, + Species.MEGANIUM, Species.BELLOSSOM, Species.HOPPIP, Species.SKIPLOOM, @@ -52318,6 +52618,7 @@ export const tmSpecies: TmSpecies = { Species.SERVINE, Species.SERPERIOR, Species.PANSAGE, + Species.SIMISAGE, Species.LEAVANNY, Species.PETILIL, Species.LILLIGANT, @@ -52371,7 +52672,10 @@ export const tmSpecies: TmSpecies = { Species.OGERPON, Species.HYDRAPPLE, Species.SHAYMIN, - Species.ROTOM, + [ + Species.ROTOM, + "mow", + ], Species.ALOLA_EXEGGUTOR, Species.HISUI_VOLTORB, Species.HISUI_ELECTRODE, diff --git a/src/egg-hatch-phase.ts b/src/egg-hatch-phase.ts index 44b72fb3d05a..3965eae74f61 100644 --- a/src/egg-hatch-phase.ts +++ b/src/egg-hatch-phase.ts @@ -11,6 +11,7 @@ import { achvs } from "./system/achv"; import PokemonInfoContainer from "./ui/pokemon-info-container"; import EggCounterContainer from "./ui/egg-counter-container"; import { EggCountChangedEvent } from "./events/egg"; +import { getPokemonNameWithAffix } from "./messages"; /** * Class that represents egg hatching @@ -342,7 +343,7 @@ export class EggHatchPhase extends Phase { this.scene.playSoundWithoutBgm("evolution_fanfare"); - this.scene.ui.showText(i18next.t("egg:hatchFromTheEgg", { pokemonName: this.pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t("egg:hatchFromTheEgg", { pokemonName: getPokemonNameWithAffix(this.pokemon) }), null, () => { this.scene.gameData.updateSpeciesDexIvs(this.pokemon.species.speciesId, this.pokemon.ivs); this.scene.gameData.setPokemonCaught(this.pokemon, true, true).then(() => { this.scene.gameData.setEggMoveUnlocked(this.pokemon.species, this.eggMoveIndex).then(() => { diff --git a/src/enums/battler-tag-type.ts b/src/enums/battler-tag-type.ts index bb7f7c05b003..52f6402861ef 100644 --- a/src/enums/battler-tag-type.ts +++ b/src/enums/battler-tag-type.ts @@ -60,5 +60,8 @@ export enum BattlerTagType { MINIMIZED = "MINIMIZED", DESTINY_BOND = "DESTINY_BOND", CENTER_OF_ATTENTION = "CENTER_OF_ATTENTION", - ICE_FACE = "ICE_FACE" + ICE_FACE = "ICE_FACE", + STOCKPILING = "STOCKPILING", + RECEIVE_DOUBLE_DAMAGE = "RECEIVE_DOUBLE_DAMAGE", + ALWAYS_GET_HIT = "ALWAYS_GET_HIT" } diff --git a/src/evolution-phase.ts b/src/evolution-phase.ts index c7986f6664fc..28edeee1a776 100644 --- a/src/evolution-phase.ts +++ b/src/evolution-phase.ts @@ -10,6 +10,7 @@ import { cos, sin } from "./field/anims"; import { PlayerPokemon } from "./field/pokemon"; import { getTypeRgb } from "./data/type"; import i18next from "i18next"; +import { getPokemonNameWithAffix } from "./messages"; export class EvolutionPhase extends Phase { protected pokemon: PlayerPokemon; @@ -116,7 +117,7 @@ export class EvolutionPhase extends Phase { doEvolution(): void { const evolutionHandler = this.scene.ui.getHandler() as EvolutionSceneHandler; - const preName = this.pokemon.name; + const preName = getPokemonNameWithAffix(this.pokemon); this.scene.ui.showText(i18next.t("menu:evolving", { pokemonName: preName }), null, () => { this.pokemon.cry(); diff --git a/src/field/arena.ts b/src/field/arena.ts index 8b1996c27da4..7d1046986a57 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -13,7 +13,7 @@ import { BattlerIndex } from "../battle"; import { Terrain, TerrainType } from "../data/terrain"; import { PostTerrainChangeAbAttr, PostWeatherChangeAbAttr, applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs } from "../data/ability"; import Pokemon from "./pokemon"; -import Overrides from "../overrides"; +import Overrides from "#app/overrides"; import { WeatherChangedEvent, TerrainChangedEvent, TagAddedEvent, TagRemovedEvent } from "../events/arena"; import { ArenaTagType } from "#enums/arena-tag-type"; import { Biome } from "#enums/biome"; diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index ecda76025693..2ae7d6d97ff8 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -23,7 +23,7 @@ import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoo import { WeatherType } from "../data/weather"; import { TempBattleStat } from "../data/temp-battle-stat"; import { ArenaTagSide, WeakenMoveScreenTag } from "../data/arena-tag"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldBattleStatMultiplierAbAttrs, FieldMultiplyBattleStatAbAttr, AddSecondStrikeAbAttr } from "../data/ability"; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldBattleStatMultiplierAbAttrs, FieldMultiplyBattleStatAbAttr, AddSecondStrikeAbAttr, IgnoreOpponentEvasionAbAttr } from "../data/ability"; import PokemonData from "../system/pokemon-data"; import { BattlerIndex } from "../battle"; import { Mode } from "../ui/ui"; @@ -37,7 +37,7 @@ import { Nature, getNatureStatMultiplier } from "../data/nature"; import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from "../data/pokemon-forms"; import { TerrainType } from "../data/terrain"; import { TrainerSlot } from "../data/trainer-config"; -import Overrides from "../overrides"; +import Overrides from "#app/overrides"; import i18next from "i18next"; import { speciesEggMoves } from "../data/egg-moves"; import { ModifierTier } from "../modifier/modifier-tier"; @@ -50,6 +50,7 @@ import { BerryType } from "#enums/berry-type"; import { Biome } from "#enums/biome"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; +import { getPokemonNameWithAffix } from "#app/messages.js"; export enum FieldPosition { CENTER, @@ -60,6 +61,7 @@ export enum FieldPosition { export default abstract class Pokemon extends Phaser.GameObjects.Container { public id: integer; public name: string; + public nickname: string; public species: PokemonSpecies; public formIndex: integer; public abilityIndex: integer; @@ -126,9 +128,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.species = species; this.pokeball = dataSource?.pokeball || PokeballType.POKEBALL; this.level = level; - this.abilityIndex = abilityIndex !== undefined - ? abilityIndex - : (species.abilityHidden && hasHiddenAbility ? species.ability2 ? 2 : 1 : species.ability2 ? randAbilityIndex : 0); + // Determine the ability index + if (abilityIndex !== undefined) { + this.abilityIndex = abilityIndex; // Use the provided ability index if it is defined + } else { + // If abilityIndex is not provided, determine it based on species and hidden ability + if (species.abilityHidden && hasHiddenAbility) { + // If the species has a hidden ability and the hidden ability is present + this.abilityIndex = species.ability2 ? 2 : 1; // Use ability index 2 if species has a second ability, otherwise use 1 + } else { + // If there is no hidden ability or species does not have a hidden ability + this.abilityIndex = species.ability2 ? randAbilityIndex : 0; // Use random ability index if species has a second ability, otherwise use 0 + } + } if (formIndex !== undefined) { this.formIndex = formIndex; } @@ -153,6 +165,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.variant = 0; } this.nature = dataSource.nature || 0 as Nature; + this.nickname = dataSource.nickname; this.natureOverride = dataSource.natureOverride !== undefined ? dataSource.natureOverride : -1; this.moveset = dataSource.moveset; this.status = dataSource.status; @@ -226,6 +239,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.calculateStats(); } + + getNameToRender() { + try { + if (this.nickname) { + return decodeURIComponent(escape(atob(this.nickname))); + } + return this.name; + } catch (err) { + console.error(`Failed to decode nickname for ${this.name}`, err); + return this.name; + } + } + init(): void { this.fieldPosition = FieldPosition.CENTER; @@ -778,6 +804,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.setNature(nature); } + isFullHp(): boolean { + return this.hp >= this.getMaxHp(); + } + getMaxHp(): integer { return this.getStat(Stat.HP); } @@ -1154,7 +1184,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { getAttackMoveEffectiveness(source: Pokemon, pokemonMove: PokemonMove, ignoreAbility: boolean = false): TypeDamageMultiplier { const move = pokemonMove.getMove(); const typeless = move.hasAttr(TypelessAttr); - const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move.type, source)); + const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move, source)); const cancelled = new Utils.BooleanHolder(false); applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier); if (!typeless && !ignoreAbility) { @@ -1169,13 +1199,20 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { /** * Calculates the type effectiveness multiplier for an attack type - * @param moveType Type of the move + * @param moveOrType The move being used, or a type if the move is unknown * @param source the Pokemon using the move * @param ignoreStrongWinds whether or not this ignores strong winds (anticipation, forewarn, stealth rocks) * @param simulated tag to only apply the strong winds effect message when the move is used * @returns a multiplier for the type effectiveness */ - getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true): TypeDamageMultiplier { + getAttackTypeEffectiveness(moveOrType: Move | Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true): TypeDamageMultiplier { + const move = (moveOrType instanceof Move) + ? moveOrType + : undefined; + const moveType = (moveOrType instanceof Move) + ? move.type + : moveOrType; + if (moveType === Type.STELLAR) { return this.isTerastallized() ? 2 : 1; } @@ -1203,9 +1240,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - if (!!this.summonData?.tags.find((tag) => tag instanceof TypeImmuneTag && tag.immuneType === moveType)) { - multiplier = 0; - } + const immuneTags = this.findTags(tag => tag instanceof TypeImmuneTag && tag.immuneType === moveType); + immuneTags.forEach(tag => { + if (move !== undefined) { + const hitsTagAttrs = move.getAttrs(HitsTagAttr).filter(attr => attr.tagType === tag.tagType); + if (hitsTagAttrs.length === 0) { + multiplier = 0; + } + } + }); return multiplier; } @@ -1738,6 +1781,43 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return (this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField())[this.getFieldIndex() ? 0 : 1]; } + /** + * Calculates the accuracy multiplier of the user against a target. + * + * This method considers various factors such as the user's accuracy level, the target's evasion level, + * abilities, and modifiers to compute the final accuracy multiplier. + * + * @param target {@linkcode Pokemon} - The target Pokémon against which the move is used. + * @param sourceMove {@linkcode Move} - The move being used by the user. + * @returns The calculated accuracy multiplier. + */ + getAccuracyMultiplier(target: Pokemon, sourceMove: Move): number { + const userAccuracyLevel = new Utils.IntegerHolder(this.summonData.battleStats[BattleStat.ACC]); + const targetEvasionLevel = new Utils.IntegerHolder(target.summonData.battleStats[BattleStat.EVA]); + + applyAbAttrs(IgnoreOpponentStatChangesAbAttr, target, null, userAccuracyLevel); + applyAbAttrs(IgnoreOpponentStatChangesAbAttr, this, null, targetEvasionLevel); + applyAbAttrs(IgnoreOpponentEvasionAbAttr, this, null, targetEvasionLevel); + applyMoveAttrs(IgnoreOpponentStatChangesAttr, this, target, sourceMove, targetEvasionLevel); + this.scene.applyModifiers(TempBattleStatBoosterModifier, this.isPlayer(), TempBattleStat.ACC, userAccuracyLevel); + + const accuracyMultiplier = new Utils.NumberHolder(1); + if (userAccuracyLevel.value !== targetEvasionLevel.value) { + accuracyMultiplier.value = userAccuracyLevel.value > targetEvasionLevel.value + ? (3 + Math.min(userAccuracyLevel.value - targetEvasionLevel.value, 6)) / 3 + : 3 / (3 + Math.min(targetEvasionLevel.value - userAccuracyLevel.value, 6)); + } + + applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, this, BattleStat.ACC, accuracyMultiplier, sourceMove); + + const evasionMultiplier = new Utils.NumberHolder(1); + applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, target, BattleStat.EVA, evasionMultiplier); + + accuracyMultiplier.value /= evasionMultiplier.value; + + return accuracyMultiplier.value; + } + apply(source: Pokemon, move: Move): HitResult { let result: HitResult; const damage = new Utils.NumberHolder(0); @@ -1753,7 +1833,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const cancelled = new Utils.BooleanHolder(false); const typeless = move.hasAttr(TypelessAttr); const typeMultiplier = new Utils.NumberHolder(!typeless && (moveCategory !== MoveCategory.STATUS || move.getAttrs(StatusMoveTypeImmunityAttr).find(attr => types.includes(attr.immuneType))) - ? this.getAttackTypeEffectiveness(move.type, source, false, false) + ? this.getAttackTypeEffectiveness(move, source, false, false) : 1); applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier); if (typeless) { @@ -1800,6 +1880,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const arenaAttackTypeMultiplier = new Utils.NumberHolder(this.scene.arena.getAttackTypeMultiplier(move.type, source.isGrounded())); applyMoveAttrs(IgnoreWeatherTypeDebuffAttr, source, this, move, arenaAttackTypeMultiplier); + const glaiveRushModifier = new Utils.IntegerHolder(1); + if (this.getTag(BattlerTagType.RECEIVE_DOUBLE_DAMAGE)) { + glaiveRushModifier.value = 2; + } let isCritical: boolean; const critOnly = new Utils.BooleanHolder(false); const critAlways = source.getTag(BattlerTagType.ALWAYS_CRIT); @@ -1884,6 +1968,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * twoStrikeMultiplier.value * targetMultiplier * criticalMultiplier.value + * glaiveRushModifier.value * randomMultiplier); if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) { @@ -1965,7 +2050,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const destinyTag = this.getTag(BattlerTagType.DESTINY_BOND); if (damage.value) { - if (this.getHpRatio() === 1) { + if (this.isFullHp()) { applyPreDefendAbAttrs(PreDefendFullHpEndureAbAttr, this, source, move, cancelled, damage); } else if (!this.isPlayer() && damage.value >= this.hp) { this.scene.applyModifiers(EnemyEndureChanceModifier, false, this); @@ -1977,6 +2062,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { */ damage.value = this.damageAndUpdate(damage.value, result as DamageResult, isCritical, isOneHitKo, isOneHitKo, true); this.turnData.damageTaken += damage.value; + if (isCritical) { this.scene.queueMessage(i18next.t("battle:hitResultCriticalHit")); } @@ -1996,7 +2082,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - if (source.turnData.hitsLeft === 1) { + // want to include is.Fainted() in case multi hit move ends early, still want to render message + if (source.turnData.hitsLeft === 1 || this.isFainted()) { switch (result) { case HitResult.SUPER_EFFECTIVE: this.scene.queueMessage(i18next.t("battle:hitResultSuperEffective")); @@ -2005,7 +2092,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.scene.queueMessage(i18next.t("battle:hitResultNotVeryEffective")); break; case HitResult.NO_EFFECT: - this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: this.name })); + this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: getPokemonNameWithAffix(this) })); break; case HitResult.IMMUNE: this.scene.queueMessage(`${this.name} is unaffected!`); @@ -2017,13 +2104,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } if (this.isFainted()) { + // set splice index here, so future scene queues happen before FaintedPhase + this.scene.setPhaseQueueSplice(); this.scene.unshiftPhase(new FaintPhase(this.scene, this.getBattlerIndex(), isOneHitKo)); this.resetSummonData(); } if (damage) { - this.scene.clearPhaseQueueSplice(); - const attacker = this.scene.getPokemonById(source.id); destinyTag?.lapse(attacker, BattlerTagLapseType.CUSTOM); } @@ -2038,7 +2125,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, move, cancelled, typeMultiplier)); } if (!typeMultiplier.value) { - this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: this.name })); + this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: getPokemonNameWithAffix(this) })); } result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS; break; @@ -2047,6 +2134,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return result; } + /** + * Called by damageAndUpdate() + * @param damage integer + * @param ignoreSegments boolean, not currently used + * @param preventEndure used to update damage if endure or sturdy + * @param ignoreFaintPhase flag on wheter to add FaintPhase if pokemon after applying damage faints + * @returns integer representing damage + */ damage(damage: integer, ignoreSegments: boolean = false, preventEndure: boolean = false, ignoreFaintPhase: boolean = false): integer { if (this.isFainted()) { return 0; @@ -2068,9 +2163,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } damage = Math.min(damage, this.hp); - this.hp = this.hp - damage; if (this.isFainted() && !ignoreFaintPhase) { + /** + * When adding the FaintPhase, want to toggle future unshiftPhase() and queueMessage() calls + * to appear before the FaintPhase (as FaintPhase will potentially end the encounter and add Phases such as + * GameOverPhase, VictoryPhase, etc.. that will interfere with anything else that happens during this MoveEffectPhase) + * + * Once the MoveEffectPhase is over (and calls it's .end() function, shiftPhase() will reset the PhaseQueueSplice via clearPhaseQueueSplice() ) + */ + this.scene.setPhaseQueueSplice(); this.scene.unshiftPhase(new FaintPhase(this.scene, this.getBattlerIndex(), preventEndure)); this.resetSummonData(); } @@ -2078,6 +2180,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return damage; } + /** + * Called by apply(), given the damage, adds a new DamagePhase and actually updates HP values, etc. + * @param damage integer - passed to damage() + * @param result an enum if it's super effective, not very, etc. + * @param critical boolean if move is a critical hit + * @param ignoreSegments boolean, passed to damage() and not used currently + * @param preventEndure boolean, ignore endure properties of pokemon, passed to damage() + * @param ignoreFaintPhase boolean to ignore adding a FaintPhase, passsed to damage() + * @returns integer of damage done + */ damageAndUpdate(damage: integer, result?: DamageResult, critical: boolean = false, ignoreSegments: boolean = false, preventEndure: boolean = false, ignoreFaintPhase: boolean = false): integer { const damagePhase = new DamagePhase(this.scene, this.getBattlerIndex(), damage, result as DamageResult, critical); this.scene.unshiftPhase(damagePhase); @@ -2124,13 +2236,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return false; } + /** @overload */ + getTag(tagType: BattlerTagType): BattlerTag; + + /** @overload */ + getTag(tagType: Constructor): T; + getTag(tagType: BattlerTagType | Constructor): BattlerTag { if (!this.summonData) { return null; } - return typeof(tagType) === "string" - ? this.summonData.tags.find(t => t.tagType === tagType) - : this.summonData.tags.find(t => t instanceof tagType); + return tagType instanceof Function + ? this.summonData.tags.find(t => t instanceof tagType) + : this.summonData.tags.find(t => t.tagType === tagType); } findTag(tagFilter: ((tag: BattlerTag) => boolean)) { @@ -2140,15 +2258,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.summonData.tags.find(t => tagFilter(t)); } - getTags(tagType: BattlerTagType | Constructor): BattlerTag[] { - if (!this.summonData) { - return []; - } - return typeof(tagType) === "string" - ? this.summonData.tags.filter(t => t.tagType === tagType) - : this.summonData.tags.filter(t => t instanceof tagType); - } - findTags(tagFilter: ((tag: BattlerTag) => boolean)): BattlerTag[] { if (!this.summonData) { return []; @@ -2178,7 +2287,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const tags = this.summonData.tags; const tag = tags.find(t => t.tagType === tagType); if (tag) { - tag.turnCount = 0; tag.onRemove(this); tags.splice(tags.indexOf(tag), 1); } @@ -3210,14 +3318,19 @@ export class PlayerPokemon extends Pokemon { } this.generateName(); if (!isFusion) { + // Prevent pokemon with an illegal ability value from breaking things too badly const abilityCount = this.getSpeciesForm().getAbilityCount(); - if (this.abilityIndex >= abilityCount) { // Shouldn't happen - this.abilityIndex = abilityCount - 1; + if (this.abilityIndex >= abilityCount) { + console.warn("this.abilityIndex is somehow an illegal value, please report this"); + console.warn(this.abilityIndex); + this.abilityIndex = 0; } - } else { + } else { // Do the same as above, but for fusions const abilityCount = this.getFusionSpeciesForm().getAbilityCount(); - if (this.fusionAbilityIndex >= abilityCount) {// Shouldn't happen - this.fusionAbilityIndex = abilityCount - 1; + if (this.fusionAbilityIndex >= abilityCount) { + console.warn("this.fusionAbilityIndex is somehow an illegal value, please report this"); + console.warn(this.fusionAbilityIndex); + this.fusionAbilityIndex = 0; } } this.compatibleTms.splice(0, this.compatibleTms.length); diff --git a/src/form-change-phase.ts b/src/form-change-phase.ts index ebf91c635fd7..55bf655081b7 100644 --- a/src/form-change-phase.ts +++ b/src/form-change-phase.ts @@ -10,6 +10,7 @@ import PartyUiHandler from "./ui/party-ui-handler"; import { BattleSpec } from "#enums/battle-spec"; import { BattlePhase, MovePhase, PokemonHealPhase } from "./phases"; import { getTypeRgb } from "./data/type"; +import { getPokemonNameWithAffix } from "./messages"; export class FormChangePhase extends EvolutionPhase { private formChange: SpeciesFormChange; @@ -34,7 +35,7 @@ export class FormChangePhase extends EvolutionPhase { } doEvolution(): void { - const preName = this.pokemon.name; + const preName = getPokemonNameWithAffix(this.pokemon); this.pokemon.getPossibleForm(this.formChange).then(transformedPokemon => { @@ -191,7 +192,7 @@ export class QuietFormChangePhase extends BattlePhase { return this.end(); } - const preName = this.pokemon.name; + const preName = getPokemonNameWithAffix(this.pokemon); if (!this.pokemon.isOnField()) { this.pokemon.changeForm(this.formChange).then(() => { diff --git a/src/game-mode.ts b/src/game-mode.ts index 34e09fb762c9..010cae03e5e2 100644 --- a/src/game-mode.ts +++ b/src/game-mode.ts @@ -4,7 +4,7 @@ import BattleScene from "./battle-scene"; import { allChallenges, applyChallenges, Challenge, ChallengeType, copyChallenge } from "./data/challenge"; import PokemonSpecies, { allSpecies } from "./data/pokemon-species"; import { Arena } from "./field/arena"; -import Overrides from "./overrides"; +import Overrides from "#app/overrides"; import * as Utils from "./utils"; import { Biome } from "#enums/biome"; import { Species } from "#enums/species"; diff --git a/src/loading-scene.ts b/src/loading-scene.ts index a422adda61dc..61178144dede 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -146,6 +146,9 @@ export class LoadingScene extends SceneBase { this.loadImage(`summary_tabs_${t}`, "ui"); } + this.loadImage("scroll_bar", "ui"); + this.loadImage("scroll_bar_handle", "ui"); + this.loadImage("starter_container_bg", "ui"); this.loadImage("starter_select_bg", "ui"); this.loadImage("select_cursor", "ui"); this.loadImage("select_cursor_highlight", "ui"); diff --git a/src/locales/de/battle.ts b/src/locales/de/battle.ts index 74ddede5c896..a9686da7524c 100644 --- a/src/locales/de/battle.ts +++ b/src/locales/de/battle.ts @@ -154,5 +154,6 @@ export const battle: SimpleTranslationEntries = { "battlerTagsSaltCuredOnAdd": "{{pokemonNameWithAffix}} wurde eingepökelt!", "battlerTagsSaltCuredLapse": "{{pokemonNameWithAffix}} wurde durch {{moveName}} verletzt!", "battlerTagsCursedOnAdd": "{{pokemonNameWithAffix}} nimmt einen Teil seiner KP und legt einen Fluch auf {{pokemonName}}!", - "battlerTagsCursedLapse": "{{pokemonNameWithAffix}} wurde durch den Fluch verletzt!" + "battlerTagsCursedLapse": "{{pokemonNameWithAffix}} wurde durch den Fluch verletzt!", + "battlerTagsStockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!" } as const; diff --git a/src/locales/de/bgm-name.ts b/src/locales/de/bgm-name.ts index f3248172dccd..b43096f6a039 100644 --- a/src/locales/de/bgm-name.ts +++ b/src/locales/de/bgm-name.ts @@ -74,15 +74,15 @@ export const bgmName: SimpleTranslationEntries = { "battle_wild": "SW Vs. Wilde Pokémon", "battle_wild_strong": "SW Vs. Starke Wilde Pokémon", "end_summit": "PMDDX Gipfel des Himmelturms", - "battle_rocket_grunt": "HGSS Team Rocket Battle", - "battle_aqua_magma_grunt": "ORAS Team Aqua & Magma Battle", - "battle_galactic_grunt": "BDSP Team Galactic Battle", + "battle_rocket_grunt": "HGSS Vs. Team Rocket Rüpel", + "battle_aqua_magma_grunt": "ORAS Vs. Team Aqua & Magma", + "battle_galactic_grunt": "BDSP Vs. Team Galaktik Rüpel", "battle_plasma_grunt": "SW Vs. Team Plasma Rüpel", - "battle_flare_grunt": "XY Team Flare Battle", + "battle_flare_grunt": "XY Vs. Team Flare Rüpel", "battle_aether_grunt": "SM Vs. Æther Foundation", "battle_skull_grunt": "SM Vs. Team Skull Rüpel", "battle_macro_grunt": "SWSH Vs. Trainer", - "battle_rocket_boss": "USUM Vs, Giovanni", + "battle_rocket_boss": "USUM Vs. Giovanni", "battle_aqua_magma_boss": "ORAS Vs. Team Magma/Aqua Boss", "battle_galactic_boss": "BDSP Vs. Zyrus", "battle_plasma_boss": "S2W2 Vs, G-Cis", @@ -91,6 +91,7 @@ export const bgmName: SimpleTranslationEntries = { "battle_skull_boss": "SM Vs. Bromley", "battle_macro_boss": "SWSH Vs. Rose", + // Biome Music "abyss": "PMD Erkundungsteam Himmel Dunkelkrater", "badlands": "PMD Erkundungsteam Himmel Kargtal", diff --git a/src/locales/de/config.ts b/src/locales/de/config.ts index cd4979e07926..940e3927bfd8 100644 --- a/src/locales/de/config.ts +++ b/src/locales/de/config.ts @@ -34,6 +34,7 @@ import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; +import { pokemonForm } from "./pokemon-form"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; import { pokemonSummary } from "./pokemon-summary"; @@ -87,6 +88,7 @@ export const deConfig = { nature: nature, pokeball: pokeball, pokemon: pokemon, + pokemonForm: pokemonForm, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, pokemonSummary: pokemonSummary, diff --git a/src/locales/de/menu.ts b/src/locales/de/menu.ts index 01e15fb76299..bfc4c31efcbb 100644 --- a/src/locales/de/menu.ts +++ b/src/locales/de/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no":"Nein", "disclaimer": "HAFTUNGSAUSSCHLUSS", "disclaimerDescription": "Dieses Spiel ist ein unfertiges Produkt. Es kann spielbeinträchtigende Fehler (bis hin zum Verlust des Speicherstandes)\n aufweisen, sich ohne Vorankündigung ändern und es gibt keine Garantie dass es weiterentwickelt oder fertiggestellt wird.", + "choosePokemon": "Wähle ein Pokémon.", + "renamePokemon": "Pokémon umbennenen", + "rename": "Umbenennen", + "nickname": "Spitzname", "errorServerDown": "Ups! Es gab einen Fehler beim Versuch\nden Server zu kontaktieren\nLasse dieses Fenster offen\nDu wirst automatisch neu verbunden.", } as const; diff --git a/src/locales/de/party-ui-handler.ts b/src/locales/de/party-ui-handler.ts index 604efb836284..097b670c768e 100644 --- a/src/locales/de/party-ui-handler.ts +++ b/src/locales/de/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Stafette nutzen", "UNPAUSE_EVOLUTION": "Entwicklung fortsetzen", "REVIVE": "Wiederbeleben", + "RENAME": "Umbenennen", "choosePokemon": "Wähle ein Pokémon.", "doWhatWithThisPokemon": "Was soll mit diesem Pokémon geschehen?", diff --git a/src/locales/de/pokemon-form.ts b/src/locales/de/pokemon-form.ts new file mode 100644 index 000000000000..ee4e3a8f9bee --- /dev/null +++ b/src/locales/de/pokemon-form.ts @@ -0,0 +1,190 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales"; + +export const pokemonForm: SimpleTranslationEntries = { + // Battle forms + "mega": "Mega-{{pokemonName}}", + "mega-x": "Mega-{{pokemonName}} X", + "mega-y": "Mega-{{pokemonName}} Y", + "primal": "Proto-{{pokemonName}}", + "gigantamax": "G-Dyna-{{pokemonName}}", + "eternamax": "U-Dyna-{{pokemonName}}", + + // Starters forms + // 1G + "pikachuCosplay": "Cosplay", + "pikachuCoolCosplay": "Rocker-Pikachu", + "pikachuBeautyCosplay": "Damen-Pikachu", + "pikachuCuteCosplay": "Star-Pikachu", + "pikachuSmartCosplay": "Professoren-Pikachu", + "pikachuToughCosplay": "Wrestler-Pikachu", + "pikachuPartner": "Partner-Pikachu", + "eeveePartner": "Partner-Evoli", + // 2G + "pichuSpiky": "Strubbelohr-Pichu", + "unownA": "A", + "unownB": "B", + "unownC": "C", + "unownD": "D", + "unownE": "E", + "unownF": "F", + "unownG": "G", + "unownH": "H", + "unownI": "I", + "unownJ": "J", + "unownK": "K", + "unownL": "L", + "unownM": "M", + "unownN": "N", + "unownO": "O", + "unownP": "P", + "unownQ": "Q", + "unownR": "R", + "unownS": "S", + "unownT": "T", + "unownU": "U", + "unownV": "V", + "unownW": "W", + "unownX": "X", + "unownY": "Y", + "unownZ": "Z", + "unownExclamation": "!", + "unownQuestion": "?", + // 3G + "castformSunny": "Sonnenform", + "castformRainy": "Regenform", + "castformSnowy": "Schneeform", + "deoxysNormal": "Normalform", + // 4G + "burmyPlant": "Pflanzenumhang", + "burmySandy": "Sandumhang", + "burmyTrash": "Lumpenumhang", + "shellosEast": "Östliches Meer", + "shellosWest": "Westliches Meer", + "rotomHeat": "Hitze-Rotom", + "rotomWash": "Wasch-Rotom", + "rotomFrost": "Frost-Rotom", + "rotomFan": "Wirbel-Rotom", + "rotomMow": "Schneid-Rotom", + "giratinaAltered": "Wandelform", + "shayminLand": "Landform", + // 5G + "basculinRedStriped": "Rotlinige Form", + "basculinBlueStriped": "Blaulinige Form", + "basculinWhiteStriped": "Weißlinige Form", + "deerlingSpring": "Frühlingsform", + "deerlingSummer": "Sommerform", + "deerlingAutumn": "Herbstform", + "deerlingWinter": "Winterform", + "tornadusIncarnate": "Inkarnationsform", + "thundurusIncarnate": "Inkarnationsform", + "landorusIncarnate": "Inkarnationsform", + "keldeoOrdinary": "Standardform", + "meloettaAria": "Gesangsform", + // 6G + "froakieBattleBond": "Ash-Form", + "scatterbugMeadow": "Blumenmeermuster", + "scatterbugIcySnow": "Frostmuster", + "scatterbugPolar": "Schneefeldmuster", + "scatterbugTundra": "Flockenmuster", + "scatterbugContinental": "Kontinentalmuster", + "scatterbugGarden": "Ziergartenmuster", + "scatterbugElegant": "Prunkmuster", + "scatterbugModern": "Innovationsmuster", + "scatterbugMarine": "Aquamarinmuster", + "scatterbugArchipelago": "Archipelmuster", + "scatterbugHighPlains": "Dürrmuster", + "scatterbugSandstorm": "Sandmuster", + "scatterbugRiver": "Flussdeltamuster", + "scatterbugMonsoon": "Monsunmuster", + "scatterbugSavanna": "Savannenmuster", + "scatterbugSun": "Sonnenmuster", + "scatterbugOcean": "Ozeanmuster", + "scatterbugJungle": "Dschungelmuster", + "scatterbugFancy": "Fantasiemuster", + "scatterbugPokeBall": "Pokéball-Muster", + "flabebeRed": "Rotblütler", + "flabebeYellow": "Gelbblütler", + "flabebeOrange": "Orangeblütler", + "flabebeBlue": "Blaublütler", + "flabebeWhite": "Weißblütler", + "furfrouHeart": "Herzchenschnitt", + "furfrouStar": "Sternchenschnitt", + "furfrouDiamond": "Diamantenschitt", + "furfrouDebutante": "Fräuleinschnitt", + "furfrouMatron": "Damenschnitt", + "furfrouDandy": "Kavalierschnitt", + "furfrouLaReine": "Königinnenschnitt", + "furfrouKabuki": "Kabuki-Schnitt", + "furfrouPharaoh": "Herrscherschnitt", + "pumpkabooSmall": "Größe S", + "pumpkabooLarge": "Größe L", + "pumpkabooSuper": "Größe XL", + "xerneasNeutral": "Ruhe-Modus", + "xerneasActive": "Aktiv-Modus", + "zygarde50": "50% Form", + "zygarde10": "10% Form", + "zygarde50Pc": "50% Form Scharwandel", + "zygarde10Pc": "10% Form Scharwandel", + "zygardeComplete": "Optimum-Form", + // 7G + "oricorioBaile": "Flamenco-Stil", + "oricorioPompom": "Cheerleading-Stil", + "oricorioPau": "Hula-Stil", + "oricorioSensu": "Buyo-Stil", + "rockruffOwnTempo": "Gleichmut", + "miniorRedMeteor": "Rote-Meteorform", + "miniorOrangeMeteor": "Oranger-Meteorform", + "miniorYellowMeteor": "Gelber-Meteorform", + "miniorGreenMeteor": "Grüner-Meteorform", + "miniorBlueMeteor": "Hellblaue-Meteorform", + "miniorIndigoMeteor": "Blaue-Meteorform", + "miniorVioletMeteor": "Violette-Meteorform", + "miniorRed": "Roter Kern", + "miniorOrange": "Oranger Kern", + "miniorYellow": "Gelber Kern", + "miniorGreen": "Grüner Kern", + "miniorBlue": "Hellblauer Kern", + "miniorIndigo": "Blauer Kern", + "miniorViolet": "Violetter Kern", + "mimikyuDisguised": "Verkleidete Form", + "mimikyuBusted": "Entlarvte Form", + "magearnaOriginal": "Originalfarbe", + "marshadowZenith": "Zenitform", + // 8G + "sinisteaPhony": "Fälschungsform", + "sinisteaAntique": "Originalform", + "eiscueNoIce": "Wohlfühlkopf", + "indeedeeMale": "männlich", + "indeedeeFemale": "weiblich", + "morpekoFullBelly": "Pappsattmuster", + "zacianHeroOfManyBattles": "Heldenhafter Krieger", + "zamazentaHeroOfManyBattles": "Heldenhafter Krieger", + "zarudeDada": "Papa", + "enamorusIncarnate": "Inkarnationsform", + // 9G + "squawkabillyGreenPlumage": "Grüngefiedert", + "squawkabillyBluePlumage": "Blaugefiedert", + "squawkabillyYellowPlumage": "Gelbgefiedert", + "squawkabillyWhitePlumage": "Weißgefiedert", + "tatsugiriCurly": "Gebogene Form", + "tatsugiriDroopy": "Hängende Form", + "tatsugiriStretchy": "Gestrekte Form", + "gimmighoulChest": "Truhenform", + "gimmighoulRoaming": "Wanderform", + "koraidonApexBuild": "Vollkommene Gestalt", + "koraidonLimitedBuild":"Gehemmte Gestalt", + "koraidonSprintingBuild":"Sprintgestalt", + "koraidonSwimmingBuild":"Schwimmgestalt", + "koraidonGlidingBuild":"Schwingengestalt", + "miraidonUltimateMode":"Kompletter Modus", + "miraidonLowPowerMode":"Begrenzter Modus", + "miraidonDriveMode":"Fahrmodus", + "miraidonAquaticMode":"Wassermodus", + "miraidonGlideMode":"Gleitmodus", + "poltchageistCounterfeit": "Imitationsform", + "poltchageistArtisan": "Kostbarkeitsform", + "paldeaTaurosCombat": "Gefechtsvariante", + "paldeaTaurosBlaze": "Flammenvariante", + "paldeaTaurosAqua": "Flutenvariante", + +} as const; diff --git a/src/locales/de/starter-select-ui-handler.ts b/src/locales/de/starter-select-ui-handler.ts index 92ead61ebe7c..9cf088464014 100644 --- a/src/locales/de/starter-select-ui-handler.ts +++ b/src/locales/de/starter-select-ui-handler.ts @@ -7,6 +7,7 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; */ export const starterSelectUiHandler: SimpleTranslationEntries = { "confirmStartTeam": "Mit diesen Pokémon losziehen?", + "invalidParty": "This is not a valid starting party!", "gen1": "I", "gen2": "II", "gen3": "III", diff --git a/src/locales/en/battle.ts b/src/locales/en/battle.ts index d7a1f6ccf90d..12a0f2c99c62 100644 --- a/src/locales/en/battle.ts +++ b/src/locales/en/battle.ts @@ -155,4 +155,5 @@ export const battle: SimpleTranslationEntries = { "battlerTagsSaltCuredLapse": "{{pokemonNameWithAffix}} is hurt by {{moveName}}!", "battlerTagsCursedOnAdd": "{{pokemonNameWithAffix}} cut its own HP and put a curse on the {{pokemonName}}!", "battlerTagsCursedLapse": "{{pokemonNameWithAffix}} is afflicted by the Curse!", + "battlerTagsStockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!" } as const; diff --git a/src/locales/en/config.ts b/src/locales/en/config.ts index e20aaa2bbb38..970bf5b71fc7 100644 --- a/src/locales/en/config.ts +++ b/src/locales/en/config.ts @@ -37,6 +37,7 @@ import { nature } from "./nature"; import { partyUiHandler } from "./party-ui-handler"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; +import { pokemonForm } from "./pokemon-form"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; import { pokemonSummary } from "./pokemon-summary"; @@ -87,6 +88,7 @@ export const enConfig = { nature: nature, pokeball: pokeball, pokemon: pokemon, + pokemonForm: pokemonForm, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, pokemonSummary: pokemonSummary, diff --git a/src/locales/en/menu.ts b/src/locales/en/menu.ts index c6a767def50c..fe4d96c51209 100644 --- a/src/locales/en/menu.ts +++ b/src/locales/en/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no":"No", "disclaimer": "DISCLAIMER", "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed.", + "choosePokemon": "Choose a Pokémon.", + "renamePokemon": "Rename Pokémon", + "rename": "Rename", + "nickname": "Nickname", "errorServerDown": "Oops! There was an issue contacting the server.\n\nYou may leave this window open,\nthe game will automatically reconnect.", } as const; diff --git a/src/locales/en/party-ui-handler.ts b/src/locales/en/party-ui-handler.ts index 78fdcc14dbe9..4f300dd36ead 100644 --- a/src/locales/en/party-ui-handler.ts +++ b/src/locales/en/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Pass Baton", "UNPAUSE_EVOLUTION": "Unpause Evolution", "REVIVE": "Revive", + "RENAME": "Rename", "choosePokemon": "Choose a Pokémon.", "doWhatWithThisPokemon": "Do what with this Pokémon?", diff --git a/src/locales/en/pokemon-form.ts b/src/locales/en/pokemon-form.ts new file mode 100644 index 000000000000..b80819d5c64b --- /dev/null +++ b/src/locales/en/pokemon-form.ts @@ -0,0 +1,190 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales"; + +export const pokemonForm: SimpleTranslationEntries = { + // Battle forms + "mega": "Mega {{pokemonName}}", + "mega-x": "Mega {{pokemonName}} X", + "mega-y": "Mega {{pokemonName}} Y", + "primal": "Primal {{pokemonName}}", + "gigantamax": "G-Max {{pokemonName}}", + "eternamax": "E-Max {{pokemonName}}", + + // Starters forms + // 1G + "pikachuCosplay": "Cosplay", + "pikachuCoolCosplay": "Cool Cosplay", + "pikachuBeautyCosplay": "Beauty Cosplay", + "pikachuCuteCosplay": "Cute Cosplay", + "pikachuSmartCosplay": "Smart Cosplay", + "pikachuToughCosplay": "Tough Cosplay", + "pikachuPartner": "Partner", + "eeveePartner": "Partner", + // 2G + "pichuSpiky": "Spiky", + "unownA": "A", + "unownB": "B", + "unownC": "C", + "unownD": "D", + "unownE": "E", + "unownF": "F", + "unownG": "G", + "unownH": "H", + "unownI": "I", + "unownJ": "J", + "unownK": "K", + "unownL": "L", + "unownM": "M", + "unownN": "N", + "unownO": "O", + "unownP": "P", + "unownQ": "Q", + "unownR": "R", + "unownS": "S", + "unownT": "T", + "unownU": "U", + "unownV": "V", + "unownW": "W", + "unownX": "X", + "unownY": "Y", + "unownZ": "Z", + "unownExclamation": "!", + "unownQuestion": "?", + // 3G + "castformSunny": "Sunny", + "castformRainy": "Rainy", + "castformSnowy": "Snowy", + "deoxysNormal": "Normal", + // 4G + "burmyPlant": "Plant", + "burmySandy": "Sandy", + "burmyTrash": "Trash", + "shellosEast": "East", + "shellosWest": "West", + "rotomHeat": "Heat", + "rotomWash": "Wash", + "rotomFrost": "Frost", + "rotomFan": "Fan", + "rotomMow": "Mow", + "giratinaAltered": "Altered", + "shayminLand": "Land", + // 5G + "basculinRedStriped": "Red Striped", + "basculinBlueStriped": "Blue Striped", + "basculinWhiteStriped": "White Striped", + "deerlingSpring": "Spring", + "deerlingSummer": "Summer", + "deerlingAutumn": "Autumn", + "deerlingWinter": "Winter", + "tornadusIncarnate": "Incarnate", + "thundurusIncarnate": "Incarnate", + "landorusIncarnate": "Incarnate", + "keldeoOrdinary": "Ordinary", + "meloettaAria": "Aria", + // 6G + "froakieBattleBond": "Battle Bond", + "scatterbugMeadow": "Meadow", + "scatterbugIcySnow": "Icy Snow", + "scatterbugPolar": "Polar", + "scatterbugTundra": "Tundra", + "scatterbugContinental": "Continental", + "scatterbugGarden": "Garden", + "scatterbugElegant": "Elegant", + "scatterbugModern": "Modern", + "scatterbugMarine": "Marine", + "scatterbugArchipelago": "Archipelago", + "scatterbugHighPlains": "High Plains", + "scatterbugSandstorm": "Sandstorm", + "scatterbugRiver": "River", + "scatterbugMonsoon": "Monsoon", + "scatterbugSavanna": "Savanna", + "scatterbugSun": "Sun", + "scatterbugOcean": "Ocean", + "scatterbugJungle": "Jungle", + "scatterbugFancy": "Fancy", + "scatterbugPokeBall": "Poké Ball", + "flabebeRed": "Red", + "flabebeYellow": "Yellow", + "flabebeOrange": "Orange", + "flabebeBlue": "Blue", + "flabebeWhite": "White", + "furfrouHeart": "Heart", + "furfrouStar": "Star", + "furfrouDiamond": "Diamond", + "furfrouDebutante": "Debutante", + "furfrouMatron": "Matron", + "furfrouDandy": "Dandy", + "furfrouLaReine": "La Reine", + "furfrouKabuki": "Kabuki", + "furfrouPharaoh": "Pharaoh", + "pumpkabooSmall": "Small", + "pumpkabooLarge": "Large", + "pumpkabooSuper": "Super", + "xerneasNeutral": "Neutral", + "xerneasActive": "Active", + "zygarde50": "50% Forme", + "zygarde10": "10% Forme", + "zygarde50Pc": "50% Forme Power Construct", + "zygarde10Pc": "10% Forme Power Construct", + "zygardeComplete": "Complete Forme", + // 7G + "oricorioBaile": "Baile", + "oricorioPompom": "Pom-Pom", + "oricorioPau": "Pau", + "oricorioSensu": "Sensu", + "rockruffOwnTempo": "Own Tempo", + "miniorRedMeteor": "Red Meteor", + "miniorOrangeMeteor": "Orange Meteor", + "miniorYellowMeteor": "Yellow Meteor", + "miniorGreenMeteor": "Green Meteor", + "miniorBlueMeteor": "Blue Meteor", + "miniorIndigoMeteor": "Indigo Meteor", + "miniorVioletMeteor": "Violet Meteor", + "miniorRed": "Red", + "miniorOrange": "Orange", + "miniorYellow": "Yellow", + "miniorGreen": "Green", + "miniorBlue": "Blue", + "miniorIndigo": "Indigo", + "miniorViolet": "Violet", + "mimikyuDisguised": "Disguised", + "mimikyuBusted": "Busted", + "magearnaOriginal": "Original", + "marshadowZenith": "Zenith", + // 8G + "sinisteaPhony": "Phony", + "sinisteaAntique": "Antique", + "eiscueNoIce": "No Ice", + "indeedeeMale": "Male", + "indeedeeFemale": "Female", + "morpekoFullBelly": "Full Belly", + "zacianHeroOfManyBattles": "Hero Of Many Battles", + "zamazentaHeroOfManyBattles": "Hero Of Many Battles", + "zarudeDada": "Dada", + "enamorusIncarnate": "Incarnate", + // 9G + "squawkabillyGreenPlumage": "Green Plumage", + "squawkabillyBluePlumage": "Blue Plumage", + "squawkabillyYellowPlumage": "Yellow Plumage", + "squawkabillyWhitePlumage": "White Plumage", + "tatsugiriCurly": "Curly", + "tatsugiriDroopy": "Droopy", + "tatsugiriStretchy": "Stretchy", + "gimmighoulChest": "Chest", + "gimmighoulRoaming": "Roaming", + "koraidonApexBuild": "Apex Build", + "koraidonLimitedBuild":"Limited Build", + "koraidonSprintingBuild":"Sprinting Build", + "koraidonSwimmingBuild":"Swimming Build", + "koraidonGlidingBuild":"Gliding Build", + "miraidonUltimateMode":"Ultimate Mode", + "miraidonLowPowerMode":"Low Power Mode", + "miraidonDriveMode":"Drive Mode", + "miraidonAquaticMode":"Aquatic Mode", + "miraidonGlideMode":"Glide Mode", + "poltchageistCounterfeit": "Counterfeit", + "poltchageistArtisan": "Artisan", + "paldeaTaurosCombat": "Combat", + "paldeaTaurosBlaze": "Blaze", + "paldeaTaurosAqua": "Aqua", + +} as const; diff --git a/src/locales/en/starter-select-ui-handler.ts b/src/locales/en/starter-select-ui-handler.ts index ac59785bab72..6d7b7f7cfb20 100644 --- a/src/locales/en/starter-select-ui-handler.ts +++ b/src/locales/en/starter-select-ui-handler.ts @@ -6,7 +6,8 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; * account interactions, descriptive text, etc. */ export const starterSelectUiHandler: SimpleTranslationEntries = { - "confirmStartTeam":"Begin with these Pokémon?", + "confirmStartTeam": "Begin with these Pokémon?", + "invalidParty": "This is not a valid starting party!", "gen1": "I", "gen2": "II", "gen3": "III", @@ -22,6 +23,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "nature": "Nature:", "eggMoves": "Egg Moves", "addToParty": "Add to Party", + "removeFromParty": "Remove from Party", "toggleIVs": "Toggle IVs", "manageMoves": "Manage Moves", "manageNature": "Manage Nature", diff --git a/src/locales/es/battle.ts b/src/locales/es/battle.ts index d0efa369b8d5..7f29060c5d3b 100644 --- a/src/locales/es/battle.ts +++ b/src/locales/es/battle.ts @@ -154,5 +154,6 @@ export const battle: SimpleTranslationEntries = { "battlerTagsSaltCuredOnAdd": "{{pokemonNameWithAffix}} is being salt cured!", "battlerTagsSaltCuredLapse": "{{pokemonNameWithAffix}} is hurt by {{moveName}}!", "battlerTagsCursedOnAdd": "{{pokemonNameWithAffix}} cut its own HP and put a curse on the {{pokemonName}}!", - "battlerTagsCursedLapse": "{{pokemonNameWithAffix}} is afflicted by the Curse!" + "battlerTagsCursedLapse": "{{pokemonNameWithAffix}} is afflicted by the Curse!", + "battlerTagsStockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!" } as const; diff --git a/src/locales/es/config.ts b/src/locales/es/config.ts index 73587d0c3d3f..ab23a52b7bb5 100644 --- a/src/locales/es/config.ts +++ b/src/locales/es/config.ts @@ -34,6 +34,7 @@ import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; +import { pokemonForm } from "./pokemon-form"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; import { pokemonSummary } from "./pokemon-summary"; @@ -87,6 +88,7 @@ export const esConfig = { nature: nature, pokeball: pokeball, pokemon: pokemon, + pokemonForm: pokemonForm, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, pokemonSummary: pokemonSummary, diff --git a/src/locales/es/menu.ts b/src/locales/es/menu.ts index 524464f32f7d..55bd9c6c0388 100644 --- a/src/locales/es/menu.ts +++ b/src/locales/es/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no":"No", "disclaimer": "AVISO", "disclaimerDescription": "Este juego es un producto inacabado; puede tener problemas de jugabilidad (incluyendo la posible pérdida\n de datos de guardado),cambiar sin avisar, y puede o no puede ser actualizado hasta ser completado.", + "choosePokemon": "Choose a Pokémon.", + "renamePokemon": "Rename Pokémon", + "rename": "Rename", + "nickname": "Nickname", "errorServerDown": "¡Ups! Ha habido un problema al contactar con el servidor.\n\nPuedes mantener esta ventana abierta,\nel juego se reconectará automáticamente.", } as const; diff --git a/src/locales/es/party-ui-handler.ts b/src/locales/es/party-ui-handler.ts index b310a98840da..cbbd6734b62f 100644 --- a/src/locales/es/party-ui-handler.ts +++ b/src/locales/es/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Relevo", "UNPAUSE_EVOLUTION": "Reanudar Evolución", "REVIVE": "Revivir", + "RENAME": "Rename", "choosePokemon": "Elige a un Pokémon.", "doWhatWithThisPokemon": "¿Que quieres hacer con este Pokémon?", diff --git a/src/locales/es/pokemon-form.ts b/src/locales/es/pokemon-form.ts new file mode 100644 index 000000000000..415593b0446b --- /dev/null +++ b/src/locales/es/pokemon-form.ts @@ -0,0 +1,190 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales"; + +export const pokemonForm: SimpleTranslationEntries = { + // Battle forms + "mega": "Mega {{pokemonName}}", + "mega-x": "Mega {{pokemonName}} X", + "mega-y": "Mega {{pokemonName}} Y", + "primal": "{{pokemonName}} Primigenio", + "gigantamax": "G-Max {{pokemonName}}", + "eternamax": "E-Max {{pokemonName}}", + + // Starters forms + // 1G + "pikachuCosplay": "Coqueta", + "pikachuCoolCosplay": "Roquera", + "pikachuBeautyCosplay": "Aristócrata", + "pikachuCuteCosplay": "Superstar", + "pikachuSmartCosplay": "Erudita", + "pikachuToughCosplay": "Enmascarada", + "pikachuPartner": "Compañero", + "eeveePartner": "Compañero", + // 2G + "pichuSpiky": "Spiky", + "unownA": "A", + "unownB": "B", + "unownC": "C", + "unownD": "D", + "unownE": "E", + "unownF": "F", + "unownG": "G", + "unownH": "H", + "unownI": "I", + "unownJ": "J", + "unownK": "K", + "unownL": "L", + "unownM": "M", + "unownN": "N", + "unownO": "O", + "unownP": "P", + "unownQ": "Q", + "unownR": "R", + "unownS": "S", + "unownT": "T", + "unownU": "U", + "unownV": "V", + "unownW": "W", + "unownX": "X", + "unownY": "Y", + "unownZ": "Z", + "unownExclamation": "!", + "unownQuestion": "?", + // 3G + "castformSunny": "Sol", + "castformRainy": "Lluvia", + "castformSnowy": "Nieve", + "deoxysNormal": "Normal", + // 4G + "burmyPlant": "Planta", + "burmySandy": "Arena", + "burmyTrash": "Basura", + "shellosEast": "Este", + "shellosWest": "Oeste", + "rotomHeat": "Calor", + "rotomWash": "Lavado", + "rotomFrost": "Frío", + "rotomFan": "Ventilador", + "rotomMow": "Corte", + "giratinaAltered": "Altered", + "shayminLand": "Land", + // 5G + "basculinRedStriped": "Raya Roja", + "basculinBlueStriped": "Raya Azul", + "basculinWhiteStriped": "Raya Blanca", + "deerlingSpring": "Primavera", + "deerlingSummer": "Verano", + "deerlingAutumn": "Otoño", + "deerlingWinter": "Invierno", + "tornadusIncarnate": "Incarnate", + "thundurusIncarnate": "Incarnate", + "landorusIncarnate": "Incarnate", + "keldeoOrdinary": "Ordinary", + "meloettaAria": "Aria", + // 6G + "froakieBattleBond": "Fuerte Afecto", + "scatterbugMeadow": "Floral", + "scatterbugIcySnow": "Polar", + "scatterbugPolar": "Taiga", + "scatterbugTundra": "Tundra", + "scatterbugContinental": "Continental", + "scatterbugGarden": "Vergel", + "scatterbugElegant": "Oriental", + "scatterbugModern": "Moderno", + "scatterbugMarine": "Marino", + "scatterbugArchipelago": "Isleño", + "scatterbugHighPlains": "Estepa", + "scatterbugSandstorm": "Desierto", + "scatterbugRiver": "Oasis", + "scatterbugMonsoon": "Monzón", + "scatterbugSavanna": "Pantano", + "scatterbugSun": "Solar", + "scatterbugOcean": "Océano", + "scatterbugJungle": "Jungla", + "scatterbugFancy": "Fantasía", + "scatterbugPokeBall": "Poké Ball", + "flabebeRed": "Rojo", + "flabebeYellow": "Amarillo", + "flabebeOrange": "Naranja", + "flabebeBlue": "Azul", + "flabebeWhite": "Blanco", + "furfrouHeart": "Corazón", + "furfrouStar": "Estrella", + "furfrouDiamond": "Diamante", + "furfrouDebutante": "Debutante", + "furfrouMatron": "Matrón", + "furfrouDandy": "Dandi", + "furfrouLaReine": "La Reine", + "furfrouKabuki": "Kabuki", + "furfrouPharaoh": "Faraón", + "pumpkabooSmall": "Pequeño", + "pumpkabooLarge": "Grande", + "pumpkabooSuper": "Enorme", + "xerneasNeutral": "Relajado", + "xerneasActive": "Activo", + "zygarde50": "Al 50%", + "zygarde10": "Al 10%", + "zygarde50Pc": "Zygarde al 50%", + "zygarde10Pc": "Zygarde al 10%", + "zygardeComplete": "Zygarde Completo", + // 7G + "oricorioBaile": "Apasionado", + "oricorioPompom": "Animado", + "oricorioPau": "Plácido", + "oricorioSensu": "Refinado", + "rockruffOwnTempo": "Ritmo Propio", + "miniorRedMeteor": "Núcleo Rojo", + "miniorOrangeMeteor": "Núcleo Naranja", + "miniorYellowMeteor": "Núcleo Amarillo", + "miniorGreenMeteor": "Núcleo Verde", + "miniorBlueMeteor": "Núcleo Azul", + "miniorIndigoMeteor": "Núcleo Añil", + "miniorVioletMeteor": "Núcleo Violeta", + "miniorRed": "Rojo", + "miniorOrange": "Naranja", + "miniorYellow": "Amarillo", + "miniorGreen": "Verde", + "miniorBlue": "Azul", + "miniorIndigo": "Añil", + "miniorViolet": "Violeta", + "mimikyuDisguised": "Encubierta", + "mimikyuBusted": "Descubierta", + "magearnaOriginal": "Vetusto", + "marshadowZenith": "Cénit", + // 8G + "sinisteaPhony": "Falsificada", + "sinisteaAntique": "Auténtica", + "eiscueNoIce": "Cara Deshielo", + "indeedeeMale": "Macho", + "indeedeeFemale": "Hembra", + "morpekoFullBelly": "Full Belly", + "zacianHeroOfManyBattles": "Hero Of Many Battles", + "zamazentaHeroOfManyBattles": "Hero Of Many Battles", + "zarudeDada": "Papá", + "enamorusIncarnate": "Incarnate", + // 9G + "squawkabillyGreenPlumage": "Plumaje Verde", + "squawkabillyBluePlumage": "Plumaje Azul", + "squawkabillyYellowPlumage": "Plumaje Amarillo", + "squawkabillyWhitePlumage": "Plumaje Blanco", + "tatsugiriCurly": "Curvada", + "tatsugiriDroopy": "Lánguida", + "tatsugiriStretchy": "Estirada", + "gimmighoulChest": "Cofre", + "gimmighoulRoaming": "Andante", + "koraidonApexBuild": "Apex Build", + "koraidonLimitedBuild":"Limited Build", + "koraidonSprintingBuild":"Sprinting Build", + "koraidonSwimmingBuild":"Swimming Build", + "koraidonGlidingBuild":"Gliding Build", + "miraidonUltimateMode":"Ultimate Mode", + "miraidonLowPowerMode":"Low Power Mode", + "miraidonDriveMode":"Drive Mode", + "miraidonAquaticMode":"Aquatic Mode", + "miraidonGlideMode":"Glide Mode", + "poltchageistCounterfeit": "Imitación", + "poltchageistArtisan": "Original", + "paldeaTaurosCombat": "Combatiente", + "paldeaTaurosBlaze": "Ardiente", + "paldeaTaurosAqua": "Acuático", + +} as const; diff --git a/src/locales/es/starter-select-ui-handler.ts b/src/locales/es/starter-select-ui-handler.ts index 14c22e220977..6f7d845ca64e 100644 --- a/src/locales/es/starter-select-ui-handler.ts +++ b/src/locales/es/starter-select-ui-handler.ts @@ -6,7 +6,8 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; * account interactions, descriptive text, etc. */ export const starterSelectUiHandler: SimpleTranslationEntries = { - "confirmStartTeam":"¿Comenzar con estos Pokémon?", + "confirmStartTeam": "¿Comenzar con estos Pokémon?", + "invalidParty": "This is not a valid starting party!", "gen1": "I", "gen2": "II", "gen3": "III", diff --git a/src/locales/fr/battle.ts b/src/locales/fr/battle.ts index 0ce9d73c70e6..861dc6fd73cf 100644 --- a/src/locales/fr/battle.ts +++ b/src/locales/fr/battle.ts @@ -154,5 +154,6 @@ export const battle: SimpleTranslationEntries = { "battlerTagsSaltCuredOnAdd": "{{pokemonNameWithAffix}}\nest couvert de sel !", "battlerTagsSaltCuredLapse": "{{pokemonNameWithAffix}} est blessé\npar la capacité {{moveName}} !", "battlerTagsCursedOnAdd": "{{pokemonNameWithAffix}} sacrifie des PV\net lance une malédiction sur {{pokemonName}} !", - "battlerTagsCursedLapse": "{{pokemonNameWithAffix}} est touché par la malédiction !" + "battlerTagsCursedLapse": "{{pokemonNameWithAffix}} est touché par la malédiction !", + "battlerTagsStockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!" } as const; diff --git a/src/locales/fr/config.ts b/src/locales/fr/config.ts index f6bc1ac68d1c..787c210c1b0a 100644 --- a/src/locales/fr/config.ts +++ b/src/locales/fr/config.ts @@ -34,6 +34,7 @@ import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; +import { pokemonForm } from "./pokemon-form"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; import { pokemonSummary } from "./pokemon-summary"; @@ -87,6 +88,7 @@ export const frConfig = { nature: nature, pokeball: pokeball, pokemon: pokemon, + pokemonForm: pokemonForm, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, pokemonSummary: pokemonSummary, diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index aeb6ad9ed7eb..41927f83b1cc 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -49,5 +49,9 @@ export const menu: SimpleTranslationEntries = { "no":"Non", "disclaimer": "AVERTISSEMENT", "disclaimerDescription": "Ce jeu n’est pas un produit fini et peut contenir des problèmes de jouabilité, dont de possibles pertes de sauvegardes,\ndes modifications sans avertissement et pourrait ou non encore être mis à jour ou terminé.", + "choosePokemon": "Sélectionnez un Pokémon.", + "renamePokemon": "Renommer Pokémon", + "rename": "Renommer", + "nickname": "Surnom", "errorServerDown": "Oupsi ! Un problème de connexion au serveur est survenu.\n\nVous pouvez garder cette fenêtre ouverte,\nle jeu se reconnectera automatiquement.", } as const; diff --git a/src/locales/fr/party-ui-handler.ts b/src/locales/fr/party-ui-handler.ts index b1324f52398b..158a6e8416ab 100644 --- a/src/locales/fr/party-ui-handler.ts +++ b/src/locales/fr/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Relais", "UNPAUSE_EVOLUTION": "Réactiver Évolution", "REVIVE": "Ranimer", + "RENAME": "Renommer", "choosePokemon": "Sélectionnez un Pokémon.", "doWhatWithThisPokemon": "Que faire avec ce Pokémon ?", diff --git a/src/locales/fr/pokemon-form.ts b/src/locales/fr/pokemon-form.ts new file mode 100644 index 000000000000..09714f80f3bf --- /dev/null +++ b/src/locales/fr/pokemon-form.ts @@ -0,0 +1,190 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales"; + +export const pokemonForm: SimpleTranslationEntries = { + // Battle forms + "mega": "Méga-{{pokemonName}}", + "mega-x": "Méga-{{pokemonName}} X", + "mega-y": "Méga-{{pokemonName}} Y", + "primal": "Primo-{{pokemonName}}", + "gigantamax": "{{pokemonName}} Gigamax", + "eternamax": "{{pokemonName}} Infinimax", + + // Starters forms + // 1G + "pikachuCosplay": "Cosplayeur", + "pikachuCoolCosplay": "Cosplay Rockeur", + "pikachuBeautyCosplay": "Cosplay Lady", + "pikachuCuteCosplay": "Cosplay Star", + "pikachuSmartCosplay": "Cosplay Docteur", + "pikachuToughCosplay": "Cosplay Catcheur", + "pikachuPartner": "Partenaire", + "eeveePartner": "Partenaire", + // 2G + "pichuSpiky": "Troizépi", + "unownA": "A", + "unownB": "B", + "unownC": "C", + "unownD": "D", + "unownE": "E", + "unownF": "F", + "unownG": "G", + "unownH": "H", + "unownI": "I", + "unownJ": "J", + "unownK": "K", + "unownL": "L", + "unownM": "M", + "unownN": "N", + "unownO": "O", + "unownP": "P", + "unownQ": "Q", + "unownR": "R", + "unownS": "S", + "unownT": "T", + "unownU": "U", + "unownV": "V", + "unownW": "W", + "unownX": "X", + "unownY": "Y", + "unownZ": "Z", + "unownExclamation": "!", + "unownQuestion": "?", + // 3G + "castformSunny": "Solaire", + "castformRainy": "Eau de Pluie", + "castformSnowy": "Blizzard", + "deoxysNormal": "Normal", + // 4G + "burmyPlant": "Plante", + "burmySandy": "Sable", + "burmyTrash": "Déchet", + "shellosEast": "Orient", + "shellosWest": "Occident", + "rotomHeat": "Chaleur", + "rotomWash": "Lavage", + "rotomFrost": "Froid", + "rotomFan": "Hélice", + "rotomMow": "Tonte", + "giratinaAltered": "Alternatif", + "shayminLand": "Terrestre", + // 5G + "basculinRedStriped": "Motif Rouge", + "basculinBlueStriped": "Motif Bleu", + "basculinWhiteStriped": "Motif Blanc", + "deerlingSpring": "Printemps", + "deerlingSummer": "Été", + "deerlingAutumn": "Automne", + "deerlingWinter": "Hiver", + "tornadusIncarnate": "Avatar", + "thundurusIncarnate": "Avatar", + "landorusIncarnate": "Avatar", + "keldeoOrdinary": "Normal", + "meloettaAria": "Chant", + // 6G + "froakieBattleBond": "Synergie", + "scatterbugMeadow": "Floraison", + "scatterbugIcySnow": "Blizzard", + "scatterbugPolar": "Banquise", + "scatterbugTundra": "Glace", + "scatterbugContinental": "Continent", + "scatterbugGarden": "Verdure", + "scatterbugElegant": "Monarchie", + "scatterbugModern": "Métropole", + "scatterbugMarine": "Rivage", + "scatterbugArchipelago": "Archipel", + "scatterbugHighPlains": "Sécheresse", + "scatterbugSandstorm": "Sable", + "scatterbugRiver": "Delta", + "scatterbugMonsoon": "Cyclone", + "scatterbugSavanna": "Mangrove", + "scatterbugSun": "Zénith", + "scatterbugOcean": "Levant", + "scatterbugJungle": "Jungle", + "scatterbugFancy": "Fantaisie", + "scatterbugPokeBall": "Poké Ball", + "flabebeRed": "Rouge", + "flabebeYellow": "Jaune", + "flabebeOrange": "Orange", + "flabebeBlue": "Bleu", + "flabebeWhite": "Blanc", + "furfrouHeart": "Cœur", + "furfrouStar": "Étoile", + "furfrouDiamond": "Diamant", + "furfrouDebutante": "Demoiselle", + "furfrouMatron": "Madame", + "furfrouDandy": "Monsieur", + "furfrouLaReine": "Reine", + "furfrouKabuki": "Kabuki", + "furfrouPharaoh": "Pharaon", + "pumpkabooSmall": "Mini", + "pumpkabooLarge": "Maxi", + "pumpkabooSuper": "Ultra", + "xerneasNeutral": "Paisible", + "xerneasActive": "Déchaîné", + "zygarde50": "Forme 50%", + "zygarde10": "Forme 10%", + "zygarde50Pc": "Rassemblement Forme 50%", + "zygarde10Pc": "Rassemblement Forme 10%", + "zygardeComplete": "Parfait", + // 7G + "oricorioBaile": "Flamenco", + "oricorioPompom": "Pom-Pom", + "oricorioPau": "Hula", + "oricorioSensu": "Buyō", + "rockruffOwnTempo": "Tempo Perso", + "miniorRedMeteor": "Météore Rouge", + "miniorOrangeMeteor": "Météore Orange", + "miniorYellowMeteor": "Météore Jaune", + "miniorGreenMeteor": "Météore Vert", + "miniorBlueMeteor": "Météore Bleu", + "miniorIndigoMeteor": "Météore Indigo", + "miniorVioletMeteor": "Météore Violet", + "miniorRed": "Rouge", + "miniorOrange": "Orange", + "miniorYellow": "Jaune", + "miniorGreen": "Vert", + "miniorBlue": "Bleu", + "miniorIndigo": "Indigo", + "miniorViolet": "Violet", + "mimikyuDisguised": "Déguisé", + "mimikyuBusted": "Démasqué", + "magearnaOriginal": "Couleur du Passé", + "marshadowZenith": "Zénith", + // 8G + "sinisteaPhony": "Contrefaçon", + "sinisteaAntique": "Authentique", + "eiscueNoIce": "Tête Dégel", + "indeedeeMale": "Mâle", + "indeedeeFemale": "Femelle", + "morpekoFullBelly": "Rassasié", + "zacianHeroOfManyBattles": "Héros Aguerri", + "zamazentaHeroOfManyBattles": "Héros Aguerri", + "zarudeDada": "Papa", + "enamorusIncarnate": "Avatar", + // 9G + "squawkabillyGreenPlumage": "Plumage Vert", + "squawkabillyBluePlumage": "Plumage Bleu", + "squawkabillyYellowPlumage": "Plumage Jaune", + "squawkabillyWhitePlumage": "Plumage Blanc", + "tatsugiriCurly": "Courbé", + "tatsugiriDroopy": "Affalé", + "tatsugiriStretchy": "Raide", + "gimmighoulChest": "Coffre", + "gimmighoulRoaming": "Marche", + "koraidonApexBuild": "Final", + "koraidonLimitedBuild":"Limité", + "koraidonSprintingBuild":"Course", + "koraidonSwimmingBuild":"Nage", + "koraidonGlidingBuild":"Vol", + "miraidonUltimateMode":"Ultime", + "miraidonLowPowerMode":"Bridé", + "miraidonDriveMode":"Terrestre", + "miraidonAquaticMode":"Aquatique", + "miraidonGlideMode":"Aérien", + "poltchageistCounterfeit": "Imitation", + "poltchageistArtisan": "Onéreux", + "paldeaTaurosCombat": "Combatif", + "paldeaTaurosBlaze": "Flamboyant", + "paldeaTaurosAqua": "Aquatique", + +} as const; diff --git a/src/locales/fr/starter-select-ui-handler.ts b/src/locales/fr/starter-select-ui-handler.ts index bddc740681e6..fa45624c0f05 100644 --- a/src/locales/fr/starter-select-ui-handler.ts +++ b/src/locales/fr/starter-select-ui-handler.ts @@ -6,7 +6,8 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; * account interactions, descriptive text, etc. */ export const starterSelectUiHandler: SimpleTranslationEntries = { - "confirmStartTeam":"Commencer avec ces Pokémon ?", + "confirmStartTeam": "Commencer avec ces Pokémon ?", + "invalidParty": "This is not a valid starting party!", "gen1": "1G", "gen2": "2G", "gen3": "3G", diff --git a/src/locales/it/battle.ts b/src/locales/it/battle.ts index 7ae8ec9f397d..d728e624ae3c 100644 --- a/src/locales/it/battle.ts +++ b/src/locales/it/battle.ts @@ -154,5 +154,6 @@ export const battle: SimpleTranslationEntries = { "battlerTagsSaltCuredOnAdd": "{{pokemonNameWithAffix}} è stato messo sotto sale!", "battlerTagsSaltCuredLapse": "{{pokemonNameWithAffix}} viene colpito da {{moveName}}!", "battlerTagsCursedOnAdd": "{{pokemonNameWithAffix}} ha sacrificato metà dei suoi PS per\nlanciare una maledizione su {{pokemonName}}!", - "battlerTagsCursedLapse": "{{pokemonNameWithAffix}} subisce la maledizione!" + "battlerTagsCursedLapse": "{{pokemonNameWithAffix}} subisce la maledizione!", + "battlerTagsStockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!" } as const; diff --git a/src/locales/it/config.ts b/src/locales/it/config.ts index 49ebe6225a41..c22ab87949ed 100644 --- a/src/locales/it/config.ts +++ b/src/locales/it/config.ts @@ -34,6 +34,7 @@ import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; +import { pokemonForm } from "./pokemon-form"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; import { pokemonSummary } from "./pokemon-summary"; @@ -87,6 +88,7 @@ export const itConfig = { nature: nature, pokeball: pokeball, pokemon: pokemon, + pokemonForm: pokemonForm, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, pokemonSummary: pokemonSummary, diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index 8df8c2db9b36..9766708f7aee 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no":"No", "disclaimer": "DISCLAIMER", "disclaimerDescription": "Questo gioco è un prodotto incompleto; si potrebbero riscontrare errori (inclusa la perdita dei dati di salvataggio),\ncambiamenti impercettibili, e non è detto che venga aggiornato nel tempo o mai completato del tutto.", - "errorServerDown": "Oops! There was an issue contacting the server.\n\nYou may leave this window open,\nthe game will automatically reconnect.", + "choosePokemon": "Scegli un Pokémon.", + "renamePokemon": "Rinomina un Pokémon", + "rename": "Rinomina", + "nickname": "Nickname", + "errorServerDown": "Poffarbacco! C'è stato un errore nella comunicazione col server.\n\nPuoi lasciare questa finestra aperta,\nil gioco si riconnetterà automaticamente.", } as const; diff --git a/src/locales/it/party-ui-handler.ts b/src/locales/it/party-ui-handler.ts index 86966a6e7f94..979e04f3ea11 100644 --- a/src/locales/it/party-ui-handler.ts +++ b/src/locales/it/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Pass Baton", "UNPAUSE_EVOLUTION": "Unpause Evolution", "REVIVE": "Revive", + "RENAME": "Rinomina", "choosePokemon": "Choose a Pokémon.", "doWhatWithThisPokemon": "Do what with this Pokémon?", diff --git a/src/locales/it/pokemon-form.ts b/src/locales/it/pokemon-form.ts new file mode 100644 index 000000000000..1831e1f600ea --- /dev/null +++ b/src/locales/it/pokemon-form.ts @@ -0,0 +1,190 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales"; + +export const pokemonForm: SimpleTranslationEntries = { + // Battle forms + "mega": "Mega {{pokemonName}}", + "mega-x": "Mega {{pokemonName}} X", + "mega-y": "Mega {{pokemonName}} Y", + "primal": "Archeo {{pokemonName}}", + "gigantamax": "GigaMax {{pokemonName}}", + "eternamax": "EternaMax {{pokemonName}}", + + // Starters forms + // 1G + "pikachuCosplay": "Cosplay", + "pikachuCoolCosplay": "Cosplay classe", + "pikachuBeautyCosplay": "Cosplay bellezza", + "pikachuCuteCosplay": "Cosplay grazie", + "pikachuSmartCosplay": "Cosplay acume", + "pikachuToughCosplay": "Cosplay grinta", + "pikachuPartner": "Compagno", + "eeveePartner": "Compagno", + // 2G + "pichuSpiky": "Spunzorek", + "unownA": "A", + "unownB": "B", + "unownC": "C", + "unownD": "D", + "unownE": "E", + "unownF": "F", + "unownG": "G", + "unownH": "H", + "unownI": "I", + "unownJ": "J", + "unownK": "K", + "unownL": "L", + "unownM": "M", + "unownN": "N", + "unownO": "O", + "unownP": "P", + "unownQ": "Q", + "unownR": "R", + "unownS": "S", + "unownT": "T", + "unownU": "U", + "unownV": "V", + "unownW": "W", + "unownX": "X", + "unownY": "Y", + "unownZ": "Z", + "unownExclamation": "!", + "unownQuestion": "?", + // 3G + "castformSunny": "Sole", + "castformRainy": "Pioggia", + "castformSnowy": "Nuvola di neve", + "deoxysNormal": "Normale", + // 4G + "burmyPlant": "Pianta", + "burmySandy": "Sabbia", + "burmyTrash": "Scarti", + "shellosEast": "Est", + "shellosWest": "Ovest", + "rotomHeat": "Calore", + "rotomWash": "Lavaggio", + "rotomFrost": "Gelo", + "rotomFan": "Vortice", + "rotomMow": "Taglio", + "giratinaAltered": "Alterata", + "shayminLand": "Terra", + // 5G + "basculinRedStriped": "Linearossa", + "basculinBlueStriped": "Lineablu", + "basculinWhiteStriped": "Lineabianca", + "deerlingSpring": "Primavera", + "deerlingSummer": "Estate", + "deerlingAutumn": "Autunno", + "deerlingWinter": "Inverno", + "tornadusIncarnate": "Incarnazione", + "thundurusIncarnate": "Incarnazione", + "landorusIncarnate": "Incarnazione", + "keldeoOrdinary": "Normale", + "meloettaAria": "Canto", + // 6G + "froakieBattleBond": "Morfosintonia", + "scatterbugMeadow": "Giardinfiore", + "scatterbugIcySnow": "Nevi perenni", + "scatterbugPolar": "Nordico", + "scatterbugTundra": "Manto di neve", + "scatterbugContinental": "Continentale", + "scatterbugGarden": "Prato", + "scatterbugElegant": "Eleganza", + "scatterbugModern": "Trendy", + "scatterbugMarine": "Marino", + "scatterbugArchipelago": "Arcipelago", + "scatterbugHighPlains": "Deserto", + "scatterbugSandstorm": "Sabbia", + "scatterbugRiver": "Fluviale", + "scatterbugMonsoon": "Pluviale", + "scatterbugSavanna": "Savana", + "scatterbugSun": "Solare", + "scatterbugOcean": "Oceanico", + "scatterbugJungle": "Giungla", + "scatterbugFancy": "Sbarazzino", + "scatterbugPokeBall": "Poké Ball", + "flabebeRed": "Rosso", + "flabebeYellow": "Giallo", + "flabebeOrange": "Arancione", + "flabebeBlue": "Blu", + "flabebeWhite": "Bianco", + "furfrouHeart": "Cuore", + "furfrouStar": "Stella", + "furfrouDiamond": "Diamante", + "furfrouDebutante": "Signorina", + "furfrouMatron": "Gentildonna", + "furfrouDandy": "Gentiluomo", + "furfrouLaReine": "Regina", + "furfrouKabuki": "Kabuki", + "furfrouPharaoh": "Faraone", + "pumpkabooSmall": "Mini", + "pumpkabooLarge": "Grande", + "pumpkabooSuper": "Maxi", + "xerneasNeutral": "Relax", + "xerneasActive": "Attivo", + "zygarde50": "Forma 50%", + "zygarde10": "Forma 10%", + "zygarde50Pc": "Forma 50% Sciamefusione", + "zygarde10Pc": "Forma 10% Sciamefusione", + "zygardeComplete": "Forma perfetta", + // 7G + "oricorioBaile": "Flamenco", + "oricorioPompom": "Cheerdance", + "oricorioPau": "Hula", + "oricorioSensu": "Buyō", + "rockruffOwnTempo": "Mentelocale", + "miniorRedMeteor": "Nucleo Rosso", + "miniorOrangeMeteor": "Nucleo Arancione", + "miniorYellowMeteor": "Nucleo Giallo", + "miniorGreenMeteor": "Nucleo Verde", + "miniorBlueMeteor": "Nucleo Azzurro", + "miniorIndigoMeteor": "Nucleo Indaco", + "miniorVioletMeteor": "Nucleo Violetto", + "miniorRed": "Rosso", + "miniorOrange": "Arancione", + "miniorYellow": "Giallo", + "miniorGreen": "Verde", + "miniorBlue": "Azzurro", + "miniorIndigo": "Indaco", + "miniorViolet": "Violetto", + "mimikyuDisguised": "Mascherata", + "mimikyuBusted": "Smascherata", + "magearnaOriginal": "Colore Antico", + "marshadowZenith": "Zenith", + // 8G + "sinisteaPhony": "Contraffatta", + "sinisteaAntique": "Autentica", + "eiscueNoIce": "Liquefaccia", + "indeedeeMale": "Maschio", + "indeedeeFemale": "Femmina", + "morpekoFullBelly": "Panciapiena", + "zacianHeroOfManyBattles": "Eroe di Mille Lotte", + "zamazentaHeroOfManyBattles": "Eroe di Mille Lotte", + "zarudeDada": "Papà", + "enamorusIncarnate": "Incarnazione", + // 9G + "squawkabillyGreenPlumage": "Piume Verdi", + "squawkabillyBluePlumage": "Piume Azzurre", + "squawkabillyYellowPlumage": "Piume Gialle", + "squawkabillyWhitePlumage": "Piume Bianche", + "tatsugiriCurly": "Arcuata", + "tatsugiriDroopy": "Adagiata", + "tatsugiriStretchy": "Tesa", + "gimmighoulChest": "Scrigno", + "gimmighoulRoaming": "Ambulante", + "koraidonApexBuild": "Foggia Integrale", + "koraidonLimitedBuild":"Foggia Parziale", + "koraidonSprintingBuild":"Foggia Scattante", + "koraidonSwimmingBuild":"Foggia Nautica", + "koraidonGlidingBuild":"Foggia Librata", + "miraidonUltimateMode":"Assetto Completo", + "miraidonLowPowerMode":"Assetto Limitato", + "miraidonDriveMode":"Assetto Sprint", + "miraidonAquaticMode":"Assetto Nuoto", + "miraidonGlideMode":"Assetto Planata", + "poltchageistCounterfeit": "Taroccata", + "poltchageistArtisan": "Pregiata", + "paldeaTaurosCombat": "Combattiva", + "paldeaTaurosBlaze": "Infuocata", + "paldeaTaurosAqua": "Acquatica", + +} as const; diff --git a/src/locales/it/starter-select-ui-handler.ts b/src/locales/it/starter-select-ui-handler.ts index c84334fcd6a2..8b42a0db8de8 100644 --- a/src/locales/it/starter-select-ui-handler.ts +++ b/src/locales/it/starter-select-ui-handler.ts @@ -6,7 +6,8 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; * account interactions, descriptive text, etc. */ export const starterSelectUiHandler: SimpleTranslationEntries = { - "confirmStartTeam":"Vuoi iniziare con questi Pokémon?", + "confirmStartTeam": "Vuoi iniziare con questi Pokémon?", + "invalidParty": "This is not a valid starting party!", "gen1": "1ª", "gen2": "2ª", "gen3": "3ª", diff --git a/src/locales/ko/ability-trigger.ts b/src/locales/ko/ability-trigger.ts index 1d6a071a51bf..2c28704fc24e 100644 --- a/src/locales/ko/ability-trigger.ts +++ b/src/locales/ko/ability-trigger.ts @@ -7,7 +7,7 @@ export const abilityTriggers: SimpleTranslationEntries = { "iceFaceAvoidedDamage": "{{pokemonName}}[[는]] {{abilityName}} 때문에\n데미지를 받지 않는다!", "perishBody": "{{pokemonName}}의 {{abilityName}} 때문에\n양쪽 포켓몬 모두는 3턴 후에 쓰러져 버린다!", "poisonHeal": "{{pokemonName}}[[는]] {{abilityName}}[[로]]인해\n조금 회복했다.", - "trace": "{{pokemonName}}[[는]] {{targetName}}의\n{{abilityName}}[[를]] 복사했다!", + "trace": "{{pokemonName}}[[는]] 상대 {{targetName}}의 \n{{abilityName}}[[를]] 트레이스했다!", "windPowerCharged": "{{pokemonName}}[[는]]\n{{moveName}}에 맞아 충전되었다!", "quickDraw": "{{pokemonName}}[[는]]\n퀵드로에 의해 행동이 빨라졌다!", "blockItemTheft": "{{pokemonNameWithAffix}}의 {{abilityName}}에 의해\n도구를 빼앗기지 않는다!", diff --git a/src/locales/ko/battle.ts b/src/locales/ko/battle.ts index 60bbc067062d..10f3e1b5853e 100644 --- a/src/locales/ko/battle.ts +++ b/src/locales/ko/battle.ts @@ -155,4 +155,5 @@ export const battle: SimpleTranslationEntries = { "battlerTagsSaltCuredLapse": "{{pokemonNameWithAffix}}[[는]] 소금절이의\n데미지를 입고 있다.", "battlerTagsCursedOnAdd": "{{pokemonNameWithAffix}}[[는]] 자신의 체력을 깎아서\n{{pokemonName}}에게 저주를 걸었다!", "battlerTagsCursedLapse": "{{pokemonNameWithAffix}}[[는]]\n저주받고 있다!", + "battlerTagsStockpilingOnAdd": "{{pokemonNameWithAffix}}[[는]]\n{{stockpiledCount}}개 비축했다!", } as const; diff --git a/src/locales/ko/config.ts b/src/locales/ko/config.ts index a3cbbeeb2394..4ec47cec036a 100644 --- a/src/locales/ko/config.ts +++ b/src/locales/ko/config.ts @@ -1,3 +1,4 @@ +import { pokemonForm } from "./pokemon-form"; import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; import { arenaFlyout } from "./arena-flyout"; @@ -87,6 +88,7 @@ export const koConfig = { nature: nature, pokeball: pokeball, pokemon: pokemon, + pokemonForm: pokemonForm, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, pokemonSummary: pokemonSummary, diff --git a/src/locales/ko/menu.ts b/src/locales/ko/menu.ts index 1025ccff5c55..368627b0d5d4 100644 --- a/src/locales/ko/menu.ts +++ b/src/locales/ko/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no":"아니오", "disclaimer": "면책 조항", "disclaimerDescription": "이 게임은 완전히 개발되지 않았습니다- (세이브 데이터 소실을 포함) 플레이에 지장을 주는 문제가 생길 수 있으며,\n공지 없이 업데이트가 진행 혹은 중지될 수 있습니다.", + "choosePokemon": "포켓몬을 선택하세요.", + "renamePokemon": "포켓몬의 닉네임은?", + "rename": "닉네임 바꾸기", + "nickname": "닉네임", "errorServerDown": "서버 연결 중 문제가 발생했습니다.\n\n이 창을 종료하지 않고 두면,\n게임은 자동으로 재접속됩니다.", } as const; diff --git a/src/locales/ko/party-ui-handler.ts b/src/locales/ko/party-ui-handler.ts index f0075809345b..ff5d81eeb524 100644 --- a/src/locales/ko/party-ui-handler.ts +++ b/src/locales/ko/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "배턴터치한다", "UNPAUSE_EVOLUTION": "진화 재개", "REVIVE": "되살린다", + "RENAME": "닉네임 바꾸기", "choosePokemon": "포켓몬을 선택하세요.", "doWhatWithThisPokemon": "포켓몬을 어떻게 하겠습니까?", diff --git a/src/locales/ko/pokemon-form.ts b/src/locales/ko/pokemon-form.ts new file mode 100644 index 000000000000..06bc743f1a1b --- /dev/null +++ b/src/locales/ko/pokemon-form.ts @@ -0,0 +1,190 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales"; + +export const pokemonForm: SimpleTranslationEntries = { + // Battle forms + "mega": "메가{{pokemonName}}", + "mega-x": "메가{{pokemonName}}X", + "mega-y": "메가{{pokemonName}}Y", + "primal": "원시{{pokemonName}}", + "gigantamax": "거다이맥스 {{pokemonName}}", + "eternamax": "무한다이맥스 {{pokemonName}}", + + // Starters forms + // 1G + "pikachuCosplay": "옷갈아입기", + "pikachuCoolCosplay": "하드록", + "pikachuBeautyCosplay": "마담", + "pikachuCuteCosplay": "아이돌", + "pikachuSmartCosplay": "닥터", + "pikachuToughCosplay": "마스크드", + "pikachuPartner": "파트너", + "eeveePartner": "파트너", + // 2G + "pichuSpiky": "삐쭉귀", + "unownA": "A", + "unownB": "B", + "unownC": "C", + "unownD": "D", + "unownE": "E", + "unownF": "F", + "unownG": "G", + "unownH": "H", + "unownI": "I", + "unownJ": "J", + "unownK": "K", + "unownL": "L", + "unownM": "M", + "unownN": "N", + "unownO": "O", + "unownP": "P", + "unownQ": "Q", + "unownR": "R", + "unownS": "S", + "unownT": "T", + "unownU": "U", + "unownV": "V", + "unownW": "W", + "unownX": "X", + "unownY": "Y", + "unownZ": "Z", + "unownExclamation": "!", + "unownQuestion": "?", + // 3G + "castformSunny": "태양의 모습", + "castformRainy": "빗방울의 모습", + "castformSnowy": "설운의 모습", + "deoxysNormal": "노말폼", + // 4G + "burmyPlant": "초목도롱", + "burmySandy": "모래땅도롱", + "burmyTrash": "슈레도롱", + "shellosEast": "동쪽바다의 모습", + "shellosWest": "서쪽바다의 모습", + "rotomHeat": "히트", + "rotomWash": "워시", + "rotomFrost": "프로스트", + "rotomFan": "스핀", + "rotomMow": "커트", + "giratinaAltered": "어나더폼", + "shayminLand": "랜드폼", + // 5G + "basculinRedStriped": "적색근의 모습", + "basculinBlueStriped": "청색근의 모습", + "basculinWhiteStriped": "백색근의 모습", + "deerlingSpring": "봄의 모습", + "deerlingSummer": "여름의 모습", + "deerlingAutumn": "가을의 모습", + "deerlingWinter": "겨울의 모습", + "tornadusIncarnate": "화신폼", + "thundurusIncarnate": "화신폼", + "landorusIncarnate": "화신폼", + "keldeoOrdinary": "평상시 모습", + "meloettaAria": "보이스폼", + // 6G + "froakieBattleBond": "유대변화", + "scatterbugMeadow": "화원의 모양", + "scatterbugIcySnow": "빙설의 모양", + "scatterbugPolar": "설국의 모양", + "scatterbugTundra": "설원의 모양", + "scatterbugContinental": "대륙의 모양", + "scatterbugGarden": "정원의 모양", + "scatterbugElegant": "우아한 모양", + "scatterbugModern": "모던한 모양", + "scatterbugMarine": "마린의 모양", + "scatterbugArchipelago": "군도의 모양", + "scatterbugHighPlains": "황야의 모양", + "scatterbugSandstorm": "사진의 모양", + "scatterbugRiver": "대하의 모양", + "scatterbugMonsoon": "스콜의 모양", + "scatterbugSavanna": "사바나의 모양", + "scatterbugSun": "태양의 모양", + "scatterbugOcean": "오션의 모양", + "scatterbugJungle": "정글의 모양", + "scatterbugFancy": "팬시한 모양", + "scatterbugPokeBall": "볼의 모양", + "flabebeRed": "빨간 꽃", + "flabebeYellow": "노란 꽃", + "flabebeOrange": "오렌지색 꽃", + "flabebeBlue": "파란 꽃", + "flabebeWhite": "하얀 꽃", + "furfrouHeart": "하트컷", + "furfrouStar": "스타컷", + "furfrouDiamond": "다이아컷", + "furfrouDebutante": "레이디컷", + "furfrouMatron": "마담컷", + "furfrouDandy": "젠틀컷", + "furfrouLaReine": "퀸컷", + "furfrouKabuki": "가부키컷", + "furfrouPharaoh": "킹덤컷", + "pumpkabooSmall": "작은 사이즈", + "pumpkabooLarge": "큰 사이즈", + "pumpkabooSuper": "특대 사이즈", + "xerneasNeutral": "릴랙스모드", + "xerneasActive": "액티브모드", + "zygarde50": "50%폼", + "zygarde10": "10%폼", + "zygarde50Pc": "스웜체인지 50%폼", + "zygarde10Pc": "스웜체인지 10%폼", + "zygardeComplete": "퍼펙트폼", + // 7G + "oricorioBaile": "이글이글스타일", + "oricorioPompom": "파칙파칙스타일", + "oricorioPau": "훌라훌라스타일", + "oricorioSensu": "하늘하늘스타일", + "rockruffOwnTempo": "마이페이스", + "miniorRedMeteor": "유성의 모습(빨강)", + "miniorOrangeMeteor": "유성의 모습(주황)", + "miniorYellowMeteor": "유성의 모습(노랑)", + "miniorGreenMeteor": "유성의 모습(초록)", + "miniorBlueMeteor": "유성의 모습(옥색)", + "miniorIndigoMeteor": "유성의 모습(파랑)", + "miniorVioletMeteor": "유성의 모습(보라)", + "miniorRed": "빨간색 코어", + "miniorOrange": "주황색 코어", + "miniorYellow": "노란색 코어", + "miniorGreen": "초록색 코어", + "miniorBlue": "옥색 코어", + "miniorIndigo": "파란색 코어", + "miniorViolet": "보라색 코어", + "mimikyuDisguised": "둔갑한 모습", + "mimikyuBusted": "들킨 모습", + "magearnaOriginal": "500년 전의 색", + "marshadowZenith": "투지를 불태운 마샤도", + // 8G + "sinisteaPhony": "위작품", + "sinisteaAntique": "진작품", + "eiscueNoIce": "나이스페이스", + "indeedeeMale": "수컷의 모습", + "indeedeeFemale": "암컷의 모습", + "morpekoFullBelly": "배부른 모양", + "zacianHeroOfManyBattles": "역전의 용사", + "zamazentaHeroOfManyBattles": "역전의 용사", + "zarudeDada": "아빠", + "enamorusIncarnate": "화신폼", + // 9G + "squawkabillyGreenPlumage": "그린 페더", + "squawkabillyBluePlumage": "블루 페더", + "squawkabillyYellowPlumage": "옐로 페더", + "squawkabillyWhitePlumage": "화이트 페더", + "tatsugiriCurly": "젖힌 모습", + "tatsugiriDroopy": "늘어진 모습", + "tatsugiriStretchy": "뻗은 모습", + "gimmighoulChest": "상자폼", + "gimmighoulRoaming": "도보폼", + "koraidonApexBuild": "완전형태", + "koraidonLimitedBuild":"제한형태", + "koraidonSprintingBuild":"질주형태", + "koraidonSwimmingBuild":"유영형태", + "koraidonGlidingBuild":"활공형태", + "miraidonUltimateMode":"컴플리트모드", + "miraidonLowPowerMode":"리미티드모드", + "miraidonDriveMode":"드라이브모드", + "miraidonAquaticMode":"플로트모드", + "miraidonGlideMode":"글라이드모드", + "poltchageistCounterfeit": "가짜배기의 모습", + "poltchageistArtisan": "알짜배기의 모습", + "paldeaTaurosCombat": "컴뱃종", + "paldeaTaurosBlaze": "블레이즈종", + "paldeaTaurosAqua": "워터종", + +} as const; diff --git a/src/locales/ko/starter-select-ui-handler.ts b/src/locales/ko/starter-select-ui-handler.ts index d7f8ddbe3ed3..a0c305b4266b 100644 --- a/src/locales/ko/starter-select-ui-handler.ts +++ b/src/locales/ko/starter-select-ui-handler.ts @@ -7,6 +7,7 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; */ export const starterSelectUiHandler: SimpleTranslationEntries = { "confirmStartTeam": "이 포켓몬들로 시작하시겠습니까?", + "invalidParty": "This is not a valid starting party!", "gen1": "1세대", "gen2": "2세대", "gen3": "3세대", diff --git a/src/locales/pt_BR/battle.ts b/src/locales/pt_BR/battle.ts index 081e91d23061..5c194ae45839 100644 --- a/src/locales/pt_BR/battle.ts +++ b/src/locales/pt_BR/battle.ts @@ -155,4 +155,5 @@ export const battle: SimpleTranslationEntries = { "battlerTagsSaltCuredLapse": "{{pokemonNameWithAffix}} foi ferido pelo {{moveName}}!", "battlerTagsCursedOnAdd": "{{pokemonNameWithAffix}} cortou seus PS pela metade e amaldiçoou {{pokemonName}}!", "battlerTagsCursedLapse": "{{pokemonNameWithAffix}} foi ferido pelo Curse!", + "battlerTagsStockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!", } as const; diff --git a/src/locales/pt_BR/config.ts b/src/locales/pt_BR/config.ts index 2f5c28dbad3e..711ba903e9bc 100644 --- a/src/locales/pt_BR/config.ts +++ b/src/locales/pt_BR/config.ts @@ -34,6 +34,7 @@ import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; +import { pokemonForm } from "./pokemon-form"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; import { pokemonSummary } from "./pokemon-summary"; @@ -87,6 +88,7 @@ export const ptBrConfig = { nature: nature, pokeball: pokeball, pokemon: pokemon, + pokemonForm: pokemonForm, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, pokemonSummary: pokemonSummary, diff --git a/src/locales/pt_BR/menu.ts b/src/locales/pt_BR/menu.ts index aca16b6b511e..927ccce518b9 100644 --- a/src/locales/pt_BR/menu.ts +++ b/src/locales/pt_BR/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no": "Não", "disclaimer": "AVISO", "disclaimerDescription": "Este jogo é um produto inacabado; ele pode ter problemas de jogabilidade (incluindo possíveis\n perdas de dados salvos), sofrer alterações sem aviso prévio e pode ou não ser atualizado ou concluído.", + "choosePokemon": "Escolha um Pokémon.", + "renamePokemon": "Renomear Pokémon", + "rename": "Renomear", + "nickname": "Apelido", "errorServerDown": "Opa! Não foi possível conectar-se ao servidor.\n\nVocê pode deixar essa janela aberta,\npois o jogo irá se reconectar automaticamente.", } as const; diff --git a/src/locales/pt_BR/move.ts b/src/locales/pt_BR/move.ts index 97e14cb81c2a..1748f7266827 100644 --- a/src/locales/pt_BR/move.ts +++ b/src/locales/pt_BR/move.ts @@ -2281,8 +2281,8 @@ export const move: MoveTranslationEntries = { name: "Parabolic Charge", effect: "O usuário ataca tudo ao seu redor. Os PS do usuário são restaurados pela metade do dano recebido por aqueles que foram atingidos." }, - "forest’SCurse": { - name: "Forest’s Curse", + "forestsCurse": { + name: "Forest's Curse", effect: "O usuário conjura uma maldição da floresta no alvo. Isso adiciona o tipo Planta à tipagem do alvo." }, "petalBlizzard": { @@ -2349,8 +2349,8 @@ export const move: MoveTranslationEntries = { name: "Fairy Lock", effect: "Bloqueando o campo de batalha, o usuário previne que todos os Pokémon fujam durante o próximo turno." }, - "king’SShield": { - name: "King’s Shield", + "kingsShield": { + name: "King's Shield", effect: "O usuário assume uma posição defensiva enquanto protege a si mesmo de dano. Isto duramente diminui o Ataque de qualquer um que faça contato direto." }, "playNice": { @@ -2461,8 +2461,8 @@ export const move: MoveTranslationEntries = { name: "Thousand Waves", effect: "O usuário ataca com tremores que se dispersam pelo chão. Alvos atingidos não podem fugir da batalha." }, - "land’SWrath": { - name: "Land’s Wrath", + "landsWrath": { + name: "Land's Wrath", effect: "O usuário reúne a energia da terra e foca esse poder nos Pokémon oponentes para causar dano." }, "lightOfRuin": { @@ -2873,547 +2873,547 @@ export const move: MoveTranslationEntries = { name: "Multi-Attack", effect: "Se envolvendo em energia concentrada, o usuário acerta o alvo. A memória segurada determina o tipo do movimento." }, - "10,000,000VoltThunderbolt": { + "tenMillionVoltThunderbolt": { name: "10,000,000 Volt Thunderbolt", effect: "Usando seu Poder Z, o Pikachu de boné acumula eletricidade e despeja-a. Golpes críticos acertam mais facilmente." }, - mindBlown: { + "mindBlown": { name: "Mind Blown", effect: "O usuário ataca tudo ao seu redor fazendo sua própria cabeça explodir. Isso também causa dano ao usuário." }, - plasmaFists: { + "plasmaFists": { name: "Plasma Fists", effect: "O usuário ataca com punhos carregados eletricamente. Este movimento transforma movimentos do tipo Normal em movimentos do tipo Elétrico." }, - photonGeyser: { + "photonGeyser": { name: "Photon Geyser", effect: "O usuário ataca o alvo com um pilar de luz. Este movimento causa dano de Ataque ou Ataque Especial—o que for maior para o usuário." }, - lightThatBurnsTheSky: { + "lightThatBurnsTheSky": { name: "Light That Burns the Sky", effect: "Este ataque causa dano de Ataque ou Ataque Especial—o que for maior para o usuário, Necrozma. Este movimento ignora a Habilidade do alvo." }, - searingSunrazeSmash: { + "searingSunrazeSmash": { name: "Searing Sunraze Smash", effect: "Após obter o Z-Power, o usuário, Solgaleo, ataca o alvo com força total. Este movimento pode ignorar o efeito da Habilidade do alvo." }, - menacingMoonrazeMaelstrom: { + "menacingMoonrazeMaelstrom": { name: "Menacing Moonraze Maelstrom", effect: "Após obter o Z-Power, o usuário, Lunala, ataca o alvo com força total. Este movimento pode ignorar o efeito da Habilidade do alvo." }, - letsSnuggleForever: { + "letsSnuggleForever": { name: "Let's Snuggle Forever", effect: "Após obter o Z-Power, o usuário, Mimikyu, soca o alvo com força total." }, - splinteredStormshards: { + "splinteredStormshards": { name: "Splintered Stormshards", effect: "Após obter o Z-Power, o usuário, Lycanroc, ataca o alvo com força total. Este movimento nega o efeito no campo de batalha." }, - clangorousSoulblaze: { + "clangorousSoulblaze": { name: "Clangorous Soulblaze", effect: "Após obter o Z-Power, o usuário, Kommo-o, ataca os Pokémon adversários com força total. Este movimento aumenta os atributos do usuário." }, - zippyZap: { + "zippyZap": { name: "Zippy Zap", effect: "O usuário ataca o alvo com rajadas de eletricidade em alta velocidade. Esse movimento sempre vai primeiro e aumenta a Evasão do usuário." }, - splishySplash: { + "splishySplash": { name: "Splishy Splash", effect: "O usuário carrega uma onda enorme com eletricidade e atinge os Pokémon adversários com a onda. Isso também pode deixar os Pokémon adversários paralisados." }, - floatyFall: { + "floatyFall": { name: "Floaty Fall", effect: "O usuário flutua no ar e então mergulha em um ângulo íngreme para atacar o alvo. Isso também pode fazer o alvo hesitar." }, - pikaPapow: { + "pikaPapow": { name: "Pika Papow", effect: "Quanto mais o Pikachu ama seu Treinador, maior o poder do movimento. Nunca erra." }, - bouncyBubble: { + "bouncyBubble": { name: "Bouncy Bubble", effect: "O usuário ataca atirando bolhas de água no alvo. Em seguida, absorve água e restaura seu HP pelo mesmo valor de dano causado ao alvo." }, - buzzyBuzz: { + "buzzyBuzz": { name: "Buzzy Buzz", effect: "O usuário dispara um choque de eletricidade para atacar o alvo. Isso também deixa o alvo paralisado." }, - sizzlySlide: { + "sizzlySlide": { name: "Sizzly Slide", effect: "O usuário se envolve em fogo e carrega contra o alvo. Isso também deixa o alvo queimado." }, - glitzyGlow: { + "glitzyGlow": { name: "Glitzy Glow", effect: "O usuário bombardeia o alvo com força telecinética. Uma parede maravilhosa de luz é erguida para enfraquecer o poder dos movimentos especiais dos Pokémon adversários." }, - baddyBad: { + "baddyBad": { name: "Baddy Bad", effect: "O usuário age mal e ataca o alvo. Uma parede maravilhosa de luz é erguida para enfraquecer o poder dos movimentos físicos dos Pokémon adversários." }, - sappySeed: { + "sappySeed": { name: "Sappy Seed", effect: "O usuário cresce um caule gigantesco que espalha sementes para atacar o alvo. As sementes drenam o HP do alvo a cada turno." }, - freezyFrost: { + "freezyFrost": { name: "Freezy Frost", effect: "O usuário ataca com um cristal feito de névoa congelada fria. Isso elimina todas as mudanças de atributo entre todos os Pokémon envolvidos na batalha." }, - sparklySwirl: { + "sparklySwirl": { name: "Sparkly Swirl", effect: "O usuário ataca o alvo envolvendo-o com um redemoinho de um aroma esmagador. Isso também cura todas as condições de status do grupo do usuário." }, - veeveeVolley: { + "veeveeVolley": { name: "Veevee Volley", effect: "Quanto mais o Eevee ama seu Treinador, maior o poder do movimento. Nunca erra." }, - doubleIronBash: { + "doubleIronBash": { name: "Double Iron Bash", effect: "O usuário gira, centrando a porca hexagonal em seu peito e depois ataca com seus braços duas vezes seguidas. Isso também pode fazer o alvo hesitar." }, - maxGuard: { + "maxGuard": { name: "Max Guard", effect: "Este movimento permite ao usuário proteger-se de todos os ataques. Sua chance de falhar aumenta se for usado em sucessão." }, - dynamaxCannon: { + "dynamaxCannon": { name: "Dynamax Cannon", effect: "O usuário libera um forte feixe de seu núcleo. Este movimento causa até o dobro do dano se o alvo estiver com seu nível acima do limite." }, - snipeShot: { + "snipeShot": { name: "Snipe Shot", effect: "O usuário ignora os efeitos dos movimentos e Habilidades dos Pokémon adversários que atraem movimentos, permitindo que este movimento atinja o alvo escolhido." }, - jawLock: { + "jawLock": { name: "Jaw Lock", effect: "Este movimento impede o usuário e o alvo de trocarem de lugar até que um deles desmaie. O efeito desaparece se qualquer um dos Pokémon deixar o campo." }, - stuffCheeks: { + "stuffCheeks": { name: "Stuff Cheeks", effect: "O usuário come sua Fruta segurada, depois aumenta muito seu atributo de Defesa." }, - noRetreat: { + "noRetreat": { name: "No Retreat", effect: "Este movimento aumenta todos os atributos do usuário, mas impede o usuário de trocar de lugar ou fugir." }, - tarShot: { + "tarShot": { name: "Tar Shot", effect: "O usuário derrama alcatrão pegajoso sobre o alvo, diminuindo o atributo de Velocidade do alvo. O alvo se torna mais fraco contra movimentos do tipo Fogo." }, - magicPowder: { + "magicPowder": { name: "Magic Powder", effect: "O usuário espalha uma nuvem de pó mágico que muda o alvo para o tipo Psíquico." }, - dragonDarts: { + "dragonDarts": { name: "Dragon Darts", effect: "O usuário ataca duas vezes usando Dreepy. Se houver dois alvos, este movimento atinge cada alvo uma vez." }, - teatime: { + "teatime": { name: "Teatime", effect: "O usuário faz hora do chá com todos os Pokémon na batalha. Cada Pokémon come sua Fruta segurada." }, - octolock: { + "octolock": { name: "Octolock", effect: "O usuário prende o alvo e impede que ele fuja. Este movimento também diminui os atributos de Defesa e Def. Esp. do alvo a cada turno." }, - boltBeak: { + "boltBeak": { name: "Bolt Beak", effect: "O usuário fere o alvo com seu bico eletrificado. Se o usuário atacar antes do alvo, o poder deste movimento é dobrado." }, - fishiousRend: { + "fishiousRend": { name: "Fishious Rend", effect: "O usuário fere o alvo com suas brânquias duras. Se o usuário atacar antes do alvo, o poder deste movimento é dobrado." }, - courtChange: { + "courtChange": { name: "Court Change", effect: "Com seu poder misterioso, o usuário troca os efeitos de cada lado do campo." }, - maxFlare: { + "maxFlare": { name: "Max Flare", effect: "Este é um ataque do tipo Fogo que Pokémon Dynamax usam. O usuário intensifica o sol por cinco turnos." }, - maxFlutterby: { + "maxFlutterby": { name: "Max Flutterby", effect: "Este é um ataque do tipo Inseto que Pokémon Dynamax usam. Isso diminui o atributo de Atq. Esp. do alvo." }, - maxLightning: { + "maxLightning": { name: "Max Lightning", effect: "Este é um ataque do tipo Elétrico que Pokémon Dynamax usam. O usuário transforma o chão em Terreno Elétrico por cinco turnos." }, - maxStrike: { + "maxStrike": { name: "Max Strike", effect: "Este é um ataque do tipo Normal que Pokémon Dynamax usam. Isso diminui o atributo de Velocidade do alvo." }, - maxKnuckle: { + "maxKnuckle": { name: "Max Knuckle", effect: "Este é um ataque do tipo Lutador que Pokémon Dynamax usam. Isso aumenta os atributos de Ataque dos Pokémon aliados." }, - maxPhantasm: { + "maxPhantasm": { name: "Max Phantasm", effect: "Este é um ataque do tipo Fantasma que Pokémon Dynamax usam. Isso diminui o atributo de Defesa do alvo." }, - maxHailstorm: { + "maxHailstorm": { name: "Max Hailstorm", effect: "Este é um ataque do tipo Gelo que Pokémon Dynamax usam. O usuário convoca uma tempestade de granizo que dura cinco turnos." }, - maxOoze: { + "maxOoze": { name: "Max Ooze", effect: "Este é um ataque do tipo Veneno que Pokémon Dynamax usam. Isso aumenta os atributos de Atq. Esp. dos Pokémon aliados." }, - maxGeyser: { + "maxGeyser": { name: "Max Geyser", effect: "Este é um ataque do tipo Água que Pokémon Dynamax usam. O usuário convoca uma chuva pesada que cai por cinco turnos." }, - maxAirstream: { + "maxAirstream": { name: "Max Airstream", effect: "Este é um ataque do tipo Voador que Pokémon Dynamax usam. Isso aumenta os atributos de Velocidade dos Pokémon aliados." }, - maxStarfall: { + "maxStarfall": { name: "Max Starfall", effect: "Este é um ataque do tipo Fada que Pokémon Dynamax usam. O usuário transforma o chão em Terreno de Nevoeiro por cinco turnos." }, - maxWyrmwind: { + "maxWyrmwind": { name: "Max Wyrmwind", effect: "Este é um ataque do tipo Dragão que Pokémon Dynamax usam. Isso diminui o atributo de Ataque do alvo." }, - maxMindstorm: { + "maxMindstorm": { name: "Max Mindstorm", effect: "Este é um ataque do tipo Psíquico que Pokémon Dynamax usam. O usuário transforma o chão em Terreno Psíquico por cinco turnos." }, - maxRockfall: { + "maxRockfall": { name: "Max Rockfall", effect: "Este é um ataque do tipo Pedra que Pokémon Dynamax usam. O usuário convoca uma tempestade de areia que dura cinco turnos." }, - maxQuake: { + "maxQuake": { name: "Max Quake", effect: "Este é um ataque do tipo Terra que Pokémon Dynamax usam. Isso aumenta os atributos de Def. Esp. dos Pokémon aliados." }, - maxDarkness: { + "maxDarkness": { name: "Max Darkness", effect: "Este é um ataque do tipo Sombrio que Pokémon Dynamax usam. Isso diminui o atributo de Def. Esp. do alvo." }, - maxOvergrowth: { + "maxOvergrowth": { name: "Max Overgrowth", effect: "Este é um ataque do tipo Grama que Pokémon Dynamax usam. O usuário transforma o chão em Terreno de Grama por cinco turnos." }, - maxSteelspike: { + "maxSteelspike": { name: "Max Steelspike", effect: "Este é um ataque do tipo Aço que Pokémon Dynamax usam. Isso aumenta os atributos de Defesa dos Pokémon aliados." }, - clangorousSoul: { + "clangorousSoul": { name: "Clangorous Soul", effect: "O usuário aumenta todos os seus atributos usando um pouco de seu HP." }, - bodyPress: { + "bodyPress": { name: "Body Press", effect: "O usuário ataca pressionando seu corpo contra o alvo. Quanto maior a Defesa do usuário, mais dano pode infligir ao alvo." }, - decorate: { + "decorate": { name: "Decorate", effect: "O usuário aumenta muito os atributos de Ataque e Atq. Esp. do alvo decorando o alvo." }, - drumBeating: { + "drumBeating": { name: "Drum Beating", effect: "O usuário toca seu tambor, controlando as raízes do tambor para atacar o alvo. Isso também diminui o atributo de Velocidade do alvo." }, - snapTrap: { + "snapTrap": { name: "Snap Trap", effect: "O usuário prende o alvo em uma armadilha rápida por quatro ou cinco turnos." }, - pyroBall: { + "pyroBall": { name: "Pyro Ball", effect: "O usuário ataca acendendo uma pequena pedra e lançando-a como uma bola de fogo no alvo. Isso também pode deixar o alvo queimado." }, - behemothBlade: { + "behemothBlade": { name: "Behemoth Blade", effect: "O usuário empunha uma espada grande e poderosa usando todo o seu corpo e corta o alvo em um ataque vigoroso." }, - behemothBash: { + "behemothBash": { name: "Behemoth Bash", effect: "O corpo do usuário se torna um escudo firme e atinge o alvo com força." }, - auraWheel: { + "auraWheel": { name: "Aura Wheel", effect: "Morpeko ataca e aumenta sua Velocidade com a energia armazenada em suas bochechas. O tipo deste movimento muda dependendo da forma do usuário." }, - breakingSwipe: { + "breakingSwipe": { name: "Breaking Swipe", effect: "O usuário balança sua cauda dura violentamente e ataca os Pokémon adversários. Isso também diminui os atributos de Ataque deles." }, - branchPoke: { + "branchPoke": { name: "Branch Poke", effect: "O usuário ataca o alvo cutucando-o com um galho pontiagudo." }, - overdrive: { + "overdrive": { name: "Overdrive", effect: "O usuário ataca os Pokémon adversários vibrando uma guitarra ou baixo, causando um eco enorme e uma vibração forte." }, - appleAcid: { + "appleAcid": { name: "Apple Acid", effect: "O usuário ataca o alvo com um líquido ácido criado a partir de maçãs azedas. Isso também diminui o atributo de Def. Esp. do alvo." }, - gravApple: { + "gravApple": { name: "Grav Apple", effect: "O usuário inflige dano derrubando uma maçã de cima. Isso também diminui o atributo de Defesa do alvo." }, - spiritBreak: { + "spiritBreak": { name: "Spirit Break", effect: "O usuário ataca o alvo com tanta força que poderia quebrar o espírito do alvo. Isso também diminui o atributo de Atq. Esp. do alvo." }, - strangeSteam: { + "strangeSteam": { name: "Strange Steam", effect: "O usuário ataca o alvo emitindo vapor. Isso também pode deixar o alvo confuso." }, - lifeDew: { + "lifeDew": { name: "Life Dew", effect: "O usuário espalha água misteriosa ao redor e restaura o HP de si mesmo e de seus Pokémon aliados na batalha." }, - obstruct: { + "obstruct": { name: "Obstruct", effect: "Este movimento permite ao usuário proteger-se de todos os ataques. Sua chance de falhar aumenta se for usado em sucessão. Contato direto reduz severamente o atributo de Defesa do atacante." }, - falseSurrender: { + "falseSurrender": { name: "False Surrender", effect: "O usuário finge abaixar a cabeça, mas então esfaqueia o alvo com seus cabelos desgrenhados. Este ataque nunca erra." }, - meteorAssault: { + "meteorAssault": { name: "Meteor Assault", effect: "O usuário ataca selvagemente com seu alho-poró grosso. O usuário não pode se mover na próxima rodada, porque a força deste movimento o faz cambalear." }, - eternabeam: { + "eternabeam": { name: "Eternabeam", effect: "Este é o ataque mais poderoso de Eternatus em sua forma original. O usuário não pode se mover na próxima rodada." }, - steelBeam: { + "steelBeam": { name: "Steel Beam", effect: "O usuário dispara um feixe de aço que coletou de todo o seu corpo. Isso também causa dano ao usuário." }, - expandingForce: { + "expandingForce": { name: "Expanding Force", effect: "O usuário ataca o alvo com seu poder psíquico. O poder deste movimento aumenta e danifica todos os Pokémon adversários no Terreno Psíquico." }, - steelRoller: { + "steelRoller": { name: "Steel Roller", effect: "O usuário ataca enquanto destrói o terreno. Este movimento falha quando o chão não foi transformado em um terreno." }, - scaleShot: { + "scaleShot": { name: "Scale Shot", effect: "O usuário ataca atirando escamas de duas a cinco vezes seguidas. Este movimento aumenta o atributo de Velocidade do usuário, mas diminui seu atributo de Defesa." }, - meteorBeam: { + "meteorBeam": { name: "Meteor Beam", effect: "Neste ataque de dois turnos, o usuário reúne energia espacial e aumenta seu atributo de Atq. Esp., depois ataca o alvo no próximo turno." }, - shellSideArm: { + "shellSideArm": { name: "Shell Side Arm", effect: "Este movimento causa dano físico ou especial, o que for mais eficaz. Isso também pode envenenar o alvo." }, - mistyExplosion: { + "mistyExplosion": { name: "Misty Explosion", effect: "O usuário ataca tudo ao seu redor e desmaia ao usar este movimento. O poder deste movimento é aumentado no Terreno de Nevoeiro." }, - grassyGlide: { + "grassyGlide": { name: "Grassy Glide", effect: "Deslizando no chão, o usuário ataca o alvo. Este movimento sempre ataca primeiro no Terreno de Grama." }, - risingVoltage: { + "risingVoltage": { name: "Rising Voltage", effect: "O usuário ataca com a voltagem elétrica que sobe do chão. O poder deste movimento dobra quando o alvo está no Terreno Elétrico." }, - terrainPulse: { + "terrainPulse": { name: "Terrain Pulse", effect: "O usuário utiliza o poder do terreno para atacar. O tipo e o poder deste movimento mudam dependendo do terreno em que é usado." }, - skitterSmack: { + "skitterSmack": { name: "Skitter Smack", effect: "O usuário corre por trás do alvo para atacar. Isso também diminui o atributo de Atq. Esp. do alvo." }, - burningJealousy: { + "burningJealousy": { name: "Burning Jealousy", effect: "O usuário ataca com energia da inveja. Isso deixa todos os Pokémon adversários que tiveram seus atributos aumentados durante o turno com uma queimadura." }, - lashOut: { + "lashOut": { name: "Lash Out", effect: "O usuário ataca para desabafar sua frustração contra o alvo. Se os atributos do usuário foram diminuídos durante este turno, o poder deste movimento é dobrado." }, - poltergeist: { + "poltergeist": { name: "Poltergeist", effect: "O usuário ataca o alvo controlando o item do alvo. O movimento falha se o alvo não tiver um item." }, - corrosiveGas: { + "corrosiveGas": { name: "Corrosive Gas", effect: "O usuário envolve tudo ao seu redor com gás altamente ácido e derrete os itens que eles seguram." }, - coaching: { + "coaching": { name: "Coaching", effect: "O usuário treina adequadamente seus Pokémon aliados, aumentando seus atributos de Ataque e Defesa." }, - flipTurn: { + "flipTurn": { name: "Flip Turn", effect: "Após fazer seu ataque, o usuário corre para trocar de lugar com um Pokémon do grupo à espera." }, - tripleAxel: { + "tripleAxel": { name: "Triple Axel", effect: "Um ataque de três chutes consecutivos que se torna mais poderoso a cada acerto bem-sucedido." }, - dualWingbeat: { + "dualWingbeat": { name: "Dual Wingbeat", effect: "O usuário atinge o alvo com suas asas. O alvo é atingido duas vezes seguidas." }, - scorchingSands: { + "scorchingSands": { name: "Scorching Sands", effect: "O usuário joga areia escaldante no alvo para atacar. Isso também pode deixar o alvo queimado." }, - jungleHealing: { + "jungleHealing": { name: "Jungle Healing", effect: "O usuário se torna um com a selva, restaurando HP e curando quaisquer condições de status de si mesmo e de seus Pokémon aliados na batalha." }, - wickedBlow: { + "wickedBlow": { name: "Wicked Blow", effect: "O usuário, tendo dominado o estilo Sombrio, atinge o alvo com um golpe feroz. Este ataque sempre resulta em um acerto crítico." }, - surgingStrikes: { + "surgingStrikes": { name: "Surging Strikes", effect: "O usuário, tendo dominado o estilo Água, atinge o alvo com um movimento fluido três vezes seguidas. Estes ataques sempre resultam em acertos críticos." }, - thunderCage: { + "thunderCage": { name: "Thunder Cage", effect: "O usuário prende o alvo em uma gaiola de eletricidade cintilante por quatro ou cinco turnos." }, - dragonEnergy: { + "dragonEnergy": { name: "Dragon Energy", effect: "Convertendo sua força vital em poder, o usuário ataca os Pokémon adversários. Quanto menor o HP do usuário, menor o poder do movimento." }, - freezingGlare: { + "freezingGlare": { name: "Freezing Glare", effect: "O usuário dispara seu poder psíquico dos olhos para atacar. Isso também pode deixar o alvo congelado." }, - fieryWrath: { + "fieryWrath": { name: "Fiery Wrath", effect: "O usuário transforma sua ira em uma aura semelhante ao fogo para atacar. Isso também pode fazer os Pokémon adversários hesitarem." }, - thunderousKick: { + "thunderousKick": { name: "Thunderous Kick", effect: "O usuário oprime o alvo com movimento semelhante ao relâmpago antes de entregar um chute. Isso também diminui o atributo de Defesa do alvo." }, - glacialLance: { + "glacialLance": { name: "Glacial Lance", effect: "O usuário ataca lançando uma lança de gelo envolta em nevasca nos Pokémon adversários." }, - astralBarrage: { + "astralBarrage": { name: "Astral Barrage", effect: "O usuário ataca enviando uma quantidade assustadora de pequenos fantasmas nos Pokémon adversários." }, - eerieSpell: { + "eerieSpell": { name: "Eerie Spell", effect: "O usuário ataca com seu tremendo poder psíquico. Isso também remove 3 PP do último movimento usado pelo alvo." }, - direClaw: { + "direClaw": { name: "Dire Claw", effect: "O usuário ataca o alvo com garras destruidoras. Isso também pode deixar o alvo envenenado, paralisado ou adormecido." }, - psyshieldBash: { + "psyshieldBash": { name: "Psyshield Bash", effect: "Envoltando-se em energia psíquica, o usuário se choca contra o alvo. Isso também aumenta o atributo de Defesa do usuário." }, - powerShift: { + "powerShift": { name: "Power Shift", effect: "O usuário troca seus atributos de Ataque e Defesa." }, - stoneAxe: { + "stoneAxe": { name: "Stone Axe", effect: "O usuário balança seus machados de pedra no alvo. Fragmentos de pedra deixados para trás por este ataque flutuam ao redor do alvo." }, - springtideStorm: { + "springtideStorm": { name: "Springtide Storm", effect: "O usuário ataca envolvendo os Pokémon adversários em ventos ferozes repletos de amor e ódio. Isso também pode diminuir os atributos de Ataque deles." }, - mysticalPower: { + "mysticalPower": { name: "Mystical Power", effect: "O usuário ataca emitindo um poder misterioso. Isso também aumenta o atributo de Atq. Esp. do usuário." }, - ragingFury: { + "ragingFury": { name: "Raging Fury", effect: "O usuário se enfurece espalhando chamas por dois ou três turnos. O usuário então fica confuso." }, - waveCrash: { + "waveCrash": { name: "Wave Crash", effect: "O usuário se envolve em água e atinge o alvo com todo o corpo para infligir dano. Isso também causa muito dano ao usuário." }, - chloroblast: { + "chloroblast": { name: "Chloroblast", effect: "O usuário lança sua clorofila acumulada para infligir dano no alvo. Isso também causa dano ao usuário." }, - mountainGale: { + "mountainGale": { name: "Mountain Gale", effect: "O usuário arremessa pedaços gigantes de gelo no alvo para infligir dano. Isso também pode fazer o alvo hesitar." }, - victoryDance: { + "victoryDance": { name: "Victory Dance", effect: "O usuário realiza uma dança intensa para inaugurar a vitória, aumentando seus atributos de Ataque, Defesa e Velocidade." }, - headlongRush: { + "headlongRush": { name: "Headlong Rush", effect: "O usuário se choca contra o alvo em um ataque de corpo inteiro. Isso também diminui os atributos de Defesa e Def. Esp. do usuário." }, - barbBarrage: { + "barbBarrage": { name: "Barb Barrage", effect: "O usuário lança inúmeras barbas tóxicas para infligir dano. O poder deste movimento é dobrado se o alvo já estiver envenenado." }, - esperWing: { + "esperWing": { name: "Esper Wing", effect: "O usuário corta o alvo com asas enriquecidas com aura. Isso também aumenta o atributo de Velocidade do usuário. Este movimento tem uma chance aumentada de causar um acerto crítico." }, - bitterMalice: { + "bitterMalice": { name: "Bitter Malice", effect: "O usuário ataca o alvo com um ressentimento arrepiante. Isso também diminui o atributo de Ataque do alvo." }, - shelter: { + "shelter": { name: "Shelter", effect: "O usuário torna sua pele tão dura quanto um escudo de ferro, aumentando muito seu atributo de Defesa." }, - tripleArrows: { + "tripleArrows": { name: "Triple Arrows", effect: "O usuário chuta e depois dispara três flechas. Este movimento tem uma chance aumentada de causar um acerto crítico e também pode diminuir o atributo de Defesa do alvo ou fazê-lo hesitar." }, - infernalParade: { + "infernalParade": { name: "Infernal Parade", effect: "O usuário ataca com miríades de bolas de fogo. Isso também pode deixar o alvo queimado. O poder deste movimento é dobrado se o alvo tiver uma condição de status." }, - ceaselessEdge: { + "ceaselessEdge": { name: "Ceaseless Edge", effect: "O usuário corta sua lâmina de concha no alvo. Fragmentos de concha deixados para trás por este ataque permanecem espalhados sob o alvo como espinhos." }, - bleakwindStorm: { + "bleakwindStorm": { name: "Bleakwind Storm", effect: "O usuário ataca com ventos selvagemente frios que fazem tanto o corpo quanto o espírito tremerem. Isso também pode diminuir os atributos de Velocidade dos Pokémon adversários." }, - wildboltStorm: { + "wildboltStorm": { name: "Wildbolt Storm", effect: "O usuário invoca uma tempestade trovejante e ataca selvagemente com relâmpagos e vento. Isso também pode deixar os Pokémon adversários paralisados." }, - sandsearStorm: { + "sandsearStorm": { name: "Sandsear Storm", effect: "O usuário ataca envolvendo os Pokémon adversários em ventos ferozes e areia escaldante. Isso também pode deixá-los queimados." }, - lunarBlessing: { + "lunarBlessing": { name: "Lunar Blessing", effect: "O usuário recebe uma bênção do crescente lunar, restaurando HP e curando condições de status para si mesmo e seus Pokémon aliados atualmente na batalha." }, - takeHeart: { + "takeHeart": { name: "Take Heart", effect: "O usuário levanta o espírito, curando suas próprias condições de status e aumentando seus atributos de Atq. Esp. e Def. Esp." }, - gMaxWildfire: { + "gMaxWildfire": { name: "G-Max Wildfire", effect: "Um ataque do tipo Fogo que o Gigantamax Charizard usa. Este movimento continua causando dano aos oponentes por quatro turnos." }, - gMaxBefuddle: { + "gMaxBefuddle": { name: "G-Max Befuddle", effect: "Um ataque do tipo Inseto que o Gigantamax Butterfree usa. Este movimento inflige as condições de envenenado, paralisado ou adormecido nos oponentes." }, - gMaxVoltCrash: { + "gMaxVoltCrash": { name: "G-Max Volt Crash", effect: "Um ataque do tipo Elétrico que o Gigantamax Pikachu usa. Este movimento paralisa os oponentes." }, - gMaxGoldRush: { + "gMaxGoldRush": { name: "G-Max Gold Rush", effect: "Um ataque do tipo Normal que o Gigantamax Meowth usa. Este movimento confunde os oponentes e também ganha dinheiro extra." }, diff --git a/src/locales/pt_BR/party-ui-handler.ts b/src/locales/pt_BR/party-ui-handler.ts index aac9e56aefa3..08132b4bfc05 100644 --- a/src/locales/pt_BR/party-ui-handler.ts +++ b/src/locales/pt_BR/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Passar Bastão", "UNPAUSE_EVOLUTION": "Ativar Evolução", "REVIVE": "Reviver", + "RENAME": "Renomear", "choosePokemon": "Escolha um Pokémon.", "doWhatWithThisPokemon": "O que você deseja fazer?", diff --git a/src/locales/pt_BR/pokemon-form.ts b/src/locales/pt_BR/pokemon-form.ts new file mode 100644 index 000000000000..04d362e75388 --- /dev/null +++ b/src/locales/pt_BR/pokemon-form.ts @@ -0,0 +1,190 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales"; + +export const pokemonForm: SimpleTranslationEntries = { + // Battle forms + "mega": "Mega {{pokemonName}}", + "mega-x": "Mega {{pokemonName}} X", + "mega-y": "Mega {{pokemonName}} Y", + "primal": "{{pokemonName}} Primordial", + "gigantamax": "G-Max {{pokemonName}}", + "eternamax": "E-Max {{pokemonName}}", + + // Starters forms + // 1G + "pikachuCosplay": "Cosplay", + "pikachuCoolCosplay": "Cosplay Legal", + "pikachuBeautyCosplay": "Cosplay Bonito", + "pikachuCuteCosplay": "Cosplay Fofo", + "pikachuSmartCosplay": "Cosplay Inteligente", + "pikachuToughCosplay": "Cosplay Forte", + "pikachuPartner": "Parceiro", + "eeveePartner": "Parceiro", + // 2G + "pichuSpiky": "Spiky", + "unownA": "A", + "unownB": "B", + "unownC": "C", + "unownD": "D", + "unownE": "E", + "unownF": "F", + "unownG": "G", + "unownH": "H", + "unownI": "I", + "unownJ": "J", + "unownK": "K", + "unownL": "L", + "unownM": "M", + "unownN": "N", + "unownO": "O", + "unownP": "P", + "unownQ": "Q", + "unownR": "R", + "unownS": "S", + "unownT": "T", + "unownU": "U", + "unownV": "V", + "unownW": "W", + "unownX": "X", + "unownY": "Y", + "unownZ": "Z", + "unownExclamation": "!", + "unownQuestion": "?", + // 3G + "castformSunny": "Ensolarado", + "castformRainy": "Chuvoso", + "castformSnowy": "Nevado", + "deoxysNormal": "Normal", + // 4G + "burmyPlant": "Vegetal", + "burmySandy": "Arenoso", + "burmyTrash": "Lixo", + "shellosEast": "Leste", + "shellosWest": "Oeste", + "rotomHeat": "Calor", + "rotomWash": "Lavagem", + "rotomFrost": "Congelante", + "rotomFan": "Ventilador", + "rotomMow": "Corte", + "giratinaAltered": "Altered", + "shayminLand": "Land", + // 5G + "basculinRedStriped": "Listras Vermelhas", + "basculinBlueStriped": "Listras Azuis", + "basculinWhiteStriped": "Listras Brancas", + "deerlingSpring": "Primavera", + "deerlingSummer": "Verão", + "deerlingAutumn": "Outono", + "deerlingWinter": "Inverno", + "tornadusIncarnate": "Incarnate", + "thundurusIncarnate": "Incarnate", + "landorusIncarnate": "Incarnate", + "keldeoOrdinary": "Ordinary", + "meloettaAria": "Aria", + // 6G + "froakieBattleBond": "Vínculo de Batalha", + "scatterbugMeadow": "Prado", + "scatterbugIcySnow": "Neve Congelada", + "scatterbugPolar": "Polar", + "scatterbugTundra": "Tundra", + "scatterbugContinental": "Continental", + "scatterbugGarden": "Jardim", + "scatterbugElegant": "Elegante", + "scatterbugModern": "Moderno", + "scatterbugMarine": "Marinho", + "scatterbugArchipelago": "Arquipélago", + "scatterbugHighPlains": "Planalto", + "scatterbugSandstorm": "Deserto", + "scatterbugRiver": "Rio", + "scatterbugMonsoon": "Monção", + "scatterbugSavanna": "Savana", + "scatterbugSun": "Solar", + "scatterbugOcean": "Oceano", + "scatterbugJungle": "Selva", + "scatterbugFancy": "Chique", + "scatterbugPokeBall": "Poké Bola", + "flabebeRed": "Vermelha", + "flabebeYellow": "Amarela", + "flabebeOrange": "Laranja", + "flabebeBlue": "Azul", + "flabebeWhite": "Branca", + "furfrouHeart": "Coração", + "furfrouStar": "Estrela", + "furfrouDiamond": "Diamante", + "furfrouDebutante": "Debutante", + "furfrouMatron": "Madame", + "furfrouDandy": "Cavalheiro", + "furfrouLaReine": "Aristocrático", + "furfrouKabuki": "Kabuki", + "furfrouPharaoh": "Faraó", + "pumpkabooSmall": "Pequeno", + "pumpkabooLarge": "Grande", + "pumpkabooSuper": "Extragrande", + "xerneasNeutral": "Relaxado", + "xerneasActive": "Ativo", + "zygarde50": "Forma 50%", + "zygarde10": "Forma 10%", + "zygarde50Pc": "Forma 50% Agrupada", + "zygarde10Pc": "Forma 10% Agrupada", + "zygardeComplete": "Forma Completa", + // 7G + "oricorioBaile": "Flamenco", + "oricorioPompom": "Pompom", + "oricorioPau": "Hula", + "oricorioSensu": "Leque", + "rockruffOwnTempo": "Próprio Tempo", + "miniorRedMeteor": "Meteoro Vermelho", + "miniorOrangeMeteor": "Meteoro Laranja", + "miniorYellowMeteor": "Meteoro Amarelo", + "miniorGreenMeteor": "Meteoro Verde", + "miniorBlueMeteor": "Meteoro Azul", + "miniorIndigoMeteor": "Meteoro Anil", + "miniorVioletMeteor": "Meteoro Violeta", + "miniorRed": "Vermelho", + "miniorOrange": "Laranja", + "miniorYellow": "Amarelo", + "miniorGreen": "Verde", + "miniorBlue": "Azul", + "miniorIndigo": "Anil", + "miniorViolet": "Violeta", + "mimikyuDisguised": "Disfarçado", + "mimikyuBusted": "Descoberto", + "magearnaOriginal": "Original", + "marshadowZenith": "Zênite", + // 8G + "sinisteaPhony": "Falsificado", + "sinisteaAntique": "Autêntico", + "eiscueNoIce": "Descongelado", + "indeedeeMale": "Macho", + "indeedeeFemale": "Fêmea", + "morpekoFullBelly": "Full Belly", + "zacianHeroOfManyBattles": "Hero Of Many Battles", + "zamazentaHeroOfManyBattles": "Hero Of Many Battles", + "zarudeDada": "Papa", + "enamorusIncarnate": "Incarnate", + // 9G + "squawkabillyGreenPlumage": "Plumas Verdes", + "squawkabillyBluePlumage": "Plumas Azuis", + "squawkabillyYellowPlumage": "Plumas Amarelas", + "squawkabillyWhitePlumage": "Plumas Brancas", + "tatsugiriCurly": "Curvado", + "tatsugiriDroopy": "Caído", + "tatsugiriStretchy": "Reto", + "gimmighoulChest": "Baú", + "gimmighoulRoaming": "Perambulante", + "koraidonApexBuild": "Apex Build", + "koraidonLimitedBuild":"Limited Build", + "koraidonSprintingBuild":"Sprinting Build", + "koraidonSwimmingBuild":"Swimming Build", + "koraidonGlidingBuild":"Gliding Build", + "miraidonUltimateMode":"Ultimate Mode", + "miraidonLowPowerMode":"Low Power Mode", + "miraidonDriveMode":"Drive Mode", + "miraidonAquaticMode":"Aquatic Mode", + "miraidonGlideMode":"Glide Mode", + "poltchageistCounterfeit": "Imitação", + "poltchageistArtisan": "Artesão", + "paldeaTaurosCombat": "Combate", + "paldeaTaurosBlaze": "Chamas", + "paldeaTaurosAqua": "Aquático", + +} as const; diff --git a/src/locales/pt_BR/starter-select-ui-handler.ts b/src/locales/pt_BR/starter-select-ui-handler.ts index eb2709a0da8d..0a06048cb51a 100644 --- a/src/locales/pt_BR/starter-select-ui-handler.ts +++ b/src/locales/pt_BR/starter-select-ui-handler.ts @@ -7,6 +7,7 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; */ export const starterSelectUiHandler: SimpleTranslationEntries = { "confirmStartTeam": "Começar com esses Pokémon?", + "invalidParty": "This is not a valid starting party!", "gen1": "G1", "gen2": "G2", "gen3": "G3", diff --git a/src/locales/zh_CN/battle.ts b/src/locales/zh_CN/battle.ts index af9f7ac6cbb8..c3c9077b7f16 100644 --- a/src/locales/zh_CN/battle.ts +++ b/src/locales/zh_CN/battle.ts @@ -146,5 +146,6 @@ export const battle: SimpleTranslationEntries = { "battlerTagsSaltCuredOnAdd": "{{pokemonNameWithAffix}}\n陷入了盐腌状态!", "battlerTagsSaltCuredLapse": "{{pokemonNameWithAffix}}\n受到了{{moveName}}的伤害!", "battlerTagsCursedOnAdd": "{{pokemonNameWithAffix}}削减了自己的体力,\n并诅咒了{{pokemonName}}!", - "battlerTagsCursedLapse": "{{pokemonNameWithAffix}}\n正受到诅咒!" + "battlerTagsCursedLapse": "{{pokemonNameWithAffix}}\n正受到诅咒!", + "battlerTagsStockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!" } as const; diff --git a/src/locales/zh_CN/config.ts b/src/locales/zh_CN/config.ts index de90e49816e3..84b74c1a20c6 100644 --- a/src/locales/zh_CN/config.ts +++ b/src/locales/zh_CN/config.ts @@ -34,6 +34,7 @@ import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; +import { pokemonForm } from "./pokemon-form"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; import { pokemonSummary } from "./pokemon-summary"; @@ -87,6 +88,7 @@ export const zhCnConfig = { nature: nature, pokeball: pokeball, pokemon: pokemon, + pokemonForm: pokemonForm, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, pokemonSummary: pokemonSummary, diff --git a/src/locales/zh_CN/menu.ts b/src/locales/zh_CN/menu.ts index b1b5b00d554c..4ff4ffc31281 100644 --- a/src/locales/zh_CN/menu.ts +++ b/src/locales/zh_CN/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no": "否", "disclaimer": "免责声明", "disclaimerDescription": "这个游戏尚未完成; 可能存在游戏性问题(包括潜在的丢档风险)、\n 不经通知的调整、 未来可能会更新或完成更多内容", + "choosePokemon": "选择一只宝可梦。", + "renamePokemon": "给宝可梦起名", + "rename": "起名", + "nickname": "昵称", "errorServerDown": "糟糕!访问服务器时发生了错误。\n\n你可以保持页面开启,\n游戏会自动重新连接。", } as const; diff --git a/src/locales/zh_CN/party-ui-handler.ts b/src/locales/zh_CN/party-ui-handler.ts index 4cb2f816b2e4..7d70ddd1503f 100644 --- a/src/locales/zh_CN/party-ui-handler.ts +++ b/src/locales/zh_CN/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "接棒", "UNPAUSE_EVOLUTION": "解除进化暂停", "REVIVE": "复活", + "RENAME": "起名", "choosePokemon": "选择一只宝可梦。", "doWhatWithThisPokemon": "要对宝可梦做什么?", diff --git a/src/locales/zh_CN/pokemon-form.ts b/src/locales/zh_CN/pokemon-form.ts new file mode 100644 index 000000000000..b8135cc78f1a --- /dev/null +++ b/src/locales/zh_CN/pokemon-form.ts @@ -0,0 +1,190 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales"; + +export const pokemonForm: SimpleTranslationEntries = { + // Battle forms + "mega": "Mega {{pokemonName}}", + "mega-x": "Mega {{pokemonName}} X", + "mega-y": "Mega {{pokemonName}} Y", + "primal": "原始回归{{pokemonName}}", + "gigantamax": "超极巨{{pokemonName}}", + "eternamax": "无极巨{{pokemonName}}", + + // Starters forms + // 1G + "pikachuCosplay": "服装", + "pikachuCoolCosplay": "摇滚巨星", + "pikachuBeautyCosplay": "贵妇", + "pikachuCuteCosplay": "流行偶像", + "pikachuSmartCosplay": "博士", + "pikachuToughCosplay": "面罩摔跤手", + "pikachuPartner": "搭档", + "eeveePartner": "搭档", + // 2G + "pichuSpiky": "刺刺耳", + "unownA": "A", + "unownB": "B", + "unownC": "C", + "unownD": "D", + "unownE": "E", + "unownF": "F", + "unownG": "G", + "unownH": "H", + "unownI": "I", + "unownJ": "J", + "unownK": "K", + "unownL": "L", + "unownM": "M", + "unownN": "N", + "unownO": "O", + "unownP": "P", + "unownQ": "Q", + "unownR": "R", + "unownS": "S", + "unownT": "T", + "unownU": "U", + "unownV": "V", + "unownW": "W", + "unownX": "X", + "unownY": "Y", + "unownZ": "Z", + "unownExclamation": "!", + "unownQuestion": "?", + // 3G + "castformSunny": "晴天", + "castformRainy": "雨天", + "castformSnowy": "雪天", + "deoxysNormal": "Normal", + // 4G + "burmyPlant": "草木蓑衣", + "burmySandy": "砂土蓑衣", + "burmyTrash": "垃圾蓑衣", + "shellosEast": "东海", + "shellosWest": "西海", + "rotomHeat": "加热", + "rotomWash": "清洗", + "rotomFrost": "结冰", + "rotomFan": "旋转", + "rotomMow": "切割", + "giratinaAltered": "Altered", + "shayminLand": "Land", + // 5G + "basculinRedStriped": "红条纹", + "basculinBlueStriped": "蓝条纹", + "basculinWhiteStriped": "白条纹", + "deerlingSpring": "春天", + "deerlingSummer": "夏天", + "deerlingAutumn": "秋天", + "deerlingWinter": "冬天", + "tornadusIncarnate": "Incarnate", + "thundurusIncarnate": "Incarnate", + "landorusIncarnate": "Incarnate", + "keldeoOrdinary": "Ordinary", + "meloettaAria": "Aria", + // 6G + "froakieBattleBond": "牵绊变身", + "scatterbugMeadow": "花园花纹", + "scatterbugIcySnow": "冰雪花纹", + "scatterbugPolar": "雪国花纹", + "scatterbugTundra": "雪原花纹", + "scatterbugContinental": "大陆花纹", + "scatterbugGarden": "庭园花纹", + "scatterbugElegant": "高雅花纹", + "scatterbugModern": "摩登花纹", + "scatterbugMarine": "大海花纹", + "scatterbugArchipelago": "群岛花纹", + "scatterbugHighPlains": "荒野花纹", + "scatterbugSandstorm": "沙尘花纹", + "scatterbugRiver": "大河花纹", + "scatterbugMonsoon": "骤雨花纹", + "scatterbugSavanna": "热带草原花纹", + "scatterbugSun": "太阳花纹", + "scatterbugOcean": "大洋花纹", + "scatterbugJungle": "热带雨林花纹", + "scatterbugFancy": "幻彩花纹", + "scatterbugPokeBall": "球球花纹", + "flabebeRed": "红花", + "flabebeYellow": "黄花", + "flabebeOrange": "橙花", + "flabebeBlue": "蓝花", + "flabebeWhite": "白花", + "furfrouHeart": "心形造型", + "furfrouStar": "星形造型", + "furfrouDiamond": "菱形造型", + "furfrouDebutante": "淑女造型", + "furfrouMatron": "贵妇造型", + "furfrouDandy": "绅士造型", + "furfrouLaReine": "女王造型", + "furfrouKabuki": "歌舞伎造型", + "furfrouPharaoh": "国王造型", + "pumpkabooSmall": "小尺寸", + "pumpkabooLarge": "大尺寸", + "pumpkabooSuper": "特大尺寸", + "xerneasNeutral": "放松模式", + "xerneasActive": "活跃模式", + "zygarde50": "50%形态", + "zygarde10": "10%形态", + "zygarde50Pc": "50%形态 群聚变形", + "zygarde10Pc": "10%形态 群聚变形", + "zygardeComplete": "完全体形态", + // 7G + "oricorioBaile": "热辣热辣风格", + "oricorioPompom": "啪滋啪滋风格", + "oricorioPau": "呼拉呼拉风格", + "oricorioSensu": "轻盈轻盈风格", + "rockruffOwnTempo": "特殊岩狗狗", + "miniorRedMeteor": "红色核心", + "miniorOrangeMeteor": "橙色核心", + "miniorYellowMeteor": "黄色核心", + "miniorGreenMeteor": "绿色核心", + "miniorBlueMeteor": "浅蓝色核心", + "miniorIndigoMeteor": "蓝色核心", + "miniorVioletMeteor": "紫色核心", + "miniorRed": "红色", + "miniorOrange": "橙色", + "miniorYellow": "黄色", + "miniorGreen": "绿色", + "miniorBlue": "浅蓝色", + "miniorIndigo": "蓝色", + "miniorViolet": "紫色", + "mimikyuDisguised": "化形", + "mimikyuBusted": "现形", + "magearnaOriginal": "500年前的颜色", + "marshadowZenith": "全力", + // 8G + "sinisteaPhony": "赝品", + "sinisteaAntique": "真品", + "eiscueNoIce": "解冻头", + "indeedeeMale": "雄性", + "indeedeeFemale": "雌性", + "morpekoFullBelly": "Full Belly", + "zacianHeroOfManyBattles": "Hero Of Many Battles", + "zamazentaHeroOfManyBattles": "Hero Of Many Battles", + "zarudeDada": "老爹", + "enamorusIncarnate": "Incarnate", + // 9G + "squawkabillyGreenPlumage": "绿羽毛", + "squawkabillyBluePlumage": "蓝羽毛", + "squawkabillyYellowPlumage": "黄羽毛", + "squawkabillyWhitePlumage": "白羽毛", + "tatsugiriCurly": "上弓姿势", + "tatsugiriDroopy": "下垂姿势", + "tatsugiriStretchy": "平挺姿势", + "gimmighoulChest": "宝箱形态", + "gimmighoulRoaming": "徒步形态", + "koraidonApexBuild": "Apex Build", + "koraidonLimitedBuild":"Limited Build", + "koraidonSprintingBuild":"Sprinting Build", + "koraidonSwimmingBuild":"Swimming Build", + "koraidonGlidingBuild":"Gliding Build", + "miraidonUltimateMode":"Ultimate Mode", + "miraidonLowPowerMode":"Low Power Mode", + "miraidonDriveMode":"Drive Mode", + "miraidonAquaticMode":"Aquatic Mode", + "miraidonGlideMode":"Glide Mode", + "poltchageistCounterfeit": "冒牌货", + "poltchageistArtisan": "高档货", + "paldeaTaurosCombat": "斗战种", + "paldeaTaurosBlaze": "火炽种", + "paldeaTaurosAqua": "水澜种", + +} as const; diff --git a/src/locales/zh_CN/starter-select-ui-handler.ts b/src/locales/zh_CN/starter-select-ui-handler.ts index 059358078f43..c23ceb66eb0d 100644 --- a/src/locales/zh_CN/starter-select-ui-handler.ts +++ b/src/locales/zh_CN/starter-select-ui-handler.ts @@ -6,7 +6,8 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; * account interactions, descriptive text, etc. */ export const starterSelectUiHandler: SimpleTranslationEntries = { - "confirmStartTeam":"使用这些宝可梦开始游戏吗?", + "confirmStartTeam": "使用这些宝可梦开始游戏吗?", + "invalidParty": "This is not a valid starting party!", "gen1": "I", "gen2": "II", "gen3": "III", diff --git a/src/locales/zh_TW/battle.ts b/src/locales/zh_TW/battle.ts index 75457b34c075..4673474d3130 100644 --- a/src/locales/zh_TW/battle.ts +++ b/src/locales/zh_TW/battle.ts @@ -144,4 +144,5 @@ export const battle: SimpleTranslationEntries = { "battlerTagsSaltCuredLapse": "{{pokemonNameWithAffix}} 受到了{{moveName}}的傷害!", "battlerTagsCursedOnAdd": "{{pokemonNameWithAffix}}削減了自己的體力,並詛咒了{{pokemonName}}!", "battlerTagsCursedLapse": "{{pokemonNameWithAffix}}正受到詛咒!", + "battlerTagsStockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!" } as const; diff --git a/src/locales/zh_TW/config.ts b/src/locales/zh_TW/config.ts index 6f7c4e51671d..63887a1f3e3c 100644 --- a/src/locales/zh_TW/config.ts +++ b/src/locales/zh_TW/config.ts @@ -34,6 +34,7 @@ import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; +import { pokemonForm } from "./pokemon-form"; import { pokemonInfo } from "./pokemon-info"; import { pokemonInfoContainer } from "./pokemon-info-container"; import { pokemonSummary } from "./pokemon-summary"; @@ -87,6 +88,7 @@ export const zhTwConfig = { nature: nature, pokeball: pokeball, pokemon: pokemon, + pokemonForm: pokemonForm, pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, pokemonSummary: pokemonSummary, diff --git a/src/locales/zh_TW/menu.ts b/src/locales/zh_TW/menu.ts index e43264de2f6a..d46f3f172de0 100644 --- a/src/locales/zh_TW/menu.ts +++ b/src/locales/zh_TW/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no":"否", "disclaimer": "DISCLAIMER", "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed.", + "choosePokemon": "Choose a Pokémon.", + "renamePokemon": "Rename Pokémon", + "rename": "Rename", + "nickname": "Nickname", "errorServerDown": "Oops! There was an issue contacting the server.\n\nYou may leave this window open,\nthe game will automatically reconnect.", } as const; diff --git a/src/locales/zh_TW/party-ui-handler.ts b/src/locales/zh_TW/party-ui-handler.ts index efa9b2c8dab2..c981e41af0eb 100644 --- a/src/locales/zh_TW/party-ui-handler.ts +++ b/src/locales/zh_TW/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Pass Baton", "UNPAUSE_EVOLUTION": "Unpause Evolution", "REVIVE": "Revive", + "RENAME": "Rename", "choosePokemon": "Choose a Pokémon.", "doWhatWithThisPokemon": "Do what with this Pokémon?", diff --git a/src/locales/zh_TW/pokemon-form.ts b/src/locales/zh_TW/pokemon-form.ts new file mode 100644 index 000000000000..2ab936b36da0 --- /dev/null +++ b/src/locales/zh_TW/pokemon-form.ts @@ -0,0 +1,190 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales"; + +export const pokemonForm: SimpleTranslationEntries = { + // Battle forms + "mega": "Mega {{pokemonName}}", + "mega-x": "Mega {{pokemonName}} X", + "mega-y": "Mega {{pokemonName}} Y", + "primal": "Primal {{pokemonName}}", + "gigantamax": "G-Max {{pokemonName}}", + "eternamax": "E-Max {{pokemonName}}", + + // Starters forms + // 1G + "pikachuCosplay": "Cosplay", + "pikachuCoolCosplay": "Cool Cosplay", + "pikachuBeautyCosplay": "Beauty Cosplay", + "pikachuCuteCosplay": "Cute Cosplay", + "pikachuSmartCosplay": "Smart Cosplay", + "pikachuToughCosplay": "Thoug Cosplay", + "pikachuPartner": "Partner", + "eeveePartner": "Partner", + // 2G + "pichuSpiky": "Spiky", + "unownA": "A", + "unownB": "B", + "unownC": "C", + "unownD": "D", + "unownE": "E", + "unownF": "F", + "unownG": "G", + "unownH": "H", + "unownI": "I", + "unownJ": "J", + "unownK": "K", + "unownL": "L", + "unownM": "M", + "unownN": "N", + "unownO": "O", + "unownP": "P", + "unownQ": "Q", + "unownR": "R", + "unownS": "S", + "unownT": "T", + "unownU": "U", + "unownV": "V", + "unownW": "W", + "unownX": "X", + "unownY": "Y", + "unownZ": "Z", + "unownExclamation": "!", + "unownQuestion": "?", + // 3G + "castformSunny": "Sunny", + "castformRainy": "Rainy", + "castformSnowy": "Snowy", + "deoxysNormal": "Normal", + // 4G + "burmyPlant": "Plant", + "burmySandy": "Sandy", + "burmyTrash": "Trash", + "shellosEast": "East", + "shellosWest": "West", + "rotomHeat": "Heat", + "rotomWash": "Wash", + "rotomFrost": "Frost", + "rotomFan": "Fan", + "rotomMow": "Mow", + "giratinaAltered": "Altered", + "shayminLand": "Land", + // 5G + "basculinRedStriped": "Red Striped", + "basculinBlueStriped": "Blue Striped", + "basculinWhiteStriped": "White Striped", + "deerlingSpring": "Spring", + "deerlingSummer": "Summer", + "deerlingAutumn": "Autumn", + "deerlingWinter": "Winter", + "tornadusIncarnate": "Incarnate", + "thundurusIncarnate": "Incarnate", + "landorusIncarnate": "Incarnate", + "keldeoOrdinary": "Ordinary", + "meloettaAria": "Aria", + // 6G + "froakieBattleBond": "Battle Bond", + "scatterbugMeadow": "Meadow", + "scatterbugIcySnow": "Icy Snow", + "scatterbugPolar": "Polar", + "scatterbugTundra": "Tundra", + "scatterbugContinental": "Continental", + "scatterbugGarden": "Garden", + "scatterbugElegant": "Elegant", + "scatterbugModern": "Modern", + "scatterbugMarine": "Marine", + "scatterbugArchipelago": "Archipelago", + "scatterbugHighPlains": "High Plains", + "scatterbugSandstorm": "Sandstorm", + "scatterbugRiver": "River", + "scatterbugMonsoon": "Monsoon", + "scatterbugSavanna": "Savanna", + "scatterbugSun": "Sun", + "scatterbugOcean": "Ocean", + "scatterbugJungle": "Jungle", + "scatterbugFancy": "Fancy", + "scatterbugPokeBall": "Poké Ball", + "flabebeRed": "Red", + "flabebeYellow": "Yellow", + "flabebeOrange": "Orange", + "flabebeBlue": "Blue", + "flabebeWhite": "White", + "furfrouHeart": "Heart", + "furfrouStar": "Star", + "furfrouDiamond": "Diamond", + "furfrouDebutante": "Debutante", + "furfrouMatron": "Matron", + "furfrouDandy": "Dandy", + "furfrouLaReine": "La Reine", + "furfrouKabuki": "Kabuki", + "furfrouPharaoh": "Pharaoh", + "pumpkabooSmall": "Small", + "pumpkabooLarge": "Large", + "pumpkabooSuper": "Super", + "xerneasNeutral": "Neutral", + "xerneasActive": "Active", + "zygarde50": "50% Forme", + "zygarde10": "10% Forme", + "zygarde50Pc": "50% Forme Power Construct", + "zygarde10Pc": "10% Forme Power Construct", + "zygardeComplete": "Complete Forme", + // 7G + "oricorioBaile": "Baile", + "oricorioPompom": "Pom-Pom", + "oricorioPau": "Pau", + "oricorioSensu": "Sensu", + "rockruffOwnTempo": "Own Tempo", + "miniorRedMeteor": "Red Meteor", + "miniorOrangeMeteor": "Orange Meteor", + "miniorYellowMeteor": "Yellow Meteor", + "miniorGreenMeteor": "Green Meteor", + "miniorBlueMeteor": "Blue Meteor", + "miniorIndigoMeteor": "Indigo Meteor", + "miniorVioletMeteor": "Violet Meteor", + "miniorRed": "Red", + "miniorOrange": "Orange", + "miniorYellow": "Yellow", + "miniorGreen": "Green", + "miniorBlue": "Blue", + "miniorIndigo": "Indigo", + "miniorViolet": "Violet", + "mimikyuDisguised": "Disguised", + "mimikyuBusted": "Busted", + "magearnaOriginal": "Original", + "marshadowZenith": "Zenith", + // 8G + "sinisteaPhony": "Phony", + "sinisteaAntique": "Antique", + "eiscueNoIce": "No Ice", + "indeedeeMale": "Male", + "indeedeeFemale": "Female", + "morpekoFullBelly": "Full Belly", + "zacianHeroOfManyBattles": "Hero Of Many Battles", + "zamazentaHeroOfManyBattles": "Hero Of Many Battles", + "zarudeDada": "Dada", + "enamorusIncarnate": "Incarnate", + // 9G + "squawkabillyGreenPlumage": "Green Plumage", + "squawkabillyBluePlumage": "Blue Plumage", + "squawkabillyYellowPlumage": "Yellow Plumage", + "squawkabillyWhitePlumage": "White Plumage", + "tatsugiriCurly": "Curly", + "tatsugiriDroopy": "Droopy", + "tatsugiriStretchy": "Stretchy", + "gimmighoulChest": "Chest", + "gimmighoulRoaming": "Roaming", + "koraidonApexBuild": "Apex Build", + "koraidonLimitedBuild":"Limited Build", + "koraidonSprintingBuild":"Sprinting Build", + "koraidonSwimmingBuild":"Swimming Build", + "koraidonGlidingBuild":"Gliding Build", + "miraidonUltimateMode":"Ultimate Mode", + "miraidonLowPowerMode":"Low Power Mode", + "miraidonDriveMode":"Drive Mode", + "miraidonAquaticMode":"Aquatic Mode", + "miraidonGlideMode":"Glide Mode", + "poltchageistCounterfeit": "Counterfeit", + "poltchageistArtisan": "Artisan", + "paldeaTaurosCombat": "Combat", + "paldeaTaurosBlaze": "Blaze", + "paldeaTaurosAqua": "Aqua", + +} as const; diff --git a/src/locales/zh_TW/starter-select-ui-handler.ts b/src/locales/zh_TW/starter-select-ui-handler.ts index ae9a4083d20b..c3b78c8078d9 100644 --- a/src/locales/zh_TW/starter-select-ui-handler.ts +++ b/src/locales/zh_TW/starter-select-ui-handler.ts @@ -6,7 +6,8 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; * account interactions, descriptive text, etc. */ export const starterSelectUiHandler: SimpleTranslationEntries = { - "confirmStartTeam":"使用這些寶可夢開始嗎?", + "confirmStartTeam": "使用這些寶可夢開始嗎?", + "invalidParty": "This is not a valid starting party!", "gen1": "I", "gen2": "II", "gen3": "III", diff --git a/src/messages.ts b/src/messages.ts index 5c465cc08e9f..2259e78abfc8 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -24,17 +24,17 @@ export function getPokemonNameWithAffix(pokemon: Pokemon): string { return !pokemon.isPlayer() ? pokemon.hasTrainer() ? i18next.t("battle:foePokemonWithAffix", { - pokemonName: pokemon.name, + pokemonName: pokemon.getNameToRender(), }) : i18next.t("battle:wildPokemonWithAffix", { - pokemonName: pokemon.name, + pokemonName: pokemon.getNameToRender(), }) - : pokemon.name; + : pokemon.getNameToRender(); case BattleSpec.FINAL_BOSS: return !pokemon.isPlayer() - ? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.name }) - : pokemon.name; + ? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender() }) + : pokemon.getNameToRender(); default: - return pokemon.name; + return pokemon.getNameToRender(); } } diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index d5bbd3b225f2..5dfad42ad1d9 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -27,6 +27,7 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { BerryType } from "#enums/berry-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; +import { getPokemonNameWithAffix } from "#app/messages.js"; const outputModifierData = false; const useMaxWeightForOutput = false; @@ -212,10 +213,10 @@ export class PokemonHeldItemModifierType extends PokemonModifierType { const matchingModifier = pokemon.scene.findModifier(m => m instanceof Modifiers.PokemonHeldItemModifier && m.pokemonId === pokemon.id && m.matchType(dummyModifier)) as Modifiers.PokemonHeldItemModifier; const maxStackCount = dummyModifier.getMaxStackCount(pokemon.scene); if (!maxStackCount) { - return i18next.t("modifierType:ModifierType.PokemonHeldItemModifierType.extra.inoperable", { "pokemonName": pokemon.name }); + return i18next.t("modifierType:ModifierType.PokemonHeldItemModifierType.extra.inoperable", { "pokemonName": getPokemonNameWithAffix(pokemon) }); } if (matchingModifier && matchingModifier.stackCount === maxStackCount) { - return i18next.t("modifierType:ModifierType.PokemonHeldItemModifierType.extra.tooMany", { "pokemonName": pokemon.name }); + return i18next.t("modifierType:ModifierType.PokemonHeldItemModifierType.extra.tooMany", { "pokemonName": getPokemonNameWithAffix(pokemon) }); } return null; }, group, soundName); @@ -234,7 +235,7 @@ export class PokemonHpRestoreModifierType extends PokemonModifierType { constructor(localeKey: string, iconImage: string, restorePoints: integer, restorePercent: integer, healStatus: boolean = false, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, group?: string) { super(localeKey, iconImage, newModifierFunc || ((_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.restorePercent, this.healStatus, false)), selectFilter || ((pokemon: PlayerPokemon) => { - if (!pokemon.hp || (pokemon.hp >= pokemon.getMaxHp() && (!this.healStatus || (!pokemon.status && !pokemon.getTag(BattlerTagType.CONFUSED))))) { + if (!pokemon.hp || (pokemon.isFullHp() && (!this.healStatus || (!pokemon.status && !pokemon.getTag(BattlerTagType.CONFUSED))))) { return PartyUiHandler.NoEffectMessage; } return null; diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 26dd9eb94cf4..9515bd2bf6b8 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -20,7 +20,7 @@ import { achvs } from "../system/achv"; import { VoucherType } from "../system/voucher"; import { FormChangeItem, SpeciesFormChangeItemTrigger } from "../data/pokemon-forms"; import { Nature } from "#app/data/nature"; -import Overrides from "../overrides"; +import Overrides from "#app/overrides"; import { ModifierType, modifierTypes } from "./modifier-type"; import { Command } from "#app/ui/command-ui-handler.js"; import { Species } from "#enums/species"; @@ -1151,7 +1151,7 @@ export class TurnHealModifier extends PokemonHeldItemModifier { apply(args: any[]): boolean { const pokemon = args[0] as Pokemon; - if (pokemon.getHpRatio() < 1) { + if (!pokemon.isFullHp()) { const scene = pokemon.scene; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), Math.max(Math.floor(pokemon.getMaxHp() / 16) * this.stackCount, 1), i18next.t("modifier:turnHealApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), typeName: this.type.name }), true)); @@ -1242,7 +1242,7 @@ export class HitHealModifier extends PokemonHeldItemModifier { apply(args: any[]): boolean { const pokemon = args[0] as Pokemon; - if (pokemon.turnData.damageDealt && pokemon.getHpRatio() < 1) { + if (pokemon.turnData.damageDealt && !pokemon.isFullHp()) { const scene = pokemon.scene; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), Math.max(Math.floor(pokemon.turnData.damageDealt / 8) * this.stackCount, 1), i18next.t("modifier:hitHealApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), typeName: this.type.name }), true)); @@ -1774,7 +1774,7 @@ export class PokemonExpBoosterModifier extends PokemonHeldItemModifier { } apply(args: any[]): boolean { - (args[1] as Utils.NumberHolder).value = Math.floor((args[1] as Utils.NumberHolder).value * (1 + (this.getStackCount() * this.boostMultiplier))); + (args[1] as Utils.NumberHolder).value += (this.getStackCount() * this.boostMultiplier); return true; } @@ -2520,7 +2520,7 @@ export class EnemyTurnHealModifier extends EnemyPersistentModifier { apply(args: any[]): boolean { const pokemon = args[0] as Pokemon; - if (pokemon.getHpRatio() < 1) { + if (!pokemon.isFullHp()) { const scene = pokemon.scene; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), Math.max(Math.floor(pokemon.getMaxHp() / (100 / this.healPercent)) * this.stackCount, 1), i18next.t("modifier:enemyTurnHealApply", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), true, false, false, false, true)); diff --git a/src/overrides.ts b/src/overrides.ts index 876938405560..abc67095bd41 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -45,8 +45,7 @@ class DefaultOverrides { /** a specific seed (default: a random string of 24 characters) */ readonly SEED_OVERRIDE: string = ""; readonly WEATHER_OVERRIDE: WeatherType = WeatherType.NONE; - readonly DOUBLE_BATTLE_OVERRIDE: boolean = false; - readonly SINGLE_BATTLE_OVERRIDE: boolean = false; + readonly BATTLE_TYPE_OVERRIDE: "double" | "single" | null = null; readonly STARTING_WAVE_OVERRIDE: integer = 0; readonly STARTING_BIOME_OVERRIDE: Biome = Biome.TOWN; readonly ARENA_TINT_OVERRIDE: TimeOfDay = null; diff --git a/src/phases.ts b/src/phases.ts index a28ad0612abf..8dc3d8661a3e 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1,11 +1,11 @@ import BattleScene, { bypassLogin } from "./battle-scene"; import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon"; import * as Utils from "./utils"; -import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, BypassRedirectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr, IncrementMovePriorityAttr } from "./data/move"; +import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, MoveTarget, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, PreMoveMessageAttr, HealStatusEffectAttr, NoEffectAttr, BypassRedirectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, ForceSwitchOutAttr, VariableTargetAttr, IncrementMovePriorityAttr } from "./data/move"; import { Mode } from "./ui/ui"; import { Command } from "./ui/command-ui-handler"; import { Stat } from "./data/pokemon-stat"; -import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier, overrideModifiers, overrideHeldItems, BypassSpeedChanceModifier, TurnStatusEffectModifier } from "./modifier/modifier"; +import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, overrideModifiers, overrideHeldItems, BypassSpeedChanceModifier, TurnStatusEffectModifier } from "./modifier/modifier"; import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball"; import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims"; @@ -24,9 +24,8 @@ import { getPokemonMessage, getPokemonNameWithAffix } from "./messages"; import { Starter } from "./ui/starter-select-ui-handler"; import { Gender } from "./data/gender"; import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather"; -import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; -import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IgnoreOpponentEvasionAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, PokemonTypeChangeAbAttr, applyPreAttackAbAttrs, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, MaxMultiHitAbAttr, HealFromBerryUseAbAttr, WonderSkinAbAttr, applyPreDefendAbAttrs, IgnoreMoveEffectsAbAttr, BlockStatusDamageAbAttr, BypassSpeedChanceAbAttr, AddSecondStrikeAbAttr } from "./data/ability"; +import { CheckTrappedAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, PokemonTypeChangeAbAttr, applyPreAttackAbAttrs, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, MaxMultiHitAbAttr, HealFromBerryUseAbAttr, IgnoreMoveEffectsAbAttr, BlockStatusDamageAbAttr, BypassSpeedChanceAbAttr, AddSecondStrikeAbAttr } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -50,7 +49,7 @@ import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run"; import { GameMode, GameModes, getGameMode } from "./game-mode"; import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./data/pokemon-species"; import i18next from "./plugins/i18n"; -import Overrides from "./overrides"; +import Overrides from "#app/overrides"; import { TextStyle, addTextObject } from "./ui/text"; import { Type } from "./data/type"; import { BerryUsedEvent, EncounterPhaseEvent, MoveUsedEvent, TurnEndEvent, TurnInitEvent } from "./events/battle-scene"; @@ -98,7 +97,7 @@ export class LoginPhase extends Phase { const loadData = () => { updateUserInfo().then(success => { if (!success[0]) { - Utils.setCookie(Utils.sessionIdKey, ""); + Utils.removeCookie(Utils.sessionIdKey); this.scene.reset(true, true); return; } @@ -119,7 +118,7 @@ export class LoginPhase extends Phase { this.scene.ui.playSelect(); updateUserInfo().then(success => { if (!success[0]) { - Utils.setCookie(Utils.sessionIdKey, ""); + Utils.removeCookie(Utils.sessionIdKey); this.scene.reset(true, true); return; } @@ -134,7 +133,7 @@ export class LoginPhase extends Phase { }, () => { const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`); const discordId = import.meta.env.VITE_DISCORD_CLIENT_ID; - const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify`; + const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify&prompt=none`; window.open(discordUrl, "_self"); }, () => { const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/google/callback`); @@ -145,7 +144,7 @@ export class LoginPhase extends Phase { ] }); } else if (statusCode === 401) { - Utils.setCookie(Utils.sessionIdKey, ""); + Utils.removeCookie(Utils.sessionIdKey); this.scene.reset(true, true); } else { this.scene.unshiftPhase(new UnavailablePhase(this.scene)); @@ -870,7 +869,7 @@ export class EncounterPhase extends BattlePhase { loadEnemyAssets.push(enemyPokemon.loadAssets()); - console.log(enemyPokemon.name, enemyPokemon.species.speciesId, enemyPokemon.stats); + console.log(getPokemonNameWithAffix(enemyPokemon), enemyPokemon.species.speciesId, enemyPokemon.stats); }); if (this.scene.getParty().filter(p => p.isShiny()).length === 6) { @@ -972,7 +971,7 @@ export class EncounterPhase extends BattlePhase { const enemyField = this.scene.getEnemyField(); if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) { - return i18next.t("battle:bossAppeared", { bossName: enemyField[0].name }); + return i18next.t("battle:bossAppeared", { bossName: getPokemonNameWithAffix(enemyField[0])}); } if (this.scene.currentBattle.battleType === BattleType.TRAINER) { @@ -985,8 +984,8 @@ export class EncounterPhase extends BattlePhase { } return enemyField.length === 1 - ? i18next.t("battle:singleWildAppeared", { pokemonName: enemyField[0].name }) - : i18next.t("battle:multiWildAppeared", { pokemonName1: enemyField[0].name, pokemonName2: enemyField[1].name }); + ? i18next.t("battle:singleWildAppeared", { pokemonName: enemyField[0].getNameToRender() }) + : i18next.t("battle:multiWildAppeared", { pokemonName1: enemyField[0].getNameToRender(), pokemonName2: enemyField[1].getNameToRender() }); } doEncounterCommon(showEncounterMessage: boolean = true) { @@ -1414,11 +1413,11 @@ export class SummonPhase extends PartyMemberPokemonPhase { // Swaps the fainted Pokemon and the first non-fainted legal Pokemon in the party [party[this.partyMemberIndex], party[legalIndex]] = [party[legalIndex], party[this.partyMemberIndex]]; - console.warn("Swapped %s %O with %s %O", partyMember?.name, partyMember, party[0]?.name, party[0]); + console.warn("Swapped %s %O with %s %O", getPokemonNameWithAffix(partyMember), partyMember, getPokemonNameWithAffix(party[0]), party[0]); } if (this.player) { - this.scene.ui.showText(i18next.t("battle:playerGo", { pokemonName: this.getPokemon().name })); + this.scene.ui.showText(i18next.t("battle:playerGo", { pokemonName: getPokemonNameWithAffix(this.getPokemon()) })); if (this.player) { this.scene.pbTray.hide(); } @@ -1438,7 +1437,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { this.scene.time.delayedCall(750, () => this.summon()); } else { const trainerName = this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER); - const pokemonName = this.getPokemon().name; + const pokemonName = getPokemonNameWithAffix(this.getPokemon()); const message = i18next.t("battle:trainerSendOut", { trainerName, pokemonName }); this.scene.pbTrayEnemy.hide(); @@ -1607,10 +1606,10 @@ export class SwitchSummonPhase extends SummonPhase { } this.scene.ui.showText(this.player ? - i18next.t("battle:playerComeBack", { pokemonName: pokemon.name }) : + i18next.t("battle:playerComeBack", { pokemonName: getPokemonNameWithAffix(pokemon) }) : i18next.t("battle:trainerComeBack", { trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER), - pokemonName: pokemon.name + pokemonName: getPokemonNameWithAffix(pokemon) }) ); this.scene.playSound("pb_rel"); @@ -1650,12 +1649,17 @@ export class SwitchSummonPhase extends SummonPhase { party[this.fieldIndex] = switchedPokemon; const showTextAndSummon = () => { this.scene.ui.showText(this.player ? - i18next.t("battle:playerGo", { pokemonName: switchedPokemon.name }) : + i18next.t("battle:playerGo", { pokemonName: getPokemonNameWithAffix(switchedPokemon) }) : i18next.t("battle:trainerGo", { trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER), - pokemonName: this.getPokemon().name + pokemonName: getPokemonNameWithAffix(this.getPokemon()) }) ); + // Ensure improperly persisted summon data (such as tags) is cleared upon switching + if (!this.batonPass) { + party[this.fieldIndex].resetBattleData(); + party[this.fieldIndex].resetSummonData(); + } this.summon(); }; if (this.player) { @@ -1812,7 +1816,7 @@ export class CheckSwitchPhase extends BattlePhase { return; } - this.scene.ui.showText(i18next.t("battle:switchQuestion", { pokemonName: this.useName ? pokemon.name : i18next.t("battle:pokemon") }), null, () => { + this.scene.ui.showText(i18next.t("battle:switchQuestion", { pokemonName: this.useName ? getPokemonNameWithAffix(pokemon) : i18next.t("battle:pokemon") }), null, () => { this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.MESSAGE); this.scene.tryRemovePhase(p => p instanceof PostSummonPhase && p.player && p.fieldIndex === this.fieldIndex); @@ -1832,7 +1836,7 @@ export class SummonMissingPhase extends SummonPhase { } preSummon(): void { - this.scene.ui.showText(i18next.t("battle:sendOutPokemon", { pokemonName: this.getPokemon().name })); + this.scene.ui.showText(i18next.t("battle:sendOutPokemon", { pokemonName: getPokemonNameWithAffix(this.getPokemon()) })); this.scene.time.delayedCall(250, () => this.summon()); } } @@ -1983,7 +1987,7 @@ export class CommandPhase extends FieldPhase { if (!moveId) { turnCommand.targets = [this.fieldIndex]; } - console.log(moveTargets, playerPokemon.name); + console.log(moveTargets, getPokemonNameWithAffix(playerPokemon)); if (moveTargets.targets.length > 1 && moveTargets.multiple) { this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); } @@ -2102,7 +2106,7 @@ export class CommandPhase extends FieldPhase { } this.scene.ui.showText( i18next.t("battle:noEscapePokemon", { - pokemonName: this.scene.getPokemonById(trapTag.sourceId).name, + pokemonName: getPokemonNameWithAffix(this.scene.getPokemonById(trapTag.sourceId)), moveName: trapTag.getMoveName(), escapeVerb: isSwitch ? i18next.t("battle:escapeVerbSwitch") : i18next.t("battle:escapeVerbFlee") }), @@ -2381,6 +2385,11 @@ export class TurnStartPhase extends FieldPhase { this.scene.pushPhase(new BerryPhase(this.scene)); this.scene.pushPhase(new TurnEndPhase(this.scene)); + /** + * this.end() will call shiftPhase(), which dumps everything from PrependQueue (aka everything that is unshifted()) to the front + * of the queue and dequeues to start the next phase + * this is important since stuff like SwitchSummon, AttemptRun, AttemptCapture Phases break the "flow" and should take precedence + */ this.end(); } } @@ -2942,6 +2951,7 @@ export class MoveEffectPhase extends PokemonPhase { if (moveHistoryEntry.result === MoveResult.PENDING) { moveHistoryEntry.result = MoveResult.MISS; } + user.pushMoveHistory(moveHistoryEntry); applyMoveAttrs(MissEffectAttr, user, null, move); continue; } @@ -3036,8 +3046,11 @@ export class MoveEffectPhase extends PokemonPhase { if (--user.turnData.hitsLeft >= 1 && this.getTarget()?.isActive()) { this.scene.unshiftPhase(this.getNewHitPhase()); } else { + // Queue message for number of hits made by multi-move + // If multi-hit attack only hits once, still want to render a message const hitsTotal = user.turnData.hitCount - Math.max(user.turnData.hitsLeft, 0); - if (hitsTotal > 1) { + if (hitsTotal > 1 || user.turnData.hitsLeft > 0) { + // If there are multiple hits, or if there are hits of the multi-hit move left this.scene.queueMessage(i18next.t("battle:attackHitsCount", { count: hitsTotal })); } this.scene.applyModifiers(HitHealModifier, this.player, user); @@ -3073,59 +3086,25 @@ export class MoveEffectPhase extends PokemonPhase { return true; } + if (target.getTag(BattlerTagType.ALWAYS_GET_HIT)) { + return true; + } + const hiddenTag = target.getTag(SemiInvulnerableTag); if (hiddenTag && !this.move.getMove().getAttrs(HitsTagAttr).some(hta => hta.tagType === hiddenTag.tagType)) { return false; } - const moveAccuracy = new Utils.NumberHolder(this.move.getMove().accuracy); + const moveAccuracy = this.move.getMove().calculateBattleAccuracy(user, target); - applyMoveAttrs(VariableAccuracyAttr, user, target, this.move.getMove(), moveAccuracy); - applyPreDefendAbAttrs(WonderSkinAbAttr, target, user, this.move.getMove(), { value: false }, moveAccuracy); - - if (moveAccuracy.value === -1) { + if (moveAccuracy === -1) { return true; } - const isOhko = this.move.getMove().hasAttr(OneHitKOAccuracyAttr); - - if (!isOhko) { - user.scene.applyModifiers(PokemonMoveAccuracyBoosterModifier, user.isPlayer(), user, moveAccuracy); - } - - if (this.scene.arena.weather?.weatherType === WeatherType.FOG) { - moveAccuracy.value = Math.floor(moveAccuracy.value * 0.9); - } - - if (!isOhko && this.scene.arena.getTag(ArenaTagType.GRAVITY)) { - moveAccuracy.value = Math.floor(moveAccuracy.value * 1.67); - } - - const userAccuracyLevel = new Utils.IntegerHolder(user.summonData.battleStats[BattleStat.ACC]); - const targetEvasionLevel = new Utils.IntegerHolder(target.summonData.battleStats[BattleStat.EVA]); - applyAbAttrs(IgnoreOpponentStatChangesAbAttr, target, null, userAccuracyLevel); - applyAbAttrs(IgnoreOpponentStatChangesAbAttr, user, null, targetEvasionLevel); - applyAbAttrs(IgnoreOpponentEvasionAbAttr, user, null, targetEvasionLevel); - applyMoveAttrs(IgnoreOpponentStatChangesAttr, user, target, this.move.getMove(), targetEvasionLevel); - this.scene.applyModifiers(TempBattleStatBoosterModifier, this.player, TempBattleStat.ACC, userAccuracyLevel); - + const accuracyMultiplier = user.getAccuracyMultiplier(target, this.move.getMove()); const rand = user.randSeedInt(100, 1); - const accuracyMultiplier = new Utils.NumberHolder(1); - if (userAccuracyLevel.value !== targetEvasionLevel.value) { - accuracyMultiplier.value = userAccuracyLevel.value > targetEvasionLevel.value - ? (3 + Math.min(userAccuracyLevel.value - targetEvasionLevel.value, 6)) / 3 - : 3 / (3 + Math.min(targetEvasionLevel.value - userAccuracyLevel.value, 6)); - } - - applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, user, BattleStat.ACC, accuracyMultiplier, this.move.getMove()); - - const evasionMultiplier = new Utils.NumberHolder(1); - applyBattleStatMultiplierAbAttrs(BattleStatMultiplierAbAttr, target, BattleStat.EVA, evasionMultiplier); - - accuracyMultiplier.value /= evasionMultiplier.value; - - return rand <= moveAccuracy.value * accuracyMultiplier.value; + return rand <= moveAccuracy * accuracyMultiplier; } getUserPokemon(): Pokemon { @@ -3250,6 +3229,8 @@ export class ShowAbilityPhase extends PokemonPhase { } } +export type StatChangeCallback = (target: Pokemon, changed: BattleStat[], relativeChanges: number[]) => void; + export class StatChangePhase extends PokemonPhase { private stats: BattleStat[]; private selfTarget: boolean; @@ -3257,8 +3238,10 @@ export class StatChangePhase extends PokemonPhase { private showMessage: boolean; private ignoreAbilities: boolean; private canBeCopied: boolean; + private onChange: StatChangeCallback; - constructor(scene: BattleScene, battlerIndex: BattlerIndex, selfTarget: boolean, stats: BattleStat[], levels: integer, showMessage: boolean = true, ignoreAbilities: boolean = false, canBeCopied: boolean = true) { + + constructor(scene: BattleScene, battlerIndex: BattlerIndex, selfTarget: boolean, stats: BattleStat[], levels: integer, showMessage: boolean = true, ignoreAbilities: boolean = false, canBeCopied: boolean = true, onChange: StatChangeCallback = null) { super(scene, battlerIndex); this.selfTarget = selfTarget; @@ -3267,6 +3250,7 @@ export class StatChangePhase extends PokemonPhase { this.showMessage = showMessage; this.ignoreAbilities = ignoreAbilities; this.canBeCopied = canBeCopied; + this.onChange = onChange; } start() { @@ -3308,6 +3292,8 @@ export class StatChangePhase extends PokemonPhase { const battleStats = this.getPokemon().summonData.battleStats; const relLevels = filteredStats.map(stat => (levels.value >= 1 ? Math.min(battleStats[stat] + levels.value, 6) : Math.max(battleStats[stat] + levels.value, -6)) - battleStats[stat]); + this.onChange?.(this.getPokemon(), filteredStats, relLevels); + const end = () => { if (this.showMessage) { const messages = this.getStatChangeMessages(filteredStats, levels.value, relLevels); @@ -3927,7 +3913,9 @@ export class VictoryPhase extends PokemonPhase { expMultiplier = Overrides.XP_MULTIPLIER_OVERRIDE; } const pokemonExp = new Utils.NumberHolder(expValue * expMultiplier); - this.scene.applyModifiers(PokemonExpBoosterModifier, true, partyMember, pokemonExp); + const modifierBonusExp = new Utils.NumberHolder(1); + this.scene.applyModifiers(PokemonExpBoosterModifier, true, partyMember, modifierBonusExp); + pokemonExp.value *= modifierBonusExp.value; partyMemberExp.push(Math.floor(pokemonExp.value)); } @@ -4491,7 +4479,7 @@ export class ExpPhase extends PlayerPartyMemberPokemonPhase { const exp = new Utils.NumberHolder(this.expValue); this.scene.applyModifiers(ExpBoosterModifier, true, exp); exp.value = Math.floor(exp.value); - this.scene.ui.showText(i18next.t("battle:expGain", { pokemonName: pokemon.name, exp: exp.value }), null, () => { + this.scene.ui.showText(i18next.t("battle:expGain", { pokemonName: getPokemonNameWithAffix(pokemon), exp: exp.value }), null, () => { const lastLevel = pokemon.level; pokemon.addExp(exp.value); const newLevel = pokemon.level; @@ -4591,7 +4579,7 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase { pokemon.updateInfo(); if (this.scene.expParty === ExpNotification.DEFAULT) { this.scene.playSound("level_up_fanfare"); - this.scene.ui.showText(i18next.t("battle:levelUp", { pokemonName: this.getPokemon().name, level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); + this.scene.ui.showText(i18next.t("battle:levelUp", { pokemonName: getPokemonNameWithAffix(this.getPokemon()), level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); } else if (this.scene.expParty === ExpNotification.SKIP) { this.end(); } else { @@ -4649,7 +4637,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { .then(() => { this.scene.ui.setMode(messageMode).then(() => { this.scene.playSound("level_up_fanfare"); - this.scene.ui.showText(i18next.t("battle:learnMove", { pokemonName: pokemon.name, moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t("battle:learnMove", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => { this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true); this.end(); }, messageMode === Mode.EVOLUTION_SCENE ? 1000 : null, true); @@ -4658,15 +4646,15 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { }); } else { this.scene.ui.setMode(messageMode).then(() => { - this.scene.ui.showText(i18next.t("battle:learnMovePrompt", { pokemonName: pokemon.name, moveName: move.name }), null, () => { - this.scene.ui.showText(i18next.t("battle:learnMoveLimitReached", { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t("battle:learnMovePrompt", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t("battle:learnMoveLimitReached", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => { this.scene.ui.showText(i18next.t("battle:learnMoveReplaceQuestion", { moveName: move.name }), null, () => { const noHandler = () => { this.scene.ui.setMode(messageMode).then(() => { this.scene.ui.showText(i18next.t("battle:learnMoveStopTeaching", { moveName: move.name }), null, () => { this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => { this.scene.ui.setMode(messageMode); - this.scene.ui.showText(i18next.t("battle:learnMoveNotLearned", { pokemonName: pokemon.name, moveName: move.name }), null, () => this.end(), null, true); + this.scene.ui.showText(i18next.t("battle:learnMoveNotLearned", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => this.end(), null, true); }, () => { this.scene.ui.setMode(messageMode); this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); @@ -4685,7 +4673,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { } this.scene.ui.setMode(messageMode).then(() => { this.scene.ui.showText(i18next.t("battle:countdownPoof"), null, () => { - this.scene.ui.showText(i18next.t("battle:learnMoveForgetSuccess", { pokemonName: pokemon.name, moveName: pokemon.moveset[moveIndex].getName() }), null, () => { + this.scene.ui.showText(i18next.t("battle:learnMoveForgetSuccess", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: pokemon.moveset[moveIndex].getName() }), null, () => { this.scene.ui.showText(i18next.t("battle:learnMoveAnd"), null, () => { pokemon.setMove(moveIndex, Moves.NONE); this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); @@ -4727,7 +4715,7 @@ export class PokemonHealPhase extends CommonAnimPhase { } start() { - if (!this.skipAnim && (this.revive || this.getPokemon().hp) && this.getPokemon().getHpRatio() < 1) { + if (!this.skipAnim && (this.revive || this.getPokemon().hp) && !this.getPokemon().isFullHp()) { super.start(); } else { this.end(); @@ -4742,10 +4730,8 @@ export class PokemonHealPhase extends CommonAnimPhase { return; } - const fullHp = pokemon.getHpRatio() >= 1; - const hasMessage = !!this.message; - const healOrDamage = (!fullHp || this.hpHealed < 0); + const healOrDamage = (!pokemon.isFullHp() || this.hpHealed < 0); let lastStatusEffect = StatusEffect.NONE; if (healOrDamage) { @@ -4923,7 +4909,10 @@ export class AttemptCapturePhase extends PokemonPhase { }); } }, - onComplete: () => this.catch() + onComplete: () => { + this.scene.gameData.setPokemonCaught(pokemon); + this.catch(); + } }); }; @@ -4964,7 +4953,6 @@ export class AttemptCapturePhase extends PokemonPhase { catch() { const pokemon = this.getPokemon() as EnemyPokemon; - this.scene.unshiftPhase(new VictoryPhase(this.scene, this.battlerIndex)); const speciesForm = !pokemon.fusionSpecies ? pokemon.getSpeciesForm() : pokemon.getFusionSpeciesForm(); @@ -4988,8 +4976,9 @@ export class AttemptCapturePhase extends PokemonPhase { this.scene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs); - this.scene.ui.showText(i18next.t("battle:pokemonCaught", { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t("battle:pokemonCaught", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => { const end = () => { + this.scene.unshiftPhase(new VictoryPhase(this.scene, this.battlerIndex)); this.scene.pokemonInfoContainer.hide(); this.removePb(); this.end(); @@ -5018,12 +5007,19 @@ export class AttemptCapturePhase extends PokemonPhase { } }); }; - Promise.all([pokemon.hideInfo(), this.scene.gameData.setPokemonCaught(pokemon)]).then(() => { + Promise.all([pokemon.hideInfo()]).then(() => { if (this.scene.getParty().length === 6) { const promptRelease = () => { - this.scene.ui.showText(i18next.t("battle:partyFull", { pokemonName: pokemon.name }), null, () => { - this.scene.pokemonInfoContainer.makeRoomForConfirmUi(); + this.scene.ui.showText(i18next.t("battle:partyFull", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => { + this.scene.pokemonInfoContainer.makeRoomForConfirmUi(1, true); this.scene.ui.setMode(Mode.CONFIRM, () => { + const newPokemon = this.scene.addPlayerPokemon(pokemon.species, pokemon.level, pokemon.abilityIndex, pokemon.formIndex, pokemon.gender, pokemon.shiny, pokemon.variant, pokemon.ivs, pokemon.nature, pokemon); + this.scene.ui.setMode(Mode.SUMMARY, newPokemon, 0, SummaryUiMode.DEFAULT, () => { + this.scene.ui.setMode(Mode.MESSAGE).then(() => { + promptRelease(); + }); + }); + }, () => { this.scene.ui.setMode(Mode.PARTY, PartyUiMode.RELEASE, this.fieldIndex, (slotIndex: integer, _option: PartyOption) => { this.scene.ui.setMode(Mode.MESSAGE).then(() => { if (slotIndex < 6) { @@ -5038,7 +5034,7 @@ export class AttemptCapturePhase extends PokemonPhase { removePokemon(); end(); }); - }); + }, "fullParty"); }); }; promptRelease(); @@ -5481,7 +5477,7 @@ export class ScanIvsPhase extends PokemonPhase { const pokemon = this.getPokemon(); - this.scene.ui.showText(i18next.t("battle:ivScannerUseQuestion", { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t("battle:ivScannerUseQuestion", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => { this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.clearText(); diff --git a/src/system/achv.ts b/src/system/achv.ts index 408ed0dde3b7..3ebaec968c49 100644 --- a/src/system/achv.ts +++ b/src/system/achv.ts @@ -305,7 +305,7 @@ export const achvs = { _50_RIBBONS: new RibbonAchv("50_RIBBONS","", 50, "ultra_ribbon", 50).setSecret(true), _75_RIBBONS: new RibbonAchv("75_RIBBONS","", 75, "rogue_ribbon", 75).setSecret(true), _100_RIBBONS: new RibbonAchv("100_RIBBONS","", 100, "master_ribbon", 100).setSecret(true), - TRANSFER_MAX_BATTLE_STAT: new Achv("TRANSFER_MAX_BATTLE_STAT","", "TRANSFER_MAX_BATTLE_STAT.description","stick", 20), + TRANSFER_MAX_BATTLE_STAT: new Achv("TRANSFER_MAX_BATTLE_STAT","", "TRANSFER_MAX_BATTLE_STAT.description","baton", 20), MAX_FRIENDSHIP: new Achv("MAX_FRIENDSHIP", "", "MAX_FRIENDSHIP.description","soothe_bell", 25), MEGA_EVOLVE: new Achv("MEGA_EVOLVE", "", "MEGA_EVOLVE.description","mega_bracelet", 50), GIGANTAMAX: new Achv("GIGANTAMAX", "", "GIGANTAMAX.description","dynamax_band", 50), @@ -325,15 +325,15 @@ export const achvs = { HIDDEN_ABILITY: new Achv("HIDDEN_ABILITY","", "HIDDEN_ABILITY.description","ability_charm", 75), PERFECT_IVS: new Achv("PERFECT_IVS","", "PERFECT_IVS.description","blunder_policy", 100), CLASSIC_VICTORY: new Achv("CLASSIC_VICTORY","", "CLASSIC_VICTORY.description","relic_crown", 150), - MONO_GEN_ONE_VICTORY: new ChallengeAchv("MONO_GEN_ONE","", "MONO_GEN_ONE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 1), - MONO_GEN_TWO_VICTORY: new ChallengeAchv("MONO_GEN_TWO","", "MONO_GEN_TWO.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 2), - MONO_GEN_THREE_VICTORY: new ChallengeAchv("MONO_GEN_THREE","", "MONO_GEN_THREE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 3), - MONO_GEN_FOUR_VICTORY: new ChallengeAchv("MONO_GEN_FOUR","", "MONO_GEN_FOUR.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 4), - MONO_GEN_FIVE_VICTORY: new ChallengeAchv("MONO_GEN_FIVE","", "MONO_GEN_FIVE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 5), - MONO_GEN_SIX_VICTORY: new ChallengeAchv("MONO_GEN_SIX","", "MONO_GEN_SIX.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 6), - MONO_GEN_SEVEN_VICTORY: new ChallengeAchv("MONO_GEN_SEVEN","", "MONO_GEN_SEVEN.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 7), - MONO_GEN_EIGHT_VICTORY: new ChallengeAchv("MONO_GEN_EIGHT","", "MONO_GEN_EIGHT.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 8), - MONO_GEN_NINE_VICTORY: new ChallengeAchv("MONO_GEN_NINE","", "MONO_GEN_NINE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 9), + MONO_GEN_ONE_VICTORY: new ChallengeAchv("MONO_GEN_ONE","", "MONO_GEN_ONE.description", "ribbon_gen1", 100, c => c instanceof SingleGenerationChallenge && c.value === 1), + MONO_GEN_TWO_VICTORY: new ChallengeAchv("MONO_GEN_TWO","", "MONO_GEN_TWO.description", "ribbon_gen2", 100, c => c instanceof SingleGenerationChallenge && c.value === 2), + MONO_GEN_THREE_VICTORY: new ChallengeAchv("MONO_GEN_THREE","", "MONO_GEN_THREE.description", "ribbon_gen3", 100, c => c instanceof SingleGenerationChallenge && c.value === 3), + MONO_GEN_FOUR_VICTORY: new ChallengeAchv("MONO_GEN_FOUR","", "MONO_GEN_FOUR.description", "ribbon_gen4", 100, c => c instanceof SingleGenerationChallenge && c.value === 4), + MONO_GEN_FIVE_VICTORY: new ChallengeAchv("MONO_GEN_FIVE","", "MONO_GEN_FIVE.description", "ribbon_gen5", 100, c => c instanceof SingleGenerationChallenge && c.value === 5), + MONO_GEN_SIX_VICTORY: new ChallengeAchv("MONO_GEN_SIX","", "MONO_GEN_SIX.description", "ribbon_gen6", 100, c => c instanceof SingleGenerationChallenge && c.value === 6), + MONO_GEN_SEVEN_VICTORY: new ChallengeAchv("MONO_GEN_SEVEN","", "MONO_GEN_SEVEN.description", "ribbon_gen7", 100, c => c instanceof SingleGenerationChallenge && c.value === 7), + MONO_GEN_EIGHT_VICTORY: new ChallengeAchv("MONO_GEN_EIGHT","", "MONO_GEN_EIGHT.description", "ribbon_gen8", 100, c => c instanceof SingleGenerationChallenge && c.value === 8), + MONO_GEN_NINE_VICTORY: new ChallengeAchv("MONO_GEN_NINE","", "MONO_GEN_NINE.description", "ribbon_gen9", 100, c => c instanceof SingleGenerationChallenge && c.value === 9), MONO_NORMAL: new ChallengeAchv("MONO_NORMAL","", "MONO_NORMAL.description", "silk_scarf", 100, c => c instanceof SingleTypeChallenge && c.value === 1), MONO_FIGHTING: new ChallengeAchv("MONO_FIGHTING","", "MONO_FIGHTING.description", "black_belt", 100, c => c instanceof SingleTypeChallenge && c.value === 2), MONO_FLYING: new ChallengeAchv("MONO_FLYING","", "MONO_FLYING.description", "sharp_beak", 100, c => c instanceof SingleTypeChallenge && c.value === 3), diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 9559efd0117d..6b8f183e94a7 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -4,7 +4,7 @@ import Pokemon, { EnemyPokemon, PlayerPokemon } from "../field/pokemon"; import { pokemonEvolutions, pokemonPrevolutions } from "../data/pokemon-evolutions"; import PokemonSpecies, { allSpecies, getPokemonSpecies, noStarterFormKeys, speciesStarters } from "../data/pokemon-species"; import * as Utils from "../utils"; -import Overrides from "../overrides"; +import Overrides from "#app/overrides"; import PokemonData from "./pokemon-data"; import PersistentModifierData from "./modifier-data"; import ArenaData from "./arena-data"; diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index 57f4c0aea938..7e8f1e21c07a 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -17,6 +17,7 @@ export default class PokemonData { public id: integer; public player: boolean; public species: Species; + public nickname: string; public formIndex: integer; public abilityIndex: integer; public passive: boolean; @@ -59,6 +60,7 @@ export default class PokemonData { this.id = source.id; this.player = sourcePokemon ? sourcePokemon.isPlayer() : source.player; this.species = sourcePokemon ? sourcePokemon.species.speciesId : source.species; + this.nickname = sourcePokemon ? sourcePokemon.nickname : source.nickname; this.formIndex = Math.max(Math.min(source.formIndex, getPokemonSpecies(this.species).forms.length - 1), 0); this.abilityIndex = source.abilityIndex; this.passive = source.passive; @@ -141,7 +143,11 @@ export default class PokemonData { toPokemon(scene: BattleScene, battleType?: BattleType, partyMemberIndex: integer = 0, double: boolean = false): Pokemon { const species = getPokemonSpecies(this.species); const ret: Pokemon = this.player - ? scene.addPlayerPokemon(species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this) + ? scene.addPlayerPokemon(species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this, (playerPokemon) => { + if (this.nickname) { + playerPokemon.nickname = this.nickname; + } + }) : scene.addEnemyPokemon(species, this.level, battleType === BattleType.TRAINER ? !double || !(partyMemberIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER : TrainerSlot.NONE, this.boss, this); if (this.summonData) { ret.primeSummonData(this.summonData); diff --git a/src/test/abilities/ability_timing.test.ts b/src/test/abilities/ability_timing.test.ts new file mode 100644 index 000000000000..84d4390652e3 --- /dev/null +++ b/src/test/abilities/ability_timing.test.ts @@ -0,0 +1,53 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import Overrides from "#app/overrides"; +import { CommandPhase, MessagePhase, TurnInitPhase } from "#app/phases"; +import { Mode } from "#app/ui/ui"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import i18next, { initI18n } from "#app/plugins/i18n"; + + +describe("Ability Timing", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.PIDGEY); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTIMIDATE); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(Array(4).fill(Moves.SPLASH)); + + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.ICE_BEAM]); + }); + + it("should trigger after switch check", async() => { + initI18n(); + i18next.changeLanguage("en"); + await game.runToSummon([Species.EEVEE, Species.FEEBAS]); + + game.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => { + game.setMode(Mode.MESSAGE); + game.endPhase(); + }, () => game.isCurrentPhase(CommandPhase) || game.isCurrentPhase(TurnInitPhase)); + + await game.phaseInterceptor.to(MessagePhase); + const message = game.textInterceptor.getLatestMessage(); + expect(message).toContain("Attack fell"); + }, 5000); +}); diff --git a/src/test/abilities/aura_break.test.ts b/src/test/abilities/aura_break.test.ts index fa7f34edb2fc..28813b5206f4 100644 --- a/src/test/abilities/aura_break.test.ts +++ b/src/test/abilities/aura_break.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { MoveEffectPhase } from "#app/phases"; import { Moves } from "#enums/moves"; @@ -27,18 +27,18 @@ describe("Abilities - Aura Break", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.MOONBLAST, Moves.DARK_PULSE, Moves.MOONBLAST, Moves.DARK_PULSE]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.AURA_BREAK); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.MOONBLAST, Moves.DARK_PULSE, Moves.MOONBLAST, Moves.DARK_PULSE]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.AURA_BREAK); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); }); it("reverses the effect of fairy aura", async () => { const moveToCheck = allMoves[Moves.MOONBLAST]; const basePower = moveToCheck.power; - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.FAIRY_AURA); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.FAIRY_AURA); vi.spyOn(moveToCheck, "calculateBattlePower"); await game.startBattle([Species.PIKACHU]); @@ -52,7 +52,7 @@ describe("Abilities - Aura Break", () => { const moveToCheck = allMoves[Moves.DARK_PULSE]; const basePower = moveToCheck.power; - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.DARK_AURA); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.DARK_AURA); vi.spyOn(moveToCheck, "calculateBattlePower"); await game.startBattle([Species.PIKACHU]); diff --git a/src/test/abilities/battery.test.ts b/src/test/abilities/battery.test.ts index b600772f3c42..06f388371e9e 100644 --- a/src/test/abilities/battery.test.ts +++ b/src/test/abilities/battery.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { Moves } from "#enums/moves"; import { getMovePosition } from "#app/test/utils/gameManagerUtils"; @@ -27,11 +27,11 @@ describe("Abilities - Battery", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.BREAKING_SWIPE, Moves.SPLASH, Moves.DAZZLING_GLEAM]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.BREAKING_SWIPE, Moves.SPLASH, Moves.DAZZLING_GLEAM]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); }); it("raises the power of allies' special moves by 30%", async () => { diff --git a/src/test/abilities/battle_bond.test.ts b/src/test/abilities/battle_bond.test.ts index a72c1a0fa67a..1ebefb99f323 100644 --- a/src/test/abilities/battle_bond.test.ts +++ b/src/test/abilities/battle_bond.test.ts @@ -28,7 +28,7 @@ describe("Abilities - BATTLE BOND", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.SPLASH; - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BATTLE_BOND); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); diff --git a/src/test/abilities/costar.test.ts b/src/test/abilities/costar.test.ts index f677d55e1831..f26c4f70758f 100644 --- a/src/test/abilities/costar.test.ts +++ b/src/test/abilities/costar.test.ts @@ -27,7 +27,7 @@ describe("Abilities - COSTAR", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(Overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.COSTAR); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NASTY_PLOT]); vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); diff --git a/src/test/abilities/disguise.test.ts b/src/test/abilities/disguise.test.ts index 41650cbd280e..0a542780ebc2 100644 --- a/src/test/abilities/disguise.test.ts +++ b/src/test/abilities/disguise.test.ts @@ -28,7 +28,7 @@ describe("Abilities - DISGUISE", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.SPLASH; - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.DISGUISE); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); diff --git a/src/test/abilities/dry_skin.test.ts b/src/test/abilities/dry_skin.test.ts index 96fcb27f5450..3d97c4148620 100644 --- a/src/test/abilities/dry_skin.test.ts +++ b/src/test/abilities/dry_skin.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { TurnEndPhase } from "#app/phases"; import { Moves } from "#enums/moves"; import { getMovePosition } from "#app/test/utils/gameManagerUtils"; @@ -24,17 +24,17 @@ describe("Abilities - Dry Skin", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.DRY_SKIN); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.CHARMANDER); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.UNNERVE); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.CHANDELURE); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.DRY_SKIN); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.CHARMANDER); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.UNNERVE); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.CHANDELURE); }); it("during sunlight, lose 1/8 of maximum health at the end of each turn", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SUNNY_DAY, Moves.SPLASH]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SUNNY_DAY, Moves.SPLASH]); await game.startBattle(); @@ -55,7 +55,7 @@ describe("Abilities - Dry Skin", () => { }); it("during rain, gain 1/8 of maximum health at the end of each turn", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.RAIN_DANCE, Moves.SPLASH]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.RAIN_DANCE, Moves.SPLASH]); await game.startBattle(); @@ -78,7 +78,7 @@ describe("Abilities - Dry Skin", () => { }); it("opposing fire attacks do 25% more damage", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.FLAMETHROWER]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.FLAMETHROWER]); await game.startBattle(); @@ -94,7 +94,7 @@ describe("Abilities - Dry Skin", () => { expect(enemy.hp > 0); enemy.hp = initialHP; - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); // second turn game.doAttack(getMovePosition(game.scene, 0, Moves.FLAMETHROWER)); @@ -105,7 +105,7 @@ describe("Abilities - Dry Skin", () => { }); it("opposing water attacks heal 1/4 of maximum health and deal no damage", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.WATER_GUN]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.WATER_GUN]); await game.startBattle(); @@ -120,7 +120,7 @@ describe("Abilities - Dry Skin", () => { }); it("opposing water attacks do not heal if they were protected from", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.WATER_GUN]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.WATER_GUN]); await game.startBattle(); @@ -128,7 +128,7 @@ describe("Abilities - Dry Skin", () => { expect(enemy).not.toBe(undefined); enemy.hp = 1; - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT]); game.doAttack(getMovePosition(game.scene, 0, Moves.WATER_GUN)); await game.phaseInterceptor.to(TurnEndPhase); @@ -136,7 +136,7 @@ describe("Abilities - Dry Skin", () => { }); it("multi-strike water attacks only heal once", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.WATER_GUN, Moves.WATER_SHURIKEN]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.WATER_GUN, Moves.WATER_SHURIKEN]); await game.startBattle(); diff --git a/src/test/abilities/hustle.test.ts b/src/test/abilities/hustle.test.ts new file mode 100644 index 000000000000..9e6012a11a43 --- /dev/null +++ b/src/test/abilities/hustle.test.ts @@ -0,0 +1,99 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import overrides from "#app/overrides"; +import { Species } from "#enums/species"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; +import { DamagePhase, MoveEffectPhase } from "#app/phases.js"; +import { Abilities } from "#app/enums/abilities.js"; +import { Stat } from "#app/enums/stat.js"; +import { allMoves } from "#app/data/move.js"; + +describe("Abilities - Hustle", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HUSTLE); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.GIGA_DRAIN, Moves.FISSURE]); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + }); + + it("increases the user's Attack stat by 50%", async () => { + await game.startBattle([Species.PIKACHU]); + const pikachu = game.scene.getPlayerPokemon(); + const atk = pikachu.stats[Stat.ATK]; + + vi.spyOn(pikachu, "getBattleStat"); + + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); + await game.phaseInterceptor.to(MoveEffectPhase, false); + vi.spyOn(game.scene.getCurrentPhase() as MoveEffectPhase, "hitCheck").mockReturnValue(true); + await game.phaseInterceptor.to(DamagePhase); + + expect(pikachu.getBattleStat).toHaveReturnedWith(atk * 1.5); + }); + + it("lowers the accuracy of the user's physical moves by 20%", async () => { + await game.startBattle([Species.PIKACHU]); + const pikachu = game.scene.getPlayerPokemon(); + + vi.spyOn(pikachu, "getAccuracyMultiplier"); + + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); + await game.phaseInterceptor.to(MoveEffectPhase); + + expect(pikachu.getAccuracyMultiplier).toHaveReturnedWith(0.8); + }); + + it("does not affect non-physical moves", async () => { + await game.startBattle([Species.PIKACHU]); + const pikachu = game.scene.getPlayerPokemon(); + const spatk = pikachu.stats[Stat.SPATK]; + + vi.spyOn(pikachu, "getBattleStat"); + vi.spyOn(pikachu, "getAccuracyMultiplier"); + + game.doAttack(getMovePosition(game.scene, 0, Moves.GIGA_DRAIN)); + await game.phaseInterceptor.to(DamagePhase); + + expect(pikachu.getBattleStat).toHaveReturnedWith(spatk); + expect(pikachu.getAccuracyMultiplier).toHaveReturnedWith(1); + }); + + // Skip until OHKO moves are fixed - it should not be affected by accuracy and evasion stats + it("does not affect OHKO moves", async () => { + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(30); + + await game.startBattle([Species.PIKACHU]); + const pikachu = game.scene.getPlayerPokemon(); + + vi.spyOn(pikachu, "getAccuracyMultiplier"); + vi.spyOn(allMoves[Moves.FISSURE], "calculateBattleAccuracy"); + + game.doAttack(getMovePosition(game.scene, 0, Moves.FISSURE)); + await game.phaseInterceptor.to(DamagePhase); + + expect(game.scene.getEnemyPokemon().turnData.damageTaken).toBe(game.scene.getEnemyPokemon().hp); + expect(pikachu.getAccuracyMultiplier).toHaveReturnedWith(1); + expect(allMoves[Moves.FISSURE].calculateBattleAccuracy).toHaveReturnedWith(100); + }, { skip: true }); +}); diff --git a/src/test/abilities/ice_face.test.ts b/src/test/abilities/ice_face.test.ts index 74972eabb659..1b00ef748ebc 100644 --- a/src/test/abilities/ice_face.test.ts +++ b/src/test/abilities/ice_face.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { MoveEffectPhase, @@ -33,10 +33,10 @@ describe("Abilities - Ice Face", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.EISCUE); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ICE_FACE); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.ICE_BEAM, Moves.TOXIC_THREAD, Moves.HAIL]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.EISCUE); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ICE_FACE); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.ICE_BEAM, Moves.TOXIC_THREAD, Moves.HAIL]); }); it("takes no damage from physical move and transforms to Noice", async () => { @@ -48,14 +48,14 @@ describe("Abilities - Ice Face", () => { const eiscue = game.scene.getEnemyPokemon(); - expect(eiscue.hp).equals(eiscue.getMaxHp()); + expect(eiscue.isFullHp()).toBe(true); expect(eiscue.formIndex).toBe(noiceForm); expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBe(undefined); }); it("takes no damage from the first hit of multihit physical move and transforms to Noice", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SURGING_STRIKES]); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(1); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SURGING_STRIKES]); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(1); await game.startBattle([Species.HITMONLEE]); game.doAttack(getMovePosition(game.scene, 0, Moves.SURGING_STRIKES)); @@ -65,7 +65,7 @@ describe("Abilities - Ice Face", () => { // First hit await game.phaseInterceptor.to(MoveEffectPhase); - expect(eiscue.hp).equals(eiscue.getMaxHp()); + expect(eiscue.isFullHp()).toBe(true); expect(eiscue.formIndex).toBe(icefaceForm); expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeUndefined(); @@ -109,8 +109,8 @@ describe("Abilities - Ice Face", () => { }); it("transforms to Ice Face when Hail or Snow starts", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.QUICK_ATTACK]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.HAIL, Moves.HAIL, Moves.HAIL, Moves.HAIL]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.QUICK_ATTACK]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.HAIL, Moves.HAIL, Moves.HAIL, Moves.HAIL]); await game.startBattle([Species.MAGIKARP]); @@ -120,7 +120,7 @@ describe("Abilities - Ice Face", () => { const eiscue = game.scene.getEnemyPokemon(); - expect(eiscue.hp).equals(eiscue.getMaxHp()); + expect(eiscue.isFullHp()).toBe(true); expect(eiscue.formIndex).toBe(noiceForm); expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBe(undefined); @@ -131,8 +131,8 @@ describe("Abilities - Ice Face", () => { }); it("transforms to Ice Face when summoned on arena with active Snow or Hail", async () => { - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SNOWSCAPE]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SNOWSCAPE]); await game.startBattle([Species.EISCUE, Species.NINJASK]); @@ -143,7 +143,7 @@ describe("Abilities - Ice Face", () => { expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBe(undefined); expect(eiscue.formIndex).toBe(noiceForm); - expect(eiscue.hp).equals(eiscue.getMaxHp()); + expect(eiscue.isFullHp()).toBe(true); await game.toNextTurn(); game.doSwitchPokemon(1); @@ -158,8 +158,8 @@ describe("Abilities - Ice Face", () => { }); it("will not revert to its Ice Face if there is already Hail when it changes into Noice", async () => { - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); await game.startBattle([Species.EISCUE]); @@ -178,7 +178,7 @@ describe("Abilities - Ice Face", () => { }); it("persists form change when switched out", async () => { - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK]); await game.startBattle([Species.EISCUE, Species.MAGIKARP]); @@ -189,7 +189,7 @@ describe("Abilities - Ice Face", () => { expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBe(undefined); expect(eiscue.formIndex).toBe(noiceForm); - expect(eiscue.hp).equals(eiscue.getMaxHp()); + expect(eiscue.isFullHp()).toBe(true); await game.toNextTurn(); game.doSwitchPokemon(1); @@ -202,10 +202,10 @@ describe("Abilities - Ice Face", () => { }); it("reverts to Ice Face on arena reset", async () => { - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(4); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(4); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue({ + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(4); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(4); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue({ [Species.EISCUE]: noiceForm, }); @@ -227,7 +227,7 @@ describe("Abilities - Ice Face", () => { }); it("cannot be suppressed", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.GASTRO_ACID]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.GASTRO_ACID]); await game.startBattle([Species.MAGIKARP]); @@ -243,7 +243,7 @@ describe("Abilities - Ice Face", () => { }); it("cannot be swapped with another ability", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SKILL_SWAP]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SKILL_SWAP]); await game.startBattle([Species.MAGIKARP]); @@ -259,7 +259,7 @@ describe("Abilities - Ice Face", () => { }); it("cannot be copied", async () => { - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.TRACE); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.TRACE); await game.startBattle([Species.MAGIKARP]); diff --git a/src/test/abilities/intimidate.test.ts b/src/test/abilities/intimidate.test.ts index 2dbad6620980..bedb78258ec7 100644 --- a/src/test/abilities/intimidate.test.ts +++ b/src/test/abilities/intimidate.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, DamagePhase, EncounterPhase, EnemyCommandPhase, SelectStarterPhase, @@ -34,13 +34,13 @@ describe("Abilities - Intimidate", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTIMIDATE); - vi.spyOn(overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTIMIDATE); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTIMIDATE); + vi.spyOn(Overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTIMIDATE); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); }); it("single - wild with switch", async() => { @@ -71,7 +71,7 @@ describe("Abilities - Intimidate", () => { }, 20000); it("single - boss should only trigger once then switch", async() => { - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10); await game.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA, @@ -98,7 +98,7 @@ describe("Abilities - Intimidate", () => { }, 20000); it("single - trainer should only trigger once with switch", async() => { - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); await game.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA, @@ -125,9 +125,8 @@ describe("Abilities - Intimidate", () => { }, 200000); it("double - trainer should only trigger once per pokemon", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); await game.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA, @@ -150,9 +149,8 @@ describe("Abilities - Intimidate", () => { }, 20000); it("double - wild: should only trigger once per pokemon", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); await game.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA, @@ -175,9 +173,8 @@ describe("Abilities - Intimidate", () => { }, 20000); it("double - boss: should only trigger once per pokemon", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10); await game.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA, @@ -200,8 +197,8 @@ describe("Abilities - Intimidate", () => { }, 20000); it("single - wild next wave opp triger once, us: none", async() => { - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(2); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.AERIAL_ACE]); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(2); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.AERIAL_ACE]); await game.startBattle([ Species.MIGHTYENA, Species.POOCHYENA, @@ -229,8 +226,8 @@ describe("Abilities - Intimidate", () => { }, 20000); it("single - wild next turn - no retrigger on next turn", async() => { - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(2); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(2); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]); await game.startBattle([ Species.MIGHTYENA, Species.POOCHYENA, @@ -256,9 +253,9 @@ describe("Abilities - Intimidate", () => { }, 20000); it("single - trainer should only trigger once and each time he switch", async() => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.VOLT_SWITCH,Moves.VOLT_SWITCH,Moves.VOLT_SWITCH,Moves.VOLT_SWITCH]); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.VOLT_SWITCH,Moves.VOLT_SWITCH,Moves.VOLT_SWITCH,Moves.VOLT_SWITCH]); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); await game.startBattle([ Species.MIGHTYENA, Species.POOCHYENA, @@ -299,9 +296,9 @@ describe("Abilities - Intimidate", () => { }, 200000); it("single - trainer should only trigger once whatever turn we are", async() => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); await game.startBattle([ Species.MIGHTYENA, Species.POOCHYENA, @@ -342,9 +339,8 @@ describe("Abilities - Intimidate", () => { }, 20000); it("double - wild vs only 1 on player side", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); await game.runToSummon([ Species.MIGHTYENA, ]); @@ -359,9 +355,8 @@ describe("Abilities - Intimidate", () => { }, 20000); it("double - wild vs only 1 alive on player side", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); await game.runToTitle(); game.onNextPrompt("TitlePhase", Mode.TITLE, () => { diff --git a/src/test/abilities/intrepid_sword.test.ts b/src/test/abilities/intrepid_sword.test.ts index 0845a8beb22a..1fae65556887 100644 --- a/src/test/abilities/intrepid_sword.test.ts +++ b/src/test/abilities/intrepid_sword.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import {Abilities} from "#enums/abilities"; import {Species} from "#enums/species"; import { @@ -26,10 +26,10 @@ describe("Abilities - Intrepid Sword", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ZACIAN); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTREPID_SWORD); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTREPID_SWORD); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ZACIAN); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTREPID_SWORD); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INTREPID_SWORD); }); it("INTREPID SWORD on player", async() => { diff --git a/src/test/abilities/libero.test.ts b/src/test/abilities/libero.test.ts index ef5348dab886..015e6a44e24b 100644 --- a/src/test/abilities/libero.test.ts +++ b/src/test/abilities/libero.test.ts @@ -32,7 +32,7 @@ describe("Abilities - Protean", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.LIBERO); vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); @@ -197,7 +197,7 @@ describe("Abilities - Protean", () => { await game.phaseInterceptor.to(TurnEndPhase); const enemyPokemon = game.scene.getEnemyPokemon(); - expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); + expect(enemyPokemon.isFullHp()).toBe(true); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); }, TIMEOUT, diff --git a/src/test/abilities/moxie.test.ts b/src/test/abilities/moxie.test.ts index 6da5561ac1f8..f7b7fe220274 100644 --- a/src/test/abilities/moxie.test.ts +++ b/src/test/abilities/moxie.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, EnemyCommandPhase, @@ -34,13 +34,13 @@ describe("Abilities - Moxie", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.AERIAL_ACE; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOXIE); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOXIE); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOXIE); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOXIE); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); it("MOXIE", async() => { diff --git a/src/test/abilities/parental_bond.test.ts b/src/test/abilities/parental_bond.test.ts index 1b0362e8120b..f29eafc72f69 100644 --- a/src/test/abilities/parental_bond.test.ts +++ b/src/test/abilities/parental_bond.test.ts @@ -30,7 +30,7 @@ describe("Abilities - Parental Bond", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.PARENTAL_BOND); vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); @@ -238,8 +238,7 @@ describe("Abilities - Parental Bond", () => { test( "ability should not apply to multi-target moves", async () => { - vi.spyOn(Overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.EARTHQUAKE]); await game.startBattle([Species.CHARIZARD, Species.PIDGEOT]); @@ -613,8 +612,7 @@ describe("Abilities - Parental Bond", () => { test( "ability should not apply to multi-target moves with Multi-Lens", async () => { - vi.spyOn(Overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.EARTHQUAKE, Moves.SPLASH]); vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "MULTI_LENS", count: 1}]); diff --git a/src/test/abilities/power_construct.test.ts b/src/test/abilities/power_construct.test.ts index c9d0e4ba755e..48c92c0e2d18 100644 --- a/src/test/abilities/power_construct.test.ts +++ b/src/test/abilities/power_construct.test.ts @@ -28,7 +28,7 @@ describe("Abilities - POWER CONSTRUCT", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.SPLASH; - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.POWER_CONSTRUCT); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); diff --git a/src/test/abilities/power_spot.test.ts b/src/test/abilities/power_spot.test.ts index 577c9f87ec57..1947cfc9c4f3 100644 --- a/src/test/abilities/power_spot.test.ts +++ b/src/test/abilities/power_spot.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { Moves } from "#enums/moves"; import { getMovePosition } from "#app/test/utils/gameManagerUtils"; @@ -27,11 +27,11 @@ describe("Abilities - Power Spot", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.BREAKING_SWIPE, Moves.SPLASH, Moves.DAZZLING_GLEAM]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.BREAKING_SWIPE, Moves.SPLASH, Moves.DAZZLING_GLEAM]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); }); it("raises the power of allies' special moves by 30%", async () => { diff --git a/src/test/abilities/protean.test.ts b/src/test/abilities/protean.test.ts index 4d8faae1cd36..6255a2bc2b28 100644 --- a/src/test/abilities/protean.test.ts +++ b/src/test/abilities/protean.test.ts @@ -32,7 +32,7 @@ describe("Abilities - Protean", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.PROTEAN); vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); @@ -197,7 +197,7 @@ describe("Abilities - Protean", () => { await game.phaseInterceptor.to(TurnEndPhase); const enemyPokemon = game.scene.getEnemyPokemon(); - expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); + expect(enemyPokemon.isFullHp()).toBe(true); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); }, TIMEOUT, diff --git a/src/test/abilities/quick_draw.test.ts b/src/test/abilities/quick_draw.test.ts index 71b889132576..9e6a39b86c90 100644 --- a/src/test/abilities/quick_draw.test.ts +++ b/src/test/abilities/quick_draw.test.ts @@ -25,18 +25,22 @@ describe("Abilities - Quick Draw", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.QUICK_DRAW); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TAIL_WHIP]); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(Array(4).fill(Moves.TACKLE)); vi.spyOn(allAbilities[Abilities.QUICK_DRAW].getAttrs(BypassSpeedChanceAbAttr)[0], "chance", "get").mockReturnValue(100); }); test("makes pokemon going first in its priority bracket", async () => { - await game.startBattle([Species.SLOWBRO]); + await game.startBattle(); const pokemon = game.scene.getPlayerPokemon(); const enemy = game.scene.getEnemyPokemon(); @@ -56,7 +60,7 @@ describe("Abilities - Quick Draw", () => { timeout: 20000, retry: 5 }, async () => { - await game.startBattle([Species.SLOWBRO]); + await game.startBattle(); const pokemon = game.scene.getPlayerPokemon(); const enemy = game.scene.getEnemyPokemon(); @@ -76,7 +80,7 @@ describe("Abilities - Quick Draw", () => { test("does not increase priority", async () => { vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(Array(4).fill(Moves.EXTREME_SPEED)); - await game.startBattle([Species.SLOWBRO]); + await game.startBattle(); const pokemon = game.scene.getPlayerPokemon(); const enemy = game.scene.getEnemyPokemon(); diff --git a/src/test/abilities/sand_veil.test.ts b/src/test/abilities/sand_veil.test.ts index 615c778ed3fa..ea75027101ac 100644 --- a/src/test/abilities/sand_veil.test.ts +++ b/src/test/abilities/sand_veil.test.ts @@ -29,7 +29,7 @@ describe("Abilities - Sand Veil", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(Overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]); vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEOWSCARADA); vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); @@ -76,7 +76,7 @@ describe("Abilities - Sand Veil", () => { await game.phaseInterceptor.to(MoveEndPhase, false); - expect(leadPokemon[0].hp).toBe(leadPokemon[0].getMaxHp()); + expect(leadPokemon[0].isFullHp()).toBe(true); expect(leadPokemon[1].hp).toBeLessThan(leadPokemon[1].getMaxHp()); }, TIMEOUT ); diff --git a/src/test/abilities/sap_sipper.test.ts b/src/test/abilities/sap_sipper.test.ts index 87a07eeff66e..9fa2001a6ad1 100644 --- a/src/test/abilities/sap_sipper.test.ts +++ b/src/test/abilities/sap_sipper.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { MoveEndPhase, TurnEndPhase, } from "#app/phases"; @@ -30,18 +30,18 @@ describe("Abilities - Sap Sipper", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); }); it("raise attack 1 level and block effects when activated against a grass attack", async() => { const moveToUse = Moves.LEAFAGE; const enemyAbility = Abilities.SAP_SIPPER; - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.DUSKULL); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(enemyAbility); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.DUSKULL); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(enemyAbility); await game.startBattle(); @@ -59,10 +59,10 @@ describe("Abilities - Sap Sipper", () => { const moveToUse = Moves.SPORE; const enemyAbility = Abilities.SAP_SIPPER; - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(enemyAbility); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(enemyAbility); await game.startBattle(); @@ -78,10 +78,10 @@ describe("Abilities - Sap Sipper", () => { const moveToUse = Moves.GRASSY_TERRAIN; const enemyAbility = Abilities.SAP_SIPPER; - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(enemyAbility); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(enemyAbility); await game.startBattle(); @@ -98,10 +98,10 @@ describe("Abilities - Sap Sipper", () => { const moveToUse = Moves.BULLET_SEED; const enemyAbility = Abilities.SAP_SIPPER; - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(enemyAbility); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(enemyAbility); await game.startBattle(); @@ -119,11 +119,11 @@ describe("Abilities - Sap Sipper", () => { const moveToUse = Moves.SPIKY_SHIELD; const ability = Abilities.SAP_SIPPER; - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(ability); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(ability); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); await game.startBattle(); @@ -145,10 +145,10 @@ describe("Abilities - Sap Sipper", () => { const moveToUse = Moves.METRONOME; const enemyAbility = Abilities.SAP_SIPPER; - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(enemyAbility); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(enemyAbility); await game.startBattle(); diff --git a/src/test/abilities/schooling.test.ts b/src/test/abilities/schooling.test.ts index 41829e5753c1..aac8a3e793f8 100644 --- a/src/test/abilities/schooling.test.ts +++ b/src/test/abilities/schooling.test.ts @@ -28,7 +28,7 @@ describe("Abilities - SCHOOLING", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.SPLASH; - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SCHOOLING); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); diff --git a/src/test/abilities/screen_cleaner.test.ts b/src/test/abilities/screen_cleaner.test.ts index 6eb9de07dff7..28253f9aaf63 100644 --- a/src/test/abilities/screen_cleaner.test.ts +++ b/src/test/abilities/screen_cleaner.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { PostSummonPhase, TurnEndPhase, } from "#app/phases"; import { Moves } from "#enums/moves"; @@ -25,14 +25,14 @@ describe("Abilities - Screen Cleaner", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SCREEN_CLEANER); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SCREEN_CLEANER); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); }); it("removes Aurora Veil", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.HAIL]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.HAIL]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL]); await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); @@ -49,7 +49,7 @@ describe("Abilities - Screen Cleaner", () => { }); it("removes Light Screen", async () => { - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN]); await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); @@ -66,7 +66,7 @@ describe("Abilities - Screen Cleaner", () => { }); it("removes Reflect", async () => { - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.REFLECT, Moves.REFLECT, Moves.REFLECT, Moves.REFLECT]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.REFLECT, Moves.REFLECT, Moves.REFLECT, Moves.REFLECT]); await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); diff --git a/src/test/abilities/serene_grace.test.ts b/src/test/abilities/serene_grace.test.ts index 2229794f16f3..6530c3ebe151 100644 --- a/src/test/abilities/serene_grace.test.ts +++ b/src/test/abilities/serene_grace.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import {Abilities} from "#enums/abilities"; import {applyAbAttrs ,MoveEffectChanceMultiplierAbAttr} from "#app/data/ability"; import {Species} from "#enums/species"; @@ -34,11 +34,11 @@ describe("Abilities - Serene Grace", () => { beforeEach(() => { game = new GameManager(phaserGame); const movesToUse = [Moves.AIR_SLASH, Moves.TACKLE]; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ONIX); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(movesToUse); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ONIX); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(movesToUse); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); it("Move chance without Serene Grace", async() => { @@ -76,7 +76,7 @@ describe("Abilities - Serene Grace", () => { it("Move chance with Serene Grace", async() => { const moveToUse = Moves.AIR_SLASH; - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SERENE_GRACE); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SERENE_GRACE); await game.startBattle([ Species.TOGEKISS ]); diff --git a/src/test/abilities/sheer_force.test.ts b/src/test/abilities/sheer_force.test.ts index b94ac33ea36a..46bd92f0d56e 100644 --- a/src/test/abilities/sheer_force.test.ts +++ b/src/test/abilities/sheer_force.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import {Abilities} from "#enums/abilities"; import {applyAbAttrs ,applyPreAttackAbAttrs,applyPostDefendAbAttrs, MoveEffectChanceMultiplierAbAttr, MovePowerBoostAbAttr, PostDefendTypeChangeAbAttr} from "#app/data/ability"; import {Species} from "#enums/species"; @@ -34,16 +34,16 @@ describe("Abilities - Sheer Force", () => { beforeEach(() => { game = new GameManager(phaserGame); const movesToUse = [Moves.AIR_SLASH, Moves.BIND, Moves.CRUSH_CLAW, Moves.TACKLE]; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ONIX); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(movesToUse); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ONIX); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(movesToUse); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); it("Sheer Force", async() => { const moveToUse = Moves.AIR_SLASH; - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); await game.startBattle([ Species.PIDGEOT ]); @@ -82,7 +82,7 @@ describe("Abilities - Sheer Force", () => { it("Sheer Force with exceptions including binding moves", async() => { const moveToUse = Moves.BIND; - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); await game.startBattle([ Species.PIDGEOT ]); @@ -121,7 +121,7 @@ describe("Abilities - Sheer Force", () => { it("Sheer Force with moves with no secondary effect", async() => { const moveToUse = Moves.TACKLE; - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); await game.startBattle([ Species.PIDGEOT ]); @@ -160,9 +160,9 @@ describe("Abilities - Sheer Force", () => { it("Sheer Force Disabling Specific Abilities", async() => { const moveToUse = Moves.CRUSH_CLAW; - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.COLOR_CHANGE); - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "KINGS_ROCK", count: 1}]); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.COLOR_CHANGE); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "KINGS_ROCK", count: 1}]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); await game.startBattle([ Species.PIDGEOT ]); diff --git a/src/test/abilities/shield_dust.test.ts b/src/test/abilities/shield_dust.test.ts index f6014c02fb05..472ba90caf9c 100644 --- a/src/test/abilities/shield_dust.test.ts +++ b/src/test/abilities/shield_dust.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Abilities } from "#enums/abilities"; import {applyAbAttrs ,applyPreDefendAbAttrs,IgnoreMoveEffectsAbAttr,MoveEffectChanceMultiplierAbAttr} from "#app/data/ability"; import {Species} from "#enums/species"; @@ -34,12 +34,12 @@ describe("Abilities - Shield Dust", () => { beforeEach(() => { game = new GameManager(phaserGame); const movesToUse = [Moves.AIR_SLASH]; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ONIX); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHIELD_DUST); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(movesToUse); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ONIX); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHIELD_DUST); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(movesToUse); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); it("Shield Dust", async() => { diff --git a/src/test/abilities/shields_down.test.ts b/src/test/abilities/shields_down.test.ts index b25a5cd7a40c..881a3f4911ff 100644 --- a/src/test/abilities/shields_down.test.ts +++ b/src/test/abilities/shields_down.test.ts @@ -28,7 +28,7 @@ describe("Abilities - SHIELDS DOWN", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.SPLASH; - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHIELDS_DOWN); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); diff --git a/src/test/abilities/steely_spirit.test.ts b/src/test/abilities/steely_spirit.test.ts index 403024c7277f..3e9993a7465c 100644 --- a/src/test/abilities/steely_spirit.test.ts +++ b/src/test/abilities/steely_spirit.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { Moves } from "#enums/moves"; import { getMovePosition } from "#app/test/utils/gameManagerUtils"; @@ -29,11 +29,11 @@ describe("Abilities - Steely Spirit", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.IRON_HEAD, Moves.SPLASH]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.IRON_HEAD, Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); vi.spyOn(allMoves[moveToCheck], "calculateBattlePower"); }); diff --git a/src/test/abilities/sturdy.test.ts b/src/test/abilities/sturdy.test.ts index f97cda3e08c5..0cfa45ef843d 100644 --- a/src/test/abilities/sturdy.test.ts +++ b/src/test/abilities/sturdy.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { DamagePhase, MoveEndPhase, @@ -30,15 +30,15 @@ describe("Abilities - Sturdy", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.LUCARIO); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.CLOSE_COMBAT, Moves.FISSURE]); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.LUCARIO); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.CLOSE_COMBAT, Moves.FISSURE]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ARON); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(5); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.STURDY); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ARON); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.STURDY); }); test( @@ -77,7 +77,7 @@ describe("Abilities - Sturdy", () => { await game.phaseInterceptor.to(MoveEndPhase); const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; - expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); + expect(enemyPokemon.isFullHp()).toBe(true); }, TIMEOUT ); @@ -85,7 +85,7 @@ describe("Abilities - Sturdy", () => { test( "Sturdy is ignored by pokemon with `Abilities.MOLD_BREAKER`", async () => { - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOLD_BREAKER); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOLD_BREAKER); await game.startBattle(); game.doAttack(getMovePosition(game.scene, 0, Moves.CLOSE_COMBAT)); diff --git a/src/test/abilities/unseen_fist.test.ts b/src/test/abilities/unseen_fist.test.ts index efea425a6619..e6025cb0a6ac 100644 --- a/src/test/abilities/unseen_fist.test.ts +++ b/src/test/abilities/unseen_fist.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Unseen Fist", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.URSHIFU); vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT]); diff --git a/src/test/abilities/volt_absorb.test.ts b/src/test/abilities/volt_absorb.test.ts index 3e199495fb63..e8c47e1420e9 100644 --- a/src/test/abilities/volt_absorb.test.ts +++ b/src/test/abilities/volt_absorb.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { TurnEndPhase, } from "#app/phases"; @@ -29,19 +29,19 @@ describe("Abilities - Volt Absorb", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); }); it("does not activate when CHARGE is used", async () => { const moveToUse = Moves.CHARGE; const ability = Abilities.VOLT_ABSORB; - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(ability); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.DUSKULL); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(ability); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.DUSKULL); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); await game.startBattle(); diff --git a/src/test/abilities/wind_power.test.ts b/src/test/abilities/wind_power.test.ts index 5f54fd8c7544..84869bd54a83 100644 --- a/src/test/abilities/wind_power.test.ts +++ b/src/test/abilities/wind_power.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { TurnEndPhase, @@ -27,11 +27,11 @@ describe("Abilities - Wind Power", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHIFTRY); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_POWER); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHIFTRY); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_POWER); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); }); it("it becomes charged when hit by wind moves", async () => { @@ -47,8 +47,8 @@ describe("Abilities - Wind Power", () => { }); it("it becomes charged when Tailwind takes effect on its side", async () => { - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_POWER); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_POWER); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); await game.startBattle([Species.SHIFTRY]); const shiftry = game.scene.getPlayerPokemon(); @@ -62,8 +62,8 @@ describe("Abilities - Wind Power", () => { }); it("does not become charged when Tailwind takes effect on opposing side", async () => { - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_POWER); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_POWER); await game.startBattle([Species.SHIFTRY]); const magikarp = game.scene.getEnemyPokemon(); @@ -81,7 +81,7 @@ describe("Abilities - Wind Power", () => { }); it("does not interact with Sandstorm", async () => { - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); await game.startBattle([Species.SHIFTRY]); const shiftry = game.scene.getPlayerPokemon(); diff --git a/src/test/abilities/wind_rider.test.ts b/src/test/abilities/wind_rider.test.ts index ffe421e29e78..d578c5a22dc5 100644 --- a/src/test/abilities/wind_rider.test.ts +++ b/src/test/abilities/wind_rider.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { TurnEndPhase, @@ -27,11 +27,11 @@ describe("Abilities - Wind Rider", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHIFTRY); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_RIDER); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHIFTRY); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_RIDER); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); }); it("takes no damage from wind moves and its Attack is increased by one stage when hit by one", async () => { @@ -44,13 +44,13 @@ describe("Abilities - Wind Rider", () => { await game.phaseInterceptor.to(TurnEndPhase); - expect(shiftry.hp).equals(shiftry.getMaxHp()); + expect(shiftry.isFullHp()).toBe(true); expect(shiftry.summonData.battleStats[BattleStat.ATK]).toBe(1); }); it("Attack is increased by one stage when Tailwind is present on its side", async () => { - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_RIDER); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_RIDER); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); await game.startBattle([Species.SHIFTRY]); const shiftry = game.scene.getPlayerPokemon(); @@ -65,8 +65,8 @@ describe("Abilities - Wind Rider", () => { }); it("does not increase Attack when Tailwind is present on opposing side", async () => { - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_RIDER); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WIND_RIDER); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); await game.startBattle([Species.SHIFTRY]); const magikarp = game.scene.getEnemyPokemon(); @@ -84,7 +84,7 @@ describe("Abilities - Wind Rider", () => { }); it("does not increase Attack when Tailwind is present on opposing side", async () => { - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); await game.startBattle([Species.SHIFTRY]); const magikarp = game.scene.getEnemyPokemon(); @@ -102,13 +102,13 @@ describe("Abilities - Wind Rider", () => { }); it("does not interact with Sandstorm", async () => { - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); await game.startBattle([Species.SHIFTRY]); const shiftry = game.scene.getPlayerPokemon(); expect(shiftry.summonData.battleStats[BattleStat.ATK]).toBe(0); - expect(shiftry.hp).equals(shiftry.getMaxHp()); + expect(shiftry.isFullHp()).toBe(true); game.doAttack(getMovePosition(game.scene, 0, Moves.SANDSTORM)); diff --git a/src/test/abilities/wonder_skin.test.ts b/src/test/abilities/wonder_skin.test.ts index 477b03f0450f..cd23b2c359f0 100644 --- a/src/test/abilities/wonder_skin.test.ts +++ b/src/test/abilities/wonder_skin.test.ts @@ -1,16 +1,14 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; -import { TurnEndPhase, } from "#app/phases"; +import { MoveEffectPhase } from "#app/phases"; import { Moves } from "#enums/moves"; import { getMovePosition } from "#app/test/utils/gameManagerUtils"; import { Abilities } from "#enums/abilities"; -import Move, { allMoves } from "#app/data/move.js"; -import { MoveAbilityBypassAbAttr, WonderSkinAbAttr } from "#app/data/ability.js"; -import { NumberHolder } from "#app/utils.js"; -import Pokemon from "#app/field/pokemon.js"; +import { allMoves } from "#app/data/move.js"; +import { allAbilities } from "#app/data/ability.js"; describe("Abilities - Wonder Skin", () => { let phaserGame: Phaser.Game; @@ -28,114 +26,52 @@ describe("Abilities - Wonder Skin", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WONDER_SKIN); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.CHARM]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.CHARM]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WONDER_SKIN); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); }); it("lowers accuracy of status moves to 50%", async () => { - await game.startBattle([Species.MAGIKARP]); + const moveToCheck = allMoves[Moves.CHARM]; - game.doAttack(getMovePosition(game.scene, 0, Moves.CHARM)); - - const mockedAccuracy = getMockedMoveAccuracy(game.scene.getEnemyPokemon(), game.scene.getPlayerPokemon(), allMoves[Moves.CHARM]); - - await game.phaseInterceptor.to(TurnEndPhase); - - expect(mockedAccuracy).not.toBe(undefined); - expect(mockedAccuracy).not.toBe(100); - expect(mockedAccuracy).toBe(50); - }); - - it("does not lower accuracy of non-status moves", async () => { - await game.startBattle([Species.MAGIKARP]); - - game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); - - const mockedAccuracy = getMockedMoveAccuracy(game.scene.getEnemyPokemon(), game.scene.getPlayerPokemon(), allMoves[Moves.TACKLE]); - - await game.phaseInterceptor.to(TurnEndPhase); - - expect(mockedAccuracy).not.toBe(undefined); - expect(mockedAccuracy).toBe(100); - expect(mockedAccuracy).not.toBe(50); - }); - - it("does not affect pokemon with Mold Breaker", async () => { - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOLD_BREAKER); - - await game.startBattle([Species.MAGIKARP]); + vi.spyOn(moveToCheck, "calculateBattleAccuracy"); + await game.startBattle([Species.PIKACHU]); game.doAttack(getMovePosition(game.scene, 0, Moves.CHARM)); + await game.phaseInterceptor.to(MoveEffectPhase); - const mockedAccuracy = getMockedMoveAccuracy(game.scene.getEnemyPokemon(), game.scene.getPlayerPokemon(), allMoves[Moves.CHARM]); - - await game.phaseInterceptor.to(TurnEndPhase); - - expect(mockedAccuracy).not.toBe(undefined); - expect(mockedAccuracy).toBe(100); - expect(mockedAccuracy).not.toBe(50); + expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(50); }); - it("does not affect pokemon with Teravolt", async () => { - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.TERAVOLT); - - await game.startBattle([Species.MAGIKARP]); - - game.doAttack(getMovePosition(game.scene, 0, Moves.CHARM)); + it("does not lower accuracy of non-status moves", async () => { + const moveToCheck = allMoves[Moves.TACKLE]; - const mockedAccuracy = getMockedMoveAccuracy(game.scene.getEnemyPokemon(), game.scene.getPlayerPokemon(), allMoves[Moves.CHARM]); + vi.spyOn(moveToCheck, "calculateBattleAccuracy"); - await game.phaseInterceptor.to(TurnEndPhase); + await game.startBattle([Species.PIKACHU]); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); + await game.phaseInterceptor.to(MoveEffectPhase); - expect(mockedAccuracy).not.toBe(undefined); - expect(mockedAccuracy).toBe(100); - expect(mockedAccuracy).not.toBe(50); + expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(100); }); - it("does not affect pokemon with Turboblaze", async () => { - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.TURBOBLAZE); - - await game.startBattle([Species.MAGIKARP]); + const bypassAbilities = [Abilities.MOLD_BREAKER, Abilities.TERAVOLT, Abilities.TURBOBLAZE]; - game.doAttack(getMovePosition(game.scene, 0, Moves.CHARM)); + bypassAbilities.forEach(ability => { + it(`does not affect pokemon with ${allAbilities[ability].name}`, async () => { + const moveToCheck = allMoves[Moves.CHARM]; - const mockedAccuracy = getMockedMoveAccuracy(game.scene.getEnemyPokemon(), game.scene.getPlayerPokemon(), allMoves[Moves.CHARM]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(ability); + vi.spyOn(moveToCheck, "calculateBattleAccuracy"); - await game.phaseInterceptor.to(TurnEndPhase); + await game.startBattle([Species.PIKACHU]); + game.doAttack(getMovePosition(game.scene, 0, Moves.CHARM)); + await game.phaseInterceptor.to(MoveEffectPhase); - expect(mockedAccuracy).not.toBe(undefined); - expect(mockedAccuracy).toBe(100); - expect(mockedAccuracy).not.toBe(50); + expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(100); + }); }); }); - -/** - * Calculates the mocked accuracy of a move. - * Note this does not consider other accuracy calculations - * except the power multiplier from Wonder Skin. - * Bypassed by MoveAbilityBypassAbAttr {@linkcode MoveAbilityBypassAbAttr} - * - * @param defender - The defending Pokémon. - * @param attacker - The attacking Pokémon. - * @param move - The move being used by the attacker. - * @returns The adjusted accuracy of the move. - */ -const getMockedMoveAccuracy = (defender: Pokemon, attacker: Pokemon, move: Move) => { - const accuracyHolder = new NumberHolder(move.accuracy); - - /** - * Simulate ignoring ability - * @see MoveAbilityBypassAbAttr - */ - if (attacker.hasAbilityWithAttr(MoveAbilityBypassAbAttr)) { - return accuracyHolder.value; - } - - const wonderSkinInstance = new WonderSkinAbAttr(); - - wonderSkinInstance.applyPreDefend(defender, false, attacker, move, { value: false }, [ accuracyHolder ]); - - return accuracyHolder.value; -}; diff --git a/src/test/abilities/zen_mode.test.ts b/src/test/abilities/zen_mode.test.ts index 34d604b4d75f..dae01b7aa894 100644 --- a/src/test/abilities/zen_mode.test.ts +++ b/src/test/abilities/zen_mode.test.ts @@ -43,7 +43,7 @@ describe("Abilities - ZEN MODE", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.SPLASH; - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE); diff --git a/src/test/abilities/zero_to_hero.test.ts b/src/test/abilities/zero_to_hero.test.ts index c9eff87362ea..6e82f151f152 100644 --- a/src/test/abilities/zero_to_hero.test.ts +++ b/src/test/abilities/zero_to_hero.test.ts @@ -28,7 +28,7 @@ describe("Abilities - ZERO TO HERO", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.SPLASH; - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZERO_TO_HERO); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); diff --git a/src/test/achievements/achievement.test.ts b/src/test/achievements/achievement.test.ts index bfcc77337ac6..f5a7416e8092 100644 --- a/src/test/achievements/achievement.test.ts +++ b/src/test/achievements/achievement.test.ts @@ -5,7 +5,7 @@ import { IntegerHolder, NumberHolder } from "#app/utils.js"; import { TurnHeldItemTransferModifier } from "#app/modifier/modifier.js"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; describe("check some Achievement related stuff", () => { it ("should check Achievement creation", () => { @@ -103,14 +103,12 @@ describe("RibbonAchv", () => { }); beforeEach(() => { - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(0); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(0); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(0); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(0); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([]); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([]); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(0); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(0); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(0); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(0); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([]); game = new GameManager(phaserGame); scene = game.scene; }); diff --git a/src/test/arena/arena_gravity.test.ts b/src/test/arena/arena_gravity.test.ts new file mode 100644 index 000000000000..ae944758bc7d --- /dev/null +++ b/src/test/arena/arena_gravity.test.ts @@ -0,0 +1,83 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import Overrides from "#app/overrides"; +import { Species } from "#enums/species"; +import { + MoveEffectPhase, + TurnEndPhase, +} from "#app/phases"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; +import { allMoves } from "#app/data/move.js"; +import { ArenaTagType } from "#app/enums/arena-tag-type.js"; +import { Abilities } from "#app/enums/abilities.js"; + +describe("Arena - Gravity", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.GRAVITY, Moves.FISSURE]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.UNNERVE); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(new Array(4).fill(Moves.SPLASH)); + }); + + it("non-OHKO move accuracy is multiplied by 1.67", async () => { + const moveToCheck = allMoves[Moves.TACKLE]; + + vi.spyOn(moveToCheck, "calculateBattleAccuracy"); + + // Setup Gravity on first turn + await game.startBattle([Species.PIKACHU]); + game.doAttack(getMovePosition(game.scene, 0, Moves.GRAVITY)); + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.arena.getTag(ArenaTagType.GRAVITY)).toBeDefined(); + + // Use non-OHKO move on second turn + await game.toNextTurn(); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); + await game.phaseInterceptor.to(MoveEffectPhase); + + expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(100 * 1.67); + }); + + it("OHKO move accuracy is not affected", async () => { + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(5); + + /** See Fissure {@link https://bulbapedia.bulbagarden.net/wiki/Fissure_(move)} */ + const moveToCheck = allMoves[Moves.FISSURE]; + + vi.spyOn(moveToCheck, "calculateBattleAccuracy"); + + // Setup Gravity on first turn + await game.startBattle([Species.PIKACHU]); + game.doAttack(getMovePosition(game.scene, 0, Moves.GRAVITY)); + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.arena.getTag(ArenaTagType.GRAVITY)).toBeDefined(); + + // Use OHKO move on second turn + await game.toNextTurn(); + game.doAttack(getMovePosition(game.scene, 0, Moves.FISSURE)); + await game.phaseInterceptor.to(MoveEffectPhase); + + expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(30); + }); +}); diff --git a/src/test/arena/weather_fog.test.ts b/src/test/arena/weather_fog.test.ts new file mode 100644 index 000000000000..85a9e334c451 --- /dev/null +++ b/src/test/arena/weather_fog.test.ts @@ -0,0 +1,51 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import Overrides from "#app/overrides"; +import { Species } from "#enums/species"; +import { + MoveEffectPhase, +} from "#app/phases"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; +import { allMoves } from "#app/data/move.js"; +import { WeatherType } from "#app/data/weather.js"; +import { Abilities } from "#app/enums/abilities.js"; + +describe("Weather - Fog", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(Overrides, "WEATHER_OVERRIDE", "get").mockReturnValue(WeatherType.FOG); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(new Array(4).fill(Moves.SPLASH)); + }); + + it("move accuracy is multiplied by 90%", async () => { + const moveToCheck = allMoves[Moves.TACKLE]; + + vi.spyOn(moveToCheck, "calculateBattleAccuracy"); + + await game.startBattle([Species.MAGIKARP]); + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); + await game.phaseInterceptor.to(MoveEffectPhase); + + expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(100 * 0.9); + }); +}); diff --git a/src/test/arena/weather_strong_winds.test.ts b/src/test/arena/weather_strong_winds.test.ts index 0cac700fb3b3..906d6c71b0dc 100644 --- a/src/test/arena/weather_strong_winds.test.ts +++ b/src/test/arena/weather_strong_winds.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { TurnStartPhase, @@ -27,15 +27,15 @@ describe("Weather - Strong Winds", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(10); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.TAILLOW); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.DELTA_STREAM); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.THUNDERBOLT, Moves.ICE_BEAM, Moves.ROCK_SLIDE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(10); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.TAILLOW); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.DELTA_STREAM); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.THUNDERBOLT, Moves.ICE_BEAM, Moves.ROCK_SLIDE]); }); it("electric type move is not very effective on Rayquaza", async () => { - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RAYQUAZA); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RAYQUAZA); await game.startBattle([Species.PIKACHU]); const pikachu = game.scene.getPlayerPokemon(); diff --git a/src/test/battle/battle-order.test.ts b/src/test/battle/battle-order.test.ts index bf06c6611418..0a6b9473ff14 100644 --- a/src/test/battle/battle-order.test.ts +++ b/src/test/battle/battle-order.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, EnemyCommandPhase, SelectTargetPhase, TurnStartPhase @@ -33,11 +33,11 @@ describe("Battle order", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); }); it("opponent faster than player 50 vs 150", async() => { @@ -83,8 +83,7 @@ describe("Battle order", () => { }, 20000); it("double - both opponents faster than player 50/50 vs 150/150", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); await game.startBattle([ Species.BULBASAUR, Species.BLASTOISE, @@ -126,8 +125,7 @@ describe("Battle order", () => { }, 20000); it("double - speed tie except 1 - 100/100 vs 100/150", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); await game.startBattle([ Species.BULBASAUR, Species.BLASTOISE, @@ -168,8 +166,7 @@ describe("Battle order", () => { }, 20000); it("double - speed tie 100/150 vs 100/150", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); await game.startBattle([ Species.BULBASAUR, Species.BLASTOISE, diff --git a/src/test/battle/battle.test.ts b/src/test/battle/battle.test.ts index 9b0e71c080d3..436b3227791c 100644 --- a/src/test/battle/battle.test.ts +++ b/src/test/battle/battle.test.ts @@ -2,7 +2,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest import {generateStarter, getMovePosition,} from "#app/test/utils/gameManagerUtils"; import {Mode} from "#app/ui/ui"; import {GameModes} from "#app/game-mode"; -import overrides from "../../overrides"; +import Overrides from "#app/overrides"; import {Command} from "#app/ui/command-ui-handler"; import { CommandPhase, DamagePhase, @@ -90,14 +90,14 @@ describe("Test Battle Phase", () => { }, 20000); it("do attack wave 3 - single battle - regular - OHKO", async() => { - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); await game.startBattle(); game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); @@ -110,14 +110,14 @@ describe("Test Battle Phase", () => { }, 20000); it("do attack wave 3 - single battle - regular - NO OHKO with opponent using non damage attack", async() => { - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(5); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP]); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); await game.startBattle(); game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); @@ -204,10 +204,10 @@ describe("Test Battle Phase", () => { }, 20000); it("2vs1", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD, @@ -217,10 +217,10 @@ describe("Test Battle Phase", () => { }, 20000); it("1vs1", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); await game.startBattle([ Species.BLASTOISE, ]); @@ -229,11 +229,11 @@ describe("Test Battle Phase", () => { }, 20000); it("2vs2", async() => { - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD, @@ -243,11 +243,11 @@ describe("Test Battle Phase", () => { }, 20000); it("4vs2", async() => { - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MIGHTYENA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD, @@ -260,15 +260,15 @@ describe("Test Battle Phase", () => { it("kill opponent pokemon", async() => { const moveToUse = Moves.SPLASH; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); await game.startBattle([ Species.DARMANITAN, Species.CHARIZARD, @@ -289,15 +289,15 @@ describe("Test Battle Phase", () => { it("to next turn", async() => { const moveToUse = Moves.SPLASH; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); await game.startBattle(); const turn = game.scene.currentBattle.turn; game.doAttack(0); @@ -307,15 +307,15 @@ describe("Test Battle Phase", () => { it("to next wave with pokemon killed, single", async() => { const moveToUse = Moves.SPLASH; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); await game.startBattle(); const waveIndex = game.scene.currentBattle.waveIndex; game.doAttack(0); diff --git a/src/test/battle/error-handling.test.ts b/src/test/battle/error-handling.test.ts index 767a26cb013b..063ac2b5210a 100644 --- a/src/test/battle/error-handling.test.ts +++ b/src/test/battle/error-handling.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import GameManager from "#app/test/utils/gameManager"; import Phaser from "phaser"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; @@ -23,15 +23,15 @@ describe("Test Battle Phase", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.SPLASH; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); it.skip("to next turn", async() => { diff --git a/src/test/battle/special_battle.test.ts b/src/test/battle/special_battle.test.ts index 2147638ad47e..cc1d2057b9bc 100644 --- a/src/test/battle/special_battle.test.ts +++ b/src/test/battle/special_battle.test.ts @@ -1,6 +1,6 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import {Mode} from "#app/ui/ui"; -import overrides from "../../overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, } from "#app/phases"; @@ -26,17 +26,17 @@ describe("Test Battle Phase", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); }); it("startBattle 2vs1 boss", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10); await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD, @@ -46,8 +46,8 @@ describe("Test Battle Phase", () => { }, 20000); it("startBattle 2vs2 boss", async() => { - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10); await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD, @@ -57,8 +57,8 @@ describe("Test Battle Phase", () => { }, 20000); it("startBattle 2vs2 trainer", async() => { - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD, @@ -68,8 +68,8 @@ describe("Test Battle Phase", () => { }, 20000); it("startBattle 2vs1 trainer", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD, @@ -79,8 +79,8 @@ describe("Test Battle Phase", () => { }, 20000); it("startBattle 2vs1 rival", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(8); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(8); await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD, @@ -90,8 +90,8 @@ describe("Test Battle Phase", () => { }, 20000); it("startBattle 2vs2 rival", async() => { - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(8); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(8); await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD, @@ -101,8 +101,8 @@ describe("Test Battle Phase", () => { }, 20000); it("startBattle 1vs1 trainer", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); await game.startBattle([ Species.BLASTOISE, ]); @@ -111,8 +111,8 @@ describe("Test Battle Phase", () => { }, 20000); it("startBattle 2vs2 trainer", async() => { - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD, @@ -122,8 +122,8 @@ describe("Test Battle Phase", () => { }, 20000); it("startBattle 4vs2 trainer", async() => { - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD, diff --git a/src/test/battlerTags/stockpiling.test.ts b/src/test/battlerTags/stockpiling.test.ts new file mode 100644 index 000000000000..5cf07c47ce1a --- /dev/null +++ b/src/test/battlerTags/stockpiling.test.ts @@ -0,0 +1,161 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; +import Pokemon, { PokemonSummonData } from "#app/field/pokemon.js"; +import BattleScene from "#app/battle-scene.js"; +import { StockpilingTag } from "#app/data/battler-tags.js"; +import { StatChangePhase } from "#app/phases.js"; +import { BattleStat } from "#app/data/battle-stat.js"; +import * as messages from "#app/messages.js"; + +beforeEach(() => { + vi.spyOn(messages, "getPokemonNameWithAffix").mockImplementation(() => ""); +}); + +describe("BattlerTag - StockpilingTag", () => { + describe("onAdd", () => { + it("unshifts a StatChangePhase with expected stat changes on add", { timeout: 10000 }, async () => { + const mockPokemon = { + scene: vi.mocked(new BattleScene()) as BattleScene, + getBattlerIndex: () => 0, + } as Pokemon; + + vi.spyOn(mockPokemon.scene, "queueMessage").mockImplementation(() => {}); + + const subject = new StockpilingTag(1); + + vi.spyOn(mockPokemon.scene, "unshiftPhase").mockImplementation(phase => { + expect(phase).toBeInstanceOf(StatChangePhase); + expect((phase as StatChangePhase)["levels"]).toEqual(1); + expect((phase as StatChangePhase)["stats"]).toEqual(expect.arrayContaining([BattleStat.DEF, BattleStat.SPDEF])); + + (phase as StatChangePhase)["onChange"](mockPokemon, [BattleStat.DEF, BattleStat.SPDEF], [1, 1]); + }); + + subject.onAdd(mockPokemon); + + expect(mockPokemon.scene.unshiftPhase).toBeCalledTimes(1); + }); + + it("unshifts a StatChangePhase with expected stat changes on add (one stat maxed)", { timeout: 10000 }, async () => { + const mockPokemon = { + scene: new BattleScene(), + summonData: new PokemonSummonData(), + getBattlerIndex: () => 0, + } as Pokemon; + + vi.spyOn(mockPokemon.scene, "queueMessage").mockImplementation(() => {}); + + mockPokemon.summonData.battleStats[BattleStat.DEF] = 6; + mockPokemon.summonData.battleStats[BattleStat.SPDEF] = 5; + + const subject = new StockpilingTag(1); + + vi.spyOn(mockPokemon.scene, "unshiftPhase").mockImplementation(phase => { + expect(phase).toBeInstanceOf(StatChangePhase); + expect((phase as StatChangePhase)["levels"]).toEqual(1); + expect((phase as StatChangePhase)["stats"]).toEqual(expect.arrayContaining([BattleStat.DEF, BattleStat.SPDEF])); + + (phase as StatChangePhase)["onChange"](mockPokemon, [BattleStat.DEF, BattleStat.SPDEF], [1, 1]); + }); + + subject.onAdd(mockPokemon); + + expect(mockPokemon.scene.unshiftPhase).toBeCalledTimes(1); + }); + }); + + describe("onOverlap", () => { + it("unshifts a StatChangePhase with expected stat changes on overlap", { timeout: 10000 }, async () => { + const mockPokemon = { + scene: new BattleScene(), + getBattlerIndex: () => 0, + } as Pokemon; + + vi.spyOn(mockPokemon.scene, "queueMessage").mockImplementation(() => {}); + + const subject = new StockpilingTag(1); + + vi.spyOn(mockPokemon.scene, "unshiftPhase").mockImplementation(phase => { + expect(phase).toBeInstanceOf(StatChangePhase); + expect((phase as StatChangePhase)["levels"]).toEqual(1); + expect((phase as StatChangePhase)["stats"]).toEqual(expect.arrayContaining([BattleStat.DEF, BattleStat.SPDEF])); + + (phase as StatChangePhase)["onChange"](mockPokemon, [BattleStat.DEF, BattleStat.SPDEF], [1, 1]); + }); + + subject.onOverlap(mockPokemon); + + expect(mockPokemon.scene.unshiftPhase).toBeCalledTimes(1); + }); + }); + + describe("stack limit, stat tracking, and removal", () => { + it("can be added up to three times, even when one stat does not change", { timeout: 10000 }, async () => { + const mockPokemon = { + scene: new BattleScene(), + summonData: new PokemonSummonData(), + getBattlerIndex: () => 0, + } as Pokemon; + + vi.spyOn(mockPokemon.scene, "queueMessage").mockImplementation(() => {}); + + mockPokemon.summonData.battleStats[BattleStat.DEF] = 5; + mockPokemon.summonData.battleStats[BattleStat.SPDEF] = 4; + + const subject = new StockpilingTag(1); + + vi.spyOn(mockPokemon.scene, "unshiftPhase").mockImplementationOnce(phase => { + expect(phase).toBeInstanceOf(StatChangePhase); + expect((phase as StatChangePhase)["levels"]).toEqual(1); + expect((phase as StatChangePhase)["stats"]).toEqual(expect.arrayContaining([BattleStat.DEF, BattleStat.SPDEF])); + + // def doesn't change + (phase as StatChangePhase)["onChange"](mockPokemon, [BattleStat.SPDEF], [1]); + }); + + subject.onAdd(mockPokemon); + expect(subject.stockpiledCount).toBe(1); + + vi.spyOn(mockPokemon.scene, "unshiftPhase").mockImplementationOnce(phase => { + expect(phase).toBeInstanceOf(StatChangePhase); + expect((phase as StatChangePhase)["levels"]).toEqual(1); + expect((phase as StatChangePhase)["stats"]).toEqual(expect.arrayContaining([BattleStat.DEF, BattleStat.SPDEF])); + + // def doesn't change + (phase as StatChangePhase)["onChange"](mockPokemon, [BattleStat.SPDEF], [1]); + }); + + subject.onOverlap(mockPokemon); + expect(subject.stockpiledCount).toBe(2); + + vi.spyOn(mockPokemon.scene, "unshiftPhase").mockImplementationOnce(phase => { + expect(phase).toBeInstanceOf(StatChangePhase); + expect((phase as StatChangePhase)["levels"]).toEqual(1); + expect((phase as StatChangePhase)["stats"]).toEqual(expect.arrayContaining([BattleStat.DEF, BattleStat.SPDEF])); + + // neither stat changes, stack count should still increase + }); + + subject.onOverlap(mockPokemon); + expect(subject.stockpiledCount).toBe(3); + + vi.spyOn(mockPokemon.scene, "unshiftPhase").mockImplementationOnce(phase => { + throw new Error("Should not be called a fourth time"); + }); + + // fourth stack should not be applied + subject.onOverlap(mockPokemon); + expect(subject.stockpiledCount).toBe(3); + expect(subject.statChangeCounts).toMatchObject({ [BattleStat.DEF]: 0, [BattleStat.SPDEF]: 2 }); + + // removing tag should reverse stat changes + vi.spyOn(mockPokemon.scene, "unshiftPhase").mockImplementationOnce(phase => { + expect(phase).toBeInstanceOf(StatChangePhase); + expect((phase as StatChangePhase)["levels"]).toEqual(-2); + expect((phase as StatChangePhase)["stats"]).toEqual(expect.arrayContaining([BattleStat.SPDEF])); + }); + + subject.onRemove(mockPokemon); + expect(mockPokemon.scene.unshiftPhase).toHaveBeenCalledOnce(); // note that re-spying each add/overlap has been refreshing call count + }); + }); +}); diff --git a/src/test/internals.test.ts b/src/test/internals.test.ts new file mode 100644 index 000000000000..a54b8b015445 --- /dev/null +++ b/src/test/internals.test.ts @@ -0,0 +1,43 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import { Species } from "#app/enums/species.js"; +import { Abilities } from "#app/enums/abilities.js"; + +describe("Internals", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + }); + + it("should provide Eevee with 3 defined abilities", async () => { + await game.runToSummon([Species.EEVEE]); + const eevee = game.scene.getPlayerPokemon(); + + expect(eevee.getSpeciesForm().getAbilityCount()).toBe(3); + + expect(eevee.getSpeciesForm().getAbility(0)).toBe(Abilities.RUN_AWAY); + expect(eevee.getSpeciesForm().getAbility(1)).toBe(Abilities.ADAPTABILITY); + expect(eevee.getSpeciesForm().getAbility(2)).toBe(Abilities.ANTICIPATION); + }); + + it("should set Eeeve abilityIndex between 0-2", async () => { + await game.runToSummon([Species.EEVEE]); + const eevee = game.scene.getPlayerPokemon(); + + expect(eevee.abilityIndex).toBeGreaterThanOrEqual(0); + expect(eevee.abilityIndex).toBeLessThanOrEqual(2); + }); +}); diff --git a/src/test/items/eviolite.test.ts b/src/test/items/eviolite.test.ts index 983a3ebd1f93..5cdcf2256c3d 100644 --- a/src/test/items/eviolite.test.ts +++ b/src/test/items/eviolite.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phase from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Stat } from "#app/data/pokemon-stat"; import { EvolutionStatBoosterModifier } from "#app/modifier/modifier"; import { modifierTypes } from "#app/modifier/modifier-type"; @@ -26,11 +26,11 @@ describe("Items - Eviolite", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); }); it("EVIOLITE activates in battle correctly", async() => { - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "EVIOLITE" }]); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "EVIOLITE" }]); const consoleSpy = vi.spyOn(console, "log"); await game.startBattle([ Species.PICHU diff --git a/src/test/items/exp_booster.test.ts b/src/test/items/exp_booster.test.ts new file mode 100644 index 000000000000..866bd6f08b6d --- /dev/null +++ b/src/test/items/exp_booster.test.ts @@ -0,0 +1,40 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phase from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import Overrides from "#app/overrides"; +import { Abilities } from "#app/enums/abilities.js"; +import { PokemonExpBoosterModifier } from "#app/modifier/modifier.js"; +import * as Utils from "#app/utils"; + +describe("EXP Modifier Items", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phase.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + }); + + it("EXP booster items stack additively", async() => { + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "LUCKY_EGG"}, {name: "GOLDEN_EGG"}]); + await game.startBattle(); + + const partyMember = game.scene.getPlayerPokemon(); + const modifierBonusExp = new Utils.NumberHolder(1); + partyMember.scene.applyModifiers(PokemonExpBoosterModifier, true, partyMember, modifierBonusExp); + expect(modifierBonusExp.value).toBe(2.4); + }, 20000); +}); diff --git a/src/test/items/grip_claw.test.ts b/src/test/items/grip_claw.test.ts index 0247ccb2076d..2aeb98253ab8 100644 --- a/src/test/items/grip_claw.test.ts +++ b/src/test/items/grip_claw.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phase from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Moves } from "#app/enums/moves.js"; import { Species } from "#app/enums/species.js"; import { BerryType } from "#app/enums/berry-type.js"; @@ -30,18 +30,18 @@ describe("Items - Grip Claw", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.POPULATION_BOMB, Moves.SPLASH ]); - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "GRIP_CLAW", count: 5}, {name: "MULTI_LENS", count: 3}]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.KLUTZ); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); - vi.spyOn(overrides, "OPP_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([ + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.POPULATION_BOMB, Moves.SPLASH ]); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "GRIP_CLAW", count: 5}, {name: "MULTI_LENS", count: 3}]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.KLUTZ); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); + vi.spyOn(Overrides, "OPP_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([ {name: "BERRY", type: BerryType.SITRUS, count: 2}, {name: "BERRY", type: BerryType.LUM, count: 2} ]); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); vi.spyOn(allMoves[Moves.POPULATION_BOMB], "accuracy", "get").mockReturnValue(100); }); diff --git a/src/test/items/leek.test.ts b/src/test/items/leek.test.ts index d81b6b8541f0..2781de45c080 100644 --- a/src/test/items/leek.test.ts +++ b/src/test/items/leek.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phase from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { Moves } from "#enums/moves"; import { CritBoosterModifier } from "#app/modifier/modifier"; @@ -27,16 +27,16 @@ describe("Items - Leek", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); }); it("LEEK activates in battle correctly", async() => { - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "LEEK" }]); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.POUND ]); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "LEEK" }]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.POUND ]); const consoleSpy = vi.spyOn(console, "log"); await game.startBattle([ Species.FARFETCHD diff --git a/src/test/items/leftovers.test.ts b/src/test/items/leftovers.test.ts new file mode 100644 index 000000000000..1d564ae534c6 --- /dev/null +++ b/src/test/items/leftovers.test.ts @@ -0,0 +1,65 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import overrides from "#app/overrides"; +import { DamagePhase, TurnEndPhase } from "#app/phases"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; + + +describe("Items - Leftovers", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.UNNERVE); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.UNNERVE); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "LEFTOVERS", count: 1}]); + }); + + it("leftovers works", async() => { + await game.startBattle([Species.ARCANINE]); + + // Make sure leftovers are there + expect(game.scene.modifiers[0].type.id).toBe("LEFTOVERS"); + + const leadPokemon = game.scene.getPlayerPokemon(); + expect(leadPokemon).toBeDefined(); + + const enemyPokemon = game.scene.getEnemyPokemon(); + expect(enemyPokemon).toBeDefined(); + + // We should have full hp + expect(leadPokemon.isFullHp()).toBe(true); + + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + + // We should have less hp after the attack + await game.phaseInterceptor.to(DamagePhase, false); + expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); + + const leadHpAfterDamage = leadPokemon.hp; + + // Check if leftovers heal us + await game.phaseInterceptor.to(TurnEndPhase); + expect(leadPokemon.hp).toBeGreaterThan(leadHpAfterDamage); + }, 20000); +}); diff --git a/src/test/items/light_ball.test.ts b/src/test/items/light_ball.test.ts index ef37860e007f..e693307e229d 100644 --- a/src/test/items/light_ball.test.ts +++ b/src/test/items/light_ball.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phase from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { Stat } from "#app/data/pokemon-stat"; import { SpeciesStatBoosterModifier } from "#app/modifier/modifier"; @@ -26,11 +26,11 @@ describe("Items - Light Ball", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); }); it("LIGHT_BALL activates in battle correctly", async() => { - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "SPECIES_STAT_BOOSTER", type: "LIGHT_BALL" }]); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "SPECIES_STAT_BOOSTER", type: "LIGHT_BALL" }]); const consoleSpy = vi.spyOn(console, "log"); await game.startBattle([ Species.PIKACHU diff --git a/src/test/items/metal_powder.test.ts b/src/test/items/metal_powder.test.ts index ea13660efaff..111bc6dfad12 100644 --- a/src/test/items/metal_powder.test.ts +++ b/src/test/items/metal_powder.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phase from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { Stat } from "#app/data/pokemon-stat"; import { SpeciesStatBoosterModifier } from "#app/modifier/modifier"; @@ -26,11 +26,11 @@ describe("Items - Metal Powder", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); }); it("METAL_POWDER activates in battle correctly", async() => { - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "SPECIES_STAT_BOOSTER", type: "METAL_POWDER" }]); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "SPECIES_STAT_BOOSTER", type: "METAL_POWDER" }]); const consoleSpy = vi.spyOn(console, "log"); await game.startBattle([ Species.DITTO diff --git a/src/test/items/quick_powder.test.ts b/src/test/items/quick_powder.test.ts index 5d858b6dec53..cddddb0eeea3 100644 --- a/src/test/items/quick_powder.test.ts +++ b/src/test/items/quick_powder.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phase from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { Stat } from "#app/data/pokemon-stat"; import { SpeciesStatBoosterModifier } from "#app/modifier/modifier"; @@ -26,11 +26,11 @@ describe("Items - Quick Powder", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); }); it("QUICK_POWDER activates in battle correctly", async() => { - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "SPECIES_STAT_BOOSTER", type: "QUICK_POWDER" }]); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "SPECIES_STAT_BOOSTER", type: "QUICK_POWDER" }]); const consoleSpy = vi.spyOn(console, "log"); await game.startBattle([ Species.DITTO diff --git a/src/test/items/scope_lens.test.ts b/src/test/items/scope_lens.test.ts index 8a90809d64e3..8f54a880c414 100644 --- a/src/test/items/scope_lens.test.ts +++ b/src/test/items/scope_lens.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phase from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { Moves } from "#enums/moves"; import { CritBoosterModifier } from "#app/modifier/modifier"; @@ -27,16 +27,16 @@ describe("Items - Scope Lens", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); }, 20000); it("SCOPE_LENS activates in battle correctly", async() => { - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "SCOPE_LENS" }]); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.POUND ]); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "SCOPE_LENS" }]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.POUND ]); const consoleSpy = vi.spyOn(console, "log"); await game.startBattle([ Species.GASTLY diff --git a/src/test/items/thick_club.test.ts b/src/test/items/thick_club.test.ts index eaa1ed4bf9ae..a0a229a5d13e 100644 --- a/src/test/items/thick_club.test.ts +++ b/src/test/items/thick_club.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phase from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { Stat } from "#app/data/pokemon-stat"; import { SpeciesStatBoosterModifier } from "#app/modifier/modifier"; @@ -26,11 +26,11 @@ describe("Items - Thick Club", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); }); it("THICK_CLUB activates in battle correctly", async() => { - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "SPECIES_STAT_BOOSTER", type: "THICK_CLUB" }]); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "SPECIES_STAT_BOOSTER", type: "THICK_CLUB" }]); const consoleSpy = vi.spyOn(console, "log"); await game.startBattle([ Species.CUBONE diff --git a/src/test/items/toxic_orb.test.ts b/src/test/items/toxic_orb.test.ts index 0861477e88f0..45662ac29cf0 100644 --- a/src/test/items/toxic_orb.test.ts +++ b/src/test/items/toxic_orb.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, EnemyCommandPhase, @@ -36,14 +36,14 @@ describe("Items - Toxic orb", () => { game = new GameManager(phaserGame); const moveToUse = Moves.GROWTH; const oppMoveToUse = Moves.TACKLE; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([oppMoveToUse, oppMoveToUse, oppMoveToUse, oppMoveToUse]); - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([oppMoveToUse, oppMoveToUse, oppMoveToUse, oppMoveToUse]); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "TOXIC_ORB", }]); }); diff --git a/src/test/localization/terrain.test.ts b/src/test/localization/terrain.test.ts index 526dedf8d245..08292bcdda76 100644 --- a/src/test/localization/terrain.test.ts +++ b/src/test/localization/terrain.test.ts @@ -1,7 +1,7 @@ import { beforeAll, describe, beforeEach, afterEach, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { TerrainType, getTerrainName } from "#app/data/terrain"; import { getTerrainStartMessage, getTerrainClearMessage, getTerrainBlockMessage } from "#app/data/weather"; @@ -21,7 +21,7 @@ describe("terrain", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); }); describe("NONE", () => { diff --git a/src/test/moves/astonish.test.ts b/src/test/moves/astonish.test.ts index bd18d159b658..4ce2f16715b6 100644 --- a/src/test/moves/astonish.test.ts +++ b/src/test/moves/astonish.test.ts @@ -28,7 +28,7 @@ describe("Moves - Astonish", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.ASTONISH, Moves.SPLASH]); vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.BLASTOISE); vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); diff --git a/src/test/moves/aurora_veil.test.ts b/src/test/moves/aurora_veil.test.ts index 258059f9c489..dad8d277b7f2 100644 --- a/src/test/moves/aurora_veil.test.ts +++ b/src/test/moves/aurora_veil.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { TurnEndPhase, } from "#app/phases"; @@ -35,14 +35,14 @@ describe("Moves - Aurora Veil", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.ABSORB, Moves.ROCK_SLIDE, Moves.TACKLE]); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL]); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "WEATHER_OVERRIDE", "get").mockReturnValue(WeatherType.HAIL); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.ABSORB, Moves.ROCK_SLIDE, Moves.TACKLE]); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL]); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "WEATHER_OVERRIDE", "get").mockReturnValue(WeatherType.HAIL); }); it("reduces damage of physical attacks by half in a single battle", async() => { @@ -58,8 +58,7 @@ describe("Moves - Aurora Veil", () => { }); it("reduces damage of physical attacks by a third in a double battle", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); const moveToUse = Moves.ROCK_SLIDE; await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); @@ -87,8 +86,7 @@ describe("Moves - Aurora Veil", () => { }); it("reduces damage of special attacks by a third in a double battle", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); const moveToUse = Moves.DAZZLING_GLEAM; await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); diff --git a/src/test/moves/ceaseless_edge.test.ts b/src/test/moves/ceaseless_edge.test.ts index 636c9c3e6180..a59d6e8f5351 100644 --- a/src/test/moves/ceaseless_edge.test.ts +++ b/src/test/moves/ceaseless_edge.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { MoveEffectPhase, TurnEndPhase @@ -32,14 +32,14 @@ describe("Moves - Ceaseless Edge", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.RUN_AWAY); - vi.spyOn(overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.RUN_AWAY); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.CEASELESS_EDGE, Moves.SPLASH, Moves.ROAR ]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.RUN_AWAY); + vi.spyOn(Overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.RUN_AWAY); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.CEASELESS_EDGE, Moves.SPLASH, Moves.ROAR ]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); vi.spyOn(allMoves[Moves.CEASELESS_EDGE], "accuracy", "get").mockReturnValue(100); }); @@ -75,7 +75,7 @@ describe("Moves - Ceaseless Edge", () => { test( "move should hit twice with multi lens and apply two layers of spikes", async () => { - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "MULTI_LENS"}]); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "MULTI_LENS"}]); await game.startBattle([ Species.ILLUMISE ]); const leadPokemon = game.scene.getPlayerPokemon(); @@ -104,8 +104,8 @@ describe("Moves - Ceaseless Edge", () => { test( "trainer - move should hit twice, apply two layers of spikes, force switch opponent - opponent takes damage", async () => { - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "MULTI_LENS"}]); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "MULTI_LENS"}]); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); await game.startBattle([ Species.ILLUMISE ]); diff --git a/src/test/moves/double_team.test.ts b/src/test/moves/double_team.test.ts new file mode 100644 index 000000000000..de9bd01fd5b4 --- /dev/null +++ b/src/test/moves/double_team.test.ts @@ -0,0 +1,55 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import Overrides from "#app/overrides"; +import { Species } from "#enums/species"; +import { + TurnEndPhase, +} from "#app/phases"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { Abilities } from "#app/enums/abilities.js"; + +describe("Moves - Double Team", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.DOUBLE_TEAM]); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SHUCKLE); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + }); + + it("increases the user's evasion by one stage.", async () => { + await game.startBattle([Species.MAGIKARP]); + + const ally = game.scene.getPlayerPokemon(); + const enemy = game.scene.getEnemyPokemon(); + + vi.spyOn(enemy, "getAccuracyMultiplier"); + expect(ally.summonData.battleStats[BattleStat.EVA]).toBe(0); + + game.doAttack(getMovePosition(game.scene, 0, Moves.DOUBLE_TEAM)); + await game.phaseInterceptor.to(TurnEndPhase); + await game.toNextTurn(); + + expect(ally.summonData.battleStats[BattleStat.EVA]).toBe(1); + expect(enemy.getAccuracyMultiplier).toHaveReturnedWith(.75); + }); +}); diff --git a/src/test/moves/dragon_rage.test.ts b/src/test/moves/dragon_rage.test.ts index 51ea9a677288..a6044044aa41 100644 --- a/src/test/moves/dragon_rage.test.ts +++ b/src/test/moves/dragon_rage.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { TurnEndPhase } from "#app/phases"; import { Moves } from "#enums/moves"; import { getMovePosition } from "#app/test/utils/gameManagerUtils"; @@ -34,20 +34,20 @@ describe("Moves - Dragon Rage", () => { beforeEach(async () => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.DRAGON_RAGE]); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.DRAGON_RAGE]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); await game.startBattle(); @@ -111,7 +111,7 @@ describe("Moves - Dragon Rage", () => { }); it("ignores damage modification from abilities such as ice scales", async () => { - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ICE_SCALES); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ICE_SCALES); game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_RAGE)); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/moves/dynamax_cannon.test.ts b/src/test/moves/dynamax_cannon.test.ts index 6535332fbd3b..aab1b210f687 100644 --- a/src/test/moves/dynamax_cannon.test.ts +++ b/src/test/moves/dynamax_cannon.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { MoveEffectPhase, DamagePhase, TurnStartPhase } from "#app/phases"; import { getMovePosition } from "#app/test/utils/gameManagerUtils"; import { allMoves } from "#app/data/move"; @@ -28,22 +28,22 @@ describe("Moves - Dynamax Cannon", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ dynamaxCannon.id ]); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(200); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ dynamaxCannon.id ]); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(200); // Note that, for Waves 1-10, the level cap is 10 - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(1); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(1); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); vi.spyOn(dynamaxCannon, "calculateBattlePower"); }); it("should return 100 power against an enemy below level cap", async() => { - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(1); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(1); await game.startBattle([ Species.ETERNATUS, ]); @@ -57,7 +57,7 @@ describe("Moves - Dynamax Cannon", () => { }, 20000); it("should return 100 power against an enemy at level cap", async() => { - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(10); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(10); await game.startBattle([ Species.ETERNATUS, ]); @@ -71,7 +71,7 @@ describe("Moves - Dynamax Cannon", () => { }, 20000); it("should return 120 power against an enemy 1% above level cap", async() => { - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(101); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(101); await game.startBattle([ Species.ETERNATUS, ]); @@ -88,7 +88,7 @@ describe("Moves - Dynamax Cannon", () => { }, 20000); it("should return 140 power against an enemy 2% above level capp", async() => { - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(102); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(102); await game.startBattle([ Species.ETERNATUS, ]); @@ -105,7 +105,7 @@ describe("Moves - Dynamax Cannon", () => { }, 20000); it("should return 160 power against an enemy 3% above level cap", async() => { - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(103); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(103); await game.startBattle([ Species.ETERNATUS, ]); @@ -122,7 +122,7 @@ describe("Moves - Dynamax Cannon", () => { }, 20000); it("should return 180 power against an enemy 4% above level cap", async() => { - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(104); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(104); await game.startBattle([ Species.ETERNATUS, ]); @@ -139,7 +139,7 @@ describe("Moves - Dynamax Cannon", () => { }, 20000); it("should return 200 power against an enemy 5% above level cap", async() => { - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(105); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(105); await game.startBattle([ Species.ETERNATUS, ]); @@ -156,7 +156,7 @@ describe("Moves - Dynamax Cannon", () => { }, 20000); it("should return 200 power against an enemy way above level cap", async() => { - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(999); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(999); await game.startBattle([ Species.ETERNATUS, ]); diff --git a/src/test/moves/fissure.test.ts b/src/test/moves/fissure.test.ts index 6d0dc70fec47..4809a3b4deec 100644 --- a/src/test/moves/fissure.test.ts +++ b/src/test/moves/fissure.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { DamagePhase } from "#app/phases"; import { Moves } from "#enums/moves"; import { getMovePosition } from "#app/test/utils/gameManagerUtils"; @@ -28,18 +28,18 @@ describe("Moves - Fissure", () => { beforeEach(async () => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.FISSURE]); - vi.spyOn(overrides, "PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.FISSURE]); + vi.spyOn(Overrides, "PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - vi.spyOn(overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); await game.startBattle(); @@ -52,8 +52,8 @@ describe("Moves - Fissure", () => { }); it("ignores damage modification from abilities such as fur coat", async () => { - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NO_GUARD); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.FUR_COAT); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NO_GUARD); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.FUR_COAT); game.doAttack(getMovePosition(game.scene, 0, Moves.FISSURE)); await game.phaseInterceptor.to(DamagePhase, true); diff --git a/src/test/moves/flower_shield.test.ts b/src/test/moves/flower_shield.test.ts index b6e196cd9f76..c36a45790c7f 100644 --- a/src/test/moves/flower_shield.test.ts +++ b/src/test/moves/flower_shield.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { TurnEndPhase, @@ -30,15 +30,15 @@ describe("Moves - Flower Shield", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.FLOWER_SHIELD, Moves.SPLASH]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.FLOWER_SHIELD, Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); }); it("increases defense of all Grass-type Pokemon on the field by one stage - single battle", async () => { - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.CHERRIM); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.CHERRIM); await game.startBattle([Species.MAGIKARP]); const cherrim = game.scene.getEnemyPokemon(); @@ -55,10 +55,9 @@ describe("Moves - Flower Shield", () => { }); it("increases defense of all Grass-type Pokemon on the field by one stage - double battle", async () => { - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "STARTING_BIOME_OVERRIDE", "get").mockReturnValue(Biome.GRASS); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "STARTING_BIOME_OVERRIDE", "get").mockReturnValue(Biome.GRASS); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); await game.startBattle([Species.CHERRIM, Species.MAGIKARP]); const field = game.scene.getField(true); @@ -81,9 +80,9 @@ describe("Moves - Flower Shield", () => { * See semi-vulnerable state tags. {@linkcode SemiInvulnerableTag} */ it("does not increase defense of a pokemon in semi-vulnerable state", async () => { - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.PARAS); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.DIG, Moves.DIG, Moves.DIG, Moves.DIG]); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(50); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.PARAS); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.DIG, Moves.DIG, Moves.DIG, Moves.DIG]); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(50); await game.startBattle([Species.CHERRIM]); const paras = game.scene.getEnemyPokemon(); @@ -102,7 +101,7 @@ describe("Moves - Flower Shield", () => { }); it("does nothing if there are no Grass-type pokemon on the field", async () => { - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); await game.startBattle([Species.MAGIKARP]); const enemy = game.scene.getEnemyPokemon(); diff --git a/src/test/moves/follow_me.test.ts b/src/test/moves/follow_me.test.ts index c444db77f173..738c9b6e8374 100644 --- a/src/test/moves/follow_me.test.ts +++ b/src/test/moves/follow_me.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, SelectTargetPhase, @@ -32,13 +32,13 @@ describe("Moves - Follow Me", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.AMOONGUSS); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.AMOONGUSS); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); test( @@ -101,9 +101,9 @@ describe("Moves - Follow Me", () => { test( "move effect should be bypassed by Stalwart", async () => { - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.STALWART); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.QUICK_ATTACK ]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.STALWART); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.QUICK_ATTACK ]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); @@ -136,8 +136,8 @@ describe("Moves - Follow Me", () => { test( "move effect should be bypassed by Snipe Shot", async () => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.SNIPE_SHOT ]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.SNIPE_SHOT ]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); diff --git a/src/test/moves/gastro_acid.test.ts b/src/test/moves/gastro_acid.test.ts index 3b446ac4a535..c8f6ab6cc6ab 100644 --- a/src/test/moves/gastro_acid.test.ts +++ b/src/test/moves/gastro_acid.test.ts @@ -3,7 +3,7 @@ import GameManager from "../utils/gameManager"; import { Moves } from "#app/enums/moves.js"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Abilities } from "#app/enums/abilities.js"; import { BattlerIndex } from "#app/battle.js"; import { getMovePosition } from "../utils/gameManagerUtils"; @@ -29,14 +29,14 @@ describe("Moves - Gastro Acid", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(1); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.GASTRO_ACID, Moves.WATER_GUN, Moves.SPLASH, Moves.CORE_ENFORCER]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.BIDOOF); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WATER_ABSORB); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(1); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.GASTRO_ACID, Moves.WATER_GUN, Moves.SPLASH, Moves.CORE_ENFORCER]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.BIDOOF); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.WATER_ABSORB); }); it("suppresses effect of ability", async () => { @@ -68,11 +68,11 @@ describe("Moves - Gastro Acid", () => { await game.phaseInterceptor.to("TurnEndPhase"); expect(enemyField[0].hp).toBeLessThan(enemyField[0].getMaxHp()); - expect(enemyField[1].hp).toBe(enemyField[1].getMaxHp()); + expect(enemyField[1].isFullHp()).toBe(true); }, TIMEOUT); it("fails if used on an enemy with an already-suppressed ability", async () => { - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue(null); await game.startBattle(); diff --git a/src/test/moves/glaive_rush.test.ts b/src/test/moves/glaive_rush.test.ts new file mode 100644 index 000000000000..8cc2dc73b723 --- /dev/null +++ b/src/test/moves/glaive_rush.test.ts @@ -0,0 +1,132 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import Overrides from "#app/overrides"; +import { DamagePhase, TurnEndPhase } from "#app/phases"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { Abilities } from "#app/enums/abilities.js"; +import { allMoves } from "#app/data/move.js"; + + +describe("Moves - Glaive Rush", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(Array(4).fill(Moves.GLAIVE_RUSH)); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.KLINK); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.UNNERVE); + vi.spyOn(Overrides, "PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.FUR_COAT); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SHADOW_SNEAK, Moves.AVALANCHE, Moves.SPLASH, Moves.GLAIVE_RUSH]); + }); + + it("takes double damage from attacks", async() => { + await game.startBattle(); + const enemy = game.scene.getEnemyPokemon(); + enemy.hp = 1000; + + vi.spyOn(game.scene, "randBattleSeedInt").mockReturnValue(0); + game.doAttack(getMovePosition(game.scene, 0, Moves.SHADOW_SNEAK)); + await game.phaseInterceptor.to(DamagePhase); + const damageDealt = 1000 - enemy.hp; + await game.phaseInterceptor.to(TurnEndPhase); + game.doAttack(getMovePosition(game.scene, 0, Moves.SHADOW_SNEAK)); + await game.phaseInterceptor.to(DamagePhase); + expect(enemy.hp).toBeLessThanOrEqual(1001 - (damageDealt * 3)); + + }, 20000); + + it("always gets hit by attacks", async() => { + await game.startBattle(); + const enemy = game.scene.getEnemyPokemon(); + enemy.hp = 1000; + + allMoves[Moves.AVALANCHE].accuracy = 0; + game.doAttack(getMovePosition(game.scene, 0, Moves.AVALANCHE)); + await game.phaseInterceptor.to(TurnEndPhase); + expect(enemy.hp).toBeLessThan(1000); + + }, 20000); + + it("interacts properly with multi-lens", async() => { + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "MULTI_LENS", count: 2}]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(Array(4).fill(Moves.AVALANCHE)); + await game.startBattle(); + const player = game.scene.getPlayerPokemon(); + const enemy = game.scene.getEnemyPokemon(); + enemy.hp = 1000; + player.hp = 1000; + + allMoves[Moves.AVALANCHE].accuracy = 0; + game.doAttack(getMovePosition(game.scene, 0, Moves.GLAIVE_RUSH)); + await game.phaseInterceptor.to(TurnEndPhase); + expect(player.hp).toBeLessThan(1000); + player.hp = 1000; + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + await game.phaseInterceptor.to(TurnEndPhase); + expect(player.hp).toBe(1000); + + }, 20000); + + it("secondary effects only last until next move", async() => { + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(Array(4).fill(Moves.SHADOW_SNEAK)); + await game.startBattle(); + const player = game.scene.getPlayerPokemon(); + const enemy = game.scene.getEnemyPokemon(); + enemy.hp = 1000; + player.hp = 1000; + allMoves[Moves.SHADOW_SNEAK].accuracy = 0; + + game.doAttack(getMovePosition(game.scene, 0, Moves.GLAIVE_RUSH)); + await game.phaseInterceptor.to(TurnEndPhase); + expect(player.hp).toBe(1000); + + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + await game.phaseInterceptor.to(TurnEndPhase); + const damagedHp = player.hp; + expect(player.hp).toBeLessThan(1000); + + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + await game.phaseInterceptor.to(TurnEndPhase); + expect(player.hp).toBe(damagedHp); + + }, 20000); + + it("secondary effects are removed upon switching", async() => { + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(Array(4).fill(Moves.SHADOW_SNEAK)); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(0); + await game.startBattle([Species.KLINK, Species.FEEBAS]); + const player = game.scene.getPlayerPokemon(); + const enemy = game.scene.getEnemyPokemon(); + enemy.hp = 1000; + allMoves[Moves.SHADOW_SNEAK].accuracy = 0; + + game.doAttack(getMovePosition(game.scene, 0, Moves.GLAIVE_RUSH)); + await game.phaseInterceptor.to(TurnEndPhase); + expect(player.hp).toBe(player.getMaxHp()); + + game.doSwitchPokemon(1); + await game.phaseInterceptor.to(TurnEndPhase); + game.doSwitchPokemon(1); + await game.phaseInterceptor.to(TurnEndPhase); + expect(player.hp).toBe(player.getMaxHp()); + + }, 20000); +}); diff --git a/src/test/moves/growth.test.ts b/src/test/moves/growth.test.ts index ddec4225e9b7..6068c114fc38 100644 --- a/src/test/moves/growth.test.ts +++ b/src/test/moves/growth.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, EnemyCommandPhase, @@ -34,13 +34,13 @@ describe("Moves - Growth", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.GROWTH; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOXIE); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOXIE); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); it("GROWTH", async() => { diff --git a/src/test/moves/hard_press.test.ts b/src/test/moves/hard_press.test.ts index 87d61ecae904..8800d66bd9a5 100644 --- a/src/test/moves/hard_press.test.ts +++ b/src/test/moves/hard_press.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { MoveEffectPhase @@ -29,12 +29,12 @@ describe("Moves - Hard Press", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MUNCHLAX); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.HARD_PRESS]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MUNCHLAX); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.HARD_PRESS]); vi.spyOn(moveToCheck, "calculateBattlePower"); }); diff --git a/src/test/moves/hyper_beam.test.ts b/src/test/moves/hyper_beam.test.ts new file mode 100644 index 000000000000..2a6486c0de52 --- /dev/null +++ b/src/test/moves/hyper_beam.test.ts @@ -0,0 +1,72 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import overrides from "#app/overrides"; +import { Abilities } from "#app/enums/abilities.js"; +import { Species } from "#app/enums/species.js"; +import { Moves } from "#app/enums/moves.js"; +import { allMoves } from "#app/data/move.js"; +import { getMovePosition } from "../utils/gameManagerUtils"; +import { BerryPhase, TurnEndPhase } from "#app/phases.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; + +const TIMEOUT = 20 * 1000; // 20 sec timeout for all tests + +describe("Moves - Hyper Beam", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + + vi.spyOn(overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(Array(4).fill(Moves.SPLASH)); + + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.HYPER_BEAM, Moves.TACKLE]); + vi.spyOn(allMoves[Moves.HYPER_BEAM], "accuracy", "get").mockReturnValue(100); + }); + + it( + "should force the user to recharge on the next turn (and only that turn)", + async () => { + await game.startBattle([Species.MAGIKARP]); + + const leadPokemon = game.scene.getPlayerPokemon(); + const enemyPokemon = game.scene.getEnemyPokemon(); + + game.doAttack(getMovePosition(game.scene, 0, Moves.HYPER_BEAM)); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); + expect(leadPokemon.getTag(BattlerTagType.RECHARGING)).toBeDefined(); + + const enemyPostAttackHp = enemyPokemon.hp; + + /** Game should progress without a new command from the player */ + await game.phaseInterceptor.to(TurnEndPhase); + + expect(enemyPokemon.hp).toBe(enemyPostAttackHp); + expect(leadPokemon.getTag(BattlerTagType.RECHARGING)).toBeUndefined(); + + game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE)); + + await game.phaseInterceptor.to(BerryPhase, false); + + expect(enemyPokemon.hp).toBeLessThan(enemyPostAttackHp); + }, TIMEOUT + ); +}); diff --git a/src/test/moves/light_screen.test.ts b/src/test/moves/light_screen.test.ts index 077c4b1b1c8e..5269ec6d8ee9 100644 --- a/src/test/moves/light_screen.test.ts +++ b/src/test/moves/light_screen.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { TurnEndPhase, } from "#app/phases"; @@ -34,13 +34,13 @@ describe("Moves - Light Screen", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.ABSORB, Moves.DAZZLING_GLEAM, Moves.TACKLE]); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN]); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.ABSORB, Moves.DAZZLING_GLEAM, Moves.TACKLE]); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN]); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); }); it("reduces damage of special attacks by half in a single battle", async() => { @@ -57,8 +57,7 @@ describe("Moves - Light Screen", () => { }); it("reduces damage of special attacks by a third in a double battle", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); const moveToUse = Moves.DAZZLING_GLEAM; await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); diff --git a/src/test/moves/magnet_rise.test.ts b/src/test/moves/magnet_rise.test.ts index c30db57c29bf..2b06867f0a75 100644 --- a/src/test/moves/magnet_rise.test.ts +++ b/src/test/moves/magnet_rise.test.ts @@ -1,7 +1,7 @@ import {beforeAll, afterEach, beforeEach, describe, vi, it, expect} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import {Moves} from "#enums/moves"; import {Species} from "#enums/species"; import {CommandPhase, TurnEndPhase} from "#app/phases.js"; @@ -23,13 +23,13 @@ describe("Moves - Magnet Rise", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.MAGNET_RISE; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGNEZONE); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.DRILL_RUN, Moves.DRILL_RUN, Moves.DRILL_RUN, Moves.DRILL_RUN]); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(1); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse, Moves.SPLASH, Moves.GRAVITY, Moves.BATON_PASS]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGNEZONE); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.DRILL_RUN, Moves.DRILL_RUN, Moves.DRILL_RUN, Moves.DRILL_RUN]); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(1); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse, Moves.SPLASH, Moves.GRAVITY, Moves.BATON_PASS]); }); it("MAGNET RISE", async () => { diff --git a/src/test/moves/make_it_rain.test.ts b/src/test/moves/make_it_rain.test.ts index 3bea38201a01..c578a70bb9ce 100644 --- a/src/test/moves/make_it_rain.test.ts +++ b/src/test/moves/make_it_rain.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { CommandPhase, @@ -31,13 +31,13 @@ describe("Moves - Make It Rain", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.MAKE_IT_RAIN, Moves.SPLASH]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.MAKE_IT_RAIN, Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); }); it("should only reduce Sp. Atk. once in a double battle", async () => { @@ -62,9 +62,8 @@ describe("Moves - Make It Rain", () => { }, TIMEOUT); it("should apply effects even if the target faints", async () => { - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(1); // ensures the enemy will faint - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(1); // ensures the enemy will faint + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); await game.startBattle([Species.CHARIZARD]); @@ -83,7 +82,7 @@ describe("Moves - Make It Rain", () => { }, TIMEOUT); it("should reduce Sp. Atk. once after KOing two enemies", async () => { - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(1); // ensures the enemy will faint + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(1); // ensures the enemy will faint await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); diff --git a/src/test/moves/multi_target.test.ts b/src/test/moves/multi_target.test.ts index a43b26065142..7548e9529d1a 100644 --- a/src/test/moves/multi_target.test.ts +++ b/src/test/moves/multi_target.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Moves } from "#enums/moves"; import { getMoveTargets } from "#app/data/move.js"; import { Abilities } from "#app/enums/abilities.js"; @@ -43,10 +43,7 @@ describe("Moves - Multi target", () => { it("1v1 - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, true, true, false), TIMEOUT); - it("2v2 (immune) - target all near others - check modifier", () => { - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.LEVITATE); - checkTargetMultiplier(game, Moves.EARTHQUAKE, false, false, true); - }, TIMEOUT); + it("2v2 (immune) - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, false, false, true, Abilities.LEVITATE), TIMEOUT); it("2v2 (immune) - target all near others - damage decrase", () => checkDamageDecrease(game, Moves.EARTHQUAKE, false, false, true, Abilities.LEVITATE), TIMEOUT); @@ -64,17 +61,15 @@ describe("Moves - Multi target", () => { it("1v1 - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, true, true, false), TIMEOUT); - it("2v2 (immune) - target all near enemies - check modifier", () => { - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SOUNDPROOF); - checkTargetMultiplier(game, Moves.HYPER_VOICE, false, false, true); - }, TIMEOUT); + it("2v2 (immune) - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, false, false, true, Abilities.SOUNDPROOF), TIMEOUT); it("2v2 (immune) - target all near enemies - damage decrase", () => checkDamageDecrease(game, Moves.HYPER_VOICE, false, false, true, Abilities.SOUNDPROOF), TIMEOUT); }); -async function checkTargetMultiplier(game: GameManager, attackMove: Moves, killAlly: boolean, killSecondEnemy: boolean, shouldMultiplied: boolean) { +async function checkTargetMultiplier(game: GameManager, attackMove: Moves, killAlly: boolean, killSecondEnemy: boolean, shouldMultiplied: boolean, oppAbility?: Abilities) { // play an attack and check target count + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(oppAbility ? oppAbility : Abilities.BALL_FETCH); await game.startBattle(); const playerPokemonRepr = game.scene.getPlayerField(); @@ -169,14 +164,14 @@ function leaveOneEnemyPokemon(game: GameManager) { function beforeTrial(phaserGame: Phaser.Game, single: boolean = false) { const game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.EARTHQUAKE, Moves.HYPER_VOICE, Moves.SURF, Moves.SPLASH]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(50); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(40); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.EEVEE); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.EARTHQUAKE, Moves.HYPER_VOICE, Moves.SURF, Moves.SPLASH]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(50); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(40); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.EEVEE); return game; } diff --git a/src/test/moves/octolock.test.ts b/src/test/moves/octolock.test.ts index b0f3b4d3ef7d..af96c2dc8721 100644 --- a/src/test/moves/octolock.test.ts +++ b/src/test/moves/octolock.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, MoveEndPhase, TurnInitPhase } from "#app/phases"; import {getMovePosition} from "#app/test/utils/gameManagerUtils"; import {BattleStat} from "#app/data/battle-stat"; @@ -28,15 +28,15 @@ describe("Moves - Octolock", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.OCTOLOCK, Moves.SPLASH]); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.OCTOLOCK, Moves.SPLASH]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); }); it("Reduces DEf and SPDEF by 1 each turn", { timeout: 10000 }, async () => { diff --git a/src/test/moves/purify.test.ts b/src/test/moves/purify.test.ts index 4addf54fa34f..282d33f85f99 100644 --- a/src/test/moves/purify.test.ts +++ b/src/test/moves/purify.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { MoveEndPhase, } from "#app/phases"; @@ -29,15 +29,15 @@ describe("Moves - Purify", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.PYUKUMUKU); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(10); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.PURIFY, Moves.SIZZLY_SLIDE]); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.PYUKUMUKU); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(10); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.PURIFY, Moves.SIZZLY_SLIDE]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(10); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(10); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); }); test( @@ -55,7 +55,7 @@ describe("Moves - Purify", () => { await game.phaseInterceptor.to(MoveEndPhase); expect(enemyPokemon.status).toBe(undefined); - expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp()); + expect(playerPokemon.isFullHp()).toBe(true); }, TIMEOUT ); diff --git a/src/test/moves/rage_powder.test.ts b/src/test/moves/rage_powder.test.ts index 10469b8d7a98..3c315447b232 100644 --- a/src/test/moves/rage_powder.test.ts +++ b/src/test/moves/rage_powder.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, SelectTargetPhase, @@ -31,19 +31,19 @@ describe("Moves - Rage Powder", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.AMOONGUSS); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.AMOONGUSS); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); test( "move effect should be bypassed by Grass type", async () => { - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER ]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER ]); await game.startBattle([ Species.AMOONGUSS, Species.VENUSAUR ]); @@ -76,8 +76,8 @@ describe("Moves - Rage Powder", () => { test( "move effect should be bypassed by Overcoat", async () => { - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.OVERCOAT); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER ]); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.OVERCOAT); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER ]); // Test with two non-Grass type player Pokemon await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); diff --git a/src/test/moves/reflect.test.ts b/src/test/moves/reflect.test.ts index 8e998e2eb444..9b57b3cdee32 100644 --- a/src/test/moves/reflect.test.ts +++ b/src/test/moves/reflect.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { TurnEndPhase, } from "#app/phases"; @@ -34,13 +34,13 @@ describe("Moves - Reflect", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.ABSORB, Moves.ROCK_SLIDE, Moves.TACKLE]); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.REFLECT, Moves.REFLECT, Moves.REFLECT, Moves.REFLECT]); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.ABSORB, Moves.ROCK_SLIDE, Moves.TACKLE]); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.REFLECT, Moves.REFLECT, Moves.REFLECT, Moves.REFLECT]); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); }); it("reduces damage of physical attacks by half in a single battle", async() => { @@ -56,8 +56,7 @@ describe("Moves - Reflect", () => { }); it("reduces damage of physical attacks by a third in a double battle", async() => { - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); const moveToUse = Moves.ROCK_SLIDE; await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); diff --git a/src/test/moves/rollout.test.ts b/src/test/moves/rollout.test.ts new file mode 100644 index 000000000000..6d8828455e4a --- /dev/null +++ b/src/test/moves/rollout.test.ts @@ -0,0 +1,82 @@ +import { allMoves } from "#app/data/move.js"; +import Overrides from "#app/overrides"; +import { CommandPhase } from "#app/phases"; +import GameManager from "#app/test/utils/gameManager"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { SPLASH_ONLY } from "../utils/testUtils"; + +describe("Moves - Rollout", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.BIDOOF); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(SPLASH_ONLY); + }); + + it("should double it's dmg on sequential uses but reset after 5", async () => { + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.ROLLOUT]); + vi.spyOn(allMoves[Moves.ROLLOUT], "accuracy", "get").mockReturnValue(100); //always hit + + const variance = 5; + const turns = 6; + const dmgHistory: number[] = []; + + await game.startBattle(); + + const playerPkm = game.scene.getParty()[0]; + vi.spyOn(playerPkm, "stats", "get").mockReturnValue([500000, 1, 1, 1, 1, 1]); // HP, ATK, DEF, SPATK, SPDEF, SPD + + const enemyPkm = game.scene.getEnemyParty()[0]; + vi.spyOn(enemyPkm, "stats", "get").mockReturnValue([500000, 1, 1, 1, 1, 1]); // HP, ATK, DEF, SPATK, SPDEF, SPD + vi.spyOn(enemyPkm, "getHeldItems").mockReturnValue([]); //no berries + + enemyPkm.hp = enemyPkm.getMaxHp(); + let previousHp = enemyPkm.hp; + + for (let i = 0; i < turns; i++) { + game.doAttack(getMovePosition(game.scene, 0, Moves.ROLLOUT)); + await game.phaseInterceptor.to(CommandPhase); + + dmgHistory.push(previousHp - enemyPkm.hp); + previousHp = enemyPkm.hp; + } + + const [turn1Dmg, turn2Dmg, turn3Dmg, turn4Dmg, turn5Dmg, turn6Dmg] = dmgHistory; + + expect(turn2Dmg).toBeGreaterThanOrEqual(turn1Dmg * 2 - variance); + expect(turn2Dmg).toBeLessThanOrEqual(turn1Dmg * 2 + variance); + expect(turn3Dmg).toBeGreaterThanOrEqual(turn2Dmg * 2 - variance); + expect(turn3Dmg).toBeLessThanOrEqual(turn2Dmg * 2 + variance); + expect(turn4Dmg).toBeGreaterThanOrEqual(turn3Dmg * 2 - variance); + expect(turn4Dmg).toBeLessThanOrEqual(turn3Dmg * 2 + variance); + expect(turn5Dmg).toBeGreaterThanOrEqual(turn4Dmg * 2 - variance); + expect(turn5Dmg).toBeLessThanOrEqual(turn4Dmg * 2 + variance); + // reset + expect(turn6Dmg).toBeGreaterThanOrEqual(turn1Dmg - variance); + expect(turn6Dmg).toBeLessThanOrEqual(turn1Dmg + variance); + }); +}); diff --git a/src/test/moves/roost.test.ts b/src/test/moves/roost.test.ts index af64fa0b88f1..7f8495e16322 100644 --- a/src/test/moves/roost.test.ts +++ b/src/test/moves/roost.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#app/enums/species.js"; import { Moves } from "#app/enums/moves.js"; import { getMovePosition } from "../utils/gameManagerUtils"; @@ -27,13 +27,13 @@ describe("Moves - Roost", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.STARAPTOR); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.STOMPING_TANTRUM ]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.ROOST,Moves.ROOST,Moves.ROOST,Moves.ROOST]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.STARAPTOR); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.STOMPING_TANTRUM ]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.ROOST,Moves.ROOST,Moves.ROOST,Moves.ROOST]); }); test( diff --git a/src/test/moves/spikes.test.ts b/src/test/moves/spikes.test.ts index cd9d8f88c5d1..44f365ea689f 100644 --- a/src/test/moves/spikes.test.ts +++ b/src/test/moves/spikes.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase } from "#app/phases"; @@ -27,15 +27,15 @@ describe("Moves - Spikes", () => { beforeEach(() => { game = new GameManager(phaserGame); game.scene.battleStyle = 1; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPIKES,Moves.SPLASH, Moves.ROAR]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPIKES,Moves.SPLASH, Moves.ROAR]); }); it("single - wild - stay on field - no damage", async() => { @@ -86,7 +86,7 @@ describe("Moves - Spikes", () => { }, 20000); it("trainer - wild - force switch opponent - should take damage", async() => { - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); // player set spikes on the field and do splash for 3 turns // opponent do splash for 4 turns // nobody should take damage @@ -104,9 +104,9 @@ describe("Moves - Spikes", () => { }, 20000); it("trainer - wild - force switch by himself opponent - should take damage", async() => { - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(5000); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(0); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(5000); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(0); // turn 1: player set spikes, opponent do splash // turn 2: player do splash, opponent switch pokemon // opponent pokemon should trigger spikes and lose HP diff --git a/src/test/moves/spit_up.test.ts b/src/test/moves/spit_up.test.ts new file mode 100644 index 000000000000..f136d8f1e2b6 --- /dev/null +++ b/src/test/moves/spit_up.test.ts @@ -0,0 +1,201 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import overrides from "#app/overrides"; +import { MovePhase, TurnInitPhase } from "#app/phases"; +import { BattleStat } from "#app/data/battle-stat"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StockpilingTag } from "#app/data/battler-tags.js"; +import { MoveResult, TurnMove } from "#app/field/pokemon.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { allMoves } from "#app/data/move.js"; + +describe("Moves - Spit Up", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ type: Phaser.HEADLESS }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + + vi.spyOn(overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPIT_UP, Moves.SPIT_UP, Moves.SPIT_UP, Moves.SPIT_UP]); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + }); + + describe("consumes all stockpile stacks to deal damage (scaling with stacks)", () => { + it("1 stack -> 100 power", { timeout: 10000 }, async () => { + const stacksToSetup = 1; + const expectedPower = 100; + + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + pokemon.addTag(BattlerTagType.STOCKPILING); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeDefined(); + expect(stockpilingTag.stockpiledCount).toBe(stacksToSetup); + + vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); + + game.doAttack(0); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(allMoves[Moves.SPIT_UP].calculateBattlePower).toHaveBeenCalledOnce(); + expect(allMoves[Moves.SPIT_UP].calculateBattlePower).toHaveReturnedWith(expectedPower); + + expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); + }); + + it("2 stacks -> 200 power", { timeout: 10000 }, async () => { + const stacksToSetup = 2; + const expectedPower = 200; + + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + pokemon.addTag(BattlerTagType.STOCKPILING); + pokemon.addTag(BattlerTagType.STOCKPILING); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeDefined(); + expect(stockpilingTag.stockpiledCount).toBe(stacksToSetup); + + vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); + + game.doAttack(0); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(allMoves[Moves.SPIT_UP].calculateBattlePower).toHaveBeenCalledOnce(); + expect(allMoves[Moves.SPIT_UP].calculateBattlePower).toHaveReturnedWith(expectedPower); + + expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); + }); + + it("3 stacks -> 300 power", { timeout: 10000 }, async () => { + const stacksToSetup = 3; + const expectedPower = 300; + + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + pokemon.addTag(BattlerTagType.STOCKPILING); + pokemon.addTag(BattlerTagType.STOCKPILING); + pokemon.addTag(BattlerTagType.STOCKPILING); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeDefined(); + expect(stockpilingTag.stockpiledCount).toBe(stacksToSetup); + + vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); + + game.doAttack(0); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(allMoves[Moves.SPIT_UP].calculateBattlePower).toHaveBeenCalledOnce(); + expect(allMoves[Moves.SPIT_UP].calculateBattlePower).toHaveReturnedWith(expectedPower); + + expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); + }); + }); + + it("fails without stacks", { timeout: 10000 }, async () => { + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeUndefined(); + + vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); + + game.doAttack(0); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(pokemon.getMoveHistory().at(-1)).toMatchObject({ move: Moves.SPIT_UP, result: MoveResult.FAIL }); + + expect(allMoves[Moves.SPIT_UP].calculateBattlePower).not.toHaveBeenCalled(); + }); + + describe("restores stat boosts granted by stacks", () => { + it("decreases stats based on stored values (both boosts equal)", { timeout: 10000 }, async () => { + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + pokemon.addTag(BattlerTagType.STOCKPILING); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeDefined(); + + vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); + + game.doAttack(0); + await game.phaseInterceptor.to(MovePhase); + + expect(pokemon.summonData.battleStats[BattleStat.DEF]).toBe(1); + expect(pokemon.summonData.battleStats[BattleStat.SPDEF]).toBe(1); + + await game.phaseInterceptor.to(TurnInitPhase); + + expect(pokemon.getMoveHistory().at(-1)).toMatchObject({ move: Moves.SPIT_UP, result: MoveResult.SUCCESS }); + + expect(allMoves[Moves.SPIT_UP].calculateBattlePower).toHaveBeenCalledOnce(); + + expect(pokemon.summonData.battleStats[BattleStat.DEF]).toBe(0); + expect(pokemon.summonData.battleStats[BattleStat.SPDEF]).toBe(0); + + expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); + }); + + it("decreases stats based on stored values (different boosts)", { timeout: 10000 }, async () => { + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + pokemon.addTag(BattlerTagType.STOCKPILING); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeDefined(); + + // for the sake of simplicity (and because other tests cover the setup), set boost amounts directly + stockpilingTag.statChangeCounts = { + [BattleStat.DEF]: -1, + [BattleStat.SPDEF]: 2, + }; + + expect(stockpilingTag.statChangeCounts).toMatchObject({ + [BattleStat.DEF]: -1, + [BattleStat.SPDEF]: 2, + }); + + vi.spyOn(allMoves[Moves.SPIT_UP], "calculateBattlePower"); + + game.doAttack(0); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(pokemon.getMoveHistory().at(-1)).toMatchObject({ move: Moves.SPIT_UP, result: MoveResult.SUCCESS }); + + expect(allMoves[Moves.SPIT_UP].calculateBattlePower).toHaveBeenCalledOnce(); + + expect(pokemon.summonData.battleStats[BattleStat.DEF]).toBe(1); + expect(pokemon.summonData.battleStats[BattleStat.SPDEF]).toBe(-2); + + expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); + }); + }); +}); diff --git a/src/test/moves/spotlight.test.ts b/src/test/moves/spotlight.test.ts index f9fb3016ec1e..88d276d3d617 100644 --- a/src/test/moves/spotlight.test.ts +++ b/src/test/moves/spotlight.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, SelectTargetPhase, @@ -31,13 +31,13 @@ describe("Moves - Spotlight", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.AMOONGUSS); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.AMOONGUSS); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); test( @@ -73,7 +73,7 @@ describe("Moves - Spotlight", () => { test( "move should cause other redirection moves to fail", async () => { - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); diff --git a/src/test/moves/stockpile.test.ts b/src/test/moves/stockpile.test.ts new file mode 100644 index 000000000000..1a23017c6b37 --- /dev/null +++ b/src/test/moves/stockpile.test.ts @@ -0,0 +1,116 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import overrides from "#app/overrides"; +import { CommandPhase, TurnInitPhase } from "#app/phases"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; +import { BattleStat } from "#app/data/battle-stat"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StockpilingTag } from "#app/data/battler-tags.js"; +import { MoveResult, TurnMove } from "#app/field/pokemon.js"; + +describe("Moves - Stockpile", () => { + describe("integration tests", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ type: Phaser.HEADLESS }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + + vi.spyOn(overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.STOCKPILE, Moves.SPLASH]); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + }); + + it("Gains a stockpile stack and increases DEF and SPDEF by 1 on each use, fails at max stacks (3)", { timeout: 10000 }, async () => { + await game.startBattle([Species.ABOMASNOW]); + + const user = game.scene.getPlayerPokemon(); + + // Unfortunately, Stockpile stacks are not directly queryable (i.e. there is no pokemon.getStockpileStacks()), + // we just have to know that they're implemented as a BattlerTag. + + expect(user.getTag(StockpilingTag)).toBeUndefined(); + expect(user.summonData.battleStats[BattleStat.DEF]).toBe(0); + expect(user.summonData.battleStats[BattleStat.SPDEF]).toBe(0); + + // use Stockpile four times + for (let i = 0; i < 4; i++) { + if (i !== 0) { + await game.phaseInterceptor.to(CommandPhase); + } + + game.doAttack(getMovePosition(game.scene, 0, Moves.STOCKPILE)); + await game.phaseInterceptor.to(TurnInitPhase); + + const stockpilingTag = user.getTag(StockpilingTag); + const def = user.summonData.battleStats[BattleStat.DEF]; + const spdef = user.summonData.battleStats[BattleStat.SPDEF]; + + if (i < 3) { // first three uses should behave normally + expect(def).toBe(i + 1); + expect(spdef).toBe(i + 1); + expect(stockpilingTag).toBeDefined(); + expect(stockpilingTag.stockpiledCount).toBe(i + 1); + + } else { // fourth should have failed + expect(def).toBe(3); + expect(spdef).toBe(3); + expect(stockpilingTag).toBeDefined(); + expect(stockpilingTag.stockpiledCount).toBe(3); + expect(user.getMoveHistory().at(-1)).toMatchObject({ result: MoveResult.FAIL, move: Moves.STOCKPILE }); + } + } + }); + + it("Gains a stockpile stack even if DEF and SPDEF are at +6", { timeout: 10000 }, async () => { + await game.startBattle([Species.ABOMASNOW]); + + const user = game.scene.getPlayerPokemon(); + + user.summonData.battleStats[BattleStat.DEF] = 6; + user.summonData.battleStats[BattleStat.SPDEF] = 6; + + expect(user.getTag(StockpilingTag)).toBeUndefined(); + expect(user.summonData.battleStats[BattleStat.DEF]).toBe(6); + expect(user.summonData.battleStats[BattleStat.SPDEF]).toBe(6); + + game.doAttack(getMovePosition(game.scene, 0, Moves.STOCKPILE)); + await game.phaseInterceptor.to(TurnInitPhase); + + const stockpilingTag = user.getTag(StockpilingTag); + expect(stockpilingTag).toBeDefined(); + expect(stockpilingTag.stockpiledCount).toBe(1); + expect(user.summonData.battleStats[BattleStat.DEF]).toBe(6); + expect(user.summonData.battleStats[BattleStat.SPDEF]).toBe(6); + + // do it again, just for good measure + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 0, Moves.STOCKPILE)); + await game.phaseInterceptor.to(TurnInitPhase); + + const stockpilingTagAgain = user.getTag(StockpilingTag); + expect(stockpilingTagAgain).toBeDefined(); + expect(stockpilingTagAgain.stockpiledCount).toBe(2); + expect(user.summonData.battleStats[BattleStat.DEF]).toBe(6); + expect(user.summonData.battleStats[BattleStat.SPDEF]).toBe(6); + }); + }); +}); diff --git a/src/test/moves/swallow.test.ts b/src/test/moves/swallow.test.ts new file mode 100644 index 000000000000..0dd4237c2329 --- /dev/null +++ b/src/test/moves/swallow.test.ts @@ -0,0 +1,197 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import overrides from "#app/overrides"; +import { MovePhase, TurnInitPhase } from "#app/phases"; +import { BattleStat } from "#app/data/battle-stat"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StockpilingTag } from "#app/data/battler-tags.js"; +import { MoveResult, TurnMove } from "#app/field/pokemon.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; + +describe("Moves - Swallow", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ type: Phaser.HEADLESS }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + + vi.spyOn(overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SWALLOW, Moves.SWALLOW, Moves.SWALLOW, Moves.SWALLOW]); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + }); + + describe("consumes all stockpile stacks to heal (scaling with stacks)", () => { + it("1 stack -> 25% heal", { timeout: 10000 }, async () => { + const stacksToSetup = 1; + const expectedHeal = 25; + + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + vi.spyOn(pokemon, "getMaxHp").mockReturnValue(100); + pokemon["hp"] = 1; + + pokemon.addTag(BattlerTagType.STOCKPILING); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeDefined(); + expect(stockpilingTag.stockpiledCount).toBe(stacksToSetup); + + vi.spyOn(pokemon, "heal"); + + game.doAttack(0); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(pokemon.heal).toHaveBeenCalledOnce(); + expect(pokemon.heal).toHaveReturnedWith(expectedHeal); + + expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); + }); + + it("2 stacks -> 50% heal", { timeout: 10000 }, async () => { + const stacksToSetup = 2; + const expectedHeal = 50; + + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + vi.spyOn(pokemon, "getMaxHp").mockReturnValue(100); + pokemon["hp"] = 1; + + pokemon.addTag(BattlerTagType.STOCKPILING); + pokemon.addTag(BattlerTagType.STOCKPILING); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeDefined(); + expect(stockpilingTag.stockpiledCount).toBe(stacksToSetup); + + vi.spyOn(pokemon, "heal"); + + game.doAttack(0); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(pokemon.heal).toHaveBeenCalledOnce(); + expect(pokemon.heal).toHaveReturnedWith(expectedHeal); + + expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); + }); + + it("3 stacks -> 100% heal", { timeout: 10000 }, async () => { + const stacksToSetup = 3; + const expectedHeal = 100; + + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + vi.spyOn(pokemon, "getMaxHp").mockReturnValue(100); + pokemon["hp"] = 0.0001; + + pokemon.addTag(BattlerTagType.STOCKPILING); + pokemon.addTag(BattlerTagType.STOCKPILING); + pokemon.addTag(BattlerTagType.STOCKPILING); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeDefined(); + expect(stockpilingTag.stockpiledCount).toBe(stacksToSetup); + + vi.spyOn(pokemon, "heal"); + + game.doAttack(0); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(pokemon.heal).toHaveBeenCalledOnce(); + expect(pokemon.heal).toHaveReturnedWith(expect.closeTo(expectedHeal)); + + expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); + }); + }); + + it("fails without stacks", { timeout: 10000 }, async () => { + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeUndefined(); + + game.doAttack(0); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(pokemon.getMoveHistory().at(-1)).toMatchObject({ move: Moves.SWALLOW, result: MoveResult.FAIL }); + }); + + describe("restores stat boosts granted by stacks", () => { + it("decreases stats based on stored values (both boosts equal)", { timeout: 10000 }, async () => { + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + pokemon.addTag(BattlerTagType.STOCKPILING); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeDefined(); + + game.doAttack(0); + await game.phaseInterceptor.to(MovePhase); + + expect(pokemon.summonData.battleStats[BattleStat.DEF]).toBe(1); + expect(pokemon.summonData.battleStats[BattleStat.SPDEF]).toBe(1); + + await game.phaseInterceptor.to(TurnInitPhase); + + expect(pokemon.getMoveHistory().at(-1)).toMatchObject({ move: Moves.SWALLOW, result: MoveResult.SUCCESS }); + + expect(pokemon.summonData.battleStats[BattleStat.DEF]).toBe(0); + expect(pokemon.summonData.battleStats[BattleStat.SPDEF]).toBe(0); + + expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); + }); + + it("decreases stats based on stored values (different boosts)", { timeout: 10000 }, async () => { + await game.startBattle([Species.ABOMASNOW]); + + const pokemon = game.scene.getPlayerPokemon(); + pokemon.addTag(BattlerTagType.STOCKPILING); + + const stockpilingTag = pokemon.getTag(StockpilingTag); + expect(stockpilingTag).toBeDefined(); + + // for the sake of simplicity (and because other tests cover the setup), set boost amounts directly + stockpilingTag.statChangeCounts = { + [BattleStat.DEF]: -1, + [BattleStat.SPDEF]: 2, + }; + + expect(stockpilingTag.statChangeCounts).toMatchObject({ + [BattleStat.DEF]: -1, + [BattleStat.SPDEF]: 2, + }); + + game.doAttack(0); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(pokemon.getMoveHistory().at(-1)).toMatchObject({ move: Moves.SWALLOW, result: MoveResult.SUCCESS }); + + expect(pokemon.summonData.battleStats[BattleStat.DEF]).toBe(1); + expect(pokemon.summonData.battleStats[BattleStat.SPDEF]).toBe(-2); + + expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); + }); + }); +}); diff --git a/src/test/moves/tackle.test.ts b/src/test/moves/tackle.test.ts index d01c62c3db92..f4b335d95764 100644 --- a/src/test/moves/tackle.test.ts +++ b/src/test/moves/tackle.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, EnemyCommandPhase, TurnEndPhase, @@ -31,18 +31,18 @@ describe("Moves - Tackle", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.TACKLE; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(1); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(97); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.GROWTH,Moves.GROWTH,Moves.GROWTH,Moves.GROWTH]); - vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(1); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(97); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.GROWTH,Moves.GROWTH,Moves.GROWTH,Moves.GROWTH]); + vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); }); it("TACKLE against ghost", async() => { const moveToUse = Moves.TACKLE; - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.GENGAR); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.GENGAR); await game.startBattle([ Species.MIGHTYENA, ]); diff --git a/src/test/moves/tail_whip.test.ts b/src/test/moves/tail_whip.test.ts index a1c9dba0bab5..662746db4ebc 100644 --- a/src/test/moves/tail_whip.test.ts +++ b/src/test/moves/tail_whip.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { CommandPhase, EnemyCommandPhase, @@ -33,13 +33,13 @@ describe("Moves - Tail whip", () => { beforeEach(() => { game = new GameManager(phaserGame); const moveToUse = Moves.TAIL_WHIP; - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.INSOMNIA); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); }); it("TAIL_WHIP", async() => { diff --git a/src/test/moves/tailwind.test.ts b/src/test/moves/tailwind.test.ts index 6f700e761704..535d0a1e525f 100644 --- a/src/test/moves/tailwind.test.ts +++ b/src/test/moves/tailwind.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { Species } from "#enums/species"; import { TurnEndPhase, @@ -28,9 +28,9 @@ describe("Abilities - Wind Rider", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double"); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); }); it("doubles the Speed stat of the Pokemons on its side", async () => { @@ -55,8 +55,7 @@ describe("Abilities - Wind Rider", () => { }); it("lasts for 4 turns", async () => { - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); await game.startBattle([Species.MAGIKARP]); @@ -79,8 +78,7 @@ describe("Abilities - Wind Rider", () => { }); it("does not affect the opposing side", async () => { - vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(false); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); await game.startBattle([Species.MAGIKARP]); diff --git a/src/test/moves/thousand_arrows.test.ts b/src/test/moves/thousand_arrows.test.ts index b46bef9626f9..950e52289280 100644 --- a/src/test/moves/thousand_arrows.test.ts +++ b/src/test/moves/thousand_arrows.test.ts @@ -1,10 +1,10 @@ -import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { - MoveEffectPhase, - TurnEndPhase + BerryPhase, + MoveEffectPhase } from "#app/phases"; import {getMovePosition} from "#app/test/utils/gameManagerUtils"; import { Moves } from "#enums/moves"; @@ -30,26 +30,20 @@ describe("Moves - Thousand Arrows", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.TOGETIC); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.THOUSAND_ARROWS ]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.TOGETIC); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.THOUSAND_ARROWS ]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH,Moves.SPLASH,Moves.SPLASH,Moves.SPLASH]); }); - test( + it( "move should hit and ground Flying-type targets", async () => { await game.startBattle([ Species.ILLUMISE ]); - const leadPokemon = game.scene.getPlayerPokemon(); - expect(leadPokemon).toBeDefined(); - const enemyPokemon = game.scene.getEnemyPokemon(); - expect(enemyPokemon).toBeDefined(); - - const enemyStartingHp = enemyPokemon.hp; game.doAttack(getMovePosition(game.scene, 0, Moves.THOUSAND_ARROWS)); @@ -57,28 +51,22 @@ describe("Moves - Thousand Arrows", () => { // Enemy should not be grounded before move effect is applied expect(enemyPokemon.getTag(BattlerTagType.IGNORE_FLYING)).toBeUndefined(); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to(BerryPhase, false); expect(enemyPokemon.getTag(BattlerTagType.IGNORE_FLYING)).toBeDefined(); - expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); }, TIMEOUT ); - test( + it( "move should hit and ground targets with Levitate", async () => { - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.LEVITATE); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.LEVITATE); await game.startBattle([ Species.ILLUMISE ]); - const leadPokemon = game.scene.getPlayerPokemon(); - expect(leadPokemon).toBeDefined(); - const enemyPokemon = game.scene.getEnemyPokemon(); - expect(enemyPokemon).toBeDefined(); - - const enemyStartingHp = enemyPokemon.hp; game.doAttack(getMovePosition(game.scene, 0, Moves.THOUSAND_ARROWS)); @@ -86,10 +74,31 @@ describe("Moves - Thousand Arrows", () => { // Enemy should not be grounded before move effect is applied expect(enemyPokemon.getTag(BattlerTagType.IGNORE_FLYING)).toBeUndefined(); - await game.phaseInterceptor.to(TurnEndPhase, false); + await game.phaseInterceptor.to(BerryPhase, false); expect(enemyPokemon.getTag(BattlerTagType.IGNORE_FLYING)).toBeDefined(); - expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); }, TIMEOUT ); + + it( + "move should hit and ground targets under the effects of Magnet Rise", + async () => { + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + + await game.startBattle([ Species.ILLUMISE ]); + + const enemyPokemon = game.scene.getEnemyPokemon(); + + enemyPokemon.addTag(BattlerTagType.MAGNET_RISEN, null, Moves.MAGNET_RISE); + + game.doAttack(getMovePosition(game.scene, 0, Moves.THOUSAND_ARROWS)); + + await game.phaseInterceptor.to(BerryPhase, false); + + expect(enemyPokemon.getTag(BattlerTagType.MAGNET_RISEN)).toBeUndefined(); + expect(enemyPokemon.getTag(BattlerTagType.IGNORE_FLYING)).toBeDefined(); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); + } + ); }); diff --git a/src/test/moves/tidy_up.test.ts b/src/test/moves/tidy_up.test.ts index 2dea945acc66..16312ce431a4 100644 --- a/src/test/moves/tidy_up.test.ts +++ b/src/test/moves/tidy_up.test.ts @@ -1,7 +1,7 @@ import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import Phaser from "phaser"; import GameManager from "#app/test/utils/gameManager"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { MoveEndPhase, TurnEndPhase } from "#app/phases"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; @@ -27,19 +27,19 @@ describe("Moves - Tidy Up", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); - vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.FEEBAS); - vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TIDY_UP]); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(50); + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.FEEBAS); + vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TIDY_UP]); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(50); }); it("spikes are cleared", async() => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPIKES, Moves.TIDY_UP]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPIKES, Moves.SPIKES, Moves.SPIKES, Moves.SPIKES]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPIKES, Moves.TIDY_UP]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPIKES, Moves.SPIKES, Moves.SPIKES, Moves.SPIKES]); await game.startBattle(); game.doAttack(getMovePosition(game.scene, 0, Moves.SPIKES)); @@ -51,8 +51,8 @@ describe("Moves - Tidy Up", () => { }, 20000); it("stealth rocks are cleared", async() => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.STEALTH_ROCK, Moves.TIDY_UP]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.STEALTH_ROCK, Moves.STEALTH_ROCK, Moves.STEALTH_ROCK, Moves.STEALTH_ROCK]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.STEALTH_ROCK, Moves.TIDY_UP]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.STEALTH_ROCK, Moves.STEALTH_ROCK, Moves.STEALTH_ROCK, Moves.STEALTH_ROCK]); await game.startBattle(); game.doAttack(getMovePosition(game.scene, 0, Moves.STEALTH_ROCK)); @@ -64,8 +64,8 @@ describe("Moves - Tidy Up", () => { }, 20000); it("toxic spikes are cleared", async() => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TOXIC_SPIKES, Moves.TIDY_UP]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TOXIC_SPIKES, Moves.TIDY_UP]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES]); await game.startBattle(); game.doAttack(getMovePosition(game.scene, 0, Moves.TOXIC_SPIKES)); @@ -77,8 +77,8 @@ describe("Moves - Tidy Up", () => { }, 20000); it("sticky webs are cleared", async() => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.STICKY_WEB, Moves.TIDY_UP]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.STICKY_WEB, Moves.STICKY_WEB, Moves.STICKY_WEB, Moves.STICKY_WEB]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.STICKY_WEB, Moves.TIDY_UP]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.STICKY_WEB, Moves.STICKY_WEB, Moves.STICKY_WEB, Moves.STICKY_WEB]); await game.startBattle(); @@ -91,8 +91,8 @@ describe("Moves - Tidy Up", () => { }, 20000); it.skip("substitutes are cleared", async() => { - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SUBSTITUTE, Moves.TIDY_UP]); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SUBSTITUTE, Moves.SUBSTITUTE, Moves.SUBSTITUTE, Moves.SUBSTITUTE]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SUBSTITUTE, Moves.TIDY_UP]); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SUBSTITUTE, Moves.SUBSTITUTE, Moves.SUBSTITUTE, Moves.SUBSTITUTE]); await game.startBattle(); diff --git a/src/test/ui/starter-select.test.ts b/src/test/ui/starter-select.test.ts index 2b5df315a701..95a4605fd68d 100644 --- a/src/test/ui/starter-select.test.ts +++ b/src/test/ui/starter-select.test.ts @@ -54,6 +54,7 @@ describe("UI - Starter select", () => { game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; handler.processInput(Button.RIGHT); + handler.processInput(Button.LEFT); handler.processInput(Button.ACTION); game.phaseInterceptor.unlock(); }); @@ -113,6 +114,7 @@ describe("UI - Starter select", () => { game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; handler.processInput(Button.RIGHT); + handler.processInput(Button.LEFT); handler.processInput(Button.CYCLE_GENDER); handler.processInput(Button.ACTION); game.phaseInterceptor.unlock(); @@ -174,6 +176,7 @@ describe("UI - Starter select", () => { game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; handler.processInput(Button.RIGHT); + handler.processInput(Button.LEFT); handler.processInput(Button.CYCLE_GENDER); handler.processInput(Button.CYCLE_NATURE); handler.processInput(Button.CYCLE_ABILITY); @@ -237,6 +240,7 @@ describe("UI - Starter select", () => { game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; handler.processInput(Button.RIGHT); + handler.processInput(Button.LEFT); handler.processInput(Button.CYCLE_GENDER); handler.processInput(Button.ACTION); game.phaseInterceptor.unlock(); @@ -297,6 +301,7 @@ describe("UI - Starter select", () => { game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; handler.processInput(Button.RIGHT); + handler.processInput(Button.LEFT); handler.processInput(Button.CYCLE_SHINY); handler.processInput(Button.ACTION); game.phaseInterceptor.unlock(); @@ -356,6 +361,7 @@ describe("UI - Starter select", () => { game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; handler.processInput(Button.RIGHT); + handler.processInput(Button.LEFT); handler.processInput(Button.V); handler.processInput(Button.V); handler.processInput(Button.ACTION); @@ -416,6 +422,7 @@ describe("UI - Starter select", () => { game.onNextPrompt("SelectStarterPhase", Mode.STARTER_SELECT, () => { const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; handler.processInput(Button.RIGHT); + handler.processInput(Button.LEFT); handler.processInput(Button.V); handler.processInput(Button.V); handler.processInput(Button.V); @@ -479,7 +486,6 @@ describe("UI - Starter select", () => { handler.processInput(Button.RIGHT); handler.processInput(Button.RIGHT); handler.processInput(Button.RIGHT); - handler.processInput(Button.RIGHT); handler.processInput(Button.ACTION); game.phaseInterceptor.unlock(); }); @@ -509,10 +515,10 @@ describe("UI - Starter select", () => { }); }); - expect(starterSelectUiHandler.starterGens[0]).toBe(0); - expect(starterSelectUiHandler.starterCursors[0]).toBe(3); - expect(starterSelectUiHandler.cursorObj.x).toBe(132 + 4 * 18); - expect(starterSelectUiHandler.cursorObj.y).toBe(10); + // expect(starterSelectUiHandler.starterGens[0]).toBe(0); + // expect(starterSelectUiHandler.starterCursors[0]).toBe(3); + // expect(starterSelectUiHandler.cursorObj.x).toBe(132 + 4 * 18); + // expect(starterSelectUiHandler.cursorObj.y).toBe(10); game.onNextPrompt("SelectStarterPhase", Mode.CONFIRM, () => { const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; @@ -544,7 +550,6 @@ describe("UI - Starter select", () => { handler.processInput(Button.RIGHT); handler.processInput(Button.RIGHT); handler.processInput(Button.RIGHT); - handler.processInput(Button.RIGHT); handler.processInput(Button.DOWN); handler.processInput(Button.ACTION); game.phaseInterceptor.unlock(); @@ -575,10 +580,11 @@ describe("UI - Starter select", () => { }); }); - expect(starterSelectUiHandler.starterGens[0]).toBe(0); - expect(starterSelectUiHandler.starterCursors[0]).toBe(12); - expect(starterSelectUiHandler.cursorObj.x).toBe(132 + 4 * 18); - expect(starterSelectUiHandler.cursorObj.y).toBe(28); + expect(starterSelectUiHandler.starterSpecies.length).toBe(1); + expect(starterSelectUiHandler.starterSpecies[0].generation).toBe(1); + expect(starterSelectUiHandler.starterSpecies[0].speciesId).toBe(32); + expect(starterSelectUiHandler.cursorObj.x).toBe(53); + expect(starterSelectUiHandler.cursorObj.y).toBe(31); game.onNextPrompt("SelectStarterPhase", Mode.CONFIRM, () => { const handler = game.scene.ui.getHandler() as StarterSelectUiHandler; diff --git a/src/test/ui/transfer-item.test.ts b/src/test/ui/transfer-item.test.ts index cc39540ae4f8..c20fa51aff9d 100644 --- a/src/test/ui/transfer-item.test.ts +++ b/src/test/ui/transfer-item.test.ts @@ -2,7 +2,7 @@ import { BerryType } from "#app/enums/berry-type"; import { Moves } from "#app/enums/moves"; import { Species } from "#app/enums/species"; import { Button } from "#app/enums/buttons"; -import overrides from "#app/overrides"; +import Overrides from "#app/overrides"; import { BattleEndPhase, SelectModifierPhase @@ -33,17 +33,17 @@ describe("UI - Transfer Items", () => { beforeEach(async () => { game = new GameManager(phaserGame); - vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); - vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); - vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(1); - vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([ + vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single"); + vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(1); + vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([ { name: "BERRY", count: 1, type: BerryType.SITRUS }, { name: "BERRY", count: 2, type: BerryType.APICOT }, { name: "BERRY", count: 2, type: BerryType.LUM }, ]); - vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.DRAGON_CLAW]); - vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); - vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]); + vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.DRAGON_CLAW]); + vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP); + vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]); await game.startBattle([Species.RAYQUAZA, Species.RAYQUAZA, Species.RAYQUAZA]); diff --git a/src/test/utils/mocks/mocksContainer/mockSprite.ts b/src/test/utils/mocks/mocksContainer/mockSprite.ts index 2eb77f813025..3a5de09b2589 100644 --- a/src/test/utils/mocks/mocksContainer/mockSprite.ts +++ b/src/test/utils/mocks/mocksContainer/mockSprite.ts @@ -90,6 +90,10 @@ export default class MockSprite { return this.phaserSprite.setPosition(x, y); } + setRotation(radians) { + return this.phaserSprite.setRotation(radians); + } + stop() { return this.phaserSprite.stop(); } diff --git a/src/test/utils/testUtils.ts b/src/test/utils/testUtils.ts index b922fc9c61ca..0a9be16a4b53 100644 --- a/src/test/utils/testUtils.ts +++ b/src/test/utils/testUtils.ts @@ -1,6 +1,10 @@ +import { Moves } from "#app/enums/moves.js"; import i18next, { type ParseKeys } from "i18next"; import { vi } from "vitest"; +/** Ready to use array of Moves.SPLASH x4 */ +export const SPLASH_ONLY = [Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]; + /** * Sets up the i18next mock. * Includes a i18next.t mocked implementation only returning the raw key (`(key) => key`) @@ -21,3 +25,4 @@ export function mockI18next() { export function arrayOfRange(start: integer, end: integer) { return Array.from({ length: end - start }, (_v, k) => k + start); } + diff --git a/src/ui/ability-bar.ts b/src/ui/ability-bar.ts index a0b249695b99..7a4ae5599750 100644 --- a/src/ui/ability-bar.ts +++ b/src/ui/ability-bar.ts @@ -1,3 +1,4 @@ +import { getPokemonNameWithAffix } from "#app/messages.js"; import BattleScene from "../battle-scene"; import Pokemon from "../field/pokemon"; import { TextStyle, addTextObject } from "./text"; @@ -36,7 +37,7 @@ export default class AbilityBar extends Phaser.GameObjects.Container { } showAbility(pokemon: Pokemon, passive: boolean = false): void { - this.abilityBarText.setText(`${i18next.t("fightUiHandler:abilityFlyInText", { pokemonName: pokemon.name, passive: passive ? i18next.t("fightUiHandler:passive") : "", abilityName: !passive ? pokemon.getAbility().name : pokemon.getPassiveAbility().name })}`); + this.abilityBarText.setText(`${i18next.t("fightUiHandler:abilityFlyInText", { pokemonName: getPokemonNameWithAffix(pokemon), passive: passive ? i18next.t("fightUiHandler:passive") : "", abilityName: !passive ? pokemon.getAbility().name : pokemon.getPassiveAbility().name })}`); if (this.shown) { return; diff --git a/src/ui/battle-flyout.ts b/src/ui/battle-flyout.ts index 5b34a6b54115..fdce96617938 100644 --- a/src/ui/battle-flyout.ts +++ b/src/ui/battle-flyout.ts @@ -7,6 +7,7 @@ import { BattleSceneEventType, BerryUsedEvent, MoveUsedEvent } from "../events/b import { BerryType } from "#enums/berry-type"; import { Moves } from "#enums/moves"; import { UiTheme } from "#enums/ui-theme"; +import { getPokemonNameWithAffix } from "#app/messages.js"; /** Container for info about a {@linkcode Move} */ interface MoveInfo { @@ -113,8 +114,8 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { initInfo(pokemon: Pokemon) { this.pokemon = pokemon; - this.name = `Flyout ${this.pokemon.name}`; - this.flyoutParent.name = `Flyout Parent ${this.pokemon.name}`; + this.name = `Flyout ${getPokemonNameWithAffix(this.pokemon)}`; + this.flyoutParent.name = `Flyout Parent ${getPokemonNameWithAffix(this.pokemon)}`; this.battleScene.eventTarget.addEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsedEvent); this.battleScene.eventTarget.addEventListener(BattleSceneEventType.BERRY_USED, this.onBerryUsedEvent); diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index 6d90e0b4fe28..2ac350e2b14d 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -278,8 +278,8 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.updateNameText(pokemon); const nameTextWidth = this.nameText.displayWidth; - this.name = pokemon.name; - this.box.name = pokemon.name; + this.name = pokemon.getNameToRender(); + this.box.name = pokemon.getNameToRender(); this.flyoutMenu?.initInfo(pokemon); @@ -507,7 +507,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { return resolve(); } - const nameUpdated = this.lastName !== pokemon.name; + const nameUpdated = this.lastName !== pokemon.getNameToRender(); if (nameUpdated) { this.updateNameText(pokemon); @@ -634,7 +634,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { } updateNameText(pokemon: Pokemon): void { - let displayName = pokemon.name.replace(/[♂♀]/g, ""); + let displayName = pokemon.getNameToRender().replace(/[♂♀]/g, ""); let nameTextWidth: number; const nameSizeTest = addTextObject(this.scene, 0, 0, displayName, TextStyle.BATTLE_INFO); @@ -649,7 +649,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { nameSizeTest.destroy(); this.nameText.setText(displayName); - this.lastName = pokemon.name; + this.lastName = pokemon.getNameToRender(); if (this.nameText.visible) { this.nameText.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.nameText.width, this.nameText.height), Phaser.Geom.Rectangle.Contains); diff --git a/src/ui/command-ui-handler.ts b/src/ui/command-ui-handler.ts index 8ccd05675c86..f083acd2f5bc 100644 --- a/src/ui/command-ui-handler.ts +++ b/src/ui/command-ui-handler.ts @@ -6,6 +6,7 @@ import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import i18next from "i18next"; import {Button} from "#enums/buttons"; +import { getPokemonNameWithAffix } from "#app/messages.js"; export enum Command { FIGHT = 0, @@ -66,7 +67,7 @@ export default class CommandUiHandler extends UiHandler { messageHandler.commandWindow.setVisible(true); messageHandler.movesWindowContainer.setVisible(false); messageHandler.message.setWordWrapWidth(1110); - messageHandler.showText(i18next.t("commandUiHandler:actionMessage", {pokemonName: commandPhase.getPokemon().name}), 0); + messageHandler.showText(i18next.t("commandUiHandler:actionMessage", {pokemonName: getPokemonNameWithAffix(commandPhase.getPokemon())}), 0); this.setCursor(this.getCursor()); return true; diff --git a/src/ui/confirm-ui-handler.ts b/src/ui/confirm-ui-handler.ts index 953ed4972acb..2d83508384b7 100644 --- a/src/ui/confirm-ui-handler.ts +++ b/src/ui/confirm-ui-handler.ts @@ -4,6 +4,7 @@ import { Mode } from "./ui"; import i18next from "i18next"; import {Button} from "#enums/buttons"; + export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { public static readonly windowWidth: integer = 48; @@ -20,7 +21,44 @@ export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { } show(args: any[]): boolean { - if (args.length >= 2 && args[0] instanceof Function && args[1] instanceof Function) { + if (args.length === 4 && args[0] instanceof Function && args[1] instanceof Function && args[2] instanceof Function && args[3] === "fullParty") { + const config: OptionSelectConfig = { + options: [ + { + label: i18next.t("partyUiHandler:SUMMARY"), + handler: () => { + args[0](); + return false; + }, + }, { + label: i18next.t("menu:yes"), + handler: () => { + args[1](); + return true; + } + }, { + label: i18next.t("menu:no"), + handler: () => { + args[2](); + return true; + } + } + ], + delay: args.length >= 8 && args[7] !== null ? args[7] as integer : 0 + }; + + super.show([ config ]); + + this.switchCheck = args.length >= 5 && args[4] !== null && args[4] as boolean; + + const xOffset = (args.length >= 6 && args[5] !== null ? args[5] as number : 0); + const yOffset = (args.length >= 7 && args[6] !== null ? args[6] as number : 0); + + this.optionSelectContainer.setPosition((this.scene.game.canvas.width / 6) - 1 + xOffset, -48 + yOffset); + + this.setCursor(this.switchCheck ? this.switchCheckCursor : 0); + return true; + } else if (args.length >= 2 && args[0] instanceof Function && args[1] instanceof Function) { const config: OptionSelectConfig = { options: [ { @@ -54,7 +92,6 @@ export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { return true; } - return false; } diff --git a/src/ui/dropdown.ts b/src/ui/dropdown.ts new file mode 100644 index 000000000000..77f4ef91ecbc --- /dev/null +++ b/src/ui/dropdown.ts @@ -0,0 +1,253 @@ +import BattleScene from "#app/battle-scene.js"; +import { SceneBase } from "#app/scene-base.js"; +import { addTextObject, TextStyle } from "./text"; +import { addWindow, WindowVariant } from "./ui-theme"; + +export enum DropDownState { + ON = 0, + OFF +} + +export enum DropDownType { + MULTI = 0, + SINGLE +} + +export enum SortDirection { + ASC = -1, + DESC = 1 +} + +export class DropDownOption extends Phaser.GameObjects.Container { + public state: DropDownState = DropDownState.ON; + public toggle: Phaser.GameObjects.Sprite; + public text: Phaser.GameObjects.Text; + public sprite?: Phaser.GameObjects.Sprite; + public val: any; + public dir: SortDirection = SortDirection.ASC; + + constructor(scene: SceneBase, val: any, text: string, sprite?: Phaser.GameObjects.Sprite, state: DropDownState = DropDownState.ON) { + super(scene); + this.val = val; + if (text) { + this.text = addTextObject(scene, 0, 0, text, TextStyle.TOOLTIP_CONTENT); + this.text.setOrigin(0, 0.5); + this.add(this.text); + } + + if (sprite) { + this.sprite = sprite.setOrigin(0, 0.5); + this.add(this.sprite); + } + this.state = state; + } + + public setupToggle(type: DropDownType): void { + if (type === DropDownType.MULTI) { + this.toggle = this.scene.add.sprite(0, 0, "candy"); + this.toggle.setScale(0.3); + this.toggle.setOrigin(0, 0.5); + } else { + this.toggle = this.scene.add.sprite(0, 0, "cursor"); + this.toggle.setScale(0.5); + this.toggle.setOrigin(0, 0.5); + this.toggle.setRotation(Math.PI / 180 * -90); + } + this.add(this.toggle); + } + + public setOptionState(state: DropDownState): DropDownState { + this.state = state % 2; + if (this.state === DropDownState.OFF) { + this.toggle.setTint(0x272727); + } else { + this.toggle.setTint(0x55ff55); + } + return this.state; + } + + public toggleOptionState(): DropDownState { + return this.setOptionState(this.state + 1); + } + + public setDirection(dir: SortDirection): void { + this.dir = dir; + this.toggle.flipX = this.dir === SortDirection.DESC; + } + + public toggleDirection(): void { + this.setDirection(this.dir * -1); + } +} + +export class DropDown extends Phaser.GameObjects.Container { + public options: DropDownOption[]; + private window: Phaser.GameObjects.NineSlice; + private cursorObj: Phaser.GameObjects.Image; + private dropDownType: DropDownType = DropDownType.MULTI; + public cursor: integer = 0; + private onChange: () => void; + private lastDir: SortDirection = SortDirection.ASC; + + constructor(scene: BattleScene, x: number, y: number, options: DropDownOption[], onChange: () => void, type: DropDownType = DropDownType.MULTI, optionSpacing: number = 2) { + const windowPadding = 5; + const optionHeight = 7; + const optionPaddingX = 4; + const optionPaddingY = 6; + const cursorOffset = 7; + const optionWidth = 100; + + super(scene, x - cursorOffset - windowPadding, y); + this.options = options; + this.dropDownType = type; + this.onChange = onChange; + + this.cursorObj = scene.add.image(optionPaddingX + 3, 0, "cursor"); + this.cursorObj.setScale(0.5); + this.cursorObj.setOrigin(0, 0.5); + this.cursorObj.setVisible(false); + + if (this.dropDownType === DropDownType.MULTI) { + this.options.unshift(new DropDownOption(scene, "ALL", "All", null, this.checkForAllOn() ? DropDownState.ON : DropDownState.OFF)); + } + + options.forEach((option, index) => { + option.setupToggle(type); + if (type === DropDownType.SINGLE && option.state === DropDownState.OFF) { + option.toggle.setVisible(false); + } + option.setOptionState(option.state); + + option.width = optionWidth; + option.y = index * optionHeight + index * optionSpacing + optionPaddingY; + + if (option.text) { + option.text.x = cursorOffset + optionPaddingX + 3 + 8; + option.text.y = optionHeight / 2; + } + if (option.sprite) { + option.sprite.x = cursorOffset + optionPaddingX + 3 + 8; + option.sprite.y = optionHeight / 2; + } + option.toggle.x = cursorOffset + optionPaddingX + 3 + (type === DropDownType.MULTI ? 0 : 3); + option.toggle.y = optionHeight / 2 + (type === DropDownType.MULTI ? 0 : 1); + }); + this.window = addWindow(scene, 0, 0, optionWidth, options[options.length - 1].y + optionHeight + optionPaddingY, false, false, null, null, WindowVariant.XTHIN); + this.add(this.window); + this.add(options); + this.add(this.cursorObj); + this.setVisible(false); + } + + toggle(): void { + this.setVisible(!this.visible); + } + + setCursor(cursor: integer): boolean { + this.cursor = cursor; + if (cursor < 0) { + cursor = 0; + this.cursorObj.setVisible(false); + return false; + } else if (cursor >= this.options.length) { + cursor = this.options.length - 1; + this.cursorObj.y = this.options[cursor].y + 3.5; + this.cursorObj.setVisible(true); + return false; + } else { + this.cursorObj.y = this.options[cursor].y + 3.5; + this.cursorObj.setVisible(true); + } + return true; + } + + toggleOptionState(): void { + if (this.dropDownType === DropDownType.MULTI) { + const newState = this.options[this.cursor].toggleOptionState(); + + if (this.cursor === 0) { + this.options.forEach((option, index) => { + if (index !== this.cursor) { + option.setOptionState(newState); + } + }); + } else { + if (this.checkForAllOff()) { + this.options[0].setOptionState(DropDownState.OFF); + } else if (this.checkForAllOn()) { + this.options[0].setOptionState(DropDownState.ON); + } + } + } else { + if (this.options[this.cursor].state === DropDownState.OFF) { + this.options.forEach((option) => { + option.setOptionState(DropDownState.OFF); + option.setDirection(SortDirection.ASC); + option.toggle.setVisible(false); + }); + this.options[this.cursor].setOptionState(DropDownState.ON); + this.options[this.cursor].setDirection(this.lastDir); + this.options[this.cursor].toggle.setVisible(true); + } else { + this.options[this.cursor].toggleDirection(); + this.lastDir = this.options[this.cursor].dir; + } + } + this.onChange(); + } + + setVisible(value: boolean): this { + super.setVisible(value); + + if (value) { + this.autoSize(); + } + + return this; + } + + checkForAllOn(): boolean { + return this.options.every((option, i) => i === 0 || option.state === DropDownState.ON); + } + + checkForAllOff(): boolean { + return this.options.every((option, i) => i === 0 || option.state === DropDownState.OFF); + } + + getVals(): any[] { + if (this.dropDownType === DropDownType.MULTI) { + return this.options.filter((option, i) => i > 0 && option.state === DropDownState.ON).map((option) => option.val); + } else { + return this.options.filter((option, i) => option.state === DropDownState.ON).map((option) => { + return {val: option.val, dir: option.dir}; + }); + } + } + + autoSize(): void { + let maxWidth = 0; + let x = 0; + for (let i = 0; i < this.options.length; i++) { + if (this.options[i].sprite) { + if (this.options[i].sprite.displayWidth > maxWidth) { + maxWidth = this.options[i].sprite.displayWidth; + x = this.options[i].sprite.x; + } + } else { + if (this.options[i].text.displayWidth > maxWidth) { + maxWidth = this.options[i].text.displayWidth; + x = this.options[i].text.x; + } + } + } + this.window.width = maxWidth + x - this.window.x + 6; + + if (this.x + this.window.width > this.parentContainer.width) { + this.x = this.parentContainer.width - this.window.width; + } + } + + isActive(): boolean { + return this.options.some((option) => option.state === DropDownState.ON); + } +} diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index c9f7ddc5873d..ae9d531a2453 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -9,7 +9,7 @@ import { getPokemonSpecies } from "../data/pokemon-species"; import { addWindow } from "./ui-theme"; import { Tutorial, handleTutorial } from "../tutorial"; import {Button} from "#enums/buttons"; -import Overrides from "../overrides"; +import Overrides from "#app/overrides"; import { GachaType } from "#app/enums/gacha-types"; import i18next from "i18next"; import { EggTier } from "#enums/egg-type"; diff --git a/src/ui/filter-bar.ts b/src/ui/filter-bar.ts new file mode 100644 index 000000000000..cc4723799d56 --- /dev/null +++ b/src/ui/filter-bar.ts @@ -0,0 +1,201 @@ +import BattleScene from "#app/battle-scene.js"; +import { DropDown } from "./dropdown"; +import { StarterContainer } from "./starter-container"; +import { addTextObject, TextStyle } from "./text"; +import { addWindow, WindowVariant } from "./ui-theme"; + +export enum DropDownColumn { + GEN, + TYPES, + UNLOCKS, + WIN, + SORT +} + +export class FilterBar extends Phaser.GameObjects.Container { + private window: Phaser.GameObjects.NineSlice; + public labels: Phaser.GameObjects.Text[] = []; + public dropDowns: DropDown[] = []; + public cursorObj: Phaser.GameObjects.Image; + public numFilters: number = 0; + public openDropDown: boolean = false; + private lastCursor: number = -1; + public defaultGenVals: any[] = []; + public defaultTypeVals: any[] = []; + public defaultUnlockVals: any[] = []; + public defaultWinVals: any[] = []; + public defaultSortVals: any[] = []; + + constructor(scene: BattleScene, x: number, y: number, width: number, height: number) { + super(scene, x, y); + + this.width = width; + this.height = height; + + this.window = addWindow(scene, 0, 0, width, height, false, false, null, null, WindowVariant.THIN); + this.add(this.window); + + this.cursorObj = this.scene.add.image(1, 1, "cursor"); + this.cursorObj.setScale(0.5); + this.cursorObj.setVisible(false); + this.cursorObj.setOrigin(0, 0); + this.add(this.cursorObj); + } + + addFilter(text: string, dropDown: DropDown): void { + const filterTypesLabel = addTextObject(this.scene, 0, 3, text, TextStyle.TOOLTIP_CONTENT); + this.labels.push(filterTypesLabel); + this.add(filterTypesLabel); + this.dropDowns.push(dropDown); + this.add(dropDown); + + this.calcFilterPositions(); + this.numFilters++; + } + + + updateFilterLabels(): void { + const genVals = this.getVals(DropDownColumn.GEN); + const typeVals = this.getVals(DropDownColumn.TYPES); + const unlockVals = this.getVals(DropDownColumn.UNLOCKS); + const winVals = this.getVals(DropDownColumn.WIN); + const sortVals = this.getVals(DropDownColumn.SORT); + + // onColor is Yellow, offColor is White + const onColor = 0xffef5c; + const offColor = 0xffffff; + + // if genVals and defaultGenVals has same elements, set the label to White else set it to Green + if (genVals.length === this.defaultGenVals.length && genVals.every((value, index) => value === this.defaultGenVals[index])) { + this.labels[DropDownColumn.GEN].setTint(offColor); + } else { + this.labels[DropDownColumn.GEN].setTint(onColor); + } + + // if typeVals and defaultTypeVals has same elements, set the label to White else set it to Green + if (typeVals.length === this.defaultTypeVals.length && typeVals.every((value, index) => value === this.defaultTypeVals[index])) { + this.labels[DropDownColumn.TYPES].setTint(offColor); + } else { + this.labels[DropDownColumn.TYPES].setTint(onColor); + } + + // if unlockVals and defaultUnlockVals has same elements, set the label to White else set it to Green + if (unlockVals.length === this.defaultUnlockVals.length && unlockVals.every((value, index) => value === this.defaultUnlockVals[index])) { + this.labels[DropDownColumn.UNLOCKS].setTint(offColor); + } else { + this.labels[DropDownColumn.UNLOCKS].setTint(onColor); + } + + // if winVals and defaultWinVals has same elements, set the label to White else set it to Green + if (winVals.length === this.defaultWinVals.length && winVals.every((value, index) => value === this.defaultWinVals[index])) { + this.labels[DropDownColumn.WIN].setTint(offColor); + } else { + this.labels[DropDownColumn.WIN].setTint(onColor); + } + + // if sortVals and defaultSortVals has same value and dir, set the label to White else set it to Green + if (sortVals[0]["dir"] === this.defaultSortVals[0]["dir"] && sortVals[0]["val"] === this.defaultSortVals[0]["val"]) { + this.labels[DropDownColumn.SORT].setTint(offColor); + } else { + this.labels[DropDownColumn.SORT].setTint(onColor); + } + } + + calcFilterPositions(): void { + const paddingX = 6; + const cursorOffset = 8; + + // position labels with even space across the width of the container + let totalWidth = paddingX * 2 + cursorOffset; + this.labels.forEach(label => { + totalWidth += label.displayWidth + cursorOffset; + }); + const spacing = (this.width - totalWidth) / (this.labels.length - 1); + for (let i=0; i -1) { + if (this.dropDowns[this.lastCursor].visible) { + this.dropDowns[this.lastCursor].setVisible(false); + this.dropDowns[cursor].setVisible(true); + this.dropDowns[cursor].setCursor(0); + } + } + + const cursorOffset = 8; + this.cursorObj.setPosition(this.labels[cursor].x - cursorOffset + 2, 6); + this.lastCursor = cursor; + } + + toggleDropDown(index: number): void { + this.dropDowns[index].toggle(); + this.openDropDown = this.dropDowns[index].visible; + this.dropDowns[index].setCursor(0); + } + + hideDropDowns(): void { + this.dropDowns.forEach(dropDown => { + dropDown.setVisible(false); + }); + this.openDropDown = false; + } + + incDropDownCursor(): boolean { + if (this.dropDowns[this.lastCursor].cursor === this.dropDowns[this.lastCursor].options.length - 1) {// if at the bottom of the list, wrap around + return this.dropDowns[this.lastCursor].setCursor(0); + } else { + return this.dropDowns[this.lastCursor].setCursor(this.dropDowns[this.lastCursor].cursor + 1); + } + } + + decDropDownCursor(): boolean { + if (this.dropDowns[this.lastCursor].cursor === 0) {// if at the top of the list, wrap around + return this.dropDowns[this.lastCursor].setCursor(this.dropDowns[this.lastCursor].options.length - 1); + } else { + return this.dropDowns[this.lastCursor].setCursor(this.dropDowns[this.lastCursor].cursor - 1); + } + } + + toggleOptionState(): void { + this.dropDowns[this.lastCursor].toggleOptionState(); + } + + getVals(col: DropDownColumn): any[] { + return this.dropDowns[col].getVals(); + } + + getNearestFilter(container: StarterContainer): number { + // find the nearest filter to the x position + const midx = container.x + container.icon.displayWidth / 2; + let nearest = 0; + let nearestDist = 1000; + for (let i=0; i < this.labels.length; i++) { + const dist = Math.abs(midx - (this.labels[i].x + this.labels[i].displayWidth / 3)); + if (dist < nearestDist) { + nearest = i; + nearestDist = dist; + } + } + + return nearest; + } + + getLastFilterX(): number { + return this.labels[this.lastCursor].x + this.labels[this.lastCursor].displayWidth / 2; + } + + isFilterActive(index: number) { + return this.dropDowns[index].isActive(); + } +} diff --git a/src/ui/login-form-ui-handler.ts b/src/ui/login-form-ui-handler.ts index 2a4f419cbbc1..971bef6ea6be 100644 --- a/src/ui/login-form-ui-handler.ts +++ b/src/ui/login-form-ui-handler.ts @@ -49,7 +49,7 @@ export default class LoginFormUiHandler extends FormModalUiHandler { discordImage.on("pointerdown", () => { const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`); const discordId = import.meta.env.VITE_DISCORD_CLIENT_ID; - const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify`; + const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify&prompt=none`; window.open(discordUrl, "_self"); }); this.discordImage = discordImage; diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index 65a9b94146ff..5555d1be01c3 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -395,7 +395,7 @@ export default class MenuUiHandler extends MessageUiHandler { const token = Utils.getCookie(Utils.sessionIdKey); const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`); const discordId = import.meta.env.VITE_DISCORD_CLIENT_ID; - const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify&state=${token}`; + const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify&state=${token}&prompt=none`; window.open(discordUrl, "_self"); return true; } else { @@ -462,7 +462,7 @@ export default class MenuUiHandler extends MessageUiHandler { if (!res.ok) { console.error(`Log out failed (${res.status}: ${res.statusText})`); } - Utils.setCookie(Utils.sessionIdKey, ""); + Utils.removeCookie(Utils.sessionIdKey); updateUserInfo().then(() => this.scene.reset(true, true)); }); }; diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index c5e369e91939..9bb8162ce2a7 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -21,6 +21,7 @@ import MoveInfoOverlay from "./move-info-overlay"; import i18next from "i18next"; import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; import { Moves } from "#enums/moves"; +import { getPokemonNameWithAffix } from "#app/messages.js"; const defaultMessage = i18next.t("partyUiHandler:choosePokemon"); @@ -52,6 +53,7 @@ export enum PartyOption { SPLICE, UNSPLICE, RELEASE, + RENAME, SCROLL_UP = 1000, SCROLL_DOWN = 1001, FORM_CHANGE_ITEM = 2000, @@ -59,7 +61,7 @@ export enum PartyOption { MOVE_2, MOVE_3, MOVE_4, - ALL = 4000 + ALL = 4000, } export type PartySelectCallback = (cursor: integer, option: PartyOption) => void; @@ -115,14 +117,14 @@ export default class PartyUiHandler extends MessageUiHandler { public static FilterNonFainted = (pokemon: PlayerPokemon) => { if (pokemon.isFainted()) { - return i18next.t("partyUiHandler:noEnergy", { pokemonName: pokemon.name }); + return i18next.t("partyUiHandler:noEnergy", { pokemonName: getPokemonNameWithAffix(pokemon) }); } return null; }; public static FilterFainted = (pokemon: PlayerPokemon) => { if (!pokemon.isFainted()) { - return i18next.t("partyUiHandler:hasEnergy", { pokemonName: pokemon.name }); + return i18next.t("partyUiHandler:hasEnergy", { pokemonName: getPokemonNameWithAffix(pokemon) }); } return null; }; @@ -136,7 +138,7 @@ export default class PartyUiHandler extends MessageUiHandler { const challengeAllowed = new Utils.BooleanHolder(true); applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, pokemon, challengeAllowed); if (!challengeAllowed.value) { - return i18next.t("partyUiHandler:cantBeUsed", { pokemonName: pokemon.name }); + return i18next.t("partyUiHandler:cantBeUsed", { pokemonName: getPokemonNameWithAffix(pokemon) }); } return null; }; @@ -146,14 +148,14 @@ export default class PartyUiHandler extends MessageUiHandler { public static FilterItemMaxStacks = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => { const matchingModifier = pokemon.scene.findModifier(m => m instanceof PokemonHeldItemModifier && m.pokemonId === pokemon.id && m.matchType(modifier)) as PokemonHeldItemModifier; if (matchingModifier && matchingModifier.stackCount === matchingModifier.getMaxStackCount(pokemon.scene)) { - return i18next.t("partyUiHandler:tooManyItems", { pokemonName: pokemon.name }); + return i18next.t("partyUiHandler:tooManyItems", { pokemonName: getPokemonNameWithAffix(pokemon) }); } return null; }; public static NoEffectMessage = i18next.t("partyUiHandler:anyEffect"); - private localizedOptions = [PartyOption.SEND_OUT, PartyOption.SUMMARY, PartyOption.CANCEL, PartyOption.APPLY, PartyOption.RELEASE, PartyOption.TEACH, PartyOption.SPLICE, PartyOption.UNSPLICE, PartyOption.REVIVE, PartyOption.TRANSFER, PartyOption.UNPAUSE_EVOLUTION, PartyOption.PASS_BATON]; + private localizedOptions = [PartyOption.SEND_OUT, PartyOption.SUMMARY, PartyOption.CANCEL, PartyOption.APPLY, PartyOption.RELEASE, PartyOption.TEACH, PartyOption.SPLICE, PartyOption.UNSPLICE, PartyOption.REVIVE, PartyOption.TRANSFER, PartyOption.UNPAUSE_EVOLUTION, PartyOption.PASS_BATON, PartyOption.RENAME]; constructor(scene: BattleScene) { super(scene, Mode.PARTY); @@ -302,7 +304,7 @@ export default class PartyUiHandler extends MessageUiHandler { } ui.playSelect(); return true; - } else if ((option !== PartyOption.SUMMARY && option !== PartyOption.UNPAUSE_EVOLUTION && option !== PartyOption.UNSPLICE && option !== PartyOption.RELEASE && option !== PartyOption.CANCEL) + } else if ((option !== PartyOption.SUMMARY && option !== PartyOption.UNPAUSE_EVOLUTION && option !== PartyOption.UNSPLICE && option !== PartyOption.RELEASE && option !== PartyOption.CANCEL && option !== PartyOption.RENAME) || (option === PartyOption.RELEASE && this.partyUiMode === PartyUiMode.RELEASE)) { let filterResult: string; const getTransferrableItemsFromPokemon = (pokemon: PlayerPokemon) => @@ -378,7 +380,7 @@ export default class PartyUiHandler extends MessageUiHandler { this.clearOptions(); ui.playSelect(); pokemon.pauseEvolutions = false; - this.showText(i18next.t("partyUiHandler:unpausedEvolutions", { pokemonName: pokemon.name }), null, () => this.showText(null, 0), null, true); + this.showText(i18next.t("partyUiHandler:unpausedEvolutions", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => this.showText(null, 0), null, true); } else if (option === PartyOption.UNSPLICE) { this.clearOptions(); ui.playSelect(); @@ -403,7 +405,7 @@ export default class PartyUiHandler extends MessageUiHandler { this.clearOptions(); ui.playSelect(); if (this.cursor >= this.scene.currentBattle.getBattlerCount() || !pokemon.isAllowedInBattle()) { - this.showText(i18next.t("partyUiHandler:releaseConfirmation", { pokemonName: pokemon.name }), null, () => { + this.showText(i18next.t("partyUiHandler:releaseConfirmation", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => { ui.setModeWithoutClear(Mode.CONFIRM, () => { ui.setMode(Mode.PARTY); this.doRelease(this.cursor); @@ -416,6 +418,25 @@ export default class PartyUiHandler extends MessageUiHandler { this.showText(i18next.t("partyUiHandler:releaseInBattle"), null, () => this.showText(null, 0), null, true); } return true; + } else if (option === PartyOption.RENAME) { + this.clearOptions(); + ui.playSelect(); + ui.setModeWithoutClear(Mode.RENAME_POKEMON, { + buttonActions: [ + (nickname: string) => { + ui.playSelect(); + pokemon.nickname = nickname; + pokemon.updateInfo(); + this.clearPartySlots(); + this.populatePartySlots(); + ui.setMode(Mode.PARTY); + }, + () => { + ui.setMode(Mode.PARTY); + } + ] + }, pokemon); + return true; } else if (option === PartyOption.CANCEL) { return this.processInput(Button.CANCEL); } @@ -762,6 +783,7 @@ export default class PartyUiHandler extends MessageUiHandler { } this.options.push(PartyOption.SUMMARY); + this.options.push(PartyOption.RENAME); if (pokemon.pauseEvolutions && pokemonEvolutions.hasOwnProperty(pokemon.species.speciesId)) { this.options.push(PartyOption.UNPAUSE_EVOLUTION); @@ -928,7 +950,7 @@ export default class PartyUiHandler extends MessageUiHandler { } doRelease(slotIndex: integer): void { - this.showText(this.getReleaseMessage(this.scene.getParty()[slotIndex].name), null, () => { + this.showText(this.getReleaseMessage(getPokemonNameWithAffix(this.scene.getParty()[slotIndex])), null, () => { this.clearPartySlots(); this.scene.removePartyMemberModifiers(slotIndex); const releasedPokemon = this.scene.getParty().splice(slotIndex, 1)[0]; @@ -1059,7 +1081,7 @@ class PartySlot extends Phaser.GameObjects.Container { const slotInfoContainer = this.scene.add.container(0, 0); this.add(slotInfoContainer); - let displayName = this.pokemon.name; + let displayName = this.pokemon.getNameToRender(); let nameTextWidth: number; const nameSizeTest = addTextObject(this.scene, 0, 0, displayName, TextStyle.PARTY); diff --git a/src/ui/pokemon-info-container.ts b/src/ui/pokemon-info-container.ts index 9f4df2b20b4e..1e958ae53b7e 100644 --- a/src/ui/pokemon-info-container.ts +++ b/src/ui/pokemon-info-container.ts @@ -364,13 +364,14 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container { }); } - makeRoomForConfirmUi(speedMultiplier: number = 1): Promise { + makeRoomForConfirmUi(speedMultiplier: number = 1, fromCatch: boolean = false): Promise { + const xPosition = fromCatch ? this.initialX - this.infoWindowWidth - 65 : this.initialX - this.infoWindowWidth - ConfirmUiHandler.windowWidth; return new Promise(resolve => { this.scene.tweens.add({ targets: this, duration: Utils.fixedInt(Math.floor(150 / speedMultiplier)), ease: "Cubic.easeInOut", - x: this.initialX - this.infoWindowWidth - ConfirmUiHandler.windowWidth, + x: xPosition, onComplete: () => { resolve(); } diff --git a/src/ui/rename-form-ui-handler.ts b/src/ui/rename-form-ui-handler.ts new file mode 100644 index 000000000000..35127564b602 --- /dev/null +++ b/src/ui/rename-form-ui-handler.ts @@ -0,0 +1,58 @@ +import { FormModalUiHandler } from "./form-modal-ui-handler"; +import { ModalConfig } from "./modal-ui-handler"; +import i18next from "i18next"; +import { PlayerPokemon } from "#app/field/pokemon.js"; + +export default class RenameFormUiHandler extends FormModalUiHandler { + getModalTitle(config?: ModalConfig): string { + return i18next.t("menu:renamePokemon"); + } + + getFields(config?: ModalConfig): string[] { + return [ i18next.t("menu:nickname") ]; + } + + getWidth(config?: ModalConfig): number { + return 160; + } + + getMargin(config?: ModalConfig): [number, number, number, number] { + return [ 0, 0, 48, 0 ]; + } + + getButtonLabels(config?: ModalConfig): string[] { + return [ i18next.t("menu:rename"), i18next.t("menu:cancel") ]; + } + + getReadableErrorMessage(error: string): string { + const colonIndex = error?.indexOf(":"); + if (colonIndex > 0) { + error = error.slice(0, colonIndex); + } + + return super.getReadableErrorMessage(error); + } + + show(args: any[]): boolean { + if (super.show(args)) { + const config = args[0] as ModalConfig; + this.inputs[0].text = (args[1] as PlayerPokemon).getNameToRender(); + + this.submitAction = (_) => { + this.sanitizeInputs(); + // const onFail = () => { + // this.scene.ui.setModeWithoutClear(Mode.RENAME_POKEMON, Object.assign(config)); + // this.scene.ui.playError(); + // }; + // if (!this.inputs[0].text) { + // return onFail(); + // } + const sanitizedName = btoa(unescape(encodeURIComponent(this.inputs[0].text))); + config.buttonActions[0](sanitizedName); + return true; + }; + return true; + } + return false; + } +} diff --git a/src/ui/scroll-bar.ts b/src/ui/scroll-bar.ts new file mode 100644 index 000000000000..02282edb4cdc --- /dev/null +++ b/src/ui/scroll-bar.ts @@ -0,0 +1,36 @@ +export class ScrollBar extends Phaser.GameObjects.Container { + private bg: Phaser.GameObjects.Image; + private handleBody: Phaser.GameObjects.Rectangle; + private handleBottom: Phaser.GameObjects.Image; + private pages: number; + private page: number; + + constructor(scene: Phaser.Scene, x: number, y: number, pages: number) { + super(scene, x, y); + + this.bg = scene.add.image(0, 0, "scroll_bar"); + this.bg.setOrigin(0, 0); + this.add(this.bg); + + this.handleBody = scene.add.rectangle(1, 1, 3, 4, 0xaaaaaa); + this.handleBody.setOrigin(0, 0); + this.add(this.handleBody); + + this.handleBottom = scene.add.image(1, 1, "scroll_bar_handle"); + this.handleBottom.setOrigin(0, 0); + this.add(this.handleBottom); + } + + setPage(page: number): void { + this.page = page; + this.handleBody.y = 1 + (this.bg.displayHeight - 1 - this.handleBottom.displayHeight) / this.pages * page; + this.handleBottom.y = this.handleBody.y + this.handleBody.displayHeight; + } + + setPages(pages: number): void { + this.pages = pages; + this.handleBody.height = (this.bg.displayHeight - 1 - this.handleBottom.displayHeight) / this.pages; + + this.setVisible(this.pages > 1); + } +} diff --git a/src/ui/starter-container.ts b/src/ui/starter-container.ts new file mode 100644 index 000000000000..ae589d138b95 --- /dev/null +++ b/src/ui/starter-container.ts @@ -0,0 +1,101 @@ +import BattleScene from "../battle-scene"; +import PokemonSpecies from "../data/pokemon-species"; +import { addTextObject, TextStyle } from "./text"; + +export class StarterContainer extends Phaser.GameObjects.Container { + public scene: BattleScene; + public species: PokemonSpecies; + public icon: Phaser.GameObjects.Sprite; + public shinyIcons: Phaser.GameObjects.Image[] = []; + public label: Phaser.GameObjects.Text; + public starterPassiveBgs: Phaser.GameObjects.Image; + public hiddenAbilityIcon: Phaser.GameObjects.Image; + public classicWinIcon: Phaser.GameObjects.Image; + public candyUpgradeIcon: Phaser.GameObjects.Image; + public candyUpgradeOverlayIcon: Phaser.GameObjects.Image; + public cost: number = 0; + + constructor(scene: BattleScene, species: PokemonSpecies) { + super(scene, 0, 0); + + this.species = species; + + const defaultDexAttr = scene.gameData.getSpeciesDefaultDexAttr(species, false, true); + const defaultProps = scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); + + // starter passive bg + const starterPassiveBg = this.scene.add.image(2, 5, "passive_bg"); + starterPassiveBg.setOrigin(0, 0); + starterPassiveBg.setScale(0.75); + starterPassiveBg.setVisible(false); + this.add(starterPassiveBg); + this.starterPassiveBgs = starterPassiveBg; + + // icon + this.icon = this.scene.add.sprite(-2, 2, species.getIconAtlasKey(defaultProps.formIndex, defaultProps.shiny, defaultProps.variant)); + this.icon.setScale(0.5); + this.icon.setOrigin(0, 0); + this.icon.setFrame(species.getIconId(defaultProps.female, defaultProps.formIndex, defaultProps.shiny, defaultProps.variant)); + this.checkIconId(defaultProps.female, defaultProps.formIndex, defaultProps.shiny, defaultProps.variant); + this.icon.setTint(0); + this.add(this.icon); + + // shiny icons + for (let i = 0; i < 3; i++) { + const shinyIcon = this.scene.add.image(i * -3 + 12, 2, "shiny_star_small"); + shinyIcon.setScale(0.5); + shinyIcon.setOrigin(0, 0); + shinyIcon.setVisible(false); + this.shinyIcons.push(shinyIcon); + } + this.add(this.shinyIcons); + + // value label + const label = addTextObject(this.scene, 1, 2, "0", TextStyle.WINDOW, { fontSize: "32px" }); + label.setShadowOffset(2, 2); + label.setOrigin(0, 0); + label.setVisible(false); + this.add(label); + this.label = label; + + // hidden ability icon + const abilityIcon = this.scene.add.image(12, 7, "ha_capsule"); + abilityIcon.setOrigin(0, 0); + abilityIcon.setScale(0.5); + abilityIcon.setVisible(false); + this.add(abilityIcon); + this.hiddenAbilityIcon = abilityIcon; + + // classic win icon + const classicWinIcon = this.scene.add.image(2, 12, "champion_ribbon"); + classicWinIcon.setOrigin(0, 0); + classicWinIcon.setScale(0.5); + classicWinIcon.setVisible(false); + this.add(classicWinIcon); + this.classicWinIcon = classicWinIcon; + + // candy upgrade icon + const candyUpgradeIcon = this.scene.add.image(12, 12, "candy"); + candyUpgradeIcon.setOrigin(0, 0); + candyUpgradeIcon.setScale(0.25); + candyUpgradeIcon.setVisible(false); + this.add(candyUpgradeIcon); + this.candyUpgradeIcon = candyUpgradeIcon; + + // candy upgrade overlay icon + const candyUpgradeOverlayIcon = this.scene.add.image(12, 12, "candy_overlay"); + candyUpgradeOverlayIcon.setOrigin(0, 0); + candyUpgradeOverlayIcon.setScale(0.25); + candyUpgradeOverlayIcon.setVisible(false); + this.add(candyUpgradeOverlayIcon); + this.candyUpgradeOverlayIcon = candyUpgradeOverlayIcon; + } + + checkIconId(female, formIndex, shiny, variant) { + if (this.icon.frame.name !== this.species.getIconId(female, formIndex, shiny, variant)) { + console.log(`${this.species.name}'s variant icon does not exist. Replacing with default.`); + this.icon.setTexture(this.species.getIconAtlasKey(formIndex, false, variant)); + this.icon.setFrame(this.species.getIconId(female, formIndex, false, variant)); + } + } +} diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index d6cab324f16b..d8321fc9c8f4 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -28,7 +28,7 @@ import { TextStyle, addBBCodeTextObject, addTextObject } from "./text"; import { Mode } from "./ui"; import { addWindow } from "./ui-theme"; import { Egg } from "#app/data/egg"; -import Overrides from "../overrides"; +import Overrides from "#app/overrides"; import {SettingKeyboard} from "#app/system/settings/settings-keyboard"; import {Passive as PassiveAttr} from "#enums/passive"; import * as Challenge from "../data/challenge"; @@ -39,6 +39,11 @@ import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import {Button} from "#enums/buttons"; import { EggSourceType } from "#app/enums/egg-source-types.js"; +import AwaitableUiHandler from "./awaitable-ui-handler"; +import { DropDown, DropDownOption, DropDownState, DropDownType } from "./dropdown"; +import { StarterContainer } from "./starter-container"; +import { DropDownColumn, FilterBar } from "./filter-bar"; +import { ScrollBar } from "./scroll-bar"; export type StarterSelectCallback = (starters: Starter[]) => void; @@ -127,44 +132,27 @@ function getSameSpeciesEggCandyCounts(baseValue: integer): integer { } /** - * Calculates the icon position for a Pokemon of a given UI index - * @param index UI index to calculate the icon position of + * Calculates the starter position for a Pokemon of a given UI index + * @param index UI index to calculate the starter position of * @returns An interface with an x and y property */ -function calcIconPosition(index: number): {x: number, y: number} { +function calcStarterPosition(index: number, scrollCursor:number = 0): {x: number, y: number} { + const yOffset = 13; + const height = 17; const x = (index % 9) * 18; - const y = Math.floor(index / 9) * 18; + const y = yOffset + (Math.floor(index / 9) - scrollCursor) * height; return {x: x, y: y}; } -/** - * Calculates the {@linkcode Phaser.GameObjects.Sprite} position for a Pokemon of a given UI index - * @param index UI index to calculate the icon position of - * @returns An interface with an x and y property - */ -function calcSpritePosition(index: number): {x: number, y: number} { - const position = calcIconPosition(index); - - return {x: position.x - 2, y: position.y + 2}; -} - -const gens = [ - i18next.t("starterSelectUiHandler:gen1"), - i18next.t("starterSelectUiHandler:gen2"), - i18next.t("starterSelectUiHandler:gen3"), - i18next.t("starterSelectUiHandler:gen4"), - i18next.t("starterSelectUiHandler:gen5"), - i18next.t("starterSelectUiHandler:gen6"), - i18next.t("starterSelectUiHandler:gen7"), - i18next.t("starterSelectUiHandler:gen8"), - i18next.t("starterSelectUiHandler:gen9") -]; - export default class StarterSelectUiHandler extends MessageUiHandler { private starterSelectContainer: Phaser.GameObjects.Container; + private starterSelectScrollBar: ScrollBar; + private filterBarContainer: Phaser.GameObjects.Container; + private filterBar: FilterBar; private shinyOverlay: Phaser.GameObjects.Image; - private starterSelectGenIconContainers: Phaser.GameObjects.Container[]; + private starterContainer: StarterContainer[] = []; + private filteredStarterContainers: StarterContainer[] = []; private pokemonNumberText: Phaser.GameObjects.Text; private pokemonSprite: Phaser.GameObjects.Sprite; private pokemonNameText: Phaser.GameObjects.Text; @@ -200,7 +188,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private pokemonHatchedIcon : Phaser.GameObjects.Sprite; private pokemonHatchedCountText: Phaser.GameObjects.Text; private pokemonShinyIcon: Phaser.GameObjects.Sprite; - private genOptionsText: Phaser.GameObjects.Text; private instructionsContainer: Phaser.GameObjects.Container; private shinyIconElement: Phaser.GameObjects.Sprite; @@ -222,22 +209,23 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private pokemonFormText: Phaser.GameObjects.Text; private moveInfoOverlay : MoveInfoOverlay; - private genMode: boolean; private statsMode: boolean; + private starterIconsCursorXOffset: number = -3; + private starterIconsCursorYOffset: number = 1; + private starterIconsCursorIndex: number; + private filterMode: boolean; private dexAttrCursor: bigint = 0n; - private abilityCursor: integer = -1; - private natureCursor: integer = -1; - private genCursor: integer = 0; - private genScrollCursor: integer = 0; + private abilityCursor: number = -1; + private natureCursor: number = -1; + private filterBarCursor: integer = 0; private starterMoveset: StarterMoveset; + private scrollCursor: number; - private genSpecies: PokemonSpecies[][] = []; + private allSpecies: PokemonSpecies[] = []; private lastSpecies: PokemonSpecies; private speciesLoaded: Map = new Map(); - public starterGens: integer[] = []; - public starterCursors: integer[] = []; - private pokerusGens: integer[] = []; - private pokerusCursors: integer[] = []; + public starterSpecies: PokemonSpecies[] = []; + private pokerusSpecies: PokemonSpecies[] = []; private starterAttr: bigint[] = []; private starterAbilityIndexes: integer[] = []; private starterNatures: Nature[] = []; @@ -258,18 +246,16 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private starterCursorObjs: Phaser.GameObjects.Image[]; private pokerusCursorObjs: Phaser.GameObjects.Image[]; private starterIcons: Phaser.GameObjects.Sprite[]; - private genCursorObj: Phaser.GameObjects.Image; - private genCursorHighlightObj: Phaser.GameObjects.Image; + private starterIconsCursorObj: Phaser.GameObjects.Image; private valueLimitLabel: Phaser.GameObjects.Text; private startCursorObj: Phaser.GameObjects.NineSlice; - private starterValueLabels: Phaser.GameObjects.Text[]; - private shinyIcons: Phaser.GameObjects.Image[][]; - private hiddenAbilityIcons: Phaser.GameObjects.Image[]; - private classicWinIcons: Phaser.GameObjects.Image[]; - private candyUpgradeIcon: Phaser.GameObjects.Image[]; - private candyUpgradeOverlayIcon: Phaser.GameObjects.Image[]; - private starterPassiveBgs: Phaser.GameObjects.Image[]; - + // private starterValueLabels: Phaser.GameObjects.Text[]; + // private shinyIcons: Phaser.GameObjects.Image[][]; + // private hiddenAbilityIcons: Phaser.GameObjects.Image[]; + // private classicWinIcons: Phaser.GameObjects.Image[]; + // private candyUpgradeIcon: Phaser.GameObjects.Image[]; + // private candyUpgradeOverlayIcon: Phaser.GameObjects.Image[]; + // private iconAnimHandler: PokemonIconAnimHandler; //variables to keep track of the dynamically rendered list of instruction prompts for starter select @@ -310,13 +296,96 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.shinyOverlay.setVisible(false); this.starterSelectContainer.add(this.shinyOverlay); - const starterContainerWindow = addWindow(this.scene, 141, 1, 178, 178); + const starterContainerWindow = addWindow(this.scene, 109, 18, 175, 161); + const starterContainerBg = this.scene.add.image(110, 19, "starter_container_bg"); + starterContainerBg.setOrigin(0, 0); + this.starterSelectContainer.add(starterContainerBg); - this.starterSelectContainer.add(addWindow(this.scene, 107, 1, 34, 58)); - this.starterSelectContainer.add(addWindow(this.scene, 107, 59, 34, 91)); - this.starterSelectContainer.add(addWindow(this.scene, 107, 145, 34, 34, true)); + this.starterSelectContainer.add(addWindow(this.scene, 285, 59, 34, 91)); + this.starterSelectContainer.add(addWindow(this.scene, 285, 145, 34, 34, true)); this.starterSelectContainer.add(starterContainerWindow); + this.filterBarContainer = this.scene.add.container(0, 0); + + // this.filterBar = new FilterBar(this.scene, 143, 1, 175, 17); + this.filterBar = new FilterBar(this.scene, 109, 1, 175, 17); + + // gen filter + const genOptions: DropDownOption[] = [ + new DropDownOption(this.scene, 1, i18next.t("starterSelectUiHandler:gen1"), null, DropDownState.ON), + new DropDownOption(this.scene, 2, i18next.t("starterSelectUiHandler:gen2"), null, DropDownState.ON), + new DropDownOption(this.scene, 3, i18next.t("starterSelectUiHandler:gen3"), null, DropDownState.ON), + new DropDownOption(this.scene, 4, i18next.t("starterSelectUiHandler:gen4"), null, DropDownState.ON), + new DropDownOption(this.scene, 5, i18next.t("starterSelectUiHandler:gen5"), null, DropDownState.ON), + new DropDownOption(this.scene, 6, i18next.t("starterSelectUiHandler:gen6"), null, DropDownState.ON), + new DropDownOption(this.scene, 7, i18next.t("starterSelectUiHandler:gen7"), null, DropDownState.ON), + new DropDownOption(this.scene, 8, i18next.t("starterSelectUiHandler:gen8"), null, DropDownState.ON), + new DropDownOption(this.scene, 9, i18next.t("starterSelectUiHandler:gen9"), null, DropDownState.ON), + ]; + this.filterBar.addFilter("Gen", new DropDown(this.scene, 0, 0, genOptions, this.updateStarters, DropDownType.MULTI)); + this.filterBar.defaultGenVals = this.filterBar.getVals(DropDownColumn.GEN); + // set gen filter to all off except for the I GEN + for (const option of genOptions) { + if (option.val !== 1) { + option.setOptionState(DropDownState.OFF); + } + } + + // type filter + const typeKeys = Object.keys(Type).filter(v => isNaN(Number(v))); + const typeOptions: DropDownOption[] = []; + typeKeys.forEach((type, index) => { + if (index === 0 || index === 19) { + return; + } + const typeSprite = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`); + typeSprite.setScale(0.5); + typeSprite.setFrame(type.toLowerCase()); + typeOptions.push(new DropDownOption(this.scene, index, null, typeSprite)); + }); + this.filterBar.addFilter("Type", new DropDown(this.scene, 0, 0, typeOptions, this.updateStarters, DropDownType.MULTI, 0.5)); + this.filterBar.defaultTypeVals = this.filterBar.getVals(DropDownColumn.TYPES); + + // Unlocks filter + const shiny1Sprite = this.scene.add.sprite(0, 0, "shiny_star_small"); + shiny1Sprite.setTint(getVariantTint(0)); + const shiny2Sprite = this.scene.add.sprite(0, 0, "shiny_star_small"); + shiny2Sprite.setTint(getVariantTint(1)); + const shiny3Sprite = this.scene.add.sprite(0, 0, "shiny_star_small"); + shiny3Sprite.setTint(getVariantTint(2)); + + const unlocksOptions = [ + new DropDownOption(this.scene, "SHINY3", null, shiny3Sprite), + new DropDownOption(this.scene, "SHINY2", null, shiny2Sprite), + new DropDownOption(this.scene, "SHINY", null, shiny1Sprite), + new DropDownOption(this.scene, "NORMAL", "Normal"), + new DropDownOption(this.scene, "UNCAUGHT", "Not Caught"), + new DropDownOption(this.scene, "PASSIVEUNLOCKED", "Passive Unlocked"), + new DropDownOption(this.scene, "PASSIVELOCKED", "Passive Locked"),]; + + this.filterBar.addFilter("Unlocks", new DropDown(this.scene, 0, 0, unlocksOptions, this.updateStarters, DropDownType.MULTI)); + this.filterBar.defaultUnlockVals = this.filterBar.getVals(DropDownColumn.UNLOCKS); + + // win filter + const winOptions = [ + new DropDownOption(this.scene, "WIN", "has won"), + new DropDownOption(this.scene, "NOTWIN", "hasn't won yet")]; + this.filterBar.addFilter("Win", new DropDown(this.scene, 0, 0, winOptions, this.updateStarters, DropDownType.MULTI)); + this.filterBar.defaultWinVals = this.filterBar.getVals(DropDownColumn.WIN); + + // sort filter + const sortOptions = [ + new DropDownOption(this.scene, 0, "No."), + new DropDownOption(this.scene, 1, "Cost", null, DropDownState.OFF), + new DropDownOption(this.scene, 2, "# Candies", null, DropDownState.OFF), + new DropDownOption(this.scene, 3, "IVs", null, DropDownState.OFF), + new DropDownOption(this.scene, 4, "Name", null, DropDownState.OFF)]; + this.filterBar.addFilter("Sort", new DropDown(this.scene, 0, 0, sortOptions, this.updateStarters, DropDownType.SINGLE)); + this.filterBarContainer.add(this.filterBar); + this.filterBar.defaultSortVals = this.filterBar.getVals(DropDownColumn.SORT); + + this.starterSelectContainer.add(this.filterBarContainer); + if (!this.scene.uiTheme) { starterContainerWindow.setVisible(false); } @@ -392,37 +461,32 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonEggMoveBgs = []; this.pokemonEggMoveLabels = []; - this.genOptionsText = addTextObject(this.scene, 124, 7, "", TextStyle.WINDOW, { fontSize: 72, lineSpacing: 39, align: "center" }); - this.genOptionsText.setShadowOffset(4.5, 4.5); - this.genOptionsText.setOrigin(0.5, 0); - this.starterSelectContainer.add(this.genOptionsText); - - this.updateGenOptions(); - - this.starterPassiveBgs = new Array(81).fill(null).map((_, i) => { - const position = calcIconPosition(i); - const ret = this.scene.add.image(position.x + 153, position.y+14, "passive_bg"); - ret.setOrigin(0, 0); - ret.setScale(0.75); - ret.setVisible(false); - this.starterSelectContainer.add(ret); - return ret; - }); + this.valueLimitLabel = addTextObject(this.scene, 302, 150, "0/10", TextStyle.TOOLTIP_CONTENT); + this.valueLimitLabel.setOrigin(0.5, 0); + this.starterSelectContainer.add(this.valueLimitLabel); - this.starterSelectGenIconContainers = new Array(gens.length).fill(null).map((_, i) => { - const container = this.scene.add.container(151, 9); - if (i) { - container.setVisible(false); - } - this.starterSelectContainer.add(container); - return container; - }); + const startLabel = addTextObject(this.scene, 302, 162, i18next.t("common:start"), TextStyle.TOOLTIP_CONTENT); + startLabel.setOrigin(0.5, 0); + this.starterSelectContainer.add(startLabel); + + this.startCursorObj = this.scene.add.nineslice(289, 160, "select_cursor", null, 26, 15, 6, 6, 6, 6); + this.startCursorObj.setVisible(false); + this.startCursorObj.setOrigin(0, 0); + this.starterSelectContainer.add(this.startCursorObj); + + const starterSpecies: Species[] = []; + + const starterBoxContainer = this.scene.add.container(115, 9); + + this.starterSelectScrollBar = new ScrollBar(this.scene, 161, 12, 0); + + starterBoxContainer.add(this.starterSelectScrollBar); this.pokerusCursorObjs = new Array(3).fill(null).map(() => { const cursorObj = this.scene.add.image(0, 0, "select_cursor_pokerus"); cursorObj.setVisible(false); cursorObj.setOrigin(0, 0); - this.starterSelectContainer.add(cursorObj); + starterBoxContainer.add(cursorObj); return cursorObj; }); @@ -430,66 +494,39 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const cursorObj = this.scene.add.image(0, 0, "select_cursor_highlight"); cursorObj.setVisible(false); cursorObj.setOrigin(0, 0); - this.starterSelectContainer.add(cursorObj); + starterBoxContainer.add(cursorObj); return cursorObj; }); this.cursorObj = this.scene.add.image(0, 0, "select_cursor"); this.cursorObj.setOrigin(0, 0); - this.starterSelectContainer.add(this.cursorObj); - - this.genCursorHighlightObj = this.scene.add.image(111, 5, "select_gen_cursor_highlight"); - this.genCursorHighlightObj.setOrigin(0, 0); - this.starterSelectContainer.add(this.genCursorHighlightObj); - - this.genCursorObj = this.scene.add.image(111, 5, "select_gen_cursor"); - this.genCursorObj.setVisible(false); - this.genCursorObj.setOrigin(0, 0); - this.starterSelectContainer.add(this.genCursorObj); + this.starterIconsCursorObj = this.scene.add.image(289, 64, "select_gen_cursor"); + this.starterIconsCursorObj.setName("starter-icons-cursor"); + this.starterIconsCursorObj.setVisible(false); + this.starterIconsCursorObj.setOrigin(0, 0); + this.starterSelectContainer.add(this.starterIconsCursorObj); - this.valueLimitLabel = addTextObject(this.scene, 124, 150, "0/10", TextStyle.TOOLTIP_CONTENT); - this.valueLimitLabel.setOrigin(0.5, 0); - this.starterSelectContainer.add(this.valueLimitLabel); + starterBoxContainer.add(this.cursorObj); - const startLabel = addTextObject(this.scene, 124, 162, i18next.t("common:start"), TextStyle.TOOLTIP_CONTENT); - startLabel.setOrigin(0.5, 0); - this.starterSelectContainer.add(startLabel); - - this.startCursorObj = this.scene.add.nineslice(111, 160, "select_cursor", null, 26, 15, 6, 6, 6, 6); - this.startCursorObj.setVisible(false); - this.startCursorObj.setOrigin(0, 0); - this.starterSelectContainer.add(this.startCursorObj); - - const starterSpecies: Species[] = []; + for (const species of allSpecies) { + if (!speciesStarters.hasOwnProperty(species.speciesId) || !species.isObtainable()) { + continue; + } - for (let g = 0; g < this.starterSelectGenIconContainers.length; g++) { - let s = 0; - this.genSpecies.push([]); + starterSpecies.push(species.speciesId); + this.speciesLoaded.set(species.speciesId, false); + this.allSpecies.push(species); - for (const species of allSpecies) { - if (!speciesStarters.hasOwnProperty(species.speciesId) || species.generation !== g + 1 || !species.isObtainable()) { - continue; - } - starterSpecies.push(species.speciesId); - this.speciesLoaded.set(species.speciesId, false); - this.genSpecies[g].push(species); - const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true); - const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); - const position = calcIconPosition(s); - const icon = this.scene.add.sprite(position.x - 2, position.y + 2, species.getIconAtlasKey(defaultProps.formIndex, defaultProps.shiny, defaultProps.variant)); - icon.setScale(0.5); - icon.setOrigin(0, 0); - icon.setFrame(species.getIconId(defaultProps.female, defaultProps.formIndex, defaultProps.shiny, defaultProps.variant)); - this.checkIconId(icon, species, defaultProps.female, defaultProps.formIndex, defaultProps.shiny, defaultProps.variant); - icon.setTint(0); - this.starterSelectGenIconContainers[g].add(icon); - this.iconAnimHandler.addOrUpdate(icon, PokemonIconAnimMode.NONE); - s++; - } + const starterContainer = new StarterContainer(this.scene, species).setVisible(false); + this.iconAnimHandler.addOrUpdate(starterContainer.icon, PokemonIconAnimMode.NONE); + this.starterContainer.push(starterContainer); + starterBoxContainer.add(starterContainer); } + this.starterSelectContainer.add(starterBoxContainer); + this.starterIcons = new Array(6).fill(null).map((_, i) => { - const icon = this.scene.add.sprite(113, 63 + 13 * i, "pokemon_icons_0"); + const icon = this.scene.add.sprite(292, 63 + 13 * i, "pokemon_icons_0"); icon.setScale(0.5); icon.setOrigin(0, 0); icon.setFrame("unknown"); @@ -498,70 +535,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { return icon; }); - this.starterValueLabels = new Array(81).fill(null).map((_, i) => { - const position = calcIconPosition(i); - const ret = addTextObject(this.scene, position.x + 152, position.y + 11, "0", TextStyle.WINDOW, { fontSize: "32px" }); - ret.setShadowOffset(2, 2); - ret.setOrigin(0, 0); - ret.setVisible(false); - this.starterSelectContainer.add(ret); - return ret; - }); - - const getShinyStar = (i: integer, v: integer): Phaser.GameObjects.Image => { - const position = calcIconPosition(i); - const ret = this.scene.add.image((position.x - v * 3) + 163, position.y + 11, "shiny_star_small"); - ret.setOrigin(0, 0); - ret.setScale(0.5); - ret.setVisible(false); - this.starterSelectContainer.add(ret); - return ret; - }; - - this.shinyIcons = new Array(81).fill(null).map((_, i) => { - return new Array(3).fill(null).map((_, v) => getShinyStar(i, v)); - }); - - this.hiddenAbilityIcons = new Array(81).fill(null).map((_, i) => { - const position = calcIconPosition(i); - const ret = this.scene.add.image(position.x + 163, position.y + 16, "ha_capsule"); - ret.setOrigin(0, 0); - ret.setScale(0.5); - ret.setVisible(false); - this.starterSelectContainer.add(ret); - return ret; - }); - - this.classicWinIcons = new Array(81).fill(null).map((_, i) => { - const position = calcIconPosition(i); - const ret = this.scene.add.image(position.x + 153, position.y + 21, "champion_ribbon"); - ret.setOrigin(0, 0); - ret.setScale(0.5); - ret.setVisible(false); - this.starterSelectContainer.add(ret); - return ret; - }); - - this.candyUpgradeIcon = new Array(81).fill(null).map((_, i) => { - const position = calcIconPosition(i); - const ret = this.scene.add.image(position.x + 163, position.y + 21, "candy"); - ret.setOrigin(0, 0); - ret.setScale(0.25); - ret.setVisible(false); - this.starterSelectContainer.add(ret); - return ret; - }); - - this.candyUpgradeOverlayIcon = new Array(81).fill(null).map((_, i) => { - const position = calcIconPosition(i); - const ret = this.scene.add.image(position.x + 163, position.y + 21, "candy_overlay"); - ret.setOrigin(0, 0); - ret.setScale(0.25); - ret.setVisible(false); - this.starterSelectContainer.add(ret); - return ret; - }); - this.pokemonSprite = this.scene.add.sprite(53, 63, "pkmn__sub"); this.pokemonSprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true }); this.starterSelectContainer.add(this.pokemonSprite); @@ -768,12 +741,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler { for (let c = 0; c < 3; c++) { let randomSpeciesId: Species; let species: PokemonSpecies; - let pokerusCursor: integer; const generateSpecies = () => { randomSpeciesId = Utils.randSeedItem(starterSpecies); species = getPokemonSpecies(randomSpeciesId); - pokerusCursor = this.genSpecies[species.generation - 1].indexOf(species); }; let dupe = false; @@ -783,17 +754,15 @@ export default class StarterSelectUiHandler extends MessageUiHandler { generateSpecies(); - for (let pc = 0; pc < c; pc++) { - if (this.pokerusGens[pc] === species.generation -1 && this.pokerusCursors[pc] === pokerusCursor) { + for (let ps = 0; ps < c; ps++) { + if (this.pokerusSpecies[ps] === species) { dupe = true; break; } } } while (dupe); - this.pokerusGens.push(species.generation - 1); - this.pokerusCursors.push(pokerusCursor); - this.pokerusCursorObjs[c].setPosition(150 + 18 * (pokerusCursor % 9), 10 + 18 * Math.floor(pokerusCursor / 9)); + this.pokerusSpecies.push(species); } }, 0, date.getTime().toString()); @@ -814,6 +783,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { y: this.scene.game.canvas.height / 6 - MoveInfoOverlay.getHeight(overlayScale) - 29, }); this.starterSelectContainer.add(this.moveInfoOverlay); + this.starterSelectContainer.bringToTop(this.filterBarContainer); this.scene.eventTarget.addEventListener(BattleSceneEventType.CANDY_UPGRADE_NOTIFICATION_CHANGED, (e) => this.onCandyUpgradeDisplayChanged(e)); @@ -832,27 +802,25 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.starterSelectContainer.setVisible(true); - this.setCursor(0); - this.setGenMode(false); - this.setCursor(0); - this.setGenMode(true); - this.setCursor(0); - this.tryUpdateValue(0); + this.allSpecies.forEach((species, s) => { + const icon = this.starterContainer[s].icon; + const dexEntry = this.scene.gameData.dexData[species.speciesId]; - for (let g = 0; g < this.genSpecies.length; g++) { - this.genSpecies[g].forEach((species, s) => { - const icon = this.starterSelectGenIconContainers[g].getAt(s) as Phaser.GameObjects.Sprite; - const dexEntry = this.scene.gameData.dexData[species.speciesId]; + if (dexEntry.caughtAttr) { + icon.clearTint(); + } else if (dexEntry.seenAttr) { + icon.setTint(0x808080); + } - if (dexEntry.caughtAttr) { - icon.clearTint(); - } else if (dexEntry.seenAttr) { - icon.setTint(0x808080); - } + this.setUpgradeAnimation(icon, species); + }); - this.setUpgradeAnimation(icon, species); - }); - } + this.updateStarters(); + + this.setFilterMode(false); + this.filterBarCursor = 0; + this.setCursor(0); + this.tryUpdateValue(0); handleTutorial(this.scene, Tutorial.Starter_Select); @@ -942,8 +910,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { return; } - const position = calcSpritePosition(this.genSpecies[species.generation - 1].indexOf(species)); - icon.y = position.y; + icon.y = 2; const tweenChain: Phaser.Types.Tweens.TweenChainBuilderConfig = { targets: icon, @@ -954,14 +921,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler { tweens: [ { targets: icon, - y: position.y - 5, + y: 2 - 5, duration: Utils.fixedInt(125), ease: "Cubic.easeOut", yoyo: true }, { targets: icon, - y: position.y - 3, + y: 2 - 3, duration: Utils.fixedInt(150), ease: "Cubic.easeOut", yoyo: true @@ -983,34 +950,29 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } /** - * Sets the visibility of a Candy Upgrade Icon given an index - * @param index The UI index of the icon within this generation container + * Sets the visibility of a Candy Upgrade Icon */ - setUpgradeIcon(index: number): void { - const species = this.genSpecies[this.getGenCursorWithScroll()][index]; + setUpgradeIcon(starter: StarterContainer): void { + const species = starter.species; const slotVisible = !!species?.speciesId; - if (!species // No Pokemon exists at that UI index - || this.scene.candyUpgradeNotification === 0 // Notification setting is 'Off' - || species.speciesId !== species.getRootSpeciesId(false)) { // Pokemon is not the base evolution and can't use candy - // Set all icons as hidden and exit early - this.candyUpgradeIcon[index].setVisible(false); - this.candyUpgradeOverlayIcon[index].setVisible(false); - + if (!species || this.scene.candyUpgradeNotification === 0 || species.speciesId !== species.getRootSpeciesId(false)) { + starter.candyUpgradeIcon.setVisible(false); + starter.candyUpgradeOverlayIcon.setVisible(false); return; } const passiveAvailable = this.isPassiveAvailable(species.speciesId); // 'Only Passive Unlocks' mode if (this.scene.candyUpgradeNotification === 1) { - this.candyUpgradeIcon[index].setVisible(slotVisible && passiveAvailable); - this.candyUpgradeOverlayIcon[index].setVisible(slotVisible && this.candyUpgradeIcon[index].visible); + starter.candyUpgradeIcon.setVisible(slotVisible && passiveAvailable); + starter.candyUpgradeOverlayIcon.setVisible(slotVisible && starter.candyUpgradeIcon.visible); // 'On' mode } else if (this.scene.candyUpgradeNotification === 2) { - this.candyUpgradeIcon[index].setVisible( + starter.candyUpgradeIcon.setVisible( slotVisible && ( passiveAvailable || this.isValueReductionAvailable(species.speciesId))); - this.candyUpgradeOverlayIcon[index].setVisible(slotVisible && this.candyUpgradeIcon[index].visible); + starter.candyUpgradeOverlayIcon.setVisible(slotVisible && starter.candyUpgradeIcon.visible); } } @@ -1026,21 +988,19 @@ export default class StarterSelectUiHandler extends MessageUiHandler { // Loop through all visible candy icons when set to 'Icon' mode if (this.scene.candyUpgradeDisplay === 0) { - this.genSpecies[this.getGenCursorWithScroll()].forEach((_species, s) => { - this.setUpgradeIcon(s); + this.filteredStarterContainers.forEach((starter) => { + this.setUpgradeIcon(starter); }); return; } // Loop through all animations when set to 'Animation' mode - for (let g = 0; g < this.genSpecies.length; g++) { - this.genSpecies[g].forEach((species, s) => { - const icon = this.starterSelectGenIconContainers[g].getAt(s) as Phaser.GameObjects.Sprite; + this.filteredStarterContainers.forEach((starter, s) => { + const icon = this.filteredStarterContainers[s].icon; - this.setUpgradeAnimation(icon, species); - }); - } + this.setUpgradeAnimation(icon, starter.species); + }); } processInput(button: Button): boolean { @@ -1048,6 +1008,19 @@ export default class StarterSelectUiHandler extends MessageUiHandler { return false; } + const numberOfStarters = this.filteredStarterContainers.length; + const numOfRows = Math.ceil(numberOfStarters / 9); + const currentRow = Math.floor(this.cursor / 9); + const onScreenFirstIndex = this.scrollCursor * 9; // this is first starter index on the screen + const onScreenLastIndex = Math.min(onScreenFirstIndex + 9*9, numberOfStarters) - 1; // this is the last starter index on the screen + const onScreenNumberOfStarters = onScreenLastIndex - onScreenFirstIndex + 1; + const onScreenNumberOfRows = Math.ceil(onScreenNumberOfStarters / 9); + // const onScreenFirstRow = Math.floor(onScreenFirstIndex / 9); + const onScreenCurrentRow = Math.floor((this.cursor - onScreenFirstIndex) / 9); + + + // console.log("this.cursor: ", this.cursor, "this.scrollCursor" , this.scrollCursor, "numberOfStarters: ", numberOfStarters, "numOfRows: ", numOfRows, "currentRow: ", currentRow, "onScreenFirstIndex: ", onScreenFirstIndex, "onScreenLastIndex: ", onScreenLastIndex, "onScreenNumberOfStarters: ", onScreenNumberOfStarters, "onScreenNumberOfRow: ", onScreenNumberOfRows, "onScreenCurrentRow: ", onScreenCurrentRow); + const ui = this.getUi(); let success = false; @@ -1060,11 +1033,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler { error = true; } } else if (button === Button.CANCEL) { - if (this.statsMode) { + if (this.filterMode && this.filterBar.openDropDown) { + this.filterBar.toggleDropDown(this.filterBarCursor); + success = true; + } else if (this.statsMode) { this.toggleStatsMode(false); success = true; - } else if (this.starterCursors.length) { - this.popStarter(); + } else if (this.starterSpecies.length) { + this.popStarter(this.starterSpecies.length - 1); success = true; this.updateInstructions(); } else { @@ -1078,7 +1054,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.scene.getCurrentPhase().end(); success = true; } - } else if (this.startCursorObj.visible) { + } else if (this.startCursorObj.visible) { // this checks to see if the start button is selected switch (button) { case Button.ACTION: if (this.tryStart(true)) { @@ -1089,77 +1065,120 @@ export default class StarterSelectUiHandler extends MessageUiHandler { break; case Button.UP: this.startCursorObj.setVisible(false); - this.setGenMode(true); + if (this.starterSpecies.length > 0) { + this.starterIconsCursorIndex = this.starterSpecies.length - 1; + this.moveStarterIconsCursor(this.starterIconsCursorIndex); + } else { + this.setFilterMode(true); + } + success = true; + break; + case Button.DOWN: + this.startCursorObj.setVisible(false); + this.starterIconsCursorIndex = 0; + this.moveStarterIconsCursor(this.starterIconsCursorIndex); success = true; break; case Button.LEFT: this.startCursorObj.setVisible(false); - this.setGenMode(false); - this.setCursor(this.cursor + 8); + this.cursorObj.setVisible(true); + success = this.setCursor(onScreenFirstIndex + (onScreenNumberOfRows-1) * 9 + 8); // set last column success = true; break; case Button.RIGHT: this.startCursorObj.setVisible(false); - this.setGenMode(false); + this.cursorObj.setVisible(true); + success = this.setCursor(onScreenFirstIndex + (onScreenNumberOfRows-1) * 9); // set first column success = true; break; } - } else if (this.genMode) { + } else if (this.filterMode) { switch (button) { + case Button.LEFT: + if (this.filterBarCursor > 0) { + success = this.setCursor(this.filterBarCursor - 1); + } else { + success = this.setCursor(this.filterBar.numFilters - 1); + } + break; + case Button.RIGHT: + if (this.filterBarCursor < this.filterBar.numFilters - 1) { + success = this.setCursor(this.filterBarCursor + 1); + } else { + success = this.setCursor(0); + } + break; case Button.UP: - if (this.genCursor) { - success = this.setCursor(this.genCursor - 1); + if (this.filterBar.openDropDown) { + success = this.filterBar.decDropDownCursor(); + // else if there is filtered starters + } else if (numberOfStarters > 0) { + this.setFilterMode(false); + this.scrollCursor = Math.max(0,numOfRows - 9); + this.updateScroll(); + const proportion = (this.filterBarCursor + 0.5) / this.filterBar.numFilters; + const targetCol = Math.floor(proportion * 9); + if (numberOfStarters % 9 > targetCol) { + success = this.setCursor(numberOfStarters - (numberOfStarters) % 9 + targetCol); + } else { + success = this.setCursor(Math.max(numberOfStarters - (numberOfStarters) % 9 + targetCol - 9,0)); + } } break; case Button.DOWN: - if (this.genCursor < 2) { - success = this.setCursor(this.genCursor + 1); - } else { - this.startCursorObj.setVisible(true); - this.setGenMode(true); + if (this.filterBar.openDropDown) { + success = this.filterBar.incDropDownCursor(); + } else if (numberOfStarters > 0) { + this.setFilterMode(false); + this.scrollCursor = 0; + this.updateScroll(); + const proportion = this.filterBarCursor / Math.max(1, this.filterBar.numFilters - 1); + this.setCursor(Math.round(proportion * (Math.min(9, numberOfStarters) - 1))); success = true; } break; - case Button.LEFT: - success = this.setGenMode(false); - this.setCursor(this.cursor + 8); - break; - case Button.RIGHT: - success = this.setGenMode(false); + case Button.ACTION: + if (!this.filterBar.openDropDown) { + this.filterBar.toggleDropDown(this.filterBarCursor); + } else { + this.filterBar.toggleOptionState(); + } + success = true; break; } } else { if (button === Button.ACTION) { if (!this.speciesStarterDexEntry?.caughtAttr) { error = true; - } else if (this.starterCursors.length < 6) { + } else if (this.starterSpecies.length < 6) { const options = [ { label: i18next.t("starterSelectUiHandler:addToParty"), handler: () => { ui.setMode(Mode.STARTER_SELECT); let isDupe = false; - for (let s = 0; s < this.starterCursors.length; s++) { - if (this.starterGens[s] === this.getGenCursorWithScroll() && this.starterCursors[s] === this.cursor) { + + const species = this.filteredStarterContainers[this.cursor].species; + for (let s = 0; s < this.starterSpecies.length; s++) { + if (species === this.starterSpecies[s]) { isDupe = true; break; } } - const species = this.genSpecies[this.getGenCursorWithScroll()][this.cursor]; const isValidForChallenge = new Utils.BooleanHolder(true); - Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), !!this.starterGens.length); + Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), !!this.starterSpecies.length); + if (!isDupe && isValidForChallenge.value && this.tryUpdateValue(this.scene.gameData.getSpeciesStarterValue(species.speciesId))) { - const cursorObj = this.starterCursorObjs[this.starterCursors.length]; + const cursorObj = this.starterCursorObjs[this.starterSpecies.length]; cursorObj.setVisible(true); cursorObj.setPosition(this.cursorObj.x, this.cursorObj.y); const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor); - this.starterIcons[this.starterCursors.length].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant)); - this.starterIcons[this.starterCursors.length].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant)); - this.checkIconId(this.starterIcons[this.starterCursors.length], species, props.female, props.formIndex, props.shiny, props.variant); - this.starterGens.push(this.getGenCursorWithScroll()); - this.starterCursors.push(this.cursor); + this.starterIcons[this.starterSpecies.length].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant)); + this.starterIcons[this.starterSpecies.length].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant)); + this.checkIconId(this.starterIcons[this.starterSpecies.length], species, props.female, props.formIndex, props.shiny, props.variant); + this.starterSpecies.push(species); this.starterAttr.push(this.dexAttrCursor); this.starterAbilityIndexes.push(this.abilityCursor); this.starterNatures.push(this.natureCursor as unknown as Nature); @@ -1167,7 +1186,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler { if (this.speciesLoaded.get(species.speciesId)) { getPokemonSpeciesForm(species.speciesId, props.formIndex).cry(this.scene); } - if (this.starterCursors.length === 6 || this.value === this.getValueLimit()) { + if (this.starterSpecies.length === 6 || this.value === this.getValueLimit()) { + this.cursorObj.setVisible(false); + this.setSpecies(null); + this.startCursorObj.setVisible(true); this.tryStart(); } this.updateInstructions(); @@ -1178,7 +1200,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { */ if (!this.canAddParty) { this.startCursorObj.setVisible(true); - this.setGenMode(true); } ui.playSelect(); @@ -1198,7 +1219,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } ]; - if (this.speciesStarterMoves.length > 1) { + if (this.speciesStarterMoves.length > 1) { // this lets you change the pokemon moves const showSwapOptions = (moveset: StarterMoveset) => { ui.setMode(Mode.STARTER_SELECT).then(() => { ui.showText(i18next.t("starterSelectUiHandler:selectMoveSwapOut"), null, () => { @@ -1279,6 +1300,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } }); } + const starterContainer = this.filteredStarterContainers[this.cursor]; const starterData = this.scene.gameData.starterData[this.lastSpecies.speciesId]; let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId]; if (this.canCycleNature) { @@ -1294,8 +1316,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { handler: () => { // update default nature in starter save data if (!starterAttributes) { - starterAttributes= - this.starterPreferences[this.lastSpecies.speciesId] = {}; + starterAttributes = this.starterPreferences[this.lastSpecies.speciesId] = {}; } starterAttributes.nature = n as unknown as integer; this.clearText(); @@ -1330,7 +1351,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } const candyCount = starterData.candyCount; const passiveAttr = starterData.passiveAttr; - if (passiveAttr & PassiveAttr.UNLOCKED) { + if (passiveAttr & PassiveAttr.UNLOCKED) { // this is for enabling and disabling the passive if (!(passiveAttr & PassiveAttr.ENABLED)) { options.push({ label: i18next.t("starterSelectUiHandler:enablePassive"), @@ -1353,7 +1374,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { }); } } - const showUseCandies = () => { + const showUseCandies = () => { // this lets you use your candies const options = []; if (!(passiveAttr & PassiveAttr.UNLOCKED)) { const passiveCost = getPassiveCandyCount(speciesStarters[this.lastSpecies.speciesId]); @@ -1376,11 +1397,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler { // Update the candy upgrade display if (this.isUpgradeIconEnabled() ) { - this.setUpgradeIcon(this.cursor); + this.setUpgradeIcon(starterContainer); } if (this.isUpgradeAnimationEnabled()) { - const genSpecies = this.genSpecies[this.lastSpecies.generation - 1]; - this.setUpgradeAnimation(this.starterSelectGenIconContainers[this.lastSpecies.generation - 1].getAt(genSpecies.indexOf(this.lastSpecies)), this.lastSpecies, true); + this.setUpgradeAnimation(starterContainer.icon, this.lastSpecies, true); } return true; @@ -1408,7 +1428,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { return this.scene.reset(true); } }); - this.updateStarterValueLabel(this.cursor); + this.updateStarterValueLabel(starterContainer); this.tryUpdateValue(0); ui.setMode(Mode.STARTER_SELECT); this.scene.playSound("buy"); @@ -1416,11 +1436,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler { // If the notification setting is set to 'On', update the candy upgrade display if (this.scene.candyUpgradeNotification === 2) { if (this.isUpgradeIconEnabled() ) { - this.setUpgradeIcon(this.cursor); + this.setUpgradeIcon(starterContainer); } if (this.isUpgradeAnimationEnabled()) { - const genSpecies = this.genSpecies[this.lastSpecies.generation - 1]; - this.setUpgradeAnimation(this.starterSelectGenIconContainers[this.lastSpecies.generation - 1].getAt(genSpecies.indexOf(this.lastSpecies)), this.lastSpecies, true); + this.setUpgradeAnimation(starterContainer.icon, this.lastSpecies, true); } } @@ -1456,17 +1475,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { ui.setMode(Mode.STARTER_SELECT); this.scene.playSound("buy"); - // If the notification setting is set to 'On', update the candy upgrade display - // if (this.scene.candyUpgradeNotification === 2) { - // if (this.isUpgradeIconEnabled() ) { - // this.setUpgradeIcon(this.cursor); - // } - // if (this.isUpgradeAnimationEnabled()) { - // const genSpecies = this.genSpecies[this.lastSpecies.generation - 1]; - // this.setUpgradeAnimation(this.starterSelectGenIconContainers[this.lastSpecies.generation - 1].getAt(genSpecies.indexOf(this.lastSpecies)), this.lastSpecies, true); - // } - // } - return true; } return false; @@ -1510,15 +1518,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler { success = true; } } else { - const genStarters = this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAll().length; - const rows = Math.ceil(genStarters / 9); - const row = Math.floor(this.cursor / 9); const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.dexAttrCursor); // prepare persistent starter data to store changes let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId]; if (!starterAttributes) { - starterAttributes = - this.starterPreferences[this.lastSpecies.speciesId] = {}; + starterAttributes = this.starterPreferences[this.lastSpecies.speciesId] = {}; } switch (button) { case Button.CYCLE_SHINY: @@ -1616,6 +1620,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } } while (newVariant !== props.variant); + starterAttributes.variant = newVariant; // store the selected variant this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, newVariant, undefined, undefined); // Cycle tint based on current sprite tint const tint = getVariantTint(newVariant); @@ -1625,51 +1630,117 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } break; case Button.UP: - if (row) { - success = this.setCursor(this.cursor - 9); + if (!this.starterIconsCursorObj.visible) { + if (currentRow > 0) { + if (this.scrollCursor > 0 && currentRow - this.scrollCursor === 0) { + this.scrollCursor--; + this.updateScroll(); + } + success = this.setCursor(this.cursor - 9); + } else { + this.filterBarCursor = this.filterBar.getNearestFilter(this.filteredStarterContainers[this.cursor]); + this.setFilterMode(true); + success = true; + } } else { - // when strictly opposite starter based on rows length - // does not exits, set cursor on the second to last row - if (this.cursor + (rows - 1) * 9 > genStarters - 1) { - success = this.setCursor(this.cursor + (rows - 2) * 9); + if (this.starterIconsCursorIndex === 0) { + this.starterIconsCursorObj.setVisible(false); + this.setSpecies(null); + this.startCursorObj.setVisible(true); } else { - success = this.setCursor(this.cursor + (rows - 1) * 9); + this.starterIconsCursorIndex--; + this.moveStarterIconsCursor(this.starterIconsCursorIndex); } + success = true; } break; case Button.DOWN: - if (row < rows - 2 || (row < rows - 1 && this.cursor % 9 <= (genStarters - 1) % 9)) { - success = this.setCursor(this.cursor + 9); + if (!this.starterIconsCursorObj.visible) { + if (currentRow < numOfRows - 1) { // not last row + if (currentRow - this.scrollCursor === 8) { // last row of visible starters + this.scrollCursor++; + } + success = this.setCursor(this.cursor + 9); + this.updateScroll(); + } else { // last row + this.setFilterMode(true); + success = true; + } } else { - // if there is no starter below while being on the second to - // last row, adjust cursor position with one line less - if (row === rows - 2 && this.cursor + 9 > genStarters - 1) { - success = this.setCursor(this.cursor - (rows - 2) * 9); + if (this.starterIconsCursorIndex <= this.starterSpecies.length - 2) { + this.starterIconsCursorIndex++; + this.moveStarterIconsCursor(this.starterIconsCursorIndex); } else { - success = this.setCursor(this.cursor - (rows - 1) * 9); + this.starterIconsCursorObj.setVisible(false); + this.setSpecies(null); + this.startCursorObj.setVisible(true); } + success = true; } break; case Button.LEFT: - if (this.cursor % 9) { - success = this.setCursor(this.cursor - 1); - } else { - if (row >= Math.min(5, rows - 1)) { - this.startCursorObj.setVisible(true); + if (!this.starterIconsCursorObj.visible) { + if (this.cursor % 9 !== 0) { + success = this.setCursor(this.cursor - 1); + } else { + if (this.starterSpecies.length === 0) { + // just wrap around to the last column + success = this.setCursor(this.cursor + Math.min(8, numberOfStarters - this.cursor)); + } else if (onScreenCurrentRow < 3) { + // always to the first starter + this.cursorObj.setVisible(false); + this.starterIconsCursorIndex = 0; + this.moveStarterIconsCursor(this.starterIconsCursorIndex); + } else if (onScreenCurrentRow < 7) { + this.cursorObj.setVisible(false); + this.starterIconsCursorIndex = Math.min(onScreenCurrentRow-2, this.starterSpecies.length - 1); + this.moveStarterIconsCursor(this.starterIconsCursorIndex); + } else { + this.cursorObj.setVisible(false); + this.setSpecies(null); + this.startCursorObj.setVisible(true); + } + success = true; } - success = this.setGenMode(true); + } else { + this.starterIconsCursorObj.setVisible(false); + this.cursorObj.setVisible(true); + success = this.setCursor(Math.min(onScreenFirstIndex + (this.starterIconsCursorIndex + 2) * 9 + 8,onScreenLastIndex)); // set last column } break; case Button.RIGHT: - if (this.cursor % 9 < (row < rows - 1 ? 8 : (genStarters - 1) % 9)) { - success = this.setCursor(this.cursor + 1); - } else { - if (row >= Math.min(5, rows - 1)) { - this.startCursorObj.setVisible(true); + if (!this.starterIconsCursorObj.visible) { + // is not right edge + if (this.cursor % 9 < (currentRow < numOfRows - 1 ? 8 : (numberOfStarters - 1) % 9)) { + success = this.setCursor(this.cursor + 1); + } else { + // in right edge + if (this.starterSpecies.length === 0) { + // just wrap around to the first column + success = this.setCursor(this.cursor - Math.min(8, this.cursor % 9)); + } else if (onScreenCurrentRow < 3) { + // always to the first starter + this.cursorObj.setVisible(false); + this.starterIconsCursorIndex = 0; + this.moveStarterIconsCursor(this.starterIconsCursorIndex); + } else if (onScreenCurrentRow < 7) { + this.cursorObj.setVisible(false); + this.starterIconsCursorIndex = Math.min(onScreenCurrentRow-2, this.starterSpecies.length - 1); + this.moveStarterIconsCursor(this.starterIconsCursorIndex); + } else { + this.cursorObj.setVisible(false); + this.setSpecies(null); + this.startCursorObj.setVisible(true); + } + success = true; } - success = this.setGenMode(true); + break; + } else { + this.starterIconsCursorObj.setVisible(false); + this.cursorObj.setVisible(true); + success = this.setCursor(Math.min(onScreenFirstIndex + (this.starterIconsCursorIndex + 2) * 9, onScreenLastIndex - (onScreenLastIndex % 9))); // set first column + break; } - break; } } } @@ -1683,6 +1754,19 @@ export default class StarterSelectUiHandler extends MessageUiHandler { return success || error; } + isInParty(species: PokemonSpecies): [boolean, number] { + let removeIndex = 0; + let isDupe = false; + for (let s = 0; s < this.starterSpecies.length; s++) { + if (this.starterSpecies[s] === species) { + isDupe = true; + removeIndex = s; + break; + } + } + return [isDupe, removeIndex]; + } + switchMoveHandler(i: number, newMove: Moves, move: Moves) { const speciesId = this.lastSpecies.speciesId; const existingMoveIndex = this.starterMoveset.indexOf(newMove); @@ -1715,6 +1799,16 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.scene.gameData.starterData[speciesId].moveset = this.starterMoveset.slice(0) as StarterMoveset; } this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, undefined, false); + + // switch moves of starter if exists + if (this.starterMovesets.length) { + Array.from({ length: this.starterSpecies.length }, (_, i) => { + const starterSpecies = this.starterSpecies[i]; + if (starterSpecies.speciesId === speciesId) { + this.starterMovesets[i] = this.starterMoveset; + } + }); + } } updateButtonIcon(iconSetting, gamepadType, iconElement, controlLabel): void { @@ -1811,132 +1905,233 @@ export default class StarterSelectUiHandler extends MessageUiHandler { return valueLimit.value; } - setCursor(cursor: integer): boolean { - let changed = false; + updateStarters = () => { + this.scrollCursor = 0; + this.filteredStarterContainers = []; + + this.pokerusCursorObjs.forEach(cursor => cursor.setVisible(false)); + this.starterCursorObjs.forEach(cursor => cursor.setVisible(false)); + + this.filterBar.updateFilterLabels(); + + // filter + this.starterContainer.forEach(container => { + container.setVisible(false); + + // First, ensure you have the caught attributes for the species else default to bigint 0 + const caughtVariants = this.scene.gameData.dexData[container.species.speciesId]?.caughtAttr || BigInt(0); + + // Define the variables based on whether their respective variants have been caught + const isVariant3Caught = !!(caughtVariants & DexAttr.VARIANT_3); + const isVariant2Caught = !!(caughtVariants & DexAttr.VARIANT_2); + const isVariantCaught = !!(caughtVariants & DexAttr.SHINY); + const isCaught = !!(caughtVariants & DexAttr.NON_SHINY); + const isUncaught = !isCaught && !isVariantCaught && !isVariant2Caught && !isVariant3Caught; + const isPassiveUnlocked = this.scene.gameData.starterData[container.species.speciesId].passiveAttr > 0; + + + const fitsGen = this.filterBar.getVals(DropDownColumn.GEN).includes(container.species.generation); + const fitsType = this.filterBar.getVals(DropDownColumn.TYPES).some(type => container.species.isOfType((type as number) - 1)); + const fitsUnlocks = this.filterBar.getVals(DropDownColumn.UNLOCKS).some(variant => { + if (variant === "SHINY3") { + return isVariant3Caught; + } else if (variant === "SHINY2") { + return isVariant2Caught && !isVariant3Caught; + } else if (variant === "SHINY") { + return isVariantCaught && !isVariant2Caught && !isVariant3Caught; + } else if (variant === "NORMAL") { + return isCaught && !isVariantCaught && !isVariant2Caught && !isVariant3Caught; + } else if (variant === "UNCAUGHT") { + return isUncaught; + } else if (variant === "PASSIVEUNLOCKED") { + return isPassiveUnlocked; + } else if (variant === "PASSIVELOCKED") { + return !isPassiveUnlocked; + } + }); + const isWin = this.scene.gameData.starterData[container.species.speciesId].classicWinCount > 0; + const isNotWin = this.scene.gameData.starterData[container.species.speciesId].classicWinCount === 0; + const isUndefined = this.scene.gameData.starterData[container.species.speciesId].classicWinCount === undefined; + + const fitsWin = this.filterBar.getVals(DropDownColumn.WIN).some(win => { + if (win === "WIN") { + return isWin; + } else if (win === "NOTWIN") { + return isNotWin || isUndefined; + } + }); - if (this.genMode) { - changed = this.genCursor !== cursor; + if (fitsGen && fitsType && fitsUnlocks && fitsWin) { + this.filteredStarterContainers.push(container); + } + }); - let genCursorWithScroll = this.getGenCursorWithScroll(); + this.starterSelectScrollBar.setPages(Math.ceil((this.filteredStarterContainers.length - 81) / 9) + 1); + this.starterSelectScrollBar.setPage(0); - if (!cursor && this.genScrollCursor) { - this.genScrollCursor--; - cursor++; - this.updateGenOptions(); - } else if (cursor === 2 && this.genScrollCursor < gens.length - 3) { - this.genScrollCursor++; - cursor--; - this.updateGenOptions(); + // sort + const sort = this.filterBar.getVals(DropDownColumn.SORT)[0]; + this.filteredStarterContainers.sort((a, b) => { + switch (sort.val) { + default: + break; + case 0: + return (a.species.speciesId - b.species.speciesId) * -sort.dir; + case 1: + return (a.cost - b.cost) * -sort.dir; + case 2: + const candyCountA = this.scene.gameData.starterData[a.species.speciesId].candyCount; + const candyCountB = this.scene.gameData.starterData[b.species.speciesId].candyCount; + return (candyCountA - candyCountB) * -sort.dir; + case 3: + const avgIVsA = this.scene.gameData.dexData[a.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[a.species.speciesId].ivs.length; + const avgIVsB = this.scene.gameData.dexData[b.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[b.species.speciesId].ivs.length; + return (avgIVsA - avgIVsB) * -sort.dir; + case 4: + return a.species.name.localeCompare(b.species.name) * -sort.dir; } + return 0; + }); + + this.updateScroll(); + }; + + updateScroll = () => { + const perRow = 9; + const maxRows = 9; + + this.starterSelectScrollBar.setPage(this.scrollCursor); - if (genCursorWithScroll !== undefined) { - this.starterSelectGenIconContainers[genCursorWithScroll].setVisible(false); + let pokerusCursorIndex = 0; + let starterCursorIndex = 0; + this.filteredStarterContainers.forEach((container, i) => { + const pos = calcStarterPosition(i, this.scrollCursor); + container.setPosition(pos.x, pos.y); + + if (i < (maxRows + this.scrollCursor) * perRow && i >= this.scrollCursor * perRow) { + container.setVisible(true); + } else { + container.setVisible(false); } - this.cursor = 0; - this.genCursor = cursor; - genCursorWithScroll = this.getGenCursorWithScroll(); - this.genCursorObj.setY(5 + 17 * this.genCursor); - this.genCursorHighlightObj.setY(this.genCursorObj.y); - this.starterSelectGenIconContainers[genCursorWithScroll].setVisible(true); - - for (let s = 0; s < this.starterCursorObjs.length; s++) { - this.starterCursorObjs[s].setVisible(this.starterGens[s] === genCursorWithScroll); + + if (this.pokerusSpecies.includes(container.species)) { + this.pokerusCursorObjs[pokerusCursorIndex].setPosition(pos.x - 1, pos.y + 1); + this.pokerusCursorObjs[pokerusCursorIndex].setVisible(true); + pokerusCursorIndex++; } - for (let s = 0; s < this.pokerusCursorObjs.length; s++) { - this.pokerusCursorObjs[s].setVisible(this.pokerusGens[s] === genCursorWithScroll); + + if (this.starterSpecies.includes(container.species)) { + this.starterCursorObjs[starterCursorIndex].setPosition(pos.x - 1, pos.y + 1); + this.starterCursorObjs[starterCursorIndex].setVisible(true); + starterCursorIndex++; } - const genLimit = this.genSpecies[genCursorWithScroll].length; - for (let s = 0; s < 81; s++) { - const speciesId = s < genLimit ? this.genSpecies[genCursorWithScroll][s].speciesId : 0 as Species; - const slotVisible = !!speciesId; - if (slotVisible) { - this.updateStarterValueLabel(s); - } - this.starterValueLabels[s].setVisible(slotVisible); - const speciesVariants = speciesId && this.scene.gameData.dexData[speciesId].caughtAttr & DexAttr.SHINY - ? [ DexAttr.DEFAULT_VARIANT, DexAttr.VARIANT_2, DexAttr.VARIANT_3 ].filter(v => !!(this.scene.gameData.dexData[speciesId].caughtAttr & v)) - : []; - for (let v = 0; v < 3; v++) { - const hasVariant = speciesVariants.length > v; - this.shinyIcons[s][v].setVisible(slotVisible && hasVariant); - if (hasVariant) { - this.shinyIcons[s][v].setTint(getVariantTint(speciesVariants[v] === DexAttr.DEFAULT_VARIANT ? 0 : speciesVariants[v] === DexAttr.VARIANT_2 ? 1 : 2)); - } + const speciesId = container.species.speciesId; + this.updateStarterValueLabel(container); + + container.label.setVisible(true); + const speciesVariants = speciesId && this.scene.gameData.dexData[speciesId].caughtAttr & DexAttr.SHINY + ? [ DexAttr.DEFAULT_VARIANT, DexAttr.VARIANT_2, DexAttr.VARIANT_3 ].filter(v => !!(this.scene.gameData.dexData[speciesId].caughtAttr & v)) + : []; + for (let v = 0; v < 3; v++) { + const hasVariant = speciesVariants.length > v; + container.shinyIcons[v].setVisible(hasVariant); + if (hasVariant) { + container.shinyIcons[v].setTint(getVariantTint(speciesVariants[v] === DexAttr.DEFAULT_VARIANT ? 0 : speciesVariants[v] === DexAttr.VARIANT_2 ? 1 : 2)); } - this.starterPassiveBgs[s].setVisible(slotVisible && !!this.scene.gameData.starterData[speciesId].passiveAttr); - this.hiddenAbilityIcons[s].setVisible(slotVisible && !!this.scene.gameData.dexData[speciesId].caughtAttr && !!(this.scene.gameData.starterData[speciesId].abilityAttr & 4)); - this.classicWinIcons[s].setVisible(slotVisible && this.scene.gameData.starterData[speciesId].classicWinCount > 0); - - // 'Candy Icon' mode - if (this.scene.candyUpgradeDisplay === 0) { + } - if (!starterColors[speciesId]) { - // Default to white if no colors are found - starterColors[speciesId] = [ "ffffff", "ffffff" ]; - } + container.starterPassiveBgs.setVisible(!!this.scene.gameData.starterData[speciesId].passiveAttr); + container.hiddenAbilityIcon.setVisible(!!this.scene.gameData.dexData[speciesId].caughtAttr && !!(this.scene.gameData.starterData[speciesId].abilityAttr & 4)); + container.classicWinIcon.setVisible(this.scene.gameData.starterData[speciesId].classicWinCount > 0); - // Set the candy colors - this.candyUpgradeIcon[s].setTint(argbFromRgba(Utils.rgbHexToRgba(starterColors[speciesId][0]))); - this.candyUpgradeOverlayIcon[s].setTint(argbFromRgba(Utils.rgbHexToRgba(starterColors[speciesId][1]))); + // 'Candy Icon' mode + if (this.scene.candyUpgradeDisplay === 0) { - this.setUpgradeIcon(s); - } else if (this.scene.candyUpgradeDisplay === 1) { - this.candyUpgradeIcon[s].setVisible(false); - this.candyUpgradeOverlayIcon[s].setVisible(false); + if (!starterColors[speciesId]) { + // Default to white if no colors are found + starterColors[speciesId] = [ "ffffff", "ffffff" ]; } + + // Set the candy colors + container.candyUpgradeIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(starterColors[speciesId][0]))); + container.candyUpgradeOverlayIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(starterColors[speciesId][1]))); + + this.setUpgradeIcon(container); + } else if (this.scene.candyUpgradeDisplay === 1) { + container.candyUpgradeIcon.setVisible(false); + container.candyUpgradeOverlayIcon.setVisible(false); } + }); + }; + + setCursor(cursor: integer): boolean { + let changed = false; + + if (this.filterMode) { + changed = this.filterBarCursor !== cursor; + this.filterBarCursor = cursor; + + this.filterBar.setCursor(cursor); } else { + cursor = Math.max(Math.min(this.filteredStarterContainers.length - 1, cursor),0); changed = super.setCursor(cursor); - this.cursorObj.setPosition(150 + 18 * (cursor % 9), 10 + 18 * Math.floor(cursor / 9)); + const pos = calcStarterPosition(cursor, this.scrollCursor); + this.cursorObj.setPosition(pos.x - 1, pos.y + 1); - const species = this.genSpecies[this.getGenCursorWithScroll()][cursor]; + const species = this.filteredStarterContainers[cursor]?.species; - const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true); - const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); - const variant = defaultProps.variant; - const tint = getVariantTint(variant); - this.pokemonShinyIcon.setFrame(getVariantIcon(variant)); - this.pokemonShinyIcon.setTint(tint); - this.setSpecies(species); - this.updateInstructions(); + if (species) { + const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true); + const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); + const variant = defaultProps.variant; + const tint = getVariantTint(variant); + this.pokemonShinyIcon.setFrame(getVariantIcon(variant)); + this.pokemonShinyIcon.setTint(tint); + this.setSpecies(species); + this.updateInstructions(); + } else { + console.warn("Species is undefined for cursor position", cursor); + this.setFilterMode(true); + } } return changed; } getGenCursorWithScroll(): integer { - return this.genCursor !== undefined - ? this.genCursor + this.genScrollCursor - : undefined; + return undefined; + // return this.genCursor !== undefined + // ? this.genCursor + this.genScrollCursor + // : undefined; } updateGenOptions(): void { - let text = ""; - for (let g = this.genScrollCursor; g <= this.genScrollCursor + 2; g++) { - let optionText = ""; - if (g === this.genScrollCursor && this.genScrollCursor) { - optionText = "↑"; - } else if (g === this.genScrollCursor + 2 && this.genScrollCursor < gens.length - 3) { - optionText = "↓"; - } else { - optionText = i18next.t(`starterSelectUiHandler:gen${g + 1}`); - } - text += `${text ? "\n" : ""}${optionText}`; - } - this.genOptionsText.setText(text); + // let text = ""; + // for (let g = this.genScrollCursor; g <= this.genScrollCursor + 2; g++) { + // let optionText = ""; + // if (g === this.genScrollCursor && this.genScrollCursor) { + // optionText = "↑"; + // } else if (g === this.genScrollCursor + 2 && this.genScrollCursor < gens.length - 3) { + // optionText = "↓"; + // } else { + // optionText = i18next.t(`starterSelectUiHandler:gen${g + 1}`); + // } + // text += `${text ? "\n" : ""}${optionText}`; + // } + // this.genOptionsText.setText(text); } - setGenMode(genMode: boolean): boolean { - this.genCursorObj.setVisible(genMode && !this.startCursorObj.visible); - this.cursorObj.setVisible(!genMode && !this.startCursorObj.visible); - - if (genMode !== this.genMode) { - this.genMode = genMode; + setFilterMode(filterMode: boolean): boolean { + // this.genCursorObj.setVisible(!filterMode); + this.cursorObj.setVisible(!filterMode); + this.filterBar.cursorObj.setVisible(filterMode); - this.setCursor(genMode ? this.genCursor : this.cursor); - if (genMode) { + if (filterMode !== this.filterMode) { + this.filterMode = filterMode; + this.setCursor(filterMode ? this.filterBarCursor : this.cursor); + if (filterMode) { this.setSpecies(null); } @@ -1946,7 +2141,17 @@ export default class StarterSelectUiHandler extends MessageUiHandler { return false; } - + moveStarterIconsCursor(index: number): void { + this.starterIconsCursorObj.x = this.starterIcons[index].x + this.starterIconsCursorXOffset; + this.starterIconsCursorObj.y = this.starterIcons[index].y + this.starterIconsCursorYOffset; + if (this.starterSpecies.length > 0) { + this.starterIconsCursorObj.setVisible(true); + this.setSpecies(this.starterSpecies[index]); + } else { + this.starterIconsCursorObj.setVisible(false); + this.setSpecies(null); + } + } setSpecies(species: PokemonSpecies) { this.speciesStarterDexEntry = species ? this.scene.gameData.dexData[species.speciesId] : null; @@ -2021,14 +2226,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler { if (this.lastSpecies) { const dexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(this.lastSpecies, false, true); const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, dexAttr); - const lastSpeciesIcon = (this.starterSelectGenIconContainers[this.lastSpecies.generation - 1].getAt(this.genSpecies[this.lastSpecies.generation - 1].indexOf(this.lastSpecies)) as Phaser.GameObjects.Sprite); - lastSpeciesIcon.setTexture(this.lastSpecies.getIconAtlasKey(props.formIndex, props.shiny, props.variant), this.lastSpecies.getIconId(props.female, props.formIndex, props.shiny, props.variant)); + const speciesIndex = this.allSpecies.indexOf(this.lastSpecies); + const lastSpeciesIcon = this.starterContainer[speciesIndex].icon; this.checkIconId(lastSpeciesIcon, this.lastSpecies, props.female, props.formIndex, props.shiny, props.variant); this.iconAnimHandler.addOrUpdate(lastSpeciesIcon, PokemonIconAnimMode.NONE); // Resume the animation for the previously selected species - const speciesIndex = this.genSpecies[this.lastSpecies.generation - 1].indexOf(this.lastSpecies); - const icon = this.starterSelectGenIconContainers[this.lastSpecies.generation - 1].getAt(speciesIndex) as Phaser.GameObjects.Sprite; + const icon = this.starterContainer[speciesIndex].icon; this.scene.tweens.getTweensOf(icon).forEach(tween => tween.resume()); } @@ -2123,30 +2327,21 @@ export default class StarterSelectUiHandler extends MessageUiHandler { // Pause the animation when the species is selected - const speciesIndex = this.genSpecies[species.generation - 1].indexOf(species); - const icon = this.starterSelectGenIconContainers[species.generation - 1].getAt(speciesIndex) as Phaser.GameObjects.Sprite; + const speciesIndex = this.allSpecies.indexOf(species); + const icon = this.starterContainer[speciesIndex].icon; if (this.isUpgradeAnimationEnabled()) { this.scene.tweens.getTweensOf(icon).forEach(tween => tween.pause()); // Reset the position of the icon - const position = calcSpritePosition(speciesIndex); - icon.x = position.x; - icon.y = position.y; + icon.x = -2; + icon.y = 2; } // Initiates the small up and down idle animation this.iconAnimHandler.addOrUpdate(icon, PokemonIconAnimMode.PASSIVE); let starterIndex = -1; - - this.starterGens.every((g, i) => { - const starterSpecies = this.genSpecies[g][this.starterCursors[i]]; - if (starterSpecies.speciesId === species.speciesId) { - starterIndex = i; - return false; - } - return true; - }); + starterIndex = this.starterSpecies.indexOf(species); let props: DexAttrProps; @@ -2174,7 +2369,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.setTypeIcons(speciesForm.type1, speciesForm.type2); this.pokemonSprite.clearTint(); - if (this.pokerusCursors.find((cursor: integer, i: integer) => cursor === this.cursor && this.pokerusGens[i] === this.getGenCursorWithScroll())) { + if (this.pokerusSpecies.includes(species)) { handleTutorial(this.scene, Tutorial.Pokerus); } } else { @@ -2300,15 +2495,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { if (forSeen ? this.speciesStarterDexEntry?.seenAttr : this.speciesStarterDexEntry?.caughtAttr) { let starterIndex = -1; - - this.starterGens.every((g, i) => { - const starterSpecies = this.genSpecies[g][this.starterCursors[i]]; - if (starterSpecies.speciesId === species.speciesId) { - starterIndex = i; - return false; - } - return true; - }); + starterIndex = this.starterSpecies.indexOf(species); if (starterIndex > -1) { this.starterAttr[starterIndex] = this.dexAttrCursor; @@ -2334,14 +2521,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const isValidForChallenge = new Utils.BooleanHolder(true); - const currentPartyValue = this.starterGens.reduce((total: number, gen: number, i: number) => total += this.scene.gameData.getSpeciesStarterValue(this.genSpecies[gen][this.starterCursors[i]].speciesId), 0); - const cursorCost = this.scene.gameData.getSpeciesStarterValue(species.speciesId); - const isValidNextPartyValue = (currentPartyValue + cursorCost) <= this.getValueLimit(); - Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), !!this.starterGens.length); - const starterSprite = this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite; + Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), !!this.starterSpecies.length); + const starterSprite = this.filteredStarterContainers[this.cursor].icon as Phaser.GameObjects.Sprite; starterSprite.setTexture(species.getIconAtlasKey(formIndex, shiny, variant), species.getIconId(female, formIndex, shiny, variant)); - starterSprite.setAlpha(isValidForChallenge.value && isValidNextPartyValue ? 1 : 0.375); - this.checkIconId((this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite), species, female, formIndex, shiny, variant); + this.filteredStarterContainers[this.cursor].checkIconId(female, formIndex, shiny, variant); this.canCycleShiny = !!(dexEntry.caughtAttr & DexAttr.NON_SHINY && dexEntry.caughtAttr & DexAttr.SHINY); this.canCycleGender = !!(dexEntry.caughtAttr & DexAttr.MALE && dexEntry.caughtAttr & DexAttr.FEMALE); this.canCycleAbility = [ abilityAttr & AbilityAttr.ABILITY_1, (abilityAttr & AbilityAttr.ABILITY_2) && species.ability2, abilityAttr & AbilityAttr.ABILITY_HIDDEN ].filter(a => a).length > 1; @@ -2410,13 +2593,15 @@ export default class StarterSelectUiHandler extends MessageUiHandler { }) as StarterMoveset; const speciesForm = getPokemonSpeciesForm(species.speciesId, formIndex); + const formText = Utils.capitalizeString(species?.forms[formIndex]?.formKey, "_", false, false); - const formText = species?.forms[formIndex]?.formKey.split("-"); - for (let i = 0; i < formText?.length; i++) { - formText[i] = formText[i].charAt(0).toUpperCase() + formText[i].substring(1); - } + const speciesName = Utils.capitalizeString(Species[species.speciesId], "_", true, false); - this.pokemonFormText.setText(formText?.join(" ")); + if (species.speciesId === Species.ARCEUS) { + this.pokemonFormText.setText(i18next.t(`pokemonInfo:Type.${formText.toUpperCase()}`)); + } else { + this.pokemonFormText.setText(formText ? i18next.t(`pokemonForm:${speciesName}${formText}`) : ""); + } this.setTypeIcons(speciesForm.type1, speciesForm.type2); } else { @@ -2479,28 +2664,54 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } - popStarter(): void { - this.starterGens.pop(); - this.starterCursors.pop(); - this.starterAttr.pop(); - this.starterAbilityIndexes.pop(); - this.starterNatures.pop(); - this.starterMovesets.pop(); - this.starterCursorObjs[this.starterCursors.length].setVisible(false); - this.starterIcons[this.starterCursors.length].setTexture("pokemon_icons_0"); - this.starterIcons[this.starterCursors.length].setFrame("unknown"); + popStarter(index: number): void { + this.starterSpecies.splice(index, 1); + this.starterAttr.splice(index, 1); + this.starterAbilityIndexes.splice(index, 1); + this.starterNatures.splice(index, 1); + this.starterMovesets.splice(index, 1); + + for (let s = 0; s < this.starterSpecies.length; s++) { + const species = this.starterSpecies[s]; + const currentDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true); + const props = this.scene.gameData.getSpeciesDexAttrProps(species, currentDexAttr); + this.starterIcons[s].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant)); + this.starterIcons[s].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant)); + if (s >= index) { + this.starterCursorObjs[s].setPosition(this.starterCursorObjs[s + 1].x, this.starterCursorObjs[s + 1].y); + this.starterCursorObjs[s].setVisible(this.starterCursorObjs[s + 1].visible); + } + } + this.starterCursorObjs[this.starterSpecies.length].setVisible(false); + this.starterIcons[this.starterSpecies.length].setTexture("pokemon_icons_0"); + this.starterIcons[this.starterSpecies.length].setFrame("unknown"); + + if (this.starterIconsCursorObj.visible) { + if (this.starterIconsCursorIndex === this.starterSpecies.length) { + if (this.starterSpecies.length > 0) { + this.starterIconsCursorIndex--; + } else { + this.starterIconsCursorObj.setVisible(false); + this.setSpecies(null); + this.setFilterMode(true); + } + } + this.moveStarterIconsCursor(this.starterIconsCursorIndex); + } + this.tryUpdateValue(); } - updateStarterValueLabel(cursor: integer): void { - const speciesId = this.genSpecies[this.getGenCursorWithScroll()][cursor].speciesId; + updateStarterValueLabel(starter: StarterContainer): void { + const speciesId = starter.species.speciesId; const baseStarterValue = speciesStarters[speciesId]; const starterValue = this.scene.gameData.getSpeciesStarterValue(speciesId); + starter.cost = starterValue; let valueStr = starterValue.toString(); if (valueStr.startsWith("0.")) { valueStr = valueStr.slice(1); } - this.starterValueLabels[cursor].setText(valueStr); + starter.label.setText(valueStr); let textStyle: TextStyle; switch (baseStarterValue - starterValue) { case 0: @@ -2514,12 +2725,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler { textStyle = TextStyle.SUMMARY_GOLD; break; } - this.starterValueLabels[cursor].setColor(this.getTextColor(textStyle)); - this.starterValueLabels[cursor].setShadowColor(this.getTextColor(textStyle, true)); + if (baseStarterValue - starterValue > 0) { + starter.label.setColor(this.getTextColor(textStyle)); + starter.label.setShadowColor(this.getTextColor(textStyle, true)); + } } - tryUpdateValue(add?: integer): boolean { - const value = this.starterGens.reduce((total: integer, gen: integer, i: integer) => total += this.scene.gameData.getSpeciesStarterValue(this.genSpecies[gen][this.starterCursors[i]].speciesId), 0); + tryUpdateValue(add?: integer, addingToParty?: boolean): boolean { + const value = this.starterSpecies.map(s => s.generation).reduce((total: integer, gen: integer, i: integer) => total += this.scene.gameData.getSpeciesStarterValue(this.starterSpecies[i].speciesId), 0); const newValue = value + (add || 0); const valueLimit = this.getValueLimit(); const overLimit = newValue > valueLimit; @@ -2534,45 +2747,61 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.scene.time.delayedCall(Utils.fixedInt(500), () => this.tryUpdateValue()); return false; } + if (addingToParty) { // this does a check to see if the pokemon being added is valid; if so, it will update the isPartyValid boolean + const isNewPokemonValid = new Utils.BooleanHolder(true); + const species = this.filteredStarterContainers[this.cursor].species; + Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isNewPokemonValid, this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true)), !!(this.starterSpecies.length + (add ? 1 : 0))); + } /** * this loop is used to set the Sprite's alpha value and check if the user can select other pokemon more. */ this.canAddParty = false; const remainValue = valueLimit - newValue; - for (let g = 0; g < this.genSpecies.length; g++) { - for (let s = 0; s < this.genSpecies[g].length; s++) { - /** Cost of pokemon species */ - const speciesStarterValue = this.scene.gameData.getSpeciesStarterValue(this.genSpecies[g][s].speciesId); - /** Used to detect if this pokemon is registered in starter */ - const speciesStarterDexEntry = this.scene.gameData.dexData[this.genSpecies[g][s].speciesId]; - /** {@linkcode Phaser.GameObjects.Sprite} object of Pokémon for setting the alpha value */ - const speciesSprite = this.starterSelectGenIconContainers[g].getAt(s) as Phaser.GameObjects.Sprite; - + for (let s = 0; s < this.allSpecies.length; s++) { + /** Cost of pokemon species */ + const speciesStarterValue = this.scene.gameData.getSpeciesStarterValue(this.allSpecies[s].speciesId); + /** Used to detect if this pokemon is registered in starter */ + const speciesStarterDexEntry = this.scene.gameData.dexData[this.allSpecies[s].speciesId]; + /** {@linkcode Phaser.GameObjects.Sprite} object of Pokémon for setting the alpha value */ + const speciesSprite = this.starterContainer[s].icon; + + /** + * If remainValue greater than or equal pokemon species and the pokemon is legal for this challenge, the user can select. + * so that the alpha value of pokemon sprite set 1. + * + * However, if isPartyValid is false, that means none of the party members are valid for the run. In this case, we should + * check the challenge to make sure evolutions and forms aren't being checked for mono type runs. + * This will let us set the sprite's alpha to show it can't be selected + * + * If speciesStarterDexEntry?.caughtAttr is true, this species registered in stater. + * we change to can AddParty value to true since the user has enough cost to choose this pokemon and this pokemon registered too. + */ + const isValidForChallenge = new Utils.BooleanHolder(true); + Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.allSpecies[s], isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(this.allSpecies[s], this.scene.gameData.getSpeciesDefaultDexAttr(this.allSpecies[s], false, true)), !!(this.starterSpecies.length + (add ? 1 : 0))); + + const canBeChosen = remainValue >= speciesStarterValue && isValidForChallenge.value; + + const isPokemonInParty = this.isInParty(this.allSpecies[s])[0]; // this will get the valud of isDupe from isInParty. This will let us see if the pokemon in question is in our party already so we don't grey out the sprites if they're invalid + + /* This code does a check to tell whether or not a sprite should be lit up or greyed out. There are 3 ways a pokemon's sprite should be lit up: + * 1) If it's in your party, it's a valid pokemon (i.e. for challenge) and you have enough points to have it + * 2) If it's in your party, it's not valid (i.e. for challenges), and you have enough points to have it + * 3) If it's not in your party, but it's a valid pokemon and you have enough points for it + * Any other time, the sprite should be greyed out. + * For example, if it's in your party, valid, but costs too much, or if it's not in your party and not valid, regardless of cost + */ + if (canBeChosen || (isPokemonInParty && remainValue >= speciesStarterValue)) { + speciesSprite.setAlpha(1); + if (speciesStarterDexEntry?.caughtAttr) { + this.canAddParty = true; + } + } else { /** - * If remainValue greater than or equal pokemon species and the pokemon is legal for this challenge, the user can select. - * so that the alpha value of pokemon sprite set 1. - * - * If speciesStarterDexEntry?.caughtAttr is true, this species registered in stater. - * we change to can AddParty value to true since the user has enough cost to choose this pokemon and this pokemon registered too. + * If it can't be chosen, the user can't select. + * so that the alpha value of pokemon sprite set 0.375. */ - const isValidForChallenge = new Utils.BooleanHolder(true); - Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.genSpecies[g][s], isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(this.genSpecies[g][s], this.scene.gameData.getSpeciesDefaultDexAttr(this.genSpecies[g][s], false, true)), !!(this.starterGens.length || add)); - - const canBeChosen = remainValue >= speciesStarterValue && isValidForChallenge.value; - - if (canBeChosen) { - speciesSprite.setAlpha(1); - if (speciesStarterDexEntry?.caughtAttr) { - this.canAddParty = true; - } - } else { - /** - * If it can't be chosen, the user can't select. - * so that the alpha value of pokemon sprite set 0.375. - */ - speciesSprite.setAlpha(0.375); - } + speciesSprite.setAlpha(0.375); } } @@ -2581,7 +2810,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } tryStart(manualTrigger: boolean = false): boolean { - if (!this.starterGens.length) { + if (!this.starterSpecies.length) { return false; } @@ -2590,39 +2819,60 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const cancel = () => { ui.setMode(Mode.STARTER_SELECT); if (!manualTrigger) { - this.popStarter(); + this.popStarter(this.starterSpecies.length - 1); } this.clearText(); }; - ui.showText(i18next.t("starterSelectUiHandler:confirmStartTeam"), null, () => { - ui.setModeWithoutClear(Mode.CONFIRM, () => { - const startRun = () => { - this.scene.money = this.scene.gameMode.getStartingMoney(); - ui.setMode(Mode.STARTER_SELECT); - const thisObj = this; - const originalStarterSelectCallback = this.starterSelectCallback; - this.starterSelectCallback = null; - originalStarterSelectCallback(new Array(this.starterGens.length).fill(0).map(function (_, i) { - const starterSpecies = thisObj.genSpecies[thisObj.starterGens[i]][thisObj.starterCursors[i]]; - return { - species: starterSpecies, - dexAttr: thisObj.starterAttr[i], - abilityIndex: thisObj.starterAbilityIndexes[i], - passive: !(thisObj.scene.gameData.starterData[starterSpecies.speciesId].passiveAttr ^ (PassiveAttr.ENABLED | PassiveAttr.UNLOCKED)), - nature: thisObj.starterNatures[i] as Nature, - moveset: thisObj.starterMovesets[i], - pokerus: !![ 0, 1, 2 ].filter(n => thisObj.pokerusGens[n] === starterSpecies.generation - 1 && thisObj.pokerusCursors[n] === thisObj.genSpecies[starterSpecies.generation - 1].indexOf(starterSpecies)).length - }; - })); - }; - startRun(); - }, cancel, null, null, 19); - }); - + const canStart = this.isPartyValid(); + + if (canStart) { + ui.showText(i18next.t("starterSelectUiHandler:confirmStartTeam"), null, () => { + ui.setModeWithoutClear(Mode.CONFIRM, () => { + const startRun = () => { + this.scene.money = this.scene.gameMode.getStartingMoney(); + ui.setMode(Mode.STARTER_SELECT); + const thisObj = this; + const originalStarterSelectCallback = this.starterSelectCallback; + this.starterSelectCallback = null; + originalStarterSelectCallback(new Array(this.starterSpecies.length).fill(0).map(function (_, i) { + const starterSpecies = thisObj.starterSpecies[i]; + return { + species: starterSpecies, + dexAttr: thisObj.starterAttr[i], + abilityIndex: thisObj.starterAbilityIndexes[i], + passive: !(thisObj.scene.gameData.starterData[starterSpecies.speciesId].passiveAttr ^ (PassiveAttr.ENABLED | PassiveAttr.UNLOCKED)), + nature: thisObj.starterNatures[i] as Nature, + moveset: thisObj.starterMovesets[i], + pokerus: thisObj.pokerusSpecies.includes(starterSpecies) + }; + })); + }; + startRun(); + }, cancel, null, null, 19); + }); + } else { + const handler = this.scene.ui.getHandler() as AwaitableUiHandler; + handler.tutorialActive = true; + this.scene.ui.showText(i18next.t("starterSelectUiHandler:invalidParty"), null, () => this.scene.ui.showText(null, 0, () => handler.tutorialActive = false), null, true); + } return true; } + /* This block checks to see if your party is valid + * It checks each pokemon against the challenge - noting that due to monotype challenges it needs to check the pokemon while ignoring their evolutions/form change items + */ + isPartyValid(): boolean { + let canStart = false; + for (let s = 0; s < this.starterSpecies.length; s++) { + const isValidForChallenge = new Utils.BooleanHolder(true); + const species = this.starterSpecies[s]; + Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), !!this.starterSpecies.length); + canStart = canStart || isValidForChallenge.value; + } + return canStart; + } + toggleStatsMode(on?: boolean): void { if (on === undefined) { on = !this.statsMode; @@ -2678,8 +2928,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.starterSelectContainer.setVisible(false); this.blockInput = false; - while (this.starterCursors.length) { - this.popStarter(); + while (this.starterSpecies.length) { + this.popStarter(this.starterSpecies.length - 1); } if (this.statsMode) { diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index e20c7dd31a2d..882bc42220f3 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -102,6 +102,7 @@ export default class SummaryUiHandler extends UiHandler { private moveSelect: boolean; private moveCursor: integer; private selectedMoveIndex: integer; + private selectCallback: Function; constructor(scene: BattleScene) { super(scene, Mode.SUMMARY); @@ -302,7 +303,7 @@ export default class SummaryUiHandler extends UiHandler { }); this.pokemon.cry(); - this.nameText.setText(this.pokemon.name); + this.nameText.setText(this.pokemon.getNameToRender()); const isFusion = this.pokemon.isFusion(); @@ -368,6 +369,9 @@ export default class SummaryUiHandler extends UiHandler { const page = args.length < 2 ? Page.PROFILE : args[2] as Page; this.hideMoveEffect(true); this.setCursor(page); + if (args.length > 3) { + this.selectCallback = args[3]; + } break; case SummaryUiMode.LEARN_MOVE: this.newMove = args[2] as Move; @@ -397,7 +401,7 @@ export default class SummaryUiHandler extends UiHandler { } const ui = this.getUi(); - + const fromPartyMode = ui.handlers[Mode.PARTY].active; let success = false; let error = false; @@ -485,7 +489,17 @@ export default class SummaryUiHandler extends UiHandler { if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { this.hideMoveSelect(); } else { - ui.setMode(Mode.PARTY); + if (this.selectCallback instanceof Function) { + const selectCallback = this.selectCallback; + this.selectCallback = null; + selectCallback(); + } + + if (!fromPartyMode) { + ui.setMode(Mode.MESSAGE); + } else { + ui.setMode(Mode.PARTY); + } } success = true; } else { @@ -495,6 +509,8 @@ export default class SummaryUiHandler extends UiHandler { case Button.DOWN: if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { break; + } else if (!fromPartyMode) { + break; } const isDown = button === Button.DOWN; const party = this.scene.getParty(); diff --git a/src/ui/ui.ts b/src/ui/ui.ts index ce834a83645b..ae1bc10a74fa 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -46,6 +46,7 @@ import SettingsDisplayUiHandler from "./settings/settings-display-ui-handler"; import SettingsAudioUiHandler from "./settings/settings-audio-ui-handler"; import { PlayerGender } from "#enums/player-gender"; import BgmBar from "#app/ui/bgm-bar"; +import RenameFormUiHandler from "./rename-form-ui-handler"; export enum Mode { MESSAGE, @@ -83,7 +84,8 @@ export enum Mode { SESSION_RELOAD, UNAVAILABLE, OUTDATED, - CHALLENGE_SELECT + CHALLENGE_SELECT, + RENAME_POKEMON } const transitionModes = [ @@ -119,7 +121,8 @@ const noTransitionModes = [ Mode.LOADING, Mode.SESSION_RELOAD, Mode.UNAVAILABLE, - Mode.OUTDATED + Mode.OUTDATED, + Mode.RENAME_POKEMON ]; export default class UI extends Phaser.GameObjects.Container { @@ -180,7 +183,8 @@ export default class UI extends Phaser.GameObjects.Container { new SessionReloadModalUiHandler(scene), new UnavailableModalUiHandler(scene), new OutdatedModalUiHandler(scene), - new GameChallengesUiHandler(scene) + new GameChallengesUiHandler(scene), + new RenameFormUiHandler(scene), ]; } diff --git a/src/ui/unavailable-modal-ui-handler.ts b/src/ui/unavailable-modal-ui-handler.ts index 2f6e1c08832d..c864801d9b4f 100644 --- a/src/ui/unavailable-modal-ui-handler.ts +++ b/src/ui/unavailable-modal-ui-handler.ts @@ -58,7 +58,7 @@ export default class UnavailableModalUiHandler extends ModalUiHandler { this.scene.playSound("pb_bounce_1"); this.reconnectCallback(); } else if (response[1] === 401) { - Utils.setCookie(Utils.sessionIdKey, ""); + Utils.removeCookie(Utils.sessionIdKey); this.scene.reset(true, true); } else { this.reconnectDuration = Math.min(this.reconnectDuration * 2, this.maxTime); // Set a max delay so it isn't infinite diff --git a/src/utils.ts b/src/utils.ts index 954ed7cc3fa3..467d7601d383 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -297,10 +297,20 @@ export const isBeta = import.meta.env.MODE === "beta"; // this checks to see if export function setCookie(cName: string, cValue: string): void { const expiration = new Date(); expiration.setTime(new Date().getTime() + 3600000 * 24 * 30 * 3/*7*/); - document.cookie = `${cName}=${cValue};Secure;SameSite=Strict;Path=/;Expires=${expiration.toUTCString()}`; + document.cookie = `${cName}=${cValue};Secure;SameSite=Strict;Domain=${window.location.hostname};Path=/;Expires=${expiration.toUTCString()}`; +} + +export function removeCookie(cName: string): void { + document.cookie = `${cName}=;Secure;SameSite=Strict;Domain=${window.location.hostname};Path=/;Max-Age=-1`; + document.cookie = `${cName}=;Secure;SameSite=Strict;Path=/;Max-Age=-1`; // legacy cookie without domain, for older cookies to prevent a login loop } export function getCookie(cName: string): string { + // check if there are multiple cookies with the same name and delete them + if (document.cookie.split(";").filter(c => c.includes(cName)).length > 1) { + removeCookie(cName); + return ""; + } const name = `${cName}=`; const ca = document.cookie.split(";"); for (let i = 0; i < ca.length; i++) { @@ -536,4 +546,24 @@ export function reverseValueToKeySetting(input) { return capitalizedWords.join("_"); } +/** + * Capitalize a string. + * + * @param str - The string to be capitalized. + * @param sep - The separator between the words of the string. + * @param lowerFirstChar - Whether the first character of the string should be lowercase or not. + * @param returnWithSpaces - Whether the returned string should have spaces between the words or not. + * @returns The capitalized string. + */ +export function capitalizeString(str: string, sep: string, lowerFirstChar: boolean = true, returnWithSpaces: boolean = false) { + if (str) { + const splitedStr = str.toLowerCase().split(sep); + + for (let i = +lowerFirstChar; i < splitedStr?.length; i++) { + splitedStr[i] = splitedStr[i].charAt(0).toUpperCase() + splitedStr[i].substring(1); + } + return returnWithSpaces ? splitedStr.join(" ") : splitedStr.join(""); + } + return null; +}