[Ability] Fully implement Pastel Veil, update Sweet Veil (after beta fix) (#3208)
* ful implement pastel veil, update sweet veil * improve docs * update docs * cleanup attrs
This commit is contained in:
parent
208f5af62a
commit
5b4a24824f
|
@ -1,4 +1,4 @@
|
|||
import Pokemon, { HitResult, PokemonMove } from "../field/pokemon";
|
||||
import Pokemon, { HitResult, PlayerPokemon, PokemonMove } from "../field/pokemon";
|
||||
import { Type } from "./type";
|
||||
import { Constructor } from "#app/utils";
|
||||
import * as Utils from "../utils";
|
||||
|
@ -2147,6 +2147,49 @@ export class PostSummonCopyAbilityAbAttr extends PostSummonAbAttr {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes supplied status effects from the user's field.
|
||||
*/
|
||||
export class PostSummonUserFieldRemoveStatusEffectAbAttr extends PostSummonAbAttr {
|
||||
private statusEffect: StatusEffect[];
|
||||
|
||||
/**
|
||||
* @param statusEffect - The status effects to be removed from the user's field.
|
||||
*/
|
||||
constructor(...statusEffect: StatusEffect[]) {
|
||||
super(false);
|
||||
|
||||
this.statusEffect = statusEffect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes supplied status effect from the user's field when user of the ability is summoned.
|
||||
*
|
||||
* @param pokemon - The Pokémon that triggered the ability.
|
||||
* @param passive - n/a
|
||||
* @param args - n/a
|
||||
* @returns A boolean or a promise that resolves to a boolean indicating the result of the ability application.
|
||||
*/
|
||||
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> {
|
||||
const party = pokemon instanceof PlayerPokemon ? pokemon.scene.getPlayerField() : pokemon.scene.getEnemyField();
|
||||
const allowedParty = party.filter(p => p.isAllowedInBattle());
|
||||
|
||||
if (allowedParty.length < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const pokemon of allowedParty) {
|
||||
if (this.statusEffect.includes(pokemon.status?.effect)) {
|
||||
pokemon.scene.queueMessage(getStatusEffectHealText(pokemon.status.effect, getPokemonNameWithAffix(pokemon)));
|
||||
pokemon.resetStatus(false);
|
||||
pokemon.updateInfo();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Attempt to copy the stat changes on an ally pokemon */
|
||||
export class PostSummonCopyAllyStatsAbAttr extends PostSummonAbAttr {
|
||||
|
@ -2398,17 +2441,33 @@ export class PreSetStatusAbAttr extends AbAttr {
|
|||
}
|
||||
}
|
||||
|
||||
export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
|
||||
/**
|
||||
* Provides immunity to status effects to specified targets.
|
||||
*/
|
||||
export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
|
||||
private immuneEffects: StatusEffect[];
|
||||
|
||||
/**
|
||||
* @param immuneEffects - The status effects to which the Pokémon is immune.
|
||||
*/
|
||||
constructor(...immuneEffects: StatusEffect[]) {
|
||||
super();
|
||||
|
||||
this.immuneEffects = immuneEffects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies immunity to supplied status effects.
|
||||
*
|
||||
* @param pokemon - The Pokémon to which the status is being applied.
|
||||
* @param passive - n/a
|
||||
* @param effect - The status effect being applied.
|
||||
* @param cancelled - A holder for a boolean value indicating if the status application was cancelled.
|
||||
* @param args - n/a
|
||||
* @returns A boolean indicating the result of the status application.
|
||||
*/
|
||||
applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) {
|
||||
if (this.immuneEffects.length < 1 || this.immuneEffects.includes(effect)) {
|
||||
cancelled.value = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -2430,13 +2489,28 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides immunity to status effects to the user.
|
||||
* @extends PreSetStatusEffectImmunityAbAttr
|
||||
*/
|
||||
export class StatusEffectImmunityAbAttr extends PreSetStatusEffectImmunityAbAttr { }
|
||||
|
||||
/**
|
||||
* Provides immunity to status effects to the user's field.
|
||||
* @extends PreSetStatusEffectImmunityAbAttr
|
||||
*/
|
||||
export class UserFieldStatusEffectImmunityAbAttr extends PreSetStatusEffectImmunityAbAttr { }
|
||||
|
||||
export class PreApplyBattlerTagAbAttr extends AbAttr {
|
||||
applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr {
|
||||
/**
|
||||
* Provides immunity to BattlerTags {@linkcode BattlerTag} to specified targets.
|
||||
*/
|
||||
export class PreApplyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr {
|
||||
private immuneTagType: BattlerTagType;
|
||||
|
||||
constructor(immuneTagType: BattlerTagType) {
|
||||
|
@ -2463,6 +2537,18 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides immunity to BattlerTags {@linkcode BattlerTag} to the user.
|
||||
* @extends PreApplyBattlerTagImmunityAbAttr
|
||||
*/
|
||||
export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagImmunityAbAttr { }
|
||||
|
||||
/**
|
||||
* Provides immunity to BattlerTags {@linkcode BattlerTag} to the user's field.
|
||||
* @extends PreApplyBattlerTagImmunityAbAttr
|
||||
*/
|
||||
export class UserFieldBattlerTagImmunityAbAttr extends PreApplyBattlerTagImmunityAbAttr { }
|
||||
|
||||
export class BlockCritAbAttr extends AbAttr {
|
||||
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
(args[0] as Utils.BooleanHolder).value = true;
|
||||
|
@ -4722,10 +4808,10 @@ export function initAbilities() {
|
|||
new Ability(Abilities.REFRIGERATE, 6)
|
||||
.attr(MoveTypeChangeAttr, Type.ICE, 1.2, (user, target, move) => move.type === Type.NORMAL),
|
||||
new Ability(Abilities.SWEET_VEIL, 6)
|
||||
.attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP)
|
||||
.attr(UserFieldStatusEffectImmunityAbAttr, StatusEffect.SLEEP)
|
||||
.attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY)
|
||||
.ignorable()
|
||||
.partial(),
|
||||
.partial(), // Mold Breaker ally should not be affected by Sweet Veil
|
||||
new Ability(Abilities.STANCE_CHANGE, 6)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
|
@ -5020,7 +5106,8 @@ export function initAbilities() {
|
|||
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonNeutralizingGas", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
||||
.partial(),
|
||||
new Ability(Abilities.PASTEL_VEIL, 8)
|
||||
.attr(StatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
||||
.attr(PostSummonUserFieldRemoveStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
||||
.attr(UserFieldStatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.HUNGER_SWITCH, 8)
|
||||
.attr(PostTurnFormChangeAbAttr, p => p.getFormKey ? 0 : 1)
|
||||
|
|
|
@ -23,7 +23,7 @@ import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoo
|
|||
import { WeatherType } from "../data/weather";
|
||||
import { TempBattleStat } from "../data/temp-battle-stat";
|
||||
import { ArenaTagSide, WeakenMoveScreenTag } from "../data/arena-tag";
|
||||
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldBattleStatMultiplierAbAttrs, FieldMultiplyBattleStatAbAttr, AddSecondStrikeAbAttr, IgnoreOpponentEvasionAbAttr } from "../data/ability";
|
||||
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldBattleStatMultiplierAbAttrs, FieldMultiplyBattleStatAbAttr, AddSecondStrikeAbAttr, IgnoreOpponentEvasionAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr } from "../data/ability";
|
||||
import PokemonData from "../system/pokemon-data";
|
||||
import { BattlerIndex } from "../battle";
|
||||
import { Mode } from "../ui/ui";
|
||||
|
@ -1779,6 +1779,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
return (this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField())[this.getFieldIndex() ? 0 : 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Pokémon on the allied field.
|
||||
*
|
||||
* @returns An array of Pokémon on the allied field.
|
||||
*/
|
||||
getAlliedField(): Pokemon[] {
|
||||
return this instanceof PlayerPokemon ? this.scene.getPlayerField() : this.scene.getEnemyField();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the accuracy multiplier of the user against a target.
|
||||
*
|
||||
|
@ -2236,6 +2245,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
const cancelled = new Utils.BooleanHolder(false);
|
||||
applyPreApplyBattlerTagAbAttrs(PreApplyBattlerTagAbAttr, this, newTag, cancelled);
|
||||
|
||||
const userField = this.getAlliedField();
|
||||
userField.forEach(pokemon => applyPreApplyBattlerTagAbAttrs(UserFieldBattlerTagImmunityAbAttr, pokemon, newTag, cancelled));
|
||||
|
||||
if (!cancelled.value && newTag.canAdd(this)) {
|
||||
this.summonData.tags.push(newTag);
|
||||
newTag.onAdd(this);
|
||||
|
@ -2644,6 +2656,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
const cancelled = new Utils.BooleanHolder(false);
|
||||
applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this, effect, cancelled, quiet);
|
||||
|
||||
const userField = this.getAlliedField();
|
||||
userField.forEach(pokemon => applyPreSetStatusAbAttrs(UserFieldStatusEffectImmunityAbAttr, pokemon, effect, cancelled, quiet));
|
||||
|
||||
if (cancelled.value) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import Phaser from "phaser";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import overrides from "#app/overrides";
|
||||
import { Species } from "#enums/species";
|
||||
import {
|
||||
CommandPhase,
|
||||
TurnEndPhase,
|
||||
} from "#app/phases";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { getMovePosition } from "#app/test/utils/gameManagerUtils";
|
||||
import { StatusEffect } from "#app/data/status-effect.js";
|
||||
import { allAbilities } from "#app/data/ability.js";
|
||||
import { Abilities } from "#app/enums/abilities.js";
|
||||
import { BattlerIndex } from "#app/battle.js";
|
||||
|
||||
describe("Abilities - Pastel Veil", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
vi.spyOn(overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double");
|
||||
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]);
|
||||
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH);
|
||||
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP);
|
||||
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TOXIC_THREAD, Moves.TOXIC_THREAD, Moves.TOXIC_THREAD, Moves.TOXIC_THREAD]);
|
||||
});
|
||||
|
||||
it("prevents the user and its allies from being afflicted by poison", async () => {
|
||||
await game.startBattle([Species.GALAR_PONYTA, Species.MAGIKARP]);
|
||||
const ponyta = game.scene.getPlayerField()[0];
|
||||
|
||||
vi.spyOn(ponyta, "getAbility").mockReturnValue(allAbilities[Abilities.PASTEL_VEIL]);
|
||||
|
||||
expect(ponyta.hasAbility(Abilities.PASTEL_VEIL)).toBe(true);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH));
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
expect(game.scene.getPlayerField().every(p => p.status?.effect)).toBe(false);
|
||||
});
|
||||
|
||||
it("it heals the poisoned status condition of allies if user is sent out into battle", async () => {
|
||||
await game.startBattle([Species.MAGIKARP, Species.MAGIKARP, Species.GALAR_PONYTA]);
|
||||
const ponyta = game.scene.getParty().find(p => p.species.speciesId === Species.GALAR_PONYTA);
|
||||
|
||||
vi.spyOn(ponyta, "getAbility").mockReturnValue(allAbilities[Abilities.PASTEL_VEIL]);
|
||||
|
||||
expect(ponyta.hasAbility(Abilities.PASTEL_VEIL)).toBe(true);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH));
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
expect(game.scene.getPlayerField().some(p => p.status?.effect === StatusEffect.POISON)).toBe(true);
|
||||
|
||||
const poisonedMon = game.scene.getPlayerField().find(p => p.status?.effect === StatusEffect.POISON);
|
||||
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.doAttack(getMovePosition(game.scene, (poisonedMon.getBattlerIndex() as BattlerIndex.PLAYER | BattlerIndex.PLAYER_2), Moves.SPLASH));
|
||||
game.doSwitchPokemon(2);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
expect(game.scene.getPlayerField().every(p => p.status?.effect)).toBe(false);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,108 @@
|
|||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import Phaser from "phaser";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import overrides from "#app/overrides";
|
||||
import { Species } from "#enums/species";
|
||||
import {
|
||||
CommandPhase,
|
||||
MoveEffectPhase,
|
||||
MovePhase,
|
||||
TurnEndPhase,
|
||||
} from "#app/phases";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { getMovePosition } from "#app/test/utils/gameManagerUtils";
|
||||
import { BattlerTagType } from "#app/enums/battler-tag-type.js";
|
||||
import { Abilities } from "#app/enums/abilities.js";
|
||||
import { BattlerIndex } from "#app/battle.js";
|
||||
|
||||
describe("Abilities - Sweet Veil", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
vi.spyOn(overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("double");
|
||||
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.REST]);
|
||||
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP);
|
||||
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BALL_FETCH);
|
||||
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.POWDER, Moves.POWDER, Moves.POWDER, Moves.POWDER]);
|
||||
});
|
||||
|
||||
it("prevents the user and its allies from falling asleep", async () => {
|
||||
await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH));
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
expect(game.scene.getPlayerField().every(p => p.status?.effect)).toBe(false);
|
||||
});
|
||||
|
||||
it("causes Rest to fail when used by the user or its allies", async () => {
|
||||
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]);
|
||||
await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
game.doAttack(getMovePosition(game.scene, 1, Moves.REST));
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
expect(game.scene.getPlayerField().every(p => p.status?.effect)).toBe(false);
|
||||
});
|
||||
|
||||
it("causes Yawn to fail if used on the user or its allies", async () => {
|
||||
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.YAWN, Moves.YAWN, Moves.YAWN, Moves.YAWN]);
|
||||
await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH));
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
expect(game.scene.getPlayerField().every(p => !!p.getTag(BattlerTagType.DROWSY))).toBe(false);
|
||||
});
|
||||
|
||||
it("prevents the user and its allies already drowsy due to Yawn from falling asleep.", async () => {
|
||||
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.PIKACHU);
|
||||
vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(5);
|
||||
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(5);
|
||||
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.YAWN, Moves.YAWN, Moves.YAWN, Moves.YAWN]);
|
||||
|
||||
await game.startBattle([Species.SHUCKLE, Species.SHUCKLE, Species.SWIRLIX]);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH));
|
||||
|
||||
// First pokemon move
|
||||
await game.phaseInterceptor.to(MoveEffectPhase, false);
|
||||
vi.spyOn(game.scene.getCurrentPhase() as MoveEffectPhase, "hitCheck").mockReturnValueOnce(true);
|
||||
|
||||
// Second pokemon move
|
||||
await game.phaseInterceptor.to(MovePhase, false);
|
||||
await game.phaseInterceptor.to(MoveEffectPhase, false);
|
||||
vi.spyOn(game.scene.getCurrentPhase() as MoveEffectPhase, "hitCheck").mockReturnValueOnce(true);
|
||||
|
||||
expect(game.scene.getPlayerField().some(p => !!p.getTag(BattlerTagType.DROWSY))).toBe(true);
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
const drowsyMon = game.scene.getPlayerField().find(p => !!p.getTag(BattlerTagType.DROWSY));
|
||||
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.doAttack(getMovePosition(game.scene, (drowsyMon.getBattlerIndex() as BattlerIndex.PLAYER | BattlerIndex.PLAYER_2), Moves.SPLASH));
|
||||
game.doSwitchPokemon(2);
|
||||
|
||||
expect(game.scene.getPlayerField().every(p => p.status?.effect)).toBe(false);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue