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,
NeutralDamageAgainstFlyingTypeMultiplierAttr,
FixedDamageAttr,
type MoveAttr,
ForceSwitchOutAttr,
} from "#app/data/moves/move";
import { allMoves } from "../data-lists";
import { ArenaTagSide } from "#app/data/arena-tag";
@ -69,7 +67,7 @@ import { BerryUsedEvent } from "#app/events/battle-scene";
// Type imports
import { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
import { PokemonMove } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon";
import type { Weather } from "#app/data/weather";
import type { BattlerTag } from "#app/data/battler-tags";
@ -1302,6 +1300,7 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr {
if (!pokemon.isTerastallized &&
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}
*/
!move.findAttr((attr) =>
@ -5630,19 +5629,19 @@ export class PostDamageForceSwitchAbAttr extends ForceSwitch(PostDamageAbAttr) {
const currentPhase = globalScene.getCurrentPhase() as MoveEffectPhase;
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
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,
// 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)
// 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)
// 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 -
// we could be sky dropped by another Pokemon or take indirect damage while skybound (both of which render this check moot)
// 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 useless)
const lastMove = source?.getLastXMoves()[0]
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.
* @param pokemon - The {@linkcode Pokemon} with this ability
* @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) {
// 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.
*/
public override applyPostDamage(pokemon: Pokemon, _damage: number, _simulated: boolean, _source: Pokemon | undefined, args: any[]): void {
public override applyPostDamage(pokemon: Pokemon): void {
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 lapseType - The {@linkcode BattlerTagLapseType | lapse type} triggering this tag's effects.
* @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
const shouldInterruptMove = Overrides.CONFUSION_ACTIVATION_OVERRIDE ?? pokemon.randBattleSeedInt(3) === 0;
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 def = pokemon.getEffectiveStat(Stat.DEF);
const damage = toDmgValue(

View File

@ -6925,15 +6925,15 @@ export class PokemonTurnData {
public hitsLeft = -1;
/**
* 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,
* 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[] = [];
/**
* The amount of damage dealt by this Pokemon's last hit.
* Used to calculate recoil damage amounts.
* TODO: Merge with `lastMoveDamageDealt` if any spread recoil moves are added
*/
public singleHitDamageDealt = 0;
// 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 { ToggleDoublePositionPhase } from "./toggle-double-position-phase";
import { VictoryPhase } from "./victory-phase";
import { isNullOrUndefined } from "#app/utils/common";
import { FRIENDSHIP_LOSS_FROM_FAINT } from "#app/data/balance/starters";
import { BattlerTagType } from "#enums/battler-tag-type";
import { isNullOrUndefined } from "#app/utils/common";
export class FaintPhase extends PokemonPhase {
/**
@ -170,7 +170,7 @@ export class FaintPhase extends PokemonPhase {
*/
globalScene.unshiftPhase(new ToggleDoublePositionPhase(true));
} 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));
}
} else {

View File

@ -43,6 +43,8 @@ describe("Abilities - Arena Trap", () => {
const enemy = game.scene.getEnemyPokemon()!;
// flee stuff goes here
game.onNextPrompt("CommandPhase", UiMode.COMMAND, () => {
// no switch out command should be queued due to arena trap
expect(game.scene.currentBattle.turnCommands[0]).toBeNull();
@ -59,14 +61,6 @@ describe("Abilities - Arena Trap", () => {
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 () => {

View File

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