From 18c4dddcf06d51ce9119c1189aef1846ce6c06ee Mon Sep 17 00:00:00 2001 From: Stephen Kelman <64545785+stephenrzkelman@users.noreply.github.com> Date: Tue, 15 Apr 2025 07:19:19 -0700 Subject: [PATCH] [Bug] Fixing Tera Starstorm for first turn of terastallization (#5658) * Updating tera starstorm targeting condition so that it is a spread move on the turn that terastallization happens * added new unit tests to verify behavior of tera starstorm under non-tera conditions as well as on terastallization turns --- src/data/moves/move.ts | 2 +- test/moves/tera_starstorm.test.ts | 34 ++++++++++++++++++++++++++++ test/testUtils/helpers/moveHelper.ts | 27 ++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index b68dd0d3e1d..9546a6a40e5 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -11205,7 +11205,7 @@ export function initMoves() { new AttackMove(Moves.TERA_STARSTORM, PokemonType.NORMAL, MoveCategory.SPECIAL, 120, 100, 5, -1, 0, 9) .attr(TeraMoveCategoryAttr) .attr(TeraStarstormTypeAttr) - .attr(VariableTargetAttr, (user, target, move) => user.hasSpecies(Species.TERAPAGOS) && user.isTerastallized ? MoveTarget.ALL_NEAR_ENEMIES : MoveTarget.NEAR_OTHER) + .attr(VariableTargetAttr, (user, target, move) => user.hasSpecies(Species.TERAPAGOS) && (user.isTerastallized || globalScene.currentBattle.preTurnCommands[user.getFieldIndex()]?.command === Command.TERA) ? MoveTarget.ALL_NEAR_ENEMIES : MoveTarget.NEAR_OTHER) .partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */ new AttackMove(Moves.FICKLE_BEAM, PokemonType.DRAGON, MoveCategory.SPECIAL, 80, 100, 5, 30, 0, 9) .attr(PreMoveMessageAttr, doublePowerChanceMessageFunc) diff --git a/test/moves/tera_starstorm.test.ts b/test/moves/tera_starstorm.test.ts index 19fe58f4057..9f97b2a51aa 100644 --- a/test/moves/tera_starstorm.test.ts +++ b/test/moves/tera_starstorm.test.ts @@ -69,6 +69,40 @@ describe("Moves - Tera Starstorm", () => { expect(enemyField.every(pokemon => pokemon.isFullHp())).toBe(false); }); + it("targets both opponents in a double battle when used by Terapagos immediately after terastallizing", async () => { + await game.classicMode.startBattle([Species.TERAPAGOS]); + + const terapagos = game.scene.getPlayerParty()[0]; + terapagos.isTerastallized = false; + + game.move.selectWithTera(Moves.TERA_STARSTORM, 0); + + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + + const enemyField = game.scene.getEnemyField(); + + // Terapagos in Stellar Form should hit both targets + await game.phaseInterceptor.to("MoveEndPhase"); + expect(enemyField.some(pokemon => pokemon.isFullHp())).toBe(false); + }); + + it("targets only one opponent in a double battle when used by Terapagos without terastallizing", async () => { + await game.classicMode.startBattle([Species.TERAPAGOS]); + + const terapagos = game.scene.getPlayerParty()[0]; + terapagos.isTerastallized = false; + + game.move.select(Moves.TERA_STARSTORM, 0, BattlerIndex.ENEMY); + + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + + const enemyField = game.scene.getEnemyField(); + + // Terapagos in Stellar Form should hit both targets + await game.phaseInterceptor.to("MoveEndPhase"); + expect(enemyField.some(pokemon => pokemon.isFullHp())).toBe(true); + }); + it("applies the effects when Terapagos in Stellar Form is fused with another Pokemon", async () => { await game.classicMode.startBattle([Species.TERAPAGOS, Species.CHARMANDER, Species.MAGIKARP]); diff --git a/test/testUtils/helpers/moveHelper.ts b/test/testUtils/helpers/moveHelper.ts index 543f46b2026..a54028ebca0 100644 --- a/test/testUtils/helpers/moveHelper.ts +++ b/test/testUtils/helpers/moveHelper.ts @@ -65,6 +65,33 @@ export class MoveHelper extends GameManagerHelper { } } + /** + * Select the move to be used by the given Pokemon(-index), **which will also terastallize on this turn**. + * Triggers during the next {@linkcode CommandPhase} + * @param move - the move to use + * @param pkmIndex - the pokemon index. Relevant for double-battles only (defaults to 0) + * @param targetIndex - The {@linkcode BattlerIndex} of the Pokemon to target for single-target moves, or `null` if a manual call to `selectTarget()` is required + */ + public selectWithTera(move: Moves, pkmIndex: 0 | 1 = 0, targetIndex?: BattlerIndex | null) { + const movePosition = getMovePosition(this.game.scene, pkmIndex, move); + this.game.scene.getPlayerParty()[pkmIndex].isTerastallized = false; + + this.game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + this.game.scene.ui.setMode( + Mode.FIGHT, + (this.game.scene.getCurrentPhase() as CommandPhase).getFieldIndex(), + Command.TERA, + ); + }); + this.game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + (this.game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.TERA, movePosition, false); + }); + + if (targetIndex !== null) { + this.game.selectTarget(movePosition, targetIndex); + } + } + /** * Forces the Paralysis or Freeze status to activate on the next move by temporarily mocking {@linkcode Overrides.STATUS_ACTIVATION_OVERRIDE}, * advancing to the next `MovePhase`, and then resetting the override to `null`