diff --git a/create-test-boilerplate.js b/create-test-boilerplate.js index 7c49efcff79..6d9cde966d5 100644 --- a/create-test-boilerplate.js +++ b/create-test-boilerplate.js @@ -14,7 +14,7 @@ import { fileURLToPath } from "url"; // Get the directory name of the current module file const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const typeChoices = ["Move", "Ability", "Item"]; +const typeChoices = ["Move", "Ability", "Item", "Mystery Encounter"]; /** * Prompts the user to select a type via list. @@ -76,6 +76,7 @@ async function runInteractive() { const fileName = fileNameAnswer.userInput .replace(/-+/g, "_") // Convert kebab-case (dashes) to underscores .replace(/([a-z])([A-Z])/g, "$1_$2") // Convert camelCase to snake_case + .replace(/\s+/g, '_') // Replace spaces with underscores .toLowerCase(); // Ensure all lowercase // Format the description for the test case @@ -96,6 +97,10 @@ async function runInteractive() { dir = path.join(__dirname, "src", "test", "items"); description = `Items - ${formattedName}`; break; + case "mystery encounter": + dir = path.join(__dirname, "src", "test", "mystery-encounter", "encounters"); + description = `Mystery Encounter - ${formattedName}`; + break; default: console.error('Invalid type. Please use "move", "ability", or "item".'); process.exit(1); @@ -112,7 +117,6 @@ import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest"; describe("${description}", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; beforeAll(() => { phaserGame = new Phaser.Game({ @@ -136,7 +140,7 @@ describe("${description}", () => { it("test case", async () => { // await game.classicMode.startBattle([Species.MAGIKARP]); // game.move.select(Moves.SPLASH); - }, TIMEOUT); + }); }); `; diff --git a/public/audio/bgm/battle_star_admin.mp3 b/public/audio/bgm/battle_star_admin.mp3 new file mode 100644 index 00000000000..461a9a2b262 Binary files /dev/null and b/public/audio/bgm/battle_star_admin.mp3 differ diff --git a/public/audio/bgm/battle_star_boss.mp3 b/public/audio/bgm/battle_star_boss.mp3 new file mode 100644 index 00000000000..51cb33139c6 Binary files /dev/null and b/public/audio/bgm/battle_star_boss.mp3 differ diff --git a/public/audio/bgm/battle_star_grunt.mp3 b/public/audio/bgm/battle_star_grunt.mp3 new file mode 100644 index 00000000000..13da4900eed Binary files /dev/null and b/public/audio/bgm/battle_star_grunt.mp3 differ diff --git a/public/images/mystery-encounters/berry_bush.json b/public/images/mystery-encounters/berries_abound_bush.json similarity index 94% rename from public/images/mystery-encounters/berry_bush.json rename to public/images/mystery-encounters/berries_abound_bush.json index 397538d8af2..749031d7da8 100644 --- a/public/images/mystery-encounters/berry_bush.json +++ b/public/images/mystery-encounters/berries_abound_bush.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "berry_bush.png", + "image": "berries_abound_bush.png", "format": "RGBA8888", "size": { "w": 49, diff --git a/public/images/mystery-encounters/berry_bush.png b/public/images/mystery-encounters/berries_abound_bush.png similarity index 100% rename from public/images/mystery-encounters/berry_bush.png rename to public/images/mystery-encounters/berries_abound_bush.png diff --git a/public/images/mystery-encounters/mad_scientist_m.json b/public/images/mystery-encounters/dark_deal_scientist.json similarity index 94% rename from public/images/mystery-encounters/mad_scientist_m.json rename to public/images/mystery-encounters/dark_deal_scientist.json index 10aa3d6f42a..95db5d1b71a 100644 --- a/public/images/mystery-encounters/mad_scientist_m.json +++ b/public/images/mystery-encounters/dark_deal_scientist.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "mad_scientist_m.png", + "image": "dark_deal_scientist.png", "format": "RGBA8888", "size": { "w": 46, diff --git a/public/images/mystery-encounters/mad_scientist_m.png b/public/images/mystery-encounters/dark_deal_scientist.png similarity index 100% rename from public/images/mystery-encounters/mad_scientist_m.png rename to public/images/mystery-encounters/dark_deal_scientist.png diff --git a/public/images/mystery-encounters/b2w2_lady.json b/public/images/mystery-encounters/department_store_sale_lady.json similarity index 99% rename from public/images/mystery-encounters/b2w2_lady.json rename to public/images/mystery-encounters/department_store_sale_lady.json index e143086e157..5ba5b2019ff 100644 --- a/public/images/mystery-encounters/b2w2_lady.json +++ b/public/images/mystery-encounters/department_store_sale_lady.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "b2w2_lady.png", + "image": "department_store_sale_lady.png", "format": "RGBA8888", "size": { "w": 399, diff --git a/public/images/mystery-encounters/b2w2_lady.png b/public/images/mystery-encounters/department_store_sale_lady.png similarity index 100% rename from public/images/mystery-encounters/b2w2_lady.png rename to public/images/mystery-encounters/department_store_sale_lady.png diff --git a/public/images/mystery-encounters/exclaim.png b/public/images/mystery-encounters/encounter_exclaim.png similarity index 100% rename from public/images/mystery-encounters/exclaim.png rename to public/images/mystery-encounters/encounter_exclaim.png diff --git a/public/images/mystery-encounters/teacher.json b/public/images/mystery-encounters/field_trip_teacher.json similarity index 94% rename from public/images/mystery-encounters/teacher.json rename to public/images/mystery-encounters/field_trip_teacher.json index 457d440a010..52a304b3421 100644 --- a/public/images/mystery-encounters/teacher.json +++ b/public/images/mystery-encounters/field_trip_teacher.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "teacher.png", + "image": "field_trip_teacher.png", "format": "RGBA8888", "size": { "w": 43, diff --git a/public/images/mystery-encounters/teacher.png b/public/images/mystery-encounters/field_trip_teacher.png similarity index 100% rename from public/images/mystery-encounters/teacher.png rename to public/images/mystery-encounters/field_trip_teacher.png diff --git a/public/images/mystery-encounters/carnival_game.json b/public/images/mystery-encounters/fun_and_games_game.json similarity index 94% rename from public/images/mystery-encounters/carnival_game.json rename to public/images/mystery-encounters/fun_and_games_game.json index 0572b95990c..71fb30fda33 100644 --- a/public/images/mystery-encounters/carnival_game.json +++ b/public/images/mystery-encounters/fun_and_games_game.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "carnival_game.png", + "image": "fun_and_games_game.png", "format": "RGBA8888", "size": { "w": 38, diff --git a/public/images/mystery-encounters/carnival_game.png b/public/images/mystery-encounters/fun_and_games_game.png similarity index 100% rename from public/images/mystery-encounters/carnival_game.png rename to public/images/mystery-encounters/fun_and_games_game.png diff --git a/public/images/mystery-encounters/carnival_man.json b/public/images/mystery-encounters/fun_and_games_man.json similarity index 94% rename from public/images/mystery-encounters/carnival_man.json rename to public/images/mystery-encounters/fun_and_games_man.json index 3e77765bbce..9536e108055 100644 --- a/public/images/mystery-encounters/carnival_man.json +++ b/public/images/mystery-encounters/fun_and_games_man.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "carnival_man.png", + "image": "fun_and_games_man.png", "format": "RGBA8888", "size": { "w": 50, diff --git a/public/images/mystery-encounters/carnival_man.png b/public/images/mystery-encounters/fun_and_games_man.png similarity index 100% rename from public/images/mystery-encounters/carnival_man.png rename to public/images/mystery-encounters/fun_and_games_man.png diff --git a/public/images/mystery-encounters/carnival_wobbuffet.json b/public/images/mystery-encounters/fun_and_games_wobbuffet.json similarity index 94% rename from public/images/mystery-encounters/carnival_wobbuffet.json rename to public/images/mystery-encounters/fun_and_games_wobbuffet.json index c059bb35a96..2f218cd208b 100644 --- a/public/images/mystery-encounters/carnival_wobbuffet.json +++ b/public/images/mystery-encounters/fun_and_games_wobbuffet.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "carnival_wobbuffet.png", + "image": "fun_and_games_wobbuffet.png", "format": "RGBA8888", "size": { "w": 45, diff --git a/public/images/mystery-encounters/carnival_wobbuffet.png b/public/images/mystery-encounters/fun_and_games_wobbuffet.png similarity index 100% rename from public/images/mystery-encounters/carnival_wobbuffet.png rename to public/images/mystery-encounters/fun_and_games_wobbuffet.png diff --git a/public/images/mystery-encounters/buoy.json b/public/images/mystery-encounters/lost_at_sea_buoy.json similarity index 100% rename from public/images/mystery-encounters/buoy.json rename to public/images/mystery-encounters/lost_at_sea_buoy.json diff --git a/public/images/mystery-encounters/buoy.png b/public/images/mystery-encounters/lost_at_sea_buoy.png similarity index 100% rename from public/images/mystery-encounters/buoy.png rename to public/images/mystery-encounters/lost_at_sea_buoy.png diff --git a/public/images/mystery-encounters/chest_blue.json b/public/images/mystery-encounters/mysterious_chest_blue.json similarity index 98% rename from public/images/mystery-encounters/chest_blue.json rename to public/images/mystery-encounters/mysterious_chest_blue.json index 916afc3242c..c55294a7bdc 100644 --- a/public/images/mystery-encounters/chest_blue.json +++ b/public/images/mystery-encounters/mysterious_chest_blue.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "chest_blue.png", + "image": "mysterious_chest_blue.png", "format": "RGBA8888", "size": { "w": 54, diff --git a/public/images/mystery-encounters/chest_blue.png b/public/images/mystery-encounters/mysterious_chest_blue.png similarity index 100% rename from public/images/mystery-encounters/chest_blue.png rename to public/images/mystery-encounters/mysterious_chest_blue.png diff --git a/public/images/mystery-encounters/chest_red.json b/public/images/mystery-encounters/mysterious_chest_red.json similarity index 98% rename from public/images/mystery-encounters/chest_red.json rename to public/images/mystery-encounters/mysterious_chest_red.json index 579cf7bda06..fe560ecf43c 100644 --- a/public/images/mystery-encounters/chest_red.json +++ b/public/images/mystery-encounters/mysterious_chest_red.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "chest_red.png", + "image": "mysterious_chest_red.png", "format": "RGBA8888", "size": { "w": 54, diff --git a/public/images/mystery-encounters/chest_red.png b/public/images/mystery-encounters/mysterious_chest_red.png similarity index 100% rename from public/images/mystery-encounters/chest_red.png rename to public/images/mystery-encounters/mysterious_chest_red.png diff --git a/public/images/mystery-encounters/warehouse_crate.json b/public/images/mystery-encounters/part_timer_crate.json similarity index 95% rename from public/images/mystery-encounters/warehouse_crate.json rename to public/images/mystery-encounters/part_timer_crate.json index fa86d1a511d..0bc67774770 100644 --- a/public/images/mystery-encounters/warehouse_crate.json +++ b/public/images/mystery-encounters/part_timer_crate.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "warehouse_crate.png", + "image": "part_timer_crate.png", "format": "RGBA8888", "size": { "w": 71, diff --git a/public/images/mystery-encounters/warehouse_crate.png b/public/images/mystery-encounters/part_timer_crate.png similarity index 100% rename from public/images/mystery-encounters/warehouse_crate.png rename to public/images/mystery-encounters/part_timer_crate.png diff --git a/public/images/mystery-encounters/bait.json b/public/images/mystery-encounters/safari_zone_bait.json similarity index 97% rename from public/images/mystery-encounters/bait.json rename to public/images/mystery-encounters/safari_zone_bait.json index ae9ee38ee13..4786dd34840 100644 --- a/public/images/mystery-encounters/bait.json +++ b/public/images/mystery-encounters/safari_zone_bait.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "bait.png", + "image": "safari_zone_bait.png", "format": "RGBA8888", "size": { "w": 14, diff --git a/public/images/mystery-encounters/bait.png b/public/images/mystery-encounters/safari_zone_bait.png similarity index 100% rename from public/images/mystery-encounters/bait.png rename to public/images/mystery-encounters/safari_zone_bait.png diff --git a/public/images/mystery-encounters/mud.json b/public/images/mystery-encounters/safari_zone_mud.json similarity index 97% rename from public/images/mystery-encounters/mud.json rename to public/images/mystery-encounters/safari_zone_mud.json index 505a6fadd27..8f58857351e 100644 --- a/public/images/mystery-encounters/mud.json +++ b/public/images/mystery-encounters/safari_zone_mud.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "mud.png", + "image": "safari_zone_mud.png", "format": "RGBA8888", "size": { "w": 14, diff --git a/public/images/mystery-encounters/mud.png b/public/images/mystery-encounters/safari_zone_mud.png similarity index 100% rename from public/images/mystery-encounters/mud.png rename to public/images/mystery-encounters/safari_zone_mud.png diff --git a/public/images/mystery-encounters/b2w2_veteran_m.json b/public/images/mystery-encounters/shady_vitamin_dealer.json similarity index 99% rename from public/images/mystery-encounters/b2w2_veteran_m.json rename to public/images/mystery-encounters/shady_vitamin_dealer.json index 8f07c7d44e2..43c707d05ca 100644 --- a/public/images/mystery-encounters/b2w2_veteran_m.json +++ b/public/images/mystery-encounters/shady_vitamin_dealer.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "b2w2_veteran_m.png", + "image": "shady_vitamin_dealer.png", "format": "RGBA8888", "size": { "w": 424, diff --git a/public/images/mystery-encounters/b2w2_veteran_m.png b/public/images/mystery-encounters/shady_vitamin_dealer.png similarity index 100% rename from public/images/mystery-encounters/b2w2_veteran_m.png rename to public/images/mystery-encounters/shady_vitamin_dealer.png diff --git a/public/images/mystery-encounters/teleporter.json b/public/images/mystery-encounters/teleporting_hijinks_teleporter.json similarity index 93% rename from public/images/mystery-encounters/teleporter.json rename to public/images/mystery-encounters/teleporting_hijinks_teleporter.json index 4fe45807be2..04a3acd4369 100644 --- a/public/images/mystery-encounters/teleporter.json +++ b/public/images/mystery-encounters/teleporting_hijinks_teleporter.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "teleporter.png", + "image": "teleporting_hijinks_teleporter.png", "format": "RGBA8888", "size": { "w": 74, diff --git a/public/images/mystery-encounters/teleporter.png b/public/images/mystery-encounters/teleporting_hijinks_teleporter.png similarity index 100% rename from public/images/mystery-encounters/teleporter.png rename to public/images/mystery-encounters/teleporting_hijinks_teleporter.png diff --git a/public/images/mystery-encounters/training_gear.json b/public/images/mystery-encounters/training_session_gear.json similarity index 94% rename from public/images/mystery-encounters/training_gear.json rename to public/images/mystery-encounters/training_session_gear.json index fb8f4ec9c8e..8196c03f305 100644 --- a/public/images/mystery-encounters/training_gear.json +++ b/public/images/mystery-encounters/training_session_gear.json @@ -1,7 +1,7 @@ { "textures": [ { - "image": "training_gear.png", + "image": "training_session_gear.png", "format": "RGBA8888", "size": { "w": 76, diff --git a/public/images/mystery-encounters/training_gear.png b/public/images/mystery-encounters/training_session_gear.png similarity index 100% rename from public/images/mystery-encounters/training_gear.png rename to public/images/mystery-encounters/training_session_gear.png diff --git a/public/images/pokemon/966-caph-starmobile.json b/public/images/pokemon/966-caph-starmobile.json new file mode 100644 index 00000000000..96c5aada282 --- /dev/null +++ b/public/images/pokemon/966-caph-starmobile.json @@ -0,0 +1,19 @@ +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 94, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 94, "h": 94 }, + "sourceSize": { "w": 120, "h": 94 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.8.1-x64", + "image": "966-caph-starmobile.png", + "format": "RGBA8888", + "size": { "w": 94, "h": 94 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/966-caph-starmobile.png b/public/images/pokemon/966-caph-starmobile.png new file mode 100644 index 00000000000..987782e529e Binary files /dev/null and b/public/images/pokemon/966-caph-starmobile.png differ diff --git a/public/images/pokemon/966-navi-starmobile.json b/public/images/pokemon/966-navi-starmobile.json new file mode 100644 index 00000000000..6a39310af00 --- /dev/null +++ b/public/images/pokemon/966-navi-starmobile.json @@ -0,0 +1,19 @@ +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 94, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 94, "h": 94 }, + "sourceSize": { "w": 120, "h": 94 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.8.1-x64", + "image": "966-navi-starmobile.png", + "format": "RGBA8888", + "size": { "w": 94, "h": 94 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/966-navi-starmobile.png b/public/images/pokemon/966-navi-starmobile.png new file mode 100644 index 00000000000..41d0fd4690c Binary files /dev/null and b/public/images/pokemon/966-navi-starmobile.png differ diff --git a/public/images/pokemon/966-ruchbah-starmobile.json b/public/images/pokemon/966-ruchbah-starmobile.json new file mode 100644 index 00000000000..c75a5630f45 --- /dev/null +++ b/public/images/pokemon/966-ruchbah-starmobile.json @@ -0,0 +1,19 @@ +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 94, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 94, "h": 94 }, + "sourceSize": { "w": 120, "h": 94 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.8.1-x64", + "image": "966-ruchbah-starmobile.png", + "format": "RGBA8888", + "size": { "w": 94, "h": 94 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/966-ruchbah-starmobile.png b/public/images/pokemon/966-ruchbah-starmobile.png new file mode 100644 index 00000000000..765f1fe5eaa Binary files /dev/null and b/public/images/pokemon/966-ruchbah-starmobile.png differ diff --git a/public/images/pokemon/966-schedar-starmobile.json b/public/images/pokemon/966-schedar-starmobile.json new file mode 100644 index 00000000000..59f77f3c975 --- /dev/null +++ b/public/images/pokemon/966-schedar-starmobile.json @@ -0,0 +1,19 @@ +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 94, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 94, "h": 94 }, + "sourceSize": { "w": 120, "h": 94 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.8.1-x64", + "image": "966-schedar-starmobile.png", + "format": "RGBA8888", + "size": { "w": 94, "h": 94 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/966-schedar-starmobile.png b/public/images/pokemon/966-schedar-starmobile.png new file mode 100644 index 00000000000..4cbc60f581f Binary files /dev/null and b/public/images/pokemon/966-schedar-starmobile.png differ diff --git a/public/images/pokemon/966-segin-starmobile.json b/public/images/pokemon/966-segin-starmobile.json new file mode 100644 index 00000000000..98b3938643b --- /dev/null +++ b/public/images/pokemon/966-segin-starmobile.json @@ -0,0 +1,19 @@ +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 94, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 94, "h": 94 }, + "sourceSize": { "w": 120, "h": 94 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.8.1-x64", + "image": "966-segin-starmobile.png", + "format": "RGBA8888", + "size": { "w": 94, "h": 94 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/966-segin-starmobile.png b/public/images/pokemon/966-segin-starmobile.png new file mode 100644 index 00000000000..fab6b1f62ee Binary files /dev/null and b/public/images/pokemon/966-segin-starmobile.png differ diff --git a/public/images/pokemon/back/966-caph-starmobile.json b/public/images/pokemon/back/966-caph-starmobile.json new file mode 100644 index 00000000000..d71eccd11d7 --- /dev/null +++ b/public/images/pokemon/back/966-caph-starmobile.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "966-caph-starmobile.png", + "format": "RGBA8888", + "size": { + "w": 84, + "h": 84 + }, + "scale": 0.333, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 96, + "h": 96 + }, + "spriteSourceSize": { + "x": 6, + "y": 20, + "w": 84, + "h": 56 + }, + "frame": { + "x": 0, + "y": 0, + "w": 84, + "h": 56 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:0226ae22b7a4822d78e38df4af1f59a7:01ce69442faf54e54474cd349cad2f7d:f9a0366e304d666e4262fa0af369d1f4$" + } +} diff --git a/public/images/pokemon/back/966-caph-starmobile.png b/public/images/pokemon/back/966-caph-starmobile.png new file mode 100644 index 00000000000..d1e67365454 Binary files /dev/null and b/public/images/pokemon/back/966-caph-starmobile.png differ diff --git a/public/images/pokemon/back/966-navi-starmobile.json b/public/images/pokemon/back/966-navi-starmobile.json new file mode 100644 index 00000000000..99059aa6edb --- /dev/null +++ b/public/images/pokemon/back/966-navi-starmobile.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "966-navi-starmobile.png", + "format": "RGBA8888", + "size": { + "w": 84, + "h": 84 + }, + "scale": 0.333, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 96, + "h": 96 + }, + "spriteSourceSize": { + "x": 6, + "y": 20, + "w": 84, + "h": 56 + }, + "frame": { + "x": 0, + "y": 0, + "w": 84, + "h": 56 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:0226ae22b7a4822d78e38df4af1f59a7:01ce69442faf54e54474cd349cad2f7d:f9a0366e304d666e4262fa0af369d1f4$" + } +} diff --git a/public/images/pokemon/back/966-navi-starmobile.png b/public/images/pokemon/back/966-navi-starmobile.png new file mode 100644 index 00000000000..d1e67365454 Binary files /dev/null and b/public/images/pokemon/back/966-navi-starmobile.png differ diff --git a/public/images/pokemon/back/966-ruchbah-starmobile.json b/public/images/pokemon/back/966-ruchbah-starmobile.json new file mode 100644 index 00000000000..b3bb8463eac --- /dev/null +++ b/public/images/pokemon/back/966-ruchbah-starmobile.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "966-ruchbah-starmobile.png", + "format": "RGBA8888", + "size": { + "w": 84, + "h": 84 + }, + "scale": 0.333, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 96, + "h": 96 + }, + "spriteSourceSize": { + "x": 6, + "y": 20, + "w": 84, + "h": 56 + }, + "frame": { + "x": 0, + "y": 0, + "w": 84, + "h": 56 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:0226ae22b7a4822d78e38df4af1f59a7:01ce69442faf54e54474cd349cad2f7d:f9a0366e304d666e4262fa0af369d1f4$" + } +} diff --git a/public/images/pokemon/back/966-ruchbah-starmobile.png b/public/images/pokemon/back/966-ruchbah-starmobile.png new file mode 100644 index 00000000000..d1e67365454 Binary files /dev/null and b/public/images/pokemon/back/966-ruchbah-starmobile.png differ diff --git a/public/images/pokemon/back/966-schedar-starmobile.json b/public/images/pokemon/back/966-schedar-starmobile.json new file mode 100644 index 00000000000..9832835b3ce --- /dev/null +++ b/public/images/pokemon/back/966-schedar-starmobile.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "966-schedar-starmobile.png", + "format": "RGBA8888", + "size": { + "w": 84, + "h": 84 + }, + "scale": 0.333, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 96, + "h": 96 + }, + "spriteSourceSize": { + "x": 6, + "y": 20, + "w": 84, + "h": 56 + }, + "frame": { + "x": 0, + "y": 0, + "w": 84, + "h": 56 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:0226ae22b7a4822d78e38df4af1f59a7:01ce69442faf54e54474cd349cad2f7d:f9a0366e304d666e4262fa0af369d1f4$" + } +} diff --git a/public/images/pokemon/back/966-schedar-starmobile.png b/public/images/pokemon/back/966-schedar-starmobile.png new file mode 100644 index 00000000000..d1e67365454 Binary files /dev/null and b/public/images/pokemon/back/966-schedar-starmobile.png differ diff --git a/public/images/pokemon/back/966-segin-starmobile.json b/public/images/pokemon/back/966-segin-starmobile.json new file mode 100644 index 00000000000..75bd4d8f304 --- /dev/null +++ b/public/images/pokemon/back/966-segin-starmobile.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "966-segin-starmobile.png", + "format": "RGBA8888", + "size": { + "w": 84, + "h": 84 + }, + "scale": 0.333, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 96, + "h": 96 + }, + "spriteSourceSize": { + "x": 6, + "y": 20, + "w": 84, + "h": 56 + }, + "frame": { + "x": 0, + "y": 0, + "w": 84, + "h": 56 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:0226ae22b7a4822d78e38df4af1f59a7:01ce69442faf54e54474cd349cad2f7d:f9a0366e304d666e4262fa0af369d1f4$" + } +} diff --git a/public/images/pokemon/back/966-segin-starmobile.png b/public/images/pokemon/back/966-segin-starmobile.png new file mode 100644 index 00000000000..d1e67365454 Binary files /dev/null and b/public/images/pokemon/back/966-segin-starmobile.png differ diff --git a/public/images/pokemon/back/shiny/966-caph-starmobile.json b/public/images/pokemon/back/shiny/966-caph-starmobile.json new file mode 100644 index 00000000000..d71eccd11d7 --- /dev/null +++ b/public/images/pokemon/back/shiny/966-caph-starmobile.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "966-caph-starmobile.png", + "format": "RGBA8888", + "size": { + "w": 84, + "h": 84 + }, + "scale": 0.333, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 96, + "h": 96 + }, + "spriteSourceSize": { + "x": 6, + "y": 20, + "w": 84, + "h": 56 + }, + "frame": { + "x": 0, + "y": 0, + "w": 84, + "h": 56 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:0226ae22b7a4822d78e38df4af1f59a7:01ce69442faf54e54474cd349cad2f7d:f9a0366e304d666e4262fa0af369d1f4$" + } +} diff --git a/public/images/pokemon/back/shiny/966-caph-starmobile.png b/public/images/pokemon/back/shiny/966-caph-starmobile.png new file mode 100644 index 00000000000..64e72d6793f Binary files /dev/null and b/public/images/pokemon/back/shiny/966-caph-starmobile.png differ diff --git a/public/images/pokemon/back/shiny/966-navi-starmobile.json b/public/images/pokemon/back/shiny/966-navi-starmobile.json new file mode 100644 index 00000000000..99059aa6edb --- /dev/null +++ b/public/images/pokemon/back/shiny/966-navi-starmobile.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "966-navi-starmobile.png", + "format": "RGBA8888", + "size": { + "w": 84, + "h": 84 + }, + "scale": 0.333, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 96, + "h": 96 + }, + "spriteSourceSize": { + "x": 6, + "y": 20, + "w": 84, + "h": 56 + }, + "frame": { + "x": 0, + "y": 0, + "w": 84, + "h": 56 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:0226ae22b7a4822d78e38df4af1f59a7:01ce69442faf54e54474cd349cad2f7d:f9a0366e304d666e4262fa0af369d1f4$" + } +} diff --git a/public/images/pokemon/back/shiny/966-navi-starmobile.png b/public/images/pokemon/back/shiny/966-navi-starmobile.png new file mode 100644 index 00000000000..64e72d6793f Binary files /dev/null and b/public/images/pokemon/back/shiny/966-navi-starmobile.png differ diff --git a/public/images/pokemon/back/shiny/966-ruchbah-starmobile.json b/public/images/pokemon/back/shiny/966-ruchbah-starmobile.json new file mode 100644 index 00000000000..b3bb8463eac --- /dev/null +++ b/public/images/pokemon/back/shiny/966-ruchbah-starmobile.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "966-ruchbah-starmobile.png", + "format": "RGBA8888", + "size": { + "w": 84, + "h": 84 + }, + "scale": 0.333, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 96, + "h": 96 + }, + "spriteSourceSize": { + "x": 6, + "y": 20, + "w": 84, + "h": 56 + }, + "frame": { + "x": 0, + "y": 0, + "w": 84, + "h": 56 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:0226ae22b7a4822d78e38df4af1f59a7:01ce69442faf54e54474cd349cad2f7d:f9a0366e304d666e4262fa0af369d1f4$" + } +} diff --git a/public/images/pokemon/back/shiny/966-ruchbah-starmobile.png b/public/images/pokemon/back/shiny/966-ruchbah-starmobile.png new file mode 100644 index 00000000000..64e72d6793f Binary files /dev/null and b/public/images/pokemon/back/shiny/966-ruchbah-starmobile.png differ diff --git a/public/images/pokemon/back/shiny/966-schedar-starmobile.json b/public/images/pokemon/back/shiny/966-schedar-starmobile.json new file mode 100644 index 00000000000..9832835b3ce --- /dev/null +++ b/public/images/pokemon/back/shiny/966-schedar-starmobile.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "966-schedar-starmobile.png", + "format": "RGBA8888", + "size": { + "w": 84, + "h": 84 + }, + "scale": 0.333, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 96, + "h": 96 + }, + "spriteSourceSize": { + "x": 6, + "y": 20, + "w": 84, + "h": 56 + }, + "frame": { + "x": 0, + "y": 0, + "w": 84, + "h": 56 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:0226ae22b7a4822d78e38df4af1f59a7:01ce69442faf54e54474cd349cad2f7d:f9a0366e304d666e4262fa0af369d1f4$" + } +} diff --git a/public/images/pokemon/back/shiny/966-schedar-starmobile.png b/public/images/pokemon/back/shiny/966-schedar-starmobile.png new file mode 100644 index 00000000000..64e72d6793f Binary files /dev/null and b/public/images/pokemon/back/shiny/966-schedar-starmobile.png differ diff --git a/public/images/pokemon/back/shiny/966-segin-starmobile.json b/public/images/pokemon/back/shiny/966-segin-starmobile.json new file mode 100644 index 00000000000..75bd4d8f304 --- /dev/null +++ b/public/images/pokemon/back/shiny/966-segin-starmobile.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "966-segin-starmobile.png", + "format": "RGBA8888", + "size": { + "w": 84, + "h": 84 + }, + "scale": 0.333, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 96, + "h": 96 + }, + "spriteSourceSize": { + "x": 6, + "y": 20, + "w": 84, + "h": 56 + }, + "frame": { + "x": 0, + "y": 0, + "w": 84, + "h": 56 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:0226ae22b7a4822d78e38df4af1f59a7:01ce69442faf54e54474cd349cad2f7d:f9a0366e304d666e4262fa0af369d1f4$" + } +} diff --git a/public/images/pokemon/back/shiny/966-segin-starmobile.png b/public/images/pokemon/back/shiny/966-segin-starmobile.png new file mode 100644 index 00000000000..64e72d6793f Binary files /dev/null and b/public/images/pokemon/back/shiny/966-segin-starmobile.png differ diff --git a/public/images/pokemon/icons/9/966-caph-starmobile.png b/public/images/pokemon/icons/9/966-caph-starmobile.png new file mode 100644 index 00000000000..fba351495bd Binary files /dev/null and b/public/images/pokemon/icons/9/966-caph-starmobile.png differ diff --git a/public/images/pokemon/icons/9/966-navi-starmobile.png b/public/images/pokemon/icons/9/966-navi-starmobile.png new file mode 100644 index 00000000000..fba351495bd Binary files /dev/null and b/public/images/pokemon/icons/9/966-navi-starmobile.png differ diff --git a/public/images/pokemon/icons/9/966-ruchbah-starmobile.png b/public/images/pokemon/icons/9/966-ruchbah-starmobile.png new file mode 100644 index 00000000000..fba351495bd Binary files /dev/null and b/public/images/pokemon/icons/9/966-ruchbah-starmobile.png differ diff --git a/public/images/pokemon/icons/9/966-schedar-starmobile.png b/public/images/pokemon/icons/9/966-schedar-starmobile.png new file mode 100644 index 00000000000..fba351495bd Binary files /dev/null and b/public/images/pokemon/icons/9/966-schedar-starmobile.png differ diff --git a/public/images/pokemon/icons/9/966-segin-starmobile.png b/public/images/pokemon/icons/9/966-segin-starmobile.png new file mode 100644 index 00000000000..fba351495bd Binary files /dev/null and b/public/images/pokemon/icons/9/966-segin-starmobile.png differ diff --git a/public/images/pokemon/icons/9/966s-caph-starmobile.png b/public/images/pokemon/icons/9/966s-caph-starmobile.png new file mode 100644 index 00000000000..e54e5c90e4a Binary files /dev/null and b/public/images/pokemon/icons/9/966s-caph-starmobile.png differ diff --git a/public/images/pokemon/icons/9/966s-navi-starmobile.png b/public/images/pokemon/icons/9/966s-navi-starmobile.png new file mode 100644 index 00000000000..e54e5c90e4a Binary files /dev/null and b/public/images/pokemon/icons/9/966s-navi-starmobile.png differ diff --git a/public/images/pokemon/icons/9/966s-ruchbah-starmobile.png b/public/images/pokemon/icons/9/966s-ruchbah-starmobile.png new file mode 100644 index 00000000000..e54e5c90e4a Binary files /dev/null and b/public/images/pokemon/icons/9/966s-ruchbah-starmobile.png differ diff --git a/public/images/pokemon/icons/9/966s-schedar-starmobile.png b/public/images/pokemon/icons/9/966s-schedar-starmobile.png new file mode 100644 index 00000000000..e54e5c90e4a Binary files /dev/null and b/public/images/pokemon/icons/9/966s-schedar-starmobile.png differ diff --git a/public/images/pokemon/icons/9/966s-segin-starmobile.png b/public/images/pokemon/icons/9/966s-segin-starmobile.png new file mode 100644 index 00000000000..e54e5c90e4a Binary files /dev/null and b/public/images/pokemon/icons/9/966s-segin-starmobile.png differ diff --git a/public/images/pokemon/shiny/966-caph-starmobile.json b/public/images/pokemon/shiny/966-caph-starmobile.json new file mode 100644 index 00000000000..96c5aada282 --- /dev/null +++ b/public/images/pokemon/shiny/966-caph-starmobile.json @@ -0,0 +1,19 @@ +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 94, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 94, "h": 94 }, + "sourceSize": { "w": 120, "h": 94 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.8.1-x64", + "image": "966-caph-starmobile.png", + "format": "RGBA8888", + "size": { "w": 94, "h": 94 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/shiny/966-caph-starmobile.png b/public/images/pokemon/shiny/966-caph-starmobile.png new file mode 100644 index 00000000000..6107a426ff6 Binary files /dev/null and b/public/images/pokemon/shiny/966-caph-starmobile.png differ diff --git a/public/images/pokemon/shiny/966-navi-starmobile.json b/public/images/pokemon/shiny/966-navi-starmobile.json new file mode 100644 index 00000000000..6a39310af00 --- /dev/null +++ b/public/images/pokemon/shiny/966-navi-starmobile.json @@ -0,0 +1,19 @@ +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 94, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 94, "h": 94 }, + "sourceSize": { "w": 120, "h": 94 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.8.1-x64", + "image": "966-navi-starmobile.png", + "format": "RGBA8888", + "size": { "w": 94, "h": 94 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/shiny/966-navi-starmobile.png b/public/images/pokemon/shiny/966-navi-starmobile.png new file mode 100644 index 00000000000..74999d4fa13 Binary files /dev/null and b/public/images/pokemon/shiny/966-navi-starmobile.png differ diff --git a/public/images/pokemon/shiny/966-ruchbah-starmobile.json b/public/images/pokemon/shiny/966-ruchbah-starmobile.json new file mode 100644 index 00000000000..c75a5630f45 --- /dev/null +++ b/public/images/pokemon/shiny/966-ruchbah-starmobile.json @@ -0,0 +1,19 @@ +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 94, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 94, "h": 94 }, + "sourceSize": { "w": 120, "h": 94 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.8.1-x64", + "image": "966-ruchbah-starmobile.png", + "format": "RGBA8888", + "size": { "w": 94, "h": 94 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/shiny/966-ruchbah-starmobile.png b/public/images/pokemon/shiny/966-ruchbah-starmobile.png new file mode 100644 index 00000000000..9de01ac6a73 Binary files /dev/null and b/public/images/pokemon/shiny/966-ruchbah-starmobile.png differ diff --git a/public/images/pokemon/shiny/966-schedar-starmobile.json b/public/images/pokemon/shiny/966-schedar-starmobile.json new file mode 100644 index 00000000000..59f77f3c975 --- /dev/null +++ b/public/images/pokemon/shiny/966-schedar-starmobile.json @@ -0,0 +1,19 @@ +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 94, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 94, "h": 94 }, + "sourceSize": { "w": 120, "h": 94 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.8.1-x64", + "image": "966-schedar-starmobile.png", + "format": "RGBA8888", + "size": { "w": 94, "h": 94 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/shiny/966-schedar-starmobile.png b/public/images/pokemon/shiny/966-schedar-starmobile.png new file mode 100644 index 00000000000..79033bb123c Binary files /dev/null and b/public/images/pokemon/shiny/966-schedar-starmobile.png differ diff --git a/public/images/pokemon/shiny/966-segin-starmobile.json b/public/images/pokemon/shiny/966-segin-starmobile.json new file mode 100644 index 00000000000..98b3938643b --- /dev/null +++ b/public/images/pokemon/shiny/966-segin-starmobile.json @@ -0,0 +1,19 @@ +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 94, "h": 94 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 26, "y": 0, "w": 94, "h": 94 }, + "sourceSize": { "w": 120, "h": 94 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.8.1-x64", + "image": "966-segin-starmobile.png", + "format": "RGBA8888", + "size": { "w": 94, "h": 94 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/shiny/966-segin-starmobile.png b/public/images/pokemon/shiny/966-segin-starmobile.png new file mode 100644 index 00000000000..f4cab89a203 Binary files /dev/null and b/public/images/pokemon/shiny/966-segin-starmobile.png differ diff --git a/public/images/pokemon_icons_9.json b/public/images/pokemon_icons_9.json index 26e28eedae0..01994a41a02 100644 --- a/public/images/pokemon_icons_9.json +++ b/public/images/pokemon_icons_9.json @@ -4,8 +4,8 @@ "image": "pokemon_icons_9.png", "format": "RGBA8888", "size": { - "w": 252, - "h": 591 + "w": 255, + "h": 646 }, "scale": 1, "frames": [ @@ -382,7 +382,7 @@ }, "frame": { "x": 0, - "y": 270, + "y": 300, "w": 30, "h": 30 } @@ -429,27 +429,6 @@ "h": 27 } }, - { - "filename": "8901", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 30, - "h": 28 - }, - "frame": { - "x": 222, - "y": 0, - "w": 30, - "h": 28 - } - }, { "filename": "1020", "rotated": false, @@ -528,12 +507,33 @@ "h": 26 }, "frame": { - "x": 126, - "y": 28, + "x": 222, + "y": 0, "w": 32, "h": 26 } }, + { + "filename": "8901", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 30, + "h": 28 + }, + "frame": { + "x": 0, + "y": 330, + "w": 30, + "h": 28 + } + }, { "filename": "8901s", "rotated": false, @@ -550,7 +550,7 @@ }, "frame": { "x": 0, - "y": 300, + "y": 358, "w": 30, "h": 28 } @@ -571,7 +571,7 @@ }, "frame": { "x": 0, - "y": 328, + "y": 386, "w": 27, "h": 30 } @@ -592,7 +592,7 @@ }, "frame": { "x": 0, - "y": 358, + "y": 416, "w": 27, "h": 30 } @@ -611,6 +611,27 @@ "w": 32, "h": 25 }, + "frame": { + "x": 126, + "y": 28, + "w": 32, + "h": 25 + } + }, + { + "filename": "984s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 32, + "h": 25 + }, "frame": { "x": 158, "y": 27, @@ -619,7 +640,7 @@ } }, { - "filename": "984s", + "filename": "1014", "rotated": false, "trimmed": true, "sourceSize": { @@ -640,7 +661,7 @@ } }, { - "filename": "992", + "filename": "1014s", "rotated": false, "trimmed": true, "sourceSize": { @@ -648,16 +669,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 6, - "y": 2, - "w": 30, - "h": 26 + "x": 4, + "y": 3, + "w": 32, + "h": 25 }, "frame": { "x": 222, - "y": 28, - "w": 30, - "h": 26 + "y": 26, + "w": 32, + "h": 25 } }, { @@ -676,7 +697,7 @@ }, "frame": { "x": 0, - "y": 388, + "y": 446, "w": 27, "h": 29 } @@ -697,7 +718,7 @@ }, "frame": { "x": 0, - "y": 417, + "y": 475, "w": 27, "h": 29 } @@ -718,7 +739,7 @@ }, "frame": { "x": 0, - "y": 446, + "y": 504, "w": 29, "h": 28 } @@ -739,7 +760,7 @@ }, "frame": { "x": 0, - "y": 474, + "y": 532, "w": 29, "h": 28 } @@ -760,7 +781,7 @@ }, "frame": { "x": 0, - "y": 502, + "y": 560, "w": 29, "h": 27 } @@ -781,7 +802,7 @@ }, "frame": { "x": 0, - "y": 529, + "y": 587, "w": 29, "h": 27 } @@ -802,7 +823,7 @@ }, "frame": { "x": 0, - "y": 556, + "y": 614, "w": 28, "h": 28 } @@ -828,90 +849,6 @@ "h": 21 } }, - { - "filename": "975s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 32, - "h": 21 - }, - "frame": { - "x": 126, - "y": 54, - "w": 32, - "h": 21 - } - }, - { - "filename": "1014", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 32, - "h": 25 - }, - "frame": { - "x": 158, - "y": 52, - "w": 32, - "h": 25 - } - }, - { - "filename": "1014s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 32, - "h": 25 - }, - "frame": { - "x": 190, - "y": 52, - "w": 32, - "h": 25 - } - }, - { - "filename": "992s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 2, - "w": 30, - "h": 26 - }, - "frame": { - "x": 222, - "y": 54, - "w": 30, - "h": 26 - } - }, { "filename": "1024-terastal", "rotated": false, @@ -926,11 +863,95 @@ "w": 32, "h": 22 }, + "frame": { + "x": 126, + "y": 53, + "w": 32, + "h": 22 + } + }, + { + "filename": "1025", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 32, + "h": 24 + }, + "frame": { + "x": 158, + "y": 52, + "w": 32, + "h": 24 + } + }, + { + "filename": "1025s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 32, + "h": 24 + }, + "frame": { + "x": 190, + "y": 52, + "w": 32, + "h": 24 + } + }, + { + "filename": "992", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 2, + "w": 30, + "h": 26 + }, + "frame": { + "x": 222, + "y": 51, + "w": 30, + "h": 26 + } + }, + { + "filename": "975s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 4, + "y": 7, + "w": 32, + "h": 21 + }, "frame": { "x": 93, "y": 75, "w": 32, - "h": 22 + "h": 21 } }, { @@ -955,7 +976,7 @@ } }, { - "filename": "1025", + "filename": "992s", "rotated": false, "trimmed": true, "sourceSize": { @@ -963,37 +984,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 4, - "y": 4, - "w": 32, - "h": 24 + "x": 6, + "y": 2, + "w": 30, + "h": 26 }, "frame": { "x": 157, - "y": 77, - "w": 32, - "h": 24 - } - }, - { - "filename": "1025s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 4, - "y": 4, - "w": 32, - "h": 24 - }, - "frame": { - "x": 189, - "y": 77, - "w": 32, - "h": 24 + "y": 76, + "w": 30, + "h": 26 } }, { @@ -1011,8 +1011,29 @@ "h": 25 }, "frame": { - "x": 221, - "y": 80, + "x": 187, + "y": 76, + "w": 30, + "h": 25 + } + }, + { + "filename": "993s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 2, + "w": 30, + "h": 25 + }, + "frame": { + "x": 217, + "y": 77, "w": 30, "h": 25 } @@ -1033,7 +1054,7 @@ }, "frame": { "x": 27, - "y": 328, + "y": 386, "w": 23, "h": 30 } @@ -1054,7 +1075,7 @@ }, "frame": { "x": 27, - "y": 358, + "y": 416, "w": 23, "h": 30 } @@ -1075,7 +1096,7 @@ }, "frame": { "x": 27, - "y": 388, + "y": 446, "w": 25, "h": 30 } @@ -1096,7 +1117,7 @@ }, "frame": { "x": 27, - "y": 418, + "y": 476, "w": 25, "h": 28 } @@ -1117,7 +1138,7 @@ }, "frame": { "x": 29, - "y": 446, + "y": 504, "w": 25, "h": 30 } @@ -1138,7 +1159,7 @@ }, "frame": { "x": 29, - "y": 476, + "y": 534, "w": 25, "h": 28 } @@ -1159,7 +1180,7 @@ }, "frame": { "x": 29, - "y": 504, + "y": 562, "w": 26, "h": 28 } @@ -1180,7 +1201,7 @@ }, "frame": { "x": 29, - "y": 532, + "y": 590, "w": 27, "h": 26 } @@ -1201,32 +1222,11 @@ }, "frame": { "x": 28, - "y": 558, + "y": 616, "w": 28, "h": 28 } }, - { - "filename": "993s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 2, - "w": 30, - "h": 25 - }, - "frame": { - "x": 62, - "y": 86, - "w": 30, - "h": 25 - } - }, { "filename": "924", "rotated": false, @@ -1242,8 +1242,8 @@ "h": 20 }, "frame": { - "x": 92, - "y": 97, + "x": 62, + "y": 86, "w": 29, "h": 20 } @@ -1263,8 +1263,8 @@ "h": 20 }, "frame": { - "x": 121, - "y": 97, + "x": 61, + "y": 106, "w": 29, "h": 20 } @@ -1284,8 +1284,8 @@ "h": 22 }, "frame": { - "x": 150, - "y": 101, + "x": 91, + "y": 96, "w": 29, "h": 22 } @@ -1305,33 +1305,12 @@ "h": 22 }, "frame": { - "x": 179, - "y": 101, + "x": 120, + "y": 97, "w": 29, "h": 22 } }, - { - "filename": "935", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 7, - "w": 13, - "h": 21 - }, - "frame": { - "x": 208, - "y": 101, - "w": 13, - "h": 21 - } - }, { "filename": "925-three", "rotated": false, @@ -1347,8 +1326,8 @@ "h": 20 }, "frame": { - "x": 221, - "y": 105, + "x": 149, + "y": 102, "w": 29, "h": 20 } @@ -1368,54 +1347,12 @@ "h": 20 }, "frame": { - "x": 61, - "y": 111, + "x": 90, + "y": 118, "w": 29, "h": 20 } }, - { - "filename": "976", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 29, - "h": 18 - }, - "frame": { - "x": 90, - "y": 117, - "w": 29, - "h": 18 - } - }, - { - "filename": "976s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 29, - "h": 18 - }, - "frame": { - "x": 119, - "y": 117, - "w": 29, - "h": 18 - } - }, { "filename": "1022", "rotated": false, @@ -1431,8 +1368,8 @@ "h": 25 }, "frame": { - "x": 148, - "y": 123, + "x": 119, + "y": 119, "w": 29, "h": 25 } @@ -1452,12 +1389,33 @@ "h": 25 }, "frame": { - "x": 177, - "y": 123, + "x": 148, + "y": 122, "w": 29, "h": 25 } }, + { + "filename": "976", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 5, + "y": 10, + "w": 29, + "h": 18 + }, + "frame": { + "x": 31, + "y": 118, + "w": 29, + "h": 18 + } + }, { "filename": "8128-blaze", "rotated": false, @@ -1473,54 +1431,12 @@ "h": 27 }, "frame": { - "x": 206, - "y": 125, + "x": 30, + "y": 136, "w": 29, "h": 27 } }, - { - "filename": "913", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 5, - "w": 17, - "h": 23 - }, - "frame": { - "x": 235, - "y": 125, - "w": 17, - "h": 23 - } - }, - { - "filename": "913s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 5, - "w": 17, - "h": 23 - }, - "frame": { - "x": 235, - "y": 148, - "w": 17, - "h": 23 - } - }, { "filename": "8128s-blaze", "rotated": false, @@ -1536,8 +1452,8 @@ "h": 27 }, "frame": { - "x": 31, - "y": 118, + "x": 30, + "y": 163, "w": 29, "h": 27 } @@ -1558,7 +1474,7 @@ }, "frame": { "x": 30, - "y": 145, + "y": 190, "w": 27, "h": 28 } @@ -1579,7 +1495,7 @@ }, "frame": { "x": 30, - "y": 173, + "y": 218, "w": 27, "h": 28 } @@ -1600,7 +1516,7 @@ }, "frame": { "x": 30, - "y": 201, + "y": 246, "w": 26, "h": 28 } @@ -1621,7 +1537,7 @@ }, "frame": { "x": 30, - "y": 229, + "y": 274, "w": 27, "h": 26 } @@ -1642,7 +1558,7 @@ }, "frame": { "x": 30, - "y": 255, + "y": 300, "w": 25, "h": 27 } @@ -1663,13 +1579,13 @@ }, "frame": { "x": 30, - "y": 282, + "y": 327, "w": 25, "h": 27 } }, { - "filename": "916", + "filename": "964-hero", "rotated": false, "trimmed": true, "sourceSize": { @@ -1677,20 +1593,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 25, - "h": 19 + "x": 9, + "y": 0, + "w": 22, + "h": 29 }, "frame": { "x": 30, - "y": 309, - "w": 25, - "h": 19 + "y": 354, + "w": 22, + "h": 29 } }, { - "filename": "911", + "filename": "976s", "rotated": false, "trimmed": true, "sourceSize": { @@ -1698,16 +1614,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 28, - "h": 23 + "x": 5, + "y": 10, + "w": 29, + "h": 18 }, "frame": { "x": 60, - "y": 131, - "w": 28, - "h": 23 + "y": 126, + "w": 29, + "h": 18 } }, { @@ -1724,9 +1640,51 @@ "w": 28, "h": 24 }, + "frame": { + "x": 59, + "y": 144, + "w": 28, + "h": 24 + } + }, + { + "filename": "911", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 28, + "h": 23 + }, + "frame": { + "x": 59, + "y": 168, + "w": 28, + "h": 23 + } + }, + { + "filename": "8128s-aqua", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 28, + "h": 24 + }, "frame": { "x": 57, - "y": 154, + "y": 191, "w": 28, "h": 24 } @@ -1747,13 +1705,13 @@ }, "frame": { "x": 57, - "y": 178, + "y": 215, "w": 28, "h": 23 } }, { - "filename": "968", + "filename": "950", "rotated": false, "trimmed": true, "sourceSize": { @@ -1761,37 +1719,58 @@ "h": 30 }, "spriteSourceSize": { - "x": 8, - "y": 0, - "w": 23, - "h": 28 - }, - "frame": { - "x": 56, - "y": 201, - "w": 23, - "h": 28 - } - }, - { - "filename": "964-hero", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 0, - "w": 22, - "h": 29 + "x": 6, + "y": 11, + "w": 28, + "h": 17 }, "frame": { "x": 57, - "y": 229, - "w": 22, - "h": 29 + "y": 238, + "w": 28, + "h": 17 + } + }, + { + "filename": "916", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 9, + "w": 25, + "h": 19 + }, + "frame": { + "x": 56, + "y": 255, + "w": 25, + "h": 19 + } + }, + { + "filename": "998", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 2, + "w": 25, + "h": 26 + }, + "frame": { + "x": 57, + "y": 274, + "w": 25, + "h": 26 } }, { @@ -1810,13 +1789,55 @@ }, "frame": { "x": 55, - "y": 258, + "y": 300, "w": 22, "h": 29 } }, { - "filename": "999", + "filename": "914", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 3, + "w": 24, + "h": 25 + }, + "frame": { + "x": 55, + "y": 329, + "w": 24, + "h": 25 + } + }, + { + "filename": "968", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 0, + "w": 23, + "h": 28 + }, + "frame": { + "x": 52, + "y": 354, + "w": 23, + "h": 28 + } + }, + { + "filename": "954", "rotated": false, "trimmed": true, "sourceSize": { @@ -1826,16 +1847,100 @@ "spriteSourceSize": { "x": 9, "y": 0, - "w": 22, + "w": 21, "h": 29 }, "frame": { - "x": 55, - "y": 287, - "w": 22, + "x": 77, + "y": 300, + "w": 21, "h": 29 } }, + { + "filename": "908", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 2, + "w": 20, + "h": 26 + }, + "frame": { + "x": 79, + "y": 329, + "w": 20, + "h": 26 + } + }, + { + "filename": "1016", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 1, + "w": 24, + "h": 27 + }, + "frame": { + "x": 75, + "y": 355, + "w": 24, + "h": 27 + } + }, + { + "filename": "950s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 11, + "w": 28, + "h": 17 + }, + "frame": { + "x": 89, + "y": 138, + "w": 28, + "h": 17 + } + }, + { + "filename": "968s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 0, + "w": 23, + "h": 28 + }, + "frame": { + "x": 87, + "y": 155, + "w": 23, + "h": 28 + } + }, { "filename": "990", "rotated": false, @@ -1851,8 +1956,8 @@ "h": 23 }, "frame": { - "x": 88, - "y": 135, + "x": 117, + "y": 144, "w": 28, "h": 23 } @@ -1872,33 +1977,12 @@ "h": 23 }, "frame": { - "x": 116, - "y": 135, + "x": 145, + "y": 147, "w": 28, "h": 23 } }, - { - "filename": "8128s-aqua", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 28, - "h": 24 - }, - "frame": { - "x": 85, - "y": 158, - "w": 28, - "h": 24 - } - }, { "filename": "972", "rotated": false, @@ -1914,8 +1998,8 @@ "h": 22 }, "frame": { - "x": 113, - "y": 158, + "x": 110, + "y": 167, "w": 27, "h": 22 } @@ -1935,14 +2019,14 @@ "h": 22 }, "frame": { - "x": 85, - "y": 182, + "x": 137, + "y": 170, "w": 27, "h": 22 } }, { - "filename": "968s", + "filename": "947", "rotated": false, "trimmed": true, "sourceSize": { @@ -1951,36 +2035,15 @@ }, "spriteSourceSize": { "x": 8, - "y": 0, + "y": 6, "w": 23, - "h": 28 + "h": 22 }, "frame": { - "x": 79, - "y": 204, + "x": 87, + "y": 183, "w": 23, - "h": 28 - } - }, - { - "filename": "998", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 25, - "h": 26 - }, - "frame": { - "x": 79, - "y": 232, - "w": 25, - "h": 26 + "h": 22 } }, { @@ -1998,14 +2061,14 @@ "h": 26 }, "frame": { - "x": 77, - "y": 258, + "x": 85, + "y": 205, "w": 25, "h": 26 } }, { - "filename": "999s", + "filename": "985", "rotated": false, "trimmed": true, "sourceSize": { @@ -2014,120 +2077,15 @@ }, "spriteSourceSize": { "x": 9, - "y": 0, - "w": 22, - "h": 29 + "y": 7, + "w": 27, + "h": 21 }, "frame": { - "x": 77, - "y": 284, - "w": 22, - "h": 29 - } - }, - { - "filename": "936", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 0, - "w": 20, - "h": 28 - }, - "frame": { - "x": 102, - "y": 204, - "w": 20, - "h": 28 - } - }, - { - "filename": "908", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 2, - "w": 20, - "h": 26 - }, - "frame": { - "x": 104, - "y": 232, - "w": 20, - "h": 26 - } - }, - { - "filename": "982", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 2, - "w": 22, - "h": 26 - }, - "frame": { - "x": 102, - "y": 258, - "w": 22, - "h": 26 - } - }, - { - "filename": "1016", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 1, - "w": 24, - "h": 27 - }, - "frame": { - "x": 99, - "y": 284, - "w": 24, - "h": 27 - } - }, - { - "filename": "1017-hearthflame-mask", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 25, - "h": 24 - }, - "frame": { - "x": 113, - "y": 180, - "w": 25, - "h": 24 + "x": 110, + "y": 189, + "w": 27, + "h": 21 } }, { @@ -2145,77 +2103,14 @@ "h": 24 }, "frame": { - "x": 113, - "y": 180, + "x": 85, + "y": 231, "w": 25, "h": 24 } }, { - "filename": "1017s-hearthflame-mask", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 25, - "h": 24 - }, - "frame": { - "x": 113, - "y": 180, - "w": 25, - "h": 24 - } - }, - { - "filename": "1017s-hearthflame-mask-tera", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 25, - "h": 24 - }, - "frame": { - "x": 113, - "y": 180, - "w": 25, - "h": 24 - } - }, - { - "filename": "936s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 0, - "w": 20, - "h": 28 - }, - "frame": { - "x": 122, - "y": 204, - "w": 20, - "h": 28 - } - }, - { - "filename": "954", + "filename": "999", "rotated": false, "trimmed": true, "sourceSize": { @@ -2225,18 +2120,18 @@ "spriteSourceSize": { "x": 9, "y": 0, - "w": 21, + "w": 22, "h": 29 }, "frame": { - "x": 124, - "y": 232, - "w": 21, + "x": 110, + "y": 210, + "w": 22, "h": 29 } }, { - "filename": "914", + "filename": "916s", "rotated": false, "trimmed": true, "sourceSize": { @@ -2244,57 +2139,57 @@ "h": 30 }, "spriteSourceSize": { - "x": 8, - "y": 3, - "w": 24, - "h": 25 - }, - "frame": { - "x": 124, - "y": 261, - "w": 24, - "h": 25 - } - }, - { - "filename": "914s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 3, - "w": 24, - "h": 25 - }, - "frame": { - "x": 123, - "y": 286, - "w": 24, - "h": 25 - } - }, - { - "filename": "916-female", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, + "x": 7, + "y": 9, "w": 25, + "h": 19 + }, + "frame": { + "x": 81, + "y": 255, + "w": 25, + "h": 19 + } + }, + { + "filename": "982", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 2, + "w": 22, + "h": 26 + }, + "frame": { + "x": 82, + "y": 274, + "w": 22, + "h": 26 + } + }, + { + "filename": "985s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 7, + "w": 27, "h": 21 }, "frame": { - "x": 55, - "y": 316, - "w": 25, + "x": 137, + "y": 192, + "w": 27, "h": 21 } }, @@ -2313,14 +2208,182 @@ "h": 27 }, "frame": { - "x": 50, - "y": 337, + "x": 132, + "y": 213, "w": 24, "h": 27 } }, { - "filename": "987", + "filename": "917", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 6, + "w": 22, + "h": 22 + }, + "frame": { + "x": 110, + "y": 239, + "w": 22, + "h": 22 + } + }, + { + "filename": "914s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 3, + "w": 24, + "h": 25 + }, + "frame": { + "x": 132, + "y": 240, + "w": 24, + "h": 25 + } + }, + { + "filename": "956", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 26, + "h": 22 + }, + "frame": { + "x": 106, + "y": 261, + "w": 26, + "h": 22 + } + }, + { + "filename": "916-female", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 132, + "y": 265, + "w": 25, + "h": 21 + } + }, + { + "filename": "1002", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 27, + "h": 21 + }, + "frame": { + "x": 104, + "y": 283, + "w": 27, + "h": 21 + } + }, + { + "filename": "956s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 26, + "h": 22 + }, + "frame": { + "x": 131, + "y": 286, + "w": 26, + "h": 22 + } + }, + { + "filename": "1017-hearthflame-mask", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 4, + "w": 25, + "h": 24 + }, + "frame": { + "x": 98, + "y": 304, + "w": 25, + "h": 24 + } + }, + { + "filename": "999s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 0, + "w": 22, + "h": 29 + }, + "frame": { + "x": 99, + "y": 328, + "w": 22, + "h": 29 + } + }, + { + "filename": "982s", "rotated": false, "trimmed": true, "sourceSize": { @@ -2329,15 +2392,36 @@ }, "spriteSourceSize": { "x": 10, - "y": 4, - "w": 24, - "h": 24 + "y": 2, + "w": 22, + "h": 26 }, "frame": { - "x": 50, - "y": 364, - "w": 24, - "h": 24 + "x": 99, + "y": 357, + "w": 22, + "h": 26 + } + }, + { + "filename": "1002s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 27, + "h": 21 + }, + "frame": { + "x": 123, + "y": 308, + "w": 27, + "h": 21 } }, { @@ -2355,8 +2439,8 @@ "h": 29 }, "frame": { - "x": 52, - "y": 388, + "x": 121, + "y": 329, "w": 21, "h": 29 } @@ -2376,14 +2460,14 @@ "h": 27 }, "frame": { - "x": 52, - "y": 417, + "x": 121, + "y": 358, "w": 22, "h": 27 } }, { - "filename": "1023", + "filename": "936", "rotated": false, "trimmed": true, "sourceSize": { @@ -2392,19 +2476,19 @@ }, "spriteSourceSize": { "x": 10, - "y": 1, + "y": 0, "w": 20, "h": 28 }, "frame": { - "x": 54, - "y": 444, + "x": 164, + "y": 170, "w": 20, "h": 28 } }, { - "filename": "1023s", + "filename": "913", "rotated": false, "trimmed": true, "sourceSize": { @@ -2412,583 +2496,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, - "y": 1, - "w": 20, - "h": 28 + "x": 11, + "y": 5, + "w": 17, + "h": 23 }, "frame": { - "x": 54, - "y": 472, - "w": 20, - "h": 28 - } - }, - { - "filename": "1000s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 1, - "w": 22, - "h": 27 - }, - "frame": { - "x": 55, - "y": 500, - "w": 22, - "h": 27 - } - }, - { - "filename": "1006", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 1, - "w": 22, - "h": 27 - }, - "frame": { - "x": 56, - "y": 527, - "w": 22, - "h": 27 - } - }, - { - "filename": "1006s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 1, - "w": 22, - "h": 27 - }, - "frame": { - "x": 56, - "y": 554, - "w": 22, - "h": 27 - } - }, - { - "filename": "908s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 2, - "w": 20, - "h": 26 - }, - "frame": { - "x": 80, - "y": 313, - "w": 20, - "h": 26 - } - }, - { - "filename": "956", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 26, - "h": 22 - }, - "frame": { - "x": 100, - "y": 311, - "w": 26, - "h": 22 - } - }, - { - "filename": "917", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 22, - "h": 22 - }, - "frame": { - "x": 126, - "y": 311, - "w": 22, - "h": 22 - } - }, - { - "filename": "956s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 26, - "h": 22 - }, - "frame": { - "x": 74, - "y": 339, - "w": 26, - "h": 22 - } - }, - { - "filename": "982s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 2, - "w": 22, - "h": 26 - }, - "frame": { - "x": 100, - "y": 333, - "w": 22, - "h": 26 - } - }, - { - "filename": "987s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 74, - "y": 361, - "w": 24, - "h": 24 - } - }, - { - "filename": "1012-artisan", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 26, - "h": 22 - }, - "frame": { - "x": 122, - "y": 333, - "w": 26, - "h": 22 - } - }, - { - "filename": "1012-counterfeit", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 26, - "h": 22 - }, - "frame": { - "x": 122, - "y": 333, - "w": 26, - "h": 22 - } - }, - { - "filename": "950", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 28, - "h": 17 - }, - "frame": { - "x": 144, - "y": 148, - "w": 28, - "h": 17 - } - }, - { - "filename": "950s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 28, - "h": 17 - }, - "frame": { - "x": 172, - "y": 148, - "w": 28, - "h": 17 - } - }, - { - "filename": "985", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 7, - "w": 27, - "h": 21 - }, - "frame": { - "x": 140, - "y": 165, - "w": 27, - "h": 21 - } - }, - { - "filename": "985s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 7, - "w": 27, - "h": 21 - }, - "frame": { - "x": 167, - "y": 165, - "w": 27, - "h": 21 - } - }, - { - "filename": "953", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 12, - "w": 24, - "h": 16 - }, - "frame": { - "x": 138, - "y": 186, - "w": 24, - "h": 16 - } - }, - { - "filename": "1010", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 2, - "w": 21, - "h": 26 - }, - "frame": { - "x": 142, - "y": 202, - "w": 21, - "h": 26 - } - }, - { - "filename": "953s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 12, - "w": 24, - "h": 16 - }, - "frame": { - "x": 162, - "y": 186, - "w": 24, - "h": 16 - } - }, - { - "filename": "1010s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 2, - "w": 21, - "h": 26 - }, - "frame": { - "x": 163, - "y": 202, - "w": 21, - "h": 26 - } - }, - { - "filename": "1002", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 27, - "h": 21 - }, - "frame": { - "x": 145, - "y": 228, - "w": 27, - "h": 21 - } - }, - { - "filename": "1017-cornerstone-mask", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 148, - "y": 249, - "w": 24, - "h": 24 - } - }, - { - "filename": "1017-cornerstone-mask-tera", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 148, - "y": 249, - "w": 24, - "h": 24 - } - }, - { - "filename": "1017s-cornerstone-mask", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 148, - "y": 249, - "w": 24, - "h": 24 - } - }, - { - "filename": "1017s-cornerstone-mask-tera", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 148, - "y": 249, - "w": 24, - "h": 24 - } - }, - { - "filename": "973", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 15, - "h": 26 - }, - "frame": { - "x": 172, - "y": 228, - "w": 15, - "h": 26 - } - }, - { - "filename": "916s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 25, - "h": 19 - }, - "frame": { - "x": 148, - "y": 273, - "w": 25, - "h": 19 - } - }, - { - "filename": "997", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 9, - "w": 21, - "h": 19 - }, - "frame": { - "x": 147, - "y": 292, - "w": 21, - "h": 19 + "x": 173, + "y": 147, + "w": 17, + "h": 23 } }, { @@ -3006,428 +2523,8 @@ "h": 25 }, "frame": { - "x": 148, - "y": 311, - "w": 20, - "h": 25 - } - }, - { - "filename": "910", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 7, - "w": 21, - "h": 21 - }, - "frame": { - "x": 148, - "y": 336, - "w": 21, - "h": 21 - } - }, - { - "filename": "906", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 18, - "h": 19 - }, - "frame": { - "x": 172, - "y": 254, - "w": 18, - "h": 19 - } - }, - { - "filename": "906s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 18, - "h": 19 - }, - "frame": { - "x": 173, - "y": 273, - "w": 18, - "h": 19 - } - }, - { - "filename": "1017-teal-mask", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 168, - "y": 292, - "w": 24, - "h": 24 - } - }, - { - "filename": "1017-teal-mask-tera", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 168, - "y": 292, - "w": 24, - "h": 24 - } - }, - { - "filename": "1017s-teal-mask", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 168, - "y": 292, - "w": 24, - "h": 24 - } - }, - { - "filename": "1017s-teal-mask-tera", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 168, - "y": 292, - "w": 24, - "h": 24 - } - }, - { - "filename": "943", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 24, - "h": 20 - }, - "frame": { - "x": 168, - "y": 316, - "w": 24, - "h": 20 - } - }, - { - "filename": "916s-female", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 25, - "h": 21 - }, - "frame": { - "x": 169, - "y": 336, - "w": 25, - "h": 21 - } - }, - { - "filename": "1002s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 27, - "h": 21 - }, - "frame": { - "x": 200, - "y": 152, - "w": 27, - "h": 21 - } - }, - { - "filename": "945", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 25, - "h": 22 - }, - "frame": { - "x": 227, - "y": 171, - "w": 25, - "h": 22 - } - }, - { - "filename": "1012s-artisan", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 26, - "h": 22 - }, - "frame": { - "x": 194, - "y": 173, - "w": 26, - "h": 22 - } - }, - { - "filename": "1012s-counterfeit", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 26, - "h": 22 - }, - "frame": { - "x": 194, - "y": 173, - "w": 26, - "h": 22 - } - }, - { - "filename": "973s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 15, - "h": 26 - }, - "frame": { - "x": 184, - "y": 202, - "w": 15, - "h": 26 - } - }, - { - "filename": "918", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 4, - "w": 22, - "h": 24 - }, - "frame": { - "x": 199, - "y": 195, - "w": 22, - "h": 24 - } - }, - { - "filename": "1017-wellspring-mask", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 221, - "y": 193, - "w": 24, - "h": 24 - } - }, - { - "filename": "1017-wellspring-mask-tera", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 221, - "y": 193, - "w": 24, - "h": 24 - } - }, - { - "filename": "1017s-wellspring-mask", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 221, - "y": 193, - "w": 24, - "h": 24 - } - }, - { - "filename": "1017s-wellspring-mask-tera", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 221, - "y": 193, - "w": 24, - "h": 24 - } - }, - { - "filename": "949s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 3, - "w": 20, - "h": 25 - }, - "frame": { - "x": 187, - "y": 228, + "x": 177, + "y": 122, "w": 20, "h": 25 } @@ -3447,138 +2544,12 @@ "h": 20 }, "frame": { - "x": 190, - "y": 253, + "x": 178, + "y": 102, "w": 20, "h": 20 } }, - { - "filename": "967", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 9, - "w": 20, - "h": 19 - }, - "frame": { - "x": 191, - "y": 273, - "w": 20, - "h": 19 - } - }, - { - "filename": "962", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 3, - "w": 19, - "h": 25 - }, - "frame": { - "x": 192, - "y": 292, - "w": 19, - "h": 25 - } - }, - { - "filename": "967s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 9, - "w": 20, - "h": 19 - }, - "frame": { - "x": 192, - "y": 317, - "w": 20, - "h": 19 - } - }, - { - "filename": "910s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 7, - "w": 21, - "h": 21 - }, - "frame": { - "x": 194, - "y": 336, - "w": 21, - "h": 21 - } - }, - { - "filename": "962s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 3, - "w": 19, - "h": 25 - }, - "frame": { - "x": 207, - "y": 219, - "w": 19, - "h": 25 - } - }, - { - "filename": "918s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 4, - "w": 22, - "h": 24 - }, - "frame": { - "x": 226, - "y": 217, - "w": 22, - "h": 24 - } - }, { "filename": "923", "rotated": false, @@ -3594,77 +2565,14 @@ "h": 24 }, "frame": { - "x": 210, - "y": 244, + "x": 198, + "y": 101, "w": 19, "h": 24 } }, { - "filename": "961", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 23, - "h": 23 - }, - "frame": { - "x": 229, - "y": 241, - "w": 23, - "h": 23 - } - }, - { - "filename": "961s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 23, - "h": 23 - }, - "frame": { - "x": 229, - "y": 264, - "w": 23, - "h": 23 - } - }, - { - "filename": "909", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 18, - "h": 19 - }, - "frame": { - "x": 211, - "y": 268, - "w": 18, - "h": 19 - } - }, - { - "filename": "945s", + "filename": "1012-artisan", "rotated": false, "trimmed": true, "sourceSize": { @@ -3674,16 +2582,58 @@ "spriteSourceSize": { "x": 7, "y": 6, - "w": 25, + "w": 26, "h": 22 }, "frame": { - "x": 211, - "y": 287, - "w": 25, + "x": 217, + "y": 102, + "w": 26, "h": 22 } }, + { + "filename": "908s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 2, + "w": 20, + "h": 26 + }, + "frame": { + "x": 197, + "y": 125, + "w": 20, + "h": 26 + } + }, + { + "filename": "1000s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 1, + "w": 22, + "h": 27 + }, + "frame": { + "x": 217, + "y": 124, + "w": 22, + "h": 27 + } + }, { "filename": "948", "rotated": false, @@ -3699,8 +2649,8 @@ "h": 21 }, "frame": { - "x": 236, - "y": 287, + "x": 239, + "y": 124, "w": 16, "h": 21 } @@ -3720,14 +2670,35 @@ "h": 21 }, "frame": { - "x": 236, - "y": 308, + "x": 239, + "y": 145, "w": 16, "h": 21 } }, { - "filename": "927", + "filename": "1012-counterfeit", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 26, + "h": 22 + }, + "frame": { + "x": 190, + "y": 151, + "w": 26, + "h": 22 + } + }, + { + "filename": "947s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3736,19 +2707,82 @@ }, "spriteSourceSize": { "x": 8, - "y": 7, - "w": 24, - "h": 21 + "y": 6, + "w": 23, + "h": 22 }, "frame": { - "x": 212, - "y": 309, - "w": 24, - "h": 21 + "x": 216, + "y": 151, + "w": 23, + "h": 22 } }, { - "filename": "920", + "filename": "951", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 8, + "w": 16, + "h": 20 + }, + "frame": { + "x": 239, + "y": 166, + "w": 16, + "h": 20 + } + }, + { + "filename": "1017s-hearthflame-mask-tera", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 4, + "w": 25, + "h": 24 + }, + "frame": { + "x": 184, + "y": 173, + "w": 25, + "h": 24 + } + }, + { + "filename": "1017s-hearthflame-mask", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 4, + "w": 25, + "h": 24 + }, + "frame": { + "x": 209, + "y": 173, + "w": 25, + "h": 24 + } + }, + { + "filename": "1010", "rotated": false, "trimmed": true, "sourceSize": { @@ -3757,19 +2791,19 @@ }, "spriteSourceSize": { "x": 9, - "y": 5, - "w": 22, - "h": 23 + "y": 2, + "w": 21, + "h": 26 }, "frame": { - "x": 215, - "y": 330, - "w": 22, - "h": 23 + "x": 234, + "y": 186, + "w": 21, + "h": 26 } }, { - "filename": "912", + "filename": "936s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3777,20 +2811,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 13, - "y": 9, - "w": 15, - "h": 19 + "x": 10, + "y": 0, + "w": 20, + "h": 28 }, "frame": { - "x": 237, - "y": 329, - "w": 15, - "h": 19 + "x": 156, + "y": 213, + "w": 20, + "h": 28 } }, { - "filename": "912s", + "filename": "963", "rotated": false, "trimmed": true, "sourceSize": { @@ -3798,16 +2832,79 @@ "h": 30 }, "spriteSourceSize": { - "x": 13, - "y": 9, - "w": 15, - "h": 19 + "x": 9, + "y": 13, + "w": 22, + "h": 15 }, "frame": { - "x": 237, - "y": 348, - "w": 15, - "h": 19 + "x": 164, + "y": 198, + "w": 22, + "h": 15 + } + }, + { + "filename": "918", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 4, + "w": 22, + "h": 24 + }, + "frame": { + "x": 156, + "y": 241, + "w": 22, + "h": 24 + } + }, + { + "filename": "1006", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 22, + "h": 27 + }, + "frame": { + "x": 157, + "y": 265, + "w": 22, + "h": 27 + } + }, + { + "filename": "1012s-artisan", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 26, + "h": 22 + }, + "frame": { + "x": 186, + "y": 197, + "w": 26, + "h": 22 } }, { @@ -3825,14 +2922,14 @@ "h": 22 }, "frame": { - "x": 215, - "y": 353, + "x": 212, + "y": 197, "w": 22, "h": 22 } }, { - "filename": "960", + "filename": "1010s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3840,16 +2937,268 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, - "y": 10, - "w": 15, - "h": 18 + "x": 9, + "y": 2, + "w": 21, + "h": 26 }, "frame": { - "x": 237, - "y": 367, - "w": 15, - "h": 18 + "x": 234, + "y": 212, + "w": 21, + "h": 26 + } + }, + { + "filename": "1012s-counterfeit", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 26, + "h": 22 + }, + "frame": { + "x": 176, + "y": 219, + "w": 26, + "h": 22 + } + }, + { + "filename": "987", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 178, + "y": 241, + "w": 24, + "h": 24 + } + }, + { + "filename": "1006s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 22, + "h": 27 + }, + "frame": { + "x": 202, + "y": 219, + "w": 22, + "h": 27 + } + }, + { + "filename": "987s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 179, + "y": 265, + "w": 24, + "h": 24 + } + }, + { + "filename": "997", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 9, + "w": 21, + "h": 19 + }, + "frame": { + "x": 202, + "y": 246, + "w": 21, + "h": 19 + } + }, + { + "filename": "918s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 4, + "w": 22, + "h": 24 + }, + "frame": { + "x": 203, + "y": 265, + "w": 22, + "h": 24 + } + }, + { + "filename": "916s-female", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 157, + "y": 292, + "w": 25, + "h": 21 + } + }, + { + "filename": "1017-cornerstone-mask-tera", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 182, + "y": 289, + "w": 24, + "h": 24 + } + }, + { + "filename": "923s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 19, + "h": 24 + }, + "frame": { + "x": 206, + "y": 289, + "w": 19, + "h": 24 + } + }, + { + "filename": "1023", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 20, + "h": 28 + }, + "frame": { + "x": 142, + "y": 329, + "w": 20, + "h": 28 + } + }, + { + "filename": "1023s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 20, + "h": 28 + }, + "frame": { + "x": 143, + "y": 357, + "w": 20, + "h": 28 + } + }, + { + "filename": "953", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 12, + "w": 24, + "h": 16 + }, + "frame": { + "x": 150, + "y": 313, + "w": 24, + "h": 16 } }, { @@ -3867,8 +3216,8 @@ "h": 21 }, "frame": { - "x": 122, - "y": 355, + "x": 174, + "y": 313, "w": 25, "h": 21 } @@ -3888,12 +3237,264 @@ "h": 21 }, "frame": { - "x": 147, - "y": 357, + "x": 199, + "y": 313, "w": 25, "h": 21 } }, + { + "filename": "945", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 25, + "h": 22 + }, + "frame": { + "x": 162, + "y": 334, + "w": 25, + "h": 22 + } + }, + { + "filename": "945s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 25, + "h": 22 + }, + "frame": { + "x": 187, + "y": 334, + "w": 25, + "h": 22 + } + }, + { + "filename": "1017-cornerstone-mask", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 163, + "y": 356, + "w": 24, + "h": 24 + } + }, + { + "filename": "1017-teal-mask-tera", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 187, + "y": 356, + "w": 24, + "h": 24 + } + }, + { + "filename": "907", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 17, + "h": 22 + }, + "frame": { + "x": 212, + "y": 334, + "w": 17, + "h": 22 + } + }, + { + "filename": "949s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 3, + "w": 20, + "h": 25 + }, + "frame": { + "x": 211, + "y": 356, + "w": 20, + "h": 25 + } + }, + { + "filename": "1017-teal-mask", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 231, + "y": 238, + "w": 24, + "h": 24 + } + }, + { + "filename": "1017-wellspring-mask-tera", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 231, + "y": 262, + "w": 24, + "h": 24 + } + }, + { + "filename": "1017-wellspring-mask", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 231, + "y": 286, + "w": 24, + "h": 24 + } + }, + { + "filename": "1017s-cornerstone-mask-tera", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 231, + "y": 310, + "w": 24, + "h": 24 + } + }, + { + "filename": "1017s-cornerstone-mask", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 231, + "y": 334, + "w": 24, + "h": 24 + } + }, + { + "filename": "1017s-teal-mask-tera", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 231, + "y": 358, + "w": 24, + "h": 24 + } + }, { "filename": "952", "rotated": false, @@ -3909,182 +3510,14 @@ "h": 22 }, "frame": { - "x": 172, - "y": 357, + "x": 163, + "y": 380, "w": 25, "h": 22 } }, { - "filename": "909s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 18, - "h": 19 - }, - "frame": { - "x": 197, - "y": 357, - "w": 18, - "h": 19 - } - }, - { - "filename": "920s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 100, - "y": 359, - "w": 22, - "h": 23 - } - }, - { - "filename": "952s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 25, - "h": 22 - }, - "frame": { - "x": 122, - "y": 376, - "w": 25, - "h": 22 - } - }, - { - "filename": "966", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 25, - "h": 21 - }, - "frame": { - "x": 147, - "y": 378, - "w": 25, - "h": 21 - } - }, - { - "filename": "966s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 25, - "h": 21 - }, - "frame": { - "x": 172, - "y": 379, - "w": 25, - "h": 21 - } - }, - { - "filename": "923s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 19, - "h": 24 - }, - "frame": { - "x": 197, - "y": 376, - "w": 19, - "h": 24 - } - }, - { - "filename": "941", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 7, - "w": 21, - "h": 21 - }, - "frame": { - "x": 216, - "y": 375, - "w": 21, - "h": 21 - } - }, - { - "filename": "960s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 10, - "w": 15, - "h": 18 - }, - "frame": { - "x": 237, - "y": 385, - "w": 15, - "h": 18 - } - }, - { - "filename": "927s", + "filename": "961", "rotated": false, "trimmed": true, "sourceSize": { @@ -4093,122 +3526,17 @@ }, "spriteSourceSize": { "x": 8, - "y": 7, - "w": 24, - "h": 21 - }, - "frame": { - "x": 98, - "y": 382, - "w": 24, - "h": 21 - } - }, - { - "filename": "943s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 24, - "h": 20 - }, - "frame": { - "x": 74, - "y": 385, - "w": 24, - "h": 20 - } - }, - { - "filename": "986", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, "y": 5, "w": 23, "h": 23 }, "frame": { - "x": 74, - "y": 405, + "x": 188, + "y": 380, "w": 23, "h": 23 } }, - { - "filename": "986s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 5, - "w": 23, - "h": 23 - }, - "frame": { - "x": 74, - "y": 428, - "w": 23, - "h": 23 - } - }, - { - "filename": "947", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 6, - "w": 23, - "h": 22 - }, - "frame": { - "x": 74, - "y": 451, - "w": 23, - "h": 22 - } - }, - { - "filename": "947s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 6, - "w": 23, - "h": 22 - }, - "frame": { - "x": 74, - "y": 473, - "w": 23, - "h": 22 - } - }, { "filename": "991", "rotated": false, @@ -4224,12 +3552,453 @@ "h": 24 }, "frame": { - "x": 77, - "y": 495, + "x": 211, + "y": 381, "w": 20, "h": 24 } }, + { + "filename": "1017s-teal-mask", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 231, + "y": 382, + "w": 24, + "h": 24 + } + }, + { + "filename": "952s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 25, + "h": 22 + }, + "frame": { + "x": 52, + "y": 382, + "w": 25, + "h": 22 + } + }, + { + "filename": "1017s-wellspring-mask-tera", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 50, + "y": 404, + "w": 24, + "h": 24 + } + }, + { + "filename": "920", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 22, + "h": 23 + }, + "frame": { + "x": 77, + "y": 382, + "w": 22, + "h": 23 + } + }, + { + "filename": "920s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 22, + "h": 23 + }, + "frame": { + "x": 99, + "y": 383, + "w": 22, + "h": 23 + } + }, + { + "filename": "966-caph-starmobile", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 121, + "y": 385, + "w": 25, + "h": 21 + } + }, + { + "filename": "907s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 17, + "h": 22 + }, + "frame": { + "x": 146, + "y": 385, + "w": 17, + "h": 22 + } + }, + { + "filename": "966-navi-starmobile", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 74, + "y": 405, + "w": 25, + "h": 21 + } + }, + { + "filename": "966-ruchbah-starmobile", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 99, + "y": 406, + "w": 25, + "h": 21 + } + }, + { + "filename": "910", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 7, + "w": 21, + "h": 21 + }, + "frame": { + "x": 124, + "y": 406, + "w": 21, + "h": 21 + } + }, + { + "filename": "953s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 12, + "w": 24, + "h": 16 + }, + "frame": { + "x": 50, + "y": 428, + "w": 24, + "h": 16 + } + }, + { + "filename": "966-schedar-starmobile", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 74, + "y": 426, + "w": 25, + "h": 21 + } + }, + { + "filename": "966-segin-starmobile", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 99, + "y": 427, + "w": 25, + "h": 21 + } + }, + { + "filename": "910s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 7, + "w": 21, + "h": 21 + }, + "frame": { + "x": 124, + "y": 427, + "w": 21, + "h": 21 + } + }, + { + "filename": "962", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 3, + "w": 19, + "h": 25 + }, + "frame": { + "x": 145, + "y": 407, + "w": 19, + "h": 25 + } + }, + { + "filename": "1017s-wellspring-mask", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 164, + "y": 402, + "w": 24, + "h": 24 + } + }, + { + "filename": "961s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 23, + "h": 23 + }, + "frame": { + "x": 188, + "y": 403, + "w": 23, + "h": 23 + } + }, + { + "filename": "939", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 20, + "h": 21 + }, + "frame": { + "x": 211, + "y": 405, + "w": 20, + "h": 21 + } + }, + { + "filename": "927", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 7, + "w": 24, + "h": 21 + }, + "frame": { + "x": 231, + "y": 406, + "w": 24, + "h": 21 + } + }, + { + "filename": "962s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 3, + "w": 19, + "h": 25 + }, + "frame": { + "x": 52, + "y": 444, + "w": 19, + "h": 25 + } + }, + { + "filename": "966", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 71, + "y": 447, + "w": 25, + "h": 21 + } + }, { "filename": "991s", "rotated": false, @@ -4245,12 +4014,117 @@ "h": 24 }, "frame": { - "x": 78, - "y": 519, + "x": 52, + "y": 469, "w": 20, "h": 24 } }, + { + "filename": "986", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 23, + "h": 23 + }, + "frame": { + "x": 72, + "y": 468, + "w": 23, + "h": 23 + } + }, + { + "filename": "966s-caph-starmobile", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 96, + "y": 448, + "w": 25, + "h": 21 + } + }, + { + "filename": "927s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 7, + "w": 24, + "h": 21 + }, + "frame": { + "x": 121, + "y": 448, + "w": 24, + "h": 21 + } + }, + { + "filename": "966s-navi-starmobile", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 95, + "y": 469, + "w": 25, + "h": 21 + } + }, + { + "filename": "966s-ruchbah-starmobile", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 120, + "y": 469, + "w": 25, + "h": 21 + } + }, { "filename": "1013-masterpiece", "rotated": false, @@ -4266,8 +4140,8 @@ "h": 24 }, "frame": { - "x": 78, - "y": 543, + "x": 145, + "y": 432, "w": 20, "h": 24 } @@ -4287,14 +4161,14 @@ "h": 24 }, "frame": { - "x": 78, - "y": 543, + "x": 145, + "y": 456, "w": 20, "h": 24 } }, { - "filename": "1013s-masterpiece", + "filename": "966s-schedar-starmobile", "rotated": false, "trimmed": true, "sourceSize": { @@ -4302,62 +4176,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 20, - "h": 24 - }, - "frame": { - "x": 78, - "y": 567, - "w": 20, - "h": 24 - } - }, - { - "filename": "1013s-unremarkable", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 20, - "h": 24 - }, - "frame": { - "x": 78, - "y": 567, - "w": 20, - "h": 24 - } - }, - { - "filename": "941s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, + "x": 7, "y": 7, - "w": 21, + "w": 25, "h": 21 }, "frame": { - "x": 216, - "y": 396, - "w": 21, + "x": 165, + "y": 426, + "w": 25, "h": 21 } }, { - "filename": "996", + "filename": "966s-segin-starmobile", "rotated": false, "trimmed": true, "sourceSize": { @@ -4365,16 +4197,37 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, - "y": 12, - "w": 15, - "h": 16 + "x": 7, + "y": 7, + "w": 25, + "h": 21 }, "frame": { - "x": 237, - "y": 403, - "w": 15, - "h": 16 + "x": 165, + "y": 447, + "w": 25, + "h": 21 + } + }, + { + "filename": "966s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 190, + "y": 426, + "w": 25, + "h": 21 } }, { @@ -4392,12 +4245,33 @@ "h": 21 }, "frame": { - "x": 122, - "y": 398, + "x": 190, + "y": 447, "w": 25, "h": 21 } }, + { + "filename": "973", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 15, + "h": 26 + }, + "frame": { + "x": 215, + "y": 426, + "w": 15, + "h": 26 + } + }, { "filename": "8128s", "rotated": false, @@ -4413,14 +4287,14 @@ "h": 21 }, "frame": { - "x": 147, - "y": 399, + "x": 230, + "y": 427, "w": 25, "h": 21 } }, { - "filename": "1024", + "filename": "943", "rotated": false, "trimmed": true, "sourceSize": { @@ -4434,8 +4308,29 @@ "h": 20 }, "frame": { - "x": 172, - "y": 400, + "x": 165, + "y": 468, + "w": 24, + "h": 20 + } + }, + { + "filename": "943s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 24, + "h": 20 + }, + "frame": { + "x": 189, + "y": 468, "w": 24, "h": 20 } @@ -4455,12 +4350,33 @@ "h": 20 }, "frame": { - "x": 196, - "y": 400, + "x": 145, + "y": 480, "w": 20, "h": 20 } }, + { + "filename": "1024", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 24, + "h": 20 + }, + "frame": { + "x": 165, + "y": 488, + "w": 24, + "h": 20 + } + }, { "filename": "1024s", "rotated": false, @@ -4476,476 +4392,14 @@ "h": 20 }, "frame": { - "x": 98, - "y": 403, + "x": 189, + "y": 488, "w": 24, "h": 20 } }, { - "filename": "939", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 20, - "h": 21 - }, - "frame": { - "x": 97, - "y": 423, - "w": 20, - "h": 21 - } - }, - { - "filename": "939s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 20, - "h": 21 - }, - "frame": { - "x": 97, - "y": 444, - "w": 20, - "h": 21 - } - }, - { - "filename": "971", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 20, - "h": 21 - }, - "frame": { - "x": 97, - "y": 465, - "w": 20, - "h": 21 - } - }, - { - "filename": "971s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 20, - "h": 21 - }, - "frame": { - "x": 97, - "y": 486, - "w": 20, - "h": 21 - } - }, - { - "filename": "969", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 16, - "w": 18, - "h": 12 - }, - "frame": { - "x": 97, - "y": 507, - "w": 18, - "h": 12 - } - }, - { - "filename": "907", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 17, - "h": 22 - }, - "frame": { - "x": 98, - "y": 519, - "w": 17, - "h": 22 - } - }, - { - "filename": "907s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 17, - "h": 22 - }, - "frame": { - "x": 98, - "y": 541, - "w": 17, - "h": 22 - } - }, - { - "filename": "929", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 17, - "h": 22 - }, - "frame": { - "x": 98, - "y": 563, - "w": 17, - "h": 22 - } - }, - { - "filename": "929s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 17, - "h": 22 - }, - "frame": { - "x": 117, - "y": 423, - "w": 17, - "h": 22 - } - }, - { - "filename": "1011", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 5, - "w": 19, - "h": 22 - }, - "frame": { - "x": 117, - "y": 445, - "w": 19, - "h": 22 - } - }, - { - "filename": "1011s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 5, - "w": 19, - "h": 22 - }, - "frame": { - "x": 117, - "y": 467, - "w": 19, - "h": 22 - } - }, - { - "filename": "931-white-plumage", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 20, - "h": 20 - }, - "frame": { - "x": 117, - "y": 489, - "w": 20, - "h": 20 - } - }, - { - "filename": "1004", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 115, - "y": 509, - "w": 21, - "h": 20 - } - }, - { - "filename": "1004s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 8, - "w": 21, - "h": 20 - }, - "frame": { - "x": 115, - "y": 529, - "w": 21, - "h": 20 - } - }, - { - "filename": "931-yellow-plumage", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 20, - "h": 20 - }, - "frame": { - "x": 115, - "y": 549, - "w": 20, - "h": 20 - } - }, - { - "filename": "931s-blue-plumage", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 20, - "h": 20 - }, - "frame": { - "x": 115, - "y": 569, - "w": 20, - "h": 20 - } - }, - { - "filename": "935s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 7, - "w": 13, - "h": 21 - }, - "frame": { - "x": 134, - "y": 419, - "w": 13, - "h": 21 - } - }, - { - "filename": "931s-green-plumage", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 20, - "h": 20 - }, - "frame": { - "x": 147, - "y": 420, - "w": 20, - "h": 20 - } - }, - { - "filename": "931s-white-plumage", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 20, - "h": 20 - }, - "frame": { - "x": 167, - "y": 420, - "w": 20, - "h": 20 - } - }, - { - "filename": "931s-yellow-plumage", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 20, - "h": 20 - }, - "frame": { - "x": 187, - "y": 420, - "w": 20, - "h": 20 - } - }, - { - "filename": "997s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 9, - "w": 21, - "h": 19 - }, - "frame": { - "x": 136, - "y": 440, - "w": 21, - "h": 19 - } - }, - { - "filename": "1015", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 7, - "w": 17, - "h": 21 - }, - "frame": { - "x": 136, - "y": 459, - "w": 17, - "h": 21 - } - }, - { - "filename": "932", + "filename": "906", "rotated": false, "trimmed": true, "sourceSize": { @@ -4959,222 +4413,12 @@ "h": 19 }, "frame": { - "x": 157, - "y": 440, + "x": 215, + "y": 452, "w": 18, "h": 19 } }, - { - "filename": "1015s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 7, - "w": 17, - "h": 21 - }, - "frame": { - "x": 153, - "y": 459, - "w": 17, - "h": 21 - } - }, - { - "filename": "932s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 18, - "h": 19 - }, - "frame": { - "x": 175, - "y": 440, - "w": 18, - "h": 19 - } - }, - { - "filename": "958", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 17, - "h": 20 - }, - "frame": { - "x": 170, - "y": 459, - "w": 17, - "h": 20 - } - }, - { - "filename": "922", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 9, - "w": 17, - "h": 19 - }, - "frame": { - "x": 193, - "y": 440, - "w": 17, - "h": 19 - } - }, - { - "filename": "958s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 17, - "h": 20 - }, - "frame": { - "x": 187, - "y": 459, - "w": 17, - "h": 20 - } - }, - { - "filename": "951", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 8, - "w": 16, - "h": 20 - }, - "frame": { - "x": 207, - "y": 420, - "w": 16, - "h": 20 - } - }, - { - "filename": "922s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 9, - "w": 17, - "h": 19 - }, - "frame": { - "x": 210, - "y": 440, - "w": 17, - "h": 19 - } - }, - { - "filename": "963", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 13, - "w": 22, - "h": 15 - }, - "frame": { - "x": 204, - "y": 459, - "w": 22, - "h": 15 - } - }, - { - "filename": "999-roaming", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 10, - "w": 14, - "h": 18 - }, - "frame": { - "x": 223, - "y": 417, - "w": 14, - "h": 18 - } - }, - { - "filename": "996s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 12, - "w": 15, - "h": 16 - }, - "frame": { - "x": 237, - "y": 419, - "w": 15, - "h": 16 - } - }, { "filename": "963s", "rotated": false, @@ -5190,8 +4434,8 @@ "h": 15 }, "frame": { - "x": 227, - "y": 435, + "x": 233, + "y": 448, "w": 22, "h": 15 } @@ -5211,12 +4455,33 @@ "h": 15 }, "frame": { - "x": 227, - "y": 450, + "x": 233, + "y": 463, "w": 22, "h": 15 } }, + { + "filename": "1013s-masterpiece", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 20, + "h": 24 + }, + "frame": { + "x": 213, + "y": 471, + "w": 20, + "h": 24 + } + }, { "filename": "964s-zero", "rotated": false, @@ -5232,8 +4497,8 @@ "h": 15 }, "frame": { - "x": 226, - "y": 465, + "x": 233, + "y": 478, "w": 22, "h": 15 } @@ -5253,12 +4518,33 @@ "h": 15 }, "frame": { - "x": 204, - "y": 474, + "x": 233, + "y": 493, "w": 22, "h": 15 } }, + { + "filename": "931-white-plumage", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 20, + "h": 20 + }, + "frame": { + "x": 213, + "y": 495, + "w": 20, + "h": 20 + } + }, { "filename": "974s", "rotated": false, @@ -5274,12 +4560,390 @@ "h": 15 }, "frame": { - "x": 226, - "y": 480, + "x": 233, + "y": 508, "w": 22, "h": 15 } }, + { + "filename": "1013s-unremarkable", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 20, + "h": 24 + }, + "frame": { + "x": 54, + "y": 493, + "w": 20, + "h": 24 + } + }, + { + "filename": "986s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 23, + "h": 23 + }, + "frame": { + "x": 54, + "y": 517, + "w": 23, + "h": 23 + } + }, + { + "filename": "941", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 7, + "w": 21, + "h": 21 + }, + "frame": { + "x": 54, + "y": 540, + "w": 21, + "h": 21 + } + }, + { + "filename": "973s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 2, + "w": 15, + "h": 26 + }, + "frame": { + "x": 74, + "y": 491, + "w": 15, + "h": 26 + } + }, + { + "filename": "939s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 20, + "h": 21 + }, + "frame": { + "x": 55, + "y": 561, + "w": 20, + "h": 21 + } + }, + { + "filename": "913s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 5, + "w": 17, + "h": 23 + }, + "frame": { + "x": 77, + "y": 517, + "w": 17, + "h": 23 + } + }, + { + "filename": "1011", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 5, + "w": 19, + "h": 22 + }, + "frame": { + "x": 75, + "y": 540, + "w": 19, + "h": 22 + } + }, + { + "filename": "931-yellow-plumage", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 20, + "h": 20 + }, + "frame": { + "x": 75, + "y": 562, + "w": 20, + "h": 20 + } + }, + { + "filename": "941s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 7, + "w": 21, + "h": 21 + }, + "frame": { + "x": 56, + "y": 582, + "w": 21, + "h": 21 + } + }, + { + "filename": "971", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 20, + "h": 21 + }, + "frame": { + "x": 56, + "y": 603, + "w": 20, + "h": 21 + } + }, + { + "filename": "1011s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 5, + "w": 19, + "h": 22 + }, + "frame": { + "x": 56, + "y": 624, + "w": 19, + "h": 22 + } + }, + { + "filename": "929", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 17, + "h": 22 + }, + "frame": { + "x": 75, + "y": 624, + "w": 17, + "h": 22 + } + }, + { + "filename": "971s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 20, + "h": 21 + }, + "frame": { + "x": 77, + "y": 582, + "w": 20, + "h": 21 + } + }, + { + "filename": "1015", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 7, + "w": 17, + "h": 21 + }, + "frame": { + "x": 76, + "y": 603, + "w": 17, + "h": 21 + } + }, + { + "filename": "929s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 17, + "h": 22 + }, + "frame": { + "x": 92, + "y": 624, + "w": 17, + "h": 22 + } + }, + { + "filename": "1015s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 7, + "w": 17, + "h": 21 + }, + "frame": { + "x": 93, + "y": 603, + "w": 17, + "h": 21 + } + }, + { + "filename": "935", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 7, + "w": 13, + "h": 21 + }, + "frame": { + "x": 89, + "y": 491, + "w": 13, + "h": 21 + } + }, + { + "filename": "1004", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 102, + "y": 490, + "w": 21, + "h": 20 + } + }, { "filename": "980", "rotated": false, @@ -5295,12 +4959,33 @@ "h": 15 }, "frame": { - "x": 137, - "y": 480, + "x": 123, + "y": 490, "w": 22, "h": 15 } }, + { + "filename": "931s-blue-plumage", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 20, + "h": 20 + }, + "frame": { + "x": 145, + "y": 500, + "w": 20, + "h": 20 + } + }, { "filename": "980s", "rotated": false, @@ -5316,12 +5001,285 @@ "h": 15 }, "frame": { - "x": 137, - "y": 495, + "x": 123, + "y": 505, "w": 22, "h": 15 } }, + { + "filename": "997s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 9, + "w": 21, + "h": 19 + }, + "frame": { + "x": 165, + "y": 508, + "w": 21, + "h": 19 + } + }, + { + "filename": "1004s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 8, + "w": 21, + "h": 20 + }, + "frame": { + "x": 186, + "y": 508, + "w": 21, + "h": 20 + } + }, + { + "filename": "931s-green-plumage", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 20, + "h": 20 + }, + "frame": { + "x": 207, + "y": 515, + "w": 20, + "h": 20 + } + }, + { + "filename": "931s-white-plumage", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 20, + "h": 20 + }, + "frame": { + "x": 227, + "y": 523, + "w": 20, + "h": 20 + } + }, + { + "filename": "935s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 7, + "w": 13, + "h": 21 + }, + "frame": { + "x": 94, + "y": 512, + "w": 13, + "h": 21 + } + }, + { + "filename": "951s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 8, + "w": 16, + "h": 20 + }, + "frame": { + "x": 107, + "y": 510, + "w": 16, + "h": 20 + } + }, + { + "filename": "931s-yellow-plumage", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 20, + "h": 20 + }, + "frame": { + "x": 94, + "y": 533, + "w": 20, + "h": 20 + } + }, + { + "filename": "967", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 9, + "w": 20, + "h": 19 + }, + "frame": { + "x": 123, + "y": 520, + "w": 20, + "h": 19 + } + }, + { + "filename": "967s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 9, + "w": 20, + "h": 19 + }, + "frame": { + "x": 143, + "y": 520, + "w": 20, + "h": 19 + } + }, + { + "filename": "970", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 12, + "w": 20, + "h": 16 + }, + "frame": { + "x": 163, + "y": 527, + "w": 20, + "h": 16 + } + }, + { + "filename": "970s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 12, + "w": 20, + "h": 16 + }, + "frame": { + "x": 183, + "y": 528, + "w": 20, + "h": 16 + } + }, + { + "filename": "906s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 9, + "w": 18, + "h": 19 + }, + "frame": { + "x": 95, + "y": 553, + "w": 18, + "h": 19 + } + }, + { + "filename": "958", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 8, + "w": 17, + "h": 20 + }, + "frame": { + "x": 97, + "y": 572, + "w": 17, + "h": 20 + } + }, { "filename": "915", "rotated": false, @@ -5337,8 +5295,8 @@ "h": 17 }, "frame": { - "x": 136, - "y": 510, + "x": 114, + "y": 539, "w": 19, "h": 17 } @@ -5358,96 +5316,12 @@ "h": 17 }, "frame": { - "x": 136, - "y": 527, + "x": 133, + "y": 539, "w": 19, "h": 17 } }, - { - "filename": "951s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 8, - "w": 16, - "h": 20 - }, - "frame": { - "x": 159, - "y": 480, - "w": 16, - "h": 20 - } - }, - { - "filename": "970", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 12, - "w": 20, - "h": 16 - }, - "frame": { - "x": 175, - "y": 479, - "w": 20, - "h": 16 - } - }, - { - "filename": "919", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 13, - "w": 16, - "h": 15 - }, - "frame": { - "x": 159, - "y": 500, - "w": 16, - "h": 15 - } - }, - { - "filename": "970s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 12, - "w": 20, - "h": 16 - }, - "frame": { - "x": 175, - "y": 495, - "w": 20, - "h": 16 - } - }, { "filename": "946", "rotated": false, @@ -5463,12 +5337,96 @@ "h": 16 }, "frame": { - "x": 155, - "y": 515, + "x": 113, + "y": 556, "w": 19, "h": 16 } }, + { + "filename": "909", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 9, + "w": 18, + "h": 19 + }, + "frame": { + "x": 114, + "y": 572, + "w": 18, + "h": 19 + } + }, + { + "filename": "909s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 9, + "w": 18, + "h": 19 + }, + "frame": { + "x": 132, + "y": 556, + "w": 18, + "h": 19 + } + }, + { + "filename": "932", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 9, + "w": 18, + "h": 19 + }, + "frame": { + "x": 132, + "y": 575, + "w": 18, + "h": 19 + } + }, + { + "filename": "938", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 14, + "y": 12, + "w": 11, + "h": 16 + }, + "frame": { + "x": 152, + "y": 539, + "w": 11, + "h": 16 + } + }, { "filename": "942", "rotated": false, @@ -5484,8 +5442,8 @@ "h": 15 }, "frame": { - "x": 155, - "y": 531, + "x": 163, + "y": 543, "w": 19, "h": 15 } @@ -5505,14 +5463,14 @@ "h": 15 }, "frame": { - "x": 136, + "x": 182, "y": 544, "w": 19, "h": 15 } }, { - "filename": "946s", + "filename": "932s", "rotated": false, "trimmed": true, "sourceSize": { @@ -5520,58 +5478,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, - "y": 12, - "w": 19, - "h": 16 + "x": 11, + "y": 9, + "w": 18, + "h": 19 }, "frame": { - "x": 135, - "y": 559, - "w": 19, - "h": 16 - } - }, - { - "filename": "965", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 12, - "w": 19, - "h": 16 - }, - "frame": { - "x": 135, - "y": 575, - "w": 19, - "h": 16 - } - }, - { - "filename": "965s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 12, - "w": 19, - "h": 16 - }, - "frame": { - "x": 155, - "y": 546, - "w": 19, - "h": 16 + "x": 150, + "y": 558, + "w": 18, + "h": 19 } }, { @@ -5589,12 +5505,327 @@ "h": 17 }, "frame": { - "x": 154, - "y": 562, + "x": 150, + "y": 577, "w": 18, "h": 17 } }, + { + "filename": "999-roaming", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 10, + "w": 14, + "h": 18 + }, + "frame": { + "x": 168, + "y": 558, + "w": 14, + "h": 18 + } + }, + { + "filename": "946s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 12, + "w": 19, + "h": 16 + }, + "frame": { + "x": 182, + "y": 559, + "w": 19, + "h": 16 + } + }, + { + "filename": "912", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 9, + "w": 15, + "h": 19 + }, + "frame": { + "x": 168, + "y": 576, + "w": 15, + "h": 19 + } + }, + { + "filename": "958s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 8, + "w": 17, + "h": 20 + }, + "frame": { + "x": 183, + "y": 575, + "w": 17, + "h": 20 + } + }, + { + "filename": "965", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 12, + "w": 19, + "h": 16 + }, + "frame": { + "x": 203, + "y": 535, + "w": 19, + "h": 16 + } + }, + { + "filename": "922", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 9, + "w": 17, + "h": 19 + }, + "frame": { + "x": 201, + "y": 551, + "w": 17, + "h": 19 + } + }, + { + "filename": "912s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 9, + "w": 15, + "h": 19 + }, + "frame": { + "x": 218, + "y": 551, + "w": 15, + "h": 19 + } + }, + { + "filename": "922s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 9, + "w": 17, + "h": 19 + }, + "frame": { + "x": 233, + "y": 543, + "w": 17, + "h": 19 + } + }, + { + "filename": "926", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 13, + "w": 17, + "h": 15 + }, + "frame": { + "x": 233, + "y": 562, + "w": 17, + "h": 15 + } + }, + { + "filename": "965s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 12, + "w": 19, + "h": 16 + }, + "frame": { + "x": 201, + "y": 570, + "w": 19, + "h": 16 + } + }, + { + "filename": "928", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 10, + "w": 13, + "h": 18 + }, + "frame": { + "x": 220, + "y": 570, + "w": 13, + "h": 18 + } + }, + { + "filename": "926s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 13, + "w": 17, + "h": 15 + }, + "frame": { + "x": 233, + "y": 577, + "w": 17, + "h": 15 + } + }, + { + "filename": "969", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 16, + "w": 18, + "h": 12 + }, + "frame": { + "x": 200, + "y": 586, + "w": 18, + "h": 12 + } + }, + { + "filename": "960", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 10, + "w": 15, + "h": 18 + }, + "frame": { + "x": 218, + "y": 588, + "w": 15, + "h": 18 + } + }, + { + "filename": "940", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 14, + "w": 17, + "h": 14 + }, + "frame": { + "x": 233, + "y": 592, + "w": 17, + "h": 14 + } + }, { "filename": "969s", "rotated": false, @@ -5610,8 +5841,8 @@ "h": 12 }, "frame": { - "x": 154, - "y": 579, + "x": 114, + "y": 591, "w": 18, "h": 12 } @@ -5631,35 +5862,14 @@ "h": 17 }, "frame": { - "x": 195, - "y": 489, + "x": 110, + "y": 603, "w": 18, "h": 17 } }, { - "filename": "928", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 10, - "w": 13, - "h": 18 - }, - "frame": { - "x": 213, - "y": 489, - "w": 13, - "h": 18 - } - }, - { - "filename": "926", + "filename": "940s", "rotated": false, "trimmed": true, "sourceSize": { @@ -5668,57 +5878,15 @@ }, "spriteSourceSize": { "x": 11, - "y": 13, + "y": 14, "w": 17, - "h": 15 + "h": 14 }, "frame": { - "x": 226, - "y": 495, + "x": 132, + "y": 594, "w": 17, - "h": 15 - } - }, - { - "filename": "926s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 13, - "w": 17, - "h": 15 - }, - "frame": { - "x": 195, - "y": 506, - "w": 17, - "h": 15 - } - }, - { - "filename": "999s-roaming", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 10, - "w": 14, - "h": 18 - }, - "frame": { - "x": 212, - "y": 507, - "w": 14, - "h": 18 + "h": 14 } }, { @@ -5736,14 +5904,14 @@ "h": 16 }, "frame": { - "x": 226, - "y": 510, + "x": 149, + "y": 594, "w": 17, "h": 16 } }, { - "filename": "940", + "filename": "955s", "rotated": false, "trimmed": true, "sourceSize": { @@ -5752,15 +5920,15 @@ }, "spriteSourceSize": { "x": 11, - "y": 14, + "y": 12, "w": 17, - "h": 14 + "h": 16 }, "frame": { - "x": 175, - "y": 511, + "x": 166, + "y": 595, "w": 17, - "h": 14 + "h": 16 } }, { @@ -5778,12 +5946,54 @@ "h": 18 }, "frame": { - "x": 174, - "y": 525, + "x": 183, + "y": 595, "w": 16, "h": 18 } }, + { + "filename": "919", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 13, + "w": 16, + "h": 15 + }, + "frame": { + "x": 199, + "y": 598, + "w": 16, + "h": 15 + } + }, + { + "filename": "919s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 13, + "w": 16, + "h": 15 + }, + "frame": { + "x": 128, + "y": 608, + "w": 16, + "h": 15 + } + }, { "filename": "921s", "rotated": false, @@ -5799,12 +6009,54 @@ "h": 18 }, "frame": { - "x": 174, - "y": 543, + "x": 144, + "y": 610, "w": 16, "h": 18 } }, + { + "filename": "960s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 10, + "w": 15, + "h": 18 + }, + "frame": { + "x": 109, + "y": 628, + "w": 15, + "h": 18 + } + }, + { + "filename": "999s-roaming", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 10, + "w": 14, + "h": 18 + }, + "frame": { + "x": 124, + "y": 628, + "w": 14, + "h": 18 + } + }, { "filename": "928s", "rotated": false, @@ -5820,8 +6072,8 @@ "h": 18 }, "frame": { - "x": 172, - "y": 562, + "x": 138, + "y": 628, "w": 13, "h": 18 } @@ -5841,8 +6093,8 @@ "h": 17 }, "frame": { - "x": 185, - "y": 561, + "x": 160, + "y": 611, "w": 16, "h": 17 } @@ -5862,138 +6114,12 @@ "h": 17 }, "frame": { - "x": 190, - "y": 525, + "x": 151, + "y": 628, "w": 16, "h": 17 } }, - { - "filename": "955s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 12, - "w": 17, - "h": 16 - }, - "frame": { - "x": 190, - "y": 542, - "w": 17, - "h": 16 - } - }, - { - "filename": "919s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 13, - "w": 16, - "h": 15 - }, - "frame": { - "x": 206, - "y": 525, - "w": 16, - "h": 15 - } - }, - { - "filename": "944", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 13, - "w": 16, - "h": 15 - }, - "frame": { - "x": 207, - "y": 540, - "w": 16, - "h": 15 - } - }, - { - "filename": "940s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 14, - "w": 17, - "h": 14 - }, - "frame": { - "x": 222, - "y": 526, - "w": 17, - "h": 14 - } - }, - { - "filename": "944s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 13, - "w": 16, - "h": 15 - }, - "frame": { - "x": 223, - "y": 540, - "w": 16, - "h": 15 - } - }, - { - "filename": "938", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 14, - "y": 12, - "w": 11, - "h": 16 - }, - "frame": { - "x": 239, - "y": 526, - "w": 11, - "h": 16 - } - }, { "filename": "938s", "rotated": false, @@ -6009,12 +6135,96 @@ "h": 16 }, "frame": { - "x": 239, - "y": 542, + "x": 167, + "y": 628, "w": 11, "h": 16 } }, + { + "filename": "944", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 13, + "w": 16, + "h": 15 + }, + "frame": { + "x": 176, + "y": 613, + "w": 16, + "h": 15 + } + }, + { + "filename": "944s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 13, + "w": 16, + "h": 15 + }, + "frame": { + "x": 192, + "y": 613, + "w": 16, + "h": 15 + } + }, + { + "filename": "996", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 12, + "w": 15, + "h": 16 + }, + "frame": { + "x": 178, + "y": 628, + "w": 15, + "h": 16 + } + }, + { + "filename": "996s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 12, + "w": 15, + "h": 16 + }, + "frame": { + "x": 193, + "y": 628, + "w": 15, + "h": 16 + } + }, { "filename": "978-curly", "rotated": false, @@ -6030,8 +6240,8 @@ "h": 14 }, "frame": { - "x": 207, - "y": 555, + "x": 208, + "y": 613, "w": 15, "h": 14 } @@ -6051,8 +6261,8 @@ "h": 14 }, "frame": { - "x": 222, - "y": 555, + "x": 208, + "y": 627, "w": 15, "h": 14 } @@ -6072,8 +6282,8 @@ "h": 14 }, "frame": { - "x": 237, - "y": 558, + "x": 223, + "y": 606, "w": 15, "h": 14 } @@ -6093,8 +6303,8 @@ "h": 14 }, "frame": { - "x": 201, - "y": 569, + "x": 223, + "y": 620, "w": 15, "h": 14 } @@ -6114,8 +6324,8 @@ "h": 14 }, "frame": { - "x": 216, - "y": 569, + "x": 238, + "y": 606, "w": 15, "h": 14 } @@ -6135,8 +6345,8 @@ "h": 14 }, "frame": { - "x": 231, - "y": 572, + "x": 238, + "y": 620, "w": 15, "h": 14 } @@ -6147,6 +6357,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:d412b44b05c0ac7988fc321b8a4eb571:51dd93a83920102d7a1b879808f62790:6fb417eff82c0971c86b4818772ba292$" + "smartupdate": "$TexturePacker:SmartUpdate:b180859bc4c006d56ee5322ca73fa54e:212d282258f5086ad99b3b2b95f7ec1a:6fb417eff82c0971c86b4818772ba292$" } } diff --git a/public/images/pokemon_icons_9.png b/public/images/pokemon_icons_9.png index 6123a15cbe9..2985fb800d6 100644 Binary files a/public/images/pokemon_icons_9.png and b/public/images/pokemon_icons_9.png differ diff --git a/public/images/trainer/atticus.json b/public/images/trainer/atticus.json new file mode 100644 index 00000000000..95621998bf2 --- /dev/null +++ b/public/images/trainer/atticus.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "atticus.png", + "format": "RGBA8888", + "size": { + "w": 46, + "h": 46 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 21, + "y": 33, + "w": 43, + "h": 46 + }, + "frame": { + "x": 0, + "y": 0, + "w": 43, + "h": 46 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:6dcd7c3d3982793cbca0d6fcd1f9260e:19c44634629fadd9d039d23dc71ec987:d26ede35f15aa571d5a7a2dd2fb868e1$" + } +} diff --git a/public/images/trainer/atticus.png b/public/images/trainer/atticus.png new file mode 100644 index 00000000000..e3e7e870f2b Binary files /dev/null and b/public/images/trainer/atticus.png differ diff --git a/public/images/trainer/eri.json b/public/images/trainer/eri.json new file mode 100644 index 00000000000..fd4daf60437 --- /dev/null +++ b/public/images/trainer/eri.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "eri.png", + "format": "RGBA8888", + "size": { + "w": 74, + "h": 74 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 15, + "y": 5, + "w": 45, + "h": 74 + }, + "frame": { + "x": 0, + "y": 0, + "w": 45, + "h": 74 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:59594ac27e74ec85e2949d12ff680dc2:d65b6b00858ac47b26ef8393a8fa6795:d7f4cd3ff755f8074c14d3006b0c8301$" + } +} diff --git a/public/images/trainer/eri.png b/public/images/trainer/eri.png new file mode 100644 index 00000000000..0c9bdf7b47b Binary files /dev/null and b/public/images/trainer/eri.png differ diff --git a/public/images/trainer/giacomo.json b/public/images/trainer/giacomo.json new file mode 100644 index 00000000000..5eeb2cd685b --- /dev/null +++ b/public/images/trainer/giacomo.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "giacomo.png", + "format": "RGBA8888", + "size": { + "w": 75, + "h": 75 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 23, + "y": 4, + "w": 37, + "h": 75 + }, + "frame": { + "x": 0, + "y": 0, + "w": 37, + "h": 75 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:8c4e7da48e5667abc6d364330268c092:0fa43e58d8a746d3b86cb2dd763719f4:8603cc19e888c8c8de62177f4011577c$" + } +} diff --git a/public/images/trainer/giacomo.png b/public/images/trainer/giacomo.png new file mode 100644 index 00000000000..275f47fad3c Binary files /dev/null and b/public/images/trainer/giacomo.png differ diff --git a/public/images/trainer/mela.json b/public/images/trainer/mela.json new file mode 100644 index 00000000000..c9db18acc5a --- /dev/null +++ b/public/images/trainer/mela.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "mela.png", + "format": "RGBA8888", + "size": { + "w": 78, + "h": 78 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 18, + "y": 1, + "w": 46, + "h": 78 + }, + "frame": { + "x": 0, + "y": 0, + "w": 46, + "h": 78 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:e26d8c926c54c848cef673b3f59f35e7:ff040c2cebb1a92d2ef61dc91c018390:68668cf06383ff459cccaafb6bf56215$" + } +} diff --git a/public/images/trainer/mela.png b/public/images/trainer/mela.png new file mode 100644 index 00000000000..fbb08ed69cf Binary files /dev/null and b/public/images/trainer/mela.png differ diff --git a/public/images/trainer/ortega.json b/public/images/trainer/ortega.json new file mode 100644 index 00000000000..53bab5dba40 --- /dev/null +++ b/public/images/trainer/ortega.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "ortega.png", + "format": "RGBA8888", + "size": { + "w": 69, + "h": 69 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 8, + "y": 10, + "w": 53, + "h": 69 + }, + "frame": { + "x": 0, + "y": 0, + "w": 53, + "h": 69 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:c6ff92d90ed884222095de81d1db9166:a91cf3c83a063f549c52afb42f7ba3b0:c3f9fcec121c8bc93f2b230b20b79c57$" + } +} diff --git a/public/images/trainer/ortega.png b/public/images/trainer/ortega.png new file mode 100644 index 00000000000..7f694c6ded6 Binary files /dev/null and b/public/images/trainer/ortega.png differ diff --git a/public/images/trainer/penny.json b/public/images/trainer/penny.json new file mode 100644 index 00000000000..da64efffa3b --- /dev/null +++ b/public/images/trainer/penny.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "penny.png", + "format": "RGBA8888", + "size": { + "w": 75, + "h": 75 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 24, + "y": 4, + "w": 34, + "h": 75 + }, + "frame": { + "x": 0, + "y": 0, + "w": 34, + "h": 75 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:54f184bf1995a94a78aff33c9a851e6b:a6c9b3fe428b0cd0344b5cf14b999f36:cf221da9747cb8cb356053d3042d8d22$" + } +} diff --git a/public/images/trainer/penny.png b/public/images/trainer/penny.png new file mode 100644 index 00000000000..0e36760e21b Binary files /dev/null and b/public/images/trainer/penny.png differ diff --git a/public/images/trainer/star_grunt_f.json b/public/images/trainer/star_grunt_f.json new file mode 100644 index 00000000000..e26477e3512 --- /dev/null +++ b/public/images/trainer/star_grunt_f.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "star_grunt_f.png", + "format": "RGBA8888", + "size": { + "w": 68, + "h": 68 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 24, + "y": 11, + "w": 30, + "h": 68 + }, + "frame": { + "x": 0, + "y": 0, + "w": 30, + "h": 68 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:b542a1bdd6995584fc776f75d578b434:f03fddece4494ab59698002fe6671972:c6f0e54e24ec5ffaa711700431b1955e$" + } +} diff --git a/public/images/trainer/star_grunt_f.png b/public/images/trainer/star_grunt_f.png new file mode 100644 index 00000000000..6eb63ae1e03 Binary files /dev/null and b/public/images/trainer/star_grunt_f.png differ diff --git a/public/images/trainer/star_grunt_m.json b/public/images/trainer/star_grunt_m.json new file mode 100644 index 00000000000..bf49e3027e6 --- /dev/null +++ b/public/images/trainer/star_grunt_m.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "star_grunt_m.png", + "format": "RGBA8888", + "size": { + "w": 70, + "h": 70 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 24, + "y": 9, + "w": 31, + "h": 70 + }, + "frame": { + "x": 0, + "y": 0, + "w": 31, + "h": 70 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:abc4b0424c37fd55a2bf2e9f5142adce:41a140aa68a1eda61d9a00cab4e07721:a0796711f9e0333796b6629cd43ff8e8$" + } +} diff --git a/public/images/trainer/star_grunt_m.png b/public/images/trainer/star_grunt_m.png new file mode 100644 index 00000000000..a69359eda8e Binary files /dev/null and b/public/images/trainer/star_grunt_m.png differ diff --git a/src/battle-scene.ts b/src/battle-scene.ts index f6e4cffcf1e..f55f1658648 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1,10 +1,10 @@ import Phaser from "phaser"; import UI from "./ui/ui"; -import Pokemon, { PlayerPokemon, EnemyPokemon } from "./field/pokemon"; -import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies } from "./data/pokemon-species"; +import Pokemon, { EnemyPokemon, PlayerPokemon } from "./field/pokemon"; +import PokemonSpecies, { allSpecies, getPokemonSpecies, PokemonSpeciesFilter } from "./data/pokemon-species"; import { Constructor, isNullOrUndefined } from "#app/utils"; import * as Utils from "./utils"; -import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, TurnHeldItemTransferModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, overrideModifiers, overrideHeldItems, PokemonIncrementingStatModifier, ExpShareModifier, ExpBalanceModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier } from "./modifier/modifier"; +import { ConsumableModifier, ConsumablePokemonModifier, DoubleBattleChanceBoosterModifier, ExpBalanceModifier, ExpShareModifier, FusePokemonModifier, HealingBoosterModifier, Modifier, ModifierBar, ModifierPredicate, MultipleParticipantExpBonusModifier, overrideHeldItems, overrideModifiers, PersistentModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, TerastallizeModifier, TurnHeldItemTransferModifier } from "./modifier/modifier"; import { PokeballType } from "./data/pokeball"; import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "./data/battle-anims"; import { Phase } from "./phase"; @@ -13,20 +13,9 @@ import { Arena, ArenaBase } from "./field/arena"; import { GameData } from "./system/game-data"; import { addTextObject, getTextColor, TextStyle } from "./ui/text"; import { allMoves } from "./data/move"; -import { - ModifierPoolType, - getDefaultModifierTypeForTier, - getEnemyModifierTypesForWave, - getLuckString, - getLuckTextTint, - getModifierPoolForType, - getModifierType, - getPartyLuckValue, - modifierTypes, PokemonHeldItemModifierType -} from "./modifier/modifier-type"; +import { getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getModifierType, getPartyLuckValue, ModifierPoolType, modifierTypes, PokemonHeldItemModifierType } from "./modifier/modifier-type"; import AbilityBar from "./ui/ability-bar"; -import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, ChangeMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability"; -import { allAbilities } from "./data/ability"; +import { allAbilities, applyAbAttrs, applyPostBattleInitAbAttrs, BlockItemTheftAbAttr, ChangeMovePriorityAbAttr, DoubleBattleChanceAbAttr, PostBattleInitAbAttr } from "./data/ability"; import Battle, { BattleType, FixedBattleConfig } from "./battle"; import { GameMode, GameModes, getGameMode } from "./game-mode"; import FieldSpritePipeline from "./pipelines/field-sprite"; @@ -46,7 +35,7 @@ import UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin"; import { addUiThemeOverrides } from "./ui/ui-theme"; import PokemonData from "./system/pokemon-data"; import { Nature } from "./data/nature"; -import { SpeciesFormChangeManualTrigger, SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger, pokemonFormChanges, FormChangeItem, SpeciesFormChange } from "./data/pokemon-forms"; +import { FormChangeItem, pokemonFormChanges, SpeciesFormChange, SpeciesFormChangeManualTrigger, SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger } from "./data/pokemon-forms"; import { FormChangePhase } from "./phases/form-change-phase"; import { getTypeRgb } from "./data/type"; import PokemonSpriteSparkleHandler from "./field/pokemon-sprite-sparkle-handler"; @@ -1081,6 +1070,11 @@ export default class BattleScene extends SceneBase { p.destroy(); } + // If this is a ME, clear any residual visual sprites before reloading + if (this.currentBattle?.mysteryEncounter?.introVisuals) { + this.field.remove(this.currentBattle.mysteryEncounter?.introVisuals, true); + } + //@ts-ignore - allowing `null` for currentBattle causes a lot of trouble this.currentBattle = null; // TODO: resolve ts-ignore @@ -1111,6 +1105,8 @@ export default class BattleScene extends SceneBase { this.trainer.setPosition(406, 186); this.trainer.setVisible(true); + this.mysteryEncounterSaveData = new MysteryEncounterSaveData(); + this.updateGameInfo(); if (reloadI18n) { @@ -1146,6 +1142,13 @@ export default class BattleScene extends SceneBase { } } + getDoubleBattleChance(newWaveIndex: number, playerField: PlayerPokemon[]) { + const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8); + this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance); + playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance)); + return Math.max(doubleChance.value, 1); + } + newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean, mysteryEncounterType?: MysteryEncounterType): Battle | null { const _startingWave = Overrides.STARTING_WAVE_OVERRIDE || startingWave; const newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (_startingWave - 1)) + 1); @@ -1229,10 +1232,7 @@ export default class BattleScene extends SceneBase { if (double === undefined && newWaveIndex > 1) { if (newBattleType === BattleType.WILD && !this.gameMode.isWaveFinal(newWaveIndex)) { - const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8); - this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance); - playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance)); - newDouble = !Utils.randSeedInt(doubleChance.value); + newDouble = !Utils.randSeedInt(this.getDoubleBattleChance(newWaveIndex, playerField)); } else if (newBattleType === BattleType.TRAINER) { newDouble = newTrainer?.variant === TrainerVariant.DOUBLE; } @@ -2164,12 +2164,16 @@ export default class BattleScene extends SceneBase { return 20.87; case "battle_macro_grunt": // SWSH Trainer Battle return 11.56; + case "battle_star_grunt": //SV Team Star Battle + return 133.362; case "battle_galactic_admin": //BDSP Team Galactic Admin Battle return 11.997; case "battle_skull_admin": //SM Team Skull Admin Battle return 15.463; case "battle_oleana": //SWSH Oleana Battle return 14.110; + case "battle_star_admin": //SV Team Star Boss Battle + return 9.493; case "battle_rocket_boss": //USUM Giovanni Battle return 9.115; case "battle_aqua_magma_boss": //ORAS Archie & Maxie Battle @@ -2186,6 +2190,8 @@ export default class BattleScene extends SceneBase { return 13.13; case "battle_macro_boss": //SWSH Rose Battle return 11.42; + case "battle_star_boss": //SV Cassiopeia Battle + return 25.764; case "mystery_encounter_gen_5_gts": // BW GTS return 8.52; case "mystery_encounter_gen_6_gts": // XY GTS @@ -3163,11 +3169,17 @@ export default class BattleScene extends SceneBase { if (encounterCandidate.encounterTier !== tier) { // Encounter is in tier return false; } - const disabledModes = encounterCandidate.disabledGameModes; - if (disabledModes && disabledModes.length > 0 - && disabledModes.includes(this.gameMode.modeId)) { // Encounter is enabled for game mode + const disallowedGameModes = encounterCandidate.disallowedGameModes; + if (disallowedGameModes && disallowedGameModes.length > 0 + && disallowedGameModes.includes(this.gameMode.modeId)) { // Encounter is enabled for game mode return false; } + if (this.gameMode.modeId === GameModes.CHALLENGE) { // Encounter is enabled for challenges + const disallowedChallenges = encounterCandidate.disallowedChallenges; + if (disallowedChallenges && disallowedChallenges.length > 0 && this.gameMode.challenges.some(challenge => disallowedChallenges.includes(challenge.id))) { + return false; + } + } if (!encounterCandidate.meetsRequirements(this)) { // Meets encounter requirements return false; } diff --git a/src/battle.ts b/src/battle.ts index 973104108b3..d99e1a91c15 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -520,31 +520,31 @@ export const classicFixedBattles: FixedBattleConfigs = { .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }), [35]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) - .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)), + .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), [55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }), [62]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) - .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)), + .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), [64]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) - .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)), + .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), [66]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) - .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA ], true)), + .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ] ], true)), [95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }), [112]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) - .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)), + .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), [114]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) - .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA ], true, 1)), + .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ] ], true, 1)), [ClassicFixedBossWaves.EVIL_BOSS_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) - .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE ])) + .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE, TrainerType.PENNY ])) .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }), [145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }), [ClassicFixedBossWaves.EVIL_BOSS_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) - .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2, TrainerType.LUSAMINE_2, TrainerType.GUZMA_2, TrainerType.ROSE_2 ])) + .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2, TrainerType.LUSAMINE_2, TrainerType.GUZMA_2, TrainerType.ROSE_2, TrainerType.PENNY_2 ])) .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }), [182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])), diff --git a/src/data/ability.ts b/src/data/ability.ts index 58233e9839e..7a8d77cc022 100755 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -165,14 +165,27 @@ export class BlockRecoilDamageAttr extends AbAttr { } } +/** + * Attribute for abilities that increase the chance of a double battle + * occurring. + * @see apply + */ export class DoubleBattleChanceAbAttr extends AbAttr { constructor() { super(false); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const doubleChance = (args[0] as Utils.IntegerHolder); - doubleChance.value = Math.max(doubleChance.value / 2, 1); + /** + * Increases the chance of a double battle occurring + * @param args [0] {@linkcode Utils.NumberHolder} for double battle chance + * @returns true if the ability was applied + */ + apply(_pokemon: Pokemon, _passive: boolean, _simulated: boolean, _cancelled: Utils.BooleanHolder, args: any[]): boolean { + const doubleBattleChance = args[0] as Utils.NumberHolder; + // This is divided because the chance is generated as a number from 0 to doubleBattleChance.value using Utils.randSeedInt + // A double battle will initiate if the generated number is 0 + doubleBattleChance.value = doubleBattleChance.value / 4; + return true; } } @@ -4831,11 +4844,9 @@ export function initAbilities() { .bypassFaint(), new Ability(Abilities.VOLT_ABSORB, 3) .attr(TypeImmunityHealAbAttr, Type.ELECTRIC) - .partial() // Healing not blocked by Heal Block .ignorable(), new Ability(Abilities.WATER_ABSORB, 3) .attr(TypeImmunityHealAbAttr, Type.WATER) - .partial() // Healing not blocked by Heal Block .ignorable(), new Ability(Abilities.OBLIVIOUS, 3) .attr(BattlerTagImmunityAbAttr, BattlerTagType.INFATUATED) @@ -4948,8 +4959,7 @@ export function initAbilities() { .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.SOUND_BASED)) .ignorable(), new Ability(Abilities.RAIN_DISH, 3) - .attr(PostWeatherLapseHealAbAttr, 1, WeatherType.RAIN, WeatherType.HEAVY_RAIN) - .partial(), // Healing not blocked by Heal Block + .attr(PostWeatherLapseHealAbAttr, 1, WeatherType.RAIN, WeatherType.HEAVY_RAIN), new Ability(Abilities.SAND_STREAM, 3) .attr(PostSummonWeatherChangeAbAttr, WeatherType.SANDSTORM) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.SANDSTORM), @@ -5080,7 +5090,6 @@ export function initAbilities() { .attr(PostWeatherLapseHealAbAttr, 2, WeatherType.RAIN, WeatherType.HEAVY_RAIN) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 1.25) .attr(TypeImmunityHealAbAttr, Type.WATER) - .partial() // Healing not blocked by Heal Block .ignorable(), new Ability(Abilities.DOWNLOAD, 4) .attr(DownloadAbAttr), @@ -5161,8 +5170,7 @@ export function initAbilities() { .ignorable(), new Ability(Abilities.ICE_BODY, 4) .attr(BlockWeatherDamageAttr, WeatherType.HAIL) - .attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL, WeatherType.SNOW) - .partial(), // Healing not blocked by Heal Block + .attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL, WeatherType.SNOW), new Ability(Abilities.SOLID_ROCK, 4) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => target.getMoveEffectiveness(user, move) >= 2, 0.75) .ignorable(), @@ -5332,8 +5340,7 @@ export function initAbilities() { .ignorable() .unimplemented(), new Ability(Abilities.CHEEK_POUCH, 6) - .attr(HealFromBerryUseAbAttr, 1/3) - .partial(), // Healing not blocked by Heal Block + .attr(HealFromBerryUseAbAttr, 1/3), new Ability(Abilities.PROTEAN, 6) .attr(PokemonTypeChangeAbAttr), //.condition((p) => !p.summonData?.abilitiesApplied.includes(Abilities.PROTEAN)), //Gen 9 Implementation @@ -5872,6 +5879,6 @@ export function initAbilities() { new Ability(Abilities.POISON_PUPPETEER, 9) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) - .conditionalAttr(pokemon => pokemon.species.speciesId===Species.PECHARUNT, ConfusionOnStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) + .attr(ConfusionOnStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) ); } diff --git a/src/data/battle-anims.ts b/src/data/battle-anims.ts index d7b995f748f..eb0dce3bf0c 100644 --- a/src/data/battle-anims.ts +++ b/src/data/battle-anims.ts @@ -743,16 +743,21 @@ export abstract class BattleAnim { public target: Pokemon | null; public sprites: Phaser.GameObjects.Sprite[]; public bgSprite: Phaser.GameObjects.TileSprite | Phaser.GameObjects.Rectangle; - public playOnEmptyField: boolean; + /** + * Will attempt to play as much of an animation as possible, even if not all targets are on the field. + * Will also play the animation, even if the user has selected "Move Animations" OFF in Settings. + * Exclusively used by MEs atm, for visual animations at the start of an encounter. + */ + public playRegardlessOfIssues: boolean; private srcLine: number[]; private dstLine: number[]; - constructor(user?: Pokemon, target?: Pokemon, playOnEmptyField: boolean = false) { + constructor(user?: Pokemon, target?: Pokemon, playRegardlessOfIssues: boolean = false) { this.user = user ?? null; this.target = target ?? null; this.sprites = []; - this.playOnEmptyField = playOnEmptyField; + this.playRegardlessOfIssues = playRegardlessOfIssues; } abstract getAnim(): AnimConfig | null; @@ -829,7 +834,7 @@ export abstract class BattleAnim { const user = !isOppAnim ? this.user! : this.target!; // TODO: are those bangs correct? const target = !isOppAnim ? this.target! : this.user!; - if (!target?.isOnField() && !this.playOnEmptyField) { + if (!target?.isOnField() && !this.playRegardlessOfIssues) { if (callback) { callback(); } @@ -896,7 +901,7 @@ export abstract class BattleAnim { } }; - if (!scene.moveAnimations) { + if (!scene.moveAnimations && !this.playRegardlessOfIssues) { return cleanUpAndComplete(); } @@ -932,7 +937,7 @@ export abstract class BattleAnim { const isUser = frame.target === AnimFrameTarget.USER; if (isUser && target === user) { continue; - } else if (this.playOnEmptyField && frame.target === AnimFrameTarget.TARGET && !target.isOnField()) { + } else if (this.playRegardlessOfIssues && frame.target === AnimFrameTarget.TARGET && !target.isOnField()) { continue; } const sprites = spriteCache[isUser ? AnimFrameTarget.USER : AnimFrameTarget.TARGET]; @@ -1145,7 +1150,7 @@ export abstract class BattleAnim { } }; - if (!scene.moveAnimations) { + if (!scene.moveAnimations && !this.playRegardlessOfIssues) { return cleanUpAndComplete(); } diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 32b3d54f302..3be6562307b 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -3,7 +3,7 @@ import { getPokemonNameWithAffix } from "../messages"; import Pokemon, { MoveResult, HitResult } from "../field/pokemon"; import { StatusEffect } from "./status-effect"; import * as Utils from "../utils"; -import { ChargeAttr, MoveFlags, allMoves } from "./move"; +import { ChargeAttr, MoveFlags, allMoves, MoveCategory, applyMoveAttrs, StatusCategoryOnAllyAttr, HealOnAllyAttr } from "./move"; import { Type } from "./type"; import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, ReverseDrainAbAttr, applyAbAttrs, ProtectStatAbAttr } from "./ability"; import { TerrainType } from "./terrain"; @@ -141,6 +141,18 @@ export abstract class MoveRestrictionBattlerTag extends BattlerTag { */ abstract isMoveRestricted(move: Moves): boolean; + /** + * Checks if this tag is restricting a move based on a user's decisions during the target selection phase + * + * @param {Moves} move {@linkcode Moves} move ID to check restriction for + * @param {Pokemon} user {@linkcode Pokemon} the user of the above move + * @param {Pokemon} target {@linkcode Pokemon} the target of the above move + * @returns {boolean} `false` unless overridden by the child tag + */ + isMoveTargetRestricted(move: Moves, user: Pokemon, target: Pokemon): boolean { + return false; + } + /** * Gets the text to display when the player attempts to select a move that is restricted by this tag. * @@ -2178,6 +2190,74 @@ export class ExposedTag extends BattlerTag { } } +/** + * Tag that prevents HP recovery from held items and move effects. It also blocks the usage of recovery moves. + * Applied by moves: {@linkcode Moves.HEAL_BLOCK | Heal Block (5 turns)}, {@linkcode Moves.PSYCHIC_NOISE | Psychic Noise (2 turns)} + * + * @extends MoveRestrictionBattlerTag + */ +export class HealBlockTag extends MoveRestrictionBattlerTag { + constructor(turnCount: number, sourceMove: Moves) { + super(BattlerTagType.HEAL_BLOCK, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.TURN_END ], turnCount, sourceMove); + } + + onActivation(pokemon: Pokemon): string { + return i18next.t("battle:battlerTagsHealBlock", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }); + } + + /** + * Checks if a move is disabled under Heal Block + * @param {Moves} move {@linkcode Moves} the move ID + * @returns `true` if the move has a TRIAGE_MOVE flag and is a status move + */ + override isMoveRestricted(move: Moves): boolean { + if (allMoves[move].hasFlag(MoveFlags.TRIAGE_MOVE) && allMoves[move].category === MoveCategory.STATUS) { + return true; + } + return false; + } + + /** + * Checks if a move is disabled under Heal Block because of its choice of target + * Implemented b/c of Pollen Puff + * @param {Moves} move {@linkcode Moves} the move ID + * @param {Pokemon} user {@linkcode Pokemon} the move user + * @param {Pokemon} target {@linkcode Pokemon} the target of the move + * @returns `true` if the move cannot be used because the target is an ally + */ + override isMoveTargetRestricted(move: Moves, user: Pokemon, target: Pokemon) { + const moveCategory = new Utils.IntegerHolder(allMoves[move].category); + applyMoveAttrs(StatusCategoryOnAllyAttr, user, target, allMoves[move], moveCategory); + if (allMoves[move].hasAttr(HealOnAllyAttr) && moveCategory.value === MoveCategory.STATUS ) { + return true; + } + return false; + } + + /** + * Uses DisabledTag's selectionDeniedText() message + */ + override selectionDeniedText(pokemon: Pokemon, move: Moves): string { + return i18next.t("battle:moveDisabled", { moveName: allMoves[move].name }); + } + + /** + * @override + * @param {Pokemon} pokemon {@linkcode Pokemon} attempting to use the restricted move + * @param {Moves} move {@linkcode Moves} ID of the move being interrupted + * @returns {string} text to display when the move is interrupted + */ + override interruptedText(pokemon: Pokemon, move: Moves): string { + return i18next.t("battle:disableInterruptedMove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name }); + } + + override onRemove(pokemon: Pokemon): void { + super.onRemove(pokemon); + + pokemon.scene.queueMessage(i18next.t("battle:battlerTagsHealBlockOnRemove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), null, false, null); + } +} + /** * Tag that doubles the type effectiveness of Fire-type moves. * @extends BattlerTag @@ -2490,6 +2570,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source return new SubstituteTag(sourceMove, sourceId); case BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON: return new MysteryEncounterPostSummonTag(); + case BattlerTagType.HEAL_BLOCK: + return new HealBlockTag(turnCount, sourceMove); case BattlerTagType.NONE: default: return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); diff --git a/src/data/challenge.ts b/src/data/challenge.ts index 737f4a6a369..ff23f3c1544 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -465,6 +465,30 @@ export class SingleGenerationChallenge extends Challenge { applyFixedBattle(waveIndex: Number, battleConfig: FixedBattleConfig): boolean { let trainerTypes: TrainerType[] = []; switch (waveIndex) { + case 35: + trainerTypes = [ TrainerType.ROCKET_GRUNT, TrainerType.ROCKET_GRUNT, Utils.randSeedItem([ TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT ]), TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, Utils.randSeedItem([ TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT ]), TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ]; + break; + case 62: + trainerTypes = [ TrainerType.ROCKET_GRUNT, TrainerType.ROCKET_GRUNT, Utils.randSeedItem([ TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT ]), TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, Utils.randSeedItem([ TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT ]), TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ]; + break; + case 64: + trainerTypes = [ TrainerType.ROCKET_GRUNT, TrainerType.ROCKET_GRUNT, Utils.randSeedItem([ TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT ]), TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, Utils.randSeedItem([ TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT ]), TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ]; + break; + case 66: + trainerTypes = [ Utils.randSeedItem([ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ]), Utils.randSeedItem([ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ]), Utils.randSeedItem([ TrainerType.TABITHA, TrainerType.COURTNEY, TrainerType.MATT, TrainerType.SHELLY ]), Utils.randSeedItem([ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ]), Utils.randSeedItem([ TrainerType.ZINZOLIN, TrainerType.ROOD ]), Utils.randSeedItem([ TrainerType.XEROSIC, TrainerType.BRYONY ]), Utils.randSeedItem([ TrainerType.FABA, TrainerType.PLUMERIA ]), TrainerType.OLEANA, Utils.randSeedItem([ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]) ]; + break; + case 112: + trainerTypes = [ TrainerType.ROCKET_GRUNT, TrainerType.ROCKET_GRUNT, Utils.randSeedItem([ TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT ]), TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, Utils.randSeedItem([ TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT ]), TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ]; + break; + case 114: + trainerTypes = [ Utils.randSeedItem([ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ]), Utils.randSeedItem([ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ]), Utils.randSeedItem([ TrainerType.TABITHA, TrainerType.COURTNEY, TrainerType.MATT, TrainerType.SHELLY ]), Utils.randSeedItem([ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ]), Utils.randSeedItem([ TrainerType.ZINZOLIN, TrainerType.ROOD ]), Utils.randSeedItem([ TrainerType.XEROSIC, TrainerType.BRYONY ]), Utils.randSeedItem([ TrainerType.FABA, TrainerType.PLUMERIA ]), TrainerType.OLEANA, Utils.randSeedItem([ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]) ]; + break; + case 115: + trainerTypes = [ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.ROCKET_BOSS_GIOVANNI_1, Utils.randSeedItem([ TrainerType.MAXIE, TrainerType.ARCHIE ]), TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, Utils.randSeedItem([ TrainerType.LUSAMINE, TrainerType.GUZMA ]), TrainerType.ROSE, TrainerType.PENNY ]; + break; + case 165: + trainerTypes = [ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.ROCKET_BOSS_GIOVANNI_2, Utils.randSeedItem([ TrainerType.MAXIE_2, TrainerType.ARCHIE_2 ]), TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2, Utils.randSeedItem([ TrainerType.LUSAMINE_2, TrainerType.GUZMA_2 ]), TrainerType.ROSE_2, TrainerType.PENNY_2 ]; + break; case 182: trainerTypes = [ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, Utils.randSeedItem([ TrainerType.HALA, TrainerType.MOLAYNE ]), TrainerType.MARNIE_ELITE, TrainerType.RIKA ]; break; diff --git a/src/data/dialogue.ts b/src/data/dialogue.ts index b01242d083a..499cd106cf9 100644 --- a/src/data/dialogue.ts +++ b/src/data/dialogue.ts @@ -837,11 +837,15 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { "dialogue:macro_grunt.encounter.1", "dialogue:macro_grunt.encounter.2", "dialogue:macro_grunt.encounter.3", + "dialogue:macro_grunt.encounter.4", + "dialogue:macro_grunt.encounter.5", ], victory: [ "dialogue:macro_grunt.victory.1", "dialogue:macro_grunt.victory.2", "dialogue:macro_grunt.victory.3", + "dialogue:macro_grunt.victory.4", + "dialogue:macro_grunt.victory.5", ] } ], @@ -859,6 +863,84 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { ] } ], + [TrainerType.STAR_GRUNT]: [ + { + encounter: [ + "dialogue:star_grunt.encounter.1", + "dialogue:star_grunt.encounter.2", + "dialogue:star_grunt.encounter.3", + "dialogue:star_grunt.encounter.4", + "dialogue:star_grunt.encounter.5", + ], + victory: [ + "dialogue:star_grunt.victory.1", + "dialogue:star_grunt.victory.2", + "dialogue:star_grunt.victory.3", + "dialogue:star_grunt.victory.4", + "dialogue:star_grunt.victory.5", + ] + } + ], + [TrainerType.GIACOMO]: [ + { + encounter: [ + "dialogue:giacomo.encounter.1", + "dialogue:giacomo.encounter.2", + ], + victory: [ + "dialogue:giacomo.victory.1", + "dialogue:giacomo.victory.2", + ] + } + ], + [TrainerType.MELA]: [ + { + encounter: [ + "dialogue:mela.encounter.1", + "dialogue:mela.encounter.2", + ], + victory: [ + "dialogue:mela.victory.1", + "dialogue:mela.victory.2", + ] + } + ], + [TrainerType.ATTICUS]: [ + { + encounter: [ + "dialogue:atticus.encounter.1", + "dialogue:atticus.encounter.2", + ], + victory: [ + "dialogue:atticus.victory.1", + "dialogue:atticus.victory.2", + ] + } + ], + [TrainerType.ORTEGA]: [ + { + encounter: [ + "dialogue:ortega.encounter.1", + "dialogue:ortega.encounter.2", + ], + victory: [ + "dialogue:ortega.victory.1", + "dialogue:ortega.victory.2", + ] + } + ], + [TrainerType.ERI]: [ + { + encounter: [ + "dialogue:eri.encounter.1", + "dialogue:eri.encounter.2", + ], + victory: [ + "dialogue:eri.victory.1", + "dialogue:eri.victory.2", + ] + } + ], [TrainerType.ROCKET_BOSS_GIOVANNI_1]: [ { encounter: [ @@ -1093,6 +1175,32 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { ] } ], + [TrainerType.PENNY]: [ + { + encounter: [ + "dialogue:star_boss_penny_1.encounter.1" + ], + victory: [ + "dialogue:star_boss_penny_1.victory.1" + ], + defeat: [ + "dialogue:star_boss_penny_1.defeat.1" + ] + } + ], + [TrainerType.PENNY_2]: [ + { + encounter: [ + "dialogue:star_boss_penny_2.encounter.1" + ], + victory: [ + "dialogue:star_boss_penny_2.victory.1" + ], + defeat: [ + "dialogue:star_boss_penny_2.defeat.1" + ] + } + ], [TrainerType.BUCK]: [ { encounter: [ diff --git a/src/data/egg-moves.ts b/src/data/egg-moves.ts index b516238c46e..3e58f993df2 100644 --- a/src/data/egg-moves.ts +++ b/src/data/egg-moves.ts @@ -264,7 +264,7 @@ export const speciesEggMoves = { [Species.PANPOUR]: [ Moves.NASTY_PLOT, Moves.ENERGY_BALL, Moves.EARTH_POWER, Moves.STEAM_ERUPTION ], [Species.MUNNA]: [ Moves.COSMIC_POWER, Moves.AURA_SPHERE, Moves.EARTH_POWER, Moves.MYSTICAL_POWER ], [Species.PIDOVE]: [ Moves.GUNK_SHOT, Moves.TIDY_UP, Moves.FLOATY_FALL, Moves.TRIPLE_ARROWS ], - [Species.BLITZLE]: [ Moves.HIGH_HORSEPOWER, Moves.THUNDEROUS_KICK, Moves.FLARE_BLITZ, Moves.VOLT_TACKLE ], + [Species.BLITZLE]: [ Moves.HORN_LEECH, Moves.SWORDS_DANCE, Moves.FLARE_BLITZ, Moves.BOLT_STRIKE ], [Species.ROGGENROLA]: [ Moves.BODY_PRESS, Moves.CURSE, Moves.SHORE_UP, Moves.DIAMOND_STORM ], [Species.WOOBAT]: [ Moves.ESPER_WING, Moves.STORED_POWER, Moves.MYSTICAL_FIRE, Moves.OBLIVION_WING ], [Species.DRILBUR]: [ Moves.IRON_HEAD, Moves.MOUNTAIN_GALE, Moves.SHIFT_GEAR, Moves.THOUSAND_ARROWS ], diff --git a/src/data/move.ts b/src/data/move.ts index de5176c3c84..86139a22adf 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -4539,6 +4539,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr { case BattlerTagType.NIGHTMARE: case BattlerTagType.DROWSY: case BattlerTagType.DISABLED: + case BattlerTagType.HEAL_BLOCK: return -5; case BattlerTagType.SEEDED: case BattlerTagType.SALT_CURED: @@ -7826,8 +7827,8 @@ export function initMoves() { .makesContact() .attr(LessPPMorePowerAttr), new StatusMove(Moves.HEAL_BLOCK, Type.PSYCHIC, 100, 15, -1, 0, 4) - .target(MoveTarget.ALL_NEAR_ENEMIES) - .unimplemented(), + .attr(AddBattlerTagAttr, BattlerTagType.HEAL_BLOCK, false, true, 5) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.WRING_OUT, Type.NORMAL, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 4) .attr(OpponentHighHpPowerAttr, 120) .makesContact(), @@ -9072,8 +9073,7 @@ export function initMoves() { new AttackMove(Moves.AURA_WHEEL, Type.ELECTRIC, MoveCategory.PHYSICAL, 110, 100, 10, 100, 0, 8) .attr(StatStageChangeAttr, [ Stat.SPD ], 1, true) .makesContact(false) - .attr(AuraWheelTypeAttr) - .condition((user, target, move) => [user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.MORPEKO)), // Missing custom fail message + .attr(AuraWheelTypeAttr), new AttackMove(Moves.BREAKING_SWIPE, Type.DRAGON, MoveCategory.PHYSICAL, 60, 100, 15, 100, 0, 8) .target(MoveTarget.ALL_NEAR_ENEMIES) .attr(StatStageChangeAttr, [ Stat.ATK ], -1), @@ -9609,7 +9609,7 @@ export function initMoves() { .recklessMove(), new AttackMove(Moves.PSYCHIC_NOISE, Type.PSYCHIC, MoveCategory.SPECIAL, 75, 100, 10, -1, 0, 9) .soundBased() - .partial(), + .attr(AddBattlerTagAttr, BattlerTagType.HEAL_BLOCK, false, false, 2), new AttackMove(Moves.UPPER_HAND, Type.FIGHTING, MoveCategory.PHYSICAL, 65, 100, 15, 100, 3, 9) .attr(FlinchAttr) .condition((user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.command === Command.FIGHT && !target.turnData.acted && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move!].category !== MoveCategory.STATUS && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move!].priority > 0 ) // TODO: is this bang correct? diff --git a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts index 18f998192ce..c9605aadc49 100644 --- a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts +++ b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts @@ -338,7 +338,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = .withOptionPhase(async (scene: BattleScene) => { // Let it have the food // Greedent joins the team, level equal to 2 below highest party member - const level = getHighestLevelPlayerPokemon(scene).level - 2; + const level = getHighestLevelPlayerPokemon(scene, false, true).level - 2; const greedent = new EnemyPokemon(scene, getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false); greedent.moveset = [new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF)]; greedent.passive = true; diff --git a/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts b/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts index eb43424a8ff..62025957abe 100644 --- a/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts +++ b/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts @@ -26,7 +26,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE) .withEncounterTier(MysteryEncounterTier.GREAT) .withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES) - .withScenePartySizeRequirement(2, 6) // Must have at least 2 pokemon in party + .withScenePartySizeRequirement(2, 6, true) // Must have at least 2 pokemon in party .withIntroSpriteConfigs([ { spriteKey: Species.LIEPARD.toString(), @@ -60,7 +60,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = .withQuery(`${namespace}.query`) .withOnInit((scene: BattleScene) => { const encounter = scene.currentBattle.mysteryEncounter!; - const pokemon = getHighestStatTotalPlayerPokemon(scene, false); + const pokemon = getHighestStatTotalPlayerPokemon(scene, true, true); const price = scene.getWaveMoneyAmount(10); encounter.setDialogueToken("strongestPokemon", pokemon.getNameToRender()); diff --git a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts index d1497c54527..9ff223947f5 100644 --- a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts +++ b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts @@ -82,7 +82,7 @@ export const BerriesAboundEncounter: MysteryEncounter = const { spriteKey, fileRoot } = getSpriteKeysFromPokemon(bossPokemon); encounter.spriteConfigs = [ { - spriteKey: "berry_bush", + spriteKey: "berries_abound_bush", fileRoot: "mystery-encounters", x: 25, y: -6, @@ -102,7 +102,7 @@ export const BerriesAboundEncounter: MysteryEncounter = ]; // Get fastest party pokemon for option 2 - const fastestPokemon = getHighestStatPlayerPokemon(scene, PERMANENT_STATS[Stat.SPD], true); + const fastestPokemon = getHighestStatPlayerPokemon(scene, PERMANENT_STATS[Stat.SPD], true, false); encounter.misc.fastestPokemon = fastestPokemon; encounter.misc.enemySpeed = bossPokemon.getStat(Stat.SPD); encounter.setDialogueToken("fastestPokemon", fastestPokemon.getNameToRender()); @@ -162,10 +162,10 @@ export const BerriesAboundEncounter: MysteryEncounter = .withOptionPhase(async (scene: BattleScene) => { // Pick race for berries const encounter = scene.currentBattle.mysteryEncounter!; - const fastestPokemon = encounter.misc.fastestPokemon; - const enemySpeed = encounter.misc.enemySpeed; + const fastestPokemon: PlayerPokemon = encounter.misc.fastestPokemon; + const enemySpeed: number = encounter.misc.enemySpeed; const speedDiff = fastestPokemon.getStat(Stat.SPD) / (enemySpeed * 1.1); - const numBerries = encounter.misc.numBerries; + const numBerries: number = encounter.misc.numBerries; const shopOptions: ModifierTypeOption[] = []; for (let i = 0; i < 5; i++) { diff --git a/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts b/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts index 202488030ee..68840943c49 100644 --- a/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts +++ b/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts @@ -376,9 +376,10 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = const onPokemonSelected = (pokemon: PlayerPokemon) => { // Get Pokemon held items and filter for valid ones const validItems = pokemon.getHeldItems().filter(item => { - return item instanceof BypassSpeedChanceModifier || + return (item instanceof BypassSpeedChanceModifier || item instanceof ContactHeldItemTransferChanceModifier || - (item instanceof AttackTypeBoosterModifier && (item.type as AttackTypeBoosterModifierType).moveType === Type.BUG); + (item instanceof AttackTypeBoosterModifier && (item.type as AttackTypeBoosterModifierType).moveType === Type.BUG)) && + item.isTransferable; }); return validItems.map((modifier: PokemonHeldItemModifier) => { diff --git a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts index d930e43c45f..e1e681e95dd 100644 --- a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts +++ b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts @@ -29,8 +29,9 @@ import { Moves } from "#enums/moves"; import { EncounterBattleAnim } from "#app/data/battle-anims"; import { MoveCategory } from "#app/data/move"; import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data"; -import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES, GameModes } from "#app/game-mode"; +import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { EncounterAnim } from "#enums/encounter-anims"; +import { Challenges } from "#enums/challenges"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounter:clowningAround"; @@ -61,7 +62,7 @@ const RANDOM_ABILITY_POOL = [ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.CLOWNING_AROUND) .withEncounterTier(MysteryEncounterTier.ULTRA) - .withDisabledGameModes(GameModes.CHALLENGE) + .withDisallowedChallenges(Challenges.SINGLE_TYPE) .withSceneWaveRangeRequirement(80, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1]) .withAnimations(EncounterAnim.SMOKESCREEN) .withAutoHideIntroVisuals(false) @@ -349,10 +350,18 @@ export const ClowningAroundEncounter: MysteryEncounter = } } newTypes.push(secondType); + + // Apply the type changes (to both base and fusion, if pokemon is fused) if (!pokemon.mysteryEncounterPokemonData) { pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(); } pokemon.mysteryEncounterPokemonData.types = newTypes; + if (pokemon.isFusion()) { + if (!pokemon.fusionMysteryEncounterPokemonData) { + pokemon.fusionMysteryEncounterPokemonData = new MysteryEncounterPokemonData(); + } + pokemon.fusionMysteryEncounterPokemonData.types = newTypes; + } } }) .withOptionPhase(async (scene: BattleScene) => { @@ -415,10 +424,17 @@ function onYesAbilitySwap(scene: BattleScene, resolve) { const onPokemonSelected = (pokemon: PlayerPokemon) => { // Do ability swap const encounter = scene.currentBattle.mysteryEncounter!; - if (!pokemon.mysteryEncounterPokemonData) { - pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(); + if (pokemon.isFusion()) { + if (!pokemon.fusionMysteryEncounterPokemonData) { + pokemon.fusionMysteryEncounterPokemonData = new MysteryEncounterPokemonData(); + } + pokemon.fusionMysteryEncounterPokemonData.ability = encounter.misc.ability; + } else { + if (!pokemon.mysteryEncounterPokemonData) { + pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(); + } + pokemon.mysteryEncounterPokemonData.ability = encounter.misc.ability; } - pokemon.mysteryEncounterPokemonData.ability = encounter.misc.ability; encounter.setDialogueToken("chosenPokemon", pokemon.getNameToRender()); scene.ui.setMode(Mode.MESSAGE).then(() => resolve(true)); }; diff --git a/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts b/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts index 8a0a18d48ea..1ceb14a7372 100644 --- a/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts +++ b/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts @@ -27,6 +27,7 @@ import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { Stat } from "#enums/stat"; import { EncounterAnim } from "#enums/encounter-anims"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import i18next from "i18next"; /** the i18n namespace for this encounter */ const namespace = "mysteryEncounter:dancingLessons"; @@ -268,9 +269,12 @@ export const DancingLessonsEncounter: MysteryEncounter = }); }; - // Only Pokemon that have a Dancing move can be selected + // Only challenge legal/unfainted Pokemon that have a Dancing move can be selected const selectableFilter = (pokemon: Pokemon) => { // If pokemon meets primary pokemon reqs, it can be selected + if (!pokemon.isAllowedInBattle()) { + return i18next.t("partyUiHandler:cantBeUsed", { pokemonName: pokemon.getNameToRender() }) ?? null; + } const meetsReqs = encounter.options[2].pokemonMeetsPrimaryRequirements(scene, pokemon); if (!meetsReqs) { return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null; diff --git a/src/data/mystery-encounters/encounters/dark-deal-encounter.ts b/src/data/mystery-encounters/encounters/dark-deal-encounter.ts index 09b058ab7c9..92009b12958 100644 --- a/src/data/mystery-encounters/encounters/dark-deal-encounter.ts +++ b/src/data/mystery-encounters/encounters/dark-deal-encounter.ts @@ -94,7 +94,7 @@ export const DarkDealEncounter: MysteryEncounter = .withEncounterTier(MysteryEncounterTier.ROGUE) .withIntroSpriteConfigs([ { - spriteKey: "mad_scientist_m", + spriteKey: "dark_deal_scientist", fileRoot: "mystery-encounters", hasShadow: true, }, @@ -115,7 +115,7 @@ export const DarkDealEncounter: MysteryEncounter = }, ]) .withSceneWaveRangeRequirement(30, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1]) - .withScenePartySizeRequirement(2, 6) // Must have at least 2 pokemon in party + .withScenePartySizeRequirement(2, 6, true) // Must have at least 2 pokemon in party .withCatchAllowed(true) .withTitle(`${namespace}.title`) .withDescription(`${namespace}.description`) @@ -139,7 +139,7 @@ export const DarkDealEncounter: MysteryEncounter = .withPreOptionPhase(async (scene: BattleScene) => { // Removes random pokemon (including fainted) from party and adds name to dialogue data tokens // Will never return last battle able mon and instead pick fainted/unable to battle - const removedPokemon = getRandomPlayerPokemon(scene, false, true); + const removedPokemon = getRandomPlayerPokemon(scene, true, false, true); // Get all the pokemon's held items const modifiers = removedPokemon.getHeldItems().filter(m => !(m instanceof PokemonFormChangeItemModifier)); scene.removePokemonFromPlayerParty(removedPokemon); diff --git a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts index 25959abe19e..90ed486efd7 100644 --- a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts +++ b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts @@ -10,7 +10,7 @@ import { CombinationPokemonRequirement, HeldItemRequirement, MoneyRequirement } import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; -import { HealingBoosterModifier, HiddenAbilityRateBoosterModifier, LevelIncrementBoosterModifier, PokemonHeldItemModifier, PreserveBerryModifier } from "#app/modifier/modifier"; +import { BerryModifier, HealingBoosterModifier, HiddenAbilityRateBoosterModifier, LevelIncrementBoosterModifier, PokemonHeldItemModifier, PreserveBerryModifier } from "#app/modifier/modifier"; import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import { applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import i18next from "#app/plugins/i18n"; @@ -159,7 +159,7 @@ export const DelibirdyEncounter: MysteryEncounter = const onPokemonSelected = (pokemon: PlayerPokemon) => { // Get Pokemon held items and filter for valid ones const validItems = pokemon.getHeldItems().filter((it) => { - return OPTION_2_ALLOWED_MODIFIERS.some(heldItem => it.constructor.name === heldItem); + return OPTION_2_ALLOWED_MODIFIERS.some(heldItem => it.constructor.name === heldItem) && it.isTransferable; }); return validItems.map((modifier: PokemonHeldItemModifier) => { @@ -179,9 +179,8 @@ export const DelibirdyEncounter: MysteryEncounter = }); }; - // Only Pokemon that can gain benefits are above 1/3rd HP with no status const selectableFilter = (pokemon: Pokemon) => { - // If pokemon meets primary pokemon reqs, it can be selected + // If pokemon has valid item, it can be selected const meetsReqs = encounter.options[1].pokemonMeetsPrimaryRequirements(scene, pokemon); if (!meetsReqs) { return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null; @@ -197,7 +196,7 @@ export const DelibirdyEncounter: MysteryEncounter = const modifier = encounter.misc.chosenModifier; // Give the player a Candy Jar if they gave a Berry, and a Healing Charm for Reviver Seed - if (modifier.type.name.includes("Berry")) { + if (modifier instanceof BerryModifier) { // Check if the player has max stacks of that Candy Jar already const existing = scene.findModifier(m => m instanceof LevelIncrementBoosterModifier) as LevelIncrementBoosterModifier; @@ -254,7 +253,7 @@ export const DelibirdyEncounter: MysteryEncounter = const onPokemonSelected = (pokemon: PlayerPokemon) => { // Get Pokemon held items and filter for valid ones const validItems = pokemon.getHeldItems().filter((it) => { - return !OPTION_3_DISALLOWED_MODIFIERS.some(heldItem => it.constructor.name === heldItem); + return !OPTION_3_DISALLOWED_MODIFIERS.some(heldItem => it.constructor.name === heldItem) && it.isTransferable; }); return validItems.map((modifier: PokemonHeldItemModifier) => { @@ -274,9 +273,8 @@ export const DelibirdyEncounter: MysteryEncounter = }); }; - // Only Pokemon that can gain benefits are above 1/3rd HP with no status const selectableFilter = (pokemon: Pokemon) => { - // If pokemon meets primary pokemon reqs, it can be selected + // If pokemon has valid item, it can be selected const meetsReqs = encounter.options[2].pokemonMeetsPrimaryRequirements(scene, pokemon); if (!meetsReqs) { return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null; diff --git a/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts b/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts index 104b46bce8a..db25d338a29 100644 --- a/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts +++ b/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts @@ -27,7 +27,7 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter = .withSceneWaveRangeRequirement(CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[0], 100) .withIntroSpriteConfigs([ { - spriteKey: "b2w2_lady", + spriteKey: "department_store_sale_lady", fileRoot: "mystery-encounters", hasShadow: true, x: -20, diff --git a/src/data/mystery-encounters/encounters/field-trip-encounter.ts b/src/data/mystery-encounters/encounters/field-trip-encounter.ts index d03a3c1fcca..82f27c5e59b 100644 --- a/src/data/mystery-encounters/encounters/field-trip-encounter.ts +++ b/src/data/mystery-encounters/encounters/field-trip-encounter.ts @@ -32,7 +32,7 @@ export const FieldTripEncounter: MysteryEncounter = hasShadow: true, }, { - spriteKey: "teacher", + spriteKey: "field_trip_teacher", fileRoot: "mystery-encounters", hasShadow: true, }, diff --git a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts index 470c4b96c82..4f5430b63d9 100644 --- a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts +++ b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts @@ -189,7 +189,7 @@ export const FieryFalloutEncounter: MysteryEncounter = } // Burn random member - const burnable = nonFireTypes.filter(p => isNullOrUndefined(p.status) || isNullOrUndefined(p.status!.effect) || p.status?.effect === StatusEffect.BURN); + const burnable = nonFireTypes.filter(p => isNullOrUndefined(p.status) || isNullOrUndefined(p.status!.effect) || p.status?.effect === StatusEffect.NONE); if (burnable?.length > 0) { const roll = randSeedInt(burnable.length); const chosenPokemon = burnable[roll]; diff --git a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts index aa11a07f218..349984f1958 100644 --- a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts +++ b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts @@ -68,6 +68,7 @@ export const FightOrFlightEncounter: MysteryEncounter = mysteryEncounterBattleEffects: (pokemon: Pokemon) => { queueEncounterMessage(pokemon.scene, `${namespace}.option.1.stat_boost`); // Randomly boost 1 stat 2 stages + // Cannot boost Spd, Acc, or Evasion pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [randSeedInt(4, 1)], 2)); } }], diff --git a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts index 9ca7c7c2865..a144aa88299 100644 --- a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts +++ b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts @@ -7,7 +7,7 @@ import { TrainerSlot } from "#app/data/trainer-config"; import Pokemon, { FieldPosition, PlayerPokemon } from "#app/field/pokemon"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; -import { getEncounterText, queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; +import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { Species } from "#enums/species"; @@ -22,6 +22,7 @@ import { PostSummonPhase } from "#app/phases/post-summon-phase"; import { modifierTypes } from "#app/modifier/modifier-type"; import { Nature } from "#enums/nature"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import { isPokemonValidForEncounterOptionSelection } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounter:funAndGames"; @@ -45,14 +46,14 @@ export const FunAndGamesEncounter: MysteryEncounter = .withSkipToFightInput(true) .withIntroSpriteConfigs([ { - spriteKey: "carnival_game", + spriteKey: "fun_and_games_game", fileRoot: "mystery-encounters", hasShadow: false, x: 0, y: 6, }, { - spriteKey: "carnival_wobbuffet", + spriteKey: "fun_and_games_wobbuffet", fileRoot: "mystery-encounters", hasShadow: true, x: -28, @@ -60,7 +61,7 @@ export const FunAndGamesEncounter: MysteryEncounter = yShadow: 6 }, { - spriteKey: "carnival_man", + spriteKey: "fun_and_games_man", fileRoot: "mystery-encounters", hasShadow: true, x: 40, @@ -110,12 +111,7 @@ export const FunAndGamesEncounter: MysteryEncounter = // Only Pokemon that are not KOed/legal can be selected const selectableFilter = (pokemon: Pokemon) => { - const meetsReqs = pokemon.isAllowedInBattle(); - if (!meetsReqs) { - return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null; - } - - return null; + return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`); }; return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter); diff --git a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts index 55d4953d438..0f9f06c9a68 100644 --- a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts +++ b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts @@ -317,7 +317,6 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = }); }; - // Only Pokemon that can gain benefits are above 1/3rd HP with no status const selectableFilter = (pokemon: Pokemon) => { // If pokemon has items to trade const meetsReqs = pokemon.getHeldItems().filter((it) => { @@ -431,14 +430,13 @@ function getPokemonTradeOptions(scene: BattleScene): Map function generateTradeOption(alreadyUsedSpecies: PokemonSpecies[], originalBst?: number): PokemonSpecies { let newSpecies: PokemonSpecies | undefined; + let bstCap = 9999; + let bstMin = 0; + if (originalBst) { + bstCap = originalBst + 100; + bstMin = originalBst - 100; + } while (isNullOrUndefined(newSpecies)) { - let bstCap = 9999; - let bstMin = 0; - if (originalBst) { - bstCap = originalBst + 100; - bstMin = originalBst - 100; - } - // Get all non-legendary species that fall within the Bst range requirements let validSpecies = allSpecies .filter(s => { diff --git a/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts b/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts index 509ffb11b26..02426c2cab6 100644 --- a/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts +++ b/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts @@ -33,7 +33,7 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with .withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES) .withIntroSpriteConfigs([ { - spriteKey: "buoy", + spriteKey: "lost_at_sea_buoy", fileRoot: "mystery-encounters", hasShadow: false, x: 20, diff --git a/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts b/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts index 18b2db53ba2..b5da4340dea 100644 --- a/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts +++ b/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts @@ -37,7 +37,7 @@ export const MysteriousChestEncounter: MysteryEncounter = .withCatchAllowed(true) .withIntroSpriteConfigs([ { - spriteKey: "chest_blue", + spriteKey: "mysterious_chest_blue", fileRoot: "mystery-encounters", hasShadow: true, y: 8, @@ -46,7 +46,7 @@ export const MysteriousChestEncounter: MysteryEncounter = disableAnimation: true, // Re-enabled after option select }, { - spriteKey: "chest_red", + spriteKey: "mysterious_chest_red", fileRoot: "mystery-encounters", hasShadow: false, y: 8, @@ -163,11 +163,12 @@ export const MysteriousChestEncounter: MysteryEncounter = leaveEncounterWithoutBattle(scene); } else { // Your highest level unfainted Pokemon gets OHKO. Start battle against a Gimmighoul (35%) - const highestLevelPokemon = getHighestLevelPlayerPokemon( - scene, - true - ); + const highestLevelPokemon = getHighestLevelPlayerPokemon(scene, true, false); koPlayerPokemon(scene, highestLevelPokemon); + + encounter.setDialogueToken("pokeName", highestLevelPokemon.getNameToRender()); + await showEncounterText(scene, `${namespace}.option.1.bad`); + // Handle game over edge case const allowedPokemon = scene.getParty().filter(p => p.isAllowedInBattle()); if (allowedPokemon.length === 0) { @@ -176,8 +177,6 @@ export const MysteriousChestEncounter: MysteryEncounter = scene.unshiftPhase(new GameOverPhase(scene)); } else { // Show which Pokemon was KOed, then start battle against Gimmighoul - encounter.setDialogueToken("pokeName", highestLevelPokemon.getNameToRender()); - await showEncounterText(scene, `${namespace}.option.1.bad`); transitionMysteryEncounterIntroVisuals(scene, true, true, 500); setEncounterRewards(scene, { fillRemaining: true }); await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]); diff --git a/src/data/mystery-encounters/encounters/part-timer-encounter.ts b/src/data/mystery-encounters/encounters/part-timer-encounter.ts index f5486d34ea9..4c31e83facb 100644 --- a/src/data/mystery-encounters/encounters/part-timer-encounter.ts +++ b/src/data/mystery-encounters/encounters/part-timer-encounter.ts @@ -8,10 +8,11 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { Stat } from "#enums/stat"; import { CHARMING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups"; -import { getEncounterText, showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; +import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import i18next from "i18next"; import Pokemon, { PlayerPokemon } from "#app/field/pokemon"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import { isPokemonValidForEncounterOptionSelection } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounter:partTimer"; @@ -27,7 +28,7 @@ export const PartTimerEncounter: MysteryEncounter = .withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES) .withIntroSpriteConfigs([ { - spriteKey: "warehouse_crate", + spriteKey: "part_timer_crate", fileRoot: "mystery-encounters", hasShadow: false, y: 6, @@ -117,11 +118,7 @@ export const PartTimerEncounter: MysteryEncounter = // Only Pokemon non-KOd pokemon can be selected const selectableFilter = (pokemon: Pokemon) => { - if (!pokemon.isAllowedInBattle()) { - return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null; - } - - return null; + return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`); }; return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter); @@ -198,11 +195,7 @@ export const PartTimerEncounter: MysteryEncounter = // Only Pokemon non-KOd pokemon can be selected const selectableFilter = (pokemon: Pokemon) => { - if (!pokemon.isAllowedInBattle()) { - return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null; - } - - return null; + return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`); }; return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter); diff --git a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts index 2690460757f..97aedc4f826 100644 --- a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts +++ b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts @@ -79,8 +79,8 @@ export const SafariZoneEncounter: MysteryEncounter = scene.loadSe("PRSFX- Bug Bite", "battle_anims", "PRSFX- Bug Bite.wav"); scene.loadSe("PRSFX- Sludge Bomb2", "battle_anims", "PRSFX- Sludge Bomb2.wav"); scene.loadSe("PRSFX- Taunt2", "battle_anims", "PRSFX- Taunt2.wav"); - scene.loadAtlas("bait", "mystery-encounters"); - scene.loadAtlas("mud", "mystery-encounters"); + scene.loadAtlas("safari_zone_bait", "mystery-encounters"); + scene.loadAtlas("safari_zone_mud", "mystery-encounters"); // Clear enemy party scene.currentBattle.enemyParty = []; await transitionMysteryEncounterIntroVisuals(scene); @@ -254,7 +254,7 @@ async function summonSafariPokemon(scene: BattleScene) { let enemySpecies; let pokemon; scene.executeWithSeedOffset(() => { - enemySpecies = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5])); + enemySpecies = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false)); const level = scene.currentBattle.getLevelForWave(); enemySpecies = getPokemonSpecies(enemySpecies.getWildSpeciesForLevel(level, true, false, scene.gameMode)); pokemon = scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.NONE, false); @@ -282,7 +282,7 @@ async function summonSafariPokemon(scene: BattleScene) { pokemon.calculateStats(); scene.currentBattle.enemyParty.unshift(pokemon); - }, scene.currentBattle.waveIndex * 1000 + encounter.misc.safariPokemonRemaining); + }, scene.currentBattle.waveIndex * 1000 * encounter.misc.safariPokemonRemaining); scene.gameData.setPokemonSeen(pokemon, true); await pokemon.loadAssets(); @@ -322,7 +322,7 @@ async function throwBait(scene: BattleScene, pokemon: EnemyPokemon): Promise { // If pokemon meets primary pokemon reqs, it can be selected - const meetsReqs = encounter.pokemonMeetsPrimaryRequirements(scene, pokemon); - if (!meetsReqs) { + if (!pokemon.isAllowed()) { + return i18next.t("partyUiHandler:cantBeUsed", { pokemonName: pokemon.getNameToRender() }) ?? null; + } + if (!encounter.pokemonMeetsPrimaryRequirements(scene, pokemon)) { return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null; } @@ -175,13 +178,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = // Only Pokemon that can gain benefits are unfainted const selectableFilter = (pokemon: Pokemon) => { - // If pokemon is unfainted it can be selected - const meetsReqs = !pokemon.isFainted(true); - if (!meetsReqs) { - return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null; - } - - return null; + return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`); }; return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter); diff --git a/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts b/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts index 10b0e5222b3..c35817255e0 100644 --- a/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts +++ b/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts @@ -44,7 +44,7 @@ export const TeleportingHijinksEncounter: MysteryEncounter = .withCatchAllowed(true) .withIntroSpriteConfigs([ { - spriteKey: "teleporter", + spriteKey: "teleporting_hijinks_teleporter", fileRoot: "mystery-encounters", hasShadow: true, x: 4, @@ -171,6 +171,12 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) { const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true); const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true); encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon)); + + // Defense/Spd buffs below wave 50, Atk/Def/Spd buffs otherwise + const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ? + [Stat.DEF, Stat.SPDEF, Stat.SPD] : + [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD]; + const config: EnemyPartyConfig = { pokemonConfigs: [{ level: level, @@ -180,7 +186,7 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) { tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { queueEncounterMessage(pokemon.scene, `${namespace}.boss_enraged`); - pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD], 1)); + pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1)); } }], }; diff --git a/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts b/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts index 104ddd3d663..91aeea79111 100644 --- a/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts @@ -1,6 +1,5 @@ -import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, setEncounterRewards, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { EnemyPartyConfig, generateModifierType, handleMysteryEncounterBattleFailed, initBattleWithEnemyConfig, setEncounterRewards, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { trainerConfigs } from "#app/data/trainer-config"; -import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import BattleScene from "#app/battle-scene"; import { randSeedShuffle } from "#app/utils"; @@ -14,8 +13,6 @@ import { Species } from "#enums/species"; import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species"; import { Nature } from "#enums/nature"; import { Moves } from "#enums/moves"; -import { Type } from "#app/data/type"; -import { Stat } from "#enums/stat"; import { PlayerPokemon } from "#app/field/pokemon"; import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { IEggOptions } from "#app/data/egg"; @@ -24,15 +21,18 @@ import { EggTier } from "#enums/egg-type"; import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { achvs } from "#app/system/achv"; +import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; +import { Type } from "#app/data/type"; +import { getPokeballTintColor } from "#app/data/pokeball"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounter:expertPokemonBreeder"; const trainerNameKey = "trainerNames:expert_pokemon_breeder"; -const FIRST_STAGE_EVOLUTION_WAVE = 30; -const SECOND_STAGE_EVOLUTION_WAVE = 45; -const FINAL_STAGE_EVOLUTION_WAVE = 60; +const FIRST_STAGE_EVOLUTION_WAVE = 45; +const SECOND_STAGE_EVOLUTION_WAVE = 60; +const FINAL_STAGE_EVOLUTION_WAVE = 75; const FRIENDSHIP_ADDED = 20; @@ -216,6 +216,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0]; const { pokemon1, pokemon1CommonEggs, pokemon1RareEggs } = encounter.misc; + encounter.misc.chosenPokemon = pokemon1; encounter.setDialogueToken("chosenPokemon", pokemon1.getNameToRender()); const eggOptions = getEggOptions(scene, pokemon1CommonEggs, pokemon1RareEggs); setEncounterRewards(scene, { fillRemaining: true }, eggOptions); @@ -241,14 +242,11 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = }); } + encounter.onGameOver = onGameOver; initBattleWithEnemyConfig(scene, config); }) .withPostOptionPhase(async (scene: BattleScene) => { - // Give achievement if in Space biome - checkAchievement(scene); - // Give 20 friendship to the chosen pokemon - scene.currentBattle.mysteryEncounter!.misc.pokemon1.addFriendship(FRIENDSHIP_ADDED); - await restorePartyAndHeldItems(scene); + await doPostEncounterCleanup(scene); }) .build() ) @@ -270,6 +268,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0]; const { pokemon2, pokemon2CommonEggs, pokemon2RareEggs } = encounter.misc; + encounter.misc.chosenPokemon = pokemon2; encounter.setDialogueToken("chosenPokemon", pokemon2.getNameToRender()); const eggOptions = getEggOptions(scene, pokemon2CommonEggs, pokemon2RareEggs); setEncounterRewards(scene, { fillRemaining: true }, eggOptions); @@ -295,14 +294,11 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = }); } + encounter.onGameOver = onGameOver; initBattleWithEnemyConfig(scene, config); }) .withPostOptionPhase(async (scene: BattleScene) => { - // Give achievement if in Space biome - checkAchievement(scene); - // Give 20 friendship to the chosen pokemon - scene.currentBattle.mysteryEncounter!.misc.pokemon2.addFriendship(FRIENDSHIP_ADDED); - await restorePartyAndHeldItems(scene); + await doPostEncounterCleanup(scene); }) .build() ) @@ -324,6 +320,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0]; const { pokemon3, pokemon3CommonEggs, pokemon3RareEggs } = encounter.misc; + encounter.misc.chosenPokemon = pokemon3; encounter.setDialogueToken("chosenPokemon", pokemon3.getNameToRender()); const eggOptions = getEggOptions(scene, pokemon3CommonEggs, pokemon3RareEggs); setEncounterRewards(scene, { fillRemaining: true }, eggOptions); @@ -349,19 +346,17 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = }); } + encounter.onGameOver = onGameOver; initBattleWithEnemyConfig(scene, config); }) .withPostOptionPhase(async (scene: BattleScene) => { - // Give achievement if in Space biome - checkAchievement(scene); - // Give 20 friendship to the chosen pokemon - scene.currentBattle.mysteryEncounter!.misc.pokemon3.addFriendship(FRIENDSHIP_ADDED); - await restorePartyAndHeldItems(scene); + await doPostEncounterCleanup(scene); }) .build() ) .withOutroDialogue([ { + speaker: trainerNameKey, text: `${namespace}.outro`, }, ]) @@ -379,7 +374,7 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig { trainerType: TrainerType.EXPERT_POKEMON_BREEDER, pokemonConfigs: [ { - nickname: i18next.t(`${namespace}.cleffa_1_nickname`), + nickname: i18next.t(`${namespace}.cleffa_1_nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName() }), species: getPokemonSpecies(cleffaSpecies), isBoss: false, abilityIndex: 1, // Magic Guard @@ -390,15 +385,7 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig { modifierConfigs: [ { modifier: generateModifierType(scene, modifierTypes.TERA_SHARD, [Type.STEEL]) as PokemonHeldItemModifierType, - }, - { - modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [Stat.ATK]) as PokemonHeldItemModifierType, - stackCount: 1 + Math.floor(waveIndex / 20), // +1 Protein every 20 waves - }, - { - modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [Stat.SPD]) as PokemonHeldItemModifierType, - stackCount: 1 + Math.floor(waveIndex / 40), // +1 Carbos every 40 waves - }, + } ] } ] @@ -407,7 +394,7 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig { if (scene.arena.biomeType === Biome.SPACE) { // All 3 members always Cleffa line, but different configs baseConfig.pokemonConfigs!.push({ - nickname: i18next.t(`${namespace}.cleffa_2_nickname`), + nickname: i18next.t(`${namespace}.cleffa_2_nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName() }), species: getPokemonSpecies(cleffaSpecies), isBoss: false, abilityIndex: 1, // Magic Guard @@ -547,3 +534,83 @@ async function restorePartyAndHeldItems(scene: BattleScene) { }); await scene.updateModifiers(true); } + +function onGameOver(scene: BattleScene) { + const encounter = scene.currentBattle.mysteryEncounter!; + + encounter.dialogue.outro = [ + { + speaker: trainerNameKey, + text: `${namespace}.outro_failed`, + }, + ]; + + // Restore original party, player loses all friendship with chosen mon (it remains fainted) + restorePartyAndHeldItems(scene); + const chosenPokemon = encounter.misc.chosenPokemon; + chosenPokemon.friendship = 0; + + // Clear all rewards that would have been earned + encounter.doEncounterRewards = undefined; + + // Set flag that encounter was failed + encounter.misc.encounterFailed = true; + + // Revert BGM + scene.playBgm(scene.arena.bgm); + + // Return enemy Pokemon + const pokemon = scene.getEnemyPokemon(); + if (pokemon) { + scene.playSound("se/pb_rel"); + pokemon.hideInfo(); + pokemon.tint(getPokeballTintColor(pokemon.pokeball), 1, 250, "Sine.easeIn"); + scene.tweens.add({ + targets: pokemon, + duration: 250, + ease: "Sine.easeIn", + scale: 0.5, + onComplete: () => { + scene.field.remove(pokemon, true); + } + }); + } + + // Show the enemy trainer + scene.time.delayedCall(250, () => { + const sprites = scene.currentBattle.trainer?.getSprites(); + const tintSprites = scene.currentBattle.trainer?.getTintSprites(); + if (sprites && tintSprites) { + for (let i = 0; i < sprites.length; i++) { + sprites[i].setVisible(true); + tintSprites[i].setVisible(true); + sprites[i].clearTint(); + tintSprites[i].clearTint(); + } + } + scene.tweens.add({ + targets: scene.currentBattle.trainer, + x: "-=16", + y: "+=16", + alpha: 1, + ease: "Sine.easeInOut", + duration: 750 + }); + }); + + + handleMysteryEncounterBattleFailed(scene, true); + + return false; +} + +async function doPostEncounterCleanup(scene: BattleScene) { + const encounter = scene.currentBattle.mysteryEncounter!; + if (!encounter.misc.encounterFailed) { + // Give achievement if in Space biome + checkAchievement(scene); + // Give 20 friendship to the chosen pokemon + encounter.misc.chosenPokemon.addFriendship(FRIENDSHIP_ADDED); + await restorePartyAndHeldItems(scene); + } +} diff --git a/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts b/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts index c26c6aa3b7f..ba6a628f51e 100644 --- a/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts @@ -58,12 +58,12 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = .withOnInit((scene: BattleScene) => { const encounter = scene.currentBattle.mysteryEncounter!; - let species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5])); + let species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false)); const tries = 0; // Reroll any species that don't have HAs while ((isNullOrUndefined(species.abilityHidden) || species.abilityHidden === Abilities.NONE) && tries < 5) { - species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5])); + species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false)); } let pokemon: PlayerPokemon; diff --git a/src/data/mystery-encounters/encounters/training-session-encounter.ts b/src/data/mystery-encounters/encounters/training-session-encounter.ts index 33d841b7f02..cdf1cef540c 100644 --- a/src/data/mystery-encounters/encounters/training-session-encounter.ts +++ b/src/data/mystery-encounters/encounters/training-session-encounter.ts @@ -13,13 +13,14 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import BattleScene from "#app/battle-scene"; import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; -import { getEncounterText, queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; +import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import HeldModifierConfig from "#app/interfaces/held-modifier-config"; import i18next from "i18next"; import { getStatKey } from "#enums/stat"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import { isPokemonValidForEncounterOptionSelection } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; /** The i18n namespace for the encounter */ const namespace = "mysteryEncounter:trainingSession"; @@ -38,7 +39,7 @@ export const TrainingSessionEncounter: MysteryEncounter = .withHideWildIntroMessage(true) .withIntroSpriteConfigs([ { - spriteKey: "training_gear", + spriteKey: "training_session_gear", fileRoot: "mystery-encounters", hasShadow: true, y: 6, @@ -77,12 +78,7 @@ export const TrainingSessionEncounter: MysteryEncounter = // Only Pokemon that are not KOed/legal can be trained const selectableFilter = (pokemon: Pokemon) => { - const meetsReqs = pokemon.isAllowedInBattle(); - if (!meetsReqs) { - return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null; - } - - return null; + return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`); }; return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter); @@ -211,12 +207,7 @@ export const TrainingSessionEncounter: MysteryEncounter = // Only Pokemon that are not KOed/legal can be trained const selectableFilter = (pokemon: Pokemon) => { - const meetsReqs = pokemon.isAllowedInBattle(); - if (!meetsReqs) { - return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null; - } - - return null; + return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`); }; return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter); @@ -307,12 +298,7 @@ export const TrainingSessionEncounter: MysteryEncounter = // Only Pokemon that are not KOed/legal can be trained const selectableFilter = (pokemon: Pokemon) => { - const meetsReqs = pokemon.isAllowedInBattle(); - if (!meetsReqs) { - return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null; - } - - return null; + return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`); }; return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter); diff --git a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts index 0816c9cd2a6..4f8a43ce364 100644 --- a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts +++ b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts @@ -50,7 +50,7 @@ export const UncommonBreedEncounter: MysteryEncounter = // Calculate boss mon // Level equal to 2 below highest party member - const level = getHighestLevelPlayerPokemon(scene).level - 2; + const level = getHighestLevelPlayerPokemon(scene, false, true).level - 2; const species = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true); const pokemon = new EnemyPokemon(scene, species, level, TrainerSlot.NONE, true); const speciesRootForm = pokemon.species.getRootSpeciesId(); diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index ed8986d99bb..0b3b4434278 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -20,7 +20,8 @@ import i18next from "#app/plugins/i18n"; import { doPokemonTransformationSequence, TransformationScreenPosition } from "#app/data/mystery-encounters/utils/encounter-transformation-sequence"; import { getLevelTotalExp } from "#app/data/exp"; import { Stat } from "#enums/stat"; -import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES, GameModes } from "#app/game-mode"; +import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; +import { Challenges } from "#enums/challenges"; /** i18n namespace for encounter */ const namespace = "mysteryEncounter:weirdDream"; @@ -82,6 +83,9 @@ const SUPER_LEGENDARY_BST_THRESHOLD = 600; const NON_LEGENDARY_BST_THRESHOLD = 570; const GAIN_OLD_GATEAU_ITEM_BST_THRESHOLD = 450; +/** 0-100 */ +const PERCENT_LEVEL_LOSS_ON_REFUSE = 12.5; + /** * Value ranges of the resulting species BST transformations after adding values to original species * 2 Pokemon in the party use this range @@ -101,7 +105,7 @@ const STANDARD_BST_TRANSFORM_BASE_VALUES: [number, number] = [40, 50]; export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.WEIRD_DREAM) .withEncounterTier(MysteryEncounterTier.ROGUE) - .withDisabledGameModes(GameModes.CHALLENGE) + .withDisallowedChallenges(Challenges.SINGLE_TYPE) .withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES) .withIntroSpriteConfigs([ { @@ -207,7 +211,7 @@ export const WeirdDreamEncounter: MysteryEncounter = async (scene: BattleScene) => { // Reduce party levels by 20% for (const pokemon of scene.getParty()) { - pokemon.level = Math.max(Math.ceil(0.8 * pokemon.level), 1); + pokemon.level = Math.max(Math.ceil((100 - PERCENT_LEVEL_LOSS_ON_REFUSE) / 100 * pokemon.level), 1); pokemon.exp = getLevelTotalExp(pokemon.level, pokemon.species.growthRate); pokemon.levelExp = 0; @@ -339,6 +343,9 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon } } + // If the previous pokemon had pokerus, transfer to new pokemon + newPokemon.pokerus = previousPokemon.pokerus; + // If the previous pokemon had higher IVs, override to those (after updating dex IVs > prevents perfect 31s on a new unlock) newPokemon.ivs = newPokemon.ivs.map((iv, index) => { return previousPokemon.ivs[index] > iv ? previousPokemon.ivs[index] : iv; @@ -349,22 +356,46 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon scene.gameData.addStarterCandy(getPokemonSpecies(speciesRootForm), 1); } - // Set the moveset of the new pokemon to be the same as previous, but with 1 egg move of the new species + // Set the moveset of the new pokemon to be the same as previous, but with 1 egg move and 1 (attempted) STAB move of the new species + newPokemon.generateAndPopulateMoveset(); + + // Try to find a favored STAB move + let favoredMove; + for (const move of newPokemon.moveset) { + // Needs to match first type, second type will be replaced + if (move?.getMove().type === newPokemon.getTypes()[0]) { + favoredMove = move; + break; + } + } + // If was unable to find a move, uses first move in moveset (typically a high power STAB move) + favoredMove = favoredMove ?? newPokemon.moveset[0]; + newPokemon.moveset = previousPokemon.moveset; + let eggMoveIndex: null | number = null; if (speciesEggMoves.hasOwnProperty(speciesRootForm)) { const eggMoves = speciesEggMoves[speciesRootForm]; - const eggMoveIndex = randSeedInt(4); - const randomEggMove = eggMoves[eggMoveIndex]; + const randomEggMoveIndex = randSeedInt(4); + const randomEggMove = eggMoves[randomEggMoveIndex]; if (newPokemon.moveset.length < 4) { newPokemon.moveset.push(new PokemonMove(randomEggMove)); } else { - newPokemon.moveset[randSeedInt(4)] = new PokemonMove(randomEggMove); + eggMoveIndex = randSeedInt(4); + newPokemon.moveset[eggMoveIndex] = new PokemonMove(randomEggMove); } // For pokemon that the player owns (including ones just caught), unlock the egg move if (!!scene.gameData.dexData[speciesRootForm].caughtAttr) { - await scene.gameData.setEggMoveUnlocked(getPokemonSpecies(speciesRootForm), eggMoveIndex, true); + await scene.gameData.setEggMoveUnlocked(getPokemonSpecies(speciesRootForm), randomEggMoveIndex, true); } } + if (favoredMove) { + let favoredMoveIndex = randSeedInt(4); + while (favoredMoveIndex === eggMoveIndex) { + favoredMoveIndex = randSeedInt(4); + } + + newPokemon.moveset[favoredMoveIndex] = favoredMove; + } // Randomize the second type of the pokemon // If the pokemon does not normally have a second type, it will gain 1 diff --git a/src/data/mystery-encounters/mystery-encounter-requirements.ts b/src/data/mystery-encounters/mystery-encounter-requirements.ts index 8dd6568e929..1141b492d42 100644 --- a/src/data/mystery-encounters/mystery-encounter-requirements.ts +++ b/src/data/mystery-encounters/mystery-encounter-requirements.ts @@ -259,23 +259,23 @@ export class WeatherRequirement extends EncounterSceneRequirement { export class PartySizeRequirement extends EncounterSceneRequirement { partySizeRange: [number, number]; - excludeFainted: boolean; + excludeDisallowedPokemon: boolean; /** * Used for specifying a party size requirement * If min and max are equivalent, will check for exact size * @param partySizeRange - * @param excludeFainted + * @param excludeDisallowedPokemon */ - constructor(partySizeRange: [number, number], excludeFainted: boolean) { + constructor(partySizeRange: [number, number], excludeDisallowedPokemon: boolean) { super(); this.partySizeRange = partySizeRange; - this.excludeFainted = excludeFainted; + this.excludeDisallowedPokemon = excludeDisallowedPokemon; } override meetsRequirement(scene: BattleScene): boolean { if (!isNullOrUndefined(this.partySizeRange) && this.partySizeRange?.[0] <= this.partySizeRange?.[1]) { - const partySize = this.excludeFainted ? scene.getParty().filter(p => p.isAllowedInBattle()).length : scene.getParty().length; + const partySize = this.excludeDisallowedPokemon ? scene.getParty().filter(p => p.isAllowedInBattle()).length : scene.getParty().length; if (partySize >= 0 && (this.partySizeRange?.[0] >= 0 && this.partySizeRange?.[0] > partySize) || (this.partySizeRange?.[1] >= 0 && this.partySizeRange?.[1] < partySize)) { return false; } @@ -767,12 +767,14 @@ export class HeldItemRequirement extends EncounterPokemonRequirement { requiredHeldItemModifiers: string[]; minNumberOfPokemon: number; invertQuery: boolean; + requireTransferable: boolean; - constructor(heldItem: string | string[], minNumberOfPokemon: number = 1, invertQuery: boolean = false) { + constructor(heldItem: string | string[], minNumberOfPokemon: number = 1, invertQuery: boolean = false, requireTransferable: boolean = true) { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; this.requiredHeldItemModifiers = Array.isArray(heldItem) ? heldItem : [heldItem]; + this.requireTransferable = requireTransferable; } override meetsRequirement(scene: BattleScene): boolean { @@ -787,21 +789,23 @@ export class HeldItemRequirement extends EncounterPokemonRequirement { if (!this.invertQuery) { return partyPokemon.filter((pokemon) => this.requiredHeldItemModifiers.some((heldItem) => { return pokemon.getHeldItems().some((it) => { - return it.constructor.name === heldItem; + return it.constructor.name === heldItem && (!this.requireTransferable || it.isTransferable); }); })); } else { // for an inverted query, we only want to get the pokemon that have any held items that are NOT in requiredHeldItemModifiers // E.g. functions as a blacklist return partyPokemon.filter((pokemon) => pokemon.getHeldItems().filter((it) => { - return !this.requiredHeldItemModifiers.some(heldItem => it.constructor.name === heldItem); + return !this.requiredHeldItemModifiers.some(heldItem => it.constructor.name === heldItem) + && (!this.requireTransferable || it.isTransferable); }).length > 0); } } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { const requiredItems = pokemon?.getHeldItems().filter((it) => { - return this.requiredHeldItemModifiers.some(heldItem => it.constructor.name === heldItem); + return this.requiredHeldItemModifiers.some(heldItem => it.constructor.name === heldItem) + && (!this.requireTransferable || it.isTransferable); }); if (requiredItems && requiredItems.length > 0) { return ["heldItem", requiredItems[0].type.name]; @@ -814,12 +818,14 @@ export class AttackTypeBoosterHeldItemTypeRequirement extends EncounterPokemonRe requiredHeldItemTypes: Type[]; minNumberOfPokemon: number; invertQuery: boolean; + requireTransferable: boolean; - constructor(heldItemTypes: Type | Type[], minNumberOfPokemon: number = 1, invertQuery: boolean = false) { + constructor(heldItemTypes: Type | Type[], minNumberOfPokemon: number = 1, invertQuery: boolean = false, requireTransferable: boolean = true) { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; this.requiredHeldItemTypes = Array.isArray(heldItemTypes) ? heldItemTypes : [heldItemTypes]; + this.requireTransferable = requireTransferable; } override meetsRequirement(scene: BattleScene): boolean { @@ -834,21 +840,29 @@ export class AttackTypeBoosterHeldItemTypeRequirement extends EncounterPokemonRe if (!this.invertQuery) { return partyPokemon.filter((pokemon) => this.requiredHeldItemTypes.some((heldItemType) => { return pokemon.getHeldItems().some((it) => { - return it instanceof AttackTypeBoosterModifier && (it.type as AttackTypeBoosterModifierType).moveType === heldItemType; + return it instanceof AttackTypeBoosterModifier + && (it.type as AttackTypeBoosterModifierType).moveType === heldItemType + && (!this.requireTransferable || it.isTransferable); }); })); } else { // for an inverted query, we only want to get the pokemon that have any held items that are NOT in requiredHeldItemModifiers // E.g. functions as a blacklist return partyPokemon.filter((pokemon) => pokemon.getHeldItems().filter((it) => { - return !this.requiredHeldItemTypes.some(heldItemType => it instanceof AttackTypeBoosterModifier && (it.type as AttackTypeBoosterModifierType).moveType === heldItemType); + return !this.requiredHeldItemTypes.some(heldItemType => + it instanceof AttackTypeBoosterModifier + && (it.type as AttackTypeBoosterModifierType).moveType === heldItemType + && (!this.requireTransferable || it.isTransferable)); }).length > 0); } } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { const requiredItems = pokemon?.getHeldItems().filter((it) => { - return this.requiredHeldItemTypes.some(heldItemType => it instanceof AttackTypeBoosterModifier && (it.type as AttackTypeBoosterModifierType).moveType === heldItemType); + return this.requiredHeldItemTypes.some(heldItemType => + it instanceof AttackTypeBoosterModifier + && (it.type as AttackTypeBoosterModifierType).moveType === heldItemType) + && (!this.requireTransferable || it.isTransferable); }); if (requiredItems && requiredItems.length > 0) { return ["heldItem", requiredItems[0].type.name]; diff --git a/src/data/mystery-encounters/mystery-encounter.ts b/src/data/mystery-encounters/mystery-encounter.ts index 2a5f6fda7e1..da4d29c94d6 100644 --- a/src/data/mystery-encounters/mystery-encounter.ts +++ b/src/data/mystery-encounters/mystery-encounter.ts @@ -15,6 +15,7 @@ import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { GameModes } from "#app/game-mode"; import { EncounterAnim } from "#enums/encounter-anims"; +import { Challenges } from "#enums/challenges"; export interface EncounterStartOfBattleEffect { sourcePokemon?: Pokemon; @@ -40,7 +41,8 @@ export interface IMysteryEncounter { spriteConfigs: MysteryEncounterSpriteConfig[]; encounterTier: MysteryEncounterTier; encounterAnimations?: EncounterAnim[]; - disabledGameModes?: GameModes[]; + disallowedGameModes?: GameModes[]; + disallowedChallenges?: Challenges[]; hideBattleIntroMessage: boolean; autoHideIntroVisuals: boolean; enterIntroVisualsFromRight: boolean; @@ -93,7 +95,11 @@ export default class MysteryEncounter implements IMysteryEncounter { /** * If specified, defines any game modes where the {@linkcode MysteryEncounter} should *NOT* spawn */ - disabledGameModes?: GameModes[]; + disallowedGameModes?: GameModes[]; + /** + * If specified, defines any challenges (from Challenge game mode) where the {@linkcode MysteryEncounter} should *NOT* spawn + */ + disallowedChallenges?: Challenges[]; /** * If true, hides "A Wild X Appeared" etc. messages * Default true @@ -161,6 +167,11 @@ export default class MysteryEncounter implements IMysteryEncounter { doEncounterRewards?: (scene: BattleScene) => boolean; /** Will execute callback during VictoryPhase of a continuousEncounter */ doContinueEncounter?: (scene: BattleScene) => Promise; + /** + * Can perform special logic when a ME battle is lost, before GameOver/battle retry prompt. + * Should return `true` if it is treated as "real" Game Over, `false` if not. + */ + onGameOver?: (scene: BattleScene) => boolean; /** * Requirements @@ -656,11 +667,21 @@ export class MysteryEncounterBuilder implements Partial { /** * Defines any game modes where the Mystery Encounter should *NOT* spawn * @returns - * @param disabledGameModes + * @param disallowedGameModes */ - withDisabledGameModes(...disabledGameModes: GameModes[]): this & Required> { - const gameModes = Array.isArray(disabledGameModes) ? disabledGameModes : [disabledGameModes]; - return Object.assign(this, { disabledGameModes: gameModes }); + withDisallowedGameModes(...disallowedGameModes: GameModes[]): this & Required> { + const gameModes = Array.isArray(disallowedGameModes) ? disallowedGameModes : [disallowedGameModes]; + return Object.assign(this, { disallowedGameModes: gameModes }); + } + + /** + * Defines any challenges (from Challenge game mode) where the Mystery Encounter should *NOT* spawn + * @returns + * @param disallowedChallenges + */ + withDisallowedChallenges(...disallowedChallenges: Challenges[]): this & Required> { + const challenges = Array.isArray(disallowedChallenges) ? disallowedChallenges : [disallowedChallenges]; + return Object.assign(this, { disallowedChallenges: challenges }); } /** @@ -742,11 +763,11 @@ export class MysteryEncounterBuilder implements Partial { * * @param min min wave (or exact size if only min is given) * @param max optional max size. If not given, defaults to min => exact wave - * @param excludeFainted if true, only counts unfainted mons + * @param excludeDisallowedPokemon if true, only counts allowed (legal in Challenge/unfainted) mons * @returns */ - withScenePartySizeRequirement(min: number, max?: number, excludeFainted: boolean = false): this & Required> { - return this.withSceneRequirement(new PartySizeRequirement([min, max ?? min], excludeFainted)); + withScenePartySizeRequirement(min: number, max?: number, excludeDisallowedPokemon: boolean = false): this & Required> { + return this.withSceneRequirement(new PartySizeRequirement([min, max ?? min], excludeDisallowedPokemon)); } /** diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index 187de3c93c4..7eb205ce3f7 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -43,7 +43,7 @@ import { Variant } from "#app/data/variant"; * @param scene */ export function doTrainerExclamation(scene: BattleScene) { - const exclamationSprite = scene.add.sprite(0, 0, "exclaim"); + const exclamationSprite = scene.add.sprite(0, 0, "encounter_exclaim"); exclamationSprite.setName("exclamation"); scene.field.add(exclamationSprite); scene.field.moveTo(exclamationSprite, scene.field.getAll().length - 1); @@ -744,6 +744,37 @@ export function handleMysteryEncounterVictory(scene: BattleScene, addHealPhase: } } +/** + * Similar to {@linkcode handleMysteryEncounterVictory}, but for cases where the player lost a battle or failed a challenge + * @param scene + * @param addHealPhase + */ +export function handleMysteryEncounterBattleFailed(scene: BattleScene, addHealPhase: boolean = false, doNotContinue: boolean = false) { + const allowedPkm = scene.getParty().filter((pkm) => pkm.isAllowedInBattle()); + + if (allowedPkm.length === 0) { + scene.clearPhaseQueue(); + scene.unshiftPhase(new GameOverPhase(scene)); + return; + } + + // If in repeated encounter variant, do nothing + // Variant must eventually be swapped in order to handle "true" end of the encounter + const encounter = scene.currentBattle.mysteryEncounter!; + if (encounter.continuousEncounter || doNotContinue) { + return; + } else if (encounter.encounterMode !== MysteryEncounterMode.NO_BATTLE) { + scene.pushPhase(new BattleEndPhase(scene, false)); + } + + scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase)); + + if (!encounter.doContinueEncounter) { + // Only lapse eggs once for multi-battle encounters + scene.pushPhase(new EggLapsePhase(scene)); + } +} + /** * * @param scene diff --git a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts index 86c86010c29..5db84186471 100644 --- a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts @@ -13,7 +13,7 @@ import { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler"; import { Species } from "#enums/species"; import { Type } from "#app/data/type"; import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species"; -import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; +import { getEncounterText, queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getPokemonNameWithAffix } from "#app/messages"; import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { Gender } from "#app/data/gender"; @@ -50,28 +50,39 @@ export function getSpriteKeysFromPokemon(pokemon: Pokemon): { spriteKey: string, } /** - * * Will never remove the player's last non-fainted Pokemon (if they only have 1) * Otherwise, picks a Pokemon completely at random and removes from the party * @param scene - * @param isAllowedInBattle Default false. If true, only picks from unfainted mons. If there is only 1 unfainted mon left and doNotReturnLastAbleMon is also true, will return fainted mon - * @param doNotReturnLastAbleMon Default false. If true, will never return the last unfainted pokemon in the party. Useful when this function is being used to determine what Pokemon to remove from the party (Don't want to remove last unfainted) + * @param isAllowed Default false. If true, only picks from legal mons. If no legal mons are found (or there is 1, with `doNotReturnLastAllowedMon = true), will return a mon that is not allowed. + * @param isFainted Default false. If true, includes fainted mons. + * @param doNotReturnLastAllowedMon Default false. If true, will never return the last unfainted pokemon in the party. Useful when this function is being used to determine what Pokemon to remove from the party (Don't want to remove last unfainted) * @returns */ -export function getRandomPlayerPokemon(scene: BattleScene, isAllowedInBattle: boolean = false, doNotReturnLastAbleMon: boolean = false): PlayerPokemon { +export function getRandomPlayerPokemon(scene: BattleScene, isAllowed: boolean = false, isFainted: boolean = false, doNotReturnLastAllowedMon: boolean = false): PlayerPokemon { const party = scene.getParty(); let chosenIndex: number; - let chosenPokemon: PlayerPokemon; - const unfaintedMons = party.filter(p => p.isAllowedInBattle()); - const faintedMons = party.filter(p => !p.isAllowedInBattle()); + let chosenPokemon: PlayerPokemon | null = null; + const fullyLegalMons = party.filter(p => (!isAllowed || p.isAllowed()) && (isFainted || !p.isFainted())); + const allowedOnlyMons = party.filter(p => p.isAllowed()); - if (doNotReturnLastAbleMon && unfaintedMons.length === 1) { - chosenIndex = randSeedInt(faintedMons.length); - chosenPokemon = faintedMons[chosenIndex]; - } else if (isAllowedInBattle) { - chosenIndex = randSeedInt(unfaintedMons.length); - chosenPokemon = unfaintedMons[chosenIndex]; - } else { + if (doNotReturnLastAllowedMon && fullyLegalMons.length === 1) { + // If there is only 1 legal/unfainted mon left, select from fainted legal mons + const faintedLegalMons = party.filter(p => (!isAllowed || p.isAllowed()) && p.isFainted()); + if (faintedLegalMons.length > 0) { + chosenIndex = randSeedInt(faintedLegalMons.length); + chosenPokemon = faintedLegalMons[chosenIndex]; + } + } + if (!chosenPokemon && fullyLegalMons.length > 0) { + chosenIndex = randSeedInt(fullyLegalMons.length); + chosenPokemon = fullyLegalMons[chosenIndex]; + } + if (!chosenPokemon && isAllowed && allowedOnlyMons.length > 0) { + chosenIndex = randSeedInt(allowedOnlyMons.length); + chosenPokemon = allowedOnlyMons[chosenIndex]; + } + if (!chosenPokemon) { + // If no other options worked, returns fully random chosenIndex = randSeedInt(party.length); chosenPokemon = party[chosenIndex]; } @@ -82,15 +93,19 @@ export function getRandomPlayerPokemon(scene: BattleScene, isAllowedInBattle: bo /** * Ties are broken by whatever mon is closer to the front of the party * @param scene - * @param unfainted Default false. If true, only picks from unfainted mons. + * @param isAllowed Default false. If true, only picks from legal mons. + * @param isFainted Default false. If true, includes fainted mons. * @returns */ -export function getHighestLevelPlayerPokemon(scene: BattleScene, unfainted: boolean = false): PlayerPokemon { +export function getHighestLevelPlayerPokemon(scene: BattleScene, isAllowed: boolean = false, isFainted: boolean = false): PlayerPokemon { const party = scene.getParty(); let pokemon: PlayerPokemon | null = null; for (const p of party) { - if (unfainted && p.isFainted()) { + if (isAllowed && !p.isAllowed()) { + continue; + } + if (!isFainted && p.isFainted()) { continue; } @@ -104,15 +119,19 @@ export function getHighestLevelPlayerPokemon(scene: BattleScene, unfainted: bool * Ties are broken by whatever mon is closer to the front of the party * @param scene * @param stat Stat to search for - * @param unfainted Default false. If true, only picks from unfainted mons. + * @param isAllowed Default false. If true, only picks from legal mons. + * @param isFainted Default false. If true, includes fainted mons. * @returns */ -export function getHighestStatPlayerPokemon(scene: BattleScene, stat: PermanentStat, unfainted: boolean = false): PlayerPokemon { +export function getHighestStatPlayerPokemon(scene: BattleScene, stat: PermanentStat, isAllowed: boolean = false, isFainted: boolean = false): PlayerPokemon { const party = scene.getParty(); let pokemon: PlayerPokemon | null = null; for (const p of party) { - if (unfainted && p.isFainted()) { + if (isAllowed && !p.isAllowed()) { + continue; + } + if (!isFainted && p.isFainted()) { continue; } @@ -125,15 +144,19 @@ export function getHighestStatPlayerPokemon(scene: BattleScene, stat: PermanentS /** * Ties are broken by whatever mon is closer to the front of the party * @param scene - * @param unfainted - default false. If true, only picks from unfainted mons. + * @param isAllowed Default false. If true, only picks from legal mons. + * @param isFainted Default false. If true, includes fainted mons. * @returns */ -export function getLowestLevelPlayerPokemon(scene: BattleScene, unfainted: boolean = false): PlayerPokemon { +export function getLowestLevelPlayerPokemon(scene: BattleScene, isAllowed: boolean = false, isFainted: boolean = false): PlayerPokemon { const party = scene.getParty(); let pokemon: PlayerPokemon | null = null; for (const p of party) { - if (unfainted && p.isFainted()) { + if (isAllowed && !p.isAllowed()) { + continue; + } + if (!isFainted && p.isFainted()) { continue; } @@ -146,15 +169,19 @@ export function getLowestLevelPlayerPokemon(scene: BattleScene, unfainted: boole /** * Ties are broken by whatever mon is closer to the front of the party * @param scene - * @param unfainted - default false. If true, only picks from unfainted mons. + * @param isAllowed Default false. If true, only picks from legal mons. + * @param isFainted Default false. If true, includes fainted mons. * @returns */ -export function getHighestStatTotalPlayerPokemon(scene: BattleScene, unfainted: boolean = false): PlayerPokemon { +export function getHighestStatTotalPlayerPokemon(scene: BattleScene, isAllowed: boolean = false, isFainted: boolean = false): PlayerPokemon { const party = scene.getParty(); let pokemon: PlayerPokemon | null = null; for (const p of party) { - if (unfainted && p.isFainted()) { + if (isAllowed && !p.isAllowed()) { + continue; + } + if (!isFainted && p.isFainted()) { continue; } @@ -170,15 +197,24 @@ export function getHighestStatTotalPlayerPokemon(scene: BattleScene, unfainted: * @param starterTiers * @param excludedSpecies * @param types + * @param allowSubLegendary + * @param allowLegendary + * @param allowMythical * @returns */ -export function getRandomSpeciesByStarterTier(starterTiers: number | [number, number], excludedSpecies?: Species[], types?: Type[]): Species { +export function getRandomSpeciesByStarterTier(starterTiers: number | [number, number], excludedSpecies?: Species[], types?: Type[], allowSubLegendary: boolean = true, allowLegendary: boolean = true, allowMythical: boolean = true): Species { let min = Array.isArray(starterTiers) ? starterTiers[0] : starterTiers; let max = Array.isArray(starterTiers) ? starterTiers[1] : starterTiers; let filteredSpecies: [PokemonSpecies, number][] = Object.keys(speciesStarters) .map(s => [parseInt(s) as Species, speciesStarters[s] as number]) - .filter(s => getPokemonSpecies(s[0]) && (!excludedSpecies || !excludedSpecies.includes(s[0]))) + .filter(s => { + const pokemonSpecies = getPokemonSpecies(s[0]); + return pokemonSpecies && (!excludedSpecies || !excludedSpecies.includes(s[0]) + && (allowSubLegendary || !pokemonSpecies.subLegendary) + && (allowLegendary || !pokemonSpecies.legendary) + && (allowMythical || !pokemonSpecies.mythical)); + }) .map(s => [getPokemonSpecies(s[0]), s[1]]); if (types && types.length > 0) { @@ -773,3 +809,23 @@ export async function addPokemonDataToDexAndValidateAchievements(scene: BattleSc scene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs); return scene.gameData.setPokemonCaught(pokemon, true, false, false); } + +/** + * Checks if a Pokemon is allowed under a challenge, and allowed in battle. + * If both are true, returns `null`. + * If one of them is not true, returns message content that the Pokemon is invalid. + * Typically used for cheecking whether a Pokemon can be selected for a {@linkcode MysteryEncounterOption} + * @param pokemon + * @param scene + * @param invalidSelectionKey + */ +export function isPokemonValidForEncounterOptionSelection(pokemon: Pokemon, scene: BattleScene, invalidSelectionKey: string): string | null { + if (!pokemon.isAllowed()) { + return i18next.t("partyUiHandler:cantBeUsed", { pokemonName: pokemon.getNameToRender() }) ?? null; + } + if (!pokemon.isAllowedInBattle()) { + return getEncounterText(scene, invalidSelectionKey) ?? null; + } + + return null; +} diff --git a/src/data/pokemon-level-moves.ts b/src/data/pokemon-level-moves.ts index b56bab724be..b5608093df2 100644 --- a/src/data/pokemon-level-moves.ts +++ b/src/data/pokemon-level-moves.ts @@ -19498,6 +19498,108 @@ export const pokemonFormLevelMoves: PokemonSpeciesFormLevelMoves = { [ 51, Moves.BELCH ], ], }, + [Species.REVAVROOM]: { + 1: [ + [ EVOLVE_MOVE, Moves.WICKED_TORQUE ], + [ EVOLVE_MOVE, Moves.SHIFT_GEAR ], + [ 1, Moves.LICK ], + [ 1, Moves.POISON_GAS ], + [ 1, Moves.MAGNET_RISE ], + [ 4, Moves.SMOG ], + [ 7, Moves.TAUNT ], + [ 10, Moves.ASSURANCE ], + [ 13, Moves.SLUDGE ], + [ 17, Moves.GYRO_BALL ], + [ 21, Moves.HEADBUTT ], + [ 25, Moves.SCREECH ], + [ 28, Moves.IRON_HEAD ], + [ 32, Moves.SWAGGER ], + [ 36, Moves.POISON_JAB ], + [ 46, Moves.UPROAR ], + [ 52, Moves.SPIN_OUT ], + [ 58, Moves.GUNK_SHOT ], + ], + 2: [ + [ EVOLVE_MOVE, Moves.BLAZING_TORQUE ], + [ EVOLVE_MOVE, Moves.SHIFT_GEAR ], + [ 1, Moves.LICK ], + [ 1, Moves.POISON_GAS ], + [ 1, Moves.MAGNET_RISE ], + [ 4, Moves.SMOG ], + [ 7, Moves.TAUNT ], + [ 10, Moves.ASSURANCE ], + [ 13, Moves.SLUDGE ], + [ 17, Moves.GYRO_BALL ], + [ 21, Moves.HEADBUTT ], + [ 25, Moves.SCREECH ], + [ 28, Moves.IRON_HEAD ], + [ 32, Moves.SWAGGER ], + [ 36, Moves.POISON_JAB ], + [ 46, Moves.UPROAR ], + [ 52, Moves.SPIN_OUT ], + [ 58, Moves.GUNK_SHOT ], + ], + 3: [ + [ EVOLVE_MOVE, Moves.NOXIOUS_TORQUE ], + [ EVOLVE_MOVE, Moves.SHIFT_GEAR ], + [ 1, Moves.LICK ], + [ 1, Moves.POISON_GAS ], + [ 1, Moves.MAGNET_RISE ], + [ 4, Moves.SMOG ], + [ 7, Moves.TAUNT ], + [ 10, Moves.ASSURANCE ], + [ 13, Moves.SLUDGE ], + [ 17, Moves.GYRO_BALL ], + [ 21, Moves.HEADBUTT ], + [ 25, Moves.SCREECH ], + [ 28, Moves.IRON_HEAD ], + [ 32, Moves.SWAGGER ], + [ 36, Moves.POISON_JAB ], + [ 46, Moves.UPROAR ], + [ 52, Moves.SPIN_OUT ], + [ 58, Moves.GUNK_SHOT ], + ], + 4: [ + [ EVOLVE_MOVE, Moves.MAGICAL_TORQUE ], + [ EVOLVE_MOVE, Moves.SHIFT_GEAR ], + [ 1, Moves.LICK ], + [ 1, Moves.POISON_GAS ], + [ 1, Moves.MAGNET_RISE ], + [ 4, Moves.SMOG ], + [ 7, Moves.TAUNT ], + [ 10, Moves.ASSURANCE ], + [ 13, Moves.SLUDGE ], + [ 17, Moves.GYRO_BALL ], + [ 21, Moves.HEADBUTT ], + [ 25, Moves.SCREECH ], + [ 28, Moves.IRON_HEAD ], + [ 32, Moves.SWAGGER ], + [ 36, Moves.POISON_JAB ], + [ 46, Moves.UPROAR ], + [ 52, Moves.SPIN_OUT ], + [ 58, Moves.GUNK_SHOT ], + ], + 5: [ + [ EVOLVE_MOVE, Moves.COMBAT_TORQUE ], + [ EVOLVE_MOVE, Moves.SHIFT_GEAR ], + [ 1, Moves.LICK ], + [ 1, Moves.POISON_GAS ], + [ 1, Moves.MAGNET_RISE ], + [ 4, Moves.SMOG ], + [ 7, Moves.TAUNT ], + [ 10, Moves.ASSURANCE ], + [ 13, Moves.SLUDGE ], + [ 17, Moves.GYRO_BALL ], + [ 21, Moves.HEADBUTT ], + [ 25, Moves.SCREECH ], + [ 28, Moves.IRON_HEAD ], + [ 32, Moves.SWAGGER ], + [ 36, Moves.POISON_JAB ], + [ 46, Moves.UPROAR ], + [ 52, Moves.SPIN_OUT ], + [ 58, Moves.GUNK_SHOT ], + ], + }, [Species.PALDEA_TAUROS]: { 1: [ [ 1, Moves.TACKLE ], diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 4eb526eeb2b..b8ddd826035 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -2545,7 +2545,14 @@ export function initSpecies() { new PokemonForm("Hero Form", "hero", Type.WATER, null, 1.8, 97.4, Abilities.ZERO_TO_HERO, Abilities.NONE, Abilities.ZERO_TO_HERO, 650, 100, 160, 97, 106, 87, 100, 45, 50, 160), ), new PokemonSpecies(Species.VAROOM, 9, false, false, false, "Single-Cyl Pokémon", Type.STEEL, Type.POISON, 1, 35, Abilities.OVERCOAT, Abilities.NONE, Abilities.SLOW_START, 300, 45, 70, 63, 30, 45, 47, 190, 50, 60, GrowthRate.MEDIUM_FAST, 50, false), - new PokemonSpecies(Species.REVAVROOM, 9, false, false, false, "Multi-Cyl Pokémon", Type.STEEL, Type.POISON, 1.8, 120, Abilities.OVERCOAT, Abilities.NONE, Abilities.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, GrowthRate.MEDIUM_FAST, 50, false), + new PokemonSpecies(Species.REVAVROOM, 9, false, false, false, "Multi-Cyl Pokémon", Type.STEEL, Type.POISON, 1.8, 120, Abilities.OVERCOAT, Abilities.NONE, Abilities.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, GrowthRate.MEDIUM_FAST, 50, false, false, + new PokemonForm("Normal", "", Type.STEEL, Type.POISON, 1.8, 120, Abilities.OVERCOAT, Abilities.NONE, Abilities.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, false, null, true), + new PokemonForm("Segin Starmobile", "segin-starmobile", Type.STEEL, Type.DARK, 1.8, 240, Abilities.INTIMIDATE, Abilities.NONE, Abilities.INTIMIDATE, 600, 120, 129, 100, 59, 77, 115, 75, 50, 175), + new PokemonForm("Schedar Starmobile", "schedar-starmobile", Type.STEEL, Type.FIRE, 1.8, 240, Abilities.SPEED_BOOST, Abilities.NONE, Abilities.SPEED_BOOST, 600, 120, 129, 100, 59, 77, 115, 75, 50, 175), + new PokemonForm("Navi Starmobile", "navi-starmobile", Type.STEEL, Type.POISON, 1.8, 240, Abilities.TOXIC_DEBRIS, Abilities.NONE, Abilities.TOXIC_DEBRIS, 600, 120, 129, 100, 59, 77, 115, 75, 50, 175), + new PokemonForm("Ruchbah Starmobile", "ruchbah-starmobile", Type.STEEL, Type.FAIRY, 1.8, 240, Abilities.MISTY_SURGE, Abilities.NONE, Abilities.MISTY_SURGE, 600, 120, 129, 100, 59, 77, 115, 75, 50, 175), + new PokemonForm("Caph Starmobile", "caph-starmobile", Type.STEEL, Type.FIGHTING, 1.8, 240, Abilities.STAMINA, Abilities.NONE, Abilities.STAMINA, 600, 120, 129, 100, 59, 77, 115, 75, 50, 175), + ), new PokemonSpecies(Species.CYCLIZAR, 9, false, false, false, "Mount Pokémon", Type.DRAGON, Type.NORMAL, 1.6, 63, Abilities.SHED_SKIN, Abilities.NONE, Abilities.REGENERATOR, 501, 70, 95, 65, 85, 65, 121, 190, 50, 175, GrowthRate.MEDIUM_SLOW, 50, false), new PokemonSpecies(Species.ORTHWORM, 9, false, false, false, "Earthworm Pokémon", Type.STEEL, null, 2.5, 310, Abilities.EARTH_EATER, Abilities.NONE, Abilities.SAND_VEIL, 480, 70, 85, 145, 60, 55, 65, 25, 50, 240, GrowthRate.SLOW, 50, false), new PokemonSpecies(Species.GLIMMET, 9, false, false, false, "Ore Pokémon", Type.ROCK, Type.POISON, 0.7, 8, Abilities.TOXIC_DEBRIS, Abilities.NONE, Abilities.CORROSION, 350, 48, 35, 42, 105, 60, 60, 70, 50, 70, GrowthRate.MEDIUM_SLOW, 50, false), @@ -3396,7 +3403,7 @@ export const starterPassiveAbilities = { [Species.POLIWAG]: Abilities.NO_GUARD, [Species.ABRA]: Abilities.PSYCHIC_SURGE, [Species.MACHOP]: Abilities.QUICK_FEET, - [Species.BELLSPROUT]: Abilities.PROTOSYNTHESIS, + [Species.BELLSPROUT]: Abilities.FLOWER_GIFT, [Species.TENTACOOL]: Abilities.TOXIC_CHAIN, [Species.GEODUDE]: Abilities.DRY_SKIN, [Species.PONYTA]: Abilities.MAGIC_GUARD, @@ -3424,7 +3431,7 @@ export const starterPassiveAbilities = { [Species.STARYU]: Abilities.REGENERATOR, [Species.SCYTHER]: Abilities.TINTED_LENS, [Species.PINSIR]: Abilities.TINTED_LENS, - [Species.TAUROS]: Abilities.SCRAPPY, + [Species.TAUROS]: Abilities.STAMINA, [Species.MAGIKARP]: Abilities.MULTISCALE, [Species.LAPRAS]: Abilities.LIGHTNING_ROD, [Species.DITTO]: Abilities.ADAPTABILITY, @@ -3492,7 +3499,7 @@ export const starterPassiveAbilities = { [Species.LARVITAR]: Abilities.SAND_RUSH, [Species.LUGIA]: Abilities.DELTA_STREAM, [Species.HO_OH]: Abilities.MAGIC_GUARD, - [Species.CELEBI]: Abilities.GRASSY_SURGE, + [Species.CELEBI]: Abilities.PSYCHIC_SURGE, [Species.TREECKO]: Abilities.TINTED_LENS, [Species.TORCHIC]: Abilities.RECKLESS, [Species.MUDKIP]: Abilities.DRIZZLE, @@ -3630,7 +3637,7 @@ export const starterPassiveAbilities = { [Species.PANPOUR]: Abilities.SAP_SIPPER, [Species.MUNNA]: Abilities.NEUTRALIZING_GAS, [Species.PIDOVE]: Abilities.SNIPER, - [Species.BLITZLE]: Abilities.RECKLESS, + [Species.BLITZLE]: Abilities.ELECTRIC_SURGE, [Species.ROGGENROLA]: Abilities.SOLID_ROCK, [Species.WOOBAT]: Abilities.OPPORTUNIST, [Species.DRILBUR]: Abilities.SAND_STREAM, @@ -3830,7 +3837,7 @@ export const starterPassiveAbilities = { [Species.DURALUDON]: Abilities.STEELWORKER, [Species.DREEPY]: Abilities.PARENTAL_BOND, [Species.ZACIAN]: Abilities.UNNERVE, - [Species.ZAMAZENTA]: Abilities.STAMINA, + [Species.ZAMAZENTA]: Abilities.UNNERVE, [Species.ETERNATUS]: Abilities.NEUTRALIZING_GAS, [Species.KUBFU]: Abilities.IRON_FIST, [Species.ZARUDE]: Abilities.TOUGH_CLAWS, @@ -3862,7 +3869,7 @@ export const starterPassiveAbilities = { [Species.KLAWF]: Abilities.WATER_ABSORB, [Species.CAPSAKID]: Abilities.PARENTAL_BOND, [Species.RELLOR]: Abilities.PRANKSTER, - [Species.FLITTLE]: Abilities.MAGIC_BOUNCE, + [Species.FLITTLE]: Abilities.DAZZLING, [Species.TINKATINK]: Abilities.STEELWORKER, [Species.WIGLETT]: Abilities.STURDY, [Species.BOMBIRDIER]: Abilities.UNBURDEN, @@ -3913,7 +3920,7 @@ export const starterPassiveAbilities = { [Species.TERAPAGOS]: Abilities.SOUL_HEART, [Species.PECHARUNT]: Abilities.TOXIC_CHAIN, [Species.ALOLA_RATTATA]: Abilities.ADAPTABILITY, - [Species.ALOLA_SANDSHREW]: Abilities.TOUGH_CLAWS, + [Species.ALOLA_SANDSHREW]: Abilities.ICE_SCALES, [Species.ALOLA_VULPIX]: Abilities.SHEER_FORCE, [Species.ALOLA_DIGLETT]: Abilities.STURDY, [Species.ALOLA_MEOWTH]: Abilities.DARK_AURA, diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index dca7b31a862..62f9589b7a3 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -1,6 +1,6 @@ import BattleScene, { startingWave } from "../battle-scene"; import { ModifierTypeFunc, modifierTypes } from "../modifier/modifier-type"; -import { EnemyPokemon } from "../field/pokemon"; +import { EnemyPokemon, PokemonMove } from "../field/pokemon"; import * as Utils from "../utils"; import { PokeballType } from "./pokeball"; import { pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions"; @@ -335,6 +335,9 @@ export class TrainerConfig { case TrainerType.ROSE_2: trainerType = TrainerType.ROSE; break; + case TrainerType.PENNY_2: + trainerType = TrainerType.PENNY; + break; case TrainerType.MARNIE_ELITE: trainerType = TrainerType.MARNIE; break; @@ -619,6 +622,41 @@ export class TrainerConfig { [TrainerPoolTier.RARE]: [Species.TINKATINK, Species.HISUI_LILLIGANT] }; } + case "star_1": { + return { + [TrainerPoolTier.COMMON]: [ Species.MURKROW, Species.SEEDOT, Species.CACNEA, Species.STUNKY, Species.SANDILE, Species.NYMBLE, Species.MASCHIFF, Species.GALAR_ZIGZAGOON ], + [TrainerPoolTier.UNCOMMON]: [ Species.UMBREON, Species.SNEASEL, Species.CORPHISH, Species.ZORUA, Species.INKAY, Species.BOMBIRDIER ], + [TrainerPoolTier.RARE]: [ Species.DEINO, Species.SPRIGATITO ] + }; + } + case "star_2": { + return { + [TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.HOUNDOUR, Species.NUMEL, Species.LITWICK, Species.FLETCHLING, Species.LITLEO, Species.ROLYCOLY, Species.CAPSAKID ], + [TrainerPoolTier.UNCOMMON]: [ Species.PONYTA, Species.FLAREON, Species.MAGBY, Species.TORKOAL, Species.SALANDIT, Species.TURTONATOR ], + [TrainerPoolTier.RARE]: [ Species.LARVESTA, Species.FUECOCO ] + }; + } + case "star_3": { + return { + [TrainerPoolTier.COMMON]: [ Species.ZUBAT, Species.GRIMER, Species.STUNKY, Species.FOONGUS, Species.MAREANIE, Species.TOXEL, Species.SHROODLE, Species.PALDEA_WOOPER ], + [TrainerPoolTier.UNCOMMON]: [ Species.GASTLY, Species.SEVIPER, Species.SKRELP, Species.ALOLA_GRIMER, Species.GALAR_SLOWPOKE, Species.HISUI_QWILFISH ], + [TrainerPoolTier.RARE]: [ Species.BULBASAUR, Species.GLIMMET ] + }; + } + case "star_4": { + return { + [TrainerPoolTier.COMMON]: [ Species.CLEFFA, Species.IGGLYBUFF, Species.AZURILL, Species.COTTONEE, Species.FLABEBE, Species.HATENNA, Species.IMPIDIMP, Species.TINKATINK ], + [TrainerPoolTier.UNCOMMON]: [ Species.TOGEPI, Species.GARDEVOIR, Species.SYLVEON, Species.KLEFKI, Species.MIMIKYU, Species.ALOLA_VULPIX ], + [TrainerPoolTier.RARE]: [ Species.POPPLIO, Species.GALAR_PONYTA ] + }; + } + case "star_5": { + return { + [TrainerPoolTier.COMMON]: [ Species.SHROOMISH, Species.MAKUHITA, Species.MEDITITE, Species.CROAGUNK, Species.SCRAGGY, Species.MIENFOO, Species.PAWMI, Species.PALDEA_TAUROS ], + [TrainerPoolTier.UNCOMMON]: [ Species.RIOLU, Species.TIMBURR, Species.HAWLUCHA, Species.PASSIMIAN, Species.FALINKS, Species.FLAMIGO ], + [TrainerPoolTier.RARE]: [ Species.JANGMO_O, Species.QUAXLY ] + }; + } } console.warn(`Evil team admin for ${team} not found. Returning empty species pools.`); @@ -911,7 +949,7 @@ export class TrainerConfig { if (!getIsInitialized()) { initI18n(); } - this.name = i18next.t(`trainerNames:${name.toLowerCase()}`); + this.name = i18next.t(`trainerNames:${name.toLowerCase().replace(/\s/g, "_")}`); return this; } @@ -1278,7 +1316,7 @@ export const signatureSpecies: SignatureSpecies = { IRIS: [Species.HAXORUS, Species.RESHIRAM, Species.ARCHEOPS], // Druddigon lead, Gmax Lapras DIANTHA: [Species.HAWLUCHA, Species.XERNEAS, Species.GOODRA], // Gourgeist lead, Mega Gardevoir HAU: [[Species.SOLGALEO, Species.LUNALA], Species.NOIVERN, [Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA], [Species.TAPU_BULU, Species.TAPU_FINI, Species.TAPU_KOKO, Species.TAPU_LELE]], // Alola Raichu lead - LEON: [Species.DRAGAPULT, [Species.ZACIAN, Species.ZAMAZENTA], Species.AEGISLASH], // Rillaboom/Cinderace/Inteleon lead, GMax Charizard + LEON: [Species.DRAGAPULT, Species.ZACIAN, Species.AEGISLASH], // Rillaboom/Cinderace/Inteleon lead, GMax Charizard GEETA: [Species.MIRAIDON, [Species.ESPATHRA, Species.VELUZA], [Species.AVALUGG, Species.HISUI_AVALUGG], Species.KINGAMBIT], // Glimmora lead NEMONA: [Species.KORAIDON, Species.PAWMOT, [Species.DUDUNSPARCE, Species.ORTHWORM], [Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL]], // Lycanroc lead KIERAN: [[Species.GRIMMSNARL, Species.INCINEROAR, Species.PORYGON_Z], Species.OGERPON, Species.TERAPAGOS, Species.HYDRAPPLE], // Poliwrath/Politoed lead @@ -1528,6 +1566,38 @@ export const trainerConfigs: TrainerConfigs = { [TrainerPoolTier.SUPER_RARE]: [Species.DURALUDON, Species.DREEPY] }), [TrainerType.OLEANA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("macro_admin", "macro", [Species.GARBODOR]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_oleana").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.STAR_GRUNT]: new TrainerConfig(++t).setHasGenders("Star Grunt Female").setHasDouble("Star Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) + .setSpeciesPools({ + [TrainerPoolTier.COMMON]: [ Species.DUNSPARCE, Species.HOUNDOUR, Species.AZURILL, Species.GULPIN, Species.FOONGUS, Species.FLETCHLING, Species.LITLEO, Species.FLABEBE, Species.CRABRAWLER, Species.NYMBLE, Species.PAWMI, Species.FIDOUGH, Species.SQUAWKABILLY, Species.MASCHIFF, Species.SHROODLE, Species.KLAWF, Species.WIGLETT, Species.PALDEA_WOOPER ], + [TrainerPoolTier.UNCOMMON]: [ Species.KOFFING, Species.EEVEE, Species.GIRAFARIG, Species.RALTS, Species.TORKOAL, Species.SEVIPER, Species.SCRAGGY, Species.ZORUA, Species.MIMIKYU, Species.IMPIDIMP, Species.FALINKS, Species.CAPSAKID, Species.TINKATINK, Species.BOMBIRDIER, Species.CYCLIZAR, Species.FLAMIGO, Species.PALDEA_TAUROS ], + [TrainerPoolTier.RARE]: [ Species.MANKEY, Species.PAWNIARD, Species.CHARCADET, Species.FLITTLE, Species.VAROOM, Species.ORTHWORM], + [TrainerPoolTier.SUPER_RARE]: [ Species.DONDOZO, Species.GIMMIGHOUL ] + }), + [TrainerType.GIACOMO]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_1", [Species.KINGAMBIT]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.REVAVROOM], TrainerSlot.TRAINER, true, p => { + p.formIndex = 1; // Segin Starmobile + p.moveset = [ new PokemonMove(Moves.WICKED_TORQUE), new PokemonMove(Moves.SPIN_OUT), new PokemonMove(Moves.SHIFT_GEAR), new PokemonMove(Moves.HIGH_HORSEPOWER) ]; + })), + [TrainerType.MELA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_2", [Species.ARMAROUGE]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.REVAVROOM], TrainerSlot.TRAINER, true, p => { + p.formIndex = 2; // Schedar Starmobile + p.moveset = [ new PokemonMove(Moves.BLAZING_TORQUE), new PokemonMove(Moves.SPIN_OUT), new PokemonMove(Moves.SHIFT_GEAR), new PokemonMove(Moves.HIGH_HORSEPOWER) ]; + })), + [TrainerType.ATTICUS]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_3", [Species.REVAVROOM]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.REVAVROOM], TrainerSlot.TRAINER, true, p => { + p.formIndex = 3; // Navi Starmobile + p.moveset = [ new PokemonMove(Moves.NOXIOUS_TORQUE), new PokemonMove(Moves.SPIN_OUT), new PokemonMove(Moves.SHIFT_GEAR), new PokemonMove(Moves.HIGH_HORSEPOWER) ]; + })), + [TrainerType.ORTEGA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_4", [Species.DACHSBUN]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.REVAVROOM], TrainerSlot.TRAINER, true, p => { + p.formIndex = 4; // Ruchbah Starmobile + p.moveset = [ new PokemonMove(Moves.MAGICAL_TORQUE), new PokemonMove(Moves.SPIN_OUT), new PokemonMove(Moves.SHIFT_GEAR), new PokemonMove(Moves.HIGH_HORSEPOWER) ]; + })), + [TrainerType.ERI]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_5", [Species.ANNIHILAPE]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.REVAVROOM], TrainerSlot.TRAINER, true, p => { + p.formIndex = 5; // Caph Starmobile + p.moveset = [ new PokemonMove(Moves.COMBAT_TORQUE), new PokemonMove(Moves.SPIN_OUT), new PokemonMove(Moves.SHIFT_GEAR), new PokemonMove(Moves.HIGH_HORSEPOWER) ]; + })), [TrainerType.BROCK]: new TrainerConfig((t = TrainerType.BROCK)).initForGymLeader(signatureSpecies["BROCK"], true, Type.ROCK).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), [TrainerType.MISTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MISTY"], false, Type.WATER).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"), @@ -2162,6 +2232,64 @@ export const trainerConfigs: TrainerConfigs = { p.generateName(); p.pokeball = PokeballType.ULTRA_BALL; })), + [TrainerType.PENNY]: new TrainerConfig(++t).setName("Cassiopeia").initForEvilTeamLeader("Star Boss", []).setMixedBattleBgm("battle_star_boss").setVictoryBgm("victory_team_plasma") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VAPOREON, Species.JOLTEON, Species.FLAREON ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ESPEON, Species.UMBREON ], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = 2; // Magic Bounce Espeon, Inner Focus Umbreon + p.generateAndPopulateMoveset(); + })) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.LEAFEON, Species.GLACEON ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.ROTOM ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.formIndex = Utils.randSeedInt(5, 1); // Heat, Wash, Frost, Fan, or Mow + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.abilityIndex = 2; // Pixilate + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.EEVEE ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + p.formIndex = 2; // G-Max Eevee + p.pokeball = PokeballType.ULTRA_BALL; + p.generateName(); + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[4]; + return [modifierTypes.TERA_SHARD().generateType([], [teraPokemon.species.type1])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier]; //TODO: is the bang correct? + }), + [TrainerType.PENNY_2]: new TrainerConfig(++t).setName("Cassiopeia").initForEvilTeamLeader("Star Boss", [], true).setMixedBattleBgm("battle_star_boss").setVictoryBgm("victory_team_plasma") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.formIndex = Utils.randSeedInt(5, 1); //Random Starmobile form + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ENTEI, Species.RAIKOU, Species.SUICUNE ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WALKING_WAKE, Species.GOUGING_FIRE, Species.RAGING_BOLT ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.abilityIndex = 2; // Pixilate + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.EEVEE ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + p.formIndex = 2; + p.generateName(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.ZAMAZENTA ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[3]; + return [modifierTypes.TERA_SHARD().generateType([], [teraPokemon.species.type1])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier]; //TODO: is the bang correct? + }), [TrainerType.BUCK]: new TrainerConfig(++t).setName("Buck").initForStatTrainer([], true) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CLAYDOL ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 3); @@ -2311,7 +2439,7 @@ export const trainerConfigs: TrainerConfigs = { .setPartyTemplates(new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, PartyMemberStrength.STRONG))), [TrainerType.BUG_TYPE_SUPERFAN]: new TrainerConfig(++t).setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.ACE_TRAINER) .setPartyTemplates(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE)), - [TrainerType.EXPERT_POKEMON_BREEDER]: new TrainerConfig(++t).setMoneyMultiplier(3).setEncounterBgm(TrainerType.ACE_TRAINER) + [TrainerType.EXPERT_POKEMON_BREEDER]: new TrainerConfig(++t).setMoneyMultiplier(3).setEncounterBgm(TrainerType.ACE_TRAINER).setLocalizedName("Expert Pokemon Breeder") .setPartyTemplates(new TrainerPartyTemplate(3, PartyMemberStrength.STRONG)) }; diff --git a/src/enums/battler-tag-type.ts b/src/enums/battler-tag-type.ts index f367b1b56c0..6cf2d260dcb 100644 --- a/src/enums/battler-tag-type.ts +++ b/src/enums/battler-tag-type.ts @@ -80,4 +80,5 @@ export enum BattlerTagType { BURNED_UP = "BURNED_UP", DOUBLE_SHOCKED = "DOUBLE_SHOCKED", MYSTERY_ENCOUNTER_POST_SUMMON = "MYSTERY_ENCOUNTER_POST_SUMMON", + HEAL_BLOCK = "HEAL_BLOCK", } diff --git a/src/enums/trainer-type.ts b/src/enums/trainer-type.ts index fa52e376a07..cb7509067b5 100644 --- a/src/enums/trainer-type.ts +++ b/src/enums/trainer-type.ts @@ -78,6 +78,12 @@ export enum TrainerType { PLUMERIA, MACRO_GRUNT, OLEANA, + STAR_GRUNT, + GIACOMO, + MELA, + ATTICUS, + ORTEGA, + ERI, ROCKET_BOSS_GIOVANNI_1, ROCKET_BOSS_GIOVANNI_2, MAXIE, @@ -96,6 +102,8 @@ export enum TrainerType { GUZMA_2, ROSE, ROSE_2, + PENNY, + PENNY_2, BUCK, CHERYL, MARLEY, diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index f7b19572038..e17272cd955 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -109,6 +109,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { public fusionVariant: Variant; public fusionGender: Gender; public fusionLuck: integer; + public fusionMysteryEncounterPokemonData: MysteryEncounterPokemonData | null; private summonDataPrimer: PokemonSummonData | null; @@ -206,6 +207,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.fusionVariant = dataSource.fusionVariant || 0; this.fusionGender = dataSource.fusionGender; this.fusionLuck = dataSource.fusionLuck; + this.fusionMysteryEncounterPokemonData = dataSource.fusionMysteryEncounterPokemonData; this.usedTMs = dataSource.usedTMs ?? []; this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(dataSource.mysteryEncounterPokemonData); } else { @@ -343,7 +345,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { isAllowed(): boolean { const challengeAllowed = new Utils.BooleanHolder(true); applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, this, challengeAllowed); - return !this.isFainted() && challengeAllowed.value; + return challengeAllowed.value; } isActive(onField?: boolean): boolean { @@ -584,7 +586,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { getSpriteScale(): number { const formKey = this.getFormKey(); - if (formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1 || formKey.indexOf(SpeciesFormKey.ETERNAMAX) > -1) { + if (this.isMax() === true || formKey === "segin-starmobile" || formKey === "schedar-starmobile" || formKey === "navi-starmobile" || formKey === "ruchbah-starmobile" || formKey === "caph-starmobile") { return 1.5; } else if (this.mysteryEncounterPokemonData.spriteScale > 0) { return this.mysteryEncounterPokemonData.spriteScale; @@ -1164,11 +1166,31 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } if (!types.length || !includeTeraType) { - if (this.mysteryEncounterPokemonData.types && this.mysteryEncounterPokemonData.types.length > 0) { - // "Permanent" override for a Pokemon's normal types, currently only used by Mystery Encounters - this.mysteryEncounterPokemonData.types.forEach(t => types.push(t)); - } else if (!ignoreOverride && this.summonData?.types && this.summonData.types.length > 0) { + if (!ignoreOverride && this.summonData?.types && this.summonData.types.length > 0) { this.summonData.types.forEach(t => types.push(t)); + } else if (this.mysteryEncounterPokemonData.types && this.mysteryEncounterPokemonData.types.length > 0) { + // "Permanent" override for a Pokemon's normal types, currently only used by Mystery Encounters + types.push(this.mysteryEncounterPokemonData.types[0]); + + // Fusing a Pokemon onto something with "permanently changed" types will still apply the fusion's types as normal + const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride); + if (fusionSpeciesForm) { + // Check if the fusion Pokemon also had "permanently changed" types + const fusionMETypes = this.fusionMysteryEncounterPokemonData?.types; + if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) { + types.push(fusionMETypes[1]); + } else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) { + types.push(fusionMETypes[0]); + } else if (fusionSpeciesForm.type2 !== null && fusionSpeciesForm.type2 !== types[0]) { + types.push(fusionSpeciesForm.type2); + } else if (fusionSpeciesForm.type1 !== types[0]) { + types.push(fusionSpeciesForm.type1); + } + } + + if (types.length === 1 && this.mysteryEncounterPokemonData.types.length >= 2) { + types.push(this.mysteryEncounterPokemonData.types[1]); + } } else { const speciesForm = this.getSpeciesForm(ignoreOverride); @@ -1176,7 +1198,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride); if (fusionSpeciesForm) { - if (fusionSpeciesForm.type2 !== null && fusionSpeciesForm.type2 !== speciesForm.type1) { + // Check if the fusion Pokemon also had "permanently changed" types + // Otherwise, use standard fusion type logic + const fusionMETypes = this.fusionMysteryEncounterPokemonData?.types; + if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) { + types.push(fusionMETypes[1]); + } else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) { + types.push(fusionMETypes[0]); + } else if (fusionSpeciesForm.type2 !== null && fusionSpeciesForm.type2 !== speciesForm.type1) { types.push(fusionSpeciesForm.type2); } else if (fusionSpeciesForm.type1 !== speciesForm.type1) { types.push(fusionSpeciesForm.type1); @@ -1228,12 +1257,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (Overrides.OPP_ABILITY_OVERRIDE && !this.isPlayer()) { return allAbilities[Overrides.OPP_ABILITY_OVERRIDE]; } + if (this.isFusion()) { + if (!isNullOrUndefined(this.fusionMysteryEncounterPokemonData?.ability) && this.fusionMysteryEncounterPokemonData!.ability !== -1) { + return allAbilities[this.fusionMysteryEncounterPokemonData!.ability]; + } else { + return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)]; + } + } if (!isNullOrUndefined(this.mysteryEncounterPokemonData.ability) && this.mysteryEncounterPokemonData.ability !== -1) { return allAbilities[this.mysteryEncounterPokemonData.ability]; } - if (this.isFusion()) { - return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)]; - } let abilityId = this.getSpeciesForm(ignoreOverride).getAbility(this.abilityIndex); if (abilityId === Abilities.NONE) { abilityId = this.species.ability1; @@ -1927,6 +1960,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.fusionVariant = 0; this.fusionGender = 0; this.fusionLuck = 0; + this.fusionMysteryEncounterPokemonData = null; this.generateName(); this.calculateStats(); @@ -2971,16 +3005,40 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.getRestrictingTag(moveId) !== null; } + /** + * Gets whether the given move is currently disabled for the user based on the player's target selection + * + * @param {Moves} moveId {@linkcode Moves} ID of the move to check + * @param {Pokemon} user {@linkcode Pokemon} the move user + * @param {Pokemon} target {@linkcode Pokemon} the target of the move + * + * @returns {boolean} `true` if the move is disabled for this Pokemon due to the player's target selection + * + * @see {@linkcode MoveRestrictionBattlerTag} + */ + isMoveTargetRestricted(moveId: Moves, user: Pokemon, target: Pokemon): boolean { + for (const tag of this.findTags(t => t instanceof MoveRestrictionBattlerTag)) { + if ((tag as MoveRestrictionBattlerTag).isMoveTargetRestricted(moveId, user, target)) { + return (tag as MoveRestrictionBattlerTag !== null); + } + } + return false; + } + /** * Gets the {@link MoveRestrictionBattlerTag} that is restricting a move, if it exists. * * @param {Moves} moveId {@linkcode Moves} ID of the move to check + * @param {Pokemon} user {@linkcode Pokemon} the move user, optional and used when the target is a factor in the move's restricted status + * @param {Pokemon} target {@linkcode Pokemon} the target of the move, optional and used when the target is a factor in the move's restricted status * @returns {MoveRestrictionBattlerTag | null} the first tag on this Pokemon that restricts the move, or `null` if the move is not restricted. */ - getRestrictingTag(moveId: Moves): MoveRestrictionBattlerTag | null { + getRestrictingTag(moveId: Moves, user?: Pokemon, target?: Pokemon): MoveRestrictionBattlerTag | null { for (const tag of this.findTags(t => t instanceof MoveRestrictionBattlerTag)) { if ((tag as MoveRestrictionBattlerTag).isMoveRestricted(moveId)) { return tag as MoveRestrictionBattlerTag; + } else if (user && target && (tag as MoveRestrictionBattlerTag).isMoveTargetRestricted(moveId, user, target)) { + return tag as MoveRestrictionBattlerTag; } } return null; @@ -4207,6 +4265,7 @@ export class PlayerPokemon extends Pokemon { this.fusionVariant = pokemon.variant; this.fusionGender = pokemon.gender; this.fusionLuck = pokemon.luck; + this.fusionMysteryEncounterPokemonData = pokemon.mysteryEncounterPokemonData; if ((pokemon.pauseEvolutions) || (this.pauseEvolutions)) { this.pauseEvolutions = true; } @@ -4749,8 +4808,15 @@ export class EnemyPokemon extends Pokemon { return true; } + /** + * Go through a boss' health segments and give stats boosts for each newly cleared segment + * The base boost is 1 to a random stat that's not already maxed out per broken shield + * For Pokemon with 3 health segments or more, breaking the last shield gives +2 instead + * For Pokemon with 5 health segments or more, breaking the last two shields give +2 each + * @param segmentIndex index of the segment to get down to (0 = no shield left, 1 = 1 shield left, etc.) + */ handleBossSegmentCleared(segmentIndex: integer): void { - while (segmentIndex - 1 < this.bossSegmentIndex) { + while (this.bossSegmentIndex > 0 && segmentIndex - 1 < this.bossSegmentIndex) { // Filter out already maxed out stat stages and weigh the rest based on existing stats const leftoverStats = EFFECTIVE_STATS.filter((s: EffectiveStat) => this.getStatStage(s) < 6); const statWeights = leftoverStats.map((s: EffectiveStat) => this.getStat(s, false)); diff --git a/src/field/trainer.ts b/src/field/trainer.ts index 1973d7216a6..b1d0263f604 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -425,14 +425,32 @@ export default class Trainer extends Phaser.GameObjects.Container { } } - if (retry && (attempt || 0) < 10) { + // Prompts reroll of party member species if species already present in the enemy party + if (this.checkDuplicateSpecies(ret)) { + console.log("Duplicate species detected, prompting reroll..."); + retry = true; + } + + if (retry && (attempt ?? 0) < 10) { console.log("Rerolling party member..."); - ret = this.genNewPartyMemberSpecies(level, strength, (attempt || 0) + 1); + ret = this.genNewPartyMemberSpecies(level, strength, (attempt ?? 0) + 1); } return ret; } + /** + * Checks if the enemy trainer already has the Pokemon species in their party + * @param {PokemonSpecies} species {@linkcode PokemonSpecies} + * @returns `true` if the species is already present in the party + */ + checkDuplicateSpecies(species: PokemonSpecies): boolean { + const currentPartySpecies = this.scene.getEnemyParty().map(p => { + return p.species.speciesId; + }); + return currentPartySpecies.includes(species.speciesId); + } + getPartyMemberMatchupScores(trainerSlot: TrainerSlot = TrainerSlot.NONE, forSwitch: boolean = false): [integer, integer][] { if (trainerSlot && !this.isDouble()) { trainerSlot = TrainerSlot.NONE; diff --git a/src/locales/de/ability.json b/src/locales/de/ability.json index 84f30fac755..e6078371535 100644 --- a/src/locales/de/ability.json +++ b/src/locales/de/ability.json @@ -1237,6 +1237,6 @@ }, "poisonPuppeteer": { "name": "Giftpuppenspiel", - "description": "Wenn Infamomo ein Ziel mit einer Attacke vergiftet, so wird dieses auch verwirrt." + "description": "Wenn das Pokémon ein Ziel mit einer Attacke vergiftet, so wird dieses auch verwirrt." } } \ No newline at end of file diff --git a/src/locales/de/battle.json b/src/locales/de/battle.json index 38e36d4b2da..7a9c2570211 100644 --- a/src/locales/de/battle.json +++ b/src/locales/de/battle.json @@ -96,5 +96,7 @@ "unlockedSomething": "{{unlockedThing}} wurde freigeschaltet.", "congratulations": "Glückwunsch!", "beatModeFirstTime": "{{speciesName}} hat den {{gameMode}} Modus zum ersten Mal beendet! Du erhältst {{newModifier}}!", - "eggSkipPrompt": "Zur Ei-Zusammenfassung springen?" + "eggSkipPrompt": "Zur Ei-Zusammenfassung springen?", + "battlerTagsHealBlock": "{{pokemonNameWithAffix}} kann nicht geheilt werden, da die Heilung blockiert wird!", + "battlerTagsHealBlockOnRemove": "{{pokemonNameWithAffix}} kann wieder geheilt werden!" } diff --git a/src/locales/de/bgm-name.json b/src/locales/de/bgm-name.json index 1eab276a70a..830fad50f7a 100644 --- a/src/locales/de/bgm-name.json +++ b/src/locales/de/bgm-name.json @@ -83,9 +83,11 @@ "battle_aether_grunt": "SM Vs. Æther Foundation", "battle_skull_grunt": "SM Vs. Team Skull Rüpel", "battle_macro_grunt": "SWSH Vs. Trainer", + "battle_star_grunt": "KAPU Vs. Team Star", "battle_galactic_admin": "BDSP Vs. Team Galactic Commander", "battle_skull_admin": "SM Vs. Team Skull Vorstand", - "battle_oleana": "SWSH Vs. Oleana", + "battle_oleana": "SWSH Vs. Olivia", + "battle_star_admin": "KAPU Vs. Team Star Boss", "battle_rocket_boss": "USUM Vs. Giovanni", "battle_aqua_magma_boss": "ORAS Vs. Team Aqua & Magma Boss", "battle_galactic_boss": "BDSP Vs. Zyrus", @@ -94,6 +96,7 @@ "battle_aether_boss": "SM Vs. Samantha", "battle_skull_boss": "SM Vs. Bromley", "battle_macro_boss": "SWSH Vs. Rose", + "battle_star_boss": "KAPU Vs. Cosima", "abyss": "PMD Erkundungsteam Himmel Dunkelkrater", "badlands": "PMD Erkundungsteam Himmel Kargtal", @@ -108,17 +111,17 @@ "forest": "PMD Erkundungsteam Himmel Düsterwald", "grass": "PMD Erkundungsteam Himmel Apfelwald", "graveyard": "PMD Erkundungsteam Himmel Verwirrwald", - "ice_cave": "PMD Erkundungsteam Himmel Rieseneisberg", + "ice_cave": "Firel - -50°C", "island": "PMD Erkundungsteam Himmel Schroffküste", "jungle": "Lmz - Jungle", "laboratory": "Firel - Laboratory", - "lake": "PMD Erkundungsteam Himmel Kristallhöhle", + "lake": "Lmz - Lake", "meadow": "PMD Erkundungsteam Himmel Himmelsgipfel-Wald", "metropolis": "Firel - Metropolis", "mountain": "PMD Erkundungsteam Himmel Hornberg", - "plains": "PMD Erkundungsteam Himmel Himmelsgipfel-Prärie", - "power_plant": "PMD Erkundungsteam Himmel Weite Ampere-Ebene", - "ruins": "PMD Erkundungsteam Himmel Tiefes Ruinenverlies", + "plains": "Firel - Route 888", + "power_plant": "Firel - The Klink", + "ruins": "Lmz - Ancient Ruins", "sea": "Andr06 - Marine Mystique", "seabed": "Firel - Seabed", "slum": "Andr06 - Sneaky Snom", @@ -128,7 +131,7 @@ "tall_grass": "PMD Erkundungsteam Himmel Nebelwald", "temple": "PMD Erkundungsteam Himmel Ägishöhle", "town": "PMD Erkundungsteam Himmel Zufälliges Dungeon-Theme 3", - "volcano": "PMD Erkundungsteam Himmel Dunsthöhle", + "volcano": "Firel - Twisturn Volcano", "wasteland": "PMD Erkundungsteam Himmel Verborgenes Hochland", "encounter_ace_trainer": "SW Trainerblicke treffen sich (Ass-Trainer)", "encounter_backpacker": "SW Trainerblicke treffen sich (Backpacker)", diff --git a/src/locales/de/dialogue.json b/src/locales/de/dialogue.json index 8a3dbb8880e..2e8804ab747 100644 --- a/src/locales/de/dialogue.json +++ b/src/locales/de/dialogue.json @@ -715,12 +715,16 @@ "encounter": { "1": "Achtung hier ist Endstation für dich!", "2": "Du bist ein Trainer, oder? Wir von MC Wertpapiere wissen so etwas.\n$Ich fürchte, das gibt dir trotzdem nicht das Recht, sich in unsere Arbeit einzumischen.", - "3": "Ich bin von MC Versicherungen! Hast du eine Lebensversicherung?" + "3": "Ich bin von MC Versicherungen! Hast du eine Lebensversicherung?", + "4": "Ich habe dich gefunden! Das bedeutet es ist Zeit für einen Pokémon-Kampf!", + "5": "Eine Standpauke von Frau Olivia ist schlimmer als alles, was Sie tun können!" }, "victory": { "1": "Ich habe keine andere Wahl, als respektvoll zurückzutreten.", "2": "Mein Erspartes aufzugeben bringt mich in die roten Zahlen...", - "3": "Okay zurück an die Arbeit. Versicherungen verkauft sich nicht von alleine." + "3": "Okay zurück an die Arbeit. Versicherungen verkauft sich nicht von alleine.", + "4": "Ich habe sogar meine Pokémon ausgetauscht...", + "5": "Kämpfen hat nicht funktioniert... Jetzt können wir nur noch rennen!" } }, "oleana": { @@ -735,6 +739,73 @@ "3": "Ich bin eine müde Olivia... Ob es Macro Cosmos Betten gibt?" } }, + "star_grunt": { + "encounter": { + "1": "Wir sind von Team Star, wo jeder nach den Sternen greifen kann!", + "2": "Wir werden mit voller Kraft auf dich losgehen - Hasta la vistar! ★", + "3": "Könntest du bitte wieder abzischen? Sonst muss ich dich davonjagen. Aus reinem Selbstschutz!", + "4": "Es tut mir furchtbar leid, aber wenn du nicht umkehrst, könnte es ungemütlich für dich werden.", + "4_female": "Es tut mir furchtbar leid, aber wenn du nicht umkehrst, könnte es ungemütlich für dich werden.", + "5": "Och nee, nicht noch so ein Clown..." + }, + "victory": { + "1": "Jetzt bin ich die Person, die Sterne sieht...", + "2": "Jemand wie du wäre bei Team Star wahrscheinlich im Nullkommanichts an der Spitze.$Alle hätten Angst vor dir. Trotzdem...", + "3": "Da war meine Selbstverteidigung wohl nicht gut genug...", + "4": "H-hasta la vistar... ★", + "5": "Als neues Mitglied bei Team Star bekommt man echt nur die Drecksarbeit ab..." + } + }, + "giacomo": { + "encounter": { + "1": "Du willst dich echt mit Team Star anlegen? Bist du lebensmüde, oder was?", + "2": "Weil ich so nett bin, leg ich zu deinem Abgang auch ein fettes Requiem auf!$Lass uns die Party in Schwung bringen" + }, + "victory": { + "1": " Besser hätte ich es auch nicht sagen können...", + "2": "Uff, da hab ich schon bessere Shows gegeben... Schade, aber verloren ist verloren." + } + }, + "mela": { + "encounter": { + "1": "Du bist also diese Pfeife, die sich unbedingt mit uns anlegen will...$Dir werd ich zeigen, was mit Leuten passiert, die sich mit uns anlegen!", + "2": "Yeah, lassen wir’s krachen!" + }, + "victory": { + "1": "Uff, ich hab echt versagt... Das war’s dann wohl...", + "2": "Ich... brannte so sehr auf diesen Kampf. Doch jetzt ist meine Flamme erloschen..." + } + }, + "atticus": { + "encounter": { + "1": "hr habt Team Star Leid angetan, unverschämter Schurke! Mein Gift soll Euer Niedergang sein!", + "2": "Eure Bereitschaft zum Duell erfreut mich! Möge der Kampf ein ehrwürdiger sein!" + }, + "victory": { + "1": "Meine Gefährten... Vergebt mir...", + "2": "Ich habe eine klare Niederlage erlitten, bei der Groll und Bitterkeit fehl am Platz wären." + } + }, + "ortega": { + "encounter": { + "1": "Wenn ich mit dir fertig bin, wirst du heulend nach Hause rennen!", + "2": "Ich werde gewinnen, also spar dir deinen überheblichen Auftritt!" + }, + "victory": { + "1": "Was?! Wie konnte ich nur verlieren? Warum? Warum nur?!", + "2": "Graaaah! Du bist viel zu stark, das ist so was von unfair!" + } + }, + "eri": { + "encounter": { + "1": "Wer auch immer es auf Team Star abgesehen hat, wird zerschmettert!", + "2": "Ich kann genauso gut austeilen wie einstecken! Wer am Ende noch steht, gewinnt." + }, + "victory": { + "1": "Leute, es tut mir so leid...", + "2": "Ich habe alles gegeben... Ich bereue nichts..." + } + }, "rocket_boss_giovanni_1": { "encounter": { "1": "Ich bin beeindruckt, du hast es bis hierher geschafft!\n$Ich bin Giovanni, der Anführer von Team Rocket!\n$Wir regieren den Untergrund von Kanto!\n$Und wir lassen sicherlich nicht zu, dass ein Kind uns aufhält!" @@ -933,6 +1004,28 @@ "1": "Ich nehme an, es muss den Anschein haben, dass ich etwas Schreckliches tue.\n$Ich erwarte nicht, dass du es verstehst. Aber ich muss der Galar-Region grenzenlose Energie\n$bereitstellen, um ewigen Wohlstand zu gewährleisten." } }, + "star_boss_penny_1": { + "encounter": { + "1": "Ich bin Team Stars Big Boss. Mein Name ist Cassiopeia...$Die Gründerin von Team Star ist kampfbereit! Verneigt euch vor meiner unermesslichen Kraft!" + }, + "victory": { + "1": "... ... .." + }, + "defeat": { + "1": "Heh..." + } + }, + "star_boss_penny_2": { + "encounter": { + "1": "Ich werde mich in diesem Kampf nicht zurückhalten! Ich werde dem Kodex von Team Star treu bleiben!$Unsere Evoli-Power verwandelt euch in Sternenstaub!" + }, + "victory": { + "1": "Es ist vorbei..." + }, + "defeat": { + "1": "Du bist unfassbar stark. Kein Wunder, dass die anderen Bosse gegen dich verloren haben..." + } + }, "brock": { "encounter": { "1": "Meine Expertise in Bezug auf Gesteins-Pokémon wird dich besiegen! Komm schon!", diff --git a/src/locales/de/move.json b/src/locales/de/move.json index b7a42cb1787..f3502978edd 100644 --- a/src/locales/de/move.json +++ b/src/locales/de/move.json @@ -3129,7 +3129,7 @@ }, "auraWheel": { "name": "Aura-Rad", - "effect": "Mithilfe der in den Backentaschen gespeicherten Energie greift der Anwender an und erhöht seine Initiative. Der Typ der Attacke hängt von Morpekos Form ab." + "effect": "Mithilfe der in den Backentaschen gespeicherten Energie greift der Anwender an und erhöht seine Initiative. Wenn dies von Morpeko verwendet wird hängt der Typ der Attacke von dessen Form ab." }, "breakingSwipe": { "name": "Breitseite", diff --git a/src/locales/de/pokemon-form.json b/src/locales/de/pokemon-form.json index d621e3165fa..16efc3af653 100644 --- a/src/locales/de/pokemon-form.json +++ b/src/locales/de/pokemon-form.json @@ -1,4 +1,5 @@ { + "pikachu": "Normal", "pikachuCosplay": "Cosplay", "pikachuCoolCosplay": "Rocker-Pikachu", "pikachuBeautyCosplay": "Damen-Pikachu", @@ -6,7 +7,9 @@ "pikachuSmartCosplay": "Professoren-Pikachu", "pikachuToughCosplay": "Wrestler-Pikachu", "pikachuPartner": "Partner-Pikachu", + "eevee": "Normal", "eeveePartner": "Partner-Evoli", + "pichu": "Normal", "pichuSpiky": "Strubbelohr-Pichu", "unownA": "A", "unownB": "B", @@ -36,36 +39,65 @@ "unownZ": "Z", "unownExclamation": "!", "unownQuestion": "?", + "castform": "Normalform", "castformSunny": "Sonnenform", "castformRainy": "Regenform", "castformSnowy": "Schneeform", "deoxysNormal": "Normalform", + "deoxysAttack": "Angriffsform", + "deoxysDefense": "Verteidigungsform", + "deoxysSpeed": "Initiativeform", "burmyPlant": "Pflanzenumhang", "burmySandy": "Sandumhang", "burmyTrash": "Lumpenumhang", + "cherubiOvercast": "Wolkenform", + "cherubiSunshine": "Sonnenform", "shellosEast": "Östliches Meer", "shellosWest": "Westliches Meer", + "rotom": "Normalform", "rotomHeat": "Hitze-Rotom", "rotomWash": "Wasch-Rotom", "rotomFrost": "Frost-Rotom", "rotomFan": "Wirbel-Rotom", "rotomMow": "Schneid-Rotom", + "dialga": "Normalform", + "dialgaOrigin": "Urform", + "palkia": "Normalform", + "palkiaOrigin": "Urform", "giratinaAltered": "Wandelform", + "giratinaOrigin": "Urform", "shayminLand": "Landform", + "shayminSky": "Zenitform", "basculinRedStriped": "Rotlinige Form", "basculinBlueStriped": "Blaulinige Form", "basculinWhiteStriped": "Weißlinige Form", + "darumaka": "Normalmodus", + "darumakaZen": "Trance-Modus", "deerlingSpring": "Frühlingsform", "deerlingSummer": "Sommerform", "deerlingAutumn": "Herbstform", "deerlingWinter": "Winterform", "tornadusIncarnate": "Inkarnationsform", + "tornadusTherian": "Tiergeistform", "thundurusIncarnate": "Inkarnationsform", + "thundurusTherian": "Tiergeistform", "landorusIncarnate": "Inkarnationsform", + "landorusTherian": "Tiergeistform", + "kyurem": "Normal", + "kyuremBlack": "Schwarzes Kyurem", + "kyuremWhite": "Weißes Kyurem", "keldeoOrdinary": "Standardform", + "keldeoResolute": "Resolutform", "meloettaAria": "Gesangsform", "meloettaPirouette": "Tanzform", - "froakieBattleBond": "Ash-Form", + "genesect": "Normal", + "genesectShock": "Blitzmodul", + "genesectBurn": "Flammenmodul", + "genesectChill": "Gefriermodul", + "genesectDouse": "Aquamodul", + "froakie": "Normalform", + "froakieBattleBond": "Freundschaftsakt", + "froakieAsh": "Ash-Form", "scatterbugMeadow": "Blumenmeermuster", "scatterbugIcySnow": "Frostmuster", "scatterbugPolar": "Schneefeldmuster", @@ -91,6 +123,7 @@ "flabebeOrange": "Orangeblütler", "flabebeBlue": "Blaublütler", "flabebeWhite": "Weißblütler", + "furfrou": "Zottelform", "furfrouHeart": "Herzchenschnitt", "furfrouStar": "Sternchenschnitt", "furfrouDiamond": "Diamantenschitt", @@ -100,6 +133,11 @@ "furfrouLaReine": "Königinnenschnitt", "furfrouKabuki": "Kabuki-Schnitt", "furfrouPharaoh": "Herrscherschnitt", + "espurrMale": "männlich", + "espurrFemale": "weiblich", + "honedgeShiled": "Schildform", + "honedgeBlade": "Klingenform", + "pumpkaboo": "Größe M", "pumpkabooSmall": "Größe S", "pumpkabooLarge": "Größe L", "pumpkabooSuper": "Größe XL", @@ -110,11 +148,37 @@ "zygarde50Pc": "50% Form Scharwandel", "zygarde10Pc": "10% Form Scharwandel", "zygardeComplete": "Optimum-Form", + "hoopa": "Gebanntes Hoopa", + "hoopaUnbound": "Entfesseltes Hoopa", "oricorioBaile": "Flamenco-Stil", "oricorioPompom": "Cheerleading-Stil", "oricorioPau": "Hula-Stil", "oricorioSensu": "Buyo-Stil", + "rockruff": "Normalform", "rockruffOwnTempo": "Gleichmut", + "rockruffMidday": "Tagform", + "rockruffMidnight": "Nachtform", + "rockruffDusk": "Zwielichtform", + "wishiwashi": "Einzelform", + "wishiwashiSchool": "Schwarmform", + "typeNullNormal": "Typ:Normal", + "typeNullFighting": "Typ:Kampf", + "typeNullFlying": "Typ:Flug", + "typeNullPoison": "Typ:Gift", + "typeNullGround": "Typ:Boden", + "typeNullRock": "Typ:Gestein", + "typeNullBug": "Typ:Käfer", + "typeNullGhost": "Typ:Geist", + "typeNullSteel": "Typ:Stahl", + "typeNullFire": "Typ:Feuer", + "typeNullWater": "Typ:Wasser", + "typeNullGrass": "Typ:Pflanze", + "typeNullElectric": "Typ:Elektro", + "typeNullPsychic": "Typ:Psycho", + "typeNullIce": "Typ:Eis", + "typeNullDragon": "Typ:Drache", + "typeNullDark": "Typ:Unlicht", + "typeNullFairy": "Typ:Fee", "miniorRedMeteor": "Rote-Meteorform", "miniorOrangeMeteor": "Oranger-Meteorform", "miniorYellowMeteor": "Gelber-Meteorform", @@ -131,25 +195,66 @@ "miniorViolet": "Violetter Kern", "mimikyuDisguised": "Verkleidete Form", "mimikyuBusted": "Entlarvte Form", + "necrozma": "Normalform", + "necrozmaDuskMane": "Abendmähne", + "necrozmaDawnWings": "Morgenschwingen", + "necrozmaUltra": "Ultra-Necrozma", + "magearna": "Normalform", "magearnaOriginal": "Originalfarbe", + "marshadow": "Normalform", "marshadowZenith": "Zenitform", + "cramorant": "Normalform", + "cramorantGulping": "Schlingform", + "cramorantGorging": "Stopfform", + "toxelAmped": "Hoch-Form", + "toxelLowkey": "Tief-Form", "sinisteaPhony": "Fälschungsform", "sinisteaAntique": "Originalform", + "milceryVanillaCream": "Vanille-Creme", + "milceryRubyCream": "Ruby-Creme", + "milceryMatchaCream": "Matcha-Creme", + "milceryMintCream": "Minz-Creme", + "milceryLemonCream": "Zitronen-Creme", + "milcerySaltedCream": "Salz-Creme", + "milceryRubySwirl": "Ruby-Mix", + "milceryCaramelSwirl": "Karamell-Mix", + "milceryRainbowSwirl": "Trio-Mix", + "eiscue": "Tiefkühlkopf", "eiscueNoIce": "Wohlfühlkopf", "indeedeeMale": "männlich", "indeedeeFemale": "weiblich", "morpekoFullBelly": "Pappsattmuster", + "morpekoHangry": "Kohldampfmuster", "zacianHeroOfManyBattles": "Heldenhafter Krieger", + "zacianCrowned": "König des Schwertes", "zamazentaHeroOfManyBattles": "Heldenhafter Krieger", + "zamazentaCrowned": "König des Schildes", + "kubfuSingleStrike": "Fokussierter Stil", + "kubfuRapidStrike": "Fließender Stil", + "zarude": "Normalform", "zarudeDada": "Papa", + "calyrex": "Normalform", + "calyrexIce": "Schimmelreiter", + "calyrexShadow": "Rappenreiter", + "basculinMale": "männlich", + "basculinFemale": "weiblich", "enamorusIncarnate": "Inkarnationsform", + "enamorusTherian": "Tiergeistform", + "lechonkMale": "männlich", + "lechonkFemale": "weiblich", + "tandemausFour": "Dreierfamilie", + "tandemausThree": "Viererfamilie", "squawkabillyGreenPlumage": "Grüngefiedert", "squawkabillyBluePlumage": "Blaugefiedert", "squawkabillyYellowPlumage": "Gelbgefiedert", "squawkabillyWhitePlumage": "Weißgefiedert", + "finizenZero": "Alltagsform", + "finizenHero": "Heldenform", "tatsugiriCurly": "Gebogene Form", "tatsugiriDroopy": "Hängende Form", "tatsugiriStretchy": "Gestrekte Form", + "dunsparceTwo": "Zweisegmentform", + "dunsparceThree": "Dreisegmentform", "gimmighoulChest": "Truhenform", "gimmighoulRoaming": "Wanderform", "koraidonApexBuild": "Vollkommene Gestalt", @@ -164,7 +269,22 @@ "miraidonGlideMode": "Gleitmodus", "poltchageistCounterfeit": "Imitationsform", "poltchageistArtisan": "Kostbarkeitsform", + "poltchageistUnremarkable": "Simple Form", + "poltchageistMasterpiece": "Edle Form", + "ogerponTealMask": "Türkisgrüne Maske", + "ogerponTealMaskTera": "Türkisgrüne Maske (Terakristallisiert)", + "ogerponWellspringMask": "Brunnenmaske", + "ogerponWellspringMaskTera": "Brunnenmaske (Terakristallisiert)", + "ogerponHearthflameMask": "Ofenmaske", + "ogerponHearthflameMaskTera": "Ofenmaske (Terakristallisiert)", + "ogerponCornerstoneMask": "Fundamentmaske", + "ogerponCornerstoneMaskTera": "Fundamentmaske (Terakristallisiert)", + "terpagos": "Normalform", + "terpagosTerastal": "Terakristall-Form", + "terpagosStellar": "Stellarform", + "galarDarumaka": "Normalmodus", + "galarDarumakaZen": "Trance-Modus", "paldeaTaurosCombat": "Gefechtsvariante", "paldeaTaurosBlaze": "Flammenvariante", "paldeaTaurosAqua": "Flutenvariante" -} \ No newline at end of file +} diff --git a/src/locales/de/trainer-classes.json b/src/locales/de/trainer-classes.json index 45826fcd310..08f9e0cebef 100644 --- a/src/locales/de/trainer-classes.json +++ b/src/locales/de/trainer-classes.json @@ -126,5 +126,8 @@ "skull_grunts": "Rüpel von Team Skull", "macro_grunt": "Angestellter von Macro Cosmos", "macro_grunt_female": "Angestellte von Macro Cosmos", - "macro_grunts": "Angestellte von Macro Cosmos" + "macro_grunts": "Angestellte von Macro Cosmos", + "star_grunt": "Rüpel von Team Star", + "star_grunt_female": "Rüpel von Team Star", + "star_grunts": "Rüpel von Team Star" } diff --git a/src/locales/de/trainer-names.json b/src/locales/de/trainer-names.json index ffbb772234c..e3430f2b283 100644 --- a/src/locales/de/trainer-names.json +++ b/src/locales/de/trainer-names.json @@ -142,6 +142,11 @@ "faba": "Fabian", "plumeria": "Fran", "oleana": "Olivia", + "giacomo": "Pinio", + "mela": "Irsa", + "atticus": "Shugi", + "ortega": "Otis", + "eri": "Rioba", "maxie": "Marc", "archie": "Adrian", @@ -151,6 +156,7 @@ "lusamine": "Samantha", "guzma": "Bromley", "rose": "Rose", + "cassiopeia": "Cosima", "blue_red_double": "Blau & Rot", "red_blue_double": "Rot & Blau", diff --git a/src/locales/de/trainer-titles.json b/src/locales/de/trainer-titles.json index 21a4b2fa7b6..2a270226463 100644 --- a/src/locales/de/trainer-titles.json +++ b/src/locales/de/trainer-titles.json @@ -19,6 +19,7 @@ "aether_boss": "Æther-Präsidentin", "skull_boss": "Skull-Boss", "macro_boss": "Geschäftsführer von Macro Cosmos", + "star_boss": "Team Star Big Boss", "rocket_admin": "Team Rocket Vorstand", "rocket_admin_female": "Team Rocket Vorstand", "magma_admin": "Team Magma Vorstand", @@ -33,6 +34,6 @@ "flare_admin_female": "Team Flare Vorstand", "aether_admin": "Æther-Regionalleiter", "skull_admin": "Team Skull Vorstand", - "macro_admin": "Vizepräsidentin von Macro Cosmos" - + "macro_admin": "Vizepräsidentin von Macro Cosmos", + "star_admin": "Team Star Boss" } diff --git a/src/locales/en/ability.json b/src/locales/en/ability.json index de2e063e966..f2ffa9b4927 100644 --- a/src/locales/en/ability.json +++ b/src/locales/en/ability.json @@ -1237,6 +1237,6 @@ }, "poisonPuppeteer": { "name": "Poison Puppeteer", - "description": "Pokémon poisoned by Pecharunt's moves will also become confused." + "description": "Pokémon poisoned by this Pokémon's moves will also become confused." } } \ No newline at end of file diff --git a/src/locales/en/battle.json b/src/locales/en/battle.json index d04dd3eac1f..2559dafecae 100644 --- a/src/locales/en/battle.json +++ b/src/locales/en/battle.json @@ -105,5 +105,7 @@ "congratulations": "Congratulations!", "beatModeFirstTime": "{{speciesName}} beat {{gameMode}} Mode for the first time!\nYou received {{newModifier}}!", "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", - "mysteryEncounterAppeared": "What's this?" + "mysteryEncounterAppeared": "What's this?", + "battlerTagsHealBlock": "{{pokemonNameWithAffix}} can't restore its HP!", + "battlerTagsHealBlockOnRemove": "{{pokemonNameWithAffix}} can restore its HP again!" } \ No newline at end of file diff --git a/src/locales/en/bgm-name.json b/src/locales/en/bgm-name.json index f38b62d14c6..0951de6b769 100644 --- a/src/locales/en/bgm-name.json +++ b/src/locales/en/bgm-name.json @@ -83,9 +83,11 @@ "battle_aether_grunt": "SM Aether Foundation Battle", "battle_skull_grunt": "SM Team Skull Battle", "battle_macro_grunt": "SWSH Trainer Battle", + "battle_star_grunt": "SV Team Star Battle", "battle_galactic_admin": "BDSP Team Galactic Admin Battle", "battle_skull_admin": "SM Team Skull Admin Battle", "battle_oleana": "SWSH Oleana Battle", + "battle_star_admin": "SV Team Star Boss", "battle_rocket_boss": "USUM Giovanni Battle", "battle_aqua_magma_boss": "ORAS Archie & Maxie Battle", "battle_galactic_boss": "BDSP Cyrus Battle", @@ -94,6 +96,7 @@ "battle_aether_boss": "SM Lusamine Battle", "battle_skull_boss": "SM Guzma Battle", "battle_macro_boss": "SWSH Rose Battle", + "battle_star_boss": "SV Cassiopeia Battle", "abyss": "PMD EoS Dark Crater", "badlands": "PMD EoS Barren Valley", @@ -108,7 +111,7 @@ "forest": "PMD EoS Dusk Forest", "grass": "PMD EoS Apple Woods", "graveyard": "PMD EoS Mystifying Forest", - "ice_cave": "Firel - -60F", + "ice_cave": "Firel - -50°C", "island": "PMD EoS Craggy Coast", "jungle": "Lmz - Jungle", "laboratory": "Firel - Laboratory", diff --git a/src/locales/en/dialogue.json b/src/locales/en/dialogue.json index 39a4238355c..9d1f0ae1c80 100644 --- a/src/locales/en/dialogue.json +++ b/src/locales/en/dialogue.json @@ -764,12 +764,17 @@ "1": "It looks like this is the end of the line for you!", "2": "You are a trainer aren't you? I'm afraid that doesn't give you the right to interfere in our work.", "2_female": "You are a trainer aren't you? I'm afraid that doesn't give you the right to interfere in our work.", - "3": "I'm from Macro Cosmos Insurance! Do you have a life insurance policy?" + "3": "I'm from Macro Cosmos Insurance! Do you have a life insurance policy?", + "4": "I found you! In that case, time for a Pokémon battle!", + "4_female": "I found you! In that case, time for a Pokémon battle!", + "5": "An earful from Ms. Oleana is way worse than anything you can do!" }, "victory": { "1": "I have little choice but to respectfully retreat.", "2": "Having to give up my pocket money... Losing means I'm back in the red...", - "3": "Nobody can beat Macro Cosmos when it comes to our dedication to our work!" + "3": "Nobody can beat Macro Cosmos when it comes to our dedication to our work!", + "4": "I even switched up my Pokémon...", + "5": "Battles didn't work... Only thing to do now is run!" } }, "oleana": { @@ -785,6 +790,77 @@ "3": "*sigh* I am one tired Oleana..." } }, + "star_grunt": { + "encounter": { + "1": "We're Team Star, kid. We burn so bright, it hurts to look at us!", + "2": "We'll come at you full force - Hasta la vistaaar! ☆", + "3": "If you don't clear out real quick-like, I'll hafta come at you in self-defense. You get me?", + "4": "Sorry, but if you don't turn yourself around here, amigo, we'll have to send you packing!", + "4_female": "Sorry, but if you don't turn yourself around here, amiga, we'll have to send you packing!", + "5": "Oh great. Here comes another rando to ruin my day.", + "5_female": "Oh great. Here comes another rando to ruin my day." + }, + "victory": { + "1": "How come I'M the one seeing stars?!", + "2": "You're scary, kid. If you joined Team Star, you'd be looking down from the top in no time!", + "3": "I defended myself all right... But it wasn't enough!", + "4": "H-hasta la vistar... ☆", + "5": "I didn't think grunt work for Team Star newbies would be this much of a chore..." + } + }, + "giacomo": { + "encounter": { + "1": "You don't really think things through, do ya? Declarin' war on Team Star is a real bad move.", + "2": "I'll play you a sick requiem as you crash and burn. Let's get this party staaarteeed!" + }, + "victory": { + "1": "Guess that's that...", + "2": "You turned my melody into a threnody..." + } + }, + "mela": { + "encounter": { + "1": "So you're the dope who picked a fight with Team Star... Prepare to get messed up.", + "1_female": "So you're the dope who picked a fight with Team Star... Prepare to get messed up.", + "2": "All riiight, BRING IT! I'll blow everythin' sky high!" + }, + "victory": { + "1": "Ugh. Is this really how it's gonna end? What a hassle...", + "2": "I burned through everythin' I had...and now I've sputtered out." + } + }, + "atticus": { + "encounter": { + "1": "You have some nerve baring your fangs at Team Star. Come, then, villainous wretch!", + "1_female": "You have some nerve baring your fangs at Team Star. Come, then, villainous wretch!", + "2": "Be warned—I shall spare thee no mercy! En garde!" + }, + "victory": { + "1": "Forgive me, my friends...", + "2": "You have utterly bested me. But thy victory stir'd no bitterness within me—such was its brilliance." + } + }, + "ortega": { + "encounter": { + "1": "I promise I'll play nice, so don't blame me when this battle sends you blubbering back home!", + "2": "I'll wipe that smug look off your face for sure! You're going down!", + "2_female": "I'll wipe that smug look off your face for sure! You're going down!" + }, + "victory": { + "1": "Ugh! How could I LOSE! What the HECK!", + "2": "Arrrrgggh! That strength of yours is SO. NOT. FAIR." + } + }, + "eri": { + "encounter": { + "1": "Doesn't matter who you are. I'll bury anyone who tries to take down Team Star!", + "2": "I give as good as I get—that's a promise! We'll see who's left standing in the end!" + }, + "victory": { + "1": "I'm so sorry, everyone...", + "2": "I gave it my all, but it wasn't enough—I wasn't enough..." + } + }, "rocket_boss_giovanni_1": { "encounter": { "1": "So! I must say, I am impressed you got here!" @@ -985,6 +1061,28 @@ "1": "I suppose it must seem that I am doing something terrible. I don't expect you to understand.\n$But I must provide the Galar region with limitless energy to ensure everlasting prosperity." } }, + "star_boss_penny_1": { + "encounter": { + "1": "I'm the big boss of Team Star. The name's Cassiopeia. \n$Now, bow down before the overwhelming might of Team Star's founder!" + }, + "victory": { + "1": "... ... .." + }, + "defeat": { + "1": "Heh..." + } + }, + "star_boss_penny_2": { + "encounter": { + "1": "I won't hold back in this battle! I'll stay true to Team Star's code! \n$My Veevee power will crush you into stardust!" + }, + "victory": { + "1": "...It's all over now." + }, + "defeat": { + "1": "I can't fault you on your battle skills at all... Considering how the bosses fell at your hands." + } + }, "stat_trainer_buck": { "encounter": { "1": "...I'm telling you right now. I'm seriously tough. Act surprised!", diff --git a/src/locales/en/move.json b/src/locales/en/move.json index 7a10335ed06..f54003a296c 100644 --- a/src/locales/en/move.json +++ b/src/locales/en/move.json @@ -3129,7 +3129,7 @@ }, "auraWheel": { "name": "Aura Wheel", - "effect": "Morpeko attacks and raises its Speed with the energy stored in its cheeks. This move's type changes depending on the user's form." + "effect": "The user attacks and raises its Speed with the energy stored in its cheeks. If used by Morpeko, this move's type changes depending on the user's form." }, "breakingSwipe": { "name": "Breaking Swipe", diff --git a/src/locales/en/mystery-encounters/the-expert-pokemon-breeder-dialogue.json b/src/locales/en/mystery-encounters/the-expert-pokemon-breeder-dialogue.json index ebe3af38add..3c74c7b2726 100644 --- a/src/locales/en/mystery-encounters/the-expert-pokemon-breeder-dialogue.json +++ b/src/locales/en/mystery-encounters/the-expert-pokemon-breeder-dialogue.json @@ -23,6 +23,7 @@ "selected": "Let's do this!" }, "outro": "Look how happy your {{chosenPokemon}} is now!$Here, you can have these as well.", + "outro_failed": "How disappointing...$It looks like you still have a long way\nto go to earn your Pokémon's trust!", "gained_eggs": "@s{item_fanfare}You received {{numEggs}}!", "eggs_tooltip": "\n(+) Earn {{eggs}}", "numEggs_one": "{{count}} {{rarity}} Egg", diff --git a/src/locales/en/pokemon-form.json b/src/locales/en/pokemon-form.json index ea7e0f60c90..642d31a2a20 100644 --- a/src/locales/en/pokemon-form.json +++ b/src/locales/en/pokemon-form.json @@ -1,4 +1,5 @@ { + "pikachu": "Normal", "pikachuCosplay": "Cosplay", "pikachuCoolCosplay": "Cool Cosplay", "pikachuBeautyCosplay": "Beauty Cosplay", @@ -6,8 +7,10 @@ "pikachuSmartCosplay": "Smart Cosplay", "pikachuToughCosplay": "Tough Cosplay", "pikachuPartner": "Partner", + "eevee": "Normal", "eeveePartner": "Partner", - "pichuSpiky": "Spiky", + "pichu": "Normal", + "pichuSpiky": "Spiky-Eared", "unownA": "A", "unownB": "B", "unownC": "C", @@ -36,135 +39,252 @@ "unownZ": "Z", "unownExclamation": "!", "unownQuestion": "?", - "castformSunny": "Sunny", - "castformRainy": "Rainy", - "castformSnowy": "Snowy", - "deoxysNormal": "Normal", - "burmyPlant": "Plant", - "burmySandy": "Sandy", - "burmyTrash": "Trash", - "shellosEast": "East", - "shellosWest": "West", + "castform": "Normal Form", + "castformSunny": "Sunny Form", + "castformRainy": "Rainy Form", + "castformSnowy": "Snowy Form", + "deoxysNormal": "Normal Forme", + "deoxysAttack": "Attack Forme", + "deoxysDefense": "Defense Forme", + "deoxysSpeed": "Speed Forme", + "burmyPlant": "Plant Cloak", + "burmySandy": "Sandy Cloak", + "burmyTrash": "Trash Cloak", + "cherubiOvercast": "Overcast Form", + "cherubiSunshine": "Sunshine Form", + "shellosEast": "East Sea", + "shellosWest": "West Sea", + "rotom": "Normal", "rotomHeat": "Heat", "rotomWash": "Wash", "rotomFrost": "Frost", "rotomFan": "Fan", "rotomMow": "Mow", - "giratinaAltered": "Altered", - "shayminLand": "Land", - "basculinRedStriped": "Red Striped", - "basculinBlueStriped": "Blue Striped", - "basculinWhiteStriped": "White Striped", - "deerlingSpring": "Spring", - "deerlingSummer": "Summer", - "deerlingAutumn": "Autumn", - "deerlingWinter": "Winter", - "tornadusIncarnate": "Incarnate", - "thundurusIncarnate": "Incarnate", - "landorusIncarnate": "Incarnate", - "keldeoOrdinary": "Ordinary", - "meloettaAria": "Aria", - "meloettaPirouette": "Pirouette", + "dialga": "Normal", + "dialgaOrigin": "Origin Forme", + "palkia": "Normal", + "palkiaOrigin": "Origin Forme", + "giratinaAltered": "Altered Forme", + "giratinaOrigin": "Origin Forme", + "shayminLand": "Land Forme", + "shayminSky": "Sky Forme", + "basculinRedStriped": "Red-Striped Form", + "basculinBlueStriped": "Blue-Striped Form", + "basculinWhiteStriped": "White-Striped Form", + "darumaka": "Standard Mode", + "darumakaZen": "Zen Mode", + "deerlingSpring": "Spring Form", + "deerlingSummer": "Summer Form", + "deerlingAutumn": "Autumn Form", + "deerlingWinter": "Winter Form", + "tornadusIncarnate": "Incarnate Forme", + "tornadusTherian": "Therian Forme", + "thundurusIncarnate": "Incarnate Forme", + "thundurusTherian": "Therian Forme", + "landorusIncarnate": "Incarnate Forme", + "landorusTherian": "Therian Forme", + "kyurem": "Normal", + "kyuremBlack": "Black", + "kyuremWhite": "White", + "keldeoOrdinary": "Ordinary Form", + "keldeoResolute": "Resolute", + "meloettaAria": "Aria Forme", + "meloettaPirouette": "Pirouette Forme", + "genesect": "Normal", + "genesectShock": "Shock Drive", + "genesectBurn": "Burn Drive", + "genesectChill": "Chill Drive", + "genesectDouse": "Douse Drive", + "froakie": "Normal", "froakieBattleBond": "Battle Bond", - "scatterbugMeadow": "Meadow", - "scatterbugIcySnow": "Icy Snow", - "scatterbugPolar": "Polar", - "scatterbugTundra": "Tundra", - "scatterbugContinental": "Continental", - "scatterbugGarden": "Garden", - "scatterbugElegant": "Elegant", - "scatterbugModern": "Modern", - "scatterbugMarine": "Marine", - "scatterbugArchipelago": "Archipelago", - "scatterbugHighPlains": "High Plains", - "scatterbugSandstorm": "Sandstorm", - "scatterbugRiver": "River", - "scatterbugMonsoon": "Monsoon", - "scatterbugSavanna": "Savanna", - "scatterbugSun": "Sun", - "scatterbugOcean": "Ocean", - "scatterbugJungle": "Jungle", - "scatterbugFancy": "Fancy", - "scatterbugPokeBall": "Poké Ball", - "flabebeRed": "Red", - "flabebeYellow": "Yellow", - "flabebeOrange": "Orange", - "flabebeBlue": "Blue", - "flabebeWhite": "White", - "furfrouHeart": "Heart", - "furfrouStar": "Star", - "furfrouDiamond": "Diamond", - "furfrouDebutante": "Debutante", - "furfrouMatron": "Matron", - "furfrouDandy": "Dandy", - "furfrouLaReine": "La Reine", - "furfrouKabuki": "Kabuki", - "furfrouPharaoh": "Pharaoh", - "pumpkabooSmall": "Small", - "pumpkabooLarge": "Large", - "pumpkabooSuper": "Super", - "xerneasNeutral": "Neutral", - "xerneasActive": "Active", + "froakieAsh": "Ash", + "scatterbugMeadow": "Meadow Pattern", + "scatterbugIcySnow": "Icy Snow Pattern", + "scatterbugPolar": "Polar Pattern", + "scatterbugTundra": "Tundra Pattern", + "scatterbugContinental": "Continental Pattern", + "scatterbugGarden": "Garden Pattern", + "scatterbugElegant": "Elegant Pattern", + "scatterbugModern": "Modern Pattern", + "scatterbugMarine": "Marine Pattern", + "scatterbugArchipelago": "Archipelago Pattern", + "scatterbugHighPlains": "High Plains Pattern", + "scatterbugSandstorm": "Sandstorm Pattern", + "scatterbugRiver": "River Pattern", + "scatterbugMonsoon": "Monsoon Pattern", + "scatterbugSavanna": "Savanna Pattern", + "scatterbugSun": "Sun Pattern", + "scatterbugOcean": "Ocean Pattern", + "scatterbugJungle": "Jungle Pattern", + "scatterbugFancy": "Fancy Pattern", + "scatterbugPokeBall": "Poké Ball Pattern", + "flabebeRed": "Red Flower", + "flabebeYellow": "Yellow Flower", + "flabebeOrange": "Orange Flower", + "flabebeBlue": "Blue Flower", + "flabebeWhite": "White Flower", + "furfrou": "Natural Form", + "furfrouHeart": "Heart Trim", + "furfrouStar": "Star Trim", + "furfrouDiamond": "Diamond Trim", + "furfrouDebutante": "Debutante Trim", + "furfrouMatron": "Matron Trim", + "furfrouDandy": "Dandy Trim", + "furfrouLaReine": "La Reine Trim", + "furfrouKabuki": "Kabuki Trim", + "furfrouPharaoh": "Pharaoh Trim", + "espurrMale": "Male", + "espurrFemale": "Female", + "honedgeShiled": "Shield Forme", + "honedgeBlade": "Blade Forme", + "pumpkaboo": "Average Size", + "pumpkabooSmall": "Small Size", + "pumpkabooLarge": "Large Size", + "pumpkabooSuper": "Super Size", + "xerneasNeutral": "Neutral Mode", + "xerneasActive": "Active Mode", "zygarde50": "50% Forme", "zygarde10": "10% Forme", "zygarde50Pc": "50% Forme Power Construct", "zygarde10Pc": "10% Forme Power Construct", "zygardeComplete": "Complete Forme", - "oricorioBaile": "Baile", - "oricorioPompom": "Pom-Pom", - "oricorioPau": "Pau", - "oricorioSensu": "Sensu", + "hoopa": "Confined", + "hoopaUnbound": "Unbound", + "oricorioBaile": "Baile Style", + "oricorioPompom": "Pom-Pom Style", + "oricorioPau": "Pau Style", + "oricorioSensu": "Sensu Style", + "rockruff": "Normal", "rockruffOwnTempo": "Own Tempo", - "miniorRedMeteor": "Red Meteor", - "miniorOrangeMeteor": "Orange Meteor", - "miniorYellowMeteor": "Yellow Meteor", - "miniorGreenMeteor": "Green Meteor", - "miniorBlueMeteor": "Blue Meteor", - "miniorIndigoMeteor": "Indigo Meteor", - "miniorVioletMeteor": "Violet Meteor", - "miniorRed": "Red", - "miniorOrange": "Orange", - "miniorYellow": "Yellow", - "miniorGreen": "Green", - "miniorBlue": "Blue", - "miniorIndigo": "Indigo", - "miniorViolet": "Violet", - "mimikyuDisguised": "Disguised", - "mimikyuBusted": "Busted", + "rockruffMidday": "Midday Form", + "rockruffMidnight": "Midnight Form", + "rockruffDusk": "Dusk Form", + "wishiwashi": "Solo Form", + "wishiwashiSchool": "School", + "typeNullNormal": "Type: Normal", + "typeNullFighting": "Type: Fighting", + "typeNullFlying": "Type: Flying", + "typeNullPoison": "Type: Poison", + "typeNullGround": "Type: Ground", + "typeNullRock": "Type: Rock", + "typeNullBug": "Type: Bug", + "typeNullGhost": "Type: Ghost", + "typeNullSteel": "Type: Steel", + "typeNullFire": "Type: Fire", + "typeNullWater": "Type: Water", + "typeNullGrass": "Type: Grass", + "typeNullElectric": "Type: Electric", + "typeNullPsychic": "Type: Psychic", + "typeNullIce": "Type: Ice", + "typeNullDragon": "Type: Dragon", + "typeNullDark": "Type: Dark", + "typeNullFairy": "Type: Fairy", + "miniorRedMeteor": "Red Meteor Form", + "miniorOrangeMeteor": "Orange Meteor Form", + "miniorYellowMeteor": "Yellow Meteor Form", + "miniorGreenMeteor": "Green Meteor Form", + "miniorBlueMeteor": "Blue Meteor Form", + "miniorIndigoMeteor": "Indigo Meteor Form", + "miniorVioletMeteor": "Violet Meteor Form", + "miniorRed": "Red Core Form", + "miniorOrange": "Orange Core Form", + "miniorYellow": "Yellow Core Form", + "miniorGreen": "Green Core Form", + "miniorBlue": "Blue Core Form", + "miniorIndigo": "Indigo Core Form", + "miniorViolet": "Violet Core Form", + "mimikyuDisguised": "Disguised Form", + "mimikyuBusted": "Busted Form", + "necrozma": "Normal", + "necrozmaDuskMane": "Dusk Mane", + "necrozmaDawnWings": "Dawn Wings", + "necrozmaUltra": "Ultra", + "magearna": "Normal", "magearnaOriginal": "Original", + "marshadow": "Normal", "marshadowZenith": "Zenith", - "sinisteaPhony": "Phony", - "sinisteaAntique": "Antique", + "cramorant": "Normal", + "cramorantGulping": "Gulping Form", + "cramorantGorging": "Gorging Form", + "toxelAmped": "Amped Form", + "toxelLowkey": "Low-Key Form", + "sinisteaPhony": "Phony Form", + "sinisteaAntique": "Antique Form", + "milceryVanillaCream": "Vanilla Cream", + "milceryRubyCream": "Ruby Cream", + "milceryMatchaCream": "Matcha Cream", + "milceryMintCream": "Mint Cream", + "milceryLemonCream": "Lemon Cream", + "milcerySaltedCream": "Salted Cream", + "milceryRubySwirl": "Ruby Swirl", + "milceryCaramelSwirl": "Caramel Swirl", + "milceryRainbowSwirl": "Rainbow Swirl", + "eiscue": "Ice Face", "eiscueNoIce": "No Ice", "indeedeeMale": "Male", "indeedeeFemale": "Female", - "morpekoFullBelly": "Full Belly", + "morpekoFullBelly": "Full Belly Mode", + "morpekoHangry": "Hangry Mode", "zacianHeroOfManyBattles": "Hero Of Many Battles", + "zacianCrowned": "Crowned", "zamazentaHeroOfManyBattles": "Hero Of Many Battles", + "zamazentaCrowned": "Crowned", + "kubfuSingleStrike": "Single Strike Style", + "kubfuRapidStrike": "Rapid Strike Style", + "zarude": "Normal", "zarudeDada": "Dada", - "enamorusIncarnate": "Incarnate", + "calyrex": "Normal", + "calyrexIce": "Ice Rider", + "calyrexShadow": "Shadow Rider", + "basculinMale": "Male", + "basculinFemale": "Female", + "enamorusIncarnate": "Incarnate Forme", + "enamorusTherian": "Therian Forme", + "lechonkMale": "Male", + "lechonkFemale": "Female", + "tandemausFour": "Family of Four", + "tandemausThree": "Family of Three", "squawkabillyGreenPlumage": "Green Plumage", "squawkabillyBluePlumage": "Blue Plumage", "squawkabillyYellowPlumage": "Yellow Plumage", "squawkabillyWhitePlumage": "White Plumage", - "tatsugiriCurly": "Curly", - "tatsugiriDroopy": "Droopy", - "tatsugiriStretchy": "Stretchy", - "gimmighoulChest": "Chest", - "gimmighoulRoaming": "Roaming", + "finizenZero": "Zero Form", + "finizenHero": "Hero Form", + "tatsugiriCurly": "Curly Form", + "tatsugiriDroopy": "Droopy Form", + "tatsugiriStretchy": "Stretchy Form", + "dunsparceTwo": "Two-Segment Form", + "dunsparceThree": "Three-Segment Form", + "gimmighoulChest": "Chest Form", + "gimmighoulRoaming": "Roaming Form", "koraidonApexBuild": "Apex Build", "koraidonLimitedBuild": "Limited Build", "koraidonSprintingBuild": "Sprinting Build", "koraidonSwimmingBuild": "Swimming Build", "koraidonGlidingBuild": "Gliding Build", "miraidonUltimateMode": "Ultimate Mode", - "miraidonLowPowerMode": "Low Power Mode", + "miraidonLowPowerMode": "Low-Power Mode", "miraidonDriveMode": "Drive Mode", "miraidonAquaticMode": "Aquatic Mode", "miraidonGlideMode": "Glide Mode", - "poltchageistCounterfeit": "Counterfeit", - "poltchageistArtisan": "Artisan", - "paldeaTaurosCombat": "Combat", - "paldeaTaurosBlaze": "Blaze", - "paldeaTaurosAqua": "Aqua" -} \ No newline at end of file + "poltchageistCounterfeit": "Counterfeit Form", + "poltchageistArtisan": "Artisan Form", + "poltchageistUnremarkable": "Unremarkable Form", + "poltchageistMasterpiece": "Masterpiece Form", + "ogerponTealMask": "Teal Mask", + "ogerponTealMaskTera": "Teal Mask Terastallized", + "ogerponWellspringMask": "Wellspring Mask", + "ogerponWellspringMaskTera": "Wellspring Mask Terastallized", + "ogerponHearthflameMask": "Hearthflame Mask", + "ogerponHearthflameMaskTera": "Hearthflame Mask Terastallized", + "ogerponCornerstoneMask": "Cornerstone Mask", + "ogerponCornerstoneMaskTera": "Cornerstone Mask Terastallized", + "terpagos": "Normal Form", + "terpagosTerastal": "Terastal Form", + "terpagosStellar": "Stellar Form", + "galarDarumaka": "Standard Mode", + "galarDarumakaZen": "Zen Mode", + "paldeaTaurosCombat": "Combat Breed", + "paldeaTaurosBlaze": "Blaze Breed", + "paldeaTaurosAqua": "Aqua Breed" +} diff --git a/src/locales/en/trainer-classes.json b/src/locales/en/trainer-classes.json index 9e30915dee6..092bc8d895d 100644 --- a/src/locales/en/trainer-classes.json +++ b/src/locales/en/trainer-classes.json @@ -126,5 +126,8 @@ "skull_grunts": "Team Skull Grunts", "macro_grunt": "Macro Cosmos Trainer", "macro_grunt_female": "Macro Cosmos Trainer", - "macro_grunts": "Macro Cosmos Trainers" + "macro_grunts": "Macro Cosmos Trainers", + "star_grunt": "Star Grunt", + "star_grunt_female": "Star Grunt", + "star_grunts": "Star Grunts" } diff --git a/src/locales/en/trainer-names.json b/src/locales/en/trainer-names.json index 3c709f6a138..5a9db128e2f 100644 --- a/src/locales/en/trainer-names.json +++ b/src/locales/en/trainer-names.json @@ -141,6 +141,11 @@ "faba": "Faba", "plumeria": "Plumeria", "oleana": "Oleana", + "giacomo": "Giacomo", + "mela": "Mela", + "atticus": "Atticus", + "ortega": "Ortega", + "eri": "Eri", "maxie": "Maxie", "archie": "Archie", @@ -150,6 +155,7 @@ "lusamine": "Lusamine", "guzma": "Guzma", "rose": "Rose", + "cassiopeia": "Penny", "blue_red_double": "Blue & Red", "red_blue_double": "Red & Blue", diff --git a/src/locales/en/trainer-titles.json b/src/locales/en/trainer-titles.json index 7ef715d115f..ae19fc30790 100644 --- a/src/locales/en/trainer-titles.json +++ b/src/locales/en/trainer-titles.json @@ -19,6 +19,7 @@ "aether_boss": "Aether President", "skull_boss": "Team Skull Boss", "macro_boss": "Macro Cosmos President", + "star_boss": "Team Star Leader", "rocket_admin": "Team Rocket Admin", "rocket_admin_female": "Team Rocket Admin", @@ -35,6 +36,7 @@ "aether_admin": "Aether Foundation Admin", "skull_admin": "Team Skull Admin", "macro_admin": "Macro Cosmos", + "star_admin": "Team Star Squad Boss", "the_winstrates": "The Winstrates'" } diff --git a/src/locales/es/ability-trigger.json b/src/locales/es/ability-trigger.json index 4380c84b8e9..07ce3459dc8 100644 --- a/src/locales/es/ability-trigger.json +++ b/src/locales/es/ability-trigger.json @@ -4,7 +4,7 @@ "costar": "¡{{pokemonName}} copió los cambios de características de {{allyName}}!", "iceFaceAvoidedDamage": "¡{{pokemonNameWithAffix}} evitó\ndaño con {{abilityName}}!", "perishBody": "¡{{abilityName}} de {{pokemonName}} debilitará a ambos Pokémon en 3 turnos!", - "poisonHeal": "¡{{pokemonNameWithAffix}} restauró algunos de sus PS gracias a {{abilityName}}!", + "poisonHeal": "¡{{pokemonName}} restauró algunos de sus PS gracias a {{abilityName}}!", "trace": "¡{{pokemonName}} ha copiado la habilidad {{abilityName}} \nde {{targetName}}!", "windPowerCharged": "¡{{pokemonName}} se ha cargado de electricidad gracias a {{moveName}}!", "quickDraw": "¡{{pokemonName}} ataca primero gracias a la habilidad Mano Rápida!", diff --git a/src/locales/es/ability.json b/src/locales/es/ability.json index 598694f441e..01b5348d742 100644 --- a/src/locales/es/ability.json +++ b/src/locales/es/ability.json @@ -1237,6 +1237,6 @@ }, "poisonPuppeteer": { "name": "Títere Tóxico", - "description": "Los rivales que Pecharunt envenene con sus movimientos también sufrirán confusión." + "description": "Los rivales que el usuario envenene con sus movimientos también sufrirán confusión." } } diff --git a/src/locales/es/battle.json b/src/locales/es/battle.json index c79315f297b..c5fbf25f3ae 100644 --- a/src/locales/es/battle.json +++ b/src/locales/es/battle.json @@ -85,5 +85,7 @@ "statSeverelyFell_one": "¡El {{stats}} de {{pokemonNameWithAffix}} ha bajado muchísimo!", "statSeverelyFell_other": "¡{{stats}} de\n{{pokemonNameWithAffix}} han bajado muchísimo!", "statWontGoAnyLower_one": "¡El {{stats}} de {{pokemonNameWithAffix}} no puede bajar más!", - "statWontGoAnyLower_other": "¡{{stats}} de\n{{pokemonNameWithAffix}} no pueden bajar más!" + "statWontGoAnyLower_other": "¡{{stats}} de\n{{pokemonNameWithAffix}} no pueden bajar más!", + "battlerTagsHealBlock": "¡{{pokemonNameWithAffix}} no puede restaurar sus PS!", + "battlerTagsHealBlockOnRemove": "¡{{pokemonNameWithAffix}} ya puede recuperar PS!" } diff --git a/src/locales/es/bgm-name.json b/src/locales/es/bgm-name.json index f0e0ab7e852..0f261bbd563 100644 --- a/src/locales/es/bgm-name.json +++ b/src/locales/es/bgm-name.json @@ -107,17 +107,17 @@ "forest": "PMD EoS - Bosque Sombrío", "grass": "PMD EoS - Manzanar", "graveyard": "PMD EoS - Bosque Misterio", - "ice_cave": "PMD EoS - Gran Iceberg", + "ice_cave": "Firel - -50°C", "island": "PMD EoS - Costa Escarpada", "jungle": "Lmz - Jungla", "laboratory": "Firel - Laboratorio", - "lake": "PMD EoS - Cueva Cristal", + "lake": "Lmz - Lake", "meadow": "PMD EoS - Bosque de la Cumbre del Cielo", "metropolis": "Firel - Metrópolis", "mountain": "PMD EoS - Monte Cuerno", - "plains": "PMD EoS - Pradera de la Cumbre del Cielo", - "power_plant": "PMD EoS - Pradera Destello", - "ruins": "PMD EoS - Sima Hermética", + "plains": "Firel - Route 888", + "power_plant": "Firel - The Klink", + "ruins": "Lmz - Ancient Ruins", "sea": "Andr06 - Misticismo marino", "seabed": "Firel - Lecho del mar", "slum": "Andr06 - Snom sigiloso", @@ -127,7 +127,7 @@ "tall_grass": "PMD EoS - Bosque Niebla", "temple": "PMD EoS - Cueva Regia", "town": "PMD EoS - Tema del territorio aleatorio 3", - "volcano": "PMD EoS - Cueva Vapor", + "volcano": "Firel - Twisturn Volcano", "wasteland": "PMD EoS - Corazón Tierra Oculta", "encounter_ace_trainer": "BW - ¡Vs. entrenador guay!", "encounter_backpacker": "BW - ¡Vs. mochilero!", diff --git a/src/locales/es/move.json b/src/locales/es/move.json index f4c28dd02e7..21f73bbf1d3 100644 --- a/src/locales/es/move.json +++ b/src/locales/es/move.json @@ -3129,7 +3129,7 @@ }, "auraWheel": { "name": "Rueda Aural", - "effect": "La energía que acumula en las mejillas le sirve para atacar y aumentar su Velocidad. Este movimiento cambia de tipo según la forma que adopte Morpeko." + "effect": "La energía que acumula en las mejillas le sirve para atacar y aumentar su Velocidad. Si es utilizado por Morpeko, este movimiento cambia de tipo según la forma que adopte." }, "breakingSwipe": { "name": "Vasto Impacto", diff --git a/src/locales/es/pokemon-form.json b/src/locales/es/pokemon-form.json index 2f70038ad2d..b6008357d89 100644 --- a/src/locales/es/pokemon-form.json +++ b/src/locales/es/pokemon-form.json @@ -1,4 +1,5 @@ { + "pikachu": "Normal", "pikachuCosplay": "Coqueta", "pikachuCoolCosplay": "Roquera", "pikachuBeautyCosplay": "Aristócrata", @@ -6,7 +7,9 @@ "pikachuSmartCosplay": "Erudita", "pikachuToughCosplay": "Enmascarada", "pikachuPartner": "Compañero", + "eevee": "Normal", "eeveePartner": "Compañero", + "pichu": "Normal", "pichuSpiky": "Picoreja", "unownA": "A", "unownB": "B", @@ -36,36 +39,65 @@ "unownZ": "Z", "unownExclamation": "!", "unownQuestion": "?", + "castform": "Normal Form", "castformSunny": "Sol", "castformRainy": "Lluvia", "castformSnowy": "Nieve", "deoxysNormal": "Normal", + "deoxysAttack": "Ataque", + "deoxysDefense": "Defensa", + "deoxysSpeed": "Velocidad", "burmyPlant": "Planta", "burmySandy": "Arena", "burmyTrash": "Basura", + "cherubiOvercast": "Encapotado", + "cherubiSunshine": "Soleado", "shellosEast": "Este", "shellosWest": "Oeste", + "rotom": "Normal", "rotomHeat": "Calor", "rotomWash": "Lavado", "rotomFrost": "Frío", "rotomFan": "Ventilador", "rotomMow": "Corte", + "dialga": "Normal", + "dialgaOrigin": "Origen", + "palkia": "Normal", + "palkiaOrigin": "Origen", "giratinaAltered": "Modificada", + "giratinaOrigin": "Origen", "shayminLand": "Tierra", + "shayminSky": "Cielo", "basculinRedStriped": "Raya Roja", "basculinBlueStriped": "Raya Azul", "basculinWhiteStriped": "Raya Blanca", + "darumaka": "Modo Normal", + "darumakaZen": "Modo Daruma", "deerlingSpring": "Primavera", "deerlingSummer": "Verano", "deerlingAutumn": "Otoño", "deerlingWinter": "Invierno", "tornadusIncarnate": "Avatar", + "tornadusTherian": "Tótem", "thundurusIncarnate": "Avatar", + "thundurusTherian": "Tótem", "landorusIncarnate": "Avatar", + "landorusTherian": "Tótem", + "kyurem": "Normal", + "kyuremBlack": "Negro", + "kyuremWhite": "Blanco", "keldeoOrdinary": "Habitual", + "keldeoResolute": "Brío", "meloettaAria": "Lírica", "meloettaPirouette": "Danza", + "genesect": "Normal", + "genesectShock": "FulgoROM", + "genesectBurn": "PiroROM", + "genesectChill": "CrioROM", + "genesectDouse": "HidroROM", + "froakie": "Normal", "froakieBattleBond": "Fuerte Afecto", + "froakieAsh": "Ash", "scatterbugMeadow": "Floral", "scatterbugIcySnow": "Polar", "scatterbugPolar": "Taiga", @@ -91,6 +123,7 @@ "flabebeOrange": "Naranja", "flabebeBlue": "Azul", "flabebeWhite": "Blanco", + "furfrou": "Salvaje", "furfrouHeart": "Corazón", "furfrouStar": "Estrella", "furfrouDiamond": "Diamante", @@ -100,9 +133,14 @@ "furfrouLaReine": "Aristócrata", "furfrouKabuki": "Kabuki", "furfrouPharaoh": "Faraónico", - "pumpkabooSmall": "Pequeño", - "pumpkabooLarge": "Grande", - "pumpkabooSuper": "Enorme", + "espurrMale": "Macho", + "espurrFemale": "Hembra", + "honedgeShiled": "Escudo", + "honedgeBlade": "Filo", + "pumpkaboo": "Tamaño Normal", + "pumpkabooSmall": "Tamaño Pequeño", + "pumpkabooLarge": "Tamaño Grande", + "pumpkabooSuper": "Tamaño Extragrande", "xerneasNeutral": "Relajado", "xerneasActive": "Activo", "zygarde50": "Al 50%", @@ -110,11 +148,37 @@ "zygarde50Pc": "Zygarde al 50%", "zygarde10Pc": "Zygarde al 10%", "zygardeComplete": "Zygarde Completo", + "hoopa": "Contenido", + "hoopaUnbound": "Desatado", "oricorioBaile": "Apasionado", "oricorioPompom": "Animado", "oricorioPau": "Plácido", "oricorioSensu": "Refinado", + "rockruff": "Normal", "rockruffOwnTempo": "Ritmo Propio", + "rockruffMidday": "Diurna", + "rockruffMidnight": "Nocturna", + "rockruffDusk": "Crepuscular", + "wishiwashi": "Solo Form", + "wishiwashiSchool": "Banco", + "typeNullNormal": "Tipo Normal", + "typeNullFighting": "Tipo Lucha", + "typeNullFlying": "Tipo Volador", + "typeNullPoison": "Tipo Veneno", + "typeNullGround": "Tipo Tierra", + "typeNullRock": "Tipo Roca", + "typeNullBug": "Tipo Bicho", + "typeNullGhost": "Tipo Fantasma", + "typeNullSteel": "Tipo Acero", + "typeNullFire": "Tipo Fuego", + "typeNullWater": "Tipo Agua", + "typeNullGrass": "Tipo Planta", + "typeNullElectric": "Tipo Eléctrico", + "typeNullPsychic": "Tipo Psíquico", + "typeNullIce": "Tipo Hielo", + "typeNullDragon": "Tipo Dragón", + "typeNullDark": "Tipo Siniestro", + "typeNullFairy": "Tipo Hada", "miniorRedMeteor": "Núcleo Rojo", "miniorOrangeMeteor": "Núcleo Naranja", "miniorYellowMeteor": "Núcleo Amarillo", @@ -131,25 +195,66 @@ "miniorViolet": "Violeta", "mimikyuDisguised": "Encubierta", "mimikyuBusted": "Descubierta", + "necrozma": "Normal", + "necrozmaDuskMane": "Melena Crepuscular", + "necrozmaDawnWings": "Asas Alvorada", + "necrozmaUltra": "Ultra", + "magearna": "Normal", "magearnaOriginal": "Vetusto", + "marshadow": "Normal", "marshadowZenith": "Cénit", + "cramorant": "Normal", + "cramorantGulping": "Tragatodo", + "cramorantGorging": "Engulletodo", + "toxelAmped": "Agudo", + "toxelLowkey": "Grave", "sinisteaPhony": "Falsificada", "sinisteaAntique": "Genuina", + "milceryVanillaCream": "Crema de Vainilla", + "milceryRubyCream": "Crema Rosa", + "milceryMatchaCream": "Crema de Té", + "milceryMintCream": "Crema de Menta", + "milceryLemonCream": "Crema de Limón", + "milcerySaltedCream": "Crema Salada", + "milceryRubySwirl": "Mezcla Rosa", + "milceryCaramelSwirl": "Mezcla Caramelo", + "milceryRainbowSwirl": "Tres Sabores", + "eiscue": "Cara de Hielo", "eiscueNoIce": "Cara Deshielo", "indeedeeMale": "Macho", "indeedeeFemale": "Hembra", "morpekoFullBelly": "Saciada", + "morpekoHangry": "Voraz", "zacianHeroOfManyBattles": "Guerrero avezado", + "zacianCrowned": "Espada Suprema", "zamazentaHeroOfManyBattles": "Guerrero avezado", + "zamazentaCrowned": "Escudo Supremo", + "kubfuSingleStrike": "Estilo Brusco", + "kubfuRapidStrike": "Estilo Fluido", + "zarude": "Normal", "zarudeDada": "Papá", + "calyrex": "Normal", + "calyrexIce": "Jinete Glacial", + "calyrexShadow": "Jinete Espectral", + "basculinMale": "Macho", + "basculinFemale": "Hembra", "enamorusIncarnate": "Avatar", + "enamorusTherian": "Tótem", + "lechonkMale": "Macho", + "lechonkFemale": "Hembra", + "tandemausFour": "Familia de Cuatro", + "tandemausThree": "Familia de Tres", "squawkabillyGreenPlumage": "Plumaje Verde", "squawkabillyBluePlumage": "Plumaje Azul", "squawkabillyYellowPlumage": "Plumaje Amarillo", "squawkabillyWhitePlumage": "Plumaje Blanco", + "finizenZero": "Ingenua", + "finizenHero": "Heroica", "tatsugiriCurly": "Curvada", "tatsugiriDroopy": "Lánguida", "tatsugiriStretchy": "Estirada", + "dunsparceTwo": "Binodular", + "dunsparceThree": "Trinodular", "gimmighoulChest": "Cofre", "gimmighoulRoaming": "Andante", "koraidonApexBuild": "Forma Plena", @@ -164,6 +269,21 @@ "miraidonGlideMode": "Modo Planeo", "poltchageistCounterfeit": "Fraudulenta", "poltchageistArtisan": "Opulenta", + "poltchageistUnremarkable": "Mediocre", + "poltchageistMasterpiece": "Exquisita", + "ogerponTealMask": "Máscara Turquesa", + "ogerponTealMaskTera": "Máscara Turquesa Teracristal", + "ogerponWellspringMask": "Máscara Fuente", + "ogerponWellspringMaskTera": "Máscara Fuente Teracristal", + "ogerponHearthflameMask": "Máscara Horno", + "ogerponHearthflameMaskTera": "Máscara Horno Teracristal", + "ogerponCornerstoneMask": "Máscara Cimiento", + "ogerponCornerstoneMaskTera": "Máscara Cimiento Teracristal", + "terpagos": "Normal", + "terpagosTerastal": "Teracristal", + "terpagosStellar": "Astral", + "galarDarumaka": "Modo Normal", + "galarDarumakaZen": "Modo Daruma", "paldeaTaurosCombat": "Combatiente", "paldeaTaurosBlaze": "Ardiente", "paldeaTaurosAqua": "Acuático" diff --git a/src/locales/es/trainer-classes.json b/src/locales/es/trainer-classes.json index 0677193e4f8..c8517ae73d3 100644 --- a/src/locales/es/trainer-classes.json +++ b/src/locales/es/trainer-classes.json @@ -98,5 +98,8 @@ "youngster": "Joven", "aether_grunt": "Empleado de la Fundación Æther", "aether_grunt_female": "Empleada de la Fundación Æther", - "aether_grunts": "Empleados de la Fundación Æther" + "aether_grunts": "Empleados de la Fundación Æther", + "star_grunt": "Star Grunt", + "star_grunt_female": "Star Grunt", + "star_grunts": "Star Grunts" } diff --git a/src/locales/es/trainer-names.json b/src/locales/es/trainer-names.json index ce09a0c9037..da18b6bbcd9 100644 --- a/src/locales/es/trainer-names.json +++ b/src/locales/es/trainer-names.json @@ -138,6 +138,15 @@ "rood": "Ruga", "xerosic": "Xero", "bryony": "Begonia", + "faba": "Fabio", + "plumeria": "Francine", + "oleana": "Olivia", + "giacomo": "Anán", + "mela": "Melo", + "atticus": "Henzo", + "ortega": "Gus", + "eri": "Erin", + "maxie": "Magno", "archie": "Aquiles", "cyrus": "Helio", @@ -145,6 +154,10 @@ "lysandre": "Lysson", "faba": "Fabio", "lusamine": "Samina", + "guzma": "Guzmán", + "rose": "Rose", + "cassiopeia": "Noa", + "blue_red_double": "Azul y Rojo", "red_blue_double": "Rojo y Azul", "tate_liza_double": "Vito y Leti", diff --git a/src/locales/es/trainer-titles.json b/src/locales/es/trainer-titles.json index 5bee9fc8c51..eda3e4b36a4 100644 --- a/src/locales/es/trainer-titles.json +++ b/src/locales/es/trainer-titles.json @@ -17,6 +17,9 @@ "plasma_boss": "Team Plasma Boss", "flare_boss": "Team Flare Boss", "aether_boss": "Presidente Æther", + "skull_boss": "Team Skull Boss", + "macro_boss": "Macro Cosmos President", + "star_boss": "Team Star Leader", "rocket_admin": "Team Rocket Admin", "rocket_admin_female": "Team Rocket Admin", @@ -30,5 +33,8 @@ "plasma_admin": "Team Plasma Admin", "flare_admin": "Team Flare Admin", "flare_admin_female": "Team Flare Admin", - "aether_admin": "Director de la Fundación Æther" + "aether_admin": "Director de la Fundación Æther", + "skull_admin": "Team Skull Admin", + "macro_admin": "Macro Cosmos", + "star_admin": "Team Star Squad Boss" } diff --git a/src/locales/fr/ability.json b/src/locales/fr/ability.json index 7db44c45fa7..e5ac2fd3361 100644 --- a/src/locales/fr/ability.json +++ b/src/locales/fr/ability.json @@ -1077,7 +1077,7 @@ }, "thermalExchange": { "name": "Thermodynamique", - "description": "Lorsque le Pokémon est touché par une capacité de type Feu, il ne subit aucun dégât et son Attaque augmente." + "description": "Lorsque le Pokémon est touché par une capacité de type Feu, son Attaque augmente. Il ne peut pas être brulé." }, "angerShell": { "name": "Courroupace", @@ -1237,6 +1237,6 @@ }, "poisonPuppeteer": { "name": "Emprise Toxique", - "description": "Lorsque Pêchaminus empoisonne un Pokémon grâce à l’une de ses capacités, ce dernier devient également confus." + "description": "Lorsque le Pokémon en empoisonne un autre grâce à l’une de ses capacités, ce dernier devient également confus." } } diff --git a/src/locales/fr/battle.json b/src/locales/fr/battle.json index 5f5e81350e1..6c555fa77be 100644 --- a/src/locales/fr/battle.json +++ b/src/locales/fr/battle.json @@ -14,6 +14,10 @@ "moneyWon": "Vous remportez\n{{moneyAmount}} ₽ !", "moneyPickedUp": "Vous obtenez {{moneyAmount}} ₽ !", "pokemonCaught": "Vous avez attrapé\n{{pokemonName}} !", + "pokemonObtained": "Vous obtenez\nun {{pokemonName}} !", + "pokemonBrokeFree": "Oh non !\nLe Pokémon s’est libéré !", + "pokemonFled": "Le {{pokemonName}} sauvage\nprend la fuite !", + "playerFled": "Vous fuyez le {{pokemonName}} !", "addedAsAStarter": "{{pokemonName}} est ajouté\ncomme starter !", "partyFull": "Votre équipe est pleine.\nRelâcher un Pokémon pour {{pokemonName}} ?", "pokemon": "de Pokémon", @@ -65,6 +69,7 @@ "skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre d’objet ?", "itemStackFull": "Quantité maximale de {{fullItemName}} atteinte.\nVous recevez {{itemName}} à la place.", "eggHatching": "Hein ?", + "eggSkipPrompt": "Aller directement au résumé des Œufs éclos ?", "ivScannerUseQuestion": "Utiliser le Scanner d’IV\nsur {{pokemonName}} ?", "wildPokemonWithAffix": "{{pokemonName}} sauvage", "foePokemonWithAffix": "{{pokemonName}} ennemi", @@ -99,5 +104,7 @@ "unlockedSomething": "{{unlockedThing}}\na été débloqué.", "congratulations": "Félicitations !", "beatModeFirstTime": "{{speciesName}} a battu le mode {{gameMode}} pour la première fois !\nVous avez reçu {{newModifier}} !", - "eggSkipPrompt": "Aller directement au résumé des Œufs éclos ?" + "ppReduced": "Les PP de la capacité {{moveName}}\nde{{targetName}} baissent de {{reduction}} !", + "battlerTagsHealBlock": "{{pokemonNameWithAffix}} ne peut pas guérir !", + "battlerTagsHealBlockOnRemove": "Le blocage de soins qui affectait\n{{pokemonNameWithAffix}} s’est dissipé !" } diff --git a/src/locales/fr/bgm-name.json b/src/locales/fr/bgm-name.json index ecf0075e79d..06eca763914 100644 --- a/src/locales/fr/bgm-name.json +++ b/src/locales/fr/bgm-name.json @@ -83,9 +83,11 @@ "battle_aether_grunt": "SL - Vs. Fondation Æther", "battle_skull_grunt": "SL - Vs. Team Skull", "battle_macro_grunt": "ÉB - Vs. Macro Cosmos", + "battle_star_grunt": "ÉV - Vs. Team Star", "battle_galactic_admin": "DÉPS - Vs. Admin Team Galaxie", "battle_skull_admin": "SL - Vs. Admin Team Skull", "battle_oleana": "ÉB - Vs. Liv", + "battle_star_admin": "ÉV - Vs. Boss de la Team Star", "battle_rocket_boss": "USUL - Vs. Giovanni", "battle_aqua_magma_boss": "ROSA - Vs. Arthur/Max", "battle_galactic_boss": "DÉPS - Vs. Hélio", @@ -94,6 +96,7 @@ "battle_aether_boss": "SL - Vs. Elsa-Mina", "battle_skull_boss": "SL - Vs. Guzma", "battle_macro_boss": "ÉB - Vs. Shehroz", + "battle_star_boss": "ÉV - Vs. Cassiopée", "abyss": "PDM EdC - Cratère Obscur", "badlands": "PDM EdC - Vallée Stérile", @@ -108,17 +111,17 @@ "forest": "PDM EdC - Forêt Crépuscule", "grass": "PDM EdC - Bois aux Pommes", "graveyard": "PDM EdC - Forêt Trompeuse", - "ice_cave": "PDM EdC - Montagne Glacier", + "ice_cave": "Firel - -50°C", "island": "PDM EdC - Côte Escarpée", "jungle": "Lmz - Jungle", "laboratory": "Firel - Laboratory", - "lake": "PDM EdC - Caverne Cristal", + "lake": "Lmz - Lake", "meadow": "PDM EdC - Pic Céleste (forêt)", "metropolis": "Firel - Metropolis", "mountain": "PDM EdC - Mont Corne", - "plains": "PDM EdC - Pic Céleste (prairie)", - "power_plant": "PDM EdC - Plaines Élek", - "ruins": "PDM EdC - Ruine Scellée", + "plains": "Firel - Route 888", + "power_plant": "Firel - The Klink", + "ruins": "Lmz - Ancient Ruins", "sea": "Andr06 - Marine Mystique", "seabed": "Firel - Seabed", "slum": "Andr06 - Sneaky Snom", @@ -128,7 +131,7 @@ "tall_grass": "PDM EdC - Forêt Brumeuse", "temple": "PDM EdC - Grotte Égide", "town": "PDM EdC - Donjon aléatoire - Thème 3", - "volcano": "PDM EdC - Grotte Étuve", + "volcano": "Firel - Twisturn Volcano", "wasteland": "PDM EdC - Terres Illusoires", "encounter_ace_trainer": "NB - Regards croisés (Topdresseur·euse)", "encounter_backpacker": "NB - Regards croisés (Randonneur·euse)", diff --git a/src/locales/fr/dialogue.json b/src/locales/fr/dialogue.json index adc58de0563..e8df718ab08 100644 --- a/src/locales/fr/dialogue.json +++ b/src/locales/fr/dialogue.json @@ -344,12 +344,17 @@ "1": "Hop hop hop ! Terminus !", "2": "T’es un Dresseur n’est-ce pas ?\n$J’ai bien peur ce que ne soit pas une excuse suffisante pour nous interrompre dans notre travail.", "2_female": "T’es une Dresseuse n’est-ce pas ?\n$J’ai bien peur ce que ne soit pas une excuse suffisante pour nous interrompre dans notre travail.", - "3": "Je travaille à Macro Cosmos Assurances !\nBesoin d’une assurance-vie ?" + "3": "Je travaille à Macro Cosmos Assurances !\nBesoin d’une assurance-vie ?", + "4": "Trouvé !\nPetit interlude combat !", + "4_female": "Trouvée !\nPetit interlude combat !", + "5": "Une soufflante de la part de madame Liv est la pire chose qui puisse arriver !" }, "victory": { "1": "Je n’ai d’autre choix que respectueusement me retirer.", "2": "Mon argent de poche…\nPlus qu’à manger des pâtes pour la fin du mois…", - "3": "Chez Macro Cosmos, rien n’est comparable à notre dévotion au travail !" + "3": "Chez Macro Cosmos, rien n’est comparable à notre dévotion au travail !", + "4": "J’ai même pensé à chager de Pokémon en combat…", + "5": "Combattre ne sert à rien…\nPlus qu’à me barrer !" } }, "oleana": { @@ -365,6 +370,77 @@ "3": "*soupir* Je suis fatiguée parton…" } }, + "star_grunt": { + "encounter": { + "1": "Ouais, un peu de respect, tu veux ?\n Tu sais à qui t’as affaire ?", + "2": "Notre comité d’accueil va pas te faire de cadeau ! Hasta la vistaaar ! ★", + "3": "Tu peux aller voir ailleurs si j’y suis ?\n$Si tu refuses, je m’autorise à faire valoir mes droits de légitime défense, je te préviens !", + "4": "Désolé, mais si tu refuses de partir, on sera obligés de t’y forcer, et ça sera pas joli joli.", + "4_female": "Désolé, mais si tu refuses de partir, on sera obligés de t’y forcer, et ça sera pas joli joli.", + "5": "Quoi ? Toi aussi, t’es venu me casser les pieds ? C’est vraiment pas ma journée…", + "5_female": "Quoi ? Toi aussi, t’es venue me casser les pieds ? C’est vraiment pas ma journée…" + }, + "victory": { + "1": "Comment c'est ça peut être moi qui voit les étoiles ?!", + "2": "T’en as dans le ventre.\n$T’as peut-être ce qu’il faut pour te faire une place dans la constellation de la Team Star.", + "3": "Ma défense était pourtant bonne…\nMais c’était pas assez visiblement !", + "4": "Ha… hasta la vistar… ☆", + "5": "J’aurais jamais cru qu’être Sbire de la Team Star serait un tel fadeau…" + } + }, + "giacomo": { + "encounter": { + "1": "Tu dois vraiment pas tenir à ta life pour défier la Team Star comme ça !", + "2": "Tends un peu l’oreille… Tu l’entends ?\nC’est ton requiem !" + }, + "victory": { + "1": "Pfff, quelle ironie, franchement…", + "2": "J’pensais pas jouer le refrain de ma défaite…" + } + }, + "mela": { + "encounter": { + "1": "Alors, c’est toi le guedin qu’ose nous défier ?\nSois prêt pour ta raclée.", + "1_female": "Alors, c’est toi la guedin qu’ose nous défier ?\nSois prête pour ta raclée.", + "2": "Y a pas à dire, t’es bien une tête brûlée !\nMais fais gaffe, j’en ai aussi sous l’capot !" + }, + "victory": { + "1": "Quoi, c’est comme ça qu’ça finit ?\nPfff… J’ai la haine…", + "2": "J’voulais tout bruler… Mais j’me suis juste consumée.\nY reste plus rien." + } + }, + "atticus": { + "encounter": { + "1": "T’as vraiment du cran de venir provoquer la Team Star.\nDestinée fatale - Au poison succombera - L’ennemi juré.", + "1_female": "T’as vraiment du cran de venir provoquer la Team Star.\nDestinée fatale - Au poison succombera - L’ennemie jurée.", + "2": "Vive expectative - Respect et adversité - Combat au sommet." + }, + "victory": { + "1": "Pardon, mes amis…", + "2": "Ta victoire n’évoque en moi ni rancune ni douleur.\nMon âme est en paix et j’accepte ma défaite." + } + }, + "ortega": { + "encounter": { + "1": "J’vais bien m’occuper de toi, alors viens pas pleurer si tu perds.", + "2": "T’as beau avoir l’air sûr de toi, aujourd’hui, c’est moi qui vais gagner. Je te le garantis !", + "2_female": "T’as beau avoir l’air sûr de toi, aujourd’hui, c’est moi qui vais gagner. Je te le garantis !" + }, + "victory": { + "1": "Hein ? J’ai perdu ? Mais pourquoi ?!\nPourquoi, pourquoi, pourquoi, POURQUOI ?!", + "2": "Mais pourquoi ça fonctionne pas ?!" + } + }, + "eri": { + "encounter": { + "1": "J’ignore tes intentions, mais mon rôle est d’anéantir quiconque s’attaque à la Team Star !", + "2": "Si on m’attaque, je riposte ! Nous verrons bien qui de nous deux restera debout à la fin !" + }, + "victory": { + "1": "Les amis…\nJe suis désolée…", + "2": "J’ai donné mon maximum… et pourtant…\nÇa n’a pas suffi… J’ai échoué…" + } + }, "rocket_boss_giovanni_1": { "encounter": { "1": "Bien. Je dois admettre que je suis impressionné de te voir ici !" @@ -499,6 +575,28 @@ "1": "Les ignorants sans aucune vision n’auront donc de cesse de souiller ce monde." } }, + "star_boss_penny_1": { + "encounter": { + "1": "Je suis la Big Boss de la Team Star, Cassiopée…\n$Incline-toi devant la toute-puissance de la Big Boss !!!" + }, + "victory": { + "1": "… … …" + }, + "defeat": { + "1": "Hé…" + } + }, + "star_boss_penny_2": { + "encounter": { + "1": "Le code d’honneur de la Team Star exige que nous donnions le maximum en combat !\n$Par le pouvoir de l’Évolition, on va te réduire en poussière d’étoiles !" + }, + "victory": { + "1": "… Tout est fini" + }, + "defeat": { + "1": "Tu es redoutable.\nPas étonnant que les boss de la Team aient perdu contre toi." + } + }, "brock": { "encounter": { "1": "Mon expertise des types Roche va te mettre au sol ! En garde !", diff --git a/src/locales/fr/move.json b/src/locales/fr/move.json index da42f188a80..6fb3cb73385 100644 --- a/src/locales/fr/move.json +++ b/src/locales/fr/move.json @@ -3129,7 +3129,7 @@ }, "auraWheel": { "name": "Roue Libre", - "effect": "Inflige et change en type Ténèbres" + "effect": "Le Pokémon libère l’énergie stockée dans ses joues pour attaquer et augmenter sa Vitesse. Le type de cette capacité change en fonction de la forme du lanceur." }, "breakingSwipe": { "name": "Abattage", diff --git a/src/locales/fr/pokemon-form.json b/src/locales/fr/pokemon-form.json index 44f2bcecf2c..b1201ae0dc9 100644 --- a/src/locales/fr/pokemon-form.json +++ b/src/locales/fr/pokemon-form.json @@ -1,4 +1,5 @@ { + "pikachu": "Normal", "pikachuCosplay": "Cosplayeur", "pikachuCoolCosplay": "Cosplay Rockeur", "pikachuBeautyCosplay": "Cosplay Lady", @@ -6,7 +7,9 @@ "pikachuSmartCosplay": "Cosplay Docteur", "pikachuToughCosplay": "Cosplay Catcheur", "pikachuPartner": "Partenaire", + "eevee": "Normal", "eeveePartner": "Partenaire", + "pichu": "Normal", "pichuSpiky": "Troizépi", "unownA": "A", "unownB": "B", @@ -36,36 +39,65 @@ "unownZ": "Z", "unownExclamation": "!", "unownQuestion": "?", + "castform": "Normal Form", "castformSunny": "Solaire", "castformRainy": "Eau de Pluie", "castformSnowy": "Blizzard", "deoxysNormal": "Normal", + "deoxysAttack": "Attaque", + "deoxysDefense": "Défense", + "deoxysSpeed": "Vitesse", "burmyPlant": "Plante", "burmySandy": "Sable", "burmyTrash": "Déchet", + "cherubiOvercast": "Couvert", + "cherubiSunshine": "Ensoleillé", "shellosEast": "Orient", "shellosWest": "Occident", + "rotom": "Normal", "rotomHeat": "Chaleur", "rotomWash": "Lavage", "rotomFrost": "Froid", "rotomFan": "Hélice", "rotomMow": "Tonte", + "dialga": "Normal", + "dialgaOrigin": "Originel", + "palkia": "Normal", + "palkiaOrigin": "Originel", "giratinaAltered": "Alternatif", + "giratinaOrigin": "Originel", "shayminLand": "Terrestre", + "shayminSky": "Céleste", "basculinRedStriped": "Motif Rouge", "basculinBlueStriped": "Motif Bleu", "basculinWhiteStriped": "Motif Blanc", + "darumaka": "Mode Normal", + "darumakaZen": "Mode Transe", "deerlingSpring": "Printemps", "deerlingSummer": "Été", "deerlingAutumn": "Automne", "deerlingWinter": "Hiver", "tornadusIncarnate": "Avatar", + "tornadusTherian": "Totémique", "thundurusIncarnate": "Avatar", + "thundurusTherian": "Totémique", "landorusIncarnate": "Avatar", + "landorusTherian": "Totémique", + "kyurem": "Normal", + "kyuremBlack": "Noir", + "kyuremWhite": "Blanc", "keldeoOrdinary": "Normal", + "keldeoResolute": "Décidé", "meloettaAria": "Chant", "meloettaPirouette": "Danse", + "genesect": "Normal", + "genesectShock": "Module Choc", + "genesectBurn": "Module Pyro", + "genesectChill": "Module Cryo", + "genesectDouse": "Module Aqua", + "froakie": "Normal", "froakieBattleBond": "Synergie", + "froakieAsh": "Sachanobi", "scatterbugMeadow": "Floraison", "scatterbugIcySnow": "Blizzard", "scatterbugPolar": "Banquise", @@ -91,6 +123,7 @@ "flabebeOrange": "Orange", "flabebeBlue": "Bleu", "flabebeWhite": "Blanc", + "furfrou": "Sauvage", "furfrouHeart": "Cœur", "furfrouStar": "Étoile", "furfrouDiamond": "Diamant", @@ -100,21 +133,52 @@ "furfrouLaReine": "Reine", "furfrouKabuki": "Kabuki", "furfrouPharaoh": "Pharaon", - "pumpkabooSmall": "Mini", - "pumpkabooLarge": "Maxi", - "pumpkabooSuper": "Ultra", + "espurrMale": "Mâle", + "espurrFemale": "Femelle", + "honedgeShiled": "Parade", + "honedgeBlade": "Assaut", + "pumpkaboo": "Taille Normale", + "pumpkabooSmall": "Taille Mini", + "pumpkabooLarge": "Taille Maxi", + "pumpkabooSuper": "Taille Ultra", "xerneasNeutral": "Paisible", - "xerneasActive": "Déchaîné", + "xerneasActive": "Déchainé", "zygarde50": "Forme 50%", "zygarde10": "Forme 10%", "zygarde50Pc": "Rassemblement Forme 50%", "zygarde10Pc": "Rassemblement Forme 10%", + "hoopa": "Enchainé", + "hoopaUnbound": "Déchainé", "zygardeComplete": "Parfait", "oricorioBaile": "Flamenco", "oricorioPompom": "Pom-Pom", "oricorioPau": "Hula", "oricorioSensu": "Buyō", + "rockruff": "Normal", "rockruffOwnTempo": "Tempo Perso", + "rockruffMidday": "Diurne", + "rockruffMidnight": "Nocturne", + "rockruffDusk": "Crépusculaire", + "wishiwashi": "Solitaire", + "wishiwashiSchool": "Banc", + "typeNullNormal": "Type: Normal", + "typeNullFighting": "Type: Combat", + "typeNullFlying": "Type: Vol", + "typeNullPoison": "Type: Poison", + "typeNullGround": "Type: Sol", + "typeNullRock": "Type: Roche", + "typeNullBug": "Type: Insecte", + "typeNullGhost": "Type: Spectre", + "typeNullSteel": "Type: Acier", + "typeNullFire": "Type: Feu", + "typeNullWater": "Type: Eau", + "typeNullGrass": "Type: Plante", + "typeNullElectric": "Type: Électrik", + "typeNullPsychic": "Type: Psy", + "typeNullIce": "Type: Glace", + "typeNullDragon": "Type: Dragon", + "typeNullDark": "Type: Ténèbres", + "typeNullFairy": "Type: Fée", "miniorRedMeteor": "Météore Rouge", "miniorOrangeMeteor": "Météore Orange", "miniorYellowMeteor": "Météore Jaune", @@ -131,25 +195,66 @@ "miniorViolet": "Violet", "mimikyuDisguised": "Déguisé", "mimikyuBusted": "Démasqué", + "necrozma": "Normal", + "necrozmaDuskMane": "Crinière du Couchant", + "necrozmaDawnWings": "Ailes de l’Aurore", + "necrozmaUltra": "Ultra", + "magearna": "Normal", "magearnaOriginal": "Couleur du Passé", + "marshadow": "Normal", "marshadowZenith": "Zénith", + "cramorant": "Normal", + "cramorantGulping": "Gobe-Tout", + "cramorantGorging": "Gobe-Chu", + "toxelAmped": "Aigu", + "toxelLowkey": "Grave", "sinisteaPhony": "Contrefaçon", "sinisteaAntique": "Authentique", + "milceryVanillaCream": "Lait Vanille", + "milceryRubyCream": "Lait Ruby", + "milceryMatchaCream": "Lait Matcha", + "milceryMintCream": "Lait Menthe", + "milceryLemonCream": "Lait Citron", + "milcerySaltedCream": "Lait Salé", + "milceryRubySwirl": "Mélange Ruby", + "milceryCaramelSwirl": "Mélange Caramel", + "milceryRainbowSwirl": "Mélange Tricolore", + "eiscue": "Tête de Gel", "eiscueNoIce": "Tête Dégel", "indeedeeMale": "Mâle", "indeedeeFemale": "Femelle", "morpekoFullBelly": "Rassasié", + "morpekoHangry": "Affamé", "zacianHeroOfManyBattles": "Héros Aguerri", + "zacianCrowned": "Épée Suprême", "zamazentaHeroOfManyBattles": "Héros Aguerri", + "zamazentaCrowned": "Bouclier Suprême", + "kubfuSingleStrike": "Poing Final", + "kubfuRapidStrike": "Mille Poings", + "zarude": "Normal", "zarudeDada": "Papa", + "calyrex": "Normal", + "calyrexIce": "Cavalier du Froid", + "calyrexShadow": "Cavalier d’Effroi", + "basculinMale": "Mâle", + "basculinFemale": "Femelle", "enamorusIncarnate": "Avatar", + "enamorusTherian": "Totémique", + "lechonkMale": "Mâle", + "lechonkFemale": "Femelle", + "tandemausFour": "Famille de Quatre", + "tandemausThree": "Famille de Trois", "squawkabillyGreenPlumage": "Plumage Vert", "squawkabillyBluePlumage": "Plumage Bleu", "squawkabillyYellowPlumage": "Plumage Jaune", "squawkabillyWhitePlumage": "Plumage Blanc", + "finizenZero": "Ordinaire", + "finizenHero": "Super", "tatsugiriCurly": "Courbé", "tatsugiriDroopy": "Affalé", "tatsugiriStretchy": "Raide", + "dunsparceTwo": "Double", + "dunsparceThree": "Triple", "gimmighoulChest": "Coffre", "gimmighoulRoaming": "Marche", "koraidonApexBuild": "Final", @@ -164,7 +269,22 @@ "miraidonGlideMode": "Aérien", "poltchageistCounterfeit": "Imitation", "poltchageistArtisan": "Onéreux", + "poltchageistUnremarkable": "Médiocre", + "poltchageistMasterpiece": "Exceptionnelle", + "ogerponTealMaskTera": "Masque Turquoise", + "ogerponTealMask": "Masque Turquoise Téracristal", + "ogerponWellspringMask": "Masque du Puits", + "ogerponWellspringMaskTera": "Masque du Puits Téracristal", + "ogerponHearthflameMask": "Masque du Fourneau", + "ogerponHearthflameMaskTera": "Masque du Fourneau Téracristal", + "ogerponCornerstoneMask": "Masque de la Pierre", + "ogerponCornerstoneMaskTera": "Masque de la Pierre Téracristal", + "terpagos": "Normal", + "terpagosTerastal": "Téracristal", + "terpagosStellar": "Stellaire", + "galarDarumaka": "Mode Normal", + "galarDarumakaZen": "Mode Transe", "paldeaTaurosCombat": "Combatif", "paldeaTaurosBlaze": "Flamboyant", "paldeaTaurosAqua": "Aquatique" -} \ No newline at end of file +} diff --git a/src/locales/fr/trainer-classes.json b/src/locales/fr/trainer-classes.json index b7027cf544f..a68f766dc8b 100644 --- a/src/locales/fr/trainer-classes.json +++ b/src/locales/fr/trainer-classes.json @@ -126,5 +126,8 @@ "skull_grunts": "Sbires de la Team Skull", "macro_grunt": "Employé de Macro Cosmos", "macro_grunt_female": "Employée de Macro Cosmos", - "macro_grunts": "Employés de Macro Cosmos" + "macro_grunts": "Employés de Macro Cosmos", + "star_grunt": "Sbire de la Team Star", + "star_grunt_female": "Sbire de la Team Star", + "star_grunts": "Sbires de la Team Star" } diff --git a/src/locales/fr/trainer-names.json b/src/locales/fr/trainer-names.json index beec7e0c313..85765dbe22e 100644 --- a/src/locales/fr/trainer-names.json +++ b/src/locales/fr/trainer-names.json @@ -141,6 +141,11 @@ "faba": "Saubohne", "plumeria": "Apocyne", "oleana": "Liv", + "giacomo": "Brome", + "mela": "Meloco", + "atticus": "Erio", + "ortega": "Ortiga", + "eri": "Nèflie", "maxie": "Max", "archie": "Arthur", @@ -150,6 +155,7 @@ "lusamine": "Elsa-Mina", "guzma": "Guzma", "rose": "Shehroz", + "cassiopeia": "Pania", "blue_red_double": "Blue & Red", "red_blue_double": "Red & Blue", diff --git a/src/locales/fr/trainer-titles.json b/src/locales/fr/trainer-titles.json index 6d966bbd9ec..ceefa452881 100644 --- a/src/locales/fr/trainer-titles.json +++ b/src/locales/fr/trainer-titles.json @@ -19,6 +19,7 @@ "aether_boss": "Présidente d’Æther", "skull_boss": "Boss de la Team Skull", "macro_boss": "Président de Macro Cosmos", + "star_boss": "Leader de la Team Star", "rocket_admin": "Admin Team Rocket", "rocket_admin_female": "Admin Team Rocket", @@ -34,5 +35,6 @@ "flare_admin_female": "Manageuse de la Team Flare", "aether_admin": "Directeur d’Æther", "skull_admin": "Admin Team Skull", - "macro_admin": "Macro Cosmos" + "macro_admin": "Macro Cosmos", + "star_admin": "Boss d’équipe de la Team Star" } diff --git a/src/locales/it/ability.json b/src/locales/it/ability.json index 18eb133d824..deec995cde7 100644 --- a/src/locales/it/ability.json +++ b/src/locales/it/ability.json @@ -1237,6 +1237,6 @@ }, "poisonPuppeteer": { "name": "\tMalia Tossica", - "description": "I Pokémon avvelenati dalle mosse di Pecharunt entreranno anche in stato di confusione." + "description": "I Pokémon avvelenati dalle mosse di questo Pokémon entreranno anche in stato di confusione." } } \ No newline at end of file diff --git a/src/locales/it/move.json b/src/locales/it/move.json index f5bb1954278..ba72e86f812 100644 --- a/src/locales/it/move.json +++ b/src/locales/it/move.json @@ -3129,7 +3129,7 @@ }, "auraWheel": { "name": "Ruota d'Aura", - "effect": "Il Pokémon emette l'energia accumulata nelle guance per attaccare e aumentare la Velocità. Il tipo della mossa cambia in base alla forma assunta da Morpeko." + "effect": "Il Pokémon emette l'energia accumulata nelle guance per attaccare e aumentare la Velocità. Se usata da Morpeko, il tipo della mossa cambia in base alla forma assunta." }, "breakingSwipe": { "name": "Vastoimpatto", diff --git a/src/locales/it/pokemon-form.json b/src/locales/it/pokemon-form.json index 505173e4c8a..e1ecb708b89 100644 --- a/src/locales/it/pokemon-form.json +++ b/src/locales/it/pokemon-form.json @@ -1,4 +1,5 @@ { + "pikachu": "Normale", "pikachuCosplay": "Cosplay", "pikachuCoolCosplay": "Cosplay classe", "pikachuBeautyCosplay": "Cosplay bellezza", @@ -6,7 +7,9 @@ "pikachuSmartCosplay": "Cosplay acume", "pikachuToughCosplay": "Cosplay grinta", "pikachuPartner": "Compagno", + "eevee": "Normale", "eeveePartner": "Compagno", + "pichu": "Normale", "pichuSpiky": "Spunzorek", "unownA": "A", "unownB": "B", @@ -36,36 +39,65 @@ "unownZ": "Z", "unownExclamation": "!", "unownQuestion": "?", + "castform": "Normale", "castformSunny": "Sole", "castformRainy": "Pioggia", "castformSnowy": "Nuvola di neve", "deoxysNormal": "Normale", + "deoxysAttack": "Attacco", + "deoxysDefense": "Difesa", + "deoxysSpeed": "Velocità", "burmyPlant": "Pianta", "burmySandy": "Sabbia", "burmyTrash": "Scarti", + "cherubiOvercast": "Nuvola", + "cherubiSunshine": "Splendore", "shellosEast": "Est", "shellosWest": "Ovest", + "rotom": "Normale", "rotomHeat": "Calore", "rotomWash": "Lavaggio", "rotomFrost": "Gelo", "rotomFan": "Vortice", "rotomMow": "Taglio", + "dialga": "Normale", + "dialgaOrigin": "Originale", + "palkia": "Normale", + "palkiaOrigin": "Originale", "giratinaAltered": "Alterata", + "giratinaOrigin": "Originale", "shayminLand": "Terra", + "shayminSky": "Cielo", "basculinRedStriped": "Linearossa", "basculinBlueStriped": "Lineablu", "basculinWhiteStriped": "Lineabianca", + "darumaka": "Stato Normale", + "darumakaZen": "Stato Zen", "deerlingSpring": "Primavera", "deerlingSummer": "Estate", "deerlingAutumn": "Autunno", "deerlingWinter": "Inverno", "tornadusIncarnate": "Incarnazione", + "tornadusTherian": "Totem", "thundurusIncarnate": "Incarnazione", + "thundurusTherian": "Totem", "landorusIncarnate": "Incarnazione", + "landorusTherian": "Totem", + "kyurem": "Normale", + "kyuremBlack": "Nero", + "kyuremWhite": "Bianco", "keldeoOrdinary": "Normale", + "keldeoResolute": "Risoluta", "meloettaAria": "Canto", "meloettaPirouette": "Danza", + "genesect": "Normale", + "genesectShock": "Voltmodulo", + "genesectBurn": "Piromodulo", + "genesectChill": "Gelomodulo", + "genesectDouse": "Idromodulo", + "froakie": "Normale", "froakieBattleBond": "Morfosintonia", + "froakieAsh": "Ash", "scatterbugMeadow": "Giardinfiore", "scatterbugIcySnow": "Nevi perenni", "scatterbugPolar": "Nordico", @@ -91,6 +123,7 @@ "flabebeOrange": "Arancione", "flabebeBlue": "Blu", "flabebeWhite": "Bianco", + "furfrou": "Selvatica", "furfrouHeart": "Cuore", "furfrouStar": "Stella", "furfrouDiamond": "Diamante", @@ -100,21 +133,52 @@ "furfrouLaReine": "Regina", "furfrouKabuki": "Kabuki", "furfrouPharaoh": "Faraone", + "espurrMale": "Maschio", + "espurrFemale": "Femmina", + "honedgeShiled": "Scudo", + "honedgeBlade": "Spada", + "pumpkaboo": "Normale", "pumpkabooSmall": "Mini", "pumpkabooLarge": "Grande", "pumpkabooSuper": "Maxi", "xerneasNeutral": "Relax", "xerneasActive": "Attivo", - "zygarde50": "Forma 50%", - "zygarde10": "Forma 10%", - "zygarde50Pc": "Forma 50% Sciamefusione", - "zygarde10Pc": "Forma 10% Sciamefusione", - "zygardeComplete": "Forma perfetta", + "zygarde50": "50%", + "zygarde10": "10%", + "zygarde50Pc": "50% Sciamefusione", + "zygarde10Pc": "10% Sciamefusione", + "zygardeComplete": "perfetta", + "hoopa": "Vincolato", + "hoopaUnbound": "Libero", "oricorioBaile": "Flamenco", "oricorioPompom": "Cheerdance", "oricorioPau": "Hula", "oricorioSensu": "Buyō", + "rockruff": "Normale", "rockruffOwnTempo": "Mentelocale", + "rockruffMidday": "Giorno", + "rockruffMidnight": "Notte", + "rockruffDusk": "Crepuscolo", + "wishiwashi": "Individuale", + "wishiwashiSchool": "Banco", + "typeNullNormal": "Tipo Normale", + "typeNullFighting": "Tipo Lotta", + "typeNullFlying": "Tipo Volante", + "typeNullPoison": "Tipo Veleno", + "typeNullGround": "Tipo Terra", + "typeNullRock": "Tipo Roccia", + "typeNullBug": "Tipo Coleottero", + "typeNullGhost": "Tipo Spettro", + "typeNullSteel": "Tipo Acciaio", + "typeNullFire": "Tipo Fuoco", + "typeNullWater": "Tipo Acqua", + "typeNullGrass": "Tipo Erba", + "typeNullElectric": "Tipo Elettro", + "typeNullPsychic": "Tipo Psico", + "typeNullIce": "Tipo Ghiaccio", + "typeNullDragon": "Tipo Drago", + "typeNullDark": "Tipo Buio", + "typeNullFairy": "Tipo Folletto", "miniorRedMeteor": "Nucleo Rosso", "miniorOrangeMeteor": "Nucleo Arancione", "miniorYellowMeteor": "Nucleo Giallo", @@ -131,25 +195,66 @@ "miniorViolet": "Violetto", "mimikyuDisguised": "Mascherata", "mimikyuBusted": "Smascherata", + "necrozma": "Normale", + "necrozmaDuskMane": "Criniera del Vespro", + "necrozmaDawnWings": "Ali dell'Aurora", + "necrozmaUltra": "Ultra", + "magearna": "Normale", "magearnaOriginal": "Colore Antico", + "marshadow": "Normale", "marshadowZenith": "Zenith", + "cramorant": "Normale", + "cramorantGulping": "Inghiottitutto", + "cramorantGorging": "Inghiottintero", + "toxelAmped": "Melodia", + "toxelLowkey": "Basso", "sinisteaPhony": "Contraffatta", "sinisteaAntique": "Autentica", + "milceryVanillaCream": "Lattevaniglia", + "milceryRubyCream": "Latterosa", + "milceryMatchaCream": "Lattematcha", + "milceryMintCream": "Lattementa", + "milceryLemonCream": "Lattelimone", + "milcerySaltedCream": "Lattesale", + "milceryRubySwirl": "Rosamix", + "milceryCaramelSwirl": "Caramelmix", + "milceryRainbowSwirl": "Triplomix", + "eiscue": "Gelofaccia", "eiscueNoIce": "Liquefaccia", "indeedeeMale": "Maschio", "indeedeeFemale": "Femmina", "morpekoFullBelly": "Panciapiena", + "morpekoHangry": "Panciavuota", "zacianHeroOfManyBattles": "Eroe di Mille Lotte", + "zacianCrowned": "Re delle Spade", "zamazentaHeroOfManyBattles": "Eroe di Mille Lotte", + "zamazentaCrowned": "Re degli Scudi", + "kubfuSingleStrike": "Singolcolpo", + "kubfuRapidStrike": "Pluricolpo", + "zarude": "Normale", "zarudeDada": "Papà", + "calyrex": "Normale", + "calyrexIce": "Cavaliere Glaciale", + "calyrexShadow": "Cavaliere Spettrale", + "basculinMale": "Maschio", + "basculinFemale": "Femmina", "enamorusIncarnate": "Incarnazione", + "enamorusTherian": "Totem", + "lechonkMale": "Maschio", + "lechonkFemale": "Femmina", + "tandemausFour": "Quadrifamiglia", + "tandemausThree": "Trifamiglia", "squawkabillyGreenPlumage": "Piume Verdi", "squawkabillyBluePlumage": "Piume Azzurre", "squawkabillyYellowPlumage": "Piume Gialle", "squawkabillyWhitePlumage": "Piume Bianche", + "finizenZero": "Ingenua", + "finizenHero": "Possente", "tatsugiriCurly": "Arcuata", "tatsugiriDroopy": "Adagiata", "tatsugiriStretchy": "Tesa", + "dunsparceTwo": "Bimetamero", + "dunsparceThree": "Trimetamero", "gimmighoulChest": "Scrigno", "gimmighoulRoaming": "Ambulante", "koraidonApexBuild": "Foggia Integrale", @@ -164,7 +269,22 @@ "miraidonGlideMode": "Assetto Planata", "poltchageistCounterfeit": "Taroccata", "poltchageistArtisan": "Pregiata", + "poltchageistUnremarkable": "Dozzinale", + "poltchageistMasterpiece": "Eccezionale", + "ogerponTealMask": "Maschera Turchese", + "ogerponTealMaskTera": "Maschera Turchese Teracristal", + "ogerponWellspringMask": "Maschera Pozzo", + "ogerponWellspringMaskTera": "Maschera Pozzo Teracristal", + "ogerponHearthflameMask": "Maschera Focolare", + "ogerponHearthflameMaskTera": "Maschera Focolare Teracristal", + "ogerponCornerstoneMask": "Maschera Fondamenta", + "ogerponCornerstoneMaskTera": "Maschera Fondamenta Teracristal", + "terpagos": "Normale", + "terpagosTerastal": "Teracristal", + "terpagosStellar": "Astrale", + "galarDarumaka": "Normale", + "galarDarumakaZen": "Stato Zen", "paldeaTaurosCombat": "Combattiva", "paldeaTaurosBlaze": "Infuocata", "paldeaTaurosAqua": "Acquatica" -} \ No newline at end of file +} diff --git a/src/locales/it/trainer-classes.json b/src/locales/it/trainer-classes.json index 205a7c59d42..a613e34b39b 100644 --- a/src/locales/it/trainer-classes.json +++ b/src/locales/it/trainer-classes.json @@ -126,5 +126,8 @@ "skull_grunts": "Reclute Team Skull", "macro_grunt": "Impiegato Macro Cosmos", "macro_grunt_female": "Impiegata Macro Cosmos", - "macro_grunts": "Impiegati Macro Cosmos" + "macro_grunts": "Impiegati Macro Cosmos", + "star_grunt": "Recluta Team Star", + "star_grunt_female": "Recluta Team Star", + "star_grunts": "Reclute Team Star" } diff --git a/src/locales/it/trainer-names.json b/src/locales/it/trainer-names.json index 6d1373c0bb3..78e76b8434c 100644 --- a/src/locales/it/trainer-names.json +++ b/src/locales/it/trainer-names.json @@ -139,6 +139,13 @@ "xerosic": "Xante", "bryony": "Bromelia", "faba": "Vicio", + "plumeria": "Plumeria", + "oleana": "Olive", + "giacomo": "Romelio", + "mela": "Pruna", + "atticus": "Henzo", + "ortega": "Ortiz", + "eri": "Nespera", "maxie": "Max", "archie": "Ivan", @@ -147,6 +154,9 @@ "lysandre": "Elisio", "lusamine": "Samina", "guzma": "Guzman", + "rose": "Rose", + "cassiopeia": "Penny", + "blue_red_double": "Blu & Rosso", "red_blue_double": "Rosso & Blu", "tate_liza_double": "Tell & Pat", diff --git a/src/locales/it/trainer-titles.json b/src/locales/it/trainer-titles.json index eff152795cd..8f28efab45d 100644 --- a/src/locales/it/trainer-titles.json +++ b/src/locales/it/trainer-titles.json @@ -19,6 +19,7 @@ "aether_boss": "Direttrice Æther", "skull_boss": "Capo Team Skull", "macro_boss": "Presidente Macro Cosmos", + "star_boss": "Arcicapo Team Star", "rocket_admin": "Tenente Team Rocket", "rocket_admin_female": "Tenente Team Rocket", @@ -34,6 +35,7 @@ "flare_admin_female": "Ufficiale Team Flare", "aether_admin": "Capo Filiale Æther", "skull_admin": "Ufficiale Team Skull", - "macro_admin": "Vicepresidente Macro Cosmos" + "macro_admin": "Vicepresidente Macro Cosmos", + "star_admin": "Capobanda Team Star" } diff --git a/src/locales/ja/ability.json b/src/locales/ja/ability.json index c44eeb06234..c7828d89c75 100644 --- a/src/locales/ja/ability.json +++ b/src/locales/ja/ability.json @@ -1237,6 +1237,6 @@ }, "poisonPuppeteer": { "name": "どくくぐつ", - "description": "モモワロウの 技によって どく状態に なった 相手は こんらん状態にも なってしまう。" + "description": "このポケモンの 技によって どく状態に なった 相手は こんらん状態にも なってしまう。" } } diff --git a/src/locales/ja/bgm-name.json b/src/locales/ja/bgm-name.json index fc3d4c0fdd2..e177d1bddfb 100644 --- a/src/locales/ja/bgm-name.json +++ b/src/locales/ja/bgm-name.json @@ -83,9 +83,11 @@ "battle_aether_grunt": "SM 戦闘!エーテル財団トレーナー", "battle_skull_grunt": "SM 戦闘!スカル団", "battle_macro_grunt": "SWSH 戦闘!トレーナー", + "battle_star_grunt": "SV 戦闘!スター団", "battle_galactic_admin": "BDSP 戦闘!ギンガ団幹部", "battle_skull_admin": "SM 戦闘!スカル団幹部", "battle_oleana": "SWSH 戦闘!オリーヴ", + "battle_star_admin": "SV 戦闘!スター団ボス", "battle_rocket_boss": "USUM 戦闘!レインボーロケット団ボス", "battle_aqua_magma_boss": "ORAS 戦闘!アクア団・マグマ団のリーダー", "battle_galactic_boss": "BDSP 戦闘!ギンガ団ボス", @@ -94,6 +96,7 @@ "battle_aether_boss": "SM 戦闘!ルザミーネ", "battle_skull_boss": "SM 戦闘!スカル団ボス", "battle_macro_boss": "SWSH 戦闘!ローズ", + "battle_star_boss": "SV 戦闘!カシオペア", "abyss": "ポケダン空 やみのかこう", "badlands": "ポケダン空 こかつのたに", @@ -108,17 +111,17 @@ "forest": "ポケダン空 くろのもり", "grass": "ポケダン空 リンゴのもり", "graveyard": "ポケダン空 しんぴのもり", - "ice_cave": "ポケダン空 だいひょうざん", + "ice_cave": "Firel - -50°C", "island": "ポケダン空 えんがんのいわば", "jungle": "Lmz - Jungle(ジャングル)", "laboratory": "Firel - Laboratory(ラボラトリー)", - "lake": "ポケダン空 すいしょうのどうくつ", + "lake": "Lmz - Lake(湖)", "meadow": "ポケダン空 そらのいただき(もり)", "metropolis": "Firel - Metropolis(大都市)", "mountain": "ポケダン空 ツノやま", - "plains": "ポケダン空 そらのいただき(そうげん)", - "power_plant": "ポケダン空 エレキへいげん", - "ruins": "ポケダン空 ふういんのいわば", + "plains": "Firel - Route 888(888ばんどうろ)", + "power_plant": "Firel - The Klink(ザ・ギアル)", + "ruins": "Lmz - Ancient Ruins", "sea": "Andr06 - Marine Mystique(海の神秘性)", "seabed": "Firel - Seabed(海底)", "slum": "Andr06 - Sneaky Snom(ずるいユキハミ)", @@ -128,7 +131,7 @@ "tall_grass": "ポケダン空 のうむのもり", "temple": "ポケダン空 ばんにんのどうくつ", "town": "ポケダン空 ランダムダンジョン3", - "volcano": "ポケダン空 ねっすいのどうくつ", + "volcano": "Firel - Twisturn Volcano(曲がる折れる火山)", "wasteland": "ポケダン空 まぼろしのだいち", "encounter_ace_trainer": "BW 視線!エリートトレーナー", "encounter_backpacker": "BW 視線!バックパッカー", diff --git a/src/locales/ja/dialogue.json b/src/locales/ja/dialogue.json index 24cd19b6ffc..9ba82ac54de 100644 --- a/src/locales/ja/dialogue.json +++ b/src/locales/ja/dialogue.json @@ -764,12 +764,16 @@ "1": "不審者を 追い払って\nたんまり ボーナス いただくぜ!", "2": "ジャマは 許しません!\n$マクロコスモスの さまざまな\n関連会社を 守るためにも 追い返します!", "2_female": "ジャマは 許しません!\n$マクロコスモスの さまざまな\n関連会社を 守るためにも 追い返します!", - "3": "マクロコスモス生命です!\n保険に 入っていますか?" + "3": "マクロコスモス生命です!\n保険に 入っていますか?", + "4": "見つけた! では 勝負だ!", + "5": "オリーヴさまに 怒られたくないから あきらめない!" }, "victory": { "1": "ボーナスが……\n夢の マイホームが……", "2": "負けたからには\n素直に 引き下がりましょう。\n$だが ローズ委員長の\nジャマは しないでくださいよ。", - "3": "マクロコスモス生命の 仕事なら\n誰にも 負けないのに…" + "3": "マクロコスモス生命の 仕事なら\n誰にも 負けないのに…", + "4": "ポケモンを 入れ替えたのに……", + "5": "かくれんぼも ダメ!\n勝負も ダメ! 逃げるしかない!" } }, "oleana": { @@ -785,6 +789,73 @@ "3": "まあ 生意気!\nオリーヴの パートナーを キズつけるなんて!" } }, + "star_grunt": { + "encounter": { + "1": "We're Team Star, kid. We burn so bright, it hurts to look at us!", + "2": "We'll come at you full force - Hasta la vistaaar! ★", + "3": "If you don't clear out real quick-like, I'll hafta come at you in self-defense. You get me?", + "4": "Sorry, but if you don't turn yourself around here, amigo, we'll have to send you packing!", + "4_female": "Sorry, but if you don't turn yourself around here, amiga, we'll have to send you packing!", + "5": "Oh great. Here comes another rando to ruin my day." + }, + "victory": { + "1": "How come I'M the one seeing stars?!", + "2": "You're scary, kid. If you joined Team Star, you'd be looking down from the top in no time!", + "3": "I defended myself all right... But it wasn't enough!", + "4": "H-hasta la vistar... ★", + "5": "I didn't think grunt work for Team Star newbies would be this much of a chore..." + } + }, + "giacomo": { + "encounter": { + "1": "You don't really think things through, do ya? Declarin' war on Team Star is a real bad move.", + "2": "I'll play you a sick requiem as you crash and burn. Let's get this party staaarteeed!" + }, + "victory": { + "1": "Guess that's that...", + "2": "You turned my melody into a threnody..." + } + }, + "mela": { + "encounter": { + "1": "So you're the dope who picked a fight with Team Star... Prepare to get messed up.", + "2": "All riiight, BRING IT! I'll blow everythin' sky high!" + }, + "victory": { + "1": "Ugh. Is this really how it's gonna end? What a hassle...", + "2": "I burned through everythin' I had...and now I've sputtered out." + } + }, + "atticus": { + "encounter": { + "1": "You have some nerve baring your fangs at Team Star. Come, then, villainous wretch!", + "2": "Be warned—I shall spare thee no mercy! En garde!" + }, + "victory": { + "1": "Forgive me, my friends...", + "2": "You have utterly bested me. But thy victory stir'd no bitterness within me—such was its brilliance." + } + }, + "ortega": { + "encounter": { + "1": "I promise I'll play nice, so don't blame me when this battle sends you blubbering back home!", + "2": "I'll wipe that smug look off your face for sure! You're going down!" + }, + "victory": { + "1": "Ugh! How could I LOSE! What the HECK!", + "2": "Arrrrgggh! That strength of yours is SO. NOT. FAIR." + } + }, + "eri": { + "encounter": { + "1": "Doesn't matter who you are. I'll bury anyone who tries to take down Team Star!", + "2": "I give as good as I get—that's a promise! We'll see who's left standing in the end!" + }, + "victory": { + "1": "I'm so sorry, everyone...", + "2": "I gave it my all, but it wasn't enough—I wasn't enough..." + } + }, "rocket_boss_giovanni_1": { "encounter": { "1": "こんな所 まで よく来た…" @@ -985,6 +1056,28 @@ "1": "I suppose it must seem that I am doing something terrible. I don't expect you to understand.\n$But I must provide the Galar region with limitless energy to ensure everlasting prosperity." } }, + "star_boss_penny_1": { + "encounter": { + "1": "I'm the big boss of Team Star. The name's Cassiopeia. \n$Now, bow down before the overwhelming might of Team Star's founder!" + }, + "victory": { + "1": "... ... .." + }, + "defeat": { + "1": "Heh..." + } + }, + "star_boss_penny_2": { + "encounter": { + "1": "I won't hold back in this battle! I'll stay true to Team Star's code! \n$My Veevee power will crush you into stardust!" + }, + "victory": { + "1": "...It's all over now." + }, + "defeat": { + "1": "I can't fault you on your battle skills at all... Considering how the bosses fell at your hands." + } + }, "brock": { "encounter": { "1": "My expertise on Rock-type Pokémon will take you down! Come on!", diff --git a/src/locales/ja/move.json b/src/locales/ja/move.json index 2e602407902..15c63a81e36 100644 --- a/src/locales/ja/move.json +++ b/src/locales/ja/move.json @@ -3129,7 +3129,7 @@ }, "auraWheel": { "name": "オーラぐるま", - "effect": "ほほぶくろに 溜めた エネルギーで 攻撃し 自分の 素早さを あげる。 モルペコの 姿で タイプが 変わる。" + "effect": "ほほぶくろに 溜めた エネルギーで 攻撃し 自分の 素早さを あげる。 モルペコが この技を 使う場合 姿で 技の タイプが 変わる。" }, "breakingSwipe": { "name": "ワイドブレイカー", diff --git a/src/locales/ja/pokemon-form.json b/src/locales/ja/pokemon-form.json index 76124904456..8ef61ec2c14 100644 --- a/src/locales/ja/pokemon-form.json +++ b/src/locales/ja/pokemon-form.json @@ -1,4 +1,5 @@ { + "pikachu": "通常", "pikachuCosplay": "コスプレ", "pikachuCoolCosplay": "クールなコスプレ", "pikachuBeautyCosplay": "きれいなコスプレ", @@ -6,7 +7,9 @@ "pikachuSmartCosplay": "かしこいコスプレ", "pikachuToughCosplay": "パワフルなコスプレ", "pikachuPartner": "パートナー", + "eevee": "通常", "eeveePartner": "パートナー", + "pichu": "通常", "pichuSpiky": "ギザみみ", "unownA": "A", "unownB": "B", @@ -36,36 +39,65 @@ "unownZ": "Z", "unownExclamation": "!", "unownQuestion": "?", + "castform": "ポワルンのすがた", "castformSunny": "たいよう", "castformRainy": "あまみず", "castformSnowy": "ゆきぐも", - "deoxysNormal": "ノーマル", - "burmyPlant": "くさき", - "burmySandy": "すなち", - "burmyTrash": "ゴミ", + "deoxysNormal": "ノーマルフォルム", + "deoxysAttack": "アタック", + "deoxysDefense": "ディフェンス", + "deoxysSpeed": "スピード", + "burmyPlant": "くさきのミノ", + "burmySandy": "すなちのミノ", + "burmyTrash": "ゴミのミノ", + "cherubiOvercast": "ネガフォルム", + "cherubiSunshine": "ポジフォルム", "shellosEast": "ひがし", "shellosWest": "にし", + "rotom": "通常", "rotomHeat": "ヒート", "rotomWash": "ウォッシュ", "rotomFrost": "フロスト", "rotomFan": "スピン", "rotomMow": "カット", - "giratinaAltered": "アナザー", - "shayminLand": "ランド", + "dialga": "通常", + "dialgaOrigin": "オリジンフォルム", + "palkia": "通常", + "palkiaOrigin": "オリジンフォルム", + "giratinaAltered": "アナザーフォルム", + "giratinaOrigin": "オリジンフォルム", + "shayminLand": "ランドフォルム", + "shayminSky": "スカイフォルム", "basculinRedStriped": "赤筋", "basculinBlueStriped": "青筋", "basculinWhiteStriped": "白筋", + "darumaka": "ノーマルモード", + "darumakaZen": "ダルマモード", "deerlingSpring": "春", "deerlingSummer": "夏", "deerlingAutumn": "秋", "deerlingWinter": "冬", - "tornadusIncarnate": "けしん", - "thundurusIncarnate": "けしん", - "landorusIncarnate": "けしん", - "keldeoOrdinary": "いつも", + "tornadusIncarnate": "けしんフォルム", + "tornadusTherian": "れいじゅうフォルム", + "thundurusIncarnate": "けしんフォルム", + "thundurusTherian": "れいじゅうフォルム", + "landorusIncarnate": "けしんフォルム", + "landorusTherian": "れいじゅうフォルム", + "kyurem": "通常", + "kyuremBlack": "ブラックキュレム", + "kyuremWhite": "ホワイトキュレム", + "keldeoOrdinary": "いつものすがた", + "keldeoResolute": "かくごのすがた", "meloettaAria": "ボイス", "meloettaPirouette": "ステップ", + "genesect": "通常", + "genesectShock": "イナズマカセット", + "genesectBurn": "ブレイズカセット", + "genesectChill": "フリーズカセット", + "genesectDouse": "アクアカセット", + "froakie": "通常", "froakieBattleBond": "きずなへんげ", + "froakieAsh": "サトシゲッコウガ", "scatterbugMeadow": "はなぞの", "scatterbugIcySnow": "ひょうせつ", "scatterbugPolar": "ゆきぐに", @@ -91,6 +123,7 @@ "flabebeOrange": "オレンジ", "flabebeBlue": "青", "flabebeWhite": "白", + "furfrou": "やせいのすがた", "furfrouHeart": "ハート", "furfrouStar": "スター", "furfrouDiamond": "ダイア", @@ -100,9 +133,14 @@ "furfrouLaReine": "クイーン", "furfrouKabuki": "カブキ", "furfrouPharaoh": "キングダム", - "pumpkabooSmall": "ちいさい", - "pumpkabooLarge": "おおきい", - "pumpkabooSuper": "とくだい", + "espurrMale": "オス", + "espurrFemale": "メス", + "honedgeShiled": "シールドフォルム", + "honedgeBlade": "ブレードフォルム", + "pumpkaboo": "ふつうのサイズ", + "pumpkabooSmall": "ちいさいサイズ", + "pumpkabooLarge": "おおきいサイズ", + "pumpkabooSuper": "とくだいサイズ", "xerneasNeutral": "リラックス", "xerneasActive": "アクティブ", "zygarde50": "50%フォルム", @@ -110,11 +148,37 @@ "zygarde50Pc": "50%フォルム スワームチェンジ", "zygarde10Pc": "10%フォルム スワームチェンジ", "zygardeComplete": "パーフェクトフォルム", + "hoopa": "いましめられしフーパ", + "hoopaUnbound": "ときはなたれしフーパ", "oricorioBaile": "めらめら", "oricorioPompom": "ぱちぱち", "oricorioPau": "ふらふら", "oricorioSensu": "まいまい", + "rockruff": "通常", "rockruffOwnTempo": "マイペース", + "rockruffMidday": "まひるのすがた", + "rockruffMidnight": "まよなかのすがた", + "rockruffDusk": "たそがれのすがた", + "wishiwashi": "たんどくのすがた", + "wishiwashiSchool": "むれたすがた", + "typeNullNormal": "タイプ:ノーマル", + "typeNullFighting": "タイプ:かくとう", + "typeNullFlying": "タイプ:ひこう", + "typeNullPoison": "タイプ:どく", + "typeNullGround": "タイプ:じめん", + "typeNullRock": "タイプ:いわ", + "typeNullBug": "タイプ:むし", + "typeNullGhost": "タイプ:ゴースト", + "typeNullSteel": "タイプ:はがね", + "typeNullFire": "タイプ:ほのお", + "typeNullWater": "タイプ:みず", + "typeNullGrass": "タイプ:くさ", + "typeNullElectric": "タイプ:でんき", + "typeNullPsychic": "タイプ:エスパー", + "typeNullIce": "タイプ:こおり", + "typeNullDragon": "タイプ:ドラゴン", + "typeNullDark": "タイプ:あく", + "typeNullFairy": "タイプ:フェアリー", "miniorRedMeteor": "赤 りゅうせい", "miniorOrangeMeteor": "オレンジ りゅうせい", "miniorYellowMeteor": "黄 りゅうせい", @@ -131,22 +195,63 @@ "miniorViolet": "紫", "mimikyuDisguised": "ばけたすがた", "mimikyuBusted": "ばれたすがた", - "magearnaOriginal": "500ねんまえ", + "necrozma": "ネクロズマ", + "necrozmaDuskMane": "たそがれのたてがみ", + "necrozmaDawnWings": "あかつきのつばさ", + "necrozmaUltra": "ウルトラネクロズマ", + "magearna": "通常", + "magearnaOriginal": "500ねんまえのいろ", + "marshadow": "通常", "marshadowZenith": "Zパワー", + "cramorant": "通常", + "cramorantGulping": "うのみのすがた", + "cramorantGorging": "まるのみのすがた", + "toxelAmped": "ハイなすがた", + "toxelLowkey": "ローなすがた", "sinisteaPhony": "がんさく", "sinisteaAntique": "しんさく", - "eiscueNoIce": "ナイスなし", + "milceryVanillaCream": "ミルキィバニラ", + "milceryRubyCream": "ミルキィルビー", + "milceryMatchaCream": "ミルキィまっちゃ", + "milceryMintCream": "ミルキィミント", + "milceryLemonCream": "ミルキィレモン", + "milcerySaltedCream": "ミルキィソルト", + "milceryRubySwirl": "ルビーミックス", + "milceryCaramelSwirl": "キャラメルミックス", + "milceryRainbowSwirl": "トリプルミックス", + "eiscue": "アイスフェイス", + "eiscueNoIce": "ナイスフェイス", "indeedeeMale": "オス", "indeedeeFemale": "メス", - "morpekoFullBelly": "まんぷく", + "morpekoFullBelly": "まんぷくもよう", + "morpekoHangry": "はらぺこもよう", "zacianHeroOfManyBattles": "れきせんのゆうしゃ", + "zacianCrowned": "けんのおう", "zamazentaHeroOfManyBattles": "れきせんのゆうしゃ", + "zamazentaCrowned": "たてのおう", + "kubfuSingleStrike": "いちげきのかた", + "kubfuRapidStrike": "れんげきのかた", + "zarude": "通常", "zarudeDada": "とうちゃん", - "enamorusIncarnate": "けしん", + "calyrex": "通常", + "calyrexIce": "はくばじょうのすがた", + "calyrexShadow": "こくばじょうのすがた", + "basculinMale": "オス", + "basculinFemale": "メス", + "enamorusIncarnate": "けしんフォルム", + "enamorusTherian": "れいじゅうフォルム", + "lechonkMale": "オス", + "lechonkFemale": "メス", + "tandemausFour": "4ひきかぞく", + "tandemausThree": "3びきかぞく", "squawkabillyGreenPlumage": "グリーンフェザー", "squawkabillyBluePlumage": "ブルーフェザー", "squawkabillyYellowPlumage": "イエローフェザー", "squawkabillyWhitePlumage": "ホワイトフェザー", + "dunsparceTwo": "ふたふしフォルム", + "dunsparceThree": "みつふしフォルム", + "finizenZero": "ナイーブフォルム", + "finizenHero": "マイティフォルム", "tatsugiriCurly": "そったすがた", "tatsugiriDroopy": "たれたすがた", "tatsugiriStretchy": "のびたすがた", @@ -164,7 +269,22 @@ "miraidonGlideMode":"グライドモード", "poltchageistCounterfeit": "マガイモノ", "poltchageistArtisan": "タカイモノ", + "poltchageistUnremarkable": "ボンサクのすがた", + "poltchageistMasterpiece": "ケッサクのすがた", + "ogerponTealMask": "みどりのめん", + "ogerponTealMaskTera": "みどりのめん テラスタル", + "ogerponWellspringMask": "いどのめん", + "ogerponWellspringMaskTera": "いどのめん テラスタル", + "ogerponHearthflameMask": "かまどのめん", + "ogerponHearthflameMaskTera": "かまどのめん テラスタル", + "ogerponCornerstoneMask": "いしずえのめん", + "ogerponCornerstoneMaskTera": "いしずえのめん テラスタル", + "terpagos": "ノーマルフォルム", + "terpagosTerastal": "テラスタルフォルム", + "terpagosStellar": "ステラフォルム", + "galarDarumaka": "ノーマルモード", + "galarDarumakaZen": "ダルマモード", "paldeaTaurosCombat": "コンバット", "paldeaTaurosBlaze": "ブレイズ", "paldeaTaurosAqua": "ウォーター" -} \ No newline at end of file +} diff --git a/src/locales/ja/trainer-classes.json b/src/locales/ja/trainer-classes.json index aba294fbbbd..a104e4e827e 100644 --- a/src/locales/ja/trainer-classes.json +++ b/src/locales/ja/trainer-classes.json @@ -126,5 +126,8 @@ "skull_grunts": "スカル団の下っ端", "macro_grunt": "マクロコスモスのトレーナ", "macro_grunt_female": "マクロコスモスのトレーナ", - "macro_grunts": "マクロコスモスのトレーナ" + "macro_grunts": "マクロコスモスのトレーナ", + "star_grunt": "スター団の下っ端", + "star_grunt_female": "スター団の下っ端", + "star_grunts": "スター団の下っ端" } diff --git a/src/locales/ja/trainer-names.json b/src/locales/ja/trainer-names.json index 70841734b5b..c152e7864cc 100644 --- a/src/locales/ja/trainer-names.json +++ b/src/locales/ja/trainer-names.json @@ -141,6 +141,11 @@ "faba": "ザオボー", "plumeria": "プルメリ", "oleana": "オリーヴ", + "giacomo": "ピーニャ", + "mela": "メロコ", + "atticus": "シュウメイ", + "ortega": "オルティガ", + "eri": "ビワ", "maxie": "マツブサ", "archie": "アオギリ", @@ -150,6 +155,7 @@ "lusamine": "ルザミーネ", "guzma": "グズマ", "rose": "ローズ", + "cassiopeia": "ボタン", "blue_red_double": "グリーンとレッド", "red_blue_double": "レッドとグリーン", diff --git a/src/locales/ja/trainer-titles.json b/src/locales/ja/trainer-titles.json index b3829c701e5..b558f7ad80c 100644 --- a/src/locales/ja/trainer-titles.json +++ b/src/locales/ja/trainer-titles.json @@ -19,6 +19,7 @@ "aether_boss": "エーテル代表", "skull_boss": "スカル団ボス", "macro_boss": "マクロコスモス社長", + "star_boss": "スター団ボス", "rocket_admin": "ロケット団幹部", "rocket_admin_female": "ロケット団幹部", @@ -34,5 +35,6 @@ "flare_admin_female": "フレア団幹部", "aether_admin": "エーテル支部長", "skull_admin": "スカル団幹部", - "macro_admin": "マクロコスモス" + "macro_admin": "マクロコスモス", + "star_admin": "スター団 組ボス" } diff --git a/src/locales/ko/ability.json b/src/locales/ko/ability.json index 420d27c6011..631a6864e85 100644 --- a/src/locales/ko/ability.json +++ b/src/locales/ko/ability.json @@ -1237,6 +1237,6 @@ }, "poisonPuppeteer": { "name": "독조종", - "description": "복숭악동의 기술에 의해 독 상태가 된 상대는 혼란 상태도 되어 버린다." + "description": "이 기술에 의해 독 상태가 된 상대는 혼란 상태도 되어 버린다." } } \ No newline at end of file diff --git a/src/locales/ko/bgm-name.json b/src/locales/ko/bgm-name.json index 5295e2d8708..f010a7ac18e 100644 --- a/src/locales/ko/bgm-name.json +++ b/src/locales/ko/bgm-name.json @@ -83,9 +83,11 @@ "battle_aether_grunt": "SM 에테르재단 배틀", "battle_skull_grunt": "SM 스컬단 배틀", "battle_macro_grunt": "SWSH 트레이너 배틀", + "battle_star_grunt": "SV 스타단 배틀", "battle_galactic_admin": "BDSP 갤럭시단 간부 배틀", "battle_skull_admin": "SM 스컬단 간부 배틀", "battle_oleana": "SWSH 올리브 배틀", + "battle_star_admin": "SV 스타단 보스 배틀", "battle_rocket_boss": "USUM 비주기 배틀", "battle_aqua_magma_boss": "ORAS 아강 & 마적 배틀", "battle_galactic_boss": "BDSP 태홍 배틀", @@ -94,6 +96,7 @@ "battle_aether_boss": "SM 루자미네 배틀", "battle_skull_boss": "SM 구즈마 배틀", "battle_macro_boss": "SWSH 로즈 배틀", + "battle_star_boss": "SV 카시오페아 배틀", "abyss": "불가사의 던전 하늘의 탐험대 어둠의 화구", "badlands": "불가사의 던전 하늘의 탐험대 불모의 계곡", "beach": "불가사의 던전 하늘의 탐험대 축축한 암반", @@ -107,17 +110,17 @@ "forest": "불가사의 던전 하늘의 탐험대 검은 숲", "grass": "불가사의 던전 하늘의 탐험대 사과의 숲", "graveyard": "불가사의 던전 하늘의 탐험대 신비의 숲", - "ice_cave": "불가사의 던전 하늘의 탐험대 광대한 얼음산", + "ice_cave": "Firel - -50°C", "island": "불가사의 던전 하늘의 탐험대 연안의 암반", - "jungle": "Lmz - Jungle", - "laboratory": "Firel - Laboratory", - "lake": "불가사의 던전 하늘의 탐험대 수정 동굴", + "jungle": "Lmz - 정글", + "laboratory": "Firel - 연구소", + "lake": "Lmz - 호수", "meadow": "불가사의 던전 하늘의 탐험대 하늘 꼭대기 숲", "metropolis": "Firel - Metropolis", "mountain": "불가사의 던전 하늘의 탐험대 뿔산", - "plains": "불가사의 던전 하늘의 탐험대 하늘 꼭대기 초원", - "power_plant": "불가사의 던전 하늘의 탐험대 일렉트릭 평원", - "ruins": "불가사의 던전 하늘의 탐험대 봉인의 암반", + "plains": "Firel - Route 888", + "power_plant": "Firel - 기어르", + "ruins": "Lmz - 고대 유적", "sea": "Andr06 - Marine Mystique", "seabed": "Firel - Seabed", "slum": "Andr06 - Sneaky Snom", @@ -127,7 +130,7 @@ "tall_grass": "불가사의 던전 하늘의 탐험대 짙은 안개의 숲", "temple": "불가사의 던전 하늘의 탐험대 파수꾼의 동굴", "town": "불가사의 던전 하늘의 탐험대 랜덤 던전 테마 3", - "volcano": "불가사의 던전 하늘의 탐험대 열수의 동굴", + "volcano": "Firel - Twisturn Volcano", "wasteland": "불가사의 던전 하늘의 탐험대 환상의 대지", "encounter_ace_trainer": "BW 눈이 마주치면 승부! (엘리트 트레이너)", "encounter_backpacker": "BW 눈이 마주치면 승부! (등산가)", diff --git a/src/locales/ko/dialogue.json b/src/locales/ko/dialogue.json index 13fcd64a8d3..407b0a1ce05 100644 --- a/src/locales/ko/dialogue.json +++ b/src/locales/ko/dialogue.json @@ -715,12 +715,16 @@ "encounter": { "1": "당신은 여기서 끝날 것 같네요!", "2": "당신은 트레이너 맞죠? 하지만 우리를 방해하는 건 용납 못 합니다!", - "3": "매크로코스모스 생명입니다! 가입하신 실비보험은 있으신가요?" + "3": "매크로코스모스 생명입니다! 가입하신 실비보험은 있으신가요?", + "4": "찾았다! 그렇다면 포켓몬 승부입니다!", + "5": "올리브님에게 혼나기 싫으니까 포기하지 않겠습니다!" }, "victory": { "1": "순순히 물러나는 것 말고는 선택지가 없군요.", "2": "용돈을 뺏기다니… 패배는 적자로 이어지는구나…", - "3": "매크로코스모스 생명에 관한 일이라면 누구에게도 지지 않을 텐데…" + "3": "매크로코스모스 생명에 관한 일이라면 누구에게도 지지 않을 텐데…", + "4": "심지어 포켓몬 교체도 했는데…", + "5": "승부도 안 되면! 도망치는 수밖에 없다!" } }, "oleana": { @@ -735,6 +739,73 @@ "3": "아아… 이 올리브님 조금 지쳤어…" } }, + "star_grunt": { + "encounter": { + "1": "우리는 우는 아이도 웃게 하는 스타단!", + "2": "멤버들을 총동원해서 공격할 테니, 수고하셨스타~! ★", + "3": "빨리 돌아가지 그래? 아니면 방어권을 행사하는 수밖에 없다고?", + "4": "미안하지만 돌아가지 않겠다면 힘으로라도 쫓아내 주겠어!", + "4_female": "미안하지만 돌아가지 않겠다면 힘으로라도 쫓아내 주겠어!", + "5": "아~ 또 사람이 와 버렸잖아." + }, + "victory": { + "1": "저 하늘의 별이 되는 건 나였네!?", + "2": "스타단에 들어가면 다들 쫄아서 꼭대기에서 군림할 수 있는 거 아니었어?", + "3": "나의 방어권이…!", + "4": "수, 수고하셨스타… ★", + "5": "스타단 신입이 이렇게 귀찮은 일일 줄이야…" + } + }, + "giacomo": { + "encounter": { + "1": "스타단에게 싸움을 걸다니, 넌 정말 겁이 없구나?", + "2": "레퀴엠을 들려줄 테니! 자! 파티를 시작하자고!" + }, + "victory": { + "1": "결국 이렇게 되는 건가…", + "2": "레퀴엠을 들은 건 내 쪽이었네." + } + }, + "mela": { + "encounter": { + "1": "…우리에게 싸움을 걸었다는 녀석이 너냐? …터뜨려 주지.", + "2": "좋아! …그럼, 한번 터뜨려 볼까!" + }, + "victory": { + "1": "이걸로 끝인 건가? …이런 이런.", + "2": "그렇게 타오르고 타오르다… 완전히 연소해 버린 건가…" + } + }, + "atticus": { + "encounter": { + "1": "스타단을 해하려 하는 괘씸한 자는 독으로 해치울 뿐!", + "2": "그럼, 진검승부를 펼쳐 봅시다!" + }, + "victory": { + "1": "동지들이여, 미안하오…", + "2": "미련 하나 남지 않을 정도로 명백한 소인의 완패였소…" + } + }, + "ortega": { + "encounter": { + "1": "잔뜩 귀여워해 줄 테니까 울며불며 돌아갈 준비나 하라고!", + "2": "어디 한번 여유롭게 굴어 보시지. 내가 이길 테니까!" + }, + "victory": { + "1": "어째서 내가 지는 건데!? 대체 왜! 어째서 진 거냐고~!!", + "2": "젠장~! 너무 강하잖아! 비겁해!" + } + }, + "eri": { + "encounter": { + "1": "어디의 누가 됐든 스타단을 노리는 자는 박살 낼 뿐!", + "2": "맞았으면 그저 맞받아칠 뿐!! 승리는 끝까지 서 있는 사람의 것이니까!!" + }, + "victory": { + "1": "얘들아… 미안해…", + "2": "열심히… 했는데… 나는 역시… 부족했어…" + } + }, "rocket_boss_giovanni_1": { "encounter": { "1": "그래서! 여기까지 오다니, 감탄이 절로 나오는군!" @@ -933,6 +1004,28 @@ "1": "너희가 보기에는 내가 끔찍한 짓을 벌이고 있는 것처럼 보이겠지? 조금도 이해가 가지 않을 거야.\n$하지만 난 가라르지방의 영원한 번영을 위해서 무한한 에너지를 가져다줘야 해." } }, + "star_boss_penny_1": { + "encounter": { + "1": "내가 바로 스타단의 진 보스, 카시오페아… \n$…진 보스의 힘 앞에 무릎 꿇게 만들어 주겠어!!" + }, + "victory": { + "1": "… … …" + }, + "defeat": { + "1": "후후…" + } + }, + "star_boss_penny_2": { + "encounter": { + "1": "승부인 이상, 봐주지 않아! 그것이 스타단의 규칙이니까! \n$브이브이 파워로 우주의 먼지로 만들어 주겠어!!" + }, + "victory": { + "1": "이걸로 진짜 끝이구나…" + }, + "defeat": { + "1": "군더더기가 없는 실력이네. 보스들이 당한 걸 생각해 보면 말이야." + } + }, "brock": { "encounter": { "1": "내 전문인 바위 타입 포켓몬으로 널 쓰러뜨려줄게! 덤벼!", diff --git a/src/locales/ko/move.json b/src/locales/ko/move.json index a06bb2b3e27..5b0d6eaeaad 100644 --- a/src/locales/ko/move.json +++ b/src/locales/ko/move.json @@ -3129,7 +3129,7 @@ }, "auraWheel": { "name": "오라휠", - "effect": "볼주머니에 저장해둔 에너지로 공격하고 자신의 스피드를 올린다. 모르페코의 모습에 따라 타입이 바뀐다." + "effect": "볼주머니에 저장해둔 에너지로 공격하고 자신의 스피드를 올린다. 모르페코가 사용할 경우 모습에 따라 타입이 바뀐다." }, "breakingSwipe": { "name": "와이드브레이커", diff --git a/src/locales/ko/pokemon-form.json b/src/locales/ko/pokemon-form.json index 885f9a9b891..dce2fcd35cf 100644 --- a/src/locales/ko/pokemon-form.json +++ b/src/locales/ko/pokemon-form.json @@ -1,4 +1,5 @@ { + "pikachu": "일반", "pikachuCosplay": "옷갈아입기", "pikachuCoolCosplay": "하드록", "pikachuBeautyCosplay": "마담", @@ -6,7 +7,9 @@ "pikachuSmartCosplay": "닥터", "pikachuToughCosplay": "마스크드", "pikachuPartner": "파트너", + "eevee": "일반", "eeveePartner": "파트너", + "pichu": "일반", "pichuSpiky": "삐쭉귀", "unownA": "A", "unownB": "B", @@ -36,36 +39,65 @@ "unownZ": "Z", "unownExclamation": "!", "unownQuestion": "?", + "castform": "평상시", "castformSunny": "태양의 모습", "castformRainy": "빗방울의 모습", "castformSnowy": "설운의 모습", "deoxysNormal": "노말폼", + "deoxysAttack": "어택폼", + "deoxysDefense": "디펜스폼", + "deoxysSpeed": "스피드폼", "burmyPlant": "초목도롱", "burmySandy": "모래땅도롱", "burmyTrash": "슈레도롱", + "cherubiOvercast": "네거폼", + "cherubiSunshine": "포지폼", "shellosEast": "동쪽바다의 모습", "shellosWest": "서쪽바다의 모습", - "rotomHeat": "히트", - "rotomWash": "워시", - "rotomFrost": "프로스트", - "rotomFan": "스핀", - "rotomMow": "커트", + "rotom": "로토무", + "rotomHeat": "히트로토무", + "rotomWash": "워시로토무", + "rotomFrost": "프로스트로토무", + "rotomFan": "스핀로토무", + "rotomMow": "커트로토무", + "dialga": "어나더폼", + "dialgaOrigin": "오리진폼", + "palkia": "어나더폼", + "palkiaOrigin": "오리진폼", "giratinaAltered": "어나더폼", + "giratinaOrigin": "오리진폼", "shayminLand": "랜드폼", + "shayminSky": "스카이폼", "basculinRedStriped": "적색근의 모습", "basculinBlueStriped": "청색근의 모습", "basculinWhiteStriped": "백색근의 모습", + "darumaka": "노말모드", + "darumakaZen": "달마모드", "deerlingSpring": "봄의 모습", "deerlingSummer": "여름의 모습", "deerlingAutumn": "가을의 모습", "deerlingWinter": "겨울의 모습", "tornadusIncarnate": "화신폼", + "tornadusTherian": "영물폼", "thundurusIncarnate": "화신폼", + "thundurusTherian": "영물폼", "landorusIncarnate": "화신폼", + "landorusTherian": "영물폼", + "kyurem": "큐레무", + "kyuremBlack": "블랙큐레무", + "kyuremWhite": "화이트큐레무", "keldeoOrdinary": "평상시 모습", + "keldeoResolute": "각오의 모습", "meloettaAria": "보이스폼", "meloettaPirouette": "스텝폼", + "genesect": "노말폼", + "genesectShock": "라이트닝폼", + "genesectBurn": "블레이즈폼", + "genesectChill": "프리즈폼", + "genesectDouse": "아쿠아폼", + "froakie": "개굴닌자", "froakieBattleBond": "유대변화", + "froakieAsh": "지우개굴닌자", "scatterbugMeadow": "화원의 모양", "scatterbugIcySnow": "빙설의 모양", "scatterbugPolar": "설국의 모양", @@ -91,6 +123,7 @@ "flabebeOrange": "오렌지색 꽃", "flabebeBlue": "파란 꽃", "flabebeWhite": "하얀 꽃", + "furfrou": "일반", "furfrouHeart": "하트컷", "furfrouStar": "스타컷", "furfrouDiamond": "다이아컷", @@ -100,6 +133,11 @@ "furfrouLaReine": "퀸컷", "furfrouKabuki": "가부키컷", "furfrouPharaoh": "킹덤컷", + "espurrMale": "수컷의 모습", + "espurrFemale": "암컷의 모습", + "honedgeShiled": "실드폼", + "honedgeBlade": "블레이드폼", + "pumpkaboo": "보통 사이즈", "pumpkabooSmall": "작은 사이즈", "pumpkabooLarge": "큰 사이즈", "pumpkabooSuper": "특대 사이즈", @@ -110,11 +148,37 @@ "zygarde50Pc": "스웜체인지 50%폼", "zygarde10Pc": "스웜체인지 10%폼", "zygardeComplete": "퍼펙트폼", + "hoopa": "굴레에 빠진 모습", + "hoopaUnbound": "굴레를 벗어난 모습", "oricorioBaile": "이글이글스타일", "oricorioPompom": "파칙파칙스타일", "oricorioPau": "훌라훌라스타일", "oricorioSensu": "하늘하늘스타일", + "rockruff": "일반", "rockruffOwnTempo": "마이페이스", + "rockruffMidday": "한낮의 모습", + "rockruffMidnight": "한밤중의 모습", + "rockruffDusk": "황혼의 모습", + "wishiwashi": "단독의 모습", + "wishiwashiSchool": "군집의 모습", + "typeNullNormal": "노말", + "typeNullFighting": "격투", + "typeNullFlying": "비행", + "typeNullPoison": "독", + "typeNullGround": "땅", + "typeNullRock": "바위", + "typeNullBug": "벌레", + "typeNullGhost": "고스트", + "typeNullSteel": "강철", + "typeNullFire": "불꽃", + "typeNullWater": "물", + "typeNullGrass": "풀", + "typeNullElectric": "전기", + "typeNullPsychic": "에스퍼", + "typeNullIce": "얼음", + "typeNullDragon": "드래곤", + "typeNullDark": "악", + "typeNullFairy": "페어리", "miniorRedMeteor": "유성의 모습(빨강)", "miniorOrangeMeteor": "유성의 모습(주황)", "miniorYellowMeteor": "유성의 모습(노랑)", @@ -131,25 +195,66 @@ "miniorViolet": "보라색 코어", "mimikyuDisguised": "둔갑한 모습", "mimikyuBusted": "들킨 모습", + "necrozma": "네크로즈마", + "necrozmaDuskMane": "황혼의 갈기", + "necrozmaDawnWings": "새벽의 날개", + "necrozmaUltra": "울트라네크로즈마", + "magearna": "일반적인 모습", "magearnaOriginal": "500년 전의 색", - "marshadowZenith": "투지를 불태운 마샤도", + "marshadow": "일반적인 모습", + "marshadowZenith": "타오르는 투지의 모습", + "cramorant": "일반", + "cramorantGulping": "그대로 삼킨 모습", + "cramorantGorging": "통째로 삼킨 모습", + "toxelAmped": "하이한 모습", + "toxelLowkey": "로우한 모습", "sinisteaPhony": "위작품", "sinisteaAntique": "진작품", + "milceryVanillaCream": "밀키바닐라", + "milceryRubyCream": "밀키루비", + "milceryMatchaCream": "밀키말차", + "milceryMintCream": "밀키민트", + "milceryLemonCream": "밀키레몬", + "milcerySaltedCream": "밀키솔트", + "milceryRubySwirl": "루비믹스", + "milceryCaramelSwirl": "캐러멜믹스", + "milceryRainbowSwirl": "트리플믹스", + "eiscue": "아이스페이스", "eiscueNoIce": "나이스페이스", "indeedeeMale": "수컷의 모습", "indeedeeFemale": "암컷의 모습", "morpekoFullBelly": "배부른 모양", + "morpekoHangry": "배고픈 모양", "zacianHeroOfManyBattles": "역전의 용사", + "zacianCrowned": "검왕", "zamazentaHeroOfManyBattles": "역전의 용사", + "zamazentaCrowned": "방패왕", + "kubfuSingleStrike": "일격의 태세", + "kubfuRapidStrike": "연격의 태세", + "zarude": "일반", "zarudeDada": "아빠", + "calyrex": "일반", + "calyrexIce": "백마 탄 모습", + "calyrexShadow": "흑마 탄 모습", + "basculinMale": "수컷의 모습", + "basculinFemale": "암컷의 모습", "enamorusIncarnate": "화신폼", + "enamorusTherian": "영물폼", + "lechonkMale": "수컷의 모습", + "lechonkFemale": "암컷의 모습", + "tandemausFour": "네 식구", + "tandemausThree": "세 식구", "squawkabillyGreenPlumage": "그린 페더", "squawkabillyBluePlumage": "블루 페더", "squawkabillyYellowPlumage": "옐로 페더", "squawkabillyWhitePlumage": "화이트 페더", + "finizenZero": "나이브폼", + "finizenHero": "마이티폼", "tatsugiriCurly": "젖힌 모습", "tatsugiriDroopy": "늘어진 모습", "tatsugiriStretchy": "뻗은 모습", + "dunsparceTwo": "두 마디 폼", + "dunsparceThree": "세 마디 폼", "gimmighoulChest": "상자폼", "gimmighoulRoaming": "도보폼", "koraidonApexBuild": "완전형태", @@ -164,7 +269,22 @@ "miraidonGlideMode": "글라이드모드", "poltchageistCounterfeit": "가짜배기의 모습", "poltchageistArtisan": "알짜배기의 모습", + "poltchageistUnremarkable": "범작의 모습", + "poltchageistMasterpiece": "걸작의 모습", + "ogerponTealMask": "벽록의가면", + "ogerponTealMaskTera": "벽록의가면 테라스탈", + "ogerponWellspringMask": "우물의가면", + "ogerponWellspringMaskTera": "우물의가면 테라스탈", + "ogerponHearthflameMask": "화덕의가면", + "ogerponHearthflameMaskTera": "화덕의가면 테라스탈", + "ogerponCornerstoneMask": "주춧돌의가면", + "ogerponCornerstoneMaskTera": "주춧돌의가면 테라스탈", + "terpagos": "노말폼", + "terpagosTerastal": "테라스탈폼", + "terpagosStellar": "스텔라폼", + "galarDarumaka": "노말모드", + "galarDarumakaZen": "달마모드", "paldeaTaurosCombat": "컴뱃종", "paldeaTaurosBlaze": "블레이즈종", "paldeaTaurosAqua": "워터종" -} \ No newline at end of file +} diff --git a/src/locales/ko/trainer-classes.json b/src/locales/ko/trainer-classes.json index da6c6f4aceb..89cbe250c83 100644 --- a/src/locales/ko/trainer-classes.json +++ b/src/locales/ko/trainer-classes.json @@ -126,5 +126,8 @@ "skull_grunts": "스컬단 조무래기들", "macro_grunt": "매크로코스모스 직원", "macro_grunt_female": "매크로코스모스 직원", - "macro_grunts": "매크로코스모스 직원들" + "macro_grunts": "매크로코스모스 직원들", + "star_grunt": "스타단 조무래기", + "star_grunt_female": "스타단 조무래기", + "star_grunts": "스타단 조무래기들" } diff --git a/src/locales/ko/trainer-names.json b/src/locales/ko/trainer-names.json index f1357a428ba..7d18cd51c4e 100644 --- a/src/locales/ko/trainer-names.json +++ b/src/locales/ko/trainer-names.json @@ -141,6 +141,11 @@ "faba": "자우보", "plumeria": "플루메리", "oleana": "올리브", + "giacomo": "피나", + "mela": "멜로코", + "atticus": "추명", + "ortega": "오르티가", + "eri": "비파", "maxie": "마적", "archie": "아강", @@ -150,6 +155,7 @@ "lusamine": "루자미네", "guzma": "구즈마", "rose": "로즈", + "cassiopeia": "모란", "blue_red_double": "그린 & 레드", "red_blue_double": "레드 & 그린", diff --git a/src/locales/ko/trainer-titles.json b/src/locales/ko/trainer-titles.json index 7cff2207817..7b5a72f6fc1 100644 --- a/src/locales/ko/trainer-titles.json +++ b/src/locales/ko/trainer-titles.json @@ -19,6 +19,7 @@ "aether_boss": "에테르재단 대표", "skull_boss": "스컬단 보스", "macro_boss": "매크로코스모스 사장", + "star_boss": "스타단 보스", "rocket_admin": "로켓단 간부", "rocket_admin_female": "로켓단 간부", @@ -34,5 +35,6 @@ "flare_admin_female": "플레어단 간부", "aether_admin": "에테르재단 지부장", "skull_admin": "스컬단 간부", - "macro_admin": "매크로코스모스 간부" + "macro_admin": "매크로코스모스 간부", + "star_admin": "스타단 군단 보스" } diff --git a/src/locales/pt_BR/ability.json b/src/locales/pt_BR/ability.json index c4180ff01dd..e30a7dd8c4f 100644 --- a/src/locales/pt_BR/ability.json +++ b/src/locales/pt_BR/ability.json @@ -1237,6 +1237,6 @@ }, "poisonPuppeteer": { "name": "Poison Puppeteer", - "description": "Pokémon envenenados pelos movimentos de Pecharunt também ficarão confusos." + "description": "Pokémon envenenados pelos movimentos deste Pokémon também ficarão confusos." } } diff --git a/src/locales/pt_BR/battle.json b/src/locales/pt_BR/battle.json index 08eeb99e0cd..392f7b2ec38 100644 --- a/src/locales/pt_BR/battle.json +++ b/src/locales/pt_BR/battle.json @@ -96,5 +96,7 @@ "retryBattle": "Você gostaria de tentar novamente desde o início da batalha?", "unlockedSomething": "{{unlockedThing}}\nfoi desbloqueado.", "congratulations": "Parabéns!", - "beatModeFirstTime": "{{speciesName}} venceu o Modo {{gameMode}} pela primeira vez!\nVocê recebeu {{newModifier}}!" + "beatModeFirstTime": "{{speciesName}} venceu o Modo {{gameMode}} pela primeira vez!\nVocê recebeu {{newModifier}}!", + "battlerTagsHealBlock": "{{pokemonNameWithAffix}} não pode restaurar seus PS!", + "battlerTagsHealBlockOnRemove": "{{pokemonNameWithAffix}} pode restaurar seus PS novamente!" } diff --git a/src/locales/pt_BR/bgm-name.json b/src/locales/pt_BR/bgm-name.json index 86d8ce3e790..d73347ad988 100644 --- a/src/locales/pt_BR/bgm-name.json +++ b/src/locales/pt_BR/bgm-name.json @@ -83,9 +83,11 @@ "battle_aether_grunt": "SM Batalha da Fundação Aether", "battle_skull_grunt": "SM Batalha da Equipe Skull", "battle_macro_grunt": "SWSH Batalha de Treinador", + "battle_star_grunt": "SV Batalha da Equipe Estrela", "battle_galactic_admin": "BDSP Batalha com Admin da Equipe Galáctica", "battle_skull_admin": "SM Batalha com Admin da Euipe Skull", "battle_oleana": "SWSH Batalha da Oleana", + "battle_star_admin": "SV Chefe da Equipe Estrela", "battle_rocket_boss": "USUM Batalha do Giovanni", "battle_aqua_magma_boss": "ORAS Batalha do Maxie & Archie", "battle_galactic_boss": "BDSP Batalha do Cyrus", @@ -94,6 +96,7 @@ "battle_aether_boss": "SM Batalha da Lusamine", "battle_skull_boss": "SM Batalha do Guzma", "battle_macro_boss": "SWSH Batalha do Rose", + "battle_star_boss": "SV Batalha da Cassiopeia", "abyss": "PMD EoS Dark Crater", "badlands": "PMD EoS Barren Valley", @@ -108,17 +111,17 @@ "forest": "PMD EoS Dusk Forest", "grass": "PMD EoS Apple Woods", "graveyard": "PMD EoS Mystifying Forest", - "ice_cave": "PMD EoS Vast Ice Mountain", + "ice_cave": "Firel - -50°C", "island": "PMD EoS Craggy Coast", "jungle": "Lmz - Jungle", "laboratory": "Firel - Laboratory", - "lake": "PMD EoS Crystal Cave", + "lake": "Lmz - Lake", "meadow": "PMD EoS Sky Peak Forest", "metropolis": "Firel - Metropolis", "mountain": "PMD EoS Mt. Horn", - "plains": "PMD EoS Sky Peak Prairie", - "power_plant": "PMD EoS Far Amp Plains", - "ruins": "PMD EoS Deep Sealed Ruin", + "plains": "Firel - Route 888", + "power_plant": "Firel - The Klink", + "ruins": "Lmz - Ancient Ruins", "sea": "Andr06 - Marine Mystique", "seabed": "Firel - Seabed", "slum": "Andr06 - Sneaky Snom", @@ -128,7 +131,7 @@ "tall_grass": "PMD EoS Foggy Forest", "temple": "PMD EoS Aegis Cave", "town": "PMD EoS Random Dungeon Theme 3", - "volcano": "PMD EoS Steam Cave", + "volcano": "Firel - Twisturn Volcano", "wasteland": "PMD EoS Hidden Highland", "encounter_ace_trainer": "BW Encontro com Treinador (Treinador Ás)", "encounter_backpacker": "BW Encontro com Treinador (Mochileiro)", diff --git a/src/locales/pt_BR/dialogue.json b/src/locales/pt_BR/dialogue.json index 2f39442ee5a..fdf472526c1 100644 --- a/src/locales/pt_BR/dialogue.json +++ b/src/locales/pt_BR/dialogue.json @@ -749,12 +749,16 @@ "encounter": { "1": "Parece que aqui é o fim da linha para você!", "2": "Você é um treinador, não é? Temo que isso não lhe dê o direito de interferir em nosso trabalho.", - "3": "Sou da Macro Cosmos Seguros! Já tem um seguro de vida?" + "3": "Sou da Macro Cosmos Seguros! Já tem um seguro de vida?", + "4": "Te encontrei! Nesse caso, é hora de uma batalha Pokémon!", + "5": "Ouvir uma bronca da Srta. Oleana é bem pior do que qualquer coisa que você possa fazer!" }, "victory": { "1": "Eu não tenho muita escolha a não ser recuar respeitosamente.", "2": "Ter que desistir do meu dinheiro... Perder significa que estou de volta no vermelho...", - "3": "Ninguém pode vencer a Macro Cosmos quando se trata de nossa dedicação ao trabalho!" + "3": "Ninguém pode vencer a Macro Cosmos quando se trata de nossa dedicação ao trabalho!", + "4": "Eu até troquei meu Pokémon...", + "5": "As batalhas não funcionaram... A única coisa a fazer agora é fugir!" } }, "oleana": { @@ -769,6 +773,73 @@ "3": "*suspiro* Eu sou uma Oleana cansada..." } }, + "star_grunt": { + "encounter": { + "1": "Nós somos a Equipe Estrela, garoto. Brilhamos tão forte que dói olhar pra nós!", + "2": "Vamos com tudo pra cima de você - Hasta la vistaaar! ★", + "3": "Se você não sair rapidinho, vou ter que me defender. Entendeu?", + "4": "Desculpe, mas se você não der meia-volta, amigo, vamos ter que te despachar!", + "4_female": "Desculpe, mas se você não der meia-volta, amiga, vamos ter que te despachar!", + "5": "Ótimo. Lá vem mais um qualquer para estragar o meu dia." + }, + "victory": { + "1": "Como é que EU estou vendo estrelas?!", + "2": "Você é assustador, garoto. Se você se juntasse à Equipe Estrela, estaria no topo rapidinho!", + "3": "Me defendi bem... Mas não foi o suficiente!", + "4": "H-hasta la vistar... ★", + "5": "Eu não achei que o trabalho de recruta da Equipe Estrela seria uma tarefa tão pesada..." + } + }, + "giacomo": { + "encounter": { + "1": "Você realmente não pensa muito, né? Declarar guerra contra a Equipe Estrela é uma jogada muito ruim.", + "2": "Vou tocar uma sinfonia do seu fracasso enquanto você cai e queima. Vamos começar a festa!" + }, + "victory": { + "1": "Acho que é isso...", + "2": "Você transformou minha melodia em um lamento..." + } + }, + "mela": { + "encounter": { + "1": "Então você é o idiota que arrumou briga com a Equipe Estrela... Prepare-se para ser destruído.", + "2": "Tudo bem, VAMOS LÁ! Vou explodir tudo!" + }, + "victory": { + "1": "Ugh. É assim que isso vai acabar? Que problema...", + "2": "Usei tudo o que eu tinha... e agora apaguei." + } + }, + "atticus": { + "encounter": { + "1": "Você tem coragem de mostrar suas garras para a Equipe Estrela. Venha, então, vil criatura!", + "2": "Esteja avisado—não te darei misericórdia! Em guarda!" + }, + "victory": { + "1": "Perdoem-me, meus amigos...", + "2": "Você me venceu completamente. Mas sua vitória não me trouxe amargura—tamanha foi sua brilhante execução." + } + }, + "ortega": { + "encounter": { + "1": "Prometo que serei gentil, então não me culpe quando essa batalha te mandar chorando de volta para casa!", + "2": "Vou apagar esse sorriso convencido do seu rosto com certeza! Você vai perder!" + }, + "victory": { + "1": "Ugh! Como eu pude PERDER! Que RAIVA!", + "2": "Arrrrgggh! Essa sua força é tão INJUSTA." + } + }, + "eri": { + "encounter": { + "1": "Não importa quem você é. Vou derrubar qualquer um que tente destruir a Equipe Estrela!", + "2": "Eu dou tudo de mim, e isso é uma promessa! Vamos ver quem fica de pé no final!" + }, + "victory": { + "1": "Me desculpem, pessoal...", + "2": "Dei tudo de mim, mas não foi o suficiente—eu não fui o suficiente..." + } + }, "rocket_boss_giovanni_1": { "encounter": { "1": "Tenho que admitir, estou impressionado que tenha chegado até aqui!" @@ -968,6 +1039,28 @@ "1": "Eu suponho que deve parecer que estou fazendo algo terrível. Eu não espero que você entenda.\n$Mas eu devo fornecer à região de Galar energia ilimitada para garantir prosperidade eterna." } }, + "star_boss_penny_1": { + "encounter": { + "1": "Eu sou a grande chefe da Equipe Estrela. Meu nome é Cassiopeia. \n$Agora, ajoelhe-se diante do poder esmagador da fundadora da Equipe Estrela!" + }, + "victory": { + "1": "... ... .." + }, + "defeat": { + "1": "Heh..." + } + }, + "star_boss_penny_2": { + "encounter": { + "1": "Não vou me segurar nesta batalha! Vou permanecer fiel ao código da Equipe Estrela! \n$Meu poder Veevee vai te reduzir a pó estelar!" + }, + "victory": { + "1": "...Agora acabou tudo." + }, + "defeat": { + "1": "Não posso te culpar por suas habilidades de batalha... Considerando como os chefes caíram diante de você." + } + }, "brock": { "encounter": { "1": "Minha especialidade em Pokémon do tipo Pedra vai te derrubar! Vamos lá!", diff --git a/src/locales/pt_BR/move.json b/src/locales/pt_BR/move.json index c463665f1ad..3c365a207ae 100644 --- a/src/locales/pt_BR/move.json +++ b/src/locales/pt_BR/move.json @@ -3129,7 +3129,7 @@ }, "auraWheel": { "name": "Aura Wheel", - "effect": "Morpeko ataca e aumenta sua Velocidade com a energia armazenada em suas bochechas. O tipo deste movimento muda dependendo da forma do usuário." + "effect": "O usuário ataca e aumenta sua Velocidade com a energia armazenada em suas bochechas. Se usado por Morpeko, o tipo deste movimento muda dependendo da forma do usuário." }, "breakingSwipe": { "name": "Breaking Swipe", diff --git a/src/locales/pt_BR/pokemon-form.json b/src/locales/pt_BR/pokemon-form.json index aa8f32a5d36..416f09c97bf 100644 --- a/src/locales/pt_BR/pokemon-form.json +++ b/src/locales/pt_BR/pokemon-form.json @@ -1,4 +1,5 @@ { + "pikachu": "Normal", "pikachuCosplay": "Cosplay", "pikachuCoolCosplay": "Cosplay Legal", "pikachuBeautyCosplay": "Cosplay Bonito", @@ -6,7 +7,9 @@ "pikachuSmartCosplay": "Cosplay Inteligente", "pikachuToughCosplay": "Cosplay Forte", "pikachuPartner": "Parceiro", + "eevee": "Normal", "eeveePartner": "Parceiro", + "pichu": "Normal", "pichuSpiky": "Orelha Espetada", "unownA": "A", "unownB": "B", @@ -36,36 +39,65 @@ "unownZ": "Z", "unownExclamation": "!", "unownQuestion": "?", + "castform": "Normal", "castformSunny": "Ensolarado", "castformRainy": "Chuvoso", "castformSnowy": "Nevado", "deoxysNormal": "Normal", + "deoxysAttack": "Ataque", + "deoxysDefense": "Defesa", + "deoxysSpeed": "Velocidade", "burmyPlant": "Vegetal", "burmySandy": "Arenoso", "burmyTrash": "Lixo", + "cherubiOvercast": "Nublado", + "cherubiSunshine": "Solar", "shellosEast": "Leste", "shellosWest": "Oeste", + "rotom": "Normal", "rotomHeat": "Calor", "rotomWash": "Lavagem", "rotomFrost": "Congelante", "rotomFan": "Ventilador", "rotomMow": "Corte", + "dialga": "Normal", + "dialgaOrigin": "Origem", + "palkia": "Normal", + "palkiaOrigin": "Origem", "giratinaAltered": "Alterado", + "giratinaOrigin": "Origem", "shayminLand": "Terrestre", + "shayminSky": "Céu", "basculinRedStriped": "Listras Vermelhas", "basculinBlueStriped": "Listras Azuis", "basculinWhiteStriped": "Listras Brancas", + "darumaka": "Padrão", + "darumakaZen": "Zen", "deerlingSpring": "Primavera", "deerlingSummer": "Verão", "deerlingAutumn": "Outono", "deerlingWinter": "Inverno", "tornadusIncarnate": "Materializado", + "tornadusTherian": "Therian", "thundurusIncarnate": "Materializado", + "thundurusTherian": "Therian", "landorusIncarnate": "Materializado", + "landorusTherian": "Therian", + "kyurem": "Normal", + "kyuremBlack": "Preto", + "kyuremWhite": "Branco", "keldeoOrdinary": "Comum", + "keldeoResolute": "Resoluto", "meloettaAria": "Ária", "meloettaPirouette": "Pirueta", + "genesect": "Normal", + "genesectShock": "Disco Elétrico", + "genesectBurn": "Disco Incendiante", + "genesectChill": "Disco Congelante", + "genesectDouse": "Disco Hídrico", + "froakie": "Normal", "froakieBattleBond": "Vínculo de Batalha", + "froakieAsh": "Ash", "scatterbugMeadow": "Prado", "scatterbugIcySnow": "Neve Congelada", "scatterbugPolar": "Polar", @@ -91,6 +123,7 @@ "flabebeOrange": "Laranja", "flabebeBlue": "Azul", "flabebeWhite": "Branca", + "furfrou": "Selvagem", "furfrouHeart": "Coração", "furfrouStar": "Estrela", "furfrouDiamond": "Diamante", @@ -100,6 +133,11 @@ "furfrouLaReine": "Aristocrático", "furfrouKabuki": "Kabuki", "furfrouPharaoh": "Faraó", + "espurrMale": "Macho", + "espurrFemale": "Fêmea", + "honedgeShiled": "Escudo", + "honedgeBlade": "Lâmina", + "pumpkaboo": "Normal", "pumpkabooSmall": "Pequeno", "pumpkabooLarge": "Grande", "pumpkabooSuper": "Extragrande", @@ -110,11 +148,37 @@ "zygarde50Pc": "Forma 50% Agrupada", "zygarde10Pc": "Forma 10% Agrupada", "zygardeComplete": "Forma Completa", + "hoopa": "Contido", + "hoopaUnbound": "Libertado", "oricorioBaile": "Flamenco", "oricorioPompom": "Pompom", "oricorioPau": "Hula", "oricorioSensu": "Leque", + "rockruff": "Normal", "rockruffOwnTempo": "Próprio Tempo", + "rockruffMidday": "Diurno", + "rockruffMidnight": "Noturno", + "rockruffDusk": "Crepúsculo", + "wishiwashi": "Individual", + "wishiwashiSchool": "Cardume", + "typeNullNormal": "Tipo: Normal", + "typeNullFighting": "Tipo: Lutador", + "typeNullFlying": "Tipo: Voador", + "typeNullPoison": "Tipo: Veneno", + "typeNullGround": "Tipo: Terra", + "typeNullRock": "Tipo: Pedra", + "typeNullBug": "Tipo: Inseto", + "typeNullGhost": "Tipo: Fantasma", + "typeNullSteel": "Tipo: Aço", + "typeNullFire": "Tipo: Fogo", + "typeNullWater": "Tipo: Água", + "typeNullGrass": "Tipo: Grama", + "typeNullElectric": "Tipo: Elétrico", + "typeNullPsychic": "Tipo: Psíquico", + "typeNullIce": "Tipo: Gelo", + "typeNullDragon": "Tipo: Dragão", + "typeNullDark": "Tipo: Sombrio", + "typeNullFairy": "Tipo: Fada", "miniorRedMeteor": "Meteoro Vermelho", "miniorOrangeMeteor": "Meteoro Laranja", "miniorYellowMeteor": "Meteoro Amarelo", @@ -131,25 +195,66 @@ "miniorViolet": "Violeta", "mimikyuDisguised": "Disfarçado", "mimikyuBusted": "Descoberto", + "necrozma": "Normal", + "necrozmaDuskMane": "Juba Crepúsculo", + "necrozmaDawnWings": "Asas Alvorada", + "necrozmaUltra": "Ultra", + "magearna": "Normal", "magearnaOriginal": "Original", + "marshadow": "Normal", "marshadowZenith": "Zênite", + "cramorant": "Normal", + "cramorantGulping": "Engolidor", + "cramorantGorging": "Devorador", + "toxelAmped": "Agudo", + "toxelLowkey": "Grave", "sinisteaPhony": "Falsificado", "sinisteaAntique": "Autêntico", + "milceryVanillaCream": "Creme de Baunilha", + "milceryRubyCream": "Creme Rubi", + "milceryMatchaCream": "Creme de Chá Verde", + "milceryMintCream": "Creme de Menta", + "milceryLemonCream": "Creme de Lima", + "milcerySaltedCream": "Creme Salgado", + "milceryRubySwirl": "Mistura Rubi", + "milceryCaramelSwirl": "Mistura de Caramelo", + "milceryRainbowSwirl": "Mistura Tricolor", + "eiscue": "Cara de Gelo", "eiscueNoIce": "Descongelado", "indeedeeMale": "Macho", "indeedeeFemale": "Fêmea", "morpekoFullBelly": "Saciado", + "morpekoHangry": "Voraz", "zacianHeroOfManyBattles": "Herói Veterano", + "zacianCrowned": "Coroado", "zamazentaHeroOfManyBattles": "Herói Veterano", + "zamazentaCrowned": "Coroado", + "kubfuSingleStrike": "Golpe Decisivo", + "kubfuRapidStrike": "Golpe Fluido", + "zarude": "Normal", "zarudeDada": "Papa", + "calyrex": "Normal", + "calyrexIce": "Cavaleiro Glacial", + "calyrexShadow": "Cavaleiro Espectral", + "basculinMale": "Macho", + "basculinFemale": "Fêmea", "enamorusIncarnate": "Materializado", + "enamorusTherian": "Therian", + "lechonkMale": "Macho", + "lechonkFemale": "Fêmea", + "tandemausFour": "Família de Quatro", + "tandemausThree": "Família de Três", "squawkabillyGreenPlumage": "Plumas Verdes", "squawkabillyBluePlumage": "Plumas Azuis", "squawkabillyYellowPlumage": "Plumas Amarelas", "squawkabillyWhitePlumage": "Plumas Brancas", + "finizenZero": "Ingênuo", + "finizenHero": "Heroico", "tatsugiriCurly": "Curvado", "tatsugiriDroopy": "Caído", "tatsugiriStretchy": "Reto", + "dunsparceTwo": "Duplo", + "dunsparceThree": "Triplo", "gimmighoulChest": "Baú", "gimmighoulRoaming": "Perambulante", "koraidonApexBuild": "Forma Plena", @@ -164,6 +269,21 @@ "miraidonGlideMode": "Modo Aéreo", "poltchageistCounterfeit": "Imitação", "poltchageistArtisan": "Artesão", + "poltchageistUnremarkable": "Medíocre", + "poltchageistMasterpiece": "Excepcional", + "ogerponTealMask": "Máscara Turquesa", + "ogerponTealMaskTera": "Máscara Turquesa Terastalizada", + "ogerponWellspringMask": "Máscara Nascente", + "ogerponWellspringMaskTera": "Máscara Nascente Terastalizada", + "ogerponHearthflameMask": "Máscara Fornalha", + "ogerponHearthflameMaskTera": "Máscara Fornalha Terastalizada", + "ogerponCornerstoneMask": "Máscara Alicerce", + "ogerponCornerstoneMaskTera": "Máscara Alicerce Terastalizada", + "terpagos": "Normal", + "terpagosTerastal": "Teracristal", + "terpagosStellar": "Astral", + "galarDarumaka": "Padrão", + "galarDarumakaZen": "Zen", "paldeaTaurosCombat": "Combate", "paldeaTaurosBlaze": "Chamas", "paldeaTaurosAqua": "Aquático" diff --git a/src/locales/pt_BR/trainer-classes.json b/src/locales/pt_BR/trainer-classes.json index 482265d00c6..e5d1e1bb4b1 100644 --- a/src/locales/pt_BR/trainer-classes.json +++ b/src/locales/pt_BR/trainer-classes.json @@ -126,6 +126,8 @@ "skull_grunts": "Capangas da Equipe Skull", "macro_grunt": "Treinador da Macro Cosmos", "macro_grunt_female": "Treinadora da Macro Cosmos", - "macro_grunts": "Treinadores da Macro Cosmos" - + "macro_grunts": "Treinadores da Macro Cosmos", + "star_grunt": "Capanga da Equipe Estrela", + "star_grunt_female": "Capanga da Equipe Estrela", + "star_grunts": "Capangas da Equipe Estrela" } diff --git a/src/locales/pt_BR/trainer-names.json b/src/locales/pt_BR/trainer-names.json index 5500e2ddb46..83557e70ee2 100644 --- a/src/locales/pt_BR/trainer-names.json +++ b/src/locales/pt_BR/trainer-names.json @@ -141,6 +141,12 @@ "faba": "Faba", "plumeria": "Plumeria", "oleana": "Oleana", + "giacomo": "Giacomo", + "mela": "Mela", + "atticus": "Atticus", + "ortega": "Ortega", + "eri": "Eri", + "maxie": "Maxie", "archie": "Archie", "cyrus": "Cyrus", @@ -149,6 +155,8 @@ "lusamine": "Lusamine", "guzma": "Guzma", "rose": "Rose", + "cassiopeia": "Penny", + "blue_red_double": "Blue & Red", "red_blue_double": "Red & Blue", "tate_liza_double": "Tate & Liza", diff --git a/src/locales/pt_BR/trainer-titles.json b/src/locales/pt_BR/trainer-titles.json index 701c2e143fa..d416e0225bf 100644 --- a/src/locales/pt_BR/trainer-titles.json +++ b/src/locales/pt_BR/trainer-titles.json @@ -19,6 +19,7 @@ "aether_boss": "Presidente Aether", "skull_boss": "Chefe da Equipe Skull", "macro_boss": "Presidente da Macro Cosmos", + "star_boss": "Líder da Equipe Estrela", "rocket_admin": "Admin da Equipe Rocket", "rocket_admin_female": "Admin da Equipe Rocket", @@ -34,5 +35,6 @@ "flare_admin_female": "Admin da Equipe Flare", "aether_admin": "Admin da Fundação Aether", "skull_admin": "Admin da Equipe Skull", - "macro_admin": "Macro Cosmos" + "macro_admin": "Macro Cosmos", + "star_admin": "Chefe de Esquadrão da Equipe Estrela" } diff --git a/src/locales/zh_CN/ability.json b/src/locales/zh_CN/ability.json index 31e3c08161d..0a81a9c6ad2 100644 --- a/src/locales/zh_CN/ability.json +++ b/src/locales/zh_CN/ability.json @@ -1237,6 +1237,6 @@ }, "poisonPuppeteer": { "name": "毒傀儡", - "description": "因桃歹郎的招式而陷入中毒状态的\n对手同时也会陷入混乱状态。" + "description": "因此宝可梦的招式而陷入中毒状态的对手\n同时也会陷入混乱状态。" } } diff --git a/src/locales/zh_CN/bgm-name.json b/src/locales/zh_CN/bgm-name.json index 065347e3bb6..7c3f5e617ae 100644 --- a/src/locales/zh_CN/bgm-name.json +++ b/src/locales/zh_CN/bgm-name.json @@ -81,9 +81,11 @@ "battle_aether_grunt": "日月「战斗!以太基金会」", "battle_skull_grunt": "日月「战斗!骷髅队」", "battle_macro_grunt": "剑盾「战斗!马洛科蒙集团」", + "battle_star_grunt": "SV Team Star Battle", "battle_galactic_admin": "晶灿钻石·明亮珍珠「战斗!银河队干部」", "battle_skull_admin": "日月「战斗!骷髅队干部」", "battle_oleana": "剑盾「战斗!奥利薇」", + "battle_star_admin": "SV Team Star Boss", "battle_rocket_boss": "究极日月「战斗!坂木」", "battle_aqua_magma_boss": "Ω红宝石α蓝宝石「战斗!水梧桐・赤焰松」", "battle_galactic_boss": "晶灿钻石·明亮珍珠「战斗!赤日」", @@ -92,6 +94,7 @@ "battle_aether_boss": "日月「战斗!露莎米奈」", "battle_skull_boss": "日月「战斗!古兹马」", "battle_macro_boss": "剑盾「战斗!洛兹」", + "battle_star_boss": "SV Cassiopeia Battle", "abyss": "空之探险队「黑暗小丘」", "badlands": "空之探险队「枯竭之谷」", @@ -106,17 +109,17 @@ "forest": "空之探险队「黑暗森林」", "grass": "空之探险队「苹果森林」", "graveyard": "空之探险队「神秘森林」", - "ice_cave": "空之探险队「大冰山」", + "ice_cave": "Firel - -50°C", "island": "空之探险队「沿岸岩地」", "jungle": "Lmz - 丛林", "laboratory": "Firel - 研究所", - "lake": "空之探险队「水晶洞窟」", + "lake": "Lmz - Lake", "meadow": "空之探险队「天空顶端(森林)」", "metropolis": "Firel - 城市", "mountain": "空之探险队「角山」", - "plains": "空之探险队「天空顶端(草原)」", - "power_plant": "空之探险队「电气平原 深处」", - "ruins": "空之探险队「封印岩地 深处」", + "plains": "Firel - Route 888", + "power_plant": "Firel - The Klink", + "ruins": "Lmz - Ancient Ruins", "sea": "Andr06 - 海洋之秘", "seabed": "Firel - 海底", "slum": "Andr06 - 狡猾的雪吞虫", @@ -126,7 +129,7 @@ "tall_grass": "空之探险队「浓雾森林」", "temple": "空之探险队「守护洞穴」", "town": "空之探险队「随机迷宫3」", - "volcano": "空之探险队「热水洞窟」", + "volcano": "Firel - Twisturn Volcano", "wasteland": "空之探险队「梦幻高原」", "encounter_ace_trainer": "黑白 「视线!精英训练师」", "encounter_backpacker": "黑白 「视线!背包客」", diff --git a/src/locales/zh_CN/dialogue.json b/src/locales/zh_CN/dialogue.json index dd0fa3fb3cc..d23fd7379bb 100644 --- a/src/locales/zh_CN/dialogue.json +++ b/src/locales/zh_CN/dialogue.json @@ -715,12 +715,16 @@ "encounter": { "1": "你的对战生涯到此为止了。", "2": "你是一名训练师吧\n你没有干涉我们工作的权力!", - "3": "我是马洛科蒙集团的,要买马洛科蒙人寿保险吗。" + "3": "我是马洛科蒙集团的,要买马洛科蒙人寿保险吗。", + "4": "I found you! In that case, time for a Pokémon battle!", + "5": "An earful from Ms. Oleana is way worse than anything you can do!" }, "victory": { "1": "除了礼貌地撤退我似乎别无选择…", "2": "没法留住我的零花钱了,我又要财政赤字了…", - "3": "没人能比马洛科蒙集团的我们工作更卷!" + "3": "没人能比马洛科蒙集团的我们工作更卷!", + "4": "I even switched up my Pokémon...", + "5": "Battles didn't work... Only thing to do now is run!" } }, "oleana": { @@ -735,6 +739,73 @@ "3": "*叹气*奥利薇累累了……" } }, + "star_grunt": { + "encounter": { + "1": "We're Team Star, kid. We burn so bright, it hurts to look at us!", + "2": "We'll come at you full force - Hasta la vistaaar! ★", + "3": "If you don't clear out real quick-like, I'll hafta come at you in self-defense. You get me?", + "4": "Sorry, but if you don't turn yourself around here, amigo, we'll have to send you packing!", + "4_female": "Sorry, but if you don't turn yourself around here, amiga, we'll have to send you packing!", + "5": "Oh great. Here comes another rando to ruin my day." + }, + "victory": { + "1": "How come I'M the one seeing stars?!", + "2": "You're scary, kid. If you joined Team Star, you'd be looking down from the top in no time!", + "3": "I defended myself all right... But it wasn't enough!", + "4": "H-hasta la vistar... ★", + "5": "I didn't think grunt work for Team Star newbies would be this much of a chore..." + } + }, + "giacomo": { + "encounter": { + "1": "You don't really think things through, do ya? Declarin' war on Team Star is a real bad move.", + "2": "I'll play you a sick requiem as you crash and burn. Let's get this party staaarteeed!" + }, + "victory": { + "1": "Guess that's that...", + "2": "You turned my melody into a threnody..." + } + }, + "mela": { + "encounter": { + "1": "So you're the dope who picked a fight with Team Star... Prepare to get messed up.", + "2": "All riiight, BRING IT! I'll blow everythin' sky high!" + }, + "victory": { + "1": "Ugh. Is this really how it's gonna end? What a hassle...", + "2": "I burned through everythin' I had...and now I've sputtered out." + } + }, + "atticus": { + "encounter": { + "1": "You have some nerve baring your fangs at Team Star. Come, then, villainous wretch!", + "2": "Be warned—I shall spare thee no mercy! En garde!" + }, + "victory": { + "1": "Forgive me, my friends...", + "2": "You have utterly bested me. But thy victory stir'd no bitterness within me—such was its brilliance." + } + }, + "ortega": { + "encounter": { + "1": "I promise I'll play nice, so don't blame me when this battle sends you blubbering back home!", + "2": "I'll wipe that smug look off your face for sure! You're going down!" + }, + "victory": { + "1": "Ugh! How could I LOSE! What the HECK!", + "2": "Arrrrgggh! That strength of yours is SO. NOT. FAIR." + } + }, + "eri": { + "encounter": { + "1": "Doesn't matter who you are. I'll bury anyone who tries to take down Team Star!", + "2": "I give as good as I get—that's a promise! We'll see who's left standing in the end!" + }, + "victory": { + "1": "I'm so sorry, everyone...", + "2": "I gave it my all, but it wasn't enough—I wasn't enough..." + } + }, "rocket_boss_giovanni_1": { "encounter": { "1": "我不得不说,能来到这里,你的确很不简单!" @@ -922,6 +993,28 @@ "1": "你完全不理解!" } }, + "star_boss_penny_1": { + "encounter": { + "1": "I'm the big boss of Team Star. The name's Cassiopeia. \n$Now, bow down before the overwhelming might of Team Star's founder!" + }, + "victory": { + "1": "... ... .." + }, + "defeat": { + "1": "Heh..." + } + }, + "star_boss_penny_2": { + "encounter": { + "1": "I won't hold back in this battle! I'll stay true to Team Star's code! \n$My Veevee power will crush you into stardust!" + }, + "victory": { + "1": "...It's all over now." + }, + "defeat": { + "1": "I can't fault you on your battle skills at all... Considering how the bosses fell at your hands." + } + }, "macro_boss_rose_2": { "encounter": { "1": "我致力于解决伽勒尔的能源问题\n——当然也是全世界的能源问题。\n$我的经验与成果,造就了马洛科蒙集团,证明了我的正确与成功!\n$就算输了,我也不会改变主意的……" diff --git a/src/locales/zh_CN/move.json b/src/locales/zh_CN/move.json index 5974271abb2..d20b09f02be 100644 --- a/src/locales/zh_CN/move.json +++ b/src/locales/zh_CN/move.json @@ -3129,7 +3129,7 @@ }, "auraWheel": { "name": "气场轮", - "effect": "用储存在颊囊里的能量进行攻击,\n并提高自己的速度。其属性会随着\n莫鲁贝可的样子而改变" + "effect": "用储存在颊囊里的能量进行攻击,\n并提高自己的速度。如果由莫鲁贝可使用,\n其属性会随着它的样子而改变" }, "breakingSwipe": { "name": "广域破坏", diff --git a/src/locales/zh_CN/pokemon-form.json b/src/locales/zh_CN/pokemon-form.json index e77f9bdb9fa..c2ad12bbf16 100644 --- a/src/locales/zh_CN/pokemon-form.json +++ b/src/locales/zh_CN/pokemon-form.json @@ -1,4 +1,5 @@ { + "pikachu": "Normal", "pikachuCosplay": "换装", "pikachuCoolCosplay": "摇滚巨星", "pikachuBeautyCosplay": "贵妇", @@ -6,7 +7,9 @@ "pikachuSmartCosplay": "博士", "pikachuToughCosplay": "面罩摔跤手", "pikachuPartner": "搭档", + "eevee": "Normal", "eeveePartner": "搭档", + "pichu": "Normal", "pichuSpiky": "刺刺耳", "unownA": "A", "unownB": "B", @@ -36,36 +39,65 @@ "unownZ": "Z", "unownExclamation": "!", "unownQuestion": "?", + "castform": "Normal Form", "castformSunny": "晴天", "castformRainy": "雨天", "castformSnowy": "雪天", "deoxysNormal": "普通", + "deoxysAttack": "Attack", + "deoxysDefense": "Defense", + "deoxysSpeed": "Speed", "burmyPlant": "草木蓑衣", "burmySandy": "砂土蓑衣", "burmyTrash": "垃圾蓑衣", + "cherubiOvercast": "Overcast", + "cherubiSunshine": "Sunshine", "shellosEast": "东海", "shellosWest": "西海", + "rotom": "Normal", "rotomHeat": "加热", "rotomWash": "清洗", "rotomFrost": "结冰", "rotomFan": "旋转", "rotomMow": "切割", + "dialga": "Normal", + "dialgaOrigin": "Origin", + "palkia": "Normal", + "palkiaOrigin": "Origin", "giratinaAltered": "别种", + "giratinaOrigin": "Origin", "shayminLand": "陆上", + "shayminSky": "Sky", "basculinRedStriped": "红条纹", "basculinBlueStriped": "蓝条纹", "basculinWhiteStriped": "白条纹", + "darumaka": "Standard Mode", + "darumakaZen": "Zen", "deerlingSpring": "春天", "deerlingSummer": "夏天", "deerlingAutumn": "秋天", "deerlingWinter": "冬天", "tornadusIncarnate": "化身", + "tornadusTherian": "Therian", "thundurusIncarnate": "化身", + "thundurusTherian": "Therian", "landorusIncarnate": "化身", + "landorusTherian": "Therian", + "kyurem": "Normal", + "kyuremBlack": "Black", + "kyuremWhite": "White", "keldeoOrdinary": "通常", + "keldeoResolute": "Resolute", "meloettaAria": "歌声", "meloettaPirouette": "舞步形态", + "genesect": "Normal", + "genesectShock": "Shock Drive", + "genesectBurn": "Burn Drive", + "genesectChill": "Chill Drive", + "genesectDouse": "Douse Drive", + "froakie": "Normal", "froakieBattleBond": "牵绊变身", + "froakieAsh": "Ash", "scatterbugMeadow": "花园花纹", "scatterbugIcySnow": "冰雪花纹", "scatterbugPolar": "雪国花纹", @@ -91,6 +123,7 @@ "flabebeOrange": "橙花", "flabebeBlue": "蓝花", "flabebeWhite": "白花", + "furfrou": "Natural Form", "furfrouHeart": "心形造型", "furfrouStar": "星形造型", "furfrouDiamond": "菱形造型", @@ -100,6 +133,11 @@ "furfrouLaReine": "女王造型", "furfrouKabuki": "歌舞伎造型", "furfrouPharaoh": "国王造型", + "espurrMale": "Male", + "espurrFemale": "Female", + "honedgeShiled": "Shield", + "honedgeBlade": "Blade", + "pumpkaboo": "Average Size", "pumpkabooSmall": "小尺寸", "pumpkabooLarge": "大尺寸", "pumpkabooSuper": "特大尺寸", @@ -110,11 +148,37 @@ "zygarde50Pc": "50%形态 群聚变形", "zygarde10Pc": "10%形态 群聚变形", "zygardeComplete": "完全体形态", + "hoopa": "Confined", + "hoopaUnbound": "Unbound", "oricorioBaile": "热辣热辣风格", "oricorioPompom": "啪滋啪滋风格", "oricorioPau": "呼拉呼拉风格", "oricorioSensu": "轻盈轻盈风格", + "rockruff": "Normal", "rockruffOwnTempo": "特殊岩狗狗", + "rockruffMidday": "Midday", + "rockruffMidnight": "Midnight", + "rockruffDusk": "Dusk", + "wishiwashi": "Solo Form", + "wishiwashiSchool": "School", + "typeNullNormal": "Type: Normal", + "typeNullFighting": "Type: Fighting", + "typeNullFlying": "Type: Flying", + "typeNullPoison": "Type: Poison", + "typeNullGround": "Type: Ground", + "typeNullRock": "Type: Rock", + "typeNullBug": "Type: Bug", + "typeNullGhost": "Type: Ghost", + "typeNullSteel": "Type: Steel", + "typeNullFire": "Type: Fire", + "typeNullWater": "Type: Water", + "typeNullGrass": "Type: Grass", + "typeNullElectric": "Type: Electric", + "typeNullPsychic": "Type: Psychic", + "typeNullIce": "Type: Ice", + "typeNullDragon": "Type: Dragon", + "typeNullDark": "Type: Dark", + "typeNullFairy": "Type: Fairy", "miniorRedMeteor": "红色核心", "miniorOrangeMeteor": "橙色核心", "miniorYellowMeteor": "黄色核心", @@ -131,25 +195,66 @@ "miniorViolet": "紫色", "mimikyuDisguised": "化形", "mimikyuBusted": "现形", + "necrozma": "Normal", + "necrozmaDuskMane": "Dusk Mane", + "necrozmaDawnWings": "Dawn Wings", + "necrozmaUltra": "Ultra", + "magearna": "Normal", "magearnaOriginal": "500年前的颜色", + "marshadow": "Normal", "marshadowZenith": "全力", + "cramorant": "Normal", + "cramorantGulping": "Gulping Form", + "cramorantGorging": "Gorging Form", + "toxelAmped": "Amped Form", + "toxelLowkey": "Low-Key Form", "sinisteaPhony": "赝品", "sinisteaAntique": "真品", + "milceryVanillaCream": "Vanilla Cream", + "milceryRubyCream": "Ruby Cream", + "milceryMatchaCream": "Matcha Cream", + "milceryMintCream": "Mint Cream", + "milceryLemonCream": "Lemon Cream", + "milcerySaltedCream": "Salted Cream", + "milceryRubySwirl": "Ruby Swirl", + "milceryCaramelSwirl": "Caramel Swirl", + "milceryRainbowSwirl": "Rainbow Swirl", + "eiscue": "Ice Face", "eiscueNoIce": "解冻头", "indeedeeMale": "雄性", "indeedeeFemale": "雌性", "morpekoFullBelly": "满腹花纹", + "morpekoHangry": "Hangry", "zacianHeroOfManyBattles": "百战勇者", + "zacianCrowned": "Crowned", "zamazentaHeroOfManyBattles": "百战勇者", + "zamazentaCrowned": "Crowned", + "kubfuSingleStrike": "Single Strike", + "kubfuRapidStrike": "Rapid Strike", + "zarude": "Normal", "zarudeDada": "老爹", + "calyrex": "Normal", + "calyrexIce": "Ice Rider", + "calyrexShadow": "Shadow Rider", + "basculinMale": "Male", + "basculinFemale": "Female", "enamorusIncarnate": "化身", + "enamorusTherian": "Therian", + "lechonkMale": "Male", + "lechonkFemale": "Female", + "tandemausFour": "Family of Four", + "tandemausThree": "Family of Three", "squawkabillyGreenPlumage": "绿羽毛", "squawkabillyBluePlumage": "蓝羽毛", "squawkabillyYellowPlumage": "黄羽毛", "squawkabillyWhitePlumage": "白羽毛", + "finizenZero": "Zero", + "finizenHero": "Hero", "tatsugiriCurly": "上弓姿势", "tatsugiriDroopy": "下垂姿势", "tatsugiriStretchy": "平挺姿势", + "dunsparceTwo": "Two-Segment", + "dunsparceThree": "Three-Segment", "gimmighoulChest": "宝箱形态", "gimmighoulRoaming": "徒步形态", "koraidonApexBuild": "顶尖形态", @@ -164,6 +269,21 @@ "miraidonGlideMode": "滑翔模式", "poltchageistCounterfeit": "冒牌货", "poltchageistArtisan": "高档货", + "poltchageistUnremarkable": "Unremarkable", + "poltchageistMasterpiece": "Masterpiece", + "ogerponTealMask": "Teal Mask", + "ogerponTealMaskTera": "Teal Mask Terastallized", + "ogerponWellspringMask": "Wellspring Mask", + "ogerponWellspringMaskTera": "Wellspring Mask Terastallized", + "ogerponHearthflameMask": "Hearthflame Mask", + "ogerponHearthflameMaskTera": "Hearthflame Mask Terastallized", + "ogerponCornerstoneMask": "Cornerstone Mask", + "ogerponCornerstoneMaskTera": "Cornerstone Mask Terastallized", + "terpagos": "Normal Form", + "terpagosTerastal": "Terastal", + "terpagosStellar": "Stellar", + "galarDarumaka": "Standard Mode", + "galarDarumakaZen": "Zen", "paldeaTaurosCombat": "斗战种", "paldeaTaurosBlaze": "火炽种", "paldeaTaurosAqua": "水澜种" diff --git a/src/locales/zh_CN/trainer-classes.json b/src/locales/zh_CN/trainer-classes.json index 3a50acf5c01..ba126b9ec65 100644 --- a/src/locales/zh_CN/trainer-classes.json +++ b/src/locales/zh_CN/trainer-classes.json @@ -126,5 +126,8 @@ "skull_grunts": "骷髅队手下", "macro_grunt": "马洛科蒙训练师", "macro_grunt_female": "马洛科蒙训练师", - "macro_grunts": "马洛科蒙训练师" + "macro_grunts": "马洛科蒙训练师", + "star_grunt": "Star Grunt", + "star_grunt_female": "Star Grunt", + "star_grunts": "Star Grunts" } diff --git a/src/locales/zh_CN/trainer-names.json b/src/locales/zh_CN/trainer-names.json index 9e03a514ff7..33cf15e8304 100644 --- a/src/locales/zh_CN/trainer-names.json +++ b/src/locales/zh_CN/trainer-names.json @@ -30,10 +30,6 @@ "crasher_wake": "吉宪", "fantina": "梅丽莎", "byron": "东瓜", - "faba": "扎奥博", - "plumeria": "布尔美丽", - "oleana": "奥莉薇", - "candice": "小菘", "volkner": "电次", "cilan": "天桐", @@ -142,6 +138,15 @@ "rood": "罗德", "xerosic": "库瑟洛斯奇", "bryony": "芭菈", + "faba": "扎奥博", + "plumeria": "布尔美丽", + "oleana": "奥莉薇", + "giacomo": "Giacomo", + "mela": "Mela", + "atticus": "Atticus", + "ortega": "Ortega", + "eri": "Eri", + "maxie": "赤焰松", "archie": "水梧桐", "cyrus": "赤日", @@ -150,6 +155,7 @@ "lusamine": "露莎米奈", "guzma": "古兹马", "rose": "洛兹", + "cassiopeia": "牡丹", "blue_red_double": "青绿 & 赤红", "red_blue_double": "赤红 & 青绿", diff --git a/src/locales/zh_CN/trainer-titles.json b/src/locales/zh_CN/trainer-titles.json index 07654ec8fc3..9ef11aafbfa 100644 --- a/src/locales/zh_CN/trainer-titles.json +++ b/src/locales/zh_CN/trainer-titles.json @@ -19,6 +19,7 @@ "aether_boss": "以太基金会理事长", "skull_boss": "骷髅队老大", "macro_boss": "马洛科蒙总裁", + "star_boss": "Team Star Leader", "rocket_admin": "火箭队干部", "rocket_admin_female": "火箭队干部", @@ -34,5 +35,6 @@ "flare_admin_female": "闪焰队干部", "aether_admin": "以太基金会干部", "skull_admin": "骷髅队干部", - "macro_admin": "马洛科蒙干部" + "macro_admin": "马洛科蒙干部", + "star_admin": "Team Star Squad Boss" } diff --git a/src/locales/zh_TW/ability.json b/src/locales/zh_TW/ability.json index 21206c5362a..5d05a6c4e73 100644 --- a/src/locales/zh_TW/ability.json +++ b/src/locales/zh_TW/ability.json @@ -1237,6 +1237,6 @@ }, "poisonPuppeteer": { "name": "毒傀儡", - "description": "因為桃歹郎的招式而陷入中\n毒狀態的對手同時也會陷入\n混亂狀態。" + "description": "因為此寶可夢的招式而陷入中毒狀態的對手\n同時也會陷入混亂狀態。" } } diff --git a/src/locales/zh_TW/bgm-name.json b/src/locales/zh_TW/bgm-name.json index e8546750977..34c9ed6806e 100644 --- a/src/locales/zh_TW/bgm-name.json +++ b/src/locales/zh_TW/bgm-name.json @@ -83,6 +83,9 @@ "battle_galactic_boss": "晶燦鑽石·明亮珍珠「戰鬥!赤日」", "battle_plasma_boss": "黑2白2「戰鬥!魁奇思」", "battle_flare_boss": "XY「戰鬥!弗拉達利」", + "battle_star_grunt": "SV Team Star Battle", + "battle_star_admin": "SV Team Star Boss", + "battle_star_boss": "SV Cassiopeia Battle", "abyss": "空之探險隊「黑暗小丘」", "badlands": "空之探險隊「枯竭之谷」", @@ -97,17 +100,17 @@ "forest": "空之探險隊「黑暗森林」", "grass": "空之探險隊「蘋果森林」", "graveyard": "空之探險隊「神秘森林」", - "ice_cave": "空之探險隊「大冰山」", + "ice_cave": "Firel - -50°C", "island": "空之探險隊「沿岸岩地」", "jungle": "Lmz - 叢林", "laboratory": "Firel - 研究所", - "lake": "空之探險隊「水晶洞窟」", + "lake": "Lmz - Lake", "meadow": "空之探險隊「天空頂端(森林)」", "metropolis": "Firel - 城市", "mountain": "空之探險隊「角山」", - "plains": "空之探險隊「天空頂端(草原)」", - "power_plant": "空之探險隊「電氣平原 深處」", - "ruins": "空之探險隊「封印岩地 深處」", + "plains": "Firel - Route 888", + "power_plant": "Firel - The Klink", + "ruins": "Lmz - Ancient Ruins", "sea": "Andr06 - 海洋之秘", "seabed": "Firel - 海底", "slum": "Andr06 - 狡猾的雪吞蟲", @@ -117,7 +120,7 @@ "tall_grass": "空之探險隊「濃霧森林」", "temple": "空之探險隊「守護洞穴」", "town": "空之探險隊「隨機迷宮3」", - "volcano": "空之探險隊「熱水洞窟」", + "volcano": "Firel - Twisturn Volcano", "wasteland": "空之探險隊「夢幻高原」", "encounter_ace_trainer": "黑白 「視線!精英訓練師」", diff --git a/src/locales/zh_TW/move.json b/src/locales/zh_TW/move.json index b8c4ec05033..3a8956b1bf9 100644 --- a/src/locales/zh_TW/move.json +++ b/src/locales/zh_TW/move.json @@ -3129,7 +3129,7 @@ }, "auraWheel": { "name": "氣場輪", - "effect": "用儲存在頰囊裏的能量進行\n攻擊,並提高自己的速度。\n其屬性會隨着莫魯貝可的樣\n子而改變" + "effect": "用儲存在頰囊裏的能量進行\n攻擊,並提高自己的速度。\n如果由莫魯貝可使用,\n其屬性會隨着它的樣子而改變" }, "breakingSwipe": { "name": "廣域破壞", diff --git a/src/locales/zh_TW/pokemon-form.json b/src/locales/zh_TW/pokemon-form.json index f1fb4dff599..104f8f5ea49 100644 --- a/src/locales/zh_TW/pokemon-form.json +++ b/src/locales/zh_TW/pokemon-form.json @@ -1,4 +1,5 @@ { + "pikachu": "Normal", "pikachuCosplay": "換裝", "pikachuCoolCosplay": "搖滾巨星", "pikachuBeautyCosplay": "貴婦", @@ -6,7 +7,9 @@ "pikachuSmartCosplay": "博士", "pikachuToughCosplay": "面罩摔跤手", "pikachuPartner": "搭檔", + "eevee": "Normal", "eeveePartner": "搭檔", + "pichu": "Normal", "pichuSpiky": "刺刺耳", "unownA": "A", "unownB": "B", @@ -36,36 +39,65 @@ "unownZ": "Z", "unownExclamation": "!", "unownQuestion": "?", + "castform": "Normal Form", "castformSunny": "晴天", "castformRainy": "雨天", "castformSnowy": "雪天", "deoxysNormal": "普通", + "deoxysAttack": "Attack", + "deoxysDefense": "Defense", + "deoxysSpeed": "Speed", "burmyPlant": "草木蓑衣", "burmySandy": "砂土蓑衣", "burmyTrash": "垃圾蓑衣", + "cherubiOvercast": "Overcast", + "cherubiSunshine": "Sunshine", "shellosEast": "東海", "shellosWest": "西海", + "rotom": "Normal", "rotomHeat": "加熱", "rotomWash": "清洗", "rotomFrost": "結冰", "rotomFan": "旋轉", "rotomMow": "切割", + "dialga": "Normal", + "dialgaOrigin": "Origin", + "palkia": "Normal", + "palkiaOrigin": "Origin", "giratinaAltered": "別種", + "giratinaOrigin": "Origin", "shayminLand": "陸上", + "shayminSky": "Sky", "basculinRedStriped": "紅條紋", "basculinBlueStriped": "藍條紋", "basculinWhiteStriped": "白條紋", + "darumaka": "Standard Mode", + "darumakaZen": "Zen", "deerlingSpring": "春天", "deerlingSummer": "夏天", "deerlingAutumn": "秋天", "deerlingWinter": "冬天", "tornadusIncarnate": "化身", + "tornadusTherian": "Therian", "thundurusIncarnate": "化身", + "thundurusTherian": "Therian", "landorusIncarnate": "化身", + "landorusTherian": "Therian", + "kyurem": "Normal", + "kyuremBlack": "Black", + "kyuremWhite": "White", "keldeoOrdinary": "通常", + "keldeoResolute": "Resolute", "meloettaAria": "歌聲", "meloettaPirouette": "舞步形態", + "genesect": "Normal", + "genesectShock": "Shock Drive", + "genesectBurn": "Burn Drive", + "genesectChill": "Chill Drive", + "genesectDouse": "Douse Drive", + "froakie": "Normal", "froakieBattleBond": "牽絆變身", + "froakieAsh": "Ash", "scatterbugMeadow": "花園花紋", "scatterbugIcySnow": "冰雪花紋", "scatterbugPolar": "雪國花紋", @@ -91,6 +123,7 @@ "flabebeOrange": "橙花", "flabebeBlue": "藍花", "flabebeWhite": "白花", + "furfrou": "Natural Form", "furfrouHeart": "心形造型", "furfrouStar": "星形造型", "furfrouDiamond": "菱形造型", @@ -100,6 +133,11 @@ "furfrouLaReine": "女王造型", "furfrouKabuki": "歌舞伎造型", "furfrouPharaoh": "國王造型", + "espurrMale": "Male", + "espurrFemale": "Female", + "honedgeShiled": "Shield", + "honedgeBlade": "Blade", + "pumpkaboo": "Average Size", "pumpkabooSmall": "小尺寸", "pumpkabooLarge": "大尺寸", "pumpkabooSuper": "特大尺寸", @@ -110,11 +148,37 @@ "zygarde50Pc": "50%形態 群聚變形", "zygarde10Pc": "10%形態 群聚變形", "zygardeComplete": "完全體形態", + "hoopa": "Confined", + "hoopaUnbound": "Unbound", "oricorioBaile": "熱辣熱辣風格", "oricorioPompom": "啪滋啪滋風格", "oricorioPau": "呼拉呼拉風格", "oricorioSensu": "輕盈輕盈風格", + "rockruff": "Normal", "rockruffOwnTempo": "特殊岩狗狗", + "rockruffMidday": "Midday", + "rockruffMidnight": "Midnight", + "rockruffDusk": "Dusk", + "wishiwashi": "Solo Form", + "wishiwashiSchool": "School", + "typeNullNormal": "Type: Normal", + "typeNullFighting": "Type: Fighting", + "typeNullFlying": "Type: Flying", + "typeNullPoison": "Type: Poison", + "typeNullGround": "Type: Ground", + "typeNullRock": "Type: Rock", + "typeNullBug": "Type: Bug", + "typeNullGhost": "Type: Ghost", + "typeNullSteel": "Type: Steel", + "typeNullFire": "Type: Fire", + "typeNullWater": "Type: Water", + "typeNullGrass": "Type: Grass", + "typeNullElectric": "Type: Electric", + "typeNullPsychic": "Type: Psychic", + "typeNullIce": "Type: Ice", + "typeNullDragon": "Type: Dragon", + "typeNullDark": "Type: Dark", + "typeNullFairy": "Type: Fairy", "miniorRedMeteor": "紅色核心", "miniorOrangeMeteor": "橙色核心", "miniorYellowMeteor": "黃色核心", @@ -131,25 +195,66 @@ "miniorViolet": "紫色", "mimikyuDisguised": "化形", "mimikyuBusted": "現形", + "necrozma": "Normal", + "necrozmaDuskMane": "Dusk Mane", + "necrozmaDawnWings": "Dawn Wings", + "necrozmaUltra": "Ultra", + "magearna": "Normal", "magearnaOriginal": "500年前的顔色", + "marshadow": "Normal", "marshadowZenith": "全力", + "cramorant": "Normal", + "cramorantGulping": "Gulping Form", + "cramorantGorging": "Gorging Form", + "toxelAmped": "Amped Form", + "toxelLowkey": "Low-Key Form", "sinisteaPhony": "赝品", "sinisteaAntique": "真品", + "milceryVanillaCream": "Vanilla Cream", + "milceryRubyCream": "Ruby Cream", + "milceryMatchaCream": "Matcha Cream", + "milceryMintCream": "Mint Cream", + "milceryLemonCream": "Lemon Cream", + "milcerySaltedCream": "Salted Cream", + "milceryRubySwirl": "Ruby Swirl", + "milceryCaramelSwirl": "Caramel Swirl", + "milceryRainbowSwirl": "Rainbow Swirl", + "eiscue": "Ice Face", "eiscueNoIce": "解凍頭", "indeedeeMale": "雄性", "indeedeeFemale": "雌性", "morpekoFullBelly": "滿腹花紋", + "morpekoHangry": "Hangry", "zacianHeroOfManyBattles": "百戰勇者", + "zacianCrowned": "Crowned", "zamazentaHeroOfManyBattles": "百戰勇者", + "zamazentaCrowned": "Crowned", + "kubfuSingleStrike": "Single Strike", + "kubfuRapidStrike": "Rapid Strike", + "zarude": "Normal", "zarudeDada": "老爹", + "calyrex": "Normal", + "calyrexIce": "Ice Rider", + "calyrexShadow": "Shadow Rider", + "basculinMale": "Male", + "basculinFemale": "Female", "enamorusIncarnate": "化身", + "enamorusTherian": "Therian", + "lechonkMale": "Male", + "lechonkFemale": "Female", + "tandemausFour": "Family of Four", + "tandemausThree": "Family of Three", "squawkabillyGreenPlumage": "綠羽毛", "squawkabillyBluePlumage": "藍羽毛", "squawkabillyYellowPlumage": "黃羽毛", "squawkabillyWhitePlumage": "白羽毛", + "finizenZero": "Zero", + "finizenHero": "Hero", "tatsugiriCurly": "上弓姿勢", "tatsugiriDroopy": "下垂姿勢", "tatsugiriStretchy": "平挺姿勢", + "dunsparceTwo": "Two-Segment", + "dunsparceThree": "Three-Segment", "gimmighoulChest": "寶箱形態", "gimmighoulRoaming": "徒步形態", "koraidonApexBuild": "頂尖形態", @@ -164,6 +269,21 @@ "miraidonGlideMode":"滑翔模式", "poltchageistCounterfeit": "冒牌貨", "poltchageistArtisan": "高檔貨", + "poltchageistUnremarkable": "Unremarkable", + "poltchageistMasterpiece": "Masterpiece", + "ogerponTealMask": "Teal Mask", + "ogerponTealMaskTera": "Teal Mask Terastallized", + "ogerponWellspringMask": "Wellspring Mask", + "ogerponWellspringMaskTera": "Wellspring Mask Terastallized", + "ogerponHearthflameMask": "Hearthflame Mask", + "ogerponHearthflameMaskTera": "Hearthflame Mask Terastallized", + "ogerponCornerstoneMask": "Cornerstone Mask", + "ogerponCornerstoneMaskTera": "Cornerstone Mask Terastallized", + "terpagos": "Normal Form", + "terpagosTerastal": "Terastal", + "terpagosStellar": "Stellar", + "galarDarumaka": "Standard Mode", + "galarDarumakaZen": "Zen", "paldeaTaurosCombat": "鬥戰種", "paldeaTaurosBlaze": "火熾種", "paldeaTaurosAqua": "水瀾種" diff --git a/src/locales/zh_TW/trainer-classes.json b/src/locales/zh_TW/trainer-classes.json index d0b0fed7e5d..7469991171e 100644 --- a/src/locales/zh_TW/trainer-classes.json +++ b/src/locales/zh_TW/trainer-classes.json @@ -117,5 +117,8 @@ "plasma_grunts": "等离子队手下們", "flare_grunt": "闪焰队手下", "flare_grunt_female": "闪焰队手下", - "flare_grunts": "闪焰队手下們" + "flare_grunts": "闪焰队手下們", + "star_grunt": "Star Grunt", + "star_grunt_female": "Star Grunt", + "star_grunts": "Star Grunts" } diff --git a/src/locales/zh_TW/trainer-names.json b/src/locales/zh_TW/trainer-names.json index 04399cf19af..e3ce88d5a40 100644 --- a/src/locales/zh_TW/trainer-names.json +++ b/src/locales/zh_TW/trainer-names.json @@ -141,6 +141,11 @@ "faba": "扎奧博", "plumeria": "布爾美麗", "oleana": "奧利薇", + "giacomo": "Giacomo", + "mela": "Mela", + "atticus": "Atticus", + "ortega": "Ortega", + "eri": "Eri", "maxie": "赤焰松", "archie": "水梧桐", @@ -150,6 +155,7 @@ "lusamine": "露莎米奈", "guzma": "古茲馬", "rose": "洛茲", + "cassiopeia": "牡丹", "blue_red_double": "青綠 & 赤紅", "red_blue_double": "赤紅 & 青綠", diff --git a/src/locales/zh_TW/trainer-titles.json b/src/locales/zh_TW/trainer-titles.json index 80b2807e7b5..0931082acc0 100644 --- a/src/locales/zh_TW/trainer-titles.json +++ b/src/locales/zh_TW/trainer-titles.json @@ -16,6 +16,10 @@ "galactic_boss": "銀河隊老大", "plasma_boss": "等離子隊老大", "flare_boss": "閃焰隊老大", + "aether_boss": "Aether President", + "skull_boss": "Team Skull Boss", + "macro_boss": "Macro Cosmos President", + "star_boss": "Team Star Leader", "rocket_admin": "火箭隊幹部", "rocket_admin_female": "火箭隊幹部", @@ -28,5 +32,9 @@ "plasma_sage": "等離子隊賢人", "plasma_admin": "等離子隊幹部", "flare_admin": "閃焰隊幹部", - "flare_admin_female": "閃焰隊幹部" + "flare_admin_female": "閃焰隊幹部", + "aether_admin": "Aether Foundation Admin", + "skull_admin": "Team Skull Admin", + "macro_admin": "Macro Cosmos", + "star_admin": "Team Star Squad Boss" } diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index ce2ffc6a462..2b4f910034b 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -1288,6 +1288,21 @@ function skipInClassicAfterWave(wave: integer, defaultWeight: integer): Weighted function skipInLastClassicWaveOrDefault(defaultWeight: integer) : WeightedModifierTypeWeightFunc { return skipInClassicAfterWave(199, defaultWeight); } + +/** + * High order function that returns a WeightedModifierTypeWeightFunc to ensure Lures don't spawn on Classic 199 + * or if the lure still has over 60% of its duration left + * @param maxBattles The max battles the lure type in question lasts. 10 for green, 15 for Super, 30 for Max + * @param weight The desired weight for the lure when it does spawn + * @returns A WeightedModifierTypeWeightFunc + */ +function lureWeightFunc(maxBattles: number, weight: number): WeightedModifierTypeWeightFunc { + return (party: Pokemon[]) => { + const lures = party[0].scene.getModifiers(Modifiers.DoubleBattleChanceBoosterModifier); + return !(party[0].scene.gameMode.isClassic && party[0].scene.currentBattle.waveIndex === 199) && (lures.length === 0 || lures.filter(m => m.getMaxBattles() === maxBattles && m.getBattleCount() >= maxBattles * 0.6).length === 0) ? weight : 0; + }; +} + class WeightedModifierType { public modifierType: ModifierType; public weight: integer | WeightedModifierTypeWeightFunc; @@ -1611,7 +1626,7 @@ const modifierPool: ModifierPool = { const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => m?.ppUsed && (m.getMovePp() - m.ppUsed) <= 5 && m.ppUsed >= Math.floor(m.getMovePp() / 2)).length).length, 3); return thresholdPartyMemberCount; }, 3), - new WeightedModifierType(modifierTypes.LURE, skipInLastClassicWaveOrDefault(2)), + new WeightedModifierType(modifierTypes.LURE, lureWeightFunc(10, 2)), new WeightedModifierType(modifierTypes.TEMP_STAT_STAGE_BOOSTER, 4), new WeightedModifierType(modifierTypes.BERRY, 2), new WeightedModifierType(modifierTypes.TM_COMMON, 2), @@ -1668,7 +1683,7 @@ const modifierPool: ModifierPool = { return thresholdPartyMemberCount; }, 3), new WeightedModifierType(modifierTypes.DIRE_HIT, 4), - new WeightedModifierType(modifierTypes.SUPER_LURE, skipInLastClassicWaveOrDefault(4)), + new WeightedModifierType(modifierTypes.SUPER_LURE, lureWeightFunc(15, 4)), new WeightedModifierType(modifierTypes.NUGGET, skipInLastClassicWaveOrDefault(5)), new WeightedModifierType(modifierTypes.EVOLUTION_ITEM, (party: Pokemon[]) => { return Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 15), 8); @@ -1691,7 +1706,7 @@ const modifierPool: ModifierPool = { }), [ModifierTier.ULTRA]: [ new WeightedModifierType(modifierTypes.ULTRA_BALL, (party: Pokemon[]) => (hasMaximumBalls(party, PokeballType.ULTRA_BALL)) ? 0 : 15, 15), - new WeightedModifierType(modifierTypes.MAX_LURE, skipInLastClassicWaveOrDefault(4)), + new WeightedModifierType(modifierTypes.MAX_LURE, lureWeightFunc(30, 4)), new WeightedModifierType(modifierTypes.BIG_NUGGET, skipInLastClassicWaveOrDefault(12)), new WeightedModifierType(modifierTypes.PP_MAX, 3), new WeightedModifierType(modifierTypes.MINT, 4), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 81a3f4f81cc..d091648b1b0 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -413,7 +413,7 @@ export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier } /** - * Modifies the chance of a double battle occurring + * Increases the chance of a double battle occurring * @param args [0] {@linkcode Utils.NumberHolder} for double battle chance * @returns true if the modifier was applied */ @@ -421,7 +421,7 @@ export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier const doubleBattleChance = args[0] as Utils.NumberHolder; // This is divided because the chance is generated as a number from 0 to doubleBattleChance.value using Utils.randSeedInt // A double battle will initiate if the generated number is 0 - doubleBattleChance.value = Math.ceil(doubleBattleChance.value / 4); + doubleBattleChance.value = doubleBattleChance.value / 4; return true; } @@ -888,7 +888,7 @@ export class PokemonBaseStatTotalModifier extends PokemonHeldItemModifier { } override matchType(modifier: Modifier): boolean { - return modifier instanceof PokemonBaseStatTotalModifier; + return modifier instanceof PokemonBaseStatTotalModifier && this.statModifier === modifier.statModifier; } override clone(): PersistentModifier { @@ -939,7 +939,7 @@ export class PokemonBaseStatFlatModifier extends PokemonHeldItemModifier { } override matchType(modifier: Modifier): boolean { - return modifier instanceof PokemonBaseStatFlatModifier; + return modifier instanceof PokemonBaseStatFlatModifier && modifier.statModifier === this.statModifier && this.stats.every(s => modifier.stats.some(stat => s === stat)); } override clone(): PersistentModifier { diff --git a/src/phases/battle-end-phase.ts b/src/phases/battle-end-phase.ts index f08e04b443a..902a85325ad 100644 --- a/src/phases/battle-end-phase.ts +++ b/src/phases/battle-end-phase.ts @@ -2,19 +2,31 @@ import { applyPostBattleAbAttrs, PostBattleAbAttr } from "#app/data/ability"; import { LapsingPersistentModifier, LapsingPokemonHeldItemModifier } from "#app/modifier/modifier"; import { BattlePhase } from "./battle-phase"; import { GameOverPhase } from "./game-over-phase"; +import BattleScene from "#app/battle-scene"; export class BattleEndPhase extends BattlePhase { + /** If true, will increment battles won */ + isVictory: boolean; + + constructor(scene: BattleScene, isVictory: boolean = true) { + super(scene); + + this.isVictory = isVictory; + } + start() { super.start(); - this.scene.currentBattle.addBattleScore(this.scene); + if (this.isVictory) { + this.scene.currentBattle.addBattleScore(this.scene); - this.scene.gameData.gameStats.battles++; - if (this.scene.currentBattle.trainer) { - this.scene.gameData.gameStats.trainersDefeated++; - } - if (this.scene.gameMode.isEndless && this.scene.currentBattle.waveIndex + 1 > this.scene.gameData.gameStats.highestEndlessWave) { - this.scene.gameData.gameStats.highestEndlessWave = this.scene.currentBattle.waveIndex + 1; + this.scene.gameData.gameStats.battles++; + if (this.scene.currentBattle.trainer) { + this.scene.gameData.gameStats.trainersDefeated++; + } + if (this.scene.gameMode.isEndless && this.scene.currentBattle.waveIndex + 1 > this.scene.gameData.gameStats.highestEndlessWave) { + this.scene.gameData.gameStats.highestEndlessWave = this.scene.currentBattle.waveIndex + 1; + } } // Endless graceful end diff --git a/src/phases/encounter-phase.ts b/src/phases/encounter-phase.ts index 012738df9ab..cead9de0fc6 100644 --- a/src/phases/encounter-phase.ts +++ b/src/phases/encounter-phase.ts @@ -164,7 +164,7 @@ export class EncounterPhase extends BattlePhase { // Load Mystery Encounter Exclamation bubble and sfx loadEnemyAssets.push(new Promise(resolve => { this.scene.loadSe("GEN8- Exclaim", "battle_anims", "GEN8- Exclaim.wav"); - this.scene.loadImage("exclaim", "mystery-encounters"); + this.scene.loadImage("encounter_exclaim", "mystery-encounters"); this.scene.load.once(Phaser.Loader.Events.COMPLETE, () => resolve()); if (!this.scene.load.isLoading()) { this.scene.load.start(); diff --git a/src/phases/game-over-phase.ts b/src/phases/game-over-phase.ts index e6ccca6c95a..b0cfa5c55e2 100644 --- a/src/phases/game-over-phase.ts +++ b/src/phases/game-over-phase.ts @@ -48,6 +48,14 @@ export class GameOverPhase extends BattlePhase { this.victory = true; } + // Handle Mystery Encounter special Game Over cases + // Situations such as when player lost a battle, but it isn't treated as full Game Over + if (!this.victory && this.scene.currentBattle.mysteryEncounter?.onGameOver && !this.scene.currentBattle.mysteryEncounter.onGameOver(this.scene)) { + // Do not end the game + return this.end(); + } + // Otherwise, continue standard Game Over logic + if (this.victory && this.scene.gameMode.isEndless) { const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET; const genderStr = PlayerGender[genderIndex].toLowerCase(); @@ -60,11 +68,6 @@ export class GameOverPhase extends BattlePhase { this.scene.ui.fadeOut(1250).then(() => { this.scene.reset(); this.scene.clearPhaseQueue(); - // If this is a ME, clear any residual visual sprites before reloading - const encounter = this.scene.currentBattle.mysteryEncounter; - if (encounter?.introVisuals) { - this.scene.field.remove(encounter.introVisuals, true); - } this.scene.gameData.loadSession(this.scene, this.scene.sessionSlotId).then(() => { this.scene.pushPhase(new EncounterPhase(this.scene, true)); diff --git a/src/phases/pokemon-heal-phase.ts b/src/phases/pokemon-heal-phase.ts index 49db2641e98..813d15ae87e 100644 --- a/src/phases/pokemon-heal-phase.ts +++ b/src/phases/pokemon-heal-phase.ts @@ -10,6 +10,8 @@ import { HealAchv } from "#app/system/achv"; import i18next from "i18next"; import * as Utils from "#app/utils"; import { CommonAnimPhase } from "./common-anim-phase"; +import { BattlerTagType } from "#app/enums/battler-tag-type"; +import { HealBlockTag } from "#app/data/battler-tags"; export class PokemonHealPhase extends CommonAnimPhase { private hpHealed: integer; @@ -50,9 +52,14 @@ export class PokemonHealPhase extends CommonAnimPhase { const hasMessage = !!this.message; const healOrDamage = (!pokemon.isFullHp() || this.hpHealed < 0); + const healBlock = pokemon.getTag(BattlerTagType.HEAL_BLOCK) as HealBlockTag; let lastStatusEffect = StatusEffect.NONE; - if (healOrDamage) { + if (healBlock && this.hpHealed > 0) { + this.scene.queueMessage(healBlock.onActivation(pokemon)); + this.message = null; + super.end(); + } else if (healOrDamage) { const hpRestoreMultiplier = new Utils.IntegerHolder(1); if (!this.revive) { this.scene.applyModifiers(HealingBoosterModifier, this.player, hpRestoreMultiplier); diff --git a/src/phases/select-target-phase.ts b/src/phases/select-target-phase.ts index 716d2737a6c..6f11f984c4b 100644 --- a/src/phases/select-target-phase.ts +++ b/src/phases/select-target-phase.ts @@ -4,6 +4,8 @@ import { Command } from "#app/ui/command-ui-handler"; import { Mode } from "#app/ui/ui"; import { CommandPhase } from "./command-phase"; import { PokemonPhase } from "./pokemon-phase"; +import i18next from "#app/plugins/i18n"; +import { allMoves } from "#app/data/move"; export class SelectTargetPhase extends PokemonPhase { constructor(scene: BattleScene, fieldIndex: integer) { @@ -17,6 +19,14 @@ export class SelectTargetPhase extends PokemonPhase { const move = turnCommand?.move?.move; this.scene.ui.setMode(Mode.TARGET_SELECT, this.fieldIndex, move, (targets: BattlerIndex[]) => { this.scene.ui.setMode(Mode.MESSAGE); + const fieldSide = this.scene.getField(); + const user = fieldSide[this.fieldIndex]; + const moveObject = allMoves[move!]; + if (moveObject && user.isMoveTargetRestricted(moveObject.id, user, fieldSide[targets[0]])) { + const errorMessage = user.getRestrictingTag(move!, user, fieldSide[targets[0]])!.selectionDeniedText(user, moveObject.id); + user.scene.queueMessage(i18next.t(errorMessage, { moveName: moveObject.name }), 0, true); + targets = []; + } if (targets.length < 1) { this.scene.currentBattle.turnCommands[this.fieldIndex] = null; this.scene.unshiftPhase(new CommandPhase(this.scene, this.fieldIndex)); diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index 0fd90e448a1..8240b6bcf84 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -54,6 +54,7 @@ export default class PokemonData { public fusionVariant: Variant; public fusionGender: Gender; public fusionLuck: integer; + public fusionMysteryEncounterPokemonData: MysteryEncounterPokemonData; public boss: boolean; public bossSegments?: integer; diff --git a/src/test/abilities/arena_trap.test.ts b/src/test/abilities/arena_trap.test.ts new file mode 100644 index 00000000000..6b313fcc8db --- /dev/null +++ b/src/test/abilities/arena_trap.test.ts @@ -0,0 +1,59 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest"; + +describe("Abilities - Arena Trap", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + const TIMEOUT = 20 * 1000; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset(Moves.SPLASH) + .ability(Abilities.ARENA_TRAP) + .enemySpecies(Species.RALTS) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.TELEPORT); + }); + + // TODO: Enable test when Issue #935 is addressed + it.todo("should not allow grounded Pokémon to flee", async () => { + game.override.battleType("single"); + + await game.classicMode.startBattle(); + + const enemy = game.scene.getEnemyPokemon(); + + game.move.select(Moves.SPLASH); + + await game.toNextTurn(); + + expect(enemy).toBe(game.scene.getEnemyPokemon()); + }, TIMEOUT); + + it("should guarantee double battle with any one LURE", async () => { + game.override + .startingModifier([ + { name: "LURE" }, + ]) + .startingWave(2); + + await game.classicMode.startBattle(); + + expect(game.scene.getEnemyField().length).toBe(2); + }, TIMEOUT); +}); diff --git a/src/test/abilities/battle_bond.test.ts b/src/test/abilities/battle_bond.test.ts index 71e9438db8f..4882001cc8d 100644 --- a/src/test/abilities/battle_bond.test.ts +++ b/src/test/abilities/battle_bond.test.ts @@ -7,7 +7,7 @@ import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - BATTLE BOND", () => { let phaserGame: Phaser.Game; @@ -60,6 +60,5 @@ describe("Abilities - BATTLE BOND", () => { expect(greninja!.formIndex).toBe(baseForm); }, - TIMEOUT ); }); diff --git a/src/test/abilities/costar.test.ts b/src/test/abilities/costar.test.ts index 794bed0d3cf..2fd1cb26408 100644 --- a/src/test/abilities/costar.test.ts +++ b/src/test/abilities/costar.test.ts @@ -8,7 +8,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - COSTAR", () => { let phaserGame: Phaser.Game; @@ -59,7 +59,6 @@ describe("Abilities - COSTAR", () => { expect(leftPokemon.getStatStage(Stat.SPATK)).toBe(2); expect(rightPokemon.getStatStage(Stat.SPATK)).toBe(2); }, - TIMEOUT, ); test( @@ -83,6 +82,5 @@ describe("Abilities - COSTAR", () => { expect(leftPokemon.getStatStage(Stat.ATK)).toBe(-2); expect(rightPokemon.getStatStage(Stat.ATK)).toBe(-2); }, - TIMEOUT, ); }); diff --git a/src/test/abilities/dancer.test.ts b/src/test/abilities/dancer.test.ts index ec5ce53f4c3..7564a254dbe 100644 --- a/src/test/abilities/dancer.test.ts +++ b/src/test/abilities/dancer.test.ts @@ -7,7 +7,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - Dancer", () => { let phaserGame: Phaser.Game; @@ -60,5 +60,5 @@ describe("Abilities - Dancer", () => { // doesn't use PP if copied move is also in moveset expect(oricorio.moveset[0]?.ppUsed).toBe(0); - }, TIMEOUT); + }); }); diff --git a/src/test/abilities/disguise.test.ts b/src/test/abilities/disguise.test.ts index fa7f26d2716..0268a738c0e 100644 --- a/src/test/abilities/disguise.test.ts +++ b/src/test/abilities/disguise.test.ts @@ -7,7 +7,7 @@ import { Stat } from "#enums/stat"; import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - Disguise", () => { let phaserGame: Phaser.Game; @@ -33,7 +33,7 @@ describe("Abilities - Disguise", () => { .enemyMoveset(Moves.SPLASH) .starterSpecies(Species.REGIELEKI) .moveset([Moves.SHADOW_SNEAK, Moves.VACUUM_WAVE, Moves.TOXIC_THREAD, Moves.SPLASH]); - }, TIMEOUT); + }); it("takes no damage from attacking move and transforms to Busted form, takes 1/8 max HP damage from the disguise breaking", async () => { await game.classicMode.startBattle(); @@ -50,7 +50,7 @@ describe("Abilities - Disguise", () => { expect(mimikyu.hp).equals(maxHp - disguiseDamage); expect(mimikyu.formIndex).toBe(bustedForm); - }, TIMEOUT); + }); it("doesn't break disguise when attacked with ineffective move", async () => { await game.classicMode.startBattle(); @@ -64,7 +64,7 @@ describe("Abilities - Disguise", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(mimikyu.formIndex).toBe(disguisedForm); - }, TIMEOUT); + }); it("takes no damage from the first hit of a multihit move and transforms to Busted form, then takes damage from the second hit", async () => { game.override.moveset([ Moves.SURGING_STRIKES ]); @@ -88,7 +88,7 @@ describe("Abilities - Disguise", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(mimikyu.hp).lessThan(maxHp - disguiseDamage); expect(mimikyu.formIndex).toBe(bustedForm); - }, TIMEOUT); + }); it("takes effects from status moves and damage from status effects", async () => { await game.classicMode.startBattle(); @@ -104,7 +104,7 @@ describe("Abilities - Disguise", () => { expect(mimikyu.status?.effect).toBe(StatusEffect.POISON); expect(mimikyu.getStatStage(Stat.SPD)).toBe(-1); expect(mimikyu.hp).toBeLessThan(mimikyu.getMaxHp()); - }, TIMEOUT); + }); it("persists form change when switched out", async () => { game.override.enemyMoveset([Moves.SHADOW_SNEAK]); @@ -129,7 +129,7 @@ describe("Abilities - Disguise", () => { await game.phaseInterceptor.to("TurnEndPhase"); expect(mimikyu.formIndex).toBe(bustedForm); - }, TIMEOUT); + }); it("persists form change when wave changes with no arena reset", async () => { game.override.starterSpecies(0); @@ -146,7 +146,7 @@ describe("Abilities - Disguise", () => { await game.toNextWave(); expect(mimikyu.formIndex).toBe(bustedForm); - }, TIMEOUT); + }); it("reverts to Disguised form on arena reset", async () => { game.override.startingWave(4); @@ -166,7 +166,7 @@ describe("Abilities - Disguise", () => { await game.toNextWave(); expect(mimikyu.formIndex).toBe(disguisedForm); - }, TIMEOUT); + }); it("reverts to Disguised form on biome change when fainted", async () => { game.override.startingWave(10); @@ -190,7 +190,7 @@ describe("Abilities - Disguise", () => { await game.phaseInterceptor.to("PartyHealPhase"); expect(mimikyu1.formIndex).toBe(disguisedForm); - }, TIMEOUT); + }); it("doesn't faint twice when fainting due to Disguise break damage, nor prevent faint from Disguise break damage if using Endure", async () => { game.override.enemyMoveset([Moves.ENDURE]); @@ -204,7 +204,7 @@ describe("Abilities - Disguise", () => { expect(game.scene.getCurrentPhase()?.constructor.name).toBe("CommandPhase"); expect(game.scene.currentBattle.waveIndex).toBe(2); - }, TIMEOUT); + }); it("activates when Aerilate circumvents immunity to the move's base type", async () => { game.override.ability(Abilities.AERILATE); @@ -222,5 +222,5 @@ describe("Abilities - Disguise", () => { expect(mimikyu.formIndex).toBe(bustedForm); expect(mimikyu.hp).toBe(maxHp - disguiseDamage); - }, TIMEOUT); + }); }); diff --git a/src/test/abilities/galvanize.test.ts b/src/test/abilities/galvanize.test.ts index f81b854180a..1b7dde9ba60 100644 --- a/src/test/abilities/galvanize.test.ts +++ b/src/test/abilities/galvanize.test.ts @@ -9,7 +9,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - Galvanize", () => { let phaserGame: Phaser.Game; @@ -59,7 +59,7 @@ describe("Abilities - Galvanize", () => { expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.EFFECTIVE); expect(move.calculateBattlePower).toHaveReturnedWith(48); expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); - }, TIMEOUT); + }); it("should cause Normal-type attacks to activate Volt Absorb", async () => { game.override.enemyAbility(Abilities.VOLT_ABSORB); @@ -81,7 +81,7 @@ describe("Abilities - Galvanize", () => { expect(playerPokemon.getMoveType).toHaveLastReturnedWith(Type.ELECTRIC); expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.NO_EFFECT); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); - }, TIMEOUT); + }); it("should not change the type of variable-type moves", async () => { game.override.enemySpecies(Species.MIGHTYENA); @@ -100,7 +100,7 @@ describe("Abilities - Galvanize", () => { expect(playerPokemon.getMoveType).not.toHaveLastReturnedWith(Type.ELECTRIC); expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.NO_EFFECT); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); - }, TIMEOUT); + }); it("should affect all hits of a Normal-type multi-hit move", async () => { await game.startBattle(); @@ -128,5 +128,5 @@ describe("Abilities - Galvanize", () => { } expect(enemyPokemon.apply).not.toHaveReturnedWith(HitResult.NO_EFFECT); - }, TIMEOUT); + }); }); diff --git a/src/test/abilities/gorilla_tactics.test.ts b/src/test/abilities/gorilla_tactics.test.ts index df698194323..5e92950526e 100644 --- a/src/test/abilities/gorilla_tactics.test.ts +++ b/src/test/abilities/gorilla_tactics.test.ts @@ -10,8 +10,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("Abilities - Gorilla Tactics", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -49,7 +47,7 @@ describe("Abilities - Gorilla Tactics", () => { // Other moves should be restricted expect(darmanitan.isMoveRestricted(Moves.TACKLE)).toBe(true); expect(darmanitan.isMoveRestricted(Moves.SPLASH)).toBe(false); - }, TIMEOUT); + }); it("should struggle if the only usable move is disabled", async () => { await game.classicMode.startBattle([Species.GALAR_DARMANITAN]); @@ -79,5 +77,5 @@ describe("Abilities - Gorilla Tactics", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(darmanitan.hp).toBeLessThan(darmanitan.getMaxHp()); - }, TIMEOUT); + }); }); diff --git a/src/test/abilities/illuminate.test.ts b/src/test/abilities/illuminate.test.ts new file mode 100644 index 00000000000..73e4a49be95 --- /dev/null +++ b/src/test/abilities/illuminate.test.ts @@ -0,0 +1,59 @@ +import { Stat } from "#app/enums/stat"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest"; + +describe("Abilities - Illuminate", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + const TIMEOUT = 20 * 1000; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset(Moves.SPLASH) + .ability(Abilities.ILLUMINATE) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SAND_ATTACK); + }); + + it("should prevent ACC stat stage from being lowered", async () => { + game.override.battleType("single"); + + await game.classicMode.startBattle(); + + const player = game.scene.getPlayerPokemon()!; + + expect(player.getStatStage(Stat.ACC)).toBe(0); + + game.move.select(Moves.SPLASH); + + await game.toNextTurn(); + + expect(player.getStatStage(Stat.ACC)).toBe(0); + }, TIMEOUT); + + it("should guarantee double battle with any one LURE", async () => { + game.override + .startingModifier([ + { name: "LURE" }, + ]) + .startingWave(2); + + await game.classicMode.startBattle(); + + expect(game.scene.getEnemyField().length).toBe(2); + }, TIMEOUT); +}); diff --git a/src/test/abilities/libero.test.ts b/src/test/abilities/libero.test.ts index 51f182d5401..f429d9ffc72 100644 --- a/src/test/abilities/libero.test.ts +++ b/src/test/abilities/libero.test.ts @@ -12,7 +12,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - Libero", () => { let phaserGame: Phaser.Game; @@ -52,7 +52,6 @@ describe("Abilities - Libero", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.SPLASH); }, - TIMEOUT, ); test.skip( @@ -92,7 +91,6 @@ describe("Abilities - Libero", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.SPLASH); }, - TIMEOUT, ); test( @@ -115,7 +113,6 @@ describe("Abilities - Libero", () => { moveType = Type[Type.FIRE]; expect(leadPokemonType).toBe(moveType); }, - TIMEOUT, ); test( @@ -138,7 +135,6 @@ describe("Abilities - Libero", () => { moveType = Type[Type.ICE]; expect(leadPokemonType).toBe(moveType); }, - TIMEOUT, ); test( @@ -157,7 +153,6 @@ describe("Abilities - Libero", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.AIR_SLASH); }, - TIMEOUT, ); test( @@ -175,7 +170,6 @@ describe("Abilities - Libero", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.DIG); }, - TIMEOUT, ); test( @@ -197,7 +191,6 @@ describe("Abilities - Libero", () => { expect(enemyPokemon.isFullHp()).toBe(true); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); }, - TIMEOUT, ); test( @@ -216,7 +209,6 @@ describe("Abilities - Libero", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); }, - TIMEOUT, ); test( @@ -235,7 +227,6 @@ describe("Abilities - Libero", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); }, - TIMEOUT, ); test( @@ -254,7 +245,6 @@ describe("Abilities - Libero", () => { expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.LIBERO); }, - TIMEOUT, ); test( @@ -274,7 +264,6 @@ describe("Abilities - Libero", () => { expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.LIBERO); }, - TIMEOUT, ); test( @@ -292,7 +281,6 @@ describe("Abilities - Libero", () => { expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.LIBERO); }, - TIMEOUT, ); test( @@ -310,7 +298,6 @@ describe("Abilities - Libero", () => { expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.LIBERO); }, - TIMEOUT, ); test( @@ -329,7 +316,6 @@ describe("Abilities - Libero", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TRICK_OR_TREAT); }, - TIMEOUT, ); test( @@ -348,7 +334,6 @@ describe("Abilities - Libero", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.CURSE); expect(leadPokemon.getTag(BattlerTagType.CURSED)).not.toBe(undefined); }, - TIMEOUT, ); }); diff --git a/src/test/abilities/magic_guard.test.ts b/src/test/abilities/magic_guard.test.ts index 4b3fb0ba985..dd8b83f7601 100644 --- a/src/test/abilities/magic_guard.test.ts +++ b/src/test/abilities/magic_guard.test.ts @@ -11,8 +11,6 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; // 20 sec timeout - describe("Abilities - Magic Guard", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -67,7 +65,7 @@ describe("Abilities - Magic Guard", () => { */ expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); it( @@ -91,7 +89,7 @@ describe("Abilities - Magic Guard", () => { */ expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); expect(getStatusEffectCatchRateMultiplier(leadPokemon.status!.effect)).toBe(1.5); - }, TIMEOUT + } ); it( @@ -113,7 +111,7 @@ describe("Abilities - Magic Guard", () => { * - The player Pokemon (that just lost its Magic Guard ability) has taken damage from poison */ expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); @@ -138,7 +136,7 @@ describe("Abilities - Magic Guard", () => { */ expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); expect(getStatusEffectCatchRateMultiplier(enemyPokemon.status!.effect)).toBe(1.5); - }, TIMEOUT + } ); it("Magic Guard prevents damage caused by toxic but other non-damaging effects are still applied", @@ -166,7 +164,7 @@ describe("Abilities - Magic Guard", () => { expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); expect(enemyPokemon.status!.turnCount).toBeGreaterThan(toxicStartCounter); expect(getStatusEffectCatchRateMultiplier(enemyPokemon.status!.effect)).toBe(1.5); - }, TIMEOUT + } ); @@ -191,7 +189,7 @@ describe("Abilities - Magic Guard", () => { */ expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); it("Magic Guard does not prevent poison from Toxic Spikes", async () => { @@ -220,7 +218,7 @@ describe("Abilities - Magic Guard", () => { expect(enemyPokemon.status!.effect).toBe(StatusEffect.POISON); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); it("Magic Guard prevents against damage from volatile status effects", @@ -246,7 +244,7 @@ describe("Abilities - Magic Guard", () => { expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); expect(enemyPokemon.getTag(BattlerTagType.CURSED)).not.toBe(undefined); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); it("Magic Guard prevents crash damage", async () => { @@ -265,7 +263,7 @@ describe("Abilities - Magic Guard", () => { * - The player Pokemon (with Magic Guard) misses High Jump Kick but does not lose HP as a result */ expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); it("Magic Guard prevents damage from recoil", async () => { @@ -283,7 +281,7 @@ describe("Abilities - Magic Guard", () => { * - The player Pokemon (with Magic Guard) uses a recoil move but does not lose HP from recoil */ expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); it("Magic Guard does not prevent damage from Struggle's recoil", async () => { @@ -301,7 +299,7 @@ describe("Abilities - Magic Guard", () => { * - The player Pokemon (with Magic Guard) uses Struggle but does lose HP from Struggle's recoil */ expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); //This tests different move attributes than the recoil tests above @@ -320,7 +318,7 @@ describe("Abilities - Magic Guard", () => { * - The player Pokemon (with Magic Guard) uses a move with an HP cost but does not lose HP from using it */ expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); /* @@ -348,7 +346,7 @@ describe("Abilities - Magic Guard", () => { * - The player Pokemon (with Magic Guard) uses a non-attacking move with an HP cost and thus loses HP from using it */ expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); it("Magic Guard prevents damage from abilities with PostTurnHurtIfSleepingAbAttr", async () => { @@ -373,7 +371,7 @@ describe("Abilities - Magic Guard", () => { */ expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); expect(leadPokemon.status!.effect).toBe(StatusEffect.SLEEP); - }, TIMEOUT + } ); it("Magic Guard prevents damage from abilities with PostFaintContactDamageAbAttr", async () => { @@ -398,7 +396,7 @@ describe("Abilities - Magic Guard", () => { */ expect(enemyPokemon.hp).toBe(0); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); it("Magic Guard prevents damage from abilities with PostDefendContactDamageAbAttr", async () => { @@ -422,7 +420,7 @@ describe("Abilities - Magic Guard", () => { */ expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); it("Magic Guard prevents damage from abilities with ReverseDrainAbAttr", async () => { @@ -446,7 +444,7 @@ describe("Abilities - Magic Guard", () => { */ expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); it("Magic Guard prevents HP loss from abilities with PostWeatherLapseDamageAbAttr", async () => { @@ -464,6 +462,6 @@ describe("Abilities - Magic Guard", () => { * - The player Pokemon (with Magic Guard) should not lose HP due to this ability attribute */ expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); }); diff --git a/src/test/abilities/no_guard.test.ts b/src/test/abilities/no_guard.test.ts new file mode 100644 index 00000000000..b793ede7099 --- /dev/null +++ b/src/test/abilities/no_guard.test.ts @@ -0,0 +1,68 @@ +import { BattlerIndex } from "#app/battle"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { MoveEndPhase } from "#app/phases/move-end-phase"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest"; + +describe("Abilities - No Guard", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + const TIMEOUT = 20 * 1000; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset(Moves.ZAP_CANNON) + .ability(Abilities.NO_GUARD) + .enemyLevel(200) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should make moves always hit regardless of move accuracy", async () => { + game.override.battleType("single"); + + await game.classicMode.startBattle([ + Species.REGIELEKI + ]); + + game.move.select(Moves.ZAP_CANNON); + + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + + await game.phaseInterceptor.to(MoveEffectPhase, false); + + const moveEffectPhase = game.scene.getCurrentPhase() as MoveEffectPhase; + vi.spyOn(moveEffectPhase, "hitCheck"); + + await game.phaseInterceptor.to(MoveEndPhase); + + expect(moveEffectPhase.hitCheck).toHaveReturnedWith(true); + }, TIMEOUT); + + it("should guarantee double battle with any one LURE", async () => { + game.override + .startingModifier([ + { name: "LURE" }, + ]) + .startingWave(2); + + await game.classicMode.startBattle(); + + expect(game.scene.getEnemyField().length).toBe(2); + }, TIMEOUT); +}); diff --git a/src/test/abilities/parental_bond.test.ts b/src/test/abilities/parental_bond.test.ts index 2ad3f9e3f5c..22c9d8028be 100644 --- a/src/test/abilities/parental_bond.test.ts +++ b/src/test/abilities/parental_bond.test.ts @@ -10,7 +10,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - Parental Bond", () => { let phaserGame: Phaser.Game; @@ -62,7 +62,7 @@ describe("Abilities - Parental Bond", () => { expect(leadPokemon.turnData.hitCount).toBe(2); expect(secondStrikeDamage).toBe(toDmgValue(0.25 * firstStrikeDamage)); - }, TIMEOUT + } ); it( @@ -81,7 +81,7 @@ describe("Abilities - Parental Bond", () => { expect(leadPokemon.turnData.hitCount).toBe(2); expect(leadPokemon.getStatStage(Stat.ATK)).toBe(2); - }, TIMEOUT + } ); it( @@ -98,7 +98,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1); - }, TIMEOUT + } ); it( @@ -116,7 +116,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(leadPokemon.turnData.hitCount).toBe(2); - }, TIMEOUT + } ); it( @@ -133,7 +133,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("DamagePhase", false); expect(leadPokemon.turnData.hitCount).toBe(1); - }, TIMEOUT + } ); it( @@ -151,7 +151,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("DamagePhase", false); expect(leadPokemon.turnData.hitCount).toBe(1); - }, TIMEOUT + } ); it( @@ -167,7 +167,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp() - 80); - }, TIMEOUT + } ); it( @@ -189,7 +189,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp() - 4 * playerDamage); - }, TIMEOUT + } ); it( @@ -209,7 +209,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("BerryPhase", false); playerPokemon.forEach(p => expect(p.turnData.hitCount).toBe(1)); - }, TIMEOUT + } ); it( @@ -225,7 +225,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("DamagePhase", false); expect(leadPokemon.turnData.hitCount).toBe(2); - }, TIMEOUT + } ); it( @@ -247,7 +247,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(leadPokemon.hp).toBe(Math.ceil(leadPokemon.getMaxHp() / 2)); - }, TIMEOUT + } ); it( @@ -271,7 +271,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(leadPokemon.isOfType(Type.FIRE)).toBe(false); - }, TIMEOUT + } ); it( @@ -289,7 +289,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("DamagePhase"); expect(leadPokemon.turnData.hitCount).toBe(4); - }, TIMEOUT + } ); it( @@ -313,7 +313,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("MoveEndPhase", false); expect(enemyPokemon.hp).toBe(Math.ceil(enemyPokemon.getMaxHp() * 0.25)); - }, TIMEOUT + } ); it( @@ -339,7 +339,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("MoveEndPhase", false); expect(enemyPokemon.hp).toBe(enemyStartingHp - 200); - }, TIMEOUT + } ); it( @@ -362,7 +362,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("TurnEndPhase"); expect(leadPokemon.getTag(BattlerTagType.RECHARGING)).toBeDefined(); - }, TIMEOUT + } ); it( @@ -389,7 +389,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("TurnEndPhase"); expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeDefined(); - }, TIMEOUT + } ); it( @@ -413,7 +413,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("TurnEndPhase"); expect(enemyPokemon.getTag(BattlerTagType.IGNORE_FLYING)).toBeDefined(); - }, TIMEOUT + } ); it( @@ -433,7 +433,7 @@ describe("Abilities - Parental Bond", () => { // This will cause this test to time out if the switch was forced on the first hit. await game.phaseInterceptor.to("MoveEffectPhase", false); - }, TIMEOUT + } ); it( @@ -457,7 +457,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.status?.effect).toBeUndefined(); - }, TIMEOUT + } ); it( @@ -475,7 +475,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(leadPokemon.getStatStage(Stat.ATK)).toBe(-1); - }, TIMEOUT + } ); it( @@ -493,7 +493,7 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(1); - }, TIMEOUT + } ); it( @@ -519,6 +519,6 @@ describe("Abilities - Parental Bond", () => { await game.phaseInterceptor.to("BerryPhase", false); enemyPokemon.forEach((p, i) => expect(enemyStartingHp[i] - p.hp).toBe(2 * enemyFirstHitDamage[i])); - }, TIMEOUT + } ); }); diff --git a/src/test/abilities/power_construct.test.ts b/src/test/abilities/power_construct.test.ts index ec37bc96c2f..94cee82fb4a 100644 --- a/src/test/abilities/power_construct.test.ts +++ b/src/test/abilities/power_construct.test.ts @@ -7,7 +7,7 @@ import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - POWER CONSTRUCT", () => { let phaserGame: Phaser.Game; @@ -60,6 +60,5 @@ describe("Abilities - POWER CONSTRUCT", () => { expect(zygarde!.formIndex).toBe(baseForm); }, - TIMEOUT ); }); diff --git a/src/test/abilities/protean.test.ts b/src/test/abilities/protean.test.ts index 4be58a677a6..8479a293722 100644 --- a/src/test/abilities/protean.test.ts +++ b/src/test/abilities/protean.test.ts @@ -12,7 +12,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - Protean", () => { let phaserGame: Phaser.Game; @@ -52,7 +52,6 @@ describe("Abilities - Protean", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.SPLASH); }, - TIMEOUT, ); test.skip( @@ -92,7 +91,6 @@ describe("Abilities - Protean", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.SPLASH); }, - TIMEOUT, ); test( @@ -115,7 +113,6 @@ describe("Abilities - Protean", () => { moveType = Type[Type.FIRE]; expect(leadPokemonType).toBe(moveType); }, - TIMEOUT, ); test( @@ -138,7 +135,6 @@ describe("Abilities - Protean", () => { moveType = Type[Type.ICE]; expect(leadPokemonType).toBe(moveType); }, - TIMEOUT, ); test( @@ -157,7 +153,6 @@ describe("Abilities - Protean", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.AIR_SLASH); }, - TIMEOUT, ); test( @@ -175,7 +170,6 @@ describe("Abilities - Protean", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.DIG); }, - TIMEOUT, ); test( @@ -197,7 +191,6 @@ describe("Abilities - Protean", () => { expect(enemyPokemon.isFullHp()).toBe(true); testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); }, - TIMEOUT, ); test( @@ -216,7 +209,6 @@ describe("Abilities - Protean", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); }, - TIMEOUT, ); test( @@ -235,7 +227,6 @@ describe("Abilities - Protean", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TACKLE); }, - TIMEOUT, ); test( @@ -254,7 +245,6 @@ describe("Abilities - Protean", () => { expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.PROTEAN); }, - TIMEOUT, ); test( @@ -274,7 +264,6 @@ describe("Abilities - Protean", () => { expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.PROTEAN); }, - TIMEOUT, ); test( @@ -292,7 +281,6 @@ describe("Abilities - Protean", () => { expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.PROTEAN); }, - TIMEOUT, ); test( @@ -310,7 +298,6 @@ describe("Abilities - Protean", () => { expect(leadPokemon.summonData.abilitiesApplied).not.toContain(Abilities.PROTEAN); }, - TIMEOUT, ); test( @@ -329,7 +316,6 @@ describe("Abilities - Protean", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.TRICK_OR_TREAT); }, - TIMEOUT, ); test( @@ -348,7 +334,6 @@ describe("Abilities - Protean", () => { testPokemonTypeMatchesDefaultMoveType(leadPokemon, Moves.CURSE); expect(leadPokemon.getTag(BattlerTagType.CURSED)).not.toBe(undefined); }, - TIMEOUT, ); }); diff --git a/src/test/abilities/quick_draw.test.ts b/src/test/abilities/quick_draw.test.ts index a02ee5cf56a..dbed6c822c4 100644 --- a/src/test/abilities/quick_draw.test.ts +++ b/src/test/abilities/quick_draw.test.ts @@ -55,7 +55,6 @@ describe("Abilities - Quick Draw", () => { }, 20000); test("does not triggered by non damage moves", { - timeout: 20000, retry: 5 }, async () => { await game.startBattle(); diff --git a/src/test/abilities/sand_veil.test.ts b/src/test/abilities/sand_veil.test.ts index da9fdcc01ab..201d8d89600 100644 --- a/src/test/abilities/sand_veil.test.ts +++ b/src/test/abilities/sand_veil.test.ts @@ -11,7 +11,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - Sand Veil", () => { let phaserGame: Phaser.Game; @@ -75,6 +75,6 @@ describe("Abilities - Sand Veil", () => { expect(leadPokemon[0].isFullHp()).toBe(true); expect(leadPokemon[1].hp).toBeLessThan(leadPokemon[1].getMaxHp()); - }, TIMEOUT + } ); }); diff --git a/src/test/abilities/schooling.test.ts b/src/test/abilities/schooling.test.ts index ad9663bf8e5..4c5a66a41b7 100644 --- a/src/test/abilities/schooling.test.ts +++ b/src/test/abilities/schooling.test.ts @@ -7,7 +7,7 @@ import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - SCHOOLING", () => { let phaserGame: Phaser.Game; @@ -60,6 +60,5 @@ describe("Abilities - SCHOOLING", () => { expect(wishiwashi.formIndex).toBe(soloForm); }, - TIMEOUT ); }); diff --git a/src/test/abilities/shields_down.test.ts b/src/test/abilities/shields_down.test.ts index 9bfec23ddf1..411c23fc652 100644 --- a/src/test/abilities/shields_down.test.ts +++ b/src/test/abilities/shields_down.test.ts @@ -7,7 +7,7 @@ import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - SHIELDS DOWN", () => { let phaserGame: Phaser.Game; @@ -60,6 +60,5 @@ describe("Abilities - SHIELDS DOWN", () => { expect(minior.formIndex).toBe(meteorForm); }, - TIMEOUT ); }); diff --git a/src/test/abilities/sturdy.test.ts b/src/test/abilities/sturdy.test.ts index dc9f774cc5b..c329d0830d3 100644 --- a/src/test/abilities/sturdy.test.ts +++ b/src/test/abilities/sturdy.test.ts @@ -8,7 +8,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - Sturdy", () => { let phaserGame: Phaser.Game; @@ -45,7 +45,6 @@ describe("Abilities - Sturdy", () => { await game.phaseInterceptor.to(MoveEndPhase); expect(game.scene.getEnemyParty()[0].hp).toBe(1); }, - TIMEOUT ); test( @@ -62,7 +61,6 @@ describe("Abilities - Sturdy", () => { expect(enemyPokemon.hp).toBe(0); expect(enemyPokemon.isFainted()).toBe(true); }, - TIMEOUT ); test( @@ -75,7 +73,6 @@ describe("Abilities - Sturdy", () => { const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; expect(enemyPokemon.isFullHp()).toBe(true); }, - TIMEOUT ); test( @@ -91,7 +88,6 @@ describe("Abilities - Sturdy", () => { expect(enemyPokemon.hp).toBe(0); expect(enemyPokemon.isFainted()).toBe(true); }, - TIMEOUT ); }); diff --git a/src/test/abilities/tera_shell.test.ts b/src/test/abilities/tera_shell.test.ts index 2826469f3bf..13df49136ca 100644 --- a/src/test/abilities/tera_shell.test.ts +++ b/src/test/abilities/tera_shell.test.ts @@ -6,8 +6,6 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -const TIMEOUT = 10 * 1000; // 10 second timeout - describe("Abilities - Tera Shell", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -54,7 +52,7 @@ describe("Abilities - Tera Shell", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(playerPokemon.getMoveEffectiveness).toHaveLastReturnedWith(2); - }, TIMEOUT + } ); it( @@ -71,7 +69,7 @@ describe("Abilities - Tera Shell", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(playerPokemon.getMoveEffectiveness).toHaveLastReturnedWith(0); - }, TIMEOUT + } ); it( @@ -88,7 +86,7 @@ describe("Abilities - Tera Shell", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(playerPokemon.getMoveEffectiveness).toHaveLastReturnedWith(0.25); - }, TIMEOUT + } ); it( @@ -106,6 +104,6 @@ describe("Abilities - Tera Shell", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(playerPokemon.apply).toHaveLastReturnedWith(HitResult.EFFECTIVE); expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp() - 40); - }, TIMEOUT + } ); }); diff --git a/src/test/abilities/unseen_fist.test.ts b/src/test/abilities/unseen_fist.test.ts index 813880c7326..0f285abd98f 100644 --- a/src/test/abilities/unseen_fist.test.ts +++ b/src/test/abilities/unseen_fist.test.ts @@ -8,7 +8,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import { BerryPhase } from "#app/phases/berry-phase"; -const TIMEOUT = 20 * 1000; + describe("Abilities - Unseen Fist", () => { let phaserGame: Phaser.Game; @@ -37,13 +37,11 @@ describe("Abilities - Unseen Fist", () => { it( "should cause a contact move to ignore Protect", () => testUnseenFistHitResult(game, Moves.QUICK_ATTACK, Moves.PROTECT, true), - TIMEOUT ); it( "should not cause a non-contact move to ignore Protect", () => testUnseenFistHitResult(game, Moves.ABSORB, Moves.PROTECT, false), - TIMEOUT ); it( @@ -51,19 +49,17 @@ describe("Abilities - Unseen Fist", () => { () => { game.override.passiveAbility(Abilities.LONG_REACH); testUnseenFistHitResult(game, Moves.QUICK_ATTACK, Moves.PROTECT, false); - }, TIMEOUT + } ); it( "should cause a contact move to ignore Wide Guard", () => testUnseenFistHitResult(game, Moves.BREAKING_SWIPE, Moves.WIDE_GUARD, true), - TIMEOUT ); it( "should not cause a non-contact move to ignore Wide Guard", () => testUnseenFistHitResult(game, Moves.BULLDOZE, Moves.WIDE_GUARD, false), - TIMEOUT ); it( @@ -83,7 +79,7 @@ describe("Abilities - Unseen Fist", () => { expect(enemyPokemon.getTag(BattlerTagType.SUBSTITUTE)).toBeUndefined(); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); }); diff --git a/src/test/abilities/zen_mode.test.ts b/src/test/abilities/zen_mode.test.ts index fd378647184..c7cbd9014e0 100644 --- a/src/test/abilities/zen_mode.test.ts +++ b/src/test/abilities/zen_mode.test.ts @@ -19,7 +19,7 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; import { Status, StatusEffect } from "#app/data/status-effect"; -const TIMEOUT = 20 * 1000; + describe("Abilities - ZEN MODE", () => { let phaserGame: Phaser.Game; @@ -67,7 +67,6 @@ describe("Abilities - ZEN MODE", () => { expect(game.scene.getParty()[0].hp).toBeLessThan(100); expect(game.scene.getParty()[0].formIndex).toBe(0); }, - TIMEOUT ); test( @@ -87,7 +86,6 @@ describe("Abilities - ZEN MODE", () => { expect(game.scene.getParty()[0].hp).not.toBe(100); expect(game.scene.getParty()[0].formIndex).not.toBe(0); }, - TIMEOUT ); test( @@ -125,7 +123,6 @@ describe("Abilities - ZEN MODE", () => { await game.phaseInterceptor.to(PostSummonPhase); expect(game.scene.getParty()[1].formIndex).toBe(1); }, - TIMEOUT ); test( @@ -156,6 +153,5 @@ describe("Abilities - ZEN MODE", () => { expect(darmanitan.formIndex).toBe(baseForm); }, - TIMEOUT ); }); diff --git a/src/test/abilities/zero_to_hero.test.ts b/src/test/abilities/zero_to_hero.test.ts index eafc32b4c79..a7f7c970218 100644 --- a/src/test/abilities/zero_to_hero.test.ts +++ b/src/test/abilities/zero_to_hero.test.ts @@ -7,7 +7,7 @@ import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Abilities - ZERO TO HERO", () => { let phaserGame: Phaser.Game; @@ -59,7 +59,7 @@ describe("Abilities - ZERO TO HERO", () => { expect(palafin1.formIndex).toBe(baseForm); expect(palafin2.formIndex).toBe(baseForm); - }, TIMEOUT); + }); it("should swap to Hero form when switching out during a battle", async () => { await game.startBattle([Species.PALAFIN, Species.FEEBAS]); @@ -70,7 +70,7 @@ describe("Abilities - ZERO TO HERO", () => { game.doSwitchPokemon(1); await game.phaseInterceptor.to(QuietFormChangePhase); expect(palafin.formIndex).toBe(heroForm); - }, TIMEOUT); + }); it("should not swap to Hero form if switching due to faint", async () => { await game.startBattle([Species.PALAFIN, Species.FEEBAS]); @@ -83,7 +83,7 @@ describe("Abilities - ZERO TO HERO", () => { game.doSelectPartyPokemon(1); await game.toNextTurn(); expect(palafin.formIndex).toBe(baseForm); - }, TIMEOUT); + }); it("should stay hero form if fainted and then revived", async () => { game.override.starterForms({ @@ -105,5 +105,5 @@ describe("Abilities - ZERO TO HERO", () => { await game.toNextTurn(); expect(palafin.formIndex).toBe(heroForm); - }, TIMEOUT); + }); }); diff --git a/src/test/arena/grassy_terrain.test.ts b/src/test/arena/grassy_terrain.test.ts index efb2539885d..01bbc778ded 100644 --- a/src/test/arena/grassy_terrain.test.ts +++ b/src/test/arena/grassy_terrain.test.ts @@ -9,8 +9,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite describe("Arena - Grassy Terrain", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -52,7 +50,7 @@ describe("Arena - Grassy Terrain", () => { await game.phaseInterceptor.to("BerryPhase"); expect(eq.calculateBattlePower).toHaveReturnedWith(50); - }, TIMEOUT); + }); it("Does not halve the damage of Earthquake if opponent is not grounded", async () => { await game.classicMode.startBattle([Species.NINJASK]); @@ -67,5 +65,5 @@ describe("Arena - Grassy Terrain", () => { await game.phaseInterceptor.to("BerryPhase"); expect(eq.calculateBattlePower).toHaveReturnedWith(100); - }, TIMEOUT); + }); }); diff --git a/src/test/battle/inverse_battle.test.ts b/src/test/battle/inverse_battle.test.ts index d808f71addb..01a0348e730 100644 --- a/src/test/battle/inverse_battle.test.ts +++ b/src/test/battle/inverse_battle.test.ts @@ -10,7 +10,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Inverse Battle", () => { let phaserGame: Phaser.Game; @@ -56,7 +56,7 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); - }, TIMEOUT); + }); it("2x effective types are 0.5x effective - Thunderbolt against Flying Type", async () => { game.override @@ -73,7 +73,7 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(0.5); - }, TIMEOUT); + }); it("0.5x effective types are 2x effective - Thunderbolt against Electric Type", async () => { game.override @@ -90,7 +90,7 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); - }, TIMEOUT); + }); it("Stealth Rock follows the inverse matchups - Stealth Rock against Charizard deals 1/32 of max HP", async () => { game.scene.arena.addTag(ArenaTagType.STEALTH_ROCK, 1, Moves.STEALTH_ROCK, 0); @@ -110,7 +110,7 @@ describe("Inverse Battle", () => { console.log("Charizard's max HP: " + maxHp, "Damage: " + damage_prediction, "Current HP: " + currentHp, "Expected HP: " + expectedHP); expect(currentHp).toBeGreaterThan(maxHp * 31 / 32 - 1); - }, TIMEOUT); + }); it("Freeze Dry is 2x effective against Water Type like other Ice type Move - Freeze Dry against Squirtle", async () => { game.override @@ -127,7 +127,7 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); - }, TIMEOUT); + }); it("Water Absorb should heal against water moves - Water Absorb against Water gun", async () => { game.override @@ -143,7 +143,7 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.hp).toBe(enemy.getMaxHp()); - }, TIMEOUT); + }); it("Fire type does not get burned - Will-O-Wisp against Charmander", async () => { game.override @@ -160,7 +160,7 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.status?.effect).not.toBe(StatusEffect.BURN); - }, TIMEOUT); + }); it("Electric type does not get paralyzed - Nuzzle against Pikachu", async () => { game.override @@ -177,7 +177,7 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.status?.effect).not.toBe(StatusEffect.PARALYSIS); - }, TIMEOUT); + }); it("Ground type is not immune to Thunder Wave - Thunder Wave against Sandshrew", async () => { game.override @@ -194,7 +194,7 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.status?.effect).toBe(StatusEffect.PARALYSIS); - }, TIMEOUT); + }); it("Anticipation should trigger on 2x effective moves - Anticipation against Thunderbolt", async () => { @@ -206,7 +206,7 @@ describe("Inverse Battle", () => { await game.challengeMode.startBattle(); expect(game.scene.getEnemyPokemon()?.summonData.abilitiesApplied[0]).toBe(Abilities.ANTICIPATION); - }, TIMEOUT); + }); it("Conversion 2 should change the type to the resistive type - Conversion 2 against Dragonite", async () => { game.override @@ -223,7 +223,7 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("TurnEndPhase"); expect(player.getTypes()[0]).toBe(Type.DRAGON); - }, TIMEOUT); + }); it("Flying Press should be 0.25x effective against Grass + Dark Type - Flying Press against Meowscarada", async () => { game.override @@ -240,7 +240,7 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(0.25); - }, TIMEOUT); + }); it("Scrappy ability has no effect - Tackle against Ghost Type still 2x effective with Scrappy", async () => { game.override @@ -258,7 +258,7 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); - }, TIMEOUT); + }); it("FORESIGHT has no effect - Tackle against Ghost Type still 2x effective with Foresight", async () => { game.override @@ -279,5 +279,5 @@ describe("Inverse Battle", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); - }, TIMEOUT); + }); }); diff --git a/src/test/battlerTags/octolock.test.ts b/src/test/battlerTags/octolock.test.ts index 7b1f9264370..ebd92dc6401 100644 --- a/src/test/battlerTags/octolock.test.ts +++ b/src/test/battlerTags/octolock.test.ts @@ -10,7 +10,7 @@ vi.mock("#app/battle-scene.js"); describe("BattlerTag - OctolockTag", () => { describe("lapse behavior", () => { - it("unshifts a StatStageChangePhase with expected stat stage changes", { timeout: 10000 }, async () => { + it("unshifts a StatStageChangePhase with expected stat stage changes", async () => { const mockPokemon = { scene: new BattleScene(), getBattlerIndex: () => 0, @@ -30,11 +30,11 @@ describe("BattlerTag - OctolockTag", () => { }); }); - it ("traps its target (extends TrappedTag)", { timeout: 2000 }, async () => { + it ("traps its target (extends TrappedTag)", async () => { expect(new OctolockTag(1)).toBeInstanceOf(TrappedTag); }); - it("can be added to pokemon who are not octolocked", { timeout: 2000 }, async => { + it("can be added to pokemon who are not octolocked", async => { const mockPokemon = { getTag: vi.fn().mockReturnValue(undefined) as Pokemon["getTag"], } as Pokemon; @@ -47,7 +47,7 @@ describe("BattlerTag - OctolockTag", () => { expect(mockPokemon.getTag).toHaveBeenCalledWith(BattlerTagType.OCTOLOCK); }); - it("cannot be added to pokemon who are octolocked", { timeout: 2000 }, async => { + it("cannot be added to pokemon who are octolocked", async => { const mockPokemon = { getTag: vi.fn().mockReturnValue(new BattlerTag(null!, null!, null!, null!)) as Pokemon["getTag"], } as Pokemon; diff --git a/src/test/battlerTags/stockpiling.test.ts b/src/test/battlerTags/stockpiling.test.ts index e568016dfef..ae2528e7b5f 100644 --- a/src/test/battlerTags/stockpiling.test.ts +++ b/src/test/battlerTags/stockpiling.test.ts @@ -12,7 +12,7 @@ beforeEach(() => { describe("BattlerTag - StockpilingTag", () => { describe("onAdd", () => { - it("unshifts a StatStageChangePhase with expected stat stage changes on add", { timeout: 10000 }, async () => { + it("unshifts a StatStageChangePhase with expected stat stage changes on add", async () => { const mockPokemon = { scene: vi.mocked(new BattleScene()) as BattleScene, getBattlerIndex: () => 0, @@ -35,7 +35,7 @@ describe("BattlerTag - StockpilingTag", () => { expect(mockPokemon.scene.unshiftPhase).toBeCalledTimes(1); }); - it("unshifts a StatStageChangePhase with expected stat changes on add (one stat maxed)", { timeout: 10000 }, async () => { + it("unshifts a StatStageChangePhase with expected stat changes on add (one stat maxed)", async () => { const mockPokemon = { scene: new BattleScene(), summonData: new PokemonSummonData(), @@ -64,7 +64,7 @@ describe("BattlerTag - StockpilingTag", () => { }); describe("onOverlap", () => { - it("unshifts a StatStageChangePhase with expected stat changes on overlap", { timeout: 10000 }, async () => { + it("unshifts a StatStageChangePhase with expected stat changes on overlap", async () => { const mockPokemon = { scene: new BattleScene(), getBattlerIndex: () => 0, @@ -89,7 +89,7 @@ describe("BattlerTag - StockpilingTag", () => { }); describe("stack limit, stat tracking, and removal", () => { - it("can be added up to three times, even when one stat does not change", { timeout: 10000 }, async () => { + it("can be added up to three times, even when one stat does not change", async () => { const mockPokemon = { scene: new BattleScene(), summonData: new PokemonSummonData(), diff --git a/src/test/battlerTags/substitute.test.ts b/src/test/battlerTags/substitute.test.ts index 12888daca50..0802b549823 100644 --- a/src/test/battlerTags/substitute.test.ts +++ b/src/test/battlerTags/substitute.test.ts @@ -10,8 +10,6 @@ import { MoveEffectPhase } from "#app/phases/move-effect-phase"; vi.mock("#app/battle-scene.js"); -const TIMEOUT = 5 * 1000; // 5 sec timeout - describe("BattlerTag - SubstituteTag", () => { let mockPokemon: Pokemon; @@ -45,7 +43,7 @@ describe("BattlerTag - SubstituteTag", () => { subject.onAdd(mockPokemon); expect(subject.hp).toBe(25); - }, TIMEOUT + } ); it( @@ -67,7 +65,7 @@ describe("BattlerTag - SubstituteTag", () => { expect(subject.sourceInFocus).toBeFalsy(); expect(mockPokemon.scene.triggerPokemonBattleAnim).toHaveBeenCalledTimes(1); expect(mockPokemon.scene.queueMessage).toHaveBeenCalledTimes(1); - }, TIMEOUT + } ); it( @@ -79,7 +77,7 @@ describe("BattlerTag - SubstituteTag", () => { subject.onAdd(mockPokemon); expect(mockPokemon.findAndRemoveTags).toHaveBeenCalledTimes(1); - }, TIMEOUT + } ); }); @@ -114,7 +112,7 @@ describe("BattlerTag - SubstituteTag", () => { expect(mockPokemon.scene.triggerPokemonBattleAnim).toHaveBeenCalledTimes(1); expect(mockPokemon.scene.queueMessage).toHaveBeenCalledTimes(1); - }, TIMEOUT + } ); }); @@ -150,7 +148,7 @@ describe("BattlerTag - SubstituteTag", () => { expect(subject.sourceInFocus).toBeTruthy(); expect(mockPokemon.scene.triggerPokemonBattleAnim).toHaveBeenCalledTimes(1); expect(mockPokemon.scene.queueMessage).not.toHaveBeenCalled(); - }, TIMEOUT + } ); it( @@ -172,7 +170,7 @@ describe("BattlerTag - SubstituteTag", () => { expect(subject.sourceInFocus).toBeFalsy(); expect(mockPokemon.scene.triggerPokemonBattleAnim).toHaveBeenCalledTimes(1); expect(mockPokemon.scene.queueMessage).not.toHaveBeenCalled(); - }, TIMEOUT + } ); /** TODO: Figure out how to mock a MoveEffectPhase correctly for this test */ @@ -200,7 +198,7 @@ describe("BattlerTag - SubstituteTag", () => { expect(mockPokemon.scene.triggerPokemonBattleAnim).not.toHaveBeenCalled(); expect(mockPokemon.scene.queueMessage).toHaveBeenCalledTimes(1); - }, TIMEOUT + } ); it( @@ -212,7 +210,7 @@ describe("BattlerTag - SubstituteTag", () => { vi.spyOn(mockPokemon.scene, "queueMessage").mockReturnValue(); expect(subject.lapse(mockPokemon, BattlerTagLapseType.CUSTOM)).toBeFalsy(); - }, TIMEOUT + } ); it( diff --git a/src/test/boss-pokemon.test.ts b/src/test/boss-pokemon.test.ts index 8a0a0e01617..e316cac0cf6 100644 --- a/src/test/boss-pokemon.test.ts +++ b/src/test/boss-pokemon.test.ts @@ -9,8 +9,6 @@ import { EnemyPokemon } from "#app/field/pokemon"; import { toDmgValue } from "#app/utils"; describe("Boss Pokemon / Shields", () => { - const TIMEOUT = 20 * 1000; - let phaserGame: Phaser.Game; let game: GameManager; @@ -35,7 +33,7 @@ describe("Boss Pokemon / Shields", () => { .enemyMoveset(Moves.SPLASH) .enemyHeldItems([]) .startingLevel(1000) - .moveset([Moves.FALSE_SWIPE, Moves.SUPER_FANG, Moves.SPLASH]) + .moveset([Moves.FALSE_SWIPE, Moves.SUPER_FANG, Moves.SPLASH, Moves.PSYCHIC]) .ability(Abilities.NO_GUARD); }); @@ -62,7 +60,7 @@ describe("Boss Pokemon / Shields", () => { // Pokemon above level 100 get an extra shield level = 100; expect(game.scene.getEncounterBossSegments(wave, level, getPokemonSpecies(Species.RATTATA))).toBe(7); - }, TIMEOUT); + }); it("should reduce the number of shields if we are in a double battle", async () => { game.override @@ -77,7 +75,7 @@ describe("Boss Pokemon / Shields", () => { expect(boss1.bossSegments).toBe(2); expect(boss2.isBoss()).toBe(true); expect(boss2.bossSegments).toBe(2); - }, TIMEOUT); + }); it("shields should stop overflow damage and give stat stage boosts when broken", async () => { game.override.startingWave(150); // Floor 150 > 2 shields / 3 health segments @@ -107,7 +105,7 @@ describe("Boss Pokemon / Shields", () => { // Breaking the last shield gives a +2 boost to ATK, DEF, SP ATK, SP DEF or SPD expect(getTotalStatStageBoosts(enemyPokemon)).toBe(3); - }, TIMEOUT); + }); it("breaking multiple shields at once requires extra damage", async () => { game.override @@ -143,7 +141,7 @@ describe("Boss Pokemon / Shields", () => { expect(boss2.bossSegmentIndex).toBe(0); expect(boss2.hp).toBe(boss2.getMaxHp() - toDmgValue(boss2SegmentHp * 4)); - }, TIMEOUT); + }); it("the number of stat stage boosts is consistent when several shields are broken at once", async () => { const shieldsToBreak = 4; @@ -196,7 +194,29 @@ describe("Boss Pokemon / Shields", () => { await game.toNextTurn(); expect(getTotalStatStageBoosts(boss2)).toBe(totalStatStages); - }, TIMEOUT); + }); + + it("the boss enduring does not proc an extra stat boost", async () => { + game.override + .enemyHealthSegments(2) + .enemyAbility(Abilities.STURDY); + + await game.classicMode.startBattle([ Species.MEWTWO ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + expect(enemyPokemon.isBoss()).toBe(true); + expect(enemyPokemon.bossSegments).toBe(2); + expect(getTotalStatStageBoosts(enemyPokemon)).toBe(0); + + game.move.select(Moves.PSYCHIC); + await game.toNextTurn(); + + // Enemy survived with Sturdy + expect(enemyPokemon.bossSegmentIndex).toBe(0); + expect(enemyPokemon.hp).toBe(1); + expect(getTotalStatStageBoosts(enemyPokemon)).toBe(1); + + }); /** * Gets the sum of the effective stat stage boosts for the given Pokemon diff --git a/src/test/enemy_command.test.ts b/src/test/enemy_command.test.ts index 9a2caa56dfc..53cddc86efb 100644 --- a/src/test/enemy_command.test.ts +++ b/src/test/enemy_command.test.ts @@ -8,7 +8,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + const NUM_TRIALS = 300; type MoveChoiceSet = { [key: number]: number }; @@ -74,7 +74,7 @@ describe("Enemy Commands - Move Selection", () => { expect(moveChoices[mv.moveId]).toBe(0); } }); - }, TIMEOUT + } ); it( @@ -101,6 +101,6 @@ describe("Enemy Commands - Move Selection", () => { expect(moveChoices[mv.moveId]).toBe(0); } }); - }, TIMEOUT + } ); }); diff --git a/src/test/evolution.test.ts b/src/test/evolution.test.ts index 16922babd7c..07865d7e64a 100644 --- a/src/test/evolution.test.ts +++ b/src/test/evolution.test.ts @@ -10,7 +10,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite describe("Evolution", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 1000 * 20; beforeAll(() => { phaserGame = new Phaser.Game({ @@ -46,7 +45,7 @@ describe("Evolution", () => { trapinch.evolve(pokemonEvolutions[Species.TRAPINCH][0], trapinch.getSpeciesForm()); expect(trapinch.abilityIndex).toBe(1); - }, TIMEOUT); + }); it("should keep same ability slot after evolving", async () => { await game.classicMode.runToSummon([Species.BULBASAUR, Species.CHARMANDER]); @@ -61,7 +60,7 @@ describe("Evolution", () => { charmander.evolve(pokemonEvolutions[Species.CHARMANDER][0], charmander.getSpeciesForm()); expect(charmander.abilityIndex).toBe(1); - }, TIMEOUT); + }); it("should handle illegal abilityIndex values", async () => { await game.classicMode.runToSummon([Species.SQUIRTLE]); @@ -71,7 +70,7 @@ describe("Evolution", () => { squirtle.evolve(pokemonEvolutions[Species.SQUIRTLE][0], squirtle.getSpeciesForm()); expect(squirtle.abilityIndex).toBe(0); - }, TIMEOUT); + }); it("should handle nincada's unique evolution", async () => { await game.classicMode.runToSummon([Species.NINCADA]); @@ -87,7 +86,7 @@ describe("Evolution", () => { expect(shedinja.abilityIndex).toBe(1); // Regression test for https://github.com/pagefaultgames/pokerogue/issues/3842 expect(shedinja.metBiome).toBe(-1); - }, TIMEOUT); + }); it("should set wild delay to NONE by default", () => { const speciesFormEvo = new SpeciesFormEvolution(Species.ABRA, null, null, 1000, null, null); @@ -120,7 +119,7 @@ describe("Evolution", () => { expect(totodile.hp).toBe(totodile.getMaxHp()); expect(totodile.hp).toBeGreaterThan(hpBefore); - }, TIMEOUT); + }); it("should not fully heal HP when evolving", async () => { game.override.moveset([Moves.SURF]) @@ -150,7 +149,7 @@ describe("Evolution", () => { expect(cyndaquil.getMaxHp()).toBeGreaterThan(maxHpBefore); expect(cyndaquil.hp).toBeGreaterThan(hpBefore); expect(cyndaquil.hp).toBeLessThan(cyndaquil.getMaxHp()); - }, TIMEOUT); + }); it("should handle rng-based split evolution", async () => { /* this test checks to make sure that tandemaus will @@ -174,5 +173,5 @@ describe("Evolution", () => { const fourForm = playerPokemon.getEvolution()!; expect(fourForm.evoFormKey).toBe(null); // meanwhile, according to the pokemon-forms, the evoFormKey for a 4 family maushold is null } - }, TIMEOUT); + }); }); diff --git a/src/test/items/double_battle_chance_booster.test.ts b/src/test/items/double_battle_chance_booster.test.ts index 1d5051fa9e9..8d2bd7c9179 100644 --- a/src/test/items/double_battle_chance_booster.test.ts +++ b/src/test/items/double_battle_chance_booster.test.ts @@ -12,8 +12,6 @@ import { Button } from "#app/enums/buttons"; describe("Items - Double Battle Chance Boosters", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -39,7 +37,7 @@ describe("Items - Double Battle Chance Boosters", () => { await game.classicMode.startBattle(); expect(game.scene.getEnemyField().length).toBe(2); - }, TIMEOUT); + }); it("should guarantee double boss battle with 3 unique tiers", async () => { game.override @@ -57,7 +55,7 @@ describe("Items - Double Battle Chance Boosters", () => { expect(enemyField.length).toBe(2); expect(enemyField[0].isBoss()).toBe(true); expect(enemyField[1].isBoss()).toBe(true); - }, TIMEOUT); + }); it("should renew how many battles are left of existing booster when picking up new booster of same tier", async() => { game.override @@ -100,5 +98,5 @@ describe("Items - Double Battle Chance Boosters", () => { } } expect(count).toBe(1); - }, TIMEOUT); + }); }); diff --git a/src/test/items/eviolite.test.ts b/src/test/items/eviolite.test.ts index d9991d47a89..7b2f9a15fce 100644 --- a/src/test/items/eviolite.test.ts +++ b/src/test/items/eviolite.test.ts @@ -9,8 +9,6 @@ import { StatBoosterModifier } from "#app/modifier/modifier"; describe("Items - Eviolite", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phase.Game({ type: Phaser.HEADLESS, @@ -50,7 +48,7 @@ describe("Items - Eviolite", () => { expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(Math.floor(defStat * 1.5)); expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(Math.floor(spDefStat * 1.5)); - }, TIMEOUT); + }); it("should not provide a boost for fully evolved, unfused pokemon", async() => { await game.classicMode.startBattle([ @@ -74,7 +72,7 @@ describe("Items - Eviolite", () => { expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(defStat); expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(spDefStat); - }, TIMEOUT); + }); it("should provide 50% boost to DEF and SPDEF for completely unevolved, fused pokemon", async() => { await game.classicMode.startBattle([ @@ -107,7 +105,7 @@ describe("Items - Eviolite", () => { expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(Math.floor(defStat * 1.5)); expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(Math.floor(spDefStat * 1.5)); - }, TIMEOUT); + }); it("should provide 25% boost to DEF and SPDEF for partially unevolved (base), fused pokemon", async() => { await game.classicMode.startBattle([ @@ -140,7 +138,7 @@ describe("Items - Eviolite", () => { expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(Math.floor(defStat * 1.25)); expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(Math.floor(spDefStat * 1.25)); - }, TIMEOUT); + }); it("should provide 25% boost to DEF and SPDEF for partially unevolved (fusion), fused pokemon", async() => { await game.classicMode.startBattle([ @@ -173,7 +171,7 @@ describe("Items - Eviolite", () => { expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(Math.floor(defStat * 1.25)); expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(Math.floor(spDefStat * 1.25)); - }, TIMEOUT); + }); it("should not provide a boost for fully evolved, fused pokemon", async() => { await game.classicMode.startBattle([ @@ -206,7 +204,7 @@ describe("Items - Eviolite", () => { expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(defStat); expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(spDefStat); - }, TIMEOUT); + }); it("should not provide a boost for Gigantamax Pokémon", async() => { game.override.starterForms({ @@ -238,5 +236,5 @@ describe("Items - Eviolite", () => { expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(defStat); expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(spDefStat); - }, TIMEOUT); + }); }); diff --git a/src/test/items/grip_claw.test.ts b/src/test/items/grip_claw.test.ts index d9871616449..29d39cabc3e 100644 --- a/src/test/items/grip_claw.test.ts +++ b/src/test/items/grip_claw.test.ts @@ -9,7 +9,7 @@ import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -const TIMEOUT = 20 * 1000; // 20 seconds +// 20 seconds describe("Items - Grip Claw", () => { let phaserGame: Phaser.Game; @@ -63,6 +63,6 @@ describe("Items - Grip Claw", () => { await game.phaseInterceptor.to(MoveEndPhase, false); expect(enemyPokemon[1].getHeldItems.length).toBe(enemyHeldItemCt[1]); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/after_you.test.ts b/src/test/moves/after_you.test.ts index efce1b28a17..025b4804bf1 100644 --- a/src/test/moves/after_you.test.ts +++ b/src/test/moves/after_you.test.ts @@ -8,7 +8,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - After You", () => { let phaserGame: Phaser.Game; @@ -47,7 +47,7 @@ describe("Moves - After You", () => { const phase = game.scene.getCurrentPhase() as MovePhase; expect(phase.pokemon).toBe(game.scene.getPlayerField()[1]); await game.phaseInterceptor.to("MoveEndPhase"); - }, TIMEOUT); + }); it("fails if target already moved", async () => { game.override.enemySpecies(Species.SHUCKLE); @@ -61,5 +61,5 @@ describe("Moves - After You", () => { await game.phaseInterceptor.to(MovePhase); expect(game.scene.getPlayerField()[1].getLastXMoves(1)[0].result).toBe(MoveResult.FAIL); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/alluring_voice.test.ts b/src/test/moves/alluring_voice.test.ts index b438d0f736a..3e86b46aa69 100644 --- a/src/test/moves/alluring_voice.test.ts +++ b/src/test/moves/alluring_voice.test.ts @@ -8,7 +8,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Alluring Voice", () => { let phaserGame: Phaser.Game; @@ -50,5 +50,5 @@ describe("Moves - Alluring Voice", () => { await game.phaseInterceptor.to(BerryPhase); expect(enemy.getTag(BattlerTagType.CONFUSED)?.tagType).toBe("CONFUSED"); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/astonish.test.ts b/src/test/moves/astonish.test.ts index b21e2a06051..694ad85803b 100644 --- a/src/test/moves/astonish.test.ts +++ b/src/test/moves/astonish.test.ts @@ -11,7 +11,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Astonish", () => { let phaserGame: Phaser.Game; @@ -67,6 +67,6 @@ describe("Moves - Astonish", () => { await game.phaseInterceptor.to(BerryPhase, false); expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/baddy_bad.test.ts b/src/test/moves/baddy_bad.test.ts index d1a221453a6..87a7e9e049d 100644 --- a/src/test/moves/baddy_bad.test.ts +++ b/src/test/moves/baddy_bad.test.ts @@ -8,8 +8,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("Moves - Baddy Bad", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -39,5 +37,5 @@ describe("Moves - Baddy Bad", () => { await game.phaseInterceptor.to("BerryPhase"); expect(game.scene.arena.tags.length).toBe(0); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/baneful_bunker.test.ts b/src/test/moves/baneful_bunker.test.ts index c4a3036565c..5f63e3b4313 100644 --- a/src/test/moves/baneful_bunker.test.ts +++ b/src/test/moves/baneful_bunker.test.ts @@ -7,7 +7,7 @@ import { Moves } from "#enums/moves"; import { BattlerIndex } from "#app/battle"; import { StatusEffect } from "#app/enums/status-effect"; -const TIMEOUT = 20 * 1000; + describe("Moves - Baneful Bunker", () => { let phaserGame: Phaser.Game; @@ -50,7 +50,7 @@ describe("Moves - Baneful Bunker", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); expect(leadPokemon.status?.effect === StatusEffect.POISON).toBeTruthy(); - }, TIMEOUT + } ); test( "should protect the user and poison attackers that make contact, regardless of accuracy checks", @@ -68,7 +68,7 @@ describe("Moves - Baneful Bunker", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); expect(leadPokemon.status?.effect === StatusEffect.POISON).toBeTruthy(); - }, TIMEOUT + } ); test( @@ -88,6 +88,6 @@ describe("Moves - Baneful Bunker", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); expect(leadPokemon.status?.effect === StatusEffect.POISON).toBeFalsy(); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/beak_blast.test.ts b/src/test/moves/beak_blast.test.ts index fe748c87826..3f4fe1d1d11 100644 --- a/src/test/moves/beak_blast.test.ts +++ b/src/test/moves/beak_blast.test.ts @@ -10,7 +10,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Beak Blast", () => { let phaserGame: Phaser.Game; @@ -54,7 +54,7 @@ describe("Moves - Beak Blast", () => { await game.phaseInterceptor.to(BerryPhase, false); expect(enemyPokemon.status?.effect).toBe(StatusEffect.BURN); - }, TIMEOUT + } ); it( @@ -74,7 +74,7 @@ describe("Moves - Beak Blast", () => { await game.phaseInterceptor.to(BerryPhase, false); expect(enemyPokemon.status?.effect).toBe(StatusEffect.BURN); - }, TIMEOUT + } ); it( @@ -94,7 +94,7 @@ describe("Moves - Beak Blast", () => { await game.phaseInterceptor.to(BerryPhase, false); expect(enemyPokemon.status?.effect).not.toBe(StatusEffect.BURN); - }, TIMEOUT + } ); it( @@ -110,7 +110,7 @@ describe("Moves - Beak Blast", () => { await game.phaseInterceptor.to(BerryPhase, false); expect(leadPokemon.turnData.hitCount).toBe(2); - }, TIMEOUT + } ); it( @@ -131,6 +131,6 @@ describe("Moves - Beak Blast", () => { await game.phaseInterceptor.to(TurnEndPhase); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); expect(leadPokemon.getTag(BattlerTagType.BEAK_BLAST_CHARGING)).toBeUndefined(); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/beat_up.test.ts b/src/test/moves/beat_up.test.ts index 70b33f56583..51ec768084c 100644 --- a/src/test/moves/beat_up.test.ts +++ b/src/test/moves/beat_up.test.ts @@ -7,8 +7,6 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; // 20 sec timeout - describe("Moves - Beat Up", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -57,7 +55,7 @@ describe("Moves - Beat Up", () => { await game.phaseInterceptor.to(MoveEffectPhase); expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); } - }, TIMEOUT + } ); it( @@ -74,7 +72,7 @@ describe("Moves - Beat Up", () => { await game.phaseInterceptor.to(MoveEffectPhase); expect(playerPokemon.turnData.hitCount).toBe(5); - }, TIMEOUT + } ); it( @@ -99,6 +97,6 @@ describe("Moves - Beat Up", () => { await game.phaseInterceptor.to(MoveEffectPhase); expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); } - }, TIMEOUT + } ); }); diff --git a/src/test/moves/belly_drum.test.ts b/src/test/moves/belly_drum.test.ts index 3d85c59a2a5..494272089e2 100644 --- a/src/test/moves/belly_drum.test.ts +++ b/src/test/moves/belly_drum.test.ts @@ -8,7 +8,7 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; import { Abilities } from "#app/enums/abilities"; -const TIMEOUT = 20 * 1000; + // RATIO : HP Cost of Move const RATIO = 2; // PREDAMAGE : Amount of extra HP lost @@ -54,7 +54,7 @@ describe("Moves - BELLY DRUM", () => { expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp() - hpLost); expect(leadPokemon.getStatStage(Stat.ATK)).toBe(6); - }, TIMEOUT + } ); test("will still take effect if an uninvolved stat stage is at max", @@ -74,7 +74,7 @@ describe("Moves - BELLY DRUM", () => { expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp() - hpLost); expect(leadPokemon.getStatStage(Stat.ATK)).toBe(6); expect(leadPokemon.getStatStage(Stat.SPATK)).toBe(6); - }, TIMEOUT + } ); test("fails if the pokemon's ATK stat stage is at its maximum", @@ -90,7 +90,7 @@ describe("Moves - BELLY DRUM", () => { expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); expect(leadPokemon.getStatStage(Stat.ATK)).toBe(6); - }, TIMEOUT + } ); test("fails if the user's health is less than 1/2", @@ -106,6 +106,6 @@ describe("Moves - BELLY DRUM", () => { expect(leadPokemon.hp).toBe(hpLost - PREDAMAGE); expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/burning_jealousy.test.ts b/src/test/moves/burning_jealousy.test.ts index 3f2bf453684..d6ebbf30bb1 100644 --- a/src/test/moves/burning_jealousy.test.ts +++ b/src/test/moves/burning_jealousy.test.ts @@ -8,7 +8,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Burning Jealousy", () => { let phaserGame: Phaser.Game; @@ -50,7 +50,7 @@ describe("Moves - Burning Jealousy", () => { await game.phaseInterceptor.to("BerryPhase"); expect(enemy.status?.effect).toBe(StatusEffect.BURN); - }, TIMEOUT); + }); it("should still burn the opponent if their stat stages were both raised and lowered in the same turn", async () => { game.override @@ -66,7 +66,7 @@ describe("Moves - Burning Jealousy", () => { await game.phaseInterceptor.to("BerryPhase"); expect(enemy.status?.effect).toBe(StatusEffect.BURN); - }, TIMEOUT); + }); it("should ignore stat stages raised by IMPOSTER", async () => { game.override @@ -81,11 +81,11 @@ describe("Moves - Burning Jealousy", () => { await game.phaseInterceptor.to("BerryPhase"); expect(enemy.status?.effect).toBeUndefined(); - }, TIMEOUT); + }); it.skip("should ignore weakness policy", async () => { // TODO: Make this test if WP is implemented await game.classicMode.startBattle(); - }, TIMEOUT); + }); it("should be boosted by Sheer Force even if opponent didn't raise stat stages", async () => { game.override @@ -98,5 +98,5 @@ describe("Moves - Burning Jealousy", () => { await game.phaseInterceptor.to("BerryPhase"); expect(allMoves[Moves.BURNING_JEALOUSY].calculateBattlePower).toHaveReturnedWith(allMoves[Moves.BURNING_JEALOUSY].power * 5461 / 4096); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/ceaseless_edge.test.ts b/src/test/moves/ceaseless_edge.test.ts index 8511b3179c6..e98fe462c62 100644 --- a/src/test/moves/ceaseless_edge.test.ts +++ b/src/test/moves/ceaseless_edge.test.ts @@ -10,7 +10,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Ceaseless Edge", () => { let phaserGame: Phaser.Game; @@ -61,7 +61,7 @@ describe("Moves - Ceaseless Edge", () => { expect(tagAfter instanceof ArenaTrapTag).toBeTruthy(); expect(tagAfter.layers).toBe(1); expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); - }, TIMEOUT + } ); test( @@ -86,7 +86,7 @@ describe("Moves - Ceaseless Edge", () => { expect(tagAfter instanceof ArenaTrapTag).toBeTruthy(); expect(tagAfter.layers).toBe(2); expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); - }, TIMEOUT + } ); test( @@ -114,6 +114,6 @@ describe("Moves - Ceaseless Edge", () => { game.move.select(Moves.SPLASH); await game.phaseInterceptor.to(TurnEndPhase, false); expect(game.scene.currentBattle.enemyParty[0].hp).toBeLessThan(hpBeforeSpikes); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/clangorous_soul.test.ts b/src/test/moves/clangorous_soul.test.ts index 015b73b4dab..8f0bfb2549f 100644 --- a/src/test/moves/clangorous_soul.test.ts +++ b/src/test/moves/clangorous_soul.test.ts @@ -6,7 +6,7 @@ import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import { Stat } from "#enums/stat"; -const TIMEOUT = 20 * 1000; + /** HP Cost of Move */ const RATIO = 3; /** Amount of extra HP lost */ @@ -54,7 +54,7 @@ describe("Moves - Clangorous Soul", () => { expect(leadPokemon.getStatStage(Stat.SPATK)).toBe(1); expect(leadPokemon.getStatStage(Stat.SPDEF)).toBe(1); expect(leadPokemon.getStatStage(Stat.SPD)).toBe(1); - }, TIMEOUT + } ); it("will still take effect if one or more of the involved stat stages are not at max", @@ -79,7 +79,7 @@ describe("Moves - Clangorous Soul", () => { expect(leadPokemon.getStatStage(Stat.SPATK)).toBe(6); expect(leadPokemon.getStatStage(Stat.SPDEF)).toBe(5); expect(leadPokemon.getStatStage(Stat.SPD)).toBe(1); - }, TIMEOUT + } ); it("fails if all stat stages involved are at max", @@ -103,7 +103,7 @@ describe("Moves - Clangorous Soul", () => { expect(leadPokemon.getStatStage(Stat.SPATK)).toBe(6); expect(leadPokemon.getStatStage(Stat.SPDEF)).toBe(6); expect(leadPokemon.getStatStage(Stat.SPD)).toBe(6); - }, TIMEOUT + } ); it("fails if the user's health is less than 1/3", @@ -123,6 +123,6 @@ describe("Moves - Clangorous Soul", () => { expect(leadPokemon.getStatStage(Stat.SPATK)).toBe(0); expect(leadPokemon.getStatStage(Stat.SPDEF)).toBe(0); expect(leadPokemon.getStatStage(Stat.SPD)).toBe(0); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/crafty_shield.test.ts b/src/test/moves/crafty_shield.test.ts index 7b962518944..63399c3a86a 100644 --- a/src/test/moves/crafty_shield.test.ts +++ b/src/test/moves/crafty_shield.test.ts @@ -9,7 +9,7 @@ import { BattlerTagType } from "#app/enums/battler-tag-type"; import { BerryPhase } from "#app/phases/berry-phase"; import { CommandPhase } from "#app/phases/command-phase"; -const TIMEOUT = 20 * 1000; + describe("Moves - Crafty Shield", () => { let phaserGame: Phaser.Game; @@ -56,7 +56,7 @@ describe("Moves - Crafty Shield", () => { await game.phaseInterceptor.to(BerryPhase, false); leadPokemon.forEach(p => expect(p.getStatStage(Stat.ATK)).toBe(0)); - }, TIMEOUT + } ); test( @@ -77,7 +77,7 @@ describe("Moves - Crafty Shield", () => { await game.phaseInterceptor.to(BerryPhase, false); expect(leadPokemon.some(p => p.hp < p.getMaxHp())).toBeTruthy(); - }, TIMEOUT + } ); test( @@ -99,7 +99,7 @@ describe("Moves - Crafty Shield", () => { await game.phaseInterceptor.to(BerryPhase, false); leadPokemon.forEach(p => expect(p.getTag(BattlerTagType.CURSED)).toBeUndefined()); - }, TIMEOUT + } ); test( diff --git a/src/test/moves/dragon_cheer.test.ts b/src/test/moves/dragon_cheer.test.ts index 0fc389ccfb6..beaf6ddb520 100644 --- a/src/test/moves/dragon_cheer.test.ts +++ b/src/test/moves/dragon_cheer.test.ts @@ -10,8 +10,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite describe("Moves - Dragon Cheer", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -47,7 +45,7 @@ describe("Moves - Dragon Cheer", () => { // After Tackle await game.phaseInterceptor.to("TurnEndPhase"); expect(enemy.getCritStage).toHaveReturnedWith(1); // getCritStage is called on defender - }, TIMEOUT); + }); it("increases the user's Dragon-type allies' critical hit ratio by two stages", async () => { await game.classicMode.startBattle([Species.MAGIKARP, Species.DRAGONAIR]); @@ -64,7 +62,7 @@ describe("Moves - Dragon Cheer", () => { // After Tackle await game.phaseInterceptor.to("TurnEndPhase"); expect(enemy.getCritStage).toHaveReturnedWith(2); // getCritStage is called on defender - }, TIMEOUT); + }); it("applies the effect based on the allies' type upon use of the move, and do not change if the allies' type changes later in battle", async () => { await game.classicMode.startBattle([Species.DRAGONAIR, Species.MAGIKARP]); @@ -96,5 +94,5 @@ describe("Moves - Dragon Cheer", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.getCritStage).toHaveReturnedWith(1); // getCritStage is called on defender - }, TIMEOUT); + }); }); diff --git a/src/test/moves/dragon_tail.test.ts b/src/test/moves/dragon_tail.test.ts index 75b2c9ba73e..4b222a0c477 100644 --- a/src/test/moves/dragon_tail.test.ts +++ b/src/test/moves/dragon_tail.test.ts @@ -10,7 +10,7 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; import GameManager from "../utils/gameManager"; -const TIMEOUT = 20 * 1000; + describe("Moves - Dragon Tail", () => { let phaserGame: Phaser.Game; @@ -55,7 +55,7 @@ describe("Moves - Dragon Tail", () => { // simply want to test that the game makes it this far without crashing await game.phaseInterceptor.to(BattleEndPhase); - }, TIMEOUT + } ); test( @@ -75,7 +75,7 @@ describe("Moves - Dragon Tail", () => { const hasFled = enemyPokemon.switchOutStatus; expect(!isVisible && hasFled).toBe(true); expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); test( @@ -109,7 +109,7 @@ describe("Moves - Dragon Tail", () => { await game.phaseInterceptor.to(BerryPhase); expect(enemySecPokemon.hp).toBeLessThan(enemySecPokemon.getMaxHp()); - }, TIMEOUT + } ); test( @@ -141,6 +141,6 @@ describe("Moves - Dragon Tail", () => { expect(secPokemon.hp).toBeLessThan(secPokemon.getMaxHp()); expect(enemyLeadPokemon.hp).toBeLessThan(enemyLeadPokemon.getMaxHp()); expect(enemySecPokemon.hp).toBeLessThan(enemySecPokemon.getMaxHp()); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/fillet_away.test.ts b/src/test/moves/fillet_away.test.ts index 68ace42c2ec..d8dd74a259c 100644 --- a/src/test/moves/fillet_away.test.ts +++ b/src/test/moves/fillet_away.test.ts @@ -7,7 +7,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + /** HP Cost of Move */ const RATIO = 2; /** Amount of extra HP lost */ @@ -53,7 +53,7 @@ describe("Moves - FILLET AWAY", () => { expect(leadPokemon.getStatStage(Stat.ATK)).toBe(2); expect(leadPokemon.getStatStage(Stat.SPATK)).toBe(2); expect(leadPokemon.getStatStage(Stat.SPD)).toBe(2); - }, TIMEOUT + } ); test("still takes effect if one or more of the involved stat stages are not at max", @@ -74,7 +74,7 @@ describe("Moves - FILLET AWAY", () => { expect(leadPokemon.getStatStage(Stat.ATK)).toBe(6); expect(leadPokemon.getStatStage(Stat.SPATK)).toBe(5); expect(leadPokemon.getStatStage(Stat.SPD)).toBe(2); - }, TIMEOUT + } ); test("fails if all stat stages involved are at max", @@ -94,7 +94,7 @@ describe("Moves - FILLET AWAY", () => { expect(leadPokemon.getStatStage(Stat.ATK)).toBe(6); expect(leadPokemon.getStatStage(Stat.SPATK)).toBe(6); expect(leadPokemon.getStatStage(Stat.SPD)).toBe(6); - }, TIMEOUT + } ); test("fails if the user's health is less than 1/2", @@ -112,6 +112,6 @@ describe("Moves - FILLET AWAY", () => { expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0); expect(leadPokemon.getStatStage(Stat.SPATK)).toBe(0); expect(leadPokemon.getStatStage(Stat.SPD)).toBe(0); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/focus_punch.test.ts b/src/test/moves/focus_punch.test.ts index ca80c688169..b839c228b68 100644 --- a/src/test/moves/focus_punch.test.ts +++ b/src/test/moves/focus_punch.test.ts @@ -10,7 +10,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Focus Punch", () => { let phaserGame: Phaser.Game; @@ -61,7 +61,7 @@ describe("Moves - Focus Punch", () => { expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); expect(leadPokemon.getMoveHistory().length).toBe(1); expect(leadPokemon.turnData.damageDealt).toBe(enemyStartingHp - enemyPokemon.hp); - }, TIMEOUT + } ); it( @@ -88,7 +88,7 @@ describe("Moves - Focus Punch", () => { expect(enemyPokemon.hp).toBe(enemyStartingHp); expect(leadPokemon.getMoveHistory().length).toBe(1); expect(leadPokemon.turnData.damageDealt).toBe(0); - }, TIMEOUT + } ); it( @@ -111,7 +111,7 @@ describe("Moves - Focus Punch", () => { expect(leadPokemon.getMoveHistory().length).toBe(1); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); it( @@ -129,6 +129,6 @@ describe("Moves - Focus Punch", () => { expect(game.scene.getCurrentPhase() instanceof SwitchSummonPhase).toBeTruthy(); expect(game.scene.phaseQueue.find(phase => phase instanceof MoveHeaderPhase)).toBeDefined(); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/follow_me.test.ts b/src/test/moves/follow_me.test.ts index 7d0c4fdb546..28fb1045a8c 100644 --- a/src/test/moves/follow_me.test.ts +++ b/src/test/moves/follow_me.test.ts @@ -8,7 +8,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Follow Me", () => { let phaserGame: Phaser.Game; @@ -54,7 +54,7 @@ describe("Moves - Follow Me", () => { expect(playerPokemon[0].hp).toBeLessThan(playerPokemon[0].getMaxHp()); expect(playerPokemon[1].hp).toBe(playerPokemon[1].getMaxHp()); - }, TIMEOUT + } ); test( @@ -77,7 +77,7 @@ describe("Moves - Follow Me", () => { expect(playerPokemon[1].hp).toBeLessThan(playerPokemon[1].getMaxHp()); expect(playerPokemon[0].hp).toBe(playerPokemon[0].getMaxHp()); - }, TIMEOUT + } ); test( @@ -102,7 +102,7 @@ describe("Moves - Follow Me", () => { // If redirection was bypassed, both enemies should be damaged expect(enemyPokemon[0].hp).toBeLessThan(enemyPokemon[0].getMaxHp()); expect(enemyPokemon[1].hp).toBeLessThan(enemyPokemon[1].getMaxHp()); - }, TIMEOUT + } ); test( @@ -125,6 +125,6 @@ describe("Moves - Follow Me", () => { // If redirection was bypassed, both enemies should be damaged expect(enemyPokemon[0].hp).toBeLessThan(enemyPokemon[0].getMaxHp()); expect(enemyPokemon[1].hp).toBeLessThan(enemyPokemon[1].getMaxHp()); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/freeze_dry.test.ts b/src/test/moves/freeze_dry.test.ts index ff9e2f07162..b901f04e6a1 100644 --- a/src/test/moves/freeze_dry.test.ts +++ b/src/test/moves/freeze_dry.test.ts @@ -9,8 +9,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite describe("Moves - Freeze-Dry", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -44,7 +42,7 @@ describe("Moves - Freeze-Dry", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(2); - }, TIMEOUT); + }); it("should deal 4x damage to water/flying types", async () => { game.override.enemySpecies(Species.WINGULL); @@ -58,7 +56,7 @@ describe("Moves - Freeze-Dry", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(4); - }, TIMEOUT); + }); it("should deal 1x damage to water/fire types", async () => { game.override.enemySpecies(Species.VOLCANION); @@ -72,7 +70,7 @@ describe("Moves - Freeze-Dry", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(1); - }, TIMEOUT); + }); // enable if this is ever fixed (lol) it.todo("should deal 2x damage to water types under Normalize", async () => { @@ -87,7 +85,7 @@ describe("Moves - Freeze-Dry", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(2); - }, TIMEOUT); + }); // enable once Electrify is implemented (and the interaction is fixed, as above) it.todo("should deal 2x damage to water types under Electrify", async () => { @@ -102,5 +100,5 @@ describe("Moves - Freeze-Dry", () => { await game.phaseInterceptor.to("BerryPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(2); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/gastro_acid.test.ts b/src/test/moves/gastro_acid.test.ts index cfc458a908f..60b2bd80c05 100644 --- a/src/test/moves/gastro_acid.test.ts +++ b/src/test/moves/gastro_acid.test.ts @@ -6,7 +6,7 @@ import { MoveResult } from "#app/field/pokemon"; import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Gastro Acid", () => { let phaserGame: Phaser.Game; @@ -60,7 +60,7 @@ describe("Moves - Gastro Acid", () => { expect(enemyField[0].hp).toBeLessThan(enemyField[0].getMaxHp()); expect(enemyField[1].isFullHp()).toBe(true); - }, TIMEOUT); + }); it("fails if used on an enemy with an already-suppressed ability", async () => { game.override.battleType(null); @@ -78,5 +78,5 @@ describe("Moves - Gastro Acid", () => { await game.phaseInterceptor.to("TurnInitPhase"); expect(game.scene.getPlayerPokemon()!.getLastXMoves()[0].result).toBe(MoveResult.FAIL); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/glaive_rush.test.ts b/src/test/moves/glaive_rush.test.ts index 9eed6868432..1a524b4aef6 100644 --- a/src/test/moves/glaive_rush.test.ts +++ b/src/test/moves/glaive_rush.test.ts @@ -6,7 +6,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Glaive Rush", () => { let phaserGame: Phaser.Game; @@ -49,7 +49,7 @@ describe("Moves - Glaive Rush", () => { await game.phaseInterceptor.to("DamagePhase"); expect(enemy.hp).toBeLessThanOrEqual(1001 - (damageDealt * 3)); - }, TIMEOUT); + }); it("always gets hit by attacks", async () => { await game.classicMode.startBattle(); @@ -62,7 +62,7 @@ describe("Moves - Glaive Rush", () => { await game.phaseInterceptor.to("TurnEndPhase"); expect(enemy.hp).toBeLessThan(1000); - }, TIMEOUT); + }); it("interacts properly with multi-lens", async () => { game.override @@ -85,7 +85,7 @@ describe("Moves - Glaive Rush", () => { await game.phaseInterceptor.to("TurnEndPhase"); expect(player.hp).toBe(1000); - }, TIMEOUT); + }); it("secondary effects only last until next move", async () => { game.override.enemyMoveset([Moves.SHADOW_SNEAK]); @@ -111,7 +111,7 @@ describe("Moves - Glaive Rush", () => { await game.phaseInterceptor.to("TurnEndPhase"); expect(player.hp).toBe(damagedHp); - }, TIMEOUT); + }); it("secondary effects are removed upon switching", async () => { game.override @@ -135,7 +135,7 @@ describe("Moves - Glaive Rush", () => { await game.phaseInterceptor.to("TurnEndPhase"); expect(player.hp).toBe(player.getMaxHp()); - }, TIMEOUT); + }); it("secondary effects don't activate if move fails", async () => { game.override.moveset([Moves.SHADOW_SNEAK, Moves.PROTECT, Moves.SPLASH, Moves.GLAIVE_RUSH]); @@ -161,5 +161,5 @@ describe("Moves - Glaive Rush", () => { const damagedHP2 = 1000 - enemy.hp; expect(damagedHP2).toBeGreaterThanOrEqual((damagedHP1 * 2) - 1); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/guard_swap.test.ts b/src/test/moves/guard_swap.test.ts index 0c24f69c32c..99769b32899 100644 --- a/src/test/moves/guard_swap.test.ts +++ b/src/test/moves/guard_swap.test.ts @@ -11,8 +11,6 @@ import { MoveEndPhase } from "#app/phases/move-end-phase"; describe("Moves - Guard Swap", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -65,5 +63,5 @@ describe("Moves - Guard Swap", () => { expect(enemy.getStatStage(s)).toBe(1); } } - }, TIMEOUT); + }); }); diff --git a/src/test/moves/haze.test.ts b/src/test/moves/haze.test.ts index 211c1a41409..e5474801899 100644 --- a/src/test/moves/haze.test.ts +++ b/src/test/moves/haze.test.ts @@ -35,7 +35,7 @@ describe("Moves - Haze", () => { game.override.ability(Abilities.NONE); }); - it("should reset all stat changes of all Pokemon on field", { timeout: 10000 }, async () => { + it("should reset all stat changes of all Pokemon on field", async () => { await game.startBattle([Species.RATTATA]); const user = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/heal_block.test.ts b/src/test/moves/heal_block.test.ts new file mode 100644 index 00000000000..8549d6211a9 --- /dev/null +++ b/src/test/moves/heal_block.test.ts @@ -0,0 +1,153 @@ +import { BattlerIndex } from "#app/battle"; +import { ArenaTagSide } from "#app/data/arena-tag"; +import { WeatherType } from "#app/data/weather"; +import GameManager from "#app/test/utils/gameManager"; +import { Abilities } from "#enums/abilities"; +import { ArenaTagType } from "#enums/arena-tag-type"; +import { BattlerTagType } from "#enums/battler-tag-type"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +const TIMEOUT = 20 * 1000; + +// Bulbapedia Reference: https://bulbapedia.bulbagarden.net/wiki/Heal_Block_(move) +describe("Moves - Heal Block", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([Moves.ABSORB, Moves.WISH, Moves.SPLASH, Moves.AQUA_RING]) + .enemyMoveset(Moves.HEAL_BLOCK) + .ability(Abilities.NO_GUARD) + .enemyAbility(Abilities.BALL_FETCH) + .enemySpecies(Species.BLISSEY) + .disableCrits(); + }); + + it("shouldn't stop damage from HP-drain attacks, just HP restoration", async() => { + + await game.classicMode.startBattle([Species.CHARIZARD]); + + const player = game.scene.getPlayerPokemon()!; + const enemy = game.scene.getEnemyPokemon()!; + + player.damageAndUpdate(enemy.getMaxHp() - 1); + + game.move.select(Moves.ABSORB); + await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(player.hp).toBe(1); + expect(enemy.hp).toBeLessThan(enemy.getMaxHp()); + }, TIMEOUT + ); + + it("shouldn't stop Liquid Ooze from dealing damage", async() => { + game.override.enemyAbility(Abilities.LIQUID_OOZE); + + await game.classicMode.startBattle([Species.CHARIZARD]); + + const player = game.scene.getPlayerPokemon()!; + const enemy = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.ABSORB); + await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(player.isFullHp()).toBe(false); + expect(enemy.isFullHp()).toBe(false); + }, TIMEOUT); + + it("should stop delayed heals, such as from Wish", async() => { + await game.classicMode.startBattle([Species.CHARIZARD]); + + const player = game.scene.getPlayerPokemon()!; + + player.damageAndUpdate(player.getMaxHp() - 1); + + game.move.select(Moves.WISH); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(game.scene.arena.getTagOnSide(ArenaTagType.WISH, ArenaTagSide.PLAYER)).toBeDefined(); + while (game.scene.arena.getTagOnSide(ArenaTagType.WISH, ArenaTagSide.PLAYER)) { + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to("TurnEndPhase"); + } + + expect(player.hp).toBe(1); + }, TIMEOUT); + + it("should prevent Grassy Terrain from restoring HP", async() => { + game.override.enemyAbility(Abilities.GRASSY_SURGE); + + await game.classicMode.startBattle([Species.CHARIZARD]); + + const player = game.scene.getPlayerPokemon()!; + + player.damageAndUpdate(player.getMaxHp() - 1); + + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(player.hp).toBe(1); + }, TIMEOUT); + + it("should prevent healing from heal-over-time moves", async() => { + await game.classicMode.startBattle([Species.CHARIZARD]); + + const player = game.scene.getPlayerPokemon()!; + + player.damageAndUpdate(player.getMaxHp() - 1); + + game.move.select(Moves.AQUA_RING); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(player.getTag(BattlerTagType.AQUA_RING)).toBeDefined(); + expect(player.hp).toBe(1); + }, TIMEOUT); + + it("should prevent abilities from restoring HP", async() => { + game.override + .weather(WeatherType.RAIN) + .ability(Abilities.RAIN_DISH); + + await game.classicMode.startBattle([Species.CHARIZARD]); + + const player = game.scene.getPlayerPokemon()!; + + player.damageAndUpdate(player.getMaxHp() - 1); + + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(player.hp).toBe(1); + }, TIMEOUT); + + it("should stop healing from items", async() => { + game.override.startingHeldItems([{name: "LEFTOVERS"}]); + + await game.classicMode.startBattle([Species.CHARIZARD]); + + const player = game.scene.getPlayerPokemon()!; + player.damageAndUpdate(player.getMaxHp() - 1); + + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(player.hp).toBe(1); + }, TIMEOUT); +}); diff --git a/src/test/moves/heart_swap.test.ts b/src/test/moves/heart_swap.test.ts index f658641d46f..a128549c459 100644 --- a/src/test/moves/heart_swap.test.ts +++ b/src/test/moves/heart_swap.test.ts @@ -11,8 +11,6 @@ import { MoveEndPhase } from "#app/phases/move-end-phase"; describe("Moves - Heart Swap", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -60,5 +58,5 @@ describe("Moves - Heart Swap", () => { expect(enemy.getStatStage(s)).toBe(0); expect(player.getStatStage(s)).toBe(1); } - }, TIMEOUT); + }); }); diff --git a/src/test/moves/hyper_beam.test.ts b/src/test/moves/hyper_beam.test.ts index 7aa2dbfec2b..a6a471569ed 100644 --- a/src/test/moves/hyper_beam.test.ts +++ b/src/test/moves/hyper_beam.test.ts @@ -9,8 +9,6 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -const TIMEOUT = 20 * 1000; // 20 sec timeout for all tests - describe("Moves - Hyper Beam", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -67,6 +65,6 @@ describe("Moves - Hyper Beam", () => { await game.phaseInterceptor.to(BerryPhase, false); expect(enemyPokemon.hp).toBeLessThan(enemyPostAttackHp); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/jaw_lock.test.ts b/src/test/moves/jaw_lock.test.ts index 75fd6f0ff32..3398ec00b3b 100644 --- a/src/test/moves/jaw_lock.test.ts +++ b/src/test/moves/jaw_lock.test.ts @@ -11,7 +11,7 @@ import { Species } from "#enums/species"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Jaw Lock", () => { let phaserGame: Phaser.Game; @@ -61,7 +61,7 @@ describe("Moves - Jaw Lock", () => { expect(leadPokemon.getTag(BattlerTagType.TRAPPED)).toBeDefined(); expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeDefined(); - }, TIMEOUT + } ); it( @@ -90,7 +90,7 @@ describe("Moves - Jaw Lock", () => { expect(leadPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - }, TIMEOUT + } ); it( @@ -114,7 +114,7 @@ describe("Moves - Jaw Lock", () => { await game.doKillOpponents(); expect(leadPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - }, TIMEOUT + } ); it( @@ -146,7 +146,7 @@ describe("Moves - Jaw Lock", () => { expect(enemyPokemon[1].getTag(BattlerTagType.TRAPPED)).toBeUndefined(); expect(playerPokemon[0].getTag(BattlerTagType.TRAPPED)).toBeDefined(); expect(playerPokemon[0].getTag(BattlerTagType.TRAPPED)?.sourceId).toBe(enemyPokemon[0].id); - }, TIMEOUT + } ); it( @@ -165,6 +165,6 @@ describe("Moves - Jaw Lock", () => { expect(playerPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined(); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/lash_out.test.ts b/src/test/moves/lash_out.test.ts index 8c414832f36..7a8ab6c5bb6 100644 --- a/src/test/moves/lash_out.test.ts +++ b/src/test/moves/lash_out.test.ts @@ -7,7 +7,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Lash Out", () => { let phaserGame: Phaser.Game; @@ -48,5 +48,5 @@ describe("Moves - Lash Out", () => { await game.phaseInterceptor.to("BerryPhase"); expect(allMoves[Moves.LASH_OUT].calculateBattlePower).toHaveReturnedWith(150); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/lucky_chant.test.ts b/src/test/moves/lucky_chant.test.ts index 57e5ff80f1d..77ea751aee1 100644 --- a/src/test/moves/lucky_chant.test.ts +++ b/src/test/moves/lucky_chant.test.ts @@ -7,7 +7,7 @@ import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import GameManager from "../utils/gameManager"; -const TIMEOUT = 20 * 1000; + describe("Moves - Lucky Chant", () => { let phaserGame: Phaser.Game; @@ -55,7 +55,7 @@ describe("Moves - Lucky Chant", () => { const secondTurnDamage = playerPokemon.getMaxHp() - playerPokemon.hp - firstTurnDamage; expect(secondTurnDamage).toBeLessThan(firstTurnDamage); - }, TIMEOUT + } ); it( @@ -81,7 +81,7 @@ describe("Moves - Lucky Chant", () => { const secondTurnDamage = playerPokemon[0].getMaxHp() - playerPokemon[0].hp - firstTurnDamage; expect(secondTurnDamage).toBeLessThan(firstTurnDamage); - }, TIMEOUT + } ); it( @@ -108,6 +108,6 @@ describe("Moves - Lucky Chant", () => { const secondTurnDamage = playerPokemon.getMaxHp() - playerPokemon.hp - firstTurnDamage; expect(secondTurnDamage).toBeLessThan(firstTurnDamage); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/make_it_rain.test.ts b/src/test/moves/make_it_rain.test.ts index 5ac35168f92..2b28a958ff0 100644 --- a/src/test/moves/make_it_rain.test.ts +++ b/src/test/moves/make_it_rain.test.ts @@ -8,7 +8,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { MoveEndPhase } from "#app/phases/move-end-phase"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; -const TIMEOUT = 20 * 1000; + describe("Moves - Make It Rain", () => { let phaserGame: Phaser.Game; @@ -46,7 +46,7 @@ describe("Moves - Make It Rain", () => { await game.phaseInterceptor.to(MoveEndPhase); expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(-1); - }, TIMEOUT); + }); it("should apply effects even if the target faints", async () => { game.override.enemyLevel(1); // ensures the enemy will faint @@ -63,7 +63,7 @@ describe("Moves - Make It Rain", () => { expect(enemyPokemon.isFainted()).toBe(true); expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(-1); - }, TIMEOUT); + }); it("should reduce Sp. Atk. once after KOing two enemies", async () => { game.override.enemyLevel(1); // ensures the enemy will faint @@ -80,7 +80,7 @@ describe("Moves - Make It Rain", () => { enemyPokemon.forEach(p => expect(p.isFainted()).toBe(true)); expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(-1); - }, TIMEOUT); + }); it("should lower SPATK stat stage by 1 if it only hits the second target", async () => { await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); @@ -96,5 +96,5 @@ describe("Moves - Make It Rain", () => { await game.phaseInterceptor.to(MoveEndPhase); expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(-1); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/mat_block.test.ts b/src/test/moves/mat_block.test.ts index b759f49bf98..0746f9bcfa9 100644 --- a/src/test/moves/mat_block.test.ts +++ b/src/test/moves/mat_block.test.ts @@ -9,7 +9,7 @@ import { BerryPhase } from "#app/phases/berry-phase"; import { CommandPhase } from "#app/phases/command-phase"; import { TurnEndPhase } from "#app/phases/turn-end-phase"; -const TIMEOUT = 20 * 1000; + describe("Moves - Mat Block", () => { let phaserGame: Phaser.Game; @@ -56,7 +56,7 @@ describe("Moves - Mat Block", () => { await game.phaseInterceptor.to(BerryPhase, false); leadPokemon.forEach(p => expect(p.hp).toBe(p.getMaxHp())); - }, TIMEOUT + } ); test( @@ -77,7 +77,7 @@ describe("Moves - Mat Block", () => { await game.phaseInterceptor.to(BerryPhase, false); leadPokemon.forEach(p => expect(p.getStatStage(Stat.ATK)).toBe(-2)); - }, TIMEOUT + } ); test( @@ -103,6 +103,6 @@ describe("Moves - Mat Block", () => { await game.phaseInterceptor.to(BerryPhase, false); expect(leadPokemon.some((p, i) => p.hp < leadStartingHp[i])).toBeTruthy(); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/multi_target.test.ts b/src/test/moves/multi_target.test.ts index 5e830f23fc7..cd69482bd8e 100644 --- a/src/test/moves/multi_target.test.ts +++ b/src/test/moves/multi_target.test.ts @@ -7,7 +7,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Multi-target damage reduction", () => { let phaserGame: Phaser.Game; @@ -75,7 +75,7 @@ describe("Multi-target damage reduction", () => { // Moves that target all enemies get reduced if there's more than one enemy expect(gleam1).toBeLessThanOrEqual(Utils.toDmgValue(gleam2 * 0.75) + 1); expect(gleam1).toBeGreaterThanOrEqual(Utils.toDmgValue(gleam2 * 0.75) - 1); - }, TIMEOUT); + }); it("should reduce earthquake when more than one pokemon other than user is not fainted", async () => { await game.startBattle([Species.MAGIKARP, Species.FEEBAS]); @@ -126,5 +126,5 @@ describe("Multi-target damage reduction", () => { // Turn 3: 1 target, should be no damage reduction expect(damageEnemy1Turn1).toBeLessThanOrEqual(Utils.toDmgValue(damageEnemy1Turn3 * 0.75) + 1); expect(damageEnemy1Turn1).toBeGreaterThanOrEqual(Utils.toDmgValue(damageEnemy1Turn3 * 0.75) - 1); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/obstruct.test.ts b/src/test/moves/obstruct.test.ts index eb12daa785d..43706a5a1d6 100644 --- a/src/test/moves/obstruct.test.ts +++ b/src/test/moves/obstruct.test.ts @@ -8,8 +8,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("Moves - Obstruct", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -41,7 +39,7 @@ describe("Moves - Obstruct", () => { expect(player.isFullHp()).toBe(true); expect(enemy.getStatStage(Stat.DEF)).toBe(-2); - }, TIMEOUT); + }); it("bypasses accuracy checks when applying protection and defense reduction", async () => { game.override.enemyMoveset(Array(4).fill(Moves.ICE_PUNCH)); @@ -57,7 +55,7 @@ describe("Moves - Obstruct", () => { await game.phaseInterceptor.to("TurnEndPhase"); expect(player.isFullHp()).toBe(true); expect(enemy.getStatStage(Stat.DEF)).toBe(-2); - }, TIMEOUT + } ); it("protects from non-contact damaging moves and doesn't lower the opponent's defense by 2 stages", async () => { @@ -72,7 +70,7 @@ describe("Moves - Obstruct", () => { expect(player.isFullHp()).toBe(true); expect(enemy.getStatStage(Stat.DEF)).toBe(0); - }, TIMEOUT); + }); it("doesn't protect from status moves", async () => { game.override.enemyMoveset(Array(4).fill(Moves.GROWL)); @@ -84,5 +82,5 @@ describe("Moves - Obstruct", () => { const player = game.scene.getPlayerPokemon()!; expect(player.getStatStage(Stat.ATK)).toBe(-1); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/octolock.test.ts b/src/test/moves/octolock.test.ts index 7618b08e9fc..d80b71a51e1 100644 --- a/src/test/moves/octolock.test.ts +++ b/src/test/moves/octolock.test.ts @@ -36,7 +36,7 @@ describe("Moves - Octolock", () => { .ability(Abilities.BALL_FETCH); }); - it("lowers DEF and SPDEF stat stages of the target Pokemon by 1 each turn", { timeout: 10000 }, async () => { + it("lowers DEF and SPDEF stat stages of the target Pokemon by 1 each turn", async () => { await game.classicMode.startBattle([ Species.GRAPPLOCT ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -57,7 +57,7 @@ describe("Moves - Octolock", () => { expect(enemyPokemon.getStatStage(Stat.SPDEF)).toBe(-2); }); - it("if target pokemon has BIG_PECKS, should only lower SPDEF stat stage by 1", { timeout: 10000 }, async () => { + it("if target pokemon has BIG_PECKS, should only lower SPDEF stat stage by 1", async () => { game.override.enemyAbility(Abilities.BIG_PECKS); await game.classicMode.startBattle([ Species.GRAPPLOCT ]); @@ -71,7 +71,7 @@ describe("Moves - Octolock", () => { expect(enemyPokemon.getStatStage(Stat.SPDEF)).toBe(-1); }); - it("if target pokemon has WHITE_SMOKE, should not reduce any stat stages", { timeout: 10000 }, async () => { + it("if target pokemon has WHITE_SMOKE, should not reduce any stat stages", async () => { game.override.enemyAbility(Abilities.WHITE_SMOKE); await game.classicMode.startBattle([ Species.GRAPPLOCT ]); @@ -85,7 +85,7 @@ describe("Moves - Octolock", () => { expect(enemyPokemon.getStatStage(Stat.SPDEF)).toBe(0); }); - it("if target pokemon has CLEAR_BODY, should not reduce any stat stages", { timeout: 10000 }, async () => { + it("if target pokemon has CLEAR_BODY, should not reduce any stat stages", async () => { game.override.enemyAbility(Abilities.CLEAR_BODY); await game.classicMode.startBattle([ Species.GRAPPLOCT ]); @@ -99,7 +99,7 @@ describe("Moves - Octolock", () => { expect(enemyPokemon.getStatStage(Stat.SPDEF)).toBe(0); }); - it("traps the target pokemon", { timeout: 10000 }, async () => { + it("traps the target pokemon", async () => { await game.classicMode.startBattle([ Species.GRAPPLOCT ]); const enemyPokemon = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/parting_shot.test.ts b/src/test/moves/parting_shot.test.ts index 52cfaf98111..fa328e15a32 100644 --- a/src/test/moves/parting_shot.test.ts +++ b/src/test/moves/parting_shot.test.ts @@ -10,7 +10,7 @@ import { FaintPhase } from "#app/phases/faint-phase"; import { MessagePhase } from "#app/phases/message-phase"; import { TurnInitPhase } from "#app/phases/turn-init-phase"; -const TIMEOUT = 20 * 1000; + describe("Moves - Parting Shot", () => { let phaserGame: Phaser.Game; @@ -53,7 +53,7 @@ describe("Moves - Parting Shot", () => { expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(0); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(Species.MURKROW); - }, TIMEOUT + } ); test( @@ -73,7 +73,7 @@ describe("Moves - Parting Shot", () => { expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(0); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(Species.MURKROW); - }, TIMEOUT + } ); it.skip( // TODO: fix this bug to pass the test! @@ -115,7 +115,7 @@ describe("Moves - Parting Shot", () => { expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-6); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(-6); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(Species.MURKROW); - }, TIMEOUT + } ); it.skip( // TODO: fix this bug to pass the test! @@ -136,7 +136,7 @@ describe("Moves - Parting Shot", () => { expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(0); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(Species.MURKROW); - }, TIMEOUT + } ); it.skip( // TODO: fix this bug to pass the test! @@ -156,7 +156,7 @@ describe("Moves - Parting Shot", () => { expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(0); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(Species.MURKROW); - }, TIMEOUT + } ); it.skip( // TODO: fix this bug to pass the test! @@ -173,7 +173,7 @@ describe("Moves - Parting Shot", () => { expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(-1); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(Species.MURKROW); - }, TIMEOUT + } ); it.skip( // TODO: fix this bug to pass the test! @@ -196,6 +196,6 @@ describe("Moves - Parting Shot", () => { expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(0); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(Species.MEOWTH); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/power_shift.test.ts b/src/test/moves/power_shift.test.ts index 3fda315193e..f39759f278b 100644 --- a/src/test/moves/power_shift.test.ts +++ b/src/test/moves/power_shift.test.ts @@ -9,8 +9,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("Moves - Power Shift", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -59,5 +57,5 @@ describe("Moves - Power Shift", () => { // Raw stats are swapped expect(playerPokemon.getStat(Stat.ATK, false)).toBe(20); expect(playerPokemon.getStat(Stat.DEF, false)).toBe(10); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/power_swap.test.ts b/src/test/moves/power_swap.test.ts index 92cd786c050..e9a4b569c92 100644 --- a/src/test/moves/power_swap.test.ts +++ b/src/test/moves/power_swap.test.ts @@ -11,8 +11,6 @@ import { MoveEndPhase } from "#app/phases/move-end-phase"; describe("Moves - Power Swap", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -65,5 +63,5 @@ describe("Moves - Power Swap", () => { expect(enemy.getStatStage(s)).toBe(1); } } - }, TIMEOUT); + }); }); diff --git a/src/test/moves/protect.test.ts b/src/test/moves/protect.test.ts index 24bbcbb9d34..dcf4211ac7f 100644 --- a/src/test/moves/protect.test.ts +++ b/src/test/moves/protect.test.ts @@ -10,7 +10,7 @@ import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; import { BattlerIndex } from "#app/battle"; import { MoveResult } from "#app/field/pokemon"; -const TIMEOUT = 20 * 1000; + describe("Moves - Protect", () => { let phaserGame: Phaser.Game; @@ -53,7 +53,7 @@ describe("Moves - Protect", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); - }, TIMEOUT + } ); test( @@ -72,7 +72,7 @@ describe("Moves - Protect", () => { expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); expect(game.scene.arena.getTagOnSide(ArenaTrapTag, ArenaTagSide.ENEMY)).toBeUndefined(); - }, TIMEOUT + } ); test( @@ -89,7 +89,7 @@ describe("Moves - Protect", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0); - }, TIMEOUT + } ); test( @@ -108,7 +108,7 @@ describe("Moves - Protect", () => { expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); expect(enemyPokemon.turnData.hitCount).toBe(1); - }, TIMEOUT + } ); test( @@ -129,6 +129,6 @@ describe("Moves - Protect", () => { expect(enemyPokemon.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS); expect(leadPokemon.getLastXMoves()[0].result).toBe(MoveResult.FAIL); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/purify.test.ts b/src/test/moves/purify.test.ts index 15d684b2d60..3ba9dfcbb65 100644 --- a/src/test/moves/purify.test.ts +++ b/src/test/moves/purify.test.ts @@ -8,7 +8,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Purify", () => { let phaserGame: Phaser.Game; @@ -55,7 +55,6 @@ describe("Moves - Purify", () => { expect(enemyPokemon.status).toBeNull(); expect(playerPokemon.isFullHp()).toBe(true); }, - TIMEOUT ); test( @@ -74,7 +73,6 @@ describe("Moves - Purify", () => { expect(playerPokemon.hp).toBe(playerInitialHp); }, - TIMEOUT ); }); diff --git a/src/test/moves/quick_guard.test.ts b/src/test/moves/quick_guard.test.ts index 9ab0fe1509c..e03beeac06a 100644 --- a/src/test/moves/quick_guard.test.ts +++ b/src/test/moves/quick_guard.test.ts @@ -8,7 +8,7 @@ import { Stat } from "#enums/stat"; import { BattlerIndex } from "#app/battle"; import { MoveResult } from "#app/field/pokemon"; -const TIMEOUT = 20 * 1000; + describe("Moves - Quick Guard", () => { let phaserGame: Phaser.Game; @@ -52,7 +52,7 @@ describe("Moves - Quick Guard", () => { await game.phaseInterceptor.to("BerryPhase", false); playerPokemon.forEach(p => expect(p.hp).toBe(p.getMaxHp())); - }, TIMEOUT + } ); test( @@ -71,7 +71,7 @@ describe("Moves - Quick Guard", () => { await game.phaseInterceptor.to("BerryPhase", false); playerPokemon.forEach(p => expect(p.getStatStage(Stat.ATK)).toBe(0)); - }, TIMEOUT + } ); test( @@ -113,6 +113,6 @@ describe("Moves - Quick Guard", () => { expect(enemyPokemon.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS); expect(playerPokemon.getLastXMoves()[0].result).toBe(MoveResult.FAIL); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/rage_powder.test.ts b/src/test/moves/rage_powder.test.ts index 86bc48ef882..bb31a1f2194 100644 --- a/src/test/moves/rage_powder.test.ts +++ b/src/test/moves/rage_powder.test.ts @@ -6,7 +6,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Rage Powder", () => { let phaserGame: Phaser.Game; @@ -50,7 +50,7 @@ describe("Moves - Rage Powder", () => { // If redirection was bypassed, both enemies should be damaged expect(enemyPokemon[0].hp).toBeLessThan(enemyPokemon[0].getMaxHp()); expect(enemyPokemon[1].hp).toBeLessThan(enemyPokemon[0].getMaxHp()); - }, TIMEOUT + } ); test( @@ -76,6 +76,6 @@ describe("Moves - Rage Powder", () => { // If redirection was bypassed, both enemies should be damaged expect(enemyPokemon[0].hp).toBeLessThan(enemyStartingHp[0]); expect(enemyPokemon[1].hp).toBeLessThan(enemyStartingHp[1]); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/relic_song.test.ts b/src/test/moves/relic_song.test.ts index 373d88f0434..67fc557a318 100644 --- a/src/test/moves/relic_song.test.ts +++ b/src/test/moves/relic_song.test.ts @@ -10,8 +10,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("Moves - Relic Song", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -47,7 +45,7 @@ describe("Moves - Relic Song", () => { await game.phaseInterceptor.to("BerryPhase"); expect(meloetta.formIndex).toBe(0); - }, TIMEOUT); + }); it("doesn't swap Meloetta's form during a mono-type challenge", async () => { game.challengeMode.addChallenge(Challenges.SINGLE_TYPE, Type.PSYCHIC + 1, 0); @@ -62,7 +60,7 @@ describe("Moves - Relic Song", () => { await game.toNextTurn(); expect(meloetta.formIndex).toBe(0); - }, TIMEOUT); + }); it("doesn't swap Meloetta's form during biome change (arena reset)", async () => { game.override @@ -77,5 +75,5 @@ describe("Moves - Relic Song", () => { await game.toNextWave(); expect(meloetta.formIndex).toBe(1); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/roost.test.ts b/src/test/moves/roost.test.ts index c1fc962e876..a1c473c0632 100644 --- a/src/test/moves/roost.test.ts +++ b/src/test/moves/roost.test.ts @@ -9,7 +9,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Roost", () => { let phaserGame: Phaser.Game; @@ -72,7 +72,7 @@ describe("Moves - Roost", () => { expect(playerPokemonTypes[0] === Type.NORMAL).toBeTruthy(); expect(playerPokemonTypes.length === 1).toBeTruthy(); expect(playerPokemon.isGrounded()).toBeTruthy(); - }, TIMEOUT + } ); test( @@ -100,7 +100,7 @@ describe("Moves - Roost", () => { expect(playerPokemonTypes[0] === Type.FLYING).toBeTruthy(); expect(playerPokemon.isGrounded()).toBeFalsy(); - }, TIMEOUT + } ); test( @@ -128,7 +128,7 @@ describe("Moves - Roost", () => { expect(playerPokemonTypes[1] === Type.FLYING).toBeTruthy(); expect(playerPokemon.isGrounded()).toBeFalsy(); - }, TIMEOUT + } ); test( @@ -157,7 +157,7 @@ describe("Moves - Roost", () => { expect(playerPokemonTypes[1] === Type.FLYING).toBeTruthy(); expect(playerPokemon.isGrounded()).toBeFalsy(); - }, TIMEOUT + } ); test( @@ -196,7 +196,7 @@ describe("Moves - Roost", () => { expect(playerPokemonTypes.length === 1).toBeTruthy(); expect(playerPokemon.isGrounded()).toBeFalsy(); - }, TIMEOUT + } ); test( @@ -236,7 +236,7 @@ describe("Moves - Roost", () => { expect(playerPokemonTypes.length === 1).toBeTruthy(); expect(playerPokemon.isGrounded()).toBeFalsy(); - }, TIMEOUT + } ); test( @@ -263,7 +263,7 @@ describe("Moves - Roost", () => { expect(playerPokemonTypes.length === 3).toBeTruthy(); expect(playerPokemon.isGrounded()).toBeFalsy(); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/safeguard.test.ts b/src/test/moves/safeguard.test.ts index 2caf698a73a..b21698d0298 100644 --- a/src/test/moves/safeguard.test.ts +++ b/src/test/moves/safeguard.test.ts @@ -8,7 +8,7 @@ import { Species } from "#enums/species"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Safeguard", () => { let phaserGame: Phaser.Game; @@ -46,7 +46,7 @@ describe("Moves - Safeguard", () => { await game.toNextTurn(); expect(enemy.status).toBeUndefined(); - }, TIMEOUT); + }); it("protects from status moves", async () => { await game.classicMode.startBattle(); @@ -57,7 +57,7 @@ describe("Moves - Safeguard", () => { await game.toNextTurn(); expect(enemyPokemon.status).toBeUndefined(); - }, TIMEOUT); + }); it("protects from confusion", async () => { game.override.moveset([Moves.CONFUSE_RAY]); @@ -69,7 +69,7 @@ describe("Moves - Safeguard", () => { await game.toNextTurn(); expect(enemyPokemon.summonData.tags).toEqual([]); - }, TIMEOUT); + }); it("protects ally from status", async () => { game.override.battleType("double"); @@ -87,7 +87,7 @@ describe("Moves - Safeguard", () => { expect(enemyPokemon[0].status).toBeUndefined(); expect(enemyPokemon[1].status).toBeUndefined(); - }, TIMEOUT); + }); it("protects from Yawn", async () => { await game.classicMode.startBattle(); @@ -98,7 +98,7 @@ describe("Moves - Safeguard", () => { await game.toNextTurn(); expect(enemyPokemon.summonData.tags).toEqual([]); - }, TIMEOUT); + }); it("doesn't protect from already existing Yawn", async () => { await game.classicMode.startBattle(); @@ -112,7 +112,7 @@ describe("Moves - Safeguard", () => { await game.toNextTurn(); expect(enemyPokemon.status?.effect).toEqual(StatusEffect.SLEEP); - }, TIMEOUT); + }); it("doesn't protect from self-inflicted via Rest or Flame Orb", async () => { game.override.enemyHeldItems([{name: "FLAME_ORB"}]); @@ -135,7 +135,7 @@ describe("Moves - Safeguard", () => { await game.toNextTurn(); expect(enemyPokemon.status?.effect).toEqual(StatusEffect.SLEEP); - }, TIMEOUT); + }); it("protects from ability-inflicted status", async () => { game.override.ability(Abilities.STATIC); @@ -151,5 +151,5 @@ describe("Moves - Safeguard", () => { await game.toNextTurn(); expect(enemyPokemon.status).toBeUndefined(); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/shell_side_arm.test.ts b/src/test/moves/shell_side_arm.test.ts index 38d2556a1a2..ded7ed82fd1 100644 --- a/src/test/moves/shell_side_arm.test.ts +++ b/src/test/moves/shell_side_arm.test.ts @@ -10,8 +10,6 @@ import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vite describe("Moves - Shell Side Arm", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -47,7 +45,7 @@ describe("Moves - Shell Side Arm", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(shellSideArmAttr.apply).toHaveLastReturnedWith(true); - }, TIMEOUT); + }); it("remains a special attack if forecasted to deal more damage as special", async () => { game.override.enemySpecies(Species.SLOWBRO); @@ -63,7 +61,7 @@ describe("Moves - Shell Side Arm", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(shellSideArmAttr.apply).toHaveLastReturnedWith(false); - }, TIMEOUT); + }); it("respects stat stage changes when forecasting base damage", async () => { game.override @@ -83,5 +81,5 @@ describe("Moves - Shell Side Arm", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(shellSideArmAttr.apply).toHaveLastReturnedWith(false); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/shell_trap.test.ts b/src/test/moves/shell_trap.test.ts index 213b9c3fd0a..1dae00e24a5 100644 --- a/src/test/moves/shell_trap.test.ts +++ b/src/test/moves/shell_trap.test.ts @@ -10,7 +10,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Shell Trap", () => { let phaserGame: Phaser.Game; @@ -60,7 +60,7 @@ describe("Moves - Shell Trap", () => { await game.phaseInterceptor.to(MoveEndPhase); enemyPokemon.forEach(p => expect(p.hp).toBeLessThan(p.getMaxHp())); - }, TIMEOUT + } ); it( @@ -86,7 +86,7 @@ describe("Moves - Shell Trap", () => { await game.phaseInterceptor.to(BerryPhase, false); enemyPokemon.forEach(p => expect(p.hp).toBe(p.getMaxHp())); - }, TIMEOUT + } ); it( @@ -112,7 +112,7 @@ describe("Moves - Shell Trap", () => { await game.phaseInterceptor.to(BerryPhase, false); enemyPokemon.forEach(p => expect(p.hp).toBe(p.getMaxHp())); - }, TIMEOUT + } ); it( @@ -138,7 +138,7 @@ describe("Moves - Shell Trap", () => { await game.phaseInterceptor.to(BerryPhase, false); enemyPokemon.forEach((p, i) => expect(p.hp).toBe(enemyStartingHp[i])); - }, TIMEOUT + } ); it( @@ -158,6 +158,6 @@ describe("Moves - Shell Trap", () => { expect(playerPokemon.getLastXMoves()[0].result).toBe(MoveResult.FAIL); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/spit_up.test.ts b/src/test/moves/spit_up.test.ts index acf7f01d991..412360c2664 100644 --- a/src/test/moves/spit_up.test.ts +++ b/src/test/moves/spit_up.test.ts @@ -43,7 +43,7 @@ describe("Moves - Spit Up", () => { }); describe("consumes all stockpile stacks to deal damage (scaling with stacks)", () => { - it("1 stack -> 100 power", { timeout: 10000 }, async () => { + it("1 stack -> 100 power", async () => { const stacksToSetup = 1; const expectedPower = 100; @@ -65,7 +65,7 @@ describe("Moves - Spit Up", () => { expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); }); - it("2 stacks -> 200 power", { timeout: 10000 }, async () => { + it("2 stacks -> 200 power", async () => { const stacksToSetup = 2; const expectedPower = 200; @@ -88,7 +88,7 @@ describe("Moves - Spit Up", () => { expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); }); - it("3 stacks -> 300 power", { timeout: 10000 }, async () => { + it("3 stacks -> 300 power", async () => { const stacksToSetup = 3; const expectedPower = 300; @@ -113,7 +113,7 @@ describe("Moves - Spit Up", () => { }); }); - it("fails without stacks", { timeout: 10000 }, async () => { + it("fails without stacks", async () => { await game.startBattle([Species.ABOMASNOW]); const pokemon = game.scene.getPlayerPokemon()!; @@ -130,7 +130,7 @@ describe("Moves - Spit Up", () => { }); describe("restores stat boosts granted by stacks", () => { - it("decreases stats based on stored values (both boosts equal)", { timeout: 10000 }, async () => { + it("decreases stats based on stored values (both boosts equal)", async () => { await game.startBattle([Species.ABOMASNOW]); const pokemon = game.scene.getPlayerPokemon()!; @@ -157,7 +157,7 @@ describe("Moves - Spit Up", () => { expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); }); - it("decreases stats based on stored values (different boosts)", { timeout: 10000 }, async () => { + it("decreases stats based on stored values (different boosts)", async () => { await game.startBattle([Species.ABOMASNOW]); const pokemon = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/spotlight.test.ts b/src/test/moves/spotlight.test.ts index aef44369642..6324c3dc6ec 100644 --- a/src/test/moves/spotlight.test.ts +++ b/src/test/moves/spotlight.test.ts @@ -6,7 +6,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Spotlight", () => { let phaserGame: Phaser.Game; @@ -50,7 +50,7 @@ describe("Moves - Spotlight", () => { expect(enemyPokemon[0].hp).toBeLessThan(enemyPokemon[0].getMaxHp()); expect(enemyPokemon[1].hp).toBe(enemyPokemon[1].getMaxHp()); - }, TIMEOUT + } ); test( @@ -70,6 +70,6 @@ describe("Moves - Spotlight", () => { expect(enemyPokemon[0].hp).toBeLessThan(enemyPokemon[0].getMaxHp()); expect(enemyPokemon[1].hp).toBe(enemyPokemon[1].getMaxHp()); - }, TIMEOUT + } ); }); diff --git a/src/test/moves/stockpile.test.ts b/src/test/moves/stockpile.test.ts index 8e7a44d053b..141ce79eb33 100644 --- a/src/test/moves/stockpile.test.ts +++ b/src/test/moves/stockpile.test.ts @@ -37,7 +37,7 @@ describe("Moves - Stockpile", () => { game.override.ability(Abilities.NONE); }); - it("gains a stockpile stack and raises user's DEF and SPDEF stat stages by 1 on each use, fails at max stacks (3)", { timeout: 10000 }, async () => { + it("gains a stockpile stack and raises user's DEF and SPDEF stat stages by 1 on each use, fails at max stacks (3)", async () => { await game.startBattle([Species.ABOMASNOW]); const user = game.scene.getPlayerPokemon()!; @@ -76,7 +76,7 @@ describe("Moves - Stockpile", () => { } }); - it("gains a stockpile stack even if user's DEF and SPDEF stat stages are at +6", { timeout: 10000 }, async () => { + it("gains a stockpile stack even if user's DEF and SPDEF stat stages are at +6", async () => { await game.startBattle([Species.ABOMASNOW]); const user = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/substitute.test.ts b/src/test/moves/substitute.test.ts index 3976247d489..6c18579e7f6 100644 --- a/src/test/moves/substitute.test.ts +++ b/src/test/moves/substitute.test.ts @@ -16,8 +16,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -const TIMEOUT = 20 * 1000; // 20 sec timeout - describe("Moves - Substitute", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -57,7 +55,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("MoveEndPhase", false); expect(leadPokemon.hp).toBe(Math.ceil(leadPokemon.getMaxHp() * 3/4)); - }, TIMEOUT + } ); it( @@ -81,7 +79,7 @@ describe("Moves - Substitute", () => { expect(leadPokemon.hp).toBe(postSubHp); expect(leadPokemon.getTag(BattlerTagType.SUBSTITUTE)).toBeDefined(); - }, TIMEOUT + } ); it( @@ -107,7 +105,7 @@ describe("Moves - Substitute", () => { expect(leadPokemon.hp).toBe(postSubHp); expect(leadPokemon.getTag(BattlerTagType.SUBSTITUTE)).toBeUndefined(); - }, TIMEOUT + } ); it( @@ -148,7 +146,7 @@ describe("Moves - Substitute", () => { expect(leadPokemon.getTag(BattlerTagType.SUBSTITUTE)).toBeDefined(); expect(leadPokemon.hp).toBeLessThan(postSubHp); - }, TIMEOUT + } ); it( @@ -172,7 +170,7 @@ describe("Moves - Substitute", () => { expect(leadPokemon.getTag(BattlerTagType.SUBSTITUTE)).toBeDefined(); expect(leadPokemon.hp).toBeLessThan(postSubHp); - }, TIMEOUT + } ); it( @@ -192,7 +190,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("MoveEndPhase", false); expect(leadPokemon.getStatStage(Stat.ATK)).toBe(2); - }, TIMEOUT + } ); it( @@ -213,7 +211,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); it( @@ -233,7 +231,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(leadPokemon.getTag(TrappedTag)).toBeUndefined(); - }, TIMEOUT + } ); it( @@ -253,7 +251,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(leadPokemon.getStatStage(Stat.DEF)).toBe(0); - }, TIMEOUT + } ); it( @@ -272,7 +270,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(leadPokemon.status?.effect).not.toBe(StatusEffect.PARALYSIS); - }, TIMEOUT + } ); it( @@ -293,7 +291,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(leadPokemon.getHeldItems().length).toBe(1); - }, TIMEOUT + } ); it( @@ -314,7 +312,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("MoveEndPhase", false); expect(enemyPokemon.getHeldItems().length).toBe(enemyNumItems); - }, TIMEOUT + } ); it( @@ -339,7 +337,7 @@ describe("Moves - Substitute", () => { expect(leadPokemon.getHeldItems().length).toBe(1); expect(enemyPokemon.hp).toBe(enemyPostAttackHp); - }, TIMEOUT + } ); it( @@ -358,7 +356,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(leadPokemon.getStatStage(Stat.ATK)).toBe(2); - }, TIMEOUT + } ); it( @@ -404,7 +402,7 @@ describe("Moves - Substitute", () => { const subTag = switchedPokemon.getTag(SubstituteTag)!; expect(subTag).toBeDefined(); expect(subTag.hp).toBe(Math.floor(leadPokemon.getMaxHp() * 1/4)); - }, TIMEOUT + } ); it( @@ -422,7 +420,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); it( @@ -447,7 +445,7 @@ describe("Moves - Substitute", () => { expect(playerPokemon.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS); expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); it( @@ -467,7 +465,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(playerPokemon.getLastXMoves()[0].result).toBe(MoveResult.FAIL); - }, TIMEOUT + } ); it( @@ -488,7 +486,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(enemyPokemon.status?.effect).not.toBe(StatusEffect.BURN); - }, TIMEOUT + } ); it( diff --git a/src/test/moves/swallow.test.ts b/src/test/moves/swallow.test.ts index 5a0e63e6e78..b8ca941d0ee 100644 --- a/src/test/moves/swallow.test.ts +++ b/src/test/moves/swallow.test.ts @@ -38,7 +38,7 @@ describe("Moves - Swallow", () => { }); describe("consumes all stockpile stacks to heal (scaling with stacks)", () => { - it("1 stack -> 25% heal", { timeout: 10000 }, async () => { + it("1 stack -> 25% heal", async () => { const stacksToSetup = 1; const expectedHeal = 25; @@ -65,7 +65,7 @@ describe("Moves - Swallow", () => { expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); }); - it("2 stacks -> 50% heal", { timeout: 10000 }, async () => { + it("2 stacks -> 50% heal", async () => { const stacksToSetup = 2; const expectedHeal = 50; @@ -93,7 +93,7 @@ describe("Moves - Swallow", () => { expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); }); - it("3 stacks -> 100% heal", { timeout: 10000 }, async () => { + it("3 stacks -> 100% heal", async () => { const stacksToSetup = 3; const expectedHeal = 100; @@ -123,7 +123,7 @@ describe("Moves - Swallow", () => { }); }); - it("fails without stacks", { timeout: 10000 }, async () => { + it("fails without stacks", async () => { await game.startBattle([Species.ABOMASNOW]); const pokemon = game.scene.getPlayerPokemon()!; @@ -138,7 +138,7 @@ describe("Moves - Swallow", () => { }); describe("restores stat stage boosts granted by stacks", () => { - it("decreases stats based on stored values (both boosts equal)", { timeout: 10000 }, async () => { + it("decreases stats based on stored values (both boosts equal)", async () => { await game.startBattle([Species.ABOMASNOW]); const pokemon = game.scene.getPlayerPokemon()!; @@ -163,7 +163,7 @@ describe("Moves - Swallow", () => { expect(pokemon.getTag(StockpilingTag)).toBeUndefined(); }); - it("lower stat stages based on stored values (different boosts)", { timeout: 10000 }, async () => { + it("lower stat stages based on stored values (different boosts)", async () => { await game.startBattle([Species.ABOMASNOW]); const pokemon = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/tar_shot.test.ts b/src/test/moves/tar_shot.test.ts index 2963f061fc6..2385bd18265 100644 --- a/src/test/moves/tar_shot.test.ts +++ b/src/test/moves/tar_shot.test.ts @@ -11,8 +11,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite describe("Moves - Tar Shot", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -54,7 +52,7 @@ describe("Moves - Tar Shot", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(4); - }, TIMEOUT); + }); it("will not double the effectiveness of Fire-type moves used on a target that is already under the effect of Tar Shot (but may still lower its Speed)", async () => { await game.classicMode.startBattle([Species.PIKACHU]); @@ -82,7 +80,7 @@ describe("Moves - Tar Shot", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(4); - }, TIMEOUT); + }); it("does not double the effectiveness of Fire-type moves against a Pokémon that is Terastallized", async () => { game.override.enemyHeldItems([{ name: "TERA_SHARD", type: Type.GRASS }]).enemySpecies(Species.SPRIGATITO); @@ -104,7 +102,7 @@ describe("Moves - Tar Shot", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(2); - }, TIMEOUT); + }); it("doubles the effectiveness of Fire-type moves against a Pokémon that is already under the effects of Tar Shot before it Terastallized", async () => { game.override.enemySpecies(Species.SPRIGATITO); @@ -128,5 +126,5 @@ describe("Moves - Tar Shot", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(4); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/thousand_arrows.test.ts b/src/test/moves/thousand_arrows.test.ts index 8d1d6ee5f4a..ad9281dc45e 100644 --- a/src/test/moves/thousand_arrows.test.ts +++ b/src/test/moves/thousand_arrows.test.ts @@ -8,7 +8,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Thousand Arrows", () => { let phaserGame: Phaser.Game; @@ -51,7 +51,7 @@ describe("Moves - Thousand Arrows", () => { expect(enemyPokemon.getTag(BattlerTagType.IGNORE_FLYING)).toBeDefined(); expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); it( @@ -74,7 +74,7 @@ describe("Moves - Thousand Arrows", () => { expect(enemyPokemon.getTag(BattlerTagType.IGNORE_FLYING)).toBeDefined(); expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); - }, TIMEOUT + } ); it( diff --git a/src/test/moves/throat_chop.test.ts b/src/test/moves/throat_chop.test.ts index cb34b4bafff..2a0ab675b25 100644 --- a/src/test/moves/throat_chop.test.ts +++ b/src/test/moves/throat_chop.test.ts @@ -10,8 +10,6 @@ import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest"; describe("Moves - Throat Chop", () => { let phaserGame: Phaser.Game; let game: GameManager; - const TIMEOUT = 20 * 1000; - beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -53,5 +51,5 @@ describe("Moves - Throat Chop", () => { await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.isFullHp()).toBe(false); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/thunder_wave.test.ts b/src/test/moves/thunder_wave.test.ts index 7ad59518013..28c5da4717b 100644 --- a/src/test/moves/thunder_wave.test.ts +++ b/src/test/moves/thunder_wave.test.ts @@ -7,7 +7,7 @@ import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -const TIMEOUT = 20 * 1000; + describe("Moves - Thunder Wave", () => { let phaserGame: Phaser.Game; @@ -45,7 +45,7 @@ describe("Moves - Thunder Wave", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.status?.effect).toBe(StatusEffect.PARALYSIS); - }, TIMEOUT); + }); it("does not paralyze if the Pokemon is a Ground-type", async () => { game.override.enemySpecies(Species.DIGLETT); @@ -58,7 +58,7 @@ describe("Moves - Thunder Wave", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.status).toBeUndefined(); - }, TIMEOUT); + }); it("does not paralyze if the Pokemon already has a status effect", async () => { game.override.enemySpecies(Species.MAGIKARP).enemyStatusEffect(StatusEffect.BURN); @@ -71,7 +71,7 @@ describe("Moves - Thunder Wave", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.status?.effect).not.toBe(StatusEffect.PARALYSIS); - }, TIMEOUT); + }); it("affects Ground types if the user has Normalize", async () => { game.override.ability(Abilities.NORMALIZE).enemySpecies(Species.DIGLETT); @@ -84,7 +84,7 @@ describe("Moves - Thunder Wave", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.status?.effect).toBe(StatusEffect.PARALYSIS); - }, TIMEOUT); + }); it("does not affect Ghost types if the user has Normalize", async () => { game.override.ability(Abilities.NORMALIZE).enemySpecies(Species.HAUNTER); @@ -97,5 +97,5 @@ describe("Moves - Thunder Wave", () => { await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.status).toBeUndefined(); - }, TIMEOUT); + }); }); diff --git a/src/test/moves/wide_guard.test.ts b/src/test/moves/wide_guard.test.ts index b4e6e305539..9ddd8905ff6 100644 --- a/src/test/moves/wide_guard.test.ts +++ b/src/test/moves/wide_guard.test.ts @@ -8,7 +8,7 @@ import { Stat } from "#enums/stat"; import { BerryPhase } from "#app/phases/berry-phase"; import { CommandPhase } from "#app/phases/command-phase"; -const TIMEOUT = 20 * 1000; + describe("Moves - Wide Guard", () => { let phaserGame: Phaser.Game; @@ -55,7 +55,7 @@ describe("Moves - Wide Guard", () => { await game.phaseInterceptor.to(BerryPhase, false); leadPokemon.forEach(p => expect(p.hp).toBe(p.getMaxHp())); - }, TIMEOUT + } ); test( @@ -76,7 +76,7 @@ describe("Moves - Wide Guard", () => { await game.phaseInterceptor.to(BerryPhase, false); leadPokemon.forEach(p => expect(p.getStatStage(Stat.ATK)).toBe(0)); - }, TIMEOUT + } ); test( @@ -97,7 +97,7 @@ describe("Moves - Wide Guard", () => { await game.phaseInterceptor.to(BerryPhase, false); expect(leadPokemon.some(p => p.hp < p.getMaxHp())).toBeTruthy(); - }, TIMEOUT + } ); test( @@ -120,6 +120,6 @@ describe("Moves - Wide Guard", () => { expect(leadPokemon[0].hp).toBe(leadPokemon[0].getMaxHp()); enemyPokemon.forEach(p => expect(p.hp).toBeLessThan(p.getMaxHp())); - }, TIMEOUT + } ); }); diff --git a/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts b/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts index 88704746a3c..c39e636b462 100644 --- a/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts @@ -231,7 +231,7 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => { }); describe("Option 3 - Leave", () => { - it("should leave encounter without battle", async () => { + it.each(Array.from({length: 30}))("should leave encounter without battle", async () => { const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); await game.runToMysteryEncounter(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, defaultParty); diff --git a/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts b/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts index af5c0f0b48b..78f4a477216 100644 --- a/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts @@ -19,7 +19,7 @@ import { CommandPhase } from "#app/phases/command-phase"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; const namespace = "mysteryEncounter:berriesAbound"; -const defaultParty = [Species.PYUKUMUKU]; +const defaultParty = [Species.PYUKUMUKU, Species.MAGIKARP, Species.PIKACHU]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -116,7 +116,9 @@ describe("Berries Abound - Mystery Encounter", () => { expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); }); - // TODO: there is some severe test flakiness occurring for this file, needs to be looked at/addressed in separate issue + /** + * Related issue-comment: {@link https://github.com/pagefaultgames/pokerogue/issues/4300#issuecomment-2362849444} + */ it("should reward the player with X berries based on wave", async () => { await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty); @@ -188,15 +190,14 @@ describe("Berries Abound - Mystery Encounter", () => { }); it("Should skip battle when fastest pokemon is faster than boss", async () => { - const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); - const encounterTextSpy = vi.spyOn(EncounterDialogueUtils, "showEncounterText"); + vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); + vi.spyOn(EncounterDialogueUtils, "showEncounterText"); await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty); - // Setting party pokemon's level arbitrarily high to outspeed - const fastestPokemon = scene.getParty()[0]; - fastestPokemon.level = 1000; - fastestPokemon.calculateStats(); + scene.getParty().forEach(pkm => { + vi.spyOn(pkm, "getStat").mockReturnValue(9999); // for ease return for every stat + }); await runMysteryEncounterToEnd(game, 2); await game.phaseInterceptor.to(SelectModifierPhase, false); @@ -210,8 +211,8 @@ describe("Berries Abound - Mystery Encounter", () => { expect(option.modifierTypeOption.type.id).toContain("BERRY"); } - expect(encounterTextSpy).toHaveBeenCalledWith(expect.any(BattleScene), `${namespace}.option.2.selected`); - expect(leaveEncounterWithoutBattleSpy).toBeCalled(); + expect(EncounterDialogueUtils.showEncounterText).toHaveBeenCalledWith(expect.any(BattleScene), `${namespace}.option.2.selected`); + expect(EncounterPhaseUtils.leaveEncounterWithoutBattle).toBeCalled(); }); }); diff --git a/src/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts b/src/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts index 5a99b0450ca..ec35b338365 100644 --- a/src/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts @@ -69,6 +69,20 @@ describe("Global Trade System - Mystery Encounter", () => { expect(GlobalTradeSystemEncounter.options.length).toBe(4); }); + it("should not loop infinitely when generating trade options for extreme BST non-legendaries", async () => { + const extremeBstTeam = [Species.SLAKING, Species.WISHIWASHI, Species.SUNKERN]; + await game.runToMysteryEncounter(MysteryEncounterType.GLOBAL_TRADE_SYSTEM, extremeBstTeam); + + expect(GlobalTradeSystemEncounter.encounterType).toBe(MysteryEncounterType.GLOBAL_TRADE_SYSTEM); + expect(GlobalTradeSystemEncounter.encounterTier).toBe(MysteryEncounterTier.COMMON); + expect(GlobalTradeSystemEncounter.dialogue).toBeDefined(); + expect(GlobalTradeSystemEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}.intro` }]); + expect(GlobalTradeSystemEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`); + expect(GlobalTradeSystemEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`); + expect(GlobalTradeSystemEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`); + expect(GlobalTradeSystemEncounter.options.length).toBe(4); + }); + it("should not spawn outside of CIVILIZATION_ENCOUNTER_BIOMES", async () => { game.override.mysteryEncounterTier(MysteryEncounterTier.COMMON); game.override.startingBiome(Biome.VOLCANO); diff --git a/src/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts b/src/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts index f7f96de3af3..44a5197a39e 100644 --- a/src/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts @@ -15,6 +15,7 @@ import { TeleportingHijinksEncounter } from "#app/data/mystery-encounters/encoun import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import { Mode } from "#app/ui/ui"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; +import { Abilities } from "#app/enums/abilities"; const namespace = "mysteryEncounter:teleportingHijinks"; const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; @@ -36,10 +37,12 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { game = new GameManager(phaserGame); scene = game.scene; scene.money = 20000; - game.override.mysteryEncounterChance(100); - game.override.startingWave(defaultWave); - game.override.startingBiome(defaultBiome); - game.override.disableTrainerWaves(); + game.override + .mysteryEncounterChance(100) + .startingWave(defaultWave) + .startingBiome(defaultBiome) + .disableTrainerWaves() + .enemyPassiveAbility(Abilities.BALL_FETCH); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ @@ -172,7 +175,16 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { expect(TRANSPORT_BIOMES).toContain(scene.arena.biomeType); }); - it("should start a battle against an enraged boss", { retry: 5 }, async () => { + it("should start a battle against an enraged boss below wave 50", { retry: 5 }, async () => { + await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty); + await runMysteryEncounterToEnd(game, 1, undefined, true); + const enemyField = scene.getEnemyField(); + expect(enemyField[0].summonData.statStages).toEqual([0, 1, 0, 1, 1, 0, 0]); + expect(enemyField[0].isBoss()).toBe(true); + }); + + it("should start a battle against an extra enraged boss above wave 50", { retry: 5 }, async () => { + game.override.startingWave(56); await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty); await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); @@ -235,10 +247,19 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { expect(TRANSPORT_BIOMES).toContain(scene.arena.biomeType); }); - it("should start a battle against an enraged boss", async () => { + it("should start a battle against an enraged boss below wave 50", async () => { await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [Species.PIKACHU]); await runMysteryEncounterToEnd(game, 2, undefined, true); const enemyField = scene.getEnemyField(); + expect(enemyField[0].summonData.statStages).toEqual([0, 1, 0, 1, 1, 0, 0]); + expect(enemyField[0].isBoss()).toBe(true); + }); + + it("should start a battle against an extra enraged boss above wave 50", { retry: 5 }, async () => { + game.override.startingWave(56); + await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty); + await runMysteryEncounterToEnd(game, 1, undefined, true); + const enemyField = scene.getEnemyField(); expect(enemyField[0].summonData.statStages).toEqual([1, 1, 1, 1, 1, 0, 0]); expect(enemyField[0].isBoss()).toBe(true); }); diff --git a/src/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts b/src/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts index d37a9d8fb7b..e2b1fe8309b 100644 --- a/src/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts @@ -53,19 +53,22 @@ describe("The Pokemon Salesman - Mystery Encounter", () => { }); it("should have the correct properties", async () => { + const { encounterType, encounterTier, dialogue, options } = ThePokemonSalesmanEncounter; + await game.runToMysteryEncounter(MysteryEncounterType.THE_POKEMON_SALESMAN, defaultParty); - expect(ThePokemonSalesmanEncounter.encounterType).toBe(MysteryEncounterType.THE_POKEMON_SALESMAN); - expect(ThePokemonSalesmanEncounter.encounterTier).toBe(MysteryEncounterTier.ULTRA); - expect(ThePokemonSalesmanEncounter.dialogue).toBeDefined(); - expect(ThePokemonSalesmanEncounter.dialogue.intro).toStrictEqual([ + expect(encounterType).toBe(MysteryEncounterType.THE_POKEMON_SALESMAN); + expect(encounterTier).toBe(MysteryEncounterTier.ULTRA); + expect(dialogue).toBeDefined(); + expect(dialogue.intro).toStrictEqual([ { text: `${namespace}.intro` }, { speaker: `${namespace}.speaker`, text: `${namespace}.intro_dialogue` } ]); - expect(ThePokemonSalesmanEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`); - expect(ThePokemonSalesmanEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`); - expect(ThePokemonSalesmanEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`); - expect(ThePokemonSalesmanEncounter.options.length).toBe(2); + const { title, description, query } = dialogue.encounterOptionsDialogue!; + expect(title).toBe(`${namespace}.title`); + expect(description).toMatch(new RegExp(`^${namespace}\\.description(_shiny)?$`)); + expect(query).toBe(`${namespace}.query`); + expect(options.length).toBe(2); }); it("should not spawn outside of HUMAN_TRANSITABLE_BIOMES", async () => { @@ -104,12 +107,13 @@ describe("The Pokemon Salesman - Mystery Encounter", () => { describe("Option 1 - Purchase the pokemon", () => { it("should have the correct properties", () => { - const option = ThePokemonSalesmanEncounter.options[0]; - expect(option.optionMode).toBe(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT); - expect(option.dialogue).toBeDefined(); - expect(option.dialogue).toStrictEqual({ + const { optionMode, dialogue } = ThePokemonSalesmanEncounter.options[0]; + + expect(optionMode).toBe(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT); + expect(dialogue).toBeDefined(); + expect(dialogue).toStrictEqual({ buttonLabel: `${namespace}.option.1.label`, - buttonTooltip: `${namespace}.option.1.tooltip`, + buttonTooltip: expect.stringMatching(new RegExp(`^${namespace}\\.option\\.1\\.tooltip(_shiny)?$`)), selected: [ { text: `${namespace}.option.1.selected_message`, diff --git a/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts b/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts index e532891810c..d858d631596 100644 --- a/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts @@ -174,7 +174,7 @@ describe("Weird Dream - Mystery Encounter", () => { }); }); - it("should reduce party levels by 20%", async () => { + it("should reduce party levels by 12.5%", async () => { const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); await game.runToMysteryEncounter(MysteryEncounterType.WEIRD_DREAM, defaultParty); @@ -184,7 +184,7 @@ describe("Weird Dream - Mystery Encounter", () => { const levelsAfter = scene.getParty().map(p => p.level); for (let i = 0; i < levelsPrior.length; i++) { - expect(Math.max(Math.ceil(0.8 * levelsPrior[i]), 1)).toBe(levelsAfter[i]); + expect(Math.max(Math.ceil(0.8875 * levelsPrior[i]), 1)).toBe(levelsAfter[i]); expect(scene.getParty()[i].levelExp).toBe(0); } diff --git a/src/test/mystery-encounter/mystery-encounter-utils.test.ts b/src/test/mystery-encounter/mystery-encounter-utils.test.ts index 61eb1eaffd1..7a13db512aa 100644 --- a/src/test/mystery-encounter/mystery-encounter-utils.test.ts +++ b/src/test/mystery-encounter/mystery-encounter-utils.test.ts @@ -67,7 +67,7 @@ describe("Mystery Encounter Utils", () => { expect(result.species.speciesId).toBe(Species.ARCEUS); }); - it("gets an unfainted pokemon from player party if isAllowedInBattle is true", () => { + it("gets an unfainted legal pokemon from player party if isAllowed is true and isFainted is false", () => { // Only faint 1st pokemon const party = scene.getParty(); party[0].hp = 0; @@ -115,12 +115,12 @@ describe("Mystery Encounter Utils", () => { // Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal) game.override.seed("random"); - let result = getRandomPlayerPokemon(scene, true, true); + let result = getRandomPlayerPokemon(scene, true, false, true); expect(result.species.speciesId).toBe(Species.ARCEUS); game.override.seed("random2"); - result = getRandomPlayerPokemon(scene, true, true); + result = getRandomPlayerPokemon(scene, true, false, true); expect(result.species.speciesId).toBe(Species.ARCEUS); }); }); @@ -301,41 +301,5 @@ describe("Mystery Encounter Utils", () => { expect(spy).toHaveBeenCalledWith("valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}", "valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}", null, expect.any(Function), 0); }); }); - - describe("initBattleWithEnemyConfig", () => { - it("", () => { - - }); - }); - - describe("setCustomEncounterRewards", () => { - it("", () => { - - }); - }); - - describe("selectPokemonForOption", () => { - it("", () => { - - }); - }); - - describe("setEncounterExp", () => { - it("", () => { - - }); - }); - - describe("leaveEncounterWithoutBattle", () => { - it("", () => { - - }); - }); - - describe("handleMysteryEncounterVictory", () => { - it("", () => { - - }); - }); }); diff --git a/src/test/reload.test.ts b/src/test/reload.test.ts index 7c4523dd9ef..5009d76d1a7 100644 --- a/src/test/reload.test.ts +++ b/src/test/reload.test.ts @@ -35,7 +35,7 @@ describe("Reload", () => { expect(preReloadRngState).toBe(postReloadRngState); }, 20000); - it("should not have RNG inconsistencies after a biome switch", async () => { + it.each(Array.from({length: 100}))("should not have RNG inconsistencies after a biome switch", async () => { game.override .startingWave(10) .battleType("single") diff --git a/src/ui-inputs.ts b/src/ui-inputs.ts index 5860702a15b..b9ecb55958c 100644 --- a/src/ui-inputs.ts +++ b/src/ui-inputs.ts @@ -169,12 +169,14 @@ export class UiInputs { } switch (this.scene.ui?.getMode()) { case Mode.MESSAGE: - if (!(this.scene.ui.getHandler() as MessageUiHandler).pendingPrompt) { + const messageHandler = this.scene.ui.getHandler(); + if (!messageHandler.pendingPrompt || messageHandler.isTextAnimationInProgress()) { return; } case Mode.TITLE: case Mode.COMMAND: case Mode.MODIFIER_SELECT: + case Mode.MYSTERY_ENCOUNTER: this.scene.ui.setOverlayMode(Mode.MENU); break; case Mode.STARTER_SELECT: diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index 3bf55119335..59d14ab3bc4 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -1,4 +1,4 @@ -import BattleScene from "../battle-scene"; +import BattleScene, { InfoToggle } from "../battle-scene"; import { addTextObject, TextStyle } from "./text"; import { getTypeDamageMultiplierColor, Type } from "../data/type"; import { Command } from "./command-ui-handler"; @@ -10,9 +10,10 @@ import i18next from "i18next"; import {Button} from "#enums/buttons"; import Pokemon, { PokemonMove } from "#app/field/pokemon"; import { CommandPhase } from "#app/phases/command-phase"; +import MoveInfoOverlay from "./move-info-overlay"; import { BattleType } from "#app/battle"; -export default class FightUiHandler extends UiHandler { +export default class FightUiHandler extends UiHandler implements InfoToggle { public static readonly MOVES_CONTAINER_NAME = "moves"; private movesContainer: Phaser.GameObjects.Container; @@ -26,6 +27,7 @@ export default class FightUiHandler extends UiHandler { private accuracyText: Phaser.GameObjects.Text; private cursorObj: Phaser.GameObjects.Image | null; private moveCategoryIcon: Phaser.GameObjects.Sprite; + private moveInfoOverlay : MoveInfoOverlay; protected fieldIndex: integer = 0; protected cursor2: integer = 0; @@ -85,6 +87,24 @@ export default class FightUiHandler extends UiHandler { this.accuracyText.setOrigin(1, 0.5); this.accuracyText.setVisible(false); this.moveInfoContainer.add(this.accuracyText); + + // prepare move overlay + const overlayScale = 1; + this.moveInfoOverlay = new MoveInfoOverlay(this.scene, { + delayVisibility: true, + scale: overlayScale, + onSide: true, + right: true, + x: 0, + y: -MoveInfoOverlay.getHeight(overlayScale, true), + width: (this.scene.game.canvas.width / 6) + 4, + hideEffectBox: true, + hideBg: true + }); + ui.add(this.moveInfoOverlay); + // register the overlay to receive toggle events + this.scene.addInfoToggle(this.moveInfoOverlay); + this.scene.addInfoToggle(this); } show(args: any[]): boolean { @@ -103,6 +123,8 @@ export default class FightUiHandler extends UiHandler { this.setCursor(this.getCursor()); } this.displayMoves(); + this.toggleInfo(false); // in case cancel was pressed while info toggle is active + this.active = true; return true; } @@ -160,6 +182,27 @@ export default class FightUiHandler extends UiHandler { return success; } + toggleInfo(visible: boolean): void { + if (visible) { + this.movesContainer.setVisible(false); + this.cursorObj?.setVisible(false); + } + this.scene.tweens.add({ + targets: [this.movesContainer, this.cursorObj], + duration: Utils.fixedInt(125), + ease: "Sine.easeInOut", + alpha: visible ? 0 : 1 + }); + if (!visible) { + this.movesContainer.setVisible(true); + this.cursorObj?.setVisible(true); + } + } + + isActive(): boolean { + return this.active; + } + getCursor(): integer { return !this.fieldIndex ? this.cursor : this.cursor2; } @@ -167,6 +210,7 @@ export default class FightUiHandler extends UiHandler { setCursor(cursor: integer): boolean { const ui = this.getUi(); + this.moveInfoOverlay.clear(); const changed = this.getCursor() !== cursor; if (changed) { if (!this.fieldIndex) { @@ -220,6 +264,7 @@ export default class FightUiHandler extends UiHandler { //** Changes the text color and shadow according to the determined TextStyle */ this.ppText.setColor(this.getTextColor(ppColorStyle, false)); this.ppText.setShadowColor(this.getTextColor(ppColorStyle, true)); + this.moveInfoOverlay.show(pokemonMove.getMove()); pokemon.getOpponents().forEach((opponent) => { opponent.updateEffectiveness(this.getEffectivenessText(pokemon, opponent, pokemonMove)); @@ -307,8 +352,10 @@ export default class FightUiHandler extends UiHandler { this.accuracyLabel.setVisible(false); this.accuracyText.setVisible(false); this.moveCategoryIcon.setVisible(false); + this.moveInfoOverlay.clear(); messageHandler.bg.setVisible(true); this.eraseCursor(); + this.active = false; } clearMoves() { diff --git a/src/ui/message-ui-handler.ts b/src/ui/message-ui-handler.ts index 54965a590fc..f1b8ed981ee 100644 --- a/src/ui/message-ui-handler.ts +++ b/src/ui/message-ui-handler.ts @@ -223,6 +223,14 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler { }; } + isTextAnimationInProgress() { + if (this.textTimer) { + return this.textTimer.repeatCount < this.textTimer.repeat; + } + + return false; + } + clearText() { this.message.setText(""); this.pendingPrompt = false; diff --git a/src/ui/move-info-overlay.ts b/src/ui/move-info-overlay.ts index a99e4c81e27..42026082b36 100644 --- a/src/ui/move-info-overlay.ts +++ b/src/ui/move-info-overlay.ts @@ -15,12 +15,16 @@ export interface MoveInfoOverlaySettings { //location and width of the component; unaffected by scaling x?: number; y?: number; - width?: number; // default is always half the screen, regardless of scale + /** Default is always half the screen, regardless of scale */ + width?: number; + /** Determines whether to display the small secondary box */ + hideEffectBox?: boolean; + hideBg?: boolean; } -const EFF_HEIGHT = 46; +const EFF_HEIGHT = 48; const EFF_WIDTH = 82; -const DESC_HEIGHT = 46; +const DESC_HEIGHT = 48; const BORDER = 8; const GLOBAL_SCALE = 6; @@ -38,6 +42,7 @@ export default class MoveInfoOverlay extends Phaser.GameObjects.Container implem private acc: Phaser.GameObjects.Text; private typ: Phaser.GameObjects.Sprite; private cat: Phaser.GameObjects.Sprite; + private descBg: Phaser.GameObjects.NineSlice; private options : MoveInfoOverlaySettings; @@ -52,9 +57,9 @@ export default class MoveInfoOverlay extends Phaser.GameObjects.Container implem // prepare the description box const width = (options?.width || MoveInfoOverlay.getWidth(scale, scene)) / scale; // divide by scale as we always want this to be half a window wide - const descBg = addWindow(scene, (options?.onSide && !options?.right ? EFF_WIDTH : 0), options?.top ? EFF_HEIGHT : 0, width - (options?.onSide ? EFF_WIDTH : 0), DESC_HEIGHT); - descBg.setOrigin(0, 0); - this.add(descBg); + this.descBg = addWindow(scene, (options?.onSide && !options?.right ? EFF_WIDTH : 0), options?.top ? EFF_HEIGHT : 0, width - (options?.onSide ? EFF_WIDTH : 0), DESC_HEIGHT); + this.descBg.setOrigin(0, 0); + this.add(this.descBg); // set up the description; wordWrap uses true pixels, unaffected by any scaling, while other values are affected this.desc = addTextObject(scene, (options?.onSide && !options?.right ? EFF_WIDTH : 0) + BORDER, (options?.top ? EFF_HEIGHT : 0) + BORDER - 2, "", TextStyle.BATTLE_INFO, { wordWrap: { width: (width - (BORDER - 2) * 2 - (options?.onSide ? EFF_WIDTH : 0)) * GLOBAL_SCALE } }); @@ -125,6 +130,14 @@ export default class MoveInfoOverlay extends Phaser.GameObjects.Container implem this.acc.setOrigin(1, 0.5); this.val.add(this.acc); + if (options?.hideEffectBox) { + this.val.setVisible(false); + } + + if (options?.hideBg) { + this.descBg.setVisible(false); + } + // hide this component for now this.setVisible(false); } @@ -176,8 +189,19 @@ export default class MoveInfoOverlay extends Phaser.GameObjects.Container implem this.active = false; } - toggleInfo(force?: boolean): void { - this.setVisible(force ?? !this.visible); + toggleInfo(visible: boolean): void { + if (visible) { + this.setVisible(true); + } + this.scene.tweens.add({ + targets: this.desc, + duration: Utils.fixedInt(125), + ease: "Sine.easeInOut", + alpha: visible ? 1 : 0 + }); + if (!visible) { + this.setVisible(false); + } } isActive(): boolean { diff --git a/src/ui/pokemon-info-container.ts b/src/ui/pokemon-info-container.ts index e9ad2a26c15..242e59c599b 100644 --- a/src/ui/pokemon-info-container.ts +++ b/src/ui/pokemon-info-container.ts @@ -12,6 +12,7 @@ import ConfirmUiHandler from "./confirm-ui-handler"; import { StatsContainer } from "./stats-container"; import { TextStyle, addBBCodeTextObject, addTextObject, getTextColor } from "./text"; import { addWindow } from "./ui-theme"; +import { Species } from "#enums/species"; interface LanguageSetting { infoContainerTextSize: string; @@ -234,7 +235,19 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container { this.pokemonGenderText.setVisible(false); } - if (pokemon.species.forms?.[pokemon.formIndex]?.formName) { + const formKey = (pokemon.species?.forms?.[pokemon.formIndex!]?.formKey); + const formText = Utils.capitalizeString(formKey, "-", false, false) || ""; + const speciesName = Utils.capitalizeString(Species[pokemon.species.getRootSpeciesId()], "_", true, false); + + let formName = ""; + if (pokemon.species.speciesId === Species.ARCEUS) { + formName = i18next.t(`pokemonInfo:Type.${formText?.toUpperCase()}`); + } else { + const i18key = `pokemonForm:${speciesName}${formText}`; + formName = i18next.exists(i18key) ? i18next.t(i18key) : formText; + } + + if (formName) { this.pokemonFormLabelText.setVisible(true); this.pokemonFormText.setVisible(true); const newForm = BigInt(1 << pokemon.formIndex) * DexAttr.DEFAULT_FORM; @@ -247,11 +260,10 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container { this.pokemonFormLabelText.setShadowColor(getTextColor(TextStyle.WINDOW, true, this.scene.uiTheme)); } - const formName = pokemon.species.forms?.[pokemon.formIndex]?.formName; this.pokemonFormText.setText(formName.length > this.numCharsBeforeCutoff ? formName.substring(0, this.numCharsBeforeCutoff - 3) + "..." : formName); if (formName.length > this.numCharsBeforeCutoff) { this.pokemonFormText.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.pokemonFormText.width, this.pokemonFormText.height), Phaser.Geom.Rectangle.Contains); - this.pokemonFormText.on("pointerover", () => (this.scene as BattleScene).ui.showTooltip("", pokemon.species.forms?.[pokemon.formIndex]?.formName, true)); + this.pokemonFormText.on("pointerover", () => (this.scene as BattleScene).ui.showTooltip("", formName, true)); this.pokemonFormText.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip()); } else { this.pokemonFormText.disableInteractive(); diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index fb9f1561447..e93fa0713c0 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -701,6 +701,7 @@ export default class SummaryUiHandler extends UiHandler { const profileContainer = this.scene.add.container(0, -pageBg.height); pageContainer.add(profileContainer); + // TODO: should add field for original trainer name to Pokemon object, to support gift/traded Pokemon from MEs const trainerText = addBBCodeTextObject(this.scene, 7, 12, `${i18next.t("pokemonSummary:ot")}/${getBBCodeFrag(loggedInUser?.username || i18next.t("pokemonSummary:unknown"), this.scene.gameData.gender === PlayerGender.FEMALE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE)}`, TextStyle.SUMMARY_ALT); trainerText.setOrigin(0, 0); profileContainer.add(trainerText); diff --git a/vitest.config.ts b/vitest.config.ts index 54462675704..9f9245687a1 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -4,6 +4,7 @@ import { defaultConfig } from "./vite.config"; export default defineProject(({ mode }) => ({ ...defaultConfig, test: { + testTimeout: 20000, setupFiles: ["./src/test/fontFace.setup.ts", "./src/test/vitest.setup.ts"], server: { deps: {