mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-12-24 10:39:15 +01:00
[Bug] Reset hit-related turn data inside MoveEndPhase (#6637)
* Reset hit-related turn data inside `MoveEndPhase` and remove `extraTurns` field * Fixed FS edge case * Fixed test hit count checks going past move end phase * fixed PB tests * Put `default` switch case last again
This commit is contained in:
parent
a6554acfe3
commit
c7bdfe7ed8
@ -5100,7 +5100,6 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
|
||||
*/
|
||||
override apply({ source, pokemon, move, targets, simulated }: PostMoveUsedAbAttrParams): void {
|
||||
if (!simulated) {
|
||||
pokemon.turnData.extraTurns++;
|
||||
// If the move is an AttackMove or a StatusMove the Dancer must replicate the move on the source of the Dance
|
||||
if (move.getMove().is("AttackMove") || move.getMove().is("StatusMove")) {
|
||||
const target = this.getTarget(pokemon, source, targets);
|
||||
|
||||
@ -1860,7 +1860,9 @@ export class TargetHalfHpDamageAttr extends FixedDamageAttr {
|
||||
super(0);
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, _move: Move, args: any[]): boolean {
|
||||
apply(user: Pokemon, target: Pokemon, _move: Move, args: [NumberHolder, ...any[]]): boolean {
|
||||
const [dmg] = args;
|
||||
|
||||
// first, determine if the hit is coming from multi lens or not
|
||||
const lensCount =
|
||||
user
|
||||
@ -1869,23 +1871,23 @@ export class TargetHalfHpDamageAttr extends FixedDamageAttr {
|
||||
?.getStackCount() ?? 0;
|
||||
if (lensCount <= 0) {
|
||||
// no multi lenses; we can just halve the target's hp and call it a day
|
||||
(args[0] as NumberHolder).value = toDmgValue(target.hp / 2);
|
||||
dmg.value = toDmgValue(target.hp / 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
// figure out what hit # we're on
|
||||
switch (user.turnData.hitCount - user.turnData.hitsLeft) {
|
||||
case lensCount + 1:
|
||||
// parental bond added hit; calc damage as normal
|
||||
(args[0] as NumberHolder).value = toDmgValue(target.hp / 2);
|
||||
// parental bond added hit; halve target's hp as normal
|
||||
dmg.value = toDmgValue(target.hp / 2);
|
||||
return true;
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: intentional?
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: intentional
|
||||
case 0:
|
||||
// first hit of move; update initialHp tracker
|
||||
// first hit of move; update initialHp tracker for first hit
|
||||
this.initialHp = target.hp;
|
||||
default:
|
||||
// multi lens added hit; use initialHp tracker to ensure correct damage
|
||||
(args[0] as NumberHolder).value = toDmgValue(this.initialHp / 2);
|
||||
dmg.value = toDmgValue(this.initialHp / 2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -7861,7 +7863,6 @@ export class RepeatMoveAttr extends MoveEffectAttr {
|
||||
targetPokemonName: getPokemonNameWithAffix(target),
|
||||
}),
|
||||
);
|
||||
target.turnData.extraTurns++;
|
||||
globalScene.phaseManager.unshiftNew(
|
||||
"MovePhase",
|
||||
target,
|
||||
|
||||
@ -124,12 +124,17 @@ export class PokemonSummonData {
|
||||
public stats: number[] = [0, 0, 0, 0, 0, 0];
|
||||
public moveset: PokemonMove[] | null;
|
||||
|
||||
// If not initialized this value will not be populated from save data.
|
||||
public types: PokemonType[] = [];
|
||||
public addedType: PokemonType | null = null;
|
||||
|
||||
/** Data pertaining to this pokemon's illusion. */
|
||||
/** Data pertaining to this pokemon's Illusion, if it has one. */
|
||||
public illusion: IllusionData | null = null;
|
||||
/**
|
||||
* Whether this Pokemon's illusion has been broken since switching out.
|
||||
* @defaultValue `false`
|
||||
*/
|
||||
// TODO: Since Illusion applies on switch in, and this entire class is reset on switch-in,
|
||||
// this may be replaceable with a check for `pokemon.summonData.illusionData !== null`
|
||||
public illusionBroken = false;
|
||||
|
||||
/** Array containing all berries eaten in the last turn; used by {@linkcode AbilityId.CUD_CHEW} */
|
||||
@ -139,6 +144,7 @@ export class PokemonSummonData {
|
||||
* An array of all moves this pokemon has used since entering the battle.
|
||||
* Used for most moves and abilities that check prior move usage or copy already-used moves.
|
||||
*/
|
||||
// TODO: Rework this into a sort of "global move history" that also allows checking execution order (for Fusion Bolt/Flare)
|
||||
public moveHistory: TurnMove[] = [];
|
||||
|
||||
constructor(source?: PokemonSummonData | SerializedPokemonSummonData) {
|
||||
@ -302,8 +308,10 @@ export class PokemonTurnData {
|
||||
/** How many times the current move should hit the target(s) */
|
||||
public hitCount = 0;
|
||||
/**
|
||||
* - `-1` = Calculate how many hits are left
|
||||
* - `0` = Move is finished
|
||||
* - `-1`: Calculate how many hits are left
|
||||
* - `0`: Move is finished
|
||||
* - `>0`: Move is in process of hitting targets
|
||||
* @defaultValue `-1`
|
||||
*/
|
||||
public hitsLeft = -1;
|
||||
public totalDamageDealt = 0;
|
||||
@ -320,20 +328,17 @@ export class PokemonTurnData {
|
||||
public summonedThisTurn = false;
|
||||
public failedRunAway = false;
|
||||
public joinedRound = false;
|
||||
/** Tracker for a pending status effect
|
||||
/**
|
||||
* Tracker for a pending status effect.
|
||||
*
|
||||
* @remarks
|
||||
* Set whenever {@linkcode Pokemon#trySetStatus} succeeds in order to prevent subsequent status effects
|
||||
* from being applied. Necessary because the status is not actually set until the {@linkcode ObtainStatusEffectPhase} runs,
|
||||
* from being applied. \
|
||||
* Necessary because the status is not actually set until the {@linkcode ObtainStatusEffectPhase} runs,
|
||||
* which may not happen before another status effect is attempted to be applied.
|
||||
* @defaultValue `StatusEffect.NONE`
|
||||
*/
|
||||
public pendingStatus: StatusEffect = StatusEffect.NONE;
|
||||
/**
|
||||
* The amount of times this Pokemon has acted again and used a move in the current turn.
|
||||
* Used to make sure multi-hits occur properly when the user is
|
||||
* forced to act again in the same turn, and **must be incremented** by any effects that grant extra actions.
|
||||
*/
|
||||
public extraTurns = 0;
|
||||
/**
|
||||
* All berries eaten by this pokemon in this turn.
|
||||
* Saved into {@linkcode PokemonSummonData | SummonData} by {@linkcode AbilityId.CUD_CHEW} on turn end.
|
||||
|
||||
@ -99,10 +99,8 @@ export class DelayedAttackTag extends PositionalTag implements DelayedAttackArgs
|
||||
public override trigger(): void {
|
||||
// Bangs are justified as the `shouldTrigger` method will queue the tag for removal
|
||||
// if the source or target no longer exist
|
||||
const source = globalScene.getPokemonById(this.sourceId)!;
|
||||
const target = this.getTarget()!;
|
||||
|
||||
source.turnData.extraTurns++;
|
||||
globalScene.phaseManager.queueMessage(
|
||||
i18next.t("moveTriggers:tookMoveAttack", {
|
||||
pokemonName: getPokemonNameWithAffix(target),
|
||||
@ -112,7 +110,9 @@ export class DelayedAttackTag extends PositionalTag implements DelayedAttackArgs
|
||||
|
||||
globalScene.phaseManager.unshiftNew(
|
||||
"MoveEffectPhase",
|
||||
this.sourceId, // TODO: Find an alternate method of passing the source pokemon without a source ID
|
||||
// TODO: Find an alternate method of passing the (currently off-field) source pokemon
|
||||
// instead of relying on pokemon getter jank
|
||||
this.sourceId,
|
||||
[this.targetIndex],
|
||||
allMoves[this.sourceMove],
|
||||
MoveUseMode.DELAYED_ATTACK,
|
||||
|
||||
@ -133,6 +133,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
if (anySuccess) {
|
||||
this.moveHistoryEntry.result = MoveResult.SUCCESS;
|
||||
} else {
|
||||
// If the move failed to impact all targets, disable all subsequent multi-hits
|
||||
user.turnData.hitCount = 1;
|
||||
user.turnData.hitsLeft = 1;
|
||||
this.moveHistoryEntry.result = allMiss ? MoveResult.MISS : MoveResult.FAIL;
|
||||
@ -258,14 +259,6 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
// Lapse `MOVE_EFFECT` effects (i.e. semi-invulnerability) when applicable
|
||||
user.lapseTags(BattlerTagLapseType.MOVE_EFFECT);
|
||||
|
||||
// If the user is acting again (such as due to Instruct or Dancer), reset hitsLeft/hitCount and
|
||||
// recalculate hit count for multi-hit moves.
|
||||
if (user.turnData.hitsLeft === 0 && user.turnData.hitCount > 0 && user.turnData.extraTurns > 0) {
|
||||
user.turnData.hitsLeft = -1;
|
||||
user.turnData.hitCount = 0;
|
||||
user.turnData.extraTurns--;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this phase is for the first hit of the invoked move,
|
||||
* resolve the move's total hit count. This block combines the
|
||||
|
||||
@ -22,6 +22,14 @@ export class MoveEndPhase extends PokemonPhase {
|
||||
super.start();
|
||||
|
||||
const pokemon = this.getPokemon();
|
||||
|
||||
// Reset hit-related temporary data.
|
||||
// TODO: These properties should be stored inside a "move in flight" object,
|
||||
// which this Phase would promptly destroy
|
||||
if (pokemon) {
|
||||
pokemon.turnData.hitsLeft = -1;
|
||||
}
|
||||
|
||||
if (!this.wasFollowUp && pokemon?.isActive(true)) {
|
||||
pokemon.lapseTags(BattlerTagLapseType.AFTER_MOVE);
|
||||
}
|
||||
|
||||
@ -422,13 +422,6 @@ export class MovePhase extends PokemonPhase {
|
||||
this.doThawCheck();
|
||||
}
|
||||
|
||||
// Reset hit-related turn data when starting follow-up moves (e.g. Metronomed moves, Dancer repeats)
|
||||
if (isVirtual(useMode)) {
|
||||
const turnData = user.turnData;
|
||||
turnData.hitsLeft = -1;
|
||||
turnData.hitCount = 0;
|
||||
}
|
||||
|
||||
const pokemonMove = this.move;
|
||||
|
||||
// Check move to see if arena.ignoreAbilities should be true.
|
||||
|
||||
@ -37,6 +37,8 @@ describe("Abilities - Parental Bond", () => {
|
||||
.enemyLevel(100);
|
||||
});
|
||||
|
||||
// TODO: Review how many of these tests are duplicated in other files
|
||||
// and/or in Multi Lens' suite
|
||||
it("should add second strike to attack move", async () => {
|
||||
game.override.moveset([MoveId.TACKLE]);
|
||||
|
||||
@ -53,7 +55,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
const firstStrikeDamage = enemyStartingHp - enemyPokemon.hp;
|
||||
enemyStartingHp = enemyPokemon.hp;
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
const secondStrikeDamage = enemyStartingHp - enemyPokemon.hp;
|
||||
|
||||
@ -70,7 +72,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
game.move.select(MoveId.POWER_UP_PUNCH);
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(leadPokemon.turnData.hitCount).toBe(2);
|
||||
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(2);
|
||||
@ -85,7 +87,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
game.move.select(MoveId.BABY_DOLL_EYES);
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1);
|
||||
});
|
||||
@ -100,7 +102,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
game.move.select(MoveId.DOUBLE_HIT);
|
||||
await game.move.forceHit();
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(leadPokemon.turnData.hitCount).toBe(2);
|
||||
});
|
||||
@ -142,7 +144,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.DRAGON_RAGE);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp() - 80);
|
||||
});
|
||||
@ -156,11 +158,11 @@ describe("Abilities - Parental Bond", () => {
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.COUNTER);
|
||||
await game.phaseInterceptor.to("DamageAnimPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
|
||||
const playerDamage = leadPokemon.getMaxHp() - leadPokemon.hp;
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp() - 4 * playerDamage);
|
||||
});
|
||||
@ -168,16 +170,13 @@ describe("Abilities - Parental Bond", () => {
|
||||
it("should not apply to multi-target moves", async () => {
|
||||
game.override.battleStyle("double").moveset([MoveId.EARTHQUAKE]).passiveAbility(AbilityId.LEVITATE);
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.FEEBAS]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerField();
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
game.move.select(MoveId.EARTHQUAKE);
|
||||
game.move.select(MoveId.EARTHQUAKE, 1);
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
playerPokemon.forEach(p => expect(p.turnData.hitCount).toBe(1));
|
||||
expect(game.field.getPlayerPokemon().turnData.hitCount).toBe(1);
|
||||
});
|
||||
|
||||
it("should apply to multi-target moves when hitting only one target", async () => {
|
||||
@ -208,7 +207,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
expect(leadPokemon.turnData.hitCount).toBe(2);
|
||||
|
||||
// This test will time out if the user faints
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(leadPokemon.hp).toBe(Math.ceil(leadPokemon.getMaxHp() / 2));
|
||||
});
|
||||
@ -229,7 +228,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
expect(enemyPokemon.hp).toBeGreaterThan(0);
|
||||
expect(leadPokemon.isOfType(PokemonType.FIRE)).toBe(true);
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(leadPokemon.isOfType(PokemonType.FIRE)).toBe(false);
|
||||
});
|
||||
@ -332,25 +331,11 @@ describe("Abilities - Parental Bond", () => {
|
||||
expect(leadPokemon.turnData.hitCount).toBe(2);
|
||||
expect(enemyPokemon.status?.effect).toBe(StatusEffect.SLEEP);
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(enemyPokemon.status?.effect).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should not cause user to hit into King's Shield more than once", async () => {
|
||||
game.override.moveset([MoveId.TACKLE]).enemyMoveset([MoveId.KINGS_SHIELD]);
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.TACKLE);
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
expect(leadPokemon.getStatStage(Stat.ATK)).toBe(-1);
|
||||
});
|
||||
|
||||
it("should not cause user to hit into Storm Drain more than once", async () => {
|
||||
game.override.moveset([MoveId.WATER_GUN]).enemyAbility(AbilityId.STORM_DRAIN);
|
||||
|
||||
@ -360,7 +345,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
game.move.select(MoveId.WATER_GUN);
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(1);
|
||||
});
|
||||
|
||||
@ -417,7 +417,8 @@ describe("Abilities - Wimp Out", () => {
|
||||
|
||||
game.move.select(MoveId.ENDURE);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
expect(enemyPokemon.turnData.hitsLeft).toBe(0);
|
||||
@ -433,7 +434,8 @@ describe("Abilities - Wimp Out", () => {
|
||||
|
||||
game.move.select(MoveId.ENDURE);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
expect(enemyPokemon.turnData.hitsLeft).toBe(0);
|
||||
@ -448,7 +450,8 @@ describe("Abilities - Wimp Out", () => {
|
||||
|
||||
game.move.select(MoveId.ENDURE);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
expect(enemyPokemon.turnData.hitsLeft).toBe(0);
|
||||
|
||||
@ -55,7 +55,7 @@ describe("Items - Multi Lens", () => {
|
||||
game.move.select(MoveId.TACKLE);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
const damageResults = spy.mock.results.map(result => result.value?.damage);
|
||||
|
||||
expect(damageResults).toHaveLength(1 + stackCount);
|
||||
@ -74,7 +74,7 @@ describe("Items - Multi Lens", () => {
|
||||
game.move.select(MoveId.TACKLE);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
expect(playerPokemon.turnData.hitCount).toBe(3);
|
||||
});
|
||||
|
||||
@ -112,7 +112,7 @@ describe("Items - Multi Lens", () => {
|
||||
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
|
||||
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(magikarp.turnData.hitCount).toBe(2);
|
||||
});
|
||||
@ -129,7 +129,7 @@ describe("Items - Multi Lens", () => {
|
||||
game.move.select(MoveId.SEISMIC_TOSS);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
const damageResults = spy.mock.results.map(result => result.value?.damage);
|
||||
|
||||
expect(damageResults).toHaveLength(2);
|
||||
|
||||
@ -86,19 +86,6 @@ describe("Moves - Beak Blast", () => {
|
||||
expect(enemyPokemon.status?.effect).not.toBe(StatusEffect.BURN);
|
||||
});
|
||||
|
||||
it("should only hit twice with Multi-Lens", async () => {
|
||||
game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]);
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.BLASTOISE]);
|
||||
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.BEAK_BLAST);
|
||||
|
||||
await game.phaseInterceptor.to(BerryPhase, false);
|
||||
expect(leadPokemon.turnData.hitCount).toBe(2);
|
||||
});
|
||||
|
||||
it("should be blocked by Protect", async () => {
|
||||
game.override.enemyMoveset([MoveId.PROTECT]);
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ describe("Moves - Electro Shot", () => {
|
||||
|
||||
game.move.select(MoveId.ELECTRO_SHOT);
|
||||
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
expect(playerPokemon.turnData.hitCount).toBe(1);
|
||||
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(1);
|
||||
});
|
||||
|
||||
@ -179,7 +179,8 @@ describe("Moves - Protect", () => {
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.PROTECT);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(charizard.hp).toBe(charizard.getMaxHp());
|
||||
expect(enemyPokemon.turnData.hitCount).toBe(1);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user