Merge 75cc306e9b
into 51bb80cb66
This commit is contained in:
commit
2b8da26e95
|
@ -0,0 +1,111 @@
|
||||||
|
{
|
||||||
|
"graphic": "",
|
||||||
|
"frames": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"zoomX": 100,
|
||||||
|
"zoomY": 100,
|
||||||
|
"visible": true,
|
||||||
|
"target": 0,
|
||||||
|
"graphicFrame": 0,
|
||||||
|
"priority": 1,
|
||||||
|
"focus": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 128,
|
||||||
|
"y": -64,
|
||||||
|
"zoomX": 100,
|
||||||
|
"zoomY": 100,
|
||||||
|
"visible": true,
|
||||||
|
"target": 1,
|
||||||
|
"graphicFrame": 0,
|
||||||
|
"opacity": 255,
|
||||||
|
"locked": true,
|
||||||
|
"priority": 1,
|
||||||
|
"focus": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 3,
|
||||||
|
"zoomX": 100,
|
||||||
|
"zoomY": 50,
|
||||||
|
"visible": true,
|
||||||
|
"target": 0,
|
||||||
|
"graphicFrame": 0,
|
||||||
|
"priority": 1,
|
||||||
|
"focus": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 128,
|
||||||
|
"y": -64,
|
||||||
|
"zoomX": 100,
|
||||||
|
"zoomY": 50,
|
||||||
|
"visible": true,
|
||||||
|
"target": 1,
|
||||||
|
"graphicFrame": 0,
|
||||||
|
"opacity": 255,
|
||||||
|
"locked": true,
|
||||||
|
"priority": 1,
|
||||||
|
"focus": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"zoomX": 100,
|
||||||
|
"zoomY": 50,
|
||||||
|
"visible": true,
|
||||||
|
"target": 0,
|
||||||
|
"graphicFrame": 0,
|
||||||
|
"priority": 1,
|
||||||
|
"focus": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 128,
|
||||||
|
"y": -64,
|
||||||
|
"zoomX": 100,
|
||||||
|
"zoomY": 50,
|
||||||
|
"visible": true,
|
||||||
|
"target": 1,
|
||||||
|
"graphicFrame": 0,
|
||||||
|
"opacity": 255,
|
||||||
|
"locked": true,
|
||||||
|
"priority": 1,
|
||||||
|
"focus": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"zoomX": 100,
|
||||||
|
"zoomY": 50,
|
||||||
|
"visible": true,
|
||||||
|
"target": 0,
|
||||||
|
"graphicFrame": 0,
|
||||||
|
"priority": 1,
|
||||||
|
"focus": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 128,
|
||||||
|
"y": -64,
|
||||||
|
"zoomX": 100,
|
||||||
|
"zoomY": 50,
|
||||||
|
"visible": true,
|
||||||
|
"target": 1,
|
||||||
|
"graphicFrame": 0,
|
||||||
|
"opacity": 255,
|
||||||
|
"locked": true,
|
||||||
|
"priority": 1,
|
||||||
|
"focus": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"position": 2,
|
||||||
|
"hue": 0
|
||||||
|
}
|
|
@ -90,6 +90,7 @@ export enum CommonAnim {
|
||||||
RAGING_BULL_FIRE,
|
RAGING_BULL_FIRE,
|
||||||
RAGING_BULL_WATER,
|
RAGING_BULL_WATER,
|
||||||
SALT_CURE,
|
SALT_CURE,
|
||||||
|
POWDER,
|
||||||
SUNNY = 2100,
|
SUNNY = 2100,
|
||||||
RAIN,
|
RAIN,
|
||||||
SANDSTORM,
|
SANDSTORM,
|
||||||
|
|
|
@ -803,6 +803,55 @@ export class SeedTag extends BattlerTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BattlerTag representing the effects of {@link https://bulbapedia.bulbagarden.net/wiki/Powder_(move) | Powder}.
|
||||||
|
* When the afflicted Pokemon uses a Fire-type move, the move is cancelled, and the
|
||||||
|
* Pokemon takes damage equal to 1/4 of it's maximum HP (rounded down).
|
||||||
|
*/
|
||||||
|
export class PowderTag extends BattlerTag {
|
||||||
|
constructor() {
|
||||||
|
super(BattlerTagType.POWDER, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.TURN_END ], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
onAdd(pokemon: Pokemon): void {
|
||||||
|
super.onAdd(pokemon);
|
||||||
|
|
||||||
|
pokemon.scene.queueMessage(i18next.t("battlerTags:powderOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies Powder's effects before the tag owner uses a Fire-type move.
|
||||||
|
* Also causes the tag to expire at the end of turn.
|
||||||
|
* @param pokemon {@linkcode Pokemon} the owner of this tag
|
||||||
|
* @param lapseType {@linkcode BattlerTagLapseType} the type of lapse functionality to carry out
|
||||||
|
* @returns `true` if the tag should not expire after this lapse; `false` otherwise.
|
||||||
|
*/
|
||||||
|
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||||
|
if (lapseType === BattlerTagLapseType.PRE_MOVE) {
|
||||||
|
const movePhase = pokemon.scene.getCurrentPhase();
|
||||||
|
if (movePhase instanceof MovePhase) {
|
||||||
|
const move = movePhase.move.getMove();
|
||||||
|
if (pokemon.getMoveType(move) === Type.FIRE) {
|
||||||
|
movePhase.cancel();
|
||||||
|
|
||||||
|
new CommonBattleAnim(CommonAnim.POWDER, pokemon).play(pokemon.scene);
|
||||||
|
|
||||||
|
const cancelDamage = new Utils.BooleanHolder(false);
|
||||||
|
applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelDamage);
|
||||||
|
if (!cancelDamage.value) {
|
||||||
|
pokemon.damageAndUpdate(Math.floor(pokemon.getMaxHp() / 4), HitResult.OTHER);
|
||||||
|
}
|
||||||
|
|
||||||
|
pokemon.scene.queueMessage(i18next.t("battlerTags:powderLapse"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return super.lapse(pokemon, lapseType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class NightmareTag extends BattlerTag {
|
export class NightmareTag extends BattlerTag {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(BattlerTagType.NIGHTMARE, BattlerTagLapseType.AFTER_MOVE, 1, Moves.NIGHTMARE);
|
super(BattlerTagType.NIGHTMARE, BattlerTagLapseType.AFTER_MOVE, 1, Moves.NIGHTMARE);
|
||||||
|
@ -2354,6 +2403,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||||
return new InfatuatedTag(sourceMove, sourceId);
|
return new InfatuatedTag(sourceMove, sourceId);
|
||||||
case BattlerTagType.SEEDED:
|
case BattlerTagType.SEEDED:
|
||||||
return new SeedTag(sourceId);
|
return new SeedTag(sourceId);
|
||||||
|
case BattlerTagType.POWDER:
|
||||||
|
return new PowderTag();
|
||||||
case BattlerTagType.NIGHTMARE:
|
case BattlerTagType.NIGHTMARE:
|
||||||
return new NightmareTag();
|
return new NightmareTag();
|
||||||
case BattlerTagType.FRENZY:
|
case BattlerTagType.FRENZY:
|
||||||
|
|
|
@ -8456,9 +8456,10 @@ export function initMoves() {
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK, Stat.SPD ], -1, false, (user, target, move) => target.status?.effect === StatusEffect.POISON || target.status?.effect === StatusEffect.TOXIC)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK, Stat.SPD ], -1, false, (user, target, move) => target.status?.effect === StatusEffect.POISON || target.status?.effect === StatusEffect.TOXIC)
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||||
new StatusMove(Moves.POWDER, Type.BUG, 100, 20, -1, 1, 6)
|
new StatusMove(Moves.POWDER, Type.BUG, 100, 20, -1, 1, 6)
|
||||||
|
.attr(AddBattlerTagAttr, BattlerTagType.POWDER, false, true)
|
||||||
.ignoresSubstitute()
|
.ignoresSubstitute()
|
||||||
.powderMove()
|
.powderMove()
|
||||||
.unimplemented(),
|
.partial(), // does not cancel Fire-type moves generated by Dancer
|
||||||
new SelfStatusMove(Moves.GEOMANCY, Type.FAIRY, -1, 10, -1, 0, 6)
|
new SelfStatusMove(Moves.GEOMANCY, Type.FAIRY, -1, 10, -1, 0, 6)
|
||||||
.attr(ChargeAttr, ChargeAnim.GEOMANCY_CHARGING, i18next.t("moveTriggers:isChargingPower", {pokemonName: "{USER}"}))
|
.attr(ChargeAttr, ChargeAnim.GEOMANCY_CHARGING, i18next.t("moveTriggers:isChargingPower", {pokemonName: "{USER}"}))
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPATK, Stat.SPDEF, Stat.SPD ], 2, true)
|
.attr(StatStageChangeAttr, [ Stat.SPATK, Stat.SPDEF, Stat.SPD ], 2, true)
|
||||||
|
|
|
@ -80,4 +80,5 @@ export enum BattlerTagType {
|
||||||
BURNED_UP = "BURNED_UP",
|
BURNED_UP = "BURNED_UP",
|
||||||
DOUBLE_SHOCKED = "DOUBLE_SHOCKED",
|
DOUBLE_SHOCKED = "DOUBLE_SHOCKED",
|
||||||
MYSTERY_ENCOUNTER_POST_SUMMON = "MYSTERY_ENCOUNTER_POST_SUMMON",
|
MYSTERY_ENCOUNTER_POST_SUMMON = "MYSTERY_ENCOUNTER_POST_SUMMON",
|
||||||
|
POWDER = "POWDER",
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
"seededOnAdd": "{{pokemonNameWithAffix}} was seeded!",
|
"seededOnAdd": "{{pokemonNameWithAffix}} was seeded!",
|
||||||
"seededLapse": "{{pokemonNameWithAffix}}'s health is\nsapped by Leech Seed!",
|
"seededLapse": "{{pokemonNameWithAffix}}'s health is\nsapped by Leech Seed!",
|
||||||
"seededLapseShed": "{{pokemonNameWithAffix}}'s Leech Seed\nsucked up the liquid ooze!",
|
"seededLapseShed": "{{pokemonNameWithAffix}}'s Leech Seed\nsucked up the liquid ooze!",
|
||||||
|
"powderOnAdd": "{{pokemonNameWithAffix}} is covered in powder!",
|
||||||
|
"powderLapse": "When the flame touched the powder\non the Pokémon, it exploded!",
|
||||||
"nightmareOnAdd": "{{pokemonNameWithAffix}} began\nhaving a Nightmare!",
|
"nightmareOnAdd": "{{pokemonNameWithAffix}} began\nhaving a Nightmare!",
|
||||||
"nightmareOnOverlap": "{{pokemonNameWithAffix}} is\nalready locked in a Nightmare!",
|
"nightmareOnOverlap": "{{pokemonNameWithAffix}} is\nalready locked in a Nightmare!",
|
||||||
"nightmareLapse": "{{pokemonNameWithAffix}} is locked\nin a Nightmare!",
|
"nightmareLapse": "{{pokemonNameWithAffix}} is locked\nin a Nightmare!",
|
||||||
|
|
|
@ -0,0 +1,215 @@
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import GameManager from "#test/utils/gameManager";
|
||||||
|
import { Abilities } from "#app/enums/abilities";
|
||||||
|
import { Moves } from "#app/enums/moves";
|
||||||
|
import { Species } from "#app/enums/species";
|
||||||
|
import { BerryPhase } from "#app/phases/berry-phase";
|
||||||
|
import { MoveResult } from "#app/field/pokemon";
|
||||||
|
import { Type } from "#app/data/type";
|
||||||
|
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
||||||
|
import { StatusEffect } from "#app/enums/status-effect";
|
||||||
|
|
||||||
|
const TIMEOUT = 20 * 1000;
|
||||||
|
|
||||||
|
describe("Moves - Powder", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
game.override.battleType("single");
|
||||||
|
|
||||||
|
game.override
|
||||||
|
.enemySpecies(Species.SNORLAX)
|
||||||
|
.enemyLevel(100)
|
||||||
|
.enemyMoveset(Array(4).fill(Moves.EMBER))
|
||||||
|
.enemyAbility(Abilities.INSOMNIA)
|
||||||
|
.startingLevel(100)
|
||||||
|
.moveset([Moves.POWDER, Moves.SPLASH, Moves.FIERY_DANCE]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should cancel the target's Fire-type move and damage the target",
|
||||||
|
async () => {
|
||||||
|
await game.classicMode.startBattle([Species.CHARIZARD]);
|
||||||
|
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(Moves.POWDER);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.getLastXMoves()[0].result).toBe(MoveResult.FAIL);
|
||||||
|
expect(enemyPokemon.hp).toBe(Math.ceil(3 * enemyPokemon.getMaxHp() / 4));
|
||||||
|
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS);
|
||||||
|
expect(enemyPokemon.hp).toBe(Math.ceil(3 * enemyPokemon.getMaxHp() / 4));
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should have no effect against Grass-type Pokemon",
|
||||||
|
async () => {
|
||||||
|
game.override.enemySpecies(Species.AMOONGUSS);
|
||||||
|
|
||||||
|
await game.classicMode.startBattle([Species.CHARIZARD]);
|
||||||
|
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(Moves.POWDER);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS);
|
||||||
|
expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp());
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should have no effect against Pokemon with Overcoat",
|
||||||
|
async () => {
|
||||||
|
game.override.enemyAbility(Abilities.OVERCOAT);
|
||||||
|
|
||||||
|
await game.classicMode.startBattle([Species.CHARIZARD]);
|
||||||
|
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(Moves.POWDER);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS);
|
||||||
|
expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp());
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should not damage the target if the target has Magic Guard",
|
||||||
|
async () => {
|
||||||
|
game.override.enemyAbility(Abilities.MAGIC_GUARD);
|
||||||
|
|
||||||
|
await game.classicMode.startBattle([Species.CHARIZARD]);
|
||||||
|
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(Moves.POWDER);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.getLastXMoves()[0].result).toBe(MoveResult.FAIL);
|
||||||
|
expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp());
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should not prevent the target from thawing out with Flame Wheel",
|
||||||
|
async () => {
|
||||||
|
game.override
|
||||||
|
.enemyMoveset(Array(4).fill(Moves.FLAME_WHEEL))
|
||||||
|
.enemyStatusEffect(StatusEffect.FREEZE);
|
||||||
|
|
||||||
|
await game.classicMode.startBattle([Species.CHARIZARD]);
|
||||||
|
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(Moves.POWDER);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.status?.effect).not.toBe(StatusEffect.FREEZE);
|
||||||
|
expect(enemyPokemon.getLastXMoves()[0].result).toBe(MoveResult.FAIL);
|
||||||
|
expect(enemyPokemon.hp).toBe(Math.ceil(3 * enemyPokemon.getMaxHp() / 4));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should not allow a target with Protean to change to Fire type",
|
||||||
|
async () => {
|
||||||
|
game.override.enemyAbility(Abilities.PROTEAN);
|
||||||
|
|
||||||
|
await game.classicMode.startBattle([Species.CHARIZARD]);
|
||||||
|
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(Moves.POWDER);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.getLastXMoves()[0].result).toBe(MoveResult.FAIL);
|
||||||
|
expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp());
|
||||||
|
expect(enemyPokemon.summonData?.types).not.toBe(Type.FIRE);
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: Implement this interaction and enable this test
|
||||||
|
it.skip(
|
||||||
|
"should cancel Fire-type moves generated by the target's Dancer ability",
|
||||||
|
async () => {
|
||||||
|
game.override
|
||||||
|
.enemySpecies(Species.BLASTOISE)
|
||||||
|
.enemyAbility(Abilities.DANCER);
|
||||||
|
|
||||||
|
await game.classicMode.startBattle([Species.CHARIZARD]);
|
||||||
|
|
||||||
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(Moves.FIERY_DANCE);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||||
|
const enemyStartingHp = enemyPokemon.hp;
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
// player should not take damage
|
||||||
|
expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp());
|
||||||
|
// enemy should have taken damage from player's Fiery Dance + 2 Powder procs
|
||||||
|
expect(enemyPokemon.hp).toBe(enemyStartingHp - 2*Math.floor(enemyPokemon.getMaxHp() / 4));
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should cancel Revelation Dance if it becomes a Fire-type move",
|
||||||
|
async () => {
|
||||||
|
game.override
|
||||||
|
.enemySpecies(Species.CHARIZARD)
|
||||||
|
.enemyMoveset(Array(4).fill(Moves.REVELATION_DANCE));
|
||||||
|
|
||||||
|
await game.classicMode.startBattle([Species.CHARIZARD]);
|
||||||
|
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(Moves.POWDER);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.getLastXMoves()[0].result).toBe(MoveResult.FAIL);
|
||||||
|
expect(enemyPokemon.hp).toBe(Math.ceil(3 * enemyPokemon.getMaxHp() / 4));
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should cancel Shell Trap and damage the target, even if the move would fail",
|
||||||
|
async () => {
|
||||||
|
game.override.enemyMoveset(Array(4).fill(Moves.SHELL_TRAP));
|
||||||
|
|
||||||
|
await game.classicMode.startBattle([Species.CHARIZARD]);
|
||||||
|
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(Moves.POWDER);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.getLastXMoves()[0].result).toBe(MoveResult.FAIL);
|
||||||
|
expect(enemyPokemon.hp).toBe(Math.ceil(3 * enemyPokemon.getMaxHp() / 4));
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
});
|
Loading…
Reference in New Issue