Fixed disguise test + comments

This commit is contained in:
Bertie690 2025-05-30 14:58:09 -04:00
parent d4b2b0af26
commit f6d2df676b
6 changed files with 22 additions and 29 deletions

View File

@ -19,8 +19,6 @@ import {
CopyMoveAttr, CopyMoveAttr,
NeutralDamageAgainstFlyingTypeMultiplierAttr, NeutralDamageAgainstFlyingTypeMultiplierAttr,
FixedDamageAttr, FixedDamageAttr,
type MoveAttr,
ForceSwitchOutAttr,
} from "#app/data/moves/move"; } from "#app/data/moves/move";
import { allMoves } from "../data-lists"; import { allMoves } from "../data-lists";
import { ArenaTagSide } from "#app/data/arena-tag"; import { ArenaTagSide } from "#app/data/arena-tag";
@ -69,7 +67,7 @@ import { BerryUsedEvent } from "#app/events/battle-scene";
// Type imports // Type imports
import { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; import { PokemonMove } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import type { Weather } from "#app/data/weather"; import type { Weather } from "#app/data/weather";
import type { BattlerTag } from "#app/data/battler-tags"; import type { BattlerTag } from "#app/data/battler-tags";
@ -1302,6 +1300,7 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr {
if (!pokemon.isTerastallized && if (!pokemon.isTerastallized &&
move.id !== Moves.STRUGGLE && move.id !== Moves.STRUGGLE &&
/** /**
* Skip moves that call other moves because these moves generate a following move that will trigger this ability attribute
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_call_other_moves} * @see {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_call_other_moves}
*/ */
!move.findAttr((attr) => !move.findAttr((attr) =>
@ -5630,19 +5629,19 @@ export class PostDamageForceSwitchAbAttr extends ForceSwitch(PostDamageAbAttr) {
const currentPhase = globalScene.getCurrentPhase() as MoveEffectPhase; const currentPhase = globalScene.getCurrentPhase() as MoveEffectPhase;
const currentMove = currentPhase.move; const currentMove = currentPhase.move;
// will not activate from self-induced HP cutting... // will not activate from self-induced HP cutting,
// TODO: Verify that Fillet Away and Clangorous Soul proc wimp out // TODO: Verify that Fillet Away and Clangorous Soul proc wimp out
const hpCutMoves = new Set<Moves>([ Moves.CURSE, Moves.BELLY_DRUM, Moves.SUBSTITUTE, Moves.PAIN_SPLIT, Moves.CLANGOROUS_SOUL, Moves.FILLET_AWAY]); const hpCutMoves = new Set<Moves>([ Moves.CURSE, Moves.BELLY_DRUM, Moves.SUBSTITUTE, Moves.PAIN_SPLIT, Moves.CLANGOROUS_SOUL, Moves.FILLET_AWAY]);
// NB: Given this attribute is only applied after _taking damage_ or recieving a damaging attack, // NB: Given this attribute is only applied after _taking damage_ or recieving a damaging attack,
// a failed Substitute or non-ghost type Curse will not trigger this ability to begin with. // a failed Substitute or non-Ghost type Curse will not trigger this code.
const notHpCut = !hpCutMoves.has(currentMove.id) const notHpCut = !hpCutMoves.has(currentMove.id)
// will not activate for forced switch moves (which trigger before wimp out activates)... // will not activate for forced switch moves (which trigger before wimp out activates),
const notForceSwitched = ![Moves.DRAGON_TAIL, Moves.CIRCLE_THROW].includes(currentMove.id) const notForceSwitched = ![Moves.DRAGON_TAIL, Moves.CIRCLE_THROW].includes(currentMove.id)
// and will not activate if the Pokemon is currently in the air from Sky Drop. // and will not activate if the Pokemon is currently in the air from Sky Drop.
// TODO: Make this check the user's tags once Sky Drop is fully implemented - // TODO: Make this check the user's tags and move to main `canApply` block once Sky Drop is fully implemented -
// we could be sky dropped by another Pokemon or take indirect damage while skybound (both of which render this check moot) // we could be sky dropped by another Pokemon or take indirect damage while skybound (both of which render this check useless)
const lastMove = source?.getLastXMoves()[0] const lastMove = source?.getLastXMoves()[0]
const notSkyDropped = !(lastMove?.move === Moves.SKY_DROP && lastMove.result === MoveResult.OTHER) const notSkyDropped = !(lastMove?.move === Moves.SKY_DROP && lastMove.result === MoveResult.OTHER)
@ -5655,7 +5654,7 @@ export class PostDamageForceSwitchAbAttr extends ForceSwitch(PostDamageAbAttr) {
* or is still above it after the hit. * or is still above it after the hit.
* @param pokemon - The {@linkcode Pokemon} with this ability * @param pokemon - The {@linkcode Pokemon} with this ability
* @param damage - The amount of damage taken. * @param damage - The amount of damage taken.
* @returns `true` if this Pokemon was knocked below half after `damage` was applied * @returns Whether the Pokemon was knocked below half after `damage` was applied
*/ */
private wasKnockedBelowHalf(pokemon: Pokemon, damage: number) { private wasKnockedBelowHalf(pokemon: Pokemon, damage: number) {
// NB: This occurs in `MoveEffectPhase` _after_ attack damage has been dealt, // NB: This occurs in `MoveEffectPhase` _after_ attack damage has been dealt,
@ -5669,7 +5668,7 @@ export class PostDamageForceSwitchAbAttr extends ForceSwitch(PostDamageAbAttr) {
* *
* @param pokemon The Pokémon that took damage. * @param pokemon The Pokémon that took damage.
*/ */
public override applyPostDamage(pokemon: Pokemon, _damage: number, _simulated: boolean, _source: Pokemon | undefined, args: any[]): void { public override applyPostDamage(pokemon: Pokemon): void {
this.doSwitch(pokemon); this.doSwitch(pokemon);
} }
} }

View File

@ -752,7 +752,7 @@ export class ConfusedTag extends BattlerTag {
} }
/** /**
* Tick down this Pokemon's confusion duration, randomly interrupting its move if not cured/ * Tick down this Pokemon's confusion duration, randomly interrupting its move if not cured.
* @param pokemon - The {@linkcode Pokemon} with this tag * @param pokemon - The {@linkcode Pokemon} with this tag
* @param lapseType - The {@linkcode BattlerTagLapseType | lapse type} triggering this tag's effects. * @param lapseType - The {@linkcode BattlerTagLapseType | lapse type} triggering this tag's effects.
* @returns Whether the tag should be kept. * @returns Whether the tag should be kept.
@ -774,7 +774,7 @@ export class ConfusedTag extends BattlerTag {
// 1/3 chance of hitting self with a 40 base power move // 1/3 chance of hitting self with a 40 base power move
const shouldInterruptMove = Overrides.CONFUSION_ACTIVATION_OVERRIDE ?? pokemon.randBattleSeedInt(3) === 0; const shouldInterruptMove = Overrides.CONFUSION_ACTIVATION_OVERRIDE ?? pokemon.randBattleSeedInt(3) === 0;
if (shouldInterruptMove) { if (shouldInterruptMove) {
// TODO: Are these calculations correct? We really shouldn't hardcode the damage formula here... // TODO: Are these calculations correct? We probably shouldn't hardcode the damage formula here...
const atk = pokemon.getEffectiveStat(Stat.ATK); const atk = pokemon.getEffectiveStat(Stat.ATK);
const def = pokemon.getEffectiveStat(Stat.DEF); const def = pokemon.getEffectiveStat(Stat.DEF);
const damage = toDmgValue( const damage = toDmgValue(

View File

@ -6925,15 +6925,15 @@ export class PokemonTurnData {
public hitsLeft = -1; public hitsLeft = -1;
/** /**
* The final amount of damage dealt by this Pokemon's last attack against each of its targets, * The final amount of damage dealt by this Pokemon's last attack against each of its targets,
* mapped by their respective `BattlerIndex`es. * indexed by their respective `BattlerIndex`es.
* Reset to an empty array upon attempting to use a move, * Reset to an empty array upon attempting to use a move,
* and is used to calculate various damage-related effects (Shell Bell, U-Turn + Wimp Out interactions, etc.). * and is used to calculate various damage-related effects (Shell Bell, U-Turn + Wimp Out interactions, etc.).
*/ */
// TODO: move this or something like it to some sort of "move in flight" object
public lastMoveDamageDealt: number[] = []; public lastMoveDamageDealt: number[] = [];
/** /**
* The amount of damage dealt by this Pokemon's last hit. * The amount of damage dealt by this Pokemon's last hit.
* Used to calculate recoil damage amounts. * Used to calculate recoil damage amounts.
* TODO: Merge with `lastMoveDamageDealt` if any spread recoil moves are added
*/ */
public singleHitDamageDealt = 0; public singleHitDamageDealt = 0;
// TODO: Make this into a "damage taken last" counter for metal burst and co. // TODO: Make this into a "damage taken last" counter for metal burst and co.

View File

@ -30,9 +30,9 @@ import { SwitchPhase } from "./switch-phase";
import { SwitchSummonPhase } from "./switch-summon-phase"; import { SwitchSummonPhase } from "./switch-summon-phase";
import { ToggleDoublePositionPhase } from "./toggle-double-position-phase"; import { ToggleDoublePositionPhase } from "./toggle-double-position-phase";
import { VictoryPhase } from "./victory-phase"; import { VictoryPhase } from "./victory-phase";
import { isNullOrUndefined } from "#app/utils/common";
import { FRIENDSHIP_LOSS_FROM_FAINT } from "#app/data/balance/starters"; import { FRIENDSHIP_LOSS_FROM_FAINT } from "#app/data/balance/starters";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { isNullOrUndefined } from "#app/utils/common";
export class FaintPhase extends PokemonPhase { export class FaintPhase extends PokemonPhase {
/** /**
@ -170,7 +170,7 @@ export class FaintPhase extends PokemonPhase {
*/ */
globalScene.unshiftPhase(new ToggleDoublePositionPhase(true)); globalScene.unshiftPhase(new ToggleDoublePositionPhase(true));
} else { } else {
// If previous conditions weren't met, push a phase to prompt the player to select a pokemon from their party. // If previous conditions weren't met, push a phase to prompt the player to select a new pokemon from their party.
globalScene.pushPhase(new SwitchPhase(SwitchType.SWITCH, this.fieldIndex, true, false)); globalScene.pushPhase(new SwitchPhase(SwitchType.SWITCH, this.fieldIndex, true, false));
} }
} else { } else {

View File

@ -43,6 +43,8 @@ describe("Abilities - Arena Trap", () => {
const enemy = game.scene.getEnemyPokemon()!; const enemy = game.scene.getEnemyPokemon()!;
// flee stuff goes here
game.onNextPrompt("CommandPhase", UiMode.COMMAND, () => { game.onNextPrompt("CommandPhase", UiMode.COMMAND, () => {
// no switch out command should be queued due to arena trap // no switch out command should be queued due to arena trap
expect(game.scene.currentBattle.turnCommands[0]).toBeNull(); expect(game.scene.currentBattle.turnCommands[0]).toBeNull();
@ -59,14 +61,6 @@ describe("Abilities - Arena Trap", () => {
abilityName: allAbilities[Abilities.ARENA_TRAP].name, abilityName: allAbilities[Abilities.ARENA_TRAP].name,
}), }),
); );
game.override.ability(Abilities.RUN_AWAY);
// do switch stuff
await game.toNextTurn();
expect(game.scene.currentBattle.waveIndex).toBe(2);
}); });
it("should interrupt player switch attempt and display message", async () => { it("should interrupt player switch attempt and display message", async () => {

View File

@ -47,7 +47,7 @@ describe("Abilities - Disguise", () => {
await game.phaseInterceptor.to("MoveEndPhase"); await game.phaseInterceptor.to("MoveEndPhase");
expect(mimikyu.hp).equals(maxHp - disguiseDamage); expect(mimikyu.hp).toBe(maxHp - disguiseDamage);
expect(mimikyu.formIndex).toBe(bustedForm); expect(mimikyu.formIndex).toBe(bustedForm);
}); });
@ -80,12 +80,12 @@ describe("Abilities - Disguise", () => {
// First hit // First hit
await game.phaseInterceptor.to("MoveEffectPhase"); await game.phaseInterceptor.to("MoveEffectPhase");
expect(mimikyu.hp).equals(maxHp - disguiseDamage); expect(mimikyu.hp).toBe(maxHp - disguiseDamage);
expect(mimikyu.formIndex).toBe(disguisedForm); expect(mimikyu.formIndex).toBe(disguisedForm);
// Second hit // Second hit
await game.phaseInterceptor.to("MoveEffectPhase"); await game.phaseInterceptor.to("MoveEffectPhase");
expect(mimikyu.hp).lessThan(maxHp - disguiseDamage); expect(mimikyu.hp).toBeLessThan(maxHp - disguiseDamage);
expect(mimikyu.formIndex).toBe(bustedForm); expect(mimikyu.formIndex).toBe(bustedForm);
}); });
@ -120,7 +120,7 @@ describe("Abilities - Disguise", () => {
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
expect(mimikyu.formIndex).toBe(bustedForm); expect(mimikyu.formIndex).toBe(bustedForm);
expect(mimikyu.hp).equals(maxHp - disguiseDamage); expect(mimikyu.hp).toBe(maxHp - disguiseDamage);
await game.toNextTurn(); await game.toNextTurn();
game.doSwitchPokemon(1); game.doSwitchPokemon(1);
@ -186,7 +186,7 @@ describe("Abilities - Disguise", () => {
await game.toNextTurn(); await game.toNextTurn();
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.doKillOpponents(); await game.doKillOpponents();
await game.phaseInterceptor.to("QuietFormChangePhase"); await game.phaseInterceptor.to("ReturnPhase");
expect(mimikyu1.formIndex).toBe(disguisedForm); expect(mimikyu1.formIndex).toBe(disguisedForm);
}); });