mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2024-11-27 01:06:09 +00:00
commit latest test changes
This commit is contained in:
parent
2fce6a2769
commit
37419eb1d3
@ -206,7 +206,7 @@ export default class Battle {
|
||||
getBgmOverride(scene: BattleScene): string {
|
||||
const battlers = this.enemyParty.slice(0, this.getBattlerCount());
|
||||
if (this.battleType === BattleType.TRAINER || this.mysteryEncounter?.encounterVariant === MysteryEncounterVariant.TRAINER_BATTLE) {
|
||||
if (!this.started && this.trainer.config.encounterBgm && this.trainer.getEncounterMessages()?.length) {
|
||||
if (!this.started && this.trainer?.config?.encounterBgm && this.trainer?.getEncounterMessages()?.length) {
|
||||
return `encounter_${this.trainer.getEncounterBgm()}`;
|
||||
}
|
||||
if (scene.musicPreference === 0) {
|
||||
|
@ -71,7 +71,7 @@ const excludedBosses = [
|
||||
/**
|
||||
* Dark Deal encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/61 | GitHub Issue #61}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const DarkDealEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DARK_DEAL)
|
||||
|
@ -18,7 +18,7 @@ const namespace = "mysteryEncounter:departmentStoreSale";
|
||||
/**
|
||||
* Department Store Sale encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/33 | GitHub Issue #33}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const DepartmentStoreSaleEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DEPARTMENT_STORE_SALE)
|
||||
|
@ -24,7 +24,7 @@ const namespace = "mysteryEncounter:fieldTrip";
|
||||
/**
|
||||
* Field Trip encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/17 | GitHub Issue #17}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const FieldTripEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.FIELD_TRIP)
|
||||
|
@ -31,7 +31,7 @@ const DAMAGE_PERCENTAGE: number = 20;
|
||||
/**
|
||||
* Fiery Fallout encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/88 | GitHub Issue #88}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const FieryFalloutEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.FIERY_FALLOUT)
|
||||
@ -127,8 +127,13 @@ export const FieryFalloutEncounter: IMysteryEncounter =
|
||||
async (scene: BattleScene) => {
|
||||
// Pick battle
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
const charcoal = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.FIRE]);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [charcoal], fillRemaining: true });
|
||||
setEncounterRewards(scene,
|
||||
{ fillRemaining: true },
|
||||
null,
|
||||
() => {
|
||||
giveLeadPokemonCharcoal(scene);
|
||||
});
|
||||
|
||||
encounter.startOfBattleEffects.push(
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
@ -196,8 +201,8 @@ export const FieryFalloutEncounter: IMysteryEncounter =
|
||||
.withOption(
|
||||
new MysteryEncounterOptionBuilder()
|
||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new TypeRequirement(Type.FIRE, true,1)) // Will set option3PrimaryName dialogue token automatically
|
||||
.withSecondaryPokemonRequirement(new TypeRequirement(Type.FIRE, true,1)) // Will set option3SecondaryName dialogue token automatically
|
||||
.withPrimaryPokemonRequirement(new TypeRequirement(Type.STEEL, true,1)) // Will set option3PrimaryName dialogue token automatically
|
||||
.withSecondaryPokemonRequirement(new TypeRequirement(Type.STEEL, true,1)) // Will set option3SecondaryName dialogue token automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}:option:3:label`,
|
||||
buttonTooltip: `${namespace}:option:3:tooltip`,
|
||||
@ -215,8 +220,12 @@ export const FieryFalloutEncounter: IMysteryEncounter =
|
||||
// Fire types help calm the Volcarona
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
transitionMysteryEncounterIntroVisuals(scene);
|
||||
const charcoal = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.FIRE]);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [charcoal], fillRemaining: true });
|
||||
setEncounterRewards(scene,
|
||||
{ fillRemaining: true },
|
||||
null,
|
||||
() => {
|
||||
giveLeadPokemonCharcoal(scene);
|
||||
});
|
||||
|
||||
const primary = encounter.options[2].primaryPokemon;
|
||||
const secondary = encounter.options[2].secondaryPokemon[0];
|
||||
@ -227,3 +236,15 @@ export const FieryFalloutEncounter: IMysteryEncounter =
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
|
||||
function giveLeadPokemonCharcoal(scene: BattleScene) {
|
||||
// Give first party pokemon Charcoal for free at end of battle
|
||||
const leadPokemon = scene.getParty()?.[0];
|
||||
if (leadPokemon) {
|
||||
const charcoal = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.FIRE]);
|
||||
scene.addModifier(charcoal.type.newModifier(leadPokemon), true);
|
||||
scene.updateModifiers();
|
||||
scene.currentBattle.mysteryEncounter.setDialogueToken("leadPokemon", leadPokemon.name);
|
||||
queueEncounterMessage(scene, `${namespace}:found_charcoal`);
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ const namespace = "mysteryEncounter:fightOrFlight";
|
||||
/**
|
||||
* Fight or Flight encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/24 | GitHub Issue #24}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const FightOrFlightEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(
|
||||
|
@ -21,7 +21,7 @@ const namespace = "mysteryEncounter:lostAtSea";
|
||||
/**
|
||||
* Lost at sea encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/9 | GitHub Issue #9}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.LOST_AT_SEA)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
|
@ -26,7 +26,7 @@ const namespace = "mysteryEncounter:mysteriousChallengers";
|
||||
/**
|
||||
* Mysterious Challengers encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/41 | GitHub Issue #41}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const MysteriousChallengersEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(
|
||||
|
@ -14,7 +14,7 @@ const namespace = "mysteryEncounter:mysteriousChest";
|
||||
/**
|
||||
* Mysterious Chest encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/32 | GitHub Issue #32}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const MysteriousChestEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.MYSTERIOUS_CHEST)
|
||||
|
@ -24,7 +24,7 @@ const TRAINER_THROW_ANIMATION_TIMES = [512, 184, 768];
|
||||
/**
|
||||
* Safari Zone encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/39 | GitHub Issue #39}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const SafariZoneEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.SAFARI_ZONE)
|
||||
|
@ -17,7 +17,7 @@ const namespace = "mysteryEncounter:shadyVitaminDealer";
|
||||
/**
|
||||
* Shady Vitamin Dealer encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/34 | GitHub Issue #34}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const ShadyVitaminDealerEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(
|
||||
|
@ -21,7 +21,7 @@ const namespace = "mysteryEncounter:slumberingSnorlax";
|
||||
/**
|
||||
* Sleeping Snorlax encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/103 | GitHub Issue #103}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const SlumberingSnorlaxEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(
|
||||
|
@ -24,7 +24,7 @@ const namespace = "mysteryEncounter:trainingSession";
|
||||
/**
|
||||
* Training Session encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/43 | GitHub Issue #43}
|
||||
* @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts)
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const TrainingSessionEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(
|
||||
|
@ -71,8 +71,6 @@ export default interface IMysteryEncounter {
|
||||
onInit?: (scene: BattleScene) => boolean;
|
||||
/** Event when battlefield visuals have finished sliding in and the encounter dialogue begins */
|
||||
onVisualsStart?: (scene: BattleScene) => boolean;
|
||||
/** Event right before MysteryEncounterPhase begins. Use for unshifting any phases before the actual encounter */
|
||||
onPreMysteryEncounterPhase?: (scene: BattleScene) => boolean;
|
||||
/** Will provide the player party EXP before rewards are displayed for that wave */
|
||||
doEncounterExp?: (scene: BattleScene) => boolean;
|
||||
/** Will provide the player a rewards shop for that wave */
|
||||
@ -392,7 +390,6 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
doEncounterRewards?: (scene: BattleScene) => boolean;
|
||||
onInit?: (scene: BattleScene) => boolean;
|
||||
onVisualsStart?: (scene: BattleScene) => boolean;
|
||||
onPreMysteryEncounterPhase?: (scene: BattleScene) => boolean;
|
||||
|
||||
hideBattleIntroMessage?: boolean;
|
||||
hideIntroVisuals?: boolean;
|
||||
@ -625,18 +622,6 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
return Object.assign(this, { onInit: onInit });
|
||||
}
|
||||
|
||||
/**
|
||||
* Event callback right before MysteryEncounterPhase begins.
|
||||
* Use for unshifting any last-minute phases before the actual encounter, as all phases are cleared and reset at that point.
|
||||
* Example: set the weather before encounter begins
|
||||
*
|
||||
* @param onVisualsStart - synchronous callback function to perform immediately before MysteryEncounterPhase begins
|
||||
* @returns
|
||||
*/
|
||||
withOnPreMysteryEncounterPhase(onPreMysteryEncounterPhase: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "onPreMysteryEncounterPhase">> {
|
||||
return Object.assign(this, { onPreMysteryEncounterPhase: onPreMysteryEncounterPhase });
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to perform some extra logic (usually animations) when the enemy field is finished sliding in
|
||||
*
|
||||
|
@ -50,7 +50,7 @@ export function doTrainerExclamation(scene: BattleScene) {
|
||||
}
|
||||
});
|
||||
|
||||
scene.playSound("GEN8- Exclaim.wav");
|
||||
scene.playSound("GEN8- Exclaim.wav", { volume: 0.8 });
|
||||
}
|
||||
|
||||
export interface EnemyPokemonConfig {
|
||||
@ -417,10 +417,10 @@ export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (p
|
||||
* Can have shop displayed or skipped
|
||||
* @param scene - Battle Scene
|
||||
* @param customShopRewards - adds a shop phase with the specified rewards / reward tiers
|
||||
* @param nonShopRewards - will add a non-shop reward phase for each specified item/modifier (can happen in addition to a shop)
|
||||
* @param nonShopPlayerItemRewards - will add a non-shop reward phase for each specified item/modifier (can happen in addition to a shop)
|
||||
* @param preRewardsCallback - can execute an arbitrary callback before the new phases if necessary (useful for updating items/party/injecting new phases before MysteryEncounterRewardsPhase)
|
||||
*/
|
||||
export function setEncounterRewards(scene: BattleScene, customShopRewards?: CustomModifierSettings, nonShopRewards?: ModifierTypeFunc[], preRewardsCallback?: Function) {
|
||||
export function setEncounterRewards(scene: BattleScene, customShopRewards?: CustomModifierSettings, nonShopPlayerItemRewards?: ModifierTypeFunc[], preRewardsCallback?: Function) {
|
||||
scene.currentBattle.mysteryEncounter.doEncounterRewards = (scene: BattleScene) => {
|
||||
if (preRewardsCallback) {
|
||||
preRewardsCallback();
|
||||
@ -432,8 +432,8 @@ export function setEncounterRewards(scene: BattleScene, customShopRewards?: Cust
|
||||
scene.tryRemovePhase(p => p instanceof SelectModifierPhase);
|
||||
}
|
||||
|
||||
if (nonShopRewards?.length > 0) {
|
||||
nonShopRewards.forEach((reward) => {
|
||||
if (nonShopPlayerItemRewards?.length > 0) {
|
||||
nonShopPlayerItemRewards.forEach((reward) => {
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, reward));
|
||||
});
|
||||
} else {
|
||||
@ -679,7 +679,7 @@ export function handleEncounterStartOfBattleEffects(scene: BattleScene) {
|
||||
} else {
|
||||
source = scene.getEnemyField()[0];
|
||||
}
|
||||
scene.pushPhase(new MovePhase(scene, source, effect.targets, effect.move, effect.followUp, effect.followUp));
|
||||
scene.pushPhase(new MovePhase(scene, source, effect.targets, effect.move, effect.followUp, effect.ignorePp));
|
||||
});
|
||||
|
||||
// Pseudo turn end phase to reset flinch states, Endure, etc.
|
||||
|
@ -8,7 +8,7 @@ export const fieryFalloutDialogue = {
|
||||
label: "Find the source",
|
||||
tooltip: "(?) Discover the source\n(-) Hard Battle",
|
||||
selected: `You push through the storm, and find two Volcarona in the middle of a mating dance!
|
||||
$They don't take kindly to the interruption and attack!`,
|
||||
$They don't take kindly to the interruption and attack!`
|
||||
},
|
||||
2: {
|
||||
label: "Hunker down",
|
||||
@ -24,5 +24,7 @@ export const fieryFalloutDialogue = {
|
||||
selected: `Your {{option3PrimaryName}} and {{option3SecondaryName}} guide you to where two Volcarona are in the middle of a mating dance!
|
||||
$Thankfully, your Pokémon are able to calm them,\nand they depart without issue.`,
|
||||
},
|
||||
}
|
||||
},
|
||||
found_charcoal: `After the weather clears,\nyour {{leadPokemon}} spots something on the ground.
|
||||
$@s{item_fanfare}{{leadPokemon}} gained a Charcoal!`
|
||||
};
|
||||
|
@ -1101,11 +1101,6 @@ export class EncounterPhase extends BattlePhase {
|
||||
this.scene.ui.clearText();
|
||||
this.scene.ui.getMessageHandler().hideNameText();
|
||||
|
||||
// Can add any additional unshift phases here before MysteryEncounterPhase begins (and all phase queues are cleared)
|
||||
if (this.scene.currentBattle.mysteryEncounter.onPreMysteryEncounterPhase) {
|
||||
this.scene.currentBattle.mysteryEncounter.onPreMysteryEncounterPhase(this.scene);
|
||||
}
|
||||
|
||||
this.scene.unshiftPhase(new MysteryEncounterPhase(this.scene));
|
||||
this.end();
|
||||
};
|
||||
|
@ -184,7 +184,7 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase {
|
||||
pokemon.lapseTags(BattlerTagLapseType.TURN_END);
|
||||
});
|
||||
|
||||
this.end();
|
||||
super.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { Button } from "#app/enums/buttons";
|
||||
import { MessagePhase, VictoryPhase } from "#app/phases";
|
||||
import { CommandPhase, MessagePhase, VictoryPhase } from "#app/phases";
|
||||
import { MysteryEncounterPhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phases";
|
||||
import MysteryEncounterUiHandler from "#app/ui/mystery-encounter-ui-handler";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import GameManager from "../utils/gameManager";
|
||||
import MessageUiHandler from "#app/ui/message-ui-handler";
|
||||
import { Status, StatusEffect } from "#app/data/status-effect";
|
||||
|
||||
export async function runSelectMysteryEncounterOption(game: GameManager, optionNo: number) {
|
||||
export async function runSelectMysteryEncounterOption(game: GameManager, optionNo: number, isBattle: boolean = false) {
|
||||
// Handle any eventual queued messages (e.g. weather phase, etc.)
|
||||
game.onNextPrompt("MessagePhase", Mode.MESSAGE, () => {
|
||||
const uiHandler = game.scene.ui.getHandler<MysteryEncounterUiHandler>();
|
||||
const uiHandler = game.scene.ui.getHandler<MessageUiHandler>();
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
});
|
||||
|
||||
@ -23,7 +24,7 @@ export async function runSelectMysteryEncounterOption(game: GameManager, optionN
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
});
|
||||
|
||||
await game.phaseInterceptor.run(MysteryEncounterPhase);
|
||||
await game.phaseInterceptor.to(MysteryEncounterPhase, true);
|
||||
|
||||
// select the desired option
|
||||
const uiHandler = game.scene.ui.getHandler<MysteryEncounterUiHandler>();
|
||||
@ -73,5 +74,23 @@ export async function runSelectMysteryEncounterOption(game: GameManager, optionN
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
});
|
||||
|
||||
await game.phaseInterceptor.to(MysteryEncounterRewardsPhase);
|
||||
if (isBattle) {
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
} else {
|
||||
await game.phaseInterceptor.to(MysteryEncounterRewardsPhase);
|
||||
}
|
||||
}
|
||||
|
||||
export async function skipBattleRunMysteryEncounterRewardsPhase(game: GameManager) {
|
||||
game.scene.clearPhaseQueue();
|
||||
game.scene.clearPhaseQueueSplice();
|
||||
game.scene.getEnemyParty().forEach(p => {
|
||||
p.hp = 0;
|
||||
p.status = new Status(StatusEffect.FAINT);
|
||||
game.scene.field.remove(p);
|
||||
});
|
||||
game.scene.unshiftPhase(new VictoryPhase(game.scene, 0));
|
||||
game.endPhase();
|
||||
game.phaseInterceptor.superEndPhase();
|
||||
await game.phaseInterceptor.to(MysteryEncounterRewardsPhase, true);
|
||||
}
|
||||
|
@ -5,6 +5,16 @@ import { Species } from "#app/enums/species";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { FieryFalloutEncounter } from "#app/data/mystery-encounters/encounters/fiery-fallout-encounter";
|
||||
import Battle from "#app/battle";
|
||||
import { Gender } from "#app/data/gender";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import * as BattleAnims from "#app/data/battle-anims";
|
||||
import { EncounterOptionMode } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils";
|
||||
import { CommandPhase, MovePhase, SelectModifierPhase } from "#app/phases";
|
||||
import { Moves } from "#enums/moves";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
|
||||
const namespace = "mysteryEncounter:fieryFallout";
|
||||
/** Arcanine and Ninetails for 2 Fire types. Lapras for burnable mon. */
|
||||
@ -15,6 +25,7 @@ const defaultWave = 45;
|
||||
describe("Fiery Fallout - Mystery Encounter", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
let scene: BattleScene;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({ type: Phaser.HEADLESS });
|
||||
@ -22,13 +33,14 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
game = new GameManager(phaserGame);
|
||||
scene = game.scene;
|
||||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
[Biome.SEA, [MysteryEncounterType.FIERY_FALLOUT]],
|
||||
[Biome.VOLCANO, [MysteryEncounterType.FIERY_FALLOUT]],
|
||||
[Biome.MOUNTAIN, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]],
|
||||
])
|
||||
);
|
||||
@ -54,7 +66,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
||||
game.override.startingBiome(Biome.MOUNTAIN);
|
||||
await game.runToMysteryEncounter();
|
||||
|
||||
expect(game.scene.currentBattle.mysteryEncounter.encounterType).not.toBe(MysteryEncounterType.LOST_AT_SEA);
|
||||
expect(scene.currentBattle.mysteryEncounter.encounterType).not.toBe(MysteryEncounterType.LOST_AT_SEA);
|
||||
});
|
||||
|
||||
it("should not run below wave 41", async () => {
|
||||
@ -62,7 +74,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
||||
|
||||
await game.runToMysteryEncounter();
|
||||
|
||||
expect(game.scene.currentBattle.mysteryEncounter.encounterType).not.toBe(MysteryEncounterType.FIERY_FALLOUT);
|
||||
expect(scene.currentBattle.mysteryEncounter.encounterType).not.toBe(MysteryEncounterType.FIERY_FALLOUT);
|
||||
});
|
||||
|
||||
it("should not run above wave 179", async () => {
|
||||
@ -70,164 +82,186 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
||||
|
||||
await game.runToMysteryEncounter();
|
||||
|
||||
expect(game.scene.currentBattle.mysteryEncounter).toBeUndefined();
|
||||
expect(scene.currentBattle.mysteryEncounter).toBeUndefined();
|
||||
});
|
||||
|
||||
// it("should set the correct dialog tokens during initialization", () => {
|
||||
// vi.spyOn(game.scene, "currentBattle", "get").mockReturnValue({ mysteryEncounter: FieryFalloutEncounter } as Battle);
|
||||
//
|
||||
// const { onInit } = FieryFalloutEncounter;
|
||||
//
|
||||
// expect(FieryFalloutEncounter.onInit).toBeDefined();
|
||||
//
|
||||
// const onInitResult = onInit(game.scene);
|
||||
//
|
||||
// expect(FieryFalloutEncounter.dialogueTokens?.damagePercentage).toBe("25");
|
||||
// expect(FieryFalloutEncounter.dialogueTokens?.option1RequiredMove).toBe(Moves[Moves.SURF]);
|
||||
// expect(FieryFalloutEncounter.dialogueTokens?.option2RequiredMove).toBe(Moves[Moves.FLY]);
|
||||
// expect(onInitResult).toBe(true);
|
||||
// });
|
||||
it("should initialize fully ", async () => {
|
||||
vi.spyOn(scene, "currentBattle", "get").mockReturnValue({ mysteryEncounter: FieryFalloutEncounter } as Battle);
|
||||
const weatherSpy = vi.spyOn(scene.arena, "trySetWeather").mockReturnValue(true);
|
||||
const moveInitSpy = vi.spyOn(BattleAnims, "loadMoveAnimAssets");
|
||||
const moveLoadSpy = vi.spyOn(BattleAnims, "loadMoveAnimAssets");
|
||||
|
||||
// describe("Option 1 - Fight 2 Volcarona", () => {
|
||||
// it("should have the correct properties", () => {
|
||||
// const option1 = LostAtSeaEncounter.options[0];
|
||||
// expect(option1.optionMode).toBe(EncounterOptionMode.DISABLED_OR_DEFAULT);
|
||||
// expect(option1.dialogue).toBeDefined();
|
||||
// expect(option1.dialogue).toStrictEqual({
|
||||
// buttonLabel: `${namespace}:option:1:label`,
|
||||
// disabledButtonLabel: `${namespace}:option:1:label_disabled`,
|
||||
// buttonTooltip: `${namespace}:option:1:tooltip`,
|
||||
// disabledButtonTooltip: `${namespace}:option:1:tooltip_disabled`,
|
||||
// selected: [
|
||||
// {
|
||||
// text: `${namespace}:option:1:selected`,
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it("should award exp to surfable PKM (Blastoise)", async () => {
|
||||
// const laprasSpecies = getPokemonSpecies(Species.LAPRAS);
|
||||
//
|
||||
// await game.runToMysteryEncounter(defaultParty);
|
||||
// const party = game.scene.getParty();
|
||||
// const blastoise = party.find((pkm) => pkm.species.speciesId === Species.PIDGEOT);
|
||||
// const expBefore = blastoise.exp;
|
||||
//
|
||||
// await runSelectMysteryEncounterOption(game, 2);
|
||||
//
|
||||
// expect(blastoise.exp).toBe(expBefore + Math.floor(laprasSpecies.baseExp * defaultWave / 5 + 1));
|
||||
// });
|
||||
//
|
||||
// it("should leave encounter without battle", async () => {
|
||||
// game.override.startingWave(33);
|
||||
// const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
//
|
||||
// await game.runToMysteryEncounter(defaultParty);
|
||||
// await runSelectMysteryEncounterOption(game, 1);
|
||||
//
|
||||
// expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||
// });
|
||||
//
|
||||
// it("should be disabled if no surfable PKM is in party", async () => {
|
||||
// // TODO
|
||||
// });
|
||||
// });
|
||||
const { onInit } = FieryFalloutEncounter;
|
||||
|
||||
// describe("Option 2 - Suffer the weather", () => {
|
||||
// it("should have the correct properties", () => {
|
||||
// const option2 = LostAtSeaEncounter.options[1];
|
||||
//
|
||||
// expect(option2.optionMode).toBe(EncounterOptionMode.DISABLED_OR_DEFAULT);
|
||||
// expect(option2.dialogue).toBeDefined();
|
||||
// expect(option2.dialogue).toStrictEqual({
|
||||
// buttonLabel: `${namespace}:option:2:label`,
|
||||
// disabledButtonLabel: `${namespace}:option:2:label_disabled`,
|
||||
// buttonTooltip: `${namespace}:option:2:tooltip`,
|
||||
// disabledButtonTooltip: `${namespace}:option:2:tooltip_disabled`,
|
||||
// selected: [
|
||||
// {
|
||||
// text: `${namespace}:option:2:selected`,
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it("should award exp to flyable PKM (Pidgeot)", async () => {
|
||||
// const laprasBaseExp = 187;
|
||||
// const wave = 33;
|
||||
// game.override.startingWave(wave);
|
||||
//
|
||||
// await game.runToMysteryEncounter(defaultParty);
|
||||
// const party = game.scene.getParty();
|
||||
// const pidgeot = party.find((pkm) => pkm.species.speciesId === Species.PIDGEOT);
|
||||
// const expBefore = pidgeot.exp;
|
||||
//
|
||||
// await runSelectMysteryEncounterOption(game, 2);
|
||||
//
|
||||
// expect(pidgeot.exp).toBe(expBefore + Math.floor(laprasBaseExp * defaultWave / 5 + 1));
|
||||
// });
|
||||
//
|
||||
// it("should leave encounter without battle", async () => {
|
||||
// game.override.startingWave(33);
|
||||
// const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
//
|
||||
// await game.runToMysteryEncounter(defaultParty);
|
||||
// await runSelectMysteryEncounterOption(game, 2);
|
||||
//
|
||||
// expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||
// });
|
||||
//
|
||||
// it("should be disabled if no flyable PKM is in party", async () => {
|
||||
// // TODO
|
||||
// });
|
||||
// });
|
||||
expect(FieryFalloutEncounter.onInit).toBeDefined();
|
||||
|
||||
// describe("Option 3 - use FIRE types", () => {
|
||||
// it("should have the correct properties", () => {
|
||||
// const option3 = LostAtSeaEncounter.options[2];
|
||||
//
|
||||
// expect(option3.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
||||
// expect(option3.dialogue).toBeDefined();
|
||||
// expect(option3.dialogue).toStrictEqual({
|
||||
// buttonLabel: `${namespace}:option:3:label`,
|
||||
// buttonTooltip: `${namespace}:option:3:tooltip`,
|
||||
// selected: [
|
||||
// {
|
||||
// text: `${namespace}:option:3:selected`,
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it("should damage all (allowed in battle) party PKM by 25%", async () => {
|
||||
// game.override.startingWave(33);
|
||||
//
|
||||
// await game.runToMysteryEncounter(defaultParty);
|
||||
//
|
||||
// const party = game.scene.getParty();
|
||||
// const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA);
|
||||
// vi.spyOn(abra, "isAllowedInBattle").mockReturnValue(false);
|
||||
//
|
||||
// await runSelectMysteryEncounterOption(game, 3);
|
||||
//
|
||||
// const allowedPkm = party.filter((pkm) => pkm.isAllowedInBattle());
|
||||
// const notAllowedPkm = party.filter((pkm) => !pkm.isAllowedInBattle());
|
||||
// allowedPkm.forEach((pkm) =>
|
||||
// expect(pkm.hp, `${pkm.name} should have receivd 25% damage: ${pkm.hp} / ${pkm.getMaxHp()} HP`).toBe(pkm.getMaxHp() - Math.floor(pkm.getMaxHp() * 0.25))
|
||||
// );
|
||||
//
|
||||
// notAllowedPkm.forEach((pkm) => expect(pkm.hp, `${pkm.name} should be full hp: ${pkm.hp} / ${pkm.getMaxHp()} HP`).toBe(pkm.getMaxHp()));
|
||||
// });
|
||||
//
|
||||
// it("should leave encounter without battle", async () => {
|
||||
// game.override.startingWave(33);
|
||||
// const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
//
|
||||
// await game.runToMysteryEncounter(defaultParty);
|
||||
// await runSelectMysteryEncounterOption(game, 3);
|
||||
//
|
||||
// expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||
// });
|
||||
// });
|
||||
const onInitResult = onInit(scene);
|
||||
|
||||
expect(FieryFalloutEncounter.enemyPartyConfigs).toEqual([
|
||||
{
|
||||
pokemonConfigs: [
|
||||
{
|
||||
species: getPokemonSpecies(Species.VOLCARONA),
|
||||
isBoss: false,
|
||||
gender: Gender.MALE
|
||||
},
|
||||
{
|
||||
species: getPokemonSpecies(Species.VOLCARONA),
|
||||
isBoss: false,
|
||||
gender: Gender.FEMALE
|
||||
}
|
||||
],
|
||||
doubleBattle: true,
|
||||
disableSwitch: true
|
||||
}
|
||||
]);
|
||||
expect(weatherSpy).toHaveBeenCalledTimes(1);
|
||||
await vi.waitFor(() => expect(moveInitSpy).toHaveBeenCalled());
|
||||
await vi.waitFor(() => expect(moveLoadSpy).toHaveBeenCalled());
|
||||
expect(onInitResult).toBe(true);
|
||||
});
|
||||
|
||||
describe("Option 1 - Fight 2 Volcarona", () => {
|
||||
it("should have the correct properties", () => {
|
||||
const option1 = FieryFalloutEncounter.options[0];
|
||||
expect(option1.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
||||
expect(option1.dialogue).toBeDefined();
|
||||
expect(option1.dialogue).toStrictEqual({
|
||||
buttonLabel: `${namespace}:option:1:label`,
|
||||
buttonTooltip: `${namespace}:option:1:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}:option:1:selected`,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should start battle against 2 Volcarona", async () => {
|
||||
const phaseSpy = vi.spyOn(scene, "pushPhase");
|
||||
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
await runSelectMysteryEncounterOption(game, 1, true);
|
||||
|
||||
const enemyField = scene.getEnemyField();
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(enemyField.length).toBe(2);
|
||||
expect(enemyField[0].species.speciesId).toBe(Species.VOLCARONA);
|
||||
expect(enemyField[1].species.speciesId).toBe(Species.VOLCARONA);
|
||||
expect(enemyField[0].gender).not.toEqual(enemyField[1].gender); // Should be opposite gender
|
||||
|
||||
const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]);
|
||||
expect(movePhases.length).toBe(4);
|
||||
expect(movePhases.filter(p => (p as MovePhase).move.moveId === Moves.FIRE_SPIN).length).toBe(2); // Fire spin used twice before battle
|
||||
expect(movePhases.filter(p => (p as MovePhase).move.moveId === Moves.QUIVER_DANCE).length).toBe(2); // Quiver Dance used twice before battle
|
||||
});
|
||||
|
||||
it("should give charcoal to lead pokemon", async () => {
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
await runSelectMysteryEncounterOption(game, 1, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
|
||||
const leadPokemonId = scene.getParty()?.[0].id;
|
||||
const leadPokemonItems = scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||
&& (m as PokemonHeldItemModifier).pokemonId === leadPokemonId, true) as PokemonHeldItemModifier[];
|
||||
const charcoal = leadPokemonItems.find(i => i.type.name === "Charcoal");
|
||||
expect(charcoal).toBeDefined;
|
||||
});
|
||||
});
|
||||
|
||||
describe("Option 2 - Suffer the weather", () => {
|
||||
it("should have the correct properties", () => {
|
||||
const option1 = FieryFalloutEncounter.options[0];
|
||||
expect(option1.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
||||
expect(option1.dialogue).toBeDefined();
|
||||
expect(option1.dialogue).toStrictEqual({
|
||||
buttonLabel: `${namespace}:option:2:label`,
|
||||
buttonTooltip: `${namespace}:option:2:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}:option:2:selected`,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should damage all (allowed in battle) party PKM by 25%", async () => {
|
||||
game.override.startingWave(33);
|
||||
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
|
||||
const party = scene.getParty();
|
||||
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA);
|
||||
vi.spyOn(abra, "isAllowedInBattle").mockReturnValue(false);
|
||||
|
||||
await runSelectMysteryEncounterOption(game, 3);
|
||||
|
||||
const allowedPkm = party.filter((pkm) => pkm.isAllowedInBattle());
|
||||
const notAllowedPkm = party.filter((pkm) => !pkm.isAllowedInBattle());
|
||||
allowedPkm.forEach((pkm) =>
|
||||
expect(pkm.hp, `${pkm.name} should have receivd 25% damage: ${pkm.hp} / ${pkm.getMaxHp()} HP`).toBe(pkm.getMaxHp() - Math.floor(pkm.getMaxHp() * 0.25))
|
||||
);
|
||||
|
||||
notAllowedPkm.forEach((pkm) => expect(pkm.hp, `${pkm.name} should be full hp: ${pkm.hp} / ${pkm.getMaxHp()} HP`).toBe(pkm.getMaxHp()));
|
||||
});
|
||||
|
||||
it("should leave encounter without battle", async () => {
|
||||
game.override.startingWave(33);
|
||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
await runSelectMysteryEncounterOption(game, 3);
|
||||
|
||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Option 3 - use FIRE types", () => {
|
||||
it("should have the correct properties", () => {
|
||||
const option1 = FieryFalloutEncounter.options[0];
|
||||
expect(option1.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
||||
expect(option1.dialogue).toBeDefined();
|
||||
expect(option1.dialogue).toStrictEqual({
|
||||
buttonLabel: `${namespace}:option:1:label`,
|
||||
buttonTooltip: `${namespace}:option:1:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}:option:1:selected`,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should damage all (allowed in battle) party PKM by 25%", async () => {
|
||||
game.override.startingWave(33);
|
||||
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
|
||||
const party = scene.getParty();
|
||||
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA);
|
||||
vi.spyOn(abra, "isAllowedInBattle").mockReturnValue(false);
|
||||
|
||||
await runSelectMysteryEncounterOption(game, 3);
|
||||
|
||||
const allowedPkm = party.filter((pkm) => pkm.isAllowedInBattle());
|
||||
const notAllowedPkm = party.filter((pkm) => !pkm.isAllowedInBattle());
|
||||
allowedPkm.forEach((pkm) =>
|
||||
expect(pkm.hp, `${pkm.name} should have receivd 25% damage: ${pkm.hp} / ${pkm.getMaxHp()} HP`).toBe(pkm.getMaxHp() - Math.floor(pkm.getMaxHp() * 0.25))
|
||||
);
|
||||
|
||||
notAllowedPkm.forEach((pkm) => expect(pkm.hp, `${pkm.name} should be full hp: ${pkm.hp} / ${pkm.getMaxHp()} HP`).toBe(pkm.getMaxHp()));
|
||||
});
|
||||
|
||||
it("should leave encounter without battle", async () => {
|
||||
game.override.startingWave(33);
|
||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
await runSelectMysteryEncounterOption(game, 3);
|
||||
|
||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -104,7 +104,8 @@ export default class PhaseInterceptor {
|
||||
[MysteryEncounterBattlePhase, this.startPhase],
|
||||
[MysteryEncounterRewardsPhase, this.startPhase],
|
||||
[PostMysteryEncounterPhase, this.startPhase],
|
||||
[LearnMovePhase, this.startPhase]
|
||||
[LearnMovePhase, this.startPhase],
|
||||
// [CommonAnimPhase, this.startPhase]
|
||||
];
|
||||
|
||||
private endBySetMode = [
|
||||
|
Loading…
Reference in New Issue
Block a user