From 1cd0f41207b6ae773ea940e2a3e736c3d5354f3a Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Tue, 19 Aug 2025 15:20:41 -0400 Subject: [PATCH] Fixes stuff --- src/data/moves/move.ts | 18 ++++++++---------- test/moves/synchronoise.test.ts | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 681b8dc7a1d..4080d66f3be 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -5375,9 +5375,9 @@ export abstract class VariableMoveTypeChartAttr extends MoveAttr { * @param target - The {@linkcode Pokemon} targeted by the move * @param move - The {@linkcode Move} with this attribute * @param args - - * `[0]`: A {@linkcode NumberHolder} holding the current type effectiveness - * `[1]`: The target's entire defensive type profile - * `[2]`: The current {@linkcode PokemonType} of the move + * - `[0]`: A {@linkcode NumberHolder} holding the current type effectiveness + * - `[1]`: The target's entire defensive type profile + * - `[2]`: The current {@linkcode PokemonType} of the move * @returns `true` if application of the attribute succeeds */ public abstract override apply(user: Pokemon, target: Pokemon, move: Move, args: [multiplier: NumberHolder, types: PokemonType[], moveType: PokemonType]): boolean; @@ -5422,16 +5422,14 @@ export class NeutralDamageAgainstFlyingTypeAttr extends VariableMoveTypeChartAtt export class HitsSameTypeAttr extends VariableMoveTypeChartAttr { public override apply(user: Pokemon, _target: Pokemon, _move: Move, args: [multiplier: NumberHolder, types: PokemonType[], moveType: PokemonType]): boolean { const [multiplier, types] = args; - if (user.getTypes(true).some(type => types.includes(type))) { + const userTypes = user.getTypes(true); + // Synchronoise is never effective if the user is typeless + if (!userTypes.includes(PokemonType.UNKNOWN) && userTypes.some(type => types.includes(type))) { return false; } multiplier.value = 0; return true; } - - getCondition(): MoveConditionFunc { - return unknownTypeCondition; - } } @@ -5441,6 +5439,8 @@ export class HitsSameTypeAttr extends VariableMoveTypeChartAttr { export class FlyingTypeMultiplierAttr extends VariableMoveTypeChartAttr { apply(user: Pokemon, target: Pokemon, _move: Move, args: [multiplier: NumberHolder, types: PokemonType[], moveType: PokemonType]): boolean { const multiplier = args[0]; + // Intentionally exclude `move` to not re-trigger the effects of various moves + // TODO: Do we need to pass `useIllusion` here? multiplier.value *= target.getAttackTypeEffectiveness(PokemonType.FLYING, {source: user}); return true; } @@ -8259,8 +8259,6 @@ export class ExposedMoveAttr extends AddBattlerTagAttr { } -const unknownTypeCondition: MoveConditionFunc = (user, target, move) => !user.getTypes().includes(PokemonType.UNKNOWN); - export type MoveTargetSet = { targets: BattlerIndex[]; multiple: boolean; diff --git a/test/moves/synchronoise.test.ts b/test/moves/synchronoise.test.ts index 547bb077952..45055483f4b 100644 --- a/test/moves/synchronoise.test.ts +++ b/test/moves/synchronoise.test.ts @@ -82,11 +82,25 @@ describe("Moves - Synchronoise", () => { }); it("should count as ineffective if no enemies share types with the user", async () => { + await game.classicMode.startBattle([SpeciesId.MAGNETON]); + + const magneton = game.field.getPlayerPokemon(); + const karp = game.field.getEnemyPokemon(); + + game.move.use(MoveId.SYNCHRONOISE); + await game.toEndOfTurn(); + + expect(magneton).toHaveUsedMove({ move: MoveId.SYNCHRONOISE, result: MoveResult.MISS }); + expect(karp).toHaveFullHp(); + }); + + it("should never affect any Pokemon if the user is typeless", async () => { await game.classicMode.startBattle([SpeciesId.BIBAREL]); const bibarel = game.field.getPlayerPokemon(); const karp = game.field.getEnemyPokemon(); bibarel.summonData.types = [PokemonType.UNKNOWN]; + karp.summonData.types = [PokemonType.UNKNOWN]; game.move.use(MoveId.SYNCHRONOISE); await game.toEndOfTurn();