mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-30 21:42:20 +02:00
Fixed Wimp out tests & ME code
finally i think all the booleans are gone i hope
This commit is contained in:
parent
3f02493f79
commit
06d250d9e7
@ -38,6 +38,7 @@ import type { BerryType } from "#enums/berry-type";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { Stat } from "#enums/stat";
|
||||
import i18next from "i18next";
|
||||
import { MoveUseType } from "#enums/move-use-type";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounters/absoluteAvarice";
|
||||
@ -303,7 +304,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY],
|
||||
move: new PokemonMove(Moves.STUFF_CHEEKS),
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
});
|
||||
|
||||
await transitionMysteryEncounterIntroVisuals(true, true, 500);
|
||||
|
@ -49,6 +49,7 @@ import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { EncounterAnim } from "#enums/encounter-anims";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { MoveUseType } from "#enums/move-use-type";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounters/clowningAround";
|
||||
@ -209,19 +210,19 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY_2],
|
||||
move: new PokemonMove(Moves.ROLE_PLAY),
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
move: new PokemonMove(Moves.TAUNT),
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.PLAYER_2],
|
||||
move: new PokemonMove(Moves.TAUNT),
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -41,6 +41,7 @@ import { PokeballType } from "#enums/pokeball";
|
||||
import { Species } from "#enums/species";
|
||||
import { Stat } from "#enums/stat";
|
||||
import i18next from "i18next";
|
||||
import { MoveUseType } from "#enums/move-use-type";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounters/dancingLessons";
|
||||
@ -216,7 +217,7 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
move: new PokemonMove(Moves.REVELATION_DANCE),
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
});
|
||||
|
||||
await hideOricorioPokemon();
|
||||
|
@ -48,6 +48,7 @@ import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { Ability } from "#app/data/abilities/ability-class";
|
||||
import { FIRE_RESISTANT_ABILITIES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||
import { MoveUseType } from "#enums/move-use-type";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounters/fieryFallout";
|
||||
@ -194,13 +195,13 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
move: new PokemonMove(Moves.FIRE_SPIN),
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.PLAYER_2],
|
||||
move: new PokemonMove(Moves.FIRE_SPIN),
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
},
|
||||
);
|
||||
await initBattleWithEnemyConfig(globalScene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]);
|
||||
|
@ -31,6 +31,7 @@ import { BerryType } from "#enums/berry-type";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import { randSeedInt } from "#app/utils/common";
|
||||
import { MoveUseType } from "#enums/move-use-type";
|
||||
|
||||
/** i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounters/slumberingSnorlax";
|
||||
@ -133,14 +134,12 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS],
|
||||
fillRemaining: true,
|
||||
});
|
||||
encounter.startOfBattleEffects.push(
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
move: new PokemonMove(Moves.SNORE),
|
||||
ignorePp: true,
|
||||
},
|
||||
);
|
||||
encounter.startOfBattleEffects.push({
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
move: new PokemonMove(Moves.SNORE),
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
});
|
||||
await initBattleWithEnemyConfig(encounter.enemyPartyConfigs[0]);
|
||||
},
|
||||
)
|
||||
|
@ -29,6 +29,7 @@ import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { MoveUseType } from "#enums/move-use-type";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounters/theStrongStuff";
|
||||
@ -211,13 +212,13 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
move: new PokemonMove(Moves.GASTRO_ACID),
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
move: new PokemonMove(Moves.STEALTH_ROCK),
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -28,6 +28,7 @@ import { BattlerIndex } from "#app/battle";
|
||||
import { PokemonMove } from "#app/field/pokemon";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { randSeedInt } from "#app/utils/common";
|
||||
import { MoveUseType } from "#enums/move-use-type";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounters/trashToTreasure";
|
||||
@ -207,13 +208,13 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
move: new PokemonMove(Moves.TOXIC),
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY],
|
||||
move: new PokemonMove(Moves.STOCKPILE),
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
},
|
||||
);
|
||||
await initBattleWithEnemyConfig(encounter.enemyPartyConfigs[0]);
|
||||
|
@ -38,6 +38,7 @@ import { BerryModifier } from "#app/modifier/modifier";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { MoveUseType } from "#enums/move-use-type";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounters/uncommonBreed";
|
||||
@ -178,7 +179,7 @@ export const UncommonBreedEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [target],
|
||||
move: pokemonMove,
|
||||
ignorePp: true,
|
||||
useType: MoveUseType.IGNORE_PP,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -28,14 +28,14 @@ import type { GameModes } from "#app/game-mode";
|
||||
import type { EncounterAnim } from "#enums/encounter-anims";
|
||||
import type { Challenges } from "#enums/challenges";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { MoveUseType } from "#enums/move-use-type";
|
||||
|
||||
export interface EncounterStartOfBattleEffect {
|
||||
sourcePokemon?: Pokemon;
|
||||
sourceBattlerIndex?: BattlerIndex;
|
||||
targets: BattlerIndex[];
|
||||
move: PokemonMove;
|
||||
ignorePp: boolean;
|
||||
followUp?: boolean;
|
||||
useType: MoveUseType; // TODO: This should always be ignore PP...
|
||||
}
|
||||
|
||||
const DEFAULT_MAX_ALLOWED_ENCOUNTERS = 2;
|
||||
@ -253,7 +253,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
||||
*/
|
||||
selectedOption?: MysteryEncounterOption;
|
||||
/**
|
||||
* Will be set by option select handlers automatically, and can be used to refer to which option was chosen by later phases
|
||||
* Array containing data pertaining to free moves used at the start of a battle mystery envounter.
|
||||
*/
|
||||
startOfBattleEffects: EncounterStartOfBattleEffect[] = [];
|
||||
/**
|
||||
|
@ -1,5 +1,4 @@
|
||||
import type Battle from "#app/battle";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { BattleType } from "#enums/battle-type";
|
||||
import { biomeLinks, BiomePoolTier } from "#app/data/balance/biomes";
|
||||
import type MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
@ -986,26 +985,9 @@ export function handleMysteryEncounterBattleStartEffects() {
|
||||
) {
|
||||
const effects = encounter.startOfBattleEffects;
|
||||
effects.forEach(effect => {
|
||||
let source: EnemyPokemon | Pokemon;
|
||||
if (effect.sourcePokemon) {
|
||||
source = effect.sourcePokemon;
|
||||
} else if (!isNullOrUndefined(effect.sourceBattlerIndex)) {
|
||||
if (effect.sourceBattlerIndex === BattlerIndex.ATTACKER) {
|
||||
source = globalScene.getEnemyField()[0];
|
||||
} else if (effect.sourceBattlerIndex === BattlerIndex.ENEMY) {
|
||||
source = globalScene.getEnemyField()[0];
|
||||
} else if (effect.sourceBattlerIndex === BattlerIndex.ENEMY_2) {
|
||||
source = globalScene.getEnemyField()[1];
|
||||
} else if (effect.sourceBattlerIndex === BattlerIndex.PLAYER) {
|
||||
source = globalScene.getPlayerField()[0];
|
||||
} else if (effect.sourceBattlerIndex === BattlerIndex.PLAYER_2) {
|
||||
source = globalScene.getPlayerField()[1];
|
||||
}
|
||||
} else {
|
||||
source = globalScene.getEnemyField()[0];
|
||||
}
|
||||
// @ts-ignore: source cannot be undefined
|
||||
globalScene.pushPhase(new MovePhase(source, effect.targets, effect.move, effect.followUp, effect.ignorePp));
|
||||
const source: EnemyPokemon | Pokemon =
|
||||
effect.sourcePokemon ?? globalScene.getField()[effect.sourceBattlerIndex ?? 0];
|
||||
globalScene.pushPhase(new MovePhase(source, effect.targets, effect.move, effect.useType));
|
||||
});
|
||||
|
||||
// Pseudo turn end phase to reset flinch states, Endure, etc.
|
||||
|
@ -44,7 +44,6 @@ describe("Abilities - Wimp Out", () => {
|
||||
|
||||
function confirmSwitch(): void {
|
||||
const [pokemon1, pokemon2] = game.scene.getPlayerParty();
|
||||
|
||||
expect(game.phaseInterceptor.log).toContain("SwitchSummonPhase");
|
||||
|
||||
expect(pokemon1.species.speciesId).not.toBe(Species.WIMPOD);
|
||||
@ -56,17 +55,34 @@ describe("Abilities - Wimp Out", () => {
|
||||
|
||||
function confirmNoSwitch(): void {
|
||||
const [pokemon1, pokemon2] = game.scene.getPlayerParty();
|
||||
|
||||
expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase");
|
||||
|
||||
expect(pokemon2.species.speciesId).not.toBe(Species.WIMPOD);
|
||||
|
||||
expect(pokemon1.species.speciesId).toBe(Species.WIMPOD);
|
||||
expect(pokemon1.isFainted()).toBe(false);
|
||||
expect(pokemon1.getHpRatio()).toBeLessThan(0.5);
|
||||
|
||||
expect(pokemon2.species.speciesId).not.toBe(Species.WIMPOD);
|
||||
}
|
||||
|
||||
it("triggers regenerator passive single time when switching out with wimp out", async () => {
|
||||
it("should switch user out when falling below 50% HP, cancelling any pending moves", async () => {
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
const wimpod = game.scene.getPlayerPokemon()!;
|
||||
wimpod.hp *= 0.51;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.phaseInterceptor.to("DamageAnimPhase", false);
|
||||
game.phaseInterceptor.clearLogs();
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
confirmSwitch();
|
||||
expect(wimpod.turnData.acted).toBe(false);
|
||||
expect(game.phaseInterceptor.log).not.toContain("MoveEffectPhase");
|
||||
});
|
||||
|
||||
it("should trigger regenerator passive when switching out", async () => {
|
||||
game.override.passiveAbility(Abilities.REGENERATOR).startingLevel(5).enemyLevel(100);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
@ -80,7 +96,7 @@ describe("Abilities - Wimp Out", () => {
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("It makes wild pokemon flee if triggered", async () => {
|
||||
it("should cause wild pokemon to flee", async () => {
|
||||
game.override.enemyAbility(Abilities.WIMP_OUT);
|
||||
await game.classicMode.startBattle([Species.GOLISOPOD, Species.TYRUNT]);
|
||||
|
||||
@ -90,12 +106,11 @@ describe("Abilities - Wimp Out", () => {
|
||||
game.move.select(Moves.FALSE_SWIPE);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
const isVisible = enemyPokemon.visible;
|
||||
const hasFled = enemyPokemon.switchOutStatus;
|
||||
expect(!isVisible && hasFled).toBe(true);
|
||||
expect(enemyPokemon.visible).toBe(false);
|
||||
expect(enemyPokemon.switchOutStatus).toBe(true);
|
||||
});
|
||||
|
||||
it("Does not trigger when HP already below half", async () => {
|
||||
it("should not trigger when HP is already below half", async () => {
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
const wimpod = game.scene.getPlayerPokemon()!;
|
||||
wimpod.hp = 5;
|
||||
@ -107,7 +122,7 @@ describe("Abilities - Wimp Out", () => {
|
||||
confirmNoSwitch();
|
||||
});
|
||||
|
||||
it("Trapping moves do not prevent Wimp Out from activating.", async () => {
|
||||
it("should bypass trapping moves and abilities", async () => {
|
||||
game.override.enemyMoveset([Moves.SPIRIT_SHACKLE]).startingLevel(53).enemyLevel(45);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
@ -122,7 +137,7 @@ describe("Abilities - Wimp Out", () => {
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("If this Ability activates due to being hit by U-turn or Volt Switch, the user of that move will not be switched out.", async () => {
|
||||
it("should block switching from U-Turn on activation", async () => {
|
||||
game.override.startingLevel(95).enemyMoveset([Moves.U_TURN]);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
@ -136,7 +151,7 @@ describe("Abilities - Wimp Out", () => {
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("If this Ability does not activate due to being hit by U-turn or Volt Switch, the user of that move will be switched out.", async () => {
|
||||
it("should not block switching from U-Turn on failed activation", async () => {
|
||||
game.override.startingLevel(190).startingWave(8).enemyMoveset([Moves.U_TURN]);
|
||||
await game.classicMode.startBattle([Species.GOLISOPOD, Species.TYRUNT]);
|
||||
const RIVAL_NINJASK1 = game.scene.getEnemyPokemon()?.id;
|
||||
@ -145,7 +160,7 @@ describe("Abilities - Wimp Out", () => {
|
||||
expect(game.scene.getEnemyPokemon()?.id !== RIVAL_NINJASK1);
|
||||
});
|
||||
|
||||
it("Dragon Tail and Circle Throw switch out Pokémon before the Ability activates.", async () => {
|
||||
it("Dragon Tail and Circle Throw switch out Pokémon before the Ability activates", async () => {
|
||||
game.override.startingLevel(69).enemyMoveset([Moves.DRAGON_TAIL]);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
@ -162,7 +177,7 @@ describe("Abilities - Wimp Out", () => {
|
||||
expect(game.scene.getPlayerPokemon()!.species.speciesId).not.toBe(Species.WIMPOD);
|
||||
});
|
||||
|
||||
it("triggers when recoil damage is taken", async () => {
|
||||
it("should trigger from recoil damage", async () => {
|
||||
game.override.moveset([Moves.HEAD_SMASH]).enemyMoveset([Moves.SPLASH]);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
@ -173,7 +188,7 @@ describe("Abilities - Wimp Out", () => {
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("It does not activate when the Pokémon cuts its own HP", async () => {
|
||||
it("should not activate when the Pokémon cuts its own HP", async () => {
|
||||
game.override.moveset([Moves.SUBSTITUTE]).enemyMoveset([Moves.SPLASH]);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
@ -186,7 +201,19 @@ describe("Abilities - Wimp Out", () => {
|
||||
confirmNoSwitch();
|
||||
});
|
||||
|
||||
it("Does not trigger when neutralized", async () => {
|
||||
it("should not trigger from Sheer Force-boosted moves", async () => {
|
||||
game.override.enemyAbility(Abilities.SHEER_FORCE).enemyMoveset(Moves.SLUDGE_BOMB).startingLevel(95);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.51;
|
||||
|
||||
game.move.select(Moves.ENDURE);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
confirmNoSwitch();
|
||||
});
|
||||
|
||||
it("should not trigger while neutralized", async () => {
|
||||
game.override.enemyAbility(Abilities.NEUTRALIZING_GAS).startingLevel(5);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
@ -223,106 +250,140 @@ describe("Abilities - Wimp Out", () => {
|
||||
},
|
||||
);
|
||||
|
||||
it("Wimp Out will activate due to weather damage", async () => {
|
||||
game.override.weather(WeatherType.HAIL).enemyMoveset([Moves.SPLASH]);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
// TODO: Condense into it.eaches
|
||||
describe("Post Turn Damage Checks - ", () => {
|
||||
beforeEach(() => {
|
||||
game.override.enemyMoveset(Moves.SPLASH);
|
||||
});
|
||||
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.51;
|
||||
it("Wimp Out will activate due to weather damage", async () => {
|
||||
game.override.weather(WeatherType.HAIL);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.51;
|
||||
|
||||
confirmSwitch();
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to post turn status damage", async () => {
|
||||
game.override.statusEffect(StatusEffect.POISON);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.51;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to leech seed", async () => {
|
||||
game.override.enemyMoveset([Moves.LEECH_SEED]);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.52;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to curse damage", async () => {
|
||||
game.override.enemySpecies(Species.DUSKNOIR).enemyMoveset([Moves.CURSE]);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.52;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to salt cure damage", async () => {
|
||||
game.override.enemySpecies(Species.NACLI).enemyMoveset([Moves.SALT_CURE]).enemyLevel(1);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.7;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to damaging trap damage", async () => {
|
||||
game.override.enemySpecies(Species.MAGIKARP).enemyMoveset([Moves.WHIRLPOOL]).enemyLevel(1);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.55;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to aftermath", async () => {
|
||||
game.override
|
||||
.moveset([Moves.THUNDER_PUNCH])
|
||||
.enemySpecies(Species.MAGIKARP)
|
||||
.enemyAbility(Abilities.AFTERMATH)
|
||||
.enemyMoveset([Moves.SPLASH])
|
||||
.enemyLevel(1);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.51;
|
||||
|
||||
game.move.select(Moves.THUNDER_PUNCH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to bad dreams", async () => {
|
||||
game.override.statusEffect(StatusEffect.SLEEP).enemyAbility(Abilities.BAD_DREAMS);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.52;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Activates due to entry hazards", async () => {
|
||||
game.scene.arena.addTag(ArenaTagType.STEALTH_ROCK, 1, Moves.STEALTH_ROCK, 0, ArenaTagSide.ENEMY);
|
||||
game.scene.arena.addTag(ArenaTagType.SPIKES, 1, Moves.SPIKES, 0, ArenaTagSide.ENEMY);
|
||||
game.override.enemySpecies(Species.CENTISKORCH).enemyAbility(Abilities.WIMP_OUT).startingWave(4);
|
||||
await game.classicMode.startBattle([Species.TYRUNT]);
|
||||
|
||||
expect(game.phaseInterceptor.log).not.toContain("MovePhase");
|
||||
expect(game.phaseInterceptor.log).toContain("BattleEndPhase");
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to Nightmare", async () => {
|
||||
game.override.enemyMoveset([Moves.NIGHTMARE]).statusEffect(StatusEffect.SLEEP);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.65;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
});
|
||||
|
||||
it("Does not trigger when enemy has sheer force", async () => {
|
||||
game.override.enemyAbility(Abilities.SHEER_FORCE).enemyMoveset(Moves.SLUDGE_BOMB).startingLevel(95);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.51;
|
||||
|
||||
game.move.select(Moves.ENDURE);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
confirmNoSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to post turn status damage", async () => {
|
||||
game.override.statusEffect(StatusEffect.POISON).enemyMoveset([Moves.SPLASH]);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.51;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to bad dreams", async () => {
|
||||
game.override.statusEffect(StatusEffect.SLEEP).enemyAbility(Abilities.BAD_DREAMS);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.52;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to leech seed", async () => {
|
||||
game.override.enemyMoveset([Moves.LEECH_SEED]);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.52;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to curse damage", async () => {
|
||||
game.override.enemySpecies(Species.DUSKNOIR).enemyMoveset([Moves.CURSE]);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.52;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to salt cure damage", async () => {
|
||||
game.override.enemySpecies(Species.NACLI).enemyMoveset([Moves.SALT_CURE]).enemyLevel(1);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.7;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to damaging trap damage", async () => {
|
||||
game.override.enemySpecies(Species.MAGIKARP).enemyMoveset([Moves.WHIRLPOOL]).enemyLevel(1);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.55;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Magic Guard passive should not allow indirect damage to trigger Wimp Out", async () => {
|
||||
it("should not trigger on Magic Guard-prevented damage", async () => {
|
||||
game.scene.arena.addTag(ArenaTagType.STEALTH_ROCK, 1, Moves.STEALTH_ROCK, 0, ArenaTagSide.ENEMY);
|
||||
game.scene.arena.addTag(ArenaTagType.SPIKES, 1, Moves.SPIKES, 0, ArenaTagSide.ENEMY);
|
||||
game.override
|
||||
@ -331,6 +392,7 @@ describe("Abilities - Wimp Out", () => {
|
||||
.weather(WeatherType.HAIL)
|
||||
.statusEffect(StatusEffect.POISON);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.51;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
@ -341,6 +403,19 @@ describe("Abilities - Wimp Out", () => {
|
||||
expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(Species.WIMPOD);
|
||||
});
|
||||
|
||||
it("triggers status on the wimp out user before a new pokemon is switched in", async () => {
|
||||
game.override.enemyMoveset(Moves.SLUDGE_BOMB).startingLevel(80);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
vi.spyOn(allMoves[Moves.SLUDGE_BOMB], "chance", "get").mockReturnValue(100);
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(game.scene.getPlayerParty()[1].status?.effect).toEqual(StatusEffect.POISON);
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Wimp Out activating should not cancel a double battle", async () => {
|
||||
game.override.battleStyle("double").enemyAbility(Abilities.WIMP_OUT).enemyMoveset([Moves.SPLASH]).enemyLevel(1);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
@ -361,59 +436,7 @@ describe("Abilities - Wimp Out", () => {
|
||||
expect(enemySecPokemon.hp).toEqual(enemySecPokemon.getMaxHp());
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to aftermath", async () => {
|
||||
game.override
|
||||
.moveset([Moves.THUNDER_PUNCH])
|
||||
.enemySpecies(Species.MAGIKARP)
|
||||
.enemyAbility(Abilities.AFTERMATH)
|
||||
.enemyMoveset([Moves.SPLASH])
|
||||
.enemyLevel(1);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.51;
|
||||
|
||||
game.move.select(Moves.THUNDER_PUNCH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("Activates due to entry hazards", async () => {
|
||||
game.scene.arena.addTag(ArenaTagType.STEALTH_ROCK, 1, Moves.STEALTH_ROCK, 0, ArenaTagSide.ENEMY);
|
||||
game.scene.arena.addTag(ArenaTagType.SPIKES, 1, Moves.SPIKES, 0, ArenaTagSide.ENEMY);
|
||||
game.override.enemySpecies(Species.CENTISKORCH).enemyAbility(Abilities.WIMP_OUT).startingWave(4);
|
||||
await game.classicMode.startBattle([Species.TYRUNT]);
|
||||
|
||||
expect(game.phaseInterceptor.log).not.toContain("MovePhase");
|
||||
expect(game.phaseInterceptor.log).toContain("BattleEndPhase");
|
||||
});
|
||||
|
||||
it("Wimp Out will activate due to Nightmare", async () => {
|
||||
game.override.enemyMoveset([Moves.NIGHTMARE]).statusEffect(StatusEffect.SLEEP);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
game.scene.getPlayerPokemon()!.hp *= 0.65;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("triggers status on the wimp out user before a new pokemon is switched in", async () => {
|
||||
game.override.enemyMoveset(Moves.SLUDGE_BOMB).startingLevel(80);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
vi.spyOn(allMoves[Moves.SLUDGE_BOMB], "chance", "get").mockReturnValue(100);
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(game.scene.getPlayerParty()[1].status?.effect).toEqual(StatusEffect.POISON);
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("triggers after last hit of multi hit move", async () => {
|
||||
it("triggers after last hit of multi hit moves", async () => {
|
||||
game.override.enemyMoveset(Moves.BULLET_SEED).enemyAbility(Abilities.SKILL_LINK);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
||||
@ -444,6 +467,7 @@ describe("Abilities - Wimp Out", () => {
|
||||
expect(enemyPokemon.turnData.hitCount).toBe(2);
|
||||
confirmSwitch();
|
||||
});
|
||||
|
||||
it("triggers after last hit of Parental Bond", async () => {
|
||||
game.override.enemyMoveset(Moves.TACKLE).enemyAbility(Abilities.PARENTAL_BOND);
|
||||
await game.classicMode.startBattle([Species.WIMPOD, Species.TYRUNT]);
|
||||
|
@ -18,6 +18,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite
|
||||
const pokemonName = "PKM";
|
||||
const sourceText = "SOURCE";
|
||||
|
||||
// TODO: Make this a giant it.each
|
||||
describe("Status Effect Messages", () => {
|
||||
describe("NONE", () => {
|
||||
const statusEffect = StatusEffect.NONE;
|
||||
@ -390,7 +391,7 @@ describe("Status Effects", () => {
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(player.status?.effect).toBeUndefined();
|
||||
expect(player.status).toBeFalsy();
|
||||
expect(player.getLastXMoves(1)[0].result).toBe(MoveResult.SUCCESS);
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { allMoves } from "#app/data/moves/move";
|
||||
import { CommandPhase } from "#app/phases/command-phase";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
@ -34,13 +33,9 @@ describe("Moves - Rollout", () => {
|
||||
game.override.enemyMoveset(Moves.SPLASH);
|
||||
});
|
||||
|
||||
it("should double it's dmg on sequential uses but reset after 5", async () => {
|
||||
game.override.moveset([Moves.ROLLOUT]);
|
||||
vi.spyOn(allMoves[Moves.ROLLOUT], "accuracy", "get").mockReturnValue(100); //always hit
|
||||
|
||||
const variance = 5;
|
||||
const turns = 6;
|
||||
const dmgHistory: number[] = [];
|
||||
it("should double dmg on sequential uses but reset after 5", async () => {
|
||||
game.override.moveset(Moves.ROLLOUT);
|
||||
vi.spyOn(allMoves[Moves.ROLLOUT], "accuracy", "get").mockReturnValue(100); // always hit
|
||||
|
||||
await game.startBattle();
|
||||
|
||||
@ -49,14 +44,13 @@ describe("Moves - Rollout", () => {
|
||||
|
||||
const enemyPkm = game.scene.getEnemyParty()[0];
|
||||
vi.spyOn(enemyPkm, "stats", "get").mockReturnValue([500000, 1, 1, 1, 1, 1]); // HP, ATK, DEF, SPATK, SPDEF, SPD
|
||||
vi.spyOn(enemyPkm, "getHeldItems").mockReturnValue([]); //no berries
|
||||
|
||||
enemyPkm.hp = enemyPkm.getMaxHp();
|
||||
let previousHp = enemyPkm.hp;
|
||||
const dmgHistory: number[] = [];
|
||||
|
||||
for (let i = 0; i < turns; i++) {
|
||||
for (let i = 0; i < 6; i++) {
|
||||
game.move.select(Moves.ROLLOUT);
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
await game.toNextTurn();
|
||||
|
||||
dmgHistory.push(previousHp - enemyPkm.hp);
|
||||
previousHp = enemyPkm.hp;
|
||||
@ -64,16 +58,12 @@ describe("Moves - Rollout", () => {
|
||||
|
||||
const [turn1Dmg, turn2Dmg, turn3Dmg, turn4Dmg, turn5Dmg, turn6Dmg] = dmgHistory;
|
||||
|
||||
expect(turn2Dmg).toBeGreaterThanOrEqual(turn1Dmg * 2 - variance);
|
||||
expect(turn2Dmg).toBeLessThanOrEqual(turn1Dmg * 2 + variance);
|
||||
expect(turn3Dmg).toBeGreaterThanOrEqual(turn2Dmg * 2 - variance);
|
||||
expect(turn3Dmg).toBeLessThanOrEqual(turn2Dmg * 2 + variance);
|
||||
expect(turn4Dmg).toBeGreaterThanOrEqual(turn3Dmg * 2 - variance);
|
||||
expect(turn4Dmg).toBeLessThanOrEqual(turn3Dmg * 2 + variance);
|
||||
expect(turn5Dmg).toBeGreaterThanOrEqual(turn4Dmg * 2 - variance);
|
||||
expect(turn5Dmg).toBeLessThanOrEqual(turn4Dmg * 2 + variance);
|
||||
// reset
|
||||
expect(turn6Dmg).toBeGreaterThanOrEqual(turn1Dmg - variance);
|
||||
expect(turn6Dmg).toBeLessThanOrEqual(turn1Dmg + variance);
|
||||
// 2 sig figs precision is more than enough
|
||||
expect(turn2Dmg).toBeCloseTo(turn1Dmg * 2);
|
||||
expect(turn3Dmg).toBeCloseTo(turn2Dmg * 2);
|
||||
expect(turn4Dmg).toBeCloseTo(turn3Dmg * 2);
|
||||
expect(turn5Dmg).toBeCloseTo(turn4Dmg * 2);
|
||||
// reset on turn 6
|
||||
expect(turn6Dmg).toBeCloseTo(turn1Dmg);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user