From 102c0ffc3708eed26246cce5a4fbd694cfb4772a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Marques?= Date: Tue, 11 Mar 2025 13:32:25 +0000 Subject: [PATCH] [BUG] fixes #5472 - transform on reload --- src/field/pokemon.ts | 2 +- src/phases/summon-phase.ts | 4 ++++ src/system/pokemon-data.ts | 6 +++++ test/abilities/imposter.test.ts | 33 ++++++++++++++++++++++++++++ test/moves/transform.test.ts | 39 ++++++++++++++++++++++++++++++++- 5 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 890c6bab0d6..42fe1dc1010 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -5575,7 +5575,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } this.resetBattleSummonData(); if (this.summonDataPrimer) { - for (const k of Object.keys(this.summonData)) { + for (const k of Object.keys(this.summonDataPrimer)) { if (this.summonDataPrimer[k]) { this.summonData[k] = this.summonDataPrimer[k]; } diff --git a/src/phases/summon-phase.ts b/src/phases/summon-phase.ts index 31cd2645e68..757030af273 100644 --- a/src/phases/summon-phase.ts +++ b/src/phases/summon-phase.ts @@ -195,6 +195,10 @@ export class SummonPhase extends PartyMemberPokemonPhase { pokemon.cry(pokemon.getHpRatio() > 0.25 ? undefined : { rate: 0.85 }); pokemon.getSprite().clearTint(); pokemon.resetSummonData(); + // necessary to stay transformed during wild waves + if (pokemon.summonData?.speciesForm) { + pokemon.loadAssets(); + } globalScene.time.delayedCall(1000, () => this.end()); }, }); diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index 4e694bc1189..b3119517102 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -170,6 +170,7 @@ export default class PokemonData { this.summonData.ability = source.summonData.ability; this.summonData.moveset = source.summonData.moveset?.map(m => PokemonMove.loadMove(m)); this.summonData.types = source.summonData.types; + this.summonData.speciesForm = source.summonData.speciesForm; if (source.summonData.tags) { this.summonData.tags = source.summonData.tags?.map(t => loadBattlerTag(t)); @@ -213,6 +214,11 @@ export default class PokemonData { this, ); if (this.summonData) { + // when loading from saved session, recover summonData.speciesFrom species object + // used to stay transformed on reload session + if (this.summonData.speciesForm) { + this.summonData.speciesForm = getPokemonSpecies(this.summonData.speciesForm.speciesId); + } ret.primeSummonData(this.summonData); } return ret; diff --git a/test/abilities/imposter.test.ts b/test/abilities/imposter.test.ts index b4469cd9042..46d342bd635 100644 --- a/test/abilities/imposter.test.ts +++ b/test/abilities/imposter.test.ts @@ -127,4 +127,37 @@ describe("Abilities - Imposter", () => { expect(game.scene.getEnemyPokemon()?.getStatStage(Stat.ATK)).toBe(-1); }); + + it("should persist transformed attributes across reloads", async () => { + game.override.moveset([Moves.ABSORB]); + + await game.classicMode.startBattle([Species.DITTO]); + + const player = game.scene.getPlayerPokemon()!; + const enemy = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.SPLASH); + await game.doKillOpponents(); + await game.toNextWave(); + + expect(game.scene.getCurrentPhase()?.constructor.name).toBe("CommandPhase"); + expect(game.scene.currentBattle.waveIndex).toBe(2); + + await game.reload.reloadSession(); + + const playerReloaded = game.scene.getPlayerPokemon()!; + const playerMoveset = player.getMoveset(); + + expect(playerReloaded.getSpeciesForm().speciesId).toBe(enemy.getSpeciesForm().speciesId); + expect(playerReloaded.getAbility()).toBe(enemy.getAbility()); + expect(playerReloaded.getGender()).toBe(enemy.getGender()); + + expect(playerReloaded.getStat(Stat.HP, false)).not.toBe(enemy.getStat(Stat.HP)); + for (const s of EFFECTIVE_STATS) { + expect(playerReloaded.getStat(s, false)).toBe(enemy.getStat(s, false)); + } + + expect(playerMoveset.length).toEqual(1); + expect(playerMoveset[0]?.moveId).toEqual(Moves.SPLASH); + }); }); diff --git a/test/moves/transform.test.ts b/test/moves/transform.test.ts index 5140202a383..a2162af7569 100644 --- a/test/moves/transform.test.ts +++ b/test/moves/transform.test.ts @@ -6,6 +6,7 @@ import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { Moves } from "#enums/moves"; import { Stat, BATTLE_STATS, EFFECTIVE_STATS } from "#enums/stat"; import { Abilities } from "#enums/abilities"; +import { BattlerIndex } from "#app/battle"; // TODO: Add more tests once Transform is fully implemented describe("Moves - Transform", () => { @@ -58,7 +59,7 @@ describe("Moves - Transform", () => { } const playerMoveset = player.getMoveset(); - const enemyMoveset = player.getMoveset(); + const enemyMoveset = enemy.getMoveset(); expect(playerMoveset.length).toBe(enemyMoveset.length); for (let i = 0; i < playerMoveset.length && i < enemyMoveset.length; i++) { @@ -127,4 +128,40 @@ describe("Moves - Transform", () => { expect(game.scene.getEnemyPokemon()?.getStatStage(Stat.ATK)).toBe(-1); }); + + it("should persist transformed attributes across reloads", async () => { + game.override.enemyMoveset([]).moveset([]); + + await game.classicMode.startBattle([Species.DITTO]); + + const player = game.scene.getPlayerPokemon()!; + const enemy = game.scene.getEnemyPokemon()!; + + game.move.changeMoveset(player, Moves.TRANSFORM); + game.move.changeMoveset(enemy, Moves.MEMENTO); + + game.move.select(Moves.TRANSFORM); + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.toNextWave(); + + expect(game.scene.getCurrentPhase()?.constructor.name).toBe("CommandPhase"); + expect(game.scene.currentBattle.waveIndex).toBe(2); + + await game.reload.reloadSession(); + + const playerReloaded = game.scene.getPlayerPokemon()!; + const playerMoveset = player.getMoveset(); + + expect(playerReloaded.getSpeciesForm().speciesId).toBe(enemy.getSpeciesForm().speciesId); + expect(playerReloaded.getAbility()).toBe(enemy.getAbility()); + expect(playerReloaded.getGender()).toBe(enemy.getGender()); + + expect(playerReloaded.getStat(Stat.HP, false)).not.toBe(enemy.getStat(Stat.HP)); + for (const s of EFFECTIVE_STATS) { + expect(playerReloaded.getStat(s, false)).toBe(enemy.getStat(s, false)); + } + + expect(playerMoveset.length).toEqual(1); + expect(playerMoveset[0]?.moveId).toEqual(Moves.MEMENTO); + }); });