Compare commits

...

17 Commits

Author SHA1 Message Date
Bertie690
1636c40b14
Merge ab968f1ac6 into 46c78a0540 2025-08-15 19:10:21 -04:00
Wlowscha
46c78a0540
[Bug][UI/UX] Bringing mon icon overlays on top correctly (#6272)
Bringing mon icon overlays on top correctly
2025-08-15 22:51:28 +00:00
AJ Fontaine
98809c28bd
[Balance] Add TM for Shock Wave (#6274)
Add TM for Shock Wave
2025-08-15 22:23:13 +00:00
damocleas
e0559e03ff Update locales 2025-08-15 17:09:51 -04:00
SmhMyHead
f6b99780fb
[UI/UIX] Dex unseen species filter (#5909)
* [UI/UIX] Dex unseen species filter

* Removed changes to icon visibility rules

* Update src/ui/pokedex-ui-handler.ts

---------

Co-authored-by: Wlowscha <54003515+Wlowscha@users.noreply.github.com>
2025-08-15 19:27:16 +00:00
Amani H.
19af9bdb8b
[Beta] [Bug] Fix Various Nuzlocke-related Issues (#6261)
* [Bug] Fix Various Nuzlocke-related Issues

* Update encounter-pokemon-utils.ts

* Update attempt-capture-phase.ts

---------

Co-authored-by: damocleas <damocleas25@gmail.com>
Co-authored-by: Wlowscha <54003515+Wlowscha@users.noreply.github.com>
2025-08-15 19:22:59 +02:00
fabske0
8e61b642a3
[UI/UX Bug] Position runname dynamically (#6271)
Fix runname position

Co-authored-by: Wlowscha <54003515+Wlowscha@users.noreply.github.com>
2025-08-15 13:16:37 -04:00
Bertie690
ab968f1ac6
Merge branch 'beta' into test-cleanup 2025-08-12 10:37:22 -04:00
Bertie690
64be310b9a Merge remote-tracking branch 'upstream/beta' into test-cleanup 2025-08-03 14:54:35 -04:00
Bertie690
bf855d5acf Fixed remaining error 2025-08-03 14:54:22 -04:00
Bertie690
bad73f0ce2 Fixed remaining issues; removed direct assignment to Pokemon.moveset 2025-08-01 11:15:43 -04:00
Bertie690
034c56473c Fiexd syntax errors 2025-07-30 22:22:55 -04:00
Bertie690
3db1cb7486 Deleted duplicate sturdy test case 2025-07-30 22:18:54 -04:00
Bertie690
a9a3b0760a Replaced game.scene.getXXXParty()[0] with game.field.getEnemyPokemon 2025-07-30 18:21:35 -04:00
Bertie690
c55f105d31 More array destructuring!!! 2025-07-30 18:15:23 -04:00
Bertie690
6013bc8c00 Replaced instances of consecutive game.scene.getPlayerParty with destructuring 2025-07-30 18:14:05 -04:00
Bertie690
5d4e93b009 Removed bangs from getEnemyParty and getPlayerParty 2025-07-30 18:08:14 -04:00
45 changed files with 555 additions and 253 deletions

@ -1 +1 @@
Subproject commit ab2716d5440c25f73986664aa3f3131821c3c392 Subproject commit 1ea8f865e30d1940caa0fceeabf37ae2e4689471

View File

@ -45736,6 +45736,285 @@ export const tmSpecies: TmSpecies = {
SpeciesId.HISUI_ARCANINE, SpeciesId.HISUI_ARCANINE,
SpeciesId.HISUI_AVALUGG, SpeciesId.HISUI_AVALUGG,
], ],
[MoveId.SHOCK_WAVE]: [
SpeciesId.RATTATA,
SpeciesId.RATICATE,
SpeciesId.PIKACHU,
SpeciesId.RAICHU,
SpeciesId.NIDORAN_F,
SpeciesId.NIDORINA,
SpeciesId.NIDOQUEEN,
SpeciesId.NIDORAN_M,
SpeciesId.NIDORINO,
SpeciesId.NIDOKING,
SpeciesId.CLEFAIRY,
SpeciesId.CLEFABLE,
SpeciesId.JIGGLYPUFF,
SpeciesId.WIGGLYTUFF,
SpeciesId.MEOWTH,
SpeciesId.PERSIAN,
SpeciesId.ABRA,
SpeciesId.KADABRA,
SpeciesId.ALAKAZAM,
SpeciesId.MAGNEMITE,
SpeciesId.MAGNETON,
SpeciesId.GRIMER,
SpeciesId.MUK,
SpeciesId.VOLTORB,
SpeciesId.ELECTRODE,
SpeciesId.LICKITUNG,
SpeciesId.KOFFING,
SpeciesId.WEEZING,
SpeciesId.RHYHORN,
SpeciesId.RHYDON,
SpeciesId.CHANSEY,
SpeciesId.TANGELA,
SpeciesId.KANGASKHAN,
SpeciesId.MR_MIME,
SpeciesId.ELECTABUZZ,
SpeciesId.TAUROS,
SpeciesId.LAPRAS,
SpeciesId.JOLTEON,
SpeciesId.PORYGON,
SpeciesId.SNORLAX,
SpeciesId.ZAPDOS,
SpeciesId.DRATINI,
SpeciesId.DRAGONAIR,
SpeciesId.DRAGONITE,
SpeciesId.MEWTWO,
SpeciesId.MEW,
SpeciesId.SENTRET,
SpeciesId.FURRET,
SpeciesId.CHINCHOU,
SpeciesId.LANTURN,
SpeciesId.PICHU,
SpeciesId.CLEFFA,
SpeciesId.IGGLYBUFF,
SpeciesId.TOGEPI,
SpeciesId.TOGETIC,
SpeciesId.MAREEP,
SpeciesId.FLAAFFY,
SpeciesId.AMPHAROS,
SpeciesId.AIPOM,
SpeciesId.MISDREAVUS,
SpeciesId.GIRAFARIG,
SpeciesId.DUNSPARCE,
SpeciesId.SNUBBULL,
SpeciesId.GRANBULL,
SpeciesId.QWILFISH,
SpeciesId.PORYGON2,
SpeciesId.STANTLER,
SpeciesId.ELEKID,
SpeciesId.MILTANK,
SpeciesId.BLISSEY,
SpeciesId.RAIKOU,
SpeciesId.TYRANITAR,
SpeciesId.LUGIA,
SpeciesId.HO_OH,
SpeciesId.CELEBI,
SpeciesId.ZIGZAGOON,
SpeciesId.LINOONE,
SpeciesId.WINGULL,
SpeciesId.PELIPPER,
SpeciesId.RALTS,
SpeciesId.KIRLIA,
SpeciesId.GARDEVOIR,
SpeciesId.SLAKOTH,
SpeciesId.VIGOROTH,
SpeciesId.SLAKING,
SpeciesId.WHISMUR,
SpeciesId.LOUDRED,
SpeciesId.EXPLOUD,
SpeciesId.NOSEPASS,
SpeciesId.SKITTY,
SpeciesId.DELCATTY,
SpeciesId.SABLEYE,
SpeciesId.ARON,
SpeciesId.LAIRON,
SpeciesId.AGGRON,
SpeciesId.ELECTRIKE,
SpeciesId.MANECTRIC,
SpeciesId.PLUSLE,
SpeciesId.MINUN,
SpeciesId.VOLBEAT,
SpeciesId.ILLUMISE,
SpeciesId.GULPIN,
SpeciesId.SWALOT,
SpeciesId.SPOINK,
SpeciesId.GRUMPIG,
SpeciesId.SPINDA,
SpeciesId.ZANGOOSE,
SpeciesId.CASTFORM,
SpeciesId.KECLEON,
SpeciesId.SHUPPET,
SpeciesId.BANETTE,
SpeciesId.CHIMECHO,
SpeciesId.ABSOL,
SpeciesId.REGIROCK,
SpeciesId.REGICE,
SpeciesId.REGISTEEL,
SpeciesId.LATIAS,
SpeciesId.LATIOS,
SpeciesId.KYOGRE,
SpeciesId.GROUDON,
SpeciesId.RAYQUAZA,
SpeciesId.JIRACHI,
SpeciesId.DEOXYS,
SpeciesId.BIDOOF,
SpeciesId.BIBAREL,
SpeciesId.SHINX,
SpeciesId.LUXIO,
SpeciesId.LUXRAY,
SpeciesId.CRANIDOS,
SpeciesId.RAMPARDOS,
SpeciesId.SHIELDON,
SpeciesId.BASTIODON,
SpeciesId.PACHIRISU,
SpeciesId.AMBIPOM,
SpeciesId.DRIFLOON,
SpeciesId.DRIFBLIM,
SpeciesId.BUNEARY,
SpeciesId.LOPUNNY,
SpeciesId.MISMAGIUS,
SpeciesId.GLAMEOW,
SpeciesId.PURUGLY,
SpeciesId.CHINGLING,
SpeciesId.MIME_JR,
SpeciesId.HAPPINY,
SpeciesId.SPIRITOMB,
SpeciesId.MUNCHLAX,
SpeciesId.MAGNEZONE,
SpeciesId.LICKILICKY,
SpeciesId.RHYPERIOR,
SpeciesId.TANGROWTH,
SpeciesId.ELECTIVIRE,
SpeciesId.TOGEKISS,
SpeciesId.PORYGON_Z,
SpeciesId.GALLADE,
SpeciesId.PROBOPASS,
SpeciesId.FROSLASS,
SpeciesId.ROTOM,
SpeciesId.UXIE,
SpeciesId.MESPRIT,
SpeciesId.AZELF,
SpeciesId.DIALGA,
SpeciesId.PALKIA,
SpeciesId.REGIGIGAS,
SpeciesId.GIRATINA,
SpeciesId.DARKRAI,
SpeciesId.ARCEUS,
SpeciesId.VICTINI,
SpeciesId.PATRAT,
SpeciesId.WATCHOG,
SpeciesId.LILLIPUP,
SpeciesId.HERDIER,
SpeciesId.STOUTLAND,
SpeciesId.MUNNA,
SpeciesId.MUSHARNA,
SpeciesId.BLITZLE,
SpeciesId.ZEBSTRIKA,
SpeciesId.WOOBAT,
SpeciesId.SWOOBAT,
SpeciesId.SIGILYPH,
SpeciesId.YAMASK,
SpeciesId.COFAGRIGUS,
SpeciesId.MINCCINO,
SpeciesId.CINCCINO,
SpeciesId.GOTHITA,
SpeciesId.GOTHORITA,
SpeciesId.GOTHITELLE,
SpeciesId.SOLOSIS,
SpeciesId.DUOSION,
SpeciesId.REUNICLUS,
SpeciesId.EMOLGA,
SpeciesId.FRILLISH,
SpeciesId.JELLICENT,
SpeciesId.JOLTIK,
SpeciesId.GALVANTULA,
SpeciesId.KLINK,
SpeciesId.KLANG,
SpeciesId.KLINKLANG,
SpeciesId.EELEKTRIK,
SpeciesId.EELEKTROSS,
SpeciesId.ELGYEM,
SpeciesId.BEHEEYEM,
SpeciesId.LITWICK,
SpeciesId.LAMPENT,
SpeciesId.CHANDELURE,
SpeciesId.AXEW,
SpeciesId.FRAXURE,
SpeciesId.HAXORUS,
SpeciesId.STUNFISK,
SpeciesId.DRUDDIGON,
SpeciesId.GOLETT,
SpeciesId.GOLURK,
SpeciesId.DEINO,
SpeciesId.ZWEILOUS,
SpeciesId.HYDREIGON,
SpeciesId.THUNDURUS,
SpeciesId.ZEKROM,
SpeciesId.MELOETTA,
SpeciesId.GENESECT,
SpeciesId.BRAIXEN,
SpeciesId.DELPHOX,
SpeciesId.ESPURR,
SpeciesId.MEOWSTIC,
SpeciesId.HONEDGE,
SpeciesId.DOUBLADE,
SpeciesId.AEGISLASH,
SpeciesId.SKRELP,
SpeciesId.DRAGALGE,
SpeciesId.HELIOPTILE,
SpeciesId.HELIOLISK,
SpeciesId.DEDENNE,
SpeciesId.GOOMY,
SpeciesId.SLIGGOO,
SpeciesId.GOODRA,
SpeciesId.ZYGARDE,
SpeciesId.HOOPA,
SpeciesId.YUNGOOS,
SpeciesId.GUMSHOOS,
SpeciesId.GRUBBIN,
SpeciesId.CHARJABUG,
SpeciesId.VIKAVOLT,
SpeciesId.PASSIMIAN,
SpeciesId.TURTONATOR,
SpeciesId.TOGEDEMARU,
SpeciesId.DRAMPA,
SpeciesId.KOMMO_O,
SpeciesId.TAPU_KOKO,
SpeciesId.SOLGALEO,
SpeciesId.LUNALA,
SpeciesId.PHEROMOSA,
SpeciesId.XURKITREE,
SpeciesId.CELESTEELA,
SpeciesId.GUZZLORD,
SpeciesId.NECROZMA,
SpeciesId.MAGEARNA,
SpeciesId.NAGANADEL,
SpeciesId.ZERAORA,
SpeciesId.TOXTRICITY,
SpeciesId.MR_RIME,
SpeciesId.REGIELEKI,
SpeciesId.WYRDEER,
SpeciesId.FARIGIRAF,
SpeciesId.DUDUNSPARCE,
SpeciesId.MIRAIDON,
SpeciesId.RAGING_BOLT,
SpeciesId.ALOLA_RATTATA,
SpeciesId.ALOLA_RATICATE,
SpeciesId.ALOLA_RAICHU,
SpeciesId.ALOLA_MEOWTH,
SpeciesId.ALOLA_PERSIAN,
SpeciesId.ALOLA_GRAVELER,
SpeciesId.ALOLA_GOLEM,
SpeciesId.ALOLA_GRIMER,
SpeciesId.ALOLA_MUK,
SpeciesId.GALAR_WEEZING,
SpeciesId.GALAR_MR_MIME,
SpeciesId.HISUI_SLIGGOO,
SpeciesId.HISUI_GOODRA,
],
[MoveId.WATER_PULSE]: [ [MoveId.WATER_PULSE]: [
SpeciesId.SQUIRTLE, SpeciesId.SQUIRTLE,
SpeciesId.WARTORTLE, SpeciesId.WARTORTLE,
@ -68747,6 +69026,7 @@ export const tmPoolTiers: TmPoolTiers = {
[MoveId.LEAF_BLADE]: ModifierTier.ULTRA, [MoveId.LEAF_BLADE]: ModifierTier.ULTRA,
[MoveId.DRAGON_DANCE]: ModifierTier.GREAT, [MoveId.DRAGON_DANCE]: ModifierTier.GREAT,
[MoveId.ROCK_BLAST]: ModifierTier.GREAT, [MoveId.ROCK_BLAST]: ModifierTier.GREAT,
[MoveId.SHOCK_WAVE]: ModifierTier.GREAT,
[MoveId.WATER_PULSE]: ModifierTier.GREAT, [MoveId.WATER_PULSE]: ModifierTier.GREAT,
[MoveId.ROOST]: ModifierTier.GREAT, [MoveId.ROOST]: ModifierTier.GREAT,
[MoveId.GRAVITY]: ModifierTier.COMMON, [MoveId.GRAVITY]: ModifierTier.COMMON,

View File

@ -99,6 +99,7 @@ export const DarkDealEncounter: MysteryEncounter = MysteryEncounterBuilder.withE
MysteryEncounterType.DARK_DEAL, MysteryEncounterType.DARK_DEAL,
) )
.withEncounterTier(MysteryEncounterTier.ROGUE) .withEncounterTier(MysteryEncounterTier.ROGUE)
.withDisallowedChallenges(Challenges.HARDCORE)
.withIntroSpriteConfigs([ .withIntroSpriteConfigs([
{ {
spriteKey: "dark_deal_scientist", spriteKey: "dark_deal_scientist",

View File

@ -673,6 +673,8 @@ export async function catchPokemon(
globalScene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs); globalScene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs);
return new Promise(resolve => { return new Promise(resolve => {
const addStatus = new BooleanHolder(true);
applyChallenges(ChallengeType.POKEMON_ADD_TO_PARTY, pokemon, addStatus);
const doPokemonCatchMenu = () => { const doPokemonCatchMenu = () => {
const end = () => { const end = () => {
// Ensure the pokemon is in the enemy party in all situations // Ensure the pokemon is in the enemy party in all situations
@ -708,9 +710,7 @@ export async function catchPokemon(
}); });
}; };
Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => { Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => {
const addStatus = new BooleanHolder(true); if (!(isObtain || addStatus.value)) {
applyChallenges(ChallengeType.POKEMON_ADD_TO_PARTY, pokemon, addStatus);
if (!addStatus.value) {
removePokemon(); removePokemon();
end(); end();
return; return;
@ -807,10 +807,16 @@ export async function catchPokemon(
}; };
if (showCatchObtainMessage) { if (showCatchObtainMessage) {
let catchMessage: string;
if (isObtain) {
catchMessage = "battle:pokemonObtained";
} else if (addStatus.value) {
catchMessage = "battle:pokemonCaught";
} else {
catchMessage = "battle:pokemonCaughtButChallenge";
}
globalScene.ui.showText( globalScene.ui.showText(
i18next.t(isObtain ? "battle:pokemonObtained" : "battle:pokemonCaught", { i18next.t(catchMessage, { pokemonName: pokemon.getNameToRender() }),
pokemonName: pokemon.getNameToRender(),
}),
null, null,
doPokemonCatchMenu, doPokemonCatchMenu,
0, 0,

View File

@ -253,8 +253,11 @@ export class AttemptCapturePhase extends PokemonPhase {
globalScene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs); globalScene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs);
const addStatus = new BooleanHolder(true);
applyChallenges(ChallengeType.POKEMON_ADD_TO_PARTY, pokemon, addStatus);
globalScene.ui.showText( globalScene.ui.showText(
i18next.t("battle:pokemonCaught", { i18next.t(addStatus.value ? "battle:pokemonCaught" : "battle:pokemonCaughtButChallenge", {
pokemonName: getPokemonNameWithAffix(pokemon), pokemonName: getPokemonNameWithAffix(pokemon),
}), }),
null, null,
@ -290,8 +293,6 @@ export class AttemptCapturePhase extends PokemonPhase {
}); });
}; };
Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => { Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => {
const addStatus = new BooleanHolder(true);
applyChallenges(ChallengeType.POKEMON_ADD_TO_PARTY, pokemon, addStatus);
if (!addStatus.value) { if (!addStatus.value) {
removePokemon(); removePokemon();
end(); end();

View File

@ -16,8 +16,10 @@ export class SelectBiomePhase extends BattlePhase {
globalScene.resetSeed(); globalScene.resetSeed();
const gameMode = globalScene.gameMode;
const currentBiome = globalScene.arena.biomeType; const currentBiome = globalScene.arena.biomeType;
const nextWaveIndex = globalScene.currentBattle.waveIndex + 1; const currentWaveIndex = globalScene.currentBattle.waveIndex;
const nextWaveIndex = currentWaveIndex + 1;
const setNextBiome = (nextBiome: BiomeId) => { const setNextBiome = (nextBiome: BiomeId) => {
if (nextWaveIndex % 10 === 1) { if (nextWaveIndex % 10 === 1) {
@ -26,6 +28,15 @@ export class SelectBiomePhase extends BattlePhase {
applyChallenges(ChallengeType.PARTY_HEAL, healStatus); applyChallenges(ChallengeType.PARTY_HEAL, healStatus);
if (healStatus.value) { if (healStatus.value) {
globalScene.phaseManager.unshiftNew("PartyHealPhase", false); globalScene.phaseManager.unshiftNew("PartyHealPhase", false);
} else {
globalScene.phaseManager.unshiftNew(
"SelectModifierPhase",
undefined,
undefined,
gameMode.isFixedBattle(currentWaveIndex)
? gameMode.getFixedBattle(currentWaveIndex).customModifierRewardSettings
: undefined,
);
} }
} }
globalScene.phaseManager.unshiftNew("SwitchBiomePhase", nextBiome); globalScene.phaseManager.unshiftNew("SwitchBiomePhase", nextBiome);
@ -33,12 +44,12 @@ export class SelectBiomePhase extends BattlePhase {
}; };
if ( if (
(globalScene.gameMode.isClassic && globalScene.gameMode.isWaveFinal(nextWaveIndex + 9)) || (gameMode.isClassic && gameMode.isWaveFinal(nextWaveIndex + 9)) ||
(globalScene.gameMode.isDaily && globalScene.gameMode.isWaveFinal(nextWaveIndex)) || (gameMode.isDaily && gameMode.isWaveFinal(nextWaveIndex)) ||
(globalScene.gameMode.hasShortBiomes && !(nextWaveIndex % 50)) (gameMode.hasShortBiomes && !(nextWaveIndex % 50))
) { ) {
setNextBiome(BiomeId.END); setNextBiome(BiomeId.END);
} else if (globalScene.gameMode.hasRandomBiomes) { } else if (gameMode.hasRandomBiomes) {
setNextBiome(this.generateNextBiome(nextWaveIndex)); setNextBiome(this.generateNextBiome(nextWaveIndex));
} else if (Array.isArray(biomeLinks[currentBiome])) { } else if (Array.isArray(biomeLinks[currentBiome])) {
const biomes: BiomeId[] = (biomeLinks[currentBiome] as (BiomeId | [BiomeId, number])[]) const biomes: BiomeId[] = (biomeLinks[currentBiome] as (BiomeId | [BiomeId, number])[])
@ -73,9 +84,6 @@ export class SelectBiomePhase extends BattlePhase {
} }
generateNextBiome(waveIndex: number): BiomeId { generateNextBiome(waveIndex: number): BiomeId {
if (!(waveIndex % 50)) { return waveIndex % 50 === 0 ? BiomeId.END : globalScene.generateRandomBiome(waveIndex);
return BiomeId.END;
}
return globalScene.generateRandomBiome(waveIndex);
} }
} }

View File

@ -3,13 +3,9 @@ import { globalScene } from "#app/global-scene";
import { modifierTypes } from "#data/data-lists"; import { modifierTypes } from "#data/data-lists";
import { BattleType } from "#enums/battle-type"; import { BattleType } from "#enums/battle-type";
import type { BattlerIndex } from "#enums/battler-index"; import type { BattlerIndex } from "#enums/battler-index";
import { ChallengeType } from "#enums/challenge-type";
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
import type { CustomModifierSettings } from "#modifiers/modifier-type";
import { handleMysteryEncounterVictory } from "#mystery-encounters/encounter-phase-utils"; import { handleMysteryEncounterVictory } from "#mystery-encounters/encounter-phase-utils";
import { PokemonPhase } from "#phases/pokemon-phase"; import { PokemonPhase } from "#phases/pokemon-phase";
import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder } from "#utils/common";
export class VictoryPhase extends PokemonPhase { export class VictoryPhase extends PokemonPhase {
public readonly phaseName = "VictoryPhase"; public readonly phaseName = "VictoryPhase";
@ -49,15 +45,19 @@ export class VictoryPhase extends PokemonPhase {
if (globalScene.currentBattle.battleType === BattleType.TRAINER) { if (globalScene.currentBattle.battleType === BattleType.TRAINER) {
globalScene.phaseManager.pushNew("TrainerVictoryPhase"); globalScene.phaseManager.pushNew("TrainerVictoryPhase");
} }
if (globalScene.gameMode.isEndless || !globalScene.gameMode.isWaveFinal(globalScene.currentBattle.waveIndex)) {
const gameMode = globalScene.gameMode;
const currentWaveIndex = globalScene.currentBattle.waveIndex;
if (gameMode.isEndless || !gameMode.isWaveFinal(currentWaveIndex)) {
globalScene.phaseManager.pushNew("EggLapsePhase"); globalScene.phaseManager.pushNew("EggLapsePhase");
if (globalScene.gameMode.isClassic) { if (gameMode.isClassic) {
switch (globalScene.currentBattle.waveIndex) { switch (currentWaveIndex) {
case ClassicFixedBossWaves.RIVAL_1: case ClassicFixedBossWaves.RIVAL_1:
case ClassicFixedBossWaves.RIVAL_2: case ClassicFixedBossWaves.RIVAL_2:
// Get event modifiers for this wave // Get event modifiers for this wave
timedEventManager timedEventManager
.getFixedBattleEventRewards(globalScene.currentBattle.waveIndex) .getFixedBattleEventRewards(currentWaveIndex)
.map(r => globalScene.phaseManager.pushNew("ModifierRewardPhase", modifierTypes[r])); .map(r => globalScene.phaseManager.pushNew("ModifierRewardPhase", modifierTypes[r]));
break; break;
case ClassicFixedBossWaves.EVIL_BOSS_2: case ClassicFixedBossWaves.EVIL_BOSS_2:
@ -66,59 +66,53 @@ export class VictoryPhase extends PokemonPhase {
break; break;
} }
} }
const healStatus = new BooleanHolder(globalScene.currentBattle.waveIndex % 10 === 0); if (currentWaveIndex % 10) {
applyChallenges(ChallengeType.PARTY_HEAL, healStatus);
if (!healStatus.value) {
globalScene.phaseManager.pushNew( globalScene.phaseManager.pushNew(
"SelectModifierPhase", "SelectModifierPhase",
undefined, undefined,
undefined, undefined,
this.getFixedBattleCustomModifiers(), gameMode.isFixedBattle(currentWaveIndex)
? gameMode.getFixedBattle(currentWaveIndex).customModifierRewardSettings
: undefined,
); );
} else if (globalScene.gameMode.isDaily) { } else if (gameMode.isDaily) {
globalScene.phaseManager.pushNew("ModifierRewardPhase", modifierTypes.EXP_CHARM); globalScene.phaseManager.pushNew("ModifierRewardPhase", modifierTypes.EXP_CHARM);
if ( if (currentWaveIndex > 10 && !gameMode.isWaveFinal(currentWaveIndex)) {
globalScene.currentBattle.waveIndex > 10 &&
!globalScene.gameMode.isWaveFinal(globalScene.currentBattle.waveIndex)
) {
globalScene.phaseManager.pushNew("ModifierRewardPhase", modifierTypes.GOLDEN_POKEBALL); globalScene.phaseManager.pushNew("ModifierRewardPhase", modifierTypes.GOLDEN_POKEBALL);
} }
} else { } else {
const superExpWave = !globalScene.gameMode.isEndless ? (globalScene.offsetGym ? 0 : 20) : 10; const superExpWave = !gameMode.isEndless ? (globalScene.offsetGym ? 0 : 20) : 10;
if (globalScene.gameMode.isEndless && globalScene.currentBattle.waveIndex === 10) { if (gameMode.isEndless && currentWaveIndex === 10) {
globalScene.phaseManager.pushNew("ModifierRewardPhase", modifierTypes.EXP_SHARE); globalScene.phaseManager.pushNew("ModifierRewardPhase", modifierTypes.EXP_SHARE);
} }
if ( if (currentWaveIndex <= 750 && (currentWaveIndex <= 500 || currentWaveIndex % 30 === superExpWave)) {
globalScene.currentBattle.waveIndex <= 750 &&
(globalScene.currentBattle.waveIndex <= 500 || globalScene.currentBattle.waveIndex % 30 === superExpWave)
) {
globalScene.phaseManager.pushNew( globalScene.phaseManager.pushNew(
"ModifierRewardPhase", "ModifierRewardPhase",
globalScene.currentBattle.waveIndex % 30 !== superExpWave || globalScene.currentBattle.waveIndex > 250 currentWaveIndex % 30 !== superExpWave || currentWaveIndex > 250
? modifierTypes.EXP_CHARM ? modifierTypes.EXP_CHARM
: modifierTypes.SUPER_EXP_CHARM, : modifierTypes.SUPER_EXP_CHARM,
); );
} }
if (globalScene.currentBattle.waveIndex <= 150 && !(globalScene.currentBattle.waveIndex % 50)) { if (currentWaveIndex <= 150 && !(currentWaveIndex % 50)) {
globalScene.phaseManager.pushNew("ModifierRewardPhase", modifierTypes.GOLDEN_POKEBALL); globalScene.phaseManager.pushNew("ModifierRewardPhase", modifierTypes.GOLDEN_POKEBALL);
} }
if (globalScene.gameMode.isEndless && !(globalScene.currentBattle.waveIndex % 50)) { if (gameMode.isEndless && !(currentWaveIndex % 50)) {
globalScene.phaseManager.pushNew( globalScene.phaseManager.pushNew(
"ModifierRewardPhase", "ModifierRewardPhase",
!(globalScene.currentBattle.waveIndex % 250) ? modifierTypes.VOUCHER_PREMIUM : modifierTypes.VOUCHER_PLUS, !(currentWaveIndex % 250) ? modifierTypes.VOUCHER_PREMIUM : modifierTypes.VOUCHER_PLUS,
); );
globalScene.phaseManager.pushNew("AddEnemyBuffModifierPhase"); globalScene.phaseManager.pushNew("AddEnemyBuffModifierPhase");
} }
} }
if (globalScene.gameMode.hasRandomBiomes || globalScene.isNewBiome()) { if (gameMode.hasRandomBiomes || globalScene.isNewBiome()) {
globalScene.phaseManager.pushNew("SelectBiomePhase"); globalScene.phaseManager.pushNew("SelectBiomePhase");
} }
globalScene.phaseManager.pushNew("NewBattlePhase"); globalScene.phaseManager.pushNew("NewBattlePhase");
} else { } else {
globalScene.currentBattle.battleType = BattleType.CLEAR; globalScene.currentBattle.battleType = BattleType.CLEAR;
globalScene.score += globalScene.gameMode.getClearScoreBonus(); globalScene.score += gameMode.getClearScoreBonus();
globalScene.updateScoreText(); globalScene.updateScoreText();
globalScene.phaseManager.pushNew("GameOverPhase", true); globalScene.phaseManager.pushNew("GameOverPhase", true);
} }
@ -126,18 +120,4 @@ export class VictoryPhase extends PokemonPhase {
this.end(); this.end();
} }
/**
* If this wave is a fixed battle with special custom modifier rewards,
* will pass those settings to the upcoming {@linkcode SelectModifierPhase}`.
*/
getFixedBattleCustomModifiers(): CustomModifierSettings | undefined {
const gameMode = globalScene.gameMode;
const waveIndex = globalScene.currentBattle.waveIndex;
if (gameMode.isFixedBattle(waveIndex)) {
return gameMode.getFixedBattle(waveIndex).customModifierRewardSettings;
}
return undefined;
}
} }

View File

@ -448,6 +448,8 @@ export function getAchievementDescription(localizationKey: string): string {
return i18next.t("achv:FLIP_STATS.description", { context: genderStr }); return i18next.t("achv:FLIP_STATS.description", { context: genderStr });
case "FLIP_INVERSE": case "FLIP_INVERSE":
return i18next.t("achv:FLIP_INVERSE.description", { context: genderStr }); return i18next.t("achv:FLIP_INVERSE.description", { context: genderStr });
case "NUZLOCKE":
return i18next.t("achv:NUZLOCKE.description", { context: genderStr });
case "BREEDERS_IN_SPACE": case "BREEDERS_IN_SPACE":
return i18next.t("achv:BREEDERS_IN_SPACE.description", { return i18next.t("achv:BREEDERS_IN_SPACE.description", {
context: genderStr, context: genderStr,

View File

@ -208,6 +208,26 @@ export class PokedexMonContainer extends Phaser.GameObjects.Container {
); );
this.checkIconId(defaultProps.female, defaultProps.formIndex, defaultProps.shiny, defaultProps.variant); this.checkIconId(defaultProps.female, defaultProps.formIndex, defaultProps.shiny, defaultProps.variant);
this.add(this.icon); this.add(this.icon);
[
this.hiddenAbilityIcon,
this.favoriteIcon,
this.classicWinIcon,
this.candyUpgradeIcon,
this.candyUpgradeOverlayIcon,
this.eggMove1Icon,
this.tmMove1Icon,
this.eggMove2Icon,
this.tmMove2Icon,
this.passive1Icon,
this.passive2Icon,
this.passive1OverlayIcon,
this.passive2OverlayIcon,
].forEach(icon => {
if (icon) {
this.bringToTop(icon);
}
});
} }
checkIconId(female, formIndex, shiny, variant) { checkIconId(female, formIndex, shiny, variant) {

View File

@ -410,6 +410,11 @@ export class PokedexUiHandler extends MessageUiHandler {
new DropDownLabel(i18next.t("filterBar:hasHiddenAbility"), undefined, DropDownState.ON), new DropDownLabel(i18next.t("filterBar:hasHiddenAbility"), undefined, DropDownState.ON),
new DropDownLabel(i18next.t("filterBar:noHiddenAbility"), undefined, DropDownState.EXCLUDE), new DropDownLabel(i18next.t("filterBar:noHiddenAbility"), undefined, DropDownState.EXCLUDE),
]; ];
const seenSpeciesLabels = [
new DropDownLabel(i18next.t("filterBar:seenSpecies"), undefined, DropDownState.OFF),
new DropDownLabel(i18next.t("filterBar:isSeen"), undefined, DropDownState.ON),
new DropDownLabel(i18next.t("filterBar:isUnseen"), undefined, DropDownState.EXCLUDE),
];
const eggLabels = [ const eggLabels = [
new DropDownLabel(i18next.t("filterBar:egg"), undefined, DropDownState.OFF), new DropDownLabel(i18next.t("filterBar:egg"), undefined, DropDownState.OFF),
new DropDownLabel(i18next.t("filterBar:eggPurchasable"), undefined, DropDownState.ON), new DropDownLabel(i18next.t("filterBar:eggPurchasable"), undefined, DropDownState.ON),
@ -423,6 +428,7 @@ export class PokedexUiHandler extends MessageUiHandler {
new DropDownOption("FAVORITE", favoriteLabels), new DropDownOption("FAVORITE", favoriteLabels),
new DropDownOption("WIN", winLabels), new DropDownOption("WIN", winLabels),
new DropDownOption("HIDDEN_ABILITY", hiddenAbilityLabels), new DropDownOption("HIDDEN_ABILITY", hiddenAbilityLabels),
new DropDownOption("SEEN_SPECIES", seenSpeciesLabels),
new DropDownOption("EGG", eggLabels), new DropDownOption("EGG", eggLabels),
new DropDownOption("POKERUS", pokerusLabels), new DropDownOption("POKERUS", pokerusLabels),
]; ];
@ -792,13 +798,15 @@ export class PokedexUiHandler extends MessageUiHandler {
this.starterSelectMessageBoxContainer.setVisible(!!text?.length); this.starterSelectMessageBoxContainer.setVisible(!!text?.length);
} }
isSeen(species: PokemonSpecies, dexEntry: DexEntry): boolean { isSeen(species: PokemonSpecies, dexEntry: DexEntry, seenFilter?: boolean): boolean {
if (dexEntry?.seenAttr) { if (dexEntry?.seenAttr) {
return true; return true;
} }
if (!seenFilter) {
const starterDexEntry = globalScene.gameData.dexData[this.getStarterSpeciesId(species.speciesId)]; const starterDexEntry = globalScene.gameData.dexData[this.getStarterSpeciesId(species.speciesId)];
return !!starterDexEntry?.caughtAttr; return !!starterDexEntry?.caughtAttr;
}
return false;
} }
/** /**
@ -1617,6 +1625,21 @@ export class PokedexUiHandler extends MessageUiHandler {
} }
}); });
// Seen Filter
const dexEntry = globalScene.gameData.dexData[species.speciesId];
const isItSeen = this.isSeen(species, dexEntry, true);
const fitsSeen = this.filterBar.getVals(DropDownColumn.MISC).some(misc => {
if (misc.val === "SEEN_SPECIES" && misc.state === DropDownState.ON) {
return isItSeen;
}
if (misc.val === "SEEN_SPECIES" && misc.state === DropDownState.EXCLUDE) {
return !isItSeen;
}
if (misc.val === "SEEN_SPECIES" && misc.state === DropDownState.OFF) {
return true;
}
});
// Egg Purchasable Filter // Egg Purchasable Filter
const isEggPurchasable = this.isSameSpeciesEggAvailable(species.speciesId); const isEggPurchasable = this.isSameSpeciesEggAvailable(species.speciesId);
const fitsEgg = this.filterBar.getVals(DropDownColumn.MISC).some(misc => { const fitsEgg = this.filterBar.getVals(DropDownColumn.MISC).some(misc => {
@ -1658,6 +1681,7 @@ export class PokedexUiHandler extends MessageUiHandler {
fitsFavorite && fitsFavorite &&
fitsWin && fitsWin &&
fitsHA && fitsHA &&
fitsSeen &&
fitsEgg && fitsEgg &&
fitsPokerus fitsPokerus
) { ) {

View File

@ -210,7 +210,8 @@ export class RunInfoUiHandler extends UiHandler {
this.runContainer.add(headerText); this.runContainer.add(headerText);
const runName = addTextObject(0, 0, this.runInfo.name, TextStyle.WINDOW); const runName = addTextObject(0, 0, this.runInfo.name, TextStyle.WINDOW);
runName.setOrigin(0, 0); runName.setOrigin(0, 0);
runName.setPositionRelative(headerBg, 60, 4); const runNameX = headerText.width / 6 + headerText.x + 4;
runName.setPositionRelative(headerBg, runNameX, 4);
this.runContainer.add(runName); this.runContainer.add(runName);
} }

View File

@ -134,7 +134,7 @@ describe("Abilities - Disguise", () => {
}); });
await game.classicMode.startBattle([SpeciesId.FURRET, SpeciesId.MIMIKYU]); await game.classicMode.startBattle([SpeciesId.FURRET, SpeciesId.MIMIKYU]);
const mimikyu = game.scene.getPlayerParty()[1]!; const mimikyu = game.scene.getPlayerParty()[1];
expect(mimikyu.formIndex).toBe(bustedForm); expect(mimikyu.formIndex).toBe(bustedForm);
game.move.select(MoveId.SPLASH); game.move.select(MoveId.SPLASH);

View File

@ -121,8 +121,8 @@ describe("Abilities - Sheer Force", () => {
await game.classicMode.startBattle([SpeciesId.PIDGEOT]); await game.classicMode.startBattle([SpeciesId.PIDGEOT]);
const pidgeot = game.scene.getPlayerParty()[0]; const pidgeot = game.field.getPlayerPokemon();
const onix = game.scene.getEnemyParty()[0]; const onix = game.field.getEnemyPokemon();
pidgeot.stats[Stat.DEF] = 10000; pidgeot.stats[Stat.DEF] = 10000;
onix.stats[Stat.DEF] = 10000; onix.stats[Stat.DEF] = 10000;

View File

@ -1,7 +1,6 @@
import { AbilityId } from "#enums/ability-id"; import { AbilityId } from "#enums/ability-id";
import { MoveId } from "#enums/move-id"; import { MoveId } from "#enums/move-id";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import type { EnemyPokemon } from "#field/pokemon";
import { DamageAnimPhase } from "#phases/damage-anim-phase"; import { DamageAnimPhase } from "#phases/damage-anim-phase";
import { MoveEndPhase } from "#phases/move-end-phase"; import { MoveEndPhase } from "#phases/move-end-phase";
import { GameManager } from "#test/test-utils/game-manager"; import { GameManager } from "#test/test-utils/game-manager";
@ -38,13 +37,13 @@ describe("Abilities - Sturdy", () => {
await game.classicMode.startBattle(); await game.classicMode.startBattle();
game.move.select(MoveId.CLOSE_COMBAT); game.move.select(MoveId.CLOSE_COMBAT);
await game.phaseInterceptor.to(MoveEndPhase); await game.phaseInterceptor.to(MoveEndPhase);
expect(game.scene.getEnemyParty()[0].hp).toBe(1); expect(game.field.getEnemyPokemon().hp).toBe(1);
}); });
test("Sturdy doesn't activate when user is not at full HP", async () => { test("Sturdy doesn't activate when user is not at full HP", async () => {
await game.classicMode.startBattle(); await game.classicMode.startBattle();
const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; const enemyPokemon = game.field.getEnemyPokemon();
enemyPokemon.hp = enemyPokemon.getMaxHp() - 1; enemyPokemon.hp = enemyPokemon.getMaxHp() - 1;
game.move.select(MoveId.CLOSE_COMBAT); game.move.select(MoveId.CLOSE_COMBAT);
@ -59,19 +58,7 @@ describe("Abilities - Sturdy", () => {
game.move.select(MoveId.FISSURE); game.move.select(MoveId.FISSURE);
await game.phaseInterceptor.to(MoveEndPhase); await game.phaseInterceptor.to(MoveEndPhase);
const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; const enemyPokemon = game.field.getEnemyPokemon();
expect(enemyPokemon.isFullHp()).toBe(true); expect(enemyPokemon.isFullHp()).toBe(true);
}); });
test("Sturdy is ignored by pokemon with `AbilityId.MOLD_BREAKER`", async () => {
game.override.ability(AbilityId.MOLD_BREAKER);
await game.classicMode.startBattle();
game.move.select(MoveId.CLOSE_COMBAT);
await game.phaseInterceptor.to(DamageAnimPhase);
const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0];
expect(enemyPokemon.hp).toBe(0);
expect(enemyPokemon.isFainted()).toBe(true);
});
}); });

View File

@ -336,7 +336,7 @@ describe("Abilities - Wimp Out", () => {
game.move.select(MoveId.SPLASH); game.move.select(MoveId.SPLASH);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
expect(game.scene.getPlayerParty()[0].getHpRatio()).toEqual(0.51); expect(game.field.getPlayerPokemon().getHpRatio()).toEqual(0.51);
expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase"); expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase");
expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.WIMPOD); expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.WIMPOD);
}); });
@ -344,8 +344,7 @@ describe("Abilities - Wimp Out", () => {
it("Wimp Out activating should not cancel a double battle", async () => { it("Wimp Out activating should not cancel a double battle", async () => {
game.override.battleStyle("double").enemyAbility(AbilityId.WIMP_OUT).enemyMoveset([MoveId.SPLASH]).enemyLevel(1); game.override.battleStyle("double").enemyAbility(AbilityId.WIMP_OUT).enemyMoveset([MoveId.SPLASH]).enemyLevel(1);
await game.classicMode.startBattle([SpeciesId.WIMPOD, SpeciesId.TYRUNT]); await game.classicMode.startBattle([SpeciesId.WIMPOD, SpeciesId.TYRUNT]);
const enemyLeadPokemon = game.scene.getEnemyParty()[0]; const [enemyLeadPokemon, enemySecPokemon] = game.scene.getEnemyParty();
const enemySecPokemon = game.scene.getEnemyParty()[1];
game.move.select(MoveId.FALSE_SWIPE, 0, BattlerIndex.ENEMY); game.move.select(MoveId.FALSE_SWIPE, 0, BattlerIndex.ENEMY);
game.move.select(MoveId.SPLASH, 1); game.move.select(MoveId.SPLASH, 1);

View File

@ -40,8 +40,7 @@ describe("Abilities - ZERO TO HERO", () => {
await game.classicMode.startBattle([SpeciesId.FEEBAS, SpeciesId.PALAFIN, SpeciesId.PALAFIN]); await game.classicMode.startBattle([SpeciesId.FEEBAS, SpeciesId.PALAFIN, SpeciesId.PALAFIN]);
const palafin1 = game.scene.getPlayerParty()[1]; const [, palafin1, palafin2] = game.scene.getPlayerParty();
const palafin2 = game.scene.getPlayerParty()[2];
expect(palafin1.formIndex).toBe(heroForm); expect(palafin1.formIndex).toBe(heroForm);
expect(palafin2.formIndex).toBe(heroForm); expect(palafin2.formIndex).toBe(heroForm);
palafin2.hp = 0; palafin2.hp = 0;

View File

@ -64,11 +64,9 @@ describe("Boss Pokemon / Shields", () => {
it("should reduce the number of shields if we are in a double battle", async () => { it("should reduce the number of shields if we are in a double battle", async () => {
game.override.battleStyle("double").startingWave(150); // Floor 150 > 2 shields / 3 health segments game.override.battleStyle("double").startingWave(150); // Floor 150 > 2 shields / 3 health segments
await game.classicMode.startBattle([SpeciesId.MEWTWO]); await game.classicMode.startBattle([SpeciesId.MEWTWO]);
const boss1: EnemyPokemon = game.scene.getEnemyParty()[0]!; const [boss1, boss2] = game.scene.getEnemyParty();
const boss2: EnemyPokemon = game.scene.getEnemyParty()[1]!;
expect(boss1.isBoss()).toBe(true); expect(boss1.isBoss()).toBe(true);
expect(boss1.bossSegments).toBe(2); expect(boss1.bossSegments).toBe(2);
expect(boss2.isBoss()).toBe(true); expect(boss2.isBoss()).toBe(true);
@ -112,7 +110,7 @@ describe("Boss Pokemon / Shields", () => {
// In this test we want to break through 3 shields at once // In this test we want to break through 3 shields at once
const brokenShields = 3; const brokenShields = 3;
const boss1: EnemyPokemon = game.scene.getEnemyParty()[0]!; const boss1 = game.field.getEnemyPokemon();
const boss1SegmentHp = boss1.getMaxHp() / boss1.bossSegments; const boss1SegmentHp = boss1.getMaxHp() / boss1.bossSegments;
const requiredDamageBoss1 = boss1SegmentHp * (1 + Math.pow(2, brokenShields)); const requiredDamageBoss1 = boss1SegmentHp * (1 + Math.pow(2, brokenShields));
expect(boss1.isBoss()).toBe(true); expect(boss1.isBoss()).toBe(true);
@ -124,7 +122,7 @@ describe("Boss Pokemon / Shields", () => {
expect(boss1.bossSegmentIndex).toBe(1); expect(boss1.bossSegmentIndex).toBe(1);
expect(boss1.hp).toBe(boss1.getMaxHp() - toDmgValue(boss1SegmentHp * 3)); expect(boss1.hp).toBe(boss1.getMaxHp() - toDmgValue(boss1SegmentHp * 3));
const boss2: EnemyPokemon = game.scene.getEnemyParty()[1]!; const boss2 = game.scene.getEnemyParty()[1];
const boss2SegmentHp = boss2.getMaxHp() / boss2.bossSegments; const boss2SegmentHp = boss2.getMaxHp() / boss2.bossSegments;
const requiredDamageBoss2 = boss2SegmentHp * (1 + Math.pow(2, brokenShields)); const requiredDamageBoss2 = boss2SegmentHp * (1 + Math.pow(2, brokenShields));
@ -144,7 +142,7 @@ describe("Boss Pokemon / Shields", () => {
await game.classicMode.startBattle([SpeciesId.MEWTWO]); await game.classicMode.startBattle([SpeciesId.MEWTWO]);
const boss1: EnemyPokemon = game.scene.getEnemyParty()[0]!; const boss1 = game.field.getEnemyPokemon();
const boss1SegmentHp = boss1.getMaxHp() / boss1.bossSegments; const boss1SegmentHp = boss1.getMaxHp() / boss1.bossSegments;
const singleShieldDamage = Math.ceil(boss1SegmentHp); const singleShieldDamage = Math.ceil(boss1SegmentHp);
expect(boss1.isBoss()).toBe(true); expect(boss1.isBoss()).toBe(true);
@ -167,7 +165,7 @@ describe("Boss Pokemon / Shields", () => {
expect(getTotalStatStageBoosts(boss1)).toBe(totalStatStages); expect(getTotalStatStageBoosts(boss1)).toBe(totalStatStages);
} }
const boss2: EnemyPokemon = game.scene.getEnemyParty()[1]!; const boss2 = game.scene.getEnemyParty()[1];
const boss2SegmentHp = boss2.getMaxHp() / boss2.bossSegments; const boss2SegmentHp = boss2.getMaxHp() / boss2.bossSegments;
const requiredDamage = boss2SegmentHp * (1 + Math.pow(2, shieldsToBreak - 1)); const requiredDamage = boss2SegmentHp * (1 + Math.pow(2, shieldsToBreak - 1));

View File

@ -1,8 +1,10 @@
import { AbilityId } from "#enums/ability-id"; import { AbilityId } from "#enums/ability-id";
import { Challenges } from "#enums/challenges"; import { Challenges } from "#enums/challenges";
import { MoveId } from "#enums/move-id"; import { MoveId } from "#enums/move-id";
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { PokeballType } from "#enums/pokeball"; import { PokeballType } from "#enums/pokeball";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounter-test-utils";
import { GameManager } from "#test/test-utils/game-manager"; import { GameManager } from "#test/test-utils/game-manager";
import Phaser from "phaser"; import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
@ -52,4 +54,18 @@ describe("Challenges - Limited Catch", () => {
expect(game.scene.getPlayerParty()).toHaveLength(1); expect(game.scene.getPlayerParty()).toHaveLength(1);
}); });
it("should allow gift Pokémon from Mystery Encounters to be added to party", async () => {
game.override
.mysteryEncounterChance(100)
.mysteryEncounter(MysteryEncounterType.THE_POKEMON_SALESMAN)
.startingWave(12);
game.scene.money = 20000;
await game.challengeMode.runToSummon([SpeciesId.NUZLEAF]);
await runMysteryEncounterToEnd(game, 1);
expect(game.scene.getPlayerParty()).toHaveLength(2);
});
}); });

View File

@ -3,6 +3,7 @@ import { Challenges } from "#enums/challenges";
import { MoveId } from "#enums/move-id"; import { MoveId } from "#enums/move-id";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { ExpBoosterModifier } from "#modifiers/modifier";
import { GameManager } from "#test/test-utils/game-manager"; import { GameManager } from "#test/test-utils/game-manager";
import { ModifierSelectUiHandler } from "#ui/modifier-select-ui-handler"; import { ModifierSelectUiHandler } from "#ui/modifier-select-ui-handler";
import Phaser from "phaser"; import Phaser from "phaser";
@ -75,6 +76,7 @@ describe("Challenges - Limited Support", () => {
await game.doKillOpponents(); await game.doKillOpponents();
await game.toNextWave(); await game.toNextWave();
expect(game.scene.getModifiers(ExpBoosterModifier)).toHaveLength(1);
expect(playerPokemon).not.toHaveFullHp(); expect(playerPokemon).not.toHaveFullHp();
game.move.use(MoveId.SPLASH); game.move.use(MoveId.SPLASH);

View File

@ -34,8 +34,7 @@ describe("Evolution", () => {
it("should keep hidden ability after evolving", async () => { it("should keep hidden ability after evolving", async () => {
await game.classicMode.runToSummon([SpeciesId.EEVEE, SpeciesId.TRAPINCH]); await game.classicMode.runToSummon([SpeciesId.EEVEE, SpeciesId.TRAPINCH]);
const eevee = game.scene.getPlayerParty()[0]; const [eevee, trapinch] = game.scene.getPlayerParty();
const trapinch = game.scene.getPlayerParty()[1];
eevee.abilityIndex = 2; eevee.abilityIndex = 2;
trapinch.abilityIndex = 2; trapinch.abilityIndex = 2;
@ -49,8 +48,7 @@ describe("Evolution", () => {
it("should keep same ability slot after evolving", async () => { it("should keep same ability slot after evolving", async () => {
await game.classicMode.runToSummon([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER]); await game.classicMode.runToSummon([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER]);
const bulbasaur = game.scene.getPlayerParty()[0]; const [bulbasaur, charmander] = game.scene.getPlayerParty();
const charmander = game.scene.getPlayerParty()[1];
bulbasaur.abilityIndex = 0; bulbasaur.abilityIndex = 0;
charmander.abilityIndex = 1; charmander.abilityIndex = 1;
@ -80,8 +78,7 @@ describe("Evolution", () => {
nincada.gender = 1; nincada.gender = 1;
await nincada.evolve(pokemonEvolutions[SpeciesId.NINCADA][0], nincada.getSpeciesForm()); await nincada.evolve(pokemonEvolutions[SpeciesId.NINCADA][0], nincada.getSpeciesForm());
const ninjask = game.scene.getPlayerParty()[0]; const [ninjask, shedinja] = game.scene.getPlayerParty();
const shedinja = game.scene.getPlayerParty()[1];
expect(ninjask.abilityIndex).toBe(2); expect(ninjask.abilityIndex).toBe(2);
expect(shedinja.abilityIndex).toBe(1); expect(shedinja.abilityIndex).toBe(1);
expect(ninjask.gender).toBe(1); expect(ninjask.gender).toBe(1);

View File

@ -85,17 +85,14 @@ describe("Spec - Pokemon", () => {
}); });
describe("Get correct fusion type", () => { describe("Get correct fusion type", () => {
let scene: BattleScene;
beforeEach(async () => { beforeEach(async () => {
game.override.enemySpecies(SpeciesId.ZUBAT).starterSpecies(SpeciesId.ABRA).enableStarterFusion(); game.override.enemySpecies(SpeciesId.ZUBAT).starterSpecies(SpeciesId.ABRA).enableStarterFusion();
scene = game.scene;
}); });
it("Fusing two mons with a single type", async () => { it("Fusing two mons with a single type", async () => {
game.override.starterFusionSpecies(SpeciesId.CHARMANDER); game.override.starterFusionSpecies(SpeciesId.CHARMANDER);
await game.classicMode.startBattle(); await game.classicMode.startBattle();
const pokemon = scene.getPlayerParty()[0]; const pokemon = game.field.getPlayerPokemon();
let types = pokemon.getTypes(); let types = pokemon.getTypes();
expect(types[0]).toBe(PokemonType.PSYCHIC); expect(types[0]).toBe(PokemonType.PSYCHIC);
@ -136,7 +133,7 @@ describe("Spec - Pokemon", () => {
it("Fusing two mons with same single type", async () => { it("Fusing two mons with same single type", async () => {
game.override.starterFusionSpecies(SpeciesId.DROWZEE); game.override.starterFusionSpecies(SpeciesId.DROWZEE);
await game.classicMode.startBattle(); await game.classicMode.startBattle();
const pokemon = scene.getPlayerParty()[0]; const pokemon = game.field.getPlayerPokemon();
const types = pokemon.getTypes(); const types = pokemon.getTypes();
expect(types[0]).toBe(PokemonType.PSYCHIC); expect(types[0]).toBe(PokemonType.PSYCHIC);
@ -146,7 +143,7 @@ describe("Spec - Pokemon", () => {
it("Fusing mons with one and two types", async () => { it("Fusing mons with one and two types", async () => {
game.override.starterSpecies(SpeciesId.CHARMANDER).starterFusionSpecies(SpeciesId.HOUNDOUR); game.override.starterSpecies(SpeciesId.CHARMANDER).starterFusionSpecies(SpeciesId.HOUNDOUR);
await game.classicMode.startBattle(); await game.classicMode.startBattle();
const pokemon = scene.getPlayerParty()[0]; const pokemon = game.field.getPlayerPokemon();
const types = pokemon.getTypes(); const types = pokemon.getTypes();
expect(types[0]).toBe(PokemonType.FIRE); expect(types[0]).toBe(PokemonType.FIRE);
@ -156,7 +153,7 @@ describe("Spec - Pokemon", () => {
it("Fusing mons with two and one types", async () => { it("Fusing mons with two and one types", async () => {
game.override.starterSpecies(SpeciesId.NUMEL).starterFusionSpecies(SpeciesId.CHARMANDER); game.override.starterSpecies(SpeciesId.NUMEL).starterFusionSpecies(SpeciesId.CHARMANDER);
await game.classicMode.startBattle(); await game.classicMode.startBattle();
const pokemon = scene.getPlayerParty()[0]; const pokemon = game.field.getPlayerPokemon();
const types = pokemon.getTypes(); const types = pokemon.getTypes();
expect(types[0]).toBe(PokemonType.FIRE); expect(types[0]).toBe(PokemonType.FIRE);
@ -166,7 +163,7 @@ describe("Spec - Pokemon", () => {
it("Fusing two mons with two types", async () => { it("Fusing two mons with two types", async () => {
game.override.starterSpecies(SpeciesId.NATU).starterFusionSpecies(SpeciesId.HOUNDOUR); game.override.starterSpecies(SpeciesId.NATU).starterFusionSpecies(SpeciesId.HOUNDOUR);
await game.classicMode.startBattle(); await game.classicMode.startBattle();
const pokemon = scene.getPlayerParty()[0]; const pokemon = game.field.getPlayerPokemon();
let types = pokemon.getTypes(); let types = pokemon.getTypes();
expect(types[0]).toBe(PokemonType.PSYCHIC); expect(types[0]).toBe(PokemonType.PSYCHIC);

View File

@ -33,7 +33,7 @@ describe("Items - Light Ball", () => {
const consoleSpy = vi.spyOn(console, "log"); const consoleSpy = vi.spyOn(console, "log");
await game.classicMode.startBattle([SpeciesId.PIKACHU]); await game.classicMode.startBattle([SpeciesId.PIKACHU]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
// Checking console log to make sure Light Ball is applied when getEffectiveStat (with the appropriate stat) is called // Checking console log to make sure Light Ball is applied when getEffectiveStat (with the appropriate stat) is called
partyMember.getEffectiveStat(Stat.DEF); partyMember.getEffectiveStat(Stat.DEF);
@ -84,7 +84,7 @@ describe("Items - Light Ball", () => {
it("LIGHT_BALL held by PIKACHU", async () => { it("LIGHT_BALL held by PIKACHU", async () => {
await game.classicMode.startBattle([SpeciesId.PIKACHU]); await game.classicMode.startBattle([SpeciesId.PIKACHU]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
const atkStat = partyMember.getStat(Stat.ATK); const atkStat = partyMember.getStat(Stat.ATK);
const spAtkStat = partyMember.getStat(Stat.SPATK); const spAtkStat = partyMember.getStat(Stat.SPATK);
@ -113,8 +113,7 @@ describe("Items - Light Ball", () => {
it("LIGHT_BALL held by fused PIKACHU (base)", async () => { it("LIGHT_BALL held by fused PIKACHU (base)", async () => {
await game.classicMode.startBattle([SpeciesId.PIKACHU, SpeciesId.MAROWAK]); await game.classicMode.startBattle([SpeciesId.PIKACHU, SpeciesId.MAROWAK]);
const partyMember = game.scene.getPlayerParty()[0]; const [partyMember, ally] = game.scene.getPlayerParty();
const ally = game.scene.getPlayerParty()[1];
// Fuse party members (taken from PlayerPokemon.fuse(...) function) // Fuse party members (taken from PlayerPokemon.fuse(...) function)
partyMember.fusionSpecies = ally.species; partyMember.fusionSpecies = ally.species;
@ -152,8 +151,7 @@ describe("Items - Light Ball", () => {
it("LIGHT_BALL held by fused PIKACHU (part)", async () => { it("LIGHT_BALL held by fused PIKACHU (part)", async () => {
await game.classicMode.startBattle([SpeciesId.MAROWAK, SpeciesId.PIKACHU]); await game.classicMode.startBattle([SpeciesId.MAROWAK, SpeciesId.PIKACHU]);
const partyMember = game.scene.getPlayerParty()[0]; const [partyMember, ally] = game.scene.getPlayerParty();
const ally = game.scene.getPlayerParty()[1];
// Fuse party members (taken from PlayerPokemon.fuse(...) function) // Fuse party members (taken from PlayerPokemon.fuse(...) function)
partyMember.fusionSpecies = ally.species; partyMember.fusionSpecies = ally.species;
@ -191,7 +189,7 @@ describe("Items - Light Ball", () => {
it("LIGHT_BALL not held by PIKACHU", async () => { it("LIGHT_BALL not held by PIKACHU", async () => {
await game.classicMode.startBattle([SpeciesId.MAROWAK]); await game.classicMode.startBattle([SpeciesId.MAROWAK]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
const atkStat = partyMember.getStat(Stat.ATK); const atkStat = partyMember.getStat(Stat.ATK);
const spAtkStat = partyMember.getStat(Stat.SPATK); const spAtkStat = partyMember.getStat(Stat.SPATK);

View File

@ -33,7 +33,7 @@ describe("Items - Metal Powder", () => {
const consoleSpy = vi.spyOn(console, "log"); const consoleSpy = vi.spyOn(console, "log");
await game.classicMode.startBattle([SpeciesId.DITTO]); await game.classicMode.startBattle([SpeciesId.DITTO]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
// Checking console log to make sure Metal Powder is applied when getEffectiveStat (with the appropriate stat) is called // Checking console log to make sure Metal Powder is applied when getEffectiveStat (with the appropriate stat) is called
partyMember.getEffectiveStat(Stat.DEF); partyMember.getEffectiveStat(Stat.DEF);
@ -84,7 +84,7 @@ describe("Items - Metal Powder", () => {
it("METAL_POWDER held by DITTO", async () => { it("METAL_POWDER held by DITTO", async () => {
await game.classicMode.startBattle([SpeciesId.DITTO]); await game.classicMode.startBattle([SpeciesId.DITTO]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
const defStat = partyMember.getStat(Stat.DEF); const defStat = partyMember.getStat(Stat.DEF);
@ -107,8 +107,7 @@ describe("Items - Metal Powder", () => {
it("METAL_POWDER held by fused DITTO (base)", async () => { it("METAL_POWDER held by fused DITTO (base)", async () => {
await game.classicMode.startBattle([SpeciesId.DITTO, SpeciesId.MAROWAK]); await game.classicMode.startBattle([SpeciesId.DITTO, SpeciesId.MAROWAK]);
const partyMember = game.scene.getPlayerParty()[0]; const [partyMember, ally] = game.scene.getPlayerParty();
const ally = game.scene.getPlayerParty()[1];
// Fuse party members (taken from PlayerPokemon.fuse(...) function) // Fuse party members (taken from PlayerPokemon.fuse(...) function)
partyMember.fusionSpecies = ally.species; partyMember.fusionSpecies = ally.species;
@ -140,8 +139,7 @@ describe("Items - Metal Powder", () => {
it("METAL_POWDER held by fused DITTO (part)", async () => { it("METAL_POWDER held by fused DITTO (part)", async () => {
await game.classicMode.startBattle([SpeciesId.MAROWAK, SpeciesId.DITTO]); await game.classicMode.startBattle([SpeciesId.MAROWAK, SpeciesId.DITTO]);
const partyMember = game.scene.getPlayerParty()[0]; const [partyMember, ally] = game.scene.getPlayerParty();
const ally = game.scene.getPlayerParty()[1];
// Fuse party members (taken from PlayerPokemon.fuse(...) function) // Fuse party members (taken from PlayerPokemon.fuse(...) function)
partyMember.fusionSpecies = ally.species; partyMember.fusionSpecies = ally.species;
@ -173,7 +171,7 @@ describe("Items - Metal Powder", () => {
it("METAL_POWDER not held by DITTO", async () => { it("METAL_POWDER not held by DITTO", async () => {
await game.classicMode.startBattle([SpeciesId.MAROWAK]); await game.classicMode.startBattle([SpeciesId.MAROWAK]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
const defStat = partyMember.getStat(Stat.DEF); const defStat = partyMember.getStat(Stat.DEF);

View File

@ -33,7 +33,7 @@ describe("Items - Quick Powder", () => {
const consoleSpy = vi.spyOn(console, "log"); const consoleSpy = vi.spyOn(console, "log");
await game.classicMode.startBattle([SpeciesId.DITTO]); await game.classicMode.startBattle([SpeciesId.DITTO]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
// Checking console log to make sure Quick Powder is applied when getEffectiveStat (with the appropriate stat) is called // Checking console log to make sure Quick Powder is applied when getEffectiveStat (with the appropriate stat) is called
partyMember.getEffectiveStat(Stat.DEF); partyMember.getEffectiveStat(Stat.DEF);
@ -84,7 +84,7 @@ describe("Items - Quick Powder", () => {
it("QUICK_POWDER held by DITTO", async () => { it("QUICK_POWDER held by DITTO", async () => {
await game.classicMode.startBattle([SpeciesId.DITTO]); await game.classicMode.startBattle([SpeciesId.DITTO]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
const spdStat = partyMember.getStat(Stat.SPD); const spdStat = partyMember.getStat(Stat.SPD);
@ -107,8 +107,7 @@ describe("Items - Quick Powder", () => {
it("QUICK_POWDER held by fused DITTO (base)", async () => { it("QUICK_POWDER held by fused DITTO (base)", async () => {
await game.classicMode.startBattle([SpeciesId.DITTO, SpeciesId.MAROWAK]); await game.classicMode.startBattle([SpeciesId.DITTO, SpeciesId.MAROWAK]);
const partyMember = game.scene.getPlayerParty()[0]; const [partyMember, ally] = game.scene.getPlayerParty();
const ally = game.scene.getPlayerParty()[1];
// Fuse party members (taken from PlayerPokemon.fuse(...) function) // Fuse party members (taken from PlayerPokemon.fuse(...) function)
partyMember.fusionSpecies = ally.species; partyMember.fusionSpecies = ally.species;
@ -140,8 +139,7 @@ describe("Items - Quick Powder", () => {
it("QUICK_POWDER held by fused DITTO (part)", async () => { it("QUICK_POWDER held by fused DITTO (part)", async () => {
await game.classicMode.startBattle([SpeciesId.MAROWAK, SpeciesId.DITTO]); await game.classicMode.startBattle([SpeciesId.MAROWAK, SpeciesId.DITTO]);
const partyMember = game.scene.getPlayerParty()[0]; const [partyMember, ally] = game.scene.getPlayerParty();
const ally = game.scene.getPlayerParty()[1];
// Fuse party members (taken from PlayerPokemon.fuse(...) function) // Fuse party members (taken from PlayerPokemon.fuse(...) function)
partyMember.fusionSpecies = ally.species; partyMember.fusionSpecies = ally.species;
@ -173,7 +171,7 @@ describe("Items - Quick Powder", () => {
it("QUICK_POWDER not held by DITTO", async () => { it("QUICK_POWDER not held by DITTO", async () => {
await game.classicMode.startBattle([SpeciesId.MAROWAK]); await game.classicMode.startBattle([SpeciesId.MAROWAK]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
const spdStat = partyMember.getStat(Stat.SPD); const spdStat = partyMember.getStat(Stat.SPD);

View File

@ -33,7 +33,7 @@ describe("Items - Thick Club", () => {
const consoleSpy = vi.spyOn(console, "log"); const consoleSpy = vi.spyOn(console, "log");
await game.classicMode.startBattle([SpeciesId.CUBONE]); await game.classicMode.startBattle([SpeciesId.CUBONE]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
// Checking console log to make sure Thick Club is applied when getEffectiveStat (with the appropriate stat) is called // Checking console log to make sure Thick Club is applied when getEffectiveStat (with the appropriate stat) is called
partyMember.getEffectiveStat(Stat.DEF); partyMember.getEffectiveStat(Stat.DEF);
@ -84,7 +84,7 @@ describe("Items - Thick Club", () => {
it("THICK_CLUB held by CUBONE", async () => { it("THICK_CLUB held by CUBONE", async () => {
await game.classicMode.startBattle([SpeciesId.CUBONE]); await game.classicMode.startBattle([SpeciesId.CUBONE]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
const atkStat = partyMember.getStat(Stat.ATK); const atkStat = partyMember.getStat(Stat.ATK);
@ -107,7 +107,7 @@ describe("Items - Thick Club", () => {
it("THICK_CLUB held by MAROWAK", async () => { it("THICK_CLUB held by MAROWAK", async () => {
await game.classicMode.startBattle([SpeciesId.MAROWAK]); await game.classicMode.startBattle([SpeciesId.MAROWAK]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
const atkStat = partyMember.getStat(Stat.ATK); const atkStat = partyMember.getStat(Stat.ATK);
@ -130,7 +130,7 @@ describe("Items - Thick Club", () => {
it("THICK_CLUB held by ALOLA_MAROWAK", async () => { it("THICK_CLUB held by ALOLA_MAROWAK", async () => {
await game.classicMode.startBattle([SpeciesId.ALOLA_MAROWAK]); await game.classicMode.startBattle([SpeciesId.ALOLA_MAROWAK]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
const atkStat = partyMember.getStat(Stat.ATK); const atkStat = partyMember.getStat(Stat.ATK);
@ -157,8 +157,7 @@ describe("Items - Thick Club", () => {
await game.classicMode.startBattle([species[randSpecies], SpeciesId.PIKACHU]); await game.classicMode.startBattle([species[randSpecies], SpeciesId.PIKACHU]);
const partyMember = game.scene.getPlayerParty()[0]; const [partyMember, ally] = game.scene.getPlayerParty();
const ally = game.scene.getPlayerParty()[1];
// Fuse party members (taken from PlayerPokemon.fuse(...) function) // Fuse party members (taken from PlayerPokemon.fuse(...) function)
partyMember.fusionSpecies = ally.species; partyMember.fusionSpecies = ally.species;
@ -194,8 +193,7 @@ describe("Items - Thick Club", () => {
await game.classicMode.startBattle([SpeciesId.PIKACHU, species[randSpecies]]); await game.classicMode.startBattle([SpeciesId.PIKACHU, species[randSpecies]]);
const partyMember = game.scene.getPlayerParty()[0]; const [partyMember, ally] = game.scene.getPlayerParty();
const ally = game.scene.getPlayerParty()[1];
// Fuse party members (taken from PlayerPokemon.fuse(...) function) // Fuse party members (taken from PlayerPokemon.fuse(...) function)
partyMember.fusionSpecies = ally.species; partyMember.fusionSpecies = ally.species;
@ -227,7 +225,7 @@ describe("Items - Thick Club", () => {
it("THICK_CLUB not held by CUBONE", async () => { it("THICK_CLUB not held by CUBONE", async () => {
await game.classicMode.startBattle([SpeciesId.PIKACHU]); await game.classicMode.startBattle([SpeciesId.PIKACHU]);
const partyMember = game.scene.getPlayerParty()[0]; const partyMember = game.field.getPlayerPokemon();
const atkStat = partyMember.getStat(Stat.ATK); const atkStat = partyMember.getStat(Stat.ATK);

View File

@ -46,7 +46,7 @@ describe("Moves - Dragon Rage", () => {
await game.classicMode.startBattle(); await game.classicMode.startBattle();
partyPokemon = game.scene.getPlayerParty()[0]; partyPokemon = game.field.getPlayerPokemon();
enemyPokemon = game.field.getEnemyPokemon(); enemyPokemon = game.field.getEnemyPokemon();
}); });

View File

@ -76,10 +76,9 @@ describe("Moves - Dragon Tail", () => {
game.override.battleStyle("double").enemyMoveset(MoveId.SPLASH).enemyAbility(AbilityId.ROUGH_SKIN); game.override.battleStyle("double").enemyMoveset(MoveId.SPLASH).enemyAbility(AbilityId.ROUGH_SKIN);
await game.classicMode.startBattle([SpeciesId.DRATINI, SpeciesId.DRATINI, SpeciesId.WAILORD, SpeciesId.WAILORD]); await game.classicMode.startBattle([SpeciesId.DRATINI, SpeciesId.DRATINI, SpeciesId.WAILORD, SpeciesId.WAILORD]);
const leadPokemon = game.scene.getPlayerParty()[0]!; const leadPokemon = game.field.getPlayerPokemon();
const enemyLeadPokemon = game.scene.getEnemyParty()[0]!; const [enemyLeadPokemon, enemySecPokemon] = game.scene.getEnemyParty();
const enemySecPokemon = game.scene.getEnemyParty()[1]!;
game.move.select(MoveId.DRAGON_TAIL, 0, BattlerIndex.ENEMY); game.move.select(MoveId.DRAGON_TAIL, 0, BattlerIndex.ENEMY);
game.move.select(MoveId.SPLASH, 1); game.move.select(MoveId.SPLASH, 1);
@ -105,11 +104,9 @@ describe("Moves - Dragon Tail", () => {
game.override.battleStyle("double").enemyMoveset(MoveId.SPLASH).enemyAbility(AbilityId.ROUGH_SKIN); game.override.battleStyle("double").enemyMoveset(MoveId.SPLASH).enemyAbility(AbilityId.ROUGH_SKIN);
await game.classicMode.startBattle([SpeciesId.DRATINI, SpeciesId.DRATINI, SpeciesId.WAILORD, SpeciesId.WAILORD]); await game.classicMode.startBattle([SpeciesId.DRATINI, SpeciesId.DRATINI, SpeciesId.WAILORD, SpeciesId.WAILORD]);
const leadPokemon = game.scene.getPlayerParty()[0]!; const [leadPokemon, secPokemon] = game.scene.getPlayerParty();
const secPokemon = game.scene.getPlayerParty()[1]!;
const enemyLeadPokemon = game.scene.getEnemyParty()[0]!; const [enemyLeadPokemon, enemySecPokemon] = game.scene.getEnemyParty();
const enemySecPokemon = game.scene.getEnemyParty()[1]!;
game.move.select(MoveId.DRAGON_TAIL, 0, BattlerIndex.ENEMY); game.move.select(MoveId.DRAGON_TAIL, 0, BattlerIndex.ENEMY);
// target the same pokemon, second move should be redirected after first flees // target the same pokemon, second move should be redirected after first flees

View File

@ -42,7 +42,7 @@ describe("Moves - Fissure", () => {
await game.classicMode.startBattle(); await game.classicMode.startBattle();
partyPokemon = game.scene.getPlayerParty()[0]; partyPokemon = game.field.getPlayerPokemon();
enemyPokemon = game.field.getEnemyPokemon(); enemyPokemon = game.field.getEnemyPokemon();
}); });

View File

@ -80,19 +80,19 @@ describe("Moves - Parting Shot", () => {
// use Memento 3 times to debuff enemy // use Memento 3 times to debuff enemy
game.move.select(MoveId.MEMENTO); game.move.select(MoveId.MEMENTO);
await game.phaseInterceptor.to(FaintPhase); await game.phaseInterceptor.to(FaintPhase);
expect(game.scene.getPlayerParty()[0].isFainted()).toBe(true); expect(game.field.getPlayerPokemon().isFainted()).toBe(true);
game.doSelectPartyPokemon(1); game.doSelectPartyPokemon(1);
await game.phaseInterceptor.to(TurnInitPhase, false); await game.phaseInterceptor.to(TurnInitPhase, false);
game.move.select(MoveId.MEMENTO); game.move.select(MoveId.MEMENTO);
await game.phaseInterceptor.to(FaintPhase); await game.phaseInterceptor.to(FaintPhase);
expect(game.scene.getPlayerParty()[0].isFainted()).toBe(true); expect(game.field.getPlayerPokemon().isFainted()).toBe(true);
game.doSelectPartyPokemon(2); game.doSelectPartyPokemon(2);
await game.phaseInterceptor.to(TurnInitPhase, false); await game.phaseInterceptor.to(TurnInitPhase, false);
game.move.select(MoveId.MEMENTO); game.move.select(MoveId.MEMENTO);
await game.phaseInterceptor.to(FaintPhase); await game.phaseInterceptor.to(FaintPhase);
expect(game.scene.getPlayerParty()[0].isFainted()).toBe(true); expect(game.field.getPlayerPokemon().isFainted()).toBe(true);
game.doSelectPartyPokemon(3); game.doSelectPartyPokemon(3);
// set up done // set up done
@ -177,8 +177,8 @@ describe("Moves - Parting Shot", () => {
game.move.select(MoveId.SPLASH); game.move.select(MoveId.SPLASH);
// intentionally kill party pokemon, switch to second slot (now 1 party mon is fainted) // intentionally kill party pokemon, switch to second slot (now 1 party mon is fainted)
await game.killPokemon(game.scene.getPlayerParty()[0]); await game.killPokemon(game.field.getPlayerPokemon());
expect(game.scene.getPlayerParty()[0].isFainted()).toBe(true); expect(game.field.getPlayerPokemon().isFainted()).toBe(true);
await game.phaseInterceptor.run(MessagePhase); await game.phaseInterceptor.run(MessagePhase);
game.doSelectPartyPokemon(1); game.doSelectPartyPokemon(1);

View File

@ -133,6 +133,6 @@ describe("Moves - Revival Blessing", () => {
await game.toNextTurn(); await game.toNextTurn();
// If there are incorrectly two switch phases into this slot, the fainted pokemon will end up in slot 3 // If there are incorrectly two switch phases into this slot, the fainted pokemon will end up in slot 3
// Make sure it's still in slot 1 // Make sure it's still in slot 1
expect(game.scene.getEnemyParty()[0]).toBe(enemyFainting); expect(game.field.getEnemyPokemon()).toBe(enemyFainting);
}); });
}); });

View File

@ -44,10 +44,10 @@ describe("Moves - Rollout", () => {
await game.classicMode.startBattle(); await game.classicMode.startBattle();
const playerPkm = game.scene.getPlayerParty()[0]; const playerPkm = game.field.getPlayerPokemon();
vi.spyOn(playerPkm, "stats", "get").mockReturnValue([500000, 1, 1, 1, 1, 1]); // HP, ATK, DEF, SPATK, SPDEF, SPD vi.spyOn(playerPkm, "stats", "get").mockReturnValue([500000, 1, 1, 1, 1, 1]); // HP, ATK, DEF, SPATK, SPDEF, SPD
const enemyPkm = game.scene.getEnemyParty()[0]; const enemyPkm = game.field.getEnemyPokemon();
vi.spyOn(enemyPkm, "stats", "get").mockReturnValue([500000, 1, 1, 1, 1, 1]); // HP, ATK, DEF, SPATK, SPDEF, SPD vi.spyOn(enemyPkm, "stats", "get").mockReturnValue([500000, 1, 1, 1, 1, 1]); // HP, ATK, DEF, SPATK, SPDEF, SPD
vi.spyOn(enemyPkm, "getHeldItems").mockReturnValue([]); //no berries vi.spyOn(enemyPkm, "getHeldItems").mockReturnValue([]); //no berries

View File

@ -6,7 +6,6 @@ import { MoveResult } from "#enums/move-result";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import { RandomMoveAttr } from "#moves/move"; import { RandomMoveAttr } from "#moves/move";
import { PokemonMove } from "#moves/pokemon-move";
import { GameManager } from "#test/test-utils/game-manager"; import { GameManager } from "#test/test-utils/game-manager";
import Phaser from "phaser"; import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
@ -40,7 +39,7 @@ describe("Moves - Sketch", () => {
await game.classicMode.startBattle([SpeciesId.REGIELEKI]); await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
const playerPokemon = game.field.getPlayerPokemon(); const playerPokemon = game.field.getPlayerPokemon();
// can't use normal moveset override because we need to check moveset changes // can't use normal moveset override because we need to check moveset changes
playerPokemon.moveset = [new PokemonMove(MoveId.SKETCH), new PokemonMove(MoveId.SKETCH)]; game.move.changeMoveset(playerPokemon, [MoveId.SKETCH, MoveId.SKETCH]);
game.move.select(MoveId.SKETCH); game.move.select(MoveId.SKETCH);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
@ -62,7 +61,7 @@ describe("Moves - Sketch", () => {
await game.classicMode.startBattle([SpeciesId.REGIELEKI]); await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
const playerPokemon = game.field.getPlayerPokemon(); const playerPokemon = game.field.getPlayerPokemon();
const enemyPokemon = game.field.getEnemyPokemon(); const enemyPokemon = game.field.getEnemyPokemon();
playerPokemon.moveset = [new PokemonMove(MoveId.SKETCH), new PokemonMove(MoveId.GROWL)]; game.move.changeMoveset(playerPokemon, [MoveId.SKETCH, MoveId.GROWL]);
game.move.select(MoveId.GROWL); game.move.select(MoveId.GROWL);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
@ -88,8 +87,9 @@ describe("Moves - Sketch", () => {
game.override.enemyMoveset([MoveId.METRONOME]); game.override.enemyMoveset([MoveId.METRONOME]);
await game.classicMode.startBattle([SpeciesId.REGIELEKI]); await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
const playerPokemon = game.field.getPlayerPokemon(); const playerPokemon = game.field.getPlayerPokemon();
playerPokemon.moveset = [new PokemonMove(MoveId.SKETCH)]; game.move.changeMoveset(playerPokemon, MoveId.SKETCH);
// Opponent uses Metronome -> False Swipe, then player uses Sketch, which should sketch Metronome // Opponent uses Metronome -> False Swipe, then player uses Sketch, which should sketch Metronome
game.move.select(MoveId.SKETCH); game.move.select(MoveId.SKETCH);

View File

@ -48,7 +48,7 @@ describe("Moves - Spikes", () => {
game.doSwitchPokemon(1); game.doSwitchPokemon(1);
await game.toNextTurn(); await game.toNextTurn();
const player = game.scene.getPlayerParty()[0]; const player = game.field.getPlayerPokemon();
expect(player.hp).toBe(player.getMaxHp()); expect(player.hp).toBe(player.getMaxHp());
}); });
@ -62,7 +62,7 @@ describe("Moves - Spikes", () => {
game.move.select(MoveId.ROAR); game.move.select(MoveId.ROAR);
await game.toNextTurn(); await game.toNextTurn();
const enemy = game.scene.getEnemyParty()[0]; const enemy = game.field.getEnemyPokemon();
expect(enemy.hp).toBeLessThan(enemy.getMaxHp()); expect(enemy.hp).toBeLessThan(enemy.getMaxHp());
}); });
@ -77,7 +77,7 @@ describe("Moves - Spikes", () => {
game.forceEnemyToSwitch(); game.forceEnemyToSwitch();
await game.toNextTurn(); await game.toNextTurn();
const enemy = game.scene.getEnemyParty()[0]; const enemy = game.field.getEnemyPokemon();
expect(enemy.hp).toBeLessThan(enemy.getMaxHp()); expect(enemy.hp).toBeLessThan(enemy.getMaxHp());
}); });

View File

@ -50,7 +50,7 @@ describe("Moves - Tackle", () => {
const moveToUse = MoveId.TACKLE; const moveToUse = MoveId.TACKLE;
await game.classicMode.startBattle([SpeciesId.MIGHTYENA]); await game.classicMode.startBattle([SpeciesId.MIGHTYENA]);
game.scene.currentBattle.enemyParty[0].stats[Stat.DEF] = 50; game.scene.currentBattle.enemyParty[0].stats[Stat.DEF] = 50;
game.scene.getPlayerParty()[0].stats[Stat.ATK] = 50; game.field.getPlayerPokemon().stats[Stat.ATK] = 50;
const hpOpponent = game.scene.currentBattle.enemyParty[0].hp; const hpOpponent = game.scene.currentBattle.enemyParty[0].hp;

View File

@ -72,7 +72,7 @@ describe("Moves - Tera Starstorm", () => {
it("targets both opponents in a double battle when used by Terapagos immediately after terastallizing", async () => { it("targets both opponents in a double battle when used by Terapagos immediately after terastallizing", async () => {
await game.classicMode.startBattle([SpeciesId.TERAPAGOS]); await game.classicMode.startBattle([SpeciesId.TERAPAGOS]);
const terapagos = game.scene.getPlayerParty()[0]; const terapagos = game.field.getPlayerPokemon();
terapagos.isTerastallized = false; terapagos.isTerastallized = false;
game.move.selectWithTera(MoveId.TERA_STARSTORM, 0); game.move.selectWithTera(MoveId.TERA_STARSTORM, 0);
@ -89,7 +89,7 @@ describe("Moves - Tera Starstorm", () => {
it("targets only one opponent in a double battle when used by Terapagos without terastallizing", async () => { it("targets only one opponent in a double battle when used by Terapagos without terastallizing", async () => {
await game.classicMode.startBattle([SpeciesId.TERAPAGOS]); await game.classicMode.startBattle([SpeciesId.TERAPAGOS]);
const terapagos = game.scene.getPlayerParty()[0]; const terapagos = game.field.getPlayerPokemon();
terapagos.isTerastallized = false; terapagos.isTerastallized = false;
game.move.select(MoveId.TERA_STARSTORM, 0, BattlerIndex.ENEMY); game.move.select(MoveId.TERA_STARSTORM, 0, BattlerIndex.ENEMY);
@ -106,8 +106,7 @@ describe("Moves - Tera Starstorm", () => {
it("applies the effects when Terapagos in Stellar Form is fused with another Pokemon", async () => { it("applies the effects when Terapagos in Stellar Form is fused with another Pokemon", async () => {
await game.classicMode.startBattle([SpeciesId.TERAPAGOS, SpeciesId.CHARMANDER, SpeciesId.MAGIKARP]); await game.classicMode.startBattle([SpeciesId.TERAPAGOS, SpeciesId.CHARMANDER, SpeciesId.MAGIKARP]);
const fusionedMon = game.scene.getPlayerParty()[0]; const [fusionedMon, , magikarp] = game.scene.getPlayerParty();
const magikarp = game.scene.getPlayerParty()[2];
// Fuse party members (taken from PlayerPokemon.fuse(...) function) // Fuse party members (taken from PlayerPokemon.fuse(...) function)
fusionedMon.fusionSpecies = magikarp.species; fusionedMon.fusionSpecies = magikarp.species;

View File

@ -7,7 +7,6 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { ShinyRateBoosterModifier } from "#modifiers/modifier"; import { ShinyRateBoosterModifier } from "#modifiers/modifier";
import { PokemonMove } from "#moves/pokemon-move";
import { AnOfferYouCantRefuseEncounter } from "#mystery-encounters/an-offer-you-cant-refuse-encounter"; import { AnOfferYouCantRefuseEncounter } from "#mystery-encounters/an-offer-you-cant-refuse-encounter";
import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils";
import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters";
@ -207,9 +206,8 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => {
it("should award EXP to a pokemon with a move in EXTORTION_MOVES", async () => { it("should award EXP to a pokemon with a move in EXTORTION_MOVES", async () => {
game.override.ability(AbilityId.SYNCHRONIZE); // Not an extortion ability, so we can test extortion move game.override.ability(AbilityId.SYNCHRONIZE); // Not an extortion ability, so we can test extortion move
await game.runToMysteryEncounter(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, [SpeciesId.ABRA]); await game.runToMysteryEncounter(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, [SpeciesId.ABRA]);
const party = scene.getPlayerParty(); const abra = game.field.getPlayerPokemon();
const abra = party.find(pkm => pkm.species.speciesId === SpeciesId.ABRA)!; game.move.changeMoveset(abra, MoveId.BEAT_UP);
abra.moveset = [new PokemonMove(MoveId.BEAT_UP)];
const expBefore = abra.exp; const expBefore = abra.exp;
await runMysteryEncounterToEnd(game, 2); await runMysteryEncounterToEnd(game, 2);

View File

@ -230,7 +230,7 @@ describe("Clowning Around - Mystery Encounter", () => {
// Stop next battle before it runs // Stop next battle before it runs
await game.phaseInterceptor.to(NewBattlePhase, false); await game.phaseInterceptor.to(NewBattlePhase, false);
const leadPokemon = scene.getPlayerParty()[0]; const leadPokemon = game.field.getPlayerPokemon();
expect(leadPokemon.customPokemonData?.ability).toBe(abilityToTrain); expect(leadPokemon.customPokemonData?.ability).toBe(abilityToTrain);
}); });
}); });
@ -263,30 +263,30 @@ describe("Clowning Around - Mystery Encounter", () => {
await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty);
// Set some moves on party for attack type booster generation // Set some moves on party for attack type booster generation
scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.TACKLE), new PokemonMove(MoveId.THIEF)]; game.move.changeMoveset(game.field.getPlayerPokemon(), [MoveId.TACKLE, MoveId.THIEF]);
// 2 Sitrus Berries on lead // 2 Sitrus Berries on lead
scene.modifiers = []; scene.modifiers = [];
let itemType = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType; let itemType = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType;
await addItemToPokemon(scene, scene.getPlayerParty()[0], 2, itemType); await addItemToPokemon(scene, game.field.getPlayerPokemon(), 2, itemType);
// 2 Ganlon Berries on lead // 2 Ganlon Berries on lead
itemType = generateModifierType(modifierTypes.BERRY, [BerryType.GANLON]) as PokemonHeldItemModifierType; itemType = generateModifierType(modifierTypes.BERRY, [BerryType.GANLON]) as PokemonHeldItemModifierType;
await addItemToPokemon(scene, scene.getPlayerParty()[0], 2, itemType); await addItemToPokemon(scene, game.field.getPlayerPokemon(), 2, itemType);
// 5 Golden Punch on lead (ultra) // 5 Golden Punch on lead (ultra)
itemType = generateModifierType(modifierTypes.GOLDEN_PUNCH) as PokemonHeldItemModifierType; itemType = generateModifierType(modifierTypes.GOLDEN_PUNCH) as PokemonHeldItemModifierType;
await addItemToPokemon(scene, scene.getPlayerParty()[0], 5, itemType); await addItemToPokemon(scene, game.field.getPlayerPokemon(), 5, itemType);
// 5 Lucky Egg on lead (ultra) // 5 Lucky Egg on lead (ultra)
itemType = generateModifierType(modifierTypes.LUCKY_EGG) as PokemonHeldItemModifierType; itemType = generateModifierType(modifierTypes.LUCKY_EGG) as PokemonHeldItemModifierType;
await addItemToPokemon(scene, scene.getPlayerParty()[0], 5, itemType); await addItemToPokemon(scene, game.field.getPlayerPokemon(), 5, itemType);
// 3 Soothe Bell on lead (great tier, but counted as ultra by this ME) // 3 Soothe Bell on lead (great tier, but counted as ultra by this ME)
itemType = generateModifierType(modifierTypes.SOOTHE_BELL) as PokemonHeldItemModifierType; itemType = generateModifierType(modifierTypes.SOOTHE_BELL) as PokemonHeldItemModifierType;
await addItemToPokemon(scene, scene.getPlayerParty()[0], 3, itemType); await addItemToPokemon(scene, game.field.getPlayerPokemon(), 3, itemType);
// 5 Soul Dew on lead (rogue) // 5 Soul Dew on lead (rogue)
itemType = generateModifierType(modifierTypes.SOUL_DEW) as PokemonHeldItemModifierType; itemType = generateModifierType(modifierTypes.SOUL_DEW) as PokemonHeldItemModifierType;
await addItemToPokemon(scene, scene.getPlayerParty()[0], 5, itemType); await addItemToPokemon(scene, game.field.getPlayerPokemon(), 5, itemType);
// 2 Golden Egg on lead (rogue) // 2 Golden Egg on lead (rogue)
itemType = generateModifierType(modifierTypes.GOLDEN_EGG) as PokemonHeldItemModifierType; itemType = generateModifierType(modifierTypes.GOLDEN_EGG) as PokemonHeldItemModifierType;
await addItemToPokemon(scene, scene.getPlayerParty()[0], 2, itemType); await addItemToPokemon(scene, game.field.getPlayerPokemon(), 2, itemType);
// 5 Soul Dew on second party pokemon (these should not change) // 5 Soul Dew on second party pokemon (these should not change)
itemType = generateModifierType(modifierTypes.SOUL_DEW) as PokemonHeldItemModifierType; itemType = generateModifierType(modifierTypes.SOUL_DEW) as PokemonHeldItemModifierType;
@ -294,7 +294,7 @@ describe("Clowning Around - Mystery Encounter", () => {
await runMysteryEncounterToEnd(game, 2); await runMysteryEncounterToEnd(game, 2);
const leadItemsAfter = scene.getPlayerParty()[0].getHeldItems(); const leadItemsAfter = game.field.getPlayerPokemon().getHeldItems();
const ultraCountAfter = leadItemsAfter const ultraCountAfter = leadItemsAfter
.filter(m => m.type.tier === ModifierTier.ULTRA) .filter(m => m.type.tier === ModifierTier.ULTRA)
.reduce((a, b) => a + b.stackCount, 0); .reduce((a, b) => a + b.stackCount, 0);
@ -348,14 +348,14 @@ describe("Clowning Around - Mystery Encounter", () => {
await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty);
// Same type moves on lead // Same type moves on lead
scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.ICE_BEAM), new PokemonMove(MoveId.SURF)]; game.move.changeMoveset(game.field.getPlayerPokemon(), [MoveId.ICE_BEAM, MoveId.SURF]);
// Different type moves on second // Different type moves on second
scene.getPlayerParty()[1].moveset = [new PokemonMove(MoveId.GRASS_KNOT), new PokemonMove(MoveId.ELECTRO_BALL)]; game.move.changeMoveset(scene.getPlayerParty()[1], [MoveId.GRASS_KNOT, MoveId.ELECTRO_BALL]);
// No moves on third // No moves on third
scene.getPlayerParty()[2].moveset = []; scene.getPlayerParty()[2].moveset = [];
await runMysteryEncounterToEnd(game, 3); await runMysteryEncounterToEnd(game, 3);
const leadTypesAfter = scene.getPlayerParty()[0].getTypes(); const leadTypesAfter = game.field.getPlayerPokemon().getTypes();
const secondaryTypesAfter = scene.getPlayerParty()[1].getTypes(); const secondaryTypesAfter = scene.getPlayerParty()[1].getTypes();
const thirdTypesAfter = scene.getPlayerParty()[2].getTypes(); const thirdTypesAfter = scene.getPlayerParty()[2].getTypes();

View File

@ -6,7 +6,6 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { PokemonMove } from "#moves/pokemon-move";
import { DancingLessonsEncounter } from "#mystery-encounters/dancing-lessons-encounter"; import { DancingLessonsEncounter } from "#mystery-encounters/dancing-lessons-encounter";
import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils";
import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters";
@ -100,7 +99,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty);
// Make party lead's level arbitrarily high to not get KOed by move // Make party lead's level arbitrarily high to not get KOed by move
const partyLead = scene.getPlayerParty()[0]; const partyLead = game.field.getPlayerPokemon();
partyLead.level = 1000; partyLead.level = 1000;
partyLead.calculateStats(); partyLead.calculateStats();
await runMysteryEncounterToEnd(game, 1, undefined, true); await runMysteryEncounterToEnd(game, 1, undefined, true);
@ -121,7 +120,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
it("should have a Baton in the rewards after battle", async () => { it("should have a Baton in the rewards after battle", async () => {
await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty);
// Make party lead's level arbitrarily high to not get KOed by move // Make party lead's level arbitrarily high to not get KOed by move
const partyLead = scene.getPlayerParty()[0]; const partyLead = game.field.getPlayerPokemon();
partyLead.level = 1000; partyLead.level = 1000;
partyLead.calculateStats(); partyLead.calculateStats();
await runMysteryEncounterToEnd(game, 1, undefined, true); await runMysteryEncounterToEnd(game, 1, undefined, true);
@ -159,7 +158,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
const phaseSpy = vi.spyOn(scene.phaseManager, "unshiftPhase"); const phaseSpy = vi.spyOn(scene.phaseManager, "unshiftPhase");
await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty);
scene.getPlayerParty()[0].moveset = []; game.field.getPlayerPokemon().moveset = [];
await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1 }); await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1 });
const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof LearnMovePhase).map(p => p[0]); const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof LearnMovePhase).map(p => p[0]);
@ -171,7 +170,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty);
scene.getPlayerParty()[0].moveset = []; game.field.getPlayerPokemon().moveset = [];
await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1 }); await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1 });
expect(leaveEncounterWithoutBattleSpy).toBeCalled(); expect(leaveEncounterWithoutBattleSpy).toBeCalled();
@ -199,7 +198,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
it("should add Oricorio to the party", async () => { it("should add Oricorio to the party", async () => {
await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty);
const partyCountBefore = scene.getPlayerParty().length; const partyCountBefore = scene.getPlayerParty().length;
scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.DRAGON_DANCE)]; game.move.changeMoveset(game.field.getPlayerPokemon(), MoveId.DRAGON_DANCE);
await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 });
const partyCountAfter = scene.getPlayerParty().length; const partyCountAfter = scene.getPlayerParty().length;
@ -238,7 +237,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty);
scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.DRAGON_DANCE)]; game.move.changeMoveset(game.field.getPlayerPokemon(), MoveId.DRAGON_DANCE);
await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 });
expect(leaveEncounterWithoutBattleSpy).toBeCalled(); expect(leaveEncounterWithoutBattleSpy).toBeCalled();

View File

@ -201,7 +201,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 2 Sitrus berries on party lead // Set 2 Sitrus berries on party lead
scene.modifiers = []; scene.modifiers = [];
const sitrus = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS])!; const sitrus = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS])!;
const sitrusMod = sitrus.newModifier(scene.getPlayerParty()[0]) as BerryModifier; const sitrusMod = sitrus.newModifier(game.field.getPlayerPokemon()) as BerryModifier;
sitrusMod.stackCount = 2; sitrusMod.stackCount = 2;
scene.addModifier(sitrusMod, true, false, false, true); scene.addModifier(sitrusMod, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -222,7 +222,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Reviver Seed on party lead // Set 1 Reviver Seed on party lead
scene.modifiers = []; scene.modifiers = [];
const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!; const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!;
const modifier = revSeed.newModifier(scene.getPlayerParty()[0]) as PokemonInstantReviveModifier; const modifier = revSeed.newModifier(game.field.getPlayerPokemon()) as PokemonInstantReviveModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
scene.addModifier(modifier, true, false, false, true); scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -248,7 +248,7 @@ describe("Delibird-y - Mystery Encounter", () => {
const sitrus = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS])!; const sitrus = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS])!;
// Sitrus berries on party // Sitrus berries on party
const sitrusMod = sitrus.newModifier(scene.getPlayerParty()[0]) as BerryModifier; const sitrusMod = sitrus.newModifier(game.field.getPlayerPokemon()) as BerryModifier;
sitrusMod.stackCount = 2; sitrusMod.stackCount = 2;
scene.addModifier(sitrusMod, true, false, false, true); scene.addModifier(sitrusMod, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -277,7 +277,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Reviver Seed on party lead // Set 1 Reviver Seed on party lead
const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!; const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!;
const modifier = revSeed.newModifier(scene.getPlayerParty()[0]) as PokemonInstantReviveModifier; const modifier = revSeed.newModifier(game.field.getPlayerPokemon()) as PokemonInstantReviveModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
scene.addModifier(modifier, true, false, false, true); scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -301,7 +301,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Soul Dew on party lead // Set 1 Soul Dew on party lead
scene.modifiers = []; scene.modifiers = [];
const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getPlayerParty()[0]); const modifier = soulDew.newModifier(game.field.getPlayerPokemon());
scene.addModifier(modifier, true, false, false, true); scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -329,7 +329,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Reviver Seed on party lead // Set 1 Reviver Seed on party lead
const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!; const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!;
const modifier = revSeed.newModifier(scene.getPlayerParty()[0]) as PokemonInstantReviveModifier; const modifier = revSeed.newModifier(game.field.getPlayerPokemon()) as PokemonInstantReviveModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
scene.addModifier(modifier, true, false, false, true); scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -363,7 +363,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 2 Soul Dew on party lead // Set 2 Soul Dew on party lead
scene.modifiers = []; scene.modifiers = [];
const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier;
modifier.stackCount = 2; modifier.stackCount = 2;
scene.addModifier(modifier, true, false, false, true); scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -384,7 +384,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Soul Dew on party lead // Set 1 Soul Dew on party lead
scene.modifiers = []; scene.modifiers = [];
const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
scene.addModifier(modifier, true, false, false, true); scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -410,7 +410,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Soul Dew on party lead // Set 1 Soul Dew on party lead
const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
scene.addModifier(modifier, true, false, false, true); scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -434,7 +434,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Reviver Seed on party lead // Set 1 Reviver Seed on party lead
scene.modifiers = []; scene.modifiers = [];
const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!; const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!;
const modifier = revSeed.newModifier(scene.getPlayerParty()[0]); const modifier = revSeed.newModifier(game.field.getPlayerPokemon());
scene.addModifier(modifier, true, false, false, true); scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -463,7 +463,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Soul Dew on party lead // Set 1 Soul Dew on party lead
scene.modifiers = []; scene.modifiers = [];
const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
scene.addModifier(modifier, true, false, false, true); scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);

View File

@ -6,7 +6,6 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { PokemonMove } from "#moves/pokemon-move";
import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils";
import { FightOrFlightEncounter } from "#mystery-encounters/fight-or-flight-encounter"; import { FightOrFlightEncounter } from "#mystery-encounters/fight-or-flight-encounter";
import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters";
@ -178,7 +177,7 @@ describe("Fight or Flight - Mystery Encounter", () => {
await game.runToMysteryEncounter(MysteryEncounterType.FIGHT_OR_FLIGHT, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.FIGHT_OR_FLIGHT, defaultParty);
// Mock moveset // Mock moveset
scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.KNOCK_OFF)]; game.move.changeMoveset(game.field.getPlayerPokemon(), MoveId.KNOCK_OFF);
const item = game.scene.currentBattle.mysteryEncounter!.misc; const item = game.scene.currentBattle.mysteryEncounter!.misc;
await runMysteryEncounterToEnd(game, 2); await runMysteryEncounterToEnd(game, 2);

View File

@ -105,14 +105,14 @@ describe("Global Trade System - Mystery Encounter", () => {
it("Should trade a Pokemon from the player's party for the first of 3 Pokemon options", async () => { it("Should trade a Pokemon from the player's party for the first of 3 Pokemon options", async () => {
await game.runToMysteryEncounter(MysteryEncounterType.GLOBAL_TRADE_SYSTEM, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.GLOBAL_TRADE_SYSTEM, defaultParty);
const speciesBefore = scene.getPlayerParty()[0].species.speciesId; const speciesBefore = game.field.getPlayerPokemon().species.speciesId;
await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1, optionNo: 1 }); await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1, optionNo: 1 });
const speciesAfter = scene.getPlayerParty().at(-1)?.species.speciesId; const speciesAfter = scene.getPlayerParty().at(-1)?.species.speciesId;
expect(speciesAfter).toBeDefined(); expect(speciesAfter).toBeDefined();
expect(speciesBefore).not.toBe(speciesAfter); expect(speciesBefore).not.toBe(speciesAfter);
expect(defaultParty.includes(speciesAfter!)).toBeFalsy(); expect(defaultParty).not.toContain(speciesAfter);
}); });
it("Should trade a Pokemon from the player's party for the second of 3 Pokemon options", async () => { it("Should trade a Pokemon from the player's party for the second of 3 Pokemon options", async () => {
@ -220,7 +220,7 @@ describe("Global Trade System - Mystery Encounter", () => {
// Set 2 Soul Dew on party lead // Set 2 Soul Dew on party lead
scene.modifiers = []; scene.modifiers = [];
const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier;
modifier.stackCount = 2; modifier.stackCount = 2;
scene.addModifier(modifier, true, false, false, true); scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -247,7 +247,7 @@ describe("Global Trade System - Mystery Encounter", () => {
// Set 1 Soul Dew on party lead // Set 1 Soul Dew on party lead
scene.modifiers = []; scene.modifiers = [];
const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
scene.addModifier(modifier, true, false, false, true); scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);

View File

@ -5,7 +5,6 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { PokemonMove } from "#moves/pokemon-move";
import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils";
import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters";
import { CIVILIZATION_ENCOUNTER_BIOMES } from "#mystery-encounters/mystery-encounters"; import { CIVILIZATION_ENCOUNTER_BIOMES } from "#mystery-encounters/mystery-encounters";
@ -110,7 +109,7 @@ describe("Part-Timer - Mystery Encounter", () => {
expect(EncounterPhaseUtils.updatePlayerMoney).toHaveBeenCalledWith(scene.getWaveMoneyAmount(1), true, false); expect(EncounterPhaseUtils.updatePlayerMoney).toHaveBeenCalledWith(scene.getWaveMoneyAmount(1), true, false);
// Expect PP of mon's moves to have been reduced to 2 // Expect PP of mon's moves to have been reduced to 2
const moves = scene.getPlayerParty()[0].moveset; const moves = game.field.getPlayerPokemon().moveset;
for (const move of moves) { for (const move of moves) {
expect((move?.getMovePp() ?? 0) - (move?.ppUsed ?? 0)).toBe(2); expect((move?.getMovePp() ?? 0) - (move?.ppUsed ?? 0)).toBe(2);
} }
@ -233,7 +232,9 @@ describe("Part-Timer - Mystery Encounter", () => {
await game.runToMysteryEncounter(MysteryEncounterType.PART_TIMER, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.PART_TIMER, defaultParty);
// Mock movesets // Mock movesets
scene.getPlayerParty().forEach(p => (p.moveset = [])); scene.getPlayerParty().forEach(p => {
p.moveset = [];
});
await game.phaseInterceptor.to(MysteryEncounterPhase, false); await game.phaseInterceptor.to(MysteryEncounterPhase, false);
const encounterPhase = scene.phaseManager.getCurrentPhase(); const encounterPhase = scene.phaseManager.getCurrentPhase();
@ -257,14 +258,14 @@ describe("Part-Timer - Mystery Encounter", () => {
await game.runToMysteryEncounter(MysteryEncounterType.PART_TIMER, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.PART_TIMER, defaultParty);
// Mock moveset // Mock moveset
scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.ATTRACT)]; game.move.changeMoveset(game.field.getPlayerPokemon(), MoveId.ATTRACT);
await runMysteryEncounterToEnd(game, 3); await runMysteryEncounterToEnd(game, 3);
expect(EncounterPhaseUtils.updatePlayerMoney).toHaveBeenCalledWith(scene.getWaveMoneyAmount(2.5), true, false); expect(EncounterPhaseUtils.updatePlayerMoney).toHaveBeenCalledWith(scene.getWaveMoneyAmount(2.5), true, false);
// Expect PP of mon's moves to have been reduced to 2 // Expect PP of mon's moves to have been reduced to 2
const moves = scene.getPlayerParty()[0].moveset; const moves = game.field.getPlayerPokemon().moveset;
for (const move of moves) { for (const move of moves) {
expect((move?.getMovePp() ?? 0) - (move?.ppUsed ?? 0)).toBe(2); expect(move.getMovePp() - move.ppUsed).toBe(2);
} }
}); });

View File

@ -11,7 +11,6 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import type { BerryModifier } from "#modifiers/modifier"; import type { BerryModifier } from "#modifiers/modifier";
import { PokemonMove } from "#moves/pokemon-move";
import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils";
import { generateModifierType } from "#mystery-encounters/encounter-phase-utils"; import { generateModifierType } from "#mystery-encounters/encounter-phase-utils";
import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters";
@ -214,11 +213,11 @@ describe("Uncommon Breed - Mystery Encounter", () => {
// Berries on party lead // Berries on party lead
const sitrus = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS])!; const sitrus = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS])!;
const sitrusMod = sitrus.newModifier(scene.getPlayerParty()[0]) as BerryModifier; const sitrusMod = sitrus.newModifier(game.field.getPlayerPokemon()) as BerryModifier;
sitrusMod.stackCount = 2; sitrusMod.stackCount = 2;
scene.addModifier(sitrusMod, true, false, false, true); scene.addModifier(sitrusMod, true, false, false, true);
const ganlon = generateModifierType(modifierTypes.BERRY, [BerryType.GANLON])!; const ganlon = generateModifierType(modifierTypes.BERRY, [BerryType.GANLON])!;
const ganlonMod = ganlon.newModifier(scene.getPlayerParty()[0]) as BerryModifier; const ganlonMod = ganlon.newModifier(game.field.getPlayerPokemon()) as BerryModifier;
ganlonMod.stackCount = 3; ganlonMod.stackCount = 3;
scene.addModifier(ganlonMod, true, false, false, true); scene.addModifier(ganlonMod, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -270,7 +269,7 @@ describe("Uncommon Breed - Mystery Encounter", () => {
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
await game.runToMysteryEncounter(MysteryEncounterType.UNCOMMON_BREED, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.UNCOMMON_BREED, defaultParty);
// Mock moveset // Mock moveset
scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.CHARM)]; game.move.changeMoveset(game.field.getPlayerPokemon(), MoveId.CHARM);
await runMysteryEncounterToEnd(game, 3); await runMysteryEncounterToEnd(game, 3);
expect(leaveEncounterWithoutBattleSpy).toBeCalled(); expect(leaveEncounterWithoutBattleSpy).toBeCalled();

View File

@ -38,7 +38,7 @@ describe("Form Change Phase", () => {
await game.classicMode.startBattle([SpeciesId.ZACIAN]); await game.classicMode.startBattle([SpeciesId.ZACIAN]);
// Before the form change: Should be Hero form // Before the form change: Should be Hero form
const zacian = game.scene.getPlayerParty()[0]; const zacian = game.field.getPlayerPokemon();
expect(zacian.getFormKey()).toBe("hero-of-many-battles"); expect(zacian.getFormKey()).toBe("hero-of-many-battles");
expect(zacian.getTypes()).toStrictEqual([PokemonType.FAIRY]); expect(zacian.getTypes()).toStrictEqual([PokemonType.FAIRY]);
expect(zacian.calculateBaseStats()).toStrictEqual([92, 120, 115, 80, 115, 138]); expect(zacian.calculateBaseStats()).toStrictEqual([92, 120, 115, 80, 115, 138]);

View File

@ -90,10 +90,10 @@ describe("UI - Starter select", () => {
}); });
await game.phaseInterceptor.whenAboutToRun(EncounterPhase); await game.phaseInterceptor.whenAboutToRun(EncounterPhase);
expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR);
expect(game.scene.getPlayerParty()[0].shiny).toBe(true); expect(game.field.getPlayerPokemon().shiny).toBe(true);
expect(game.scene.getPlayerParty()[0].variant).toBe(2); expect(game.field.getPlayerPokemon().variant).toBe(2);
expect(game.scene.getPlayerParty()[0].gender).toBe(Gender.MALE); expect(game.field.getPlayerPokemon().gender).toBe(Gender.MALE);
}); });
it("Bulbasaur - shiny - variant 2 female hardy overgrow", async () => { it("Bulbasaur - shiny - variant 2 female hardy overgrow", async () => {
@ -151,11 +151,11 @@ describe("UI - Starter select", () => {
}); });
await game.phaseInterceptor.whenAboutToRun(EncounterPhase); await game.phaseInterceptor.whenAboutToRun(EncounterPhase);
expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR);
expect(game.scene.getPlayerParty()[0].shiny).toBe(true); expect(game.field.getPlayerPokemon().shiny).toBe(true);
expect(game.scene.getPlayerParty()[0].variant).toBe(2); expect(game.field.getPlayerPokemon().variant).toBe(2);
expect(game.scene.getPlayerParty()[0].nature).toBe(Nature.HARDY); expect(game.field.getPlayerPokemon().nature).toBe(Nature.HARDY);
expect(game.scene.getPlayerParty()[0].getAbility().id).toBe(AbilityId.OVERGROW); expect(game.field.getPlayerPokemon().getAbility().id).toBe(AbilityId.OVERGROW);
}); });
it("Bulbasaur - shiny - variant 2 female lonely chlorophyl", async () => { it("Bulbasaur - shiny - variant 2 female lonely chlorophyl", async () => {
@ -215,12 +215,12 @@ describe("UI - Starter select", () => {
}); });
await game.phaseInterceptor.whenAboutToRun(EncounterPhase); await game.phaseInterceptor.whenAboutToRun(EncounterPhase);
expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR);
expect(game.scene.getPlayerParty()[0].shiny).toBe(true); expect(game.field.getPlayerPokemon().shiny).toBe(true);
expect(game.scene.getPlayerParty()[0].variant).toBe(2); expect(game.field.getPlayerPokemon().variant).toBe(2);
expect(game.scene.getPlayerParty()[0].gender).toBe(Gender.FEMALE); expect(game.field.getPlayerPokemon().gender).toBe(Gender.FEMALE);
expect(game.scene.getPlayerParty()[0].nature).toBe(Nature.LONELY); expect(game.field.getPlayerPokemon().nature).toBe(Nature.LONELY);
expect(game.scene.getPlayerParty()[0].getAbility().id).toBe(AbilityId.CHLOROPHYLL); expect(game.field.getPlayerPokemon().getAbility().id).toBe(AbilityId.CHLOROPHYLL);
}); });
it("Bulbasaur - shiny - variant 2 female", async () => { it("Bulbasaur - shiny - variant 2 female", async () => {
@ -278,10 +278,10 @@ describe("UI - Starter select", () => {
}); });
await game.phaseInterceptor.whenAboutToRun(EncounterPhase); await game.phaseInterceptor.whenAboutToRun(EncounterPhase);
expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR);
expect(game.scene.getPlayerParty()[0].shiny).toBe(true); expect(game.field.getPlayerPokemon().shiny).toBe(true);
expect(game.scene.getPlayerParty()[0].variant).toBe(2); expect(game.field.getPlayerPokemon().variant).toBe(2);
expect(game.scene.getPlayerParty()[0].gender).toBe(Gender.FEMALE); expect(game.field.getPlayerPokemon().gender).toBe(Gender.FEMALE);
}); });
it("Bulbasaur - not shiny", async () => { it("Bulbasaur - not shiny", async () => {
@ -339,9 +339,9 @@ describe("UI - Starter select", () => {
}); });
await game.phaseInterceptor.whenAboutToRun(EncounterPhase); await game.phaseInterceptor.whenAboutToRun(EncounterPhase);
expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR);
expect(game.scene.getPlayerParty()[0].shiny).toBe(false); expect(game.field.getPlayerPokemon().shiny).toBe(false);
expect(game.scene.getPlayerParty()[0].variant).toBe(0); expect(game.field.getPlayerPokemon().variant).toBe(0);
}); });
it("Bulbasaur - shiny - variant 1", async () => { it("Bulbasaur - shiny - variant 1", async () => {
@ -401,9 +401,9 @@ describe("UI - Starter select", () => {
}); });
await game.phaseInterceptor.whenAboutToRun(EncounterPhase); await game.phaseInterceptor.whenAboutToRun(EncounterPhase);
expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR);
expect(game.scene.getPlayerParty()[0].shiny).toBe(true); expect(game.field.getPlayerPokemon().shiny).toBe(true);
expect(game.scene.getPlayerParty()[0].variant).toBe(1); expect(game.field.getPlayerPokemon().variant).toBe(1);
}); });
it("Bulbasaur - shiny - variant 0", async () => { it("Bulbasaur - shiny - variant 0", async () => {
@ -462,9 +462,9 @@ describe("UI - Starter select", () => {
}); });
await game.phaseInterceptor.whenAboutToRun(EncounterPhase); await game.phaseInterceptor.whenAboutToRun(EncounterPhase);
expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR);
expect(game.scene.getPlayerParty()[0].shiny).toBe(true); expect(game.field.getPlayerPokemon().shiny).toBe(true);
expect(game.scene.getPlayerParty()[0].variant).toBe(0); expect(game.field.getPlayerPokemon().variant).toBe(0);
}); });
it("Check if first pokemon in party is caterpie from gen 1 and 1rd row, 3rd column", async () => { it("Check if first pokemon in party is caterpie from gen 1 and 1rd row, 3rd column", async () => {
@ -528,7 +528,7 @@ describe("UI - Starter select", () => {
saveSlotSelectUiHandler.processInput(Button.ACTION); saveSlotSelectUiHandler.processInput(Button.ACTION);
}); });
await game.phaseInterceptor.whenAboutToRun(EncounterPhase); await game.phaseInterceptor.whenAboutToRun(EncounterPhase);
expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.CATERPIE); expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.CATERPIE);
}); });
it("Check if first pokemon in party is nidoran_m from gen 1 and 2nd row, 4th column (cursor (9+4)-1)", async () => { it("Check if first pokemon in party is nidoran_m from gen 1 and 2nd row, 4th column (cursor (9+4)-1)", async () => {
@ -594,6 +594,6 @@ describe("UI - Starter select", () => {
saveSlotSelectUiHandler.processInput(Button.ACTION); saveSlotSelectUiHandler.processInput(Button.ACTION);
}); });
await game.phaseInterceptor.whenAboutToRun(EncounterPhase); await game.phaseInterceptor.whenAboutToRun(EncounterPhase);
expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.NIDORAN_M); expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.NIDORAN_M);
}); });
}); });