diff --git a/.gitignore b/.gitignore index 55f9203a81d..d4fd3762cb4 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,9 @@ dist-ssr *.sln *.sw? +# Docummentation +docs/* + public/images/trainer/convert/* public/images/battle_anims/input/*.png public/images/pokemon/input/*.png diff --git a/public/images/cg/end_f.png b/public/images/cg/end_f.png new file mode 100644 index 00000000000..84f94d7e05d Binary files /dev/null and b/public/images/cg/end_f.png differ diff --git a/public/images/cg/end_m.png b/public/images/cg/end_m.png new file mode 100644 index 00000000000..abdcb49aff9 Binary files /dev/null and b/public/images/cg/end_m.png differ diff --git a/public/images/items.json b/public/images/items.json index 939b3927e7a..05f715ff078 100644 --- a/public/images/items.json +++ b/public/images/items.json @@ -4,8 +4,8 @@ "image": "items.png", "format": "RGBA8888", "size": { - "w": 396, - "h": 396 + "w": 399, + "h": 399 }, "scale": 1, "frames": [ @@ -555,6 +555,27 @@ "h": 20 } }, + { + "filename": "lure", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 17, + "h": 24 + }, + "frame": { + "x": 382, + "y": 0, + "w": 17, + "h": 24 + } + }, { "filename": "catching_charm", "rotated": false, @@ -703,7 +724,7 @@ } }, { - "filename": "mega_bracelet", + "filename": "coupon", "rotated": false, "trimmed": true, "sourceSize": { @@ -711,20 +732,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 16 + "x": 4, + "y": 7, + "w": 23, + "h": 19 }, "frame": { "x": 0, "y": 380, - "w": 20, - "h": 16 + "w": 23, + "h": 19 } }, { - "filename": "relic_band", + "filename": "golden_mystic_ticket", "rotated": false, "trimmed": true, "sourceSize": { @@ -732,16 +753,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 17, - "h": 16 + "x": 4, + "y": 7, + "w": 23, + "h": 19 }, "frame": { - "x": 20, + "x": 23, "y": 380, - "w": 17, - "h": 16 + "w": 23, + "h": 19 } }, { @@ -1039,7 +1060,7 @@ } }, { - "filename": "elixir", + "filename": "oval_charm", "rotated": false, "trimmed": true, "sourceSize": { @@ -1047,15 +1068,15 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, + "x": 6, "y": 4, - "w": 18, + "w": 21, "h": 24 }, "frame": { "x": 378, - "y": 20, - "w": 18, + "y": 24, + "w": 21, "h": 24 } }, @@ -1102,7 +1123,7 @@ } }, { - "filename": "oval_charm", + "filename": "red_orb", "rotated": false, "trimmed": true, "sourceSize": { @@ -1112,13 +1133,13 @@ "spriteSourceSize": { "x": 6, "y": 4, - "w": 21, + "w": 20, "h": 24 }, "frame": { "x": 24, "y": 224, - "w": 21, + "w": 20, "h": 24 } }, @@ -1228,7 +1249,7 @@ } }, { - "filename": "abomasite", + "filename": "mega_bracelet", "rotated": false, "trimmed": true, "sourceSize": { @@ -1236,83 +1257,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, + "x": 6, "y": 8, - "w": 16, + "w": 20, "h": 16 }, "frame": { "x": 24, "y": 364, - "w": 16, + "w": 20, "h": 16 } }, { - "filename": "absolite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 37, - "y": 380, - "w": 16, - "h": 16 - } - }, - { - "filename": "aerodactylite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 40, - "y": 364, - "w": 16, - "h": 16 - } - }, - { - "filename": "aggronite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 53, - "y": 380, - "w": 16, - "h": 16 - } - }, - { - "filename": "ether", + "filename": "elixir", "rotated": false, "trimmed": true, "sourceSize": { @@ -1333,7 +1291,7 @@ } }, { - "filename": "full_restore", + "filename": "ether", "rotated": false, "trimmed": true, "sourceSize": { @@ -1354,7 +1312,7 @@ } }, { - "filename": "max_elixir", + "filename": "full_restore", "rotated": false, "trimmed": true, "sourceSize": { @@ -1417,7 +1375,7 @@ } }, { - "filename": "max_ether", + "filename": "max_elixir", "rotated": false, "trimmed": true, "sourceSize": { @@ -1438,7 +1396,7 @@ } }, { - "filename": "hp_up", + "filename": "max_ether", "rotated": false, "trimmed": true, "sourceSize": { @@ -1446,20 +1404,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, + "x": 7, "y": 4, - "w": 16, + "w": 18, "h": 24 }, "frame": { - "x": 45, + "x": 44, "y": 224, - "w": 16, + "w": 18, "h": 24 } }, { - "filename": "iron", + "filename": "hp_up", "rotated": false, "trimmed": true, "sourceSize": { @@ -1480,7 +1438,7 @@ } }, { - "filename": "lure", + "filename": "iron", "rotated": false, "trimmed": true, "sourceSize": { @@ -1490,13 +1448,13 @@ "spriteSourceSize": { "x": 8, "y": 4, - "w": 17, + "w": 16, "h": 24 }, "frame": { "x": 47, "y": 272, - "w": 17, + "w": 16, "h": 24 } }, @@ -1563,69 +1521,6 @@ "h": 23 } }, - { - "filename": "alakazite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 56, - "y": 364, - "w": 16, - "h": 16 - } - }, - { - "filename": "altarianite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 69, - "y": 380, - "w": 16, - "h": 16 - } - }, - { - "filename": "revive", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 12, - "h": 17 - }, - "frame": { - "x": 382, - "y": 0, - "w": 12, - "h": 17 - } - }, { "filename": "ability_capsule", "rotated": false, @@ -1641,12 +1536,33 @@ "h": 14 }, "frame": { - "x": 138, - "y": 46, + "x": 44, + "y": 364, "w": 24, "h": 14 } }, + { + "filename": "amulet_coin", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 23, + "h": 21 + }, + "frame": { + "x": 46, + "y": 378, + "w": 23, + "h": 21 + } + }, { "filename": "choice_specs", "rotated": false, @@ -1662,29 +1578,8 @@ "h": 18 }, "frame": { - "x": 162, - "y": 45, - "w": 24, - "h": 18 - } - }, - { - "filename": "dragon_scale", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 24, - "h": 18 - }, - "frame": { - "x": 186, - "y": 45, + "x": 138, + "y": 46, "w": 24, "h": 18 } @@ -1704,7 +1599,7 @@ "h": 22 }, "frame": { - "x": 210, + "x": 162, "y": 45, "w": 24, "h": 22 @@ -1725,7 +1620,7 @@ "h": 22 }, "frame": { - "x": 234, + "x": 186, "y": 45, "w": 24, "h": 22 @@ -1746,7 +1641,7 @@ "h": 23 }, "frame": { - "x": 258, + "x": 210, "y": 45, "w": 24, "h": 23 @@ -1767,7 +1662,7 @@ "h": 23 }, "frame": { - "x": 282, + "x": 234, "y": 45, "w": 24, "h": 23 @@ -1788,8 +1683,8 @@ "h": 23 }, "frame": { - "x": 306, - "y": 44, + "x": 258, + "y": 45, "w": 24, "h": 23 } @@ -1809,56 +1704,14 @@ "h": 22 }, "frame": { - "x": 330, - "y": 43, + "x": 282, + "y": 45, "w": 24, "h": 22 } }, { - "filename": "healing_charm", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 23, - "h": 22 - }, - "frame": { - "x": 354, - "y": 43, - "w": 23, - "h": 22 - } - }, - { - "filename": "lock_capsule", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 19, - "h": 22 - }, - "frame": { - "x": 377, - "y": 44, - "w": 19, - "h": 22 - } - }, - { - "filename": "icy_reins_of_unity", + "filename": "rare_candy", "rotated": false, "trimmed": true, "sourceSize": { @@ -1867,141 +1720,15 @@ }, "spriteSourceSize": { "x": 4, - "y": 7, - "w": 24, - "h": 20 - }, - "frame": { - "x": 330, - "y": 65, - "w": 24, - "h": 20 - } - }, - { - "filename": "amulet_coin", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, "y": 5, "w": 23, - "h": 21 - }, - "frame": { - "x": 354, - "y": 65, - "w": 23, - "h": 21 - } - }, - { - "filename": "metal_coat", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 19, - "h": 22 - }, - "frame": { - "x": 377, - "y": 66, - "w": 19, - "h": 22 - } - }, - { - "filename": "rusted_shield", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 24, - "h": 20 + "h": 23 }, "frame": { "x": 306, - "y": 67, - "w": 24, - "h": 20 - } - }, - { - "filename": "sacred_ash", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 24, - "h": 20 - }, - "frame": { - "x": 330, - "y": 85, - "w": 24, - "h": 20 - } - }, - { - "filename": "auspicious_armor", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, + "y": 44, "w": 23, - "h": 21 - }, - "frame": { - "x": 354, - "y": 86, - "w": 23, - "h": 21 - } - }, - { - "filename": "spell_tag", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 19, - "h": 21 - }, - "frame": { - "x": 377, - "y": 88, - "w": 19, - "h": 21 + "h": 23 } }, { @@ -2026,7 +1753,7 @@ } }, { - "filename": "red_orb", + "filename": "super_lure", "rotated": false, "trimmed": true, "sourceSize": { @@ -2034,102 +1761,18 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, + "x": 8, "y": 4, - "w": 20, + "w": 17, "h": 24 }, "frame": { "x": 61, "y": 200, - "w": 20, + "w": 17, "h": 24 } }, - { - "filename": "bug_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 61, - "y": 224, - "w": 22, - "h": 23 - } - }, - { - "filename": "dark_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 63, - "y": 247, - "w": 22, - "h": 23 - } - }, - { - "filename": "dragon_fang", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 21, - "h": 23 - }, - "frame": { - "x": 64, - "y": 270, - "w": 21, - "h": 23 - } - }, - { - "filename": "dragon_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 64, - "y": 293, - "w": 22, - "h": 23 - } - }, { "filename": "max_repel", "rotated": false, @@ -2145,8 +1788,8 @@ "h": 24 }, "frame": { - "x": 70, - "y": 316, + "x": 62, + "y": 224, "w": 16, "h": 24 } @@ -2166,14 +1809,14 @@ "h": 24 }, "frame": { - "x": 70, - "y": 340, + "x": 63, + "y": 248, "w": 16, "h": 24 } }, { - "filename": "ampharosite", + "filename": "pp_up", "rotated": false, "trimmed": true, "sourceSize": { @@ -2182,19 +1825,19 @@ }, "spriteSourceSize": { "x": 8, - "y": 8, + "y": 4, "w": 16, - "h": 16 + "h": 24 }, "frame": { - "x": 72, - "y": 364, + "x": 63, + "y": 272, "w": 16, - "h": 16 + "h": 24 } }, { - "filename": "audinite", + "filename": "protein", "rotated": false, "trimmed": true, "sourceSize": { @@ -2203,15 +1846,225 @@ }, "spriteSourceSize": { "x": 8, - "y": 8, + "y": 4, "w": 16, - "h": 16 + "h": 24 }, "frame": { - "x": 85, - "y": 380, + "x": 64, + "y": 296, "w": 16, - "h": 16 + "h": 24 + } + }, + { + "filename": "repel", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 16, + "h": 24 + }, + "frame": { + "x": 70, + "y": 320, + "w": 16, + "h": 24 + } + }, + { + "filename": "apicot_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 19, + "h": 20 + }, + "frame": { + "x": 70, + "y": 344, + "w": 19, + "h": 20 + } + }, + { + "filename": "bug_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 69, + "y": 364, + "w": 22, + "h": 23 + } + }, + { + "filename": "relic_gold", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 9, + "y": 11, + "w": 15, + "h": 11 + }, + "frame": { + "x": 69, + "y": 387, + "w": 15, + "h": 11 + } + }, + { + "filename": "dragon_scale", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, + "w": 24, + "h": 18 + }, + "frame": { + "x": 330, + "y": 43, + "w": 24, + "h": 18 + } + }, + { + "filename": "icy_reins_of_unity", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 7, + "w": 24, + "h": 20 + }, + "frame": { + "x": 354, + "y": 43, + "w": 24, + "h": 20 + } + }, + { + "filename": "dragon_fang", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 21, + "h": 23 + }, + "frame": { + "x": 378, + "y": 48, + "w": 21, + "h": 23 + } + }, + { + "filename": "rusted_shield", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 24, + "h": 20 + }, + "frame": { + "x": 329, + "y": 61, + "w": 24, + "h": 20 + } + }, + { + "filename": "sacred_ash", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 7, + "w": 24, + "h": 20 + }, + "frame": { + "x": 353, + "y": 63, + "w": 24, + "h": 20 + } + }, + { + "filename": "dark_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 377, + "y": 71, + "w": 22, + "h": 23 } }, { @@ -2256,6 +2109,27 @@ "h": 20 } }, + { + "filename": "auspicious_armor", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 23, + "h": 21 + }, + "frame": { + "x": 115, + "y": 50, + "w": 23, + "h": 21 + } + }, { "filename": "binding_band", "rotated": false, @@ -2271,8 +2145,8 @@ "h": 20 }, "frame": { - "x": 115, - "y": 50, + "x": 138, + "y": 64, "w": 23, "h": 20 } @@ -2292,8 +2166,8 @@ "h": 17 }, "frame": { - "x": 138, - "y": 60, + "x": 161, + "y": 67, "w": 23, "h": 17 } @@ -2313,8 +2187,8 @@ "h": 17 }, "frame": { - "x": 161, - "y": 63, + "x": 184, + "y": 67, "w": 23, "h": 17 } @@ -2334,14 +2208,14 @@ "h": 17 }, "frame": { - "x": 184, - "y": 63, + "x": 207, + "y": 68, "w": 23, "h": 17 } }, { - "filename": "coupon", + "filename": "douse_drive", "rotated": false, "trimmed": true, "sourceSize": { @@ -2350,36 +2224,99 @@ }, "spriteSourceSize": { "x": 4, - "y": 7, + "y": 8, "w": 23, - "h": 19 - }, - "frame": { - "x": 207, - "y": 67, - "w": 23, - "h": 19 - } - }, - { - "filename": "golden_mystic_ticket", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 19 + "h": 17 }, "frame": { "x": 230, + "y": 68, + "w": 23, + "h": 17 + } + }, + { + "filename": "healing_charm", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 23, + "h": 22 + }, + "frame": { + "x": 253, + "y": 68, + "w": 23, + "h": 22 + } + }, + { + "filename": "berry_pot", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 18, + "h": 22 + }, + "frame": { + "x": 276, + "y": 68, + "w": 18, + "h": 22 + } + }, + { + "filename": "rarer_candy", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 23, + "h": 23 + }, + "frame": { + "x": 294, "y": 67, "w": 23, - "h": 19 + "h": 23 + } + }, + { + "filename": "revive", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 12, + "h": 17 + }, + "frame": { + "x": 317, + "y": 67, + "w": 12, + "h": 17 } }, { @@ -2397,8 +2334,8 @@ "h": 21 }, "frame": { - "x": 253, - "y": 68, + "x": 60, + "y": 70, "w": 23, "h": 21 } @@ -2418,73 +2355,10 @@ "h": 21 }, "frame": { - "x": 276, - "y": 68, - "w": 23, - "h": 21 - } - }, - { - "filename": "douse_drive", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 23, - "h": 17 - }, - "frame": { - "x": 60, + "x": 83, "y": 70, "w": 23, - "h": 17 - } - }, - { - "filename": "rare_candy", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 23, - "h": 23 - }, - "frame": { - "x": 57, - "y": 87, - "w": 23, - "h": 23 - } - }, - { - "filename": "rarer_candy", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 23, - "h": 23 - }, - "frame": { - "x": 57, - "y": 110, - "w": 23, - "h": 23 + "h": 21 } }, { @@ -2503,13 +2377,13 @@ }, "frame": { "x": 57, - "y": 133, + "y": 91, "w": 23, "h": 23 } }, { - "filename": "apicot_berry", + "filename": "dragon_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -2518,36 +2392,15 @@ }, "spriteSourceSize": { "x": 6, - "y": 6, - "w": 19, - "h": 20 + "y": 4, + "w": 22, + "h": 23 }, "frame": { - "x": 63, - "y": 156, - "w": 19, - "h": 20 - } - }, - { - "filename": "mystic_ticket", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 19 - }, - "frame": { - "x": 83, - "y": 70, - "w": 23, - "h": 19 + "x": 80, + "y": 91, + "w": 22, + "h": 23 } }, { @@ -2565,12 +2418,33 @@ "h": 23 }, "frame": { - "x": 80, - "y": 89, + "x": 57, + "y": 114, "w": 22, "h": 23 } }, + { + "filename": "super_repel", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 16, + "h": 24 + }, + "frame": { + "x": 57, + "y": 137, + "w": 16, + "h": 24 + } + }, { "filename": "fairy_tera_shard", "rotated": false, @@ -2586,14 +2460,14 @@ "h": 23 }, "frame": { - "x": 80, - "y": 112, + "x": 79, + "y": 114, "w": 22, "h": 23 } }, { - "filename": "deep_sea_tooth", + "filename": "fighting_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -2601,16 +2475,58 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 6, + "x": 6, + "y": 4, "w": 22, - "h": 21 + "h": 23 }, "frame": { - "x": 80, - "y": 135, + "x": 73, + "y": 137, "w": 22, - "h": 21 + "h": 23 + } + }, + { + "filename": "candy_overlay", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 12, + "w": 16, + "h": 15 + }, + "frame": { + "x": 63, + "y": 161, + "w": 16, + "h": 15 + } + }, + { + "filename": "unknown", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 16, + "h": 24 + }, + "frame": { + "x": 79, + "y": 160, + "w": 16, + "h": 24 } }, { @@ -2629,13 +2545,13 @@ }, "frame": { "x": 106, - "y": 70, + "y": 71, "w": 23, "h": 21 } }, { - "filename": "fighting_tera_shard", + "filename": "rusted_sword", "rotated": false, "trimmed": true, "sourceSize": { @@ -2643,16 +2559,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 + "x": 4, + "y": 5, + "w": 23, + "h": 22 }, "frame": { "x": 102, - "y": 91, - "w": 22, - "h": 23 + "y": 92, + "w": 23, + "h": 22 } }, { @@ -2670,54 +2586,12 @@ "h": 23 }, "frame": { - "x": 102, + "x": 101, "y": 114, "w": 22, "h": 23 } }, - { - "filename": "blunder_policy", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 19 - }, - "frame": { - "x": 102, - "y": 137, - "w": 22, - "h": 19 - } - }, - { - "filename": "reviver_seed", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 8, - "w": 23, - "h": 20 - }, - "frame": { - "x": 82, - "y": 156, - "w": 23, - "h": 20 - } - }, { "filename": "fire_tera_shard", "rotated": false, @@ -2733,8 +2607,8 @@ "h": 23 }, "frame": { - "x": 79, - "y": 176, + "x": 95, + "y": 137, "w": 22, "h": 23 } @@ -2754,12 +2628,33 @@ "h": 23 }, "frame": { - "x": 81, - "y": 199, + "x": 95, + "y": 160, "w": 22, "h": 23 } }, + { + "filename": "abomasite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 79, + "y": 184, + "w": 16, + "h": 16 + } + }, { "filename": "focus_sash", "rotated": false, @@ -2775,8 +2670,8 @@ "h": 23 }, "frame": { - "x": 83, - "y": 222, + "x": 78, + "y": 200, "w": 22, "h": 23 } @@ -2796,12 +2691,33 @@ "h": 23 }, "frame": { - "x": 85, - "y": 245, + "x": 78, + "y": 223, "w": 22, "h": 23 } }, + { + "filename": "shock_drive", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, + "w": 23, + "h": 17 + }, + "frame": { + "x": 95, + "y": 183, + "w": 23, + "h": 17 + } + }, { "filename": "grass_tera_shard", "rotated": false, @@ -2817,8 +2733,8 @@ "h": 23 }, "frame": { - "x": 85, - "y": 268, + "x": 79, + "y": 246, "w": 22, "h": 23 } @@ -2838,8 +2754,8 @@ "h": 23 }, "frame": { - "x": 86, - "y": 291, + "x": 79, + "y": 269, "w": 22, "h": 23 } @@ -2859,8 +2775,8 @@ "h": 23 }, "frame": { - "x": 86, - "y": 314, + "x": 100, + "y": 200, "w": 22, "h": 23 } @@ -2880,92 +2796,8 @@ "h": 23 }, "frame": { - "x": 86, - "y": 337, - "w": 22, - "h": 23 - } - }, - { - "filename": "big_nugget", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 - }, - "frame": { - "x": 88, - "y": 360, - "w": 20, - "h": 20 - } - }, - { - "filename": "banettite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 101, - "y": 380, - "w": 16, - "h": 16 - } - }, - { - "filename": "blue_orb", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 - }, - "frame": { - "x": 105, - "y": 156, - "w": 20, - "h": 20 - } - }, - { - "filename": "normal_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 101, - "y": 176, + "x": 100, + "y": 223, "w": 22, "h": 23 } @@ -2985,8 +2817,8 @@ "h": 23 }, "frame": { - "x": 103, - "y": 199, + "x": 101, + "y": 246, "w": 21, "h": 23 } @@ -3006,12 +2838,33 @@ "h": 23 }, "frame": { - "x": 105, - "y": 222, + "x": 101, + "y": 269, "w": 21, "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": 80, + "y": 292, + "w": 22, + "h": 23 + } + }, { "filename": "mystic_water", "rotated": false, @@ -3027,8 +2880,8 @@ "h": 23 }, "frame": { - "x": 107, - "y": 245, + "x": 102, + "y": 292, "w": 20, "h": 23 } @@ -3048,12 +2901,33 @@ "h": 23 }, "frame": { - "x": 107, - "y": 268, + "x": 86, + "y": 315, "w": 22, "h": 23 } }, + { + "filename": "full_heal", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 9, + "y": 4, + "w": 15, + "h": 23 + }, + "frame": { + "x": 108, + "y": 315, + "w": 15, + "h": 23 + } + }, { "filename": "poison_tera_shard", "rotated": false, @@ -3069,8 +2943,8 @@ "h": 23 }, "frame": { - "x": 108, - "y": 291, + "x": 89, + "y": 338, "w": 22, "h": 23 } @@ -3090,56 +2964,14 @@ "h": 23 }, "frame": { - "x": 108, - "y": 314, + "x": 91, + "y": 361, "w": 22, "h": 23 } }, { - "filename": "reaper_cloth", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 108, - "y": 337, - "w": 22, - "h": 23 - } - }, - { - "filename": "deep_sea_scale", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 20 - }, - "frame": { - "x": 108, - "y": 360, - "w": 22, - "h": 20 - } - }, - { - "filename": "beedrillite", + "filename": "hyper_potion", "rotated": false, "trimmed": true, "sourceSize": { @@ -3148,246 +2980,78 @@ }, "spriteSourceSize": { "x": 8, + "y": 5, + "w": 17, + "h": 23 + }, + "frame": { + "x": 111, + "y": 338, + "w": 17, + "h": 23 + } + }, + { + "filename": "potion", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 17, + "h": 23 + }, + "frame": { + "x": 113, + "y": 361, + "w": 17, + "h": 23 + } + }, + { + "filename": "prism_scale", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 9, "y": 8, + "w": 15, + "h": 15 + }, + "frame": { + "x": 91, + "y": 384, + "w": 15, + "h": 15 + } + }, + { + "filename": "zinc", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, "w": 16, - "h": 16 + "h": 24 }, "frame": { "x": 117, - "y": 380, - "w": 16, - "h": 16 - } - }, - { - "filename": "pp_up", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, + "y": 137, "w": 16, "h": 24 - }, - "frame": { - "x": 124, - "y": 91, - "w": 16, - "h": 24 - } - }, - { - "filename": "protein", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 124, - "y": 115, - "w": 16, - "h": 24 - } - }, - { - "filename": "everstone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 17 - }, - "frame": { - "x": 124, - "y": 139, - "w": 20, - "h": 17 - } - }, - { - "filename": "candy_jar", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 19, - "h": 20 - }, - "frame": { - "x": 125, - "y": 156, - "w": 19, - "h": 20 - } - }, - { - "filename": "rock_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 123, - "y": 176, - "w": 22, - "h": 23 - } - }, - { - "filename": "sharp_beak", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 21, - "h": 23 - }, - "frame": { - "x": 124, - "y": 199, - "w": 21, - "h": 23 - } - }, - { - "filename": "steel_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 126, - "y": 222, - "w": 22, - "h": 23 - } - }, - { - "filename": "stellar_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 127, - "y": 245, - "w": 22, - "h": 23 - } - }, - { - "filename": "water_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 129, - "y": 268, - "w": 22, - "h": 23 - } - }, - { - "filename": "whipped_dream", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 4, - "w": 21, - "h": 23 - }, - "frame": { - "x": 130, - "y": 291, - "w": 21, - "h": 23 - } - }, - { - "filename": "wide_lens", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 130, - "y": 314, - "w": 22, - "h": 23 } }, { @@ -3405,533 +3069,8 @@ "h": 22 }, "frame": { - "x": 130, - "y": 337, - "w": 22, - "h": 22 - } - }, - { - "filename": "liechi_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 21 - }, - "frame": { - "x": 130, - "y": 359, - "w": 22, - "h": 21 - } - }, - { - "filename": "blastoisinite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 133, - "y": 380, - "w": 16, - "h": 16 - } - }, - { - "filename": "blazikenite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 149, - "y": 380, - "w": 16, - "h": 16 - } - }, - { - "filename": "dusk_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 21, - "h": 21 - }, - "frame": { - "x": 140, - "y": 77, - "w": 21, - "h": 21 - } - }, - { - "filename": "dire_hit", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 140, - "y": 98, - "w": 22, - "h": 22 - } - }, - { - "filename": "dubious_disc", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 22, - "h": 19 - }, - "frame": { - "x": 140, - "y": 120, - "w": 22, - "h": 19 - } - }, - { - "filename": "relic_crown", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 18 - }, - "frame": { - "x": 161, - "y": 80, - "w": 23, - "h": 18 - } - }, - { - "filename": "pair_of_tickets", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 19 - }, - "frame": { - "x": 184, - "y": 80, - "w": 23, - "h": 19 - } - }, - { - "filename": "dna_splicers", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 162, - "y": 98, - "w": 22, - "h": 22 - } - }, - { - "filename": "rusted_sword", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 23, - "h": 22 - }, - "frame": { - "x": 184, - "y": 99, - "w": 23, - "h": 22 - } - }, - { - "filename": "electirizer", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 207, - "y": 86, - "w": 22, - "h": 22 - } - }, - { - "filename": "enigma_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 229, - "y": 86, - "w": 22, - "h": 22 - } - }, - { - "filename": "fairy_feather", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 22, - "h": 20 - }, - "frame": { - "x": 162, - "y": 120, - "w": 22, - "h": 20 - } - }, - { - "filename": "sachet", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 18, - "h": 23 - }, - "frame": { - "x": 144, - "y": 139, - "w": 18, - "h": 23 - } - }, - { - "filename": "ganlon_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 162, - "y": 140, - "w": 22, - "h": 22 - } - }, - { - "filename": "guard_spec", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 184, - "y": 121, - "w": 22, - "h": 22 - } - }, - { - "filename": "ice_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 184, - "y": 143, - "w": 22, - "h": 22 - } - }, - { - "filename": "shell_bell", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 23, - "h": 20 - }, - "frame": { - "x": 251, - "y": 89, - "w": 23, - "h": 20 - } - }, - { - "filename": "wellspring_mask", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 23, - "h": 21 - }, - "frame": { - "x": 274, - "y": 89, - "w": 23, - "h": 21 - } - }, - { - "filename": "shock_drive", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 23, - "h": 17 - }, - "frame": { - "x": 207, - "y": 108, - "w": 23, - "h": 17 - } - }, - { - "filename": "magmarizer", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 206, - "y": 125, - "w": 22, - "h": 22 - } - }, - { - "filename": "malicious_armor", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 20 - }, - "frame": { - "x": 206, - "y": 147, - "w": 22, - "h": 20 - } - }, - { - "filename": "masterpiece_teacup", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 21, - "h": 18 - }, - "frame": { - "x": 230, - "y": 108, - "w": 21, - "h": 18 - } - }, - { - "filename": "memory_bug", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 228, - "y": 126, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_dark", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 228, - "y": 148, + "x": 117, + "y": 161, "w": 22, "h": 22 } @@ -3951,12 +3090,579 @@ "h": 17 }, "frame": { - "x": 251, - "y": 109, + "x": 118, + "y": 183, "w": 23, "h": 17 } }, + { + "filename": "reaper_cloth", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 23 + }, + "frame": { + "x": 122, + "y": 200, + "w": 22, + "h": 23 + } + }, + { + "filename": "rock_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 122, + "y": 223, + "w": 22, + "h": 23 + } + }, + { + "filename": "steel_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 122, + "y": 246, + "w": 22, + "h": 23 + } + }, + { + "filename": "stellar_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 122, + "y": 269, + "w": 22, + "h": 23 + } + }, + { + "filename": "water_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 122, + "y": 292, + "w": 22, + "h": 23 + } + }, + { + "filename": "sharp_beak", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 21, + "h": 23 + }, + "frame": { + "x": 123, + "y": 315, + "w": 21, + "h": 23 + } + }, + { + "filename": "sachet", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 18, + "h": 23 + }, + "frame": { + "x": 128, + "y": 338, + "w": 18, + "h": 23 + } + }, + { + "filename": "super_potion", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 17, + "h": 23 + }, + "frame": { + "x": 130, + "y": 361, + "w": 17, + "h": 23 + } + }, + { + "filename": "whipped_dream", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 4, + "w": 21, + "h": 23 + }, + "frame": { + "x": 123, + "y": 114, + "w": 21, + "h": 23 + } + }, + { + "filename": "dire_hit", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 125, + "y": 92, + "w": 22, + "h": 22 + } + }, + { + "filename": "wide_lens", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 147, + "y": 84, + "w": 22, + "h": 23 + } + }, + { + "filename": "dna_splicers", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 169, + "y": 84, + "w": 22, + "h": 22 + } + }, + { + "filename": "leftovers", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 15, + "h": 22 + }, + "frame": { + "x": 191, + "y": 84, + "w": 15, + "h": 22 + } + }, + { + "filename": "wellspring_mask", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 23, + "h": 21 + }, + "frame": { + "x": 206, + "y": 85, + "w": 23, + "h": 21 + } + }, + { + "filename": "deep_sea_tooth", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 21 + }, + "frame": { + "x": 229, + "y": 85, + "w": 22, + "h": 21 + } + }, + { + "filename": "mystic_ticket", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 7, + "w": 23, + "h": 19 + }, + "frame": { + "x": 251, + "y": 90, + "w": 23, + "h": 19 + } + }, + { + "filename": "pair_of_tickets", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 7, + "w": 23, + "h": 19 + }, + "frame": { + "x": 274, + "y": 90, + "w": 23, + "h": 19 + } + }, + { + "filename": "big_nugget", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 20, + "h": 20 + }, + "frame": { + "x": 297, + "y": 90, + "w": 20, + "h": 20 + } + }, + { + "filename": "electirizer", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 317, + "y": 84, + "w": 22, + "h": 22 + } + }, + { + "filename": "enigma_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 133, + "y": 137, + "w": 22, + "h": 22 + } + }, + { + "filename": "ganlon_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 139, + "y": 159, + "w": 22, + "h": 22 + } + }, + { + "filename": "blunder_policy", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 19 + }, + "frame": { + "x": 141, + "y": 181, + "w": 22, + "h": 19 + } + }, + { + "filename": "guard_spec", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 144, + "y": 200, + "w": 22, + "h": 22 + } + }, + { + "filename": "ice_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 144, + "y": 222, + "w": 22, + "h": 22 + } + }, + { + "filename": "magmarizer", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 144, + "y": 244, + "w": 22, + "h": 22 + } + }, + { + "filename": "memory_bug", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 144, + "y": 266, + "w": 22, + "h": 22 + } + }, + { + "filename": "memory_dark", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 144, + "y": 288, + "w": 22, + "h": 22 + } + }, { "filename": "memory_dragon", "rotated": false, @@ -3972,701 +3678,8 @@ "h": 22 }, "frame": { - "x": 250, - "y": 126, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_electric", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 250, - "y": 148, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_fairy", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 274, - "y": 110, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_fighting", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 272, - "y": 132, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_fire", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 272, - "y": 154, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_flying", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 145, - "y": 162, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_ghost", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 145, - "y": 184, - "w": 22, - "h": 22 - } - }, - { - "filename": "super_lure", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 17, - "h": 24 - }, - "frame": { - "x": 167, - "y": 162, - "w": 17, - "h": 24 - } - }, - { - "filename": "memory_grass", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 184, - "y": 165, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_ground", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 206, - "y": 167, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_ice", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 228, - "y": 170, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_normal", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 250, - "y": 170, - "w": 22, - "h": 22 - } - }, - { - "filename": "tm_normal", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 250, - "y": 170, - "w": 22, - "h": 22 - } - }, - { - "filename": "golden_egg", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 17, - "h": 20 - }, - "frame": { - "x": 167, - "y": 186, - "w": 17, - "h": 20 - } - }, - { - "filename": "memory_poison", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 184, - "y": 187, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_psychic", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 206, - "y": 189, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_rock", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 228, - "y": 192, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_steel", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 250, - "y": 192, - "w": 22, - "h": 22 - } - }, - { - "filename": "memory_water", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 272, - "y": 176, - "w": 22, - "h": 22 - } - }, - { - "filename": "mini_black_hole", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 272, - "y": 198, - "w": 22, - "h": 22 - } - }, - { - "filename": "cameruptite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 145, - "y": 206, - "w": 16, - "h": 16 - } - }, - { - "filename": "protector", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 161, - "y": 206, - "w": 22, - "h": 22 - } - }, - { - "filename": "scroll_of_darkness", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 183, - "y": 209, - "w": 22, - "h": 22 - } - }, - { - "filename": "scroll_of_waters", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 205, - "y": 211, - "w": 22, - "h": 22 - } - }, - { - "filename": "shed_shell", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 227, - "y": 214, - "w": 22, - "h": 22 - } - }, - { - "filename": "starf_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 249, - "y": 214, - "w": 22, - "h": 22 - } - }, - { - "filename": "sweet_apple", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 21 - }, - "frame": { - "x": 271, - "y": 220, - "w": 22, - "h": 21 - } - }, - { - "filename": "repel", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 294, - "y": 132, - "w": 16, - "h": 24 - } - }, - { - "filename": "super_repel", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 294, - "y": 156, - "w": 16, - "h": 24 - } - }, - { - "filename": "unknown", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 294, - "y": 180, - "w": 16, - "h": 24 - } - }, - { - "filename": "dawn_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 21 - }, - "frame": { - "x": 310, - "y": 87, - "w": 20, - "h": 21 - } - }, - { - "filename": "berry_pot", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 18, - "h": 22 - }, - "frame": { - "x": 296, - "y": 110, - "w": 18, - "h": 22 - } - }, - { - "filename": "zinc", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 314, - "y": 108, - "w": 16, - "h": 24 - } - }, - { - "filename": "thunder_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 330, - "y": 105, + "x": 144, + "y": 310, "w": 22, "h": 22 } @@ -4686,12 +3699,915 @@ "h": 22 }, "frame": { - "x": 310, - "y": 132, + "x": 146, + "y": 332, "w": 20, "h": 22 } }, + { + "filename": "lock_capsule", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 19, + "h": 22 + }, + "frame": { + "x": 147, + "y": 354, + "w": 19, + "h": 22 + } + }, + { + "filename": "deep_sea_scale", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 20 + }, + "frame": { + "x": 147, + "y": 107, + "w": 22, + "h": 20 + } + }, + { + "filename": "liechi_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 21 + }, + "frame": { + "x": 169, + "y": 106, + "w": 22, + "h": 21 + } + }, + { + "filename": "memory_electric", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 191, + "y": 106, + "w": 22, + "h": 22 + } + }, + { + "filename": "memory_fairy", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 213, + "y": 106, + "w": 22, + "h": 22 + } + }, + { + "filename": "mystery_egg", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 18 + }, + "frame": { + "x": 235, + "y": 106, + "w": 16, + "h": 18 + } + }, + { + "filename": "relic_crown", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 7, + "w": 23, + "h": 18 + }, + "frame": { + "x": 251, + "y": 109, + "w": 23, + "h": 18 + } + }, + { + "filename": "reviver_seed", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 8, + "w": 23, + "h": 20 + }, + "frame": { + "x": 274, + "y": 109, + "w": 23, + "h": 20 + } + }, + { + "filename": "blue_orb", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 20, + "h": 20 + }, + "frame": { + "x": 297, + "y": 110, + "w": 20, + "h": 20 + } + }, + { + "filename": "memory_fighting", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 317, + "y": 106, + "w": 22, + "h": 22 + } + }, + { + "filename": "memory_fire", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 155, + "y": 127, + "w": 22, + "h": 22 + } + }, + { + "filename": "memory_flying", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 339, + "y": 83, + "w": 22, + "h": 22 + } + }, + { + "filename": "memory_ghost", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 339, + "y": 105, + "w": 22, + "h": 22 + } + }, + { + "filename": "absolite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 361, + "y": 83, + "w": 16, + "h": 16 + } + }, + { + "filename": "memory_grass", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 377, + "y": 94, + "w": 22, + "h": 22 + } + }, + { + "filename": "aerodactylite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 361, + "y": 99, + "w": 16, + "h": 16 + } + }, + { + "filename": "aggronite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 361, + "y": 115, + "w": 16, + "h": 16 + } + }, + { + "filename": "memory_ground", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 377, + "y": 116, + "w": 22, + "h": 22 + } + }, + { + "filename": "memory_ice", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 177, + "y": 128, + "w": 22, + "h": 22 + } + }, + { + "filename": "memory_normal", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 199, + "y": 128, + "w": 22, + "h": 22 + } + }, + { + "filename": "tm_normal", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 199, + "y": 128, + "w": 22, + "h": 22 + } + }, + { + "filename": "memory_poison", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 221, + "y": 128, + "w": 22, + "h": 22 + } + }, + { + "filename": "memory_psychic", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 243, + "y": 127, + "w": 22, + "h": 22 + } + }, + { + "filename": "shell_bell", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 23, + "h": 20 + }, + "frame": { + "x": 265, + "y": 129, + "w": 23, + "h": 20 + } + }, + { + "filename": "dubious_disc", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 22, + "h": 19 + }, + "frame": { + "x": 288, + "y": 130, + "w": 22, + "h": 19 + } + }, + { + "filename": "big_mushroom", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 19, + "h": 19 + }, + "frame": { + "x": 147, + "y": 376, + "w": 19, + "h": 19 + } + }, + { + "filename": "fairy_feather", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 22, + "h": 20 + }, + "frame": { + "x": 339, + "y": 127, + "w": 22, + "h": 20 + } + }, + { + "filename": "malicious_armor", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 20 + }, + "frame": { + "x": 317, + "y": 128, + "w": 22, + "h": 20 + } + }, + { + "filename": "alakazite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 361, + "y": 131, + "w": 16, + "h": 16 + } + }, + { + "filename": "memory_rock", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 377, + "y": 138, + "w": 22, + "h": 22 + } + }, + { + "filename": "altarianite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 161, + "y": 149, + "w": 16, + "h": 16 + } + }, + { + "filename": "memory_steel", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 177, + "y": 150, + "w": 22, + "h": 22 + } + }, + { + "filename": "memory_water", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 199, + "y": 150, + "w": 22, + "h": 22 + } + }, + { + "filename": "mini_black_hole", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 221, + "y": 150, + "w": 22, + "h": 22 + } + }, + { + "filename": "protector", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 243, + "y": 149, + "w": 22, + "h": 22 + } + }, + { + "filename": "scroll_of_darkness", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 265, + "y": 149, + "w": 22, + "h": 22 + } + }, + { + "filename": "scroll_of_waters", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 287, + "y": 149, + "w": 22, + "h": 22 + } + }, + { + "filename": "ampharosite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 161, + "y": 165, + "w": 16, + "h": 16 + } + }, + { + "filename": "lum_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 20, + "h": 19 + }, + "frame": { + "x": 163, + "y": 181, + "w": 20, + "h": 19 + } + }, + { + "filename": "metal_coat", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 19, + "h": 22 + }, + "frame": { + "x": 166, + "y": 200, + "w": 19, + "h": 22 + } + }, + { + "filename": "shed_shell", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 166, + "y": 222, + "w": 22, + "h": 22 + } + }, + { + "filename": "starf_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 166, + "y": 244, + "w": 22, + "h": 22 + } + }, + { + "filename": "thunder_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 166, + "y": 266, + "w": 22, + "h": 22 + } + }, { "filename": "tm_bug", "rotated": false, @@ -4707,33 +4623,12 @@ "h": 22 }, "frame": { - "x": 330, - "y": 127, + "x": 166, + "y": 288, "w": 22, "h": 22 } }, - { - "filename": "sitrus_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 20, - "h": 22 - }, - "frame": { - "x": 310, - "y": 154, - "w": 20, - "h": 22 - } - }, { "filename": "tm_dark", "rotated": false, @@ -4749,8 +4644,8 @@ "h": 22 }, "frame": { - "x": 330, - "y": 149, + "x": 166, + "y": 310, "w": 22, "h": 22 } @@ -4770,8 +4665,8 @@ "h": 22 }, "frame": { - "x": 352, - "y": 107, + "x": 166, + "y": 332, "w": 22, "h": 22 } @@ -4791,12 +4686,33 @@ "h": 22 }, "frame": { - "x": 374, - "y": 109, + "x": 166, + "y": 354, "w": 22, "h": 22 } }, + { + "filename": "sweet_apple", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 21 + }, + "frame": { + "x": 166, + "y": 376, + "w": 22, + "h": 21 + } + }, { "filename": "tm_fairy", "rotated": false, @@ -4812,8 +4728,8 @@ "h": 22 }, "frame": { - "x": 352, - "y": 129, + "x": 183, + "y": 172, "w": 22, "h": 22 } @@ -4833,14 +4749,14 @@ "h": 22 }, "frame": { - "x": 374, - "y": 131, + "x": 205, + "y": 172, "w": 22, "h": 22 } }, { - "filename": "syrupy_apple", + "filename": "metronome", "rotated": false, "trimmed": true, "sourceSize": { @@ -4848,16 +4764,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 21 + "x": 7, + "y": 5, + "w": 17, + "h": 22 }, "frame": { - "x": 352, - "y": 151, - "w": 22, - "h": 21 + "x": 227, + "y": 172, + "w": 17, + "h": 22 } }, { @@ -4875,8 +4791,8 @@ "h": 22 }, "frame": { - "x": 374, - "y": 153, + "x": 244, + "y": 171, "w": 22, "h": 22 } @@ -4896,54 +4812,12 @@ "h": 22 }, "frame": { - "x": 310, - "y": 176, + "x": 266, + "y": 171, "w": 22, "h": 22 } }, - { - "filename": "gb", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 - }, - "frame": { - "x": 332, - "y": 171, - "w": 20, - "h": 20 - } - }, - { - "filename": "tart_apple", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 21 - }, - "frame": { - "x": 352, - "y": 172, - "w": 22, - "h": 21 - } - }, { "filename": "tm_ghost", "rotated": false, @@ -4959,54 +4833,12 @@ "h": 22 }, "frame": { - "x": 374, - "y": 175, + "x": 288, + "y": 171, "w": 22, "h": 22 } }, - { - "filename": "big_mushroom", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 19, - "h": 19 - }, - "frame": { - "x": 294, - "y": 204, - "w": 19, - "h": 19 - } - }, - { - "filename": "lum_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 20, - "h": 19 - }, - "frame": { - "x": 293, - "y": 223, - "w": 20, - "h": 19 - } - }, { "filename": "tm_grass", "rotated": false, @@ -5022,8 +4854,8 @@ "h": 22 }, "frame": { - "x": 313, - "y": 198, + "x": 185, + "y": 194, "w": 22, "h": 22 } @@ -5043,33 +4875,12 @@ "h": 22 }, "frame": { - "x": 313, - "y": 220, + "x": 207, + "y": 194, "w": 22, "h": 22 } }, - { - "filename": "hyper_potion", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 17, - "h": 23 - }, - "frame": { - "x": 335, - "y": 191, - "w": 17, - "h": 23 - } - }, { "filename": "tm_ice", "rotated": false, @@ -5085,8 +4896,8 @@ "h": 22 }, "frame": { - "x": 352, - "y": 193, + "x": 188, + "y": 216, "w": 22, "h": 22 } @@ -5106,33 +4917,12 @@ "h": 22 }, "frame": { - "x": 374, - "y": 197, + "x": 188, + "y": 238, "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": 335, - "y": 214, - "w": 17, - "h": 23 - } - }, { "filename": "tm_psychic", "rotated": false, @@ -5148,8 +4938,8 @@ "h": 22 }, "frame": { - "x": 352, - "y": 215, + "x": 188, + "y": 260, "w": 22, "h": 22 } @@ -5169,54 +4959,12 @@ "h": 22 }, "frame": { - "x": 374, - "y": 219, + "x": 188, + "y": 282, "w": 22, "h": 22 } }, - { - "filename": "tera_orb", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 20 - }, - "frame": { - "x": 335, - "y": 237, - "w": 22, - "h": 20 - } - }, - { - "filename": "lucky_egg", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 17, - "h": 20 - }, - "frame": { - "x": 357, - "y": 237, - "w": 17, - "h": 20 - } - }, { "filename": "tm_steel", "rotated": false, @@ -5232,33 +4980,12 @@ "h": 22 }, "frame": { - "x": 374, - "y": 241, + "x": 188, + "y": 304, "w": 22, "h": 22 } }, - { - "filename": "candy", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 11, - "w": 18, - "h": 18 - }, - "frame": { - "x": 165, - "y": 228, - "w": 18, - "h": 18 - } - }, { "filename": "tm_water", "rotated": false, @@ -5274,8 +5001,8 @@ "h": 22 }, "frame": { - "x": 183, - "y": 231, + "x": 188, + "y": 326, "w": 22, "h": 22 } @@ -5295,33 +5022,12 @@ "h": 22 }, "frame": { - "x": 205, - "y": 233, + "x": 188, + "y": 348, "w": 22, "h": 22 } }, - { - "filename": "upgrade", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 22, - "h": 19 - }, - "frame": { - "x": 227, - "y": 236, - "w": 22, - "h": 19 - } - }, { "filename": "x_accuracy", "rotated": false, @@ -5337,12 +5043,33 @@ "h": 22 }, "frame": { - "x": 249, - "y": 236, + "x": 188, + "y": 370, "w": 22, "h": 22 } }, + { + "filename": "sitrus_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 20, + "h": 22 + }, + "frame": { + "x": 210, + "y": 216, + "w": 20, + "h": 22 + } + }, { "filename": "x_attack", "rotated": false, @@ -5358,8 +5085,8 @@ "h": 22 }, "frame": { - "x": 271, - "y": 241, + "x": 210, + "y": 238, "w": 22, "h": 22 } @@ -5379,33 +5106,12 @@ "h": 22 }, "frame": { - "x": 293, - "y": 242, + "x": 210, + "y": 260, "w": 22, "h": 22 } }, - { - "filename": "magnet", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 - }, - "frame": { - "x": 315, - "y": 242, - "w": 20, - "h": 20 - } - }, { "filename": "x_sp_atk", "rotated": false, @@ -5421,8 +5127,8 @@ "h": 22 }, "frame": { - "x": 149, - "y": 246, + "x": 210, + "y": 282, "w": 22, "h": 22 } @@ -5442,8 +5148,8 @@ "h": 22 }, "frame": { - "x": 151, - "y": 268, + "x": 210, + "y": 304, "w": 22, "h": 22 } @@ -5463,12 +5169,96 @@ "h": 22 }, "frame": { - "x": 151, - "y": 290, + "x": 210, + "y": 326, "w": 22, "h": 22 } }, + { + "filename": "syrupy_apple", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 21 + }, + "frame": { + "x": 210, + "y": 348, + "w": 22, + "h": 21 + } + }, + { + "filename": "tart_apple", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 21 + }, + "frame": { + "x": 210, + "y": 369, + "w": 22, + "h": 21 + } + }, + { + "filename": "soothe_bell", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 17, + "h": 22 + }, + "frame": { + "x": 229, + "y": 194, + "w": 17, + "h": 22 + } + }, + { + "filename": "dusk_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 21, + "h": 21 + }, + "frame": { + "x": 246, + "y": 193, + "w": 21, + "h": 21 + } + }, { "filename": "poison_barb", "rotated": false, @@ -5484,8 +5274,8 @@ "h": 21 }, "frame": { - "x": 152, - "y": 312, + "x": 267, + "y": 193, "w": 21, "h": 21 } @@ -5505,12 +5295,117 @@ "h": 21 }, "frame": { - "x": 152, - "y": 333, + "x": 288, + "y": 193, "w": 21, "h": 21 } }, + { + "filename": "dawn_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 20, + "h": 21 + }, + "frame": { + "x": 230, + "y": 216, + "w": 20, + "h": 21 + } + }, + { + "filename": "tera_orb", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 20 + }, + "frame": { + "x": 250, + "y": 214, + "w": 22, + "h": 20 + } + }, + { + "filename": "upgrade", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 22, + "h": 19 + }, + "frame": { + "x": 272, + "y": 214, + "w": 22, + "h": 19 + } + }, + { + "filename": "quick_claw", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 19, + "h": 21 + }, + "frame": { + "x": 232, + "y": 237, + "w": 19, + "h": 21 + } + }, + { + "filename": "spell_tag", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 19, + "h": 21 + }, + "frame": { + "x": 232, + "y": 258, + "w": 19, + "h": 21 + } + }, { "filename": "zoom_lens", "rotated": false, @@ -5526,35 +5421,14 @@ "h": 21 }, "frame": { - "x": 152, - "y": 354, + "x": 232, + "y": 279, "w": 21, "h": 21 } }, { - "filename": "mystery_egg", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 18 - }, - "frame": { - "x": 149, - "y": 228, - "w": 16, - "h": 18 - } - }, - { - "filename": "metal_alloy", + "filename": "gb", "rotated": false, "trimmed": true, "sourceSize": { @@ -5563,19 +5437,19 @@ }, "spriteSourceSize": { "x": 6, - "y": 7, - "w": 21, - "h": 19 + "y": 6, + "w": 20, + "h": 20 }, "frame": { - "x": 335, - "y": 257, - "w": 21, - "h": 19 + "x": 232, + "y": 300, + "w": 20, + "h": 20 } }, { - "filename": "oval_stone", + "filename": "magnet", "rotated": false, "trimmed": true, "sourceSize": { @@ -5583,16 +5457,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 19 + "x": 6, + "y": 6, + "w": 20, + "h": 20 }, "frame": { - "x": 356, - "y": 257, - "w": 18, - "h": 19 + "x": 232, + "y": 320, + "w": 20, + "h": 20 } }, { @@ -5610,75 +5484,12 @@ "h": 20 }, "frame": { - "x": 315, - "y": 262, + "x": 232, + "y": 340, "w": 20, "h": 20 } }, - { - "filename": "sharp_meteorite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 21, - "h": 18 - }, - "frame": { - "x": 374, - "y": 263, - "w": 21, - "h": 18 - } - }, - { - "filename": "unremarkable_teacup", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 21, - "h": 18 - }, - "frame": { - "x": 335, - "y": 276, - "w": 21, - "h": 18 - } - }, - { - "filename": "dark_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 18 - }, - "frame": { - "x": 356, - "y": 276, - "w": 18, - "h": 18 - } - }, { "filename": "pb", "rotated": false, @@ -5694,161 +5505,14 @@ "h": 20 }, "frame": { - "x": 374, - "y": 281, + "x": 232, + "y": 360, "w": 20, "h": 20 } }, { - "filename": "full_heal", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 9, - "y": 4, - "w": 15, - "h": 23 - }, - "frame": { - "x": 173, - "y": 282, - "w": 15, - "h": 23 - } - }, - { - "filename": "super_potion", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 17, - "h": 23 - }, - "frame": { - "x": 173, - "y": 305, - "w": 17, - "h": 23 - } - }, - { - "filename": "metronome", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 17, - "h": 22 - }, - "frame": { - "x": 173, - "y": 328, - "w": 17, - "h": 22 - } - }, - { - "filename": "soothe_bell", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 17, - "h": 22 - }, - "frame": { - "x": 173, - "y": 350, - "w": 17, - "h": 22 - } - }, - { - "filename": "light_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 18 - }, - "frame": { - "x": 173, - "y": 264, - "w": 18, - "h": 18 - } - }, - { - "filename": "relic_gold", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 15, - "h": 11 - }, - "frame": { - "x": 171, - "y": 253, - "w": 15, - "h": 11 - } - }, - { - "filename": "leftovers", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 15, - "h": 22 - }, - "frame": { - "x": 188, - "y": 282, - "w": 15, - "h": 22 - } - }, - { - "filename": "hard_stone", + "filename": "metal_alloy", "rotated": false, "trimmed": true, "sourceSize": { @@ -5857,15 +5521,15 @@ }, "spriteSourceSize": { "x": 6, - "y": 6, - "w": 19, - "h": 20 + "y": 7, + "w": 21, + "h": 19 }, "frame": { - "x": 190, - "y": 304, - "w": 19, - "h": 20 + "x": 232, + "y": 380, + "w": 21, + "h": 19 } }, { @@ -5883,8 +5547,8 @@ "h": 20 }, "frame": { - "x": 190, - "y": 324, + "x": 251, + "y": 234, "w": 20, "h": 20 } @@ -5904,14 +5568,14 @@ "h": 20 }, "frame": { - "x": 190, - "y": 344, + "x": 251, + "y": 254, "w": 20, "h": 20 } }, { - "filename": "miracle_seed", + "filename": "candy_jar", "rotated": false, "trimmed": true, "sourceSize": { @@ -5920,15 +5584,57 @@ }, "spriteSourceSize": { "x": 6, - "y": 7, + "y": 6, "w": 19, - "h": 19 + "h": 20 }, "frame": { - "x": 191, - "y": 263, + "x": 294, + "y": 214, "w": 19, - "h": 19 + "h": 20 + } + }, + { + "filename": "hard_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 19, + "h": 20 + }, + "frame": { + "x": 253, + "y": 274, + "w": 19, + "h": 20 + } + }, + { + "filename": "everstone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 17 + }, + "frame": { + "x": 253, + "y": 294, + "w": 20, + "h": 17 } }, { @@ -5946,54 +5652,12 @@ "h": 20 }, "frame": { - "x": 210, - "y": 255, + "x": 252, + "y": 311, "w": 20, "h": 20 } }, - { - "filename": "razor_fang", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 18, - "h": 20 - }, - "frame": { - "x": 230, - "y": 255, - "w": 18, - "h": 20 - } - }, - { - "filename": "razor_claw", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 20, - "h": 19 - }, - "frame": { - "x": 248, - "y": 258, - "w": 20, - "h": 19 - } - }, { "filename": "strange_ball", "rotated": false, @@ -6009,8 +5673,8 @@ "h": 20 }, "frame": { - "x": 268, - "y": 263, + "x": 252, + "y": 331, "w": 20, "h": 20 } @@ -6030,12 +5694,138 @@ "h": 20 }, "frame": { - "x": 288, - "y": 264, + "x": 252, + "y": 351, "w": 20, "h": 20 } }, + { + "filename": "miracle_seed", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 19, + "h": 19 + }, + "frame": { + "x": 253, + "y": 371, + "w": 19, + "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": 339, + "y": 147, + "w": 21, + "h": 18 + } + }, + { + "filename": "golden_egg", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 17, + "h": 20 + }, + "frame": { + "x": 360, + "y": 147, + "w": 17, + "h": 20 + } + }, + { + "filename": "sharp_meteorite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 21, + "h": 18 + }, + "frame": { + "x": 377, + "y": 160, + "w": 21, + "h": 18 + } + }, + { + "filename": "unremarkable_teacup", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 21, + "h": 18 + }, + "frame": { + "x": 272, + "y": 233, + "w": 21, + "h": 18 + } + }, + { + "filename": "razor_claw", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 20, + "h": 19 + }, + "frame": { + "x": 271, + "y": 251, + "w": 20, + "h": 19 + } + }, { "filename": "wl_ability_urge", "rotated": false, @@ -6051,8 +5841,8 @@ "h": 18 }, "frame": { - "x": 190, - "y": 364, + "x": 293, + "y": 234, "w": 20, "h": 18 } @@ -6072,14 +5862,14 @@ "h": 18 }, "frame": { - "x": 210, - "y": 275, + "x": 291, + "y": 252, "w": 20, "h": 18 } }, { - "filename": "charizardite_x", + "filename": "razor_fang", "rotated": false, "trimmed": true, "sourceSize": { @@ -6087,16 +5877,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 + "x": 7, + "y": 6, + "w": 18, + "h": 20 }, "frame": { - "x": 230, - "y": 275, - "w": 16, - "h": 16 + "x": 272, + "y": 270, + "w": 18, + "h": 20 } }, { @@ -6114,12 +5904,33 @@ "h": 18 }, "frame": { - "x": 246, - "y": 277, + "x": 290, + "y": 270, "w": 20, "h": 18 } }, + { + "filename": "lucky_egg", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 17, + "h": 20 + }, + "frame": { + "x": 273, + "y": 290, + "w": 17, + "h": 20 + } + }, { "filename": "wl_burn_heal", "rotated": false, @@ -6135,8 +5946,8 @@ "h": 18 }, "frame": { - "x": 266, - "y": 283, + "x": 290, + "y": 288, "w": 20, "h": 18 } @@ -6156,12 +5967,54 @@ "h": 18 }, "frame": { - "x": 286, - "y": 284, + "x": 290, + "y": 306, "w": 20, "h": 18 } }, + { + "filename": "oval_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 18, + "h": 19 + }, + "frame": { + "x": 272, + "y": 311, + "w": 18, + "h": 19 + } + }, + { + "filename": "candy", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 11, + "w": 18, + "h": 18 + }, + "frame": { + "x": 272, + "y": 330, + "w": 18, + "h": 18 + } + }, { "filename": "wl_custom_thief", "rotated": false, @@ -6177,12 +6030,33 @@ "h": 18 }, "frame": { - "x": 209, - "y": 293, + "x": 290, + "y": 324, "w": 20, "h": 18 } }, + { + "filename": "dark_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 18, + "h": 18 + }, + "frame": { + "x": 272, + "y": 348, + "w": 18, + "h": 18 + } + }, { "filename": "wl_elixir", "rotated": false, @@ -6198,12 +6072,33 @@ "h": 18 }, "frame": { - "x": 210, - "y": 311, + "x": 290, + "y": 342, "w": 20, "h": 18 } }, + { + "filename": "light_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 18, + "h": 18 + }, + "frame": { + "x": 272, + "y": 366, + "w": 18, + "h": 18 + } + }, { "filename": "wl_ether", "rotated": false, @@ -6219,8 +6114,8 @@ "h": 18 }, "frame": { - "x": 210, - "y": 329, + "x": 290, + "y": 360, "w": 20, "h": 18 } @@ -6240,8 +6135,8 @@ "h": 18 }, "frame": { - "x": 210, - "y": 347, + "x": 290, + "y": 378, "w": 20, "h": 18 } @@ -6261,33 +6156,12 @@ "h": 18 }, "frame": { - "x": 210, - "y": 365, + "x": 311, + "y": 252, "w": 20, "h": 18 } }, - { - "filename": "candy_overlay", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 12, - "w": 16, - "h": 15 - }, - "frame": { - "x": 230, - "y": 291, - "w": 16, - "h": 15 - } - }, { "filename": "wl_guard_spec", "rotated": false, @@ -6303,33 +6177,12 @@ "h": 18 }, "frame": { - "x": 246, - "y": 295, + "x": 310, + "y": 270, "w": 20, "h": 18 } }, - { - "filename": "charizardite_y", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 230, - "y": 306, - "w": 16, - "h": 16 - } - }, { "filename": "wl_hyper_potion", "rotated": false, @@ -6345,8 +6198,8 @@ "h": 18 }, "frame": { - "x": 230, - "y": 322, + "x": 310, + "y": 288, "w": 20, "h": 18 } @@ -6366,8 +6219,8 @@ "h": 18 }, "frame": { - "x": 230, - "y": 340, + "x": 310, + "y": 306, "w": 20, "h": 18 } @@ -6387,8 +6240,8 @@ "h": 18 }, "frame": { - "x": 230, - "y": 358, + "x": 310, + "y": 324, "w": 20, "h": 18 } @@ -6408,8 +6261,8 @@ "h": 18 }, "frame": { - "x": 266, - "y": 301, + "x": 310, + "y": 342, "w": 20, "h": 18 } @@ -6429,33 +6282,12 @@ "h": 18 }, "frame": { - "x": 286, - "y": 302, + "x": 310, + "y": 360, "w": 20, "h": 18 } }, - { - "filename": "diancite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 250, - "y": 313, - "w": 16, - "h": 16 - } - }, { "filename": "wl_max_ether", "rotated": false, @@ -6471,8 +6303,8 @@ "h": 18 }, "frame": { - "x": 250, - "y": 329, + "x": 310, + "y": 378, "w": 20, "h": 18 } @@ -6492,8 +6324,8 @@ "h": 18 }, "frame": { - "x": 250, - "y": 347, + "x": 309, + "y": 193, "w": 20, "h": 18 } @@ -6513,8 +6345,8 @@ "h": 18 }, "frame": { - "x": 250, - "y": 365, + "x": 313, + "y": 211, "w": 20, "h": 18 } @@ -6534,33 +6366,12 @@ "h": 18 }, "frame": { - "x": 230, - "y": 376, + "x": 313, + "y": 229, "w": 20, "h": 18 } }, - { - "filename": "galladite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 270, - "y": 319, - "w": 16, - "h": 16 - } - }, { "filename": "wl_potion", "rotated": false, @@ -6576,33 +6387,12 @@ "h": 18 }, "frame": { - "x": 286, - "y": 320, + "x": 309, + "y": 149, "w": 20, "h": 18 } }, - { - "filename": "garchompite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 270, - "y": 335, - "w": 16, - "h": 16 - } - }, { "filename": "wl_reset_urge", "rotated": false, @@ -6618,8 +6408,8 @@ "h": 18 }, "frame": { - "x": 270, - "y": 351, + "x": 310, + "y": 167, "w": 20, "h": 18 } @@ -6639,8 +6429,8 @@ "h": 18 }, "frame": { - "x": 270, - "y": 369, + "x": 330, + "y": 165, "w": 20, "h": 18 } @@ -6660,12 +6450,264 @@ "h": 18 }, "frame": { - "x": 165, - "y": 375, + "x": 350, + "y": 167, "w": 20, "h": 18 } }, + { + "filename": "relic_band", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 9, + "w": 17, + "h": 16 + }, + "frame": { + "x": 333, + "y": 183, + "w": 17, + "h": 16 + } + }, + { + "filename": "audinite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 350, + "y": 185, + "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": 333, + "y": 199, + "w": 16, + "h": 16 + } + }, + { + "filename": "beedrillite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 333, + "y": 215, + "w": 16, + "h": 16 + } + }, + { + "filename": "blastoisinite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 333, + "y": 231, + "w": 16, + "h": 16 + } + }, + { + "filename": "blazikenite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 349, + "y": 201, + "w": 16, + "h": 16 + } + }, + { + "filename": "cameruptite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 349, + "y": 217, + "w": 16, + "h": 16 + } + }, + { + "filename": "charizardite_x", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 349, + "y": 233, + "w": 16, + "h": 16 + } + }, + { + "filename": "charizardite_y", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 331, + "y": 247, + "w": 16, + "h": 16 + } + }, + { + "filename": "diancite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 347, + "y": 249, + "w": 16, + "h": 16 + } + }, + { + "filename": "galladite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 331, + "y": 263, + "w": 16, + "h": 16 + } + }, + { + "filename": "garchompite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 330, + "y": 279, + "w": 16, + "h": 16 + } + }, { "filename": "gardevoirite", "rotated": false, @@ -6681,8 +6723,8 @@ "h": 16 }, "frame": { - "x": 290, - "y": 338, + "x": 330, + "y": 295, "w": 16, "h": 16 } @@ -6702,8 +6744,8 @@ "h": 16 }, "frame": { - "x": 290, - "y": 354, + "x": 330, + "y": 311, "w": 16, "h": 16 } @@ -6723,8 +6765,8 @@ "h": 16 }, "frame": { - "x": 290, - "y": 370, + "x": 330, + "y": 327, "w": 16, "h": 16 } @@ -6744,8 +6786,8 @@ "h": 16 }, "frame": { - "x": 306, - "y": 284, + "x": 330, + "y": 343, "w": 16, "h": 16 } @@ -6765,8 +6807,8 @@ "h": 16 }, "frame": { - "x": 306, - "y": 300, + "x": 330, + "y": 359, "w": 16, "h": 16 } @@ -6786,8 +6828,8 @@ "h": 16 }, "frame": { - "x": 306, - "y": 316, + "x": 330, + "y": 375, "w": 16, "h": 16 } @@ -6807,8 +6849,8 @@ "h": 16 }, "frame": { - "x": 306, - "y": 332, + "x": 347, + "y": 265, "w": 16, "h": 16 } @@ -6828,8 +6870,8 @@ "h": 16 }, "frame": { - "x": 306, - "y": 348, + "x": 346, + "y": 281, "w": 16, "h": 16 } @@ -6849,8 +6891,8 @@ "h": 16 }, "frame": { - "x": 306, - "y": 364, + "x": 346, + "y": 297, "w": 16, "h": 16 } @@ -6870,8 +6912,8 @@ "h": 16 }, "frame": { - "x": 306, - "y": 380, + "x": 346, + "y": 313, "w": 16, "h": 16 } @@ -6891,8 +6933,8 @@ "h": 16 }, "frame": { - "x": 322, - "y": 294, + "x": 346, + "y": 329, "w": 16, "h": 16 } @@ -6912,8 +6954,8 @@ "h": 16 }, "frame": { - "x": 338, - "y": 294, + "x": 346, + "y": 345, "w": 16, "h": 16 } @@ -6933,8 +6975,8 @@ "h": 16 }, "frame": { - "x": 322, - "y": 310, + "x": 346, + "y": 361, "w": 16, "h": 16 } @@ -6954,8 +6996,8 @@ "h": 16 }, "frame": { - "x": 354, - "y": 294, + "x": 346, + "y": 377, "w": 16, "h": 16 } @@ -6975,8 +7017,8 @@ "h": 16 }, "frame": { - "x": 322, - "y": 326, + "x": 366, + "y": 185, "w": 16, "h": 16 } @@ -6996,8 +7038,8 @@ "h": 16 }, "frame": { - "x": 338, - "y": 310, + "x": 365, + "y": 201, "w": 16, "h": 16 } @@ -7017,8 +7059,8 @@ "h": 16 }, "frame": { - "x": 322, - "y": 342, + "x": 365, + "y": 217, "w": 16, "h": 16 } @@ -7038,8 +7080,8 @@ "h": 16 }, "frame": { - "x": 338, - "y": 326, + "x": 365, + "y": 233, "w": 16, "h": 16 } @@ -7059,8 +7101,8 @@ "h": 16 }, "frame": { - "x": 354, - "y": 310, + "x": 363, + "y": 249, "w": 16, "h": 16 } @@ -7080,8 +7122,8 @@ "h": 16 }, "frame": { - "x": 322, - "y": 358, + "x": 363, + "y": 265, "w": 16, "h": 16 } @@ -7101,8 +7143,8 @@ "h": 16 }, "frame": { - "x": 338, - "y": 342, + "x": 362, + "y": 281, "w": 16, "h": 16 } @@ -7122,8 +7164,8 @@ "h": 16 }, "frame": { - "x": 354, - "y": 326, + "x": 362, + "y": 297, "w": 16, "h": 16 } @@ -7143,8 +7185,8 @@ "h": 16 }, "frame": { - "x": 322, - "y": 374, + "x": 362, + "y": 313, "w": 16, "h": 16 } @@ -7164,8 +7206,8 @@ "h": 16 }, "frame": { - "x": 338, - "y": 358, + "x": 362, + "y": 329, "w": 16, "h": 16 } @@ -7185,8 +7227,8 @@ "h": 16 }, "frame": { - "x": 354, - "y": 342, + "x": 362, + "y": 345, "w": 16, "h": 16 } @@ -7206,8 +7248,8 @@ "h": 16 }, "frame": { - "x": 338, - "y": 374, + "x": 362, + "y": 361, "w": 16, "h": 16 } @@ -7227,8 +7269,8 @@ "h": 16 }, "frame": { - "x": 354, - "y": 358, + "x": 362, + "y": 377, "w": 16, "h": 16 } @@ -7248,8 +7290,8 @@ "h": 16 }, "frame": { - "x": 354, - "y": 374, + "x": 382, + "y": 178, "w": 16, "h": 16 } @@ -7269,8 +7311,8 @@ "h": 16 }, "frame": { - "x": 370, - "y": 301, + "x": 382, + "y": 194, "w": 16, "h": 16 } @@ -7290,8 +7332,8 @@ "h": 16 }, "frame": { - "x": 370, - "y": 317, + "x": 381, + "y": 210, "w": 16, "h": 16 } @@ -7311,8 +7353,8 @@ "h": 16 }, "frame": { - "x": 370, - "y": 333, + "x": 381, + "y": 226, "w": 16, "h": 16 } @@ -7332,8 +7374,8 @@ "h": 16 }, "frame": { - "x": 370, - "y": 349, + "x": 381, + "y": 242, "w": 16, "h": 16 } @@ -7353,32 +7395,11 @@ "h": 16 }, "frame": { - "x": 370, - "y": 365, + "x": 379, + "y": 258, "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": 370, - "y": 381, - "w": 15, - "h": 15 - } } ] } @@ -7386,6 +7407,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:e6d832697add1029764f6145e5fa98b7:47250d3d95167f73038d290f7a73b96e:110e074689c9edd2c54833ce2e4d9270$" + "smartupdate": "$TexturePacker:SmartUpdate:5676fc2ef4e2b6e18c96ca3c80e7521d:a6286201546cef975121cad6b35c7005:110e074689c9edd2c54833ce2e4d9270$" } } diff --git a/public/images/items.png b/public/images/items.png index 7ddd284fac7..9af295e16ad 100644 Binary files a/public/images/items.png and b/public/images/items.png differ diff --git a/public/images/items/quick_claw.png b/public/images/items/quick_claw.png new file mode 100644 index 00000000000..e6317898e2a Binary files /dev/null and b/public/images/items/quick_claw.png differ diff --git a/public/images/trainer/student_f.json b/public/images/trainer/school_kid_f.json similarity index 99% rename from public/images/trainer/student_f.json rename to public/images/trainer/school_kid_f.json index 7f739c78d7f..5d38900ba35 100644 --- a/public/images/trainer/student_f.json +++ b/public/images/trainer/school_kid_f.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "student_f.png", + "image": "school_kid_f.png", "format": "RGBA8888", "size": { "w": 192, diff --git a/public/images/trainer/student_f.png b/public/images/trainer/school_kid_f.png similarity index 100% rename from public/images/trainer/student_f.png rename to public/images/trainer/school_kid_f.png diff --git a/public/images/trainer/student_m.json b/public/images/trainer/school_kid_m.json similarity index 99% rename from public/images/trainer/student_m.json rename to public/images/trainer/school_kid_m.json index f87341e1bf8..daee7de2a03 100644 --- a/public/images/trainer/student_m.json +++ b/public/images/trainer/school_kid_m.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "student_m.png", + "image": "school_kid_m.png", "format": "RGBA8888", "size": { "w": 178, diff --git a/public/images/trainer/student_m.png b/public/images/trainer/school_kid_m.png similarity index 100% rename from public/images/trainer/student_m.png rename to public/images/trainer/school_kid_m.png diff --git a/src/account.ts b/src/account.ts index afb9aca3593..f5d4e2858b4 100644 --- a/src/account.ts +++ b/src/account.ts @@ -7,18 +7,29 @@ export interface UserInfo { } export let loggedInUser: UserInfo = null; +export const clientSessionId = Utils.randomString(32); export function updateUserInfo(): Promise<[boolean, integer]> { return new Promise<[boolean, integer]>(resolve => { if (bypassLogin) { + loggedInUser = { username: 'Guest', lastSessionSlot: -1 }; let lastSessionSlot = -1; - for (let s = 0; s < 2; s++) { - if (localStorage.getItem(`sessionData${s ? s : ''}`)) { + for (let s = 0; s < 5; s++) { + if (localStorage.getItem(`sessionData${s ? s : ''}_${loggedInUser.username}`)) { lastSessionSlot = s; break; } } - loggedInUser = { username: 'Guest', lastSessionSlot: lastSessionSlot }; + loggedInUser.lastSessionSlot = lastSessionSlot; + // Migrate old data from before the username was appended + [ 'data', 'sessionData', 'sessionData1', 'sessionData2', 'sessionData3', 'sessionData4' ].map(d => { + if (localStorage.hasOwnProperty(d)) { + if (localStorage.hasOwnProperty(`${d}_${loggedInUser.username}`)) + localStorage.setItem(`${d}_${loggedInUser.username}_bak`, localStorage.getItem(`${d}_${loggedInUser.username}`)); + localStorage.setItem(`${d}_${loggedInUser.username}`, localStorage.getItem(d)); + localStorage.removeItem(d); + } + }); return resolve([ true, 200 ]); } Utils.apiFetch('account/info', true).then(response => { diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 111e5439b12..0f75447a500 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -88,6 +88,7 @@ export default class BattleScene extends SceneBase { public uiInputs: UiInputs; public sessionPlayTime: integer = null; + public lastSavePlayTime: integer = null; public masterVolume: number = 0.5; public bgmVolume: number = 1; public seVolume: number = 1; @@ -452,6 +453,8 @@ export default class BattleScene extends SceneBase { initSession(): void { if (this.sessionPlayTime === null) this.sessionPlayTime = 0; + if (this.lastSavePlayTime === null) + this.lastSavePlayTime = 0; if (this.playTimeTimer) this.playTimeTimer.destroy(); @@ -464,6 +467,8 @@ export default class BattleScene extends SceneBase { this.gameData.gameStats.playTime++; if (this.sessionPlayTime !== null) this.sessionPlayTime++; + if (this.lastSavePlayTime !== null) + this.lastSavePlayTime++; } }); @@ -1007,6 +1012,8 @@ export default class BattleScene extends SceneBase { case Species.FLORGES: case Species.FURFROU: case Species.ORICORIO: + case Species.MAGEARNA: + case Species.ZARUDE: case Species.SQUAWKABILLY: case Species.TATSUGIRI: case Species.PALDEA_TAUROS: diff --git a/src/data/ability.ts b/src/data/ability.ts index 0ff03ed6776..a257525efd0 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -3456,7 +3456,7 @@ export function initAbilities() { .attr(MovePowerBoostAbAttr, (user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.POKEMON, 2), new Ability(Abilities.WATER_BUBBLE, 7) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5) - .attr(MoveTypePowerBoostAbAttr, Type.WATER, 1) + .attr(MoveTypePowerBoostAbAttr, Type.WATER, 2) .attr(StatusEffectImmunityAbAttr, StatusEffect.BURN) .ignorable(), new Ability(Abilities.STEELWORKER, 7) diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 257f56d46ed..6ab249864cd 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -14,7 +14,8 @@ import { BattlerTagType } from "./enums/battler-tag-type"; import { TerrainType } from "./terrain"; import { WeatherType } from "./weather"; import { BattleStat } from "./battle-stat"; -import { allAbilities } from "./ability" +import { allAbilities } from "./ability"; +import { Species } from "./enums/species"; export enum BattlerTagLapseType { FAINT, @@ -117,7 +118,11 @@ export class TrappedTag extends BattlerTag { } canAdd(pokemon: Pokemon): boolean { - return !pokemon.isOfType(Type.GHOST) && !pokemon.getTag(BattlerTagType.TRAPPED); + const isGhost = pokemon.isOfType(Type.GHOST); + const isTrapped = pokemon.getTag(BattlerTagType.TRAPPED); + const isAllowedGhostType = pokemon.species.speciesId === Species.PHANTUMP || pokemon.species.speciesId === Species.TREVENANT; + + return !isTrapped && (!isGhost || isAllowedGhostType); } onAdd(pokemon: Pokemon): void { @@ -544,6 +549,33 @@ export class AquaRingTag extends BattlerTag { } } +/** Tag used to allow moves that interact with {@link Moves.MINIMIZE} to function */ +export class MinimizeTag extends BattlerTag { + constructor() { + super(BattlerTagType.MINIMIZED, BattlerTagLapseType.TURN_END, 1, Moves.MINIMIZE, undefined); + } + + canAdd(pokemon: Pokemon): boolean { + return !pokemon.isMax(); + } + + onAdd(pokemon: Pokemon): void { + super.onAdd(pokemon); + } + + lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { + //If a pokemon dynamaxes they lose minimized status + if(pokemon.isMax()){ + return false + } + return lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType); + } + + onRemove(pokemon: Pokemon): void { + super.onRemove(pokemon); + } +} + export class DrowsyTag extends BattlerTag { constructor() { super(BattlerTagType.DROWSY, BattlerTagLapseType.TURN_END, 2, Moves.YAWN); @@ -1358,6 +1390,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true); case BattlerTagType.MAGNET_RISEN: return new MagnetRisenTag(tagType, sourceMove); + case BattlerTagType.MINIMIZED: + return new MinimizeTag(); case BattlerTagType.NONE: default: return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); diff --git a/src/data/berry.ts b/src/data/berry.ts index 96b50caa932..1521f3488ef 100644 --- a/src/data/berry.ts +++ b/src/data/berry.ts @@ -7,6 +7,7 @@ import { BattlerTagType } from "./enums/battler-tag-type"; import { getStatusEffectHealText } from "./status-effect"; import * as Utils from "../utils"; import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./ability"; +import i18next from '../plugins/i18n'; export enum BerryType { SITRUS, @@ -22,32 +23,12 @@ export enum BerryType { LEPPA } -export function getBerryName(berryType: BerryType) { - return `${Utils.toReadableString(BerryType[berryType])} Berry`; +export function getBerryName(berryType: BerryType): string { + return i18next.t(`berry:${BerryType[berryType]}.name`); } -export function getBerryEffectDescription(berryType: BerryType) { - switch (berryType) { - case BerryType.SITRUS: - return 'Restores 25% HP if HP is below 50%'; - case BerryType.LUM: - return 'Cures any non-volatile status condition and confusion'; - case BerryType.ENIGMA: - return 'Restores 25% HP if hit by a super effective move'; - case BerryType.LIECHI: - case BerryType.GANLON: - case BerryType.PETAYA: - case BerryType.APICOT: - case BerryType.SALAC: - const stat = (berryType - BerryType.LIECHI) as BattleStat; - return `Raises ${getBattleStatName(stat)} if HP is below 25%`; - case BerryType.LANSAT: - return 'Raises critical hit ratio if HP is below 25%'; - case BerryType.STARF: - return 'Sharply raises a random stat if HP is below 25%'; - case BerryType.LEPPA: - return 'Restores 10 PP to a move if its PP reaches 0'; - } +export function getBerryEffectDescription(berryType: BerryType): string { + return i18next.t(`berry:${BerryType[berryType]}.effect`); } export type BerryPredicate = (pokemon: Pokemon) => boolean; diff --git a/src/data/biomes.ts b/src/data/biomes.ts index 61da0410dcf..c4fb750542d 100644 --- a/src/data/biomes.ts +++ b/src/data/biomes.ts @@ -48,7 +48,7 @@ export const biomeLinks: BiomeLinks = { [Biome.SEABED]: [ Biome.CAVE, [ Biome.VOLCANO, 4 ] ], [Biome.MOUNTAIN]: [ Biome.VOLCANO, [ Biome.WASTELAND, 3 ] ], [Biome.BADLANDS]: [ Biome.DESERT, Biome.MOUNTAIN ], - [Biome.CAVE]: [ Biome.BADLANDS, Biome.BEACH ], + [Biome.CAVE]: [ Biome.BADLANDS, Biome.LAKE ], [Biome.DESERT]: Biome.RUINS, [Biome.ICE_CAVE]: Biome.SNOWY_FOREST, [Biome.MEADOW]: [ Biome.PLAINS, [ Biome.FAIRY_CAVE, 2 ] ], @@ -1647,7 +1647,7 @@ export const biomeTrainerPools: BiomeTrainerPools = { [BiomePoolTier.BOSS_ULTRA_RARE]: [] }, [Biome.GRASS]: { - [BiomePoolTier.COMMON]: [ TrainerType.BREEDER, TrainerType.STUDENT ], + [BiomePoolTier.COMMON]: [ TrainerType.BREEDER, TrainerType.SCHOOL_KID ], [BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER ], [BiomePoolTier.RARE]: [ TrainerType.BLACK_BELT ], [BiomePoolTier.SUPER_RARE]: [], @@ -7270,7 +7270,7 @@ export const biomeTrainerPools: BiomeTrainerPools = { ] ], [ TrainerType.STRIKER, [] ], - [ TrainerType.STUDENT, [ + [ TrainerType.SCHOOL_KID, [ [ Biome.GRASS, BiomePoolTier.COMMON ] ] ], @@ -7871,4 +7871,4 @@ export const biomeTrainerPools: BiomeTrainerPools = { } console.log(JSON.stringify(pokemonBiomes, null, ' '));*/ -} \ No newline at end of file +} diff --git a/src/data/dialogue.ts b/src/data/dialogue.ts index 830b5f43775..e54196d9e25 100644 --- a/src/data/dialogue.ts +++ b/src/data/dialogue.ts @@ -288,7 +288,7 @@ export const trainerTypeDialogue = { ] } ], - [TrainerType.STUDENT]: [ + [TrainerType.SCHOOL_KID]: [ { encounter: [ `…Heehee. I'm confident in my calculations and analysis.`, @@ -2290,6 +2290,25 @@ export const battleSpecDialogue = { } }; +export const miscDialogue = { + ending: [ + `@c{smile}Oh? You won?@d{96} @c{smile_eclosed}I guess I should've known.\nBut, you're back now. + $@c{smile}It's over.@d{64} You ended the loop. + $@c{serious_smile_fists}You fulfilled your dream too, didn't you?\nYou didn't lose even once. + $@c{neutral}I'm the only one who'll remember what you did.@d{96}\nI guess that's okay, isn't it? + $@c{serious_smile_fists}Your legend will always live on in our hearts. + $@c{smile_eclosed}Anyway, I've had about enough of this place, haven't you? Let's head home. + $@c{serious_smile_fists}Maybe when we get back, we can have another battle?\nIf you're up to it.`, + `@c{shock}You're back?@d{32} Does that mean…@d{96} you won?!\n@c{smile_ehalf}I should have known you had it in you. + $@c{smile_eclosed}Of course… I always had that feeling.\n@c{smile}It's over now, right? You ended the loop. + $@c{smile_ehalf}You fulfilled your dream too, didn't you?\nYou didn't lose even once. + $I'll be the only one to remember what you did.\n@c{angry_mopen}I'll try not to forget! + $@c{smile_wave_wink}Just kidding!@d{64} @c{smile}I'd never forget.@d{32}\nYour legend will live on in our hearts. + $@c{smile_wave}Anyway,@d{64} it's getting late…@d{96} I think?\nIt's hard to tell in this place. + $Let's go home. @c{smile_wave_wink}Maybe tomorrow, we can have another battle, for old time's sake?` + ] +} + export function getCharVariantFromDialogue(message: string): string { const variantMatch = /@c\{(.*?)\}/.exec(message); if (variantMatch) diff --git a/src/data/egg.ts b/src/data/egg.ts index 41216f27ee7..6437dfce262 100644 --- a/src/data/egg.ts +++ b/src/data/egg.ts @@ -4,6 +4,7 @@ import BattleScene from "../battle-scene"; import { Species } from "./enums/species"; import { getPokemonSpecies, speciesStarters } from "./pokemon-species"; import { EggTier } from "./enums/egg-type"; +import i18next from '../plugins/i18n'; export const EGG_SEED = 1073741824; @@ -56,34 +57,34 @@ export function getEggDescriptor(egg: Egg): string { return 'Manaphy'; switch (egg.tier) { case EggTier.GREAT: - return 'Rare'; + return i18next.t('egg:greatTier'); case EggTier.ULTRA: - return 'Epic'; + return i18next.t('egg:ultraTier'); case EggTier.MASTER: - return 'Legendary'; + return i18next.t('egg:masterTier'); default: - return 'Common'; + return i18next.t('egg:defaultTier'); } } export function getEggHatchWavesMessage(hatchWaves: integer): string { if (hatchWaves <= 5) - return 'Sounds can be heard coming from inside! It will hatch soon!'; + return i18next.t('egg:hatchWavesMessageSoon'); if (hatchWaves <= 15) - return 'It appears to move occasionally. It may be close to hatching.'; + return i18next.t('egg:hatchWavesMessageClose'); if (hatchWaves <= 50) - return 'What will hatch from this? It doesn\'t seem close to hatching.'; - return 'It looks like this Egg will take a long time to hatch.'; + return i18next.t('egg:hatchWavesMessageNotClose'); + return i18next.t('egg:hatchWavesMessageLongTime'); } export function getEggGachaTypeDescriptor(scene: BattleScene, egg: Egg): string { switch (egg.gachaType) { case GachaType.LEGENDARY: - return `Legendary Rate Up (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, egg.timestamp)).getName()})`; + return `${i18next.t('egg:gachaTypeLegendary')} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, egg.timestamp)).getName()})`; case GachaType.MOVE: - return 'Rare Egg Move Rate Up'; + return i18next.t('egg:gachaTypeMove'); case GachaType.SHINY: - return 'Shiny Rate Up'; + return i18next.t('egg:gachaTypeShiny'); } } diff --git a/src/data/enums/battler-tag-type.ts b/src/data/enums/battler-tag-type.ts index d18ccf1c52f..9411d70a670 100644 --- a/src/data/enums/battler-tag-type.ts +++ b/src/data/enums/battler-tag-type.ts @@ -55,5 +55,6 @@ export enum BattlerTagType { CURSED = "CURSED", CHARGED = "CHARGED", GROUNDED = "GROUNDED", - MAGNET_RISEN = "MAGNET_RISEN" + MAGNET_RISEN = "MAGNET_RISEN", + MINIMIZED = "MINIMIZED" } diff --git a/src/data/enums/trainer-type.ts b/src/data/enums/trainer-type.ts index c30b098960c..c263baae3b7 100644 --- a/src/data/enums/trainer-type.ts +++ b/src/data/enums/trainer-type.ts @@ -43,7 +43,7 @@ export enum TrainerType { SMASHER, SNOW_WORKER, STRIKER, - STUDENT, + SCHOOL_KID, SWIMMER, TWINS, VETERAN, diff --git a/src/data/move.ts b/src/data/move.ts index 3c99ad8c169..99ef179ad30 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1,6 +1,6 @@ import { Moves } from "./enums/moves"; import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims"; -import { BattleEndPhase, MovePhase, NewBattlePhase, PartyStatusCurePhase, PokemonHealPhase, StatChangePhase, SwitchSummonPhase } from "../phases"; +import { BattleEndPhase, MoveEffectPhase, MovePhase, NewBattlePhase, PartyStatusCurePhase, PokemonHealPhase, StatChangePhase, SwitchSummonPhase } from "../phases"; import { BattleStat, getBattleStatName } from "./battle-stat"; import { EncoreTag } from "./battler-tags"; import { BattlerTagType } from "./enums/battler-tag-type"; @@ -33,20 +33,26 @@ export enum MoveCategory { } export enum MoveTarget { + /** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_the_user Moves that target the User} */ USER, OTHER, ALL_OTHERS, NEAR_OTHER, + /** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_adjacent_Pok%C3%A9mon Moves that target all adjacent Pokemon} */ ALL_NEAR_OTHERS, NEAR_ENEMY, + /** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_adjacent_foes Moves that taret all adjacent foes} */ ALL_NEAR_ENEMIES, RANDOM_NEAR_ENEMY, ALL_ENEMIES, + /** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Counterattacks Counterattacks} */ ATTACKER, + /** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_one_adjacent_ally Moves that target one adjacent ally} */ NEAR_ALLY, ALLY, USER_OR_NEAR_ALLY, USER_AND_ALLIES, + /** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_Pok%C3%A9mon Moves that target all Pokemon} */ ALL, USER_SIDE, ENEMY_SIDE, @@ -67,8 +73,8 @@ export enum MoveFlags { PUNCHING_MOVE = 1 << 8, SLICING_MOVE = 1 << 9, /** - * Indicates a move should be affected by {@link Abilities.RECKLESS} - * @see {@link Move.recklessMove()} + * Indicates a move should be affected by {@linkcode Abilities.RECKLESS} + * @see {@linkcode Move.recklessMove()} */ RECKLESS_MOVE = 1 << 10, BALLBOMB_MOVE = 1 << 11, @@ -277,10 +283,10 @@ export default class Move implements Localizable { } /** - * Sets the {@link MoveFlags.RECKLESS_MOVE} flag for the calling Move - * @see {@link Abilities.RECKLESS} - * @param {boolean} recklessMove The value to set the flag to - * @returns {Move} The {@link Move} that called this function + * Sets the {@linkcode MoveFlags.RECKLESS_MOVE} flag for the calling Move + * @see {@linkcode Abilities.RECKLESS} + * @param recklessMove The value to set the flag to + * @returns The {@linkcode Move} that called this function */ recklessMove(recklessMove?: boolean): this { this.setFlag(MoveFlags.RECKLESS_MOVE, recklessMove); @@ -434,29 +440,67 @@ export class SelfStatusMove extends Move { } } +/** + * Base class defining all {@linkcode Move} Attributes + * @abstract + * @see {@linkcode apply} + */ export abstract class MoveAttr { + /** Should this {@linkcode Move} target the user? */ public selfTarget: boolean; constructor(selfTarget: boolean = false) { this.selfTarget = selfTarget; } + /** + * Applies move attributes + * @see {@linkcode applyMoveAttrsInternal} + * @virtual + * @param user {@linkcode Pokemon} using the move + * @param target {@linkcode Pokemon} target of the move + * @param move {@linkcode Move} with this attribute + * @param args Set of unique arguments needed by this attribute + * @returns true if application of the ability succeeds + */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean | Promise { return true; } + /** + * @virtual + * @returns the {@linkcode MoveCondition} or {@linkcode MoveConditionFunc} for this {@linkcode Move} + */ getCondition(): MoveCondition | MoveConditionFunc { return null; } + /** + * @virtual + * @param user {@linkcode Pokemon} using the move + * @param target {@linkcode Pokemon} target of the move + * @param move {@linkcode Move} with this attribute + * @param cancelled {@linkcode Utils.BooleanHolder} which stores if the move should fail + * @returns the string representing failure of this {@linkcode Move} + */ getFailedText(user: Pokemon, target: Pokemon, move: Move, cancelled: Utils.BooleanHolder): string | null { return null; } + /** + * Used by the Enemy AI to rank an attack based on a given user + * @see {@linkcode EnemyPokemon.getNextMove} + * @virtual + */ getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { return 0; } + /** + * Used by the Enemy AI to rank an attack based on a given target + * @see {@linkcode EnemyPokemon.getNextMove} + * @virtual + */ getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { return 0; } @@ -470,8 +514,16 @@ export enum MoveEffectTrigger { POST_TARGET, } +/** Base class defining all Move Effect Attributes + * @extends MoveAttr + * @see {@linkcode apply} + */ export class MoveEffectAttr extends MoveAttr { + /** Defines when this effect should trigger in the move's effect order + * @see {@linkcode MoveEffectPhase.start} + */ public trigger: MoveEffectTrigger; + /** Should this effect only apply on the first hit? */ public firstHitOnly: boolean; constructor(selfTarget?: boolean, trigger?: MoveEffectTrigger, firstHitOnly: boolean = false) { @@ -480,11 +532,21 @@ export class MoveEffectAttr extends MoveAttr { this.firstHitOnly = firstHitOnly; } + /** + * Determines whether the {@linkcode Move}'s effects are valid to {@linkcode apply} + * @virtual + * @param user {@linkcode Pokemon} using the move + * @param target {@linkcode Pokemon} target of the move + * @param move {@linkcode Move} with this attribute + * @param args Set of unique arguments needed by this attribute + * @returns true if basic application of the ability attribute should be possible + */ canApply(user: Pokemon, target: Pokemon, move: Move, args: any[]) { - return !!(this.selfTarget ? user.hp && !user.getTag(BattlerTagType.FRENZY) : target.hp) - && (this.selfTarget || !target.getTag(BattlerTagType.PROTECTED) || move.hasFlag(MoveFlags.IGNORE_PROTECT)); + return !! (this.selfTarget ? user.hp && !user.getTag(BattlerTagType.FRENZY) : target.hp) + && (this.selfTarget || !target.getTag(BattlerTagType.PROTECTED) || move.hasFlag(MoveFlags.IGNORE_PROTECT)); } + /** Applies move effects so long as they are able based on {@linkcode canApply} */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean | Promise { return this.canApply(user, target, move, args); } @@ -738,17 +800,64 @@ export class RecoilAttr extends MoveEffectAttr { } } + +/** + * Attribute used for moves which self KO the user regardless if the move hits a target + * @extends MoveEffectAttr + * @see {@linkcode apply} + **/ export class SacrificialAttr extends MoveEffectAttr { constructor() { - super(true, MoveEffectTrigger.PRE_APPLY); + super(true, MoveEffectTrigger.POST_TARGET); } + /** + * Deals damage to the user equal to their current hp + * @param user {@linkcode Pokemon} that used the move + * @param target {@linkcode Pokemon} target of the move + * @param move {@linkcode Move} with this attribute + * @param args N/A + * @returns true if the function succeeds + **/ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + user.damageAndUpdate(user.hp, HitResult.OTHER, false, true, true); + user.turnData.damageTaken += user.hp; + + return true; + } + + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + if (user.isBoss()) + return -20; + return Math.ceil(((1 - user.getHpRatio()) * 10 - 10) * (target.getAttackTypeEffectiveness(move.type, user) - 0.5)); + } +} + +/** + * Attribute used for moves which self KO the user but only if the move hits a target + * @extends MoveEffectAttr + * @see {@linkcode apply} + **/ +export class SacrificialAttrOnHit extends MoveEffectAttr { + constructor() { + super(true, MoveEffectTrigger.POST_TARGET); + } + + /** + * Deals damage to the user equal to their current hp if the move lands + * @param user {@linkcode Pokemon} that used the move + * @param target {@linkcode Pokemon} target of the move + * @param move {@linkcode Move} with this attribute + * @param args N/A + * @returns true if the function succeeds + **/ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + // If the move fails to hit a target, then the user does not faint and the function returns false if (!super.apply(user, target, move, args)) return false; user.damageAndUpdate(user.hp, HitResult.OTHER, false, true, true); - user.turnData.damageTaken += user.hp; + user.turnData.damageTaken += user.hp; return true; } @@ -762,7 +871,9 @@ export class SacrificialAttr extends MoveEffectAttr { /** * Attribute used for moves which cut the user's Max HP in half. - * Triggers using POST_TARGET. + * Triggers using {@linkcode MoveEffectTrigger.POST_TARGET}. + * @extends MoveEffectAttr + * @see {@linkcode apply} */ export class HalfSacrificialAttr extends MoveEffectAttr { constructor() { @@ -771,9 +882,9 @@ export class HalfSacrificialAttr extends MoveEffectAttr { /** * Cut's the user's Max HP in half and displays the appropriate recoil message - * @param user Pokemon that used the move + * @param user {@linkcode Pokemon} that used the move * @param target N/A - * @param move Move with this attribute + * @param move {@linkcode Move} with this attribute * @param args N/A * @returns true if the function succeeds */ @@ -806,8 +917,15 @@ export enum MultiHitType { _1_TO_10, } +/** + * Heals the user or target by {@linkcode healRatio} depending on the value of {@linkcode selfTarget} + * @extends MoveEffectAttr + * @see {@linkcode apply} + */ export class HealAttr extends MoveEffectAttr { + /** The percentage of {@linkcode Stat.HP} to heal */ private healRatio: number; + /** Should an animation be shown? */ private showAnim: boolean; constructor(healRatio?: number, showAnim?: boolean, selfTarget?: boolean) { @@ -822,6 +940,10 @@ export class HealAttr extends MoveEffectAttr { return true; } + /** + * Creates a new {@linkcode PokemonHealPhase}. + * This heals the target and shows the appropriate message. + */ addHealPhase(target: Pokemon, healRatio: number) { target.scene.unshiftPhase(new PokemonHealPhase(target.scene, target.getBattlerIndex(), Math.max(Math.floor(target.getMaxHp() * healRatio), 1), getPokemonMessage(target, ' \nhad its HP restored.'), true, !this.showAnim)); @@ -835,11 +957,13 @@ export class HealAttr extends MoveEffectAttr { /** * Cures the user's party of non-volatile status conditions, ie. Heal Bell, Aromatherapy - * @param {string} message Message to display after using move - * @param {Abilities} abilityCondition Skips mons with this ability, ie. Soundproof + * @extends MoveEffectAttr + * @see {@linkcode apply} */ export class PartyStatusCureAttr extends MoveEffectAttr { + /** Message to display after using move */ private message: string; + /** Skips mons with this ability, ie. Soundproof */ private abilityCondition: Abilities; constructor(message: string, abilityCondition: Abilities) { @@ -891,19 +1015,23 @@ export class SacrificialFullRestoreAttr extends SacrificialAttr { /** * Attribute used for moves which ignore type-based debuffs from weather, namely Hydro Steam. * Called during damage calculation after getting said debuff from getAttackTypeMultiplier in the Pokemon class. + * @extends MoveAttr + * @see {@linkcode apply} */ export class IgnoreWeatherTypeDebuffAttr extends MoveAttr { + /** The {@linkcode WeatherType} this move ignores */ public weather: WeatherType; + constructor(weather: WeatherType){ super(); this.weather = weather; } /** * Changes the type-based weather modifier if this move's power would be reduced by it - * @param user Pokemon that used the move + * @param user {@linkcode Pokemon} that used the move * @param target N/A - * @param move Move with this attribute - * @param args Utils.NumberHolder for arenaAttackTypeMultiplier + * @param move {@linkcode Move} with this attribute + * @param args [0] {@linkcode Utils.NumberHolder} for arenaAttackTypeMultiplier * @returns true if the function succeeds */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { @@ -963,27 +1091,19 @@ export class SandHealAttr extends WeatherHealAttr { } /** - * Heals the target by either {@link normalHealRatio} or {@link boostedHealRatio} - * depending on the evaluation of {@link condition} - * @see {@link apply} - * @param user The Pokemon using this move - * @param target The target Pokemon of this move - * @param move This move - * @param args N/A - * @returns if the move was successful + * Heals the target or the user by either {@linkcode normalHealRatio} or {@linkcode boostedHealRatio} + * depending on the evaluation of {@linkcode condition} + * @extends HealAttr + * @see {@linkcode apply} */ export class BoostHealAttr extends HealAttr { + /** Healing received when {@linkcode condition} is false */ private normalHealRatio?: number; + /** Healing received when {@linkcode condition} is true */ private boostedHealRatio?: number; + /** The lambda expression to check against when boosting the healing value */ private condition?: MoveConditionFunc; - /** - * @param normalHealRatio Healing received when {@link condition} is false - * @param boostedHealRatio Healing received when {@link condition} is true - * @param showAnim Should a healing animation be showed? - * @param selfTarget Should the move target the user? - * @param condition The condition to check against when boosting the healing value - */ constructor(normalHealRatio?: number, boostedHealRatio?: number, showAnim?: boolean, selfTarget?: boolean, condition?: MoveConditionFunc) { super(normalHealRatio, showAnim, selfTarget); this.normalHealRatio = normalHealRatio; @@ -991,6 +1111,13 @@ export class BoostHealAttr extends HealAttr { this.condition = condition; } + /** + * @param user {@linkcode Pokemon} using the move + * @param target {@linkcode Pokemon} target of the move + * @param move {@linkcode Move} with this attribute + * @param args N/A + * @returns true if the move was successful + */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const healRatio = this.condition(user, target, move) ? this.boostedHealRatio : this.normalHealRatio; this.addHealPhase(target, healRatio); @@ -1356,15 +1483,17 @@ export class BypassSleepAttr extends MoveAttr { /** * Attribute used for moves that bypass the burn damage reduction of physical moves, currently only facade * Called during damage calculation - * @param user N/A - * @param target N/A - * @param move Move with this attribute - * @param args Utils.BooleanHolder for burnDamageReductionCancelled - * @returns true if the function succeeds + * @extends MoveAttr + * @see {@linkcode apply} */ export class BypassBurnDamageReductionAttr extends MoveAttr { - - /** Prevents the move's damage from being reduced by burn */ + /** Prevents the move's damage from being reduced by burn + * @param user N/A + * @param target N/A + * @param move {@linkcode Move} with this attribute + * @param args [0] {@linkcode Utils.BooleanHolder} for burnDamageReductionCancelled + * @returns true if the function succeeds + */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { (args[0] as Utils.BooleanHolder).value = true; @@ -1792,7 +1921,7 @@ export class CopyStatsAttr extends MoveEffectAttr { target.updateInfo(); user.updateInfo(); - target.scene.queueMessage(getPokemonMessage(user, 'copied\n') + getPokemonMessage(target, `'s stat changes!`)); + target.scene.queueMessage(getPokemonMessage(user, ' copied\n') + getPokemonMessage(target, `'s stat changes!`)); return true; } @@ -2000,36 +2129,27 @@ export class WeightPowerAttr extends VariablePowerAttr { } } -export class BattleStatRatioPowerAttr extends VariablePowerAttr { - private stat: Stat; - private invert: boolean; - - constructor(stat: Stat, invert: boolean = false) { - super(); - - this.stat = stat; - this.invert = invert; - } - +/** + * Attribute used for Electro Ball move. + * @extends VariablePowerAttr + * @see {@linkcode apply} + **/ +export class ElectroBallPowerAttr extends VariablePowerAttr { + /** + * Move that deals more damage the faster {@linkcode BattleStat.SPD} + * the user is compared to the target. + * @param user Pokemon that used the move + * @param target The target of the move + * @param move Move with this attribute + * @param args N/A + * @returns true if the function succeeds + */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const power = args[0] as Utils.NumberHolder; - const statRatio = target.getStat(this.stat) / user.getStat(this.stat); + const statRatio = target.getBattleStat(Stat.SPD) / user.getBattleStat(Stat.SPD); const statThresholds = [ 0.25, 1 / 3, 0.5, 1, -1 ]; - let statThresholdPowers = [ 150, 120, 80, 60, 40 ]; - - if (this.invert) { - // Gyro ball uses a specific formula - let userSpeed = user.getBattleStat(this.stat); - if (userSpeed < 1) { - // Gen 6+ always have 1 base power - power.value = 1; - return true; - } - let bp = Math.floor(Math.min(150, 25 * target.getBattleStat(this.stat) / userSpeed + 1)); - power.value = bp; - return true; - } + const statThresholdPowers = [ 150, 120, 80, 60, 40 ]; let w = 0; while (w < statThresholds.length - 1 && statRatio > statThresholds[w]) { @@ -2038,7 +2158,36 @@ export class BattleStatRatioPowerAttr extends VariablePowerAttr { } power.value = statThresholdPowers[w]; + return true; + } +} + +/** + * Attribute used for Gyro Ball move. + * @extends VariablePowerAttr + * @see {@linkcode apply} + **/ +export class GyroBallPowerAttr extends VariablePowerAttr { + /** + * Move that deals more damage the slower {@linkcode BattleStat.SPD} + * the user is compared to the target. + * @param user Pokemon that used the move + * @param target The target of the move + * @param move Move with this attribute + * @param args N/A + * @returns true if the function succeeds + */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const power = args[0] as Utils.NumberHolder; + const userSpeed = user.getBattleStat(Stat.SPD); + if (userSpeed < 1) { + // Gen 6+ always have 1 base power + power.value = 1; + return true; + } + + power.value = Math.floor(Math.min(150, 25 * target.getBattleStat(Stat.SPD) / userSpeed + 1)); return true; } } @@ -2372,6 +2521,33 @@ export class ThunderAccuracyAttr extends VariableAccuracyAttr { } } +/** + * Attribute used for moves which never miss + * against Pokemon with the {@linkcode BattlerTagType.MINIMIZED} + * @extends VariableAccuracyAttr + * @see {@linkcode apply} + */ +export class MinimizeAccuracyAttr extends VariableAccuracyAttr { + /** + * @see {@linkcode apply} + * @param user N/A + * @param target {@linkcode Pokemon} target of the move + * @param move N/A + * @param args [0] Accuracy of the move to be modified + * @returns true if the function succeeds + */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + if (target.getTag(BattlerTagType.MINIMIZED)){ + const accuracy = args[0] as Utils.NumberHolder + accuracy.value = -1; + + return true; + } + + return false; + } +} + export class ToxicAccuracyAttr extends VariableAccuracyAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { if (user.isOfType(Type.POISON)) { @@ -3127,8 +3303,14 @@ export class FaintCountdownAttr extends AddBattlerTagAttr { } } +/** + * Attribute used when a move hits a {@linkcode BattlerTagType} for double damage + * @extends MoveAttr +*/ export class HitsTagAttr extends MoveAttr { + /** The {@linkcode BattlerTagType} this move hits */ public tagType: BattlerTagType; + /** Should this move deal double damage against {@linkcode HitsTagAttr.tagType}? */ public doubleDamage: boolean; constructor(tagType: BattlerTagType, doubleDamage?: boolean) { @@ -4295,6 +4477,8 @@ export function initMoves() { new AttackMove(Moves.SLAM, Type.NORMAL, MoveCategory.PHYSICAL, 80, 75, 20, -1, 0, 1), new AttackMove(Moves.VINE_WHIP, Type.GRASS, MoveCategory.PHYSICAL, 45, 100, 25, -1, 0, 1), new AttackMove(Moves.STOMP, Type.NORMAL, MoveCategory.PHYSICAL, 65, 100, 20, 30, 0, 1) + .attr(MinimizeAccuracyAttr) + .attr(HitsTagAttr, BattlerTagType.MINIMIZED, true) .attr(FlinchAttr), new AttackMove(Moves.DOUBLE_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 30, 100, 30, -1, 0, 1) .attr(MultiHitAttr, MultiHitType._2), @@ -4318,6 +4502,8 @@ export function initMoves() { .attr(OneHitKOAccuracyAttr), new AttackMove(Moves.TACKLE, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, 0, 1), new AttackMove(Moves.BODY_SLAM, Type.NORMAL, MoveCategory.PHYSICAL, 85, 100, 15, 30, 0, 1) + .attr(MinimizeAccuracyAttr) + .attr(HitsTagAttr, BattlerTagType.MINIMIZED, true) .attr(StatusEffectAttr, StatusEffect.PARALYSIS), new AttackMove(Moves.WRAP, Type.NORMAL, MoveCategory.PHYSICAL, 15, 90, 20, 100, 0, 1) .attr(TrapAttr, BattlerTagType.WRAP), @@ -4515,6 +4701,7 @@ export function initMoves() { new SelfStatusMove(Moves.HARDEN, Type.NORMAL, -1, 30, -1, 0, 1) .attr(StatChangeAttr, BattleStat.DEF, 1, true), new SelfStatusMove(Moves.MINIMIZE, Type.NORMAL, -1, 10, -1, 0, 1) + .attr(AddBattlerTagAttr, BattlerTagType.MINIMIZED, true, false) .attr(StatChangeAttr, BattleStat.EVA, 2, true), new StatusMove(Moves.SMOKESCREEN, Type.NORMAL, 100, 20, -1, 0, 1) .attr(StatChangeAttr, BattleStat.ACC, -1), @@ -4960,12 +5147,12 @@ export function initMoves() { new StatusMove(Moves.WILL_O_WISP, Type.FIRE, 85, 15, -1, 0, 3) .attr(StatusEffectAttr, StatusEffect.BURN), new StatusMove(Moves.MEMENTO, Type.DARK, 100, 10, -1, 0, 3) - .attr(SacrificialAttr) + .attr(SacrificialAttrOnHit) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -2), new AttackMove(Moves.FACADE, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 3) .attr(MovePowerMultiplierAttr, (user, target, move) => user.status && (user.status.effect === StatusEffect.BURN || user.status.effect === StatusEffect.POISON || user.status.effect === StatusEffect.TOXIC || user.status.effect === StatusEffect.PARALYSIS) ? 2 : 1) - .attr(BypassBurnDamageReductionAttr), + .attr(BypassBurnDamageReductionAttr), new AttackMove(Moves.FOCUS_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 150, 100, 20, -1, -3, 3) .punchingMove() .ignoresVirtual() @@ -5221,7 +5408,7 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPD, -1, true) .punchingMove(), new AttackMove(Moves.GYRO_BALL, Type.STEEL, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 4) - .attr(BattleStatRatioPowerAttr, Stat.SPD, true) + .attr(GyroBallPowerAttr) .ballBombMove(), new SelfStatusMove(Moves.HEALING_WISH, Type.PSYCHIC, -1, 10, -1, 0, 4) .attr(SacrificialFullRestoreAttr) @@ -5354,6 +5541,8 @@ export function initMoves() { new AttackMove(Moves.DRAGON_PULSE, Type.DRAGON, MoveCategory.SPECIAL, 85, 100, 10, -1, 0, 4) .pulseMove(), new AttackMove(Moves.DRAGON_RUSH, Type.DRAGON, MoveCategory.PHYSICAL, 100, 75, 10, 20, 0, 4) + .attr(MinimizeAccuracyAttr) + .attr(HitsTagAttr, BattlerTagType.MINIMIZED, true) .attr(FlinchAttr), new AttackMove(Moves.POWER_GEM, Type.ROCK, MoveCategory.SPECIAL, 80, 100, 20, -1, 0, 4), new AttackMove(Moves.DRAIN_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 75, 100, 10, -1, 0, 4) @@ -5496,7 +5685,7 @@ export function initMoves() { new AttackMove(Moves.SPACIAL_REND, Type.DRAGON, MoveCategory.SPECIAL, 100, 95, 5, -1, 0, 4) .attr(HighCritAttr), new SelfStatusMove(Moves.LUNAR_DANCE, Type.PSYCHIC, -1, 10, -1, 0, 4) - .attr(SacrificialAttr) + .attr(SacrificialAttrOnHit) .danceMove() .triageMove() .unimplemented(), @@ -5508,7 +5697,7 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.SLEEP) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.SEED_FLARE, Type.GRASS, MoveCategory.SPECIAL, 120, 85, 5, 40, 0, 4) - .attr(StatChangeAttr, BattleStat.SPDEF, -1), + .attr(StatChangeAttr, BattleStat.SPDEF, -2), new AttackMove(Moves.OMINOUS_WIND, Type.GHOST, MoveCategory.SPECIAL, 60, 100, 5, 10, 0, 4) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, true) .windMove(), @@ -5563,14 +5752,16 @@ export function initMoves() { .attr(StatChangeAttr, [ BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, true) .danceMove(), new AttackMove(Moves.HEAVY_SLAM, Type.STEEL, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 5) + .attr(MinimizeAccuracyAttr) .attr(CompareWeightPowerAttr) + .attr(HitsTagAttr, BattlerTagType.MINIMIZED, true) .condition(failOnMaxCondition), new AttackMove(Moves.SYNCHRONOISE, Type.PSYCHIC, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 5) .target(MoveTarget.ALL_NEAR_OTHERS) .condition(unknownTypeCondition) .attr(hitsSameTypeAttr), new AttackMove(Moves.ELECTRO_BALL, Type.ELECTRIC, MoveCategory.SPECIAL, -1, 100, 10, -1, 0, 5) - .attr(BattleStatRatioPowerAttr, Stat.SPD) + .attr(ElectroBallPowerAttr) .ballBombMove(), new StatusMove(Moves.SOAK, Type.WATER, 100, 20, -1, 0, 5) .attr(ChangeTypeAttr, Type.WATER), @@ -5645,7 +5836,7 @@ export function initMoves() { .partial(), new AttackMove(Moves.FINAL_GAMBIT, Type.FIGHTING, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 5) .attr(UserHpDamageAttr) - .attr(SacrificialAttr), + .attr(SacrificialAttrOnHit), new StatusMove(Moves.BESTOW, Type.NORMAL, -1, 15, -1, 0, 5) .ignoresProtect() .unimplemented(), @@ -5694,7 +5885,9 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.DEF, -1) .slicingMove(), new AttackMove(Moves.HEAT_CRASH, Type.FIRE, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 5) + .attr(MinimizeAccuracyAttr) .attr(CompareWeightPowerAttr) + .attr(HitsTagAttr, BattlerTagType.MINIMIZED, true) .condition(failOnMaxCondition), new AttackMove(Moves.LEAF_TORNADO, Type.GRASS, MoveCategory.SPECIAL, 65, 90, 10, 50, 0, 5) .attr(StatChangeAttr, BattleStat.ACC, -1), @@ -5765,7 +5958,9 @@ export function initMoves() { .makesContact(false) .partial(), new AttackMove(Moves.FLYING_PRESS, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 95, 10, -1, 0, 6) + .attr(MinimizeAccuracyAttr) .attr(FlyingTypeMultiplierAttr) + .attr(HitsTagAttr, BattlerTagType.MINIMIZED, true) .condition(failOnGravityCondition), new StatusMove(Moves.MAT_BLOCK, Type.FIGHTING, -1, 10, -1, 0, 6) .unimplemented(), diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index 9a38ed81e34..a8bc07e92df 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -705,7 +705,9 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.OGERPON, 'cornerstone-mask-tera', 'cornerstone-mask', new SpeciesFormChangeManualTrigger(), true) //When no longer holding a Rock Tera Shard ], [Species.TERAPAGOS]: [ - new SpeciesFormChange(Species.TERAPAGOS, '', 'terastal', new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.TERAPAGOS, '', 'terastal', new SpeciesFormChangeManualTrigger(), true), + new SpeciesFormChange(Species.TERAPAGOS, 'terastal', 'stellar', new SpeciesFormChangeManualTrigger(), true), //When holding a Stellar Tera Shard + new SpeciesFormChange(Species.TERAPAGOS, 'stellar', 'terastal', new SpeciesFormChangeManualTrigger(), true) //When no longer holding a Stellar Tera Shard ], [Species.GALAR_DARMANITAN]: [ new SpeciesFormChange(Species.GALAR_DARMANITAN, '', 'zen', new SpeciesFormChangeManualTrigger(), true), diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index c8f99936941..218423d3232 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -1504,7 +1504,7 @@ export function initSpecies() { new PokemonForm("Origin Forme", "origin", Type.WATER, Type.DRAGON, 6.3, 659, Abilities.PRESSURE, Abilities.NONE, Abilities.TELEPATHY, 680, 90, 100, 100, 150, 120, 120, 3, 0, 340), ), new PokemonSpecies(Species.HEATRAN, 4, true, false, false, "Lava Dome Pokémon", Type.FIRE, Type.STEEL, 1.7, 430, Abilities.FLASH_FIRE, Abilities.NONE, Abilities.FLAME_BODY, 600, 91, 90, 106, 130, 106, 77, 3, 100, 300, GrowthRate.SLOW, 50, false), - new PokemonSpecies(Species.REGIGIGAS, 4, false, true, false, "Colossal Pokémon", Type.NORMAL, null, 3.7, 420, Abilities.SLOW_START, Abilities.NONE, Abilities.NORMALIZE, 670, 110, 160, 110, 80, 110, 100, 3, 0, 335, GrowthRate.SLOW, null, false), + new PokemonSpecies(Species.REGIGIGAS, 4, true, false, false, "Colossal Pokémon", Type.NORMAL, null, 3.7, 420, Abilities.SLOW_START, Abilities.NONE, Abilities.NORMALIZE, 670, 110, 160, 110, 80, 110, 100, 3, 0, 335, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.GIRATINA, 4, false, true, false, "Renegade Pokémon", Type.GHOST, Type.DRAGON, 4.5, 750, Abilities.PRESSURE, Abilities.NONE, Abilities.TELEPATHY, 680, 150, 100, 120, 100, 120, 90, 3, 0, 340, GrowthRate.SLOW, null, false, true, new PokemonForm("Altered Forme", "altered", Type.GHOST, Type.DRAGON, 4.5, 750, Abilities.PRESSURE, Abilities.NONE, Abilities.TELEPATHY, 680, 150, 100, 120, 100, 120, 90, 3, 0, 340), new PokemonForm("Origin Forme", "origin", Type.GHOST, Type.DRAGON, 6.9, 650, Abilities.LEVITATE, Abilities.NONE, Abilities.NONE, 680, 150, 120, 100, 120, 100, 90, 3, 0, 340), @@ -1931,7 +1931,7 @@ export function initSpecies() { new PokemonForm("Active Mode", "active", Type.FAIRY, null, 3, 215, Abilities.FAIRY_AURA, Abilities.NONE, Abilities.NONE, 680, 126, 131, 95, 131, 98, 99, 45, 0, 340) ), new PokemonSpecies(Species.YVELTAL, 6, false, true, false, "Destruction Pokémon", Type.DARK, Type.FLYING, 5.8, 203, Abilities.DARK_AURA, Abilities.NONE, Abilities.NONE, 680, 126, 131, 95, 131, 98, 99, 45, 0, 340, GrowthRate.SLOW, null, false), - new PokemonSpecies(Species.ZYGARDE, 6, true, false, false, "Order Pokémon", Type.DRAGON, Type.GROUND, 5, 305, Abilities.AURA_BREAK, Abilities.NONE, Abilities.NONE, 600, 108, 100, 121, 81, 95, 95, 3, 0, 300, GrowthRate.SLOW, null, false, false, + new PokemonSpecies(Species.ZYGARDE, 6, false, true, false, "Order Pokémon", Type.DRAGON, Type.GROUND, 5, 305, Abilities.AURA_BREAK, Abilities.NONE, Abilities.NONE, 600, 108, 100, 121, 81, 95, 95, 3, 0, 300, GrowthRate.SLOW, null, false, false, new PokemonForm("50% Forme", "50", Type.DRAGON, Type.GROUND, 5, 305, Abilities.AURA_BREAK, Abilities.NONE, Abilities.NONE, 600, 108, 100, 121, 81, 95, 95, 3, 0, 300, false, ""), new PokemonForm("10% Forme", "10", Type.DRAGON, Type.GROUND, 1.2, 33.5, Abilities.AURA_BREAK, Abilities.NONE, Abilities.NONE, 486, 54, 100, 71, 61, 85, 115, 3, 0, 300), new PokemonForm("50% Forme Power Construct", "50-pc", Type.DRAGON, Type.GROUND, 5, 305, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 600, 108, 100, 121, 81, 95, 95, 3, 0, 300, false, ""), @@ -2285,7 +2285,7 @@ export function initSpecies() { new PokemonSpecies(Species.REGIDRAGO, 8, true, false, false, "Dragon Orb Pokémon", Type.DRAGON, null, 2.1, 200, Abilities.DRAGONS_MAW, Abilities.NONE, Abilities.NONE, 580, 200, 100, 50, 100, 50, 80, 3, 35, 290, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.GLASTRIER, 8, true, false, false, "Wild Horse Pokémon", Type.ICE, null, 2.2, 800, Abilities.CHILLING_NEIGH, Abilities.NONE, Abilities.NONE, 580, 100, 145, 130, 65, 110, 30, 3, 35, 290, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.SPECTRIER, 8, true, false, false, "Swift Horse Pokémon", Type.GHOST, null, 2, 44.5, Abilities.GRIM_NEIGH, Abilities.NONE, Abilities.NONE, 580, 100, 65, 60, 145, 80, 130, 3, 35, 290, GrowthRate.SLOW, null, false), - new PokemonSpecies(Species.CALYREX, 8, true, false, false, "King Pokémon", Type.PSYCHIC, Type.GRASS, 1.1, 7.7, Abilities.UNNERVE, Abilities.NONE, Abilities.NONE, 500, 100, 80, 80, 80, 80, 80, 3, 100, 250, GrowthRate.SLOW, null, false, true, + new PokemonSpecies(Species.CALYREX, 8, false, true, false, "King Pokémon", Type.PSYCHIC, Type.GRASS, 1.1, 7.7, Abilities.UNNERVE, Abilities.NONE, Abilities.NONE, 500, 100, 80, 80, 80, 80, 80, 3, 100, 250, GrowthRate.SLOW, null, false, true, new PokemonForm("Normal", "", Type.PSYCHIC, Type.GRASS, 1.1, 7.7, Abilities.UNNERVE, Abilities.NONE, Abilities.NONE, 500, 100, 80, 80, 80, 80, 80, 3, 100, 250), new PokemonForm("Ice", "ice", Type.PSYCHIC, Type.ICE, 2.4, 809.1, Abilities.AS_ONE_GLASTRIER, Abilities.NONE, Abilities.NONE, 680, 100, 165, 150, 85, 130, 50, 3, 100, 250), new PokemonForm("Shadow", "shadow", Type.PSYCHIC, Type.GHOST, 2.4, 53.6, Abilities.AS_ONE_SPECTRIER, Abilities.NONE, Abilities.NONE, 680, 100, 85, 80, 165, 100, 150, 3, 100, 250), @@ -2453,10 +2453,10 @@ export function initSpecies() { new PokemonForm("Unremarkable Form", "unremarkable", Type.GRASS, Type.GHOST, 0.2, 2.2, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 508, 71, 60, 106, 121, 80, 70, 60, 50, 178), new PokemonForm("Masterpiece Form", "masterpiece", Type.GRASS, Type.GHOST, 0.2, 2.2, Abilities.HOSPITALITY, Abilities.NONE, Abilities.HEATPROOF, 508, 71, 60, 106, 121, 80, 70, 60, 50, 178), ), - new PokemonSpecies(Species.OKIDOGI, 9, false, true, false, "Retainer Pokémon", Type.POISON, Type.FIGHTING, 1.8, 92.2, Abilities.TOXIC_CHAIN, Abilities.NONE, Abilities.GUARD_DOG, 555, 88, 128, 115, 58, 86, 80, 3, 0, 276, GrowthRate.SLOW, 100, false), - new PokemonSpecies(Species.MUNKIDORI, 9, false, true, false, "Retainer Pokémon", Type.POISON, Type.PSYCHIC, 1, 12.2, Abilities.TOXIC_CHAIN, Abilities.NONE, Abilities.FRISK, 555, 88, 75, 66, 130, 90, 106, 3, 0, 276, GrowthRate.SLOW, 100, false), - new PokemonSpecies(Species.FEZANDIPITI, 9, false, true, false, "Retainer Pokémon", Type.POISON, Type.FAIRY, 1.4, 30.1, Abilities.TOXIC_CHAIN, Abilities.NONE, Abilities.TECHNICIAN, 555, 88, 91, 82, 70, 125, 99, 3, 0, 276, GrowthRate.SLOW, 100, false), - new PokemonSpecies(Species.OGERPON, 9, false, true, false, "Mask Pokémon", Type.GRASS, null, 1.2, 39.8, Abilities.DEFIANT, Abilities.NONE, Abilities.NONE, 550, 80, 120, 84, 60, 96, 110, 5, 50, 275, GrowthRate.SLOW, 0, false, false, + new PokemonSpecies(Species.OKIDOGI, 9, true, false, false, "Retainer Pokémon", Type.POISON, Type.FIGHTING, 1.8, 92.2, Abilities.TOXIC_CHAIN, Abilities.NONE, Abilities.GUARD_DOG, 555, 88, 128, 115, 58, 86, 80, 3, 0, 276, GrowthRate.SLOW, 100, false), + new PokemonSpecies(Species.MUNKIDORI, 9, true, false, false, "Retainer Pokémon", Type.POISON, Type.PSYCHIC, 1, 12.2, Abilities.TOXIC_CHAIN, Abilities.NONE, Abilities.FRISK, 555, 88, 75, 66, 130, 90, 106, 3, 0, 276, GrowthRate.SLOW, 100, false), + new PokemonSpecies(Species.FEZANDIPITI, 9, true, false, false, "Retainer Pokémon", Type.POISON, Type.FAIRY, 1.4, 30.1, Abilities.TOXIC_CHAIN, Abilities.NONE, Abilities.TECHNICIAN, 555, 88, 91, 82, 70, 125, 99, 3, 0, 276, GrowthRate.SLOW, 100, false), + new PokemonSpecies(Species.OGERPON, 9, true, false, false, "Mask Pokémon", Type.GRASS, null, 1.2, 39.8, Abilities.DEFIANT, Abilities.NONE, Abilities.NONE, 550, 80, 120, 84, 60, 96, 110, 5, 50, 275, GrowthRate.SLOW, 0, false, false, new PokemonForm("Teal Mask", "teal-mask", Type.GRASS, null, 1.2, 39.8, Abilities.DEFIANT, Abilities.NONE, Abilities.NONE, 550, 80, 120, 84, 60, 96, 110, 5, 50, 275), new PokemonForm("Wellspring Mask", "wellspring-mask", Type.GRASS, Type.WATER, 1.2, 39.8, Abilities.WATER_ABSORB, Abilities.NONE, Abilities.NONE, 550, 80, 120, 84, 60, 96, 110, 5, 50, 275), new PokemonForm("Hearthflame Mask", "hearthflame-mask", Type.GRASS, Type.FIRE, 1.2, 39.8, Abilities.MOLD_BREAKER, Abilities.NONE, Abilities.NONE, 550, 80, 120, 84, 60, 96, 110, 5, 50, 275), diff --git a/src/data/splash-messages.ts b/src/data/splash-messages.ts index 198ff07cec9..c650b038287 100644 --- a/src/data/splash-messages.ts +++ b/src/data/splash-messages.ts @@ -1,37 +1,45 @@ -export const battleCountSplashMessage = '{COUNT} Battles Won!'; +import i18next from "../plugins/i18n"; -export const splashMessages = Array(10).fill(battleCountSplashMessage); -splashMessages.push(...[ - 'Join the Discord!', - 'Infinite Levels!', - 'Everything Stacks!', - 'Optional Save Scumming!', - '35 Biomes!', - 'Open Source!', - 'Play with 5x Speed!', - 'Live Bug Testing!', - 'Heavy RoR2 Influence!', - 'Pokémon Risk and Pokémon Rain!', - 'Now with 33% More Salt!', - 'Infinite Fusion at Home!', - 'Broken Egg Moves!', - 'Magnificent!', - 'Mubstitute!', - 'That\'s Crazy!', - 'Orance Juice!', - 'Questionable Balancing!', - 'Cool Shaders!', - 'AI-Free!', - 'Sudden Difficulty Spikes!', - 'Based on an Unfinished Flash Game!', - 'More Addictive than Intended!', - 'Mostly Consistent Seeds!', - 'Achievement Points Don\'t Do Anything!', - 'You Do Not Start at Level 2000!', - 'Don\'t Talk About the Manaphy Egg Incident!', - 'Also Try Pokéngine!', - 'Also Try Emerald Rogue!', - 'Also Try Radical Red!', - 'Eevee Expo!', - 'YNOproject!' -]); \ No newline at end of file +export function getBattleCountSplashMessage(): string { + return `{COUNT} ${i18next.t('splashMessages:battlesWon')}`; +} + +export function getSplashMessages(): string[] { + const splashMessages = Array(10).fill(getBattleCountSplashMessage()); + splashMessages.push(...[ + i18next.t('splashMessages:joinTheDiscord'), + i18next.t('splashMessages:infiniteLevels'), + i18next.t('splashMessages:everythingStacks'), + i18next.t('splashMessages:optionalSaveScumming'), + i18next.t('splashMessages:biomes'), + i18next.t('splashMessages:openSource'), + i18next.t('splashMessages:playWithSpeed'), + i18next.t('splashMessages:liveBugTesting'), + i18next.t('splashMessages:heavyInfluence'), + i18next.t('splashMessages:pokemonRiskAndPokemonRain'), + i18next.t('splashMessages:nowWithMoreSalt'), + i18next.t('splashMessages:infiniteFusionAtHome'), + i18next.t('splashMessages:brokenEggMoves'), + i18next.t('splashMessages:magnificent'), + i18next.t('splashMessages:mubstitute'), + i18next.t('splashMessages:thatsCrazy'), + i18next.t('splashMessages:oranceJuice'), + i18next.t('splashMessages:questionableBalancing'), + i18next.t('splashMessages:coolShaders'), + i18next.t('splashMessages:aiFree'), + i18next.t('splashMessages:suddenDifficultySpikes'), + i18next.t('splashMessages:basedOnAnUnfinishedFlashGame'), + i18next.t('splashMessages:moreAddictiveThanIntended'), + i18next.t('splashMessages:mostlyConsistentSeeds'), + i18next.t('splashMessages:achievementPointsDontDoAnything'), + i18next.t('splashMessages:youDoNotStartAtLevel'), + i18next.t('splashMessages:dontTalkAboutTheManaphyEggIncident'), + i18next.t('splashMessages:alsoTryPokengine'), + i18next.t('splashMessages:alsoTryEmeraldRogue'), + i18next.t('splashMessages:alsoTryRadicalRed'), + i18next.t('splashMessages:eeveeExpo'), + i18next.t('splashMessages:ynoproject'), + ]); + + return splashMessages +} \ No newline at end of file diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 36d76edcfab..712cd13a38d 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -1,161 +1,163 @@ -import BattleScene, { startingWave } from "../battle-scene"; -import { ModifierTypeFunc, modifierTypes } from "../modifier/modifier-type"; -import { EnemyPokemon } from "../field/pokemon"; +import BattleScene, {startingWave} from "../battle-scene"; +import {ModifierTypeFunc, modifierTypes} from "../modifier/modifier-type"; +import {EnemyPokemon} from "../field/pokemon"; import * as Utils from "../utils"; -import { TrainerType } from "./enums/trainer-type"; -import { Moves } from "./enums/moves"; -import { PokeballType } from "./pokeball"; -import { pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions"; -import PokemonSpecies, { PokemonSpeciesFilter, getPokemonSpecies } from "./pokemon-species"; -import { Species } from "./enums/species"; -import { tmSpecies } from "./tms"; -import { Type } from "./type"; -import { initTrainerTypeDialogue } from "./dialogue"; -import { PersistentModifier } from "../modifier/modifier"; -import { TrainerVariant } from "../field/trainer"; -import { PartyMemberStrength } from "./enums/party-member-strength"; +import {TrainerType} from "./enums/trainer-type"; +import {Moves} from "./enums/moves"; +import {PokeballType} from "./pokeball"; +import {pokemonEvolutions, pokemonPrevolutions} from "./pokemon-evolutions"; +import PokemonSpecies, {PokemonSpeciesFilter, getPokemonSpecies} from "./pokemon-species"; +import {Species} from "./enums/species"; +import {tmSpecies} from "./tms"; +import {Type} from "./type"; +import {initTrainerTypeDialogue} from "./dialogue"; +import {PersistentModifier} from "../modifier/modifier"; +import {TrainerVariant} from "../field/trainer"; +import {PartyMemberStrength} from "./enums/party-member-strength"; +import i18next from "i18next"; +import {getIsInitialized, initI18n} from "#app/plugins/i18n"; export enum TrainerPoolTier { - COMMON, - UNCOMMON, - RARE, - SUPER_RARE, - ULTRA_RARE + COMMON, + UNCOMMON, + RARE, + SUPER_RARE, + ULTRA_RARE } export interface TrainerTierPools { - [key: integer]: Species[] + [key: integer]: Species[] } export enum TrainerSlot { - NONE, - TRAINER, - TRAINER_PARTNER + NONE, + TRAINER, + TRAINER_PARTNER } export class TrainerPartyTemplate { - public size: integer; - public strength: PartyMemberStrength; - public sameSpecies: boolean; - public balanced: boolean; + public size: integer; + public strength: PartyMemberStrength; + public sameSpecies: boolean; + public balanced: boolean; - constructor(size: integer, strength: PartyMemberStrength, sameSpecies?: boolean, balanced?: boolean) { - this.size = size; - this.strength = strength; - this.sameSpecies = !!sameSpecies; - this.balanced = !!balanced; - } + constructor(size: integer, strength: PartyMemberStrength, sameSpecies?: boolean, balanced?: boolean) { + this.size = size; + this.strength = strength; + this.sameSpecies = !!sameSpecies; + this.balanced = !!balanced; + } - getStrength(index: integer): PartyMemberStrength { - return this.strength; - } + getStrength(index: integer): PartyMemberStrength { + return this.strength; + } - isSameSpecies(index: integer): boolean { - return this.sameSpecies; - } + isSameSpecies(index: integer): boolean { + return this.sameSpecies; + } - isBalanced(index: integer): boolean { - return this.balanced; - } + isBalanced(index: integer): boolean { + return this.balanced; + } } export class TrainerPartyCompoundTemplate extends TrainerPartyTemplate { - public templates: TrainerPartyTemplate[]; + public templates: TrainerPartyTemplate[]; - constructor(...templates: TrainerPartyTemplate[]) { - super(templates.reduce((total: integer, template: TrainerPartyTemplate) => { - total += template.size; - return total; - }, 0), PartyMemberStrength.AVERAGE); - this.templates = templates; - } - - getStrength(index: integer): PartyMemberStrength { - let t = 0; - for (let template of this.templates) { - if (t + template.size > index) - return template.getStrength(index - t); - t += template.size; + constructor(...templates: TrainerPartyTemplate[]) { + super(templates.reduce((total: integer, template: TrainerPartyTemplate) => { + total += template.size; + return total; + }, 0), PartyMemberStrength.AVERAGE); + this.templates = templates; } - return super.getStrength(index); - } + getStrength(index: integer): PartyMemberStrength { + let t = 0; + for (let template of this.templates) { + if (t + template.size > index) + return template.getStrength(index - t); + t += template.size; + } - isSameSpecies(index: integer): boolean { - let t = 0; - for (let template of this.templates) { - if (t + template.size > index) - return template.isSameSpecies(index - t); - t += template.size; + return super.getStrength(index); } - return super.isSameSpecies(index); - } + isSameSpecies(index: integer): boolean { + let t = 0; + for (let template of this.templates) { + if (t + template.size > index) + return template.isSameSpecies(index - t); + t += template.size; + } - isBalanced(index: integer): boolean { - let t = 0; - for (let template of this.templates) { - if (t + template.size > index) - return template.isBalanced(index - t); - t += template.size; + return super.isSameSpecies(index); } - return super.isBalanced(index); - } + isBalanced(index: integer): boolean { + let t = 0; + for (let template of this.templates) { + if (t + template.size > index) + return template.isBalanced(index - t); + t += template.size; + } + + return super.isBalanced(index); + } } export const trainerPartyTemplates = { - ONE_WEAK_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.WEAK), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), - ONE_AVG: new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), - ONE_AVG_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), - ONE_STRONG: new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), - ONE_STRONGER: new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER), - TWO_WEAKER: new TrainerPartyTemplate(2, PartyMemberStrength.WEAKER), - TWO_WEAK: new TrainerPartyTemplate(2, PartyMemberStrength.WEAK), - TWO_WEAK_ONE_AVG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.WEAK), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE)), - TWO_WEAK_SAME_ONE_AVG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.WEAK, true), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE)), - TWO_WEAK_SAME_TWO_WEAK_SAME: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.WEAK, true), new TrainerPartyTemplate(2, PartyMemberStrength.WEAK, true)), - TWO_WEAK_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.WEAK), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), - TWO_AVG: new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE), - TWO_AVG_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), - TWO_AVG_SAME_ONE_AVG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE)), - TWO_AVG_SAME_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), - TWO_AVG_SAME_TWO_AVG_SAME: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, true)), - TWO_STRONG: new TrainerPartyTemplate(2, PartyMemberStrength.STRONG), - THREE_WEAK: new TrainerPartyTemplate(3, PartyMemberStrength.WEAK), - THREE_WEAK_SAME: new TrainerPartyTemplate(3, PartyMemberStrength.WEAK, true), - THREE_AVG: new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE), - THREE_AVG_SAME: new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE, true), - THREE_WEAK_BALANCED: new TrainerPartyTemplate(3, PartyMemberStrength.WEAK, false, true), - FOUR_WEAKER: new TrainerPartyTemplate(4, PartyMemberStrength.WEAKER), - FOUR_WEAKER_SAME: new TrainerPartyTemplate(4, PartyMemberStrength.WEAKER, true), - FOUR_WEAK: new TrainerPartyTemplate(4, PartyMemberStrength.WEAK), - FOUR_WEAK_SAME: new TrainerPartyTemplate(4, PartyMemberStrength.WEAK, true), - FOUR_WEAK_BALANCED: new TrainerPartyTemplate(4, PartyMemberStrength.WEAK, false, true), - FIVE_WEAKER: new TrainerPartyTemplate(5, PartyMemberStrength.WEAKER), - FIVE_WEAK: new TrainerPartyTemplate(5, PartyMemberStrength.WEAK), - FIVE_WEAK_BALANCED: new TrainerPartyTemplate(5, PartyMemberStrength.WEAK, false, true), - SIX_WEAKER: new TrainerPartyTemplate(6, PartyMemberStrength.WEAKER), - SIX_WEAKER_SAME: new TrainerPartyTemplate(6, PartyMemberStrength.WEAKER, true), - SIX_WEAK_SAME: new TrainerPartyTemplate(6, PartyMemberStrength.WEAKER, true), - SIX_WEAK_BALANCED: new TrainerPartyTemplate(6, PartyMemberStrength.WEAK, false, true), + ONE_WEAK_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.WEAK), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), + ONE_AVG: new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), + ONE_AVG_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), + ONE_STRONG: new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), + ONE_STRONGER: new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER), + TWO_WEAKER: new TrainerPartyTemplate(2, PartyMemberStrength.WEAKER), + TWO_WEAK: new TrainerPartyTemplate(2, PartyMemberStrength.WEAK), + TWO_WEAK_ONE_AVG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.WEAK), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE)), + TWO_WEAK_SAME_ONE_AVG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.WEAK, true), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE)), + TWO_WEAK_SAME_TWO_WEAK_SAME: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.WEAK, true), new TrainerPartyTemplate(2, PartyMemberStrength.WEAK, true)), + TWO_WEAK_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.WEAK), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), + TWO_AVG: new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE), + TWO_AVG_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), + TWO_AVG_SAME_ONE_AVG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE)), + TWO_AVG_SAME_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), + TWO_AVG_SAME_TWO_AVG_SAME: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, true)), + TWO_STRONG: new TrainerPartyTemplate(2, PartyMemberStrength.STRONG), + THREE_WEAK: new TrainerPartyTemplate(3, PartyMemberStrength.WEAK), + THREE_WEAK_SAME: new TrainerPartyTemplate(3, PartyMemberStrength.WEAK, true), + THREE_AVG: new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE), + THREE_AVG_SAME: new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE, true), + THREE_WEAK_BALANCED: new TrainerPartyTemplate(3, PartyMemberStrength.WEAK, false, true), + FOUR_WEAKER: new TrainerPartyTemplate(4, PartyMemberStrength.WEAKER), + FOUR_WEAKER_SAME: new TrainerPartyTemplate(4, PartyMemberStrength.WEAKER, true), + FOUR_WEAK: new TrainerPartyTemplate(4, PartyMemberStrength.WEAK), + FOUR_WEAK_SAME: new TrainerPartyTemplate(4, PartyMemberStrength.WEAK, true), + FOUR_WEAK_BALANCED: new TrainerPartyTemplate(4, PartyMemberStrength.WEAK, false, true), + FIVE_WEAKER: new TrainerPartyTemplate(5, PartyMemberStrength.WEAKER), + FIVE_WEAK: new TrainerPartyTemplate(5, PartyMemberStrength.WEAK), + FIVE_WEAK_BALANCED: new TrainerPartyTemplate(5, PartyMemberStrength.WEAK, false, true), + SIX_WEAKER: new TrainerPartyTemplate(6, PartyMemberStrength.WEAKER), + SIX_WEAKER_SAME: new TrainerPartyTemplate(6, PartyMemberStrength.WEAKER, true), + SIX_WEAK_SAME: new TrainerPartyTemplate(6, PartyMemberStrength.WEAKER, true), + SIX_WEAK_BALANCED: new TrainerPartyTemplate(6, PartyMemberStrength.WEAK, false, true), - GYM_LEADER_1: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), - GYM_LEADER_2: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)), - GYM_LEADER_3: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)), - GYM_LEADER_4: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)), - GYM_LEADER_5: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)), + GYM_LEADER_1: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), + GYM_LEADER_2: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)), + GYM_LEADER_3: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)), + GYM_LEADER_4: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)), + GYM_LEADER_5: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)), - ELITE_FOUR: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)), + ELITE_FOUR: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)), - CHAMPION: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER), new TrainerPartyTemplate(5, PartyMemberStrength.STRONG, false, true)), + CHAMPION: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER), new TrainerPartyTemplate(5, PartyMemberStrength.STRONG, false, true)), - RIVAL: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE)), - RIVAL_2: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.WEAK, false, true)), - RIVAL_3: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.WEAK, false, true)), - RIVAL_4: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.WEAK, false, true)), - RIVAL_5: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), - RIVAL_6: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)) + RIVAL: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE)), + RIVAL_2: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.WEAK, false, true)), + RIVAL_3: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.WEAK, false, true)), + RIVAL_4: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.WEAK, false, true)), + RIVAL_5: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)), + RIVAL_6: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)) }; type PartyTemplateFunc = (scene: BattleScene) => TrainerPartyTemplate; @@ -163,368 +165,440 @@ type PartyMemberFunc = (scene: BattleScene, level: integer, strength: PartyMembe type GenModifiersFunc = (party: EnemyPokemon[]) => PersistentModifier[]; export interface PartyMemberFuncs { - [key: integer]: PartyMemberFunc + [key: integer]: PartyMemberFunc } export class TrainerConfig { - public trainerType: TrainerType; - public name: string; - public nameFemale: string; - public nameDouble: string; - public title: string; - public hasGenders: boolean = false; - public hasDouble: boolean = false; - public hasCharSprite: boolean = false; - public doubleOnly: boolean = false; - public moneyMultiplier: number = 1; - public isBoss: boolean = false; - public hasStaticParty: boolean = false; - public useSameSeedForAllMembers: boolean = false; - public battleBgm: string; - public encounterBgm: string; - public femaleEncounterBgm: string; - public doubleEncounterBgm: string; - public victoryBgm: string; - public genModifiersFunc: GenModifiersFunc; - public modifierRewardFuncs: ModifierTypeFunc[] = []; - public partyTemplates: TrainerPartyTemplate[]; - public partyTemplateFunc: PartyTemplateFunc; - public partyMemberFuncs: PartyMemberFuncs = {}; - public speciesPools: TrainerTierPools; - public speciesFilter: PokemonSpeciesFilter; - public specialtyTypes: Type[] = []; + public trainerType: TrainerType; + public name: string; + public nameFemale: string; + public nameDouble: string; + public title: string; + public hasGenders: boolean = false; + public hasDouble: boolean = false; + public hasCharSprite: boolean = false; + public doubleOnly: boolean = false; + public moneyMultiplier: number = 1; + public isBoss: boolean = false; + public hasStaticParty: boolean = false; + public useSameSeedForAllMembers: boolean = false; + public battleBgm: string; + public encounterBgm: string; + public femaleEncounterBgm: string; + public doubleEncounterBgm: string; + public victoryBgm: string; + public genModifiersFunc: GenModifiersFunc; + public modifierRewardFuncs: ModifierTypeFunc[] = []; + public partyTemplates: TrainerPartyTemplate[]; + public partyTemplateFunc: PartyTemplateFunc; + public partyMemberFuncs: PartyMemberFuncs = {}; + public speciesPools: TrainerTierPools; + public speciesFilter: PokemonSpeciesFilter; + public specialtyTypes: Type[] = []; - public encounterMessages: string[] = []; - public victoryMessages: string[] = []; - public defeatMessages: string[] = []; + public encounterMessages: string[] = []; + public victoryMessages: string[] = []; + public defeatMessages: string[] = []; - public femaleEncounterMessages: string[]; - public femaleVictoryMessages: string[]; - public femaleDefeatMessages: string[]; + public femaleEncounterMessages: string[]; + public femaleVictoryMessages: string[]; + public femaleDefeatMessages: string[]; - public doubleEncounterMessages: string[]; - public doubleVictoryMessages: string[]; - public doubleDefeatMessages: string[]; + public doubleEncounterMessages: string[]; + public doubleVictoryMessages: string[]; + public doubleDefeatMessages: string[]; - constructor(trainerType: TrainerType, allowLegendaries?: boolean) { - this.trainerType = trainerType; - this.name = Utils.toReadableString(TrainerType[this.getDerivedType()]); - this.battleBgm = 'battle_trainer'; - this.victoryBgm = 'victory_trainer'; - this.partyTemplates = [ trainerPartyTemplates.TWO_AVG ]; - this.speciesFilter = species => (allowLegendaries || (!species.legendary && !species.subLegendary && !species.mythical)) && !species.isTrainerForbidden(); - } - - getKey(): string { - return TrainerType[this.getDerivedType()].toString().toLowerCase(); - } - - getSpriteKey(female?: boolean): string { - let ret = this.getKey(); - if (this.hasGenders) - ret += `_${female ? 'f' : 'm'}`; - return ret; - } - - setName(name: string): TrainerConfig { - this.name = name; - return this; - } - - setTitle(title: string): TrainerConfig { - this.title = title; - return this; - } - - getDerivedType(): TrainerType { - let trainerType = this.trainerType; - switch (trainerType) { - case TrainerType.RIVAL_2: - case TrainerType.RIVAL_3: - case TrainerType.RIVAL_4: - case TrainerType.RIVAL_5: - case TrainerType.RIVAL_6: - trainerType = TrainerType.RIVAL; - break; - case TrainerType.LANCE_CHAMPION: - trainerType = TrainerType.LANCE; - break; - case TrainerType.LARRY_ELITE: - trainerType = TrainerType.LARRY; - break; + constructor(trainerType: TrainerType, allowLegendaries?: boolean) { + this.trainerType = trainerType; + this.name = Utils.toReadableString(TrainerType[this.getDerivedType()]); + this.battleBgm = 'battle_trainer'; + this.victoryBgm = 'victory_trainer'; + this.partyTemplates = [trainerPartyTemplates.TWO_AVG]; + this.speciesFilter = species => (allowLegendaries || (!species.legendary && !species.subLegendary && !species.mythical)) && !species.isTrainerForbidden(); } - return trainerType; - } - - setHasGenders(nameFemale?: string, femaleEncounterBgm?: TrainerType | string): TrainerConfig { - this.hasGenders = true; - this.nameFemale = nameFemale; - if (femaleEncounterBgm) - this.femaleEncounterBgm = typeof femaleEncounterBgm === 'number' ? TrainerType[femaleEncounterBgm].toString().replace(/\_/g, ' ').toLowerCase() : femaleEncounterBgm; - return this; - } - - setHasDouble(nameDouble: string, doubleEncounterBgm?: TrainerType | string): TrainerConfig { - this.hasDouble = true; - this.nameDouble = nameDouble; - if (doubleEncounterBgm) - this.doubleEncounterBgm = typeof doubleEncounterBgm === 'number' ? TrainerType[doubleEncounterBgm].toString().replace(/\_/g, ' ').toLowerCase() : doubleEncounterBgm; - return this; - } - - setHasCharSprite(): TrainerConfig { - this.hasCharSprite = true; - return this; - } - - setDoubleOnly(): TrainerConfig { - this.doubleOnly = true; - return this; - } - - setMoneyMultiplier(moneyMultiplier: number): TrainerConfig { - this.moneyMultiplier = moneyMultiplier; - return this; - } - - setBoss(): TrainerConfig { - this.isBoss = true; - return this; - } - - setStaticParty(): TrainerConfig { - this.hasStaticParty = true; - return this; - } - - setUseSameSeedForAllMembers(): TrainerConfig { - this.useSameSeedForAllMembers = true; - return this; - } - - setBattleBgm(battleBgm: string): TrainerConfig { - this.battleBgm = battleBgm; - return this; - } - - setEncounterBgm(encounterBgm: TrainerType | string): TrainerConfig { - this.encounterBgm = typeof encounterBgm === 'number' ? TrainerType[encounterBgm].toString().toLowerCase() : encounterBgm; - return this; - } - - setVictoryBgm(victoryBgm: string): TrainerConfig { - this.victoryBgm = victoryBgm; - return this; - } - - setPartyTemplates(...partyTemplates: TrainerPartyTemplate[]): TrainerConfig { - this.partyTemplates = partyTemplates; - return this; - } - - setPartyTemplateFunc(partyTemplateFunc: PartyTemplateFunc): TrainerConfig { - this.partyTemplateFunc = partyTemplateFunc; - return this; - } - - setPartyMemberFunc(slotIndex: integer, partyMemberFunc: PartyMemberFunc): TrainerConfig { - this.partyMemberFuncs[slotIndex] = partyMemberFunc; - return this; - } - - setSpeciesPools(speciesPools: TrainerTierPools | Species[]): TrainerConfig { - this.speciesPools = (Array.isArray(speciesPools) ? { [TrainerPoolTier.COMMON]: speciesPools } : speciesPools) as unknown as TrainerTierPools; - return this; - } - - setSpeciesFilter(speciesFilter: PokemonSpeciesFilter, allowLegendaries?: boolean): TrainerConfig { - const baseFilter = this.speciesFilter; - this.speciesFilter = allowLegendaries ? speciesFilter : species => speciesFilter(species) && baseFilter(species); - return this; - } - - setSpecialtyTypes(...specialtyTypes: Type[]): TrainerConfig { - this.specialtyTypes = specialtyTypes; - return this; - } - - setGenModifiersFunc(genModifiersFunc: GenModifiersFunc): TrainerConfig { - this.genModifiersFunc = genModifiersFunc; - return this; - } - - setModifierRewardFuncs(...modifierTypeFuncs: (() => ModifierTypeFunc)[]): TrainerConfig { - this.modifierRewardFuncs = modifierTypeFuncs.map(func => () => { - const modifierTypeFunc = func(); - const modifierType = modifierTypeFunc(); - modifierType.withIdFromFunc(modifierTypeFunc); - return modifierType; - }); - return this; - } - - initForGymLeader(signatureSpecies: (Species | Species[])[], ...specialtyTypes: Type[]): TrainerConfig { - this.setPartyTemplateFunc(getGymLeaderPartyTemplate); - signatureSpecies.forEach((speciesPool, s) => { - if (!Array.isArray(speciesPool)) - speciesPool = [ speciesPool ]; - this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); - }); - if (specialtyTypes.length) { - this.setSpeciesFilter(p => specialtyTypes.find(t => p.isOfType(t)) !== undefined); - this.setSpecialtyTypes(...specialtyTypes); - } - this.setTitle('Gym Leader'); - this.setMoneyMultiplier(2.5); - this.setBoss(); - this.setStaticParty(); - this.setBattleBgm('battle_unova_gym'); - this.setVictoryBgm('victory_gym'); - this.setGenModifiersFunc(party => { - const waveIndex = party[0].scene.currentBattle.waveIndex; - return getRandomTeraModifiers(party, waveIndex >= 100 ? 1 : 0, specialtyTypes.length ? specialtyTypes : null); - }); - return this; - } - - initForEliteFour(signatureSpecies: (Species | Species[])[], ...specialtyTypes: Type[]): TrainerConfig { - this.setPartyTemplates(trainerPartyTemplates.ELITE_FOUR); - signatureSpecies.forEach((speciesPool, s) => { - if (!Array.isArray(speciesPool)) - speciesPool = [ speciesPool ]; - this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); - }); - if (specialtyTypes.length) { - this.setSpeciesFilter(p => specialtyTypes.find(t => p.isOfType(t)) && p.baseTotal >= 450); - this.setSpecialtyTypes(...specialtyTypes); - } else - this.setSpeciesFilter(p => p.baseTotal >= 450); - this.setTitle('Elite Four'); - this.setMoneyMultiplier(3.25); - this.setBoss(); - this.setStaticParty(); - this.setBattleBgm('battle_elite'); - this.setVictoryBgm('victory_gym'); - this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 2, specialtyTypes.length ? specialtyTypes : null)); - return this; - } - - initForChampion(signatureSpecies: (Species | Species[])[]): TrainerConfig { - this.setPartyTemplates(trainerPartyTemplates.CHAMPION); - signatureSpecies.forEach((speciesPool, s) => { - if (!Array.isArray(speciesPool)) - speciesPool = [ speciesPool ]; - this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); - }); - this.setSpeciesFilter(p => p.baseTotal >= 470); - this.setTitle('Champion'); - this.setMoneyMultiplier(10); - this.setBoss(); - this.setStaticParty(); - this.setBattleBgm('battle_champion_alder'); - this.setVictoryBgm('victory_champion'); - this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 3)); - return this; - } - - getTitle(trainerSlot: TrainerSlot = TrainerSlot.NONE, variant: TrainerVariant): string { - let ret = this.name; - - if (!trainerSlot && variant === TrainerVariant.DOUBLE && this.nameDouble) - return this.nameDouble; - - if (this.hasGenders) { - if (this.nameFemale) { - if (variant === TrainerVariant.FEMALE || (variant === TrainerVariant.DOUBLE && trainerSlot === TrainerSlot.TRAINER_PARTNER)) - return this.nameFemale; - } else - ret += !variant ? '♂' : '♀'; + getKey(): string { + return TrainerType[this.getDerivedType()].toString().toLowerCase(); } - return ret; - } + getSpriteKey(female?: boolean): string { + let ret = this.getKey(); + if (this.hasGenders) + ret += `_${female ? 'f' : 'm'}`; + return ret; + } + + setName(name: string): TrainerConfig { + if (name === 'Finn') { + // Give the rival a localized name + // First check if i18n is initialized + if (!getIsInitialized()) { + initI18n(); + } + if (name === 'Finn') { + name = i18next.t('trainerNames:rival'); + } + - loadAssets(scene: BattleScene, variant: TrainerVariant): Promise { - return new Promise(resolve => { - const isDouble = variant === TrainerVariant.DOUBLE; - const trainerKey = this.getSpriteKey(variant === TrainerVariant.FEMALE); - const partnerTrainerKey = this.getSpriteKey(true); - scene.loadAtlas(trainerKey, 'trainer'); - if (isDouble) - scene.loadAtlas(partnerTrainerKey, 'trainer'); - scene.load.once(Phaser.Loader.Events.COMPLETE, () => { - const originalWarn = console.warn; - // Ignore warnings for missing frames, because there will be a lot - console.warn = () => {}; - const frameNames = scene.anims.generateFrameNames(trainerKey, { zeroPad: 4, suffix: ".png", start: 1, end: 128 }); - const partnerFrameNames = isDouble - ? scene.anims.generateFrameNames(partnerTrainerKey, { zeroPad: 4, suffix: ".png", start: 1, end: 128 }) - : null; - console.warn = originalWarn; - scene.anims.create({ - key: trainerKey, - frames: frameNames, - frameRate: 24, - repeat: -1 - }); - if (isDouble) { - scene.anims.create({ - key: partnerTrainerKey, - frames: partnerFrameNames, - frameRate: 24, - repeat: -1 - }); } - resolve(); - }); - if (!scene.load.isLoading()) - scene.load.start(); - }); - } + this.name = name; + return this; + } + + setTitle(title: string): TrainerConfig { + // First check if i18n is initialized + if (!getIsInitialized()) { + initI18n(); + } + + // Make the title lowercase and replace spaces with underscores + title = title.toLowerCase().replace(/\s/g, '_'); + + this.title = i18next.t(`titles:${title}`); + + + return this; + } + + getDerivedType(): TrainerType { + let trainerType = this.trainerType; + switch (trainerType) { + case TrainerType.RIVAL_2: + case TrainerType.RIVAL_3: + case TrainerType.RIVAL_4: + case TrainerType.RIVAL_5: + case TrainerType.RIVAL_6: + trainerType = TrainerType.RIVAL; + break; + case TrainerType.LANCE_CHAMPION: + trainerType = TrainerType.LANCE; + break; + case TrainerType.LARRY_ELITE: + trainerType = TrainerType.LARRY; + break; + } + + return trainerType; + } + + setHasGenders(nameFemale?: string, femaleEncounterBgm?: TrainerType | string): TrainerConfig { + if (nameFemale === 'Ivy') { + // Give the rival a localized name + // First check if i18n is initialized + if (!getIsInitialized()) { + initI18n(); + } + this.nameFemale = i18next.t('trainerNames:rival_female'); + } else { + this.nameFemale = nameFemale; + } + + this.hasGenders = true; + if (femaleEncounterBgm) + this.femaleEncounterBgm = typeof femaleEncounterBgm === 'number' ? TrainerType[femaleEncounterBgm].toString().replace(/\_/g, ' ').toLowerCase() : femaleEncounterBgm; + return this; + } + + setHasDouble(nameDouble: string, doubleEncounterBgm?: TrainerType | string): TrainerConfig { + this.hasDouble = true; + this.nameDouble = nameDouble; + if (doubleEncounterBgm) + this.doubleEncounterBgm = typeof doubleEncounterBgm === 'number' ? TrainerType[doubleEncounterBgm].toString().replace(/\_/g, ' ').toLowerCase() : doubleEncounterBgm; + return this; + } + + setHasCharSprite(): TrainerConfig { + this.hasCharSprite = true; + return this; + } + + setDoubleOnly(): TrainerConfig { + this.doubleOnly = true; + return this; + } + + setMoneyMultiplier(moneyMultiplier: number): TrainerConfig { + this.moneyMultiplier = moneyMultiplier; + return this; + } + + setBoss(): TrainerConfig { + this.isBoss = true; + return this; + } + + setStaticParty(): TrainerConfig { + this.hasStaticParty = true; + return this; + } + + setUseSameSeedForAllMembers(): TrainerConfig { + this.useSameSeedForAllMembers = true; + return this; + } + + setBattleBgm(battleBgm: string): TrainerConfig { + this.battleBgm = battleBgm; + return this; + } + + setEncounterBgm(encounterBgm: TrainerType | string): TrainerConfig { + this.encounterBgm = typeof encounterBgm === 'number' ? TrainerType[encounterBgm].toString().toLowerCase() : encounterBgm; + return this; + } + + setVictoryBgm(victoryBgm: string): TrainerConfig { + this.victoryBgm = victoryBgm; + return this; + } + + setPartyTemplates(...partyTemplates: TrainerPartyTemplate[]): TrainerConfig { + this.partyTemplates = partyTemplates; + return this; + } + + setPartyTemplateFunc(partyTemplateFunc: PartyTemplateFunc): TrainerConfig { + this.partyTemplateFunc = partyTemplateFunc; + return this; + } + + setPartyMemberFunc(slotIndex: integer, partyMemberFunc: PartyMemberFunc): TrainerConfig { + this.partyMemberFuncs[slotIndex] = partyMemberFunc; + return this; + } + + setSpeciesPools(speciesPools: TrainerTierPools | Species[]): TrainerConfig { + this.speciesPools = (Array.isArray(speciesPools) ? {[TrainerPoolTier.COMMON]: speciesPools} : speciesPools) as unknown as TrainerTierPools; + return this; + } + + setSpeciesFilter(speciesFilter: PokemonSpeciesFilter, allowLegendaries?: boolean): TrainerConfig { + const baseFilter = this.speciesFilter; + this.speciesFilter = allowLegendaries ? speciesFilter : species => speciesFilter(species) && baseFilter(species); + return this; + } + + setSpecialtyTypes(...specialtyTypes: Type[]): TrainerConfig { + this.specialtyTypes = specialtyTypes; + return this; + } + + setGenModifiersFunc(genModifiersFunc: GenModifiersFunc): TrainerConfig { + this.genModifiersFunc = genModifiersFunc; + return this; + } + + setModifierRewardFuncs(...modifierTypeFuncs: (() => ModifierTypeFunc)[]): TrainerConfig { + this.modifierRewardFuncs = modifierTypeFuncs.map(func => () => { + const modifierTypeFunc = func(); + const modifierType = modifierTypeFunc(); + modifierType.withIdFromFunc(modifierTypeFunc); + return modifierType; + }); + return this; + } + + initForGymLeader(signatureSpecies: (Species | Species[])[], ...specialtyTypes: Type[]): TrainerConfig { + if (!getIsInitialized()) { + initI18n(); + } + + this.setPartyTemplateFunc(getGymLeaderPartyTemplate); + signatureSpecies.forEach((speciesPool, s) => { + if (!Array.isArray(speciesPool)) + speciesPool = [speciesPool]; + this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); + }); + if (specialtyTypes.length) { + this.setSpeciesFilter(p => specialtyTypes.find(t => p.isOfType(t)) !== undefined); + this.setSpecialtyTypes(...specialtyTypes); + } + + // Handle name by checking this.name - making it lowercase and replacing spaces with underscores and then calling i18next.t with the name + const nameForCall = this.name.toLowerCase().replace(/\s/g, '_'); + this.name = i18next.t(`trainerNames:${nameForCall}`); + + + + this.setTitle("gym_leader"); + this.setMoneyMultiplier(2.5); + this.setBoss(); + this.setStaticParty(); + this.setBattleBgm('battle_unova_gym'); + this.setVictoryBgm('victory_gym'); + this.setGenModifiersFunc(party => { + const waveIndex = party[0].scene.currentBattle.waveIndex; + return getRandomTeraModifiers(party, waveIndex >= 100 ? 1 : 0, specialtyTypes.length ? specialtyTypes : null); + }); + return this; + } + + initForEliteFour(signatureSpecies: (Species | Species[])[], ...specialtyTypes: Type[]): TrainerConfig { + if (!getIsInitialized()) { + initI18n(); + } + + this.setPartyTemplates(trainerPartyTemplates.ELITE_FOUR); + signatureSpecies.forEach((speciesPool, s) => { + if (!Array.isArray(speciesPool)) + speciesPool = [speciesPool]; + this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); + }); + if (specialtyTypes.length) { + this.setSpeciesFilter(p => specialtyTypes.find(t => p.isOfType(t)) && p.baseTotal >= 450); + this.setSpecialtyTypes(...specialtyTypes); + } else + this.setSpeciesFilter(p => p.baseTotal >= 450); + // Handle name by checking this.name - making it lowercase and replacing spaces with underscores and then calling i18next.t with the name + const nameForCall = this.name.toLowerCase().replace(/\s/g, '_'); + this.name = i18next.t(`trainerNames:${nameForCall}`); + + this.setTitle("elite_four"); + this.setMoneyMultiplier(3.25); + this.setBoss(); + this.setStaticParty(); + this.setBattleBgm('battle_elite'); + this.setVictoryBgm('victory_gym'); + this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 2, specialtyTypes.length ? specialtyTypes : null)); + return this; + } + + initForChampion(signatureSpecies: (Species | Species[])[]): TrainerConfig { + if (!getIsInitialized()) { + initI18n(); + } + this.setPartyTemplates(trainerPartyTemplates.CHAMPION); + signatureSpecies.forEach((speciesPool, s) => { + if (!Array.isArray(speciesPool)) + speciesPool = [speciesPool]; + this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); + }); + this.setSpeciesFilter(p => p.baseTotal >= 470); + // Handle name by checking this.name - making it lowercase and replacing spaces with underscores and then calling i18next.t with the name + const nameForCall = this.name.toLowerCase().replace(/\s/g, '_'); + this.name = i18next.t(`trainerNames:${nameForCall}`); + this.setTitle("champion"); + this.setMoneyMultiplier(10); + this.setBoss(); + this.setStaticParty(); + this.setBattleBgm('battle_champion_alder'); + this.setVictoryBgm('victory_champion'); + this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 3)); + return this; + } + + getTitle(trainerSlot: TrainerSlot = TrainerSlot.NONE, variant: TrainerVariant): string { + let ret = this.name; + + if (!trainerSlot && variant === TrainerVariant.DOUBLE && this.nameDouble) + return this.nameDouble; + + if (this.hasGenders) { + if (this.nameFemale) { + if (variant === TrainerVariant.FEMALE || (variant === TrainerVariant.DOUBLE && trainerSlot === TrainerSlot.TRAINER_PARTNER)) + return this.nameFemale; + } else + + // Check if !variant is true, if so return the name, else return the name with _female appended + if (variant) { + if (!getIsInitialized()) { + initI18n(); + } + // Check if the female version exists in the i18n file + if (i18next.exists(`trainerClasses:${this.name.toLowerCase().replace}`)) { + // If it does, return + return ret + "_female"; + } else { + // If it doesn't, we do not do anything and go to the normal return + // This is to prevent the game from displaying an error if a female version of the trainer does not exist in the localization + } + } + } + + return ret; + } + + loadAssets(scene: BattleScene, variant: TrainerVariant): Promise { + return new Promise(resolve => { + const isDouble = variant === TrainerVariant.DOUBLE; + const trainerKey = this.getSpriteKey(variant === TrainerVariant.FEMALE); + const partnerTrainerKey = this.getSpriteKey(true); + scene.loadAtlas(trainerKey, 'trainer'); + if (isDouble) + scene.loadAtlas(partnerTrainerKey, 'trainer'); + scene.load.once(Phaser.Loader.Events.COMPLETE, () => { + const originalWarn = console.warn; + // Ignore warnings for missing frames, because there will be a lot + console.warn = () => { + }; + const frameNames = scene.anims.generateFrameNames(trainerKey, {zeroPad: 4,suffix: ".png",start: 1,end: 128}); + const partnerFrameNames = isDouble + ? scene.anims.generateFrameNames(partnerTrainerKey, {zeroPad: 4,suffix: ".png",start: 1,end: 128}) + : null; + console.warn = originalWarn; + scene.anims.create({ + key: trainerKey, + frames: frameNames, + frameRate: 24, + repeat: -1 + }); + if (isDouble) { + scene.anims.create({ + key: partnerTrainerKey, + frames: partnerFrameNames, + frameRate: 24, + repeat: -1 + }); + } + resolve(); + }); + if (!scene.load.isLoading()) + scene.load.start(); + }); + } } let t = 0; interface TrainerConfigs { - [key: integer]: TrainerConfig + [key: integer]: TrainerConfig } function getWavePartyTemplate(scene: BattleScene, ...templates: TrainerPartyTemplate[]) { - return templates[Math.min(Math.max(Math.ceil((scene.gameMode.getWaveForDifficulty(scene.currentBattle?.waveIndex || startingWave, true) - 20) / 30), 0), templates.length - 1)]; + return templates[Math.min(Math.max(Math.ceil((scene.gameMode.getWaveForDifficulty(scene.currentBattle?.waveIndex || startingWave, true) - 20) / 30), 0), templates.length - 1)]; } function getGymLeaderPartyTemplate(scene: BattleScene) { - return getWavePartyTemplate(scene, trainerPartyTemplates.GYM_LEADER_1, trainerPartyTemplates.GYM_LEADER_2, trainerPartyTemplates.GYM_LEADER_3, trainerPartyTemplates.GYM_LEADER_4, trainerPartyTemplates.GYM_LEADER_5); + return getWavePartyTemplate(scene, trainerPartyTemplates.GYM_LEADER_1, trainerPartyTemplates.GYM_LEADER_2, trainerPartyTemplates.GYM_LEADER_3, trainerPartyTemplates.GYM_LEADER_4, trainerPartyTemplates.GYM_LEADER_5); } function getRandomPartyMemberFunc(speciesPool: Species[], trainerSlot: TrainerSlot = TrainerSlot.TRAINER, ignoreEvolution: boolean = false, postProcess?: (enemyPokemon: EnemyPokemon) => void): PartyMemberFunc { - return (scene: BattleScene, level: integer, strength: PartyMemberStrength) => { - let species = Utils.randSeedItem(speciesPool); - if (!ignoreEvolution) - species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength); - return scene.addEnemyPokemon(getPokemonSpecies(species), level, trainerSlot, undefined, undefined, postProcess); - }; + return (scene: BattleScene, level: integer, strength: PartyMemberStrength) => { + let species = Utils.randSeedItem(speciesPool); + if (!ignoreEvolution) + species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength); + return scene.addEnemyPokemon(getPokemonSpecies(species), level, trainerSlot, undefined, undefined, postProcess); + }; } function getSpeciesFilterRandomPartyMemberFunc(speciesFilter: PokemonSpeciesFilter, trainerSlot: TrainerSlot = TrainerSlot.TRAINER, allowLegendaries?: boolean, postProcess?: (EnemyPokemon: EnemyPokemon) => void): PartyMemberFunc { - const originalSpeciesFilter = speciesFilter; - speciesFilter = (species: PokemonSpecies) => (allowLegendaries || (!species.legendary && !species.subLegendary && !species.mythical)) && !species.isTrainerForbidden() && originalSpeciesFilter(species); - return (scene: BattleScene, level: integer, strength: PartyMemberStrength) => { - const ret = scene.addEnemyPokemon(getPokemonSpecies(scene.randomSpecies(scene.currentBattle.waveIndex, level, false, speciesFilter).getTrainerSpeciesForLevel(level, true, strength)), level, trainerSlot, undefined, undefined, postProcess); - return ret; - }; + const originalSpeciesFilter = speciesFilter; + speciesFilter = (species: PokemonSpecies) => (allowLegendaries || (!species.legendary && !species.subLegendary && !species.mythical)) && !species.isTrainerForbidden() && originalSpeciesFilter(species); + return (scene: BattleScene, level: integer, strength: PartyMemberStrength) => { + const ret = scene.addEnemyPokemon(getPokemonSpecies(scene.randomSpecies(scene.currentBattle.waveIndex, level, false, speciesFilter).getTrainerSpeciesForLevel(level, true, strength)), level, trainerSlot, undefined, undefined, postProcess); + return ret; + }; } function getRandomTeraModifiers(party: EnemyPokemon[], count: integer, types?: Type[]): PersistentModifier[] { - const ret: PersistentModifier[] = []; - const partyMemberIndexes = new Array(party.length).fill(null).map((_, i) => i); - for (let t = 0; t < Math.min(count, party.length); t++) { - const randomIndex = Utils.randSeedItem(partyMemberIndexes); - partyMemberIndexes.splice(partyMemberIndexes.indexOf(randomIndex), 1); - ret.push(modifierTypes.TERA_SHARD().generateType(null, [ Utils.randSeedItem(types ? types : party[randomIndex].getTypes()) ]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(party[randomIndex]) as PersistentModifier); - } - return ret; + const ret: PersistentModifier[] = []; + const partyMemberIndexes = new Array(party.length).fill(null).map((_, i) => i); + for (let t = 0; t < Math.min(count, party.length); t++) { + const randomIndex = Utils.randSeedItem(partyMemberIndexes); + partyMemberIndexes.splice(partyMemberIndexes.indexOf(randomIndex), 1); + ret.push(modifierTypes.TERA_SHARD().generateType(null, [Utils.randSeedItem(types ? types : party[randomIndex].getTypes())]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(party[randomIndex]) as PersistentModifier); + } + return ret; } export const trainerConfigs: TrainerConfigs = { @@ -662,7 +736,7 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.SMASHER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), [TrainerType.SNOW_WORKER]: new TrainerConfig(++t).setName('Worker').setHasGenders().setHasDouble('Workers').setMoneyMultiplier(1.7).setEncounterBgm(TrainerType.CLERK).setSpeciesFilter(s => s.isOfType(Type.ICE) || s.isOfType(Type.STEEL)), [TrainerType.STRIKER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), - [TrainerType.STUDENT]: new TrainerConfig(++t).setMoneyMultiplier(0.75).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders(undefined, 'lass').setHasDouble('Students') + [TrainerType.SCHOOL_KID]: new TrainerConfig(++t).setMoneyMultiplier(0.75).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders(undefined, 'lass').setHasDouble('School Kids') .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.ODDISH, Species.EXEGGCUTE, Species.TEDDIURSA, Species.WURMPLE, Species.RALTS, Species.SHROOMISH, Species.FLETCHLING ], [TrainerPoolTier.UNCOMMON]: [ Species.VOLTORB, Species.WHISMUR, Species.MEDITITE, Species.MIME_JR, Species.NYMBLE ], @@ -855,14 +929,20 @@ export const trainerConfigs: TrainerConfigs = { }), [TrainerType.RIVAL_6]: new TrainerConfig(++t).setName('Finn').setHasGenders('Ivy').setHasCharSprite().setTitle('Rival').setBoss().setStaticParty().setMoneyMultiplier(3).setEncounterBgm('final').setBattleBgm('battle_rival_3').setPartyTemplates(trainerPartyTemplates.RIVAL_6) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ], TrainerSlot.TRAINER, true, - p => p.setBoss(true, 3)) - ) + p => { + p.setBoss(true, 3); + p.generateAndPopulateMoveset(); + })) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ], TrainerSlot.TRAINER, true, - p => p.setBoss(true, 2))) + p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + })) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setSpeciesFilter(species => species.baseTotal >= 540) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.RAYQUAZA ], TrainerSlot.TRAINER, true, p => { p.setBoss(); + p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; p.shiny = true; p.variant = 1; @@ -874,6 +954,6 @@ export const trainerConfigs: TrainerConfigs = { }), }; -(function() { - initTrainerTypeDialogue(); -})(); \ No newline at end of file +(function () { + initTrainerTypeDialogue(); +})(); diff --git a/src/data/trainer-names.ts b/src/data/trainer-names.ts index 348976eae92..2b95a91314e 100644 --- a/src/data/trainer-names.ts +++ b/src/data/trainer-names.ts @@ -61,7 +61,7 @@ const trainerNameConfigs: TrainerNameConfigs = { [TrainerType.SMASHER]: new TrainerNameConfig(TrainerType.SMASHER), [TrainerType.SNOW_WORKER]: new TrainerNameConfig(TrainerType.SNOW_WORKER, 'Worker'), [TrainerType.STRIKER]: new TrainerNameConfig(TrainerType.STRIKER), - [TrainerType.STUDENT]: new TrainerNameConfig(TrainerType.STUDENT, 'School_Kid'), + [TrainerType.SCHOOL_KID]: new TrainerNameConfig(TrainerType.SCHOOL_KID, 'School_Kid'), [TrainerType.SWIMMER]: new TrainerNameConfig(TrainerType.SWIMMER), [TrainerType.TWINS]: new TrainerNameConfig(TrainerType.TWINS), [TrainerType.VETERAN]: new TrainerNameConfig(TrainerType.VETERAN), @@ -111,7 +111,7 @@ export const trainerNamePools = { [TrainerType.SMASHER]: ["Aspen","Elena","Mari","Amy","Lizzy"], [TrainerType.SNOW_WORKER]: [["Braden","Brendon","Colin","Conrad","Dillan","Gary","Gerardo","Holden","Jackson","Mason","Quentin","Willy","Noel","Arnold","Brady","Brand","Cairn","Cliff","Don","Eddie","Felix","Filipe","Glenn","Gus","Heath","Matthew","Patton","Rich","Rob","Ryan","Scott","Shelby","Sterling","Tyler","Victor","Zack","Friedrich","Herman","Isaac","Leo","Maynard","Mitchell","Morgann","Nathan","Niel","Pasqual","Paul","Tavarius","Tibor","Dimitri","Narek","Yusif","Frank","Jeff","Vaclav","Ovid","Francis","Keith","Russel","Sangon","Toway","Bomber","Chean","Demit","Hubor","Kebile","Laber","Ordo","Retay","Ronix","Wagel","Dobit","Kaster","Lobel","Releo","Saken","Rustix"],["Georgia","Sandra","Yvonne"]], [TrainerType.STRIKER]: ["Marco","Roberto","Tony"], - [TrainerType.STUDENT]: [["Alan","Billy","Chad","Danny","Dudley","Jack","Joe","Johnny","Kipp","Nate","Ricky","Tommy","Jerry","Paul","Ted","Chance","Esteban","Forrest","Harrison","Connor","Sherman","Torin","Travis","Al","Carter","Edgar","Jem","Sammy","Shane","Shayne","Alvin","Keston","Neil","Seymour","William","Carson","Clark","Nolan"],["Georgia","Karen","Meiko","Christine","Mackenzie","Tiera","Ann","Gina","Lydia","Marsha","Millie","Sally","Serena","Silvia","Alberta","Cassie","Mara","Rita","Georgie","Meena","Nitzel"]], + [TrainerType.SCHOOL_KID]: [["Alan","Billy","Chad","Danny","Dudley","Jack","Joe","Johnny","Kipp","Nate","Ricky","Tommy","Jerry","Paul","Ted","Chance","Esteban","Forrest","Harrison","Connor","Sherman","Torin","Travis","Al","Carter","Edgar","Jem","Sammy","Shane","Shayne","Alvin","Keston","Neil","Seymour","William","Carson","Clark","Nolan"],["Georgia","Karen","Meiko","Christine","Mackenzie","Tiera","Ann","Gina","Lydia","Marsha","Millie","Sally","Serena","Silvia","Alberta","Cassie","Mara","Rita","Georgie","Meena","Nitzel"]], [TrainerType.SWIMMER]: [["Berke","Cameron","Charlie","George","Harold","Jerome","Kirk","Mathew","Parker","Randall","Seth","Simon","Tucker","Austin","Barry","Chad","Cody","Darrin","David","Dean","Douglas","Franklin","Gilbert","Herman","Jack","Luis","Matthew","Reed","Richard","Rodney","Roland","Spencer","Stan","Tony","Clarence","Declan","Dominik","Harrison","Kevin","Leonardo","Nolen","Pete","Santiago","Axle","Braden","Finn","Garrett","Mymo","Reece","Samir","Toby","Adrian","Colton","Dillon","Erik","Evan","Francisco","Glenn","Kurt","Oscar","Ricardo","Sam","Sheltin","Troy","Vincent","Wade","Wesley","Duane","Elmo","Esteban","Frankie","Ronald","Tyson","Bart","Matt","Tim","Wright","Jeffery","Kyle","Alessandro","Estaban","Kieran","Ramses","Casey","Dakota","Jared","Kalani","Keoni","Lawrence","Logan","Robert","Roddy","Yasu","Derek","Jacob","Bruce","Clayton"],["Briana","Dawn","Denise","Diana","Elaine","Kara","Kaylee","Lori","Nicole","Nikki","Paula","Susie","Wendy","Alice","Beth","Beverly","Brenda","Dana","Debra","Grace","Jenny","Katie","Laurel","Linda","Missy","Sharon","Tanya","Tara","Tisha","Carlee","Imani","Isabelle","Kyla","Sienna","Abigail","Amara","Anya","Connie","Maria","Melissa","Nora","Shirley","Shania","Tiffany","Aubree","Cassandra","Claire","Crystal","Erica","Gabrielle","Haley","Jessica","Joanna","Lydia","Mallory","Mary","Miranda","Paige","Sophia","Vanessa","Chelan","Debbie","Joy","Kendra","Leona","Mina","Caroline","Joyce","Larissa","Rebecca","Tyra","Dara","Desiree","Kaoru","Ruth","Coral","Genevieve","Isla","Marissa","Romy","Sheryl","Alexandria","Alicia","Chelsea","Jade","Kelsie","Laura","Portia","Shelby","Sara","Tiare","Kyra","Natasha","Layla","Scarlett","Cora"]], [TrainerType.TWINS]: ["Amy & May","Jo & Zoe","Meg & Peg","Ann & Anne","Lea & Pia","Amy & Liv","Gina & Mia","Miu & Yuki","Tori & Tia","Eli & Anne","Jen & Kira","Joy & Meg","Kiri & Jan","Miu & Mia","Emma & Lil","Liv & Liz","Teri & Tia","Amy & Mimi","Clea & Gil","Day & Dani","Kay & Tia","Tori & Til","Saya & Aya","Emy & Lin","Kumi & Amy","Mayo & May","Ally & Amy","Lia & Lily","Rae & Ula","Sola & Ana","Tara & Val","Faith & Joy","Nana & Nina"], [TrainerType.VETERAN]: [["Armando","Brenden","Brian","Clayton","Edgar","Emanuel","Grant","Harlan","Terrell","Arlen","Chester","Hugo","Martell","Ray","Shaun","Abraham","Carter","Claude","Jerry","Lucius","Murphy","Rayne","Ron","Sinan","Sterling","Vincent","Zach","Gerard","Gilles","Louis","Timeo","Akira","Don","Eric","Harry","Leon","Roger","Angus","Aristo","Brone","Johnny"],["Julia","Karla","Kim","Sayuri","Tiffany","Cathy","Cecile","Chloris","Denae","Gina","Maya","Oriana","Portia","Rhona","Rosaline","Catrina","Inga","Trisha","Heather","Lynn","Sheri","Alonsa","Ella","Leticia","Kiara"]], diff --git a/src/data/weather.ts b/src/data/weather.ts index 1409920a1bc..c8bd47fc12d 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -1,5 +1,5 @@ import { Biome } from "./enums/biome"; -import { getPokemonMessage } from "../messages"; +import { getPokemonMessage, getPokemonPrefix } from "../messages"; import Pokemon from "../field/pokemon"; import { Type } from "./type"; import Move, { AttackMove } from "./move"; @@ -7,6 +7,7 @@ import * as Utils from "../utils"; import BattleScene from "../battle-scene"; import { SuppressWeatherEffectAbAttr } from "./ability"; import { TerrainType } from "./terrain"; +import i18next from "i18next"; export enum WeatherType { NONE, @@ -121,23 +122,23 @@ export class Weather { export function getWeatherStartMessage(weatherType: WeatherType): string { switch (weatherType) { case WeatherType.SUNNY: - return 'The sunlight got bright!'; + return i18next.t('weather:sunnyStartMessage'); case WeatherType.RAIN: - return 'A downpour started!'; + return i18next.t('weather:rainStartMessage'); case WeatherType.SANDSTORM: - return 'A sandstorm brewed!'; + return i18next.t('weather:sandstormStartMessage'); case WeatherType.HAIL: - return 'It started to hail!'; + return i18next.t('weather:hailStartMessage'); case WeatherType.SNOW: - return 'It started to snow!'; + return i18next.t('weather:snowStartMessage'); case WeatherType.FOG: - return 'A thick fog emerged!' + return i18next.t('weather:fogStartMessage'); case WeatherType.HEAVY_RAIN: - return 'A heavy downpour started!' + return i18next.t('weather:heavyRainStartMessage'); case WeatherType.HARSH_SUN: - return 'The sunlight got hot!' + return i18next.t('weather:harshSunStartMessage'); case WeatherType.STRONG_WINDS: - return 'A heavy wind began!'; + return i18next.t('weather:strongWindsStartMessage'); } return null; @@ -146,23 +147,23 @@ export function getWeatherStartMessage(weatherType: WeatherType): string { export function getWeatherLapseMessage(weatherType: WeatherType): string { switch (weatherType) { case WeatherType.SUNNY: - return 'The sunlight is strong.'; + return i18next.t('weather:sunnyLapseMessage'); case WeatherType.RAIN: - return 'The downpour continues.'; + return i18next.t('weather:rainLapseMessage'); case WeatherType.SANDSTORM: - return 'The sandstorm rages.'; + return i18next.t('weather:sandstormLapseMessage'); case WeatherType.HAIL: - return 'Hail continues to fall.'; + return i18next.t('weather:hailLapseMessage'); case WeatherType.SNOW: - return 'The snow is falling down.'; + return i18next.t('weather:snowLapseMessage'); case WeatherType.FOG: - return 'The fog continues.'; + return i18next.t('weather:fogLapseMessage'); case WeatherType.HEAVY_RAIN: - return 'The heavy downpour continues.' + return i18next.t('weather:heavyRainLapseMessage'); case WeatherType.HARSH_SUN: - return 'The sun is scorching hot.' + return i18next.t('weather:harshSunLapseMessage'); case WeatherType.STRONG_WINDS: - return 'The wind blows intensely.'; + return i18next.t('weather:strongWindsLapseMessage'); } return null; @@ -171,9 +172,9 @@ export function getWeatherLapseMessage(weatherType: WeatherType): string { export function getWeatherDamageMessage(weatherType: WeatherType, pokemon: Pokemon): string { switch (weatherType) { case WeatherType.SANDSTORM: - return getPokemonMessage(pokemon, ' is buffeted\nby the sandstorm!'); + return i18next.t('weather:sandstormDamageMessage', {pokemonPrefix: getPokemonPrefix(pokemon), pokemonName: pokemon.name}); case WeatherType.HAIL: - return getPokemonMessage(pokemon, ' is pelted\nby the hail!'); + return i18next.t('weather:hailDamageMessage', {pokemonPrefix: getPokemonPrefix(pokemon), pokemonName: pokemon.name}); } return null; @@ -182,23 +183,23 @@ export function getWeatherDamageMessage(weatherType: WeatherType, pokemon: Pokem export function getWeatherClearMessage(weatherType: WeatherType): string { switch (weatherType) { case WeatherType.SUNNY: - return 'The sunlight faded.'; + return i18next.t('weather:sunnyClearMessage'); case WeatherType.RAIN: - return 'The rain stopped.'; + return i18next.t('weather:rainClearMessage'); case WeatherType.SANDSTORM: - return 'The sandstorm subsided.'; + return i18next.t('weather:sandstormClearMessage'); case WeatherType.HAIL: - return 'The hail stopped.'; + return i18next.t('weather:hailClearMessage'); case WeatherType.SNOW: - return 'The snow stopped.'; + return i18next.t('weather:snowClearMessage'); case WeatherType.FOG: - return 'The fog disappeared.' + return i18next.t('weather:fogClearMessage'); case WeatherType.HEAVY_RAIN: - return 'The heavy rain stopped.' + return i18next.t('weather:heavyRainClearMessage'); case WeatherType.HARSH_SUN: - return 'The harsh sunlight faded.' + return i18next.t('weather:harshSunClearMessage'); case WeatherType.STRONG_WINDS: - return 'The heavy wind stopped.'; + return i18next.t('weather:strongWindsClearMessage'); } return null; diff --git a/src/evolution-phase.ts b/src/evolution-phase.ts index fb3803a1e75..7684d7797a2 100644 --- a/src/evolution-phase.ts +++ b/src/evolution-phase.ts @@ -9,6 +9,7 @@ import { LearnMovePhase } from "./phases"; import { cos, sin } from "./field/anims"; import { PlayerPokemon } from "./field/pokemon"; import { getTypeRgb } from "./data/type"; +import i18next from "i18next"; export class EvolutionPhase extends Phase { protected pokemon: PlayerPokemon; @@ -115,7 +116,7 @@ export class EvolutionPhase extends Phase { const evolutionHandler = this.scene.ui.getHandler() as EvolutionSceneHandler; const preName = this.pokemon.name; - this.scene.ui.showText(`What?\n${preName} is evolving!`, null, () => { + this.scene.ui.showText(i18next.t('menu:evolving', { pokemonName: preName }), null, () => { this.pokemon.cry(); this.pokemon.getPossibleEvolution(this.evolution).then(evolvedPokemon => { @@ -187,8 +188,8 @@ export class EvolutionPhase extends Phase { this.scene.unshiftPhase(new EndEvolutionPhase(this.scene)); - this.scene.ui.showText(`${preName} stopped evolving.`, null, () => { - this.scene.ui.showText(`Would you like to pause evolutions for ${preName}?\nEvolutions can be re-enabled from the party screen.`, null, () => { + this.scene.ui.showText(i18next.t('menu:stoppedEvolving', { pokemonName: preName }), null, () => { + this.scene.ui.showText(i18next.t('menu:pauseEvolutionsQuestion', { pokemonName: preName }), null, () => { const end = () => { this.scene.ui.showText(null, 0); this.scene.playBgm(); @@ -198,7 +199,7 @@ export class EvolutionPhase extends Phase { this.scene.ui.setOverlayMode(Mode.CONFIRM, () => { this.scene.ui.revertMode(); this.pokemon.pauseEvolutions = true; - this.scene.ui.showText(`Evolutions have been paused for ${preName}.`, null, end, 3000); + this.scene.ui.showText(i18next.t('menu:evolutionsPaused', { pokemonName: preName }), null, end, 3000); }, () => { this.scene.ui.revertMode(); this.scene.time.delayedCall(3000, end); @@ -249,7 +250,7 @@ export class EvolutionPhase extends Phase { this.scene.playSoundWithoutBgm('evolution_fanfare'); evolvedPokemon.destroy(); - this.scene.ui.showText(`Congratulations!\nYour ${preName} evolved into ${this.pokemon.name}!`, null, () => this.end(), null, true, Utils.fixedInt(4000)); + this.scene.ui.showText(i18next.t('menu:evolutionDone', { pokemonName: preName, evolvedPokemonName: this.pokemon.name }), null, () => this.end(), null, true, Utils.fixedInt(4000)); this.scene.time.delayedCall(Utils.fixedInt(4250), () => this.scene.playBgm()); }); }); diff --git a/src/field/arena.ts b/src/field/arena.ts index a2bde94229d..75cc86fcebc 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -206,6 +206,7 @@ export class Arena { case Biome.TALL_GRASS: return Type.GRASS; case Biome.FOREST: + case Biome.JUNGLE: return Type.BUG; case Biome.SLUM: case Biome.SWAMP: @@ -237,8 +238,10 @@ export class Arena { case Biome.TEMPLE: return Type.GHOST; case Biome.DOJO: + case Biome.CONSTRUCTION_SITE: return Type.FIGHTING; case Biome.FACTORY: + case Biome.LABORATORY: return Type.STEEL; case Biome.RUINS: case Biome.SPACE: @@ -248,6 +251,8 @@ export class Arena { return Type.DRAGON; case Biome.ABYSS: return Type.DARK; + default: + return Type.UNKNOWN; } } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 97d94bdba7c..eb08af3da55 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1229,14 +1229,20 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { for (let i = 0; i < 3; i++) { const moveId = speciesEggMoves[this.species.getRootSpeciesId()][i]; if (!movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(' (N)')) - movePool.push([moveId, Math.min(this.level * 0.5, 40)]); + movePool.push([moveId, 40]); } + const moveId = speciesEggMoves[this.species.getRootSpeciesId()][3]; + if (this.level >= 170 && !movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(' (N)') && !this.isBoss()) // No rare egg moves before e4 + movePool.push([moveId, 30]); if (this.fusionSpecies) { for (let i = 0; i < 3; i++) { const moveId = speciesEggMoves[this.fusionSpecies.getRootSpeciesId()][i]; if (!movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(' (N)')) - movePool.push([moveId, Math.min(this.level * 0.5, 30)]); + movePool.push([moveId, 40]); } + const moveId = speciesEggMoves[this.fusionSpecies.getRootSpeciesId()][3]; + if (this.level >= 170 && !movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(' (N)') && !this.isBoss()) // No rare egg moves before e4 + movePool.push([moveId, 30]); } } } @@ -1544,6 +1550,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { applyPreAttackAbAttrs(DamageBoostAbAttr, source, this, battlerMove, damage); + /** + * For each {@link HitsTagAttr} the move has, doubles the damage of the move if: + * The target has a {@link BattlerTagType} that this move interacts with + * AND + * The move doubles damage when used against that tag + * */ move.getAttrs(HitsTagAttr).map(hta => hta as HitsTagAttr).filter(hta => hta.doubleDamage).forEach(hta => { if (this.getTag(hta.tagType)) damage.value *= 2; diff --git a/src/field/trainer.ts b/src/field/trainer.ts index 4a7458652c4..faa691406b9 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -10,6 +10,8 @@ import { PersistentModifier } from "../modifier/modifier"; import { trainerNamePools } from "../data/trainer-names"; import { ArenaTagType } from "#app/data/enums/arena-tag-type"; import { ArenaTag, ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; +import {getIsInitialized, initI18n} from "#app/plugins/i18n"; +import i18next from "i18next"; export enum TrainerVariant { DEFAULT, @@ -97,9 +99,16 @@ export default class Trainer extends Phaser.GameObjects.Container { getName(trainerSlot: TrainerSlot = TrainerSlot.NONE, includeTitle: boolean = false): string { let name = this.config.getTitle(trainerSlot, this.variant); let title = includeTitle && this.config.title ? this.config.title : null; + + if (this.name) { if (includeTitle) - title = name; + + // Check if i18n is initialized + if (!getIsInitialized()) { + initI18n() + } + title = i18next.t(`trainerClasses:${name.toLowerCase().replace(/\s/g, '_')}`); if (!trainerSlot) { name = this.name; if (this.partnerName) @@ -107,6 +116,7 @@ export default class Trainer extends Phaser.GameObjects.Container { } else name = trainerSlot === TrainerSlot.TRAINER ? this.name : this.partnerName || this.name; } + return title ? `${title} ${name}` : name; } @@ -368,16 +378,29 @@ export default class Trainer extends Phaser.GameObjects.Container { }; const sprites = this.getSprites(); const tintSprites = this.getTintSprites(); - sprites[0].play(trainerAnimConfig); - tintSprites[0].play(trainerAnimConfig); + + // Don't try to play an animation when there isn't one + if (sprites.length > 1) { + sprites[0].play(trainerAnimConfig); + tintSprites[0].play(trainerAnimConfig); + } + else + console.warn(`No animation found for '${this.getKey()}'. Is this intentional?`); + if (this.variant === TrainerVariant.DOUBLE && !this.config.doubleOnly) { const partnerTrainerAnimConfig = { key: this.getKey(true), repeat: 0, startFrame: 0 }; - sprites[1].play(partnerTrainerAnimConfig); - tintSprites[1].play(partnerTrainerAnimConfig); + + // Don't try to play an animation when there isn't one + if (sprites.length > 1) { + sprites[1].play(partnerTrainerAnimConfig); + tintSprites[1].play(partnerTrainerAnimConfig); + } + else + console.warn(`No animation found for '${this.getKey()}'. Is this intentional?`); } } diff --git a/src/loading-scene.ts b/src/loading-scene.ts index a49fed480e6..56d0ab47f13 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -209,6 +209,9 @@ export class LoadingScene extends SceneBase { this.loadImage('egg_list_bg', 'ui'); + this.loadImage('end_m', 'cg'); + this.loadImage('end_f', 'cg'); + for (let i = 0; i < 10; i++) { this.loadAtlas(`pokemon_icons_${i}`, ''); if (i) diff --git a/src/locales/de/ability-trigger.ts b/src/locales/de/ability-trigger.ts index 88900741218..27d2053b621 100644 --- a/src/locales/de/ability-trigger.ts +++ b/src/locales/de/ability-trigger.ts @@ -1,5 +1,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const abilityTriggers: SimpleTranslationEntries = { - 'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`, -} as const; \ No newline at end of file + 'blockRecoilDamage' : `{{pokemonName}} wurde durch {{abilityName}}\nvor Rückstoß geschützt!`, +} as const; diff --git a/src/locales/de/battle-message-ui-handler.ts b/src/locales/de/battle-message-ui-handler.ts new file mode 100644 index 00000000000..daedb8550d0 --- /dev/null +++ b/src/locales/de/battle-message-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battleMessageUiHandler: SimpleTranslationEntries = { + "ivBest": "Sensationell", + "ivFantastic": "Fantastisch", + "ivVeryGood": "Sehr Gut", + "ivPrettyGood": "Gut", + "ivDecent": "Nicht Übel", + "ivNoGood": "Schlecht", +} as const; diff --git a/src/locales/de/battle.ts b/src/locales/de/battle.ts index ca0e60bf94c..5504e541be0 100644 --- a/src/locales/de/battle.ts +++ b/src/locales/de/battle.ts @@ -3,6 +3,7 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}} erscheint.", "trainerAppeared": "{{trainerName}}\nmöchte kämpfen!", + "trainerAppearedDouble": "{{trainerName}}\nmöchten kämpfen!", "singleWildAppeared": "Ein wildes {{pokemonName}} erscheint!", "multiWildAppeared": "Ein wildes {{pokemonName1}}\nund {{pokemonName2}} erscheinen!", "playerComeBack": "Komm zurück, {{pokemonName}}!", @@ -31,7 +32,9 @@ export const battle: SimpleTranslationEntries = { "learnMoveNotLearned": "{{pokemonName}} hat\n{{moveName}} nicht erlernt.", "learnMoveForgetQuestion": "Welche Attacke soll vergessen werden?", "learnMoveForgetSuccess": "{{pokemonName}} hat\n{{moveName}} vergessen.", - "levelCapUp": "Das Levellimit\nhat sich zu {{levelCap}} erhöht!", + "countdownPoof": "@d{32}Eins, @d{15}zwei @d{15}und@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}schwupp!", + "learnMoveAnd": "Und…", + "levelCapUp": "Das Levelbeschränkung\nwurde auf {{levelCap}} erhöht!", "moveNotImplemented": "{{moveName}} ist noch nicht implementiert und kann nicht ausgewählt werden.", "moveNoPP": "Es sind keine AP für\ndiese Attacke mehr übrig!", "moveDisabled": "{{moveName}} ist deaktiviert!", @@ -43,7 +46,7 @@ export const battle: SimpleTranslationEntries = { "noEscapeTrainer": "Du kannst nicht\naus einem Trainerkampf fliehen!", "noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nverhindert {{escapeVerb}}!", "runAwaySuccess": "Du bist entkommen!", - "runAwayCannotEscape": 'Flucht unmöglich!', + "runAwayCannotEscape": 'Flucht gescheitert!', "escapeVerbSwitch": "auswechseln", "escapeVerbFlee": "flucht", "skipItemQuestion": "Bist du sicher, dass du kein Item nehmen willst?", diff --git a/src/locales/de/berry.ts b/src/locales/de/berry.ts new file mode 100644 index 00000000000..8c8bc5ee280 --- /dev/null +++ b/src/locales/de/berry.ts @@ -0,0 +1,48 @@ +import { BerryTranslationEntries } from "#app/plugins/i18n"; + +export const berry: BerryTranslationEntries = { + "SITRUS": { + name: "Sitrus Berry", + effect: "Restores 25% HP if HP is below 50%", + }, + "LUM": { + name: "Lum Berry", + effect: "Cures any non-volatile status condition and confusion", + }, + "ENIGMA": { + name: "Enigma Berry", + effect: "Restores 25% HP if hit by a super effective move", + }, + "LIECHI": { + name: "Liechi Berry", + effect: "Raises Attack if HP is below 25%", + }, + "GANLON": { + name: "Ganlon Berry", + effect: "Raises Defense if HP is below 25%", + }, + "PETAYA": { + name: "Petaya Berry", + effect: "Raises Sp. Atk if HP is below 25%", + }, + "APICOT": { + name: "Apicot Berry", + effect: "Raises Sp. Def if HP is below 25%", + }, + "SALAC": { + name: "Salac Berry", + effect: "Raises Speed if HP is below 25%", + }, + "LANSAT": { + name: "Lansat Berry", + effect: "Raises critical hit ratio if HP is below 25%", + }, + "STARF": { + name: "Starf Berry", + effect: "Sharply raises a random stat if HP is below 25%", + }, + "LEPPA": { + name: "Leppa Berry", + effect: "Restores 10 PP to a move if its PP reaches 0", + }, +} as const; \ No newline at end of file diff --git a/src/locales/de/config.ts b/src/locales/de/config.ts index a9f4cd68297..7aeeeb7a925 100644 --- a/src/locales/de/config.ts +++ b/src/locales/de/config.ts @@ -2,33 +2,48 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; +import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; import { menuUiHandler } from "./menu-ui-handler"; +import { modifierType } from "./modifier-type"; import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonStat } from "./pokemon-stat"; +import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; +import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; - +import { weather } from "./weather"; +import { battleMessageUiHandler } from "./battle-message-ui-handler"; +import { berry } from "./berry"; export const deConfig = { ability: ability, abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, + egg: egg, fightUiHandler: fightUiHandler, - menuUiHandler: menuUiHandler, + growth: growth, menu: menu, + menuUiHandler: menuUiHandler, + modifierType: modifierType, move: move, - pokeball: pokeball, - pokemonStat: pokemonStat, - pokemon: pokemon, - starterSelectUiHandler: starterSelectUiHandler, - tutorial: tutorial, nature: nature, - growth: growth + pokeball: pokeball, + pokemon: pokemon, + pokemonStat: pokemonStat, + splashMessages: splashMessages, + starterSelectUiHandler: starterSelectUiHandler, + titles: titles, + trainerClasses: trainerClasses, + trainerNames: trainerNames, + tutorial: tutorial, + weather: weather, + battleMessageUiHandler: battleMessageUiHandler, + berry: berry, } \ No newline at end of file diff --git a/src/locales/de/egg.ts b/src/locales/de/egg.ts new file mode 100644 index 00000000000..3950d6729ff --- /dev/null +++ b/src/locales/de/egg.ts @@ -0,0 +1,21 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const egg: SimpleTranslationEntries = { + "egg": "Ei", + "greatTier": "Selten", + "ultraTier": "Episch", + "masterTier": "Legendär", + "defaultTier": "Gewöhnlich", + "hatchWavesMessageSoon": "Man kann schon etwas hören! Es wird wohl bald schlüpfen!", + "hatchWavesMessageClose": "Manchmal bewegt es sich! Es braucht wohl noch ein Weilchen.", + "hatchWavesMessageNotClose": "Was wird da wohl schlüpfen? Es wird sicher noch lange dauern.", + "hatchWavesMessageLongTime": "Dieses Ei braucht sicher noch sehr viel Zeit.", + "gachaTypeLegendary": "Erhöhte Chance auf legendäre Eier", + "gachaTypeMove": "Erhöhte Chance auf Eier mit seltenen Attacken", + "gachaTypeShiny": "Erhöhte Chance auf schillernde Eier", + "selectMachine": "Wähle eine Maschine", + "notEnoughVouchers": "Du hast nicht genug Ei-Gutscheine!", + "tooManyEggs": "Du hast schon zu viele Eier!", + "pull": "Pull", + "pulls": "Pulls" +} as const; \ No newline at end of file diff --git a/src/locales/de/menu-ui-handler.ts b/src/locales/de/menu-ui-handler.ts index e330b726998..aa09a3b4c6f 100644 --- a/src/locales/de/menu-ui-handler.ts +++ b/src/locales/de/menu-ui-handler.ts @@ -9,8 +9,8 @@ export const menuUiHandler: SimpleTranslationEntries = { "EGG_GACHA": "Eier-Gacha", "MANAGE_DATA": "Daten verwalten", "COMMUNITY": "Community", - "RETURN_TO_TITLE": "Zurück zum Titelbildschirm", - "LOG_OUT": "Ausloggen", + "SAVE_AND_QUIT": "Speichern und Beenden", + "LOG_OUT": "Abmelden", "slot": "Slot {{slotNumber}}", "importSession": "Sitzung importieren", "importSlotSelect": "Wähle einen Slot zum Importieren.", @@ -20,4 +20,4 @@ export const menuUiHandler: SimpleTranslationEntries = { "exportData": "Daten exportieren", "cancel": "Abbrechen", "losingProgressionWarning": "Du wirst jeglichen Fortschritt seit Anfang dieses Kampfes verlieren. Fortfahren?" -} as const; \ No newline at end of file +} as const; diff --git a/src/locales/de/menu.ts b/src/locales/de/menu.ts index c22b940a8eb..0d33fb4cbd8 100644 --- a/src/locales/de/menu.ts +++ b/src/locales/de/menu.ts @@ -12,10 +12,10 @@ export const menu: SimpleTranslationEntries = { "loadGame": "Spiel laden", "newGame": "Neues Spiel", "selectGameMode": "Wähle einen Spielmodus", - "logInOrCreateAccount": "Logge dich ein oder erstelle einen Account zum starten. Keine Email nötig!", + "logInOrCreateAccount": "Melde dich an oder erstelle einen Account zum starten. Keine Email nötig!", "username": "Benutzername", "password": "Passwort", - "login": "Einloggen", + "login": "Anmelden", "register": "Registrieren", "emptyUsername": "Benutzername darf nicht leer sein", "invalidLoginUsername": "Der eingegebene Benutzername ist ungültig", @@ -26,15 +26,20 @@ export const menu: SimpleTranslationEntries = { "accountNonExistent": "Der eingegebene Benutzer existiert nicht", "unmatchingPassword": "Das eingegebene Passwort stimmt nicht überein", "passwordNotMatchingConfirmPassword": "Passwort muss mit Bestätigungspasswort übereinstimmen", - "confirmPassword": "Besätige Passwort", + "confirmPassword": "Bestätige Passwort", "registrationAgeWarning": "Mit der Registrierung bestätigen Sie, dass Sie 13 Jahre oder älter sind.", - "backToLogin": "Zurück zum Einloggen", + "backToLogin": "Zurück zur Anmeldung", "failedToLoadSaveData": "Speicherdaten konnten nicht geladen werden. Bitte laden Sie die Seite neu.\nWenn dies weiterhin der Fall ist, wenden Sie sich bitte an den Administrator.", "sessionSuccess": "Sitzung erfolgreich geladen.", "failedToLoadSession": "Ihre Sitzungsdaten konnten nicht geladen werden.\nSie könnten beschädigt sein.", "boyOrGirl": "Bist du ein Junge oder ein Mädchen?", "boy": "Junge", "girl": "Mädchen", + "evolving": "Nanu?\n{{pokemonName}} entwickelt sich!", + "stoppedEvolving": "Hm? {{pokemonName}} hat die Entwicklung \nabgebrochen.", // "Hm? Entwicklung wurde abgebrochen!" without naming the pokemon seems to be the original. + "pauseEvolutionsQuestion": "Die Entwicklung von {{pokemonName}} vorübergehend pausieren?\nEntwicklungen können im Gruppenmenü wieder aktiviert werden.", + "evolutionsPaused": "Entwicklung von {{pokemonName}} pausiert.", + "evolutionDone": "Glückwunsch!\nDein {{pokemonName}} entwickelte sich zu {{evolvedPokemonName}}!", "dailyRankings": "Tägliche Rangliste", "weeklyRankings": "Wöchentliche Rangliste", "noRankings": "Keine Rangliste", @@ -43,4 +48,4 @@ export const menu: SimpleTranslationEntries = { "empty":"Leer", "yes":"Ja", "no":"Nein", -} as const; \ No newline at end of file +} as const; diff --git a/src/locales/de/modifier-type.ts b/src/locales/de/modifier-type.ts new file mode 100644 index 00000000000..dea1421ac20 --- /dev/null +++ b/src/locales/de/modifier-type.ts @@ -0,0 +1,410 @@ +import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; + +export const modifierType: ModifierTypeTranslationEntries = { + ModifierType: { + "AddPokeballModifierType": { + name: "{{modifierCount}}x {{pokeballName}}", + description: "Erhalte {{pokeballName}} x{{modifierCount}} (Inventar: {{pokeballAmount}}) \nFangrate: {{catchRate}}", + }, + "AddVoucherModifierType": { + name: "{{modifierCount}}x {{voucherTypeName}}", + description: "Erhalte {{voucherTypeName}} x{{modifierCount}}", + }, + "PokemonHeldItemModifierType": { + extra: { + "inoperable": "{{pokemonName}} kann dieses\nItem nicht nehmen!", + "tooMany": "{{pokemonName}} hat zu viele\nvon diesem Item!", + } + }, + "PokemonHpRestoreModifierType": { + description: "Füllt {{restorePoints}} KP oder {{restorePercent}}% der KP für ein Pokémon auf. Je nachdem, welcher Wert höher ist", + extra: { + "fully": "Füllt die KP eines Pokémon wieder vollständig auf.", + "fullyWithStatus": "Füllt die KP eines Pokémon wieder vollständig auf und behebt alle Statusprobleme", + } + }, + "PokemonReviveModifierType": { + description: "Belebt ein kampunfähiges Pokémon wieder und stellt {{restorePercent}}% KP wieder her", + }, + "PokemonStatusHealModifierType": { + description: "Behebt alle Statusprobleme eines Pokémon", + }, + "PokemonPpRestoreModifierType": { + description: "Füllt {{restorePoints}} AP der ausgewählten Attacke eines Pokémon auf", + extra: { + "fully": "Füllt alle AP der ausgewählten Attacke eines Pokémon auf", + } + }, + "PokemonAllMovePpRestoreModifierType": { + description: "Stellt {{restorePoints}} AP für alle Attacken eines Pokémon auf", + extra: { + "fully": "Füllt alle AP für alle Attacken eines Pokémon auf", + } + }, + "PokemonPpUpModifierType": { + description: "Erhöht die maximale Anzahl der AP der ausgewählten Attacke um {{upPoints}} für jede 5 maximale AP (maximal 3)", + }, + "PokemonNatureChangeModifierType": { + name: "{{natureName}} Minze", + description: "Ändert das Wesen zu {{natureName}}. Schaltet dieses Wesen permanent für diesen Starter frei.", + }, + "DoubleBattleChanceBoosterModifierType": { + description: "Verdoppelt die Wahrscheinlichkeit, dass die nächsten {{battleCount}} Begegnungen mit wilden Pokémon ein Doppelkampf sind.", + }, + "TempBattleStatBoosterModifierType": { + description: "Erhöht die {{tempBattleStatName}} aller Teammitglieder für 5 Kämpfe um eine Stufe", + }, + "AttackTypeBoosterModifierType": { + description: "Erhöht die Stärke aller {{moveType}}attacken eines Pokémon um 20%", + }, + "PokemonLevelIncrementModifierType": { + description: "Erhöht das Level eines Pokémon um 1", + }, + "AllPokemonLevelIncrementModifierType": { + description: "Erhöht das Level aller Teammitglieder um 1", + }, + "PokemonBaseStatBoosterModifierType": { + description: "Erhöht den {{statName}} Basiswert des Trägers um 10%. Das Stapellimit erhöht sich, je höher dein IS-Wert ist.", + }, + "AllPokemonFullHpRestoreModifierType": { + description: "Stellt 100% der KP aller Pokémon her", + }, + "AllPokemonFullReviveModifierType": { + description: "Belebt alle kampunfähigen Pokémon wieder und stellt ihre KP vollständig wieder her", + }, + "MoneyRewardModifierType": { + description:"Gewährt einen {{moneyMultiplier}} Geldbetrag von (₽{{moneyAmount}})", + extra: { + "small": "kleinen", + "moderate": "moderaten", + "large": "großen", + }, + }, + "ExpBoosterModifierType": { + description: "Erhöht die erhaltenen Erfahrungspunkte um {{boostPercent}}%", + }, + "PokemonExpBoosterModifierType": { + description: "Erhöht die Menge der erhaltenen Erfahrungspunkte für den Träger um {{boostPercent}}%", + }, + "PokemonFriendshipBoosterModifierType": { + description: "Erhöht den Freundschaftszuwachs pro Sieg um 50%.", + }, + "PokemonMoveAccuracyBoosterModifierType": { + description: "Erhöht die Genauigkeit der Angriffe um {{accuracyAmount}} (maximal 100)", + }, + "PokemonMultiHitModifierType": { + description: "Attacken treffen ein weiteres mal mit einer Reduktion von 60/75/82,5% der Stärke", + }, + "TmModifierType": { + name: "TM{{moveId}} - {{moveName}}", + description: "Bringt einem Pokémon {{moveName}} bei", + }, + "EvolutionItemModifierType": { + description: "Erlaubt es bestimmten Pokémon sich zu entwickeln", + }, + "FormChangeItemModifierType": { + description: "Erlaubt es bestimmten Pokémon ihre Form zu ändern", + }, + "FusePokemonModifierType": { + description: "Fusioniert zwei Pokémon (überträgt die Fähigkeit, teilt Basiswerte und Typ auf, gemeinsamer Attackenpool)", + }, + "TerastallizeModifierType": { + name: "{{teraType}} Terra-Stück", + description: "{{teraType}} Terakristallisiert den Träger für bis zu 10 Kämpfe", + }, + "ContactHeldItemTransferChanceModifierType": { + description:"Beim Angriff besteht eine {{chancePercent}}%ige Chance, dass das getragene Item des Gegners gestohlen wird." + }, + "TurnHeldItemTransferModifierType": { + description: "Jede Runde erhält der Träger ein getragenes Item des Gegners", + }, + "EnemyAttackStatusEffectChanceModifierType": { + description: "Fügt Angriffen eine {{chancePercent}}%ige Chance hinzu, {{statusEffect}} zu verursachen", + }, + "EnemyEndureChanceModifierType": { + description: "Gibt den Träger eine {{chancePercent}}%ige Chance, einen Angriff zu überleben", + }, + + "RARE_CANDY": { name: "Sonderbonbon" }, + "RARER_CANDY": { name: "Supersondererbonbon" }, + + "MEGA_BRACELET": { name: "Mega-Armband", description: "Mega-Steine werden verfügbar" }, + "DYNAMAX_BAND": { name: "Dynamax-Band", description: "Dyna-Pilze werden verfügbar" }, + "TERA_ORB": { name: "Terakristall-Orb", description: "Tera-Stücke werden verfügbar" }, + + "MAP": { name: "Karte", description: "Ermöglicht es dir, an einer Kreuzung dein Ziel zu wählen." }, + + "POTION": { name: "Trank" }, + "SUPER_POTION": { name: "Supertrank" }, + "HYPER_POTION": { name: "Hypertrank" }, + "MAX_POTION": { name: "Top-Trank" }, + "FULL_RESTORE": { name: "Top-Genesung" }, + + "REVIVE": { name: "Beleber" }, + "MAX_REVIVE": { name: "Top-Beleber" }, + + "FULL_HEAL": { name: "Hyperheiler" }, + + "SACRED_ASH": { name: "Zauberasche" }, + + "REVIVER_SEED": { name: "Belebersamen", description: "Belebt den Träger mit der Hälfte seiner KP wieder sollte er kampfunfähig werden" }, + + "ETHER": { name: "Äther" }, + "MAX_ETHER": { name: "Top-Äther" }, + + "ELIXIR": { name: "Elixir" }, + "MAX_ELIXIR": { name: "Top-Elixir" }, + + "PP_UP": { name: "AP-Plus" }, + "PP_MAX": { name: "AP-Top" }, + + "LURE": { name: "Lockparfüm" }, + "SUPER_LURE": { name: "Super-Lockparfüm" }, + "MAX_LURE": { name: "Top-Lockparfüm" }, + + "MEMORY_MUSHROOM": { name: "Erinnerungspilz", description: "Lässt ein Pokémon eine vergessene Attacke wiedererlernen" }, + + "EXP_SHARE": { name: "EP-Teiler", description: "Pokémon, die nicht am Kampf teilgenommen haben, bekommen 20% der Erfahrungspunkte eines Kampfteilnehmers" }, + "EXP_BALANCE": { name: "EP-Ausgleicher", description: "Gewichtet die in Kämpfen erhaltenen Erfahrungspunkte auf niedrigstufigere Gruppenmitglieder." }, + + "OVAL_CHARM": { name: "Ovalpin", description: "Wenn mehrere Pokémon am Kampf teilnehmen, erhählt jeder von ihnen 10% extra Erfahrungspunkte" }, + + "EXP_CHARM": { name: "EP-Pin" }, + "SUPER_EXP_CHARM": { name: "Super-EP-Pin" }, + "GOLDEN_EXP_CHARM": { name: "Goldener EP-Pin" }, + + "LUCKY_EGG": { name: "Glücks-Ei" }, + "GOLDEN_EGG": { name: "Goldenes Ei" }, + + "SOOTHE_BELL": { name: "Sanftglocke" }, + + "SOUL_DEW": { name: "Seelentau", description: "Erhöht den Einfluss des Wesens eines Pokemon auf seine Werte um 10% (additiv)" }, + + "NUGGET": { name: "Nugget" }, + "BIG_NUGGET": { name: "Riesennugget" }, + "RELIC_GOLD": { name: "Alter Dukat" }, + + "AMULET_COIN": { name: "Münzamulett", description: "Erhöht das Preisgeld um 20%" }, + "GOLDEN_PUNCH": { name: "Goldschlag", description: "Gewährt Geld in Höhe von 50% des zugefügten Schadens" }, + "COIN_CASE": { name: "Münzkorb", description: "Erhalte nach jedem 10ten Kampf 10% Zinsen auf dein Geld" }, + + "LOCK_CAPSULE": { name: "Tresorkapsel", description: "Erlaubt es die Seltenheitsstufe der Items festzusetzen wenn diese neu gerollt werden" }, + + "GRIP_CLAW": { name: "Griffklaue" }, + "WIDE_LENS": { name: "Großlinse" }, + + "MULTI_LENS": { name: "Mehrfachlinse" }, + + "HEALING_CHARM": { name: "Heilungspin", description: "Erhöht die Effektivität von Heilungsattacken sowie Heilitems um 10% (Beleber ausgenommen)" }, + "CANDY_JAR": { name: "Bonbonglas", description: "Erhöht die Anzahl der Level die ein Sonderbonbon erhöht um 1" }, + + "BERRY_POUCH": { name: "Beerentüte", description: "Fügt eine 25% Chance hinzu, dass Beeren nicht verbraucht werden" }, + + "FOCUS_BAND": { name: "Fokusband", description: "Fügt eine 10% Chance hinzu, dass Angriffe die zur Kampfunfähigkeit führen mit 1 KP überlebt werden" }, + + "QUICK_CLAW": { name: "Quick Claw", description: "Fügt eine 10% Change hinzu als erster anzugreifen. (Nach Prioritätsangriffen)" }, + + "KINGS_ROCK": { name: "King-Stein", description: "Fügt eine 10% Chance hinzu, dass der Gegner nach einem Angriff zurückschreckt" }, + + "LEFTOVERS": { name: "Überreste", description: "Heilt 1/16 der maximalen KP eines Pokémon pro Runde" }, + "SHELL_BELL": { name: "Muschelglocke", description: "Heilt den Anwender um 1/8 des von ihm zugefügten Schadens" }, + + "BATON": { name: "Stab", description: "Ermöglicht das Weitergeben von Effekten beim Wechseln von Pokémon, wodurch auch Fallen umgangen werden." }, + + "SHINY_CHARM": { name: "Schillerpin", description: "Erhöht die Chance deutlich, dass ein wildes Pokémon ein schillernd ist" }, + "ABILITY_CHARM": { name: "Ability Charm", description: "Erhöht die Chance deutlich, dass ein wildes Pokémon eine versteckte Fähigkeit hat" }, + + "IV_SCANNER": { name: "IS-Scanner", description: "Erlaubt es die IS-Werte von wilden Pokémon zu scannen.\n(2 IS-Werte pro Staplung. Die besten IS-Werte zuerst)" }, + + "DNA_SPLICERS": { name: "DNS-Keil" }, + + "MINI_BLACK_HOLE": { name: "Mini schwarzes Loch" }, + + "GOLDEN_POKEBALL": { name: "Goldener Pokéball", description: "Fügt eine zusätzliche Item-Auswahlmöglichkeit nach jedem Kampf hinzu" }, + + "ENEMY_DAMAGE_BOOSTER": { name: "Schadensmarke", description: "Erhöht den Schaden um 5%" }, + "ENEMY_DAMAGE_REDUCTION": { name: "Schutzmarke", description: "Verringert den erhaltenen Schaden um 2,5%" }, + "ENEMY_HEAL": { name: "Wiederherstellungsmarke", description: "Heilt 2% der maximalen KP pro Runde" }, + "ENEMY_ATTACK_POISON_CHANCE": { name: "Giftmarke" }, + "ENEMY_ATTACK_PARALYZE_CHANCE": { "name": "Lähmungsmarke" }, + "ENEMY_ATTACK_SLEEP_CHANCE": { "name": "Schlafmarke" }, + "ENEMY_ATTACK_FREEZE_CHANCE": { "name": "Gefriermarke" }, + "ENEMY_ATTACK_BURN_CHANCE": { "name": "Brandmarke" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { "name": "Vollheilungsmarke", "description": "Fügt eine 10%ige Chance hinzu, jede Runde einen Statuszustand zu heilen" }, + "ENEMY_ENDURE_CHANCE": { "name": "Ausdauer-Marke" }, + "ENEMY_FUSED_CHANCE": { "name": "Fusionsmarke", "description": "Fügt eine 1%ige Chance hinzu, dass ein wildes Pokémon eine Fusion ist" }, + + }, + TempBattleStatBoosterItem: { + "x_attack": "X-Angriff", + "x_defense": "X-Verteidigung", + "x_sp_atk": "X-Sp.-Ang.", + "x_sp_def": "X-Sp.-Vert.", + "x_speed": "X-Tempo", + "x_accuracy": "X-Treffer", + "dire_hit": "X-Volltreffer", + }, + AttackTypeBoosterItem: { + "silk_scarf": "Seidenschal", + "black_belt": "Schwarzgurt", + "sharp_beak": "Spitzer Schnabel", + "poison_barb": "Giftstich", + "soft_sand": "Pudersand", + "hard_stone": "Granitstein", + "silver_powder": "Silberstaub", + "spell_tag": "Bannsticker", + "metal_coat": "Metallmantel", + "charcoal": "Holzkohle", + "mystic_water": "Zauberwasser", + "miracle_seed": "Wundersaat", + "magnet": "Magnet", + "twisted_spoon": "Krümmlöffel", + "never_melt_ice": "Ewiges Eis", + "dragon_fang": "Drachenzahn", + "black_glasses": "Schattenbrille", + "fairy_feather": "Feendaune", + }, + BaseStatBoosterItem: { + "hp_up": "KP-Plus", + "protein": "Protein", + "iron": "Eisen", + "calcium": "Kalzium", + "zinc": "Zink", + "carbos": "Carbon", + }, + EvolutionItem: { + "NONE": "Keins", + + "LINKING_CORD": "Linkkabel", + "SUN_STONE": "Sonnenstein", + "MOON_STONE": "Mondstein", + "LEAF_STONE": "Blattstein", + "FIRE_STONE": "Feuerstein", + "WATER_STONE": "Wasserstein", + "THUNDER_STONE": "Donnerstein", + "ICE_STONE": "Eisstein", + "DUSK_STONE": "Finsterstein", + "DAWN_STONE": "Funkelstein", + "SHINY_STONE": "Leuchtstein", + "CRACKED_POT": "Rissige Kanne", + "SWEET_APPLE": "Süßer Apfel", + "TART_APPLE": "Saurer Apfel", + "STRAWBERRY_SWEET": "Zucker-Erdbeere", + "UNREMARKABLE_TEACUP": "Simple Teeschale", + + "CHIPPED_POT": "Löchrige Kanne", + "BLACK_AUGURITE": "Schwarzaugit", + "GALARICA_CUFF": "Galarnuss-Reif", + "GALARICA_WREATH": "Galarnuss-Kranz", + "PEAT_BLOCK": "Torfblock", + "AUSPICIOUS_ARMOR": "Glorienrüstung", + "MALICIOUS_ARMOR": "Fluchrüstung", + "MASTERPIECE_TEACUP": "Edle Teeschale", + "METAL_ALLOY": "Legierungsmetall", + "SCROLL_OF_DARKNESS": "Unlicht-Schriftrolle", + "SCROLL_OF_WATERS": "Wasser-Schriftrolle", + "SYRUPY_APPLE": "Saftiger Apfel", + }, + FormChangeItem: { + "NONE": "Keins", + + "ABOMASITE": "Rexblisarnit", + "ABSOLITE": "Absolnit", + "AERODACTYLITE": "Aerodactylonit", + "AGGRONITE": "Stollossnit", + "ALAKAZITE": "Simsalanit", + "ALTARIANITE": "Altarianit", + "AMPHAROSITE": "Ampharosnit", + "AUDINITE": "Ohrdochnit", + "BANETTITE": "Banetteonit", + "BEEDRILLITE": "Bibornit", + "BLASTOISINITE": "Turtoknit", + "BLAZIKENITE": "Lohgocknit", + "CAMERUPTITE": "Cameruptnit", + "CHARIZARDITE_X": "Gluraknit X", + "CHARIZARDITE_Y": "Gluraknit Y", + "DIANCITE": "Diancienit", + "GALLADITE": "Galagladinit", + "GARCHOMPITE": "Knakracknit", + "GARDEVOIRITE": "Guardevoirnit", + "GENGARITE": "Gengarnit ", + "GLALITITE": "Firnontornit", + "GYARADOSITE": "Garadosnit", + "HERACRONITE": "Skarabornit", + "HOUNDOOMINITE": "Hundemonit ", + "KANGASKHANITE": "Kangamanit", + "LATIASITE": "Latiasnit", + "LATIOSITE": "Latiosnit", + "LOPUNNITE": "Schlapornit", + "LUCARIONITE": "Lucarionit", + "MANECTITE": "Voltensonit", + "MAWILITE": "Flunkifernit", + "MEDICHAMITE": "Meditalisnit", + "METAGROSSITE": "Metagrossnit", + "MEWTWONITE_X": "Mewtunit X", + "MEWTWONITE_Y": "Mewtunit Y", + "PIDGEOTITE": "Taubossnit", + "PINSIRITE": "Pinsirnit", + "RAYQUAZITE": "Rayquazanit", + "SABLENITE": "Zobirisnit", + "SALAMENCITE": "Brutalandanit", + "SCEPTILITE": "Gewaldronit", + "SCIZORITE": "Scheroxnit", + "SHARPEDONITE": "Tohaidonit", + "SLOWBRONITE": "Lahmusnit", + "STEELIXITE": "Stahlosnit", + "SWAMPERTITE": "Sumpexnit", + "TYRANITARITE": "Despotarnit", + "VENUSAURITE": "Bisaflornit", + + "BLUE_ORB": "Blauer Edelstein", + "RED_ORB": "Roter Edelstein", + "SHARP_METEORITE": "Scharfer Meteorit", + "HARD_METEORITE": "Harter Meteorit", + "SMOOTH_METEORITE": "Glatter Meteorit", + "ADAMANT_CRYSTAL": "Adamantkristall", + "LUSTROUS_ORB": "Weiß-Orb", + "GRISEOUS_CORE": "Platinumkristall", + "REVEAL_GLASS": "Wahrspiegel", + "GRACIDEA": "Gracidea", + "MAX_MUSHROOMS": "Dyna-Pilz", + "DARK_STONE": "Dunkelstein", + "LIGHT_STONE": "Lichtstein", + "PRISON_BOTTLE": "Banngefäß", + "N_LUNARIZER": "Necrolun", + "N_SOLARIZER": "Necrosol", + "RUSTED_SWORD": "Rostiges Schwert", + "RUSTED_SHIELD": "Rostiges Schild", + "ICY_REINS_OF_UNITY": "eisige Zügel des Bundes", + "SHADOW_REINS_OF_UNITY": "schattige Zügel des Bundes", + "WELLSPRING_MASK": "Brunnenmaske", + "HEARTHFLAME_MASK": "Ofenmaske", + "CORNERSTONE_MASK": "Fundamentmaske", + "SHOCK_DRIVE": "Blitzmodul", + "BURN_DRIVE": "Flammenmodul", + "CHILL_DRIVE": "Gefriermodul", + "DOUSE_DRIVE": "Aquamodul", + }, + TeraType: { + "UNKNOWN": "Unbekannt", + "NORMAL": "Normal", + "FIGHTING": "Kampf", + "FLYING": "Flug", + "POISON": "Gift", + "GROUND": "Boden", + "ROCK": "Gestein", + "BUG": "Käfer", + "GHOST": "Geist", + "STEEL": "Stahl", + "FIRE": "Feuer", + "WATER": "Wasser", + "GRASS": "Pflanze", + "ELECTRIC": "Elektro", + "PSYCHIC": "Psycho", + "ICE": "Eis", + "DRAGON": "Drache", + "DARK": "Unlicht", + "FAIRY": "Fee", + "STELLAR": "Stellar", + }, +} as const; \ No newline at end of file diff --git a/src/locales/de/splash-messages.ts b/src/locales/de/splash-messages.ts new file mode 100644 index 00000000000..6815d7f1824 --- /dev/null +++ b/src/locales/de/splash-messages.ts @@ -0,0 +1,37 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const splashMessages: SimpleTranslationEntries = { + "battlesWon": "Battles Won!", + "joinTheDiscord": "Join the Discord!", + "infiniteLevels": "Infinite Levels!", + "everythingStacks": "Everything Stacks!", + "optionalSaveScumming": "Optional Save Scumming!", + "biomes": "35 Biomes!", + "openSource": "Open Source!", + "playWithSpeed": "Play with 5x Speed!", + "liveBugTesting": "Live Bug Testing!", + "heavyInfluence": "Heavy RoR2 Influence!", + "pokemonRiskAndPokemonRain": "Pokémon Risk and Pokémon Rain!", + "nowWithMoreSalt": "Now with 33% More Salt!", + "infiniteFusionAtHome": "Infinite Fusion at Home!", + "brokenEggMoves": "Broken Egg Moves!", + "magnificent": "Magnificent!", + "mubstitute": "Mubstitute!", + "thatsCrazy": "That\'s Crazy!", + "oranceJuice": "Orance Juice!", + "questionableBalancing": "Questionable Balancing!", + "coolShaders": "Cool Shaders!", + "aiFree": "AI-Free!", + "suddenDifficultySpikes": "Sudden Difficulty Spikes!", + "basedOnAnUnfinishedFlashGame": "Based on an Unfinished Flash Game!", + "moreAddictiveThanIntended": "More Addictive than Intended!", + "mostlyConsistentSeeds": "Mostly Consistent Seeds!", + "achievementPointsDontDoAnything": "Achievement Points Don\'t Do Anything!", + "youDoNotStartAtLevel": "You Do Not Start at Level 2000!", + "dontTalkAboutTheManaphyEggIncident": "Don\'t Talk About the Manaphy Egg Incident!", + "alsoTryPokengine": "Also Try Pokéngine!", + "alsoTryEmeraldRogue": "Also Try Emerald Rogue!", + "alsoTryRadicalRed": "Also Try Radical Red!", + "eeveeExpo": "Eevee Expo!", + "ynoproject": "YNOproject!", +} as const; \ No newline at end of file diff --git a/src/locales/de/starter-select-ui-handler.ts b/src/locales/de/starter-select-ui-handler.ts index 2e733c1a0ed..0723c14ad82 100644 --- a/src/locales/de/starter-select-ui-handler.ts +++ b/src/locales/de/starter-select-ui-handler.ts @@ -7,8 +7,17 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; */ export const starterSelectUiHandler: SimpleTranslationEntries = { "confirmStartTeam": "Mit diesen Pokémon losziehen?", + "gen1": "I", + "gen2": "II", + "gen3": "III", + "gen4": "IV", + "gen5": "V", + "gen6": "VI", + "gen7": "VII", + "gen8": "VIII", + "gen9": "IX", "growthRate": "Wachstum:", - "ability": "Fhgkeit:", + "ability": "Fähgkeit:", "passive": "Passiv:", "nature": "Wesen:", "eggMoves": "Ei-Attacken", @@ -31,5 +40,5 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "disablePassive": "Passiv-Skill deaktivieren", "locked": "Gesperrt", "disabled": "Deaktiviert", - "uncaught": "Uncaught" -} \ No newline at end of file + "uncaught": "Ungefangen" +} diff --git a/src/locales/de/trainers.ts b/src/locales/de/trainers.ts new file mode 100644 index 00000000000..1820c7eb281 --- /dev/null +++ b/src/locales/de/trainers.ts @@ -0,0 +1,244 @@ +import {SimpleTranslationEntries} from "#app/plugins/i18n"; + +// Titles of special trainers like gym leaders, elite four, and the champion +export const titles: SimpleTranslationEntries = { + "elite_four": "Top Vier", + "gym_leader": "Arenaleiter", + "gym_leader_female": "Arenaleiterin", + "champion": "Champion", + "rival": "Rivale", + "professor": "Professor", + "frontier_brain": "Kampfkoryphäen", + // Maybe if we add the evil teams we can add "Team Rocket" and "Team Aqua" etc. here as well as "Team Rocket Boss" and "Team Aqua Admin" etc. +} as const; + +// Titles of trainers like "Youngster" or "Lass" +export const trainerClasses: SimpleTranslationEntries = { + "ace_trainer": "Ass-Trainer", + "ace_trainer_female": "Ass-Trainerin", + "ace_duo": "Ass-Duo", + "artist": "Künstler", + "artist_female": "Künstlerin", + "backers": "Anhänger", + "backpacker": "Backpacker", + "backpacker_female": "Backpackerin", + "backpackers": "Backpacker", + "baker": "Bäckerin", + "battle_girl": "Kämpferin", + "beauty": "Schönheit", + "beginners": "Anfänger", + "biker": "Rowdy", + "black_belt": "Schwarzgurt", + "breeder": "Pokémon Züchter", + "breeder_female": "Pokémon Züchterin", + "breeders": "Pokémon Züchter", + "clerk": "Angestellter", + "clerk_female": "Angestellte", + "colleagues": "Geschäftspartner", + "crush_kin": "Mühlensippe", + "cyclist": "Biker", + "cyclist_female": "Bikerin", + "cyclists": "Biker", + "dancer": "Tänzer", + "dancer_female": "Tänzerin", + "depot_agent": "Bahnangestellter", + "doctor": "Arzt", + "doctor_female": "Ärztin", + "fisherman": "Angler", + "fisherman_female": "Angler", // Seems to be the same in german but exists in other languages like italian + "gentleman": "Gentleman", + "guitarist": "Gitarrist", + "guitarist_female": "Gitarristin", + "harlequin": "Kasper", + "hiker": "Wanderer", + "hooligans": "Rabauken", + "hoopster": "Basketballer", + "infielder": "Baseballer", + "janitor": "Hausmeister", + "lady": "Lady", + "lass": "Göre", + "linebacker": "Footballer", + "maid": "Zofe", + "madame": "Madam", + "medical_team": "Mediziner", + "musician": "Musiker", + "hex_maniac": "Hexe", + "nurse": "Pflegerin", + "nursery_aide": "Erzieherin", + "officer": "Polizist", + "parasol_lady": "Schirmdame", + "pilot": "Pilot", + "pokefan": "Pokéfan", + "pokefan_family": "Pokéfan-Pärchen", + "preschooler": "Vorschüler", + "preschooler_female": "Vorschülerin", + "preschoolers": "Vorschüler", + "psychic": "Seher", + "psychic_female": "Seherin", + "psychics": "Seher", + "pokémon_ranger": "Pokémon-Ranger", + "pokémon_rangers": "Pokémon-Ranger", + "ranger": "Ranger", + "restaurant_staff": "Restaurant Angestellte", + "rich": "Rich", + "rich_female": "Rich", + "rich_boy": "Schnösel", + "rich_couple": "Reiches Paar", + "rich_kid": "Rich Kid", + "rich_kid_female": "Rich Kid", + "rich_kids": "Schnösel", + "roughneck": "Raufbold", + "scientist": "Forscher", + "scientist_female": "Forscherin", + "scientists": "Forscher", + "smasher": "Tennis-Ass", + "snow_worker": "Schneearbeiter", // There is a trainer type for this but no actual trainer class? They seem to be just workers but dressed differently + "snow_worker_female": "Schneearbeiterin", + "striker": "Fußballer", + "school_kid": "Schulkind", + "school_kid_female": "Schulkind", // Same in german but different in italian + "school_kids": "Schüler", + "swimmer": "Schwimmer", + "swimmer_female": "Schwimmerin", + "swimmers": "Schwimmerpaar", + "twins": "Zwillinge", + "veteran": "Veteran", + "veteran_female": "Veteran", // same in german, different in other languages + "veteran_duo": "Veteranen", + "waiter": "Servierer", + "waitress": "Serviererin", + "worker": "Arbeiter", + "worker_female": "Arbeiterin", + "workers": "Arbeiter", + "youngster": "Knirps" +} as const; + +// Names of special trainers like gym leaders, elite four, and the champion +export const trainerNames: SimpleTranslationEntries = { + "brock": "Rocko", + "misty": "Misty", + "lt_surge": "Major Bob", + "erika": "Erika", + "janine": "Janina", + "sabrina": "Sabrina", + "blaine": "Pyro", + "giovanni": "Giovanni", + "falkner": "Falk", + "bugsy": "Kai", + "whitney": "Bianka", + "morty": "Jens", + "chuck": "Hartwig", + "jasmine": "Jasmin", + "pryce": "Norbert", + "clair": "Sandra", + "roxanne": "Felizia", + "brawly": "Kamillo", + "wattson": "Walter", + "flannery": "Flavia", + "norman": "Norman", + "winona": "Wibke", + "tate": "Ben", + "liza": "Svenja", + "juan": "Juan", + "roark": "Veit", + "gardenia": "Silvana", + "maylene": "Hilda", + "crasher_wake": "Wellenbrecher Marinus", + "fantina": "Lamina", + "byron": "Adam", + "candice": "Frida", + "volkner": "Volkner", + "cilan": "Benny", + "chili": "Maik", + "cress": "Colin", + "cheren": "Cheren", + "lenora": "Aloe", + "roxie": "Mica", + "burgh": "Artie", + "elesa": "Kamilla", + "clay": "Turner", + "skyla": "Géraldine", + "brycen": "Sandro", + "drayden": "Lysander", + "marlon": "Benson", + "viola": "Viola", + "grant": "Lino", + "korrina": "Connie", + "ramos": "Amaro", + "clemont": "Citro", + "valerie": "Valerie", + "olympia": "Astrid", + "wulfric": "Galantho", + "milo": "Yarro", + "nessa": "Kate", + "kabu": "Kabu", + "bea": "Saida", + "allister": "Nio", + "opal": "Papella", + "bede": "Betys", + "gordie": "Mac", + "melony": "Mel", + "piers": "Nezz", + "marnie": "Mary", + "raihan": "Roy", + "katy": "Ronah", + "brassius": "Colzo", + "iono": "Enigmara", + "kofu": "Kombu", + "larry": "Aoki", + "ryme": "Etta", + "tulip": "Tulia", + "grusha": "Grusha", + "lorelei": "Lorelei", + "bruno": "Bruno", + "agatha": "Agathe", + "lance": "Siegfried", + "will": "Willi", + "koga": "Koga", + "karen": "Melanie", + "sidney": "Ulrich", + "phoebe": "Antonia", + "glacia": "Frosina", + "drake": "Dragan", + "aaron": "Herbaro", + "bertha": "Teresa", + "flint": "Ignaz", + "lucian": "Lucian", + "shauntal": "Anissa", + "marshal": "Eugen", + "grimsley": "Astor", + "caitlin": "Kattlea", + "malva": "Pachira", + "siebold": "Narcisse", + "wikstrom": "Thymelot", + "drasna": "Dracena", + "hala": "Hala", + "molayne": "Marlon", + "olivia": "Mayla", + "acerola": "Lola", + "kahili": "Kahili", + "rika": "Cay", + "poppy": "Poppy", + "larry_elite": "Aoki", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "hassel": "Sinius", + "crispin": "Matt", + "amarys": "Erin", + "lacey": "Tara", + "drayton": "Levy", + "blue": "Blau", + "red": "Rot", + "lance_champion": "Siegfried", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "steven": "Troy", + "wallace": "Wassili", + "cynthia": "Cynthia", + "alder": "Lauro", + "iris": "Lilia", + "diantha": "Diantha", + "hau": "Tali", + "geeta": "Sagaria", + "nemona": "Nemila", + "kieran": "Jo", + "leon": "Delion", + "rival": "Finn", + "rival_female": "Ivy", +} as const; \ No newline at end of file diff --git a/src/locales/de/weather.ts b/src/locales/de/weather.ts new file mode 100644 index 00000000000..0c5635de736 --- /dev/null +++ b/src/locales/de/weather.ts @@ -0,0 +1,44 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +/** + * The weather namespace holds text displayed when weather is active during a battle + */ +export const weather: SimpleTranslationEntries = { + "sunnyStartMessage": "Die Sonne hellt auf!", + "sunnyLapseMessage": "Die Sonne blendet.", + "sunnyClearMessage": "Die Sonne schwächt ab.", + + "rainStartMessage": "Es fängt an zu regnen!", + "rainLapseMessage": "Es regnet weiterhin.", + "rainClearMessage": "Es hört auf zu regnen.", + + "sandstormStartMessage": "Ein Sandsturm braut sich zusammen!", + "sandstormLapseMessage": "Der Sandsturm tobt.", + "sandstormClearMessage": "Der Sandsturm lässt nach.", + "sandstormDamageMessage": "{{pokemonPrefix}}{{pokemonName}} ist vom\nSandsturm beeinträchtigt!", + + "hailStartMessage": "Es fängt an zu hageln!", + "hailLapseMessage": "Es hagelt weiterhin.", + "hailClearMessage": "Es hört auf zu hageln.", + "hailDamageMessage": "{{pokemonPrefix}}{{pokemonName}} ist vom\nHagel beeinträchtigt!", + + "snowStartMessage": "Es fängt an zu schneien!", + "snowLapseMessage": "Es schneit weiterhin.", + "snowClearMessage": "Es hört auf zu schneien.", + + "fogStartMessage": "Es fängt an zu nebeln!", + "fogLapseMessage": "Es nebelt weiterhin.", + "fogClearMessage": "Es hört auf zu nebeln.", + + "heavyRainStartMessage": "Ein Starkregen beginnt!", + "heavyRainLapseMessage": "Der Starkregen hält an.", + "heavyRainClearMessage": "Der Starkregen lässt nach.", + + "harshSunStartMessage": "Das Sonnenlicht wird wärmer!", + "harshSunLapseMessage": "Das Sonnenlicht brennt.", + "harshSunClearMessage": "Das Sonnenlicht schwächt ab.", + + "strongWindsStartMessage": "Ein starker Wind zieht auf!", + "strongWindsLapseMessage": "Der starke Wind tobt.", + "strongWindsClearMessage": "Der starke Wind legt sich." +} diff --git a/src/locales/en/battle-message-ui-handler.ts b/src/locales/en/battle-message-ui-handler.ts new file mode 100644 index 00000000000..346f856872c --- /dev/null +++ b/src/locales/en/battle-message-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battleMessageUiHandler: SimpleTranslationEntries = { + "ivBest": "Best", + "ivFantastic": "Fantastic", + "ivVeryGood": "Very Good", + "ivPrettyGood": "Pretty Good", + "ivDecent": "Decent", + "ivNoGood": "No Good", +} as const; \ No newline at end of file diff --git a/src/locales/en/battle.ts b/src/locales/en/battle.ts index 7c948e6f09f..a6ed2fabc64 100644 --- a/src/locales/en/battle.ts +++ b/src/locales/en/battle.ts @@ -3,6 +3,7 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}} appeared.", "trainerAppeared": "{{trainerName}}\nwould like to battle!", + "trainerAppearedDouble": "{{trainerName}}\nwould like to battle!", "singleWildAppeared": "A wild {{pokemonName}} appeared!", "multiWildAppeared": "A wild {{pokemonName1}}\nand {{pokemonName2}} appeared!", "playerComeBack": "Come back, {{pokemonName}}!", @@ -31,6 +32,8 @@ export const battle: SimpleTranslationEntries = { "learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.", "learnMoveForgetQuestion": "Which move should be forgotten?", "learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.", + "countdownPoof": "@d{32}1, @d{15}2, and@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}Poof!", + "learnMoveAnd": "And…", "levelCapUp": "The level cap\nhas increased to {{levelCap}}!", "moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.", "moveNoPP": "There's no PP left for\nthis move!", diff --git a/src/locales/en/berry.ts b/src/locales/en/berry.ts new file mode 100644 index 00000000000..8c8bc5ee280 --- /dev/null +++ b/src/locales/en/berry.ts @@ -0,0 +1,48 @@ +import { BerryTranslationEntries } from "#app/plugins/i18n"; + +export const berry: BerryTranslationEntries = { + "SITRUS": { + name: "Sitrus Berry", + effect: "Restores 25% HP if HP is below 50%", + }, + "LUM": { + name: "Lum Berry", + effect: "Cures any non-volatile status condition and confusion", + }, + "ENIGMA": { + name: "Enigma Berry", + effect: "Restores 25% HP if hit by a super effective move", + }, + "LIECHI": { + name: "Liechi Berry", + effect: "Raises Attack if HP is below 25%", + }, + "GANLON": { + name: "Ganlon Berry", + effect: "Raises Defense if HP is below 25%", + }, + "PETAYA": { + name: "Petaya Berry", + effect: "Raises Sp. Atk if HP is below 25%", + }, + "APICOT": { + name: "Apicot Berry", + effect: "Raises Sp. Def if HP is below 25%", + }, + "SALAC": { + name: "Salac Berry", + effect: "Raises Speed if HP is below 25%", + }, + "LANSAT": { + name: "Lansat Berry", + effect: "Raises critical hit ratio if HP is below 25%", + }, + "STARF": { + name: "Starf Berry", + effect: "Sharply raises a random stat if HP is below 25%", + }, + "LEPPA": { + name: "Leppa Berry", + effect: "Restores 10 PP to a move if its PP reaches 0", + }, +} as const; \ No newline at end of file diff --git a/src/locales/en/config.ts b/src/locales/en/config.ts index f5e8a68b09c..6b23d2f2983 100644 --- a/src/locales/en/config.ts +++ b/src/locales/en/config.ts @@ -2,33 +2,48 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; +import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; import { menuUiHandler } from "./menu-ui-handler"; +import { modifierType } from "./modifier-type"; import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonStat } from "./pokemon-stat"; +import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; +import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; - +import { weather } from "./weather"; +import { battleMessageUiHandler } from "./battle-message-ui-handler"; +import { berry } from "./berry"; export const enConfig = { ability: ability, abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, + egg: egg, fightUiHandler: fightUiHandler, - menuUiHandler: menuUiHandler, + growth: growth, menu: menu, + menuUiHandler: menuUiHandler, + modifierType: modifierType, move: move, - pokeball: pokeball, - pokemonStat: pokemonStat, - pokemon: pokemon, - starterSelectUiHandler: starterSelectUiHandler, - tutorial: tutorial, nature: nature, - growth: growth + pokeball: pokeball, + pokemon: pokemon, + pokemonStat: pokemonStat, + splashMessages: splashMessages, + starterSelectUiHandler: starterSelectUiHandler, + titles: titles, + trainerClasses: trainerClasses, + trainerNames: trainerNames, + tutorial: tutorial, + weather: weather, + battleMessageUiHandler: battleMessageUiHandler, + berry: berry, } \ No newline at end of file diff --git a/src/locales/en/egg.ts b/src/locales/en/egg.ts new file mode 100644 index 00000000000..358c1b4a503 --- /dev/null +++ b/src/locales/en/egg.ts @@ -0,0 +1,21 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const egg: SimpleTranslationEntries = { + "egg": "Egg", + "greatTier": "Rare", + "ultraTier": "Epic", + "masterTier": "Legendary", + "defaultTier": "Common", + "hatchWavesMessageSoon": "Sounds can be heard coming from inside! It will hatch soon!", + "hatchWavesMessageClose": "It appears to move occasionally. It may be close to hatching.", + "hatchWavesMessageNotClose": "What will hatch from this? It doesn't seem close to hatching.", + "hatchWavesMessageLongTime": "It looks like this Egg will take a long time to hatch.", + "gachaTypeLegendary": "Legendary Rate Up", + "gachaTypeMove": "Rare Egg Move Rate Up", + "gachaTypeShiny": "Shiny Rate Up", + "selectMachine": "Select a machine.", + "notEnoughVouchers": "You don't have enough vouchers!", + "tooManyEggs": "You have too many eggs!", + "pull": "Pull", + "pulls": "Pulls" +} as const; \ No newline at end of file diff --git a/src/locales/en/menu-ui-handler.ts b/src/locales/en/menu-ui-handler.ts index 5fde37ae360..eb8e474ee60 100644 --- a/src/locales/en/menu-ui-handler.ts +++ b/src/locales/en/menu-ui-handler.ts @@ -9,7 +9,7 @@ export const menuUiHandler: SimpleTranslationEntries = { "EGG_GACHA": "Egg Gacha", "MANAGE_DATA": "Manage Data", "COMMUNITY": "Community", - "RETURN_TO_TITLE": "Return To Title", + "SAVE_AND_QUIT": "Save and Quit", "LOG_OUT": "Log Out", "slot": "Slot {{slotNumber}}", "importSession": "Import Session", diff --git a/src/locales/en/menu.ts b/src/locales/en/menu.ts index 7a5043a98e2..7db9ea3aa6a 100644 --- a/src/locales/en/menu.ts +++ b/src/locales/en/menu.ts @@ -35,6 +35,11 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "Are you a boy or a girl?", "boy": "Boy", "girl": "Girl", + "evolving": "What?\n{{pokemonName}} is evolving!", + "stoppedEvolving": "{{pokemonName}} stopped evolving.", + "pauseEvolutionsQuestion": "Would you like to pause evolutions for {{pokemonName}}?\nEvolutions can be re-enabled from the party screen.", + "evolutionsPaused": "Evolutions have been paused for {{pokemonName}}.", + "evolutionDone": "Congratulations!\nYour {{pokemonName}} evolved into {{evolvedPokemonName}}!", "dailyRankings": "Daily Rankings", "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", diff --git a/src/locales/en/modifier-type.ts b/src/locales/en/modifier-type.ts new file mode 100644 index 00000000000..043d7a705d5 --- /dev/null +++ b/src/locales/en/modifier-type.ts @@ -0,0 +1,409 @@ +import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; + +export const modifierType: ModifierTypeTranslationEntries = { + ModifierType: { + "AddPokeballModifierType": { + name: "{{modifierCount}}x {{pokeballName}}", + description: "Receive {{pokeballName}} x{{modifierCount}} (Inventory: {{pokeballAmount}}) \nCatch Rate: {{catchRate}}", + }, + "AddVoucherModifierType": { + name: "{{modifierCount}}x {{voucherTypeName}}", + description: "Receive {{voucherTypeName}} x{{modifierCount}}", + }, + "PokemonHeldItemModifierType": { + extra: { + "inoperable": "{{pokemonName}} can't take\nthis item!", + "tooMany": "{{pokemonName}} has too many\nof this item!", + } + }, + "PokemonHpRestoreModifierType": { + description: "Restores {{restorePoints}} HP or {{restorePercent}}% HP for one Pokémon, whichever is higher", + extra: { + "fully": "Fully restores HP for one Pokémon", + "fullyWithStatus": "Fully restores HP for one Pokémon and heals any status ailment", + } + }, + "PokemonReviveModifierType": { + description: "Revives one Pokémon and restores {{restorePercent}}% HP", + }, + "PokemonStatusHealModifierType": { + description: "Heals any status ailment for one Pokémon", + }, + "PokemonPpRestoreModifierType": { + description: "Restores {{restorePoints}} PP for one Pokémon move", + extra: { + "fully": "Restores all PP for one Pokémon move", + } + }, + "PokemonAllMovePpRestoreModifierType": { + description: "Restores {{restorePoints}} PP for all of one Pokémon's moves", + extra: { + "fully": "Restores all PP for all of one Pokémon's moves", + } + }, + "PokemonPpUpModifierType": { + description: "Permanently increases PP for one Pokémon move by {{upPoints}} for every 5 maximum PP (maximum 3)", + }, + "PokemonNatureChangeModifierType": { + name: "{{natureName}} Mint", + description: "Changes a Pokémon's nature to {{natureName}} and permanently unlocks the nature for the starter.", + }, + "DoubleBattleChanceBoosterModifierType": { + description: "Doubles the chance of an encounter being a double battle for {{battleCount}} battles", + }, + "TempBattleStatBoosterModifierType": { + description: "Increases the {{tempBattleStatName}} of all party members by 1 stage for 5 battles", + }, + "AttackTypeBoosterModifierType": { + description: "Increases the power of a Pokémon's {{moveType}}-type moves by 20%", + }, + "PokemonLevelIncrementModifierType": { + description: "Increases a Pokémon's level by 1", + }, + "AllPokemonLevelIncrementModifierType": { + description: "Increases all party members' level by 1", + }, + "PokemonBaseStatBoosterModifierType": { + description: "Increases the holder's base {{statName}} by 10%. The higher your IVs, the higher the stack limit.", + }, + "AllPokemonFullHpRestoreModifierType": { + description: "Restores 100% HP for all Pokémon", + }, + "AllPokemonFullReviveModifierType": { + description: "Revives all fainted Pokémon, fully restoring HP", + }, + "MoneyRewardModifierType": { + description: "Grants a {{moneyMultiplier}} amount of money (₽{{moneyAmount}})", + extra: { + "small": "small", + "moderate": "moderate", + "large": "large", + }, + }, + "ExpBoosterModifierType": { + description: "Increases gain of EXP. Points by {{boostPercent}}%", + }, + "PokemonExpBoosterModifierType": { + description: "Increases the holder's gain of EXP. Points by {{boostPercent}}%", + }, + "PokemonFriendshipBoosterModifierType": { + description: "Increases friendship gain per victory by 50%", + }, + "PokemonMoveAccuracyBoosterModifierType": { + description: "Increases move accuracy by {{accuracyAmount}} (maximum 100)", + }, + "PokemonMultiHitModifierType": { + description: "Attacks hit one additional time at the cost of a 60/75/82.5% power reduction per stack respectively", + }, + "TmModifierType": { + name: "TM{{moveId}} - {{moveName}}", + description: "Teach {{moveName}} to a Pokémon", + }, + "EvolutionItemModifierType": { + description: "Causes certain Pokémon to evolve", + }, + "FormChangeItemModifierType": { + description: "Causes certain Pokémon to change form", + }, + "FusePokemonModifierType": { + description: "Combines two Pokémon (transfers Ability, splits base stats and types, shares move pool)", + }, + "TerastallizeModifierType": { + name: "{{teraType}} Tera Shard", + description: "{{teraType}} Terastallizes the holder for up to 10 battles", + }, + "ContactHeldItemTransferChanceModifierType": { + description: "Upon attacking, there is a {{chancePercent}}% chance the foe's held item will be stolen", + }, + "TurnHeldItemTransferModifierType": { + description: "Every turn, the holder acquires one held item from the foe", + }, + "EnemyAttackStatusEffectChanceModifierType": { + description: "Adds a {{chancePercent}}% chance to inflict {{statusEffect}} with attack moves", + }, + "EnemyEndureChanceModifierType": { + description: "Adds a {{chancePercent}}% chance of enduring a hit", + }, + + "RARE_CANDY": { name: "Rare Candy" }, + "RARER_CANDY": { name: "Rarer Candy" }, + + "MEGA_BRACELET": { name: "Mega Bracelet", description: "Mega Stones become available" }, + "DYNAMAX_BAND": { name: "Dynamax Band", description: "Max Mushrooms become available" }, + "TERA_ORB": { name: "Tera Orb", description: "Tera Shards become available" }, + + "MAP": { name: "Map", description: "Allows you to choose your destination at a crossroads" }, + + "POTION": { name: "Potion" }, + "SUPER_POTION": { name: "Super Potion" }, + "HYPER_POTION": { name: "Hyper Potion" }, + "MAX_POTION": { name: "Max Potion" }, + "FULL_RESTORE": { name: "Full Restore" }, + + "REVIVE": { name: "Revive" }, + "MAX_REVIVE": { name: "Max Revive" }, + + "FULL_HEAL": { name: "Full Heal" }, + + "SACRED_ASH": { name: "Sacred Ash" }, + + "REVIVER_SEED": { name: "Reviver Seed", description: "Revives the holder for 1/2 HP upon fainting" }, + + "ETHER": { name: "Ether" }, + "MAX_ETHER": { name: "Max Ether" }, + + "ELIXIR": { name: "Elixir" }, + "MAX_ELIXIR": { name: "Max Elixir" }, + + "PP_UP": { name: "PP Up" }, + "PP_MAX": { name: "PP Max" }, + + "LURE": { name: "Lure" }, + "SUPER_LURE": { name: "Super Lure" }, + "MAX_LURE": { name: "Max Lure" }, + + "MEMORY_MUSHROOM": { name: "Memory Mushroom", description: "Recall one Pokémon's forgotten move" }, + + "EXP_SHARE": { name: "EXP. All", description: "Non-participants receive 20% of a single participant's EXP. Points" }, + "EXP_BALANCE": { name: "EXP. Balance", description: "Weighs EXP. Points received from battles towards lower-leveled party members" }, + + "OVAL_CHARM": { name: "Oval Charm", description: "When multiple Pokémon participate in a battle, each gets an extra 10% of the total EXP" }, + + "EXP_CHARM": { name: "EXP. Charm" }, + "SUPER_EXP_CHARM": { name: "Super EXP. Charm" }, + "GOLDEN_EXP_CHARM": { name: "Golden EXP. Charm" }, + + "LUCKY_EGG": { name: "Lucky Egg" }, + "GOLDEN_EGG": { name: "Golden Egg" }, + + "SOOTHE_BELL": { name: "Soothe Bell" }, + + "SOUL_DEW": { name: "Soul Dew", description: "Increases the influence of a Pokémon's nature on its stats by 10% (additive)" }, + + "NUGGET": { name: "Nugget" }, + "BIG_NUGGET": { name: "Big Nugget" }, + "RELIC_GOLD": { name: "Relic Gold" }, + + "AMULET_COIN": { name: "Amulet Coin", description: "Increases money rewards by 20%" }, + "GOLDEN_PUNCH": { name: "Golden Punch", description: "Grants 50% of damage inflicted as money" }, + "COIN_CASE": { name: "Coin Case", description: "After every 10th battle, receive 10% of your money in interest" }, + + "LOCK_CAPSULE": { name: "Lock Capsule", description: "Allows you to lock item rarities when rerolling items" }, + + "GRIP_CLAW": { name: "Grip Claw" }, + "WIDE_LENS": { name: "Wide Lens" }, + + "MULTI_LENS": { name: "Multi Lens" }, + + "HEALING_CHARM": { name: "Healing Charm", description: "Increases the effectiveness of HP restoring moves and items by 10% (excludes Revives)" }, + "CANDY_JAR": { name: "Candy Jar", description: "Increases the number of levels added by Rare Candy items by 1" }, + + "BERRY_POUCH": { name: "Berry Pouch", description: "Adds a 25% chance that a used berry will not be consumed" }, + + "FOCUS_BAND": { name: "Focus Band", description: "Adds a 10% chance to survive with 1 HP after being damaged enough to faint" }, + + "QUICK_CLAW": { name: "Quick Claw", description: "Adds a 10% chance to move first regardless of speed (after priority)" }, + + "KINGS_ROCK": { name: "King's Rock", description: "Adds a 10% chance an attack move will cause the opponent to flinch" }, + + "LEFTOVERS": { name: "Leftovers", description: "Heals 1/16 of a Pokémon's maximum HP every turn" }, + "SHELL_BELL": { name: "Shell Bell", description: "Heals 1/8 of a Pokémon's dealt damage" }, + + "BATON": { name: "Baton", description: "Allows passing along effects when switching Pokémon, which also bypasses traps" }, + + "SHINY_CHARM": { name: "Shiny Charm", description: "Dramatically increases the chance of a wild Pokémon being Shiny" }, + "ABILITY_CHARM": { name: "Ability Charm", description: "Dramatically increases the chance of a wild Pokémon having a Hidden Ability" }, + + "IV_SCANNER": { name: "IV Scanner", description: "Allows scanning the IVs of wild Pokémon. 2 IVs are revealed per stack. The best IVs are shown first" }, + + "DNA_SPLICERS": { name: "DNA Splicers" }, + + "MINI_BLACK_HOLE": { name: "Mini Black Hole" }, + + "GOLDEN_POKEBALL": { name: "Golden Poké Ball", description: "Adds 1 extra item option at the end of every battle" }, + + "ENEMY_DAMAGE_BOOSTER": { name: "Damage Token", description: "Increases damage by 5%" }, + "ENEMY_DAMAGE_REDUCTION": { name: "Protection Token", description: "Reduces incoming damage by 2.5%" }, + "ENEMY_HEAL": { name: "Recovery Token", description: "Heals 2% of max HP every turn" }, + "ENEMY_ATTACK_POISON_CHANCE": { name: "Poison Token" }, + "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Paralyze Token" }, + "ENEMY_ATTACK_SLEEP_CHANCE": { name: "Sleep Token" }, + "ENEMY_ATTACK_FREEZE_CHANCE": { name: "Freeze Token" }, + "ENEMY_ATTACK_BURN_CHANCE": { name: "Burn Token" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Adds a 10% chance every turn to heal a status condition" }, + "ENEMY_ENDURE_CHANCE": { name: "Endure Token" }, + "ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Adds a 1% chance that a wild Pokémon will be a fusion" }, + }, + TempBattleStatBoosterItem: { + "x_attack": "X Attack", + "x_defense": "X Defense", + "x_sp_atk": "X Sp. Atk", + "x_sp_def": "X Sp. Def", + "x_speed": "X Speed", + "x_accuracy": "X Accuracy", + "dire_hit": "Dire Hit", + }, + AttackTypeBoosterItem: { + "silk_scarf": "Silk Scarf", + "black_belt": "Black Belt", + "sharp_beak": "Sharp Beak", + "poison_barb": "Poison Barb", + "soft_sand": "Soft Sand", + "hard_stone": "Hard Stone", + "silver_powder": "Silver Powder", + "spell_tag": "Spell Tag", + "metal_coat": "Metal Coat", + "charcoal": "Charcoal", + "mystic_water": "Mystic Water", + "miracle_seed": "Miracle Seed", + "magnet": "Magnet", + "twisted_spoon": "Twisted Spoon", + "never_melt_ice": "Never-Melt Ice", + "dragon_fang": "Dragon Fang", + "black_glasses": "Black Glasses", + "fairy_feather": "Fairy Feather", + }, + BaseStatBoosterItem: { + "hp_up": "HP Up", + "protein": "Protein", + "iron": "Iron", + "calcium": "Calcium", + "zinc": "Zinc", + "carbos": "Carbos", + }, + EvolutionItem: { + "NONE": "None", + + "LINKING_CORD": "Linking Cord", + "SUN_STONE": "Sun Stone", + "MOON_STONE": "Moon Stone", + "LEAF_STONE": "Leaf Stone", + "FIRE_STONE": "Fire Stone", + "WATER_STONE": "Water Stone", + "THUNDER_STONE": "Thunder Stone", + "ICE_STONE": "Ice Stone", + "DUSK_STONE": "Dusk Stone", + "DAWN_STONE": "Dawn Stone", + "SHINY_STONE": "Shiny Stone", + "CRACKED_POT": "Cracked Pot", + "SWEET_APPLE": "Sweet Apple", + "TART_APPLE": "Tart Apple", + "STRAWBERRY_SWEET": "Strawberry Sweet", + "UNREMARKABLE_TEACUP": "Unremarkable Teacup", + + "CHIPPED_POT": "Chipped Pot", + "BLACK_AUGURITE": "Black Augurite", + "GALARICA_CUFF": "Galarica Cuff", + "GALARICA_WREATH": "Galarica Wreath", + "PEAT_BLOCK": "Peat Block", + "AUSPICIOUS_ARMOR": "Auspicious Armor", + "MALICIOUS_ARMOR": "Malicious Armor", + "MASTERPIECE_TEACUP": "Masterpiece Teacup", + "METAL_ALLOY": "Metal Alloy", + "SCROLL_OF_DARKNESS": "Scroll Of Darkness", + "SCROLL_OF_WATERS": "Scroll Of Waters", + "SYRUPY_APPLE": "Syrupy Apple", + }, + FormChangeItem: { + "NONE": "None", + + "ABOMASITE": "Abomasite", + "ABSOLITE": "Absolite", + "AERODACTYLITE": "Aerodactylite", + "AGGRONITE": "Aggronite", + "ALAKAZITE": "Alakazite", + "ALTARIANITE": "Altarianite", + "AMPHAROSITE": "Ampharosite", + "AUDINITE": "Audinite", + "BANETTITE": "Banettite", + "BEEDRILLITE": "Beedrillite", + "BLASTOISINITE": "Blastoisinite", + "BLAZIKENITE": "Blazikenite", + "CAMERUPTITE": "Cameruptite", + "CHARIZARDITE_X": "Charizardite X", + "CHARIZARDITE_Y": "Charizardite Y", + "DIANCITE": "Diancite", + "GALLADITE": "Galladite", + "GARCHOMPITE": "Garchompite", + "GARDEVOIRITE": "Gardevoirite", + "GENGARITE": "Gengarite", + "GLALITITE": "Glalitite", + "GYARADOSITE": "Gyaradosite", + "HERACRONITE": "Heracronite", + "HOUNDOOMINITE": "Houndoominite", + "KANGASKHANITE": "Kangaskhanite", + "LATIASITE": "Latiasite", + "LATIOSITE": "Latiosite", + "LOPUNNITE": "Lopunnite", + "LUCARIONITE": "Lucarionite", + "MANECTITE": "Manectite", + "MAWILITE": "Mawilite", + "MEDICHAMITE": "Medichamite", + "METAGROSSITE": "Metagrossite", + "MEWTWONITE_X": "Mewtwonite X", + "MEWTWONITE_Y": "Mewtwonite Y", + "PIDGEOTITE": "Pidgeotite", + "PINSIRITE": "Pinsirite", + "RAYQUAZITE": "Rayquazite", + "SABLENITE": "Sablenite", + "SALAMENCITE": "Salamencite", + "SCEPTILITE": "Sceptilite", + "SCIZORITE": "Scizorite", + "SHARPEDONITE": "Sharpedonite", + "SLOWBRONITE": "Slowbronite", + "STEELIXITE": "Steelixite", + "SWAMPERTITE": "Swampertite", + "TYRANITARITE": "Tyranitarite", + "VENUSAURITE": "Venusaurite", + + "BLUE_ORB": "Blue Orb", + "RED_ORB": "Red Orb", + "SHARP_METEORITE": "Sharp Meteorite", + "HARD_METEORITE": "Hard Meteorite", + "SMOOTH_METEORITE": "Smooth Meteorite", + "ADAMANT_CRYSTAL": "Adamant Crystal", + "LUSTROUS_ORB": "Lustrous Orb", + "GRISEOUS_CORE": "Griseous Core", + "REVEAL_GLASS": "Reveal Glass", + "GRACIDEA": "Gracidea", + "MAX_MUSHROOMS": "Max Mushrooms", + "DARK_STONE": "Dark Stone", + "LIGHT_STONE": "Light Stone", + "PRISON_BOTTLE": "Prison Bottle", + "N_LUNARIZER": "N Lunarizer", + "N_SOLARIZER": "N Solarizer", + "RUSTED_SWORD": "Rusted Sword", + "RUSTED_SHIELD": "Rusted Shield", + "ICY_REINS_OF_UNITY": "Icy Reins Of Unity", + "SHADOW_REINS_OF_UNITY": "Shadow Reins Of Unity", + "WELLSPRING_MASK": "Wellspring Mask", + "HEARTHFLAME_MASK": "Hearthflame Mask", + "CORNERSTONE_MASK": "Cornerstone Mask", + "SHOCK_DRIVE": "Shock Drive", + "BURN_DRIVE": "Burn Drive", + "CHILL_DRIVE": "Chill Drive", + "DOUSE_DRIVE": "Douse Drive", + }, + TeraType: { + "UNKNOWN": "Unknown", + "NORMAL": "Normal", + "FIGHTING": "Fighting", + "FLYING": "Flying", + "POISON": "Poison", + "GROUND": "Ground", + "ROCK": "Rock", + "BUG": "Bug", + "GHOST": "Ghost", + "STEEL": "Steel", + "FIRE": "Fire", + "WATER": "Water", + "GRASS": "Grass", + "ELECTRIC": "Electric", + "PSYCHIC": "Psychic", + "ICE": "Ice", + "DRAGON": "Dragon", + "DARK": "Dark", + "FAIRY": "Fairy", + "STELLAR": "Stellar", + }, +} as const; \ No newline at end of file diff --git a/src/locales/en/splash-messages.ts b/src/locales/en/splash-messages.ts new file mode 100644 index 00000000000..6815d7f1824 --- /dev/null +++ b/src/locales/en/splash-messages.ts @@ -0,0 +1,37 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const splashMessages: SimpleTranslationEntries = { + "battlesWon": "Battles Won!", + "joinTheDiscord": "Join the Discord!", + "infiniteLevels": "Infinite Levels!", + "everythingStacks": "Everything Stacks!", + "optionalSaveScumming": "Optional Save Scumming!", + "biomes": "35 Biomes!", + "openSource": "Open Source!", + "playWithSpeed": "Play with 5x Speed!", + "liveBugTesting": "Live Bug Testing!", + "heavyInfluence": "Heavy RoR2 Influence!", + "pokemonRiskAndPokemonRain": "Pokémon Risk and Pokémon Rain!", + "nowWithMoreSalt": "Now with 33% More Salt!", + "infiniteFusionAtHome": "Infinite Fusion at Home!", + "brokenEggMoves": "Broken Egg Moves!", + "magnificent": "Magnificent!", + "mubstitute": "Mubstitute!", + "thatsCrazy": "That\'s Crazy!", + "oranceJuice": "Orance Juice!", + "questionableBalancing": "Questionable Balancing!", + "coolShaders": "Cool Shaders!", + "aiFree": "AI-Free!", + "suddenDifficultySpikes": "Sudden Difficulty Spikes!", + "basedOnAnUnfinishedFlashGame": "Based on an Unfinished Flash Game!", + "moreAddictiveThanIntended": "More Addictive than Intended!", + "mostlyConsistentSeeds": "Mostly Consistent Seeds!", + "achievementPointsDontDoAnything": "Achievement Points Don\'t Do Anything!", + "youDoNotStartAtLevel": "You Do Not Start at Level 2000!", + "dontTalkAboutTheManaphyEggIncident": "Don\'t Talk About the Manaphy Egg Incident!", + "alsoTryPokengine": "Also Try Pokéngine!", + "alsoTryEmeraldRogue": "Also Try Emerald Rogue!", + "alsoTryRadicalRed": "Also Try Radical Red!", + "eeveeExpo": "Eevee Expo!", + "ynoproject": "YNOproject!", +} as const; \ No newline at end of file diff --git a/src/locales/en/starter-select-ui-handler.ts b/src/locales/en/starter-select-ui-handler.ts index 2acceab69ff..19f8649dcc3 100644 --- a/src/locales/en/starter-select-ui-handler.ts +++ b/src/locales/en/starter-select-ui-handler.ts @@ -7,6 +7,15 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; */ export const starterSelectUiHandler: SimpleTranslationEntries = { "confirmStartTeam":'Begin with these Pokémon?', + "gen1": "I", + "gen2": "II", + "gen3": "III", + "gen4": "IV", + "gen5": "V", + "gen6": "VI", + "gen7": "VII", + "gen8": "VIII", + "gen9": "IX", "growthRate": "Growth Rate:", "ability": "Ability:", "passive": "Passive:", @@ -32,4 +41,4 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "locked": "Locked", "disabled": "Disabled", "uncaught": "Uncaught" -} \ No newline at end of file +} diff --git a/src/locales/en/trainers.ts b/src/locales/en/trainers.ts new file mode 100644 index 00000000000..d824baeba8f --- /dev/null +++ b/src/locales/en/trainers.ts @@ -0,0 +1,244 @@ +import {SimpleTranslationEntries} from "#app/plugins/i18n"; + +// Titles of special trainers like gym leaders, elite four, and the champion +export const titles: SimpleTranslationEntries = { + "elite_four": "Elite Four", + "gym_leader": "Gym Leader", + "gym_leader_female": "Gym Leader", + "champion": "Champion", + "rival": "Rival", + "professor": "Professor", + "frontier_brain": "Frontier Brain", + // Maybe if we add the evil teams we can add "Team Rocket" and "Team Aqua" etc. here as well as "Team Rocket Boss" and "Team Aqua Admin" etc. +} as const; + +// Titles of trainers like "Youngster" or "Lass" +export const trainerClasses: SimpleTranslationEntries = { + "ace_trainer": "Ace Trainer", + "ace_trainer_female": "Ace Trainer", + "ace_duo": "Ace Duo", + "artist": "Artist", + "artist_female": "Artist", + "backers": "Backers", + "backpacker": "Backpacker", + "backpacker_female": "Backpacker", + "backpackers": "Backpackers", + "baker": "Baker", + "battle_girl": "Battle Girl", + "beauty": "Beauty", + "beginners": "Beginners", + "biker": "Biker", + "black_belt": "Black Belt", + "breeder": "Breeder", + "breeder_female": "Breeder", + "breeders": "Breeders", + "clerk": "Clerk", + "clerk_female": "Clerk", + "colleagues": "Colleagues", + "crush_kin": "Crush Kin", + "cyclist": "Cyclist", + "cyclist_female": "Cyclist", + "cyclists": "Cyclists", + "dancer": "Dancer", + "dancer_female": "Dancer", + "depot_agent": "Depot Agent", + "doctor": "Doctor", + "doctor_female": "Doctor", + "fisherman": "Fisherman", + "fisherman_female": "Fisherman", + "gentleman": "Gentleman", + "guitarist": "Guitarist", + "guitarist_female": "Guitarist", + "harlequin": "Harlequin", + "hiker": "Hiker", + "hooligans": "Hooligans", + "hoopster": "Hoopster", + "infielder": "Infielder", + "janitor": "Janitor", + "lady": "Lady", + "lass": "Lass", + "linebacker": "Linebacker", + "maid": "Maid", + "madame": "Madame", + "medical_team": "Medical Team", + "musician": "Musician", + "hex_maniac": "Hex Maniac", + "nurse": "Nurse", + "nursery_aide": "Nursery Aide", + "officer": "Officer", + "parasol_lady": "Parasol Lady", + "pilot": "Pilot", + "pokefan": "Poké Fan", + "pokefan_family": "Poké Fan Family", + "preschooler": "Preschooler", + "preschooler_female": "Preschooler", + "preschoolers": "Preschoolers", + "psychic": "Psychic", + "psychic_female": "Psychic", + "psychics": "Psychics", + "pokémon_ranger": "Pokémon Ranger", + "pokémon_rangers": "Pokémon Ranger", + "ranger": "Ranger", + "restaurant_staff": "Restaurant Staff", + "rich": "Rich", + "rich_female": "Rich", + "rich_boy": "Rich Boy", + "rich_couple": "Rich Couple", + "rich_kid": "Rich Kid", + "rich_kid_female": "Rich Kid", + "rich_kids": "Rich Kids", + "roughneck": "Roughneck", + "scientist": "Scientist", + "scientist_female": "Scientist", + "scientists": "Scientists", + "smasher": "Smasher", + "snow_worker": "Snow Worker", + "snow_worker_female": "Snow Worker", + "striker": "Striker", + "school_kid": "School Kid", + "school_kid_female": "School Kid", + "school_kids": "School Kids", + "swimmer": "Swimmer", + "swimmer_female": "Swimmer", + "swimmers": "Swimmers", + "twins": "Twins", + "veteran": "Veteran", + "veteran_female": "Veteran", + "veteran_duo": "Veteran Duo", + "waiter": "Waiter", + "waitress": "Waitress", + "worker": "Worker", + "worker_female": "Worker", + "workers": "Workers", + "youngster": "Youngster" +} as const; + +// Names of special trainers like gym leaders, elite four, and the champion +export const trainerNames: SimpleTranslationEntries = { + "brock": "Brock", + "misty": "Misty", + "lt_surge": "Lt Surge", + "erika": "Erika", + "janine": "Janine", + "sabrina": "Sabrina", + "blaine": "Blaine", + "giovanni": "Giovanni", + "falkner": "Falkner", + "bugsy": "Bugsy", + "whitney": "Whitney", + "morty": "Morty", + "chuck": "Chuck", + "jasmine": "Jasmine", + "pryce": "Pryce", + "clair": "Clair", + "roxanne": "Roxanne", + "brawly": "Brawly", + "wattson": "Wattson", + "flannery": "Flannery", + "norman": "Norman", + "winona": "Winona", + "tate": "Tate", + "liza": "Liza", + "juan": "Juan", + "roark": "Roark", + "gardenia": "Gardenia", + "maylene": "Maylene", + "crasher_wake": "Crasher Wake", + "fantina": "Fantina", + "byron": "Byron", + "candice": "Candice", + "volkner": "Volkner", + "cilan": "Cilan", + "chili": "Chili", + "cress": "Cress", + "cheren": "Cheren", + "lenora": "Lenora", + "roxie": "Roxie", + "burgh": "Burgh", + "elesa": "Elesa", + "clay": "Clay", + "skyla": "Skyla", + "brycen": "Brycen", + "drayden": "Drayden", + "marlon": "Marlon", + "viola": "Viola", + "grant": "Grant", + "korrina": "Korrina", + "ramos": "Ramos", + "clemont": "Clemont", + "valerie": "Valerie", + "olympia": "Olympia", + "wulfric": "Wulfric", + "milo": "Milo", + "nessa": "Nessa", + "kabu": "Kabu", + "bea": "Bea", + "allister": "Allister", + "opal": "Opal", + "bede": "Bede", + "gordie": "Gordie", + "melony": "Melony", + "piers": "Piers", + "marnie": "Marnie", + "raihan": "Raihan", + "katy": "Katy", + "brassius": "Brassius", + "iono": "Iono", + "kofu": "Kofu", + "larry": "Larry", + "ryme": "Ryme", + "tulip": "Tulip", + "grusha": "Grusha", + "lorelei": "Lorelei", + "bruno": "Bruno", + "agatha": "Agatha", + "lance": "Lance", + "will": "Will", + "koga": "Koga", + "karen": "Karen", + "sidney": "Sidney", + "phoebe": "Phoebe", + "glacia": "Glacia", + "drake": "Drake", + "aaron": "Aaron", + "bertha": "Bertha", + "flint": "Flint", + "lucian": "Lucian", + "shauntal": "Shauntal", + "marshal": "Marshal", + "grimsley": "Grimsley", + "caitlin": "Caitlin", + "malva": "Malva", + "siebold": "Siebold", + "wikstrom": "Wikstrom", + "drasna": "Drasna", + "hala": "Hala", + "molayne": "Molayne", + "olivia": "Olivia", + "acerola": "Acerola", + "kahili": "Kahili", + "rika": "Rika", + "poppy": "Poppy", + "larry_elite": "Larry", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "hassel": "Hassel", + "crispin": "Crispin", + "amarys": "Amarys", + "lacey": "Lacey", + "drayton": "Drayton", + "blue": "Blue", + "red": "Red", + "lance_champion": "Lance", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "steven": "Steven", + "wallace": "Wallace", + "cynthia": "Cynthia", + "alder": "Alder", + "iris": "Iris", + "diantha": "Diantha", + "hau": "Hau", + "geeta": "Geeta", + "nemona": "Nemona", + "kieran": "Kieran", + "leon": "Leon", + "rival": "Finn", + "rival_female": "Ivy", +} as const; diff --git a/src/locales/en/weather.ts b/src/locales/en/weather.ts new file mode 100644 index 00000000000..999613f1566 --- /dev/null +++ b/src/locales/en/weather.ts @@ -0,0 +1,44 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +/** + * The weather namespace holds text displayed when weather is active during a battle + */ +export const weather: SimpleTranslationEntries = { + "sunnyStartMessage": "The sunlight got bright!", + "sunnyLapseMessage": "The sunlight is strong.", + "sunnyClearMessage": "The sunlight faded.", + + "rainStartMessage": "A downpour started!", + "rainLapseMessage": "The downpour continues.", + "rainClearMessage": "The rain stopped.", + + "sandstormStartMessage": "A sandstorm brewed!", + "sandstormLapseMessage": "The sandstorm rages.", + "sandstormClearMessage": "The sandstorm subsided.", + "sandstormDamageMessage": "{{pokemonPrefix}}{{pokemonName}} is buffeted\nby the sandstorm!", + + "hailStartMessage": "It started to hail!", + "hailLapseMessage": "Hail continues to fall.", + "hailClearMessage": "The hail stopped.", + "hailDamageMessage": "{{pokemonPrefix}}{{pokemonName}} is pelted\nby the hail!", + + "snowStartMessage": "It started to snow!", + "snowLapseMessage": "The snow is falling down.", + "snowClearMessage": "The snow stopped.", + + "fogStartMessage": "A thick fog emerged!", + "fogLapseMessage": "The fog continues.", + "fogClearMessage": "The fog disappeared.", + + "heavyRainStartMessage": "A heavy downpour started!", + "heavyRainLapseMessage": "The heavy downpour continues.", + "heavyRainClearMessage": "The heavy rain stopped.", + + "harshSunStartMessage": "The sunlight got hot!", + "harshSunLapseMessage": "The sun is scorching hot.", + "harshSunClearMessage": "The harsh sunlight faded.", + + "strongWindsStartMessage": "A heavy wind began!", + "strongWindsLapseMessage": "The wind blows intensely.", + "strongWindsClearMessage": "The heavy wind stopped." +} \ No newline at end of file diff --git a/src/locales/es/battle-message-ui-handler.ts b/src/locales/es/battle-message-ui-handler.ts new file mode 100644 index 00000000000..346f856872c --- /dev/null +++ b/src/locales/es/battle-message-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battleMessageUiHandler: SimpleTranslationEntries = { + "ivBest": "Best", + "ivFantastic": "Fantastic", + "ivVeryGood": "Very Good", + "ivPrettyGood": "Pretty Good", + "ivDecent": "Decent", + "ivNoGood": "No Good", +} as const; \ No newline at end of file diff --git a/src/locales/es/battle.ts b/src/locales/es/battle.ts index 6fdcf4fbc86..5715c58ece0 100644 --- a/src/locales/es/battle.ts +++ b/src/locales/es/battle.ts @@ -3,6 +3,7 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const battle: SimpleTranslationEntries = { "bossAppeared": "¡{{bossName}} te corta el paso!", "trainerAppeared": "¡{{trainerName}}\nte desafía!", + "trainerAppearedDouble": "{{trainerName}}\nwould like to battle!", "singleWildAppeared": "¡Un {{pokemonName}} salvaje te corta el paso!", "multiWildAppeared": "¡Un {{pokemonName1}} y un {{pokemonName2}} salvajes\nte cortan el paso!", "playerComeBack": "¡{{pokemonName}}, ven aquí!", @@ -14,11 +15,11 @@ export const battle: SimpleTranslationEntries = { "pokemonCaught": "¡{{pokemonName}} atrapado!", "pokemon": "Pokémon", "sendOutPokemon": "¡Adelante, {{pokemonName}}!", - "hitResultCriticalHit": "A critical hit!", - "hitResultSuperEffective": "It's super effective!", - "hitResultNotVeryEffective": "It's not very effective…", - "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", - "hitResultOneHitKO": "It's a one-hit KO!", + "hitResultCriticalHit": "!Un golpe crítico!", + "hitResultSuperEffective": "!Es supereficaz!", + "hitResultNotVeryEffective": "No es muy eficaz…", + "hitResultNoEffect": "No afecta a {{pokemonName}}!", + "hitResultOneHitKO": "!KO en 1 golpe!", "attackFailed": "¡Pero ha fallado!", "attackHitsCount": `N.º de golpes: {{count}}.`, "expGain": "{{pokemonName}} ha ganado\n{{exp}} puntos de experiencia.", @@ -31,6 +32,8 @@ export const battle: SimpleTranslationEntries = { "learnMoveNotLearned": "{{pokemonName}} no ha aprendido {{moveName}}.", "learnMoveForgetQuestion": "¿Qué movimiento quieres que olvide?", "learnMoveForgetSuccess": "{{pokemonName}} ha olvidado cómo utilizar {{moveName}}.", + "countdownPoof": "@d{32}1, @d{15}2, @d{15}y@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}¡Puf!", + "learnMoveAnd": "Y…", "levelCapUp": "¡Se ha incrementado el\nnivel máximo a {{levelCap}}!", "moveNotImplemented": "{{moveName}} aún no está implementado y no se puede seleccionar.", "moveNoPP": "There's no PP left for\nthis move!", diff --git a/src/locales/es/berry.ts b/src/locales/es/berry.ts new file mode 100644 index 00000000000..8c8bc5ee280 --- /dev/null +++ b/src/locales/es/berry.ts @@ -0,0 +1,48 @@ +import { BerryTranslationEntries } from "#app/plugins/i18n"; + +export const berry: BerryTranslationEntries = { + "SITRUS": { + name: "Sitrus Berry", + effect: "Restores 25% HP if HP is below 50%", + }, + "LUM": { + name: "Lum Berry", + effect: "Cures any non-volatile status condition and confusion", + }, + "ENIGMA": { + name: "Enigma Berry", + effect: "Restores 25% HP if hit by a super effective move", + }, + "LIECHI": { + name: "Liechi Berry", + effect: "Raises Attack if HP is below 25%", + }, + "GANLON": { + name: "Ganlon Berry", + effect: "Raises Defense if HP is below 25%", + }, + "PETAYA": { + name: "Petaya Berry", + effect: "Raises Sp. Atk if HP is below 25%", + }, + "APICOT": { + name: "Apicot Berry", + effect: "Raises Sp. Def if HP is below 25%", + }, + "SALAC": { + name: "Salac Berry", + effect: "Raises Speed if HP is below 25%", + }, + "LANSAT": { + name: "Lansat Berry", + effect: "Raises critical hit ratio if HP is below 25%", + }, + "STARF": { + name: "Starf Berry", + effect: "Sharply raises a random stat if HP is below 25%", + }, + "LEPPA": { + name: "Leppa Berry", + effect: "Restores 10 PP to a move if its PP reaches 0", + }, +} as const; \ No newline at end of file diff --git a/src/locales/es/config.ts b/src/locales/es/config.ts index c56a8d384c2..a3b06982d33 100644 --- a/src/locales/es/config.ts +++ b/src/locales/es/config.ts @@ -2,33 +2,48 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; +import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; import { menuUiHandler } from "./menu-ui-handler"; +import { modifierType } from "./modifier-type"; import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonStat } from "./pokemon-stat"; +import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; +import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; - +import { weather } from "./weather"; +import { battleMessageUiHandler } from "./battle-message-ui-handler"; +import { berry } from "./berry"; export const esConfig = { ability: ability, abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, + egg: egg, fightUiHandler: fightUiHandler, - menuUiHandler: menuUiHandler, + growth: growth, menu: menu, + menuUiHandler: menuUiHandler, + modifierType: modifierType, move: move, - pokeball: pokeball, - pokemonStat: pokemonStat, - pokemon: pokemon, - starterSelectUiHandler: starterSelectUiHandler, - tutorial: tutorial, nature: nature, - growth: growth + pokeball: pokeball, + pokemon: pokemon, + pokemonStat: pokemonStat, + splashMessages: splashMessages, + starterSelectUiHandler: starterSelectUiHandler, + titles: titles, + trainerClasses: trainerClasses, + trainerNames: trainerNames, + tutorial: tutorial, + weather: weather, + battleMessageUiHandler: battleMessageUiHandler, + berry: berry, } \ No newline at end of file diff --git a/src/locales/es/egg.ts b/src/locales/es/egg.ts new file mode 100644 index 00000000000..358c1b4a503 --- /dev/null +++ b/src/locales/es/egg.ts @@ -0,0 +1,21 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const egg: SimpleTranslationEntries = { + "egg": "Egg", + "greatTier": "Rare", + "ultraTier": "Epic", + "masterTier": "Legendary", + "defaultTier": "Common", + "hatchWavesMessageSoon": "Sounds can be heard coming from inside! It will hatch soon!", + "hatchWavesMessageClose": "It appears to move occasionally. It may be close to hatching.", + "hatchWavesMessageNotClose": "What will hatch from this? It doesn't seem close to hatching.", + "hatchWavesMessageLongTime": "It looks like this Egg will take a long time to hatch.", + "gachaTypeLegendary": "Legendary Rate Up", + "gachaTypeMove": "Rare Egg Move Rate Up", + "gachaTypeShiny": "Shiny Rate Up", + "selectMachine": "Select a machine.", + "notEnoughVouchers": "You don't have enough vouchers!", + "tooManyEggs": "You have too many eggs!", + "pull": "Pull", + "pulls": "Pulls" +} as const; \ No newline at end of file diff --git a/src/locales/es/fight-ui-handler.ts b/src/locales/es/fight-ui-handler.ts index 7a02ce66f3c..951d043d393 100644 --- a/src/locales/es/fight-ui-handler.ts +++ b/src/locales/es/fight-ui-handler.ts @@ -3,5 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", "power": "Potencia", - "accuracy": "Accuracy", + "accuracy": "Precisión", } as const; diff --git a/src/locales/es/menu-ui-handler.ts b/src/locales/es/menu-ui-handler.ts index ba7ea78fd8f..ebb76de6f77 100644 --- a/src/locales/es/menu-ui-handler.ts +++ b/src/locales/es/menu-ui-handler.ts @@ -9,7 +9,7 @@ export const menuUiHandler: SimpleTranslationEntries = { "EGG_GACHA": "Gacha de Huevos", "MANAGE_DATA": "Gestionar Datos", "COMMUNITY": "Comunidad", - "RETURN_TO_TITLE": "Volver al Título", + "SAVE_AND_QUIT": "Save and Quit", "LOG_OUT": "Cerrar Sesión", "slot": "Ranura {{slotNumber}}", "importSession": "Importar Sesión", diff --git a/src/locales/es/menu.ts b/src/locales/es/menu.ts index 4839630bc56..6a7f2587a0f 100644 --- a/src/locales/es/menu.ts +++ b/src/locales/es/menu.ts @@ -35,6 +35,11 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "¿Eres un chico o una chica?", "boy": "Chico", "girl": "Chica", + "evolving": "What?\n{{pokemonName}} is evolving!", + "stoppedEvolving": "{{pokemonName}} stopped evolving.", + "pauseEvolutionsQuestion": "Would you like to pause evolutions for {{pokemonName}}?\nEvolutions can be re-enabled from the party screen.", + "evolutionsPaused": "Evolutions have been paused for {{pokemonName}}.", + "evolutionDone": "Congratulations!\nYour {{pokemonName}} evolved into {{evolvedPokemonName}}!", "dailyRankings": "Rankings Diarios", "weeklyRankings": "Rankings Semanales", "noRankings": "Sin Rankings", diff --git a/src/locales/es/modifier-type.ts b/src/locales/es/modifier-type.ts new file mode 100644 index 00000000000..043d7a705d5 --- /dev/null +++ b/src/locales/es/modifier-type.ts @@ -0,0 +1,409 @@ +import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; + +export const modifierType: ModifierTypeTranslationEntries = { + ModifierType: { + "AddPokeballModifierType": { + name: "{{modifierCount}}x {{pokeballName}}", + description: "Receive {{pokeballName}} x{{modifierCount}} (Inventory: {{pokeballAmount}}) \nCatch Rate: {{catchRate}}", + }, + "AddVoucherModifierType": { + name: "{{modifierCount}}x {{voucherTypeName}}", + description: "Receive {{voucherTypeName}} x{{modifierCount}}", + }, + "PokemonHeldItemModifierType": { + extra: { + "inoperable": "{{pokemonName}} can't take\nthis item!", + "tooMany": "{{pokemonName}} has too many\nof this item!", + } + }, + "PokemonHpRestoreModifierType": { + description: "Restores {{restorePoints}} HP or {{restorePercent}}% HP for one Pokémon, whichever is higher", + extra: { + "fully": "Fully restores HP for one Pokémon", + "fullyWithStatus": "Fully restores HP for one Pokémon and heals any status ailment", + } + }, + "PokemonReviveModifierType": { + description: "Revives one Pokémon and restores {{restorePercent}}% HP", + }, + "PokemonStatusHealModifierType": { + description: "Heals any status ailment for one Pokémon", + }, + "PokemonPpRestoreModifierType": { + description: "Restores {{restorePoints}} PP for one Pokémon move", + extra: { + "fully": "Restores all PP for one Pokémon move", + } + }, + "PokemonAllMovePpRestoreModifierType": { + description: "Restores {{restorePoints}} PP for all of one Pokémon's moves", + extra: { + "fully": "Restores all PP for all of one Pokémon's moves", + } + }, + "PokemonPpUpModifierType": { + description: "Permanently increases PP for one Pokémon move by {{upPoints}} for every 5 maximum PP (maximum 3)", + }, + "PokemonNatureChangeModifierType": { + name: "{{natureName}} Mint", + description: "Changes a Pokémon's nature to {{natureName}} and permanently unlocks the nature for the starter.", + }, + "DoubleBattleChanceBoosterModifierType": { + description: "Doubles the chance of an encounter being a double battle for {{battleCount}} battles", + }, + "TempBattleStatBoosterModifierType": { + description: "Increases the {{tempBattleStatName}} of all party members by 1 stage for 5 battles", + }, + "AttackTypeBoosterModifierType": { + description: "Increases the power of a Pokémon's {{moveType}}-type moves by 20%", + }, + "PokemonLevelIncrementModifierType": { + description: "Increases a Pokémon's level by 1", + }, + "AllPokemonLevelIncrementModifierType": { + description: "Increases all party members' level by 1", + }, + "PokemonBaseStatBoosterModifierType": { + description: "Increases the holder's base {{statName}} by 10%. The higher your IVs, the higher the stack limit.", + }, + "AllPokemonFullHpRestoreModifierType": { + description: "Restores 100% HP for all Pokémon", + }, + "AllPokemonFullReviveModifierType": { + description: "Revives all fainted Pokémon, fully restoring HP", + }, + "MoneyRewardModifierType": { + description: "Grants a {{moneyMultiplier}} amount of money (₽{{moneyAmount}})", + extra: { + "small": "small", + "moderate": "moderate", + "large": "large", + }, + }, + "ExpBoosterModifierType": { + description: "Increases gain of EXP. Points by {{boostPercent}}%", + }, + "PokemonExpBoosterModifierType": { + description: "Increases the holder's gain of EXP. Points by {{boostPercent}}%", + }, + "PokemonFriendshipBoosterModifierType": { + description: "Increases friendship gain per victory by 50%", + }, + "PokemonMoveAccuracyBoosterModifierType": { + description: "Increases move accuracy by {{accuracyAmount}} (maximum 100)", + }, + "PokemonMultiHitModifierType": { + description: "Attacks hit one additional time at the cost of a 60/75/82.5% power reduction per stack respectively", + }, + "TmModifierType": { + name: "TM{{moveId}} - {{moveName}}", + description: "Teach {{moveName}} to a Pokémon", + }, + "EvolutionItemModifierType": { + description: "Causes certain Pokémon to evolve", + }, + "FormChangeItemModifierType": { + description: "Causes certain Pokémon to change form", + }, + "FusePokemonModifierType": { + description: "Combines two Pokémon (transfers Ability, splits base stats and types, shares move pool)", + }, + "TerastallizeModifierType": { + name: "{{teraType}} Tera Shard", + description: "{{teraType}} Terastallizes the holder for up to 10 battles", + }, + "ContactHeldItemTransferChanceModifierType": { + description: "Upon attacking, there is a {{chancePercent}}% chance the foe's held item will be stolen", + }, + "TurnHeldItemTransferModifierType": { + description: "Every turn, the holder acquires one held item from the foe", + }, + "EnemyAttackStatusEffectChanceModifierType": { + description: "Adds a {{chancePercent}}% chance to inflict {{statusEffect}} with attack moves", + }, + "EnemyEndureChanceModifierType": { + description: "Adds a {{chancePercent}}% chance of enduring a hit", + }, + + "RARE_CANDY": { name: "Rare Candy" }, + "RARER_CANDY": { name: "Rarer Candy" }, + + "MEGA_BRACELET": { name: "Mega Bracelet", description: "Mega Stones become available" }, + "DYNAMAX_BAND": { name: "Dynamax Band", description: "Max Mushrooms become available" }, + "TERA_ORB": { name: "Tera Orb", description: "Tera Shards become available" }, + + "MAP": { name: "Map", description: "Allows you to choose your destination at a crossroads" }, + + "POTION": { name: "Potion" }, + "SUPER_POTION": { name: "Super Potion" }, + "HYPER_POTION": { name: "Hyper Potion" }, + "MAX_POTION": { name: "Max Potion" }, + "FULL_RESTORE": { name: "Full Restore" }, + + "REVIVE": { name: "Revive" }, + "MAX_REVIVE": { name: "Max Revive" }, + + "FULL_HEAL": { name: "Full Heal" }, + + "SACRED_ASH": { name: "Sacred Ash" }, + + "REVIVER_SEED": { name: "Reviver Seed", description: "Revives the holder for 1/2 HP upon fainting" }, + + "ETHER": { name: "Ether" }, + "MAX_ETHER": { name: "Max Ether" }, + + "ELIXIR": { name: "Elixir" }, + "MAX_ELIXIR": { name: "Max Elixir" }, + + "PP_UP": { name: "PP Up" }, + "PP_MAX": { name: "PP Max" }, + + "LURE": { name: "Lure" }, + "SUPER_LURE": { name: "Super Lure" }, + "MAX_LURE": { name: "Max Lure" }, + + "MEMORY_MUSHROOM": { name: "Memory Mushroom", description: "Recall one Pokémon's forgotten move" }, + + "EXP_SHARE": { name: "EXP. All", description: "Non-participants receive 20% of a single participant's EXP. Points" }, + "EXP_BALANCE": { name: "EXP. Balance", description: "Weighs EXP. Points received from battles towards lower-leveled party members" }, + + "OVAL_CHARM": { name: "Oval Charm", description: "When multiple Pokémon participate in a battle, each gets an extra 10% of the total EXP" }, + + "EXP_CHARM": { name: "EXP. Charm" }, + "SUPER_EXP_CHARM": { name: "Super EXP. Charm" }, + "GOLDEN_EXP_CHARM": { name: "Golden EXP. Charm" }, + + "LUCKY_EGG": { name: "Lucky Egg" }, + "GOLDEN_EGG": { name: "Golden Egg" }, + + "SOOTHE_BELL": { name: "Soothe Bell" }, + + "SOUL_DEW": { name: "Soul Dew", description: "Increases the influence of a Pokémon's nature on its stats by 10% (additive)" }, + + "NUGGET": { name: "Nugget" }, + "BIG_NUGGET": { name: "Big Nugget" }, + "RELIC_GOLD": { name: "Relic Gold" }, + + "AMULET_COIN": { name: "Amulet Coin", description: "Increases money rewards by 20%" }, + "GOLDEN_PUNCH": { name: "Golden Punch", description: "Grants 50% of damage inflicted as money" }, + "COIN_CASE": { name: "Coin Case", description: "After every 10th battle, receive 10% of your money in interest" }, + + "LOCK_CAPSULE": { name: "Lock Capsule", description: "Allows you to lock item rarities when rerolling items" }, + + "GRIP_CLAW": { name: "Grip Claw" }, + "WIDE_LENS": { name: "Wide Lens" }, + + "MULTI_LENS": { name: "Multi Lens" }, + + "HEALING_CHARM": { name: "Healing Charm", description: "Increases the effectiveness of HP restoring moves and items by 10% (excludes Revives)" }, + "CANDY_JAR": { name: "Candy Jar", description: "Increases the number of levels added by Rare Candy items by 1" }, + + "BERRY_POUCH": { name: "Berry Pouch", description: "Adds a 25% chance that a used berry will not be consumed" }, + + "FOCUS_BAND": { name: "Focus Band", description: "Adds a 10% chance to survive with 1 HP after being damaged enough to faint" }, + + "QUICK_CLAW": { name: "Quick Claw", description: "Adds a 10% chance to move first regardless of speed (after priority)" }, + + "KINGS_ROCK": { name: "King's Rock", description: "Adds a 10% chance an attack move will cause the opponent to flinch" }, + + "LEFTOVERS": { name: "Leftovers", description: "Heals 1/16 of a Pokémon's maximum HP every turn" }, + "SHELL_BELL": { name: "Shell Bell", description: "Heals 1/8 of a Pokémon's dealt damage" }, + + "BATON": { name: "Baton", description: "Allows passing along effects when switching Pokémon, which also bypasses traps" }, + + "SHINY_CHARM": { name: "Shiny Charm", description: "Dramatically increases the chance of a wild Pokémon being Shiny" }, + "ABILITY_CHARM": { name: "Ability Charm", description: "Dramatically increases the chance of a wild Pokémon having a Hidden Ability" }, + + "IV_SCANNER": { name: "IV Scanner", description: "Allows scanning the IVs of wild Pokémon. 2 IVs are revealed per stack. The best IVs are shown first" }, + + "DNA_SPLICERS": { name: "DNA Splicers" }, + + "MINI_BLACK_HOLE": { name: "Mini Black Hole" }, + + "GOLDEN_POKEBALL": { name: "Golden Poké Ball", description: "Adds 1 extra item option at the end of every battle" }, + + "ENEMY_DAMAGE_BOOSTER": { name: "Damage Token", description: "Increases damage by 5%" }, + "ENEMY_DAMAGE_REDUCTION": { name: "Protection Token", description: "Reduces incoming damage by 2.5%" }, + "ENEMY_HEAL": { name: "Recovery Token", description: "Heals 2% of max HP every turn" }, + "ENEMY_ATTACK_POISON_CHANCE": { name: "Poison Token" }, + "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Paralyze Token" }, + "ENEMY_ATTACK_SLEEP_CHANCE": { name: "Sleep Token" }, + "ENEMY_ATTACK_FREEZE_CHANCE": { name: "Freeze Token" }, + "ENEMY_ATTACK_BURN_CHANCE": { name: "Burn Token" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Adds a 10% chance every turn to heal a status condition" }, + "ENEMY_ENDURE_CHANCE": { name: "Endure Token" }, + "ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Adds a 1% chance that a wild Pokémon will be a fusion" }, + }, + TempBattleStatBoosterItem: { + "x_attack": "X Attack", + "x_defense": "X Defense", + "x_sp_atk": "X Sp. Atk", + "x_sp_def": "X Sp. Def", + "x_speed": "X Speed", + "x_accuracy": "X Accuracy", + "dire_hit": "Dire Hit", + }, + AttackTypeBoosterItem: { + "silk_scarf": "Silk Scarf", + "black_belt": "Black Belt", + "sharp_beak": "Sharp Beak", + "poison_barb": "Poison Barb", + "soft_sand": "Soft Sand", + "hard_stone": "Hard Stone", + "silver_powder": "Silver Powder", + "spell_tag": "Spell Tag", + "metal_coat": "Metal Coat", + "charcoal": "Charcoal", + "mystic_water": "Mystic Water", + "miracle_seed": "Miracle Seed", + "magnet": "Magnet", + "twisted_spoon": "Twisted Spoon", + "never_melt_ice": "Never-Melt Ice", + "dragon_fang": "Dragon Fang", + "black_glasses": "Black Glasses", + "fairy_feather": "Fairy Feather", + }, + BaseStatBoosterItem: { + "hp_up": "HP Up", + "protein": "Protein", + "iron": "Iron", + "calcium": "Calcium", + "zinc": "Zinc", + "carbos": "Carbos", + }, + EvolutionItem: { + "NONE": "None", + + "LINKING_CORD": "Linking Cord", + "SUN_STONE": "Sun Stone", + "MOON_STONE": "Moon Stone", + "LEAF_STONE": "Leaf Stone", + "FIRE_STONE": "Fire Stone", + "WATER_STONE": "Water Stone", + "THUNDER_STONE": "Thunder Stone", + "ICE_STONE": "Ice Stone", + "DUSK_STONE": "Dusk Stone", + "DAWN_STONE": "Dawn Stone", + "SHINY_STONE": "Shiny Stone", + "CRACKED_POT": "Cracked Pot", + "SWEET_APPLE": "Sweet Apple", + "TART_APPLE": "Tart Apple", + "STRAWBERRY_SWEET": "Strawberry Sweet", + "UNREMARKABLE_TEACUP": "Unremarkable Teacup", + + "CHIPPED_POT": "Chipped Pot", + "BLACK_AUGURITE": "Black Augurite", + "GALARICA_CUFF": "Galarica Cuff", + "GALARICA_WREATH": "Galarica Wreath", + "PEAT_BLOCK": "Peat Block", + "AUSPICIOUS_ARMOR": "Auspicious Armor", + "MALICIOUS_ARMOR": "Malicious Armor", + "MASTERPIECE_TEACUP": "Masterpiece Teacup", + "METAL_ALLOY": "Metal Alloy", + "SCROLL_OF_DARKNESS": "Scroll Of Darkness", + "SCROLL_OF_WATERS": "Scroll Of Waters", + "SYRUPY_APPLE": "Syrupy Apple", + }, + FormChangeItem: { + "NONE": "None", + + "ABOMASITE": "Abomasite", + "ABSOLITE": "Absolite", + "AERODACTYLITE": "Aerodactylite", + "AGGRONITE": "Aggronite", + "ALAKAZITE": "Alakazite", + "ALTARIANITE": "Altarianite", + "AMPHAROSITE": "Ampharosite", + "AUDINITE": "Audinite", + "BANETTITE": "Banettite", + "BEEDRILLITE": "Beedrillite", + "BLASTOISINITE": "Blastoisinite", + "BLAZIKENITE": "Blazikenite", + "CAMERUPTITE": "Cameruptite", + "CHARIZARDITE_X": "Charizardite X", + "CHARIZARDITE_Y": "Charizardite Y", + "DIANCITE": "Diancite", + "GALLADITE": "Galladite", + "GARCHOMPITE": "Garchompite", + "GARDEVOIRITE": "Gardevoirite", + "GENGARITE": "Gengarite", + "GLALITITE": "Glalitite", + "GYARADOSITE": "Gyaradosite", + "HERACRONITE": "Heracronite", + "HOUNDOOMINITE": "Houndoominite", + "KANGASKHANITE": "Kangaskhanite", + "LATIASITE": "Latiasite", + "LATIOSITE": "Latiosite", + "LOPUNNITE": "Lopunnite", + "LUCARIONITE": "Lucarionite", + "MANECTITE": "Manectite", + "MAWILITE": "Mawilite", + "MEDICHAMITE": "Medichamite", + "METAGROSSITE": "Metagrossite", + "MEWTWONITE_X": "Mewtwonite X", + "MEWTWONITE_Y": "Mewtwonite Y", + "PIDGEOTITE": "Pidgeotite", + "PINSIRITE": "Pinsirite", + "RAYQUAZITE": "Rayquazite", + "SABLENITE": "Sablenite", + "SALAMENCITE": "Salamencite", + "SCEPTILITE": "Sceptilite", + "SCIZORITE": "Scizorite", + "SHARPEDONITE": "Sharpedonite", + "SLOWBRONITE": "Slowbronite", + "STEELIXITE": "Steelixite", + "SWAMPERTITE": "Swampertite", + "TYRANITARITE": "Tyranitarite", + "VENUSAURITE": "Venusaurite", + + "BLUE_ORB": "Blue Orb", + "RED_ORB": "Red Orb", + "SHARP_METEORITE": "Sharp Meteorite", + "HARD_METEORITE": "Hard Meteorite", + "SMOOTH_METEORITE": "Smooth Meteorite", + "ADAMANT_CRYSTAL": "Adamant Crystal", + "LUSTROUS_ORB": "Lustrous Orb", + "GRISEOUS_CORE": "Griseous Core", + "REVEAL_GLASS": "Reveal Glass", + "GRACIDEA": "Gracidea", + "MAX_MUSHROOMS": "Max Mushrooms", + "DARK_STONE": "Dark Stone", + "LIGHT_STONE": "Light Stone", + "PRISON_BOTTLE": "Prison Bottle", + "N_LUNARIZER": "N Lunarizer", + "N_SOLARIZER": "N Solarizer", + "RUSTED_SWORD": "Rusted Sword", + "RUSTED_SHIELD": "Rusted Shield", + "ICY_REINS_OF_UNITY": "Icy Reins Of Unity", + "SHADOW_REINS_OF_UNITY": "Shadow Reins Of Unity", + "WELLSPRING_MASK": "Wellspring Mask", + "HEARTHFLAME_MASK": "Hearthflame Mask", + "CORNERSTONE_MASK": "Cornerstone Mask", + "SHOCK_DRIVE": "Shock Drive", + "BURN_DRIVE": "Burn Drive", + "CHILL_DRIVE": "Chill Drive", + "DOUSE_DRIVE": "Douse Drive", + }, + TeraType: { + "UNKNOWN": "Unknown", + "NORMAL": "Normal", + "FIGHTING": "Fighting", + "FLYING": "Flying", + "POISON": "Poison", + "GROUND": "Ground", + "ROCK": "Rock", + "BUG": "Bug", + "GHOST": "Ghost", + "STEEL": "Steel", + "FIRE": "Fire", + "WATER": "Water", + "GRASS": "Grass", + "ELECTRIC": "Electric", + "PSYCHIC": "Psychic", + "ICE": "Ice", + "DRAGON": "Dragon", + "DARK": "Dark", + "FAIRY": "Fairy", + "STELLAR": "Stellar", + }, +} as const; \ No newline at end of file diff --git a/src/locales/es/splash-messages.ts b/src/locales/es/splash-messages.ts new file mode 100644 index 00000000000..6815d7f1824 --- /dev/null +++ b/src/locales/es/splash-messages.ts @@ -0,0 +1,37 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const splashMessages: SimpleTranslationEntries = { + "battlesWon": "Battles Won!", + "joinTheDiscord": "Join the Discord!", + "infiniteLevels": "Infinite Levels!", + "everythingStacks": "Everything Stacks!", + "optionalSaveScumming": "Optional Save Scumming!", + "biomes": "35 Biomes!", + "openSource": "Open Source!", + "playWithSpeed": "Play with 5x Speed!", + "liveBugTesting": "Live Bug Testing!", + "heavyInfluence": "Heavy RoR2 Influence!", + "pokemonRiskAndPokemonRain": "Pokémon Risk and Pokémon Rain!", + "nowWithMoreSalt": "Now with 33% More Salt!", + "infiniteFusionAtHome": "Infinite Fusion at Home!", + "brokenEggMoves": "Broken Egg Moves!", + "magnificent": "Magnificent!", + "mubstitute": "Mubstitute!", + "thatsCrazy": "That\'s Crazy!", + "oranceJuice": "Orance Juice!", + "questionableBalancing": "Questionable Balancing!", + "coolShaders": "Cool Shaders!", + "aiFree": "AI-Free!", + "suddenDifficultySpikes": "Sudden Difficulty Spikes!", + "basedOnAnUnfinishedFlashGame": "Based on an Unfinished Flash Game!", + "moreAddictiveThanIntended": "More Addictive than Intended!", + "mostlyConsistentSeeds": "Mostly Consistent Seeds!", + "achievementPointsDontDoAnything": "Achievement Points Don\'t Do Anything!", + "youDoNotStartAtLevel": "You Do Not Start at Level 2000!", + "dontTalkAboutTheManaphyEggIncident": "Don\'t Talk About the Manaphy Egg Incident!", + "alsoTryPokengine": "Also Try Pokéngine!", + "alsoTryEmeraldRogue": "Also Try Emerald Rogue!", + "alsoTryRadicalRed": "Also Try Radical Red!", + "eeveeExpo": "Eevee Expo!", + "ynoproject": "YNOproject!", +} as const; \ No newline at end of file diff --git a/src/locales/es/starter-select-ui-handler.ts b/src/locales/es/starter-select-ui-handler.ts index 9b037209819..79bf6f9476e 100644 --- a/src/locales/es/starter-select-ui-handler.ts +++ b/src/locales/es/starter-select-ui-handler.ts @@ -7,6 +7,15 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; */ export const starterSelectUiHandler: SimpleTranslationEntries = { "confirmStartTeam":'¿Comenzar con estos Pokémon?', + "gen1": "I", + "gen2": "II", + "gen3": "III", + "gen4": "IV", + "gen5": "V", + "gen6": "VI", + "gen7": "VII", + "gen8": "VIII", + "gen9": "IX", "growthRate": "Crecimiento:", "ability": "Habilid:", "passive": "Pasiva:", @@ -32,4 +41,4 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "locked": "Locked", "disabled": "Disabled", "uncaught": "Uncaught" -} \ No newline at end of file +} diff --git a/src/locales/es/trainers.ts b/src/locales/es/trainers.ts new file mode 100644 index 00000000000..443718693ca --- /dev/null +++ b/src/locales/es/trainers.ts @@ -0,0 +1,244 @@ +import {SimpleTranslationEntries} from "#app/plugins/i18n"; + +// Titles of special trainers like gym leaders, elite four, and the champion +export const titles: SimpleTranslationEntries = { + "elite_four": "Elite Four", + "gym_leader": "Gym Leader", + "gym_leader_female": "Gym Leader", + "champion": "Champion", + "rival": "Rival", + "professor": "Professor", + "frontier_brain": "Frontier Brain", + // Maybe if we add the evil teams we can add "Team Rocket" and "Team Aqua" etc. here as well as "Team Rocket Boss" and "Team Aqua Admin" etc. +} as const; + +// Titles of trainers like "Youngster" or "Lass" +export const trainerClasses: SimpleTranslationEntries = { + "ace_trainer": "Ace Trainer", + "ace_trainer_female": "Ace Trainer", + "ace_duo": "Ace Duo", + "artist": "Artist", + "artist_female": "Artist", + "backers": "Backers", + "backpacker": "Backpacker", + "backpacker_female": "Backpacker", + "backpackers": "Backpackers", + "baker": "Baker", + "battle_girl": "Battle Girl", + "beauty": "Beauty", + "beginners": "Beginners", + "biker": "Biker", + "black_belt": "Black Belt", + "breeder": "Breeder", + "breeder_female": "Breeder", + "breeders": "Breeders", + "clerk": "Clerk", + "clerk_female": "Clerk", + "colleagues": "Colleagues", + "crush_kin": "Crush Kin", + "cyclist": "Cyclist", + "cyclist_female": "Cyclist", + "cyclists": "Cyclists", + "dancer": "Dancer", + "dancer_female": "Dancer", + "depot_agent": "Depot Agent", + "doctor": "Doctor", + "doctor_female": "Doctor", + "fisherman": "Fisherman", + "fisherman_female": "Fisherman", + "gentleman": "Gentleman", + "guitarist": "Guitarist", + "guitarist_female": "Guitarist", + "harlequin": "Harlequin", + "hiker": "Hiker", + "hooligans": "Hooligans", + "hoopster": "Hoopster", + "infielder": "Infielder", + "janitor": "Janitor", + "lady": "Lady", + "lass": "Lass", + "linebacker": "Linebacker", + "maid": "Maid", + "madame": "Madame", + "medical_team": "Medical Team", + "musician": "Musician", + "hex_maniac": "Hex Maniac", + "nurse": "Nurse", + "nursery_aide": "Nursery Aide", + "officer": "Officer", + "parasol_lady": "Parasol Lady", + "pilot": "Pilot", + "pokefan": "Poké Fan", + "pokefan_family": "Poké Fan Family", + "preschooler": "Preschooler", + "preschooler_female": "Preschooler", + "preschoolers": "Preschoolers", + "psychic": "Psychic", + "psychic_female": "Psychic", + "psychics": "Psychics", + "pokémon_ranger": "Pokémon Ranger", + "pokémon_rangers": "Pokémon Ranger", + "ranger": "Ranger", + "restaurant_staff": "Restaurant Staff", + "rich": "Rich", + "rich_female": "Rich", + "rich_boy": "Rich Boy", + "rich_couple": "Rich Couple", + "rich_kid": "Rich Kid", + "rich_kid_female": "Rich Kid", + "rich_kids": "Rich Kids", + "roughneck": "Roughneck", + "scientist": "Scientist", + "scientist_female": "Scientist", + "scientists": "Scientists", + "smasher": "Smasher", + "snow_worker": "Snow Worker", + "snow_worker_female": "Snow Worker", + "striker": "Striker", + "school_kid": "School Kid", + "school_kid_female": "School Kid", + "school_kids": "School Kids", + "swimmer": "Swimmer", + "swimmer_female": "Swimmer", + "swimmers": "Swimmers", + "twins": "Twins", + "veteran": "Veteran", + "veteran_female": "Veteran", + "veteran_duo": "Veteran Duo", + "waiter": "Waiter", + "waitress": "Waitress", + "worker": "Worker", + "worker_female": "Worker", + "workers": "Workers", + "youngster": "Youngster" +} as const; + +// Names of special trainers like gym leaders, elite four, and the champion +export const trainerNames: SimpleTranslationEntries = { + "brock": "Brock", + "misty": "Misty", + "lt_surge": "Lt Surge", + "erika": "Erika", + "janine": "Janine", + "sabrina": "Sabrina", + "blaine": "Blaine", + "giovanni": "Giovanni", + "falkner": "Falkner", + "bugsy": "Bugsy", + "whitney": "Whitney", + "morty": "Morty", + "chuck": "Chuck", + "jasmine": "Jasmine", + "pryce": "Pryce", + "clair": "Clair", + "roxanne": "Roxanne", + "brawly": "Brawly", + "wattson": "Wattson", + "flannery": "Flannery", + "norman": "Norman", + "winona": "Winona", + "tate": "Tate", + "liza": "Liza", + "juan": "Juan", + "roark": "Roark", + "gardenia": "Gardenia", + "maylene": "Maylene", + "crasher_wake": "Crasher Wake", + "fantina": "Fantina", + "byron": "Byron", + "candice": "Candice", + "volkner": "Volkner", + "cilan": "Cilan", + "chili": "Chili", + "cress": "Cress", + "cheren": "Cheren", + "lenora": "Lenora", + "roxie": "Roxie", + "burgh": "Burgh", + "elesa": "Elesa", + "clay": "Clay", + "skyla": "Skyla", + "brycen": "Brycen", + "drayden": "Drayden", + "marlon": "Marlon", + "viola": "Viola", + "grant": "Grant", + "korrina": "Korrina", + "ramos": "Ramos", + "clemont": "Clemont", + "valerie": "Valerie", + "olympia": "Olympia", + "wulfric": "Wulfric", + "milo": "Milo", + "nessa": "Nessa", + "kabu": "Kabu", + "bea": "Bea", + "allister": "Allister", + "opal": "Opal", + "bede": "Bede", + "gordie": "Gordie", + "melony": "Melony", + "piers": "Piers", + "marnie": "Marnie", + "raihan": "Raihan", + "katy": "Katy", + "brassius": "Brassius", + "iono": "Iono", + "kofu": "Kofu", + "larry": "Larry", + "ryme": "Ryme", + "tulip": "Tulip", + "grusha": "Grusha", + "lorelei": "Lorelei", + "bruno": "Bruno", + "agatha": "Agatha", + "lance": "Lance", + "will": "Will", + "koga": "Koga", + "karen": "Karen", + "sidney": "Sidney", + "phoebe": "Phoebe", + "glacia": "Glacia", + "drake": "Drake", + "aaron": "Aaron", + "bertha": "Bertha", + "flint": "Flint", + "lucian": "Lucian", + "shauntal": "Shauntal", + "marshal": "Marshal", + "grimsley": "Grimsley", + "caitlin": "Caitlin", + "malva": "Malva", + "siebold": "Siebold", + "wikstrom": "Wikstrom", + "drasna": "Drasna", + "hala": "Hala", + "molayne": "Molayne", + "olivia": "Olivia", + "acerola": "Acerola", + "kahili": "Kahili", + "rika": "Rika", + "poppy": "Poppy", + "larry_elite": "Larry", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "hassel": "Hassel", + "crispin": "Crispin", + "amarys": "Amarys", + "lacey": "Lacey", + "drayton": "Drayton", + "blue": "Blue", + "red": "Red", + "lance_champion": "Lance", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "steven": "Steven", + "wallace": "Wallace", + "cynthia": "Cynthia", + "alder": "Alder", + "iris": "Iris", + "diantha": "Diantha", + "hau": "Hau", + "geeta": "Geeta", + "nemona": "Nemona", + "kieran": "Kieran", + "leon": "Leon", + "rival": "Finn", + "rival_female": "Ivy", +} as const; diff --git a/src/locales/es/weather.ts b/src/locales/es/weather.ts new file mode 100644 index 00000000000..999613f1566 --- /dev/null +++ b/src/locales/es/weather.ts @@ -0,0 +1,44 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +/** + * The weather namespace holds text displayed when weather is active during a battle + */ +export const weather: SimpleTranslationEntries = { + "sunnyStartMessage": "The sunlight got bright!", + "sunnyLapseMessage": "The sunlight is strong.", + "sunnyClearMessage": "The sunlight faded.", + + "rainStartMessage": "A downpour started!", + "rainLapseMessage": "The downpour continues.", + "rainClearMessage": "The rain stopped.", + + "sandstormStartMessage": "A sandstorm brewed!", + "sandstormLapseMessage": "The sandstorm rages.", + "sandstormClearMessage": "The sandstorm subsided.", + "sandstormDamageMessage": "{{pokemonPrefix}}{{pokemonName}} is buffeted\nby the sandstorm!", + + "hailStartMessage": "It started to hail!", + "hailLapseMessage": "Hail continues to fall.", + "hailClearMessage": "The hail stopped.", + "hailDamageMessage": "{{pokemonPrefix}}{{pokemonName}} is pelted\nby the hail!", + + "snowStartMessage": "It started to snow!", + "snowLapseMessage": "The snow is falling down.", + "snowClearMessage": "The snow stopped.", + + "fogStartMessage": "A thick fog emerged!", + "fogLapseMessage": "The fog continues.", + "fogClearMessage": "The fog disappeared.", + + "heavyRainStartMessage": "A heavy downpour started!", + "heavyRainLapseMessage": "The heavy downpour continues.", + "heavyRainClearMessage": "The heavy rain stopped.", + + "harshSunStartMessage": "The sunlight got hot!", + "harshSunLapseMessage": "The sun is scorching hot.", + "harshSunClearMessage": "The harsh sunlight faded.", + + "strongWindsStartMessage": "A heavy wind began!", + "strongWindsLapseMessage": "The wind blows intensely.", + "strongWindsClearMessage": "The heavy wind stopped." +} \ No newline at end of file diff --git a/src/locales/fr/ability.ts b/src/locales/fr/ability.ts index 292467fcad6..49bfeb53acf 100644 --- a/src/locales/fr/ability.ts +++ b/src/locales/fr/ability.ts @@ -1109,7 +1109,7 @@ export const ability: AbilityTranslationEntries = { name: "Turbine Éolienne", description: "Si le Pokémon est touché par une capacité faisant appel au vent, il se charge en électricité.", }, - zerotoHero: { + zeroToHero: { name: "Supermutation", description: "Le Pokémon prend sa Forme Super en quittant le combat.", }, @@ -1129,23 +1129,23 @@ export const ability: AbilityTranslationEntries = { name: "Charge Quantique", description: "Quand un champ électrifié est actif ou que le Pokémon tient une capsule d’Énergie Booster, sa stat la plus élevée augmente.", }, - goodasGold: { + goodAsGold: { name: "Corps en Or", description: "Le corps en or pur et robuste du Pokémon l’immunise contre les capacités de statut des autres Pokémon.", }, - vesselofRuin: { + vesselOfRuin: { name: "Urne du Fléau", description: "Le pouvoir de l’urne qui appelle le fléau affaiblit l’Attaque Spéciale de tous les autres Pokémon.", }, - swordofRuin: { + swordOfRuin: { name: "Épée du Fléau", description: "Le pouvoir de l’épée qui appelle le fléau affaiblit la Défense de tous les autres Pokémon.", }, - tabletsofRuin: { + tabletsOfRuin: { name: "Bois du Fléau", description: "Le pouvoir du bois qui appelle le fléau affaiblit l’Attaque de tous les autres Pokémon.", }, - beadsofRuin: { + beadsOfRuin: { name: "Perles du Fléau", description: "Le pouvoir des perles qui appellent le fléau affaiblit la Défense Spéciale de tous les autres Pokémon.", }, diff --git a/src/locales/fr/battle-message-ui-handler.ts b/src/locales/fr/battle-message-ui-handler.ts new file mode 100644 index 00000000000..8dc980d49a4 --- /dev/null +++ b/src/locales/fr/battle-message-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battleMessageUiHandler: SimpleTranslationEntries = { + "ivBest": "Exceptionnel", + "ivFantastic": "Fantastique", + "ivVeryGood": "Très bon", + "ivPrettyGood": "Bon", + "ivDecent": "Passable…", + "ivNoGood": "Pas top…", +} as const; diff --git a/src/locales/fr/battle.ts b/src/locales/fr/battle.ts index e34902b8cb1..827cea6b2d7 100644 --- a/src/locales/fr/battle.ts +++ b/src/locales/fr/battle.ts @@ -1,11 +1,12 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const battle: SimpleTranslationEntries = { - "bossAppeared": "Un {{bossName}} apparaît.", + "bossAppeared": "Un {{bossName}} apparait.", "trainerAppeared": "Un combat est lancé\npar {{trainerName}} !", - "singleWildAppeared": "Un {{pokemonName}} sauvage apparaît !", + "trainerAppearedDouble": "Un combat est lancé\npar {{trainerName}} !", + "singleWildAppeared": "Un {{pokemonName}} sauvage apparait !", "multiWildAppeared": "Un {{pokemonName1}} et un {{pokemonName2}}\nsauvages apparaissent !", - "playerComeBack": "{{pokemonName}}, on change !\nReviens !", + "playerComeBack": "{{pokemonName}} !\nReviens !", "trainerComeBack": "{{trainerName}} retire {{pokemonName}} !", "playerGo": "{{pokemonName}} ! Go !", "trainerGo": "{{pokemonName}} est envoyé par\n{{trainerName}} !", @@ -31,6 +32,8 @@ export const battle: SimpleTranslationEntries = { "learnMoveNotLearned": "{{pokemonName}} n’a pas appris\n{{moveName}}.", "learnMoveForgetQuestion": "Quelle capacité doit être oubliée ?", "learnMoveForgetSuccess": "{{pokemonName}} oublie comment\nutiliser {{moveName}}.", + "countdownPoof": "@d{32}1, @d{15}2, @d{15}et@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}Tadaaa !", + "learnMoveAnd": "Et…", "levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !", "moveNotImplemented": "{{moveName}} n’est pas encore implémenté et ne peut pas être sélectionné.", "moveNoPP": "Il n’y a plus de PP pour\ncette capacité !", diff --git a/src/locales/fr/berry.ts b/src/locales/fr/berry.ts new file mode 100644 index 00000000000..dd6b387f4cc --- /dev/null +++ b/src/locales/fr/berry.ts @@ -0,0 +1,48 @@ +import { BerryTranslationEntries } from "#app/plugins/i18n"; + +export const berry: BerryTranslationEntries = { + "SITRUS": { + name: "Baie Sitrus", + effect: "Restaure 25% des PV s’ils sont inférieurs à 50%", + }, + "LUM": { + name: "Baie Prine", + effect: "Soigne tout problème de statut permanant et la confusion", + }, + "ENIGMA": { + name: "Baie Enigma", + effect: "Restaure 25% des PV si touché par une capacité super efficace", + }, + "LIECHI": { + name: "Baie Lichii", + effect: "Augmente l’Attaque si les PV sont inférieurs à 25%", + }, + "GANLON": { + name: "Baie Lingan", + effect: "Augmente la Défense si les PV sont inférieurs à 25%", + }, + "PETAYA": { + name: "Baie Pitaye", + effect: "Augmente l’Atq. Spé. si les PV sont inférieurs à 25%", + }, + "APICOT": { + name: "Baie Abriko", + effect: "Augmente la Déf. Spé. si les PV sont inférieurs à 25%", + }, + "SALAC": { + name: "Baie Sailak", + effect: "Augmente la Vitesse si les PV sont inférieurs à 25%", + }, + "LANSAT": { + name: "Baie Lansat", + effect: "Augmente le taux de coups critiques si les PV sont inférieurs à 25%", + }, + "STARF": { + name: "Baie Frista", + effect: "Augmente énormément une statistique au hasard si les PV sont inférieurs à 25%", + }, + "LEPPA": { + name: "Baie Mepo", + effect: "Restaure 10 PP à une capacité dès que ses PP tombent à 0", + }, +} as const; diff --git a/src/locales/fr/config.ts b/src/locales/fr/config.ts index 89669aceb73..867a08621bb 100644 --- a/src/locales/fr/config.ts +++ b/src/locales/fr/config.ts @@ -2,33 +2,48 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; +import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; import { menuUiHandler } from "./menu-ui-handler"; +import { modifierType } from "./modifier-type"; import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonStat } from "./pokemon-stat"; +import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; +import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; - +import { weather } from "./weather"; +import { battleMessageUiHandler } from "./battle-message-ui-handler"; +import { berry } from "./berry"; export const frConfig = { ability: ability, abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, + egg: egg, fightUiHandler: fightUiHandler, - menuUiHandler: menuUiHandler, + growth: growth, menu: menu, + menuUiHandler: menuUiHandler, + modifierType: modifierType, move: move, - pokeball: pokeball, - pokemonStat: pokemonStat, - pokemon: pokemon, - starterSelectUiHandler: starterSelectUiHandler, - tutorial: tutorial, nature: nature, - growth: growth + pokeball: pokeball, + pokemon: pokemon, + pokemonStat: pokemonStat, + splashMessages: splashMessages, + starterSelectUiHandler: starterSelectUiHandler, + titles: titles, + trainerClasses: trainerClasses, + trainerNames: trainerNames, + tutorial: tutorial, + weather: weather, + battleMessageUiHandler: battleMessageUiHandler, + berry: berry, } \ No newline at end of file diff --git a/src/locales/fr/egg.ts b/src/locales/fr/egg.ts new file mode 100644 index 00000000000..566e423b69f --- /dev/null +++ b/src/locales/fr/egg.ts @@ -0,0 +1,21 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const egg: SimpleTranslationEntries = { + "egg": "Œuf", + "greatTier": "Rare", + "ultraTier": "Épique", + "masterTier": "Légendaire", + "defaultTier": "Commun", + "hatchWavesMessageSoon": "Il fait du bruit. Il va éclore !", + "hatchWavesMessageClose": "Il bouge de temps en temps. Il devrait bientôt éclore.", + "hatchWavesMessageNotClose": "Qu’est-ce qui va en sortir ? Ça va mettre du temps.", + "hatchWavesMessageLongTime": "Cet Œuf va sûrement mettre du temps à éclore.", + "gachaTypeLegendary": "Taux de Légendaires élevé", + "gachaTypeMove": "Taux de Capacité Œuf Rare élevé", + "gachaTypeShiny": "Taux de Chromatiques élevé", + "selectMachine": "Sélectionnez une machine.", + "notEnoughVouchers": "Vous n’avez pas assez de coupons !", + "tooManyEggs": "Vous avez trop d’Œufs !", + "pull": "Tirage", + "pulls": "Tirages" +} as const; \ No newline at end of file diff --git a/src/locales/fr/menu-ui-handler.ts b/src/locales/fr/menu-ui-handler.ts index 54328a05eb1..20e66754667 100644 --- a/src/locales/fr/menu-ui-handler.ts +++ b/src/locales/fr/menu-ui-handler.ts @@ -9,7 +9,7 @@ export const menuUiHandler: SimpleTranslationEntries = { "EGG_GACHA": "Gacha-Œufs", "MANAGE_DATA": "Mes données", "COMMUNITY": "Communauté", - "RETURN_TO_TITLE": "Écran titre", + "SAVE_AND_QUIT": "Sauver & quitter", "LOG_OUT": "Déconnexion", "slot": "Emplacement {{slotNumber}}", "importSession": "Importer session", diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index 2723de58752..f6d5cfac063 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -30,6 +30,11 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "Es-tu un garçon ou une fille ?", "boy": "Garçon", "girl": "Fille", + "evolving": "Quoi ?\n{{pokemonName}} évolue !", + "stoppedEvolving": "Hein ?\n{{pokemonName}} n’évolue plus !", + "pauseEvolutionsQuestion": "Mettre en pause les évolutions pour {{pokemonName}} ?\nElles peuvent être réactivées depuis l’écran d’équipe.", + "evolutionsPaused": "Les évolutions ont été mises en pause pour {{pokemonName}}.", + "evolutionDone": "Félicitations !\n{{pokemonName}} a évolué en {{evolvedPokemonName}} !", "dailyRankings": "Classement du Jour", "weeklyRankings": "Classement de la Semaine", "noRankings": "Pas de Classement", diff --git a/src/locales/fr/modifier-type.ts b/src/locales/fr/modifier-type.ts new file mode 100644 index 00000000000..95daf50f9b1 --- /dev/null +++ b/src/locales/fr/modifier-type.ts @@ -0,0 +1,409 @@ +import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; + +export const modifierType: ModifierTypeTranslationEntries = { + ModifierType: { + "AddPokeballModifierType": { + name: "{{pokeballName}} x{{modifierCount}}", + description: "Recevez {{modifierCount}} {{pokeballName}}s (Inventaire : {{pokeballAmount}}) \nTaux de capture : {{catchRate}}", + }, + "AddVoucherModifierType": { + name: "{{voucherTypeName}} x{{modifierCount}}", + description: "Recevez {{modifierCount}} {{voucherTypeName}}", + }, + "PokemonHeldItemModifierType": { + extra: { + "inoperable": "{{pokemonName}} ne peut pas\nporter cet objet !", + "tooMany": "{{pokemonName}} possède trop\nd’exemplaires de cet objet !", + } + }, + "PokemonHpRestoreModifierType": { + description: "Restaure {{restorePoints}} PV ou {{restorePercent}}% des PV totaux d’un Pokémon, en fonction duquel des deux est le plus élevé", + extra: { + "fully": "Restaure tous les PV d’un Pokémon", + "fullyWithStatus": "Restaure tous les PV d’un Pokémon et soigne tous ses problèmes de statut", + } + }, + "PokemonReviveModifierType": { + description: "Réanime un Pokémon et restaure {{restorePercent}}% de ses PV", + }, + "PokemonStatusHealModifierType": { + description: "Soigne tous les problèmes de statut d’un Pokémon", + }, + "PokemonPpRestoreModifierType": { + description: "Restaure {{restorePoints}} PP à une capacité d’un Pokémon", + extra: { + "fully": "Restaure tous les PP à une capacité d’un Pokémon", + } + }, + "PokemonAllMovePpRestoreModifierType": { + description: "Restaure {{restorePoints}} PP à toutes les capacités d’un Pokémon", + extra: { + "fully": "Restaure tous les PP à toutes les capacités d’un Pokémon", + } + }, + "PokemonPpUpModifierType": { + description: "Augmente le max de PP de {{upPoints}} à une capacité d’un Pokémon pour chaque 5 PP max (max : 3)", + }, + "PokemonNatureChangeModifierType": { + name: "Aromate {{natureName}}", + description: "Donne la nature {{natureName}} à un Pokémon et la débloque pour le starter lui étant lié.", + }, + "DoubleBattleChanceBoosterModifierType": { + description: "Double les chances de tomber sur un combat double pendant {{battleCount}} combats", + }, + "TempBattleStatBoosterModifierType": { + description: "Augmente d’1 cran {{tempBattleStatName}} pour toute l’équipe pendant 5 combats", + }, + "AttackTypeBoosterModifierType": { + description: "Augmente de 20% la puissance des capacités de type {{moveType}} d’un Pokémon", + }, + "PokemonLevelIncrementModifierType": { + description: "Fait monter un Pokémon d’1 niveau", + }, + "AllPokemonLevelIncrementModifierType": { + description: "Fait monter toute l’équipe d’1 niveau", + }, + "PokemonBaseStatBoosterModifierType": { + description: "Augmente de 10% {{statName}} de base de son porteur. Plus les IV sont hauts, plus il peut en porter.", + }, + "AllPokemonFullHpRestoreModifierType": { + description: "Restaure tous les PV de toute l'équipe", + }, + "AllPokemonFullReviveModifierType": { + description: "Réanime et restaure tous les PV de tous les Pokémon K.O.", + }, + "MoneyRewardModifierType": { + description: "Octroie une {{moneyMultiplier}} somme d’argent ({{moneyAmount}}₽)", + extra: { + "small": "petite", + "moderate": "moyenne", + "large": "grande", + }, + }, + "ExpBoosterModifierType": { + description: "Augmente de {{boostPercent}}% le gain de Points d’Exp", + }, + "PokemonExpBoosterModifierType": { + description: "Augmente de {{boostPercent}}% le gain de Points d’Exp du porteur", + }, + "PokemonFriendshipBoosterModifierType": { + description: "Augmente le gain d’amitié de 50% par victoire", + }, + "PokemonMoveAccuracyBoosterModifierType": { + description: "Augmente de {{accuracyAmount}} la précision des capacités (maximum 100)", + }, + "PokemonMultiHitModifierType": { + description: "Frappe une fois de plus en échange d’une baisse de puissance de respectivement 60/75/82,5% par cumul", + }, + "TmModifierType": { + name: "CT{{moveId}} - {{moveName}}", + description: "Apprend la capacité {{moveName}} à un Pokémon", + }, + "EvolutionItemModifierType": { + description: "Permet à certains Pokémon d’évoluer", + }, + "FormChangeItemModifierType": { + description: "Permet à certains Pokémon de changer de forme", + }, + "FusePokemonModifierType": { + description: "Fusionne deux Pokémon (transfère le Talent, sépare les stats de base et les types, partage le movepool)", + }, + "TerastallizeModifierType": { + name: "Téra-Éclat {{teraType}}", + description: "{{teraType}} Téracristallise son porteur pendant 10 combats", + }, + "ContactHeldItemTransferChanceModifierType": { + description: "{{chancePercent}}% de chances de voler un objet de l’adversaire en l’attaquant", + }, + "TurnHeldItemTransferModifierType": { + description: "À chaque tour, son porteur obtient un objet de son adversaire", + }, + "EnemyAttackStatusEffectChanceModifierType": { + description: "Ajoute {{chancePercent}}% de chances d’infliger le statut {{statusEffect}} avec des capacités offensives", + }, + "EnemyEndureChanceModifierType": { + description: "Ajoute {{chancePercent}}% de chances d’encaisser un coup", + }, + + "RARE_CANDY": { name: "Super Bonbon" }, + "RARER_CANDY": { name: "Hyper Bonbon" }, + + "MEGA_BRACELET": { name: "Méga-Bracelet", description: "Débloque les Méga-Gemmes" }, + "DYNAMAX_BAND": { name: "Poignet Dynamax", description: "Débloque le Dynamax" }, + "TERA_ORB": { name: "Orbe Téracristal", description: "Débloque les Téra-Éclats" }, + + "MAP": { name: "Carte", description: "Vous permet de choisir votre destination à un croisement" }, + + "POTION": { name: "Potion" }, + "SUPER_POTION": { name: "Super Potion" }, + "HYPER_POTION": { name: "Hyper Potion" }, + "MAX_POTION": { name: "Potion Max" }, + "FULL_RESTORE": { name: "Guérison" }, + + "REVIVE": { name: "Rappel" }, + "MAX_REVIVE": { name: "Rappel Max" }, + + "FULL_HEAL": { name: "Total Soin" }, + + "SACRED_ASH": { name: "Cendres Sacrées" }, + + "REVIVER_SEED": { name: "Résugraine", description: "Réanime et restaure la moitié des PV de son porteur s’il tombe K.O." }, + + "ETHER": { name: "Huile" }, + "MAX_ETHER": { name: "Huile Max" }, + + "ELIXIR": { name: "Élixir" }, + "MAX_ELIXIR": { name: "Élixir Max" }, + + "PP_UP": { name: "PP Plus" }, + "PP_MAX": { name: "PP Max" }, + + "LURE": { name: "Parfum" }, + "SUPER_LURE": { name: "Super Parfum" }, + "MAX_LURE": { name: "Parfum Max" }, + + "MEMORY_MUSHROOM": { name: "Champi Mémoriel", description: "Remémore une capacité à un Pokémon" }, + + "EXP_SHARE": { name: "Multi Exp", description: "Tous les non-participants reçoivent 20% des Points d’Exp d’un participant" }, + "EXP_BALANCE": { name: "Équilibr’Exp", description: "Équilibre les Points d’Exp à l’avantage des membres de l’équipe aux plus bas niveaux" }, + + "OVAL_CHARM": { name: "Charme Ovale", description: "Quand plusieurs Pokémon sont en combat, chacun gagne 10% supplémentaires du total d’Exp" }, + + "EXP_CHARM": { name: "Charme Exp" }, + "SUPER_EXP_CHARM": { name: "Super Charme Exp" }, + "GOLDEN_EXP_CHARM": { name: "Charme Exp Doré" }, + + "LUCKY_EGG": { name: "Œuf Chance" }, + "GOLDEN_EGG": { name: "Œuf d’Or" }, + + "SOOTHE_BELL": { name: "Grelot Zen" }, + + "SOUL_DEW": { name: "Rosée Âme", description: "Augmente de 10% l’influence de la nature d’un Pokémon sur ses statistiques (cumulatif)" }, + + "NUGGET": { name: "Pépite" }, + "BIG_NUGGET": { name: "Maxi Pépite" }, + "RELIC_GOLD": { name: "Vieux Ducat" }, + + "AMULET_COIN": { name: "Pièce Rune", description: "Augmente de 20% les gains d’argent" }, + "GOLDEN_PUNCH": { name: "Poing Doré", description: "50% des dégâts infligés sont convertis en argent" }, + "COIN_CASE": { name: "Boite Jetons", description: "Tous les 10 combats, recevez 10% de votre argent en intérêts" }, + + "LOCK_CAPSULE": { name: "Poké Écrin", description: "Permet de verrouiller des objets rares si vous relancez les objets proposés" }, + + "GRIP_CLAW": { name: "Accro Griffe" }, + "WIDE_LENS": { name: "Loupe" }, + + "MULTI_LENS": { name: "Multi Loupe" }, + + "HEALING_CHARM": { name: "Charme Soin", description: "Augmente de 10% l’efficacité des capacités et objets de soin de PV (hors Rappels)" }, + "CANDY_JAR": { name: "Jarre de Bonbons", description: "Augmente de 1 le nombre de niveaux gagnés à l’utilisation d’un Super Bonbon" }, + + "BERRY_POUCH": { name: "Sac à Baies", description: "Ajoute 25% de chances qu’une Baie utilisée ne soit pas consommée" }, + + "FOCUS_BAND": { name: "Bandeau", description: "Ajoute 10% de chances de survivre avec 1 PV si les dégâts reçus pouvaient mettre K.O." }, + + "QUICK_CLAW": { name: "Vive Griffe", description: "Ajoute 10% de chances d’agir en premier, indépendamment de la vitesse (après la priorité)" }, + + "KINGS_ROCK": { name: "Roche Royale", description: "Ajoute 10% de chances qu’une capacité offensive apeure l’adversaire" }, + + "LEFTOVERS": { name: "Restes", description: "Soigne à chaque tour 1/16 des PV max d’un Pokémon" }, + "SHELL_BELL": { name: "Grelot Coque", description: "Soigne 1/8 des dégâts infligés par un Pokémon" }, + + "BATON": { name: "Bâton", description: "Permet de transmettre les effets en cas de changement de Pokémon. Ignore les pièges." }, + + "SHINY_CHARM": { name: "Charme Chroma", description: "Augmente énormément les chances de rencontrer un Pokémon sauvage chromatique" }, + "ABILITY_CHARM": { name: "Charme Talent", description: "Augmente énormément les chances de rencontrer un Pokémon sauvage avec un Talent Caché" }, + + "IV_SCANNER": { name: "Scanner d’IV", description: "Scanne les IV d’un Pokémon sauvage. 2 IV sont révélés par Scanner. Les meilleurs sont montrés en 1er." }, + + "DNA_SPLICERS": { name: "Pointeau ADN" }, + + "MINI_BLACK_HOLE": { name: "Mini Trou Noir" }, + + "GOLDEN_POKEBALL": { name: "Poké Ball Dorée", description: "Ajoute 1 choix d’objet à la fin de chaque combat" }, + + "ENEMY_DAMAGE_BOOSTER": { name: "Jeton Dégâts", description: "Augmente les dégâts de 5%" }, + "ENEMY_DAMAGE_REDUCTION": { name: "Jeton Protection", description: "Diminue les dégâts reçus de 2,5%" }, + "ENEMY_HEAL": { name: "Jeton Soin", description: "Soigne 2% des PV max à chaque tour" }, + "ENEMY_ATTACK_POISON_CHANCE": { name: "Jeton Poison" }, + "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Jeton Paralysie" }, + "ENEMY_ATTACK_SLEEP_CHANCE": { name: "Jeton Sommeil" }, + "ENEMY_ATTACK_FREEZE_CHANCE": { name: "Jeton Gel" }, + "ENEMY_ATTACK_BURN_CHANCE": { name: "Jeton Brulure" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Jeton Total Soin", description: "Ajoute 10% de chances à chaque tour de se soigner d’un problème de statut." }, + "ENEMY_ENDURE_CHANCE": { name: "Jeton Ténacité" }, + "ENEMY_FUSED_CHANCE": { name: "Jeton Fusion", description: "Ajoute 1% de chances qu’un Pokémon sauvage soit une fusion." }, + }, + TempBattleStatBoosterItem: { + "x_attack": "Attaque +", + "x_defense": "Défense +", + "x_sp_atk": "Atq. Spé. +", + "x_sp_def": "Déf. Spé. +", + "x_speed": "Vitesse +", + "x_accuracy": "Précision +", + "dire_hit": "Muscle +", + }, + AttackTypeBoosterItem: { + "silk_scarf": "Mouchoir Soie", + "black_belt": "Ceinture Noire", + "sharp_beak": "Bec Pointu", + "poison_barb": "Pic Venin", + "soft_sand": "Sable Doux", + "hard_stone": "Pierre Dure", + "silver_powder": "Poudre Argentée", + "spell_tag": "Rune Sort", + "metal_coat": "Peau Métal", + "charcoal": "Charbon", + "mystic_water": "Eau Mystique", + "miracle_seed": "Graine Miracle", + "magnet": "Aimant", + "twisted_spoon": "Cuillère Tordue", + "never_melt_ice": "Glace Éternelle", + "dragon_fang": "Croc Dragon", + "black_glasses": "Lunettes Noires", + "fairy_feather": "Plume Enchantée", + }, + BaseStatBoosterItem: { + "hp_up": "PV Plus", + "protein": "Protéine", + "iron": "Fer", + "calcium": "Calcium", + "zinc": "Zinc", + "carbos": "Carbone", + }, + EvolutionItem: { + "NONE": "Aucun", + + "LINKING_CORD": "Fil de Liaison", + "SUN_STONE": "Pierre Soleil", + "MOON_STONE": "Pierre Lune", + "LEAF_STONE": "Pierre Plante", + "FIRE_STONE": "Pierre Feu", + "WATER_STONE": "Pierre Eau", + "THUNDER_STONE": "Pierre Foudre", + "ICE_STONE": "Pierre Glace", + "DUSK_STONE": "Pierre Nuit", + "DAWN_STONE": "Pierre Aube", + "SHINY_STONE": "Pierre Éclat", + "CRACKED_POT": "Théière Fêlée", + "SWEET_APPLE": "Pomme Sucrée", + "TART_APPLE": "Pomme Acidulée", + "STRAWBERRY_SWEET": "Fraise en Sucre", + "UNREMARKABLE_TEACUP": "Bol Médiocre", + + "CHIPPED_POT": "Théière Ébréchée", + "BLACK_AUGURITE": "Obsidienne", + "GALARICA_CUFF": "Bracelet Galanoa", + "GALARICA_WREATH": "Couronne Galanoa", + "PEAT_BLOCK": "Bloc de Tourbe", + "AUSPICIOUS_ARMOR": "Armure de la Fortune", + "MALICIOUS_ARMOR": "Armure de la Rancune", + "MASTERPIECE_TEACUP": "Bol Exceptionnel", + "METAL_ALLOY": "Métal Composite", + "SCROLL_OF_DARKNESS": "Rouleau des Ténèbres", + "SCROLL_OF_WATERS": "Rouleau de l’Eau", + "SYRUPY_APPLE": "Pomme Nectar", + }, + FormChangeItem: { + "NONE": "Aucun", + + "ABOMASITE": "Blizzarite", + "ABSOLITE": "Absolite", + "AERODACTYLITE": "Ptéraïte", + "AGGRONITE": "Galekingite", + "ALAKAZITE": "Alakazamite", + "ALTARIANITE": "Altarite", + "AMPHAROSITE": "Pharampite", + "AUDINITE": "Nanméouïte", + "BANETTITE": "Branettite", + "BEEDRILLITE": "Dardargnite", + "BLASTOISINITE": "Tortankite", + "BLAZIKENITE": "Braségalite", + "CAMERUPTITE": "Caméruptite", + "CHARIZARDITE_X": "Dracaufite X", + "CHARIZARDITE_Y": "Dracaufite Y", + "DIANCITE": "Diancite", + "GALLADITE": "Gallamite", + "GARCHOMPITE": "Carchacrokite", + "GARDEVOIRITE": "Gardevoirite", + "GENGARITE": "Ectoplasmite", + "GLALITITE": "Oniglalite", + "GYARADOSITE": "Léviatorite", + "HERACRONITE": "Scarhinoïte", + "HOUNDOOMINITE": "Démolossite", + "KANGASKHANITE": "Kangourexite", + "LATIASITE": "Latiasite", + "LATIOSITE": "Latiosite", + "LOPUNNITE": "Lockpinite", + "LUCARIONITE": "Lucarite", + "MANECTITE": "Élecsprintite", + "MAWILITE": "Mysdibulite", + "MEDICHAMITE": "Charminite", + "METAGROSSITE": "Métalossite", + "MEWTWONITE_X": "Mewtwoïte X", + "MEWTWONITE_Y": "Mewtwoïte Y", + "PIDGEOTITE": "Roucarnagite", + "PINSIRITE": "Scarabruite", + "RAYQUAZITE": "Rayquazite", + "SABLENITE": "Ténéfixite", + "SALAMENCITE": "Drattakite", + "SCEPTILITE": "Jungkite", + "SCIZORITE": "Cizayoxite", + "SHARPEDONITE": "Sharpedite", + "SLOWBRONITE": "Flagadossite", + "STEELIXITE": "Steelixite", + "SWAMPERTITE": "Laggronite", + "TYRANITARITE": "Tyranocivite", + "VENUSAURITE": "Florizarrite", + + "BLUE_ORB": "Gemme Bleue", + "RED_ORB": "Gemme Rouge", + "SHARP_METEORITE": "Méteorite Aiguisée", + "HARD_METEORITE": "Méteorite Solide", + "SMOOTH_METEORITE": "Méteorite Lisse", + "ADAMANT_CRYSTAL": "Globe Adamant", + "LUSTROUS_ORB": "Orbe Perlé", + "GRISEOUS_CORE": "Globe Platiné", + "REVEAL_GLASS": "Miroir Sacré", + "GRACIDEA": "Gracidée", + "MAX_MUSHROOMS": "Maxi Champis", + "DARK_STONE": "Galet Noir", + "LIGHT_STONE": "Galet Blanc", + "PRISON_BOTTLE": "Vase Scellé", + "N_LUNARIZER": "Necroluna", + "N_SOLARIZER": "Necrosol", + "RUSTED_SWORD": "Épée Rouillée", + "RUSTED_SHIELD": "Bouclier Rouillé", + "ICY_REINS_OF_UNITY": "Rênes de l’Unité du Froid", + "SHADOW_REINS_OF_UNITY": "Rênes de l’Unité d’Effroi", + "WELLSPRING_MASK": "Masque du Puits", + "HEARTHFLAME_MASK": "Masque du Fourneau", + "CORNERSTONE_MASK": "Masque de la Pierre", + "SHOCK_DRIVE": "Module Choc", + "BURN_DRIVE": "Module Pyro", + "CHILL_DRIVE": "Module Aqua", + "DOUSE_DRIVE": "Module Choc", + }, + TeraType: { + "UNKNOWN": "Inconnu", + "NORMAL": "Normal", + "FIGHTING": "Combat", + "FLYING": "Vol", + "POISON": "Poison", + "GROUND": "Sol", + "ROCK": "Roche", + "BUG": "Insecte", + "GHOST": "Spectre", + "STEEL": "Acier", + "FIRE": "Feu", + "WATER": "Eau", + "GRASS": "Plante", + "ELECTRIC": "Électrik", + "PSYCHIC": "Psy", + "ICE": "Glace", + "DRAGON": "Dragon", + "DARK": "Ténèbres", + "FAIRY": "Fée", + "STELLAR": "Stellaire", + }, +} as const; diff --git a/src/locales/fr/move.ts b/src/locales/fr/move.ts index e4d7f5e03fa..3a0ce42c44d 100644 --- a/src/locales/fr/move.ts +++ b/src/locales/fr/move.ts @@ -2915,7 +2915,7 @@ export const move: MoveTranslationEntries = { }, "zippyZap": { name: "Pika-Sprint", - effect: "Une attaque électrique rapide comme l’éclair qui auguemente l’esquive. Frappe en priorité." + effect: "Une attaque électrique rapide comme l’éclair qui augmente l’esquive. Frappe en priorité." }, "splishySplash": { name: "Pika-Splash", diff --git a/src/locales/fr/pokemon-stat.ts b/src/locales/fr/pokemon-stat.ts index 3ab39f0af23..62aa97fc1fd 100644 --- a/src/locales/fr/pokemon-stat.ts +++ b/src/locales/fr/pokemon-stat.ts @@ -7,10 +7,10 @@ export const pokemonStat: SimpleTranslationEntries = { "ATKshortened": "Atq", "DEF": "Défense", "DEFshortened": "Déf", - "SPATK": "Atq. Spé", + "SPATK": "Atq. Spé.", "SPATKshortened": "AtqSp", - "SPDEF": "Déf. Spé", + "SPDEF": "Déf. Spé.", "SPDEFshortened": "DéfSp", "SPD": "Vitesse", "SPDshortened": "Vit" -} as const; \ No newline at end of file +} as const; diff --git a/src/locales/fr/splash-messages.ts b/src/locales/fr/splash-messages.ts new file mode 100644 index 00000000000..ef7a8c3335a --- /dev/null +++ b/src/locales/fr/splash-messages.ts @@ -0,0 +1,37 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const splashMessages: SimpleTranslationEntries = { + "battlesWon": "combats gagnés !", + "joinTheDiscord": "Rejoins le Discord !", + "infiniteLevels": "Niveaux infinis !", + "everythingStacks": "Tout se cumule !", + "optionalSaveScumming": "Optional Save Scumming!", + "biomes": "35 biomes !", + "openSource": "Open Source !", + "playWithSpeed": "Joue en vitesse x5 !", + "liveBugTesting": "Tests de bugs en direct !", + "heavyInfluence": "Grosse influence de RoR2 !", + "pokemonRiskAndPokemonRain": "Pokémon Risk et Pokémon Rain !", + "nowWithMoreSalt": "Désormais avec 33% de sel en plus !", + "infiniteFusionAtHome": "Infinite Fusion, chez vous !", + "brokenEggMoves": "Des Capacités Œuf craquées !", + "magnificent": "Magnifique !", + "mubstitute": "Mubstitute !", + "thatsCrazy": "C’est une dinguerie !", + "oranceJuice": "Jus d’orange !", + "questionableBalancing": "Équilibrage douteux !", + "coolShaders": "Cool shaders !", + "aiFree": "Garanti sans IA !", + "suddenDifficultySpikes": "De soudains pics de difficultés !", + "basedOnAnUnfinishedFlashGame": "Basé sur un jeu Flash abandonné !", + "moreAddictiveThanIntended": "Plus addictif que prévu !", + "mostlyConsistentSeeds": "Des seeds à peu près stables !", + "achievementPointsDontDoAnything": "Les Points de Succès servent à rien !", + "youDoNotStartAtLevel": "Ne commence pas au Niveau 2000 !", + "dontTalkAboutTheManaphyEggIncident": "Ne parle pas de l'incident de l’Œuf de Manaphy !", + "alsoTryPokengine": "Essaye aussi Pokéngine !", + "alsoTryEmeraldRogue": "Essaye aussi Emerald Rogue!", + "alsoTryRadicalRed": "Essaye aussi Radical Red !", + "eeveeExpo": "Eevee Expo !", + "ynoproject": "YNOproject !", +} as const; diff --git a/src/locales/fr/starter-select-ui-handler.ts b/src/locales/fr/starter-select-ui-handler.ts index d26fa3314b6..380f4e9fd56 100644 --- a/src/locales/fr/starter-select-ui-handler.ts +++ b/src/locales/fr/starter-select-ui-handler.ts @@ -7,6 +7,15 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; */ export const starterSelectUiHandler: SimpleTranslationEntries = { "confirmStartTeam":'Commencer avec ces Pokémon ?', + "gen1": "1G", + "gen2": "2G", + "gen3": "3G", + "gen4": "4G", + "gen5": "5G", + "gen6": "6G", + "gen7": "7G", + "gen8": "8G", + "gen9": "9G", "growthRate": "Croissance :", "ability": "Talent :", "passive": "Passif :", @@ -31,5 +40,5 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "disablePassive": "Désactiver Passif", "locked": "Verrouillé", "disabled": "Désactivé", - "uncaught": "Uncaught" + "uncaught": "Non-capturé" } diff --git a/src/locales/fr/trainers.ts b/src/locales/fr/trainers.ts new file mode 100644 index 00000000000..c73f0b1b1c5 --- /dev/null +++ b/src/locales/fr/trainers.ts @@ -0,0 +1,244 @@ +import {SimpleTranslationEntries} from "#app/plugins/i18n"; + +// Titles of special trainers like gym leaders, elite four, and the champion +export const titles: SimpleTranslationEntries = { + "elite_four": "Conseil 4", + "gym_leader": "Champion d’Arène", + "gym_leader_female": "Championne d’Arène", + "champion": "Maitre·esse", //Written in gender-inclusive language in wait of a potential split of the entry + "rival": "Rival·e", //Written in gender-inclusive language in wait of a potential split of the entry + "professor": "Professeur·e", //Written in gender-inclusive language in wait of a potential split of the entry + "frontier_brain": "Meneur·euse de Zone", //Written in gender-inclusive language in wait of a potential split of the entry + // Maybe if we add the evil teams we can add "Team Rocket" and "Team Aqua" etc. here as well as "Team Rocket Boss" and "Team Aqua Admin" etc. +} as const; + +// Titles of trainers like "Youngster" or "Lass" +export const trainerClasses: SimpleTranslationEntries = { + "ace_trainer": "Topdresseur", + "ace_trainer_female": "Topdresseuse", + "ace_duo": "Topdresseurs", + "artist": "Artiste", + "artist_female": "Artiste", + "backers": "Pompom Girls", + "backpacker": "Randonneur", + "backpacker_female": "Randonneuse", + "backpackers": "Randonneurs", + "baker": "Boulangère", + "battle_girl": "Combattante", + "beauty": "Canon", + "beginners": "Beginners", + "biker": "Motard", + "black_belt": "Karatéka", + "breeder": "Éleveur", + "breeder_female": "Éleveuse", + "breeders": "Éleveurs", + "clerk": "Employé", + "clerk_female": "Employée", + "colleagues": "Collègues de Bureau", + "crush_kin": "Duo Baston", + "cyclist": "Cycliste", + "cyclist_female": "Cycliste", + "cyclists": "Cyclistes", + "dancer": "Danseur", + "dancer_female": "Danseuse", + "depot_agent": "Cheminot", + "doctor": "Docteur", + "doctor_female": "Docteure", + "fisherman": "Pêcheur", + "fisherman_female": "Pêcheuse", + "gentleman": "Gentleman", + "guitarist": "Guitariste", + "guitarist_female": "Guitariste", + "harlequin": "Clown", + "hiker": "Montagnard", + "hooligans": "Loubards", + "hoopster": "Basketteur", + "infielder": "Baseballeur", + "janitor": "Nettoyeur", + "lady": "Mademoiselle", + "lass": "Fillette", + "linebacker": "Quaterback", + "maid": "Gouvernante", + "madame": "Mondaine", + "medical_team": "Médecins", + "musician": "Musicien", + "hex_maniac": "Mystimaniac", + "nurse": "Infirmière", + "nursery_aide": "Institutrice", + "officer": "Policier", + "parasol_lady": "Sœur Parasol", + "pilot": "Pilote", + "pokefan": "Poké Fan", + "pokefan_family": "Couple de Pokéfans", + "preschooler": "Petit", + "preschooler_female": "Petite", + "preschoolers": "Petits", + "psychic": "Kinésiste", + "psychic_female": "Kinésiste", + "psychics": "Kinésistes", + "pokémon_ranger": "Pokémon Ranger", + "pokémon_rangers": "Pokémon Rangers", + "ranger": "Ranger", + "restaurant_staff": "Serveurs", + "rich": "Rich", + "rich_female": "Mondaine", + "rich_boy": "Gentleman", + "rich_couple": "Couple de Bourgeois", + "rich_kid": "Richard", + "rich_kid_female": "Mademoiselle", + "rich_kids": "Richards", + "roughneck": "Loubard", + "scientist": "Scientifique", + "scientist_female": "Scientifique", + "scientists": "Scientifiques", + "smasher": "Tenniswoman", + "snow_worker": "Ouvrier Alpin", + "snow_worker_female": "Ouvrière Alpine", + "striker": "Footballeur", + "school_kid": "Élève", + "school_kid_female": "Élève", + "school_kids": "Élèves", + "swimmer": "Nageur", + "swimmer_female": "Nageuse", + "swimmers": "Nageurs", + "twins": "Jumelles", + "veteran": "Vénérable", + "veteran_female": "Vénérable", + "veteran_duo": "Vénérables", + "waiter": "Serveur", + "waitress": "Serveuse", + "worker": "Ouvrier", + "worker_female": "Ouvrière", + "workers": "Ouvriers", + "youngster": "Gamin" +} as const; + +// Names of special trainers like gym leaders, elite four, and the champion +export const trainerNames: SimpleTranslationEntries = { + "brock": "Pierre", + "misty": "Ondine", + "lt_surge": "Major Bob", + "erika": "Erika", + "janine": "Jeannine", + "sabrina": "Morgane", + "blaine": "Auguste", + "giovanni": "Giovanni", + "falkner": "Albert", + "bugsy": "Hector", + "whitney": "Blanche", + "morty": "Mortimer", + "chuck": "Chuck", + "jasmine": "Jasmine", + "pryce": "Frédo", + "clair": "Sandra", + "roxanne": "Roxanne", + "brawly": "Bastien", + "wattson": "Voltère", + "flannery": "Adriane", + "norman": "Norman", + "winona": "Alizée", + "tate": "Lévy", + "liza": "Tatia", + "juan": "Juan", + "roark": "Pierrick", + "gardenia": "Flo", + "maylene": "Mélina", + "crasher_wake": "Lovis", + "fantina": "Kiméra", + "byron": "Charles", + "candice": "Gladys", + "volkner": "Tanguy", + "cilan": "Rachid", + "chili": "Armando", + "cress": "Noa", + "cheren": "Tcheren", + "lenora": "Aloé", + "roxie": "Strykna", + "burgh": "Artie", + "elesa": "Inezia", + "clay": "Bardane", + "skyla": "Carolina", + "brycen": "Zhu", + "drayden": "Watson", + "marlon": "Amana", + "viola": "Violette", + "grant": "Lino", + "korrina": "Cornélia", + "ramos": "Amaro", + "clemont": "Lem", + "valerie": "Valériane", + "olympia": "Astera", + "wulfric": "Urup", + "milo": "Percy", + "nessa": "Donna", + "kabu": "Kabu", + "bea": "Faïza", + "allister": "Alistair", + "opal": "Sally", + "bede": "Travis", + "gordie": "Chaz", + "melony": "Lona", + "piers": "Peterson", + "marnie": "Rosemary", + "raihan": "Roy", + "katy": "Éra", + "brassius": "Colza", + "iono": "Mashynn", + "kofu": "Kombu", + "larry": "Okuba", + "ryme": "Laïm", + "tulip": "Tully", + "grusha": "Grusha", + "lorelei": "Olga", + "bruno": "Aldo", + "agatha": "Agatha", + "lance": "Peter", + "will": "Clément", + "koga": "Koga", + "karen": "Marion", + "sidney": "Damien", + "phoebe": "Spectra", + "glacia": "Glacia", + "drake": "Aragon", + "aaron": "Aaron", + "bertha": "Terry", + "flint": "Adrien", + "lucian": "Lucio", + "shauntal": "Anis", + "marshal": "Kunz", + "grimsley": "Pieris", + "caitlin": "Percila", + "malva": "Malva", + "siebold": "Narcisse", + "wikstrom": "Tileo", + "drasna": "Dracéna", + "hala": "Pectorius", + "molayne": "Molène", + "olivia": "Alyxia", + "acerola": "Margie", + "kahili": "Kahili", + "rika": "Cayenn", + "poppy": "Popi", + "larry_elite": "Okuba", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "hassel": "Hassa", + "crispin": "Rubépin", + "amarys": "Nérine", + "lacey": "Taro", + "drayton": "Irido", + "blue": "Blue", + "red": "Red", + "lance_champion": "Peter", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "steven": "Pierre Rochard", + "wallace": "Marc", + "cynthia": "Cynthia", + "alder": "Goyah", + "iris": "Iris", + "diantha": "Dianthéa", + "hau": "Tili", + "geeta": "Alisma", + "nemona": "Menzi", + "kieran": "Kass", + "leon": "Tarak", + "rival": "Gwenaël", //Male breton name, a celtic language spoken in Brittany (France) and related to the word for "white" (gwenn). Finn meaning is also "white" in irish/goidelic which are also celtic languages. + "rival_female": "Papina", //Litteral translation of ivy, also used as Female name in a North-American indigenous language +} as const; diff --git a/src/locales/fr/weather.ts b/src/locales/fr/weather.ts new file mode 100644 index 00000000000..f00e7e08a03 --- /dev/null +++ b/src/locales/fr/weather.ts @@ -0,0 +1,44 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +/** + * The weather namespace holds text displayed when weather is active during a battle + */ +export const weather: SimpleTranslationEntries = { + "sunnyStartMessage": "Les rayons du soleil brillent !", + "sunnyLapseMessage": "Les rayons du soleil brillent fort !", + "sunnyClearMessage": "Les rayons du soleil s’affaiblissent !", + + "rainStartMessage": "Il commence à pleuvoir !", + "rainLapseMessage": "La pluie continue de tomber !", + "rainClearMessage": "La pluie s’est arrêtée !", + + "sandstormStartMessage": "Une tempête de sable se prépare !", + "sandstormLapseMessage": "La tempête de sable fait rage !", + "sandstormClearMessage": "La tempête de sable se calme !", + "sandstormDamageMessage": "La tempête de sable inflige des dégâts\nà {{pokemonPrefix}}{{pokemonName}} !", + + "hailStartMessage": "Il commence à grêler !", + "hailLapseMessage": "La grêle continue de tomber !", + "hailClearMessage": "La grêle s’est arrêtée !", + "hailDamageMessage": "La grêle inflige des dégâts\nà {{pokemonPrefix}}{{pokemonName}} !", + + "snowStartMessage": "Il commence à neiger !", + "snowLapseMessage": "Il y a une tempête de neige !", + "snowClearMessage": "La neige s’est arrêtée !", + + "fogStartMessage": "Le brouillard devient épais…", + "fogLapseMessage": "Le brouillard continue !", + "fogClearMessage": "Le brouillard s’est dissipé !", + + "heavyRainStartMessage": "Une pluie battante s’abat soudainement !", + "heavyRainLapseMessage": "La pluie battante continue.", + "heavyRainClearMessage": "La pluie battante s’est arrêtée…", + + "harshSunStartMessage": "Les rayons du soleil s’intensifient !", + "harshSunLapseMessage": "Les rayons du soleil sont brulants !", + "harshSunClearMessage": "Les rayons du soleil s’affaiblissent !", + + "strongWindsStartMessage": "Un vent mystérieux se lève !", + "strongWindsLapseMessage": "Le vent mystérieux souffle violemment !", + "strongWindsClearMessage": "Le vent mystérieux s’est dissipé…" +} diff --git a/src/locales/it/battle-message-ui-handler.ts b/src/locales/it/battle-message-ui-handler.ts new file mode 100644 index 00000000000..346f856872c --- /dev/null +++ b/src/locales/it/battle-message-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battleMessageUiHandler: SimpleTranslationEntries = { + "ivBest": "Best", + "ivFantastic": "Fantastic", + "ivVeryGood": "Very Good", + "ivPrettyGood": "Pretty Good", + "ivDecent": "Decent", + "ivNoGood": "No Good", +} as const; \ No newline at end of file diff --git a/src/locales/it/battle.ts b/src/locales/it/battle.ts index a3cffaa60d7..3eff2493ed6 100644 --- a/src/locales/it/battle.ts +++ b/src/locales/it/battle.ts @@ -3,6 +3,7 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}} è apparso.", "trainerAppeared": "{{trainerName}}\nvuole combattere!", + "trainerAppearedDouble": "{{trainerName}}\nwould like to battle!", "singleWildAppeared": "Appare {{pokemonName}} selvatico!", "multiWildAppeared": "Appaiono {{pokemonName1}}\ne {{pokemonName2}} salvatici!", "playerComeBack": "Rientra, {{pokemonName}}!", @@ -31,6 +32,8 @@ export const battle: SimpleTranslationEntries = { "learnMoveNotLearned": "{{pokemonName}} non ha imparato\n{{moveName}}.", "learnMoveForgetQuestion": "Quale mossa deve dimenticare?", "learnMoveForgetSuccess": "{{pokemonName}} ha dimenticato la mossa\n{{moveName}}.", + "countdownPoof": "@d{32}1, @d{15}2, @d{15}e@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}Puff!", + "learnMoveAnd": "E…", "levelCapUp": "Il livello massimo\nè aumentato a {{levelCap}}!", "moveNotImplemented": "{{moveName}} non è ancora implementata e non può essere selezionata.", "moveNoPP": "Non ci sono PP rimanenti\nper questa mossa!", diff --git a/src/locales/it/berry.ts b/src/locales/it/berry.ts new file mode 100644 index 00000000000..8c8bc5ee280 --- /dev/null +++ b/src/locales/it/berry.ts @@ -0,0 +1,48 @@ +import { BerryTranslationEntries } from "#app/plugins/i18n"; + +export const berry: BerryTranslationEntries = { + "SITRUS": { + name: "Sitrus Berry", + effect: "Restores 25% HP if HP is below 50%", + }, + "LUM": { + name: "Lum Berry", + effect: "Cures any non-volatile status condition and confusion", + }, + "ENIGMA": { + name: "Enigma Berry", + effect: "Restores 25% HP if hit by a super effective move", + }, + "LIECHI": { + name: "Liechi Berry", + effect: "Raises Attack if HP is below 25%", + }, + "GANLON": { + name: "Ganlon Berry", + effect: "Raises Defense if HP is below 25%", + }, + "PETAYA": { + name: "Petaya Berry", + effect: "Raises Sp. Atk if HP is below 25%", + }, + "APICOT": { + name: "Apicot Berry", + effect: "Raises Sp. Def if HP is below 25%", + }, + "SALAC": { + name: "Salac Berry", + effect: "Raises Speed if HP is below 25%", + }, + "LANSAT": { + name: "Lansat Berry", + effect: "Raises critical hit ratio if HP is below 25%", + }, + "STARF": { + name: "Starf Berry", + effect: "Sharply raises a random stat if HP is below 25%", + }, + "LEPPA": { + name: "Leppa Berry", + effect: "Restores 10 PP to a move if its PP reaches 0", + }, +} as const; \ No newline at end of file diff --git a/src/locales/it/config.ts b/src/locales/it/config.ts index 6ba9aa3affa..89d78304120 100644 --- a/src/locales/it/config.ts +++ b/src/locales/it/config.ts @@ -2,33 +2,48 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; +import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; import { menuUiHandler } from "./menu-ui-handler"; +import { modifierType } from "./modifier-type"; import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonStat } from "./pokemon-stat"; +import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; +import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; - +import { weather } from "./weather"; +import { battleMessageUiHandler } from "./battle-message-ui-handler"; +import { berry } from "./berry"; export const itConfig = { ability: ability, abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, + egg: egg, fightUiHandler: fightUiHandler, - menuUiHandler: menuUiHandler, + growth: growth, menu: menu, + menuUiHandler: menuUiHandler, + modifierType: modifierType, move: move, - pokeball: pokeball, - pokemonStat: pokemonStat, - pokemon: pokemon, - starterSelectUiHandler: starterSelectUiHandler, - tutorial: tutorial, nature: nature, - growth: growth + pokeball: pokeball, + pokemon: pokemon, + pokemonStat: pokemonStat, + splashMessages: splashMessages, + starterSelectUiHandler: starterSelectUiHandler, + titles: titles, + trainerClasses: trainerClasses, + trainerNames: trainerNames, + tutorial: tutorial, + weather: weather, + battleMessageUiHandler: battleMessageUiHandler, + berry: berry, } \ No newline at end of file diff --git a/src/locales/it/egg.ts b/src/locales/it/egg.ts new file mode 100644 index 00000000000..5634a2ae15b --- /dev/null +++ b/src/locales/it/egg.ts @@ -0,0 +1,21 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const egg: SimpleTranslationEntries = { + "egg": "Uovo", + "defaultTier": "Comune", + "greatTier": "Raro", + "ultraTier": "Epico", + "masterTier": "Leggendario", + "hatchWavesMessageSoon": "Si sentono dei suoni provenienti dall'interno! Si schiuderà presto!", + "hatchWavesMessageClose": "Sembra muoversi di tanto in tanto. Potrebbe essere prossimo alla schiusa.", + "hatchWavesMessageNotClose": "Cosa uscirà da qui? Non sembra si schiuderà presto.", + "hatchWavesMessageLongTime": "Sembra che questo uovo impiegherà molto tempo per schiudersi.", + "gachaTypeLegendary": "Tasso dei Leggendari Aumentato", + "gachaTypeMove": "Tasso delle Mosse Rare delle Uova Aumentato", + "gachaTypeShiny": "Tasso degli Shiny Aumentato", + "selectMachine": "Seleziona un distributore.", + "notEnoughVouchers": "Non hai abbastanza Biglietti!", + "tooManyEggs": "Hai troppe Uova!", + "pull": "Tiro", + "pulls": "Tiri" +} as const; \ No newline at end of file diff --git a/src/locales/it/menu-ui-handler.ts b/src/locales/it/menu-ui-handler.ts index 9def62d8da3..e0328fccdc1 100644 --- a/src/locales/it/menu-ui-handler.ts +++ b/src/locales/it/menu-ui-handler.ts @@ -9,7 +9,7 @@ export const menuUiHandler: SimpleTranslationEntries = { "EGG_GACHA": "Gacha Uova", "MANAGE_DATA": "Gestisci Dati", "COMMUNITY": "Community", - "RETURN_TO_TITLE": "Ritorna al Titolo", + "SAVE_AND_QUIT": "Salva ed Esci", "LOG_OUT": "Disconnettiti", "slot": "Slot {{slotNumber}}", "importSession": "Importa Sessione", diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index 1344b21cc53..e86a6be25ed 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -40,6 +40,11 @@ export const menu: SimpleTranslationEntries = { "noRankings": "Nessuna Classifica", "loading": "Caricamento…", "playersOnline": "Giocatori Online", + "evolving": "Cosa?\n{{pokemonName}} si evolvendo!", + "stoppedEvolving": "{{pokemonName}} ha smesso di evolversi.", + "pauseEvolutionsQuestion": "Vuoi sospendere le evoluzioni per {{pokemonName}}?\nLe evoluzioni possono essere riattivate dalla schermata del party.", + "evolutionsPaused": "Le evoluzioni sono state sospese per {{pokemonName}}.", + "evolutionDone": "Congratulazioni!\n{{pokemonName}} si è evoluto in {{evolvedPokemonName}}!", "empty":"Vuoto", "yes":"Si", "no":"No", diff --git a/src/locales/it/modifier-type.ts b/src/locales/it/modifier-type.ts new file mode 100644 index 00000000000..7f342309acf --- /dev/null +++ b/src/locales/it/modifier-type.ts @@ -0,0 +1,409 @@ +import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; + +export const modifierType: ModifierTypeTranslationEntries = { + ModifierType: { + "AddPokeballModifierType": { + name: "{{modifierCount}}x {{pokeballName}}", + description: "Ricevi {{pokeballName}} x{{modifierCount}} (Inventario: {{pokeballAmount}}) \nTasso di cattura: {{catchRate}}", + }, + "AddVoucherModifierType": { + name: "{{modifierCount}}x {{voucherTypeName}}", + description: "Ricevi {{voucherTypeName}} x{{modifierCount}}", + }, + "PokemonHeldItemModifierType": { + extra: { + "inoperable": "{{pokemonName}} non può prendere\nquesto oggetto!", + "tooMany": "{{pokemonName}} ne ha troppi\ndi questo oggetto!", + } + }, + "PokemonHpRestoreModifierType": { + description: "Restituisce {{restorePoints}} PS o {{restorePercent}}% PS ad un Pokémon, a seconda del valore più alto", + extra: { + "fully": "Restituisce tutti gli PS ad un Pokémon", + "fullyWithStatus": "Restituisce tutti gli PS ad un Pokémon e lo cura da ogni stato", + } + }, + "PokemonReviveModifierType": { + description: "Rianima un Pokémon esausto e gli restituisce il {{restorePercent}}% PS", + }, + "PokemonStatusHealModifierType": { + description: "Cura tutti i problemi di stato di un Pokémon", + }, + "PokemonPpRestoreModifierType": { + description: "Restituisce {{restorePoints}} PP per una mossa di un Pokémon ", + extra: { + "fully": "Restituisce tutti i PP di una mossa", + } + }, + "PokemonAllMovePpRestoreModifierType": { + description: "Restituisce {{restorePoints}} PP a tutte le mosse di un Pokémon", + extra: { + "fully": "Restituisce tutti i PP a tutte le mosse di un Pokémon", + } + }, + "PokemonPpUpModifierType": { + description: "Aumenta i PP di una mossa di {{upPoints}} per ogni 5 PP (massimo 3)", + }, + "PokemonNatureChangeModifierType": { + name: "Menta {{natureName}}", + description: "Cambia la natura del Pokémon in {{natureName}} e sblocca la natura per il Pokémon iniziale", + }, + "DoubleBattleChanceBoosterModifierType": { + description: "Raddoppia la possibilità di imbattersi in doppie battaglie per {{battleCount}} battaglie", + }, + "TempBattleStatBoosterModifierType": { + description: "Aumenta {{tempBattleStatName}} di un livello a tutti i Pokémon nel gruppo per 5 battaglie", + }, + "AttackTypeBoosterModifierType": { + description: "Aumenta la potenza delle mosse di tipo {{moveType}} del 20% per un Pokémon", + }, + "PokemonLevelIncrementModifierType": { + description: "Fa salire un Pokémon di un livello", + }, + "AllPokemonLevelIncrementModifierType": { + description: "Aumenta il livello di tutti i Pokémon nel gruppo di 1", + }, + "PokemonBaseStatBoosterModifierType": { + description: "Aumenta {{statName}} di base del possessore del 10%", + }, + "AllPokemonFullHpRestoreModifierType": { + description: "Recupera il 100% degli PS per tutti i Pokémon", + }, + "AllPokemonFullReviveModifierType": { + description: "Rianima tutti i Pokémon esausti restituendogli tutti i PS", + }, + "MoneyRewardModifierType": { + description: "Garantisce una {{moneyMultiplier}} quantità di soldi (₽{{moneyAmount}})", + extra: { + "small": "poca", + "moderate": "moderata", + "large": "grande", + }, + }, + "ExpBoosterModifierType": { + description: "Aumenta il guadagno di Punti Esperienza del {{boostPercent}}%", + }, + "PokemonExpBoosterModifierType": { + description: "Aumenta il guadagno di Punti Esperienza del possessore del {{boostPercent}}%", + }, + "PokemonFriendshipBoosterModifierType": { + description: "Aumenta del 50% il guadagno di amicizia per vittoria", + }, + "PokemonMoveAccuracyBoosterModifierType": { + description: "Aumenta l'accuratezza delle mosse di {{accuracyAmount}} (massimo 100)", + }, + "PokemonMultiHitModifierType": { + description: "Gli attacchi colpiscono una volta in più al costo di una riduzione di potenza del 60/75/82,5% per mossa", + }, + "TmModifierType": { + name: "MT{{moveId}} - {{moveName}}", + description: "Insegna {{moveName}} a un Pokémon", + }, + "EvolutionItemModifierType": { + description: "Fa evolvere determinate specie di Pokémon", + }, + "FormChangeItemModifierType": { + description: "Fa cambiare forma a determinati Pokémon", + }, + "FusePokemonModifierType": { + description: "Combina due Pokémon (trasferisce i poteri, divide le statistiche e i tipi base, condivide il pool di mosse)", + }, + "TerastallizeModifierType": { + name: "Teralite {{teraType}}", + description: "Teracristallizza in {{teraType}} il possessore per massimo 10 battaglie", + }, + "ContactHeldItemTransferChanceModifierType": { + description: "Quando si attacca, c'è una probabilità del {{chancePercent}}% che l'oggetto in possesso del nemico venga rubato", + }, + "TurnHeldItemTransferModifierType": { + description: "Ogni turno, il possessore acquisisce un oggetto posseduto dal nemico", + }, + "EnemyAttackStatusEffectChanceModifierType": { + description: "Aggiunge una probabilità del {{chancePercent}}% di infliggere {{statusEffect}} con le mosse d'attacco", + }, + "EnemyEndureChanceModifierType": { + description: "Aggiunge una probabilità del {{probabilitàPercent}}% di resistere ad un colpo", + }, + + "RARE_CANDY": { name: "Caramella Rara" }, + "RARER_CANDY": { name: "Caramella Molto Rara" }, + + "MEGA_BRACELET": { name: "Megapolsiera", description: "Le Megapietre sono disponibili" }, + "DYNAMAX_BAND": { name: "Polsino Dynamax", description: "I Fungomax sono disponibili" }, + "TERA_ORB": { name: "Terasfera", description: "I Teraliti sono disponibili" }, + + "MAP": { name: "Mappa", description: "Permette di scegliere la propria strada a un bivio" }, + + "POTION": { name: "Pozione" }, + "SUPER_POTION": { name: "Superpozione" }, + "HYPER_POTION": { name: "Iperpozione" }, + "MAX_POTION": { name: "Pozione Max" }, + "FULL_RESTORE": { name: "Ricarica Totale" }, + + "REVIVE": { name: "Revitalizzante" }, + "MAX_REVIVE": { name: "Revitalizzante Max" }, + + "FULL_HEAL": { name: "Cura Totale" }, + + "SACRED_ASH": { name: "Cenere Magica" }, + + "REVIVER_SEED": { name: "Revitalseme", description: "Il possessore recupera 1/2 di PS in caso di svenimento" }, + + "ETHER": { name: "Etere" }, + "MAX_ETHER": { name: "Etere Max" }, + + "ELIXIR": { name: "Elisir" }, + "MAX_ELIXIR": { name: "Elisir Max" }, + + "PP_UP": { name: "PP-su" }, + "PP_MAX": { name: "PP-max" }, + + "LURE": { name: "Profumo Invito" }, + "SUPER_LURE": { name: "Profumo Invito Super" }, + "MAX_LURE": { name: "Profumo Invito Max" }, + + "MEMORY_MUSHROOM": { name: "Fungo della Memoria", description: "Ricorda la mossa dimenticata di un Pokémon" }, + + "EXP_SHARE": { name: "Condividi Esperienza", description: "Tutti i Pokémon della squadra ricevono il 20% dei Punti Esperienza dalla lotta anche se non vi hanno partecipato" }, + "EXP_BALANCE": { name: "Bilancia Esperienza", description: "Bilancia i Punti Esperienza ricevuti verso i Pokémon del gruppo di livello inferiore" }, + + "OVAL_CHARM": { name: "Ovamuleto", description: "Quando più Pokémon partecipano a una battaglia, ognuno di essi riceve il 10% in più dell'esperienza totale" }, + + "EXP_CHARM": { name: "Esperienzamuleto" }, + "SUPER_EXP_CHARM": { name: "Esperienzamuleto Super" }, + "GOLDEN_EXP_CHARM": { name: "Esperienzamuleto Oro" }, + + "LUCKY_EGG": { name: "Uovo Fortunato" }, + "GOLDEN_EGG": { name: "Uovo d'Oro" }, + + "SOOTHE_BELL": { name: "Calmanella" }, + + "SOUL_DEW": { name: "Cuorugiada", description: "Aumenta del 10% l'influenza della natura di un Pokémon sulle sue statistiche (Aggiuntivo)" }, + + "NUGGET": { name: "Pepita" }, + "BIG_NUGGET": { name: "Granpepita" }, + "RELIC_GOLD": { name: " Dobloantico" }, + + "AMULET_COIN": { name: "Monetamuleto", description: "Aumenta le ricompense in denaro del 20%" }, + "GOLDEN_PUNCH": { name: "Pugno Dorato", description: "Garantisce il 50% dei danni inflitti come denaro" }, + "COIN_CASE": { name: " Salvadanaio", description: "Dopo ogni 10° battaglia, riceverete il 10% del vostro denaro in interessi" }, + + "LOCK_CAPSULE": { name: "Capsula Scrigno", description: "Permette di bloccare le rarità degli oggetti quando si fa un reroll degli oggetti" }, + + "GRIP_CLAW": { name: "Presartigli" }, + "WIDE_LENS": { name: "Grandelente" }, + + "MULTI_LENS": { name: "Multilente" }, + + "HEALING_CHARM": { name: "Curamuleto", description: "Aumenta del 10% l'efficacia delle mosse e degli oggetti che ripristinano gli PS (escluse le rianimazioni)" }, + "CANDY_JAR": { name: "Barattolo di caramelle", description: "Aumenta di 1 il numero di livelli aggiunti dalle Caramelle Rare" }, + + "BERRY_POUCH": { name: "Porta Bacche", description: "Aggiunge il 25% di possibilità che una bacca usata non venga consumata" }, + + "FOCUS_BAND": { name: "Bandana", description: "Chi ce l'ha ottiene il 10% di possibilità aggiuntivo di evitare un potenziale KO e rimanere con un solo PS" }, + + "QUICK_CLAW": { name: "Rapidartigli", description: "Aggiunge una probabilità del 10% di muoversi per primi, indipendentemente dalla velocità (dopo la priorità)" }, + + "KINGS_ROCK": { name: "Roccia di re", description: "Aggiunge il 10% di possibilità che una mossa d'attacco faccia tentennare l'avversario" }, + + "LEFTOVERS": { name: "Avanzi", description: "Ripristina 1/16 dei PS massimi di un Pokémon ogni turno" }, + "SHELL_BELL": { name: "Conchinella", description: "Guarisce 1/8 del danno inflitto a un Pokémon" }, + + "BATON": { name: "Staffetta", description: "Permette di trasmettere gli effetti quando si cambia Pokémon, aggirando anche le trappole" }, + + "SHINY_CHARM": { name: "Cromamuleto", description: "Misterioso amuleto luminoso che aumenta la probabilità di incontrare Pokémon cromatici" }, + "ABILITY_CHARM": { name: "Abilitamuleto", description: "Aumenta drasticamente la possibilità che un Pokémon selvatico abbia un'abilità nascosta" }, + + "IV_SCANNER": { name: "Scanner IV", description: "Permette di scansionare gli IV dei Pokémon selvatici. Vengono rivelati 2 IV per pila. I migliori IV vengono mostrati per primi" }, + + "DNA_SPLICERS": { name: " Cuneo DNA" }, + + "MINI_BLACK_HOLE": { name: "Piccolo Buco Nero" }, + + "GOLDEN_POKEBALL": { name: "Poké Ball Oro", description: "Aggiunge 1 opzione di oggetto extra alla fine di ogni battaglia" }, + + "ENEMY_DAMAGE_BOOSTER": { name: "Gettone del Danno", description: "Aumenta il danno del 5%" }, + "ENEMY_DAMAGE_REDUCTION": { name: "Gettone della Protezione", description: "Riduce i danni ricevuti del 2.5%" }, + "ENEMY_HEAL": { name: "Gettone del Recupero", description: "Cura il 2% dei PS massimi ogni turno" }, + "ENEMY_ATTACK_POISON_CHANCE": { name: "Gettone del Veleno" }, + "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Gettone della Paralisi" }, + "ENEMY_ATTACK_SLEEP_CHANCE": { name: "Gettone del Sonno" }, + "ENEMY_ATTACK_FREEZE_CHANCE": { name: "Gettone del Congelamento" }, + "ENEMY_ATTACK_BURN_CHANCE": { name: "Gettone della Bruciatura" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Gettone Guarigione Completa", description: "Aggiunge una probabilità del 10% a ogni turno di curare una condizione di stato" }, + "ENEMY_ENDURE_CHANCE": { name: "Gettone di Resistenza" }, + "ENEMY_FUSED_CHANCE": { name: "Gettone della fusione", description: "Aggiunge l'1% di possibilità che un Pokémon selvatico sia una fusione" }, + }, + TempBattleStatBoosterItem: { + "x_attack": "Attacco X", + "x_defense": "Difesa X", + "x_sp_atk": "Att. Speciale X", + "x_sp_def": "Dif. Speciale X", + "x_speed": "Velocità X", + "x_accuracy": "Precisione X", + "dire_hit": "Supercolpo", + }, + AttackTypeBoosterItem: { + "silk_scarf": "Sciarpa seta", + "black_belt": "Cinturanera", + "sharp_beak": "Beccaffilato", + "poison_barb": "Velenaculeo", + "soft_sand": "Sabbia soffice", + "hard_stone": "Pietradura", + "silver_powder": "Argenpolvere", + "spell_tag": "Spettrotarga", + "metal_coat": "Metalcopertura", + "charcoal": "Carbonella", + "mystic_water": "Acqua magica", + "miracle_seed": "Miracolseme", + "magnet": "Magnete", + "twisted_spoon": "Cucchiaio torto", + "never_melt_ice": "Gelomai", + "dragon_fang": "Dente di drago", + "black_glasses": "Occhialineri", + "fairy_feather": "Piuma fatata", + }, + BaseStatBoosterItem: { + "hp_up": "PS-su", + "protein": "Proteina", + "iron": "Ferro", + "calcium": "Calcio", + "zinc": "Zinco", + "carbos": "Carburante", + }, + EvolutionItem: { + "NONE": "Nessuno", + + "LINKING_CORD": "Filo dell'unione", + "SUN_STONE": "Pietrasolare", + "MOON_STONE": "Pietralunare", + "LEAF_STONE": "Pietrafoglia", + "FIRE_STONE": "Pietrafocaia", + "WATER_STONE": "Pietraidrica", + "THUNDER_STONE": "Pietratuono", + "ICE_STONE": "Pietragelo", + "DUSK_STONE": "Neropietra", + "DAWN_STONE": "Pietralbore", + "SHINY_STONE": "Pietrabrillo", + "CRACKED_POT": "Teiera rotta", + "SWEET_APPLE": "Dolcepomo", + "TART_APPLE": "Aspropomo", + "STRAWBERRY_SWEET": "Bonbonfragola", + "UNREMARKABLE_TEACUP": "Tazza dozzinale", + + "CHIPPED_POT": "Teiera crepata", + "BLACK_AUGURITE": "Augite nera", + "GALARICA_CUFF": "Fascia Galarnoce", + "GALARICA_WREATH": "Corona Galarnoce", + "PEAT_BLOCK": "Blocco di torba", + "AUSPICIOUS_ARMOR": "Armatura fausta", + "MALICIOUS_ARMOR": "Armatura infausta", + "MASTERPIECE_TEACUP": "Tazza eccezionale", + "METAL_ALLOY": "Metallo composito", + "SCROLL_OF_DARKNESS": "Rotolo del Buio", + "SCROLL_OF_WATERS": "Rotolo dell'Acqua", + "SYRUPY_APPLE": "Sciroppomo", + }, + FormChangeItem: { + "NONE": "Nessuno", + + "ABOMASITE": "Abomasnowite", + "ABSOLITE": "Absolite", + "AERODACTYLITE": "Aerodactylite", + "AGGRONITE": "Aggronite", + "ALAKAZITE": "Alakazamite", + "ALTARIANITE": "Altarite", + "AMPHAROSITE": "Ampharosite", + "AUDINITE": "Audinite", + "BANETTITE": "Banettite", + "BEEDRILLITE": "Beedrillite", + "BLASTOISINITE": "Blastoisite", + "BLAZIKENITE": "Blazikenite", + "CAMERUPTITE": "Cameruptite", + "CHARIZARDITE_X": "Charizardite X", + "CHARIZARDITE_Y": "Charizardite Y", + "DIANCITE": "Diancite", + "GALLADITE": "Galladite", + "GARCHOMPITE": "Garchompite", + "GARDEVOIRITE": "Gardevoirite", + "GENGARITE": "Gengarite", + "GLALITITE": "Glalite", + "GYARADOSITE": "Gyaradosite", + "HERACRONITE": "Heracronite", + "HOUNDOOMINITE": "Houndoomite", + "KANGASKHANITE": "Kangaskhanite", + "LATIASITE": "Latiasite", + "LATIOSITE": "Latiosite", + "LOPUNNITE": "Lopunnite", + "LUCARIONITE": "Lucarite", + "MANECTITE": "Manectricite", + "MAWILITE": "Mawilite", + "MEDICHAMITE": "Medichamite", + "METAGROSSITE": "Metagrossite", + "MEWTWONITE_X": "Mewtwoite X", + "MEWTWONITE_Y": "Mewtwoite Y", + "PIDGEOTITE": "Pidgeotite", + "PINSIRITE": "Pinsirite", + "RAYQUAZITE": "Rayquazite", + "SABLENITE": "Sableyite", + "SALAMENCITE": "Salamencite", + "SCEPTILITE": "Sceptilite", + "SCIZORITE": "Scizorite", + "SHARPEDONITE": "Sharpedite", + "SLOWBRONITE": "Slowbroite", + "STEELIXITE": "Steelixite", + "SWAMPERTITE": "Swampertite", + "TYRANITARITE": "Tyranitarite", + "VENUSAURITE": "Venusaurite", + + "BLUE_ORB": "Gemma Blu", + "RED_ORB": "Gemma Rossa", + "SHARP_METEORITE": "Meteorite Tagliente", + "HARD_METEORITE": "Meteorite Dura", + "SMOOTH_METEORITE": "Meteorite Liscia", + "ADAMANT_CRYSTAL": "Adamasferoide", + "LUSTROUS_ORB": "Splendisfera", + "GRISEOUS_CORE": "Grigiosferoide", + "REVEAL_GLASS": "Verispecchio", + "GRACIDEA": "Gracidea", + "MAX_MUSHROOMS": "Fungomax", + "DARK_STONE": "Scurolite", + "LIGHT_STONE": "Chiarolite", + "PRISON_BOTTLE": "Vaso del Vincolo", + "N_LUNARIZER": "Necrolunix", + "N_SOLARIZER": "Necrosolix", + "RUSTED_SWORD": "Spada Rovinata", + "RUSTED_SHIELD": "Scudo Rovinato", + "ICY_REINS_OF_UNITY": "Briglie Legame Giaccio", + "SHADOW_REINS_OF_UNITY": "Briglie legame Ombra", + "WELLSPRING_MASK": "Maschera Pozzo", + "HEARTHFLAME_MASK": "Maschera Focolare", + "CORNERSTONE_MASK": "Maschera Fondamenta", + "SHOCK_DRIVE": "Voltmodulo", + "BURN_DRIVE": "Piromodulo", + "CHILL_DRIVE": "Gelomodulo", + "DOUSE_DRIVE": "Idromodulo", + }, + TeraType: { + "UNKNOWN": "Sconosciuto", + "NORMAL": "Normale", + "FIGHTING": "Lotta", + "FLYING": "Volante", + "POISON": "Veleno", + "GROUND": "Terra", + "ROCK": "Roccia", + "BUG": "Coleottero", + "GHOST": "Spettro", + "STEEL": "Acciaio", + "FIRE": "Fuoco", + "WATER": "Acqua", + "GRASS": "Erba", + "ELECTRIC": "Elettro", + "PSYCHIC": "Psico", + "ICE": "Ghiaccio", + "DRAGON": "Drago", + "DARK": "Buio", + "FAIRY": "Folletto", + "STELLAR": "Astrale", + }, +} as const; \ No newline at end of file diff --git a/src/locales/it/splash-messages.ts b/src/locales/it/splash-messages.ts new file mode 100644 index 00000000000..3bddc68f0b5 --- /dev/null +++ b/src/locales/it/splash-messages.ts @@ -0,0 +1,37 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const splashMessages: SimpleTranslationEntries = { + "battlesWon": "Battaglie Vinte!", + "joinTheDiscord": "Entra nel Discord!", + "infiniteLevels": "Livelli Infiniti!", + "everythingStacks": "Tutto si impila!", + "optionalSaveScumming": "Salvataggio Facoltativo!", + "biomes": "35 Biomi!", + "openSource": "Open Source!", + "playWithSpeed": "Gioca con il 5x di Velocità!", + "liveBugTesting": "Test dei Bug in Tempo Reale!", + "heavyInfluence": "Influenzato da RoR2!", + "pokemonRiskAndPokemonRain": "Pokémon Risk e Pokémon Rain!", + "nowWithMoreSalt": "Adesso con il 33% di sale in più!", + "infiniteFusionAtHome": "Fusioni Infinite a Casa!", + "brokenEggMoves": "Mosse delle Uova Rotte!", + "magnificent": "Magnifico!", + "mubstitute": "Mubstitute!", + "thatsCrazy": "È Pazzesco!", + "oranceJuice": "Succo d\'Arancia!", + "questionableBalancing": "Bilanciamento Discutibile!", + "coolShaders": "Shader fantastici!", + "aiFree": "Senza Intelligenza Artificiale!", + "suddenDifficultySpikes": "Picchi di Difficoltà Improvvisi!", + "basedOnAnUnfinishedFlashGame": "Basato su un Gioco Flash Incompiuto!", + "moreAddictiveThanIntended": "Crea Dipendeza più del Dovuto!", + "mostlyConsistentSeeds": "Seeds Consistenti!", + "achievementPointsDontDoAnything": "I Punti Obiettivo non Fanno Nulla!", + "youDoNotStartAtLevel": "Non Cominci dal Livello 2000!", + "dontTalkAboutTheManaphyEggIncident": "Non Parlare dell'Incidente dell'Uovo di Manaphy!", + "alsoTryPokengine": "Prova anche Pokéngine!", + "alsoTryEmeraldRogue": "Prova anche Emerald Rogue!", + "alsoTryRadicalRed": "Prova anche Radical Red!", + "eeveeExpo": "Eevee Expo!", + "ynoproject": "YNOproject!", +} as const; \ No newline at end of file diff --git a/src/locales/it/starter-select-ui-handler.ts b/src/locales/it/starter-select-ui-handler.ts index 79c2e26c642..f2b44c37297 100644 --- a/src/locales/it/starter-select-ui-handler.ts +++ b/src/locales/it/starter-select-ui-handler.ts @@ -7,6 +7,15 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; */ export const starterSelectUiHandler: SimpleTranslationEntries = { "confirmStartTeam":'Vuoi iniziare con questi Pokémon?', + "gen1": "I", + "gen2": "II", + "gen3": "III", + "gen4": "IV", + "gen5": "V", + "gen6": "VI", + "gen7": "VII", + "gen8": "VIII", + "gen9": "IX", "growthRate": "Vel. Crescita:", "ability": "Abilità:", "passive": "Passiva:", @@ -29,7 +38,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleVariant": 'V: Alterna Variante', "enablePassive": "Attiva Passiva", "disablePassive": "Disattiva Passiva", - "locked": "Locked", - "disabled": "Disabled", - "uncaught": "Uncaught" + "locked": "Bloccato", + "disabled": "Disabilitato", + "uncaught": "Non Catturato" } \ No newline at end of file diff --git a/src/locales/it/trainers.ts b/src/locales/it/trainers.ts new file mode 100644 index 00000000000..443718693ca --- /dev/null +++ b/src/locales/it/trainers.ts @@ -0,0 +1,244 @@ +import {SimpleTranslationEntries} from "#app/plugins/i18n"; + +// Titles of special trainers like gym leaders, elite four, and the champion +export const titles: SimpleTranslationEntries = { + "elite_four": "Elite Four", + "gym_leader": "Gym Leader", + "gym_leader_female": "Gym Leader", + "champion": "Champion", + "rival": "Rival", + "professor": "Professor", + "frontier_brain": "Frontier Brain", + // Maybe if we add the evil teams we can add "Team Rocket" and "Team Aqua" etc. here as well as "Team Rocket Boss" and "Team Aqua Admin" etc. +} as const; + +// Titles of trainers like "Youngster" or "Lass" +export const trainerClasses: SimpleTranslationEntries = { + "ace_trainer": "Ace Trainer", + "ace_trainer_female": "Ace Trainer", + "ace_duo": "Ace Duo", + "artist": "Artist", + "artist_female": "Artist", + "backers": "Backers", + "backpacker": "Backpacker", + "backpacker_female": "Backpacker", + "backpackers": "Backpackers", + "baker": "Baker", + "battle_girl": "Battle Girl", + "beauty": "Beauty", + "beginners": "Beginners", + "biker": "Biker", + "black_belt": "Black Belt", + "breeder": "Breeder", + "breeder_female": "Breeder", + "breeders": "Breeders", + "clerk": "Clerk", + "clerk_female": "Clerk", + "colleagues": "Colleagues", + "crush_kin": "Crush Kin", + "cyclist": "Cyclist", + "cyclist_female": "Cyclist", + "cyclists": "Cyclists", + "dancer": "Dancer", + "dancer_female": "Dancer", + "depot_agent": "Depot Agent", + "doctor": "Doctor", + "doctor_female": "Doctor", + "fisherman": "Fisherman", + "fisherman_female": "Fisherman", + "gentleman": "Gentleman", + "guitarist": "Guitarist", + "guitarist_female": "Guitarist", + "harlequin": "Harlequin", + "hiker": "Hiker", + "hooligans": "Hooligans", + "hoopster": "Hoopster", + "infielder": "Infielder", + "janitor": "Janitor", + "lady": "Lady", + "lass": "Lass", + "linebacker": "Linebacker", + "maid": "Maid", + "madame": "Madame", + "medical_team": "Medical Team", + "musician": "Musician", + "hex_maniac": "Hex Maniac", + "nurse": "Nurse", + "nursery_aide": "Nursery Aide", + "officer": "Officer", + "parasol_lady": "Parasol Lady", + "pilot": "Pilot", + "pokefan": "Poké Fan", + "pokefan_family": "Poké Fan Family", + "preschooler": "Preschooler", + "preschooler_female": "Preschooler", + "preschoolers": "Preschoolers", + "psychic": "Psychic", + "psychic_female": "Psychic", + "psychics": "Psychics", + "pokémon_ranger": "Pokémon Ranger", + "pokémon_rangers": "Pokémon Ranger", + "ranger": "Ranger", + "restaurant_staff": "Restaurant Staff", + "rich": "Rich", + "rich_female": "Rich", + "rich_boy": "Rich Boy", + "rich_couple": "Rich Couple", + "rich_kid": "Rich Kid", + "rich_kid_female": "Rich Kid", + "rich_kids": "Rich Kids", + "roughneck": "Roughneck", + "scientist": "Scientist", + "scientist_female": "Scientist", + "scientists": "Scientists", + "smasher": "Smasher", + "snow_worker": "Snow Worker", + "snow_worker_female": "Snow Worker", + "striker": "Striker", + "school_kid": "School Kid", + "school_kid_female": "School Kid", + "school_kids": "School Kids", + "swimmer": "Swimmer", + "swimmer_female": "Swimmer", + "swimmers": "Swimmers", + "twins": "Twins", + "veteran": "Veteran", + "veteran_female": "Veteran", + "veteran_duo": "Veteran Duo", + "waiter": "Waiter", + "waitress": "Waitress", + "worker": "Worker", + "worker_female": "Worker", + "workers": "Workers", + "youngster": "Youngster" +} as const; + +// Names of special trainers like gym leaders, elite four, and the champion +export const trainerNames: SimpleTranslationEntries = { + "brock": "Brock", + "misty": "Misty", + "lt_surge": "Lt Surge", + "erika": "Erika", + "janine": "Janine", + "sabrina": "Sabrina", + "blaine": "Blaine", + "giovanni": "Giovanni", + "falkner": "Falkner", + "bugsy": "Bugsy", + "whitney": "Whitney", + "morty": "Morty", + "chuck": "Chuck", + "jasmine": "Jasmine", + "pryce": "Pryce", + "clair": "Clair", + "roxanne": "Roxanne", + "brawly": "Brawly", + "wattson": "Wattson", + "flannery": "Flannery", + "norman": "Norman", + "winona": "Winona", + "tate": "Tate", + "liza": "Liza", + "juan": "Juan", + "roark": "Roark", + "gardenia": "Gardenia", + "maylene": "Maylene", + "crasher_wake": "Crasher Wake", + "fantina": "Fantina", + "byron": "Byron", + "candice": "Candice", + "volkner": "Volkner", + "cilan": "Cilan", + "chili": "Chili", + "cress": "Cress", + "cheren": "Cheren", + "lenora": "Lenora", + "roxie": "Roxie", + "burgh": "Burgh", + "elesa": "Elesa", + "clay": "Clay", + "skyla": "Skyla", + "brycen": "Brycen", + "drayden": "Drayden", + "marlon": "Marlon", + "viola": "Viola", + "grant": "Grant", + "korrina": "Korrina", + "ramos": "Ramos", + "clemont": "Clemont", + "valerie": "Valerie", + "olympia": "Olympia", + "wulfric": "Wulfric", + "milo": "Milo", + "nessa": "Nessa", + "kabu": "Kabu", + "bea": "Bea", + "allister": "Allister", + "opal": "Opal", + "bede": "Bede", + "gordie": "Gordie", + "melony": "Melony", + "piers": "Piers", + "marnie": "Marnie", + "raihan": "Raihan", + "katy": "Katy", + "brassius": "Brassius", + "iono": "Iono", + "kofu": "Kofu", + "larry": "Larry", + "ryme": "Ryme", + "tulip": "Tulip", + "grusha": "Grusha", + "lorelei": "Lorelei", + "bruno": "Bruno", + "agatha": "Agatha", + "lance": "Lance", + "will": "Will", + "koga": "Koga", + "karen": "Karen", + "sidney": "Sidney", + "phoebe": "Phoebe", + "glacia": "Glacia", + "drake": "Drake", + "aaron": "Aaron", + "bertha": "Bertha", + "flint": "Flint", + "lucian": "Lucian", + "shauntal": "Shauntal", + "marshal": "Marshal", + "grimsley": "Grimsley", + "caitlin": "Caitlin", + "malva": "Malva", + "siebold": "Siebold", + "wikstrom": "Wikstrom", + "drasna": "Drasna", + "hala": "Hala", + "molayne": "Molayne", + "olivia": "Olivia", + "acerola": "Acerola", + "kahili": "Kahili", + "rika": "Rika", + "poppy": "Poppy", + "larry_elite": "Larry", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "hassel": "Hassel", + "crispin": "Crispin", + "amarys": "Amarys", + "lacey": "Lacey", + "drayton": "Drayton", + "blue": "Blue", + "red": "Red", + "lance_champion": "Lance", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "steven": "Steven", + "wallace": "Wallace", + "cynthia": "Cynthia", + "alder": "Alder", + "iris": "Iris", + "diantha": "Diantha", + "hau": "Hau", + "geeta": "Geeta", + "nemona": "Nemona", + "kieran": "Kieran", + "leon": "Leon", + "rival": "Finn", + "rival_female": "Ivy", +} as const; diff --git a/src/locales/it/weather.ts b/src/locales/it/weather.ts new file mode 100644 index 00000000000..d5f0f440e1e --- /dev/null +++ b/src/locales/it/weather.ts @@ -0,0 +1,44 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +/** + * The weather namespace holds text displayed when weather is active during a battle + */ +export const weather: SimpleTranslationEntries = { + "sunnyStartMessage": "La luce solare è intensa!", + "sunnyLapseMessage": "La luce solare è forte.", + "sunnyClearMessage": "La luce solare si sta attenuando.", + + "rainStartMessage": "Ha iniziato a piovere!", + "rainLapseMessage": "La pioggia continua.", + "rainClearMessage": "Ha smesso di piovere.", + + "sandstormStartMessage": "Si è scatenata una tempesta di sabbia!", + "sandstormLapseMessage": "La tempesta di sabbia infuria.", + "sandstormClearMessage": "La tempesta di sabbia si è placata.", + "sandstormDamageMessage": "{{pokemonPrefix}}{{pokemonName}} è stato colpito\ndalla tempesta di sabbia!", + + "hailStartMessage": "Ha iniziato a grandinare!", + "hailLapseMessage": "La grandine continua a cadere.", + "hailClearMessage": "Ha smesso di grandinare.", + "hailDamageMessage": "{{pokemonPrefix}}{{pokemonName}} è stato colpito\ndalla grandine!", + + "snowStartMessage": "Ha iniziato a nevicare!", + "snowLapseMessage": "La neve sta continuando a cadere.", + "snowClearMessage": "Ha smesso di nevicare!.", + + "fogStartMessage": "È emersa una fitta nebbia!", + "fogLapseMessage": "La nebbia continua.", + "fogClearMessage": "La nebbia è scomparsa.", + + "heavyRainStartMessage": "Ha iniziato a piovere forte!", + "heavyRainLapseMessage": "La pioggia battente continua.", + "heavyRainClearMessage": "La pioggia battente è cessata.", + + "harshSunStartMessage": "La luce solare è molto intensa!", + "harshSunLapseMessage": "La luce solare è estremamente calda.", + "harshSunClearMessage": "La luce solare si sta attenuando.", + + "strongWindsStartMessage": "È apparsa una corrente d'aria misteriosa!", + "strongWindsLapseMessage": "La corrente d'aria soffia intensamente.", + "strongWindsClearMessage": "La corrente d'aria è cessata." +} \ No newline at end of file diff --git a/src/locales/pt_BR/battle-message-ui-handler.ts b/src/locales/pt_BR/battle-message-ui-handler.ts new file mode 100644 index 00000000000..346f856872c --- /dev/null +++ b/src/locales/pt_BR/battle-message-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battleMessageUiHandler: SimpleTranslationEntries = { + "ivBest": "Best", + "ivFantastic": "Fantastic", + "ivVeryGood": "Very Good", + "ivPrettyGood": "Pretty Good", + "ivDecent": "Decent", + "ivNoGood": "No Good", +} as const; \ No newline at end of file diff --git a/src/locales/pt_BR/battle.ts b/src/locales/pt_BR/battle.ts index ed579845cd7..8d8ce72ef67 100644 --- a/src/locales/pt_BR/battle.ts +++ b/src/locales/pt_BR/battle.ts @@ -3,6 +3,7 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}} apareceu.", "trainerAppeared": "{{trainerName}}\nquer batalhar!", + "trainerAppearedDouble": "{{trainerName}}\nwould like to battle!", "singleWildAppeared": "Um {{pokemonName}} selvagem apareceu!", "multiWildAppeared": "Um {{pokemonName1}} e um {{pokemonName2}} selvagens\napareceram!", "playerComeBack": "{{pokemonName}}, retorne!", @@ -31,6 +32,8 @@ export const battle: SimpleTranslationEntries = { "learnMoveNotLearned": "{{pokemonName}} não aprendeu {{moveName}}.", "learnMoveForgetQuestion": "Qual movimento quer esquecer?", "learnMoveForgetSuccess": "{{pokemonName}} esqueceu como usar {{moveName}}.", + "countdownPoof": "@d{32}1, @d{15}2, @d{15}e@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}Puf!", + "learnMoveAnd": "E…", "levelCapUp": "O nível máximo aumentou\npara {{levelCap}}!", "moveNotImplemented": "{{moveName}} ainda não foi implementado e não pode ser usado.", "moveNoPP": "Não há mais PP\npara esse movimento!", diff --git a/src/locales/pt_BR/berry.ts b/src/locales/pt_BR/berry.ts new file mode 100644 index 00000000000..8c8bc5ee280 --- /dev/null +++ b/src/locales/pt_BR/berry.ts @@ -0,0 +1,48 @@ +import { BerryTranslationEntries } from "#app/plugins/i18n"; + +export const berry: BerryTranslationEntries = { + "SITRUS": { + name: "Sitrus Berry", + effect: "Restores 25% HP if HP is below 50%", + }, + "LUM": { + name: "Lum Berry", + effect: "Cures any non-volatile status condition and confusion", + }, + "ENIGMA": { + name: "Enigma Berry", + effect: "Restores 25% HP if hit by a super effective move", + }, + "LIECHI": { + name: "Liechi Berry", + effect: "Raises Attack if HP is below 25%", + }, + "GANLON": { + name: "Ganlon Berry", + effect: "Raises Defense if HP is below 25%", + }, + "PETAYA": { + name: "Petaya Berry", + effect: "Raises Sp. Atk if HP is below 25%", + }, + "APICOT": { + name: "Apicot Berry", + effect: "Raises Sp. Def if HP is below 25%", + }, + "SALAC": { + name: "Salac Berry", + effect: "Raises Speed if HP is below 25%", + }, + "LANSAT": { + name: "Lansat Berry", + effect: "Raises critical hit ratio if HP is below 25%", + }, + "STARF": { + name: "Starf Berry", + effect: "Sharply raises a random stat if HP is below 25%", + }, + "LEPPA": { + name: "Leppa Berry", + effect: "Restores 10 PP to a move if its PP reaches 0", + }, +} as const; \ No newline at end of file diff --git a/src/locales/pt_BR/config.ts b/src/locales/pt_BR/config.ts index fc58d45ce87..157df19a80b 100644 --- a/src/locales/pt_BR/config.ts +++ b/src/locales/pt_BR/config.ts @@ -5,6 +5,7 @@ import { fightUiHandler } from "./fight-ui-handler"; import { growth } from "./growth"; import { menu } from "./menu"; import { menuUiHandler } from "./menu-ui-handler"; +import { modifierType } from "./modifier-type"; import { move } from "./move"; import { nature } from "./nature"; import { pokeball } from "./pokeball"; @@ -12,6 +13,8 @@ import { pokemon } from "./pokemon"; import { pokemonStat } from "./pokemon-stat"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; import { tutorial } from "./tutorial"; +import { weather } from "./weather"; +import { berry } from "./berry"; export const ptBrConfig = { @@ -28,5 +31,8 @@ export const ptBrConfig = { starterSelectUiHandler: starterSelectUiHandler, tutorial: tutorial, nature: nature, - growth: growth + growth: growth, + weather: weather, + modifierType: modifierType, + berry: berry, } \ No newline at end of file diff --git a/src/locales/pt_BR/menu-ui-handler.ts b/src/locales/pt_BR/menu-ui-handler.ts index 2e4d798cf65..5a60b614338 100644 --- a/src/locales/pt_BR/menu-ui-handler.ts +++ b/src/locales/pt_BR/menu-ui-handler.ts @@ -1,23 +1,23 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const menuUiHandler: SimpleTranslationEntries = { - "GAME_SETTINGS": 'Configurações', + "GAME_SETTINGS": "Configurações", "ACHIEVEMENTS": "Conquistas", "STATS": "Estatísticas", "VOUCHERS": "Vouchers", "EGG_LIST": "Incubadora", - "EGG_GACHA": "Gacha de Ovos", - "MANAGE_DATA": "Gerenciar Dados", + "EGG_GACHA": "Gacha de ovos", + "MANAGE_DATA": "Gerenciar dados", "COMMUNITY": "Comunidade", - "RETURN_TO_TITLE": "Voltar ao Início", + "SAVE_AND_QUIT": "Salvar e sair", "LOG_OUT": "Logout", "slot": "Slot {{slotNumber}}", - "importSession": "Importar Sessão", + "importSession": "Importar sessão", "importSlotSelect": "Selecione um slot para importar.", - "exportSession": "Exportar Sessão", + "exportSession": "Exportar sessão", "exportSlotSelect": "Selecione um slot para exportar.", - "importData": "Importar Dados", - "exportData": "Exportar Dados", + "importData": "Importar dados", + "exportData": "Exportar dados", "cancel": "Cancelar", "losingProgressionWarning": "Você vai perder todo o progresso desde o início da batalha. Confirmar?" } as const; \ No newline at end of file diff --git a/src/locales/pt_BR/menu.ts b/src/locales/pt_BR/menu.ts index 474ac867efc..10f3fa4dff8 100644 --- a/src/locales/pt_BR/menu.ts +++ b/src/locales/pt_BR/menu.ts @@ -8,7 +8,7 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const menu: SimpleTranslationEntries = { "cancel": "Cancelar", "continue": "Continuar", - "dailyRun": "Desafio diário (Beta)", + "dailyRun": "Desafio Diário (Beta)", "loadGame": "Carregar Jogo", "newGame": "Novo Jogo", "selectGameMode": "Escolha um modo de jogo.", @@ -35,6 +35,11 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "Você é um menino ou uma menina?", "boy": "Menino", "girl": "Menina", + "evolving": "Que?\n{{pokemonName}} tá evoluindo!", + "stoppedEvolving": "{{pokemonName}} parou de evoluir.", + "pauseEvolutionsQuestion": "Gostaria de pausar evoluções para {{pokemonName}}?\nEvoluções podem ser religadas na tela de equipe.", + "evolutionsPaused": "Evoluções foram paradas para {{pokemonName}}.", + "evolutionDone": "Parabéns!\nSeu {{pokemonName}} evolui para {{evolvedPokemonName}}!", "dailyRankings": "Classificação Diária", "weeklyRankings": "Classificação Semanal", "noRankings": "Sem Classificação", diff --git a/src/locales/pt_BR/modifier-type.ts b/src/locales/pt_BR/modifier-type.ts new file mode 100644 index 00000000000..043d7a705d5 --- /dev/null +++ b/src/locales/pt_BR/modifier-type.ts @@ -0,0 +1,409 @@ +import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; + +export const modifierType: ModifierTypeTranslationEntries = { + ModifierType: { + "AddPokeballModifierType": { + name: "{{modifierCount}}x {{pokeballName}}", + description: "Receive {{pokeballName}} x{{modifierCount}} (Inventory: {{pokeballAmount}}) \nCatch Rate: {{catchRate}}", + }, + "AddVoucherModifierType": { + name: "{{modifierCount}}x {{voucherTypeName}}", + description: "Receive {{voucherTypeName}} x{{modifierCount}}", + }, + "PokemonHeldItemModifierType": { + extra: { + "inoperable": "{{pokemonName}} can't take\nthis item!", + "tooMany": "{{pokemonName}} has too many\nof this item!", + } + }, + "PokemonHpRestoreModifierType": { + description: "Restores {{restorePoints}} HP or {{restorePercent}}% HP for one Pokémon, whichever is higher", + extra: { + "fully": "Fully restores HP for one Pokémon", + "fullyWithStatus": "Fully restores HP for one Pokémon and heals any status ailment", + } + }, + "PokemonReviveModifierType": { + description: "Revives one Pokémon and restores {{restorePercent}}% HP", + }, + "PokemonStatusHealModifierType": { + description: "Heals any status ailment for one Pokémon", + }, + "PokemonPpRestoreModifierType": { + description: "Restores {{restorePoints}} PP for one Pokémon move", + extra: { + "fully": "Restores all PP for one Pokémon move", + } + }, + "PokemonAllMovePpRestoreModifierType": { + description: "Restores {{restorePoints}} PP for all of one Pokémon's moves", + extra: { + "fully": "Restores all PP for all of one Pokémon's moves", + } + }, + "PokemonPpUpModifierType": { + description: "Permanently increases PP for one Pokémon move by {{upPoints}} for every 5 maximum PP (maximum 3)", + }, + "PokemonNatureChangeModifierType": { + name: "{{natureName}} Mint", + description: "Changes a Pokémon's nature to {{natureName}} and permanently unlocks the nature for the starter.", + }, + "DoubleBattleChanceBoosterModifierType": { + description: "Doubles the chance of an encounter being a double battle for {{battleCount}} battles", + }, + "TempBattleStatBoosterModifierType": { + description: "Increases the {{tempBattleStatName}} of all party members by 1 stage for 5 battles", + }, + "AttackTypeBoosterModifierType": { + description: "Increases the power of a Pokémon's {{moveType}}-type moves by 20%", + }, + "PokemonLevelIncrementModifierType": { + description: "Increases a Pokémon's level by 1", + }, + "AllPokemonLevelIncrementModifierType": { + description: "Increases all party members' level by 1", + }, + "PokemonBaseStatBoosterModifierType": { + description: "Increases the holder's base {{statName}} by 10%. The higher your IVs, the higher the stack limit.", + }, + "AllPokemonFullHpRestoreModifierType": { + description: "Restores 100% HP for all Pokémon", + }, + "AllPokemonFullReviveModifierType": { + description: "Revives all fainted Pokémon, fully restoring HP", + }, + "MoneyRewardModifierType": { + description: "Grants a {{moneyMultiplier}} amount of money (₽{{moneyAmount}})", + extra: { + "small": "small", + "moderate": "moderate", + "large": "large", + }, + }, + "ExpBoosterModifierType": { + description: "Increases gain of EXP. Points by {{boostPercent}}%", + }, + "PokemonExpBoosterModifierType": { + description: "Increases the holder's gain of EXP. Points by {{boostPercent}}%", + }, + "PokemonFriendshipBoosterModifierType": { + description: "Increases friendship gain per victory by 50%", + }, + "PokemonMoveAccuracyBoosterModifierType": { + description: "Increases move accuracy by {{accuracyAmount}} (maximum 100)", + }, + "PokemonMultiHitModifierType": { + description: "Attacks hit one additional time at the cost of a 60/75/82.5% power reduction per stack respectively", + }, + "TmModifierType": { + name: "TM{{moveId}} - {{moveName}}", + description: "Teach {{moveName}} to a Pokémon", + }, + "EvolutionItemModifierType": { + description: "Causes certain Pokémon to evolve", + }, + "FormChangeItemModifierType": { + description: "Causes certain Pokémon to change form", + }, + "FusePokemonModifierType": { + description: "Combines two Pokémon (transfers Ability, splits base stats and types, shares move pool)", + }, + "TerastallizeModifierType": { + name: "{{teraType}} Tera Shard", + description: "{{teraType}} Terastallizes the holder for up to 10 battles", + }, + "ContactHeldItemTransferChanceModifierType": { + description: "Upon attacking, there is a {{chancePercent}}% chance the foe's held item will be stolen", + }, + "TurnHeldItemTransferModifierType": { + description: "Every turn, the holder acquires one held item from the foe", + }, + "EnemyAttackStatusEffectChanceModifierType": { + description: "Adds a {{chancePercent}}% chance to inflict {{statusEffect}} with attack moves", + }, + "EnemyEndureChanceModifierType": { + description: "Adds a {{chancePercent}}% chance of enduring a hit", + }, + + "RARE_CANDY": { name: "Rare Candy" }, + "RARER_CANDY": { name: "Rarer Candy" }, + + "MEGA_BRACELET": { name: "Mega Bracelet", description: "Mega Stones become available" }, + "DYNAMAX_BAND": { name: "Dynamax Band", description: "Max Mushrooms become available" }, + "TERA_ORB": { name: "Tera Orb", description: "Tera Shards become available" }, + + "MAP": { name: "Map", description: "Allows you to choose your destination at a crossroads" }, + + "POTION": { name: "Potion" }, + "SUPER_POTION": { name: "Super Potion" }, + "HYPER_POTION": { name: "Hyper Potion" }, + "MAX_POTION": { name: "Max Potion" }, + "FULL_RESTORE": { name: "Full Restore" }, + + "REVIVE": { name: "Revive" }, + "MAX_REVIVE": { name: "Max Revive" }, + + "FULL_HEAL": { name: "Full Heal" }, + + "SACRED_ASH": { name: "Sacred Ash" }, + + "REVIVER_SEED": { name: "Reviver Seed", description: "Revives the holder for 1/2 HP upon fainting" }, + + "ETHER": { name: "Ether" }, + "MAX_ETHER": { name: "Max Ether" }, + + "ELIXIR": { name: "Elixir" }, + "MAX_ELIXIR": { name: "Max Elixir" }, + + "PP_UP": { name: "PP Up" }, + "PP_MAX": { name: "PP Max" }, + + "LURE": { name: "Lure" }, + "SUPER_LURE": { name: "Super Lure" }, + "MAX_LURE": { name: "Max Lure" }, + + "MEMORY_MUSHROOM": { name: "Memory Mushroom", description: "Recall one Pokémon's forgotten move" }, + + "EXP_SHARE": { name: "EXP. All", description: "Non-participants receive 20% of a single participant's EXP. Points" }, + "EXP_BALANCE": { name: "EXP. Balance", description: "Weighs EXP. Points received from battles towards lower-leveled party members" }, + + "OVAL_CHARM": { name: "Oval Charm", description: "When multiple Pokémon participate in a battle, each gets an extra 10% of the total EXP" }, + + "EXP_CHARM": { name: "EXP. Charm" }, + "SUPER_EXP_CHARM": { name: "Super EXP. Charm" }, + "GOLDEN_EXP_CHARM": { name: "Golden EXP. Charm" }, + + "LUCKY_EGG": { name: "Lucky Egg" }, + "GOLDEN_EGG": { name: "Golden Egg" }, + + "SOOTHE_BELL": { name: "Soothe Bell" }, + + "SOUL_DEW": { name: "Soul Dew", description: "Increases the influence of a Pokémon's nature on its stats by 10% (additive)" }, + + "NUGGET": { name: "Nugget" }, + "BIG_NUGGET": { name: "Big Nugget" }, + "RELIC_GOLD": { name: "Relic Gold" }, + + "AMULET_COIN": { name: "Amulet Coin", description: "Increases money rewards by 20%" }, + "GOLDEN_PUNCH": { name: "Golden Punch", description: "Grants 50% of damage inflicted as money" }, + "COIN_CASE": { name: "Coin Case", description: "After every 10th battle, receive 10% of your money in interest" }, + + "LOCK_CAPSULE": { name: "Lock Capsule", description: "Allows you to lock item rarities when rerolling items" }, + + "GRIP_CLAW": { name: "Grip Claw" }, + "WIDE_LENS": { name: "Wide Lens" }, + + "MULTI_LENS": { name: "Multi Lens" }, + + "HEALING_CHARM": { name: "Healing Charm", description: "Increases the effectiveness of HP restoring moves and items by 10% (excludes Revives)" }, + "CANDY_JAR": { name: "Candy Jar", description: "Increases the number of levels added by Rare Candy items by 1" }, + + "BERRY_POUCH": { name: "Berry Pouch", description: "Adds a 25% chance that a used berry will not be consumed" }, + + "FOCUS_BAND": { name: "Focus Band", description: "Adds a 10% chance to survive with 1 HP after being damaged enough to faint" }, + + "QUICK_CLAW": { name: "Quick Claw", description: "Adds a 10% chance to move first regardless of speed (after priority)" }, + + "KINGS_ROCK": { name: "King's Rock", description: "Adds a 10% chance an attack move will cause the opponent to flinch" }, + + "LEFTOVERS": { name: "Leftovers", description: "Heals 1/16 of a Pokémon's maximum HP every turn" }, + "SHELL_BELL": { name: "Shell Bell", description: "Heals 1/8 of a Pokémon's dealt damage" }, + + "BATON": { name: "Baton", description: "Allows passing along effects when switching Pokémon, which also bypasses traps" }, + + "SHINY_CHARM": { name: "Shiny Charm", description: "Dramatically increases the chance of a wild Pokémon being Shiny" }, + "ABILITY_CHARM": { name: "Ability Charm", description: "Dramatically increases the chance of a wild Pokémon having a Hidden Ability" }, + + "IV_SCANNER": { name: "IV Scanner", description: "Allows scanning the IVs of wild Pokémon. 2 IVs are revealed per stack. The best IVs are shown first" }, + + "DNA_SPLICERS": { name: "DNA Splicers" }, + + "MINI_BLACK_HOLE": { name: "Mini Black Hole" }, + + "GOLDEN_POKEBALL": { name: "Golden Poké Ball", description: "Adds 1 extra item option at the end of every battle" }, + + "ENEMY_DAMAGE_BOOSTER": { name: "Damage Token", description: "Increases damage by 5%" }, + "ENEMY_DAMAGE_REDUCTION": { name: "Protection Token", description: "Reduces incoming damage by 2.5%" }, + "ENEMY_HEAL": { name: "Recovery Token", description: "Heals 2% of max HP every turn" }, + "ENEMY_ATTACK_POISON_CHANCE": { name: "Poison Token" }, + "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Paralyze Token" }, + "ENEMY_ATTACK_SLEEP_CHANCE": { name: "Sleep Token" }, + "ENEMY_ATTACK_FREEZE_CHANCE": { name: "Freeze Token" }, + "ENEMY_ATTACK_BURN_CHANCE": { name: "Burn Token" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Adds a 10% chance every turn to heal a status condition" }, + "ENEMY_ENDURE_CHANCE": { name: "Endure Token" }, + "ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Adds a 1% chance that a wild Pokémon will be a fusion" }, + }, + TempBattleStatBoosterItem: { + "x_attack": "X Attack", + "x_defense": "X Defense", + "x_sp_atk": "X Sp. Atk", + "x_sp_def": "X Sp. Def", + "x_speed": "X Speed", + "x_accuracy": "X Accuracy", + "dire_hit": "Dire Hit", + }, + AttackTypeBoosterItem: { + "silk_scarf": "Silk Scarf", + "black_belt": "Black Belt", + "sharp_beak": "Sharp Beak", + "poison_barb": "Poison Barb", + "soft_sand": "Soft Sand", + "hard_stone": "Hard Stone", + "silver_powder": "Silver Powder", + "spell_tag": "Spell Tag", + "metal_coat": "Metal Coat", + "charcoal": "Charcoal", + "mystic_water": "Mystic Water", + "miracle_seed": "Miracle Seed", + "magnet": "Magnet", + "twisted_spoon": "Twisted Spoon", + "never_melt_ice": "Never-Melt Ice", + "dragon_fang": "Dragon Fang", + "black_glasses": "Black Glasses", + "fairy_feather": "Fairy Feather", + }, + BaseStatBoosterItem: { + "hp_up": "HP Up", + "protein": "Protein", + "iron": "Iron", + "calcium": "Calcium", + "zinc": "Zinc", + "carbos": "Carbos", + }, + EvolutionItem: { + "NONE": "None", + + "LINKING_CORD": "Linking Cord", + "SUN_STONE": "Sun Stone", + "MOON_STONE": "Moon Stone", + "LEAF_STONE": "Leaf Stone", + "FIRE_STONE": "Fire Stone", + "WATER_STONE": "Water Stone", + "THUNDER_STONE": "Thunder Stone", + "ICE_STONE": "Ice Stone", + "DUSK_STONE": "Dusk Stone", + "DAWN_STONE": "Dawn Stone", + "SHINY_STONE": "Shiny Stone", + "CRACKED_POT": "Cracked Pot", + "SWEET_APPLE": "Sweet Apple", + "TART_APPLE": "Tart Apple", + "STRAWBERRY_SWEET": "Strawberry Sweet", + "UNREMARKABLE_TEACUP": "Unremarkable Teacup", + + "CHIPPED_POT": "Chipped Pot", + "BLACK_AUGURITE": "Black Augurite", + "GALARICA_CUFF": "Galarica Cuff", + "GALARICA_WREATH": "Galarica Wreath", + "PEAT_BLOCK": "Peat Block", + "AUSPICIOUS_ARMOR": "Auspicious Armor", + "MALICIOUS_ARMOR": "Malicious Armor", + "MASTERPIECE_TEACUP": "Masterpiece Teacup", + "METAL_ALLOY": "Metal Alloy", + "SCROLL_OF_DARKNESS": "Scroll Of Darkness", + "SCROLL_OF_WATERS": "Scroll Of Waters", + "SYRUPY_APPLE": "Syrupy Apple", + }, + FormChangeItem: { + "NONE": "None", + + "ABOMASITE": "Abomasite", + "ABSOLITE": "Absolite", + "AERODACTYLITE": "Aerodactylite", + "AGGRONITE": "Aggronite", + "ALAKAZITE": "Alakazite", + "ALTARIANITE": "Altarianite", + "AMPHAROSITE": "Ampharosite", + "AUDINITE": "Audinite", + "BANETTITE": "Banettite", + "BEEDRILLITE": "Beedrillite", + "BLASTOISINITE": "Blastoisinite", + "BLAZIKENITE": "Blazikenite", + "CAMERUPTITE": "Cameruptite", + "CHARIZARDITE_X": "Charizardite X", + "CHARIZARDITE_Y": "Charizardite Y", + "DIANCITE": "Diancite", + "GALLADITE": "Galladite", + "GARCHOMPITE": "Garchompite", + "GARDEVOIRITE": "Gardevoirite", + "GENGARITE": "Gengarite", + "GLALITITE": "Glalitite", + "GYARADOSITE": "Gyaradosite", + "HERACRONITE": "Heracronite", + "HOUNDOOMINITE": "Houndoominite", + "KANGASKHANITE": "Kangaskhanite", + "LATIASITE": "Latiasite", + "LATIOSITE": "Latiosite", + "LOPUNNITE": "Lopunnite", + "LUCARIONITE": "Lucarionite", + "MANECTITE": "Manectite", + "MAWILITE": "Mawilite", + "MEDICHAMITE": "Medichamite", + "METAGROSSITE": "Metagrossite", + "MEWTWONITE_X": "Mewtwonite X", + "MEWTWONITE_Y": "Mewtwonite Y", + "PIDGEOTITE": "Pidgeotite", + "PINSIRITE": "Pinsirite", + "RAYQUAZITE": "Rayquazite", + "SABLENITE": "Sablenite", + "SALAMENCITE": "Salamencite", + "SCEPTILITE": "Sceptilite", + "SCIZORITE": "Scizorite", + "SHARPEDONITE": "Sharpedonite", + "SLOWBRONITE": "Slowbronite", + "STEELIXITE": "Steelixite", + "SWAMPERTITE": "Swampertite", + "TYRANITARITE": "Tyranitarite", + "VENUSAURITE": "Venusaurite", + + "BLUE_ORB": "Blue Orb", + "RED_ORB": "Red Orb", + "SHARP_METEORITE": "Sharp Meteorite", + "HARD_METEORITE": "Hard Meteorite", + "SMOOTH_METEORITE": "Smooth Meteorite", + "ADAMANT_CRYSTAL": "Adamant Crystal", + "LUSTROUS_ORB": "Lustrous Orb", + "GRISEOUS_CORE": "Griseous Core", + "REVEAL_GLASS": "Reveal Glass", + "GRACIDEA": "Gracidea", + "MAX_MUSHROOMS": "Max Mushrooms", + "DARK_STONE": "Dark Stone", + "LIGHT_STONE": "Light Stone", + "PRISON_BOTTLE": "Prison Bottle", + "N_LUNARIZER": "N Lunarizer", + "N_SOLARIZER": "N Solarizer", + "RUSTED_SWORD": "Rusted Sword", + "RUSTED_SHIELD": "Rusted Shield", + "ICY_REINS_OF_UNITY": "Icy Reins Of Unity", + "SHADOW_REINS_OF_UNITY": "Shadow Reins Of Unity", + "WELLSPRING_MASK": "Wellspring Mask", + "HEARTHFLAME_MASK": "Hearthflame Mask", + "CORNERSTONE_MASK": "Cornerstone Mask", + "SHOCK_DRIVE": "Shock Drive", + "BURN_DRIVE": "Burn Drive", + "CHILL_DRIVE": "Chill Drive", + "DOUSE_DRIVE": "Douse Drive", + }, + TeraType: { + "UNKNOWN": "Unknown", + "NORMAL": "Normal", + "FIGHTING": "Fighting", + "FLYING": "Flying", + "POISON": "Poison", + "GROUND": "Ground", + "ROCK": "Rock", + "BUG": "Bug", + "GHOST": "Ghost", + "STEEL": "Steel", + "FIRE": "Fire", + "WATER": "Water", + "GRASS": "Grass", + "ELECTRIC": "Electric", + "PSYCHIC": "Psychic", + "ICE": "Ice", + "DRAGON": "Dragon", + "DARK": "Dark", + "FAIRY": "Fairy", + "STELLAR": "Stellar", + }, +} as const; \ No newline at end of file diff --git a/src/locales/pt_BR/nature.ts b/src/locales/pt_BR/nature.ts index b78168f13c8..3cb33340e2c 100644 --- a/src/locales/pt_BR/nature.ts +++ b/src/locales/pt_BR/nature.ts @@ -8,7 +8,7 @@ export const nature: SimpleTranslationEntries = { "Naughty": "Teimosa", "Bold": "Corajosa", "Docile": "Dócil", - "Relaxed": "Descontraída", + "Relaxed": "Relaxada", "Impish": "Inquieta", "Lax": "Relaxada", "Timid": "Tímida", @@ -20,7 +20,7 @@ export const nature: SimpleTranslationEntries = { "Mild": "Mansa", "Quiet": "Quieta", "Bashful": "Atrapalhada", - "Rash": "Imprudente", + "Rash": "Rabugenta", "Calm": "Calma", "Gentle": "Gentil", "Sassy": "Atrevida", diff --git a/src/locales/pt_BR/starter-select-ui-handler.ts b/src/locales/pt_BR/starter-select-ui-handler.ts index ba180c2cfb2..7d77f48f290 100644 --- a/src/locales/pt_BR/starter-select-ui-handler.ts +++ b/src/locales/pt_BR/starter-select-ui-handler.ts @@ -7,10 +7,19 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; */ export const starterSelectUiHandler: SimpleTranslationEntries = { "confirmStartTeam": 'Começar com esses Pokémon?', + "gen1": "I", + "gen2": "II", + "gen3": "III", + "gen4": "IV", + "gen5": "V", + "gen6": "VI", + "gen7": "VII", + "gen8": "VIII", + "gen9": "IX", "growthRate": "Crescimento:", - "ability": "Hab.:", + "ability": "Habilidade:", "passive": "Passiva:", - "nature": "Nature:", + "nature": "Natureza:", "eggMoves": "Mov. de Ovo", "start": "Iniciar", "addToParty": "Adicionar à equipe", @@ -25,11 +34,11 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleForm": 'F: Mudar Forma', "cycleGender": 'G: Mudar Gênero', "cycleAbility": 'E: Mudar Habilidade', - "cycleNature": 'N: Mudar Nature', + "cycleNature": 'N: Mudar Natureza', "cycleVariant": 'V: Mudar Variante', "enablePassive": "Ativar Passiva", "disablePassive": "Desativar Passiva", - "locked": "Bloqueado", - "disabled": "Desativado", + "locked": "Bloqueada", + "disabled": "Desativada", "uncaught": "Não capturado" -} \ No newline at end of file +} diff --git a/src/locales/pt_BR/trainers.ts b/src/locales/pt_BR/trainers.ts new file mode 100644 index 00000000000..af6393bce8e --- /dev/null +++ b/src/locales/pt_BR/trainers.ts @@ -0,0 +1,244 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +// Titles of special trainers like gym leaders, elite four, and the champion +export const titles: SimpleTranslationEntries = { + "elite_four": "Elite dos Quatro", + "gym_leader": "Líder de Ginásio", + "gym_leader_female": "Líder de Ginásio", + "champion": "Campeão", + "rival": "Rival", + "professor": "Professor", + "frontier_brain": "Cérebro da Fronteira", + // Maybe if we add the evil teams we can add "Team Rocket" and "Team Aqua" etc. here as well as "Team Rocket Boss" and "Team Aqua Admin" etc. +} as const; + +// Titles of trainers like "Youngster" or "Lass" +export const trainerClasses: SimpleTranslationEntries = { + "ace_trainer": "Trinador Ás", + "ace_trainer_female": "Trinadora Ás", + "ace_duo": "Ace Duo", + "artist": "Artista", + "artist_female": "Artista", + "backpackers": "Backpackers", + "backers": "Torcedores", + "backpacker": "Mochileiro", + "backpacker_female": "Mochileira", + "baker": "Padeira", + "battle_girl": "Lutadora", + "beauty": "Modelo", + "beginners": "Beginners", + "biker": "Motoqueiro", + "black_belt": "Faixa Preta", + "breeder": "Criador", + "breeder_female": "Criadora", + "breeders": "Breeders", + "clerk": "Funcionário", + "clerk_female": "Funcionária", + "colleagues": "Colleagues", + "crush_kin": "Crush Kin", + "cyclist": "Ciclista", + "cyclist_female": "Ciclista", + "cyclists": "Cyclists", + "dancer": "Dançarino", + "dancer_female": "Dançarina", + "depot_agent": "Ferroviário", + "doctor": "Doutor", + "doctor_female": "Doutora", + "fisherman": "Pescador", + "fisherman_female": "Pescadora", + "gentleman": "Gentleman", + "guitarist": "Guitarrista", + "guitarist_female": "Guitarrista", + "harlequin": "Arlequim", + "hiker": "Montanhista", + "hooligans": "Bandoleiro", + "hoopster": "Jogador de basquete", + "infielder": "Jogador de baseball", + "janitor": "Faxineiro", + "lady": "Dama", + "lass": "Senhorita", + "linebacker": "Zagueiro", + "maid": "Doméstica", + "madame": "Madame", + "medical_team": "Medical Team", + "musician": "Músico", + "hex_maniac": "Ocultista", + "nurse": "Enfermeira", + "nursery_aide": "Professora do Berçário", + "officer": "Policial", + "parasol_lady": "Moça de Sombrinha", + "pilot": "Piloto", + "pokefan": "Pokefã", + "pokefan_family": "Poké Fan Family", + "preschooler": "Menino do Prezinho", + "preschooler_female": "Menina do Prezinho", + "preschoolers": "Preschoolers", + "psychic": "Médium", + "psychic_female": "Médium", + "psychics": "Psychics", + "pokémon_ranger": "Pokémon Ranger", + "pokémon_rangers": "Pokémon Ranger", + "ranger": "Guarda", + "restaurant_staff": "Restaurant Staff", + "rich": "Rich", + "rich_female": "Rich", + "rich_boy": "Rich Boy", + "rich_couple": "Rich Couple", + "rich_kid": "Rich Kid", + "rich_kid_female": "Rich Kid", + "rich_kids": "Rich Kids", + "roughneck": "Arruaceiro", + "scientist": "Cientista", + "scientist_female": "Cientista", + "scientists": "Scientists", + "smasher": "Tenista", + "snow_worker": "Operário da Neve", + "snow_worker_female": "Operária da Neve", + "striker": "Atacante", + "school_kid": "Estudante", + "school_kid_female": "Estudante", + "school_kids": "School Kids", + "swimmer": "Nadador", + "swimmer_female": "Nadadora", + "swimmers": "Swimmers", + "twins": "Gêmeos", + "veteran": "Veterano", + "veteran_female": "Veterana", + "veteran_duo": "Veteran Duo", + "waiter": "Garçom", + "waitress": "Garçonete", + "worker": "Operário", + "worker_female": "Operária", + "workers": "Workers", + "youngster": "Jovem", +} as const; + +// Names of special trainers like gym leaders, elite four, and the champion +export const trainerNames: SimpleTranslationEntries = { + "brock": "Brock", + "misty": "Misty", + "lt_surge": "Ten. Surge", + "erika": "Erika", + "janine": "Janine", + "sabrina": "Sabrina", + "blaine": "Blaine", + "giovanni": "Giovanni", + "falkner": "Falkner", + "bugsy": "Bugsy", + "whitney": "Whitney", + "morty": "Morty", + "chuck": "Chuck", + "jasmine": "Jasmine", + "pryce": "Pryce", + "clair": "Clair", + "roxanne": "Roxanne", + "brawly": "Brawly", + "wattson": "Wattson", + "flannery": "Flannery", + "norman": "Norman", + "winona": "Winona", + "tate": "Tate", + "liza": "Liza", + "juan": "Juan", + "roark": "Roark", + "gardenia": "Gardenia", + "maylene": "Maylene", + "crasher_wake": "Demolidor Wake", + "fantina": "Fantina", + "byron": "Byron", + "candice": "Candice", + "volkner": "Volkner", + "cilan": "Cilan", + "chili": "Chili", + "cress": "Cress", + "cheren": "Cheren", + "lenora": "Lenora", + "roxie": "Roxie", + "burgh": "Burgh", + "elesa": "Elesa", + "clay": "Clay", + "skyla": "Skyla", + "brycen": "Brycen", + "drayden": "Drayden", + "marlon": "Marlon", + "viola": "Viola", + "grant": "Grant", + "korrina": "Korrina", + "ramos": "Ramos", + "clemont": "Clemont", + "valerie": "Valerie", + "olympia": "Olympia", + "wulfric": "Wulfric", + "milo": "Milo", + "nessa": "Nessa", + "kabu": "Kabu", + "bea": "Bea", + "allister": "Allister", + "opal": "Opal", + "bede": "Bede", + "gordie": "Gordie", + "melony": "Melony", + "piers": "Piers", + "marnie": "Marnie", + "raihan": "Raihan", + "katy": "Katy", + "brassius": "Brassius", + "iono": "Iono", + "kofu": "Kofu", + "larry": "Larry", + "ryme": "Ryme", + "tulip": "Tulip", + "grusha": "Grusha", + "lorelei": "Lorelei", + "bruno": "Bruno", + "agatha": "Agatha", + "lance": "Lance", + "will": "Will", + "koga": "Koga", + "karen": "Karen", + "sidney": "Sidney", + "phoebe": "Phoebe", + "glacia": "Glacia", + "drake": "Drake", + "aaron": "Aaron", + "bertha": "Bertha", + "flint": "Flint", + "lucian": "Lucian", + "shauntal": "Shauntal", + "marshal": "Marshal", + "grimsley": "Grimsley", + "caitlin": "Caitlin", + "malva": "Malva", + "siebold": "Siebold", + "wikstrom": "Wikstrom", + "drasna": "Drasna", + "hala": "Hala", + "molayne": "Molayne", + "olivia": "Olivia", + "acerola": "Acerola", + "kahili": "Kahili", + "rika": "Rika", + "poppy": "Poppy", + "larry_elite": "Larry", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "hassel": "Hassel", + "crispin": "Crispin", + "amarys": "Amarys", + "lacey": "Lacey", + "drayton": "Drayton", + "blue": "Blue", + "red": "Red", + "lance_champion": "Lance", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "steven": "Steven", + "wallace": "Wallace", + "cynthia": "Cynthia", + "alder": "Alder", + "iris": "Iris", + "diantha": "Diantha", + "hau": "Hau", + "geeta": "Geeta", + "nemona": "Nemona", + "kieran": "Kieran", + "leon": "Leon", + "rival": "Finn", + "rival_female": "Ivy", +} as const; \ No newline at end of file diff --git a/src/locales/pt_BR/weather.ts b/src/locales/pt_BR/weather.ts new file mode 100644 index 00000000000..de37cab7812 --- /dev/null +++ b/src/locales/pt_BR/weather.ts @@ -0,0 +1,44 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +/** + * The weather namespace holds text displayed when weather is active during a battle + */ +export const weather: SimpleTranslationEntries = { + "sunnyStartMessage": "A luz do sol ficou clara!", + "sunnyLapseMessage": "A luz do sol está forte.", + "sunnyClearMessage": "A luz do sol sumiu.", + + "rainStartMessage": "Começou a chover!", + "rainLapseMessage": "A chuva continua forte.", + "rainClearMessage": "A chuva parou.", + + "sandstormStartMessage": "Uma tempestade de areia se formou!", + "sandstormLapseMessage": "A tempestade de areia é violenta.", + "sandstormClearMessage": "A tempestade de areia diminuiu.", + "sandstormDamageMessage": "{{pokemonPrefix}}{{pokemonName}} é atingido\npela tempestade de areia!", + + "hailStartMessage": "Começou a chover granizo!", + "hailLapseMessage": "Granizo cai do céu.", + "hailClearMessage": "O granizo parou.", + "hailDamageMessage": "{{pokemonPrefix}}{{pokemonName}} é atingido\npelo granizo!", + + "snowStartMessage": "Começou a nevar!", + "snowLapseMessage": "A neve continua caindo.", + "snowClearMessage": "Parou de nevar.", + + "fogStartMessage": "Uma névoa densa se formou!", + "fogLapseMessage": "A névoa continua forte.", + "fogClearMessage": "A névoa sumiu.", + + "heavyRainStartMessage": "Um temporal começou!", + "heavyRainLapseMessage": "O temporal continua forte.", + "heavyRainClearMessage": "O temporal parou.", + + "harshSunStartMessage": "A luz do sol está escaldante!", + "harshSunLapseMessage": "A luz do sol é intensa.", + "harshSunClearMessage": "A luz do sol enfraqueceu.", + + "strongWindsStartMessage": "Ventos fortes apareceram!", + "strongWindsLapseMessage": "Os ventos fortes continuam.", + "strongWindsClearMessage": "Os ventos fortes diminuíram.", +} \ No newline at end of file diff --git a/src/locales/zh_CN/ability-trigger.ts b/src/locales/zh_CN/ability-trigger.ts index 88900741218..85152b1bccc 100644 --- a/src/locales/zh_CN/ability-trigger.ts +++ b/src/locales/zh_CN/ability-trigger.ts @@ -1,5 +1,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const abilityTriggers: SimpleTranslationEntries = { - 'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`, + 'blockRecoilDamage' : `{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力!`, } as const; \ No newline at end of file diff --git a/src/locales/zh_CN/battle-message-ui-handler.ts b/src/locales/zh_CN/battle-message-ui-handler.ts new file mode 100644 index 00000000000..346f856872c --- /dev/null +++ b/src/locales/zh_CN/battle-message-ui-handler.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battleMessageUiHandler: SimpleTranslationEntries = { + "ivBest": "Best", + "ivFantastic": "Fantastic", + "ivVeryGood": "Very Good", + "ivPrettyGood": "Pretty Good", + "ivDecent": "Decent", + "ivNoGood": "No Good", +} as const; \ No newline at end of file diff --git a/src/locales/zh_CN/battle.ts b/src/locales/zh_CN/battle.ts index 3a92b4f9f21..cf58add1d6d 100644 --- a/src/locales/zh_CN/battle.ts +++ b/src/locales/zh_CN/battle.ts @@ -3,6 +3,7 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}} 出现了。", "trainerAppeared": "{{trainerName}}\n想要和你对战!", + "trainerAppearedDouble": "{{trainerName}}\nwould like to battle!", "singleWildAppeared": "一只野生 {{pokemonName}} 出现了。!", "multiWildAppeared": "野生的 {{pokemonName1}}\n和 {{pokemonName2}} 出现了。!", "playerComeBack": "回来吧, {{pokemonName}}!", @@ -31,6 +32,8 @@ export const battle: SimpleTranslationEntries = { "learnMoveNotLearned": "{{pokemonName}} 没有学会 {{moveName}}。", "learnMoveForgetQuestion": "要忘记哪个技能?", "learnMoveForgetSuccess": "{{pokemonName}} 忘记了\n如何使用 {{moveName}}。", + "countdownPoof": "@d{32}1, @d{15}2, @d{15}和@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}噗!", + "learnMoveAnd": "然后...", "levelCapUp": "等级上限提升到 {{levelCap}}!", "moveNotImplemented": "{{moveName}} 尚未实装,无法选择。", "moveNoPP": "这个技能的 PP 用完了", diff --git a/src/locales/zh_CN/berry.ts b/src/locales/zh_CN/berry.ts new file mode 100644 index 00000000000..08b16d58e68 --- /dev/null +++ b/src/locales/zh_CN/berry.ts @@ -0,0 +1,48 @@ +import { BerryTranslationEntries } from "#app/plugins/i18n"; + +export const berry: BerryTranslationEntries = { + "SITRUS": { + name: "文柚果", + effect: "HP低于50%时,回复最大HP的25%", + }, + "LUM": { + name: "木子果", + effect: "治愈任何异常状态和混乱状态", + }, + "ENIGMA": { + name: "谜芝果", + effect: "受到效果绝佳的招式攻击时,回复25%最大HP", + }, + "LIECHI": { + name: "枝荔果", + effect: "HP低于25%时,攻击提升一个等级", + }, + "GANLON": { + name: "龙睛果", + effect: "HP低于25%时,防御提升一个等级", + }, + "PETAYA": { + name: "龙火果", + effect: "HP低于25%时,特攻提升一个等级", + }, + "APICOT": { + name: "杏仔果", + effect: "HP低于25%时,特防提升一个等级", + }, + "SALAC": { + name: "沙鳞果", + effect: "HP低于25%时,速度提升一个等级", + }, + "LANSAT": { + name: "兰萨果", + effect: "HP低于25%时,击中要害率提升两个等级", + }, + "STARF": { + name: "星桃果", + effect: "HP低于25%时,提高随机一项能力两个等级", + }, + "LEPPA": { + name: "苹野果", + effect: "有招式的PP降到0时,恢复该招式10PP", + }, +} as const; \ No newline at end of file diff --git a/src/locales/zh_CN/config.ts b/src/locales/zh_CN/config.ts index 496fd983c06..9c3a62f59f0 100644 --- a/src/locales/zh_CN/config.ts +++ b/src/locales/zh_CN/config.ts @@ -2,32 +2,48 @@ import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; +// import { egg } from "./egg"; import { fightUiHandler } from "./fight-ui-handler"; +import { growth } from "./growth"; import { menu } from "./menu"; import { menuUiHandler } from "./menu-ui-handler"; +import { modifierType } from "./modifier-type"; import { move } from "./move"; +import { nature } from "./nature"; import { pokeball } from "./pokeball"; import { pokemon } from "./pokemon"; import { pokemonStat } from "./pokemon-stat"; +// import { splashMessages } from "./splash-messages"; import { starterSelectUiHandler } from "./starter-select-ui-handler"; +import { titles, trainerClasses, trainerNames } from "./trainers"; import { tutorial } from "./tutorial"; -import { nature } from "./nature"; - +import { weather } from "./weather"; +import { battleMessageUiHandler } from "./battle-message-ui-handler"; +import { berry } from "./berry"; export const zhCnConfig = { ability: ability, abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, + // egg: egg, fightUiHandler: fightUiHandler, - menuUiHandler: menuUiHandler, + growth: growth, menu: menu, + menuUiHandler: menuUiHandler, + modifierType: modifierType, move: move, + nature: nature, pokeball: pokeball, - pokemonStat: pokemonStat, pokemon: pokemon, + pokemonStat: pokemonStat, + // splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, + titles: titles, + trainerClasses: trainerClasses, + trainerNames: trainerNames, tutorial: tutorial, - - nature: nature + weather: weather, + battleMessageUiHandler: battleMessageUiHandler, + berry: berry, } \ No newline at end of file diff --git a/src/locales/zh_CN/fight-ui-handler.ts b/src/locales/zh_CN/fight-ui-handler.ts index 7546e9af66a..d86767bd13d 100644 --- a/src/locales/zh_CN/fight-ui-handler.ts +++ b/src/locales/zh_CN/fight-ui-handler.ts @@ -2,6 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", - "power": "Power", - "accuracy": "Accuracy", + "power": "威力", + "accuracy": "命中率", } as const; \ No newline at end of file diff --git a/src/locales/zh_CN/growth.ts b/src/locales/zh_CN/growth.ts new file mode 100644 index 00000000000..daeeed63385 --- /dev/null +++ b/src/locales/zh_CN/growth.ts @@ -0,0 +1,10 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const growth: SimpleTranslationEntries = { + "Erratic": "最快", + "Fast": "快", + "Medium_Fast": "较快", + "Medium_Slow": "较慢", + "Slow": "慢", + "Fluctuating": "最慢" +} as const; \ No newline at end of file diff --git a/src/locales/zh_CN/menu-ui-handler.ts b/src/locales/zh_CN/menu-ui-handler.ts index 0405b3ececc..22058daa7cb 100644 --- a/src/locales/zh_CN/menu-ui-handler.ts +++ b/src/locales/zh_CN/menu-ui-handler.ts @@ -9,7 +9,7 @@ export const menuUiHandler: SimpleTranslationEntries = { "EGG_GACHA": "扭蛋机", "MANAGE_DATA": "管理数据", "COMMUNITY": "社区", - "RETURN_TO_TITLE": "返回标题画面", + "SAVE_AND_QUIT": "保存并退出", "LOG_OUT": "登出", "slot": "存档位 {{slotNumber}}", "importSession": "导入存档", diff --git a/src/locales/zh_CN/menu.ts b/src/locales/zh_CN/menu.ts index e9e12a6b328..14bba6f5e6e 100644 --- a/src/locales/zh_CN/menu.ts +++ b/src/locales/zh_CN/menu.ts @@ -35,10 +35,15 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "你是男孩还是女孩?", "boy": "男孩", "girl": "女孩", + "evolving": "咦?\n{{pokemonName}} 开始进化了!", + "stoppedEvolving": "{{pokemonName}} 停止了进化.", + "pauseEvolutionsQuestion": "你确定要停止 {{pokemonName}} 的进化吗?\n你可以在队伍界面中重新进化.", + "evolutionsPaused": "{{pokemonName}} 的进化停止了.", + "evolutionDone": "恭喜!\n你的 {{pokemonName}} 进化成了 {{evolvedPokemonName}}!", "dailyRankings": "每日排名", "weeklyRankings": "每周排名", "noRankings": "无排名", - "loading": "加载中…", + "loading": "加载中...", "playersOnline": "在线玩家", "empty": "空", "yes": "是", diff --git a/src/locales/zh_CN/modifier-type.ts b/src/locales/zh_CN/modifier-type.ts new file mode 100644 index 00000000000..80ddc1f92dd --- /dev/null +++ b/src/locales/zh_CN/modifier-type.ts @@ -0,0 +1,409 @@ +import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; + +export const modifierType: ModifierTypeTranslationEntries = { + ModifierType: { + "AddPokeballModifierType": { + name: "{{modifierCount}}x {{pokeballName}}", + description: "获得 {{pokeballName}} x{{modifierCount}} (已有:{{pokeballAmount}}) \n捕捉倍率:{{catchRate}}", + }, + "AddVoucherModifierType": { + name: "{{modifierCount}}x {{voucherTypeName}}", + description: "获得 {{voucherTypeName}} x{{modifierCount}}", + }, + "PokemonHeldItemModifierType": { + extra: { + "inoperable": "{{pokemonName}} 无法携带\n这个物品!", + "tooMany": "{{pokemonName}} 已有太多\n这个物品!", + } + }, + "PokemonHpRestoreModifierType": { + description: "为一只宝可梦回复 {{restorePoints}} HP 或 {{restorePercent}}% HP,取最大值", + extra: { + "fully": "为一只宝可梦回复全部HP", + "fullyWithStatus": "为一只宝可梦回复全部HP并消除所有负面状态", + } + }, + "PokemonReviveModifierType": { + description: "复活一只宝可梦并回复 {{restorePercent}}% HP", + }, + "PokemonStatusHealModifierType": { + description: "为一只宝可梦消除所有负面状态", + }, + "PokemonPpRestoreModifierType": { + description: "为一只宝可梦的一个招式回复 {{restorePoints}} PP", + extra: { + "fully": "完全回复一只宝可梦一个招式的PP", + } + }, + "PokemonAllMovePpRestoreModifierType": { + description: "为一只宝可梦的所有招式回复 {{restorePoints}} PP", + extra: { + "fully": "为一只宝可梦的所有招式回复所有PP", + } + }, + "PokemonPpUpModifierType": { + description: "为一只宝可梦的一个招式永久增加{{upPoints}}点PP每5点当前最大PP (最多3点)", + }, + "PokemonNatureChangeModifierType": { + name: "{{natureName}}薄荷", + description: "将一只宝可梦的性格改为{{natureName}}并为该宝可梦永久解锁该性格.", + }, + "DoubleBattleChanceBoosterModifierType": { + description: "接下来的{{battleCount}}场战斗是双打的概率翻倍", + }, + "TempBattleStatBoosterModifierType": { + description: "为所有成员宝可梦提升一级{{tempBattleStatName}},持续5场战斗", + }, + "AttackTypeBoosterModifierType": { + description: "一只宝可梦的{{moveType}}系招式威力提升20%", + }, + "PokemonLevelIncrementModifierType": { + description: "一只宝可梦等级提升1级", + }, + "AllPokemonLevelIncrementModifierType": { + description: "所有成员宝可梦等级提升1级", + }, + "PokemonBaseStatBoosterModifierType": { + description: "增加持有者的{{statName}}10%. 个体值越高堆叠上限越高.", + }, + "AllPokemonFullHpRestoreModifierType": { + description: "所有宝可梦完全回复HP", + }, + "AllPokemonFullReviveModifierType": { + description: "复活所有濒死宝可梦,完全回复HP", + }, + "MoneyRewardModifierType": { + description: "获得{{moneyMultiplier}}金钱 (₽{{moneyAmount}})", + extra: { + "small": "少量", + "moderate": "中等", + "large": "大量", + }, + }, + "ExpBoosterModifierType": { + description: "EXP.获取量增加{{boostPercent}}%", + }, + "PokemonExpBoosterModifierType": { + description: "持有者EXP.获取量增加{{boostPercent}}%", + }, + "PokemonFriendshipBoosterModifierType": { + description: "每场战斗获得的好感度提升50%", + }, + "PokemonMoveAccuracyBoosterModifierType": { + description: "招式命中率增加{{accuracyAmount}} (最大100)", + }, + "PokemonMultiHitModifierType": { + description: "攻击造成一次额外伤害,每次堆叠额外伤害分别衰减60/75/82.5%", + }, + "TmModifierType": { + name: "招式学习器 {{moveId}} - {{moveName}}", + description: "教会一只宝可梦{{moveName}}", + }, + "EvolutionItemModifierType": { + description: "使某些宝可梦进化", + }, + "FormChangeItemModifierType": { + description: "使某些宝可梦更改形态", + }, + "FusePokemonModifierType": { + description: "融合两只宝可梦 (改变特性, 平分基础点数和属性, 共享招式池)", + }, + "TerastallizeModifierType": { + name: "{{teraType}}太晶碎块", + description: "持有者获得{{teraType}}太晶化10场战斗", + }, + "ContactHeldItemTransferChanceModifierType": { + description: "攻击时{{chancePercent}}%概率偷取对手物品", + }, + "TurnHeldItemTransferModifierType": { + description: "持有者每回合从对手那里获得一个持有的物品", + }, + "EnemyAttackStatusEffectChanceModifierType": { + description: "攻击时{{chancePercent}}%概率造成{{statusEffect}}", + }, + "EnemyEndureChanceModifierType": { + description: "增加{{chancePercent}}%遭受攻击的概率", + }, + + "RARE_CANDY": { name: "神奇糖果" }, + "RARER_CANDY": { name: "超神奇糖果" }, + + "MEGA_BRACELET": { name: "超级手镯", description: "能让携带着超级石战斗的宝可梦进行超级进化" }, + "DYNAMAX_BAND": { name: "极巨腕带", description: "能让携带着极巨菇菇战斗的宝可梦进行极巨化" }, + "TERA_ORB": { name: "太晶珠", description: "能让携带着太晶碎块战斗的宝可梦进行太晶化" }, + + "MAP": { name: "地图", description: "允许你在切换宝可梦群落时选择目的地"}, + + "POTION": { name: "伤药" }, + "SUPER_POTION": { name: "好伤药" }, + "HYPER_POTION": { name: "厉害伤药" }, + "MAX_POTION": { name: "全满药" }, + "FULL_RESTORE": { name: "全复药" }, + + "REVIVE": { name: "活力碎片" }, + "MAX_REVIVE": { name: "活力块" }, + + "FULL_HEAL": { name: "万灵药" }, + + "SACRED_ASH": { name: "圣灰" }, + + "REVIVER_SEED": { name: "复活种子", description: "恢复1只濒死宝可梦的HP至1/2" }, + + "ETHER": { name: "PP单项小补剂" }, + "MAX_ETHER": { name: "PP单项全补剂" }, + + "ELIXIR": { name: "PP多项小补剂" }, + "MAX_ELIXIR": { name: "PP多项全补剂" }, + + "PP_UP": { name: "PP提升剂" }, + "PP_MAX": { name: "PP极限提升剂" }, + + "LURE": { name: "引虫香水" }, + "SUPER_LURE": { name: "白银香水" }, + "MAX_LURE": { name: "黄金香水" }, + + "MEMORY_MUSHROOM": { name: "回忆蘑菇", description: "回忆一个宝可梦已经遗忘的招式" }, + + "EXP_SHARE": { name: "学习装置", description: "未参加对战的宝可梦获得20%的经验值" }, + "EXP_BALANCE": { name: "均衡型学习装置", description: "增加战斗中获得的EXP.分配给低级成员宝可梦的权重" }, + + "OVAL_CHARM": { name: "圆形护符", description: "当多只宝可梦参与战斗, 分别获得总EXP.10%的额外EXP." }, + + "EXP_CHARM": { name: "经验护符" }, + "SUPER_EXP_CHARM": { name: "超级经验护符" }, + "GOLDEN_EXP_CHARM": { name: "黄金经验护符" }, + + "LUCKY_EGG": { name: "幸运蛋" }, + "GOLDEN_EGG": { name: "金蛋" }, + + "SOOTHE_BELL": { name: "安抚之铃" }, + + "SOUL_DEW": { name: "心之水滴", description: "增加宝可梦性格影响10% (加算)" }, + + "NUGGET": { name: "金珠" }, + "BIG_NUGGET": { name: "巨大金珠" }, + "RELIC_GOLD": { name: "古代金币" }, + + "AMULET_COIN": { name: "护符金币", description: "金钱奖励增加20%" }, + "GOLDEN_PUNCH": { name: "黄金拳头", description: "将50%造成的伤害转换为金钱" }, + "COIN_CASE": { name: "代币盒", description: "每十场战斗, 获得自己金钱10%的利息" }, + + "LOCK_CAPSULE": { name: "上锁的容器", description: "允许在刷新物品时锁定物品稀有度" }, + + "GRIP_CLAW": { name: "紧缠钩爪" }, + "WIDE_LENS": { name: "广角镜" }, + + "MULTI_LENS": { name: "多重镜" }, + + "HEALING_CHARM": { name: "治愈护符", description: "HP回复量增加10% (含复活)" }, + "CANDY_JAR": { name: "糖果罐", description: "神奇糖果提供的升级提升1级" }, + + "BERRY_POUCH": { name: "树果袋", description: "使用树果时有25%的几率不会消耗树果" }, + + "FOCUS_BAND": { name: "气势头带", description: "携带该道具的宝可梦有10%几率在受到攻击而将陷入濒死状态时,保留1点HP不陷入濒死状态。" }, + + "QUICK_CLAW": { name: "先制之爪", description: "有10%的几率无视速度优先使出招式 (先制技能优先)" }, + + "KINGS_ROCK": { name: "王者之证", description: "携带该道具的宝可梦使用任意原本不会造成畏缩状态的攻击招式并造成伤害时,有10%几率使目标陷入畏缩状态。" }, + + "LEFTOVERS": { name: "吃剩的东西", description: "携带该道具的宝可梦在每个回合结束时恢复最大HP的1/16" }, + "SHELL_BELL": { name: "贝壳之铃", description: "携带该道具的宝可梦在攻击对方成功造成伤害时,携带者的HP会恢复其所造成伤害的1/8" }, + + "BATON": { name: "接力棒", description: "允许在切换宝可梦时保留能力变化, 对陷阱同样生效" }, + + "SHINY_CHARM": { name: "闪耀护符", description: "显著增加野生宝可梦的闪光概率" }, + "ABILITY_CHARM": { name: "特性护符", description: "显著增加野生宝可梦有隐藏特性的概率" }, + + "IV_SCANNER": { name: "个体值探测器", description: "允许扫描野生宝可梦的个体值。 每个次显示2个个体值. 最好的个体值优先显示" }, + + "DNA_SPLICERS": { name: "基因之楔" }, + + "MINI_BLACK_HOLE": { name: "迷你黑洞" }, + + "GOLDEN_POKEBALL": { name: "黄金精灵球", description: "在每场战斗结束后增加一个额外物品选项" }, + + "ENEMY_DAMAGE_BOOSTER": { name: "伤害硬币", description: "增加5%造成伤害" }, + "ENEMY_DAMAGE_REDUCTION": { name: "防御硬币", description: "减少2.5%承受伤害" }, + "ENEMY_HEAL": { name: "回复硬币", description: "每回合回复2%最大HP" }, + "ENEMY_ATTACK_POISON_CHANCE": { name: "剧毒硬币" }, + "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "麻痹硬币" }, + "ENEMY_ATTACK_SLEEP_CHANCE": { name: "睡眠硬币" }, + "ENEMY_ATTACK_FREEZE_CHANCE": { name: "冰冻硬币" }, + "ENEMY_ATTACK_BURN_CHANCE": { name: "灼烧硬币" }, + "ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "万灵药硬币", description: "增加10%每回合治愈异常状态的概率" }, + "ENEMY_ENDURE_CHANCE": { name: "忍受硬币" }, + "ENEMY_FUSED_CHANCE": { name: "融合硬币", description: "增加1%野生融合宝可梦出现概率" }, + }, + TempBattleStatBoosterItem: { + "x_attack": "力量强化", + "x_defense": "防御强化", + "x_sp_atk": "特攻强化", + "x_sp_def": "特防强化", + "x_speed": "速度强化", + "x_accuracy": "命中强化", + "dire_hit": "要害攻击", + }, + AttackTypeBoosterItem: { + "silk_scarf": "丝绸围巾", + "black_belt": "黑带", + "sharp_beak": "锐利鸟嘴", + "poison_barb": "毒针", + "soft_sand": "柔软沙子", + "hard_stone": "硬石头", + "silver_powder": "银粉", + "spell_tag": "诅咒之符", + "metal_coat": "金属膜", + "charcoal": "木炭", + "mystic_water": "神秘水滴", + "miracle_seed": "奇迹种子", + "magnet": "磁铁", + "twisted_spoon": "弯曲的汤匙", + "never_melt_ice": "不融冰", + "dragon_fang": "龙之牙", + "black_glasses": "黑色眼镜", + "fairy_feather": "妖精之羽", + }, + BaseStatBoosterItem: { + "hp_up": "HP增强剂", + "protein": "攻击增强剂", + "iron": "防御增强剂", + "calcium": "特攻增强剂", + "zinc": "特防增强剂", + "carbos": "速度增强剂", + }, + EvolutionItem: { + "NONE": "None", + + "LINKING_CORD": "联系绳", + "SUN_STONE": "日之石", + "MOON_STONE": "月之石", + "LEAF_STONE": "叶之石", + "FIRE_STONE": "火之石", + "WATER_STONE": "水之石", + "THUNDER_STONE": "雷之石", + "ICE_STONE": "冰之石", + "DUSK_STONE": "暗之石", + "DAWN_STONE": "觉醒之石", + "SHINY_STONE": "光之石", + "CRACKED_POT": "破裂的茶壶", + "SWEET_APPLE": "甜甜苹果", + "TART_APPLE": "酸酸苹果", + "STRAWBERRY_SWEET": "草莓糖饰", + "UNREMARKABLE_TEACUP": "凡作茶碗", + + "CHIPPED_POT": "缺损的茶壶", + "BLACK_AUGURITE": "黑奇石", + "GALARICA_CUFF": "伽勒豆蔻手环", + "GALARICA_WREATH": "伽勒豆蔻花圈", + "PEAT_BLOCK": "泥炭块", + "AUSPICIOUS_ARMOR": "庆祝之铠", + "MALICIOUS_ARMOR": "咒术之铠", + "MASTERPIECE_TEACUP": "杰作茶碗", + "METAL_ALLOY": "复合金属", + "SCROLL_OF_DARKNESS": "恶之挂轴", + "SCROLL_OF_WATERS": "水之挂轴", + "SYRUPY_APPLE": "蜜汁苹果", + }, + FormChangeItem: { + "NONE": "None", + + "ABOMASITE": "暴雪王进化石", + "ABSOLITE": "阿勃梭鲁进化石", + "AERODACTYLITE": "化石翼龙进化石", + "AGGRONITE": "波士可多拉进化石", + "ALAKAZITE": "胡地进化石", + "ALTARIANITE": "七夕青鸟进化石", + "AMPHAROSITE": "电龙进化石", + "AUDINITE": "差不多娃娃进化石", + "BANETTITE": "诅咒娃娃进化石", + "BEEDRILLITE": "大针蜂进化石", + "BLASTOISINITE": "水箭龟进化石", + "BLAZIKENITE": "火焰鸡进化石", + "CAMERUPTITE": "喷火驼进化石", + "CHARIZARDITE_X": "喷火龙进化石X", + "CHARIZARDITE_Y": "喷火龙进化石Y", + "DIANCITE": "蒂安希进化石", + "GALLADITE": "艾路雷朵进化石", + "GARCHOMPITE": "烈咬陆鲨进化石", + "GARDEVOIRITE": "沙奈朵进化石", + "GENGARITE": "耿鬼进化石", + "GLALITITE": "冰鬼护进化石", + "GYARADOSITE": "暴鲤龙进化石", + "HERACRONITE": "赫拉克罗斯进化石", + "HOUNDOOMINITE": "黑鲁加进化石", + "KANGASKHANITE": "袋兽进化石", + "LATIASITE": "拉帝亚斯进化石", + "LATIOSITE": "拉帝欧斯进化石", + "LOPUNNITE": "长耳兔进化石", + "LUCARIONITE": "路卡利欧进化石", + "MANECTITE": "雷电兽进化石", + "MAWILITE": "大嘴娃进化石", + "MEDICHAMITE": "恰雷姆进化石", + "METAGROSSITE": "巨金怪进化石", + "MEWTWONITE_X": "超梦进化石X", + "MEWTWONITE_Y": "超梦进化石Y", + "PIDGEOTITE": "大比鸟进化石", + "PINSIRITE": "凯罗斯进化石", + "RAYQUAZITE": "烈空坐进化石", + "SABLENITE": "勾魂眼进化石", + "SALAMENCITE": "暴飞龙进化石", + "SCEPTILITE": "蜥蜴王进化石", + "SCIZORITE": "巨钳螳螂进化石", + "SHARPEDONITE": "巨牙鲨进化石", + "SLOWBRONITE": "呆壳兽进化石", + "STEELIXITE": "大钢蛇进化石", + "SWAMPERTITE": "巨沼怪进化石", + "TYRANITARITE": "班基拉斯进化石", + "VENUSAURITE": "妙蛙花进化石", + + "BLUE_ORB": "靛蓝色宝珠", + "RED_ORB": "朱红色宝珠", + "SHARP_METEORITE": "锐利陨石", + "HARD_METEORITE": "坚硬陨石", + "SMOOTH_METEORITE": "光滑陨石", + "ADAMANT_CRYSTAL": "大金刚宝玉", + "LUSTROUS_ORB": "白玉宝珠", + "GRISEOUS_CORE": "大白金宝玉", + "REVEAL_GLASS": "现形镜", + "GRACIDEA": "葛拉西蒂亚花", + "MAX_MUSHROOMS": "极巨菇菇", + "DARK_STONE": "黑暗石", + "LIGHT_STONE": "光明石", + "PRISON_BOTTLE": "惩戒之壶", + "N_LUNARIZER": "奈克洛露奈合体器", + "N_SOLARIZER": "奈克洛索尔合体器", + "RUSTED_SWORD": "腐朽的剑", + "RUSTED_SHIELD": "腐朽的盾", + "ICY_REINS_OF_UNITY": "牵绊缰绳(冰)", + "SHADOW_REINS_OF_UNITY": "牵绊缰绳(幽灵)", + "WELLSPRING_MASK": "水井面具", + "HEARTHFLAME_MASK": "火灶面具", + "CORNERSTONE_MASK": "础石面具", + "SHOCK_DRIVE": "闪电卡带", + "BURN_DRIVE": "火焰卡带", + "CHILL_DRIVE": "冰冻卡带", + "DOUSE_DRIVE": "水流卡带", + }, + TeraType: { + "UNKNOWN": "Unknown", + "NORMAL": "一般", + "FIGHTING": "格斗", + "FLYING": "飞行", + "POISON": "毒", + "GROUND": "地面", + "ROCK": "岩石", + "BUG": "虫", + "GHOST": "幽灵", + "STEEL": "钢", + "FIRE": "火", + "WATER": "水", + "GRASS": "草", + "ELECTRIC": "电", + "PSYCHIC": "超能力", + "ICE": "冰", + "DRAGON": "龙", + "DARK": "恶", + "FAIRY": "妖精", + "STELLAR": "星晶", + }, +} as const; \ No newline at end of file diff --git a/src/locales/zh_CN/nature.ts b/src/locales/zh_CN/nature.ts index f29917ff60d..00beeefdfa4 100644 --- a/src/locales/zh_CN/nature.ts +++ b/src/locales/zh_CN/nature.ts @@ -1,29 +1,29 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const nature: SimpleTranslationEntries = { - "Hardy": "Hardy", - "Lonely": "Lonely", - "Brave": "Brave", - "Adamant": "Adamant", - "Naughty": "Naughty", - "Bold": "Bold", - "Docile": "Docile", - "Relaxed": "Relaxed", - "Impish": "Impish", - "Lax": "Lax", - "Timid": "Timid", - "Hasty": "Hasty", - "Serious": "Serious", - "Jolly": "Jolly", - "Naive": "Naive", - "Modest": "Modest", - "Mild": "Mild", - "Quiet": "Quiet", - "Bashful": "Bashful", - "Rash": "Rash", - "Calm": "Calm", - "Gentle": "Gentle", - "Sassy": "Sassy", - "Careful": "Careful", - "Quirky": "Quirky" + "Hardy": "勤奋", + "Lonely": "怕寂寞", + "Brave": "勇敢", + "Adamant": "固执", + "Naughty": "顽皮", + "Bold": "大胆", + "Docile": "坦率", + "Relaxed": "悠闲", + "Impish": "淘气", + "Lax": "乐天", + "Timid": "胆小", + "Hasty": "急躁", + "Serious": "认真", + "Jolly": "爽朗", + "Naive": "天真", + "Modest": "内敛", + "Mild": "慢吞吞", + "Quiet": "冷静", + "Bashful": "害羞", + "Rash": "马虎", + "Calm": "温和", + "Gentle": "温顺", + "Sassy": "自大", + "Careful": "慎重", + "Quirky": "浮躁" } as const; \ No newline at end of file diff --git a/src/locales/zh_CN/starter-select-ui-handler.ts b/src/locales/zh_CN/starter-select-ui-handler.ts index ace02c1c227..0713b454376 100644 --- a/src/locales/zh_CN/starter-select-ui-handler.ts +++ b/src/locales/zh_CN/starter-select-ui-handler.ts @@ -7,6 +7,15 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; */ export const starterSelectUiHandler: SimpleTranslationEntries = { "confirmStartTeam":'使用这些宝可梦开始游戏吗?', + "gen1": "I", + "gen2": "II", + "gen3": "III", + "gen4": "IV", + "gen5": "V", + "gen6": "VI", + "gen7": "VII", + "gen8": "VIII", + "gen9": "IX", "growthRate": "成长速度:", "ability": "特性:", "passive": "被动:", @@ -29,7 +38,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleVariant": 'V: 切换变种', "enablePassive": "启用被动", "disablePassive": "禁用被动", - "locked": "Locked", - "disabled": "Disabled", - "uncaught": "Uncaught" -} \ No newline at end of file + "locked": "未解锁", + "disabled": "已禁用", + "uncaught": "未捕获" +} diff --git a/src/locales/zh_CN/trainers.ts b/src/locales/zh_CN/trainers.ts new file mode 100644 index 00000000000..fae8301c627 --- /dev/null +++ b/src/locales/zh_CN/trainers.ts @@ -0,0 +1,302 @@ +import {SimpleTranslationEntries} from "#app/plugins/i18n"; + +// Titles of special trainers like gym leaders, elite four, and the champion +export const titles: SimpleTranslationEntries = { + "elite_four": "四天王", + "gym_leader": "道馆馆主", + "gym_leader_female": "道馆馆主", + "champion": "冠军", + "rival": "劲敌", + "professor": "博士", + "frontier_brain": "开拓头脑", + // Maybe if we add the evil teams we can add "Team Rocket" and "Team Aqua" etc. here as well as "Team Rocket Boss" and "Team Aqua Admin" etc. +} as const; + +// Titles of trainers like "Youngster" or "Lass" +export const trainerClasses: SimpleTranslationEntries = { + "ace_trainer": "精英训练家", + "ace_trainer_female": "精英训练家", + "ace_duo": "精英组合", + "artist": "艺术家", + "artist_female": "艺术家", + "backers": "啦啦队", + "backpacker": "背包客", + "backpacker_female": "背包客", + "backpackers": "背包客组合", + "baker": "面包师", + "battle_girl": "对战少女", + "beauty": "大姐姐", + "beginners": "新人训练家组合", + "biker": "飙车族", + "black_belt": "空手道王", + "breeder": "宝可梦培育家", + "breeder_female": "宝可梦培育家", + "breeders": "宝可梦培育家组合", + "clerk": "商务人士", + "clerk_female": "职场OL", + "colleagues": "商务伙伴", + "crush_kin": "格斗姐弟", + "cyclist": "自行车手", + "cyclist_female": "自行车手", + "cyclists": "自行车手组合", + "dancer": "舞者", + "dancer_female": "舞者", + "depot_agent": "铁路员工", + "doctor": "医生", + "doctor_female": "医生", + "fisherman": "垂钓者", + "fisherman_female": "垂钓者", + "gentleman": "绅士", + "guitarist": "吉他手", + "guitarist_female": "吉他手", + "harlequin": "滑稽演员", + "hiker": "登山男", + "hooligans": "坏组合", + "hoopster": "篮球选手", + "infielder": "棒球选手", + "janitor": "清洁员", + "lady": "千金小姐", + "lass": "迷你裙", + "linebacker": "美式橄榄球选手", + "maid": "女仆", + "madame": "女士", + "medical_team": "医疗团队", + "musician": "音乐家", + "hex_maniac": "灵异迷", + "nurse": "护士", + "nursery_aide": "幼儿园老师", + "officer": "警察", + "parasol_lady": "阳伞姐姐", + "pilot": "飞行员", + "pokefan": "发烧友俱乐部", + "pokefan_family": "同好夫妇", + "preschooler": "幼儿园小朋友", + "preschooler_female": "幼儿园小朋友", + "preschoolers": "幼儿园小朋友组合", + "psychic": "超能力者", + "psychic_female": "超能力者", + "psychics": "超能力者组合", + "pokémon_ranger": "宝可梦巡护员", + "pokémon_rangers": "宝可梦巡护员组合", + "ranger": "巡护员", + "restaurant_staff": "服务生组合", + "rich": "Rich", + "rich_female": "Rich", + "rich_boy": "富家少爷", + "rich_couple": "富豪夫妇", + "rich_kid": "Rich Kid", + "rich_kid_female": "Rich Kid", + "rich_kids": "富二代组合", + "roughneck": "光头男", + "scientist": "研究员", + "scientist_female": "研究员", + "scientists": "研究员组合", + "smasher": "网球选手", + "snow_worker": "雪地工人", + "snow_worker_female": "雪地工人", + "striker": "足球选手", + "school_kid": "补习班学生", + "school_kid_female": "补习班学生", + "school_kids": "补习班学生组合", + "swimmer": "泳裤小伙子", + "swimmer_female": "比基尼大姐姐", + "swimmers": "泳装情侣", + "twins": "双胞胎", + "veteran": "资深训练家", + "veteran_female": "资深训练家", + "veteran_duo": "资深组合", + "waiter": "服务生", + "waitress": "女服务生", + "worker": "工人", + "worker_female": "工人", + "workers": "工人组合", + "youngster": "短裤小子" +} as const; + +// Names of special trainers like gym leaders, elite four, and the champion +export const trainerNames: SimpleTranslationEntries = { + // ---- 馆主 Gym leader ---- + // 关都地区 Kanto Region + "brock": "小刚", + "misty": "小霞", + "lt_surge": "马志士", + "erika": "莉佳", + "janine": "阿杏", + "sabrina": "娜姿", + "blaine": "夏伯", + "giovanni": "坂木", + + // 城都地区 Johto Region + "falkner": "阿速", + "bugsy": "阿笔", + "whitney": "小茜", + "morty": "松叶", + "chuck": "阿四", + "jasmine": "阿蜜", + "pryce": "柳伯", + "clair": "小椿", + + // 丰缘地区 Hoenn Region + "roxanne": "杜娟", + "brawly": "藤树", + "wattson": "铁旋", + "flannery": "亚莎", + "norman": "千里", + "winona": "娜琪", + "tate": "小枫", + "liza": "小南", + "juan": "亚当", + + // 神奥地区 Sinnoh Region + "roark": "瓢太", + "gardenia": "菜种", + "maylene": "阿李", + "crasher_wake": "吉宪", + "fantina": "梅丽莎", + "byron": "东瓜", + "candice": "小菘", + "volkner": "电次", + + // 合众地区 Unova Region + "cilan": "天桐", + "chili": "伯特", + "cress": "寇恩", + "cheren": "黑连", + "lenora": "芦荟", + "roxie": "霍米加", + "burgh": "亚堤", + "elesa": "小菊儿", + "clay": "菊老大", + "skyla": "风露", + "brycen": "哈奇库", + "drayden": "夏卡", + "marlon": "西子伊", + + // 卡洛斯地区 Kalos Region + "viola": "紫罗兰", + "grant": "查克洛", + "korrina": "可尔妮", + "ramos": "福爷", + "clemont": "希特隆", + "valerie": "玛绣", + "olympia": "葛吉花", + "wulfric": "得抚", + + // 伽勒尔地区 Galar Region + "milo": "亚洛", + "nessa": "露璃娜", + "kabu": "卡芜", + "bea": "彩豆", + "allister": "欧尼奥", + "opal": "波普菈", + "bede": "彼特", + "gordie": "玛瓜", + "melony": "美蓉", + "piers": "聂梓", + "marnie": "玛俐", + "raihan": "奇巴纳", + + // 帕底亚地区 Paldea Region + "katy": "阿枫", + "brassius": "寇沙", + "iono": "奇树", + "kofu": "海岱", + "larry": "青木", + "ryme": "莱姆", + "tulip": "莉普", + "grusha": "古鲁夏", + + // ---- 四天王 Elite Four ---- + // 关都地区 Kanto Region + "lorelei": "科拿", + "bruno": "希巴", + "agatha": "菊子", + "lance": "阿渡", + + // 城都地区 Johto Region + "will": "一树", + "koga": "阿桔", + "karen": "梨花", + + // 丰都地区 Hoenn Region + "sidney": "花月", + "phoebe": "芙蓉", + "glacia": "波妮", + "drake": "源治", + + // 神奥地区 Sinnoh Region + "aaron": "阿柳", + "bertha": "菊野", + "flint": "大叶", + "lucian": "悟松", + + // 合众地区 Unova Region + "shauntal": "婉龙", + "marshal": "连武", + "grimsley": "越橘", + "caitlin": "嘉德丽雅", + + // 卡洛斯地区 Kalos Region + "malva": "帕琦拉", + "siebold": "志米", + "wikstrom": "雁铠", + "drasna": "朵拉塞娜", + + // 阿罗拉地区 Alola Region + "hala": "哈拉", + "molayne": "马睿因", + "olivia": "丽姿", + "acerola": "阿塞萝拉", + "kahili": "卡希丽", + + // 帕底亚地区 Paldea Region + "rika": "辛俐", + "poppy": "波琵", + "larry_elite": "青木", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + "hassel": "八朔", + + // 蓝莓学院 Blueberry Academy + "crispin": "赤松", + "amarys": "纳莉", + "lacey": "紫竽", + "drayton": "杜若", + + // ---- 冠军 Champion ---- + // 关都地区 Kanto Region + "blue": "青绿", + "red": "赤红", + + // 城都地区 Johto Region + "lance_champion": "阿渡", // Does this really need to be an extra entry? (it is in trainer-type.ts so I added it here) + + // 丰缘地区 Hoenn Region + "steven": "大吾", + "wallace": "米可利", + + // 神奥地区 Sinnoh Region + "cynthia": "竹兰", + + // 合众地区 Unova Region + "alder": "阿戴克", + "iris": "艾莉丝", + + // 卡洛斯地区 Kalos Region + "diantha": "卡露妮", + + // 阿罗拉地区 Alola Region + "hau": "哈乌", + + // 伽勒尔地区 Galar Region + "leon": "丹帝", + + // 帕底亚地区 paldea Region + "geeta": "也慈", + "nemona": "妮莫", + + // 蓝莓学院 Blueberry academy + "kieran": "乌栗", + + // 劲敌 rival + "rival": "芬恩", + "rival_female": "艾薇", +} as const; diff --git a/src/locales/zh_CN/weather.ts b/src/locales/zh_CN/weather.ts new file mode 100644 index 00000000000..50fb2227b2b --- /dev/null +++ b/src/locales/zh_CN/weather.ts @@ -0,0 +1,44 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +/** + * The weather namespace holds text displayed when weather is active during a battle + */ +export const weather: SimpleTranslationEntries = { + "sunnyStartMessage": "日照变强了!", + "sunnyLapseMessage": "日照很强。", + "sunnyClearMessage": "日照复原了。", + + "rainStartMessage": "下大雨了!", + "rainLapseMessage": "雨继续下。", + "rainClearMessage": "雨停了。", + + "sandstormStartMessage": "开始刮沙尘暴了!", + "sandstormLapseMessage": "沙尘暴肆虐。", + "sandstormClearMessage": "沙尘暴停止了。", + "sandstormDamageMessage": "沙尘暴袭击了{{pokemonPrefix}}{{pokemonName}}!", + + "hailStartMessage": "开始下冰雹了!", + "hailLapseMessage": "冰雹继续肆虐。", + "hailClearMessage": "冰雹不再下了。", + "hailDamageMessage": "冰雹袭击了{{pokemonPrefix}}{{pokemonName}}!", + + "snowStartMessage": "开始下雪了!", + "snowLapseMessage": "雪继续下。", + "snowClearMessage": "雪停了。", + + "fogStartMessage": "起雾了!", + "fogLapseMessage": "雾很浓。", + "fogClearMessage": "雾散了。", + + "heavyRainStartMessage": "开始下起了暴雨!", + "heavyRainLapseMessage": "暴雨势头不减。", + "heavyRainClearMessage": "暴雨停了。", + + "harshSunStartMessage": "日照变得非常强了!", + "harshSunLapseMessage": "强日照势头不减。", + "harshSunClearMessage": "日照复原了。", + + "strongWindsStartMessage": "吹起了神秘的乱流!", + "strongWindsLapseMessage": "神秘的乱流势头不减。", + "strongWindsClearMessage": "神秘的乱流停止了。" +} \ No newline at end of file diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 982f8a6548d..1e21af58564 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -3,7 +3,7 @@ import { AttackMove, allMoves } from '../data/move'; import { Moves } from "../data/enums/moves"; import { PokeballType, getPokeballCatchMultiplier, getPokeballName } from '../data/pokeball'; import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from '../field/pokemon'; -import { EvolutionItem, SpeciesFriendshipEvolutionCondition, pokemonEvolutions } from '../data/pokemon-evolutions'; +import { EvolutionItem, pokemonEvolutions } from '../data/pokemon-evolutions'; import { Stat, getStatName } from '../data/pokemon-stat'; import { tmPoolTiers, tmSpecies } from '../data/tms'; import { Type } from '../data/type'; @@ -19,7 +19,7 @@ import { VoucherType, getVoucherTypeIcon, getVoucherTypeName } from '../system/v import { FormChangeItem, SpeciesFormChangeItemTrigger, pokemonFormChanges } from '../data/pokemon-forms'; import { ModifierTier } from './modifier-tier'; import { Nature, getNatureName, getNatureStatMultiplier } from '#app/data/nature'; -import { Localizable } from '#app/plugins/i18n'; +import i18next from '#app/plugins/i18n'; import { getModifierTierTextTint } from '#app/ui/text'; const outputModifierData = false; @@ -40,25 +40,27 @@ type NewModifierFunc = (type: ModifierType, args: any[]) => Modifier; export class ModifierType { public id: string; public generatorId: string; - public name: string; - protected description: string; + public localeKey: string; public iconImage: string; public group: string; public soundName: string; public tier: ModifierTier; protected newModifierFunc: NewModifierFunc; - constructor(name: string, description: string, newModifierFunc: NewModifierFunc, iconImage?: string, group?: string, soundName?: string) { - this.name = name; - this.description = description; - this.iconImage = iconImage || name?.replace(/[ \-]/g, '_')?.replace(/['\.]/g, '')?.toLowerCase(); + constructor(localeKey: string, iconImage: string, newModifierFunc: NewModifierFunc, group?: string, soundName?: string) { + this.localeKey = localeKey; + this.iconImage = iconImage; this.group = group || ''; this.soundName = soundName || 'restore'; this.newModifierFunc = newModifierFunc; } + get name(): string { + return i18next.t(`${this.localeKey}.name` as any); + } + getDescription(scene: BattleScene): string { - return this.description; + return i18next.t(`${this.localeKey}.description` as any); } setTier(tier: ModifierTier): void { @@ -114,7 +116,7 @@ export class ModifierTypeGenerator extends ModifierType { private genTypeFunc: ModifierTypeGeneratorFunc; constructor(genTypeFunc: ModifierTypeGeneratorFunc) { - super(null, null, null, null); + super(null, null, null); this.genTypeFunc = genTypeFunc; } @@ -133,58 +135,80 @@ export interface GeneratedPersistentModifierType { getPregenArgs(): any[]; } -class AddPokeballModifierType extends ModifierType implements Localizable { +class AddPokeballModifierType extends ModifierType { private pokeballType: PokeballType; private count: integer; - constructor(pokeballType: PokeballType, count: integer, iconImage?: string) { - super('', '', (_type, _args) => new Modifiers.AddPokeballModifier(this, pokeballType, count), iconImage, 'pb', 'pb_bounce_1'); + constructor(iconImage: string, pokeballType: PokeballType, count: integer) { + super('', iconImage, (_type, _args) => new Modifiers.AddPokeballModifier(this, pokeballType, count), 'pb', 'pb_bounce_1'); this.pokeballType = pokeballType; this.count = count; } - localize(): void { - // TODO: Actually use i18n to localize this description. - this.name = `${this.count}x ${getPokeballName(this.pokeballType)}`; - this.description = `Receive ${getPokeballName(this.pokeballType)} x${this.count} (Inventory: {AMOUNT}) \nCatch Rate: ${getPokeballCatchMultiplier(this.pokeballType) > -1 ? `${getPokeballCatchMultiplier(this.pokeballType)}x` : 'Certain'}`; - } - - getDescription(scene: BattleScene): string { - this.localize(); - return this.description.replace('{AMOUNT}', scene.pokeballCounts[this.pokeballType].toString()); + get name(): string { + return i18next.t(`modifierType:ModifierType.AddPokeballModifierType.name`, { + 'modifierCount': this.count, + 'pokeballName': getPokeballName(this.pokeballType), + }); } + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.AddPokeballModifierType.description`, { + 'modifierCount': this.count, + 'pokeballName': getPokeballName(this.pokeballType), + 'catchRate': getPokeballCatchMultiplier(this.pokeballType) > -1 ? `${getPokeballCatchMultiplier(this.pokeballType)}x` : '100%', + 'pokeballAmount': `${scene.pokeballCounts[this.pokeballType]}`, + }); + } } class AddVoucherModifierType extends ModifierType { + private voucherType: VoucherType; + private count: integer; + constructor(voucherType: VoucherType, count: integer) { - super(`${count}x ${getVoucherTypeName(voucherType)}`, `Receive ${getVoucherTypeName(voucherType)} x${count}`, - (_type, _args) => new Modifiers.AddVoucherModifier(this, voucherType, count), getVoucherTypeIcon(voucherType), 'voucher'); + super('', getVoucherTypeIcon(voucherType), (_type, _args) => new Modifiers.AddVoucherModifier(this, voucherType, count), 'voucher'); + this.count = count; + this.voucherType = voucherType; + } + + get name(): string { + return i18next.t(`modifierType:ModifierType.AddVoucherModifierType.name`, { + 'modifierCount': this.count, + 'voucherTypeName': getVoucherTypeName(this.voucherType), + }); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.AddVoucherModifierType.description`, { + 'modifierCount': this.count, + 'voucherTypeName': getVoucherTypeName(this.voucherType), + }); } } export class PokemonModifierType extends ModifierType { public selectFilter: PokemonSelectFilter; - constructor(name: string, description: string, newModifierFunc: NewModifierFunc, selectFilter?: PokemonSelectFilter, iconImage?: string, group?: string, soundName?: string) { - super(name, description, newModifierFunc, iconImage, group, soundName); + constructor(localeKey: string, iconImage: string, newModifierFunc: NewModifierFunc, selectFilter?: PokemonSelectFilter, group?: string, soundName?: string) { + super(localeKey, iconImage, newModifierFunc, group, soundName); this.selectFilter = selectFilter; } } export class PokemonHeldItemModifierType extends PokemonModifierType { - constructor(name: string, description: string, newModifierFunc: NewModifierFunc, iconImage?: string, group?: string, soundName?: string) { - super(name, description, newModifierFunc, (pokemon: PlayerPokemon) => { + constructor(localeKey: string, iconImage: string, newModifierFunc: NewModifierFunc, group?: string, soundName?: string) { + super(localeKey, iconImage, newModifierFunc, (pokemon: PlayerPokemon) => { const dummyModifier = this.newModifier(pokemon); 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 `${pokemon.name} can\'t take\nthis item!`; + return i18next.t(`modifierType:ModifierType.PokemonHeldItemModifierType.extra.inoperable`, { 'pokemonName': pokemon.name }); if (matchingModifier && matchingModifier.stackCount === maxStackCount) - return `${pokemon.name} has too many\nof this item!`; + return i18next.t(`modifierType:ModifierType.PokemonHeldItemModifierType.extra.tooMany`, { 'pokemonName': pokemon.name }); return null; - }, iconImage, group, soundName); + }, group, soundName); } newModifier(...args: any[]): Modifiers.PokemonHeldItemModifier { @@ -197,57 +221,72 @@ export class PokemonHpRestoreModifierType extends PokemonModifierType { protected restorePercent: integer; protected healStatus: boolean; - constructor(name: string, restorePoints: integer, restorePercent: integer, healStatus: boolean = false, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, iconImage?: string, group?: string) { - super(name, restorePoints ? `Restores ${restorePoints} HP or ${restorePercent}% HP for one Pokémon, whichever is higher` : `Fully restores HP for one Pokémon${healStatus ? ' and heals any status ailment' : ''}`, - newModifierFunc || ((_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.restorePercent, this.healStatus, false)), + 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))) return PartyUiHandler.NoEffectMessage; return null; - }), iconImage, group || 'potion'); + }), group || 'potion'); this.restorePoints = restorePoints; this.restorePercent = restorePercent; this.healStatus = healStatus; } + + getDescription(scene: BattleScene): string { + return this.restorePoints + ? i18next.t(`modifierType:ModifierType.PokemonHpRestoreModifierType.description`, { + restorePoints: this.restorePoints, + restorePercent: this.restorePercent, + }) + : this.healStatus + ? i18next.t(`modifierType:ModifierType.PokemonHpRestoreModifierType.extra.fullyWithStatus`) + : i18next.t(`modifierType:ModifierType.PokemonHpRestoreModifierType.extra.fully`); + } } export class PokemonReviveModifierType extends PokemonHpRestoreModifierType { - constructor(name: string, restorePercent: integer, iconImage?: string) { - super(name, 0, restorePercent, false, (_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, 0, this.restorePercent, false, true), + constructor(localeKey: string, iconImage: string, restorePercent: integer) { + super(localeKey, iconImage, 0, restorePercent, false, (_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, 0, this.restorePercent, false, true), ((pokemon: PlayerPokemon) => { if (!pokemon.isFainted()) return PartyUiHandler.NoEffectMessage; return null; - }), iconImage, 'revive'); + }), 'revive'); - this.description = `Revives one Pokémon and restores ${restorePercent}% HP`; this.selectFilter = (pokemon: PlayerPokemon) => { if (pokemon.hp) return PartyUiHandler.NoEffectMessage; return null; }; } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.PokemonReviveModifierType.description`, { restorePercent: this.restorePercent }); + } } export class PokemonStatusHealModifierType extends PokemonModifierType { - constructor(name: string) { - super(name, `Heals any status ailment for one Pokémon`, - ((_type, args) => new Modifiers.PokemonStatusHealModifier(this, (args[0] as PlayerPokemon).id)), + constructor(localeKey: string, iconImage: string) { + super(localeKey, iconImage, ((_type, args) => new Modifiers.PokemonStatusHealModifier(this, (args[0] as PlayerPokemon).id)), ((pokemon: PlayerPokemon) => { if (!pokemon.hp || !pokemon.status) return PartyUiHandler.NoEffectMessage; return null; })); } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.PokemonStatusHealModifierType.description`); + } } export abstract class PokemonMoveModifierType extends PokemonModifierType { public moveSelectFilter: PokemonMoveSelectFilter; - constructor(name: string, description: string, newModifierFunc: NewModifierFunc, selectFilter?: PokemonSelectFilter, moveSelectFilter?: PokemonMoveSelectFilter, - iconImage?: string, group?: string) { - super(name, description, newModifierFunc, selectFilter, iconImage, group); + constructor(localeKey: string, iconImage: string, newModifierFunc: NewModifierFunc, selectFilter?: PokemonSelectFilter, moveSelectFilter?: PokemonMoveSelectFilter, group?: string) { + super(localeKey, iconImage, newModifierFunc, selectFilter, group); this.moveSelectFilter = moveSelectFilter; } @@ -256,101 +295,136 @@ export abstract class PokemonMoveModifierType extends PokemonModifierType { export class PokemonPpRestoreModifierType extends PokemonMoveModifierType { protected restorePoints: integer; - constructor(name: string, restorePoints: integer, iconImage?: string) { - super(name, `Restores ${restorePoints > -1 ? restorePoints : 'all'} PP for one Pokémon move`, (_type, args) => new Modifiers.PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.restorePoints), + constructor(localeKey: string, iconImage: string, restorePoints: integer) { + super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.restorePoints), (_pokemon: PlayerPokemon) => { return null; }, (pokemonMove: PokemonMove) => { if (!pokemonMove.ppUsed) return PartyUiHandler.NoEffectMessage; return null; - }, iconImage, 'ether'); + }, 'ether'); this.restorePoints = restorePoints; } + + getDescription(scene: BattleScene): string { + return this.restorePoints > -1 + ? i18next.t(`modifierType:ModifierType.PokemonPpRestoreModifierType.description`, { restorePoints: this.restorePoints }) + : i18next.t(`modifierType:ModifierType.PokemonPpRestoreModifierType.extra.fully`) + ; + } } export class PokemonAllMovePpRestoreModifierType extends PokemonModifierType { protected restorePoints: integer; - constructor(name: string, restorePoints: integer, iconImage?: string) { - super(name, `Restores ${restorePoints > -1 ? restorePoints : 'all'} PP for all of one Pokémon's moves`, (_type, args) => new Modifiers.PokemonAllMovePpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints), + constructor(localeKey: string, iconImage: string, restorePoints: integer) { + super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonAllMovePpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints), (pokemon: PlayerPokemon) => { if (!pokemon.getMoveset().filter(m => m.ppUsed).length) return PartyUiHandler.NoEffectMessage; return null; - }, iconImage, 'elixir'); + }, 'elixir'); this.restorePoints = restorePoints; } + + getDescription(scene: BattleScene): string { + return this.restorePoints > -1 + ? i18next.t(`modifierType:ModifierType.PokemonAllMovePpRestoreModifierType.description`, { restorePoints: this.restorePoints }) + : i18next.t(`modifierType:ModifierType.PokemonAllMovePpRestoreModifierType.extra.fully`) + ; + } } export class PokemonPpUpModifierType extends PokemonMoveModifierType { protected upPoints: integer; - constructor(name: string, upPoints: integer, iconImage?: string) { - super(name, `Permanently increases PP for one Pokémon move by ${upPoints} for every 5 maximum PP (maximum 3)`, (_type, args) => new Modifiers.PokemonPpUpModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.upPoints), + constructor(localeKey: string, iconImage: string, upPoints: integer) { + super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonPpUpModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.upPoints), (_pokemon: PlayerPokemon) => { return null; }, (pokemonMove: PokemonMove) => { if (pokemonMove.getMove().pp < 5 || pokemonMove.ppUp >= 3) return PartyUiHandler.NoEffectMessage; return null; - }, iconImage, 'ppUp'); + }, 'ppUp'); this.upPoints = upPoints; } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.PokemonPpUpModifierType.description`, { upPoints: this.upPoints }); + } } export class PokemonNatureChangeModifierType extends PokemonModifierType { protected nature: Nature; constructor(nature: Nature) { - super(`${getNatureName(nature)} Mint`, `Changes a Pokémon\'s nature to ${getNatureName(nature, true, true, true)} and permanently unlocks the nature for the starter.`, ((_type, args) => new Modifiers.PokemonNatureChangeModifier(this, (args[0] as PlayerPokemon).id, this.nature)), + super('', `mint_${Utils.getEnumKeys(Stat).find(s => getNatureStatMultiplier(nature, Stat[s]) > 1)?.toLowerCase() || 'neutral' }`, ((_type, args) => new Modifiers.PokemonNatureChangeModifier(this, (args[0] as PlayerPokemon).id, this.nature)), ((pokemon: PlayerPokemon) => { if (pokemon.getNature() === this.nature) return PartyUiHandler.NoEffectMessage; return null; - }), `mint_${Utils.getEnumKeys(Stat).find(s => getNatureStatMultiplier(nature, Stat[s]) > 1)?.toLowerCase() || 'neutral' }`, 'mint'); + }), 'mint'); this.nature = nature; } + + get name(): string { + return i18next.t(`modifierType:ModifierType.PokemonNatureChangeModifierType.name`, { natureName: getNatureName(this.nature) }); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.PokemonNatureChangeModifierType.description`, { natureName: getNatureName(this.nature, true, true, true) }); + } } export class RememberMoveModifierType extends PokemonModifierType { - constructor(name: string, description: string, iconImage?: string, group?: string) { - super(name, description, (type, args) => new Modifiers.RememberMoveModifier(type, (args[0] as PlayerPokemon).id, (args[1] as integer)), + constructor(localeKey: string, iconImage: string, group?: string) { + super(localeKey, iconImage, (type, args) => new Modifiers.RememberMoveModifier(type, (args[0] as PlayerPokemon).id, (args[1] as integer)), (pokemon: PlayerPokemon) => { if (!pokemon.getLearnableLevelMoves().length) return PartyUiHandler.NoEffectMessage; return null; - }, iconImage, group); + }, group); } } export class DoubleBattleChanceBoosterModifierType extends ModifierType { public battleCount: integer; - constructor(name: string, battleCount: integer) { - super(name, `Doubles the chance of an encounter being a double battle for ${battleCount} battles`, (_type, _args) => new Modifiers.DoubleBattleChanceBoosterModifier(this, this.battleCount), - null, 'lure'); + constructor(localeKey: string, iconImage: string, battleCount: integer) { + super(localeKey, iconImage, (_type, _args) => new Modifiers.DoubleBattleChanceBoosterModifier(this, this.battleCount), 'lure'); this.battleCount = battleCount; } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.DoubleBattleChanceBoosterModifierType.description`, { battleCount: this.battleCount }); + } } export class TempBattleStatBoosterModifierType extends ModifierType implements GeneratedPersistentModifierType { public tempBattleStat: TempBattleStat; constructor(tempBattleStat: TempBattleStat) { - super(getTempBattleStatBoosterItemName(tempBattleStat), - `Increases the ${getTempBattleStatName(tempBattleStat)} of all party members by 1 stage for 5 battles`, - (_type, _args) => new Modifiers.TempBattleStatBoosterModifier(this, this.tempBattleStat), - getTempBattleStatBoosterItemName(tempBattleStat).replace(/\./g, '').replace(/[ ]/g, '_').toLowerCase()); + super('', getTempBattleStatBoosterItemName(tempBattleStat).replace(/\./g, '').replace(/[ ]/g, '_').toLowerCase(), + (_type, _args) => new Modifiers.TempBattleStatBoosterModifier(this, this.tempBattleStat)); this.tempBattleStat = tempBattleStat; } + get name(): string { + return i18next.t(`modifierType:TempBattleStatBoosterItem.${getTempBattleStatBoosterItemName(this.tempBattleStat).replace(/\./g, '').replace(/[ ]/g, '_').toLowerCase()}`); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.TempBattleStatBoosterModifierType.description`, { tempBattleStatName: getTempBattleStatName(this.tempBattleStat) }); + } + getPregenArgs(): any[] { return [ this.tempBattleStat ]; } @@ -360,13 +434,19 @@ export class BerryModifierType extends PokemonHeldItemModifierType implements Ge private berryType: BerryType; constructor(berryType: BerryType) { - super(getBerryName(berryType), getBerryEffectDescription(berryType), - (type, args) => new Modifiers.BerryModifier(type, (args[0] as Pokemon).id, berryType), - null, 'berry'); + super('', `${BerryType[berryType].toLowerCase()}_berry`, (type, args) => new Modifiers.BerryModifier(type, (args[0] as Pokemon).id, berryType), 'berry'); this.berryType = berryType; } + get name(): string { + return getBerryName(this.berryType); + } + + getDescription(scene: BattleScene): string { + return getBerryEffectDescription(this.berryType); + } + getPregenArgs(): any[] { return [ this.berryType ]; } @@ -418,29 +498,44 @@ export class AttackTypeBoosterModifierType extends PokemonHeldItemModifierType i public boostPercent: integer; constructor(moveType: Type, boostPercent: integer) { - super(getAttackTypeBoosterItemName(moveType), `Increases the power of a Pokémon's ${Utils.toReadableString(Type[moveType])}-type moves by 20%`, - (_type, args) => new Modifiers.AttackTypeBoosterModifier(this, (args[0] as Pokemon).id, moveType, boostPercent), - `${getAttackTypeBoosterItemName(moveType).replace(/[ \-]/g, '_').toLowerCase()}`); + super('', `${getAttackTypeBoosterItemName(moveType).replace(/[ \-]/g, '_').toLowerCase()}`, + (_type, args) => new Modifiers.AttackTypeBoosterModifier(this, (args[0] as Pokemon).id, moveType, boostPercent)); this.moveType = moveType; this.boostPercent = boostPercent; } + get name(): string { + return i18next.t(`modifierType:AttackTypeBoosterItem.${getAttackTypeBoosterItemName(this.moveType).replace(/[ \-]/g, '_').toLowerCase()}`); + } + + getDescription(scene: BattleScene): string { + // TODO: Need getTypeName? + return i18next.t(`modifierType:ModifierType.AttackTypeBoosterModifierType.description`, { moveType: Utils.toReadableString(Type[this.moveType]) }); + } + getPregenArgs(): any[] { return [ this.moveType ]; } } export class PokemonLevelIncrementModifierType extends PokemonModifierType { - constructor(name: string, iconImage?: string) { - super(name, `Increases a Pokémon\'s level by 1`, (_type, args) => new Modifiers.PokemonLevelIncrementModifier(this, (args[0] as PlayerPokemon).id), - (_pokemon: PlayerPokemon) => null, iconImage); + constructor(localeKey: string, iconImage: string) { + super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonLevelIncrementModifier(this, (args[0] as PlayerPokemon).id), (_pokemon: PlayerPokemon) => null); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.PokemonLevelIncrementModifierType.description`); } } export class AllPokemonLevelIncrementModifierType extends ModifierType { - constructor(name: string, iconImage?: string) { - super(name, `Increases all party members' level by 1`, (_type, _args) => new Modifiers.PokemonLevelIncrementModifier(this, -1), iconImage); + constructor(localeKey: string, iconImage: string) { + super(localeKey, iconImage, (_type, _args) => new Modifiers.PokemonLevelIncrementModifier(this, -1)); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.AllPokemonLevelIncrementModifierType.description`); } } @@ -462,73 +557,127 @@ function getBaseStatBoosterItemName(stat: Stat) { } export class PokemonBaseStatBoosterModifierType extends PokemonHeldItemModifierType implements GeneratedPersistentModifierType { + private localeName: string; private stat: Stat; - constructor(name: string, stat: Stat, _iconImage?: string) { - super(name, `Increases the holder's base ${getStatName(stat)} by 10%. The higher your IVs, the higher the stack limit.`, (_type, args) => new Modifiers.PokemonBaseStatModifier(this, (args[0] as Pokemon).id, this.stat)); + constructor(localeName: string, stat: Stat) { + super('', localeName.replace(/[ \-]/g, '_').toLowerCase(), (_type, args) => new Modifiers.PokemonBaseStatModifier(this, (args[0] as Pokemon).id, this.stat)); + this.localeName = localeName; this.stat = stat; } + get name(): string { + return i18next.t(`modifierType:BaseStatBoosterItem.${this.localeName.replace(/[ \-]/g, '_').toLowerCase()}`); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.PokemonBaseStatBoosterModifierType.description`, { statName: getStatName(this.stat) }); + } + getPregenArgs(): any[] { return [ this.stat ]; } } class AllPokemonFullHpRestoreModifierType extends ModifierType { - constructor(name: string, description?: string, newModifierFunc?: NewModifierFunc, iconImage?: string) { - super(name, description || `Restores 100% HP for all Pokémon`, newModifierFunc || ((_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100, false)), iconImage); + private descriptionKey: string; + + constructor(localeKey: string, iconImage: string, descriptionKey?: string, newModifierFunc?: NewModifierFunc) { + super(localeKey, iconImage, newModifierFunc || ((_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100, false))); + + this.descriptionKey = descriptionKey; + } + + getDescription(scene: BattleScene): string { + return i18next.t(`${this.descriptionKey || `modifierType:ModifierType.AllPokemonFullHpRestoreModifierType`}.description` as any); } } class AllPokemonFullReviveModifierType extends AllPokemonFullHpRestoreModifierType { - constructor(name: string, iconImage?: string) { - super(name, `Revives all fainted Pokémon, fully restoring HP`, (_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100, false, true), iconImage); + constructor(localeKey: string, iconImage: string) { + super(localeKey, iconImage, `modifierType:ModifierType.AllPokemonFullReviveModifierType`, (_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100, false, true)); } } export class MoneyRewardModifierType extends ModifierType { private moneyMultiplier: number; + private moneyMultiplierDescriptorKey: string; - constructor(name: string, moneyMultiplier: number, moneyMultiplierDescriptor: string, iconImage?: string) { - super(name, `Grants a ${moneyMultiplierDescriptor} amount of money (₽{AMOUNT})`, (_type, _args) => new Modifiers.MoneyRewardModifier(this, moneyMultiplier), iconImage, 'money', 'buy'); + constructor(localeKey: string, iconImage: string, moneyMultiplier: number, moneyMultiplierDescriptorKey: string) { + super(localeKey, iconImage, (_type, _args) => new Modifiers.MoneyRewardModifier(this, moneyMultiplier), 'money', 'buy'); this.moneyMultiplier = moneyMultiplier; + this.moneyMultiplierDescriptorKey = moneyMultiplierDescriptorKey; } getDescription(scene: BattleScene): string { - return this.description.replace('{AMOUNT}', scene.getWaveMoneyAmount(this.moneyMultiplier).toLocaleString('en-US')); + return i18next.t(`modifierType:ModifierType.MoneyRewardModifierType.description`, { + moneyMultiplier: i18next.t(this.moneyMultiplierDescriptorKey as any), + moneyAmount: scene.getWaveMoneyAmount(this.moneyMultiplier).toLocaleString('en-US'), + }); } } export class ExpBoosterModifierType extends ModifierType { - constructor(name: string, boostPercent: integer, iconImage?: string) { - super(name, `Increases gain of EXP. Points by ${boostPercent}%`, () => new Modifiers.ExpBoosterModifier(this, boostPercent), iconImage); + private boostPercent: integer; + + constructor(localeKey: string, iconImage: string, boostPercent: integer) { + super(localeKey, iconImage, () => new Modifiers.ExpBoosterModifier(this, boostPercent)); + + this.boostPercent = boostPercent; + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.ExpBoosterModifierType.description`, { boostPercent: this.boostPercent }); } } export class PokemonExpBoosterModifierType extends PokemonHeldItemModifierType { - constructor(name: string, boostPercent: integer, iconImage?: string) { - super(name, `Increases the holder's gain of EXP. Points by ${boostPercent}%`, (_type, args) => new Modifiers.PokemonExpBoosterModifier(this, (args[0] as Pokemon).id, boostPercent), - iconImage); + private boostPercent: integer; + + constructor(localeKey: string, iconImage: string, boostPercent: integer) { + super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonExpBoosterModifier(this, (args[0] as Pokemon).id, boostPercent)); + + this.boostPercent = boostPercent; + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.PokemonExpBoosterModifierType.description`, { boostPercent: this.boostPercent }); } } export class PokemonFriendshipBoosterModifierType extends PokemonHeldItemModifierType { - constructor(name: string, iconImage?: string) { - super(name,'Increases friendship gain per victory by 50%', (_type, args) => new Modifiers.PokemonFriendshipBoosterModifier(this, (args[0] as Pokemon).id), iconImage); + constructor(localeKey: string, iconImage: string) { + super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonFriendshipBoosterModifier(this, (args[0] as Pokemon).id)); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.PokemonFriendshipBoosterModifierType.description`); } } export class PokemonMoveAccuracyBoosterModifierType extends PokemonHeldItemModifierType { - constructor(name: string, amount: integer, iconImage?: string, group?: string, soundName?: string) { - super(name, `Increases move accuracy by ${amount} (maximum 100)`, (_type, args) => new Modifiers.PokemonMoveAccuracyBoosterModifier(this, (args[0] as Pokemon).id, amount), iconImage, group, soundName); + private amount: integer; + + constructor(localeKey: string, iconImage: string, amount: integer, group?: string, soundName?: string) { + super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonMoveAccuracyBoosterModifier(this, (args[0] as Pokemon).id, amount), group, soundName); + + this.amount = amount; + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.PokemonMoveAccuracyBoosterModifierType.description`, { accuracyAmount: this.amount }); } } export class PokemonMultiHitModifierType extends PokemonHeldItemModifierType { - constructor(name: string, iconImage?: string) { - super(name, `Attacks hit one additional time at the cost of a 60/75/82.5% power reduction per stack respectively.`, (type, args) => new Modifiers.PokemonMultiHitModifier(type as PokemonMultiHitModifierType, (args[0] as Pokemon).id), iconImage); + constructor(localeKey: string, iconImage: string) { + super(localeKey, iconImage, (type, args) => new Modifiers.PokemonMultiHitModifier(type as PokemonMultiHitModifierType, (args[0] as Pokemon).id)); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.PokemonMultiHitModifierType.description`); } } @@ -536,22 +685,33 @@ export class TmModifierType extends PokemonModifierType { public moveId: Moves; constructor(moveId: Moves) { - super(`TM${Utils.padInt(Object.keys(tmSpecies).indexOf(moveId.toString()) + 1, 3)} - ${allMoves[moveId].name}`, `Teach ${allMoves[moveId].name} to a Pokémon`, (_type, args) => new Modifiers.TmModifier(this, (args[0] as PlayerPokemon).id), + super('', `tm_${Type[allMoves[moveId].type].toLowerCase()}`, (_type, args) => new Modifiers.TmModifier(this, (args[0] as PlayerPokemon).id), (pokemon: PlayerPokemon) => { if (pokemon.compatibleTms.indexOf(moveId) === -1 || pokemon.getMoveset().filter(m => m?.moveId === moveId).length) return PartyUiHandler.NoEffectMessage; return null; - }, `tm_${Type[allMoves[moveId].type].toLowerCase()}`, 'tm'); + }, 'tm'); this.moveId = moveId; } + + get name(): string { + return i18next.t(`modifierType:ModifierType.TmModifierType.name`, { + moveId: Utils.padInt(Object.keys(tmSpecies).indexOf(this.moveId.toString()) + 1, 3), + moveName: allMoves[this.moveId].name, + }); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.TmModifierType.description`, { moveName: allMoves[this.moveId].name }); + } } export class EvolutionItemModifierType extends PokemonModifierType implements GeneratedPersistentModifierType { public evolutionItem: EvolutionItem; constructor(evolutionItem: EvolutionItem) { - super(Utils.toReadableString(EvolutionItem[evolutionItem]), `Causes certain Pokémon to evolve`, (_type, args) => new Modifiers.EvolutionItemModifier(this, (args[0] as PlayerPokemon).id), + super('', EvolutionItem[evolutionItem].toLowerCase(), (_type, args) => new Modifiers.EvolutionItemModifier(this, (args[0] as PlayerPokemon).id), (pokemon: PlayerPokemon) => { if (pokemonEvolutions.hasOwnProperty(pokemon.species.speciesId) && pokemonEvolutions[pokemon.species.speciesId].filter(e => e.item === this.evolutionItem && (!e.condition || e.condition.predicate(pokemon))).length && (pokemon.getFormKey() !== SpeciesFormKey.GIGANTAMAX)) @@ -561,10 +721,18 @@ export class EvolutionItemModifierType extends PokemonModifierType implements Ge return null; return PartyUiHandler.NoEffectMessage; - }, EvolutionItem[evolutionItem].toLowerCase()); + }); this.evolutionItem = evolutionItem; } + + get name(): string { + return i18next.t(`modifierType:EvolutionItem.${EvolutionItem[this.evolutionItem]}`); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.EvolutionItemModifierType.description`); + } getPregenArgs(): any[] { return [ this.evolutionItem ]; @@ -575,31 +743,43 @@ export class FormChangeItemModifierType extends PokemonModifierType implements G public formChangeItem: FormChangeItem; constructor(formChangeItem: FormChangeItem) { - super(Utils.toReadableString(FormChangeItem[formChangeItem]), `Causes certain Pokémon to change form`, (_type, args) => new Modifiers.PokemonFormChangeItemModifier(this, (args[0] as PlayerPokemon).id, formChangeItem, true), + super('', FormChangeItem[formChangeItem].toLowerCase(), (_type, args) => new Modifiers.PokemonFormChangeItemModifier(this, (args[0] as PlayerPokemon).id, formChangeItem, true), (pokemon: PlayerPokemon) => { if (pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId) && !!pokemonFormChanges[pokemon.species.speciesId].find(fc => fc.trigger.hasTriggerType(SpeciesFormChangeItemTrigger) && (fc.trigger as SpeciesFormChangeItemTrigger).item === this.formChangeItem)) return null; return PartyUiHandler.NoEffectMessage; - }, FormChangeItem[formChangeItem].toLowerCase()); + }); this.formChangeItem = formChangeItem; } + get name(): string { + return i18next.t(`modifierType:FormChangeItem.${FormChangeItem[this.formChangeItem]}`); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.FormChangeItemModifierType.description`); + } + getPregenArgs(): any[] { return [ this.formChangeItem ]; } } export class FusePokemonModifierType extends PokemonModifierType { - constructor(name: string, iconImage?: string) { - super(name, 'Combines two Pokémon (transfers Ability, splits base stats and types, shares move pool)', (_type, args) => new Modifiers.FusePokemonModifier(this, (args[0] as PlayerPokemon).id, (args[1] as PlayerPokemon).id), + constructor(localeKey: string, iconImage: string) { + super(localeKey, iconImage, (_type, args) => new Modifiers.FusePokemonModifier(this, (args[0] as PlayerPokemon).id, (args[1] as PlayerPokemon).id), (pokemon: PlayerPokemon) => { if (pokemon.isFusion()) return PartyUiHandler.NoEffectMessage; return null; - }, iconImage); + }); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.FusePokemonModifierType.description`); } } @@ -712,37 +892,78 @@ export class TerastallizeModifierType extends PokemonHeldItemModifierType implem private teraType: Type; constructor(teraType: Type) { - super(`${Utils.toReadableString(Type[teraType])} Tera Shard`, `${Utils.toReadableString(Type[teraType])} Terastallizes the holder for up to 10 battles`, (type, args) => new Modifiers.TerastallizeModifier(type as TerastallizeModifierType, (args[0] as Pokemon).id, teraType), null, 'tera_shard'); + super('', `${Type[teraType].toLowerCase()}_tera_shard`, (type, args) => new Modifiers.TerastallizeModifier(type as TerastallizeModifierType, (args[0] as Pokemon).id, teraType), 'tera_shard'); this.teraType = teraType; } + get name(): string { + return i18next.t(`modifierType:ModifierType.TerastallizeModifierType.name`, { teraType: i18next.t(`modifierType:TeraType.${Type[this.teraType]}`) }); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.TerastallizeModifierType.description`, { teraType: i18next.t(`modifierType:TeraType.${Type[this.teraType]}`) }); + } + getPregenArgs(): any[] { return [ this.teraType ]; } } export class ContactHeldItemTransferChanceModifierType extends PokemonHeldItemModifierType { - constructor(name: string, chancePercent: integer, iconImage?: string, group?: string, soundName?: string) { - super(name, `Upon attacking, there is a ${chancePercent}% chance the foe's held item will be stolen.`, (type, args) => new Modifiers.ContactHeldItemTransferChanceModifier(type, (args[0] as Pokemon).id, chancePercent), iconImage, group, soundName); + private chancePercent: integer; + + constructor(localeKey: string, iconImage: string, chancePercent: integer, group?: string, soundName?: string) { + super(localeKey, iconImage, (type, args) => new Modifiers.ContactHeldItemTransferChanceModifier(type, (args[0] as Pokemon).id, chancePercent), group, soundName); + + this.chancePercent = chancePercent; + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.ContactHeldItemTransferChanceModifierType.description`, { chancePercent: this.chancePercent }); } } export class TurnHeldItemTransferModifierType extends PokemonHeldItemModifierType { - constructor(name: string, iconImage?: string, group?: string, soundName?: string) { - super(name, 'Every turn, the holder acquires one held item from the foe.', (type, args) => new Modifiers.TurnHeldItemTransferModifier(type, (args[0] as Pokemon).id), iconImage, group, soundName); + constructor(localeKey: string, iconImage: string, group?: string, soundName?: string) { + super(localeKey, iconImage, (type, args) => new Modifiers.TurnHeldItemTransferModifier(type, (args[0] as Pokemon).id), group, soundName); + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.TurnHeldItemTransferModifierType.description`); } } export class EnemyAttackStatusEffectChanceModifierType extends ModifierType { - constructor(name: string, chancePercent: integer, effect: StatusEffect, iconImage?: string) { - super(name, `Adds a ${chancePercent}% chance to inflict ${getStatusEffectDescriptor(effect)} with attack moves`, (type, args) => new Modifiers.EnemyAttackStatusEffectChanceModifier(type, effect, chancePercent), iconImage, 'enemy_status_chance') + private chancePercent: integer; + private effect: StatusEffect; + + constructor(localeKey: string, iconImage: string, chancePercent: integer, effect: StatusEffect) { + super(localeKey, iconImage, (type, args) => new Modifiers.EnemyAttackStatusEffectChanceModifier(type, effect, chancePercent), 'enemy_status_chance') + + this.chancePercent = chancePercent; + this.effect = effect; + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.EnemyAttackStatusEffectChanceModifierType.description`, { + chancePercent: this.chancePercent, + statusEffect: getStatusEffectDescriptor(this.effect), + }); } } export class EnemyEndureChanceModifierType extends ModifierType { - constructor(name: string, chancePercent: number, iconImage?: string) { - super(name, `Adds a ${chancePercent}% chance of enduring a hit`, (type, _args) => new Modifiers.EnemyEndureChanceModifier(type, chancePercent), iconImage, 'enemy_endure'); + private chancePercent: number; + + constructor(localeKey: string, iconImage: string, chancePercent: number) { + super(localeKey, iconImage, (type, _args) => new Modifiers.EnemyEndureChanceModifier(type, chancePercent), 'enemy_endure'); + + this.chancePercent = chancePercent; + } + + getDescription(scene: BattleScene): string { + return i18next.t(`modifierType:ModifierType.EnemyEndureChanceModifierType.description`, { chancePercent: this.chancePercent }); } } @@ -767,57 +988,56 @@ class WeightedModifierType { } export const modifierTypes = { - POKEBALL: () => new AddPokeballModifierType(PokeballType.POKEBALL, 5, 'pb'), - GREAT_BALL: () => new AddPokeballModifierType(PokeballType.GREAT_BALL, 5, 'gb'), - ULTRA_BALL: () => new AddPokeballModifierType(PokeballType.ULTRA_BALL, 5, 'ub'), - ROGUE_BALL: () => new AddPokeballModifierType(PokeballType.ROGUE_BALL, 5, 'rb'), - MASTER_BALL: () => new AddPokeballModifierType(PokeballType.MASTER_BALL, 1, 'mb'), + POKEBALL: () => new AddPokeballModifierType('pb', PokeballType.POKEBALL, 5), + GREAT_BALL: () => new AddPokeballModifierType('gb', PokeballType.GREAT_BALL, 5), + ULTRA_BALL: () => new AddPokeballModifierType('ub', PokeballType.ULTRA_BALL, 5), + ROGUE_BALL: () => new AddPokeballModifierType('rb', PokeballType.ROGUE_BALL, 5), + MASTER_BALL: () => new AddPokeballModifierType('mb', PokeballType.MASTER_BALL, 1), - RARE_CANDY: () => new PokemonLevelIncrementModifierType('Rare Candy'), - RARER_CANDY: () => new AllPokemonLevelIncrementModifierType('Rarer Candy'), + RARE_CANDY: () => new PokemonLevelIncrementModifierType(`modifierType:ModifierType.RARE_CANDY`, 'rare_candy'), + RARER_CANDY: () => new AllPokemonLevelIncrementModifierType(`modifierType:ModifierType.RARER_CANDY`, 'rarer_candy'), EVOLUTION_ITEM: () => new EvolutionItemModifierTypeGenerator(false), RARE_EVOLUTION_ITEM: () => new EvolutionItemModifierTypeGenerator(true), FORM_CHANGE_ITEM: () => new FormChangeItemModifierTypeGenerator(), - MEGA_BRACELET: () => new ModifierType('Mega Bracelet', 'Mega Stones become available.', (type, _args) => new Modifiers.MegaEvolutionAccessModifier(type)), - DYNAMAX_BAND: () => new ModifierType('Dynamax Band', 'Max Mushrooms become available.', (type, _args) => new Modifiers.GigantamaxAccessModifier(type)), - TERA_ORB: () => new ModifierType('Tera Orb', 'Tera Shards become available.', (type, _args) => new Modifiers.TerastallizeAccessModifier(type)), + MEGA_BRACELET: () => new ModifierType(`modifierType:ModifierType.MEGA_BRACELET`, 'mega_bracelet', (type, _args) => new Modifiers.MegaEvolutionAccessModifier(type)), + DYNAMAX_BAND: () => new ModifierType(`modifierType:ModifierType.DYNAMAX_BAND`, 'dynamax_band', (type, _args) => new Modifiers.GigantamaxAccessModifier(type)), + TERA_ORB: () => new ModifierType(`modifierType:ModifierType.TERA_ORB`, 'tera_orb', (type, _args) => new Modifiers.TerastallizeAccessModifier(type)), - MAP: () => new ModifierType('Map', 'Allows you to choose your destination at a crossroads', (type, _args) => new Modifiers.MapModifier(type)), + MAP: () => new ModifierType(`modifierType:ModifierType.MAP`, 'map', (type, _args) => new Modifiers.MapModifier(type)), - POTION: () => new PokemonHpRestoreModifierType('Potion', 20, 10), - SUPER_POTION: () => new PokemonHpRestoreModifierType('Super Potion', 50, 25), - HYPER_POTION: () => new PokemonHpRestoreModifierType('Hyper Potion', 200, 50), - MAX_POTION: () => new PokemonHpRestoreModifierType('Max Potion', 0, 100), - FULL_RESTORE: () => new PokemonHpRestoreModifierType('Full Restore', 0, 100, true), + POTION: () => new PokemonHpRestoreModifierType(`modifierType:ModifierType.POTION`, 'potion', 20, 10), + SUPER_POTION: () => new PokemonHpRestoreModifierType(`modifierType:ModifierType.SUPER_POTION`, 'super_potion', 50, 25), + HYPER_POTION: () => new PokemonHpRestoreModifierType(`modifierType:ModifierType.HYPER_POTION`, 'hyper_potion', 200, 50), + MAX_POTION: () => new PokemonHpRestoreModifierType(`modifierType:ModifierType.MAX_POTION`, 'max_potion', 0, 100), + FULL_RESTORE: () => new PokemonHpRestoreModifierType(`modifierType:ModifierType.FULL_RESTORE`, 'full_restore', 0, 100, true), - REVIVE: () => new PokemonReviveModifierType('Revive', 50), - MAX_REVIVE: () => new PokemonReviveModifierType('Max Revive', 100), + REVIVE: () => new PokemonReviveModifierType(`modifierType:ModifierType.REVIVE`, 'revive', 50), + MAX_REVIVE: () => new PokemonReviveModifierType(`modifierType:ModifierType.MAX_REVIVE`, 'max_revive', 100), - FULL_HEAL: () => new PokemonStatusHealModifierType('Full Heal'), + FULL_HEAL: () => new PokemonStatusHealModifierType(`modifierType:ModifierType.FULL_HEAL`, 'full_heal'), - SACRED_ASH: () => new AllPokemonFullReviveModifierType('Sacred Ash'), + SACRED_ASH: () => new AllPokemonFullReviveModifierType(`modifierType:ModifierType.SACRED_ASH`, 'sacred_ash'), - REVIVER_SEED: () => new PokemonHeldItemModifierType('Reviver Seed', 'Revives the holder for 1/2 HP upon fainting', - (type, args) => new Modifiers.PokemonInstantReviveModifier(type, (args[0] as Pokemon).id)), + REVIVER_SEED: () => new PokemonHeldItemModifierType(`modifierType:ModifierType.REVIVER_SEED`, 'reviver_seed', (type, args) => new Modifiers.PokemonInstantReviveModifier(type, (args[0] as Pokemon).id)), - ETHER: () => new PokemonPpRestoreModifierType('Ether', 10), - MAX_ETHER: () => new PokemonPpRestoreModifierType('Max Ether', -1), + ETHER: () => new PokemonPpRestoreModifierType(`modifierType:ModifierType.ETHER`, 'ether', 10), + MAX_ETHER: () => new PokemonPpRestoreModifierType(`modifierType:ModifierType.MAX_ETHER`, 'max_ether', -1), - ELIXIR: () => new PokemonAllMovePpRestoreModifierType('Elixir', 10), - MAX_ELIXIR: () => new PokemonAllMovePpRestoreModifierType('Max Elixir', -1), + ELIXIR: () => new PokemonAllMovePpRestoreModifierType(`modifierType:ModifierType.ELIXIR`, 'elixir', 10), + MAX_ELIXIR: () => new PokemonAllMovePpRestoreModifierType(`modifierType:ModifierType.MAX_ELIXIR`, 'max_elixir', -1), - PP_UP: () => new PokemonPpUpModifierType('PP Up', 1), - PP_MAX: () => new PokemonPpUpModifierType('PP Max', 3), + PP_UP: () => new PokemonPpUpModifierType(`modifierType:ModifierType.PP_UP`, 'pp_up', 1), + PP_MAX: () => new PokemonPpUpModifierType(`modifierType:ModifierType.PP_MAX`, 'pp_max', 3), /*REPEL: () => new DoubleBattleChanceBoosterModifierType('Repel', 5), SUPER_REPEL: () => new DoubleBattleChanceBoosterModifierType('Super Repel', 10), MAX_REPEL: () => new DoubleBattleChanceBoosterModifierType('Max Repel', 25),*/ - LURE: () => new DoubleBattleChanceBoosterModifierType('Lure', 5), - SUPER_LURE: () => new DoubleBattleChanceBoosterModifierType('Super Lure', 10), - MAX_LURE: () => new DoubleBattleChanceBoosterModifierType('Max Lure', 25), + LURE: () => new DoubleBattleChanceBoosterModifierType(`modifierType:ModifierType.LURE`, 'lure', 5), + SUPER_LURE: () => new DoubleBattleChanceBoosterModifierType(`modifierType:ModifierType.SUPER_LURE`, 'super_lure', 10), + MAX_LURE: () => new DoubleBattleChanceBoosterModifierType(`modifierType:ModifierType.MAX_LURE`, 'max_lure', 25), TEMP_STAT_BOOSTER: () => new ModifierTypeGenerator((party: Pokemon[], pregenArgs?: any[]) => { if (pregenArgs) @@ -879,91 +1099,82 @@ export const modifierTypes = { TM_GREAT: () => new TmModifierTypeGenerator(ModifierTier.GREAT), TM_ULTRA: () => new TmModifierTypeGenerator(ModifierTier.ULTRA), - MEMORY_MUSHROOM: () => new RememberMoveModifierType('Memory Mushroom', 'Recall one Pokémon\'s forgotten move', 'big_mushroom'), + MEMORY_MUSHROOM: () => new RememberMoveModifierType(`modifierType:ModifierType.MEMORY_MUSHROOM`, 'big_mushroom'), - EXP_SHARE: () => new ModifierType('EXP. All', 'Non-participants receive 20% of a single participant\'s EXP. Points.', - (type, _args) => new Modifiers.ExpShareModifier(type), 'exp_share'), - EXP_BALANCE: () => new ModifierType('EXP. Balance', 'Weighs EXP. Points received from battles towards lower-leveled party members', - (type, _args) => new Modifiers.ExpBalanceModifier(type)), + EXP_SHARE: () => new ModifierType(`modifierType:ModifierType.EXP_SHARE`, 'exp_share', (type, _args) => new Modifiers.ExpShareModifier(type)), + EXP_BALANCE: () => new ModifierType(`modifierType:ModifierType.EXP_BALANCE`, 'exp_balance', (type, _args) => new Modifiers.ExpBalanceModifier(type)), - OVAL_CHARM: () => new ModifierType('Oval Charm', 'When multiple Pokémon participate in a battle, each gets an extra 10% of the total EXP.', - (type, _args) => new Modifiers.MultipleParticipantExpBonusModifier(type)), + OVAL_CHARM: () => new ModifierType(`modifierType:ModifierType.OVAL_CHARM`, 'oval_charm', (type, _args) => new Modifiers.MultipleParticipantExpBonusModifier(type)), - EXP_CHARM: () => new ExpBoosterModifierType('EXP. Charm', 25), - SUPER_EXP_CHARM: () => new ExpBoosterModifierType('Super EXP. Charm', 60), - GOLDEN_EXP_CHARM: () => new ExpBoosterModifierType('Golden EXP. Charm', 100), + EXP_CHARM: () => new ExpBoosterModifierType(`modifierType:ModifierType.EXP_CHARM`, 'exp_charm', 25), + SUPER_EXP_CHARM: () => new ExpBoosterModifierType(`modifierType:ModifierType.SUPER_EXP_CHARM`, 'super_exp_charm', 60), + GOLDEN_EXP_CHARM: () => new ExpBoosterModifierType(`modifierType:ModifierType.GOLDEN_EXP_CHARM`, 'golden_exp_charm', 100), - LUCKY_EGG: () => new PokemonExpBoosterModifierType('Lucky Egg', 40), - GOLDEN_EGG: () => new PokemonExpBoosterModifierType('Golden Egg', 100), + LUCKY_EGG: () => new PokemonExpBoosterModifierType(`modifierType:ModifierType.LUCKY_EGG`, 'lucky_egg', 40), + GOLDEN_EGG: () => new PokemonExpBoosterModifierType(`modifierType:ModifierType.GOLDEN_EGG`, 'golden_egg', 100), - SOOTHE_BELL: () => new PokemonFriendshipBoosterModifierType('Soothe Bell'), + SOOTHE_BELL: () => new PokemonFriendshipBoosterModifierType(`modifierType:ModifierType.SOOTHE_BELL`, 'soothe_bell'), - SOUL_DEW: () => new PokemonHeldItemModifierType('Soul Dew', 'Increases the influence of a Pokémon\'s nature on its stats by 10% (additive)', (type, args) => new Modifiers.PokemonNatureWeightModifier(type, (args[0] as Pokemon).id)), + SOUL_DEW: () => new PokemonHeldItemModifierType(`modifierType:ModifierType.SOUL_DEW`, 'soul_dew', (type, args) => new Modifiers.PokemonNatureWeightModifier(type, (args[0] as Pokemon).id)), - NUGGET: () => new MoneyRewardModifierType('Nugget', 1, 'small'), - BIG_NUGGET: () => new MoneyRewardModifierType('Big Nugget', 2.5, 'moderate'), - RELIC_GOLD: () => new MoneyRewardModifierType('Relic Gold', 10, 'large'), + NUGGET: () => new MoneyRewardModifierType(`modifierType:ModifierType.NUGGET`, 'nugget', 1, `modifierType:ModifierType.MoneyRewardModifierType.extra.small`), + BIG_NUGGET: () => new MoneyRewardModifierType(`modifierType:ModifierType.BIG_NUGGET`, 'big_nugget', 2.5, `modifierType:ModifierType.MoneyRewardModifierType.extra.moderate`), + RELIC_GOLD: () => new MoneyRewardModifierType(`modifierType:ModifierType.RELIC_GOLD`, 'relic_gold', 10, `modifierType:ModifierType.MoneyRewardModifierType.extra.large`), - AMULET_COIN: () => new ModifierType('Amulet Coin', 'Increases money rewards by 20%', (type, _args) => new Modifiers.MoneyMultiplierModifier(type)), - GOLDEN_PUNCH: () => new PokemonHeldItemModifierType('Golden Punch', 'Grants 50% of damage inflicted as money', (type, args) => new Modifiers.DamageMoneyRewardModifier(type, (args[0] as Pokemon).id)), - COIN_CASE: () => new ModifierType('Coin Case', 'After every 10th battle, receive 10% of your money in interest.', (type, _args) => new Modifiers.MoneyInterestModifier(type)), + AMULET_COIN: () => new ModifierType(`modifierType:ModifierType.AMULET_COIN`, 'amulet_coin', (type, _args) => new Modifiers.MoneyMultiplierModifier(type)), + GOLDEN_PUNCH: () => new PokemonHeldItemModifierType(`modifierType:ModifierType.GOLDEN_PUNCH`, 'golden_punch', (type, args) => new Modifiers.DamageMoneyRewardModifier(type, (args[0] as Pokemon).id)), + COIN_CASE: () => new ModifierType(`modifierType:ModifierType.COIN_CASE`, 'coin_case', (type, _args) => new Modifiers.MoneyInterestModifier(type)), - LOCK_CAPSULE: () => new ModifierType('Lock Capsule', 'Allows you to lock item rarities when rerolling items', (type, _args) => new Modifiers.LockModifierTiersModifier(type), 'lock_capsule'), + LOCK_CAPSULE: () => new ModifierType(`modifierType:ModifierType.LOCK_CAPSULE`, 'lock_capsule', (type, _args) => new Modifiers.LockModifierTiersModifier(type)), - GRIP_CLAW: () => new ContactHeldItemTransferChanceModifierType('Grip Claw', 10), - WIDE_LENS: () => new PokemonMoveAccuracyBoosterModifierType('Wide Lens', 5, 'wide_lens'), + GRIP_CLAW: () => new ContactHeldItemTransferChanceModifierType(`modifierType:ModifierType.GRIP_CLAW`, 'grip_claw', 10), + WIDE_LENS: () => new PokemonMoveAccuracyBoosterModifierType(`modifierType:ModifierType.WIDE_LENS`, 'wide_lens', 5), - MULTI_LENS: () => new PokemonMultiHitModifierType('Multi Lens', 'zoom_lens'), + MULTI_LENS: () => new PokemonMultiHitModifierType(`modifierType:ModifierType.MULTI_LENS`, 'zoom_lens'), - HEALING_CHARM: () => new ModifierType('Healing Charm', 'Increases the effectiveness of HP restoring moves and items by 10% (excludes Revives)', - (type, _args) => new Modifiers.HealingBoosterModifier(type, 1.1), 'healing_charm'), - CANDY_JAR: () => new ModifierType('Candy Jar', 'Increases the number of levels added by Rare Candy items by 1', (type, _args) => new Modifiers.LevelIncrementBoosterModifier(type)), + HEALING_CHARM: () => new ModifierType(`modifierType:ModifierType.HEALING_CHARM`, 'healing_charm', (type, _args) => new Modifiers.HealingBoosterModifier(type, 1.1)), + CANDY_JAR: () => new ModifierType(`modifierType:ModifierType.CANDY_JAR`, 'candy_jar', (type, _args) => new Modifiers.LevelIncrementBoosterModifier(type)), - BERRY_POUCH: () => new ModifierType('Berry Pouch', 'Adds a 25% chance that a used berry will not be consumed', - (type, _args) => new Modifiers.PreserveBerryModifier(type)), + BERRY_POUCH: () => new ModifierType(`modifierType:ModifierType.BERRY_POUCH`, 'berry_pouch', (type, _args) => new Modifiers.PreserveBerryModifier(type)), - FOCUS_BAND: () => new PokemonHeldItemModifierType('Focus Band', 'Adds a 10% chance to survive with 1 HP after being damaged enough to faint', - (type, args) => new Modifiers.SurviveDamageModifier(type, (args[0] as Pokemon).id)), + FOCUS_BAND: () => new PokemonHeldItemModifierType(`modifierType:ModifierType.FOCUS_BAND`, 'focus_band', (type, args) => new Modifiers.SurviveDamageModifier(type, (args[0] as Pokemon).id)), - KINGS_ROCK: () => new PokemonHeldItemModifierType('King\'s Rock', 'Adds a 10% chance an attack move will cause the opponent to flinch', - (type, args) => new Modifiers.FlinchChanceModifier(type, (args[0] as Pokemon).id)), + QUICK_CLAW: () => new PokemonHeldItemModifierType(`modifierType:ModifierType.QUICK_CLAW`, 'quick_claw', (type, args) => new Modifiers.BypassSpeedChanceModifier(type, (args[0] as Pokemon).id)), - LEFTOVERS: () => new PokemonHeldItemModifierType('Leftovers', 'Heals 1/16 of a Pokémon\'s maximum HP every turn', - (type, args) => new Modifiers.TurnHealModifier(type, (args[0] as Pokemon).id)), - SHELL_BELL: () => new PokemonHeldItemModifierType('Shell Bell', 'Heals 1/8 of a Pokémon\'s dealt damage', - (type, args) => new Modifiers.HitHealModifier(type, (args[0] as Pokemon).id)), + KINGS_ROCK: () => new PokemonHeldItemModifierType(`modifierType:ModifierType.KINGS_ROCK`, 'kings_rock', (type, args) => new Modifiers.FlinchChanceModifier(type, (args[0] as Pokemon).id)), - BATON: () => new PokemonHeldItemModifierType('Baton', 'Allows passing along effects when switching Pokémon, which also bypasses traps', - (type, args) => new Modifiers.SwitchEffectTransferModifier(type, (args[0] as Pokemon).id), 'stick'), + LEFTOVERS: () => new PokemonHeldItemModifierType(`modifierType:ModifierType.LEFTOVERS`, 'leftovers', (type, args) => new Modifiers.TurnHealModifier(type, (args[0] as Pokemon).id)), + SHELL_BELL: () => new PokemonHeldItemModifierType(`modifierType:ModifierType.SHELL_BELL`, 'shell_bell', (type, args) => new Modifiers.HitHealModifier(type, (args[0] as Pokemon).id)), - SHINY_CHARM: () => new ModifierType('Shiny Charm', 'Dramatically increases the chance of a wild Pokémon being Shiny', (type, _args) => new Modifiers.ShinyRateBoosterModifier(type)), - ABILITY_CHARM: () => new ModifierType('Ability Charm', 'Dramatically increases the chance of a wild Pokémon having a Hidden Ability', (type, _args) => new Modifiers.HiddenAbilityRateBoosterModifier(type)), + BATON: () => new PokemonHeldItemModifierType(`modifierType:ModifierType.BATON`, 'stick', (type, args) => new Modifiers.SwitchEffectTransferModifier(type, (args[0] as Pokemon).id)), - IV_SCANNER: () => new ModifierType('IV Scanner', 'Allows scanning the IVs of wild Pokémon. 2 IVs are revealed per stack. The best IVs are shown first.', (type, _args) => new Modifiers.IvScannerModifier(type), 'scanner'), + SHINY_CHARM: () => new ModifierType(`modifierType:ModifierType.SHINY_CHARM`, 'shiny_charm', (type, _args) => new Modifiers.ShinyRateBoosterModifier(type)), + ABILITY_CHARM: () => new ModifierType(`modifierType:ModifierType.ABILITY_CHARM`, 'ability_charm', (type, _args) => new Modifiers.HiddenAbilityRateBoosterModifier(type)), - DNA_SPLICERS: () => new FusePokemonModifierType('DNA Splicers'), + IV_SCANNER: () => new ModifierType(`modifierType:ModifierType.IV_SCANNER`, 'scanner', (type, _args) => new Modifiers.IvScannerModifier(type)), - MINI_BLACK_HOLE: () => new TurnHeldItemTransferModifierType('Mini Black Hole'), + DNA_SPLICERS: () => new FusePokemonModifierType(`modifierType:ModifierType.DNA_SPLICERS`, 'dna_splicers'), + + MINI_BLACK_HOLE: () => new TurnHeldItemTransferModifierType(`modifierType:ModifierType.MINI_BLACK_HOLE`, 'mini_black_hole'), VOUCHER: () => new AddVoucherModifierType(VoucherType.REGULAR, 1), VOUCHER_PLUS: () => new AddVoucherModifierType(VoucherType.PLUS, 1), VOUCHER_PREMIUM: () => new AddVoucherModifierType(VoucherType.PREMIUM, 1), - GOLDEN_POKEBALL: () => new ModifierType(`Golden ${getPokeballName(PokeballType.POKEBALL)}`, 'Adds 1 extra item option at the end of every battle', - (type, _args) => new Modifiers.ExtraModifierModifier(type), 'pb_gold', null, 'pb_bounce_1'), + GOLDEN_POKEBALL: () => new ModifierType(`modifierType:ModifierType.GOLDEN_POKEBALL`, 'pb_gold', (type, _args) => new Modifiers.ExtraModifierModifier(type), null, 'pb_bounce_1'), - ENEMY_DAMAGE_BOOSTER: () => new ModifierType('Damage Token', 'Increases damage by 5%', (type, _args) => new Modifiers.EnemyDamageBoosterModifier(type, 5), 'wl_item_drop'), - ENEMY_DAMAGE_REDUCTION: () => new ModifierType('Protection Token', 'Reduces incoming damage by 2.5%', (type, _args) => new Modifiers.EnemyDamageReducerModifier(type, 2.5), 'wl_guard_spec'), + ENEMY_DAMAGE_BOOSTER: () => new ModifierType(`modifierType:ModifierType.ENEMY_DAMAGE_BOOSTER`, 'wl_item_drop', (type, _args) => new Modifiers.EnemyDamageBoosterModifier(type, 5)), + ENEMY_DAMAGE_REDUCTION: () => new ModifierType(`modifierType:ModifierType.ENEMY_DAMAGE_REDUCTION`, 'wl_guard_spec', (type, _args) => new Modifiers.EnemyDamageReducerModifier(type, 2.5)), //ENEMY_SUPER_EFFECT_BOOSTER: () => new ModifierType('Type Advantage Token', 'Increases damage of super effective attacks by 30%', (type, _args) => new Modifiers.EnemySuperEffectiveDamageBoosterModifier(type, 30), 'wl_custom_super_effective'), - ENEMY_HEAL: () => new ModifierType('Recovery Token', 'Heals 2% of max HP every turn', (type, _args) => new Modifiers.EnemyTurnHealModifier(type, 2), 'wl_potion'), - ENEMY_ATTACK_POISON_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType('Poison Token', 10, StatusEffect.POISON, 'wl_antidote'), - ENEMY_ATTACK_PARALYZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType('Paralyze Token', 10, StatusEffect.PARALYSIS, 'wl_paralyze_heal'), - ENEMY_ATTACK_SLEEP_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType('Sleep Token', 10, StatusEffect.SLEEP, 'wl_awakening'), - ENEMY_ATTACK_FREEZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType('Freeze Token', 10, StatusEffect.FREEZE, 'wl_ice_heal'), - ENEMY_ATTACK_BURN_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType('Burn Token', 10, StatusEffect.BURN, 'wl_burn_heal'), - ENEMY_STATUS_EFFECT_HEAL_CHANCE: () => new ModifierType('Full Heal Token', 'Adds a 10% chance every turn to heal a status condition', (type, _args) => new Modifiers.EnemyStatusEffectHealChanceModifier(type, 10), 'wl_full_heal'), - ENEMY_ENDURE_CHANCE: () => new EnemyEndureChanceModifierType('Endure Token', 2.5, 'wl_reset_urge'), - ENEMY_FUSED_CHANCE: () => new ModifierType('Fusion Token', 'Adds a 1% chance that a wild Pokémon will be a fusion', (type, _args) => new Modifiers.EnemyFusionChanceModifier(type, 1), 'wl_custom_spliced'), + ENEMY_HEAL: () => new ModifierType(`modifierType:ModifierType.ENEMY_HEAL`, 'wl_potion', (type, _args) => new Modifiers.EnemyTurnHealModifier(type, 2)), + ENEMY_ATTACK_POISON_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType(`modifierType:ModifierType.ENEMY_ATTACK_POISON_CHANCE`, 'wl_antidote', 10, StatusEffect.POISON), + ENEMY_ATTACK_PARALYZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType(`modifierType:ModifierType.ENEMY_ATTACK_PARALYZE_CHANCE`, 'wl_paralyze_heal', 10, StatusEffect.PARALYSIS), + ENEMY_ATTACK_SLEEP_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType(`modifierType:ModifierType.ENEMY_ATTACK_SLEEP_CHANCE`, 'wl_awakening', 10, StatusEffect.SLEEP), + ENEMY_ATTACK_FREEZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType(`modifierType:ModifierType.ENEMY_ATTACK_FREEZE_CHANCE`, 'wl_ice_heal', 10, StatusEffect.FREEZE), + ENEMY_ATTACK_BURN_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType(`modifierType:ModifierType.ENEMY_ATTACK_BURN_CHANCE`, 'wl_burn_heal', 10, StatusEffect.BURN), + ENEMY_STATUS_EFFECT_HEAL_CHANCE: () => new ModifierType(`modifierType:ModifierType.ENEMY_STATUS_EFFECT_HEAL_CHANCE`, 'wl_full_heal', (type, _args) => new Modifiers.EnemyStatusEffectHealChanceModifier(type, 10)), + ENEMY_ENDURE_CHANCE: () => new EnemyEndureChanceModifierType(`modifierType:ModifierType.ENEMY_ENDURE_CHANCE`, 'wl_reset_urge', 2.5), + ENEMY_FUSED_CHANCE: () => new ModifierType(`modifierType:ModifierType.ENEMY_FUSED_CHANCE`, 'wl_custom_spliced', (type, _args) => new Modifiers.EnemyFusionChanceModifier(type, 1)), }; interface ModifierPool { @@ -975,19 +1186,19 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.POKEBALL, 6), new WeightedModifierType(modifierTypes.RARE_CANDY, 2), new WeightedModifierType(modifierTypes.POTION, (party: Pokemon[]) => { - const thresholdPartyMemberCount = Math.min(party.filter(p => p.getInverseHp() >= 10 || p.getHpRatio() <= 0.875).length, 3); + const thresholdPartyMemberCount = Math.min(party.filter(p => (p.getInverseHp() >= 10 || p.getHpRatio() <= 0.875) && !p.isFainted()).length, 3); return thresholdPartyMemberCount * 3; }, 9), new WeightedModifierType(modifierTypes.SUPER_POTION, (party: Pokemon[]) => { - const thresholdPartyMemberCount = Math.min(party.filter(p => p.getInverseHp() >= 25 || p.getHpRatio() <= 0.75).length, 3); + const thresholdPartyMemberCount = Math.min(party.filter(p => (p.getInverseHp() >= 25 || p.getHpRatio() <= 0.75) && !p.isFainted()).length, 3); return thresholdPartyMemberCount; }, 3), new WeightedModifierType(modifierTypes.ETHER, (party: Pokemon[]) => { - const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3); + const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMovePp() - m.ppUsed) <= 5).length).length, 3); return thresholdPartyMemberCount * 3; }, 9), new WeightedModifierType(modifierTypes.MAX_ETHER, (party: Pokemon[]) => { - const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3); + const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMovePp() - m.ppUsed) <= 5).length).length, 3); return thresholdPartyMemberCount; }, 3), new WeightedModifierType(modifierTypes.LURE, 2), @@ -1013,24 +1224,24 @@ const modifierPool: ModifierPool = { return party.filter(p => p.isFainted()).length >= Math.ceil(party.length / 2) ? 1 : 0; }, 1), new WeightedModifierType(modifierTypes.HYPER_POTION, (party: Pokemon[]) => { - const thresholdPartyMemberCount = Math.min(party.filter(p => p.getInverseHp() >= 100 || p.getHpRatio() <= 0.625).length, 3); + const thresholdPartyMemberCount = Math.min(party.filter(p => (p.getInverseHp() >= 100 || p.getHpRatio() <= 0.625) && !p.isFainted()).length, 3); return thresholdPartyMemberCount * 3; }, 9), new WeightedModifierType(modifierTypes.MAX_POTION, (party: Pokemon[]) => { - const thresholdPartyMemberCount = Math.min(party.filter(p => p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5).length, 3); + const thresholdPartyMemberCount = Math.min(party.filter(p => (p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5) && !p.isFainted()).length, 3); return thresholdPartyMemberCount; }, 3), new WeightedModifierType(modifierTypes.FULL_RESTORE, (party: Pokemon[]) => { const statusEffectPartyMemberCount = Math.min(party.filter(p => p.hp && !!p.status).length, 3); - const thresholdPartyMemberCount = Math.floor((Math.min(party.filter(p => p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5).length, 3) + statusEffectPartyMemberCount) / 2); + const thresholdPartyMemberCount = Math.floor((Math.min(party.filter(p => (p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5) && !p.isFainted()).length, 3) + statusEffectPartyMemberCount) / 2); return thresholdPartyMemberCount; }, 3), new WeightedModifierType(modifierTypes.ELIXIR, (party: Pokemon[]) => { - const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3); + const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMovePp() - m.ppUsed) <= 5).length).length, 3); return thresholdPartyMemberCount * 3; }, 9), new WeightedModifierType(modifierTypes.MAX_ELIXIR, (party: Pokemon[]) => { - const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3); + const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMovePp() - m.ppUsed) <= 5).length).length, 3); return thresholdPartyMemberCount; }, 3), new WeightedModifierType(modifierTypes.DIRE_HIT, 4), @@ -1087,6 +1298,7 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.SOOTHE_BELL, 4), new WeightedModifierType(modifierTypes.ABILITY_CHARM, 6), new WeightedModifierType(modifierTypes.FOCUS_BAND, 5), + new WeightedModifierType(modifierTypes.QUICK_CLAW, 3), new WeightedModifierType(modifierTypes.KINGS_ROCK, 3), new WeightedModifierType(modifierTypes.LOCK_CAPSULE, 3), new WeightedModifierType(modifierTypes.SUPER_EXP_CHARM, 10), @@ -1138,6 +1350,7 @@ const trainerModifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.REVIVER_SEED, 2), new WeightedModifierType(modifierTypes.FOCUS_BAND, 2), new WeightedModifierType(modifierTypes.LUCKY_EGG, 4), + new WeightedModifierType(modifierTypes.QUICK_CLAW, 1), new WeightedModifierType(modifierTypes.GRIP_CLAW, 1), new WeightedModifierType(modifierTypes.WIDE_LENS, 1), ].map(m => { m.setTier(ModifierTier.ROGUE); return m; }), @@ -1198,6 +1411,7 @@ const dailyStarterModifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.GRIP_CLAW, 5), new WeightedModifierType(modifierTypes.BATON, 2), new WeightedModifierType(modifierTypes.FOCUS_BAND, 5), + new WeightedModifierType(modifierTypes.QUICK_CLAW, 3), new WeightedModifierType(modifierTypes.KINGS_ROCK, 3), ].map(m => { m.setTier(ModifierTier.ROGUE); return m; }), [ModifierTier.MASTER]: [ diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 8a5fba17d1c..0736831a01e 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -731,6 +731,40 @@ export class SurviveDamageModifier extends PokemonHeldItemModifier { } } +export class BypassSpeedChanceModifier extends PokemonHeldItemModifier { + constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) { + super(type, pokemonId, stackCount); + } + + matchType(modifier: Modifier) { + return modifier instanceof BypassSpeedChanceModifier; + } + + clone() { + return new BypassSpeedChanceModifier(this.type, this.pokemonId, this.stackCount); + } + + shouldApply(args: any[]): boolean { + return super.shouldApply(args) && args.length === 2 && args[1] instanceof Utils.BooleanHolder; + } + + apply(args: any[]): boolean { + const pokemon = args[0] as Pokemon; + const bypassSpeed = args[1] as Utils.BooleanHolder; + + if (!bypassSpeed.value && pokemon.randSeedInt(10) < this.getStackCount()) { + bypassSpeed.value = true; + return true; + } + + return false; + } + + getMaxHeldItemCount(pokemon: Pokemon): integer { + return 3; + } +} + export class FlinchChanceModifier extends PokemonHeldItemModifier { constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) { super(type, pokemonId, stackCount); diff --git a/src/overrides.ts b/src/overrides.ts index 704019a1d80..b7307ab2f7f 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -48,6 +48,13 @@ export const POKEBALL_OVERRIDE: { active: boolean, pokeballs: PokeballCounts } = export const STARTER_FORM_OVERRIDE: integer = 0; // default 5 or 20 for Daily export const STARTING_LEVEL_OVERRIDE: integer = 0; +/** + * SPECIES OVERRIDE + * will only apply to the first starter in your party or each enemy pokemon + * default is 0 to not override + * @example SPECIES_OVERRIDE = Species.Bulbasaur; + */ +export const STARTER_SPECIES_OVERRIDE: Species | integer = 0; export const ABILITY_OVERRIDE: Abilities = Abilities.NONE; export const PASSIVE_ABILITY_OVERRIDE: Abilities = Abilities.NONE; export const MOVESET_OVERRIDE: Array = []; @@ -58,21 +65,13 @@ export const VARIANT_OVERRIDE: Variant = 0; * OPPONENT / ENEMY OVERRIDES */ +export const OPP_SPECIES_OVERRIDE: Species | integer = 0; export const OPP_ABILITY_OVERRIDE: Abilities = Abilities.NONE; export const OPP_PASSIVE_ABILITY_OVERRIDE = Abilities.NONE; export const OPP_MOVESET_OVERRIDE: Array = []; export const OPP_SHINY_OVERRIDE: boolean = false; export const OPP_VARIANT_OVERRIDE: Variant = 0; -/** - * SPECIES OVERRIDE - * will only apply to the first starter in your party or each enemy pokemon - * default is 0 to not override - * @example SPECIES_OVERRIDE = Species.Bulbasaur; - */ -export const STARTER_SPECIES_OVERRIDE: Species | integer = 0; -export const OPP_SPECIES_OVERRIDE: Species | integer = 0; - /** * MODIFIER / ITEM OVERRIDES * if count is not provided, it will default to 1 diff --git a/src/phases.ts b/src/phases.ts index 12316902159..1137c85afa6 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2,11 +2,11 @@ import BattleScene, { AnySound, bypassLogin, startingWave } from "./battle-scene import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon"; import * as Utils from './utils'; import { Moves } from "./data/enums/moves"; -import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, BypassRedirectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr } from "./data/move"; +import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, BypassRedirectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr, SacrificialAttr } 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, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier, overrideModifiers, overrideHeldItems } from "./modifier/modifier"; +import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier, overrideModifiers, overrideHeldItems, BypassSpeedChanceModifier } 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"; @@ -37,7 +37,7 @@ import { BattleType, BattlerIndex, TurnCommand } from "./battle"; import { BattleSpec } from "./enums/battle-spec"; import { Species } from "./data/enums/species"; import { HealAchv, LevelAchv, achvs } from "./system/achv"; -import { TrainerSlot, trainerConfigs } from "./data/trainer-config"; +import { TrainerConfig, TrainerSlot, trainerConfigs } from "./data/trainer-config"; import { TrainerType } from "./data/enums/trainer-type"; import { EggHatchPhase } from "./egg-hatch-phase"; import { Egg } from "./data/egg"; @@ -46,7 +46,7 @@ import { loggedInUser, updateUserInfo } from "./account"; import { PlayerGender, SessionSaveData } from "./system/game-data"; import { addPokeballCaptureStars, addPokeballOpenParticles } from "./field/anims"; import { SpeciesFormChangeActiveTrigger, SpeciesFormChangeManualTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangePreMoveTrigger } from "./data/pokemon-forms"; -import { battleSpecDialogue, getCharVariantFromDialogue } from "./data/dialogue"; +import { battleSpecDialogue, getCharVariantFromDialogue, miscDialogue } from "./data/dialogue"; import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "./ui/modifier-select-ui-handler"; import { Setting } from "./system/settings"; import { Tutorial, handleTutorial } from "./tutorial"; @@ -59,6 +59,9 @@ import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm, speciesStarte import i18next from './plugins/i18n'; import { Abilities } from "./data/enums/abilities"; import * as Overrides from './overrides'; +import { TextStyle, addTextObject } from "./ui/text"; +import { Type } from "./data/type"; + export class LoginPhase extends Phase { private showText: boolean; @@ -160,7 +163,6 @@ export class TitlePhase extends Phase { this.scene.gameData.getSession(loggedInUser.lastSessionSlot).then(sessionData => { if (sessionData) { this.lastSessionData = sessionData; - console.log(sessionData); const biomeKey = getBiomeKey(sessionData.arena.biome); const bgTexture = `${biomeKey}_bg`; this.scene.arenaBg.setTexture(bgTexture); @@ -330,6 +332,7 @@ export class TitlePhase extends Phase { this.scene.newBattle(); this.scene.arena.init(); this.scene.sessionPlayTime = 0; + this.scene.lastSavePlayTime = 0; this.end(); }); }; @@ -393,8 +396,12 @@ export class UnavailablePhase extends Phase { } export class ReloadSessionPhase extends Phase { - constructor(scene: BattleScene) { + private systemDataStr: string; + + constructor(scene: BattleScene, systemDataStr?: string) { super(scene); + + this.systemDataStr = systemDataStr; } start(): void { @@ -410,7 +417,9 @@ export class ReloadSessionPhase extends Phase { delayElapsed = true; }); - this.scene.gameData.loadSystem().then(() => { + this.scene.gameData.clearLocalData(); + + (this.systemDataStr ? this.scene.gameData.initSystem(this.systemDataStr) : this.scene.gameData.loadSystem()).then(() => { if (delayElapsed) this.end(); else @@ -531,6 +540,7 @@ export class SelectStarterPhase extends Phase { this.scene.newBattle(); this.scene.arena.init(); this.scene.sessionPlayTime = 0; + this.scene.lastSavePlayTime = 0; this.end(); }); }); @@ -784,7 +794,7 @@ export class EncounterPhase extends BattlePhase { this.scene.ui.setMode(Mode.MESSAGE).then(() => { if (!this.loaded) { - this.scene.gameData.saveAll(this.scene, true).then(success => { + this.scene.gameData.saveAll(this.scene, true, battle.waveIndex % 10 === 1 || this.scene.lastSavePlayTime >= 300).then(success => { this.scene.disableMenu = false; if (!success) return this.scene.reset(true); @@ -833,8 +843,15 @@ export class EncounterPhase extends BattlePhase { if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) return i18next.t('battle:bossAppeared', {bossName: enemyField[0].name}); - if (this.scene.currentBattle.battleType === BattleType.TRAINER) - return i18next.t('battle:trainerAppeared', {trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true)}); + if (this.scene.currentBattle.battleType === BattleType.TRAINER) { + if (this.scene.currentBattle.double) { + return i18next.t('battle:trainerAppearedDouble', {trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true)}); + + } + else { + return i18next.t('battle:trainerAppeared', {trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true)}); + } + } return enemyField.length === 1 ? i18next.t('battle:singleWildAppeared', {pokemonName: enemyField[0].name}) @@ -1801,7 +1818,14 @@ export class CommandPhase extends FieldPhase { if (!isSwitch && this.fieldIndex) this.scene.currentBattle.turnCommands[this.fieldIndex - 1].skip = true; } else if (trapTag) { - if (!isSwitch) { + if(trapTag.sourceMove === Moves.INGRAIN && this.scene.getPokemonById(trapTag.sourceId).isOfType(Type.GHOST)) { + success = true; + this.scene.currentBattle.turnCommands[this.fieldIndex] = isSwitch + ? { command: Command.POKEMON, cursor: cursor, args: args } + : { command: Command.RUN }; + break; + } + if (!isSwitch) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); } @@ -1962,6 +1986,14 @@ export class TurnStartPhase extends FieldPhase { const field = this.scene.getField(); const order = this.getOrder(); + const battlerBypassSpeed = {}; + + this.scene.getField(true).filter(p => p.summonData).map(p => { + const bypassSpeed = new Utils.BooleanHolder(false); + this.scene.applyModifiers(BypassSpeedChanceModifier, p.isPlayer(), p, bypassSpeed); + battlerBypassSpeed[p.getBattlerIndex()] = bypassSpeed; + }); + const moveOrder = order.slice(0); moveOrder.sort((a, b) => { @@ -1986,6 +2018,9 @@ export class TurnStartPhase extends FieldPhase { if (aPriority.value !== bPriority.value) return aPriority.value < bPriority.value ? 1 : -1; } + + if (battlerBypassSpeed[a].value !== battlerBypassSpeed[b].value) + return battlerBypassSpeed[a].value ? -1 : 1; const aIndex = order.indexOf(a); const bIndex = order.indexOf(b); @@ -2251,12 +2286,8 @@ export class MovePhase extends BattlePhase { } const targets = this.scene.getField(true).filter(p => { - if (this.targets.indexOf(p.getBattlerIndex()) > -1) { - const hiddenTag = p.getTag(HiddenTag); - if (hiddenTag && !this.move.getMove().getAttrs(HitsTagAttr).filter(hta => (hta as HitsTagAttr).tagType === hiddenTag.tagType).length && !p.hasAbilityWithAttr(AlwaysHitAbAttr) && !this.pokemon.hasAbilityWithAttr(AlwaysHitAbAttr)) - return false; + if (this.targets.indexOf(p.getBattlerIndex()) > -1) return true; - } return false; }); @@ -2296,11 +2327,18 @@ export class MovePhase extends BattlePhase { if (this.move.moveId) this.showMoveText(); - - if ((moveQueue.length && moveQueue[0].move === Moves.NONE) || !targets.length) { - moveQueue.shift(); + + // This should only happen when there are no valid targets left on the field + if ((moveQueue.length && moveQueue[0].move === Moves.NONE) || !targets.length) { + this.showFailedText(); this.cancel(); + + // Record a failed move so Abilities like Truant don't trigger next turn and soft-lock this.pokemon.pushMoveHistory({ move: Moves.NONE, result: MoveResult.FAIL }); + + this.pokemon.lapseTags(BattlerTagLapseType.MOVE_EFFECT); // Remove any tags from moves like Fly/Dive/etc. + + moveQueue.shift(); return this.end(); } @@ -2529,8 +2567,14 @@ export class MoveEffectPhase extends PokemonPhase { })); } // Trigger effect which should only apply one time after all targeted effects have already applied - applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.POST_TARGET, - user, null, this.move.getMove()) + const postTarget = applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.POST_TARGET, + user, null, this.move.getMove()); + + if (applyAttrs.length) // If there is a pending asynchronous move effect, do this after + applyAttrs[applyAttrs.length - 1]?.then(() => postTarget); + else // Otherwise, push a new asynchronous move effect + applyAttrs.push(postTarget); + Promise.allSettled(applyAttrs).then(() => this.end()); }); }); @@ -2565,13 +2609,14 @@ export class MoveEffectPhase extends PokemonPhase { if (user.hasAbilityWithAttr(AlwaysHitAbAttr) || target.hasAbilityWithAttr(AlwaysHitAbAttr)) return true; + // If the user should ignore accuracy on a target, check who the user targeted last turn and see if they match + if (user.getTag(BattlerTagType.IGNORE_ACCURACY) && (user.getLastXMoves().slice(1).find(() => true)?.targets || []).indexOf(target.getBattlerIndex()) !== -1) + return true; + const hiddenTag = target.getTag(HiddenTag); if (hiddenTag && !this.move.getMove().getAttrs(HitsTagAttr).filter(hta => (hta as HitsTagAttr).tagType === hiddenTag.tagType).length) return false; - if (user.getTag(BattlerTagType.IGNORE_ACCURACY) && (user.getLastXMoves().find(() => true)?.targets || []).indexOf(target.getBattlerIndex()) > -1) - return true; - const moveAccuracy = new Utils.NumberHolder(this.move.getMove().accuracy); applyMoveAttrs(VariableAccuracyAttr, user, target, this.move.getMove(), moveAccuracy); @@ -3183,11 +3228,10 @@ export class FaintPhase extends PokemonPhase { if (defeatSource?.isOnField()) { applyPostVictoryAbAttrs(PostVictoryAbAttr, defeatSource); const pvmove = allMoves[pokemon.turnData.attacksReceived[0].move]; - const pvattrs = pvmove.getAttrs(PostVictoryStatChangeAttr); + const pvattrs = pvmove.getAttrs(PostVictoryStatChangeAttr) as PostVictoryStatChangeAttr[]; if (pvattrs.length) { - for (let pvattr of pvattrs) { + for (let pvattr of pvattrs) pvattr.applyPostVictory(defeatSource, defeatSource, pvmove); - } } } } @@ -3502,10 +3546,10 @@ export class GameOverModifierRewardPhase extends ModifierRewardPhase { this.scene.playSound('level_up_fanfare'); this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.fadeIn(250).then(() => { - this.scene.ui.showText(`You received\n${newModifier.type.name}!`, null, () => { - this.scene.time.delayedCall(1500, () => this.scene.arenaBg.setVisible(true)); - resolve(); - }, null, true, 1500); + this.scene.ui.showText(`You received\n${newModifier.type.name}!`, null, () => { + this.scene.time.delayedCall(1500, () => this.scene.arenaBg.setVisible(true)); + resolve(); + }, null, true, 1500); }); }); }) @@ -3527,11 +3571,9 @@ export class RibbonModifierRewardPhase extends ModifierRewardPhase { this.scene.addModifier(newModifier).then(() => { this.scene.playSound('level_up_fanfare'); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.fadeIn(250).then(() => { - this.scene.ui.showText(`${this.species.name} beat ${this.scene.gameMode.getName()} Mode for the first time!\nYou received ${newModifier.type.name}!`, null, () => { - resolve(); - }, null, true, 1500); - }); + this.scene.ui.showText(`${this.species.name} beat ${this.scene.gameMode.getName()} Mode for the first time!\nYou received ${newModifier.type.name}!`, null, () => { + resolve(); + }, null, true, 1500); }); }) } @@ -3583,6 +3625,7 @@ export class GameOverPhase extends BattlePhase { handleGameOver(): void { const doGameOver = (newClear: boolean) => { + this.scene.disableMenu = true; this.scene.time.delayedCall(1000, () => { let firstClear = false; if (this.victory && newClear) { @@ -3604,20 +3647,40 @@ export class GameOverPhase extends BattlePhase { const activeBattlers = this.scene.getField().filter(p => p?.isActive(true)); activeBattlers.map(p => p.hideInfo()); this.scene.ui.fadeOut(fadeDuration).then(() => { - [ this.scene.field, ...activeBattlers ].map(a => a.setVisible(false)); + activeBattlers.map(a => a.setVisible(false)); this.scene.setFieldScale(1, true); this.scene.clearPhaseQueue(); this.scene.ui.clearText(); - if (newClear) - this.handleUnlocks(); - if (this.victory && newClear) { - for (let species of this.firstRibbons) - this.scene.unshiftPhase(new RibbonModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PLUS, species)); - if (!firstClear) - this.scene.unshiftPhase(new GameOverModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PREMIUM)); + + const clear = (endCardPhase?: EndCardPhase) => { + if (newClear) + this.handleUnlocks(); + if (this.victory && newClear) { + for (let species of this.firstRibbons) + this.scene.unshiftPhase(new RibbonModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PLUS, species)); + if (!firstClear) + this.scene.unshiftPhase(new GameOverModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PREMIUM)); + } + this.scene.pushPhase(new PostGameOverPhase(this.scene, endCardPhase)); + this.end(); } - this.scene.pushPhase(new PostGameOverPhase(this.scene)); - this.end(); + + if (this.victory && this.scene.gameMode.isClassic) { + this.scene.ui.fadeIn(500).then(() => { + this.scene.charSprite.showCharacter(`rival_${this.scene.gameData.gender === PlayerGender.FEMALE ? 'm' : 'f'}`, getCharVariantFromDialogue(miscDialogue.ending[this.scene.gameData.gender === PlayerGender.FEMALE ? 0 : 1])).then(() => { + this.scene.ui.showDialogue(miscDialogue.ending[this.scene.gameData.gender === PlayerGender.FEMALE ? 0 : 1], this.scene.gameData.gender === PlayerGender.FEMALE ? trainerConfigs[TrainerType.RIVAL].name : trainerConfigs[TrainerType.RIVAL].nameFemale, null, () => { + this.scene.ui.fadeOut(500).then(() => { + this.scene.charSprite.hide().then(() => { + const endCardPhase = new EndCardPhase(this.scene); + this.scene.unshiftPhase(endCardPhase); + clear(endCardPhase); + }); + }); + }); + }); + }); + } else + clear(); }); }); }; @@ -3660,6 +3723,41 @@ export class GameOverPhase extends BattlePhase { } } +export class EndCardPhase extends Phase { + public endCard: Phaser.GameObjects.Image; + public text: Phaser.GameObjects.Text; + + constructor(scene: BattleScene) { + super(scene); + } + + start(): void { + super.start(); + + this.scene.ui.getMessageHandler().bg.setVisible(false); + this.scene.ui.getMessageHandler().nameBoxContainer.setVisible(false); + + this.endCard = this.scene.add.image(0, 0, `end_${this.scene.gameData.gender === PlayerGender.FEMALE ? 'f' : 'm'}`); + this.endCard.setOrigin(0); + this.endCard.setScale(0.5); + this.scene.field.add(this.endCard); + + this.text = addTextObject(this.scene, this.scene.game.canvas.width / 12, (this.scene.game.canvas.height / 6) - 16, 'Congratulations!', TextStyle.SUMMARY, { fontSize: '128px' }); + this.text.setOrigin(0.5); + this.scene.field.add(this.text); + + this.scene.ui.clearText(); + + this.scene.ui.fadeIn(1000).then(() => { + + this.scene.ui.showText('', null, () => { + this.scene.ui.getMessageHandler().bg.setVisible(true); + this.end(); + }, null, true); + }); + } +} + export class UnlockPhase extends Phase { private unlockable: Unlockables; @@ -3674,35 +3772,50 @@ export class UnlockPhase extends Phase { this.scene.gameData.unlocks[this.unlockable] = true; this.scene.playSound('level_up_fanfare'); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.fadeIn(250).then(() => { - this.scene.ui.showText(`${getUnlockableName(this.unlockable)}\nhas been unlocked.`, null, () => { - this.scene.time.delayedCall(1500, () => this.scene.arenaBg.setVisible(true)); - this.end(); - }, null, true, 1500); - }); + this.scene.ui.showText(`${getUnlockableName(this.unlockable)}\nhas been unlocked.`, null, () => { + this.scene.time.delayedCall(1500, () => this.scene.arenaBg.setVisible(true)); + this.end(); + }, null, true, 1500); }); } } export class PostGameOverPhase extends Phase { - constructor(scene: BattleScene) { + private endCardPhase: EndCardPhase; + + constructor(scene: BattleScene, endCardPhase: EndCardPhase) { super(scene); + + this.endCardPhase = endCardPhase; } start() { super.start(); - this.scene.gameData.saveSystem().then(success => { - if (!success) - return this.scene.reset(true); - this.scene.gameData.tryClearSession(this.scene, this.scene.sessionSlotId).then((success: boolean | [boolean, boolean]) => { - if (!success[0]) + const saveAndReset = () => { + this.scene.gameData.saveAll(this.scene, true, true, true).then(success => { + if (!success) return this.scene.reset(true); - this.scene.reset(); - this.scene.unshiftPhase(new TitlePhase(this.scene)); - this.end(); + this.scene.gameData.tryClearSession(this.scene, this.scene.sessionSlotId).then((success: boolean | [boolean, boolean]) => { + if (!success[0]) + return this.scene.reset(true); + this.scene.reset(); + this.scene.unshiftPhase(new TitlePhase(this.scene)); + this.end(); + }); }); - }); + }; + + if (this.endCardPhase) { + this.scene.ui.fadeOut(500).then(() => { + this.scene.ui.getMessageHandler().bg.setVisible(true); + + this.endCardPhase.endCard.destroy(); + this.endCardPhase.text.destroy(); + saveAndReset(); + }); + } else + saveAndReset(); } } @@ -3942,9 +4055,9 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { return; } this.scene.ui.setMode(messageMode).then(() => { - this.scene.ui.showText('@d{32}1, @d{15}2, and@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}Poof!', null, () => { + 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('And…', 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)); this.end(); diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 82a5a51ba12..5c9de28fe82 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -8,7 +8,6 @@ import { frConfig } from '#app/locales/fr/config.js'; import { itConfig } from '#app/locales/it/config.js'; import { ptBrConfig } from '#app/locales/pt_BR/config.js'; import { zhCnConfig } from '#app/locales/zh_CN/config.js'; - export interface SimpleTranslationEntries { [key: string]: string } @@ -31,16 +30,48 @@ export interface AbilityTranslationEntries { [key: string]: AbilityTranslationEntry } +export interface ModifierTypeTranslationEntry { + name?: string, + description?: string, + extra?: SimpleTranslationEntries +} + +export interface ModifierTypeTranslationEntries { + ModifierType: { [key: string]: ModifierTypeTranslationEntry }, + AttackTypeBoosterItem: SimpleTranslationEntries, + TempBattleStatBoosterItem: SimpleTranslationEntries, + BaseStatBoosterItem: SimpleTranslationEntries, + EvolutionItem: SimpleTranslationEntries, + FormChangeItem: SimpleTranslationEntries, + TeraType: SimpleTranslationEntries, +} + +export interface BerryTranslationEntry { + name: string, + effect: string +} + +export interface BerryTranslationEntries { + [key: string]: BerryTranslationEntry +} + export interface Localizable { localize(): void; } export function initI18n(): void { + // Prevent reinitialization + if (isInitialized) { + return; + } + isInitialized = true; let lang = ''; if (localStorage.getItem('prLang')) lang = localStorage.getItem('prLang'); + + /** * i18next is a localization library for maintaining and using translation resources. * @@ -106,12 +137,27 @@ declare module 'i18next' { pokemonStat: SimpleTranslationEntries; commandUiHandler: SimpleTranslationEntries; fightUiHandler: SimpleTranslationEntries; + titles: SimpleTranslationEntries; + trainerClasses: SimpleTranslationEntries; + trainerNames: SimpleTranslationEntries; tutorial: SimpleTranslationEntries; starterSelectUiHandler: SimpleTranslationEntries; + splashMessages: SimpleTranslationEntries; nature: SimpleTranslationEntries; growth: SimpleTranslationEntries; + egg: SimpleTranslationEntries; + weather: SimpleTranslationEntries; + modifierType: ModifierTypeTranslationEntries; + battleMessageUiHandler: SimpleTranslationEntries; + berry: BerryTranslationEntries; }; } } export default i18next; + +export function getIsInitialized(): boolean { + return isInitialized; +} + +let isInitialized = false; diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 5e942b4fa5b..2691e79be61 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -20,7 +20,7 @@ import { Egg } from "../data/egg"; import { VoucherType, vouchers } from "./voucher"; import { AES, enc } from "crypto-js"; import { Mode } from "../ui/ui"; -import { loggedInUser, updateUserInfo } from "../account"; +import { clientSessionId, loggedInUser, updateUserInfo } from "../account"; import { Nature } from "../data/nature"; import { GameStats } from "./game-stats"; import { Tutorial } from "../tutorial"; @@ -67,6 +67,18 @@ export function getDataTypeKey(dataType: GameDataType, slotId: integer = 0): str } } +function encrypt(data: string, bypassLogin: boolean): string { + return (bypassLogin + ? (data: string) => btoa(data) + : (data: string) => AES.encrypt(data, saveKey))(data); +} + +function decrypt(data: string, bypassLogin: boolean): string { + return (bypassLogin + ? (data: string) => atob(data) + : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8))(data); +} + interface SystemSaveData { trainerId: integer; secretId: integer; @@ -277,8 +289,10 @@ export class GameData { const maxIntAttrValue = Math.pow(2, 31); const systemData = JSON.stringify(data, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v); + localStorage.setItem(`data_${loggedInUser.username}`, encrypt(systemData, bypassLogin)); + if (!bypassLogin) { - Utils.apiPost(`savedata/update?datatype=${GameDataType.SYSTEM}`, systemData, undefined, true) + Utils.apiPost(`savedata/update?datatype=${GameDataType.SYSTEM}&clientSessionId=${clientSessionId}`, systemData, undefined, true) .then(response => response.text()) .then(error => { this.scene.ui.savingIcon.hide(); @@ -296,10 +310,6 @@ export class GameData { resolve(true); }); } else { - localStorage.setItem('data_bak', localStorage.getItem('data')); - - localStorage.setItem('data', btoa(systemData)); - this.scene.ui.savingIcon.hide(); resolve(true); @@ -309,120 +319,13 @@ export class GameData { public loadSystem(): Promise { return new Promise(resolve => { - if (bypassLogin && !localStorage.hasOwnProperty('data')) + console.log('Client Session:', clientSessionId); + + if (bypassLogin && !localStorage.getItem(`data_${loggedInUser.username}`)) return resolve(false); - const handleSystemData = (systemDataStr: string) => { - try { - const systemData = this.parseSystemData(systemDataStr); - - console.debug(systemData); - - /*const versions = [ this.scene.game.config.gameVersion, data.gameVersion || '0.0.0' ]; - - if (versions[0] !== versions[1]) { - const [ versionNumbers, oldVersionNumbers ] = versions.map(ver => ver.split('.').map(v => parseInt(v))); - }*/ - - this.trainerId = systemData.trainerId; - this.secretId = systemData.secretId; - - this.gender = systemData.gender; - - this.saveSetting(Setting.Player_Gender, systemData.gender === PlayerGender.FEMALE ? 1 : 0); - - const initStarterData = !systemData.starterData; - - if (initStarterData) { - this.initStarterData(); - - if (systemData['starterMoveData']) { - const starterMoveData = systemData['starterMoveData']; - for (let s of Object.keys(starterMoveData)) - this.starterData[s].moveset = starterMoveData[s]; - } - - if (systemData['starterEggMoveData']) { - const starterEggMoveData = systemData['starterEggMoveData']; - for (let s of Object.keys(starterEggMoveData)) - this.starterData[s].eggMoves = starterEggMoveData[s]; - } - - this.migrateStarterAbilities(systemData, this.starterData); - } else { - if ([ '1.0.0', '1.0.1' ].includes(systemData.gameVersion)) - this.migrateStarterAbilities(systemData); - //this.fixVariantData(systemData); - this.fixStarterData(systemData); - // Migrate ability starter data if empty for caught species - Object.keys(systemData.starterData).forEach(sd => { - if (systemData.dexData[sd].caughtAttr && !systemData.starterData[sd].abilityAttr) - systemData.starterData[sd].abilityAttr = 1; - }); - this.starterData = systemData.starterData; - } - - if (systemData.gameStats) { - if (systemData.gameStats.legendaryPokemonCaught !== undefined && systemData.gameStats.subLegendaryPokemonCaught === undefined) - this.fixLegendaryStats(systemData); - this.gameStats = systemData.gameStats; - } - - if (systemData.unlocks) { - for (let key of Object.keys(systemData.unlocks)) { - if (this.unlocks.hasOwnProperty(key)) - this.unlocks[key] = systemData.unlocks[key]; - } - } - - if (systemData.achvUnlocks) { - for (let a of Object.keys(systemData.achvUnlocks)) { - if (achvs.hasOwnProperty(a)) - this.achvUnlocks[a] = systemData.achvUnlocks[a]; - } - } - - if (systemData.voucherUnlocks) { - for (let v of Object.keys(systemData.voucherUnlocks)) { - if (vouchers.hasOwnProperty(v)) - this.voucherUnlocks[v] = systemData.voucherUnlocks[v]; - } - } - - if (systemData.voucherCounts) { - Utils.getEnumKeys(VoucherType).forEach(key => { - const index = VoucherType[key]; - this.voucherCounts[index] = systemData.voucherCounts[index] || 0; - }); - } - - this.eggs = systemData.eggs - ? systemData.eggs.map(e => e.toEgg()) - : []; - - this.dexData = Object.assign(this.dexData, systemData.dexData); - this.consolidateDexData(this.dexData); - this.defaultDexData = null; - - if (initStarterData) { - const starterIds = Object.keys(this.starterData).map(s => parseInt(s) as Species); - for (let s of starterIds) { - this.starterData[s].candyCount += this.dexData[s].caughtCount; - this.starterData[s].candyCount += this.dexData[s].hatchedCount * 2; - if (this.dexData[s].caughtAttr & DexAttr.SHINY) - this.starterData[s].candyCount += 4; - } - } - - resolve(true); - } catch (err) { - console.error(err); - resolve(false); - } - } - if (!bypassLogin) { - Utils.apiFetch(`savedata/get?datatype=${GameDataType.SYSTEM}`, true) + Utils.apiFetch(`savedata/system?clientSessionId=${clientSessionId}`, true) .then(response => response.text()) .then(response => { if (!response.length || response[0] !== '{') { @@ -437,10 +340,134 @@ export class GameData { return resolve(false); } - handleSystemData(response); + const cachedSystem = localStorage.getItem(`data_${loggedInUser.username}`); + this.initSystem(response, cachedSystem ? AES.decrypt(cachedSystem, saveKey).toString(enc.Utf8) : null).then(resolve); }); } else - handleSystemData(atob(localStorage.getItem('data'))); + this.initSystem(decrypt(localStorage.getItem(`data_${loggedInUser.username}`), bypassLogin)).then(resolve); + }); + } + + public initSystem(systemDataStr: string, cachedSystemDataStr?: string): Promise { + return new Promise(resolve => { + try { + let systemData = this.parseSystemData(systemDataStr); + + if (cachedSystemDataStr) { + let cachedSystemData = this.parseSystemData(cachedSystemDataStr); + if (cachedSystemData.timestamp > systemData.timestamp) { + console.debug('Use cached system'); + systemData = cachedSystemData; + systemDataStr = cachedSystemDataStr; + } else + this.clearLocalData(); + } + + console.debug(systemData); + + localStorage.setItem(`data_${loggedInUser.username}`, encrypt(systemDataStr, bypassLogin)); + + /*const versions = [ this.scene.game.config.gameVersion, data.gameVersion || '0.0.0' ]; + + if (versions[0] !== versions[1]) { + const [ versionNumbers, oldVersionNumbers ] = versions.map(ver => ver.split('.').map(v => parseInt(v))); + }*/ + + this.trainerId = systemData.trainerId; + this.secretId = systemData.secretId; + + this.gender = systemData.gender; + + this.saveSetting(Setting.Player_Gender, systemData.gender === PlayerGender.FEMALE ? 1 : 0); + + const initStarterData = !systemData.starterData; + + if (initStarterData) { + this.initStarterData(); + + if (systemData['starterMoveData']) { + const starterMoveData = systemData['starterMoveData']; + for (let s of Object.keys(starterMoveData)) + this.starterData[s].moveset = starterMoveData[s]; + } + + if (systemData['starterEggMoveData']) { + const starterEggMoveData = systemData['starterEggMoveData']; + for (let s of Object.keys(starterEggMoveData)) + this.starterData[s].eggMoves = starterEggMoveData[s]; + } + + this.migrateStarterAbilities(systemData, this.starterData); + } else { + if ([ '1.0.0', '1.0.1' ].includes(systemData.gameVersion)) + this.migrateStarterAbilities(systemData); + //this.fixVariantData(systemData); + this.fixStarterData(systemData); + // Migrate ability starter data if empty for caught species + Object.keys(systemData.starterData).forEach(sd => { + if (systemData.dexData[sd].caughtAttr && !systemData.starterData[sd].abilityAttr) + systemData.starterData[sd].abilityAttr = 1; + }); + this.starterData = systemData.starterData; + } + + if (systemData.gameStats) { + if (systemData.gameStats.legendaryPokemonCaught !== undefined && systemData.gameStats.subLegendaryPokemonCaught === undefined) + this.fixLegendaryStats(systemData); + this.gameStats = systemData.gameStats; + } + + if (systemData.unlocks) { + for (let key of Object.keys(systemData.unlocks)) { + if (this.unlocks.hasOwnProperty(key)) + this.unlocks[key] = systemData.unlocks[key]; + } + } + + if (systemData.achvUnlocks) { + for (let a of Object.keys(systemData.achvUnlocks)) { + if (achvs.hasOwnProperty(a)) + this.achvUnlocks[a] = systemData.achvUnlocks[a]; + } + } + + if (systemData.voucherUnlocks) { + for (let v of Object.keys(systemData.voucherUnlocks)) { + if (vouchers.hasOwnProperty(v)) + this.voucherUnlocks[v] = systemData.voucherUnlocks[v]; + } + } + + if (systemData.voucherCounts) { + Utils.getEnumKeys(VoucherType).forEach(key => { + const index = VoucherType[key]; + this.voucherCounts[index] = systemData.voucherCounts[index] || 0; + }); + } + + this.eggs = systemData.eggs + ? systemData.eggs.map(e => e.toEgg()) + : []; + + this.dexData = Object.assign(this.dexData, systemData.dexData); + this.consolidateDexData(this.dexData); + this.defaultDexData = null; + + if (initStarterData) { + const starterIds = Object.keys(this.starterData).map(s => parseInt(s) as Species); + for (let s of starterIds) { + this.starterData[s].candyCount += this.dexData[s].caughtCount; + this.starterData[s].candyCount += this.dexData[s].hatchedCount * 2; + if (this.dexData[s].caughtAttr & DexAttr.SHINY) + this.starterData[s].candyCount += 4; + } + } + + resolve(true); + } catch (err) { + console.error(err); + resolve(false); + } }); } @@ -474,6 +501,31 @@ export class GameData { return dataStr; } + public async verify(): Promise { + if (bypassLogin) + return true; + + const response = await Utils.apiPost(`savedata/system/verify`, JSON.stringify({ clientSessionId: clientSessionId }), undefined, true) + .then(response => response.json()); + + if (!response.valid) { + this.scene.clearPhaseQueue(); + this.scene.unshiftPhase(new ReloadSessionPhase(this.scene, JSON.stringify(response.systemData))); + this.clearLocalData(); + return false; + } + + return true; + } + + public clearLocalData(): void { + if (bypassLogin) + return; + localStorage.removeItem(`data_${loggedInUser.username}`); + for (let s = 0; s < 5; s++) + localStorage.removeItem(`sessionData${s ? s : ''}_${loggedInUser.username}`); + } + public saveSetting(setting: Setting, valueIndex: integer): boolean { let settings: object = {}; if (localStorage.hasOwnProperty('settings')) @@ -557,40 +609,6 @@ export class GameData { } as SessionSaveData; } - saveSession(scene: BattleScene, skipVerification?: boolean): Promise { - return new Promise(resolve => { - Utils.executeIf(!skipVerification, updateUserInfo).then(success => { - if (success !== null && !success) - return resolve(false); - - const sessionData = this.getSessionSaveData(scene); - - if (!bypassLogin) { - Utils.apiPost(`savedata/update?datatype=${GameDataType.SESSION}&slot=${scene.sessionSlotId}&trainerId=${this.trainerId}&secretId=${this.secretId}`, JSON.stringify(sessionData), undefined, true) - .then(response => response.text()) - .then(error => { - if (error) { - if (error.startsWith('session out of date')) { - this.scene.clearPhaseQueue(); - this.scene.unshiftPhase(new ReloadSessionPhase(this.scene)); - } - console.error(error); - return resolve(false); - } - console.debug('Session data saved'); - resolve(true); - }); - } else { - localStorage.setItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}`, btoa(JSON.stringify(sessionData))); - - console.debug('Session data saved'); - - resolve(true); - } - }); - }); - } - getSession(slotId: integer): Promise { return new Promise(async (resolve, reject) => { if (slotId < 0) @@ -605,8 +623,8 @@ export class GameData { } }; - if (!bypassLogin) { - Utils.apiFetch(`savedata/get?datatype=${GameDataType.SESSION}&slot=${slotId}`, true) + if (!bypassLogin && !localStorage.getItem(`sessionData${slotId ? slotId : ''}_${loggedInUser.username}`)) { + Utils.apiFetch(`savedata/session?slot=${slotId}&clientSessionId=${clientSessionId}`, true) .then(response => response.text()) .then(async response => { if (!response.length || response[0] !== '{') { @@ -614,12 +632,14 @@ export class GameData { return resolve(null); } + localStorage.setItem(`sessionData${slotId ? slotId : ''}_${loggedInUser.username}`, encrypt(response, bypassLogin)); + await handleSessionData(response); }); } else { - const sessionData = localStorage.getItem(`sessionData${slotId ? slotId : ''}`); + const sessionData = localStorage.getItem(`sessionData${slotId ? slotId : ''}_${loggedInUser.username}`); if (sessionData) - await handleSessionData(atob(sessionData)); + await handleSessionData(decrypt(sessionData, bypassLogin)); else return resolve(null); } @@ -640,6 +660,7 @@ export class GameData { console.log('Seed:', scene.seed); scene.sessionPlayTime = sessionData.playTime || 0; + scene.lastSavePlayTime = 0; const loadPokemonAssets: Promise[] = []; @@ -731,16 +752,17 @@ export class GameData { deleteSession(slotId: integer): Promise { return new Promise(resolve => { if (bypassLogin) { - localStorage.removeItem('sessionData'); + localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ''}_${loggedInUser.username}`); return resolve(true); } updateUserInfo().then(success => { if (success !== null && !success) return resolve(false); - Utils.apiFetch(`savedata/delete?datatype=${GameDataType.SESSION}&slot=${slotId}`, true).then(response => { + Utils.apiFetch(`savedata/delete?datatype=${GameDataType.SESSION}&slot=${slotId}&clientSessionId=${clientSessionId}`, true).then(response => { if (response.ok) { loggedInUser.lastSessionSlot = -1; + localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ''}_${loggedInUser.username}`); resolve(true); } return response.text(); @@ -792,7 +814,7 @@ export class GameData { tryClearSession(scene: BattleScene, slotId: integer): Promise<[success: boolean, newClear: boolean]> { return new Promise<[boolean, boolean]>(resolve => { if (bypassLogin) { - localStorage.removeItem(`sessionData${slotId ? slotId : ''}`); + localStorage.removeItem(`sessionData${slotId ? slotId : ''}_${loggedInUser.username}`); return resolve([true, true]); } @@ -800,9 +822,11 @@ export class GameData { if (success !== null && !success) return resolve([false, false]); const sessionData = this.getSessionSaveData(scene); - Utils.apiPost(`savedata/clear?slot=${slotId}&trainerId=${this.trainerId}&secretId=${this.secretId}`, JSON.stringify(sessionData), undefined, true).then(response => { - if (response.ok) + Utils.apiPost(`savedata/clear?slot=${slotId}&trainerId=${this.trainerId}&secretId=${this.secretId}&clientSessionId=${clientSessionId}`, JSON.stringify(sessionData), undefined, true).then(response => { + if (response.ok) { loggedInUser.lastSessionSlot = -1; + localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ''}_${loggedInUser.username}`); + } return response.json(); }).then(jsonResponse => { if (!jsonResponse.error) @@ -855,29 +879,39 @@ export class GameData { }) as SessionSaveData; } - saveAll(scene: BattleScene, skipVerification?: boolean): Promise { + saveAll(scene: BattleScene, skipVerification: boolean = false, sync: boolean = false, useCachedSession: boolean = false, useCachedSystem: boolean = false): Promise { return new Promise(resolve => { Utils.executeIf(!skipVerification, updateUserInfo).then(success => { if (success !== null && !success) return resolve(false); - this.scene.ui.savingIcon.show(); - const data = this.getSystemSaveData(); - const sessionData = this.getSessionSaveData(scene); + if (sync) + this.scene.ui.savingIcon.show(); + const sessionData = useCachedSession ? this.parseSessionData(decrypt(localStorage.getItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}_${loggedInUser.username}`), bypassLogin)) : this.getSessionSaveData(scene); const maxIntAttrValue = Math.pow(2, 31); - const systemData = this.getSystemSaveData(); + const systemData = useCachedSystem ? this.parseSystemData(decrypt(localStorage.getItem(`data_${loggedInUser.username}`), bypassLogin)) : this.getSystemSaveData(); const request = { system: systemData, session: sessionData, - sessionSlotId: scene.sessionSlotId + sessionSlotId: scene.sessionSlotId, + clientSessionId: clientSessionId }; - if (!bypassLogin) { + localStorage.setItem(`data_${loggedInUser.username}`, encrypt(JSON.stringify(systemData, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v), bypassLogin)); + + localStorage.setItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}_${loggedInUser.username}`, encrypt(JSON.stringify(sessionData), bypassLogin)); + + console.debug('Session data saved'); + + if (!bypassLogin && sync) { Utils.apiPost('savedata/updateall', JSON.stringify(request, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v), undefined, true) .then(response => response.text()) .then(error => { - this.scene.ui.savingIcon.hide(); + if (sync) { + this.scene.lastSavePlayTime = 0; + this.scene.ui.savingIcon.hide(); + } if (error) { if (error.startsWith('client version out of date')) { this.scene.clearPhaseQueue(); @@ -892,17 +926,10 @@ export class GameData { resolve(true); }); } else { - localStorage.setItem('data_bak', localStorage.getItem('data')); - - localStorage.setItem('data', btoa(JSON.stringify(systemData, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v))); - - localStorage.setItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}`, btoa(JSON.stringify(sessionData))); - - console.debug('Session data saved'); - - this.scene.ui.savingIcon.hide(); - - resolve(true); + this.verify().then(success => { + this.scene.ui.savingIcon.hide(); + resolve(success); + }); } }); }); @@ -910,7 +937,7 @@ export class GameData { public tryExportData(dataType: GameDataType, slotId: integer = 0): Promise { return new Promise(resolve => { - const dataKey: string = getDataTypeKey(dataType, slotId); + const dataKey: string = `${getDataTypeKey(dataType, slotId)}_${loggedInUser.username}`; const handleData = (dataStr: string) => { switch (dataType) { case GameDataType.SYSTEM: @@ -926,7 +953,7 @@ export class GameData { link.remove(); }; if (!bypassLogin && dataType < GameDataType.SETTINGS) { - Utils.apiFetch(`savedata/get?datatype=${dataType}${dataType === GameDataType.SESSION ? `&slot=${slotId}` : ''}`, true) + Utils.apiFetch(`savedata/${dataType === GameDataType.SYSTEM ? 'system' : 'session'}?clientSessionId=${clientSessionId}${dataType === GameDataType.SESSION ? `&slot=${slotId}` : ''}`, true) .then(response => response.text()) .then(response => { if (!response.length || response[0] !== '{') { @@ -941,14 +968,14 @@ export class GameData { } else { const data = localStorage.getItem(dataKey); if (data) - handleData(atob(data)); + handleData(decrypt(data, bypassLogin)); resolve(!!data); } }); } public importData(dataType: GameDataType, slotId: integer = 0): void { - const dataKey = getDataTypeKey(dataType, slotId); + const dataKey = `${getDataTypeKey(dataType, slotId)}_${loggedInUser.username}`; let saveFile: any = document.getElementById('saveFile'); if (saveFile) @@ -1009,11 +1036,13 @@ export class GameData { return this.scene.ui.showText(`Your ${dataName} data could not be loaded. It may be corrupted.`, null, () => this.scene.ui.showText(null, 0), Utils.fixedInt(1500)); this.scene.ui.showText(`Your ${dataName} data will be overridden and the page will reload. Proceed?`, null, () => { this.scene.ui.setOverlayMode(Mode.CONFIRM, () => { + localStorage.setItem(dataKey, encrypt(dataStr, bypassLogin)); + if (!bypassLogin && dataType < GameDataType.SETTINGS) { updateUserInfo().then(success => { if (!success) return displayError(`Could not contact the server. Your ${dataName} data could not be imported.`); - Utils.apiPost(`savedata/update?datatype=${dataType}${dataType === GameDataType.SESSION ? `&slot=${slotId}` : ''}&trainerId=${this.trainerId}&secretId=${this.secretId}`, dataStr, undefined, true) + Utils.apiPost(`savedata/update?datatype=${dataType}${dataType === GameDataType.SESSION ? `&slot=${slotId}` : ''}&trainerId=${this.trainerId}&secretId=${this.secretId}&clientSessionId=${clientSessionId}`, dataStr, undefined, true) .then(response => response.text()) .then(error => { if (error) { @@ -1023,10 +1052,8 @@ export class GameData { window.location = window.location; }); }); - } else { - localStorage.setItem(dataKey, btoa(dataStr)); + } else window.location = window.location; - } }, () => { this.scene.ui.revertMode(); this.scene.ui.showText(null, 0); diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index 2923540c867..dc34b9592e5 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -269,8 +269,24 @@ export default class BattleInfo extends Phaser.GameObjects.Container { const dexEntry = pokemon.scene.gameData.dexData[pokemon.species.speciesId]; this.ownedIcon.setVisible(!!dexEntry.caughtAttr); - const dexAttr = pokemon.getDexAttr(); - if ((dexEntry.caughtAttr & dexAttr) < dexAttr || !(pokemon.scene.gameData.starterData[pokemon.species.getRootSpeciesId()].abilityAttr & Math.pow(2, pokemon.abilityIndex))) + const opponentPokemonDexAttr = pokemon.getDexAttr(); + if ((dexEntry.caughtAttr & opponentPokemonDexAttr) < opponentPokemonDexAttr || !(pokemon.scene.gameData.starterData[pokemon.species.getRootSpeciesId()].abilityAttr & Math.pow(2, pokemon.abilityIndex))) + + // Check if Player owns all genders and forms of the Pokemon + const missingDexAttrs = ((dexEntry.caughtAttr & opponentPokemonDexAttr) < opponentPokemonDexAttr); + + /** + * If the opposing Pokemon only has 1 normal ability and is using the hidden ability it should have the same behavior + * if it had 2 normal abilities. This code checks if that is the case and uses the correct opponent Pokemon abilityIndex (2) + * for calculations so it aligns with where the hidden ability is stored in the starter data's abilityAttr (4) + */ + const opponentPokemonOneNormalAbility = (pokemon.species.getAbilityCount() === 2); + const opponentPokemonAbilityIndex = (opponentPokemonOneNormalAbility && pokemon.abilityIndex === 1) ? 2 : pokemon.abilityIndex; + const opponentPokemonAbilityAttr = Math.pow(2, opponentPokemonAbilityIndex); + + const rootFormHasHiddenAbility = pokemon.scene.gameData.starterData[pokemon.species.getRootSpeciesId()].abilityAttr & opponentPokemonAbilityAttr; + + if (missingDexAttrs || !rootFormHasHiddenAbility) this.ownedIcon.setTint(0x808080); if(pokemon.scene.gameData.starterData[pokemon.species.getRootSpeciesId()].classicWinCount > 0 && pokemon.scene.gameData.starterData[pokemon.species.getRootSpeciesId(true)].classicWinCount > 0) { diff --git a/src/ui/battle-message-ui-handler.ts b/src/ui/battle-message-ui-handler.ts index d04a98ea810..b7dccef52b5 100644 --- a/src/ui/battle-message-ui-handler.ts +++ b/src/ui/battle-message-ui-handler.ts @@ -7,6 +7,7 @@ import { getStatName, Stat } from "../data/pokemon-stat"; import { addWindow } from "./ui-theme"; import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; import {Button} from "../enums/buttons"; +import i18next from '../plugins/i18n'; export default class BattleMessageUiHandler extends MessageUiHandler { private levelUpStatsContainer: Phaser.GameObjects.Container; @@ -31,7 +32,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler { this.textCallbackTimer = null; const bg = this.scene.add.sprite(0, 0, 'bg', this.scene.windowType); - bg.setOrigin(0, 1); + bg.setOrigin(0, 1); ui.add(bg); this.bg = bg; @@ -234,20 +235,20 @@ export default class BattleMessageUiHandler extends MessageUiHandler { const textStyle: TextStyle = isBetter ? TextStyle.SUMMARY_GREEN : TextStyle.SUMMARY; const color = getTextColor(textStyle, false, uiTheme); return `[color=${color}][shadow=${getTextColor(textStyle, true, uiTheme)}]${text}[/shadow][/color]`; - }; +}; - if (value > 30) - return coloredText('Best', value > starterIvs[typeIv]); - if (value === 30) - return coloredText('Fantastic', value > starterIvs[typeIv]); - if (value > 20) - return coloredText('Very Good', value > starterIvs[typeIv]); - if (value > 10) - return coloredText('Pretty Good', value > starterIvs[typeIv]); - if (value > 0) - return coloredText('Decent', value > starterIvs[typeIv]); + if (value > 30) + return coloredText(i18next.t('battleMessageUiHandler:ivBest'), value > starterIvs[typeIv]); + if (value === 30) + return coloredText(i18next.t('battleMessageUiHandler:ivFantastic'), value > starterIvs[typeIv]); + if (value > 20) + return coloredText(i18next.t('battleMessageUiHandler:ivVeryGood'), value > starterIvs[typeIv]); + if (value > 10) + return coloredText(i18next.t('battleMessageUiHandler:ivPrettyGood'), value > starterIvs[typeIv]); + if (value > 0) + return coloredText(i18next.t('battleMessageUiHandler:ivDecent'), value > starterIvs[typeIv]); - return coloredText('No Good', value > starterIvs[typeIv]); + return coloredText(i18next.t('battleMessageUiHandler:ivNoGood'), value > starterIvs[typeIv]); } showNameText(name: string): void { diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index 315dfdbd3d3..7fd49157da7 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -10,8 +10,7 @@ import { addWindow } from "./ui-theme"; import { Tutorial, handleTutorial } from "../tutorial"; import { EggTier } from "../data/enums/egg-type"; import {Button} from "../enums/buttons"; - -const defaultText = 'Select a machine.'; +import i18next from '../plugins/i18n'; export default class EggGachaUiHandler extends MessageUiHandler { private eggGachaContainer: Phaser.GameObjects.Container; @@ -33,6 +32,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { private cursorObj: Phaser.GameObjects.Image; private transitioning: boolean; private transitionCancelled: boolean; + private defaultText: string; constructor(scene: BattleScene) { super(scene, Mode.EGG_GACHA); @@ -43,6 +43,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { this.gachaInfoContainers = []; this.voucherCountLabels = []; + this.defaultText = i18next.t('egg:selectMachine'); } setup() { @@ -151,8 +152,27 @@ export default class EggGachaUiHandler extends MessageUiHandler { this.eggGachaOptionSelectBg.setOrigin(1, 1); this.eggGachaOptionsContainer.add(this.eggGachaOptionSelectBg); - const optionText = addTextObject(this.scene, 0, 0, ' x1 1 Pull\n x10 10 Pulls\n x1 5 Pulls\n x1 10 Pulls\n x1 25 Pulls\nCancel', TextStyle.WINDOW); - optionText.setLineSpacing(12); + const pullOptions = [ + { multiplier: 'x1', description: `1 ${i18next.t('egg:pull')}` }, + { multiplier: 'x10', description: `10 ${i18next.t('egg:pulls')}` }, + { multiplier: 'x1', description: `5 ${i18next.t('egg:pulls')}` }, + { multiplier: 'x1', description: `10 ${i18next.t('egg:pulls')}` }, + { multiplier: 'x1', description: `25 ${i18next.t('egg:pulls')}` } + ]; + + const pullOptionsText = pullOptions.map(option => ` ${option.multiplier.padEnd(4)} ${option.description}`).join('\n'); + + const optionText = addTextObject( + this.scene, + 0, + 0, + `${pullOptionsText}\n${i18next.t('menu:cancel')}`, + TextStyle.WINDOW, + ); + + optionText.setLineSpacing(28); + optionText.setFontSize('80px'); + this.eggGachaOptionsContainer.add(optionText); optionText.setPositionRelative(this.eggGachaOptionSelectBg, 16, 9); @@ -223,7 +243,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { show(args: any[]): boolean { super.show(args); - this.getUi().showText(defaultText, 0); + this.getUi().showText(this.defaultText, 0); this.setGachaCursor(1); @@ -372,7 +392,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { this.scene.gameData.gameStats.eggsPulled++; } - this.scene.gameData.saveSystem().then(success => { + (this.scene.currentBattle ? this.scene.gameData.saveAll(this.scene, true, true, true) : this.scene.gameData.saveSystem()).then(success => { if (!success) return this.scene.reset(true); doPull(); @@ -474,7 +494,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { showText(text: string, delay?: number, callback?: Function, callbackDelay?: number, prompt?: boolean, promptDelay?: number): void { if (!text) - text = defaultText; + text = this.defaultText; if (text?.indexOf('\n') === -1) { this.eggGachaMessageBox.setSize(320, 32); @@ -490,7 +510,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { } showError(text: string): void { - this.showText(text, null, () => this.showText(defaultText), Utils.fixedInt(1500)); + this.showText(text, null, () => this.showText(this.defaultText), Utils.fixedInt(1500)); } setTransitioning(transitioning: boolean): void { @@ -526,27 +546,27 @@ export default class EggGachaUiHandler extends MessageUiHandler { case 0: if (!this.scene.gameData.voucherCounts[VoucherType.REGULAR]) { error = true; - this.showError('You don\'t have enough vouchers!'); + this.showError(i18next.t('egg:notEnoughVouchers')); } else if (this.scene.gameData.eggs.length < 99) { this.consumeVouchers(VoucherType.REGULAR, 1); this.pull(); success = true; } else { error = true; - this.showError('You have too many eggs!'); + this.showError(i18next.t('egg:tooManyEggs')); } break; case 2: if (!this.scene.gameData.voucherCounts[VoucherType.PLUS]) { error = true; - this.showError('You don\'t have enough vouchers!'); + this.showError(i18next.t('egg:notEnoughVouchers')); } else if (this.scene.gameData.eggs.length < 95) { this.consumeVouchers(VoucherType.PLUS, 1); this.pull(5); success = true; } else { error = true; - this.showError('You have too many eggs!'); + this.showError(i18next.t('egg:tooManyEggs')); } break; case 1: @@ -554,7 +574,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { if ((this.cursor === 1 && this.scene.gameData.voucherCounts[VoucherType.REGULAR] < 10) || (this.cursor === 3 && !this.scene.gameData.voucherCounts[VoucherType.PREMIUM])) { error = true; - this.showError('You don\'t have enough vouchers!'); + this.showError(i18next.t('egg:notEnoughVouchers')); } else if (this.scene.gameData.eggs.length < 90) { if (this.cursor === 3) this.consumeVouchers(VoucherType.PREMIUM, 1); @@ -564,20 +584,20 @@ export default class EggGachaUiHandler extends MessageUiHandler { success = true; } else { error = true; - this.showError('You have too many eggs!'); + this.showError(i18next.t('egg:tooManyEggs')); } break; case 4: if (!this.scene.gameData.voucherCounts[VoucherType.GOLDEN]) { error = true; - this.showError('You don\'t have enough vouchers!'); + this.showError(i18next.t('egg:notEnoughVouchers')); } else if (this.scene.gameData.eggs.length < 75) { this.consumeVouchers(VoucherType.GOLDEN, 1); this.pull(25); success = true; } else { error = true; - this.showError('You have too many eggs!'); + this.showError(i18next.t('egg:tooManyEggs')); } break; case 5: diff --git a/src/ui/egg-list-ui-handler.ts b/src/ui/egg-list-ui-handler.ts index edeac7d71c7..a62eb743697 100644 --- a/src/ui/egg-list-ui-handler.ts +++ b/src/ui/egg-list-ui-handler.ts @@ -7,6 +7,7 @@ import { EGG_SEED, Egg, GachaType, getEggGachaTypeDescriptor, getEggHatchWavesMe import * as Utils from "../utils"; import { addWindow } from "./ui-theme"; import {Button} from "../enums/buttons"; +import i18next from '../plugins/i18n'; export default class EggListUiHandler extends MessageUiHandler { private eggListContainer: Phaser.GameObjects.Container; @@ -165,7 +166,7 @@ export default class EggListUiHandler extends MessageUiHandler { setEggDetails(egg: Egg): void { this.eggSprite.setFrame(`egg_${egg.getKey()}`); - this.eggNameText.setText(`Egg (${getEggDescriptor(egg)})`); + this.eggNameText.setText(`${i18next.t('egg:egg')} (${getEggDescriptor(egg)})`); this.eggDateText.setText( new Date(egg.timestamp).toLocaleString(undefined, { weekday: 'short', diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index bf032667610..fb253d94f9b 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -20,7 +20,7 @@ export enum MenuOptions { EGG_GACHA, MANAGE_DATA, COMMUNITY, - RETURN_TO_TITLE, + SAVE_AND_QUIT, LOG_OUT } @@ -297,15 +297,18 @@ export default class MenuUiHandler extends MessageUiHandler { ui.setOverlayMode(Mode.MENU_OPTION_SELECT, this.communityConfig); success = true; break; - case MenuOptions.RETURN_TO_TITLE: + case MenuOptions.SAVE_AND_QUIT: if (this.scene.currentBattle) { success = true; - ui.showText(i18next.t("menuUiHandler:losingProgressionWarning"), null, () => { - ui.setOverlayMode(Mode.CONFIRM, () => this.scene.reset(true), () => { - ui.revertMode(); - ui.showText(null, 0); - }, false, -98); - }); + if (this.scene.currentBattle.turn > 1) { + ui.showText(i18next.t("menuUiHandler:losingProgressionWarning"), null, () => { + ui.setOverlayMode(Mode.CONFIRM, () => this.scene.gameData.saveAll(this.scene, true, true, true, true).then(() => this.scene.reset(true)), () => { + ui.revertMode(); + ui.showText(null, 0); + }, false, -98); + }); + } else + this.scene.gameData.saveAll(this.scene, true, true, true, true).then(() => this.scene.reset(true)); } else error = true; break; diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 8443ed5741e..a20f3a3647f 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -86,7 +86,17 @@ function getValueReductionCandyCounts(baseValue: integer): [integer, integer] { } } -const gens = [ 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' ]; +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; @@ -245,30 +255,54 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonUncaughtText.setOrigin(0, 0); this.starterSelectContainer.add(this.pokemonUncaughtText); - this.pokemonAbilityLabelText = addTextObject(this.scene, 6, 127, i18next.t("starterSelectUiHandler:ability"), TextStyle.SUMMARY_ALT, { fontSize: '56px' }); + let starterInfoXPosition = 31; // Only text + // The position should be set per language + const currentLanguage = i18next.language; + switch (currentLanguage) { + case 'pt_BR': + starterInfoXPosition = 32; + break; + default: + starterInfoXPosition = 31; + break + } + + let starterInfoTextSize = '56px'; // Labels and text + // The font size should be set per language + // currentLanguage is already defined + switch (currentLanguage) { + case 'pt_BR': + starterInfoTextSize = '47px'; + break; + default: + starterInfoTextSize = '56px'; + break + } + + this.pokemonAbilityLabelText = addTextObject(this.scene, 6, 127, i18next.t("starterSelectUiHandler:ability"), TextStyle.SUMMARY_ALT, { fontSize: starterInfoTextSize }); this.pokemonAbilityLabelText.setOrigin(0, 0); this.pokemonAbilityLabelText.setVisible(false); this.starterSelectContainer.add(this.pokemonAbilityLabelText); - this.pokemonAbilityText = addTextObject(this.scene, 31, 127, '', TextStyle.SUMMARY_ALT, { fontSize: '56px' }); + this.pokemonAbilityText = addTextObject(this.scene, starterInfoXPosition, 127, '', TextStyle.SUMMARY_ALT, { fontSize: starterInfoTextSize }); this.pokemonAbilityText.setOrigin(0, 0); this.starterSelectContainer.add(this.pokemonAbilityText); - this.pokemonPassiveLabelText = addTextObject(this.scene, 6, 136, i18next.t("starterSelectUiHandler:passive"), TextStyle.SUMMARY_ALT, { fontSize: '56px' }); + this.pokemonPassiveLabelText = addTextObject(this.scene, 6, 136, i18next.t("starterSelectUiHandler:passive"), TextStyle.SUMMARY_ALT, { fontSize: starterInfoTextSize }); this.pokemonPassiveLabelText.setOrigin(0, 0); this.pokemonPassiveLabelText.setVisible(false); this.starterSelectContainer.add(this.pokemonPassiveLabelText); - this.pokemonPassiveText = addTextObject(this.scene, 31, 136, '', TextStyle.SUMMARY_ALT, { fontSize: '56px' }); + this.pokemonPassiveText = addTextObject(this.scene, starterInfoXPosition, 136, '', TextStyle.SUMMARY_ALT, { fontSize: starterInfoTextSize }); this.pokemonPassiveText.setOrigin(0, 0); this.starterSelectContainer.add(this.pokemonPassiveText); - this.pokemonNatureLabelText = addTextObject(this.scene, 6, 145, i18next.t("starterSelectUiHandler:nature"), TextStyle.SUMMARY_ALT, { fontSize: '56px' }); + this.pokemonNatureLabelText = addTextObject(this.scene, 6, 145, i18next.t("starterSelectUiHandler:nature"), TextStyle.SUMMARY_ALT, { fontSize: starterInfoTextSize }); this.pokemonNatureLabelText.setOrigin(0, 0); this.pokemonNatureLabelText.setVisible(false); this.starterSelectContainer.add(this.pokemonNatureLabelText); - this.pokemonNatureText = addBBCodeTextObject(this.scene, 31, 145, '', TextStyle.SUMMARY_ALT, { fontSize: '56px' }); + this.pokemonNatureText = addBBCodeTextObject(this.scene, starterInfoXPosition, 145, '', TextStyle.SUMMARY_ALT, { fontSize: starterInfoTextSize }); this.pokemonNatureText.setOrigin(0, 0); this.starterSelectContainer.add(this.pokemonNatureText); @@ -556,8 +590,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler { let instructionTextSize = '42px'; // The font size should be set per language - const currentLanguage = i18next.language; + // currentLanguage is already defined in the previous code block switch (currentLanguage) { + case 'de': + instructionTextSize = '35px'; + break; case 'en': instructionTextSize = '42px'; break; @@ -567,12 +604,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler { case 'fr': instructionTextSize = '42px'; break; - case 'de': - instructionTextSize = '35px'; - break; case 'it': instructionTextSize = '38px'; break; + case 'pt_BR': + instructionTextSize = '38px'; + break; case 'zh_CN': instructionTextSize = '42px'; break; @@ -1260,15 +1297,17 @@ export default class StarterSelectUiHandler extends MessageUiHandler { updateGenOptions(): void { let text = ''; for (let g = this.genScrollCursor; g <= this.genScrollCursor + 2; g++) { - let optionText = gens[g]; - if (g === this.genScrollCursor && this.genScrollCursor) - optionText = '↑'; - else if (g === this.genScrollCursor + 2 && this.genScrollCursor < gens.length - 3) - optionText = '↓' - text += `${text ? '\n' : ''}${optionText}`; + 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); @@ -1833,4 +1872,4 @@ export default class StarterSelectUiHandler extends MessageUiHandler { icon.setFrame(species.getIconId(female, formIndex, false, variant)); } } -} \ No newline at end of file +} diff --git a/src/ui/title-ui-handler.ts b/src/ui/title-ui-handler.ts index c808611b093..4da4f189f6b 100644 --- a/src/ui/title-ui-handler.ts +++ b/src/ui/title-ui-handler.ts @@ -4,7 +4,7 @@ import OptionSelectUiHandler from "./option-select-ui-handler"; import { Mode } from "./ui"; import * as Utils from "../utils"; import { TextStyle, addTextObject } from "./text"; -import { battleCountSplashMessage, splashMessages } from "../data/splash-messages"; +import { getBattleCountSplashMessage, getSplashMessages } from "../data/splash-messages"; import i18next from "i18next"; export default class TitleUiHandler extends OptionSelectUiHandler { @@ -63,8 +63,8 @@ export default class TitleUiHandler extends OptionSelectUiHandler { .then(request => request.json()) .then(stats => { this.playerCountLabel.setText(`${stats.playerCount} ${i18next.t("menu:playersOnline")}`); - if (this.splashMessage === battleCountSplashMessage) - this.splashMessageText.setText(battleCountSplashMessage.replace('{COUNT}', stats.battleCount.toLocaleString('en-US'))); + if (this.splashMessage === getBattleCountSplashMessage()) + this.splashMessageText.setText(getBattleCountSplashMessage().replace('{COUNT}', stats.battleCount.toLocaleString('en-US'))); }) .catch(err => { console.error("Failed to fetch title stats:\n", err); @@ -75,7 +75,7 @@ export default class TitleUiHandler extends OptionSelectUiHandler { const ret = super.show(args); if (ret) { - this.splashMessage = Utils.randItem(splashMessages); + this.splashMessage = Utils.randItem(getSplashMessages()); this.splashMessageText.setText(this.splashMessage.replace('{COUNT}', '?')); const ui = this.getUi();