mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-07 07:59:26 +02:00
Compare commits
18 Commits
a40087e2fc
...
1a907c22bd
Author | SHA1 | Date | |
---|---|---|---|
|
1a907c22bd | ||
|
83180002df | ||
|
1633df75c4 | ||
|
3b36ab17e4 | ||
|
375587213e | ||
|
8da02bad50 | ||
|
5bfcb1d379 | ||
|
40443d2afa | ||
|
800b8c9905 | ||
|
8a2b888971 | ||
|
0bc78cb715 | ||
|
e8ab79ebed | ||
|
491df80b66 | ||
|
5ed9e152ab | ||
|
acb1f4184b | ||
|
957a3e5c24 | ||
|
1f5e089818 | ||
|
97ddcb711b |
@ -19,7 +19,6 @@
|
||||
// and having to verify whether each individual file is ignored
|
||||
"includes": [
|
||||
"**",
|
||||
"!**/*.d.ts",
|
||||
"!**/dist/**/*",
|
||||
"!**/build/**/*",
|
||||
"!**/coverage/**/*",
|
||||
@ -180,7 +179,7 @@
|
||||
// Overrides to prevent unused import removal inside `overrides.ts` and enums files (for TSDoc linkcodes),
|
||||
// as well as in all TS files in `scripts/` (which are assumed to be boilerplate templates).
|
||||
{
|
||||
"includes": ["**/src/overrides.ts", "**/src/enums/**/*", "**/scripts/**/*.ts"],
|
||||
"includes": ["**/src/overrides.ts", "**/src/enums/**/*", "**/scripts/**/*.ts", "**/*.d.ts"],
|
||||
"linter": {
|
||||
"rules": {
|
||||
"correctness": {
|
||||
|
10
global.d.ts
vendored
10
global.d.ts
vendored
@ -1,7 +1,6 @@
|
||||
import type { AnyFn } from "#types/type-helpers";
|
||||
import type { SetupServerApi } from "msw/node";
|
||||
|
||||
export {};
|
||||
|
||||
declare global {
|
||||
/**
|
||||
* Only used in testing.
|
||||
@ -11,4 +10,11 @@ declare global {
|
||||
* To set up your own server in a test see `game-data.test.ts`
|
||||
*/
|
||||
var server: SetupServerApi;
|
||||
|
||||
// Overloads for `Function.apply` and `Function.call` to add type safety on matching argument types
|
||||
interface Function {
|
||||
apply<T extends AnyFn>(this: T, thisArg: ThisParameterType<T>, argArray: Parameters<T>): ReturnType<T>;
|
||||
|
||||
call<T extends AnyFn>(this: T, thisArg: ThisParameterType<T>, ...argArray: Parameters<T>): ReturnType<T>;
|
||||
}
|
||||
}
|
||||
|
@ -15,3 +15,10 @@ export interface AccountRegisterRequest {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface AccountChangePwRequest {
|
||||
password: string;
|
||||
}
|
||||
export interface AccountChangePwResponse {
|
||||
success: boolean;
|
||||
}
|
||||
|
@ -94,3 +94,12 @@ export type AbstractConstructor<T> = abstract new (...args: any[]) => T;
|
||||
export type CoerceNullPropertiesToUndefined<T extends object> = {
|
||||
[K in keyof T]: null extends T[K] ? Exclude<T[K], null> | undefined : T[K];
|
||||
};
|
||||
|
||||
/**
|
||||
* Type helper to mark all properties in `T` as optional, while still mandating that at least 1
|
||||
* of its properties be present.
|
||||
*
|
||||
* Distinct from {@linkcode Partial} as this requires at least 1 property to _not_ be undefined.
|
||||
* @typeParam T - The type to render partial
|
||||
*/
|
||||
export type AtLeastOne<T extends object> = Partial<T> & ObjectValues<{ [K in keyof T]: Pick<Required<T>, K> }>;
|
||||
|
@ -380,9 +380,21 @@ export class BattleScene extends SceneBase {
|
||||
};
|
||||
}
|
||||
|
||||
populateAnims();
|
||||
/**
|
||||
* These moves serve as fallback animations for other moves without loaded animations, and
|
||||
* must be loaded prior to game start.
|
||||
*/
|
||||
const defaultMoves = [MoveId.TACKLE, MoveId.TAIL_WHIP, MoveId.FOCUS_ENERGY, MoveId.STRUGGLE];
|
||||
|
||||
await this.initVariantData();
|
||||
await Promise.all([
|
||||
populateAnims(),
|
||||
this.initVariantData(),
|
||||
initCommonAnims().then(() => loadCommonAnimAssets(true)),
|
||||
Promise.all(defaultMoves.map(m => initMoveAnim(m))).then(() => loadMoveAnimAssets(defaultMoves, true)),
|
||||
this.initStarterColors(),
|
||||
]).catch(reason => {
|
||||
throw new Error(`Unexpected error during BattleScene preLoad!\nReason: ${reason}`);
|
||||
});
|
||||
}
|
||||
|
||||
create() {
|
||||
@ -584,8 +596,6 @@ export class BattleScene extends SceneBase {
|
||||
|
||||
this.party = [];
|
||||
|
||||
const loadPokemonAssets = [];
|
||||
|
||||
this.arenaPlayer = new ArenaBase(true);
|
||||
this.arenaPlayer.setName("arena-player");
|
||||
this.arenaPlayerTransition = new ArenaBase(true);
|
||||
@ -640,26 +650,14 @@ export class BattleScene extends SceneBase {
|
||||
|
||||
this.reset(false, false, true);
|
||||
|
||||
// Initialize UI-related aspects and then start the login phase.
|
||||
const ui = new UI();
|
||||
this.uiContainer.add(ui);
|
||||
|
||||
this.ui = ui;
|
||||
|
||||
ui.setup();
|
||||
|
||||
const defaultMoves = [MoveId.TACKLE, MoveId.TAIL_WHIP, MoveId.FOCUS_ENERGY, MoveId.STRUGGLE];
|
||||
|
||||
Promise.all([
|
||||
Promise.all(loadPokemonAssets),
|
||||
initCommonAnims().then(() => loadCommonAnimAssets(true)),
|
||||
Promise.all(
|
||||
[MoveId.TACKLE, MoveId.TAIL_WHIP, MoveId.FOCUS_ENERGY, MoveId.STRUGGLE].map(m => initMoveAnim(m)),
|
||||
).then(() => loadMoveAnimAssets(defaultMoves, true)),
|
||||
this.initStarterColors(),
|
||||
]).then(() => {
|
||||
this.phaseManager.toTitleScreen(true);
|
||||
this.phaseManager.shiftPhase();
|
||||
});
|
||||
this.phaseManager.toTitleScreen(true);
|
||||
this.phaseManager.shiftPhase();
|
||||
}
|
||||
|
||||
initSession(): void {
|
||||
@ -3530,6 +3528,7 @@ export class BattleScene extends SceneBase {
|
||||
this.gameMode.hasMysteryEncounters &&
|
||||
battleType === BattleType.WILD &&
|
||||
!this.gameMode.isBoss(waveIndex) &&
|
||||
waveIndex % 10 !== 1 &&
|
||||
waveIndex < highestMysteryEncounterWave &&
|
||||
waveIndex > lowestMysteryEncounterWave
|
||||
);
|
||||
|
@ -1768,7 +1768,7 @@ export interface AddSecondStrikeAbAttrParams extends Omit<AugmentMoveInteraction
|
||||
|
||||
/**
|
||||
* Class for abilities that add additional strikes to single-target moves.
|
||||
* Used by {@linkcode Moves.PARENTAL_BOND | Parental Bond}.
|
||||
* Used by {@linkcode MoveId.PARENTAL_BOND | Parental Bond}.
|
||||
*/
|
||||
export class AddSecondStrikeAbAttr extends PreAttackAbAttr {
|
||||
/**
|
||||
|
@ -1291,11 +1291,11 @@ export const biomePokemonPools: BiomePokemonPools = {
|
||||
[TimeOfDay.ALL]: [ { 1: [ SpeciesId.BELDUM ], 20: [ SpeciesId.METANG ], 45: [ SpeciesId.METAGROSS ] }, SpeciesId.SIGILYPH, { 1: [ SpeciesId.SOLOSIS ], 32: [ SpeciesId.DUOSION ], 41: [ SpeciesId.REUNICLUS ] } ]
|
||||
},
|
||||
[BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ SpeciesId.PORYGON ], 30: [ SpeciesId.PORYGON2 ] } ] },
|
||||
[BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ SpeciesId.COSMOG ], 23: [ SpeciesId.COSMOEM ] }, SpeciesId.CELESTEELA ] },
|
||||
[BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ SpeciesId.COSMOG ], 60: [ SpeciesId.COSMOEM ] }, SpeciesId.CELESTEELA ] },
|
||||
[BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [ SpeciesId.SOLROCK ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ SpeciesId.LUNATONE ], [TimeOfDay.ALL]: [ SpeciesId.CLEFABLE, SpeciesId.BRONZONG, SpeciesId.MUSHARNA, SpeciesId.REUNICLUS, SpeciesId.MINIOR ] },
|
||||
[BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.METAGROSS, SpeciesId.PORYGON_Z ] },
|
||||
[BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.CELESTEELA ] },
|
||||
[BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [ SpeciesId.SOLGALEO ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ SpeciesId.LUNALA ], [TimeOfDay.ALL]: [ SpeciesId.RAYQUAZA, SpeciesId.NECROZMA ] }
|
||||
[BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [ { 1: [ SpeciesId.COSMOG ], 60: [ SpeciesId.COSMOEM ], 80: [ SpeciesId.SOLGALEO ] } ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ { 1: [ SpeciesId.COSMOG ], 60: [ SpeciesId.COSMOEM ], 80: [ SpeciesId.LUNALA ] } ], [TimeOfDay.ALL]: [ SpeciesId.RAYQUAZA, SpeciesId.NECROZMA ] }
|
||||
},
|
||||
[BiomeId.CONSTRUCTION_SITE]: {
|
||||
[BiomePoolTier.COMMON]: {
|
||||
|
@ -1191,11 +1191,11 @@ export const pokemonEvolutions: PokemonEvolutions = {
|
||||
new SpeciesEvolution(SpeciesId.KOMMO_O, 45, null, null)
|
||||
],
|
||||
[SpeciesId.COSMOG]: [
|
||||
new SpeciesEvolution(SpeciesId.COSMOEM, 23, null, null)
|
||||
new SpeciesEvolution(SpeciesId.COSMOEM, 1, null, {key: EvoCondKey.FRIENDSHIP, value: 43}, SpeciesWildEvolutionDelay.VERY_LONG)
|
||||
],
|
||||
[SpeciesId.COSMOEM]: [
|
||||
new SpeciesEvolution(SpeciesId.SOLGALEO, 1, EvolutionItem.SUN_FLUTE, null, SpeciesWildEvolutionDelay.VERY_LONG),
|
||||
new SpeciesEvolution(SpeciesId.LUNALA, 1, EvolutionItem.MOON_FLUTE, null, SpeciesWildEvolutionDelay.VERY_LONG)
|
||||
new SpeciesEvolution(SpeciesId.SOLGALEO, 13, EvolutionItem.SUN_FLUTE, null, SpeciesWildEvolutionDelay.VERY_LONG),
|
||||
new SpeciesEvolution(SpeciesId.LUNALA, 13, EvolutionItem.MOON_FLUTE, null, SpeciesWildEvolutionDelay.VERY_LONG)
|
||||
],
|
||||
[SpeciesId.MELTAN]: [
|
||||
new SpeciesEvolution(SpeciesId.MELMETAL, 48, null, null)
|
||||
@ -1824,7 +1824,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
|
||||
new SpeciesEvolution(SpeciesId.ROSELIA, 1, null, [{key: EvoCondKey.FRIENDSHIP, value: 70}, {key: EvoCondKey.TIME, time: [TimeOfDay.DAWN, TimeOfDay.DAY]}], SpeciesWildEvolutionDelay.SHORT)
|
||||
],
|
||||
[SpeciesId.BUNEARY]: [
|
||||
new SpeciesEvolution(SpeciesId.LOPUNNY, 1, null, {key: EvoCondKey.FRIENDSHIP, value: 70}, SpeciesWildEvolutionDelay.MEDIUM)
|
||||
new SpeciesEvolution(SpeciesId.LOPUNNY, 1, null, {key: EvoCondKey.FRIENDSHIP, value: 50}, SpeciesWildEvolutionDelay.MEDIUM)
|
||||
],
|
||||
[SpeciesId.CHINGLING]: [
|
||||
new SpeciesEvolution(SpeciesId.CHIMECHO, 1, null, [{key: EvoCondKey.FRIENDSHIP, value: 90}, {key: EvoCondKey.TIME, time: [TimeOfDay.DUSK, TimeOfDay.NIGHT]}], SpeciesWildEvolutionDelay.MEDIUM)
|
||||
|
1784
src/data/balance/pokemon-species.ts
Normal file
1784
src/data/balance/pokemon-species.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -2055,7 +2055,7 @@ export class TruantTag extends AbilityBattlerTag {
|
||||
const lastMove = pokemon.getLastXMoves()[0];
|
||||
|
||||
if (!lastMove || lastMove.move === MoveId.NONE) {
|
||||
// Don't interrupt move if last move was `Moves.NONE` OR no prior move was found
|
||||
// Don't interrupt move if last move was `MoveId.NONE` OR no prior move was found
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2115,8 +2115,8 @@ export class SlowStartTag extends AbilityBattlerTag {
|
||||
|
||||
export class HighestStatBoostTag extends AbilityBattlerTag {
|
||||
public declare readonly tagType: HighestStatBoostTagType;
|
||||
public stat: Stat;
|
||||
public multiplier: number;
|
||||
public stat: EffectiveStat = Stat.ATK;
|
||||
public multiplier = 1.3;
|
||||
|
||||
constructor(tagType: HighestStatBoostTagType, ability: AbilityId) {
|
||||
super(tagType, ability, BattlerTagLapseType.CUSTOM, 1);
|
||||
@ -2128,28 +2128,28 @@ export class HighestStatBoostTag extends AbilityBattlerTag {
|
||||
*/
|
||||
public override loadTag<T extends this>(source: BaseBattlerTag & Pick<T, "tagType" | "stat" | "multiplier">): void {
|
||||
super.loadTag(source);
|
||||
this.stat = source.stat as Stat;
|
||||
this.stat = source.stat;
|
||||
this.multiplier = source.multiplier;
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
let highestStat: EffectiveStat;
|
||||
EFFECTIVE_STATS.map(s =>
|
||||
pokemon.getEffectiveStat(s, undefined, undefined, undefined, undefined, undefined, undefined, undefined, true),
|
||||
).reduce((highestValue: number, value: number, i: number) => {
|
||||
if (value > highestValue) {
|
||||
highestStat = EFFECTIVE_STATS[i];
|
||||
return value;
|
||||
}
|
||||
return highestValue;
|
||||
}, 0);
|
||||
const highestStat = EFFECTIVE_STATS.reduce(
|
||||
(curr: [EffectiveStat, number], stat: EffectiveStat) => {
|
||||
const value = pokemon.getEffectiveStat(stat, undefined, undefined, true, true, true, false, true, true);
|
||||
if (value > curr[1]) {
|
||||
curr[0] = stat;
|
||||
curr[1] = value;
|
||||
}
|
||||
return curr;
|
||||
},
|
||||
[Stat.ATK, 0],
|
||||
)[0];
|
||||
|
||||
highestStat = highestStat!; // tell TS compiler it's defined!
|
||||
this.stat = highestStat;
|
||||
|
||||
this.multiplier = this.stat === Stat.SPD ? 1.5 : 1.3;
|
||||
this.multiplier = highestStat === Stat.SPD ? 1.5 : 1.3;
|
||||
globalScene.phaseManager.queueMessage(
|
||||
i18next.t("battlerTags:highestStatBoostOnAdd", {
|
||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||
@ -2614,7 +2614,7 @@ export class IceFaceBlockDamageTag extends FormBlockDamageTag {
|
||||
*/
|
||||
export class CommandedTag extends SerializableBattlerTag {
|
||||
public override readonly tagType = BattlerTagType.COMMANDED;
|
||||
public readonly tatsugiriFormKey: string;
|
||||
public readonly tatsugiriFormKey: string = "curly";
|
||||
|
||||
constructor(sourceId: number) {
|
||||
super(BattlerTagType.COMMANDED, BattlerTagLapseType.CUSTOM, 0, MoveId.NONE, sourceId);
|
||||
@ -2668,7 +2668,7 @@ export class StockpilingTag extends SerializableBattlerTag {
|
||||
super(BattlerTagType.STOCKPILING, BattlerTagLapseType.CUSTOM, 1, sourceMove);
|
||||
}
|
||||
|
||||
private onStatStagesChanged: StatStageChangeCallback = (_, statsChanged, statChanges) => {
|
||||
private onStatStagesChanged(_: Pokemon | null, statsChanged: BattleStat[], statChanges: number[]) {
|
||||
const defChange = statChanges[statsChanged.indexOf(Stat.DEF)] ?? 0;
|
||||
const spDefChange = statChanges[statsChanged.indexOf(Stat.SPDEF)] ?? 0;
|
||||
|
||||
@ -2678,7 +2678,11 @@ export class StockpilingTag extends SerializableBattlerTag {
|
||||
if (spDefChange) {
|
||||
this.statChangeCounts[Stat.SPDEF]++;
|
||||
}
|
||||
};
|
||||
|
||||
// Removed during bundling; used to ensure this method's signature retains parity
|
||||
// with the `StatStageChangeCallback` type.
|
||||
this.onStatStagesChanged satisfies StatStageChangeCallback;
|
||||
}
|
||||
|
||||
public override loadTag(
|
||||
source: BaseBattlerTag & Pick<StockpilingTag, "tagType" | "stockpiledCount" | "statChangeCounts">,
|
||||
@ -2718,7 +2722,7 @@ export class StockpilingTag extends SerializableBattlerTag {
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
this.onStatStagesChanged,
|
||||
this.onStatStagesChanged.bind(this),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -3560,6 +3564,7 @@ export class GrudgeTag extends SerializableBattlerTag {
|
||||
* @param sourcePokemon - The source of the move that fainted the tag's bearer
|
||||
* @returns `false` if Grudge activates its effect or lapses
|
||||
*/
|
||||
// TODO: Confirm whether this should interact with copying moves
|
||||
override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType, sourcePokemon?: Pokemon): boolean {
|
||||
if (lapseType === BattlerTagLapseType.CUSTOM && sourcePokemon) {
|
||||
if (sourcePokemon.isActive() && pokemon.isOpponent(sourcePokemon)) {
|
||||
|
@ -4,15 +4,12 @@ import { defaultStarterSpecies } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { pokemonEvolutions } from "#balance/pokemon-evolutions";
|
||||
import { speciesStarterCosts } from "#balance/starters";
|
||||
import { getEggTierForSpecies } from "#data/egg";
|
||||
import { pokemonFormChanges } from "#data/pokemon-forms";
|
||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||
import { getPokemonSpeciesForm } from "#data/pokemon-species";
|
||||
import { BattleType } from "#enums/battle-type";
|
||||
import { ChallengeType } from "#enums/challenge-type";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { TypeColor, TypeShadow } from "#enums/color";
|
||||
import { EggTier } from "#enums/egg-type";
|
||||
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import type { MoveId } from "#enums/move-id";
|
||||
@ -26,9 +23,9 @@ import type { Pokemon } from "#field/pokemon";
|
||||
import { Trainer } from "#field/trainer";
|
||||
import { PokemonMove } from "#moves/pokemon-move";
|
||||
import type { DexAttrProps, GameData } from "#system/game-data";
|
||||
import { BooleanHolder, type NumberHolder, randSeedItem } from "#utils/common";
|
||||
import { BooleanHolder, isBetween, type NumberHolder, randSeedItem } from "#utils/common";
|
||||
import { deepCopy } from "#utils/data";
|
||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||
import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils";
|
||||
import { toCamelCase, toSnakeCase } from "#utils/strings";
|
||||
import i18next from "i18next";
|
||||
|
||||
@ -685,14 +682,11 @@ export class SingleTypeChallenge extends Challenge {
|
||||
*/
|
||||
export class FreshStartChallenge extends Challenge {
|
||||
constructor() {
|
||||
super(Challenges.FRESH_START, 3);
|
||||
super(Challenges.FRESH_START, 2);
|
||||
}
|
||||
|
||||
applyStarterChoice(pokemon: PokemonSpecies, valid: BooleanHolder): boolean {
|
||||
if (
|
||||
(this.value === 1 && !defaultStarterSpecies.includes(pokemon.speciesId)) ||
|
||||
(this.value === 2 && getEggTierForSpecies(pokemon) >= EggTier.EPIC)
|
||||
) {
|
||||
if (this.value === 1 && !defaultStarterSpecies.includes(pokemon.speciesId)) {
|
||||
valid.value = false;
|
||||
return true;
|
||||
}
|
||||
@ -708,12 +702,18 @@ export class FreshStartChallenge extends Challenge {
|
||||
pokemon.abilityIndex = pokemon.abilityIndex % 2; // Always base ability, if you set it to hidden it wraps to first ability
|
||||
pokemon.passive = false; // Passive isn't unlocked
|
||||
pokemon.nature = Nature.HARDY; // Neutral nature
|
||||
pokemon.moveset = pokemon.species
|
||||
let validMoves = pokemon.species
|
||||
.getLevelMoves()
|
||||
.filter(m => m[0] <= 5)
|
||||
.map(lm => lm[1])
|
||||
.slice(0, 4)
|
||||
.map(m => new PokemonMove(m)); // No egg moves
|
||||
.filter(m => isBetween(m[0], 1, 5))
|
||||
.map(lm => lm[1]);
|
||||
// Filter egg moves out of the moveset
|
||||
pokemon.moveset = pokemon.moveset.filter(pm => validMoves.includes(pm.moveId));
|
||||
if (pokemon.moveset.length < 4) {
|
||||
// If there's empty slots fill with remaining valid moves
|
||||
const existingMoveIds = pokemon.moveset.map(pm => pm.moveId);
|
||||
validMoves = validMoves.filter(m => !existingMoveIds.includes(m));
|
||||
pokemon.moveset = pokemon.moveset.concat(validMoves.map(m => new PokemonMove(m))).slice(0, 4);
|
||||
}
|
||||
pokemon.luck = 0; // No luck
|
||||
pokemon.shiny = false; // Not shiny
|
||||
pokemon.variant = 0; // Not shiny
|
||||
|
@ -2,7 +2,7 @@ import { pokerogueApi } from "#api/pokerogue-api";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { speciesStarterCosts } from "#balance/starters";
|
||||
import type { PokemonSpeciesForm } from "#data/pokemon-species";
|
||||
import { getPokemonSpeciesForm, PokemonSpecies } from "#data/pokemon-species";
|
||||
import { PokemonSpecies } from "#data/pokemon-species";
|
||||
import { BiomeId } from "#enums/biome-id";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import type { SpeciesId } from "#enums/species-id";
|
||||
@ -10,7 +10,7 @@ import { PlayerPokemon } from "#field/pokemon";
|
||||
import type { Starter } from "#ui/starter-select-ui-handler";
|
||||
import { randSeedGauss, randSeedInt, randSeedItem } from "#utils/common";
|
||||
import { getEnumValues } from "#utils/enums";
|
||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||
import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils";
|
||||
|
||||
export interface DailyRunConfig {
|
||||
seed: number;
|
||||
|
@ -256,7 +256,7 @@ export const noAbilityTypeOverrideMoves: ReadonlySet<MoveId> = new Set([
|
||||
MoveId.HIDDEN_POWER,
|
||||
]);
|
||||
|
||||
/** Set of all moves that cannot be copied by {@linkcode Moves.SKETCH}. */
|
||||
/** Set of all moves that cannot be copied by {@linkcode MoveId.SKETCH}. */
|
||||
export const invalidSketchMoves: ReadonlySet<MoveId> = new Set([
|
||||
MoveId.NONE,
|
||||
MoveId.CHATTER,
|
||||
@ -270,7 +270,7 @@ export const invalidSketchMoves: ReadonlySet<MoveId> = new Set([
|
||||
MoveId.BREAKNECK_BLITZ__SPECIAL,
|
||||
]);
|
||||
|
||||
/** Set of all moves that cannot be locked into by {@linkcode Moves.ENCORE}. */
|
||||
/** Set of all moves that cannot be locked into by {@linkcode MoveId.ENCORE}. */
|
||||
export const invalidEncoreMoves: ReadonlySet<MoveId> = new Set([
|
||||
MoveId.MIMIC,
|
||||
MoveId.MIRROR_MOVE,
|
||||
|
@ -2587,7 +2587,7 @@ export class PsychoShiftEffectAttr extends MoveEffectAttr {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the effect of {@linkcode Moves.PSYCHO_SHIFT} to its target.
|
||||
* Applies the effect of {@linkcode MoveId.PSYCHO_SHIFT} to its target.
|
||||
* Psycho Shift takes the user's status effect and passes it onto the target.
|
||||
* The user is then healed after the move has been successfully executed.
|
||||
* @param user - The {@linkcode Pokemon} using the move
|
||||
@ -2927,7 +2927,7 @@ export class HealStatusEffectAttr extends MoveEffectAttr {
|
||||
|
||||
/**
|
||||
* Attribute to add the {@linkcode BattlerTagType.BYPASS_SLEEP | BYPASS_SLEEP Battler Tag} for 1 turn to the user before move use.
|
||||
* Used by {@linkcode Moves.SNORE} and {@linkcode Moves.SLEEP_TALK}.
|
||||
* Used by {@linkcode MoveId.SNORE} and {@linkcode MoveId.SLEEP_TALK}.
|
||||
*/
|
||||
// TODO: Should this use a battler tag?
|
||||
// TODO: Give this `userSleptOrComatoseCondition` by default
|
||||
@ -5912,20 +5912,21 @@ export class ProtectAttr extends AddBattlerTagAttr {
|
||||
getCondition(): MoveConditionFunc {
|
||||
return ((user, target, move): boolean => {
|
||||
let timesUsed = 0;
|
||||
const moveHistory = user.getLastXMoves();
|
||||
let turnMove: TurnMove | undefined;
|
||||
|
||||
while (moveHistory.length) {
|
||||
turnMove = moveHistory.shift();
|
||||
if (!allMoves[turnMove?.move ?? MoveId.NONE].hasAttr("ProtectAttr") || turnMove?.result !== MoveResult.SUCCESS) {
|
||||
for (const turnMove of user.getLastXMoves(-1).slice()) {
|
||||
if (
|
||||
// Quick & Wide guard increment the Protect counter without using it for fail chance
|
||||
!(allMoves[turnMove.move].hasAttr("ProtectAttr") ||
|
||||
[MoveId.QUICK_GUARD, MoveId.WIDE_GUARD].includes(turnMove.move)) ||
|
||||
turnMove.result !== MoveResult.SUCCESS
|
||||
) {
|
||||
break;
|
||||
}
|
||||
timesUsed++;
|
||||
|
||||
timesUsed++
|
||||
}
|
||||
if (timesUsed) {
|
||||
return !user.randBattleSeedInt(Math.pow(3, timesUsed));
|
||||
}
|
||||
return true;
|
||||
|
||||
return timesUsed === 0 || user.randBattleSeedInt(Math.pow(3, timesUsed)) === 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -7139,7 +7140,7 @@ export class CopyMoveAttr extends CallMoveAttr {
|
||||
/**
|
||||
* Attribute used for moves that cause the target to repeat their last used move.
|
||||
*
|
||||
* Used by {@linkcode Moves.INSTRUCT | Instruct}.
|
||||
* Used by {@linkcode MoveId.INSTRUCT | Instruct}.
|
||||
* @see [Instruct on Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Instruct_(move))
|
||||
*/
|
||||
export class RepeatMoveAttr extends MoveEffectAttr {
|
||||
@ -7402,7 +7403,7 @@ const targetMoveCopiableCondition: MoveConditionFunc = (user, target, move) => {
|
||||
|
||||
/**
|
||||
* Attribute to temporarily copy the last move in the target's moveset.
|
||||
* Used by {@linkcode Moves.MIMIC}.
|
||||
* Used by {@linkcode MoveId.MIMIC}.
|
||||
*/
|
||||
export class MovesetCopyMoveAttr extends OverrideMoveEffectAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
@ -7966,7 +7967,7 @@ export class VariableTargetAttr extends MoveAttr {
|
||||
/**
|
||||
* Attribute to cause the target to move immediately after the user.
|
||||
*
|
||||
* Used by {@linkcode Moves.AFTER_YOU}.
|
||||
* Used by {@linkcode MoveId.AFTER_YOU}.
|
||||
*/
|
||||
export class AfterYouAttr extends MoveEffectAttr {
|
||||
/**
|
||||
|
@ -59,7 +59,7 @@ export const TeleportingHijinksEncounter: MysteryEncounter = MysteryEncounterBui
|
||||
)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withSceneRequirement(new WaveModulusRequirement([1, 2, 3], 10)) // Must be in first 3 waves after boss wave
|
||||
.withSceneRequirement(new WaveModulusRequirement([2, 3, 4], 10)) // Must be in first 3 waves after boss wave
|
||||
.withSceneRequirement(new MoneyRequirement(0, MONEY_COST_MULTIPLIER)) // Must be able to pay teleport cost
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withCatchAllowed(true)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@ import { loadBattlerTag, SerializableBattlerTag } from "#data/battler-tags";
|
||||
import { allSpecies } from "#data/data-lists";
|
||||
import type { Gender } from "#data/gender";
|
||||
import { PokemonMove } from "#data/moves/pokemon-move";
|
||||
import { getPokemonSpeciesForm, type PokemonSpeciesForm } from "#data/pokemon-species";
|
||||
import type { PokemonSpeciesForm } from "#data/pokemon-species";
|
||||
import type { TypeDamageMultiplier } from "#data/type";
|
||||
import type { AbilityId } from "#enums/ability-id";
|
||||
import type { BerryType } from "#enums/berry-type";
|
||||
@ -16,6 +16,7 @@ import type { IllusionData } from "#types/illusion-data";
|
||||
import type { TurnMove } from "#types/turn-move";
|
||||
import type { CoerceNullPropertiesToUndefined } from "#types/type-helpers";
|
||||
import { isNullOrUndefined } from "#utils/common";
|
||||
import { getPokemonSpeciesForm } from "#utils/pokemon-utils";
|
||||
|
||||
/**
|
||||
* The type that {@linkcode PokemonSpeciesForm} is converted to when an object containing it serializes it.
|
||||
@ -161,6 +162,7 @@ export class PokemonSummonData {
|
||||
|
||||
if (key === "speciesForm" || key === "fusionSpeciesForm") {
|
||||
this[key] = deserializePokemonSpeciesForm(value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key === "illusion" && typeof value === "object") {
|
||||
@ -181,6 +183,7 @@ export class PokemonSummonData {
|
||||
}
|
||||
}
|
||||
this[key] = illusionData as IllusionData;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key === "moveset") {
|
||||
@ -250,7 +253,6 @@ export class PokemonTempSummonData {
|
||||
* Only currently used for positioning the battle cursor.
|
||||
*/
|
||||
turnCount = 1;
|
||||
|
||||
/**
|
||||
* The number of turns this pokemon has spent in the active position since the start of the wave
|
||||
* without switching out.
|
||||
|
@ -1244,12 +1244,58 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setHasDouble("Breeders")
|
||||
.setPartyTemplateFunc(() =>
|
||||
getWavePartyTemplate(
|
||||
trainerPartyTemplates.FOUR_WEAKER,
|
||||
trainerPartyTemplates.FIVE_WEAKER,
|
||||
trainerPartyTemplates.SIX_WEAKER,
|
||||
trainerPartyTemplates.FOUR_WEAK,
|
||||
trainerPartyTemplates.FIVE_WEAK,
|
||||
trainerPartyTemplates.SIX_WEAK,
|
||||
),
|
||||
)
|
||||
.setSpeciesFilter(s => s.baseTotal < 450),
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [
|
||||
SpeciesId.PICHU,
|
||||
SpeciesId.CLEFFA,
|
||||
SpeciesId.IGGLYBUFF,
|
||||
SpeciesId.TOGEPI,
|
||||
SpeciesId.TYROGUE,
|
||||
SpeciesId.SMOOCHUM,
|
||||
SpeciesId.AZURILL,
|
||||
SpeciesId.BUDEW,
|
||||
SpeciesId.CHINGLING,
|
||||
SpeciesId.BONSLY,
|
||||
SpeciesId.MIME_JR,
|
||||
SpeciesId.HAPPINY,
|
||||
SpeciesId.MANTYKE,
|
||||
SpeciesId.TOXEL,
|
||||
],
|
||||
[TrainerPoolTier.UNCOMMON]: [
|
||||
SpeciesId.DITTO,
|
||||
SpeciesId.ELEKID,
|
||||
SpeciesId.MAGBY,
|
||||
SpeciesId.WYNAUT,
|
||||
SpeciesId.MUNCHLAX,
|
||||
SpeciesId.RIOLU,
|
||||
SpeciesId.AUDINO,
|
||||
],
|
||||
[TrainerPoolTier.RARE]: [
|
||||
SpeciesId.ALOLA_RATTATA,
|
||||
SpeciesId.ALOLA_SANDSHREW,
|
||||
SpeciesId.ALOLA_VULPIX,
|
||||
SpeciesId.ALOLA_DIGLETT,
|
||||
SpeciesId.ALOLA_MEOWTH,
|
||||
SpeciesId.GALAR_PONYTA,
|
||||
],
|
||||
[TrainerPoolTier.SUPER_RARE]: [
|
||||
SpeciesId.ALOLA_GEODUDE,
|
||||
SpeciesId.ALOLA_GRIMER,
|
||||
SpeciesId.GALAR_MEOWTH,
|
||||
SpeciesId.GALAR_SLOWPOKE,
|
||||
SpeciesId.GALAR_FARFETCHD,
|
||||
SpeciesId.HISUI_GROWLITHE,
|
||||
SpeciesId.HISUI_VOLTORB,
|
||||
SpeciesId.HISUI_QWILFISH,
|
||||
SpeciesId.HISUI_SNEASEL,
|
||||
SpeciesId.HISUI_ZORUA,
|
||||
],
|
||||
}),
|
||||
[TrainerType.CLERK]: new TrainerConfig(++t)
|
||||
.setHasGenders("Clerk Female")
|
||||
.setHasDouble("Colleagues")
|
||||
|
@ -144,6 +144,7 @@ export const trainerPartyTemplates = {
|
||||
FIVE_WEAK_BALANCED: new TrainerPartyTemplate(5, PartyMemberStrength.WEAK, false, true),
|
||||
SIX_WEAKER: new TrainerPartyTemplate(6, PartyMemberStrength.WEAKER),
|
||||
SIX_WEAKER_SAME: new TrainerPartyTemplate(6, PartyMemberStrength.WEAKER, true),
|
||||
SIX_WEAK: new TrainerPartyTemplate(6, PartyMemberStrength.WEAK),
|
||||
SIX_WEAK_SAME: new TrainerPartyTemplate(6, PartyMemberStrength.WEAK, true),
|
||||
SIX_WEAK_BALANCED: new TrainerPartyTemplate(6, PartyMemberStrength.WEAK, false, true),
|
||||
|
||||
|
@ -43,5 +43,6 @@ export enum UiMode {
|
||||
TEST_DIALOGUE,
|
||||
AUTO_COMPLETE,
|
||||
ADMIN,
|
||||
MYSTERY_ENCOUNTER
|
||||
MYSTERY_ENCOUNTER,
|
||||
CHANGE_PASSWORD_FORM,
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ import {
|
||||
} from "#data/pokemon-data";
|
||||
import type { SpeciesFormChange } from "#data/pokemon-forms";
|
||||
import type { PokemonSpeciesForm } from "#data/pokemon-species";
|
||||
import { getFusedSpeciesName, getPokemonSpeciesForm, PokemonSpecies } from "#data/pokemon-species";
|
||||
import { PokemonSpecies } from "#data/pokemon-species";
|
||||
import { getRandomStatus, getStatusEffectOverlapText, Status } from "#data/status-effect";
|
||||
import { getTerrainBlockMessage, TerrainType } from "#data/terrain";
|
||||
import type { TypeDamageMultiplier } from "#data/type";
|
||||
@ -168,7 +168,7 @@ import {
|
||||
toDmgValue,
|
||||
} from "#utils/common";
|
||||
import { getEnumValues } from "#utils/enums";
|
||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||
import { getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils";
|
||||
import { argbFromRgba, QuantizerCelebi, rgbaFromArgb } from "@material/material-color-utilities";
|
||||
import i18next from "i18next";
|
||||
import Phaser from "phaser";
|
||||
@ -725,7 +725,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
/**
|
||||
* Load all assets needed for this Pokemon's use in battle
|
||||
* @param ignoreOverride - Whether to ignore overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `true`
|
||||
* @param ignoreOverride - Whether to ignore overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `true`
|
||||
* @param useIllusion - Whether to consider this pokemon's active illusion; default `false`
|
||||
* @returns A promise that resolves once all the corresponding assets have been loaded.
|
||||
*/
|
||||
@ -1032,7 +1032,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
/**
|
||||
* Return this Pokemon's {@linkcode PokemonSpeciesForm | SpeciesForm}.
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `false`
|
||||
* and overrides `useIllusion`.
|
||||
* @param useIllusion - Whether to consider this Pokemon's illusion if present; default `false`.
|
||||
* @returns This Pokemon's {@linkcode PokemonSpeciesForm}.
|
||||
@ -1088,7 +1088,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
/**
|
||||
* Return the {@linkcode PokemonSpeciesForm | SpeciesForm} of this Pokemon's fusion counterpart.
|
||||
* @param ignoreOverride - Whether to ignore species overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param ignoreOverride - Whether to ignore species overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `false`
|
||||
* @param useIllusion - Whether to consider the species of this Pokemon's illusion; default `false`
|
||||
* @returns The {@linkcode PokemonSpeciesForm} of this Pokemon's fusion counterpart.
|
||||
*/
|
||||
@ -1659,7 +1659,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
/**
|
||||
* Return this Pokemon's {@linkcode Gender}.
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `false`
|
||||
* @param useIllusion - Whether to consider this pokemon's illusion if present; default `false`
|
||||
* @returns the {@linkcode Gender} of this {@linkcode Pokemon}.
|
||||
*/
|
||||
@ -1675,7 +1675,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
/**
|
||||
* Return this Pokemon's fusion's {@linkcode Gender}.
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `false`
|
||||
* @param useIllusion - Whether to consider this pokemon's illusion if present; default `false`
|
||||
* @returns The {@linkcode Gender} of this {@linkcode Pokemon}'s fusion.
|
||||
*/
|
||||
@ -1817,12 +1817,10 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
/**
|
||||
* Return all the {@linkcode PokemonMove}s that make up this Pokemon's moveset.
|
||||
* Takes into account player/enemy moveset overrides (which will also override PP count).
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `false`
|
||||
* @returns An array of {@linkcode PokemonMove}, as described above.
|
||||
*/
|
||||
getMoveset(ignoreOverride = false): PokemonMove[] {
|
||||
const ret = !ignoreOverride && this.summonData.moveset ? this.summonData.moveset : this.moveset;
|
||||
|
||||
// Overrides moveset based on arrays specified in overrides.ts
|
||||
let overrideArray: MoveId | Array<MoveId> = this.isPlayer()
|
||||
? Overrides.MOVESET_OVERRIDE
|
||||
@ -1838,7 +1836,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
return !ignoreOverride && this.summonData.moveset ? this.summonData.moveset : this.moveset;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1885,7 +1883,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* Evaluate and return this Pokemon's typing.
|
||||
* @param includeTeraType - Whether to use this Pokemon's tera type if Terastallized; default `false`
|
||||
* @param forDefend - Whether this Pokemon is currently receiving an attack; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `false`
|
||||
* @param useIllusion - Whether to consider this Pokemon's illusion if present; default `false`
|
||||
* @returns An array of {@linkcode PokemonType}s corresponding to this Pokemon's typing (real or percieved).
|
||||
*/
|
||||
@ -2008,7 +2006,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* @param type - The {@linkcode PokemonType} to check
|
||||
* @param includeTeraType - Whether to use this Pokemon's tera type if Terastallized; default `true`
|
||||
* @param forDefend - Whether this Pokemon is currently receiving an attack; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `false`
|
||||
* @returns Whether this Pokemon is of the specified type.
|
||||
*/
|
||||
public isOfType(type: PokemonType, includeTeraType = true, forDefend = false, ignoreOverride = false): boolean {
|
||||
@ -2021,7 +2019,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* Should rarely be called directly in favor of {@linkcode hasAbility} or {@linkcode hasAbilityWithAttr},
|
||||
* both of which check both ability slots and account for suppression.
|
||||
* @see {@linkcode hasAbility} and {@linkcode hasAbilityWithAttr} are the intended ways to check abilities in most cases
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `false`
|
||||
* @returns The non-passive {@linkcode Ability} of this Pokemon.
|
||||
*/
|
||||
public getAbility(ignoreOverride = false): Ability {
|
||||
@ -2203,7 +2201,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* Accounts for all the various effects which can disable or modify abilities.
|
||||
* @param ability - The {@linkcode Abilities | Ability} to check for
|
||||
* @param canApply - Whether to check if the ability is currently active; default `true`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `false`
|
||||
* @returns Whether this {@linkcode Pokemon} has the given ability
|
||||
*/
|
||||
public hasAbility(ability: AbilityId, canApply = true, ignoreOverride = false): boolean {
|
||||
@ -2218,7 +2216,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* Accounts for all the various effects which can disable or modify abilities.
|
||||
* @param attrType - The {@linkcode AbAttr | attribute} to check for
|
||||
* @param canApply - Whether to check if the ability is currently active; default `true`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `false`
|
||||
* @returns Whether this Pokemon has an ability with the given {@linkcode AbAttr}.
|
||||
*/
|
||||
public hasAbilityWithAttr(attrType: AbAttrString, canApply = true, ignoreOverride = false): boolean {
|
||||
@ -4468,7 +4466,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* Return the most recently executed {@linkcode TurnMove} this {@linkcode Pokemon} has used that is:
|
||||
* - Not {@linkcode MoveId.NONE}
|
||||
* - Non-virtual ({@linkcode MoveUseMode | useMode} < {@linkcode MoveUseMode.INDIRECT})
|
||||
* @param ignoreStruggle - Whether to additionally ignore {@linkcode Moves.STRUGGLE}; default `false`
|
||||
* @param ignoreStruggle - Whether to additionally ignore {@linkcode MoveId.STRUGGLE}; default `false`
|
||||
* @param ignoreFollowUp - Whether to ignore moves with a use type of {@linkcode MoveUseMode.FOLLOW_UP}
|
||||
* (e.g. ones called by Copycat/Mirror Move); default `true`.
|
||||
* @returns The last move this Pokemon has used satisfying the aforementioned conditions,
|
||||
@ -5096,6 +5094,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
*/
|
||||
resetWaveData(): void {
|
||||
this.waveData = new PokemonWaveData();
|
||||
this.tempSummonData.waveTurnCount = 1;
|
||||
}
|
||||
|
||||
resetTera(): void {
|
||||
|
@ -2,10 +2,10 @@ import { initAbilities } from "#abilities/ability";
|
||||
import { initBiomes } from "#balance/biomes";
|
||||
import { initEggMoves } from "#balance/egg-moves";
|
||||
import { initPokemonPrevolutions, initPokemonStarters } from "#balance/pokemon-evolutions";
|
||||
import { initSpecies } from "#balance/pokemon-species";
|
||||
import { initChallenges } from "#data/challenge";
|
||||
import { initTrainerTypeDialogue } from "#data/dialogue";
|
||||
import { initPokemonForms } from "#data/pokemon-forms";
|
||||
import { initSpecies } from "#data/pokemon-species";
|
||||
import { initModifierPools } from "#modifiers/init-modifier-pools";
|
||||
import { initModifierTypes } from "#modifiers/modifier-type";
|
||||
import { initMoves } from "#moves/move";
|
||||
|
@ -58,12 +58,6 @@ export class BattleEndPhase extends BattlePhase {
|
||||
globalScene.phaseManager.unshiftNew("GameOverPhase", true);
|
||||
}
|
||||
|
||||
for (const pokemon of globalScene.getField()) {
|
||||
if (pokemon) {
|
||||
pokemon.tempSummonData.waveTurnCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (const pokemon of globalScene.getPokemonAllowedInBattle()) {
|
||||
applyAbAttrs("PostBattleAbAttr", { pokemon, victory: this.isVictory });
|
||||
}
|
||||
|
@ -649,7 +649,6 @@ export class MovePhase extends BattlePhase {
|
||||
* Displays the move's usage text to the player as applicable for the move being used.
|
||||
*/
|
||||
public showMoveText(): void {
|
||||
// No text for Moves.NONE, recharging/2-turn moves or interrupted moves
|
||||
if (
|
||||
this.move.moveId === MoveId.NONE ||
|
||||
this.pokemon.getTag(BattlerTagType.RECHARGING) ||
|
||||
@ -658,7 +657,6 @@ export class MovePhase extends BattlePhase {
|
||||
return;
|
||||
}
|
||||
|
||||
// Play message for magic coat reflection
|
||||
// TODO: This should be done by the move...
|
||||
globalScene.phaseManager.queueMessage(
|
||||
i18next.t(isReflected(this.useMode) ? "battle:magicCoatActivated" : "battle:useMove", {
|
||||
|
@ -99,8 +99,12 @@ export class SelectStarterPhase extends Phase {
|
||||
starterPokemon.generateFusionSpecies(true);
|
||||
}
|
||||
starterPokemon.setVisible(false);
|
||||
applyChallenges(ChallengeType.STARTER_MODIFY, starterPokemon);
|
||||
const chalApplied = applyChallenges(ChallengeType.STARTER_MODIFY, starterPokemon);
|
||||
party.push(starterPokemon);
|
||||
if (chalApplied) {
|
||||
// If any challenges modified the starter, it should update
|
||||
loadPokemonAssets.push(starterPokemon.updateInfo());
|
||||
}
|
||||
loadPokemonAssets.push(starterPokemon.loadAssets());
|
||||
});
|
||||
overrideModifiers();
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { ApiBase } from "#api/api-base";
|
||||
import { SESSION_ID_COOKIE_NAME } from "#app/constants";
|
||||
import type {
|
||||
AccountChangePwRequest,
|
||||
AccountInfoResponse,
|
||||
AccountLoginRequest,
|
||||
AccountLoginResponse,
|
||||
@ -95,4 +96,19 @@ export class PokerogueAccountApi extends ApiBase {
|
||||
|
||||
removeCookie(SESSION_ID_COOKIE_NAME); // we are always clearing the cookie.
|
||||
}
|
||||
|
||||
public async changePassword(changePwData: AccountChangePwRequest) {
|
||||
try {
|
||||
const response = await this.doPost("/account/changepw", changePwData, "form-urlencoded");
|
||||
if (response.ok) {
|
||||
return null;
|
||||
}
|
||||
console.warn("Change password failed!", response.status, response.statusText);
|
||||
return response.text();
|
||||
} catch (err) {
|
||||
console.warn("Change password failed!", err);
|
||||
}
|
||||
|
||||
return "Unknown error!";
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { Gender } from "#data/gender";
|
||||
import { CustomPokemonData, PokemonBattleData, PokemonSummonData } from "#data/pokemon-data";
|
||||
import { getPokemonSpeciesForm } from "#data/pokemon-species";
|
||||
import { Status } from "#data/status-effect";
|
||||
import { BattleType } from "#enums/battle-type";
|
||||
import type { BiomeId } from "#enums/biome-id";
|
||||
@ -14,7 +13,7 @@ import { TrainerSlot } from "#enums/trainer-slot";
|
||||
import { EnemyPokemon, Pokemon } from "#field/pokemon";
|
||||
import { PokemonMove } from "#moves/pokemon-move";
|
||||
import type { Variant } from "#sprites/variant";
|
||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||
import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils";
|
||||
|
||||
export class PokemonData {
|
||||
public id: number;
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonSpeciesForm } from "#data/pokemon-species";
|
||||
import { DexAttr } from "#enums/dex-attr";
|
||||
import type { SessionSaveData, SystemSaveData } from "#system/game-data";
|
||||
import type { SessionSaveMigrator } from "#types/session-save-migrator";
|
||||
import type { SystemSaveMigrator } from "#types/system-save-migrator";
|
||||
import { isNullOrUndefined } from "#utils/common";
|
||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||
import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils";
|
||||
|
||||
/**
|
||||
* If a starter is caught, but the only forms registered as caught are not starterSelectable,
|
||||
|
1
src/typings/i18next.d.ts
vendored
1
src/typings/i18next.d.ts
vendored
@ -3,6 +3,7 @@ import type { TOptions } from "i18next";
|
||||
// Module declared to make referencing keys in the localization files type-safe.
|
||||
declare module "i18next" {
|
||||
interface TFunction {
|
||||
// biome-ignore lint/style/useShorthandFunctionType: This needs to be an interface due to interface merging
|
||||
(key: string | string[], options?: TOptions & Record<string, unknown>): string;
|
||||
}
|
||||
}
|
||||
|
42
src/typings/phaser/index.d.ts
vendored
42
src/typings/phaser/index.d.ts
vendored
@ -1,7 +1,7 @@
|
||||
import "phaser";
|
||||
|
||||
declare module "phaser" {
|
||||
namespace GameObjects {
|
||||
namespace GameObjects {
|
||||
interface GameObject {
|
||||
width: number;
|
||||
|
||||
@ -16,45 +16,45 @@ declare module "phaser" {
|
||||
y: number;
|
||||
}
|
||||
|
||||
interface Container {
|
||||
interface Container {
|
||||
/**
|
||||
* Sets this object's position relative to another object with a given offset
|
||||
*/
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
interface Sprite {
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
interface Sprite {
|
||||
/**
|
||||
* Sets this object's position relative to another object with a given offset
|
||||
*/
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
interface Image {
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
interface Image {
|
||||
/**
|
||||
* Sets this object's position relative to another object with a given offset
|
||||
*/
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
interface NineSlice {
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
interface NineSlice {
|
||||
/**
|
||||
* Sets this object's position relative to another object with a given offset
|
||||
*/
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
interface Text {
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
interface Text {
|
||||
/**
|
||||
* Sets this object's position relative to another object with a given offset
|
||||
*/
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
interface Rectangle {
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
interface Rectangle {
|
||||
/**
|
||||
* Sets this object's position relative to another object with a given offset
|
||||
*/
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
}
|
||||
setPositionRelative(guideObject: any, x: number, y: number): this;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Input {
|
||||
namespace Input {
|
||||
namespace Gamepad {
|
||||
interface GamepadPlugin {
|
||||
/**
|
||||
|
124
src/ui/change-password-form-ui-handler.ts
Normal file
124
src/ui/change-password-form-ui-handler.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
import type { InputFieldConfig } from "#ui/form-modal-ui-handler";
|
||||
import { FormModalUiHandler } from "#ui/form-modal-ui-handler";
|
||||
import type { ModalConfig } from "#ui/modal-ui-handler";
|
||||
import i18next from "i18next";
|
||||
|
||||
export class ChangePasswordFormUiHandler extends FormModalUiHandler {
|
||||
private readonly ERR_PASSWORD: string = "invalid password";
|
||||
private readonly ERR_ACCOUNT_EXIST: string = "account doesn't exist";
|
||||
private readonly ERR_PASSWORD_MISMATCH: string = "password doesn't match";
|
||||
|
||||
constructor(mode: UiMode | null = null) {
|
||||
super(mode);
|
||||
}
|
||||
|
||||
setup(): void {
|
||||
super.setup();
|
||||
}
|
||||
|
||||
override getModalTitle(_config?: ModalConfig): string {
|
||||
return i18next.t("menu:changePassword");
|
||||
}
|
||||
|
||||
override getWidth(_config?: ModalConfig): number {
|
||||
return 160;
|
||||
}
|
||||
|
||||
override getMargin(_config?: ModalConfig): [number, number, number, number] {
|
||||
return [0, 0, 48, 0];
|
||||
}
|
||||
|
||||
override getButtonLabels(_config?: ModalConfig): string[] {
|
||||
return [i18next.t("settings:buttonSubmit"), i18next.t("menu:cancel")];
|
||||
}
|
||||
|
||||
override getReadableErrorMessage(error: string): string {
|
||||
const colonIndex = error?.indexOf(":");
|
||||
if (colonIndex > 0) {
|
||||
error = error.slice(0, colonIndex);
|
||||
}
|
||||
switch (error) {
|
||||
case this.ERR_PASSWORD:
|
||||
return i18next.t("menu:invalidRegisterPassword");
|
||||
case this.ERR_ACCOUNT_EXIST:
|
||||
return i18next.t("menu:accountNonExistent");
|
||||
case this.ERR_PASSWORD_MISMATCH:
|
||||
return i18next.t("menu:passwordNotMatchingConfirmPassword");
|
||||
}
|
||||
|
||||
return super.getReadableErrorMessage(error);
|
||||
}
|
||||
|
||||
override getInputFieldConfigs(): InputFieldConfig[] {
|
||||
const inputFieldConfigs: InputFieldConfig[] = [];
|
||||
inputFieldConfigs.push({
|
||||
label: i18next.t("menu:password"),
|
||||
isPassword: true,
|
||||
});
|
||||
inputFieldConfigs.push({
|
||||
label: i18next.t("menu:confirmPassword"),
|
||||
isPassword: true,
|
||||
});
|
||||
return inputFieldConfigs;
|
||||
}
|
||||
|
||||
override show(args: [ModalConfig, ...any]): boolean {
|
||||
if (super.show(args)) {
|
||||
const config = args[0];
|
||||
const originalSubmitAction = this.submitAction;
|
||||
this.submitAction = () => {
|
||||
if (globalScene.tweens.getTweensOf(this.modalContainer).length === 0) {
|
||||
// Prevent overlapping overrides on action modification
|
||||
this.submitAction = originalSubmitAction;
|
||||
this.sanitizeInputs();
|
||||
globalScene.ui.setMode(UiMode.LOADING, { buttonActions: [] });
|
||||
const onFail = (error: string | null) => {
|
||||
globalScene.ui.setMode(UiMode.CHANGE_PASSWORD_FORM, Object.assign(config, { errorMessage: error?.trim() }));
|
||||
globalScene.ui.playError();
|
||||
};
|
||||
const [passwordInput, confirmPasswordInput] = this.inputs;
|
||||
if (!passwordInput?.text) {
|
||||
return onFail(this.getReadableErrorMessage("invalid password"));
|
||||
}
|
||||
if (passwordInput.text !== confirmPasswordInput.text) {
|
||||
return onFail(this.ERR_PASSWORD_MISMATCH);
|
||||
}
|
||||
|
||||
pokerogueApi.account.changePassword({ password: passwordInput.text }).then(error => {
|
||||
if (!error && originalSubmitAction) {
|
||||
globalScene.ui.playSelect();
|
||||
originalSubmitAction();
|
||||
// Only clear inputs if the action was successful
|
||||
for (const input of this.inputs) {
|
||||
input.setText("");
|
||||
}
|
||||
} else {
|
||||
onFail(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
// Upon pressing cancel, the inputs should be cleared
|
||||
const originalCancelAction = this.cancelAction;
|
||||
this.cancelAction = () => {
|
||||
globalScene.ui.playSelect();
|
||||
for (const input of this.inputs) {
|
||||
input.setText("");
|
||||
}
|
||||
originalCancelAction?.();
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
override clear() {
|
||||
super.clear();
|
||||
this.setMouseCursorStyle("default"); //reset cursor
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ export abstract class FormModalUiHandler extends ModalUiHandler {
|
||||
protected inputs: InputText[];
|
||||
protected errorMessage: Phaser.GameObjects.Text;
|
||||
protected submitAction: Function | null;
|
||||
protected cancelAction: (() => void) | null;
|
||||
protected tween: Phaser.Tweens.Tween;
|
||||
protected formLabels: Phaser.GameObjects.Text[];
|
||||
|
||||
@ -126,22 +127,37 @@ export abstract class FormModalUiHandler extends ModalUiHandler {
|
||||
});
|
||||
}
|
||||
|
||||
show(args: any[]): boolean {
|
||||
override show(args: any[]): boolean {
|
||||
if (super.show(args)) {
|
||||
this.inputContainers.map(ic => ic.setVisible(true));
|
||||
|
||||
const config = args[0] as FormModalConfig;
|
||||
|
||||
this.submitAction = config.buttonActions.length ? config.buttonActions[0] : null;
|
||||
this.cancelAction = config.buttonActions[1] ?? null;
|
||||
|
||||
if (this.buttonBgs.length) {
|
||||
this.buttonBgs[0].off("pointerdown");
|
||||
this.buttonBgs[0].on("pointerdown", () => {
|
||||
if (this.submitAction && globalScene.tweens.getTweensOf(this.modalContainer).length === 0) {
|
||||
this.submitAction();
|
||||
// #region: Override button pointerDown
|
||||
// Override the pointerDown event for the buttonBgs to call the `submitAction` and `cancelAction`
|
||||
// properties that we set above, allowing their behavior to change after this method terminates
|
||||
// Some subclasses use this to add behavior to the submit and cancel action
|
||||
|
||||
this.buttonBgs[0].off("pointerdown");
|
||||
this.buttonBgs[0].on("pointerdown", () => {
|
||||
if (this.submitAction && globalScene.tweens.getTweensOf(this.modalContainer).length === 0) {
|
||||
this.submitAction();
|
||||
}
|
||||
});
|
||||
const cancelBg = this.buttonBgs[1];
|
||||
if (cancelBg) {
|
||||
cancelBg.off("pointerdown");
|
||||
cancelBg.on("pointerdown", () => {
|
||||
// The seemingly redundant cancelAction check is intentionally left in as a defensive programming measure
|
||||
if (this.cancelAction && globalScene.tweens.getTweensOf(this.modalContainer).length === 0) {
|
||||
this.cancelAction();
|
||||
}
|
||||
});
|
||||
}
|
||||
//#endregion: Override pointerDown events
|
||||
|
||||
this.modalContainer.y += 24;
|
||||
this.modalContainer.setAlpha(0);
|
||||
|
@ -311,6 +311,17 @@ export class MenuUiHandler extends MessageUiHandler {
|
||||
},
|
||||
keepOpen: true,
|
||||
},
|
||||
{
|
||||
// Note: i18n key is under `menu`, not `menuUiHandler` to avoid duplication
|
||||
label: i18next.t("menu:changePassword"),
|
||||
handler: () => {
|
||||
ui.setOverlayMode(UiMode.CHANGE_PASSWORD_FORM, {
|
||||
buttonActions: [() => ui.revertMode(), () => ui.revertMode()],
|
||||
});
|
||||
return true;
|
||||
},
|
||||
keepOpen: true,
|
||||
},
|
||||
{
|
||||
label: i18next.t("menuUiHandler:consentPreferences"),
|
||||
handler: () => {
|
||||
|
@ -7,7 +7,7 @@ import { UiHandler } from "#ui/ui-handler";
|
||||
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
||||
|
||||
export interface ModalConfig {
|
||||
buttonActions: Function[];
|
||||
buttonActions: ((...args: any[]) => any)[];
|
||||
}
|
||||
|
||||
export abstract class ModalUiHandler extends UiHandler {
|
||||
|
@ -827,6 +827,11 @@ export class PartyUiHandler extends MessageUiHandler {
|
||||
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeItemTrigger, false, true);
|
||||
}
|
||||
|
||||
// This is processed before the filter result since releasing does not depend on status.
|
||||
if (option === PartyOption.RELEASE) {
|
||||
return this.processReleaseOption(pokemon);
|
||||
}
|
||||
|
||||
// If the pokemon is filtered out for this option, we cannot continue
|
||||
const filterResult = this.getFilterResult(option, pokemon);
|
||||
if (filterResult) {
|
||||
@ -850,10 +855,6 @@ export class PartyUiHandler extends MessageUiHandler {
|
||||
// PartyUiMode.POST_BATTLE_SWITCH (SEND_OUT)
|
||||
|
||||
// These are the options that need a callback
|
||||
if (option === PartyOption.RELEASE) {
|
||||
return this.processReleaseOption(pokemon);
|
||||
}
|
||||
|
||||
if (this.partyUiMode === PartyUiMode.SPLICE) {
|
||||
if (option === PartyOption.SPLICE) {
|
||||
(this.selectCallback as PartyModifierSpliceSelectCallback)(this.transferCursor, this.cursor);
|
||||
|
@ -25,7 +25,7 @@ import { getNatureName } from "#data/nature";
|
||||
import type { SpeciesFormChange } from "#data/pokemon-forms";
|
||||
import { pokemonFormChanges } from "#data/pokemon-forms";
|
||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||
import { getPokemonSpeciesForm, normalForm } from "#data/pokemon-species";
|
||||
import { normalForm } from "#data/pokemon-species";
|
||||
import { AbilityAttr } from "#enums/ability-attr";
|
||||
import type { AbilityId } from "#enums/ability-id";
|
||||
import { BiomeId } from "#enums/biome-id";
|
||||
@ -56,7 +56,7 @@ import { addBBCodeTextObject, addTextObject, getTextColor, getTextStyleOptions }
|
||||
import { addWindow } from "#ui/ui-theme";
|
||||
import { BooleanHolder, getLocalizedSpriteKey, isNullOrUndefined, padInt, rgbHexToRgba } from "#utils/common";
|
||||
import { getEnumValues } from "#utils/enums";
|
||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||
import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils";
|
||||
import { toTitleCase } from "#utils/strings";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
import i18next from "i18next";
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
import { speciesTmMoves } from "#balance/tms";
|
||||
import { allAbilities, allMoves, allSpecies } from "#data/data-lists";
|
||||
import type { PokemonForm, PokemonSpecies } from "#data/pokemon-species";
|
||||
import { getPokemonSpeciesForm, getPokerusStarters, normalForm } from "#data/pokemon-species";
|
||||
import { normalForm } from "#data/pokemon-species";
|
||||
import { AbilityAttr } from "#enums/ability-attr";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { BiomeId } from "#enums/biome-id";
|
||||
@ -46,6 +46,7 @@ import { addWindow } from "#ui/ui-theme";
|
||||
import { BooleanHolder, fixedInt, getLocalizedSpriteKey, padInt, randIntRange, rgbHexToRgba } from "#utils/common";
|
||||
import type { StarterPreferences } from "#utils/data";
|
||||
import { loadStarterPreferences } from "#utils/data";
|
||||
import { getPokemonSpeciesForm, getPokerusStarters } from "#utils/pokemon-utils";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
import i18next from "i18next";
|
||||
|
||||
|
@ -5,7 +5,6 @@ import { allMoves } from "#data/data-lists";
|
||||
import { getEggTierForSpecies } from "#data/egg";
|
||||
import type { EggHatchData } from "#data/egg-hatch-data";
|
||||
import { Gender } from "#data/gender";
|
||||
import { getPokemonSpeciesForm } from "#data/pokemon-species";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TextStyle } from "#enums/text-style";
|
||||
@ -13,6 +12,7 @@ import type { PlayerPokemon } from "#field/pokemon";
|
||||
import { PokemonInfoContainer } from "#ui/pokemon-info-container";
|
||||
import { addTextObject } from "#ui/text";
|
||||
import { padInt, rgbHexToRgba } from "#utils/common";
|
||||
import { getPokemonSpeciesForm } from "#utils/pokemon-utils";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
|
||||
/**
|
||||
|
@ -24,7 +24,6 @@ import { Gender, getGenderColor, getGenderSymbol } from "#data/gender";
|
||||
import { getNatureName } from "#data/nature";
|
||||
import { pokemonFormChanges } from "#data/pokemon-forms";
|
||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||
import { getPokemonSpeciesForm, getPokerusStarters } from "#data/pokemon-species";
|
||||
import { AbilityAttr } from "#enums/ability-attr";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { Button } from "#enums/buttons";
|
||||
@ -72,6 +71,7 @@ import {
|
||||
} from "#utils/common";
|
||||
import type { StarterPreferences } from "#utils/data";
|
||||
import { loadStarterPreferences, saveStarterPreferences } from "#utils/data";
|
||||
import { getPokemonSpeciesForm, getPokerusStarters } from "#utils/pokemon-utils";
|
||||
import { toTitleCase } from "#utils/strings";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
import i18next from "i18next";
|
||||
|
@ -13,6 +13,7 @@ import { BallUiHandler } from "#ui/ball-ui-handler";
|
||||
import { BattleMessageUiHandler } from "#ui/battle-message-ui-handler";
|
||||
import type { BgmBar } from "#ui/bgm-bar";
|
||||
import { GameChallengesUiHandler } from "#ui/challenges-select-ui-handler";
|
||||
import { ChangePasswordFormUiHandler } from "#ui/change-password-form-ui-handler";
|
||||
import { CommandUiHandler } from "#ui/command-ui-handler";
|
||||
import { ConfirmUiHandler } from "#ui/confirm-ui-handler";
|
||||
import { EggGachaUiHandler } from "#ui/egg-gacha-ui-handler";
|
||||
@ -102,6 +103,7 @@ const noTransitionModes = [
|
||||
UiMode.ADMIN,
|
||||
UiMode.MYSTERY_ENCOUNTER,
|
||||
UiMode.RUN_INFO,
|
||||
UiMode.CHANGE_PASSWORD_FORM,
|
||||
];
|
||||
|
||||
export class UI extends Phaser.GameObjects.Container {
|
||||
@ -172,6 +174,7 @@ export class UI extends Phaser.GameObjects.Container {
|
||||
new AutoCompleteUiHandler(),
|
||||
new AdminUiHandler(),
|
||||
new MysteryEncounterUiHandler(),
|
||||
new ChangePasswordFormUiHandler(),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { POKERUS_STARTER_COUNT, speciesStarterCosts } from "#balance/starters";
|
||||
import { allSpecies } from "#data/data-lists";
|
||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||
import type { PokemonSpecies, PokemonSpeciesForm } from "#data/pokemon-species";
|
||||
import type { SpeciesId } from "#enums/species-id";
|
||||
import { randSeedItem } from "./common";
|
||||
|
||||
/**
|
||||
* Gets the {@linkcode PokemonSpecies} object associated with the {@linkcode SpeciesId} enum given
|
||||
@ -19,3 +22,104 @@ export function getPokemonSpecies(species: SpeciesId | SpeciesId[]): PokemonSpec
|
||||
}
|
||||
return allSpecies[species - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the daily list of starters with Pokerus.
|
||||
* @returns A list of starters with Pokerus
|
||||
*/
|
||||
export function getPokerusStarters(): PokemonSpecies[] {
|
||||
const pokerusStarters: PokemonSpecies[] = [];
|
||||
const date = new Date();
|
||||
date.setUTCHours(0, 0, 0, 0);
|
||||
globalScene.executeWithSeedOffset(
|
||||
() => {
|
||||
while (pokerusStarters.length < POKERUS_STARTER_COUNT) {
|
||||
const randomSpeciesId = Number.parseInt(randSeedItem(Object.keys(speciesStarterCosts)), 10);
|
||||
const species = getPokemonSpecies(randomSpeciesId);
|
||||
if (!pokerusStarters.includes(species)) {
|
||||
pokerusStarters.push(species);
|
||||
}
|
||||
}
|
||||
},
|
||||
0,
|
||||
date.getTime().toString(),
|
||||
);
|
||||
return pokerusStarters;
|
||||
}
|
||||
|
||||
export function getFusedSpeciesName(speciesAName: string, speciesBName: string): string {
|
||||
const fragAPattern = /([a-z]{2}.*?[aeiou(?:y$)\-']+)(.*?)$/i;
|
||||
const fragBPattern = /([a-z]{2}.*?[aeiou(?:y$)\-'])(.*?)$/i;
|
||||
|
||||
const [speciesAPrefixMatch, speciesBPrefixMatch] = [speciesAName, speciesBName].map(n => /^(?:[^ ]+) /.exec(n));
|
||||
const [speciesAPrefix, speciesBPrefix] = [speciesAPrefixMatch, speciesBPrefixMatch].map(m => (m ? m[0] : ""));
|
||||
|
||||
if (speciesAPrefix) {
|
||||
speciesAName = speciesAName.slice(speciesAPrefix.length);
|
||||
}
|
||||
if (speciesBPrefix) {
|
||||
speciesBName = speciesBName.slice(speciesBPrefix.length);
|
||||
}
|
||||
|
||||
const [speciesASuffixMatch, speciesBSuffixMatch] = [speciesAName, speciesBName].map(n => / (?:[^ ]+)$/.exec(n));
|
||||
const [speciesASuffix, speciesBSuffix] = [speciesASuffixMatch, speciesBSuffixMatch].map(m => (m ? m[0] : ""));
|
||||
|
||||
if (speciesASuffix) {
|
||||
speciesAName = speciesAName.slice(0, -speciesASuffix.length);
|
||||
}
|
||||
if (speciesBSuffix) {
|
||||
speciesBName = speciesBName.slice(0, -speciesBSuffix.length);
|
||||
}
|
||||
|
||||
const splitNameA = speciesAName.split(/ /g);
|
||||
const splitNameB = speciesBName.split(/ /g);
|
||||
|
||||
const fragAMatch = fragAPattern.exec(speciesAName);
|
||||
const fragBMatch = fragBPattern.exec(speciesBName);
|
||||
|
||||
let fragA: string;
|
||||
let fragB: string;
|
||||
|
||||
fragA = splitNameA.length === 1 ? (fragAMatch ? fragAMatch[1] : speciesAName) : splitNameA[splitNameA.length - 1];
|
||||
|
||||
if (splitNameB.length === 1) {
|
||||
if (fragBMatch) {
|
||||
const lastCharA = fragA.slice(fragA.length - 1);
|
||||
const prevCharB = fragBMatch[1].slice(fragBMatch.length - 1);
|
||||
fragB = (/[-']/.test(prevCharB) ? prevCharB : "") + fragBMatch[2] || prevCharB;
|
||||
if (lastCharA === fragB[0]) {
|
||||
if (/[aiu]/.test(lastCharA)) {
|
||||
fragB = fragB.slice(1);
|
||||
} else {
|
||||
const newCharMatch = new RegExp(`[^${lastCharA}]`).exec(fragB);
|
||||
if (newCharMatch?.index !== undefined && newCharMatch.index > 0) {
|
||||
fragB = fragB.slice(newCharMatch.index);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fragB = speciesBName;
|
||||
}
|
||||
} else {
|
||||
fragB = splitNameB[splitNameB.length - 1];
|
||||
}
|
||||
|
||||
if (splitNameA.length > 1) {
|
||||
fragA = `${splitNameA.slice(0, splitNameA.length - 1).join(" ")} ${fragA}`;
|
||||
}
|
||||
|
||||
fragB = `${fragB.slice(0, 1).toLowerCase()}${fragB.slice(1)}`;
|
||||
|
||||
return `${speciesAPrefix || speciesBPrefix}${fragA}${fragB}${speciesBSuffix || speciesASuffix}`;
|
||||
}
|
||||
|
||||
export function getPokemonSpeciesForm(species: SpeciesId, formIndex: number): PokemonSpeciesForm {
|
||||
const retSpecies: PokemonSpecies =
|
||||
species >= 2000
|
||||
? allSpecies.find(s => s.speciesId === species)! // TODO: is the bang correct?
|
||||
: allSpecies[species - 1];
|
||||
if (formIndex < retSpecies.forms?.length) {
|
||||
return retSpecies.forms[formIndex];
|
||||
}
|
||||
return retSpecies;
|
||||
}
|
||||
|
18
src/vite.env.d.ts
vendored
18
src/vite.env.d.ts
vendored
@ -1,16 +1,16 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_PORT?: string;
|
||||
readonly VITE_BYPASS_LOGIN?: string;
|
||||
readonly VITE_BYPASS_TUTORIAL?: string;
|
||||
readonly VITE_API_BASE_URL?: string;
|
||||
readonly VITE_SERVER_URL?: string;
|
||||
readonly VITE_DISCORD_CLIENT_ID?: string;
|
||||
readonly VITE_GOOGLE_CLIENT_ID?: string;
|
||||
readonly VITE_I18N_DEBUG?: string;
|
||||
readonly VITE_PORT?: string;
|
||||
readonly VITE_BYPASS_LOGIN?: string;
|
||||
readonly VITE_BYPASS_TUTORIAL?: string;
|
||||
readonly VITE_API_BASE_URL?: string;
|
||||
readonly VITE_SERVER_URL?: string;
|
||||
readonly VITE_DISCORD_CLIENT_ID?: string;
|
||||
readonly VITE_GOOGLE_CLIENT_ID?: string;
|
||||
readonly VITE_I18N_DEBUG?: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
|
135
test/@types/vitest.d.ts
vendored
135
test/@types/vitest.d.ts
vendored
@ -1,26 +1,139 @@
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import type { TerrainType } from "#app/data/terrain";
|
||||
import type { AbilityId } from "#enums/ability-id";
|
||||
import type { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import type { MoveId } from "#enums/move-id";
|
||||
import type { PokemonType } from "#enums/pokemon-type";
|
||||
import type { expect } from "vitest";
|
||||
import type { BattleStat, EffectiveStat, Stat } from "#enums/stat";
|
||||
import type { StatusEffect } from "#enums/status-effect";
|
||||
import type { WeatherType } from "#enums/weather-type";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import type { ToHaveEffectiveStatMatcherOptions } from "#test/test-utils/matchers/to-have-effective-stat";
|
||||
import type { expectedStatusType } from "#test/test-utils/matchers/to-have-status-effect";
|
||||
import type { toHaveTypesOptions } from "#test/test-utils/matchers/to-have-types";
|
||||
import type { TurnMove } from "#types/turn-move";
|
||||
import type { AtLeastOne } from "#types/type-helpers";
|
||||
import type { expect } from "vitest";
|
||||
import type Overrides from "#app/overrides";
|
||||
import type { PokemonMove } from "#moves/pokemon-move";
|
||||
|
||||
declare module "vitest" {
|
||||
interface Assertion {
|
||||
/**
|
||||
* Matcher to check if an array contains EXACTLY the given items (in any order).
|
||||
* Check whether an array contains EXACTLY the given items (in any order).
|
||||
*
|
||||
* Different from {@linkcode expect.arrayContaining} as the latter only requires the array contain
|
||||
* _at least_ the listed items.
|
||||
* Different from {@linkcode expect.arrayContaining} as the latter only checks for subset equality
|
||||
* (as opposed to full equality).
|
||||
*
|
||||
* @param expected - The expected contents of the array, in any order.
|
||||
* @param expected - The expected contents of the array, in any order
|
||||
* @see {@linkcode expect.arrayContaining}
|
||||
*/
|
||||
toEqualArrayUnsorted<E>(expected: E[]): void;
|
||||
|
||||
/**
|
||||
* Matcher to check if a {@linkcode Pokemon}'s current typing includes the given types.
|
||||
* Check whether a {@linkcode Pokemon}'s current typing includes the given types.
|
||||
*
|
||||
* @param expected - The expected types (in any order).
|
||||
* @param options - The options passed to the matcher.
|
||||
* @param expected - The expected types (in any order)
|
||||
* @param options - The options passed to the matcher
|
||||
*/
|
||||
toHaveTypes(expected: PokemonType[], options?: toHaveTypesOptions): void;
|
||||
toHaveTypes(expected: [PokemonType, ...PokemonType[]], options?: toHaveTypesOptions): void;
|
||||
|
||||
/**
|
||||
* Matcher to check the contents of a {@linkcode Pokemon}'s move history.
|
||||
*
|
||||
* @param expectedValue - The expected value; can be a {@linkcode MoveId} or a partially filled {@linkcode TurnMove}
|
||||
* containing the desired properties to check
|
||||
* @param index - The index of the move history entry to check, in order from most recent to least recent.
|
||||
* Default `0` (last used move)
|
||||
* @see {@linkcode Pokemon.getLastXMoves}
|
||||
*/
|
||||
toHaveUsedMove(expected: MoveId | AtLeastOne<TurnMove>, index?: number): void;
|
||||
|
||||
/**
|
||||
* Check whether a {@linkcode Pokemon}'s effective stat is as expected
|
||||
* (checked after all stat value modifications).
|
||||
*
|
||||
* @param stat - The {@linkcode EffectiveStat} to check
|
||||
* @param expectedValue - The expected value of {@linkcode stat}
|
||||
* @param options - (Optional) The {@linkcode ToHaveEffectiveStatMatcherOptions}
|
||||
* @remarks
|
||||
* If you want to check the stat **before** modifiers are applied, use {@linkcode Pokemon.getStat} instead.
|
||||
*/
|
||||
toHaveEffectiveStat(stat: EffectiveStat, expectedValue: number, options?: ToHaveEffectiveStatMatcherOptions): void;
|
||||
|
||||
/**
|
||||
* Check whether a {@linkcode Pokemon} has taken a specific amount of damage.
|
||||
* @param expectedDamageTaken - The expected amount of damage taken
|
||||
* @param roundDown - Whether to round down {@linkcode expectedDamageTaken} with {@linkcode toDmgValue}; default `true`
|
||||
*/
|
||||
toHaveTakenDamage(expectedDamageTaken: number, roundDown?: boolean): void;
|
||||
|
||||
/**
|
||||
* Check whether the current {@linkcode WeatherType} is as expected.
|
||||
* @param expectedWeatherType - The expected {@linkcode WeatherType}
|
||||
*/
|
||||
toHaveWeather(expectedWeatherType: WeatherType): void;
|
||||
|
||||
/**
|
||||
* Check whether the current {@linkcode TerrainType} is as expected.
|
||||
* @param expectedTerrainType - The expected {@linkcode TerrainType}
|
||||
*/
|
||||
toHaveTerrain(expectedTerrainType: TerrainType): void;
|
||||
|
||||
/**
|
||||
* Check whether a {@linkcode Pokemon} is at full HP.
|
||||
*/
|
||||
toHaveFullHp(): void;
|
||||
|
||||
/**
|
||||
* Check whether a {@linkcode Pokemon} has a specific {@linkcode StatusEffect | non-volatile status effect}.
|
||||
* @param expectedStatusEffect - The {@linkcode StatusEffect} the Pokemon is expected to have,
|
||||
* or a partially filled {@linkcode Status} containing the desired properties
|
||||
*/
|
||||
toHaveStatusEffect(expectedStatusEffect: expectedStatusType): void;
|
||||
|
||||
/**
|
||||
* Check whether a {@linkcode Pokemon} has a specific {@linkcode Stat} stage.
|
||||
* @param stat - The {@linkcode BattleStat} to check
|
||||
* @param expectedStage - The expected stat stage value of {@linkcode stat}
|
||||
*/
|
||||
toHaveStatStage(stat: BattleStat, expectedStage: number): void;
|
||||
|
||||
/**
|
||||
* Check whether a {@linkcode Pokemon} has a specific {@linkcode BattlerTagType}.
|
||||
* @param expectedBattlerTagType - The expected {@linkcode BattlerTagType}
|
||||
*/
|
||||
toHaveBattlerTag(expectedBattlerTagType: BattlerTagType): void;
|
||||
|
||||
/**
|
||||
* Check whether a {@linkcode Pokemon} has applied a specific {@linkcode AbilityId}.
|
||||
* @param expectedAbilityId - The expected {@linkcode AbilityId}
|
||||
*/
|
||||
toHaveAbilityApplied(expectedAbilityId: AbilityId): void;
|
||||
|
||||
/**
|
||||
* Check whether a {@linkcode Pokemon} has a specific amount of {@linkcode Stat.HP | HP}.
|
||||
* @param expectedHp - The expected amount of {@linkcode Stat.HP | HP} to have
|
||||
*/
|
||||
toHaveHp(expectedHp: number): void;
|
||||
|
||||
/**
|
||||
* Check whether a {@linkcode Pokemon} is currently fainted (as determined by {@linkcode Pokemon.isFainted}).
|
||||
* @remarks
|
||||
* When checking whether an enemy wild Pokemon is fainted, one must reference it in a variable _before_ the fainting effect occurs
|
||||
* as otherwise the Pokemon will be GC'ed and rendered `undefined`.
|
||||
*/
|
||||
toHaveFainted(): void;
|
||||
|
||||
/**
|
||||
* Check whether a {@linkcode Pokemon} has consumed the given amount of PP for one of its moves.
|
||||
* @param expectedValue - The {@linkcode MoveId} of the {@linkcode PokemonMove} that should have consumed PP
|
||||
* @param ppUsed - The numerical amount of PP that should have been consumed,
|
||||
* or `all` to indicate the move should be _out_ of PP
|
||||
* @remarks
|
||||
* If the Pokemon's moveset has been set via {@linkcode Overrides.MOVESET_OVERRIDE}/{@linkcode Overrides.OPP_MOVESET_OVERRIDE},
|
||||
* does not contain {@linkcode expectedMove}
|
||||
* or contains the desired move more than once, this will fail the test.
|
||||
*/
|
||||
toHaveUsedPP(expectedMove: MoveId, ppUsed: number | "all"): void;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ describe("Abilities - Analytic", () => {
|
||||
it("should increase damage if the user moves last", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.ARCEUS]);
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.TACKLE);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
|
@ -36,7 +36,7 @@ describe("Ability - Anger Point", () => {
|
||||
it("should set the user's attack stage to +6 when hit by a critical hit", async () => {
|
||||
game.override.enemyAbility(AbilityId.ANGER_POINT).moveset(MoveId.FALSE_SWIPE);
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
// minimize the enemy's attack stage to ensure it is always set to +6
|
||||
enemy.setStatStage(Stat.ATK, -6);
|
||||
@ -53,7 +53,7 @@ describe("Ability - Anger Point", () => {
|
||||
.enemyAbility(AbilityId.ANGER_POINT)
|
||||
.ability(AbilityId.SKILL_LINK);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
vi.spyOn(enemy, "getCriticalHitResult").mockReturnValueOnce(true);
|
||||
const angerPointSpy = vi.spyOn(PostReceiveCritStatStageChangeAbAttr.prototype, "apply");
|
||||
game.move.select(MoveId.BULLET_SEED);
|
||||
@ -68,7 +68,7 @@ describe("Ability - Anger Point", () => {
|
||||
.enemyHasPassiveAbility(true)
|
||||
.moveset(MoveId.FALSE_SWIPE);
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
vi.spyOn(enemy, "getCriticalHitResult").mockReturnValueOnce(true);
|
||||
enemy.setStatStage(Stat.ATK, 6);
|
||||
game.move.select(MoveId.FALSE_SWIPE);
|
||||
|
@ -36,7 +36,7 @@ describe("Abilities - Beast Boost", () => {
|
||||
it("should prefer highest stat to boost its corresponding stat stage by 1 when winning a battle", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.SLOWBRO]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
// Set the pokemon's highest stat to DEF, so it should be picked by Beast Boost
|
||||
vi.spyOn(playerPokemon, "stats", "get").mockReturnValue([10000, 100, 1000, 200, 100, 100]);
|
||||
console.log(playerPokemon.stats);
|
||||
@ -54,7 +54,7 @@ describe("Abilities - Beast Boost", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.SLOWBRO]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
// If the opponent uses Guard Split, the pokemon's second highest stat (SPATK) should be chosen
|
||||
vi.spyOn(playerPokemon, "stats", "get").mockReturnValue([10000, 100, 201, 200, 100, 100]);
|
||||
|
||||
@ -72,7 +72,7 @@ describe("Abilities - Beast Boost", () => {
|
||||
// Order preference follows the order of EFFECTIVE_STAT
|
||||
await game.classicMode.startBattle([SpeciesId.SLOWBRO]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
// Set up tie between SPATK, SPDEF, and SPD, where SPATK should win
|
||||
vi.spyOn(playerPokemon, "stats", "get").mockReturnValue([10000, 1, 1, 100, 100, 100]);
|
||||
|
@ -36,7 +36,7 @@ describe("Abilities - Competitive", () => {
|
||||
it("lower atk and def by 1 via tickle, then increase spatk by 4 via competitive", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.FLYGON]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
@ -49,7 +49,7 @@ describe("Abilities - Competitive", () => {
|
||||
game.override.enemyMoveset(MoveId.SPLASH);
|
||||
await game.classicMode.startBattle([SpeciesId.FLYGON]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
game.move.select(MoveId.CLOSE_COMBAT);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
@ -62,7 +62,7 @@ describe("Abilities - Competitive", () => {
|
||||
game.override.startingHeldItems([{ name: "WHITE_HERB" }]);
|
||||
await game.classicMode.startBattle([SpeciesId.FLYGON]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
|
@ -33,7 +33,7 @@ describe("Abilities - Contrary", () => {
|
||||
it("should invert stat changes when applied", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.SLOWBRO]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||
});
|
||||
@ -43,7 +43,7 @@ describe("Abilities - Contrary", () => {
|
||||
game.override.enemyPassiveAbility(AbilityId.CLEAR_BODY).moveset([MoveId.TAIL_WHIP]);
|
||||
await game.classicMode.startBattle([SpeciesId.SLOWBRO]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||
|
||||
@ -57,7 +57,7 @@ describe("Abilities - Contrary", () => {
|
||||
game.override.enemyPassiveAbility(AbilityId.CLEAR_BODY).enemyMoveset(MoveId.HOWL).moveset([MoveId.SPLASH]);
|
||||
await game.classicMode.startBattle([SpeciesId.SLOWBRO]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||
|
||||
|
@ -43,7 +43,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
it("stores inside summonData at end of turn", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.FARIGIRAF]);
|
||||
|
||||
const farigiraf = game.scene.getPlayerPokemon()!;
|
||||
const farigiraf = game.field.getPlayerPokemon();
|
||||
farigiraf.hp = 1; // needed to allow sitrus procs
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -71,7 +71,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
game.override.enemyMoveset([MoveId.SPLASH, MoveId.HEAL_PULSE]);
|
||||
await game.classicMode.startBattle([SpeciesId.FARIGIRAF]);
|
||||
|
||||
const farigiraf = game.scene.getPlayerPokemon()!;
|
||||
const farigiraf = game.field.getPlayerPokemon();
|
||||
// Dip below half to eat berry
|
||||
farigiraf.hp = farigiraf.getMaxHp() / 2 - 1;
|
||||
|
||||
@ -120,7 +120,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
.enemyMoveset(MoveId.TEATIME);
|
||||
await game.classicMode.startBattle([SpeciesId.FARIGIRAF]);
|
||||
|
||||
const farigiraf = game.scene.getPlayerPokemon()!;
|
||||
const farigiraf = game.field.getPlayerPokemon();
|
||||
farigiraf.hp = 1; // needed to allow berry procs
|
||||
|
||||
game.move.select(MoveId.STUFF_CHEEKS);
|
||||
@ -148,7 +148,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
it("should reset both arrays on switch", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.FARIGIRAF, SpeciesId.GIRAFARIG]);
|
||||
|
||||
const farigiraf = game.scene.getPlayerPokemon()!;
|
||||
const farigiraf = game.field.getPlayerPokemon();
|
||||
farigiraf.hp = 1;
|
||||
|
||||
// eat berry turn 1, switch out turn 2
|
||||
@ -177,7 +177,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
game.override.enemyAbility(AbilityId.NEUTRALIZING_GAS);
|
||||
await game.classicMode.startBattle([SpeciesId.FARIGIRAF]);
|
||||
|
||||
const farigiraf = game.scene.getPlayerPokemon()!;
|
||||
const farigiraf = game.field.getPlayerPokemon();
|
||||
farigiraf.hp = 1;
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -199,7 +199,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
const apply = vi.spyOn(CudChewConsumeBerryAbAttr.prototype, "apply");
|
||||
await game.classicMode.startBattle([SpeciesId.FARIGIRAF]);
|
||||
|
||||
const farigiraf = game.scene.getPlayerPokemon()!;
|
||||
const farigiraf = game.field.getPlayerPokemon();
|
||||
farigiraf.hp = 1;
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -225,7 +225,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
game.override.enemyAbility(AbilityId.UNNERVE);
|
||||
await game.classicMode.startBattle([SpeciesId.FARIGIRAF]);
|
||||
|
||||
const farigiraf = game.scene.getPlayerPokemon()!;
|
||||
const farigiraf = game.field.getPlayerPokemon();
|
||||
farigiraf.hp = 1;
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -243,7 +243,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
game.override.enemyMoveset(MoveId.INCINERATE);
|
||||
await game.classicMode.startBattle([SpeciesId.FARIGIRAF]);
|
||||
|
||||
const farigiraf = game.scene.getPlayerPokemon()!;
|
||||
const farigiraf = game.field.getPlayerPokemon();
|
||||
farigiraf.hp = farigiraf.getMaxHp() / 4;
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -262,7 +262,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
.startingHeldItems([]);
|
||||
await game.classicMode.startBattle([SpeciesId.FARIGIRAF]);
|
||||
|
||||
const farigiraf = game.scene.getPlayerPokemon()!;
|
||||
const farigiraf = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.BUG_BITE);
|
||||
await game.toNextTurn();
|
||||
@ -278,7 +278,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
game.override.passiveAbility(AbilityId.RIPEN);
|
||||
await game.classicMode.startBattle([SpeciesId.FARIGIRAF]);
|
||||
|
||||
const farigiraf = game.scene.getPlayerPokemon()!;
|
||||
const farigiraf = game.field.getPlayerPokemon();
|
||||
farigiraf.hp = 1;
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -294,7 +294,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
game.override.enemyLevel(1);
|
||||
await game.classicMode.startBattle([SpeciesId.FARIGIRAF]);
|
||||
|
||||
const farigiraf = game.scene.getPlayerPokemon()!;
|
||||
const farigiraf = game.field.getPlayerPokemon();
|
||||
farigiraf.hp = 1;
|
||||
|
||||
game.move.select(MoveId.HYPER_VOICE);
|
||||
@ -307,7 +307,7 @@ describe("Abilities - Cud Chew", () => {
|
||||
// reload and the berry should still be there
|
||||
await game.reload.reloadSession();
|
||||
|
||||
const farigirafReloaded = game.scene.getPlayerPokemon()!;
|
||||
const farigirafReloaded = game.field.getPlayerPokemon();
|
||||
expect(farigirafReloaded.summonData.berriesEatenLast).toEqual([BerryType.SITRUS]);
|
||||
|
||||
const wave1Hp = farigirafReloaded.hp;
|
||||
|
@ -125,7 +125,7 @@ describe("Abilities - Dancer", () => {
|
||||
game.override.battleStyle("double").moveset(MoveId.SPLASH).enemyMoveset([MoveId.SWORDS_DANCE, MoveId.FAKE_OUT]);
|
||||
await game.classicMode.startBattle([SpeciesId.ORICORIO]);
|
||||
|
||||
const oricorio = game.scene.getPlayerPokemon()!;
|
||||
const oricorio = game.field.getPlayerPokemon();
|
||||
expect(oricorio).toBeDefined();
|
||||
|
||||
// get faked out and copy swords dance
|
||||
|
@ -36,7 +36,7 @@ describe("Abilities - Defiant", () => {
|
||||
it("lower atk and def by 1 via tickle, then increase atk by 4 via defiant", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.FLYGON]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
@ -48,7 +48,7 @@ describe("Abilities - Defiant", () => {
|
||||
game.override.enemyMoveset(MoveId.SPLASH);
|
||||
await game.classicMode.startBattle([SpeciesId.FLYGON]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
game.move.select(MoveId.CLOSE_COMBAT);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
@ -61,7 +61,7 @@ describe("Abilities - Defiant", () => {
|
||||
game.override.startingHeldItems([{ name: "WHITE_HERB" }]);
|
||||
await game.classicMode.startBattle([SpeciesId.FLYGON]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
|
@ -145,7 +145,7 @@ describe("Abilities - Desolate Land", () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.HARSH_SUN);
|
||||
|
||||
vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0);
|
||||
vi.spyOn(game.field.getPlayerPokemon(), "randBattleSeedInt").mockReturnValue(0);
|
||||
vi.spyOn(globalScene, "randBattleSeedInt").mockReturnValue(0);
|
||||
|
||||
const commandPhase = game.scene.phaseManager.getCurrentPhase() as CommandPhase;
|
||||
|
@ -37,7 +37,7 @@ describe("Abilities - Disguise", () => {
|
||||
it("takes no damage from attacking move and transforms to Busted form, takes 1/8 max HP damage from the disguise breaking", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const mimikyu = game.scene.getEnemyPokemon()!;
|
||||
const mimikyu = game.field.getEnemyPokemon();
|
||||
const maxHp = mimikyu.getMaxHp();
|
||||
const disguiseDamage = toDmgValue(maxHp / 8);
|
||||
|
||||
@ -54,7 +54,7 @@ describe("Abilities - Disguise", () => {
|
||||
it("doesn't break disguise when attacked with ineffective move", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const mimikyu = game.scene.getEnemyPokemon()!;
|
||||
const mimikyu = game.field.getEnemyPokemon();
|
||||
|
||||
expect(mimikyu.formIndex).toBe(disguisedForm);
|
||||
|
||||
@ -69,7 +69,7 @@ describe("Abilities - Disguise", () => {
|
||||
game.override.moveset([MoveId.SURGING_STRIKES]).enemyLevel(5);
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const mimikyu = game.scene.getEnemyPokemon()!;
|
||||
const mimikyu = game.field.getEnemyPokemon();
|
||||
const maxHp = mimikyu.getMaxHp();
|
||||
const disguiseDamage = toDmgValue(maxHp / 8);
|
||||
|
||||
@ -91,7 +91,7 @@ describe("Abilities - Disguise", () => {
|
||||
it("takes effects from status moves and damage from status effects", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const mimikyu = game.scene.getEnemyPokemon()!;
|
||||
const mimikyu = game.field.getEnemyPokemon();
|
||||
expect(mimikyu.hp).toBe(mimikyu.getMaxHp());
|
||||
|
||||
game.move.select(MoveId.TOXIC_THREAD);
|
||||
@ -109,7 +109,7 @@ describe("Abilities - Disguise", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MIMIKYU, SpeciesId.FURRET]);
|
||||
|
||||
const mimikyu = game.scene.getPlayerPokemon()!;
|
||||
const mimikyu = game.field.getPlayerPokemon();
|
||||
const maxHp = mimikyu.getMaxHp();
|
||||
const disguiseDamage = toDmgValue(maxHp / 8);
|
||||
|
||||
@ -154,7 +154,7 @@ describe("Abilities - Disguise", () => {
|
||||
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const mimikyu = game.scene.getPlayerPokemon()!;
|
||||
const mimikyu = game.field.getPlayerPokemon();
|
||||
|
||||
expect(mimikyu.formIndex).toBe(bustedForm);
|
||||
|
||||
@ -175,7 +175,7 @@ describe("Abilities - Disguise", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MIMIKYU, SpeciesId.FURRET]);
|
||||
|
||||
const mimikyu1 = game.scene.getPlayerPokemon()!;
|
||||
const mimikyu1 = game.field.getPlayerPokemon();
|
||||
|
||||
expect(mimikyu1.formIndex).toBe(bustedForm);
|
||||
|
||||
@ -190,7 +190,7 @@ describe("Abilities - Disguise", () => {
|
||||
game.override.enemyMoveset([MoveId.ENDURE]);
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const mimikyu = game.scene.getEnemyPokemon()!;
|
||||
const mimikyu = game.field.getEnemyPokemon();
|
||||
mimikyu.hp = 1;
|
||||
|
||||
game.move.select(MoveId.SHADOW_SNEAK);
|
||||
@ -205,7 +205,7 @@ describe("Abilities - Disguise", () => {
|
||||
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const mimikyu = game.scene.getEnemyPokemon()!;
|
||||
const mimikyu = game.field.getEnemyPokemon();
|
||||
const maxHp = mimikyu.getMaxHp();
|
||||
const disguiseDamage = toDmgValue(maxHp / 8);
|
||||
|
||||
@ -225,6 +225,6 @@ describe("Abilities - Disguise", () => {
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(game.scene.getEnemyPokemon()!.formIndex).toBe(disguisedForm);
|
||||
expect(game.field.getEnemyPokemon().formIndex).toBe(disguisedForm);
|
||||
});
|
||||
});
|
||||
|
@ -35,7 +35,7 @@ describe("Abilities - Dry Skin", () => {
|
||||
it("during sunlight, lose 1/8 of maximum health at the end of each turn", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
// first turn
|
||||
game.move.select(MoveId.SUNNY_DAY);
|
||||
@ -52,7 +52,7 @@ describe("Abilities - Dry Skin", () => {
|
||||
it("during rain, gain 1/8 of maximum health at the end of each turn", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
enemy.hp = 1;
|
||||
|
||||
@ -72,7 +72,7 @@ describe("Abilities - Dry Skin", () => {
|
||||
game.override.moveset([MoveId.FLAMETHROWER]);
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
const initialHP = 1000;
|
||||
enemy.hp = initialHP;
|
||||
|
||||
@ -95,7 +95,7 @@ describe("Abilities - Dry Skin", () => {
|
||||
it("opposing water attacks heal 1/4 of maximum health and deal no damage", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
enemy.hp = 1;
|
||||
|
||||
@ -109,7 +109,7 @@ describe("Abilities - Dry Skin", () => {
|
||||
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
enemy.hp = 1;
|
||||
|
||||
@ -123,7 +123,7 @@ describe("Abilities - Dry Skin", () => {
|
||||
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
enemy.hp = 1;
|
||||
|
||||
@ -145,7 +145,7 @@ describe("Abilities - Dry Skin", () => {
|
||||
it("opposing water moves still heal regardless of accuracy check", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.WATER_GUN);
|
||||
enemy.hp = enemy.hp - 1;
|
||||
|
@ -37,7 +37,7 @@ describe("Abilities - Early Bird", () => {
|
||||
it("reduces Rest's sleep time to 1 turn", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const player = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.BELLY_DRUM);
|
||||
await game.toNextTurn();
|
||||
@ -62,7 +62,7 @@ describe("Abilities - Early Bird", () => {
|
||||
it("reduces 3-turn sleep to 1 turn", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const player = game.field.getPlayerPokemon();
|
||||
player.status = new Status(StatusEffect.SLEEP, 0, 4);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -81,7 +81,7 @@ describe("Abilities - Early Bird", () => {
|
||||
it("reduces 1-turn sleep to 0 turns", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const player = game.field.getPlayerPokemon();
|
||||
player.status = new Status(StatusEffect.SLEEP, 0, 2);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
|
@ -39,7 +39,7 @@ describe("Abilities - Flash Fire", () => {
|
||||
game.override.enemyMoveset([MoveId.EMBER]).moveset(MoveId.SPLASH);
|
||||
await game.classicMode.startBattle([SpeciesId.BLISSEY]);
|
||||
|
||||
const blissey = game.scene.getPlayerPokemon()!;
|
||||
const blissey = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
@ -50,7 +50,7 @@ describe("Abilities - Flash Fire", () => {
|
||||
game.override.enemyMoveset([MoveId.EMBER]).moveset([MoveId.PROTECT]);
|
||||
await game.classicMode.startBattle([SpeciesId.BLISSEY]);
|
||||
|
||||
const blissey = game.scene.getPlayerPokemon()!;
|
||||
const blissey = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.PROTECT);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
@ -61,7 +61,7 @@ describe("Abilities - Flash Fire", () => {
|
||||
game.override.enemyMoveset([MoveId.WILL_O_WISP]).moveset(MoveId.SPLASH);
|
||||
await game.classicMode.startBattle([SpeciesId.BLISSEY]);
|
||||
|
||||
const blissey = game.scene.getPlayerPokemon()!;
|
||||
const blissey = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.move.forceHit();
|
||||
@ -76,7 +76,7 @@ describe("Abilities - Flash Fire", () => {
|
||||
game.override.enemyMoveset([MoveId.EMBER]).moveset(MoveId.SPLASH).statusEffect(StatusEffect.FREEZE);
|
||||
await game.classicMode.startBattle([SpeciesId.BLISSEY]);
|
||||
|
||||
const blissey = game.scene.getPlayerPokemon()!;
|
||||
const blissey = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
|
||||
@ -95,8 +95,8 @@ describe("Abilities - Flash Fire", () => {
|
||||
game.doSelectPartyPokemon(1);
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
const chansey = game.scene.getPlayerPokemon()!;
|
||||
expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(SpeciesId.CHANSEY);
|
||||
const chansey = game.field.getPlayerPokemon();
|
||||
expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.CHANSEY);
|
||||
expect(chansey!.getTag(BattlerTagType.FIRE_BOOST)).toBeUndefined();
|
||||
});
|
||||
|
||||
@ -107,7 +107,7 @@ describe("Abilities - Flash Fire", () => {
|
||||
.enemyAbility(AbilityId.FLASH_FIRE)
|
||||
.ability(AbilityId.NONE);
|
||||
await game.classicMode.startBattle([SpeciesId.BLISSEY]);
|
||||
const blissey = game.scene.getPlayerPokemon()!;
|
||||
const blissey = game.field.getPlayerPokemon();
|
||||
const initialHP = 1000;
|
||||
blissey.hp = initialHP;
|
||||
|
||||
@ -137,7 +137,7 @@ describe("Abilities - Flash Fire", () => {
|
||||
.enemySpecies(SpeciesId.BLISSEY);
|
||||
await game.classicMode.startBattle([SpeciesId.RATTATA]);
|
||||
|
||||
const blissey = game.scene.getEnemyPokemon()!;
|
||||
const blissey = game.field.getEnemyPokemon();
|
||||
const initialHP = 1000;
|
||||
blissey.hp = initialHP;
|
||||
|
||||
|
@ -27,7 +27,7 @@ describe("Abilities - Flower Gift", () => {
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
|
||||
expect(game.scene.getPlayerPokemon()?.formIndex).toBe(OVERCAST_FORM);
|
||||
expect(game.field.getPlayerPokemon().formIndex).toBe(OVERCAST_FORM);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -169,7 +169,7 @@ describe("Abilities - Flower Gift", () => {
|
||||
game.override.weather(WeatherType.HARSH_SUN);
|
||||
await game.classicMode.startBattle([SpeciesId.CHERRIM]);
|
||||
|
||||
const cherrim = game.scene.getPlayerPokemon()!;
|
||||
const cherrim = game.field.getPlayerPokemon();
|
||||
expect(cherrim.formIndex).toBe(SUNSHINE_FORM);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -188,7 +188,7 @@ describe("Abilities - Flower Gift", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.CHERRIM, SpeciesId.MAGIKARP]);
|
||||
|
||||
const cherrim = game.scene.getPlayerPokemon()!;
|
||||
const cherrim = game.field.getPlayerPokemon();
|
||||
|
||||
expect(cherrim.formIndex).toBe(SUNSHINE_FORM);
|
||||
|
||||
@ -215,7 +215,7 @@ describe("Abilities - Flower Gift", () => {
|
||||
game.override.weather(WeatherType.SUNNY);
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.CASTFORM, SpeciesId.MAGIKARP]);
|
||||
const cherrim = game.scene.getPlayerPokemon()!;
|
||||
const cherrim = game.field.getPlayerPokemon();
|
||||
|
||||
expect(cherrim.formIndex).toBe(SUNSHINE_FORM);
|
||||
|
||||
|
@ -46,7 +46,7 @@ describe("Abilities - Flower Veil", () => {
|
||||
.moveset([MoveId.REST, MoveId.SPLASH])
|
||||
.startingHeldItems([{ name: "FLAME_ORB" }]);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
const user = game.scene.getPlayerPokemon()!;
|
||||
const user = game.field.getPlayerPokemon();
|
||||
game.move.select(MoveId.REST);
|
||||
await game.move.selectEnemyMove(MoveId.TACKLE);
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
@ -74,7 +74,7 @@ describe("Abilities - Flower Veil", () => {
|
||||
await game.move.selectEnemyMove(MoveId.YAWN, BattlerIndex.PLAYER_2);
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
const user = game.scene.getPlayerPokemon()!;
|
||||
const user = game.field.getPlayerPokemon();
|
||||
expect(user.getTag(BattlerTagType.DROWSY)).toBeFalsy();
|
||||
expect(ally.getTag(BattlerTagType.DROWSY)).toBeFalsy();
|
||||
});
|
||||
@ -87,7 +87,7 @@ describe("Abilities - Flower Veil", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.move.selectEnemyMove(MoveId.THUNDER_WAVE);
|
||||
await game.toNextTurn();
|
||||
expect(game.scene.getPlayerPokemon()!.status).toBeUndefined();
|
||||
expect(game.field.getPlayerPokemon().status).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should not prevent status conditions for a non-grass user and its non-grass allies", async () => {
|
||||
@ -155,7 +155,7 @@ describe("Abilities - Flower Veil", () => {
|
||||
it("should prevent the drops while retaining the boosts from spicy extract", async () => {
|
||||
game.override.enemyMoveset([MoveId.SPICY_EXTRACT]).moveset([MoveId.SPLASH]);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
const user = game.scene.getPlayerPokemon()!;
|
||||
const user = game.field.getPlayerPokemon();
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
expect(user.getStatStage(Stat.ATK)).toBe(2);
|
||||
|
@ -32,7 +32,7 @@ describe("Abilities - Forecast", () => {
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
|
||||
expect(game.scene.getPlayerPokemon()?.formIndex).toBe(NORMAL_FORM);
|
||||
expect(game.field.getPlayerPokemon().formIndex).toBe(NORMAL_FORM);
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
@ -186,14 +186,14 @@ describe("Abilities - Forecast", () => {
|
||||
game.move.select(MoveId.RAIN_DANCE);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
expect(game.scene.getPlayerPokemon()?.formIndex).toBe(RAINY_FORM);
|
||||
expect(game.scene.getEnemyPokemon()?.formIndex).not.toBe(RAINY_FORM);
|
||||
expect(game.field.getPlayerPokemon().formIndex).toBe(RAINY_FORM);
|
||||
expect(game.field.getEnemyPokemon().formIndex).not.toBe(RAINY_FORM);
|
||||
});
|
||||
|
||||
it("reverts to Normal Form when Forecast is suppressed, changes form to match the weather when it regains it", async () => {
|
||||
game.override.enemyMoveset([MoveId.GASTRO_ACID]).weather(WeatherType.RAIN);
|
||||
await game.classicMode.startBattle([SpeciesId.CASTFORM, SpeciesId.PIKACHU]);
|
||||
const castform = game.scene.getPlayerPokemon()!;
|
||||
const castform = game.field.getPlayerPokemon();
|
||||
|
||||
expect(castform.formIndex).toBe(RAINY_FORM);
|
||||
|
||||
@ -233,7 +233,7 @@ describe("Abilities - Forecast", () => {
|
||||
game.doSwitchPokemon(1);
|
||||
await game.phaseInterceptor.to(PostSummonPhase);
|
||||
|
||||
const castform = game.scene.getPlayerPokemon()!;
|
||||
const castform = game.field.getPlayerPokemon();
|
||||
|
||||
// Damage phase should come first
|
||||
await game.phaseInterceptor.to(DamageAnimPhase);
|
||||
@ -248,7 +248,7 @@ describe("Abilities - Forecast", () => {
|
||||
game.override.weather(WeatherType.RAIN);
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.CASTFORM, SpeciesId.MAGIKARP]);
|
||||
const castform = game.scene.getPlayerPokemon()!;
|
||||
const castform = game.field.getPlayerPokemon();
|
||||
|
||||
expect(castform.formIndex).toBe(RAINY_FORM);
|
||||
|
||||
@ -263,14 +263,14 @@ describe("Abilities - Forecast", () => {
|
||||
it("should trigger player's form change when summoned at the same time as an enemy with a weather changing ability", async () => {
|
||||
game.override.enemyAbility(AbilityId.DROUGHT);
|
||||
await game.classicMode.startBattle([SpeciesId.CASTFORM, SpeciesId.MAGIKARP]);
|
||||
const castform = game.scene.getPlayerPokemon()!;
|
||||
const castform = game.field.getPlayerPokemon();
|
||||
expect(castform.formIndex).toBe(SUNNY_FORM);
|
||||
});
|
||||
|
||||
it("should trigger enemy's form change when summoned at the same time as a player with a weather changing ability", async () => {
|
||||
game.override.ability(AbilityId.DROUGHT).enemySpecies(SpeciesId.CASTFORM).enemyAbility(AbilityId.FORECAST);
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
const castform = game.scene.getEnemyPokemon()!;
|
||||
const castform = game.field.getEnemyPokemon();
|
||||
expect(castform.formIndex).toBe(SUNNY_FORM);
|
||||
});
|
||||
});
|
||||
|
@ -43,7 +43,7 @@ describe("Abilities - Good As Gold", () => {
|
||||
game.override.enemyMoveset([MoveId.GROWL]);
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const player = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
|
||||
|
@ -40,7 +40,7 @@ describe("Abilities - Gorilla Tactics", () => {
|
||||
it("boosts the Pokémon's Attack by 50%, but limits the Pokémon to using only one move", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.GALAR_DARMANITAN]);
|
||||
|
||||
const darmanitan = game.scene.getPlayerPokemon()!;
|
||||
const darmanitan = game.field.getPlayerPokemon();
|
||||
const initialAtkStat = darmanitan.getStat(Stat.ATK);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -86,7 +86,7 @@ describe("Abilities - Gorilla Tactics", () => {
|
||||
vi.spyOn(RandomMoveAttr.prototype, "getMoveOverride").mockReturnValue(MoveId.TACKLE);
|
||||
await game.classicMode.startBattle([SpeciesId.GALAR_DARMANITAN]);
|
||||
|
||||
const darmanitan = game.scene.getPlayerPokemon()!;
|
||||
const darmanitan = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.METRONOME);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
@ -52,7 +52,7 @@ describe("Abilities - Gulp Missile", () => {
|
||||
|
||||
it("changes to Gulping Form if HP is over half when Surf or Dive is used", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.DIVE);
|
||||
await game.toNextTurn();
|
||||
@ -66,7 +66,7 @@ describe("Abilities - Gulp Missile", () => {
|
||||
|
||||
it("changes to Gorging Form if HP is under half when Surf or Dive is used", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
|
||||
vi.spyOn(cramorant, "getHpRatio").mockReturnValue(0.49);
|
||||
expect(cramorant.getHpRatio()).toBe(0.49);
|
||||
@ -80,7 +80,7 @@ describe("Abilities - Gulp Missile", () => {
|
||||
|
||||
it("changes to base form when switched out after Surf or Dive is used", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT, SpeciesId.MAGIKARP]);
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.SURF);
|
||||
await game.toNextTurn();
|
||||
@ -95,7 +95,7 @@ describe("Abilities - Gulp Missile", () => {
|
||||
|
||||
it("changes form during Dive's charge turn", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.DIVE);
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
@ -108,7 +108,7 @@ describe("Abilities - Gulp Missile", () => {
|
||||
game.override.enemyMoveset(MoveId.TACKLE);
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
vi.spyOn(enemy, "damageAndUpdate");
|
||||
|
||||
game.move.select(MoveId.SURF);
|
||||
@ -121,7 +121,7 @@ describe("Abilities - Gulp Missile", () => {
|
||||
game.override.enemyMoveset(MoveId.TAIL_WHIP);
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
vi.spyOn(cramorant, "getHpRatio").mockReturnValue(0.55);
|
||||
|
||||
game.move.select(MoveId.SURF);
|
||||
@ -140,8 +140,8 @@ describe("Abilities - Gulp Missile", () => {
|
||||
game.override.enemyMoveset(MoveId.TACKLE);
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
vi.spyOn(enemy, "damageAndUpdate");
|
||||
vi.spyOn(cramorant, "getHpRatio").mockReturnValue(0.55);
|
||||
@ -164,8 +164,8 @@ describe("Abilities - Gulp Missile", () => {
|
||||
game.override.enemyMoveset(MoveId.TACKLE);
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
vi.spyOn(enemy, "damageAndUpdate");
|
||||
vi.spyOn(cramorant, "getHpRatio").mockReturnValue(0.45);
|
||||
@ -188,7 +188,7 @@ describe("Abilities - Gulp Missile", () => {
|
||||
game.override.enemyMoveset(MoveId.SURF);
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.DIVE);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
@ -201,8 +201,8 @@ describe("Abilities - Gulp Missile", () => {
|
||||
game.override.enemyMoveset(MoveId.TACKLE).enemyAbility(AbilityId.MAGIC_GUARD);
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
vi.spyOn(cramorant, "getHpRatio").mockReturnValue(0.55);
|
||||
|
||||
@ -225,7 +225,7 @@ describe("Abilities - Gulp Missile", () => {
|
||||
game.override.enemyMoveset(MoveId.THUNDERBOLT);
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.SURF);
|
||||
await game.phaseInterceptor.to("FaintPhase");
|
||||
@ -233,7 +233,7 @@ describe("Abilities - Gulp Missile", () => {
|
||||
expect(cramorant.hp).toBe(0);
|
||||
expect(cramorant.getTag(BattlerTagType.GULP_MISSILE_ARROKUDA)).toBeUndefined();
|
||||
expect(cramorant.formIndex).toBe(NORMAL_FORM);
|
||||
expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.DEF)).toBe(-1);
|
||||
expect(game.field.getEnemyPokemon().getStatStage(Stat.DEF)).toBe(-1);
|
||||
});
|
||||
|
||||
it("doesn't trigger if user is behind a substitute", async () => {
|
||||
@ -244,21 +244,21 @@ describe("Abilities - Gulp Missile", () => {
|
||||
await game.move.selectEnemyMove(MoveId.SPLASH);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.formIndex).toBe(GULPING_FORM);
|
||||
expect(game.field.getPlayerPokemon().formIndex).toBe(GULPING_FORM);
|
||||
|
||||
game.move.select(MoveId.SUBSTITUTE);
|
||||
await game.move.selectEnemyMove(MoveId.POWER_TRIP);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.formIndex).toBe(GULPING_FORM);
|
||||
expect(game.field.getPlayerPokemon().formIndex).toBe(GULPING_FORM);
|
||||
});
|
||||
|
||||
it("cannot be suppressed", async () => {
|
||||
game.override.enemyMoveset(MoveId.GASTRO_ACID);
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
vi.spyOn(cramorant, "getHpRatio").mockReturnValue(0.55);
|
||||
|
||||
game.move.select(MoveId.SURF);
|
||||
@ -278,7 +278,7 @@ describe("Abilities - Gulp Missile", () => {
|
||||
game.override.enemyMoveset(MoveId.SKILL_SWAP);
|
||||
await game.classicMode.startBattle([SpeciesId.CRAMORANT]);
|
||||
|
||||
const cramorant = game.scene.getPlayerPokemon()!;
|
||||
const cramorant = game.field.getPlayerPokemon();
|
||||
vi.spyOn(cramorant, "getHpRatio").mockReturnValue(0.55);
|
||||
|
||||
game.move.select(MoveId.SURF);
|
||||
@ -301,6 +301,6 @@ describe("Abilities - Gulp Missile", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("TurnStartPhase");
|
||||
|
||||
expect(game.scene.getEnemyPokemon()?.hasAbility(AbilityId.GULP_MISSILE)).toBe(false);
|
||||
expect(game.field.getEnemyPokemon().hasAbility(AbilityId.GULP_MISSILE)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@ -19,7 +19,7 @@ describe("Abilities - Harvest", () => {
|
||||
let game: GameManager;
|
||||
|
||||
const getPlayerBerries = () =>
|
||||
game.scene.getModifiers(BerryModifier, true).filter(b => b.pokemonId === game.scene.getPlayerPokemon()?.id);
|
||||
game.scene.getModifiers(BerryModifier, true).filter(b => b.pokemonId === game.field.getPlayerPokemon().id);
|
||||
|
||||
/** Check whether the player's Modifiers contains the specified berries and nothing else. */
|
||||
function expectBerriesContaining(...berries: ModifierOverride[]): void {
|
||||
@ -64,11 +64,11 @@ describe("Abilities - Harvest", () => {
|
||||
await game.move.selectEnemyMove(MoveId.NUZZLE);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
expect(getPlayerBerries()).toHaveLength(0);
|
||||
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toHaveLength(1);
|
||||
expect(game.field.getPlayerPokemon().battleData.berriesEaten).toHaveLength(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expectBerriesContaining({ name: "BERRY", type: BerryType.LUM, count: 1 });
|
||||
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toEqual([]);
|
||||
expect(game.field.getPlayerPokemon().battleData.berriesEaten).toEqual([]);
|
||||
});
|
||||
|
||||
it("tracks berries eaten while disabled/not present", async () => {
|
||||
@ -82,7 +82,7 @@ describe("Abilities - Harvest", () => {
|
||||
.enemyAbility(AbilityId.NEUTRALIZING_GAS);
|
||||
await game.classicMode.startBattle([SpeciesId.MILOTIC]);
|
||||
|
||||
const milotic = game.scene.getPlayerPokemon()!;
|
||||
const milotic = game.field.getPlayerPokemon();
|
||||
expect(milotic).toBeDefined();
|
||||
|
||||
// Chug a few berries without harvest (should get tracked)
|
||||
@ -122,7 +122,7 @@ describe("Abilities - Harvest", () => {
|
||||
.ability(AbilityId.BALL_FETCH); // don't actually need harvest for this test
|
||||
await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
|
||||
|
||||
const regieleki = game.scene.getPlayerPokemon()!;
|
||||
const regieleki = game.field.getPlayerPokemon();
|
||||
regieleki.hp = 1;
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -150,7 +150,7 @@ describe("Abilities - Harvest", () => {
|
||||
.enemyAbility(AbilityId.COMPOUND_EYES);
|
||||
await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
|
||||
|
||||
const regieleki = game.scene.getPlayerPokemon()!;
|
||||
const regieleki = game.field.getPlayerPokemon();
|
||||
regieleki.hp = regieleki.getMaxHp() / 4 + 1;
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -161,7 +161,7 @@ describe("Abilities - Harvest", () => {
|
||||
// ate 1 berry and recovered it
|
||||
expect(regieleki.battleData.berriesEaten).toEqual([]);
|
||||
expect(getPlayerBerries()).toEqual([expect.objectContaining({ berryType: BerryType.PETAYA, stackCount: 1 })]);
|
||||
expect(game.scene.getPlayerPokemon()?.getStatStage(Stat.SPATK)).toBe(1);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.SPATK)).toBe(1);
|
||||
|
||||
// heal up so harvest doesn't proc and kill enemy
|
||||
game.move.select(MoveId.EARTHQUAKE);
|
||||
@ -170,13 +170,13 @@ describe("Abilities - Harvest", () => {
|
||||
await game.toNextWave();
|
||||
|
||||
expectBerriesContaining({ name: "BERRY", count: 1, type: BerryType.PETAYA });
|
||||
expect(game.scene.getPlayerPokemon()?.getStatStage(Stat.SPATK)).toBe(1);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.SPATK)).toBe(1);
|
||||
|
||||
await game.reload.reloadSession();
|
||||
|
||||
expect(regieleki.battleData.berriesEaten).toEqual([]);
|
||||
expectBerriesContaining({ name: "BERRY", count: 1, type: BerryType.PETAYA });
|
||||
expect(game.scene.getPlayerPokemon()?.getStatStage(Stat.SPATK)).toBe(1);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.SPATK)).toBe(1);
|
||||
});
|
||||
|
||||
it("cannot restore capped berries", async () => {
|
||||
@ -187,7 +187,7 @@ describe("Abilities - Harvest", () => {
|
||||
game.override.startingHeldItems(initBerries);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const feebas = game.scene.getPlayerPokemon()!;
|
||||
const feebas = game.field.getPlayerPokemon();
|
||||
feebas.battleData.berriesEaten = [BerryType.LUM, BerryType.STARF];
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -215,7 +215,7 @@ describe("Abilities - Harvest", () => {
|
||||
game.override.startingHeldItems(initBerries);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const player = game.field.getPlayerPokemon();
|
||||
player.battleData.berriesEaten = [BerryType.LUM, BerryType.STARF];
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -234,7 +234,7 @@ describe("Abilities - Harvest", () => {
|
||||
await game.move.selectEnemyMove(MoveId.INCINERATE);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toEqual([]);
|
||||
expect(game.field.getPlayerPokemon().battleData.berriesEaten).toEqual([]);
|
||||
});
|
||||
|
||||
it("cannot restore knocked off berries", async () => {
|
||||
@ -245,7 +245,7 @@ describe("Abilities - Harvest", () => {
|
||||
await game.move.selectEnemyMove(MoveId.KNOCK_OFF);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toEqual([]);
|
||||
expect(game.field.getPlayerPokemon().battleData.berriesEaten).toEqual([]);
|
||||
});
|
||||
|
||||
it("can restore berries eaten by Teatime", async () => {
|
||||
@ -257,7 +257,7 @@ describe("Abilities - Harvest", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toEqual([]);
|
||||
expect(game.field.getPlayerPokemon().battleData.berriesEaten).toEqual([]);
|
||||
expectBerriesContaining(...initBerries);
|
||||
});
|
||||
|
||||
@ -271,8 +271,8 @@ describe("Abilities - Harvest", () => {
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
// pluck triggers harvest for neither side
|
||||
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toEqual([]);
|
||||
expect(game.scene.getEnemyPokemon()?.battleData.berriesEaten).toEqual([]);
|
||||
expect(game.field.getPlayerPokemon().battleData.berriesEaten).toEqual([]);
|
||||
expect(game.field.getEnemyPokemon().battleData.berriesEaten).toEqual([]);
|
||||
expect(getPlayerBerries()).toEqual([]);
|
||||
});
|
||||
|
||||
@ -293,7 +293,7 @@ describe("Abilities - Harvest", () => {
|
||||
await game.phaseInterceptor.to("TurnEndPhase", false);
|
||||
|
||||
// won't trigger harvest since we didn't lose the berry (it just doesn't ever add it to the array)
|
||||
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toEqual([]);
|
||||
expect(game.field.getPlayerPokemon().battleData.berriesEaten).toEqual([]);
|
||||
expectBerriesContaining(...initBerries);
|
||||
});
|
||||
|
||||
@ -303,7 +303,7 @@ describe("Abilities - Harvest", () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MEOWSCARADA]);
|
||||
|
||||
// pre damage
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const player = game.field.getPlayerPokemon();
|
||||
player.hp = 1;
|
||||
|
||||
// steal a sitrus and immediately consume it
|
||||
@ -326,7 +326,7 @@ describe("Abilities - Harvest", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toBe([]);
|
||||
expect(game.field.getPlayerPokemon().battleData.berriesEaten).toBe([]);
|
||||
expect(getPlayerBerries()).toEqual([]);
|
||||
});
|
||||
|
||||
@ -339,7 +339,7 @@ describe("Abilities - Harvest", () => {
|
||||
game.move.select(MoveId.NATURAL_GIFT);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()?.battleData.berriesEaten).toHaveLength(0);
|
||||
expect(game.field.getPlayerPokemon().battleData.berriesEaten).toHaveLength(0);
|
||||
expectBerriesContaining(...initBerries);
|
||||
});
|
||||
});
|
||||
|
@ -46,7 +46,7 @@ describe("Abilities - Healer", () => {
|
||||
game.override.moveset([MoveId.SPLASH, MoveId.LUNAR_DANCE]);
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MAGIKARP]);
|
||||
|
||||
const user = game.scene.getPlayerPokemon()!;
|
||||
const user = game.field.getPlayerPokemon();
|
||||
// Only want one magikarp to have the ability
|
||||
vi.spyOn(user, "getAbility").mockReturnValue(allAbilities[AbilityId.HEALER]);
|
||||
game.move.select(MoveId.SPLASH);
|
||||
|
@ -40,7 +40,7 @@ describe("Abilities - Heatproof", () => {
|
||||
it("reduces Fire type damage by half", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
const initialHP = 1000;
|
||||
enemy.hp = initialHP;
|
||||
|
||||
@ -63,7 +63,7 @@ describe("Abilities - Heatproof", () => {
|
||||
game.override.enemyStatusEffect(StatusEffect.BURN).enemySpecies(SpeciesId.ABRA);
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.toNextTurn();
|
||||
|
@ -62,7 +62,7 @@ describe("Abilities - Honey Gather", () => {
|
||||
game.scene.money = 1000;
|
||||
|
||||
// something weird is going on with the test framework, so this is required to prevent a crash
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
vi.spyOn(enemy, "scene", "get").mockReturnValue(game.scene);
|
||||
// Expects next wave so run must succeed
|
||||
vi.spyOn(Overrides, "RUN_SUCCESS_OVERRIDE", "get").mockReturnValue(true);
|
||||
|
@ -35,7 +35,7 @@ describe("Abilities - Hustle", () => {
|
||||
|
||||
it("increases the user's Attack stat by 50%", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.PIKACHU]);
|
||||
const pikachu = game.scene.getPlayerPokemon()!;
|
||||
const pikachu = game.field.getPlayerPokemon();
|
||||
const atk = pikachu.stats[Stat.ATK];
|
||||
|
||||
vi.spyOn(pikachu, "getEffectiveStat");
|
||||
@ -49,7 +49,7 @@ describe("Abilities - Hustle", () => {
|
||||
|
||||
it("lowers the accuracy of the user's physical moves by 20%", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.PIKACHU]);
|
||||
const pikachu = game.scene.getPlayerPokemon()!;
|
||||
const pikachu = game.field.getPlayerPokemon();
|
||||
|
||||
vi.spyOn(pikachu, "getAccuracyMultiplier");
|
||||
|
||||
@ -61,7 +61,7 @@ describe("Abilities - Hustle", () => {
|
||||
|
||||
it("does not affect non-physical moves", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.PIKACHU]);
|
||||
const pikachu = game.scene.getPlayerPokemon()!;
|
||||
const pikachu = game.field.getPlayerPokemon();
|
||||
const spatk = pikachu.stats[Stat.SPATK];
|
||||
|
||||
vi.spyOn(pikachu, "getEffectiveStat");
|
||||
@ -78,8 +78,8 @@ describe("Abilities - Hustle", () => {
|
||||
game.override.startingLevel(100).enemyLevel(30);
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.PIKACHU]);
|
||||
const pikachu = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const pikachu = game.field.getPlayerPokemon();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
vi.spyOn(pikachu, "getAccuracyMultiplier");
|
||||
vi.spyOn(allMoves[MoveId.FISSURE], "calculateBattleAccuracy");
|
||||
|
@ -36,7 +36,7 @@ describe("Abilities - Hyper Cutter", () => {
|
||||
it("only prevents ATK drops", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.OCTOLOCK);
|
||||
await game.toNextTurn();
|
||||
|
@ -44,7 +44,7 @@ describe("Abilities - Ice Face", () => {
|
||||
|
||||
await game.phaseInterceptor.to(MoveEndPhase);
|
||||
|
||||
const eiscue = game.scene.getEnemyPokemon()!;
|
||||
const eiscue = game.field.getEnemyPokemon();
|
||||
|
||||
expect(eiscue.isFullHp()).toBe(true);
|
||||
expect(eiscue.formIndex).toBe(noiceForm);
|
||||
@ -57,7 +57,7 @@ describe("Abilities - Ice Face", () => {
|
||||
|
||||
game.move.select(MoveId.SURGING_STRIKES);
|
||||
|
||||
const eiscue = game.scene.getEnemyPokemon()!;
|
||||
const eiscue = game.field.getEnemyPokemon();
|
||||
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeDefined();
|
||||
|
||||
// First hit
|
||||
@ -85,7 +85,7 @@ describe("Abilities - Ice Face", () => {
|
||||
|
||||
await game.phaseInterceptor.to(MoveEndPhase);
|
||||
|
||||
const eiscue = game.scene.getEnemyPokemon()!;
|
||||
const eiscue = game.field.getEnemyPokemon();
|
||||
|
||||
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).not.toBe(undefined);
|
||||
expect(eiscue.formIndex).toBe(icefaceForm);
|
||||
@ -99,7 +99,7 @@ describe("Abilities - Ice Face", () => {
|
||||
|
||||
await game.phaseInterceptor.to(MoveEndPhase);
|
||||
|
||||
const eiscue = game.scene.getEnemyPokemon()!;
|
||||
const eiscue = game.field.getEnemyPokemon();
|
||||
|
||||
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).not.toBe(undefined);
|
||||
expect(eiscue.formIndex).toBe(icefaceForm);
|
||||
@ -114,7 +114,7 @@ describe("Abilities - Ice Face", () => {
|
||||
|
||||
await game.phaseInterceptor.to(MoveEndPhase);
|
||||
|
||||
const eiscue = game.scene.getEnemyPokemon()!;
|
||||
const eiscue = game.field.getEnemyPokemon();
|
||||
|
||||
expect(eiscue.isFullHp()).toBe(true);
|
||||
expect(eiscue.formIndex).toBe(noiceForm);
|
||||
@ -134,7 +134,7 @@ describe("Abilities - Ice Face", () => {
|
||||
game.move.select(MoveId.SNOWSCAPE);
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
let eiscue = game.scene.getPlayerPokemon()!;
|
||||
let eiscue = game.field.getPlayerPokemon();
|
||||
|
||||
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeUndefined();
|
||||
expect(eiscue.formIndex).toBe(noiceForm);
|
||||
@ -146,7 +146,7 @@ describe("Abilities - Ice Face", () => {
|
||||
game.doSwitchPokemon(1);
|
||||
|
||||
await game.phaseInterceptor.to(QuietFormChangePhase);
|
||||
eiscue = game.scene.getPlayerPokemon()!;
|
||||
eiscue = game.field.getPlayerPokemon();
|
||||
|
||||
expect(eiscue.formIndex).toBe(icefaceForm);
|
||||
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).not.toBe(undefined);
|
||||
@ -158,7 +158,7 @@ describe("Abilities - Ice Face", () => {
|
||||
await game.classicMode.startBattle([SpeciesId.EISCUE]);
|
||||
|
||||
game.move.select(MoveId.HAIL);
|
||||
const eiscue = game.scene.getPlayerPokemon()!;
|
||||
const eiscue = game.field.getPlayerPokemon();
|
||||
|
||||
await game.phaseInterceptor.to(QuietFormChangePhase);
|
||||
|
||||
@ -179,7 +179,7 @@ describe("Abilities - Ice Face", () => {
|
||||
game.move.select(MoveId.ICE_BEAM);
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
let eiscue = game.scene.getPlayerPokemon()!;
|
||||
let eiscue = game.field.getPlayerPokemon();
|
||||
|
||||
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeUndefined();
|
||||
expect(eiscue.formIndex).toBe(noiceForm);
|
||||
@ -206,7 +206,7 @@ describe("Abilities - Ice Face", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.EISCUE]);
|
||||
|
||||
const eiscue = game.scene.getPlayerPokemon()!;
|
||||
const eiscue = game.field.getPlayerPokemon();
|
||||
|
||||
expect(eiscue.formIndex).toBe(noiceForm);
|
||||
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeUndefined();
|
||||
@ -229,7 +229,7 @@ describe("Abilities - Ice Face", () => {
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(game.scene.getEnemyPokemon()!.formIndex).toBe(icefaceForm);
|
||||
expect(game.field.getEnemyPokemon().formIndex).toBe(icefaceForm);
|
||||
});
|
||||
|
||||
it("cannot be suppressed", async () => {
|
||||
@ -241,7 +241,7 @@ describe("Abilities - Ice Face", () => {
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
const eiscue = game.scene.getEnemyPokemon()!;
|
||||
const eiscue = game.field.getEnemyPokemon();
|
||||
|
||||
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).not.toBe(undefined);
|
||||
expect(eiscue.formIndex).toBe(icefaceForm);
|
||||
@ -257,7 +257,7 @@ describe("Abilities - Ice Face", () => {
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
const eiscue = game.scene.getEnemyPokemon()!;
|
||||
const eiscue = game.field.getEnemyPokemon();
|
||||
|
||||
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeDefined();
|
||||
expect(eiscue.formIndex).toBe(icefaceForm);
|
||||
@ -269,10 +269,10 @@ describe("Abilities - Ice Face", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const eiscue = game.scene.getEnemyPokemon()!;
|
||||
const eiscue = game.field.getEnemyPokemon();
|
||||
|
||||
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeDefined();
|
||||
expect(eiscue.formIndex).toBe(icefaceForm);
|
||||
expect(game.scene.getPlayerPokemon()!.hasAbility(AbilityId.TRACE)).toBe(true);
|
||||
expect(game.field.getPlayerPokemon().hasAbility(AbilityId.TRACE)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -33,7 +33,7 @@ describe("Abilities - Illuminate", () => {
|
||||
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const player = game.field.getPlayerPokemon();
|
||||
|
||||
expect(player.getStatStage(Stat.ACC)).toBe(0);
|
||||
|
||||
|
@ -35,8 +35,8 @@ describe("Abilities - Illusion", () => {
|
||||
|
||||
it("creates illusion at the start", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.FEEBAS]);
|
||||
const zoroark = game.scene.getPlayerPokemon()!;
|
||||
const zorua = game.scene.getEnemyPokemon()!;
|
||||
const zoroark = game.field.getPlayerPokemon();
|
||||
const zorua = game.field.getEnemyPokemon();
|
||||
|
||||
expect(!!zoroark.summonData.illusion).equals(true);
|
||||
expect(!!zorua.summonData.illusion).equals(true);
|
||||
@ -48,7 +48,7 @@ describe("Abilities - Illusion", () => {
|
||||
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
const zorua = game.scene.getEnemyPokemon()!;
|
||||
const zorua = game.field.getEnemyPokemon();
|
||||
|
||||
expect(!!zorua.summonData.illusion).equals(false);
|
||||
expect(zorua.name).equals("Zorua");
|
||||
@ -60,7 +60,7 @@ describe("Abilities - Illusion", () => {
|
||||
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
const zorua = game.scene.getEnemyPokemon()!;
|
||||
const zorua = game.field.getEnemyPokemon();
|
||||
|
||||
expect(!!zorua.summonData.illusion).equals(false);
|
||||
});
|
||||
@ -69,7 +69,7 @@ describe("Abilities - Illusion", () => {
|
||||
game.override.enemyAbility(AbilityId.NEUTRALIZING_GAS);
|
||||
await game.classicMode.startBattle([SpeciesId.KOFFING]);
|
||||
|
||||
const zorua = game.scene.getEnemyPokemon()!;
|
||||
const zorua = game.field.getEnemyPokemon();
|
||||
|
||||
expect(!!zorua.summonData.illusion).equals(false);
|
||||
});
|
||||
@ -85,15 +85,15 @@ describe("Abilities - Illusion", () => {
|
||||
game.doSwitchPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.summonData.illusion).toBeFalsy();
|
||||
expect(game.field.getPlayerPokemon().summonData.illusion).toBeFalsy();
|
||||
});
|
||||
|
||||
it("causes enemy AI to consider the illusion's type instead of the actual type when considering move effectiveness", async () => {
|
||||
game.override.enemyMoveset([MoveId.FLAMETHROWER, MoveId.PSYCHIC, MoveId.TACKLE]);
|
||||
await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.FEEBAS]);
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const zoroark = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
const zoroark = game.field.getPlayerPokemon();
|
||||
|
||||
const flameThrower = enemy.getMoveset()[0]!.getMove();
|
||||
const psychic = enemy.getMoveset()[1]!.getMove();
|
||||
@ -125,7 +125,7 @@ describe("Abilities - Illusion", () => {
|
||||
await game.move.forceEnemyMove(MoveId.WILL_O_WISP);
|
||||
await game.toEndOfTurn();
|
||||
|
||||
const zoroark = game.scene.getPlayerPokemon()!;
|
||||
const zoroark = game.field.getPlayerPokemon();
|
||||
expect(!!zoroark.summonData.illusion).equals(true);
|
||||
});
|
||||
|
||||
@ -143,7 +143,7 @@ describe("Abilities - Illusion", () => {
|
||||
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
const zoroark = game.scene.getPlayerPokemon()!;
|
||||
const zoroark = game.field.getPlayerPokemon();
|
||||
|
||||
expect(zoroark.summonData.illusion?.name).equals("Axew");
|
||||
expect(zoroark.getNameToRender(true)).equals("axew nickname");
|
||||
@ -155,7 +155,7 @@ describe("Abilities - Illusion", () => {
|
||||
it("breaks when suppressed", async () => {
|
||||
game.override.moveset(MoveId.GASTRO_ACID);
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
const zorua = game.scene.getEnemyPokemon()!;
|
||||
const zorua = game.field.getEnemyPokemon();
|
||||
|
||||
expect(!!zorua.summonData?.illusion).toBe(true);
|
||||
|
||||
|
@ -58,8 +58,8 @@ describe("Abilities - Infiltrator", () => {
|
||||
])("should bypass the target's $effectName", async ({ tagType, move }) => {
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const player = game.field.getPlayerPokemon();
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
const preScreenDmg = enemy.getAttackDamage({ source: player, move: allMoves[move] }).damage;
|
||||
|
||||
@ -74,8 +74,8 @@ describe("Abilities - Infiltrator", () => {
|
||||
it("should bypass the target's Safeguard", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const player = game.field.getPlayerPokemon();
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
game.scene.arena.addTag(ArenaTagType.SAFEGUARD, 1, MoveId.NONE, enemy.id, ArenaTagSide.ENEMY, true);
|
||||
|
||||
@ -90,8 +90,8 @@ describe("Abilities - Infiltrator", () => {
|
||||
it.todo("should bypass the target's Mist", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const player = game.field.getPlayerPokemon();
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
game.scene.arena.addTag(ArenaTagType.MIST, 1, MoveId.NONE, enemy.id, ArenaTagSide.ENEMY, true);
|
||||
|
||||
@ -105,8 +105,8 @@ describe("Abilities - Infiltrator", () => {
|
||||
it("should bypass the target's Substitute", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const player = game.field.getPlayerPokemon();
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
enemy.addTag(BattlerTagType.SUBSTITUTE, 1, MoveId.NONE, enemy.id);
|
||||
|
||||
|
@ -32,8 +32,8 @@ describe("Abilities - Intrepid Sword", () => {
|
||||
it("should raise ATK stat stage by 1 on entry", async () => {
|
||||
await game.classicMode.runToSummon([SpeciesId.ZACIAN]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
await game.phaseInterceptor.to(CommandPhase, false);
|
||||
|
||||
|
@ -42,7 +42,7 @@ describe("Abilities - Magic Bounce", () => {
|
||||
|
||||
game.move.use(MoveId.GROWL);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
expect(game.scene.getPlayerPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.ATK)).toBe(-1);
|
||||
});
|
||||
|
||||
it("should not bounce moves while the target is in the semi-invulnerable state", async () => {
|
||||
@ -53,7 +53,7 @@ describe("Abilities - Magic Bounce", () => {
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.getStatStage(Stat.ATK)).toBe(0);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.ATK)).toBe(0);
|
||||
});
|
||||
|
||||
it("should individually bounce back multi-target moves", async () => {
|
||||
@ -70,12 +70,12 @@ describe("Abilities - Magic Bounce", () => {
|
||||
|
||||
it("should still bounce back a move that would otherwise fail", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
game.scene.getEnemyPokemon()?.setStatStage(Stat.ATK, -6);
|
||||
game.field.getEnemyPokemon().setStatStage(Stat.ATK, -6);
|
||||
|
||||
game.move.use(MoveId.GROWL);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.ATK)).toBe(-1);
|
||||
});
|
||||
|
||||
it("should not bounce back a move that was just bounced", async () => {
|
||||
@ -85,7 +85,7 @@ describe("Abilities - Magic Bounce", () => {
|
||||
game.move.select(MoveId.GROWL);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.ATK)).toBe(-1);
|
||||
});
|
||||
|
||||
it("should receive the stat change after reflecting a move back to a mirror armor user", async () => {
|
||||
@ -95,7 +95,7 @@ describe("Abilities - Magic Bounce", () => {
|
||||
game.move.select(MoveId.GROWL);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
|
||||
expect(game.field.getEnemyPokemon().getStatStage(Stat.ATK)).toBe(-1);
|
||||
});
|
||||
|
||||
it("should not bounce back a move from a mold breaker user", async () => {
|
||||
@ -105,7 +105,7 @@ describe("Abilities - Magic Bounce", () => {
|
||||
game.move.use(MoveId.GROWL);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
|
||||
expect(game.field.getEnemyPokemon().getStatStage(Stat.ATK)).toBe(-1);
|
||||
});
|
||||
|
||||
it("should bounce back a spread status move against both pokemon", async () => {
|
||||
@ -156,7 +156,7 @@ describe("Abilities - Magic Bounce", () => {
|
||||
game.move.select(MoveId.CURSE);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getEnemyPokemon()!.getTag(BattlerTagType.CURSED)).toBeDefined();
|
||||
expect(game.field.getEnemyPokemon().getTag(BattlerTagType.CURSED)).toBeDefined();
|
||||
});
|
||||
|
||||
// TODO: enable when Magic Bounce is fixed to properly reset the hit count
|
||||
@ -164,8 +164,8 @@ describe("Abilities - Magic Bounce", () => {
|
||||
game.override.moveset([MoveId.SPLASH, MoveId.GROWL, MoveId.ENCORE]).enemyMoveset([MoveId.TACKLE, MoveId.GROWL]);
|
||||
// game.override.ability(AbilityId.MOLD_BREAKER);
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
// Give the player MOLD_BREAKER for this turn to bypass Magic Bounce.
|
||||
const playerAbilitySpy = game.field.mockAbility(playerPokemon, AbilityId.MOLD_BREAKER);
|
||||
@ -194,8 +194,8 @@ describe("Abilities - Magic Bounce", () => {
|
||||
.enemyAbility(AbilityId.MAGIC_BOUNCE);
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
// turn 1
|
||||
game.move.select(MoveId.GROWL);
|
||||
@ -237,7 +237,7 @@ describe("Abilities - Magic Bounce", () => {
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const stomping_tantrum = allMoves[MoveId.STOMPING_TANTRUM];
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
vi.spyOn(stomping_tantrum, "calculateBattlePower");
|
||||
|
||||
// Spore gets reflected back onto us
|
||||
@ -260,35 +260,35 @@ describe("Abilities - Magic Bounce", () => {
|
||||
// Turn 1 - thunder wave immunity test
|
||||
game.move.select(MoveId.THUNDER_WAVE);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
expect(game.scene.getPlayerPokemon()!.status).toBeUndefined();
|
||||
expect(game.field.getPlayerPokemon().status).toBeUndefined();
|
||||
|
||||
// Turn 2 - soundproof immunity test
|
||||
game.move.select(MoveId.GROWL);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
expect(game.scene.getPlayerPokemon()!.getStatStage(Stat.ATK)).toBe(0);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.ATK)).toBe(0);
|
||||
});
|
||||
|
||||
it("should bounce back a move before the accuracy check", async () => {
|
||||
game.override.moveset([MoveId.SPORE]);
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const attacker = game.scene.getPlayerPokemon()!;
|
||||
const attacker = game.field.getPlayerPokemon();
|
||||
|
||||
vi.spyOn(attacker, "getAccuracyMultiplier").mockReturnValue(0.0);
|
||||
game.move.select(MoveId.SPORE);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
expect(game.scene.getPlayerPokemon()!.status?.effect).toBe(StatusEffect.SLEEP);
|
||||
expect(game.field.getPlayerPokemon().status?.effect).toBe(StatusEffect.SLEEP);
|
||||
});
|
||||
|
||||
it("should take the accuracy of the magic bounce user into account", async () => {
|
||||
game.override.moveset([MoveId.SPORE]);
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
const opponent = game.scene.getEnemyPokemon()!;
|
||||
const opponent = game.field.getEnemyPokemon();
|
||||
|
||||
vi.spyOn(opponent, "getAccuracyMultiplier").mockReturnValue(0);
|
||||
game.move.select(MoveId.SPORE);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
expect(game.scene.getPlayerPokemon()!.status).toBeUndefined();
|
||||
expect(game.field.getPlayerPokemon().status).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should always apply the leftmost available target's magic bounce when bouncing moves like sticky webs in doubles", async () => {
|
||||
@ -332,14 +332,14 @@ describe("Abilities - Magic Bounce", () => {
|
||||
await game.move.selectEnemyMove(MoveId.FLY);
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.TOXIC);
|
||||
expect(game.scene.getPlayerPokemon()!.status).toBeUndefined();
|
||||
expect(game.field.getEnemyPokemon().status?.effect).toBe(StatusEffect.TOXIC);
|
||||
expect(game.field.getPlayerPokemon().status).toBeUndefined();
|
||||
|
||||
game.override.ability(AbilityId.NO_GUARD);
|
||||
game.move.select(MoveId.CHARM);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.ATK)).toBe(-2);
|
||||
expect(game.scene.getPlayerPokemon()!.getStatStage(Stat.ATK)).toBe(0);
|
||||
expect(game.field.getEnemyPokemon().getStatStage(Stat.ATK)).toBe(-2);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.ATK)).toBe(0);
|
||||
});
|
||||
});
|
||||
|
@ -47,44 +47,44 @@ describe("Abilities - Mimicry", () => {
|
||||
});
|
||||
|
||||
it("Pokemon should revert back to its original, root type once terrain ends", async () => {
|
||||
game.override
|
||||
.moveset([MoveId.SPLASH, MoveId.TRANSFORM])
|
||||
.enemyAbility(AbilityId.MIMICRY)
|
||||
.enemyMoveset([MoveId.SPLASH, MoveId.PSYCHIC_TERRAIN]);
|
||||
game.override.enemyAbility(AbilityId.MIMICRY);
|
||||
await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon();
|
||||
game.move.select(MoveId.TRANSFORM);
|
||||
await game.move.selectEnemyMove(MoveId.PSYCHIC_TERRAIN);
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.use(MoveId.SKILL_SWAP);
|
||||
await game.move.forceEnemyMove(MoveId.PSYCHIC_TERRAIN);
|
||||
await game.toNextTurn();
|
||||
expect(playerPokemon?.getTypes().includes(PokemonType.PSYCHIC)).toBe(true);
|
||||
|
||||
expect(playerPokemon.getTypes()).toEqual([PokemonType.PSYCHIC]);
|
||||
|
||||
if (game.scene.arena.terrain) {
|
||||
game.scene.arena.terrain.turnsLeft = 1;
|
||||
}
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.move.selectEnemyMove(MoveId.SPLASH);
|
||||
game.move.use(MoveId.SPLASH);
|
||||
await game.move.forceEnemyMove(MoveId.SPLASH);
|
||||
await game.toNextTurn();
|
||||
expect(playerPokemon?.getTypes().includes(PokemonType.ELECTRIC)).toBe(true);
|
||||
|
||||
expect(playerPokemon.getTypes()).toEqual([PokemonType.ELECTRIC]);
|
||||
});
|
||||
|
||||
it("If the Pokemon is under the effect of a type-adding move and an equivalent terrain activates, the move's effect disappears", async () => {
|
||||
game.override.enemyMoveset([MoveId.FORESTS_CURSE, MoveId.GRASSY_TERRAIN]);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon();
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.move.selectEnemyMove(MoveId.FORESTS_CURSE);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(playerPokemon?.summonData.addedType).toBe(PokemonType.GRASS);
|
||||
expect(playerPokemon.summonData.addedType).toBe(PokemonType.GRASS);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.move.selectEnemyMove(MoveId.GRASSY_TERRAIN);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(playerPokemon?.summonData.addedType).toBeNull();
|
||||
expect(playerPokemon?.getTypes().includes(PokemonType.GRASS)).toBe(true);
|
||||
expect(playerPokemon.summonData.addedType).toBeNull();
|
||||
expect(playerPokemon.getTypes()).toEqual([PokemonType.GRASS]);
|
||||
});
|
||||
});
|
||||
|
@ -40,8 +40,8 @@ describe("Ability - Mirror Armor", () => {
|
||||
game.override.ability(AbilityId.MIRROR_ARMOR).enemyAbility(AbilityId.INTIMIDATE);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const userPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const userPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
// Enemy has intimidate, enemy should lose -1 atk
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -56,8 +56,8 @@ describe("Ability - Mirror Armor", () => {
|
||||
game.override.enemyAbility(AbilityId.MIRROR_ARMOR).ability(AbilityId.INTIMIDATE);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const userPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const userPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
// Enemy has intimidate, enemy should lose -1 atk
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -112,8 +112,8 @@ describe("Ability - Mirror Armor", () => {
|
||||
game.override.ability(AbilityId.MIRROR_ARMOR).enemyAbility(AbilityId.INTIMIDATE);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const userPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const userPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
// Enemy has intimidate and uses tickle, enemy receives -2 atk and -1 defense
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -153,8 +153,8 @@ describe("Ability - Mirror Armor", () => {
|
||||
game.override.enemyAbility(AbilityId.MIRROR_ARMOR).ability(AbilityId.INTIMIDATE);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const userPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const userPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
// Enemy has intimidate and uses tickle, enemy receives -2 atk and -1 defense
|
||||
game.move.select(MoveId.TICKLE);
|
||||
@ -171,8 +171,8 @@ describe("Ability - Mirror Armor", () => {
|
||||
game.override.enemyAbility(AbilityId.WHITE_SMOKE).ability(AbilityId.MIRROR_ARMOR);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const userPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const userPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
// Enemy has intimidate and uses tickle, enemy has white smoke, no one loses stats
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -189,8 +189,8 @@ describe("Ability - Mirror Armor", () => {
|
||||
game.override.ability(AbilityId.WHITE_SMOKE).enemyAbility(AbilityId.MIRROR_ARMOR);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const userPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const userPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
// Enemy has intimidate and uses tickle, enemy has white smoke, no one loses stats
|
||||
game.move.select(MoveId.TICKLE);
|
||||
@ -207,8 +207,8 @@ describe("Ability - Mirror Armor", () => {
|
||||
game.override.ability(AbilityId.MIRROR_ARMOR);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const userPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const userPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
// Enemy uses octolock, player loses stats at end of turn
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -225,8 +225,8 @@ describe("Ability - Mirror Armor", () => {
|
||||
game.override.enemyAbility(AbilityId.MIRROR_ARMOR);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const userPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const userPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
// Player uses octolock, enemy loses stats at end of turn
|
||||
game.move.select(MoveId.OCTOLOCK);
|
||||
@ -243,8 +243,8 @@ describe("Ability - Mirror Armor", () => {
|
||||
game.override.enemyAbility(AbilityId.MIRROR_ARMOR).ability(AbilityId.MIRROR_ARMOR).ability(AbilityId.INTIMIDATE);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const userPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const userPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.move.selectEnemyMove(MoveId.SPLASH, BattlerIndex.PLAYER);
|
||||
@ -258,8 +258,8 @@ describe("Ability - Mirror Armor", () => {
|
||||
game.override.ability(AbilityId.MIRROR_ARMOR);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER, SpeciesId.SQUIRTLE]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const userPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const userPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.move.selectEnemyMove(MoveId.STICKY_WEB, BattlerIndex.PLAYER);
|
||||
|
@ -35,7 +35,7 @@ describe("Abilities - Moody", () => {
|
||||
it("should increase one stat stage by 2 and decrease a different stat stage by 1", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.toNextTurn();
|
||||
|
||||
@ -52,7 +52,7 @@ describe("Abilities - Moody", () => {
|
||||
it("should only increase one stat stage by 2 if all stat stages are at -6", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
// Set all stat stages to -6
|
||||
vi.spyOn(playerPokemon.summonData, "statStages", "get").mockReturnValue(new Array(BATTLE_STATS.length).fill(-6));
|
||||
@ -70,7 +70,7 @@ describe("Abilities - Moody", () => {
|
||||
it("should only decrease one stat stage by 1 stage if all stat stages are at 6", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
// Set all stat stages to 6
|
||||
vi.spyOn(playerPokemon.summonData, "statStages", "get").mockReturnValue(new Array(BATTLE_STATS.length).fill(6));
|
||||
|
@ -41,7 +41,7 @@ describe("Abilities - Moxie", () => {
|
||||
const moveToUse = MoveId.AERIAL_ACE;
|
||||
await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.MIGHTYENA]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||
|
||||
|
@ -37,7 +37,7 @@ describe("Abilities - Mummy", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getEnemyPokemon()?.getAbility().id).toBe(AbilityId.MUMMY);
|
||||
expect(game.field.getEnemyPokemon().getAbility().id).toBe(AbilityId.MUMMY);
|
||||
});
|
||||
|
||||
it("should not change the enemy's ability hit by a non-contact move", async () => {
|
||||
@ -47,6 +47,6 @@ describe("Abilities - Mummy", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getEnemyPokemon()?.getAbility().id).toBe(AbilityId.BALL_FETCH);
|
||||
expect(game.field.getEnemyPokemon().getAbility().id).toBe(AbilityId.BALL_FETCH);
|
||||
});
|
||||
});
|
||||
|
@ -42,12 +42,12 @@ describe("Abilities - Mycelium Might", () => {
|
||||
* https://www.smogon.com/forums/threads/scarlet-violet-battle-mechanics-research.3709545/page-24
|
||||
*/
|
||||
|
||||
it("will move last in its priority bracket and ignore protective abilities", async () => {
|
||||
it("should move last in its priority bracket and ignore protective abilities", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon();
|
||||
const playerIndex = game.scene.getPlayerPokemon()?.getBattlerIndex();
|
||||
const enemyIndex = enemyPokemon?.getBattlerIndex();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const playerIndex = game.field.getPlayerPokemon().getBattlerIndex();
|
||||
const enemyIndex = enemyPokemon.getBattlerIndex();
|
||||
|
||||
game.move.select(MoveId.BABY_DOLL_EYES);
|
||||
|
||||
@ -62,16 +62,16 @@ describe("Abilities - Mycelium Might", () => {
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
// Despite the opponent's ability (Clear Body), its ATK stat stage is still reduced.
|
||||
expect(enemyPokemon?.getStatStage(Stat.ATK)).toBe(-1);
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1);
|
||||
});
|
||||
|
||||
it("will still go first if a status move that is in a higher priority bracket than the opponent's move is used", async () => {
|
||||
it("should still go first if a status move that is in a higher priority bracket than the opponent's move is used", async () => {
|
||||
game.override.enemyMoveset(MoveId.TACKLE);
|
||||
await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon();
|
||||
const playerIndex = game.scene.getPlayerPokemon()?.getBattlerIndex();
|
||||
const enemyIndex = enemyPokemon?.getBattlerIndex();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const playerIndex = game.field.getPlayerPokemon().getBattlerIndex();
|
||||
const enemyIndex = enemyPokemon.getBattlerIndex();
|
||||
|
||||
game.move.select(MoveId.BABY_DOLL_EYES);
|
||||
|
||||
@ -85,14 +85,14 @@ describe("Abilities - Mycelium Might", () => {
|
||||
expect(commandOrder).toEqual([playerIndex, enemyIndex]);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
// Despite the opponent's ability (Clear Body), its ATK stat stage is still reduced.
|
||||
expect(enemyPokemon?.getStatStage(Stat.ATK)).toBe(-1);
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1);
|
||||
});
|
||||
|
||||
it("will not affect non-status moves", async () => {
|
||||
it("should not affect non-status moves", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
|
||||
|
||||
const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
|
||||
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
|
||||
const playerIndex = game.field.getPlayerPokemon().getBattlerIndex();
|
||||
const enemyIndex = game.field.getEnemyPokemon().getBattlerIndex();
|
||||
|
||||
game.move.select(MoveId.QUICK_ATTACK);
|
||||
|
||||
|
@ -46,7 +46,7 @@ describe("Abilities - Neutralizing Gas", () => {
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
// Intimidate is suppressed, so the attack stat should not be lowered
|
||||
expect(game.scene.getPlayerPokemon()?.getStatStage(Stat.ATK)).toBe(0);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.ATK)).toBe(0);
|
||||
});
|
||||
|
||||
it("should allow the user's passive to activate", async () => {
|
||||
@ -56,7 +56,7 @@ describe("Abilities - Neutralizing Gas", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()?.getStatStage(Stat.ATK)).toBe(1);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.ATK)).toBe(1);
|
||||
});
|
||||
|
||||
it.todo("should activate before other abilities", async () => {
|
||||
@ -68,7 +68,7 @@ describe("Abilities - Neutralizing Gas", () => {
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
// Intimidate is suppressed even when the user's speed is lower
|
||||
expect(game.scene.getPlayerPokemon()?.getStatStage(Stat.ATK)).toBe(0);
|
||||
expect(game.field.getPlayerPokemon().getStatStage(Stat.ATK)).toBe(0);
|
||||
});
|
||||
|
||||
it("should activate other abilities when removed", async () => {
|
||||
@ -79,15 +79,15 @@ describe("Abilities - Neutralizing Gas", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon();
|
||||
expect(enemyPokemon?.getStatStage(Stat.ATK)).toBe(0);
|
||||
expect(enemyPokemon?.getStatStage(Stat.DEF)).toBe(0);
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||
expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
// Enemy removes user's ability, so both abilities are activated
|
||||
expect(enemyPokemon?.getStatStage(Stat.ATK)).toBe(1);
|
||||
expect(enemyPokemon?.getStatStage(Stat.DEF)).toBe(1);
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||
expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(1);
|
||||
});
|
||||
|
||||
it("should not activate the user's other ability when removed", async () => {
|
||||
@ -95,13 +95,13 @@ describe("Abilities - Neutralizing Gas", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
// Neutralising gas user's passive is still active
|
||||
const enemyPokemon = game.scene.getEnemyPokemon();
|
||||
expect(enemyPokemon?.getStatStage(Stat.ATK)).toBe(-1);
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
// Intimidate did not reactivate after neutralizing gas was removed
|
||||
expect(enemyPokemon?.getStatStage(Stat.ATK)).toBe(-1);
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1);
|
||||
});
|
||||
|
||||
it("should only deactivate when all setters are off the field", async () => {
|
||||
@ -164,7 +164,7 @@ describe("Abilities - Neutralizing Gas", () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeDefined();
|
||||
|
||||
vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0);
|
||||
vi.spyOn(game.field.getPlayerPokemon(), "randBattleSeedInt").mockReturnValue(0);
|
||||
vi.spyOn(globalScene, "randBattleSeedInt").mockReturnValue(0);
|
||||
|
||||
const commandPhase = game.scene.phaseManager.getCurrentPhase() as CommandPhase;
|
||||
@ -178,7 +178,7 @@ describe("Abilities - Neutralizing Gas", () => {
|
||||
game.override.battleStyle("single").ability(AbilityId.NEUTRALIZING_GAS).enemyAbility(AbilityId.DELTA_STREAM);
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
const weatherChangeAttr = enemy.getAbilityAttrs("PostSummonWeatherChangeAbAttr", false)[0];
|
||||
const weatherChangeSpy = vi.spyOn(weatherChangeAttr, "apply");
|
||||
|
||||
@ -186,7 +186,7 @@ describe("Abilities - Neutralizing Gas", () => {
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.killPokemon(enemy);
|
||||
await game.killPokemon(game.scene.getPlayerPokemon()!);
|
||||
await game.killPokemon(game.field.getPlayerPokemon());
|
||||
|
||||
expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeUndefined();
|
||||
expect(weatherChangeSpy).not.toHaveBeenCalled();
|
||||
|
@ -58,10 +58,10 @@ describe.each([
|
||||
it(`should change Normal-type attacks to ${tyName} type and boost their power`, async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const typeSpy = vi.spyOn(playerPokemon, "getMoveType");
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const enemySpy = vi.spyOn(enemyPokemon, "getMoveEffectiveness");
|
||||
const powerSpy = vi.spyOn(allMoves[MoveId.TACKLE], "calculateBattlePower");
|
||||
|
||||
@ -103,10 +103,10 @@ describe.each([
|
||||
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const tySpy = vi.spyOn(playerPokemon, "getMoveType");
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const enemyEffectivenessSpy = vi.spyOn(enemyPokemon, "getMoveEffectiveness");
|
||||
|
||||
enemyPokemon.hp = Math.floor(enemyPokemon.getMaxHp() * 0.8);
|
||||
@ -137,7 +137,7 @@ describe.each([
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const tySpy = vi.spyOn(playerPokemon, "getMoveType");
|
||||
|
||||
game.move.select(move);
|
||||
@ -149,10 +149,10 @@ describe.each([
|
||||
it("should affect all hits of a Normal-type multi-hit move", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const tySpy = vi.spyOn(playerPokemon, "getMoveType");
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.FURY_SWIPES);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
@ -183,7 +183,7 @@ describe.each([
|
||||
expect(boost, "power boost should be defined").toBeDefined();
|
||||
|
||||
const powerSpy = vi.spyOn(testMoveInstance, "calculateBattlePower");
|
||||
const typeSpy = vi.spyOn(game.scene.getPlayerPokemon()!, "getMoveType");
|
||||
const typeSpy = vi.spyOn(game.field.getPlayerPokemon(), "getMoveType");
|
||||
game.move.select(MoveId.TACKLE);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
expect(typeSpy, "type was not changed").toHaveLastReturnedWith(ty);
|
||||
|
@ -39,14 +39,14 @@ describe("Abilities - Oblivious", () => {
|
||||
.moveset(MoveId.SKILL_SWAP)
|
||||
.enemyMoveset(MoveId.SPLASH);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
const enemy = game.scene.getEnemyPokemon();
|
||||
enemy?.addTag(BattlerTagType.TAUNT);
|
||||
expect(enemy?.getTag(BattlerTagType.TAUNT)).toBeTruthy();
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
enemy.addTag(BattlerTagType.TAUNT);
|
||||
expect(enemy.getTag(BattlerTagType.TAUNT)).toBeDefined();
|
||||
|
||||
game.move.select(MoveId.SKILL_SWAP);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(enemy?.getTag(BattlerTagType.TAUNT)).toBeFalsy();
|
||||
expect(enemy.getTag(BattlerTagType.TAUNT)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should remove infatuation when gained", async () => {
|
||||
@ -56,14 +56,15 @@ describe("Abilities - Oblivious", () => {
|
||||
.moveset(MoveId.SKILL_SWAP)
|
||||
.enemyMoveset(MoveId.SPLASH);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
const enemy = game.scene.getEnemyPokemon();
|
||||
vi.spyOn(enemy!, "isOppositeGender").mockReturnValue(true);
|
||||
enemy?.addTag(BattlerTagType.INFATUATED, 5, MoveId.JUDGMENT, game.scene.getPlayerPokemon()?.id); // sourceID needs to be defined
|
||||
expect(enemy?.getTag(BattlerTagType.INFATUATED)).toBeTruthy();
|
||||
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
vi.spyOn(enemy, "isOppositeGender").mockReturnValue(true);
|
||||
enemy.addTag(BattlerTagType.INFATUATED, 5, MoveId.JUDGMENT, game.field.getPlayerPokemon().id); // sourceID needs to be defined
|
||||
expect(enemy.getTag(BattlerTagType.INFATUATED)).toBeTruthy();
|
||||
|
||||
game.move.select(MoveId.SKILL_SWAP);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(enemy?.getTag(BattlerTagType.INFATUATED)).toBeFalsy();
|
||||
expect(enemy.getTag(BattlerTagType.INFATUATED)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
@ -42,8 +42,8 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
let enemyStartingHp = enemyPokemon.hp;
|
||||
|
||||
@ -66,7 +66,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.POWER_UP_PUNCH);
|
||||
|
||||
@ -81,7 +81,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.BABY_DOLL_EYES);
|
||||
|
||||
@ -95,7 +95,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.DOUBLE_HIT);
|
||||
await game.move.forceHit();
|
||||
@ -110,7 +110,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.SELF_DESTRUCT);
|
||||
|
||||
@ -124,7 +124,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.ROLLOUT);
|
||||
await game.move.forceHit();
|
||||
@ -139,7 +139,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.DRAGON_RAGE);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
@ -152,8 +152,8 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.SHUCKLE]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.COUNTER);
|
||||
await game.phaseInterceptor.to("DamageAnimPhase");
|
||||
@ -185,7 +185,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.EARTHQUAKE);
|
||||
await game.phaseInterceptor.to("DamageAnimPhase", false);
|
||||
@ -199,7 +199,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.MIND_BLOWN);
|
||||
|
||||
@ -218,8 +218,8 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.CHARIZARD]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.BURN_UP);
|
||||
|
||||
@ -239,7 +239,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.HYPER_BEAM);
|
||||
await game.move.forceHit();
|
||||
@ -259,8 +259,8 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.ANCHOR_SHOT);
|
||||
await game.move.forceHit();
|
||||
@ -283,8 +283,8 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.SMACK_DOWN);
|
||||
await game.move.forceHit();
|
||||
@ -304,7 +304,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.BLASTOISE]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.U_TURN);
|
||||
await game.move.forceHit();
|
||||
@ -321,8 +321,8 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.WAKE_UP_SLAP);
|
||||
await game.move.forceHit();
|
||||
@ -342,7 +342,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.TACKLE);
|
||||
|
||||
@ -356,7 +356,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.WATER_GUN);
|
||||
|
||||
@ -369,7 +369,7 @@ describe("Abilities - Parental Bond", () => {
|
||||
game.override.enemyLevel(1000).moveset(MoveId.FUTURE_SIGHT);
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER, SpeciesId.SQUIRTLE]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
vi.spyOn(enemyPokemon, "damageAndUpdate");
|
||||
|
||||
game.move.select(MoveId.FUTURE_SIGHT);
|
||||
|
@ -34,55 +34,55 @@ describe("Abilities - Perish Song", () => {
|
||||
|
||||
it("should trigger when hit with damaging move", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
const cursola = game.scene.getPlayerPokemon();
|
||||
const magikarp = game.scene.getEnemyPokemon();
|
||||
const cursola = game.field.getPlayerPokemon();
|
||||
const magikarp = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(cursola?.summonData.tags[0].turnCount).toBe(3);
|
||||
expect(magikarp?.summonData.tags[0].turnCount).toBe(3);
|
||||
expect(cursola.summonData.tags[0].turnCount).toBe(3);
|
||||
expect(magikarp.summonData.tags[0].turnCount).toBe(3);
|
||||
});
|
||||
|
||||
it("should trigger even when fainting", async () => {
|
||||
game.override.enemyLevel(100).startingLevel(1);
|
||||
await game.classicMode.startBattle([SpeciesId.CURSOLA, SpeciesId.FEEBAS]);
|
||||
const magikarp = game.scene.getEnemyPokemon();
|
||||
const magikarp = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(magikarp?.summonData.tags[0].turnCount).toBe(3);
|
||||
expect(magikarp.summonData.tags[0].turnCount).toBe(3);
|
||||
});
|
||||
|
||||
it("should not activate if attacker already has perish song", async () => {
|
||||
game.override.enemyMoveset([MoveId.PERISH_SONG, MoveId.AQUA_JET, MoveId.SPLASH]);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS, SpeciesId.CURSOLA]);
|
||||
const feebas = game.scene.getPlayerPokemon();
|
||||
const magikarp = game.scene.getEnemyPokemon();
|
||||
const feebas = game.field.getPlayerPokemon();
|
||||
const magikarp = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.move.selectEnemyMove(MoveId.PERISH_SONG);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(feebas?.summonData.tags[0].turnCount).toBe(3);
|
||||
expect(magikarp?.summonData.tags[0].turnCount).toBe(3);
|
||||
expect(feebas.summonData.tags[0].turnCount).toBe(3);
|
||||
expect(magikarp.summonData.tags[0].turnCount).toBe(3);
|
||||
|
||||
game.doSwitchPokemon(1);
|
||||
await game.move.selectEnemyMove(MoveId.SPLASH);
|
||||
await game.toNextTurn();
|
||||
|
||||
const cursola = game.scene.getPlayerPokemon();
|
||||
expect(cursola?.summonData.tags.length).toBe(0);
|
||||
expect(magikarp?.summonData.tags[0].turnCount).toBe(2);
|
||||
const cursola = game.field.getPlayerPokemon();
|
||||
expect(cursola.summonData.tags.length).toBe(0);
|
||||
expect(magikarp.summonData.tags[0].turnCount).toBe(2);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.move.selectEnemyMove(MoveId.AQUA_JET);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(cursola?.summonData.tags.length).toBe(0);
|
||||
expect(magikarp?.summonData.tags[0].turnCount).toBe(1);
|
||||
expect(cursola.summonData.tags.length).toBe(0);
|
||||
expect(magikarp.summonData.tags[0].turnCount).toBe(1);
|
||||
});
|
||||
|
||||
it("should activate if cursola already has perish song, but not reset its counter", async () => {
|
||||
@ -91,22 +91,22 @@ describe("Abilities - Perish Song", () => {
|
||||
.moveset([MoveId.WHIRLWIND, MoveId.SPLASH])
|
||||
.startingWave(5);
|
||||
await game.classicMode.startBattle([SpeciesId.CURSOLA]);
|
||||
const cursola = game.scene.getPlayerPokemon();
|
||||
const cursola = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(MoveId.WHIRLWIND);
|
||||
await game.move.selectEnemyMove(MoveId.PERISH_SONG);
|
||||
await game.toNextTurn();
|
||||
|
||||
const magikarp = game.scene.getEnemyPokemon();
|
||||
expect(cursola?.summonData.tags[0].turnCount).toBe(3);
|
||||
expect(magikarp?.summonData.tags.length).toBe(0);
|
||||
const magikarp = game.field.getEnemyPokemon();
|
||||
expect(cursola.summonData.tags[0].turnCount).toBe(3);
|
||||
expect(magikarp.summonData.tags.length).toBe(0);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.move.selectEnemyMove(MoveId.AQUA_JET);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(cursola?.summonData.tags[0].turnCount).toBe(2);
|
||||
expect(magikarp?.summonData.tags.length).toBe(1);
|
||||
expect(magikarp?.summonData.tags[0].turnCount).toBe(3);
|
||||
expect(cursola.summonData.tags[0].turnCount).toBe(2);
|
||||
expect(magikarp.summonData.tags.length).toBe(1);
|
||||
expect(magikarp.summonData.tags[0].turnCount).toBe(3);
|
||||
});
|
||||
});
|
||||
|
@ -42,10 +42,10 @@ describe("Abilities - Protosynthesis", () => {
|
||||
.startingLevel(100)
|
||||
.enemyLevel(100);
|
||||
await game.classicMode.startBattle([SpeciesId.MEW]);
|
||||
const mew = game.scene.getPlayerPokemon()!;
|
||||
const mew = game.field.getPlayerPokemon();
|
||||
// Nature of starting mon is randomized. We need to fix it to a neutral nature for the automated test.
|
||||
mew.setNature(Nature.HARDY);
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
const def_before_boost = mew.getEffectiveStat(
|
||||
Stat.DEF,
|
||||
undefined,
|
||||
|
@ -43,8 +43,8 @@ describe("Abilities - Quick Draw", () => {
|
||||
test("makes pokemon going first in its priority bracket", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const pokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const pokemon = game.field.getPlayerPokemon();
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
pokemon.hp = 1;
|
||||
enemy.hp = 1;
|
||||
@ -65,8 +65,8 @@ describe("Abilities - Quick Draw", () => {
|
||||
async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const pokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const pokemon = game.field.getPlayerPokemon();
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
pokemon.hp = 1;
|
||||
enemy.hp = 1;
|
||||
@ -85,8 +85,8 @@ describe("Abilities - Quick Draw", () => {
|
||||
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const pokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const pokemon = game.field.getPlayerPokemon();
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
|
||||
pokemon.hp = 1;
|
||||
enemy.hp = 1;
|
||||
|
@ -45,7 +45,7 @@ describe("Abilities - Sap Sipper", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const initialEnemyHp = enemyPokemon.hp;
|
||||
|
||||
game.move.select(moveToUse);
|
||||
@ -63,7 +63,7 @@ describe("Abilities - Sap Sipper", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(moveToUse);
|
||||
|
||||
@ -86,7 +86,7 @@ describe("Abilities - Sap Sipper", () => {
|
||||
|
||||
expect(game.scene.arena.terrain).toBeDefined();
|
||||
expect(game.scene.arena.terrain!.terrainType).toBe(TerrainType.GRASSY);
|
||||
expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.ATK)).toBe(0);
|
||||
expect(game.field.getEnemyPokemon().getStatStage(Stat.ATK)).toBe(0);
|
||||
});
|
||||
|
||||
it("activate once against multi-hit grass attacks", async () => {
|
||||
@ -96,7 +96,7 @@ describe("Abilities - Sap Sipper", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const initialEnemyHp = enemyPokemon.hp;
|
||||
|
||||
game.move.select(moveToUse);
|
||||
@ -114,7 +114,7 @@ describe("Abilities - Sap Sipper", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.select(moveToUse);
|
||||
|
||||
@ -140,7 +140,7 @@ describe("Abilities - Sap Sipper", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const initialEnemyHp = enemyPokemon.hp;
|
||||
|
||||
game.move.select(moveToUse);
|
||||
@ -156,7 +156,7 @@ describe("Abilities - Sap Sipper", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.LEAF_BLADE);
|
||||
await game.phaseInterceptor.to("MoveEffectPhase");
|
||||
|
@ -38,8 +38,8 @@ describe("Abilities - Shield Dust", () => {
|
||||
it("Shield Dust", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.PIDGEOT]);
|
||||
|
||||
game.scene.getEnemyPokemon()!.stats[Stat.SPDEF] = 10000;
|
||||
expect(game.scene.getPlayerPokemon()!.formIndex).toBe(0);
|
||||
game.field.getEnemyPokemon().stats[Stat.SPDEF] = 10000;
|
||||
expect(game.field.getPlayerPokemon().formIndex).toBe(0);
|
||||
|
||||
game.move.select(MoveId.AIR_SLASH);
|
||||
|
||||
|
@ -66,7 +66,7 @@ describe("Abilities - SHIELDS DOWN", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.status).toBe(undefined);
|
||||
expect(game.field.getPlayerPokemon().status).toBe(undefined);
|
||||
});
|
||||
|
||||
test("should still ignore non-volatile status moves used by a pokemon with mold breaker", async () => {
|
||||
@ -78,7 +78,7 @@ describe("Abilities - SHIELDS DOWN", () => {
|
||||
await game.move.selectEnemyMove(MoveId.SPORE);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.status).toBe(undefined);
|
||||
expect(game.field.getPlayerPokemon().status).toBe(undefined);
|
||||
});
|
||||
|
||||
test("should ignore non-volatile secondary status effects", async () => {
|
||||
@ -89,7 +89,7 @@ describe("Abilities - SHIELDS DOWN", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.status).toBe(undefined);
|
||||
expect(game.field.getPlayerPokemon().status).toBe(undefined);
|
||||
});
|
||||
|
||||
test("should ignore status moves even through mold breaker", async () => {
|
||||
@ -101,7 +101,7 @@ describe("Abilities - SHIELDS DOWN", () => {
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.status).toBe(undefined);
|
||||
expect(game.field.getPlayerPokemon().status).toBe(undefined);
|
||||
});
|
||||
|
||||
// toxic spikes currently does not poison flying types when gravity is in effect
|
||||
@ -122,9 +122,9 @@ describe("Abilities - SHIELDS DOWN", () => {
|
||||
await game.move.selectEnemyMove(MoveId.SPLASH);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(SpeciesId.MINIOR);
|
||||
expect(game.scene.getPlayerPokemon()!.species.formIndex).toBe(0);
|
||||
expect(game.scene.getPlayerPokemon()!.status?.effect).toBe(StatusEffect.POISON);
|
||||
expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.MINIOR);
|
||||
expect(game.field.getPlayerPokemon().species.formIndex).toBe(0);
|
||||
expect(game.field.getPlayerPokemon().status?.effect).toBe(StatusEffect.POISON);
|
||||
});
|
||||
|
||||
test("should ignore yawn", async () => {
|
||||
@ -136,7 +136,7 @@ describe("Abilities - SHIELDS DOWN", () => {
|
||||
await game.move.selectEnemyMove(MoveId.YAWN);
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
expect(game.scene.getPlayerPokemon()!.findTag(tag => tag.tagType === BattlerTagType.DROWSY)).toBe(undefined);
|
||||
expect(game.field.getPlayerPokemon().findTag(tag => tag.tagType === BattlerTagType.DROWSY)).toBe(undefined);
|
||||
});
|
||||
|
||||
test("should not ignore volatile status effects", async () => {
|
||||
@ -149,7 +149,7 @@ describe("Abilities - SHIELDS DOWN", () => {
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.findTag(tag => tag.tagType === BattlerTagType.CONFUSED)).not.toBe(undefined);
|
||||
expect(game.field.getPlayerPokemon().findTag(tag => tag.tagType === BattlerTagType.CONFUSED)).not.toBe(undefined);
|
||||
});
|
||||
|
||||
// the `NoTransformAbilityAbAttr` attribute is not checked anywhere, so this test cannot pass.
|
||||
@ -162,7 +162,7 @@ describe("Abilities - SHIELDS DOWN", () => {
|
||||
await game.move.selectEnemyMove(MoveId.SPLASH);
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.SLEEP);
|
||||
expect(game.field.getEnemyPokemon().status?.effect).toBe(StatusEffect.SLEEP);
|
||||
});
|
||||
|
||||
test("should not prevent minior from receiving the fainted status effect in trainer battles", async () => {
|
||||
@ -173,7 +173,7 @@ describe("Abilities - SHIELDS DOWN", () => {
|
||||
.startingWave(5)
|
||||
.enemySpecies(SpeciesId.MINIOR);
|
||||
await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
|
||||
const minior = game.scene.getEnemyPokemon()!;
|
||||
const minior = game.field.getEnemyPokemon();
|
||||
|
||||
game.move.select(MoveId.THUNDERBOLT);
|
||||
await game.toNextTurn();
|
||||
|
@ -33,7 +33,7 @@ describe("Abilities - Simple", () => {
|
||||
it("should double stat changes when applied", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.SLOWBRO]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
|
||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-2);
|
||||
});
|
||||
|
@ -40,7 +40,7 @@ describe("Abilities - Speed Boost", () => {
|
||||
it("should increase speed by 1 stage at end of turn", async () => {
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.toNextTurn();
|
||||
|
||||
@ -53,7 +53,7 @@ describe("Abilities - Speed Boost", () => {
|
||||
game.move.select(MoveId.U_TURN);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
expect(playerPokemon.getStatStage(Stat.SPD)).toBe(0);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -69,13 +69,13 @@ describe("Abilities - Speed Boost", () => {
|
||||
game.move.select(MoveId.U_TURN);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
expect(game.scene.getPlayerPokemon()!).toBe(ninjask);
|
||||
expect(game.field.getPlayerPokemon()).toBe(ninjask);
|
||||
expect(ninjask.getStatStage(Stat.SPD)).toBe(0);
|
||||
|
||||
game.move.select(MoveId.U_TURN);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.toNextTurn();
|
||||
expect(game.scene.getPlayerPokemon()!).toBe(shuckle);
|
||||
expect(game.field.getPlayerPokemon()).toBe(shuckle);
|
||||
expect(shuckle.getStatStage(Stat.SPD)).toBe(0);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -88,7 +88,7 @@ describe("Abilities - Speed Boost", () => {
|
||||
|
||||
game.doSwitchPokemon(1);
|
||||
await game.toNextTurn();
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
expect(playerPokemon.getStatStage(Stat.SPD)).toBe(0);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -109,7 +109,7 @@ describe("Abilities - Speed Boost", () => {
|
||||
await game.phaseInterceptor.to(AttemptRunPhase);
|
||||
await game.toNextTurn();
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
expect(playerPokemon.getStatStage(Stat.SPD)).toBe(0);
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
|
@ -40,8 +40,8 @@ describe("Abilities - Stall", () => {
|
||||
it("Pokemon with Stall should move last in its priority bracket regardless of speed", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.SHUCKLE]);
|
||||
|
||||
const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
|
||||
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
|
||||
const playerIndex = game.field.getPlayerPokemon().getBattlerIndex();
|
||||
const enemyIndex = game.field.getEnemyPokemon().getBattlerIndex();
|
||||
|
||||
game.move.select(MoveId.QUICK_ATTACK);
|
||||
|
||||
@ -58,8 +58,8 @@ describe("Abilities - Stall", () => {
|
||||
it("Pokemon with Stall will go first if a move that is in a higher priority bracket than the opponent's move is used", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.SHUCKLE]);
|
||||
|
||||
const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
|
||||
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
|
||||
const playerIndex = game.field.getPlayerPokemon().getBattlerIndex();
|
||||
const enemyIndex = game.field.getEnemyPokemon().getBattlerIndex();
|
||||
|
||||
game.move.select(MoveId.TACKLE);
|
||||
|
||||
@ -77,8 +77,8 @@ describe("Abilities - Stall", () => {
|
||||
game.override.ability(AbilityId.STALL);
|
||||
await game.classicMode.startBattle([SpeciesId.SHUCKLE]);
|
||||
|
||||
const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
|
||||
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
|
||||
const playerIndex = game.field.getPlayerPokemon().getBattlerIndex();
|
||||
const enemyIndex = game.field.getEnemyPokemon().getBattlerIndex();
|
||||
|
||||
game.move.select(MoveId.TACKLE);
|
||||
|
||||
|
@ -39,7 +39,7 @@ describe("Abilities - Steely Spirit", () => {
|
||||
it("increases Steel-type moves' power used by the user and its allies by 50%", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.PIKACHU, SpeciesId.SHUCKLE]);
|
||||
const boostSource = game.scene.getPlayerField()[1];
|
||||
const enemyToCheck = game.scene.getEnemyPokemon()!;
|
||||
const enemyToCheck = game.field.getEnemyPokemon();
|
||||
|
||||
vi.spyOn(boostSource, "getAbility").mockReturnValue(allAbilities[AbilityId.STEELY_SPIRIT]);
|
||||
|
||||
@ -54,7 +54,7 @@ describe("Abilities - Steely Spirit", () => {
|
||||
|
||||
it("stacks if multiple users with this ability are on the field.", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.PIKACHU, SpeciesId.PIKACHU]);
|
||||
const enemyToCheck = game.scene.getEnemyPokemon()!;
|
||||
const enemyToCheck = game.field.getEnemyPokemon();
|
||||
|
||||
game.scene.getPlayerField().forEach(p => {
|
||||
vi.spyOn(p, "getAbility").mockReturnValue(allAbilities[AbilityId.STEELY_SPIRIT]);
|
||||
@ -74,7 +74,7 @@ describe("Abilities - Steely Spirit", () => {
|
||||
it("does not take effect when suppressed", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.PIKACHU, SpeciesId.SHUCKLE]);
|
||||
const boostSource = game.scene.getPlayerField()[1];
|
||||
const enemyToCheck = game.scene.getEnemyPokemon()!;
|
||||
const enemyToCheck = game.field.getEnemyPokemon();
|
||||
|
||||
vi.spyOn(boostSource, "getAbility").mockReturnValue(allAbilities[AbilityId.STEELY_SPIRIT]);
|
||||
expect(boostSource.hasAbility(AbilityId.STEELY_SPIRIT)).toBe(true);
|
||||
|
@ -32,7 +32,7 @@ describe("Abilities - Super Luck", () => {
|
||||
|
||||
it("should increase the user's crit stage by 1", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
const enemy = game.field.getEnemyPokemon();
|
||||
const critSpy = vi.spyOn(enemy, "getCritStage"); // crit stage is called on enemy
|
||||
|
||||
game.move.select(MoveId.TACKLE);
|
||||
|
@ -38,7 +38,7 @@ describe("Abilities - Synchronize", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.status).toBeUndefined();
|
||||
expect(game.field.getPlayerPokemon().status).toBeUndefined();
|
||||
expect(game.phaseInterceptor.log).not.toContain("ShowAbilityPhase");
|
||||
});
|
||||
|
||||
@ -48,8 +48,8 @@ describe("Abilities - Synchronize", () => {
|
||||
game.move.select(MoveId.THUNDER_WAVE);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.status?.effect).toBe(StatusEffect.PARALYSIS);
|
||||
expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.PARALYSIS);
|
||||
expect(game.field.getPlayerPokemon().status?.effect).toBe(StatusEffect.PARALYSIS);
|
||||
expect(game.field.getEnemyPokemon().status?.effect).toBe(StatusEffect.PARALYSIS);
|
||||
expect(game.phaseInterceptor.log).toContain("ShowAbilityPhase");
|
||||
});
|
||||
|
||||
@ -60,8 +60,8 @@ describe("Abilities - Synchronize", () => {
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.status?.effect).toBeUndefined();
|
||||
expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.SLEEP);
|
||||
expect(game.field.getPlayerPokemon().status?.effect).toBeUndefined();
|
||||
expect(game.field.getEnemyPokemon().status?.effect).toBe(StatusEffect.SLEEP);
|
||||
expect(game.phaseInterceptor.log).not.toContain("ShowAbilityPhase");
|
||||
});
|
||||
|
||||
@ -76,8 +76,8 @@ describe("Abilities - Synchronize", () => {
|
||||
game.doSwitchPokemon(1);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.status?.effect).toBe(StatusEffect.POISON);
|
||||
expect(game.scene.getEnemyPokemon()!.status?.effect).toBeUndefined();
|
||||
expect(game.field.getPlayerPokemon().status?.effect).toBe(StatusEffect.POISON);
|
||||
expect(game.field.getEnemyPokemon().status?.effect).toBeUndefined();
|
||||
expect(game.phaseInterceptor.log).not.toContain("ShowAbilityPhase");
|
||||
});
|
||||
|
||||
@ -87,8 +87,8 @@ describe("Abilities - Synchronize", () => {
|
||||
game.move.select(MoveId.THUNDER_WAVE);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!.status?.effect).toBeUndefined();
|
||||
expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.PARALYSIS);
|
||||
expect(game.field.getPlayerPokemon().status?.effect).toBeUndefined();
|
||||
expect(game.field.getEnemyPokemon().status?.effect).toBe(StatusEffect.PARALYSIS);
|
||||
expect(game.phaseInterceptor.log).toContain("ShowAbilityPhase");
|
||||
});
|
||||
});
|
||||
|
@ -36,7 +36,7 @@ describe("Abilities - Tera Shell", () => {
|
||||
it("should change the effectiveness of non-resisted attacks when the source is at full HP", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.SNORLAX]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
vi.spyOn(playerPokemon, "getMoveEffectiveness");
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -57,7 +57,7 @@ describe("Abilities - Tera Shell", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.SNORLAX]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
vi.spyOn(playerPokemon, "getMoveEffectiveness");
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -71,7 +71,7 @@ describe("Abilities - Tera Shell", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.AGGRON]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
vi.spyOn(playerPokemon, "getMoveEffectiveness");
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -85,7 +85,7 @@ describe("Abilities - Tera Shell", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.CHARIZARD]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const spy = vi.spyOn(playerPokemon, "getMoveEffectiveness");
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
@ -100,7 +100,7 @@ describe("Abilities - Tera Shell", () => {
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.SNORLAX]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const spy = vi.spyOn(playerPokemon, "getMoveEffectiveness");
|
||||
|
||||
game.move.select(MoveId.SPLASH);
|
||||
|
@ -38,7 +38,7 @@ describe("Abilities - Trace", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getPlayerPokemon()?.getAbility().id).toBe(AbilityId.BALL_FETCH);
|
||||
expect(game.field.getPlayerPokemon().getAbility().id).toBe(AbilityId.BALL_FETCH);
|
||||
});
|
||||
|
||||
it("should activate a copied post-summon ability", async () => {
|
||||
@ -48,6 +48,6 @@ describe("Abilities - Trace", () => {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(game.scene.getEnemyPokemon()?.getStatStage(Stat.ATK)).toBe(-1);
|
||||
expect(game.field.getEnemyPokemon().getStatStage(Stat.ATK)).toBe(-1);
|
||||
});
|
||||
});
|
||||
|
@ -64,7 +64,7 @@ describe("Abilities - Unburden", () => {
|
||||
game.override.enemyMoveset(MoveId.FALSE_SWIPE);
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const playerHeldItems = getHeldItemCount(playerPokemon);
|
||||
const initialPlayerSpeed = playerPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -80,7 +80,7 @@ describe("Abilities - Unburden", () => {
|
||||
game.override.enemyMoveset(MoveId.FALSE_SWIPE).startingModifier([{ name: "BERRY_POUCH", count: 5850 }]);
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const playerHeldItems = getHeldItemCount(playerPokemon);
|
||||
const initialPlayerSpeed = playerPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -95,9 +95,9 @@ describe("Abilities - Unburden", () => {
|
||||
it("should activate for the target, and not the stealer, when a berry is stolen", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const initialPlayerSpeed = playerPokemon.getStat(Stat.SPD);
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const enemyHeldItemCt = getHeldItemCount(enemyPokemon);
|
||||
const initialEnemySpeed = enemyPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -113,7 +113,7 @@ describe("Abilities - Unburden", () => {
|
||||
it("should activate when an item is knocked off", async () => {
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const enemyHeldItemCt = getHeldItemCount(enemyPokemon);
|
||||
const initialEnemySpeed = enemyPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -129,7 +129,7 @@ describe("Abilities - Unburden", () => {
|
||||
game.override.ability(AbilityId.MAGICIAN).startingHeldItems([]); // Remove player's full stacks of held items so it can steal opponent's held items
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const enemyHeldItemCt = getHeldItemCount(enemyPokemon);
|
||||
const initialEnemySpeed = enemyPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -145,7 +145,7 @@ describe("Abilities - Unburden", () => {
|
||||
game.override.enemyAbility(AbilityId.PICKPOCKET).enemyHeldItems([]); // Remove opponent's full stacks of held items so it can steal player's held items
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const playerHeldItems = getHeldItemCount(playerPokemon);
|
||||
const initialPlayerSpeed = playerPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -161,7 +161,7 @@ describe("Abilities - Unburden", () => {
|
||||
game.override.moveset(MoveId.THIEF).startingHeldItems([]); // Remove player's full stacks of held items so it can steal opponent's held items
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const enemyHeldItemCt = getHeldItemCount(enemyPokemon);
|
||||
const initialEnemySpeed = enemyPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -177,11 +177,11 @@ describe("Abilities - Unburden", () => {
|
||||
game.override.startingHeldItems([{ name: "GRIP_CLAW", count: 1 }]);
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const gripClaw = playerPokemon.getHeldItems()[0] as ContactHeldItemTransferChanceModifier;
|
||||
vi.spyOn(gripClaw, "chance", "get").mockReturnValue(100);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
const enemyHeldItemCt = getHeldItemCount(enemyPokemon);
|
||||
const initialEnemySpeed = enemyPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -197,7 +197,7 @@ describe("Abilities - Unburden", () => {
|
||||
game.override.enemyAbility(AbilityId.NEUTRALIZING_GAS).enemyMoveset(MoveId.FALSE_SWIPE);
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const playerHeldItems = getHeldItemCount(playerPokemon);
|
||||
const initialPlayerSpeed = playerPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -214,7 +214,7 @@ describe("Abilities - Unburden", () => {
|
||||
game.override.moveset(MoveId.STUFF_CHEEKS);
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const playerHeldItemCt = getHeldItemCount(playerPokemon);
|
||||
const initialPlayerSpeed = playerPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -292,7 +292,7 @@ describe("Abilities - Unburden", () => {
|
||||
game.override.enemyMoveset([MoveId.FALSE_SWIPE, MoveId.WORRY_SEED]);
|
||||
await game.classicMode.startBattle([SpeciesId.PURRLOIN]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const playerHeldItems = getHeldItemCount(playerPokemon);
|
||||
const initialPlayerSpeed = playerPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -317,7 +317,7 @@ describe("Abilities - Unburden", () => {
|
||||
game.override.startingHeldItems([{ name: "REVIVER_SEED" }]).enemyMoveset([MoveId.WING_ATTACK]);
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerPokemon = game.field.getPlayerPokemon();
|
||||
const playerHeldItems = getHeldItemCount(playerPokemon);
|
||||
const initialPlayerSpeed = playerPokemon.getStat(Stat.SPD);
|
||||
|
||||
@ -334,7 +334,7 @@ describe("Abilities - Unburden", () => {
|
||||
game.override.enemyMoveset([MoveId.SPLASH, MoveId.THIEF]);
|
||||
await game.classicMode.startBattle([SpeciesId.TREECKO, SpeciesId.FEEBAS]);
|
||||
|
||||
const treecko = game.scene.getPlayerPokemon()!;
|
||||
const treecko = game.field.getPlayerPokemon();
|
||||
const treeckoInitialHeldItems = getHeldItemCount(treecko);
|
||||
const initialSpeed = treecko.getStat(Stat.SPD);
|
||||
|
||||
@ -348,7 +348,7 @@ describe("Abilities - Unburden", () => {
|
||||
await game.move.selectEnemyMove(MoveId.SPLASH);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(game.scene.getPlayerPokemon()!).toBe(treecko);
|
||||
expect(game.field.getPlayerPokemon()).toBe(treecko);
|
||||
expect(getHeldItemCount(treecko)).toBeLessThan(treeckoInitialHeldItems);
|
||||
expect(treecko.getEffectiveStat(Stat.SPD)).toBe(initialSpeed);
|
||||
});
|
||||
|
@ -55,7 +55,7 @@ describe("Abilities - Unseen Fist", () => {
|
||||
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
enemyPokemon.addTag(BattlerTagType.SUBSTITUTE, 0, MoveId.NONE, enemyPokemon.id);
|
||||
|
||||
game.move.select(MoveId.TACKLE);
|
||||
@ -77,10 +77,10 @@ async function testUnseenFistHitResult(
|
||||
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
const leadPokemon = game.field.getPlayerPokemon();
|
||||
expect(leadPokemon).not.toBe(undefined);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemyPokemon = game.field.getEnemyPokemon();
|
||||
expect(enemyPokemon).not.toBe(undefined);
|
||||
|
||||
const enemyStartingHp = enemyPokemon.hp;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user