diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 6e53ef00f45..66bcc7b9c3c 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -39,13 +39,15 @@ export class BattlerTag { public turnCount: number; public sourceMove: Moves; public sourceId?: number; + public isBatonPassable: boolean; - constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType | BattlerTagLapseType[], turnCount: number, sourceMove?: Moves, sourceId?: number) { + constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType | BattlerTagLapseType[], turnCount: number, sourceMove?: Moves, sourceId?: number, isBatonPassable: boolean = false) { this.tagType = tagType; this.lapseTypes = Array.isArray(lapseType) ? lapseType : [ lapseType ]; this.turnCount = turnCount; this.sourceMove = sourceMove!; // TODO: is this bang correct? this.sourceId = sourceId; + this.isBatonPassable = isBatonPassable; } canAdd(pokemon: Pokemon): boolean { @@ -206,7 +208,7 @@ export class ShellTrapTag extends BattlerTag { export class TrappedTag extends BattlerTag { constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, turnCount: number, sourceMove: Moves, sourceId: number) { - super(tagType, lapseType, turnCount, sourceMove, sourceId); + super(tagType, lapseType, turnCount, sourceMove, sourceId, true); } canAdd(pokemon: Pokemon): boolean { @@ -326,7 +328,7 @@ export class InterruptedTag extends BattlerTag { */ export class ConfusedTag extends BattlerTag { constructor(turnCount: number, sourceMove: Moves) { - super(BattlerTagType.CONFUSED, BattlerTagLapseType.MOVE, turnCount, sourceMove); + super(BattlerTagType.CONFUSED, BattlerTagLapseType.MOVE, turnCount, sourceMove, undefined, true); } canAdd(pokemon: Pokemon): boolean { @@ -386,7 +388,7 @@ export class ConfusedTag extends BattlerTag { */ export class DestinyBondTag extends BattlerTag { constructor(sourceMove: Moves, sourceId: number) { - super(BattlerTagType.DESTINY_BOND, BattlerTagLapseType.PRE_MOVE, 1, sourceMove, sourceId); + super(BattlerTagType.DESTINY_BOND, BattlerTagLapseType.PRE_MOVE, 1, sourceMove, sourceId, true); } /** @@ -505,7 +507,7 @@ export class SeedTag extends BattlerTag { private sourceIndex: number; constructor(sourceId: number) { - super(BattlerTagType.SEEDED, BattlerTagLapseType.TURN_END, 1, Moves.LEECH_SEED, sourceId); + super(BattlerTagType.SEEDED, BattlerTagLapseType.TURN_END, 1, Moves.LEECH_SEED, sourceId, true); } /** @@ -776,7 +778,7 @@ export class OctolockTag extends TrappedTag { export class AquaRingTag extends BattlerTag { constructor() { - super(BattlerTagType.AQUA_RING, BattlerTagLapseType.TURN_END, 1, Moves.AQUA_RING, undefined); + super(BattlerTagType.AQUA_RING, BattlerTagLapseType.TURN_END, 1, Moves.AQUA_RING, undefined, true); } onAdd(pokemon: Pokemon): void { @@ -808,7 +810,7 @@ export class AquaRingTag extends BattlerTag { /** Tag used to allow moves that interact with {@link Moves.MINIMIZE} to function */ export class MinimizeTag extends BattlerTag { constructor() { - super(BattlerTagType.MINIMIZED, BattlerTagLapseType.TURN_END, 1, Moves.MINIMIZE, undefined); + super(BattlerTagType.MINIMIZED, BattlerTagLapseType.TURN_END, 1, Moves.MINIMIZE); } canAdd(pokemon: Pokemon): boolean { @@ -1206,7 +1208,7 @@ export class SturdyTag extends BattlerTag { export class PerishSongTag extends BattlerTag { constructor(turnCount: number) { - super(BattlerTagType.PERISH_SONG, BattlerTagLapseType.TURN_END, turnCount, Moves.PERISH_SONG); + super(BattlerTagType.PERISH_SONG, BattlerTagLapseType.TURN_END, turnCount, Moves.PERISH_SONG, undefined, true); } canAdd(pokemon: Pokemon): boolean { @@ -1262,7 +1264,7 @@ export class AbilityBattlerTag extends BattlerTag { public ability: Abilities; constructor(tagType: BattlerTagType, ability: Abilities, lapseType: BattlerTagLapseType, turnCount: number) { - super(tagType, lapseType, turnCount, undefined); + super(tagType, lapseType, turnCount); this.ability = ability; } @@ -1438,7 +1440,7 @@ export class TypeImmuneTag extends BattlerTag { public immuneType: Type; constructor(tagType: BattlerTagType, sourceMove: Moves, immuneType: Type, length: number = 1) { - super(tagType, BattlerTagLapseType.TURN_END, length, sourceMove); + super(tagType, BattlerTagLapseType.TURN_END, length, sourceMove, undefined, true); this.immuneType = immuneType; } @@ -1502,7 +1504,7 @@ export class TypeBoostTag extends BattlerTag { export class CritBoostTag extends BattlerTag { constructor(tagType: BattlerTagType, sourceMove: Moves) { - super(tagType, BattlerTagLapseType.TURN_END, 1, sourceMove); + super(tagType, BattlerTagLapseType.TURN_END, 1, sourceMove, undefined, true); } onAdd(pokemon: Pokemon): void { @@ -1594,7 +1596,7 @@ export class CursedTag extends BattlerTag { private sourceIndex: number; constructor(sourceId: number) { - super(BattlerTagType.CURSED, BattlerTagLapseType.TURN_END, 1, Moves.CURSE, sourceId); + super(BattlerTagType.CURSED, BattlerTagLapseType.TURN_END, 1, Moves.CURSE, sourceId, true); } /** diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 405a26d4a16..e0a9a4a86ce 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2660,11 +2660,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } for (const tag of source.summonData.tags) { - - // bypass those can not be passed via Baton Pass - const excludeTagTypes = new Set([BattlerTagType.DROWSY, BattlerTagType.INFATUATED, BattlerTagType.FIRE_BOOST]); - - if (excludeTagTypes.has(tag.tagType)) { + if (!tag.isBatonPassable) { continue; } diff --git a/src/test/moves/baton_pass.test.ts b/src/test/moves/baton_pass.test.ts index 0643b73e481..1a4edafdd36 100644 --- a/src/test/moves/baton_pass.test.ts +++ b/src/test/moves/baton_pass.test.ts @@ -1,13 +1,13 @@ -import { Stat } from "#enums/stat"; -import { PostSummonPhase } from "#app/phases/post-summon-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { BattlerIndex } from "#app/battle"; import GameManager from "#app/test/utils/gameManager"; +import { Abilities } from "#enums/abilities"; +import { BattlerTagType } from "#enums/battler-tag-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; +import { Stat } from "#enums/stat"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import { SPLASH_ONLY } from "../utils/testUtils"; - describe("Moves - Baton Pass", () => { let phaserGame: Phaser.Game; @@ -27,20 +27,17 @@ describe("Moves - Baton Pass", () => { game = new GameManager(phaserGame); game.override .battleType("single") - .enemySpecies(Species.DUGTRIO) - .startingLevel(1) - .startingWave(97) + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) .moveset([Moves.BATON_PASS, Moves.NASTY_PLOT, Moves.SPLASH]) + .ability(Abilities.BALL_FETCH) .enemyMoveset(SPLASH_ONLY) .disableCrits(); }); it("transfers all stat stages when player uses it", async() => { // arrange - await game.startBattle([ - Species.RAICHU, - Species.SHUCKLE - ]); + await game.classicMode.startBattle([Species.RAICHU, Species.SHUCKLE]); // round 1 - buff game.move.select(Moves.NASTY_PLOT); @@ -53,7 +50,7 @@ describe("Moves - Baton Pass", () => { // round 2 - baton pass game.move.select(Moves.BATON_PASS); game.doSelectPartyPokemon(1); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); // assert playerPokemon = game.scene.getPlayerPokemon()!; @@ -66,10 +63,7 @@ describe("Moves - Baton Pass", () => { game.override .startingWave(5) .enemyMoveset(new Array(4).fill([Moves.NASTY_PLOT])); - await game.startBattle([ - Species.RAICHU, - Species.SHUCKLE - ]); + await game.classicMode.startBattle([Species.RAICHU, Species.SHUCKLE]); // round 1 - ai buffs game.move.select(Moves.SPLASH); @@ -79,7 +73,7 @@ describe("Moves - Baton Pass", () => { game.scene.getEnemyPokemon()!.hp = 100; game.override.enemyMoveset(new Array(4).fill(Moves.BATON_PASS)); game.move.select(Moves.SPLASH); - await game.phaseInterceptor.to(PostSummonPhase, false); + await game.phaseInterceptor.to("PostSummonPhase", false); // assert // check buffs are still there @@ -94,4 +88,20 @@ describe("Moves - Baton Pass", () => { "PostSummonPhase" ]); }, 20000); + + it("doesn't transfer effects that aren't transferrable", async() => { + game.override.enemyMoveset(Array(4).fill(Moves.SALT_CURE)); + await game.classicMode.startBattle([Species.PIKACHU, Species.FEEBAS]); + + const [player1, player2] = game.scene.getParty(); + + game.move.select(Moves.BATON_PASS); + await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.phaseInterceptor.to("MoveEndPhase"); + expect(player1.findTag((t) => t.tagType === BattlerTagType.SALT_CURED)).toBeTruthy(); + game.doSelectPartyPokemon(1); + await game.toNextTurn(); + + expect(player2.findTag((t) => t.tagType === BattlerTagType.SALT_CURED)).toBeUndefined(); + }, 20000); });