diff --git a/public/images/arenas/beach_b_2.png b/public/images/arenas/beach_b_2.png index 50c9be97b0d..6c3e89c1b25 100644 Binary files a/public/images/arenas/beach_b_2.png and b/public/images/arenas/beach_b_2.png differ diff --git a/public/images/arenas/cave_b_2.png b/public/images/arenas/cave_b_2.png index f76560e1f03..99c850ecdf6 100644 Binary files a/public/images/arenas/cave_b_2.png and b/public/images/arenas/cave_b_2.png differ diff --git a/public/images/arenas/factory_b_3.png b/public/images/arenas/factory_b_3.png index f2bb93128cf..e7716f0e168 100644 Binary files a/public/images/arenas/factory_b_3.png and b/public/images/arenas/factory_b_3.png differ diff --git a/public/images/arenas/forest_b.png b/public/images/arenas/forest_b.png index dcd1981a5e9..9f2cfc20c09 100644 Binary files a/public/images/arenas/forest_b.png and b/public/images/arenas/forest_b.png differ diff --git a/public/images/arenas/ice_cave_b_2.png b/public/images/arenas/ice_cave_b_2.png index d7e6fb1784e..636f4e95946 100644 Binary files a/public/images/arenas/ice_cave_b_2.png and b/public/images/arenas/ice_cave_b_2.png differ diff --git a/public/images/arenas/island_bg.png b/public/images/arenas/island_bg.png index e05c3afa775..8a8d703af5d 100644 Binary files a/public/images/arenas/island_bg.png and b/public/images/arenas/island_bg.png differ diff --git a/public/images/arenas/jungle_bg.png b/public/images/arenas/jungle_bg.png index e03de2a3223..4a8fa41fbb3 100644 Binary files a/public/images/arenas/jungle_bg.png and b/public/images/arenas/jungle_bg.png differ diff --git a/public/images/arenas/laboratory_b_2.png b/public/images/arenas/laboratory_b_2.png index fcd945b8b86..b5d73b8a9ed 100644 Binary files a/public/images/arenas/laboratory_b_2.png and b/public/images/arenas/laboratory_b_2.png differ diff --git a/public/images/arenas/laboratory_bg.png b/public/images/arenas/laboratory_bg.png index 0e64877c0b6..decb26240b3 100644 Binary files a/public/images/arenas/laboratory_bg.png and b/public/images/arenas/laboratory_bg.png differ diff --git a/public/images/arenas/lake_b_1.png b/public/images/arenas/lake_b_1.png index 5426dd1e8d9..8786fb6c728 100644 Binary files a/public/images/arenas/lake_b_1.png and b/public/images/arenas/lake_b_1.png differ diff --git a/public/images/arenas/lake_b_2.png b/public/images/arenas/lake_b_2.png index b08ccd7b8e4..454c9e89d29 100644 Binary files a/public/images/arenas/lake_b_2.png and b/public/images/arenas/lake_b_2.png differ diff --git a/public/images/arenas/metropolis_bg.png b/public/images/arenas/metropolis_bg.png index 374744f245e..b790221b323 100644 Binary files a/public/images/arenas/metropolis_bg.png and b/public/images/arenas/metropolis_bg.png differ diff --git a/public/images/arenas/plains_b_2.png b/public/images/arenas/plains_b_2.png index a35dbec9917..4d8d679d12f 100644 Binary files a/public/images/arenas/plains_b_2.png and b/public/images/arenas/plains_b_2.png differ diff --git a/public/images/arenas/plains_bg.png b/public/images/arenas/plains_bg.png index f2cbec9197c..9c0cff9b7dc 100644 Binary files a/public/images/arenas/plains_bg.png and b/public/images/arenas/plains_bg.png differ diff --git a/public/images/arenas/snowy_forest_b_3.png b/public/images/arenas/snowy_forest_b_3.png index 14c8f4c64aa..d8c89496d14 100644 Binary files a/public/images/arenas/snowy_forest_b_3.png and b/public/images/arenas/snowy_forest_b_3.png differ diff --git a/public/images/arenas/snowy_forest_bg.png b/public/images/arenas/snowy_forest_bg.png index b0dcc3ddfc5..62ff03f5b1c 100644 Binary files a/public/images/arenas/snowy_forest_bg.png and b/public/images/arenas/snowy_forest_bg.png differ diff --git a/public/images/arenas/wasteland_b_1.png b/public/images/arenas/wasteland_b_1.png index d10a7f27699..7f62b29f9a8 100644 Binary files a/public/images/arenas/wasteland_b_1.png and b/public/images/arenas/wasteland_b_1.png differ diff --git a/public/images/arenas/wasteland_b_3.png b/public/images/arenas/wasteland_b_3.png index cdc5a2bdd50..73a5b283861 100644 Binary files a/public/images/arenas/wasteland_b_3.png and b/public/images/arenas/wasteland_b_3.png differ diff --git a/public/images/battle_anims/PRAS- Pulverizing Pancake BG2.png b/public/images/battle_anims/PRAS- Pulverizing Pancake BG2.png index 44b50a6d385..4c55dd5f1c8 100644 Binary files a/public/images/battle_anims/PRAS- Pulverizing Pancake BG2.png and b/public/images/battle_anims/PRAS- Pulverizing Pancake BG2.png differ diff --git a/public/images/battle_anims/PRAS- Pulverizing Pancake.png b/public/images/battle_anims/PRAS- Pulverizing Pancake.png index 519a52c63c6..b284493c6da 100644 Binary files a/public/images/battle_anims/PRAS- Pulverizing Pancake.png and b/public/images/battle_anims/PRAS- Pulverizing Pancake.png differ diff --git a/public/images/battle_anims/PRAS- Spectral thief BG.png b/public/images/battle_anims/PRAS- Spectral thief BG.png index 35fc434fdca..92c356c5ec5 100644 Binary files a/public/images/battle_anims/PRAS- Spectral thief BG.png and b/public/images/battle_anims/PRAS- Spectral thief BG.png differ diff --git a/public/images/egg/egg_crack.png b/public/images/egg/egg_crack.png index 9d553ebf378..f5b5ee7b7e1 100644 Binary files a/public/images/egg/egg_crack.png and b/public/images/egg/egg_crack.png differ diff --git a/public/images/items.png b/public/images/items.png index a4ca454a153..ecc8d42daea 100644 Binary files a/public/images/items.png and b/public/images/items.png differ diff --git a/public/images/items/common_egg.png b/public/images/items/common_egg.png index 5eccff2f690..c449611d532 100644 Binary files a/public/images/items/common_egg.png and b/public/images/items/common_egg.png differ diff --git a/public/images/items/great_ribbon.png b/public/images/items/great_ribbon.png index 4db20f29c1f..284ee6a3b3b 100644 Binary files a/public/images/items/great_ribbon.png and b/public/images/items/great_ribbon.png differ diff --git a/public/images/mystery-encounters/fun_and_games_wobbuffet.png b/public/images/mystery-encounters/fun_and_games_wobbuffet.png index 71997be5692..5d61512ea78 100644 Binary files a/public/images/mystery-encounters/fun_and_games_wobbuffet.png and b/public/images/mystery-encounters/fun_and_games_wobbuffet.png differ diff --git a/public/images/mystery-encounters/mysterious_chest_blue.png b/public/images/mystery-encounters/mysterious_chest_blue.png index f959db13aa7..6fa3a7c5475 100644 Binary files a/public/images/mystery-encounters/mysterious_chest_blue.png and b/public/images/mystery-encounters/mysterious_chest_blue.png differ diff --git a/public/images/ui/champion_ribbon_bronze.png b/public/images/ui/champion_ribbon_bronze.png index b69efbb8f88..4bd1cb8ea2d 100644 Binary files a/public/images/ui/champion_ribbon_bronze.png and b/public/images/ui/champion_ribbon_bronze.png differ diff --git a/public/images/ui/champion_ribbon_diamond.png b/public/images/ui/champion_ribbon_diamond.png index fd0e1f77480..207ade56c19 100644 Binary files a/public/images/ui/champion_ribbon_diamond.png and b/public/images/ui/champion_ribbon_diamond.png differ diff --git a/public/images/ui/champion_ribbon_silver.png b/public/images/ui/champion_ribbon_silver.png index 92b6f4cf8c7..52cde028406 100644 Binary files a/public/images/ui/champion_ribbon_silver.png and b/public/images/ui/champion_ribbon_silver.png differ diff --git a/public/images/ui/legacy/champion_ribbon_bronze.png b/public/images/ui/legacy/champion_ribbon_bronze.png index b69efbb8f88..4bd1cb8ea2d 100644 Binary files a/public/images/ui/legacy/champion_ribbon_bronze.png and b/public/images/ui/legacy/champion_ribbon_bronze.png differ diff --git a/public/images/ui/legacy/champion_ribbon_diamond.png b/public/images/ui/legacy/champion_ribbon_diamond.png index fd0e1f77480..207ade56c19 100644 Binary files a/public/images/ui/legacy/champion_ribbon_diamond.png and b/public/images/ui/legacy/champion_ribbon_diamond.png differ diff --git a/public/images/ui/legacy/champion_ribbon_silver.png b/public/images/ui/legacy/champion_ribbon_silver.png index 92b6f4cf8c7..52cde028406 100644 Binary files a/public/images/ui/legacy/champion_ribbon_silver.png and b/public/images/ui/legacy/champion_ribbon_silver.png differ diff --git a/public/locales b/public/locales index e0657485ae7..2686cd3edc0 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit e0657485ae75ff0361a6e3f0fb4c7ed649a1fb39 +Subproject commit 2686cd3edc0bd2c7a7f12cc54c00c109e51a48d7 diff --git a/src/phases/command-phase.ts b/src/phases/command-phase.ts index 6ca0679af4d..37e07c6c282 100644 --- a/src/phases/command-phase.ts +++ b/src/phases/command-phase.ts @@ -456,7 +456,7 @@ export class CommandPhase extends FieldPhase { const numBallTypes = 5; if (cursor < numBallTypes) { - const targetPokemon = globalScene.getEnemyPokemon(); + const targetPokemon = globalScene.getEnemyPokemon(false); if ( targetPokemon?.isBoss() && targetPokemon?.bossSegmentIndex >= 1 && diff --git a/src/phases/evolution-phase.ts b/src/phases/evolution-phase.ts index ad3db97d520..542a2100452 100644 --- a/src/phases/evolution-phase.ts +++ b/src/phases/evolution-phase.ts @@ -31,6 +31,7 @@ export class EvolutionPhase extends Phase { private evolutionBgm: AnySound; private evolutionHandler: EvolutionSceneHandler; + /** Container for all assets used by the scene. When the scene is cleared, the children within this are destroyed. */ protected evolutionContainer: Phaser.GameObjects.Container; protected evolutionBaseBg: Phaser.GameObjects.Image; protected evolutionBg: Phaser.GameObjects.Video; @@ -522,6 +523,7 @@ export class EvolutionPhase extends Phase { return; } if (i === lastCycle) { + this.pokemonTintSprite.setVisible(false).setActive(false); this.pokemonEvoTintSprite.setScale(1); } }, diff --git a/src/ui/battle-info/enemy-battle-info.ts b/src/ui/battle-info/enemy-battle-info.ts index e1063be95af..7a2af017219 100644 --- a/src/ui/battle-info/enemy-battle-info.ts +++ b/src/ui/battle-info/enemy-battle-info.ts @@ -115,6 +115,9 @@ export class EnemyBattleInfo extends BattleInfo { globalScene.gameData.starterData[pokemon.species.getRootSpeciesId()].classicWinCount > 0 && globalScene.gameData.starterData[pokemon.species.getRootSpeciesId(true)].classicWinCount > 0 ) { + // move the ribbon to the left if there is no owned icon + const championRibbonX = this.ownedIcon.visible ? 8 : 0; + this.championRibbon.setPositionRelative(this.nameText, championRibbonX, 11.75); this.championRibbon.setVisible(true); } diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 73fc1bfc010..a7c7a134488 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -613,6 +613,20 @@ export class PartyUiHandler extends MessageUiHandler { ui.playSelect(); return true; } + + if (option === PartyOption.SUMMARY) { + return this.processSummaryOption(pokemon); + } + if (option === PartyOption.POKEDEX) { + return this.processPokedexOption(pokemon); + } + if (option === PartyOption.UNPAUSE_EVOLUTION) { + return this.processUnpauseEvolutionOption(pokemon); + } + if (option === PartyOption.RENAME) { + return this.processRenameOption(pokemon); + } + return false; } diff --git a/src/ui/text.ts b/src/ui/text.ts index 8aa50983874..bac53f81ba6 100644 --- a/src/ui/text.ts +++ b/src/ui/text.ts @@ -349,6 +349,15 @@ export function getTextStyleOptions( styleOptions.fontSize = defaultFontSize - 42; styleOptions.padding = { top: 4 }; break; + case "ko": + styleOptions.fontSize = defaultFontSize - 38; + styleOptions.padding = { top: 4, left: 6 }; + break; + case "zh-CN": + case "zh-TW": + styleOptions.fontSize = defaultFontSize - 42; + styleOptions.padding = { top: 5, left: 14 }; + break; default: styleOptions.fontSize = defaultFontSize - 30; styleOptions.padding = { left: 12 }; diff --git a/test/ui/transfer-item-options.test.ts b/test/ui/transfer-item-options.test.ts new file mode 100644 index 00000000000..901aa261f50 --- /dev/null +++ b/test/ui/transfer-item-options.test.ts @@ -0,0 +1,235 @@ +import { BerryType } from "#enums/berry-type"; +import { Button } from "#enums/buttons"; +import { MoveId } from "#enums/move-id"; +import { SpeciesId } from "#enums/species-id"; +import { UiMode } from "#enums/ui-mode"; +import { GameManager } from "#test/test-utils/game-manager"; +import { type PartyUiHandler, PartyUiMode } from "#ui/party-ui-handler"; +import type { RenameFormUiHandler } from "#ui/rename-form-ui-handler"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +// todo: Some tests fail when running all tests at once, but pass when running individually. Seams like it's always the 2nd and 4th (non todo) tests that fail. +describe("UI - Transfer Item Options", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(async () => { + game = new GameManager(phaserGame); + game.override + .battleStyle("single") + .startingLevel(100) + .startingHeldItems([ + { name: "BERRY", count: 1, type: BerryType.SITRUS }, + { name: "BERRY", count: 2, type: BerryType.APICOT }, + { name: "BERRY", count: 2, type: BerryType.LUM }, + ]) + .enemySpecies(SpeciesId.MAGIKARP) + .enemyMoveset(MoveId.SPLASH); + + await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.SQUIRTLE, SpeciesId.CHARMANDER]); + + game.move.use(MoveId.DRAGON_CLAW); + + await game.phaseInterceptor.to("SelectModifierPhase"); + await game.scene.ui.setModeWithoutClear(UiMode.PARTY, PartyUiMode.MODIFIER_TRANSFER); + }); + + it.todo("should open the summary screen while transfering an item", async () => { + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // Select first party member + handler.setCursor(0); + handler.processInput(Button.ACTION); + + resolve(); + }); + }); + + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + // select item to transfer + handler.processInput(Button.ACTION); + resolve(); + }); + }); + + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // move to second pokemon + handler.setCursor(1); + handler.processInput(Button.ACTION); + + // select summary + handler.processInput(Button.DOWN); + handler.processInput(Button.ACTION); + + await new Promise(r => setTimeout(r, 100)); + expect(game.scene.ui.getMode()).toBe(UiMode.SUMMARY); + }); + + it.todo("should open the pokèdex screen while transfering an item", async () => { + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // Select first party member + handler.setCursor(0); + handler.processInput(Button.ACTION); + + resolve(); + }); + }); + + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + // select item to transfer + handler.processInput(Button.ACTION); + resolve(); + }); + }); + + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + // move to second pokemon + handler.setCursor(1); + handler.processInput(Button.ACTION); + + // select pokèdex + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.ACTION); + + await new Promise(r => setTimeout(r, 100)); + expect(game.scene.ui.getMode()).toBe(UiMode.POKEDEX_PAGE); + }); + + it.todo("should open the rename screen and rename the pokemon while transfering an item", async () => { + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // Select first party member + handler.setCursor(0); + handler.processInput(Button.ACTION); + + resolve(); + }); + }); + + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + // select item to transfer + handler.processInput(Button.ACTION); + resolve(); + }); + }); + + await new Promise(r => setTimeout(r, 100)); + let handler: PartyUiHandler | RenameFormUiHandler | undefined; + handler = game.scene.ui.getHandler() as PartyUiHandler; + + // move to second pokemon + handler.setCursor(1); + handler.processInput(Button.ACTION); + + // select rename + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.ACTION); + + const pokemon = game.scene.getPlayerParty()[1]; + if (!pokemon) { + expect.fail("Pokemon is undefined"); + } + const nickname = pokemon.nickname; + + expect(nickname).toBe(undefined); + + await new Promise(r => setTimeout(r, 100)); + expect(game.scene.ui.getMode()).toBe(UiMode.RENAME_POKEMON); + await new Promise(r => setTimeout(r, 100)); + handler = game.scene.ui.getHandler() as RenameFormUiHandler; + handler["inputs"][0].setText("New nickname"); + handler.processInput(Button.SUBMIT); + await new Promise(r => setTimeout(r, 100)); + // get the sanitized name + const sanitizedName = btoa(unescape(encodeURIComponent("New nickname"))); + expect(pokemon.nickname).toBe(sanitizedName); + }); + + it.todo("should pause the evolution while transfering an item", async () => { + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // Select first party member + handler.setCursor(0); + handler.processInput(Button.ACTION); + + resolve(); + }); + }); + + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + // select item to transfer + handler.processInput(Button.ACTION); + resolve(); + }); + }); + + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // move to second pokemon + handler.setCursor(1); + handler.processInput(Button.ACTION); + + const pokemon = game.scene.getPlayerParty()[1]; + + if (!pokemon) { + expect.fail("Pokemon is undefined"); + } + if (pokemon.pauseEvolutions !== undefined) { + expect(pokemon.pauseEvolutions).toBe(false); + } + + // select pause evolution + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.ACTION); + + await new Promise(r => setTimeout(r, 100)); + expect(game.scene.ui.getMode()).toBe(UiMode.PARTY); + expect(pokemon.pauseEvolutions).toBe(true); + }); +});