fix ME null checks and unit tests with beta update
This commit is contained in:
parent
0b698a04a2
commit
39c6c375f8
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
@ -2474,34 +2474,33 @@ export default class BattleScene extends SceneBase {
|
|||
modifier.stackCount = stackCount;
|
||||
// TODO: set isTransferable
|
||||
// modifier.setIsTransferable(isTransferable);
|
||||
this.addEnemyModifier(modifier, false, true);
|
||||
this.addEnemyModifier(modifier, true);
|
||||
});
|
||||
}
|
||||
|
||||
const isBoss = enemyPokemon.isBoss() || (this.currentBattle.battleType === BattleType.TRAINER && !!this.currentBattle.trainer?.config.isBoss);
|
||||
let upgradeChance = 32;
|
||||
if (isBoss) {
|
||||
upgradeChance /= 2;
|
||||
}
|
||||
if (isFinalBoss) {
|
||||
upgradeChance /= 8;
|
||||
}
|
||||
const modifierChance = this.gameMode.getEnemyModifierChance(isBoss);
|
||||
let pokemonModifierChance = modifierChance;
|
||||
if (this.currentBattle.battleType === BattleType.TRAINER && this.currentBattle.trainer)
|
||||
pokemonModifierChance = Math.ceil(pokemonModifierChance * this.currentBattle.trainer.getPartyMemberModifierChanceMultiplier(i)); // eslint-disable-line
|
||||
let count = 0;
|
||||
for (let c = 0; c < chances; c++) {
|
||||
if (!Utils.randSeedInt(modifierChance)) {
|
||||
count++;
|
||||
} else {
|
||||
const isBoss = enemyPokemon.isBoss() || (this.currentBattle.battleType === BattleType.TRAINER && !!this.currentBattle.trainer?.config.isBoss);
|
||||
let upgradeChance = 32;
|
||||
if (isBoss) {
|
||||
upgradeChance /= 2;
|
||||
}
|
||||
if (isFinalBoss) {
|
||||
upgradeChance /= 8;
|
||||
}
|
||||
const modifierChance = this.gameMode.getEnemyModifierChance(isBoss);
|
||||
let pokemonModifierChance = modifierChance;
|
||||
if (this.currentBattle.battleType === BattleType.TRAINER && this.currentBattle.trainer)
|
||||
pokemonModifierChance = Math.ceil(pokemonModifierChance * this.currentBattle.trainer.getPartyMemberModifierChanceMultiplier(i)); // eslint-disable-line
|
||||
let count = 0;
|
||||
for (let c = 0; c < chances; c++) {
|
||||
if (!Utils.randSeedInt(modifierChance)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (isBoss) {
|
||||
count = Math.max(count, Math.floor(chances / 2));
|
||||
}
|
||||
getEnemyModifierTypesForWave(difficultyWaveIndex, count, [ enemyPokemon ], this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD, upgradeChance)
|
||||
.map(mt => mt.newModifier(enemyPokemon).add(this.enemyModifiers, false, this));
|
||||
}
|
||||
if (isBoss) {
|
||||
count = Math.max(count, Math.floor(chances / 2));
|
||||
}
|
||||
getEnemyModifierTypesForWave(difficultyWaveIndex, count, [ enemyPokemon ], this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD, upgradeChance)
|
||||
.map(mt => mt.newModifier(enemyPokemon).add(this.enemyModifiers, false, this));
|
||||
|
||||
return true;
|
||||
});
|
||||
this.updateModifiers(false).then(() => resolve());
|
||||
|
@ -2786,7 +2785,7 @@ export default class BattleScene extends SceneBase {
|
|||
}
|
||||
|
||||
// Check for queued encounters first
|
||||
if (!encounter && this.mysteryEncounterData?.nextEncounterQueue?.length > 0) {
|
||||
if (!encounter && this.mysteryEncounterData?.nextEncounterQueue && this.mysteryEncounterData.nextEncounterQueue.length > 0) {
|
||||
let i = 0;
|
||||
while (i < this.mysteryEncounterData.nextEncounterQueue.length && !!encounter) {
|
||||
const candidate = this.mysteryEncounterData.nextEncounterQueue[i];
|
||||
|
@ -2801,7 +2800,7 @@ export default class BattleScene extends SceneBase {
|
|||
|
||||
if (encounter) {
|
||||
encounter = new MysteryEncounter(encounter);
|
||||
encounter.populateDialogueTokensFromRequirements!(this);
|
||||
encounter.populateDialogueTokensFromRequirements(this);
|
||||
return encounter;
|
||||
}
|
||||
|
||||
|
|
|
@ -440,7 +440,7 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent {
|
|||
scene.field.add(moveAnim.bgSprite);
|
||||
const fieldPokemon = scene.getEnemyPokemon() || scene.getPlayerPokemon();
|
||||
if (!isNullOrUndefined(priority)) {
|
||||
scene.field.moveTo(moveAnim.bgSprite as Phaser.GameObjects.GameObject, priority);
|
||||
scene.field.moveTo(moveAnim.bgSprite as Phaser.GameObjects.GameObject, priority!);
|
||||
} else if (fieldPokemon?.isOnField()) {
|
||||
scene.field.moveBelow(moveAnim.bgSprite as Phaser.GameObjects.GameObject, fieldPokemon);
|
||||
}
|
||||
|
@ -540,7 +540,7 @@ export function initMoveAnim(scene: BattleScene, move: Moves): Promise<void> {
|
|||
export async function initEncounterAnims(scene: BattleScene, encounterAnim: EncounterAnim | EncounterAnim[]): Promise<void> {
|
||||
const anims = Array.isArray(encounterAnim) ? encounterAnim : [encounterAnim];
|
||||
const encounterAnimNames = Utils.getEnumKeys(EncounterAnim);
|
||||
const encounterAnimFetches = [];
|
||||
const encounterAnimFetches: Promise<Map<EncounterAnim, AnimConfig>>[] = [];
|
||||
for (const anim of anims) {
|
||||
if (encounterAnims.has(anim) && !isNullOrUndefined(encounterAnims.get(anim))) {
|
||||
continue;
|
||||
|
@ -806,7 +806,7 @@ export abstract class BattleAnim {
|
|||
play(scene: BattleScene, callback?: Function) {
|
||||
const isOppAnim = this.isOppAnim();
|
||||
const user = !isOppAnim ? this.user! : this.target!; // TODO: are those bangs correct?
|
||||
const target = !isOppAnim ? this.target : this.user;
|
||||
const target = !isOppAnim ? this.target! : this.user!;
|
||||
|
||||
if (!target?.isOnField() && !this.playOnEmptyField) {
|
||||
if (callback) {
|
||||
|
@ -1052,7 +1052,7 @@ export abstract class BattleAnim {
|
|||
y += targetInitialY;
|
||||
const angle = -frame.angle;
|
||||
const key = frame.target === AnimFrameTarget.GRAPHIC ? g++ : frame.target === AnimFrameTarget.USER ? u++ : t++;
|
||||
ret.get(frame.target).set(key, { x: x, y: y, scaleX: scaleX, scaleY: scaleY, angle: angle });
|
||||
ret.get(frame.target)?.set(key, { x: x, y: y, scaleX: scaleX, scaleY: scaleY, angle: angle });
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1102,17 +1102,17 @@ export abstract class BattleAnim {
|
|||
this.srcLine = [ userFocusX, userFocusY, targetFocusX, targetFocusY ];
|
||||
this.dstLine = [ 150, 75, targetInitialX, targetInitialY ];
|
||||
|
||||
let r = anim.frames.length;
|
||||
let r = anim!.frames.length;
|
||||
let f = 0;
|
||||
|
||||
const existingFieldSprites = [...scene.field.getAll()];
|
||||
|
||||
scene.tweens.addCounter({
|
||||
duration: Utils.getFrameMs(3) * frameTimeMult,
|
||||
repeat: anim.frames.length,
|
||||
repeat: anim!.frames.length,
|
||||
onRepeat: () => {
|
||||
const spriteFrames = anim.frames[f];
|
||||
const frameData = this.getGraphicFrameDataWithoutTarget(anim.frames[f], targetInitialX, targetInitialY);
|
||||
const spriteFrames = anim!.frames[f];
|
||||
const frameData = this.getGraphicFrameDataWithoutTarget(anim!.frames[f], targetInitialX, targetInitialY);
|
||||
const u = 0;
|
||||
const t = 0;
|
||||
let g = 0;
|
||||
|
@ -1124,7 +1124,7 @@ export abstract class BattleAnim {
|
|||
|
||||
const sprites = spriteCache[AnimFrameTarget.GRAPHIC];
|
||||
if (g === sprites.length) {
|
||||
const newSprite: Phaser.GameObjects.Sprite = scene.addFieldSprite(0, 0, anim.graphic, 1);
|
||||
const newSprite: Phaser.GameObjects.Sprite = scene.addFieldSprite(0, 0, anim!.graphic, 1);
|
||||
sprites.push(newSprite);
|
||||
scene.field.add(newSprite);
|
||||
spritePriorities.push(1);
|
||||
|
@ -1147,17 +1147,19 @@ export abstract class BattleAnim {
|
|||
}
|
||||
moveSprite.setFrame(frame.graphicFrame);
|
||||
|
||||
const graphicFrameData = frameData.get(frame.target).get(graphicIndex);
|
||||
moveSprite.setPosition(graphicFrameData.x, graphicFrameData.y);
|
||||
moveSprite.setAngle(graphicFrameData.angle);
|
||||
moveSprite.setScale(graphicFrameData.scaleX, graphicFrameData.scaleY);
|
||||
const graphicFrameData = frameData.get(frame.target)?.get(graphicIndex);
|
||||
if (graphicFrameData) {
|
||||
moveSprite.setPosition(graphicFrameData.x, graphicFrameData.y);
|
||||
moveSprite.setAngle(graphicFrameData.angle);
|
||||
moveSprite.setScale(graphicFrameData.scaleX, graphicFrameData.scaleY);
|
||||
|
||||
moveSprite.setAlpha(frame.opacity / 255);
|
||||
moveSprite.setVisible(frame.visible);
|
||||
moveSprite.setBlendMode(frame.blendType === AnimBlendType.NORMAL ? Phaser.BlendModes.NORMAL : frame.blendType === AnimBlendType.ADD ? Phaser.BlendModes.ADD : Phaser.BlendModes.DIFFERENCE);
|
||||
moveSprite.setAlpha(frame.opacity / 255);
|
||||
moveSprite.setVisible(frame.visible);
|
||||
moveSprite.setBlendMode(frame.blendType === AnimBlendType.NORMAL ? Phaser.BlendModes.NORMAL : frame.blendType === AnimBlendType.ADD ? Phaser.BlendModes.ADD : Phaser.BlendModes.DIFFERENCE);
|
||||
}
|
||||
}
|
||||
if (anim.frameTimedEvents.has(f)) {
|
||||
for (const event of anim.frameTimedEvents.get(f)) {
|
||||
if (anim?.frameTimedEvents.get(f)) {
|
||||
for (const event of anim.frameTimedEvents.get(f)!) {
|
||||
r = Math.max((anim.frames.length - f) + event.execute(scene, this, frameTimedEventPriority), r);
|
||||
}
|
||||
}
|
||||
|
@ -1277,8 +1279,8 @@ export class EncounterBattleAnim extends BattleAnim {
|
|||
this.oppAnim = oppAnim ?? false;
|
||||
}
|
||||
|
||||
getAnim(): AnimConfig {
|
||||
return encounterAnims.get(this.encounterAnim);
|
||||
getAnim(): AnimConfig | null {
|
||||
return encounterAnims.get(this.encounterAnim) ?? null;
|
||||
}
|
||||
|
||||
isOppAnim(): boolean {
|
||||
|
|
|
@ -86,7 +86,7 @@ export class Egg {
|
|||
|
||||
private _overrideHiddenAbility: boolean;
|
||||
|
||||
private _eventEggTypeDescriptor: string;
|
||||
private _eventEggTypeDescriptor?: string;
|
||||
|
||||
////
|
||||
// #endregion
|
||||
|
@ -186,7 +186,7 @@ export class Egg {
|
|||
this.addEggToGameData(eggOptions.scene!); // TODO: is this bang correct?
|
||||
}
|
||||
|
||||
this._eventEggTypeDescriptor = eggOptions.eventEggTypeDescriptor ?? null;
|
||||
this._eventEggTypeDescriptor = eggOptions?.eventEggTypeDescriptor;
|
||||
}
|
||||
|
||||
////
|
||||
|
|
|
@ -76,13 +76,13 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
|||
text: `${namespace}.${trainerNameKey}.intro_dialogue`
|
||||
}
|
||||
];
|
||||
encounter.options[0].dialogue.selected = [
|
||||
encounter.options[0].dialogue!.selected = [
|
||||
{
|
||||
speaker: `trainerNames:${trainerNameKey}`,
|
||||
text: `${namespace}.${trainerNameKey}.accept`
|
||||
}
|
||||
];
|
||||
encounter.options[1].dialogue.selected = [
|
||||
encounter.options[1].dialogue!.selected = [
|
||||
{
|
||||
speaker: `trainerNames:${trainerNameKey}`,
|
||||
text: `${namespace}.${trainerNameKey}.decline`
|
||||
|
|
|
@ -22,6 +22,7 @@ import { applyModifierTypeToPlayerPokemon, catchPokemon, getHighestLevelPlayerPo
|
|||
import { TrainerSlot } from "#app/data/trainer-config";
|
||||
import { PokeballType } from "#app/data/pokeball";
|
||||
import HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:absoluteAvarice";
|
||||
|
@ -39,8 +40,8 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
|||
.withIntroSpriteConfigs([
|
||||
{
|
||||
// This sprite has the shadow
|
||||
spriteKey: null,
|
||||
fileRoot: null,
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.GREEDENT,
|
||||
hasShadow: true,
|
||||
alpha: 0.001,
|
||||
|
@ -48,8 +49,8 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
|||
x: -5
|
||||
},
|
||||
{
|
||||
spriteKey: null,
|
||||
fileRoot: null,
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.GREEDENT,
|
||||
hasShadow: false,
|
||||
repeat: true,
|
||||
|
@ -254,7 +255,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
|||
queueEncounterMessage(scene, `${namespace}.option.1.food_stash`);
|
||||
};
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true }, null, givePartyPokemonReviverSeeds);
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, givePartyPokemonReviverSeeds);
|
||||
encounter.startOfBattleEffects.push({
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY],
|
||||
|
@ -287,7 +288,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
|||
const party = scene.getParty();
|
||||
party.forEach(pokemon => {
|
||||
const stolenBerries: BerryModifier[] = berryMap.get(pokemon.id);
|
||||
const berryTypesAsArray = [];
|
||||
const berryTypesAsArray: BerryType[] = [];
|
||||
stolenBerries?.forEach(bMod => berryTypesAsArray.push(...new Array(bMod.stackCount).fill(bMod.berryType)));
|
||||
const returnedBerryCount = Math.floor((berryTypesAsArray.length ?? 0) * 2 / 5);
|
||||
|
||||
|
@ -330,7 +331,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
|||
// Let it have the food
|
||||
// Greedent joins the team, level equal to 2 below highest party member
|
||||
const level = getHighestLevelPlayerPokemon(scene).level - 2;
|
||||
const greedent = new EnemyPokemon(scene, getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false, null);
|
||||
const greedent = new EnemyPokemon(scene, getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false);
|
||||
greedent.moveset = [new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF)];
|
||||
greedent.passive = true;
|
||||
|
||||
|
@ -346,7 +347,7 @@ function doGreedentSpriteSteal(scene: BattleScene) {
|
|||
const shakeDelay = 50;
|
||||
const slideDelay = 500;
|
||||
|
||||
const greedentSprites = scene.currentBattle.mysteryEncounter.introVisuals.getSpriteAtIndex(1);
|
||||
const greedentSprites = scene.currentBattle.mysteryEncounter.introVisuals?.getSpriteAtIndex(1);
|
||||
|
||||
scene.playSound("Follow Me");
|
||||
scene.tweens.chain({
|
||||
|
@ -420,7 +421,7 @@ function doGreedentSpriteSteal(scene: BattleScene) {
|
|||
}
|
||||
|
||||
function doGreedentEatBerries(scene: BattleScene) {
|
||||
const greedentSprites = scene.currentBattle.mysteryEncounter.introVisuals.getSpriteAtIndex(1);
|
||||
const greedentSprites = scene.currentBattle.mysteryEncounter.introVisuals?.getSpriteAtIndex(1);
|
||||
let index = 1;
|
||||
scene.tweens.add({
|
||||
targets: greedentSprites,
|
||||
|
@ -455,7 +456,12 @@ function doBerrySpritePile(scene: BattleScene, isEat: boolean = false) {
|
|||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
animationOrder.forEach((berry, i) => {
|
||||
const introVisualsIndex = encounter.spriteConfigs.findIndex(config => config.spriteKey?.includes(berry));
|
||||
const [ sprite, tintSprite ] = encounter.introVisuals.getSpriteAtIndex(introVisualsIndex);
|
||||
let sprite: Phaser.GameObjects.Sprite, tintSprite: Phaser.GameObjects.Sprite;
|
||||
const sprites = encounter.introVisuals?.getSpriteAtIndex(introVisualsIndex);
|
||||
if (sprites) {
|
||||
sprite = sprites[0];
|
||||
tintSprite = sprites[1];
|
||||
}
|
||||
scene.time.delayedCall(berryAddDelay * i + 400, () => {
|
||||
if (sprite) {
|
||||
sprite.setVisible(!isEat);
|
||||
|
|
|
@ -136,7 +136,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
|||
// Update money and remove pokemon from party
|
||||
updatePlayerMoney(scene, encounter.misc.price);
|
||||
|
||||
setEncounterExp(scene, encounter.options[1].primaryPokemon.id, getPokemonSpecies(Species.LIEPARD).baseExp, true);
|
||||
setEncounterExp(scene, encounter.options[1].primaryPokemon!.id, getPokemonSpecies(Species.LIEPARD).baseExp, true);
|
||||
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
|
|
|
@ -146,7 +146,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
|||
|
||||
// Calculate boss mon
|
||||
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, scene.currentBattle.waveIndex, 0, getPartyLuckValue(scene.getParty()), true);
|
||||
const bossPokemon = new EnemyPokemon(scene, bossSpecies, scene.currentBattle.waveIndex, TrainerSlot.NONE, true, null);
|
||||
const bossPokemon = new EnemyPokemon(scene, bossSpecies, scene.currentBattle.waveIndex, TrainerSlot.NONE, true);
|
||||
encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon));
|
||||
const config: EnemyPartyConfig = {
|
||||
levelAdditiveMultiplier: 1,
|
||||
|
@ -222,7 +222,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
|||
shopOptions.push(generateModifierTypeOption(scene, modifierTypes.BERRY));
|
||||
}
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, null, doBerryRewards);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, undefined, doBerryRewards);
|
||||
await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0]);
|
||||
}
|
||||
)
|
||||
|
@ -262,12 +262,12 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
|||
};
|
||||
|
||||
const config = scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0];
|
||||
config.pokemonConfigs[0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
||||
config.pokemonConfigs[0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
|
||||
config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
||||
config.pokemonConfigs![0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.2.boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD], 1));
|
||||
};
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, null, doBerryRewards);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, undefined, doBerryRewards);
|
||||
await showEncounterText(scene, `${namespace}.option.2.selected_bad`);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
return;
|
||||
|
@ -287,8 +287,8 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
|||
}
|
||||
};
|
||||
|
||||
setEncounterExp(scene, fastestPokemon.id, encounter.enemyPartyConfigs[0].pokemonConfigs[0].species.baseExp);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, null, doFasterBerryRewards);
|
||||
setEncounterExp(scene, fastestPokemon.id, encounter.enemyPartyConfigs[0].pokemonConfigs![0].species.baseExp);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, undefined, doFasterBerryRewards);
|
||||
await showEncounterText(scene, `${namespace}.option.2.selected`);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, selectPokemonForOption, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, selectPokemonForOption, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { trainerConfigs, TrainerPartyCompoundTemplate, TrainerPartyTemplate, } from "#app/data/trainer-config";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
|
@ -28,7 +28,6 @@ import { BattlerIndex } from "#app/battle";
|
|||
import { Moves } from "#enums/moves";
|
||||
import { EncounterAnim, EncounterBattleAnim } from "#app/data/battle-anims";
|
||||
import { MoveCategory } from "#app/data/move";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:clowningAround";
|
||||
|
@ -129,7 +128,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||
},
|
||||
{ // Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter
|
||||
species: getPokemonSpecies(Species.BLACEPHALON),
|
||||
mysteryEncounterData: new MysteryEncounterPokemonData(null, ability, null, [randSeedInt(18), randSeedInt(18)]),
|
||||
mysteryEncounterData: new MysteryEncounterPokemonData(undefined, ability, undefined, [randSeedInt(18), randSeedInt(18)]),
|
||||
isBoss: true,
|
||||
moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN]
|
||||
},
|
||||
|
@ -206,7 +205,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||
ease: "Sine.easeInOut",
|
||||
duration: 250
|
||||
});
|
||||
const background = new EncounterBattleAnim(EncounterAnim.SMOKESCREEN, scene.getPlayerPokemon(), scene.getPlayerPokemon());
|
||||
const background = new EncounterBattleAnim(EncounterAnim.SMOKESCREEN, scene.getPlayerPokemon()!, scene.getPlayerPokemon());
|
||||
background.playWithoutTargets(scene, 230, 40, 2);
|
||||
return true;
|
||||
})
|
||||
|
@ -292,7 +291,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||
// Play animations
|
||||
const background = new EncounterBattleAnim(EncounterAnim.SMOKESCREEN, scene.getPlayerPokemon(), scene.getPlayerPokemon());
|
||||
const background = new EncounterBattleAnim(EncounterAnim.SMOKESCREEN, scene.getPlayerPokemon()!, scene.getPlayerPokemon());
|
||||
background.playWithoutTargets(scene, 230, 40, 2);
|
||||
await transitionMysteryEncounterIntroVisuals(scene);
|
||||
})
|
||||
|
@ -327,8 +326,8 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||
// If the Pokemon has non-status moves that don't match the Pokemon's type, prioritizes those as the new type
|
||||
// Makes the "randomness" of the shuffle slightly less punishing
|
||||
let priorityTypes = pokemon.moveset
|
||||
.filter(move => !originalTypes.includes(move.getMove().type) && move.getMove().category !== MoveCategory.STATUS)
|
||||
.map(move => move.getMove().type);
|
||||
.filter(move => move && !originalTypes.includes(move.getMove().type) && move.getMove().category !== MoveCategory.STATUS)
|
||||
.map(move => move!.getMove().type);
|
||||
if (priorityTypes?.length > 0) {
|
||||
priorityTypes = [...new Set(priorityTypes)];
|
||||
randSeedShuffle(priorityTypes);
|
||||
|
@ -350,7 +349,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||
}
|
||||
|
||||
if (!pokemon.mysteryEncounterData) {
|
||||
pokemon.mysteryEncounterData = new MysteryEncounterPokemonData(null, null, null, newTypes);
|
||||
pokemon.mysteryEncounterData = new MysteryEncounterPokemonData(undefined, undefined, undefined, newTypes);
|
||||
} else {
|
||||
pokemon.mysteryEncounterData.types = newTypes;
|
||||
}
|
||||
|
@ -361,7 +360,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||
// Play animations
|
||||
const background = new EncounterBattleAnim(EncounterAnim.SMOKESCREEN, scene.getPlayerPokemon(), scene.getPlayerPokemon());
|
||||
const background = new EncounterBattleAnim(EncounterAnim.SMOKESCREEN, scene.getPlayerPokemon()!, scene.getPlayerPokemon());
|
||||
background.playWithoutTargets(scene, 230, 40, 2);
|
||||
await transitionMysteryEncounterIntroVisuals(scene);
|
||||
})
|
||||
|
@ -441,8 +440,7 @@ function generateItemsOfTier(scene: BattleScene, pokemon: PlayerPokemon, numItem
|
|||
[modifierTypes.GOLDEN_PUNCH, 5],
|
||||
[modifierTypes.ATTACK_TYPE_BOOSTER, 99],
|
||||
[modifierTypes.QUICK_CLAW, 3],
|
||||
[modifierTypes.WIDE_LENS, 3],
|
||||
[modifierTypes.WHITE_HERB, 2]
|
||||
[modifierTypes.WIDE_LENS, 3]
|
||||
];
|
||||
|
||||
const roguePool = [
|
||||
|
@ -450,7 +448,7 @@ function generateItemsOfTier(scene: BattleScene, pokemon: PlayerPokemon, numItem
|
|||
[modifierTypes.SHELL_BELL, 4],
|
||||
[modifierTypes.SOUL_DEW, 10],
|
||||
[modifierTypes.SOOTHE_BELL, 3],
|
||||
[modifierTypes.SCOPE_LENS, 5],
|
||||
[modifierTypes.SCOPE_LENS, 1],
|
||||
[modifierTypes.BATON, 1],
|
||||
[modifierTypes.FOCUS_BAND, 5],
|
||||
[modifierTypes.KINGS_ROCK, 3],
|
||||
|
|
|
@ -87,7 +87,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||
.withAutoHideIntroVisuals(false)
|
||||
.withCatchAllowed(true)
|
||||
.withOnVisualsStart((scene: BattleScene) => {
|
||||
const danceAnim = new EncounterBattleAnim(EncounterAnim.DANCE, scene.getEnemyPokemon(), scene.getPlayerPokemon());
|
||||
const danceAnim = new EncounterBattleAnim(EncounterAnim.DANCE, scene.getEnemyPokemon()!, scene.getPlayerPokemon());
|
||||
danceAnim.play(scene);
|
||||
|
||||
return true;
|
||||
|
@ -104,8 +104,8 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
|
||||
const species = getPokemonSpecies(Species.ORICORIO);
|
||||
const enemyPokemon = scene.addEnemyPokemon(species, scene.currentBattle.enemyLevels[0], TrainerSlot.NONE, false);
|
||||
if (!enemyPokemon.moveset.some(m => m.getMove().id === Moves.REVELATION_DANCE)) {
|
||||
const enemyPokemon = scene.addEnemyPokemon(species, scene.currentBattle.enemyLevels![0], TrainerSlot.NONE, false);
|
||||
if (!enemyPokemon.moveset.some(m => m && m.getMove().id === Moves.REVELATION_DANCE)) {
|
||||
if (enemyPokemon.moveset.length < 4) {
|
||||
enemyPokemon.moveset.push(new PokemonMove(Moves.REVELATION_DANCE));
|
||||
} else {
|
||||
|
@ -206,7 +206,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||
scene.unshiftPhase(new LearnMovePhase(scene, scene.getParty().indexOf(pokemon), Moves.REVELATION_DANCE));
|
||||
|
||||
// Play animation again to "learn" the dance
|
||||
const danceAnim = new EncounterBattleAnim(EncounterAnim.DANCE, scene.getEnemyPokemon(), scene.getPlayerPokemon());
|
||||
const danceAnim = new EncounterBattleAnim(EncounterAnim.DANCE, scene.getEnemyPokemon()!, scene.getPlayerPokemon());
|
||||
danceAnim.play(scene);
|
||||
};
|
||||
|
||||
|
@ -239,7 +239,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||
// Return the options for nature selection
|
||||
return pokemon.moveset
|
||||
.filter(move => DANCING_MOVES.includes(move.getMove().id))
|
||||
.filter(move => move && DANCING_MOVES.includes(move.getMove().id))
|
||||
.map((move: PokemonMove) => {
|
||||
const option: OptionSelectItem = {
|
||||
label: move.getName(),
|
||||
|
@ -261,13 +261,13 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||
// If pokemon meets primary pokemon reqs, it can be selected
|
||||
const meetsReqs = encounter.options[2].pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`);
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Show the Oricorio a dance, and recruit it
|
||||
|
|
|
@ -47,8 +47,8 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||
))
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: null,
|
||||
fileRoot: null,
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.DELIBIRD,
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
|
@ -56,16 +56,16 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||
scale: 0.94
|
||||
},
|
||||
{
|
||||
spriteKey: null,
|
||||
fileRoot: null,
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.DELIBIRD,
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
scale: 1.06
|
||||
},
|
||||
{
|
||||
spriteKey: null,
|
||||
fileRoot: null,
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.DELIBIRD,
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
|
@ -116,7 +116,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
|
||||
scene.playSound("item_fanfare");
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, true);
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true);
|
||||
} else {
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.ABILITY_CHARM));
|
||||
}
|
||||
|
@ -169,13 +169,13 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||
// If pokemon meets primary pokemon reqs, it can be selected
|
||||
const meetsReqs = encounter.options[1].pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`);
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
|
@ -191,7 +191,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
|
||||
scene.playSound("item_fanfare");
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, true);
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true);
|
||||
} else {
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.CANDY_JAR));
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
|
||||
scene.playSound("item_fanfare");
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, true);
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true);
|
||||
} else {
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.HEALING_CHARM));
|
||||
}
|
||||
|
@ -264,13 +264,13 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||
// If pokemon meets primary pokemon reqs, it can be selected
|
||||
const meetsReqs = encounter.options[2].pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`);
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
|
@ -284,7 +284,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
|
||||
scene.playSound("item_fanfare");
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), null, true);
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true);
|
||||
} else {
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.BERRY_POUCH));
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import {
|
|||
leaveEncounterWithoutBattle,
|
||||
setEncounterRewards,
|
||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { ModifierTypeFunc, modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { randSeedInt } from "#app/utils";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { Species } from "#enums/species";
|
||||
|
@ -32,8 +32,8 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
|||
x: -20,
|
||||
},
|
||||
{
|
||||
spriteKey: null,
|
||||
fileRoot: null,
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.FURFROU,
|
||||
hasShadow: true,
|
||||
repeat: true,
|
||||
|
@ -60,7 +60,7 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
|||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose TMs
|
||||
const modifiers = [];
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 4) {
|
||||
// 2/2/1 weight on TM rarity
|
||||
|
@ -86,7 +86,7 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
|||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose Vitamins
|
||||
const modifiers = [];
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 3) {
|
||||
// 2/1 weight on base stat booster vs PP Up
|
||||
|
@ -110,7 +110,7 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
|||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose X Items
|
||||
const modifiers = [];
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 5) {
|
||||
// 4/1 weight on base stat booster vs Dire Hit
|
||||
|
@ -134,7 +134,7 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
|||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose Pokeballs
|
||||
const modifiers = [];
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 4) {
|
||||
// 10/30/20/5 weight on pokeballs
|
||||
|
|
|
@ -78,7 +78,7 @@ export const FieldTripEncounter: MysteryEncounter =
|
|||
const correctMove = move.getMove().category === MoveCategory.PHYSICAL;
|
||||
encounter.setDialogueToken("moveCategory", "Physical");
|
||||
if (!correctMove) {
|
||||
encounter.options[0].dialogue.selected = [
|
||||
encounter.options[0].dialogue!.selected = [
|
||||
{
|
||||
text: `${namespace}.option.incorrect`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
|
@ -97,7 +97,7 @@ export const FieldTripEncounter: MysteryEncounter =
|
|||
} else {
|
||||
encounter.setDialogueToken("pokeName", pokemon.getNameToRender());
|
||||
encounter.setDialogueToken("move", move.getName());
|
||||
encounter.options[0].dialogue.selected = [
|
||||
encounter.options[0].dialogue!.selected = [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
},
|
||||
|
@ -164,7 +164,7 @@ export const FieldTripEncounter: MysteryEncounter =
|
|||
const correctMove = move.getMove().category === MoveCategory.SPECIAL;
|
||||
encounter.setDialogueToken("moveCategory", "Special");
|
||||
if (!correctMove) {
|
||||
encounter.options[1].dialogue.selected = [
|
||||
encounter.options[1].dialogue!.selected = [
|
||||
{
|
||||
text: `${namespace}.option.incorrect`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
|
@ -189,7 +189,7 @@ export const FieldTripEncounter: MysteryEncounter =
|
|||
} else {
|
||||
encounter.setDialogueToken("pokeName", pokemon.getNameToRender());
|
||||
encounter.setDialogueToken("move", move.getName());
|
||||
encounter.options[1].dialogue.selected = [
|
||||
encounter.options[1].dialogue!.selected = [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
},
|
||||
|
@ -256,7 +256,7 @@ export const FieldTripEncounter: MysteryEncounter =
|
|||
const correctMove = move.getMove().category === MoveCategory.STATUS;
|
||||
encounter.setDialogueToken("moveCategory", "Status");
|
||||
if (!correctMove) {
|
||||
encounter.options[2].dialogue.selected = [
|
||||
encounter.options[2].dialogue!.selected = [
|
||||
{
|
||||
text: `${namespace}.option.incorrect`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
|
@ -275,7 +275,7 @@ export const FieldTripEncounter: MysteryEncounter =
|
|||
} else {
|
||||
encounter.setDialogueToken("pokeName", pokemon.getNameToRender());
|
||||
encounter.setDialogueToken("move", move.getName());
|
||||
encounter.options[2].dialogue.selected = [
|
||||
encounter.options[2].dialogue!.selected = [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
},
|
||||
|
|
|
@ -75,8 +75,8 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
|||
// Load hidden Volcarona sprites
|
||||
encounter.spriteConfigs = [
|
||||
{
|
||||
spriteKey: null,
|
||||
fileRoot: null,
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.VOLCARONA,
|
||||
repeat: true,
|
||||
hidden: true,
|
||||
|
@ -85,8 +85,8 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
|||
startFrame: 20
|
||||
},
|
||||
{
|
||||
spriteKey: null,
|
||||
fileRoot: null,
|
||||
spriteKey: "",
|
||||
fileRoot: "",
|
||||
species: Species.VOLCARONA,
|
||||
repeat: true,
|
||||
hidden: true,
|
||||
|
@ -104,9 +104,9 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
|||
})
|
||||
.withOnVisualsStart((scene: BattleScene) => {
|
||||
// Play animations
|
||||
const background = new EncounterBattleAnim(EncounterAnim.MAGMA_BG, scene.getPlayerPokemon(), scene.getPlayerPokemon());
|
||||
const background = new EncounterBattleAnim(EncounterAnim.MAGMA_BG, scene.getPlayerPokemon()!, scene.getPlayerPokemon());
|
||||
background.playWithoutTargets(scene, 200, 70, 2, 3);
|
||||
const animation = new EncounterBattleAnim(EncounterAnim.MAGMA_SPOUT, scene.getPlayerPokemon(), scene.getPlayerPokemon());
|
||||
const animation = new EncounterBattleAnim(EncounterAnim.MAGMA_SPOUT, scene.getPlayerPokemon()!, scene.getPlayerPokemon());
|
||||
animation.playWithoutTargets(scene, 80, 100, 2);
|
||||
scene.time.delayedCall(600, () => {
|
||||
animation.playWithoutTargets(scene, -20, 100, 2);
|
||||
|
@ -133,7 +133,7 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
|||
async (scene: BattleScene) => {
|
||||
// Pick battle
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
setEncounterRewards(scene, { fillRemaining: true }, null, () => giveLeadPokemonCharcoal(scene));
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, () => giveLeadPokemonCharcoal(scene));
|
||||
|
||||
encounter.startOfBattleEffects.push(
|
||||
{
|
||||
|
@ -185,7 +185,7 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
|||
}
|
||||
|
||||
// Burn random member
|
||||
const burnable = nonFireTypes.filter(p => isNullOrUndefined(p.status) || isNullOrUndefined(p.status.effect) || p.status?.effect === StatusEffect.BURN);
|
||||
const burnable = nonFireTypes.filter(p => isNullOrUndefined(p.status) || isNullOrUndefined(p.status!.effect) || p.status?.effect === StatusEffect.BURN);
|
||||
if (burnable?.length > 0) {
|
||||
const roll = randSeedInt(burnable.length);
|
||||
const chosenPokemon = burnable[roll];
|
||||
|
@ -224,13 +224,13 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
|||
transitionMysteryEncounterIntroVisuals(scene);
|
||||
setEncounterRewards(scene,
|
||||
{ fillRemaining: true },
|
||||
null,
|
||||
undefined,
|
||||
() => {
|
||||
giveLeadPokemonCharcoal(scene);
|
||||
});
|
||||
|
||||
const primary = encounter.options[2].primaryPokemon;
|
||||
const secondary = encounter.options[2].secondaryPokemon[0];
|
||||
const primary = encounter.options[2].primaryPokemon!;
|
||||
const secondary = encounter.options[2].secondaryPokemon![0];
|
||||
|
||||
setEncounterExp(scene, [primary.id, secondary.id], getPokemonSpecies(Species.VOLCARONA).baseExp * 2);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
|
|
|
@ -50,7 +50,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
|||
|
||||
// Calculate boss mon
|
||||
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, scene.currentBattle.waveIndex, 0, getPartyLuckValue(scene.getParty()), true);
|
||||
const bossPokemon = new EnemyPokemon(scene, bossSpecies, scene.currentBattle.waveIndex, TrainerSlot.NONE, true, null);
|
||||
const bossPokemon = new EnemyPokemon(scene, bossSpecies, scene.currentBattle.waveIndex, TrainerSlot.NONE, true);
|
||||
const config: EnemyPartyConfig = {
|
||||
levelAdditiveMultiplier: 1,
|
||||
pokemonConfigs: [{
|
||||
|
@ -72,7 +72,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
|||
? ModifierTier.ULTRA
|
||||
: ModifierTier.GREAT;
|
||||
regenerateModifierPoolThresholds(scene.getParty(), ModifierPoolType.PLAYER, 0);
|
||||
let item: ModifierTypeOption;
|
||||
let item: ModifierTypeOption | null = null;
|
||||
// TMs excluded from possible rewards as they're too swingy in value for a singular item reward
|
||||
while (!item || item.type.id.includes("TM_")) {
|
||||
item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [tier], allowLuckUpgrades: false })[0];
|
||||
|
@ -147,8 +147,8 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
|||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
||||
|
||||
// Use primaryPokemon to execute the thievery
|
||||
const primaryPokemon = encounter.options[1].primaryPokemon;
|
||||
setEncounterExp(scene, primaryPokemon.id, encounter.enemyPartyConfigs[0].pokemonConfigs[0].species.baseExp);
|
||||
const primaryPokemon = encounter.options[1].primaryPokemon!;
|
||||
setEncounterExp(scene, primaryPokemon.id, encounter.enemyPartyConfigs[0].pokemonConfigs![0].species.baseExp);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
})
|
||||
.build()
|
||||
|
|
|
@ -87,6 +87,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
|||
const e4Template = trainerPartyTemplates.ELITE_FOUR;
|
||||
const brutalConfig = trainerConfigs[brutalTrainerType].copy();
|
||||
brutalConfig.setPartyTemplates(e4Template);
|
||||
// @ts-ignore
|
||||
brutalConfig.partyTemplateFunc = null; // Overrides gym leader party template func
|
||||
female = false;
|
||||
if (brutalConfig.hasGenders) {
|
||||
|
|
|
@ -57,7 +57,7 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
|||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
// Play animation
|
||||
const introVisuals =
|
||||
scene.currentBattle.mysteryEncounter.introVisuals;
|
||||
scene.currentBattle.mysteryEncounter.introVisuals!;
|
||||
introVisuals.spriteConfigs[0].disableAnimation = false;
|
||||
introVisuals.playAnim();
|
||||
})
|
||||
|
|
|
@ -100,8 +100,10 @@ export const PartTimerEncounter: MysteryEncounter =
|
|||
|
||||
// Reduce all PP to 2 (if they started at greater than 2)
|
||||
pokemon.moveset.forEach(move => {
|
||||
const newPpUsed = move.getMovePp() - 2;
|
||||
move.ppUsed = move.ppUsed < newPpUsed ? newPpUsed : move.ppUsed;
|
||||
if (move) {
|
||||
const newPpUsed = move.getMovePp() - 2;
|
||||
move.ppUsed = move.ppUsed < newPpUsed ? newPpUsed : move.ppUsed;
|
||||
}
|
||||
});
|
||||
|
||||
setEncounterExp(scene, pokemon.id, 100);
|
||||
|
@ -115,13 +117,13 @@ export const PartTimerEncounter: MysteryEncounter =
|
|||
// Only Pokemon non-KOd pokemon can be selected
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
if (!pokemon.isAllowedInBattle()) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`);
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Pick Deliveries
|
||||
|
@ -179,8 +181,10 @@ export const PartTimerEncounter: MysteryEncounter =
|
|||
|
||||
// Reduce all PP to 2 (if they started at greater than 2)
|
||||
pokemon.moveset.forEach(move => {
|
||||
const newPpUsed = move.getMovePp() - 2;
|
||||
move.ppUsed = move.ppUsed < newPpUsed ? newPpUsed : move.ppUsed;
|
||||
if (move) {
|
||||
const newPpUsed = move.getMovePp() - 2;
|
||||
move.ppUsed = move.ppUsed < newPpUsed ? newPpUsed : move.ppUsed;
|
||||
}
|
||||
});
|
||||
|
||||
setEncounterExp(scene, pokemon.id, 100);
|
||||
|
@ -194,13 +198,13 @@ export const PartTimerEncounter: MysteryEncounter =
|
|||
// Only Pokemon non-KOd pokemon can be selected
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
if (!pokemon.isAllowedInBattle()) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`);
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Pick Move Warehouse items
|
||||
|
@ -241,13 +245,15 @@ export const PartTimerEncounter: MysteryEncounter =
|
|||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
const selectedPokemon = encounter.selectedOption.primaryPokemon;
|
||||
const selectedPokemon = encounter.selectedOption?.primaryPokemon!;
|
||||
encounter.setDialogueToken("selectedPokemon", selectedPokemon.getNameToRender());
|
||||
|
||||
// Reduce all PP to 2 (if they started at greater than 2)
|
||||
selectedPokemon.moveset.forEach(move => {
|
||||
const newPpUsed = move.getMovePp() - 2;
|
||||
move.ppUsed = move.ppUsed < newPpUsed ? newPpUsed : move.ppUsed;
|
||||
if (move) {
|
||||
const newPpUsed = move.getMovePp() - 2;
|
||||
move.ppUsed = move.ppUsed < newPpUsed ? newPpUsed : move.ppUsed;
|
||||
}
|
||||
});
|
||||
|
||||
setEncounterExp(scene, selectedPokemon.id, 100);
|
||||
|
|
|
@ -172,9 +172,9 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [
|
|||
// 80% chance to increase flee stage +1
|
||||
const fleeChangeResult = tryChangeFleeStage(scene, 1, 8);
|
||||
if (!fleeChangeResult) {
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.busy_eating`), 1000, false );
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.busy_eating`) ?? "", 1000, false );
|
||||
} else {
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.eating`), 1000, false);
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.eating`) ?? "", 1000, false);
|
||||
}
|
||||
|
||||
await doEndTurn(scene, 1);
|
||||
|
@ -201,9 +201,9 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [
|
|||
// 80% chance to decrease catch stage -1
|
||||
const catchChangeResult = tryChangeCatchStage(scene, -1, 8);
|
||||
if (!catchChangeResult) {
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.beside_itself_angry`), 1000, false );
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.beside_itself_angry`) ?? "", 1000, false );
|
||||
} else {
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.angry`), 1000, false );
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.angry`) ?? "", 1000, false );
|
||||
}
|
||||
|
||||
await doEndTurn(scene, 2);
|
||||
|
@ -239,7 +239,7 @@ async function summonSafariPokemon(scene: BattleScene) {
|
|||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
// Message pokemon remaining
|
||||
encounter.setDialogueToken("remainingCount", encounter.misc.safariPokemonRemaining);
|
||||
scene.queueMessage(getEncounterText(scene, `${namespace}.safari.remaining_count`), null, true);
|
||||
scene.queueMessage(getEncounterText(scene, `${namespace}.safari.remaining_count`) ?? "", null, true);
|
||||
|
||||
// Generate pokemon using safariPokemonRemaining so they are always the same pokemon no matter how many turns are taken
|
||||
// Safari pokemon roll twice on shiny and HA chances, but are otherwise normal
|
||||
|
@ -288,7 +288,7 @@ async function summonSafariPokemon(scene: BattleScene) {
|
|||
scene.unshiftPhase(new SummonPhase(scene, 0, false));
|
||||
|
||||
encounter.setDialogueToken("pokemonName", getPokemonNameWithAffix(pokemon));
|
||||
showEncounterText(scene, getEncounterText(scene, "battle:singleWildAppeared"), 1500, false)
|
||||
showEncounterText(scene, getEncounterText(scene, "battle:singleWildAppeared") ?? "", 1500, false)
|
||||
.then(() => {
|
||||
const ivScannerModifier = scene.findModifier(m => m instanceof IvScannerModifier);
|
||||
if (ivScannerModifier) {
|
||||
|
@ -494,7 +494,7 @@ async function doEndTurn(scene: BattleScene, cursorIndex: number) {
|
|||
leaveEncounterWithoutBattle(scene, true);
|
||||
}
|
||||
} else {
|
||||
scene.queueMessage(getEncounterText(scene, `${namespace}.safari.watching`), 0, null, 1000);
|
||||
scene.queueMessage(getEncounterText(scene, `${namespace}.safari.watching`) ?? "", 0, null, 1000);
|
||||
initSubsequentOptionSelect(scene, { overrideOptions: safariZoneGameOptions, startingCursorIndex: cursorIndex, hideDescription: true });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,13 +95,13 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
|||
// If pokemon meets primary pokemon reqs, it can be selected
|
||||
const meetsReqs = encounter.pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`);
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Choose Cheap Option
|
||||
|
@ -178,13 +178,13 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
|||
// If pokemon meets primary pokemon reqs, it can be selected
|
||||
const meetsReqs = encounter.pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`);
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Choose Expensive Option
|
||||
|
|
|
@ -140,7 +140,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
|||
const instance = scene.currentBattle.mysteryEncounter;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS], fillRemaining: false });
|
||||
// Snorlax exp to Pokemon that did the stealing
|
||||
setEncounterExp(scene, instance.primaryPokemon.id, getPokemonSpecies(Species.SNORLAX).baseExp);
|
||||
setEncounterExp(scene, instance.primaryPokemon!.id, getPokemonSpecies(Species.SNORLAX).baseExp);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
})
|
||||
.build()
|
||||
|
|
|
@ -29,7 +29,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
|||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.THE_POKEMON_SALESMAN)
|
||||
.withEncounterTier(MysteryEncounterTier.ULTRA)
|
||||
.withSceneWaveRangeRequirement(10, 180)
|
||||
.withSceneRequirement(new MoneyRequirement(null, MAX_POKEMON_PRICE_MULTIPLIER)) // Some costs may not be as significant, this is the max you'd pay
|
||||
.withSceneRequirement(new MoneyRequirement(undefined, MAX_POKEMON_PRICE_MULTIPLIER)) // Some costs may not be as significant, this is the max you'd pay
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
|
@ -66,10 +66,10 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
|||
// If no HA mon found or you roll 1%, give shiny Magikarp
|
||||
species = getPokemonSpecies(Species.MAGIKARP);
|
||||
const hiddenIndex = species.ability2 ? 2 : 1;
|
||||
pokemon = new PlayerPokemon(scene, species, 5, hiddenIndex, species.formIndex, null, true, null, null, null, null);
|
||||
pokemon = new PlayerPokemon(scene, species, 5, hiddenIndex, species.formIndex, undefined, true);
|
||||
} else {
|
||||
const hiddenIndex = species.ability2 ? 2 : 1;
|
||||
pokemon = new PlayerPokemon(scene, species, 5, hiddenIndex, species.formIndex, null, null, null, null, null, null);
|
||||
pokemon = new PlayerPokemon(scene, species, 5, hiddenIndex, species.formIndex);
|
||||
}
|
||||
|
||||
const { spriteKey, fileRoot } = getSpriteKeysFromPokemon(pokemon);
|
||||
|
@ -88,8 +88,8 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
|||
// Always max price for shiny (flip HA back to normal), and add special messaging
|
||||
priceMultiplier = MAX_POKEMON_PRICE_MULTIPLIER;
|
||||
pokemon.abilityIndex = 0;
|
||||
encounter.dialogue.encounterOptionsDialogue.description = `${namespace}.description_shiny`;
|
||||
encounter.options[0].dialogue.buttonTooltip = `${namespace}.option.1.tooltip_shiny`;
|
||||
encounter.dialogue.encounterOptionsDialogue!.description = `${namespace}.description_shiny`;
|
||||
encounter.options[0].dialogue!.buttonTooltip = `${namespace}.option.1.tooltip_shiny`;
|
||||
}
|
||||
const price = scene.getWaveMoneyAmount(priceMultiplier);
|
||||
encounter.setDialogueToken("purchasePokemon", pokemon.getNameToRender());
|
||||
|
@ -107,7 +107,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
|||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withHasDexProgress(true)
|
||||
.withSceneMoneyRequirement(null, MAX_POKEMON_PRICE_MULTIPLIER) // Wave scaling money multiplier of 2
|
||||
.withSceneMoneyRequirement(undefined, MAX_POKEMON_PRICE_MULTIPLIER) // Wave scaling money multiplier of 2
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
|
|
|
@ -127,7 +127,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
|||
// -20 to all base stats of highest BST, +10 to all base stats of rest of party
|
||||
// Get highest BST mon
|
||||
const party = scene.getParty();
|
||||
let highestBst: PlayerPokemon = null;
|
||||
let highestBst: PlayerPokemon | null = null;
|
||||
let statTotal = 0;
|
||||
for (const pokemon of party) {
|
||||
if (!highestBst) {
|
||||
|
@ -157,7 +157,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
|||
}
|
||||
|
||||
encounter.setDialogueToken("highBstPokemon", highestBst.getNameToRender());
|
||||
await showEncounterText(scene, `${namespace}.option.1.selected_2`, null, true);
|
||||
await showEncounterText(scene, `${namespace}.option.1.selected_2`, undefined, true);
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true });
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
|
|
|
@ -140,7 +140,7 @@ async function spawnNextTrainerOrEndEncounter(scene: BattleScene) {
|
|||
await transitionMysteryEncounterIntroVisuals(scene, false, false);
|
||||
await showEncounterDialogue(scene, `${namespace}.victory`, `${namespace}.speaker`);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.MYSTERY_ENCOUNTER_MACHO_BRACE], fillRemaining: false });
|
||||
encounter.doContinueEncounter = null;
|
||||
encounter.doContinueEncounter = undefined;
|
||||
leaveEncounterWithoutBattle(scene, false, MysteryEncounterMode.TRAINER_BATTLE);
|
||||
} else {
|
||||
await initBattleWithEnemyConfig(scene, nextConfig);
|
||||
|
@ -151,17 +151,21 @@ function endTrainerBattleAndShowDialogue(scene: BattleScene): Promise<void> {
|
|||
return new Promise(async resolve => {
|
||||
if (scene.currentBattle.mysteryEncounter.enemyPartyConfigs.length === 0) {
|
||||
// Battle is over
|
||||
scene.tweens.add({
|
||||
targets: scene.currentBattle.trainer,
|
||||
x: "+=16",
|
||||
y: "-=16",
|
||||
alpha: 0,
|
||||
ease: "Sine.easeInOut",
|
||||
duration: 750,
|
||||
onComplete: () => {
|
||||
scene.field.remove(scene.currentBattle.trainer, true);
|
||||
}
|
||||
});
|
||||
const trainer = scene.currentBattle.trainer;
|
||||
if (trainer) {
|
||||
scene.tweens.add({
|
||||
targets: trainer,
|
||||
x: "+=16",
|
||||
y: "-=16",
|
||||
alpha: 0,
|
||||
ease: "Sine.easeInOut",
|
||||
duration: 750,
|
||||
onComplete: () => {
|
||||
scene.field.remove(trainer, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await spawnNextTrainerOrEndEncounter(scene);
|
||||
resolve(); // Wait for all dialogue/post battle stuff to complete before resolving
|
||||
} else {
|
||||
|
@ -186,18 +190,20 @@ function endTrainerBattleAndShowDialogue(scene: BattleScene): Promise<void> {
|
|||
// Unassign previous trainer from battle so it isn't destroyed before animation completes
|
||||
scene.currentBattle.trainer = null;
|
||||
await spawnNextTrainerOrEndEncounter(scene);
|
||||
scene.tweens.add({
|
||||
targets: trainer,
|
||||
x: "+=16",
|
||||
y: "-=16",
|
||||
alpha: 0,
|
||||
ease: "Sine.easeInOut",
|
||||
duration: 750,
|
||||
onComplete: () => {
|
||||
scene.field.remove(trainer, true);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
if (trainer) {
|
||||
scene.tweens.add({
|
||||
targets: trainer,
|
||||
x: "+=16",
|
||||
y: "-=16",
|
||||
alpha: 0,
|
||||
ease: "Sine.easeInOut",
|
||||
duration: 750,
|
||||
onComplete: () => {
|
||||
scene.field.remove(trainer, true);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,11 +6,10 @@ import { Stat } from "#app/data/pokemon-stat";
|
|||
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { pokemonInfo } from "#app/locales/en/pokemon-info";
|
||||
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
import { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
import { AbilityAttr } from "#app/system/game-data";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||
import { randSeedShuffle } from "#app/utils";
|
||||
import { isNullOrUndefined, randSeedShuffle } from "#app/utils";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
|
@ -19,6 +18,7 @@ import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
|||
import { getEncounterText, queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||
|
||||
/** The i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:trainingSession";
|
||||
|
@ -77,13 +77,13 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
const meetsReqs = pokemon.isAllowedInBattle();
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`);
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
|
@ -125,7 +125,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
encounter.setDialogueToken("stat1", "-");
|
||||
encounter.setDialogueToken("stat2", "-");
|
||||
// Add the pokemon back to party with IV boost
|
||||
const ivIndexes = [];
|
||||
const ivIndexes: any[] = [];
|
||||
playerPokemon.ivs.forEach((iv, index) => {
|
||||
if (iv < 31) {
|
||||
ivIndexes.push({ iv: iv, index: index });
|
||||
|
@ -147,12 +147,12 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
if (improvedCount === 0) {
|
||||
encounter.setDialogueToken(
|
||||
"stat1",
|
||||
getIvName(ivToChange.index)
|
||||
getIvName(ivToChange.index) ?? ""
|
||||
);
|
||||
} else {
|
||||
encounter.setDialogueToken(
|
||||
"stat2",
|
||||
getIvName(ivToChange.index)
|
||||
getIvName(ivToChange.index) ?? ""
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -185,12 +185,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
queueEncounterMessage(scene, `${namespace}.option.1.finished`);
|
||||
};
|
||||
|
||||
setEncounterRewards(
|
||||
scene,
|
||||
{ fillRemaining: true },
|
||||
null,
|
||||
onBeforeRewardsPhase
|
||||
);
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
||||
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
|
@ -237,13 +232,13 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
const meetsReqs = pokemon.isAllowedInBattle();
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`);
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
|
@ -278,12 +273,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
scene.updateModifiers(true);
|
||||
};
|
||||
|
||||
setEncounterRewards(
|
||||
scene,
|
||||
{ fillRemaining: true },
|
||||
null,
|
||||
onBeforeRewardsPhase
|
||||
);
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
||||
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
|
@ -339,13 +329,13 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
const meetsReqs = pokemon.isAllowedInBattle();
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`);
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
|
@ -354,18 +344,10 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
// Spawn hard training session with chosen pokemon
|
||||
// Every 30 waves, add +1 boss segment, capping at 6
|
||||
// Also starts with +1 to all stats
|
||||
const segments = Math.min(
|
||||
2 + Math.floor(scene.currentBattle.waveIndex / 30),
|
||||
6
|
||||
);
|
||||
const segments = Math.min(2 + Math.floor(scene.currentBattle.waveIndex / 30), 6);
|
||||
const modifiers = new ModifiersHolder();
|
||||
const config = getEnemyConfig(
|
||||
scene,
|
||||
playerPokemon,
|
||||
segments,
|
||||
modifiers
|
||||
);
|
||||
config.pokemonConfigs[0].tags = [
|
||||
const config = getEnemyConfig(scene, playerPokemon, segments, modifiers);
|
||||
config.pokemonConfigs![0].tags = [
|
||||
BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON,
|
||||
];
|
||||
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
||||
|
@ -376,15 +358,10 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
const abilityIndex = encounter.misc.abilityIndex;
|
||||
if (!!playerPokemon.getFusionSpeciesForm()) {
|
||||
playerPokemon.fusionAbilityIndex = abilityIndex;
|
||||
if (
|
||||
speciesStarters.hasOwnProperty(
|
||||
playerPokemon.fusionSpecies.speciesId
|
||||
)
|
||||
) {
|
||||
scene.gameData.starterData[
|
||||
playerPokemon.fusionSpecies.speciesId
|
||||
].abilityAttr |=
|
||||
abilityIndex !== 1 || playerPokemon.fusionSpecies.ability2
|
||||
if (!isNullOrUndefined(playerPokemon.fusionSpecies?.speciesId) && speciesStarters.hasOwnProperty(playerPokemon.fusionSpecies!.speciesId)) {
|
||||
scene.gameData.starterData[playerPokemon.fusionSpecies!.speciesId]
|
||||
.abilityAttr |=
|
||||
abilityIndex !== 1 || playerPokemon.fusionSpecies!.ability2
|
||||
? Math.pow(2, playerPokemon.fusionAbilityIndex)
|
||||
: AbilityAttr.ABILITY_HIDDEN;
|
||||
}
|
||||
|
@ -414,12 +391,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
scene.updateModifiers(true);
|
||||
};
|
||||
|
||||
setEncounterRewards(
|
||||
scene,
|
||||
{ fillRemaining: true },
|
||||
null,
|
||||
onBeforeRewardsPhase
|
||||
);
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
||||
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
|
@ -432,7 +404,11 @@ function getEnemyConfig(scene: BattleScene, playerPokemon: PlayerPokemon,segment
|
|||
|
||||
// Passes modifiers by reference
|
||||
modifiers.value = scene.findModifiers((m) => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === playerPokemon.id) as PokemonHeldItemModifier[];
|
||||
const modifierTypes = modifiers.value.map((mod) => mod.type) as PokemonHeldItemModifierType[];
|
||||
const modifierConfigs = modifiers.value.map((mod) => {
|
||||
return {
|
||||
modifierType: mod.type
|
||||
};
|
||||
}) as HeldModifierConfig[];
|
||||
|
||||
const data = new PokemonData(playerPokemon);
|
||||
return {
|
||||
|
@ -444,7 +420,7 @@ function getEnemyConfig(scene: BattleScene, playerPokemon: PlayerPokemon,segment
|
|||
formIndex: playerPokemon.formIndex,
|
||||
level: playerPokemon.level,
|
||||
dataSource: data,
|
||||
modifierConfigs: modifierTypes,
|
||||
modifierConfigs: modifierConfigs,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
@ -178,7 +178,7 @@ async function tryApplyDigRewardItems(scene: BattleScene) {
|
|||
}
|
||||
|
||||
scene.playSound("item_fanfare");
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: "2 " + leftovers.name }), null, true);
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: "2 " + leftovers.name }), undefined, true);
|
||||
|
||||
// First Shell bell
|
||||
for (const pokemon of party) {
|
||||
|
@ -205,7 +205,7 @@ async function tryApplyDigRewardItems(scene: BattleScene) {
|
|||
}
|
||||
|
||||
scene.playSound("item_fanfare");
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: "2 " + shellBell.name }), null, true);
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: "2 " + shellBell.name }), undefined, true);
|
||||
}
|
||||
|
||||
async function doGarbageDig(scene: BattleScene) {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { leaveEncounterWithoutBattle, setEncounterRewards, } from "../utils/enco
|
|||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import Pokemon, { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { IntegerHolder, randSeedInt, randSeedShuffle } from "#app/utils";
|
||||
import { IntegerHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils";
|
||||
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { HiddenAbilityRateBoosterModifier, PokemonBaseStatTotalModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
import { achvs } from "#app/system/achv";
|
||||
|
@ -362,7 +362,7 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
|
|||
}
|
||||
newTypes.push(newType);
|
||||
if (!newPokemon.mysteryEncounterData) {
|
||||
newPokemon.mysteryEncounterData = new MysteryEncounterPokemonData(null, null, null, newTypes);
|
||||
newPokemon.mysteryEncounterData = new MysteryEncounterPokemonData(undefined, undefined, undefined, newTypes);
|
||||
} else {
|
||||
newPokemon.mysteryEncounterData.types = newTypes;
|
||||
}
|
||||
|
@ -381,9 +381,11 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
|
|||
// Def or SpDef
|
||||
stats.push(baseStats[Stat.DEF] < baseStats[Stat.SPDEF] ? Stat.DEF : Stat.SPDEF);
|
||||
// const mod = modifierTypes.MYSTERY_ENCOUNTER_OLD_GATEAU().newModifier(newPokemon, 20, stats);
|
||||
const modType = modifierTypes.MYSTERY_ENCOUNTER_OLD_GATEAU().generateType(null, [20, stats]);
|
||||
const modifier = modType.newModifier(newPokemon);
|
||||
scene.addModifier(modifier);
|
||||
const modType = modifierTypes.MYSTERY_ENCOUNTER_OLD_GATEAU().generateType(scene.getParty(), [20, stats]);
|
||||
const modifier = modType?.newModifier(newPokemon);
|
||||
if (modifier) {
|
||||
scene.addModifier(modifier);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable passive if previous had it
|
||||
|
@ -422,8 +424,8 @@ function getOriginalBst(scene: BattleScene, pokemon: Pokemon) {
|
|||
}
|
||||
|
||||
function getTransformedSpecies(originalBst: number, bstSearchRange: [number, number], hasPokemonBstHigherThan600: boolean, hasPokemonBstBetween570And600: boolean, alreadyUsedSpecies: PokemonSpecies[]): PokemonSpecies {
|
||||
let newSpecies: PokemonSpecies;
|
||||
while (!newSpecies) {
|
||||
let newSpecies: PokemonSpecies | undefined;
|
||||
while (isNullOrUndefined(newSpecies)) {
|
||||
const bstCap = originalBst + bstSearchRange[1];
|
||||
const bstMin = Math.max(originalBst + bstSearchRange[0], 0);
|
||||
|
||||
|
@ -442,7 +444,7 @@ function getTransformedSpecies(originalBst: number, bstSearchRange: [number, num
|
|||
if (validSpecies?.length > 20) {
|
||||
validSpecies = randSeedShuffle(validSpecies);
|
||||
newSpecies = validSpecies.pop();
|
||||
while (alreadyUsedSpecies.includes(newSpecies)) {
|
||||
while (isNullOrUndefined(newSpecies) || alreadyUsedSpecies.includes(newSpecies!)) {
|
||||
newSpecies = validSpecies.pop();
|
||||
}
|
||||
} else {
|
||||
|
@ -452,7 +454,7 @@ function getTransformedSpecies(originalBst: number, bstSearchRange: [number, num
|
|||
}
|
||||
}
|
||||
|
||||
return newSpecies;
|
||||
return newSpecies!;
|
||||
}
|
||||
|
||||
function doShowDreamBackground(scene: BattleScene) {
|
||||
|
@ -503,7 +505,7 @@ function doHideDreamBackground(scene: BattleScene) {
|
|||
|
||||
function doSideBySideTransformations(scene: BattleScene, transformations: PokemonTransformation[]) {
|
||||
return new Promise<void>(resolve => {
|
||||
const allTransformationPromises = [];
|
||||
const allTransformationPromises: Promise<void>[] = [];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const delay = i * 4000;
|
||||
scene.time.delayedCall(delay, () => {
|
||||
|
|
|
@ -8,16 +8,32 @@ import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequiremen
|
|||
import { CanLearnMoveRequirement, CanLearnMoveRequirementOptions } from "./requirements/can-learn-move-requirement";
|
||||
import { isNullOrUndefined } from "#app/utils";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||
|
||||
|
||||
export type OptionPhaseCallback = (scene: BattleScene) => Promise<void | boolean>;
|
||||
|
||||
// export default interface MysteryEncounterOption {
|
||||
//
|
||||
// }
|
||||
/**
|
||||
* Used by {@link MysteryEncounterOptionBuilder} class to define required/optional properties on the {@link MysteryEncounterOption} class when building.
|
||||
*
|
||||
* Should ONLY contain properties that are necessary for {@link MysteryEncounterOption} construction.
|
||||
* Post-construct and flag data properties are defined in the {@link MysteryEncounterOption} class itself.
|
||||
*/
|
||||
export interface IMysteryEncounterOption {
|
||||
optionMode: MysteryEncounterOptionMode;
|
||||
hasDexProgress: boolean;
|
||||
requirements: EncounterSceneRequirement[];
|
||||
primaryPokemonRequirements: EncounterPokemonRequirement[];
|
||||
secondaryPokemonRequirements: EncounterPokemonRequirement[];
|
||||
excludePrimaryFromSecondaryRequirements: boolean;
|
||||
|
||||
export default class MysteryEncounterOption {
|
||||
dialogue?: OptionTextDisplay;
|
||||
|
||||
onPreOptionPhase?: OptionPhaseCallback;
|
||||
onOptionPhase: OptionPhaseCallback;
|
||||
onPostOptionPhase?: OptionPhaseCallback;
|
||||
}
|
||||
|
||||
export default class MysteryEncounterOption implements IMysteryEncounterOption {
|
||||
optionMode: MysteryEncounterOptionMode;
|
||||
hasDexProgress: boolean;
|
||||
requirements: EncounterSceneRequirement[];
|
||||
|
@ -40,12 +56,14 @@ export default class MysteryEncounterOption {
|
|||
/** Executes after the encounter is over. Usually this will be for calculating dialogueTokens or performing data updates */
|
||||
onPostOptionPhase?: OptionPhaseCallback;
|
||||
|
||||
constructor(option: MysteryEncounterOption | null) {
|
||||
Object.assign(this, option);
|
||||
this.hasDexProgress = !isNullOrUndefined(this.hasDexProgress) ? this.hasDexProgress : false;
|
||||
this.requirements = this.requirements ? this.requirements : [];
|
||||
this.primaryPokemonRequirements = this.primaryPokemonRequirements ? this.primaryPokemonRequirements : [];
|
||||
this.secondaryPokemonRequirements = this.secondaryPokemonRequirements ? this.secondaryPokemonRequirements : [];
|
||||
constructor(option: IMysteryEncounterOption | null) {
|
||||
if (!isNullOrUndefined(option)) {
|
||||
Object.assign(this, option);
|
||||
}
|
||||
this.hasDexProgress = this.hasDexProgress ?? false;
|
||||
this.requirements = this.requirements ?? [];
|
||||
this.primaryPokemonRequirements = this.primaryPokemonRequirements ?? [];
|
||||
this.secondaryPokemonRequirements = this.secondaryPokemonRequirements ?? [];
|
||||
}
|
||||
|
||||
hasRequirements() {
|
||||
|
@ -70,7 +88,8 @@ export default class MysteryEncounterOption {
|
|||
for (const req of this.primaryPokemonRequirements) {
|
||||
if (req.meetsRequirement(scene)) {
|
||||
if (req instanceof EncounterPokemonRequirement) {
|
||||
qualified = qualified.filter(pkmn => req.queryParty(scene.getParty()).includes(pkmn));
|
||||
const queryParty = req.queryParty(scene.getParty());
|
||||
qualified = qualified.filter(pkmn => queryParty.includes(pkmn));
|
||||
}
|
||||
} else {
|
||||
this.primaryPokemon = undefined;
|
||||
|
@ -125,8 +144,8 @@ export default class MysteryEncounterOption {
|
|||
for (const req of this.secondaryPokemonRequirements) {
|
||||
if (req.meetsRequirement(scene)) {
|
||||
if (req instanceof EncounterPokemonRequirement) {
|
||||
qualified = qualified.filter(pkmn => req.queryParty(scene.getParty()).includes(pkmn));
|
||||
|
||||
const queryParty = req.queryParty(scene.getParty());
|
||||
qualified = qualified.filter(pkmn => queryParty.includes(pkmn));
|
||||
}
|
||||
} else {
|
||||
this.secondaryPokemon = [];
|
||||
|
@ -138,7 +157,7 @@ export default class MysteryEncounterOption {
|
|||
}
|
||||
}
|
||||
|
||||
export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOption> {
|
||||
export class MysteryEncounterOptionBuilder implements Partial<IMysteryEncounterOption> {
|
||||
optionMode: MysteryEncounterOptionMode = MysteryEncounterOptionMode.DEFAULT;
|
||||
requirements: EncounterSceneRequirement[] = [];
|
||||
primaryPokemonRequirements: EncounterPokemonRequirement[] = [];
|
||||
|
@ -146,26 +165,17 @@ export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOp
|
|||
excludePrimaryFromSecondaryRequirements: boolean = false;
|
||||
isDisabledOnRequirementsNotMet: boolean = true;
|
||||
hasDexProgress: boolean = false;
|
||||
onPreOptionPhase?: OptionPhaseCallback;
|
||||
onOptionPhase: OptionPhaseCallback;
|
||||
onPostOptionPhase?: OptionPhaseCallback;
|
||||
dialogue: OptionTextDisplay;
|
||||
dialogue?: OptionTextDisplay;
|
||||
|
||||
hasRequirements = MysteryEncounter.prototype["hasRequirements"];
|
||||
meetsRequirements = MysteryEncounter.prototype["meetsRequirements"];
|
||||
pokemonMeetsPrimaryRequirements = MysteryEncounter.prototype["pokemonMeetsPrimaryRequirements"];
|
||||
meetsPrimaryRequirementAndPrimaryPokemonSelected = MysteryEncounter.prototype["meetsPrimaryRequirementAndPrimaryPokemonSelected"];
|
||||
meetsSupportingRequirementAndSupportingPokemonSelected = MysteryEncounter.prototype["meetsSupportingRequirementAndSupportingPokemonSelected"];
|
||||
|
||||
static newOptionWithMode(optionMode: MysteryEncounterOptionMode): MysteryEncounterOptionBuilder & Pick<MysteryEncounterOption, "optionMode"> {
|
||||
static newOptionWithMode(optionMode: MysteryEncounterOptionMode): MysteryEncounterOptionBuilder & Pick<IMysteryEncounterOption, "optionMode"> {
|
||||
return Object.assign(new MysteryEncounterOptionBuilder(), { optionMode });
|
||||
}
|
||||
|
||||
withHasDexProgress(hasDexProgress: boolean): this & Required<Pick<MysteryEncounterOption, "hasDexProgress">> {
|
||||
withHasDexProgress(hasDexProgress: boolean): this & Required<Pick<IMysteryEncounterOption, "hasDexProgress">> {
|
||||
return Object.assign(this, { hasDexProgress: hasDexProgress });
|
||||
}
|
||||
|
||||
withSceneRequirement(requirement: EncounterSceneRequirement): this & Required<Pick<MysteryEncounterOption, "requirements">> {
|
||||
withSceneRequirement(requirement: EncounterSceneRequirement): this & Required<Pick<IMysteryEncounterOption, "requirements">> {
|
||||
if (requirement instanceof EncounterPokemonRequirement) {
|
||||
Error("Incorrectly added pokemon requirement as scene requirement.");
|
||||
}
|
||||
|
@ -174,23 +184,23 @@ export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOp
|
|||
return Object.assign(this, { requirements: this.requirements });
|
||||
}
|
||||
|
||||
withSceneMoneyRequirement(requiredMoney: number, scalingMultiplier?: number) {
|
||||
withSceneMoneyRequirement(requiredMoney?: number, scalingMultiplier?: number) {
|
||||
return this.withSceneRequirement(new MoneyRequirement(requiredMoney, scalingMultiplier));
|
||||
}
|
||||
|
||||
withPreOptionPhase(onPreOptionPhase: OptionPhaseCallback): this & Required<Pick<MysteryEncounterOption, "onPreOptionPhase">> {
|
||||
withPreOptionPhase(onPreOptionPhase: OptionPhaseCallback): this & Required<Pick<IMysteryEncounterOption, "onPreOptionPhase">> {
|
||||
return Object.assign(this, { onPreOptionPhase: onPreOptionPhase });
|
||||
}
|
||||
|
||||
withOptionPhase(onOptionPhase: OptionPhaseCallback): this & Required<Pick<MysteryEncounterOption, "onOptionPhase">> {
|
||||
withOptionPhase(onOptionPhase: OptionPhaseCallback): this & Required<Pick<IMysteryEncounterOption, "onOptionPhase">> {
|
||||
return Object.assign(this, { onOptionPhase: onOptionPhase });
|
||||
}
|
||||
|
||||
withPostOptionPhase(onPostOptionPhase: OptionPhaseCallback): this & Required<Pick<MysteryEncounterOption, "onPostOptionPhase">> {
|
||||
withPostOptionPhase(onPostOptionPhase: OptionPhaseCallback): this & Required<Pick<IMysteryEncounterOption, "onPostOptionPhase">> {
|
||||
return Object.assign(this, { onPostOptionPhase: onPostOptionPhase });
|
||||
}
|
||||
|
||||
withPrimaryPokemonRequirement(requirement: EncounterPokemonRequirement): this & Required<Pick<MysteryEncounterOption, "primaryPokemonRequirements">> {
|
||||
withPrimaryPokemonRequirement(requirement: EncounterPokemonRequirement): this & Required<Pick<IMysteryEncounterOption, "primaryPokemonRequirements">> {
|
||||
if (requirement instanceof EncounterSceneRequirement) {
|
||||
Error("Incorrectly added scene requirement as pokemon requirement.");
|
||||
}
|
||||
|
@ -223,7 +233,7 @@ export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOp
|
|||
return this.withPrimaryPokemonRequirement(new CanLearnMoveRequirement(move, options));
|
||||
}
|
||||
|
||||
withSecondaryPokemonRequirement(requirement: EncounterPokemonRequirement, excludePrimaryFromSecondaryRequirements: boolean = true): this & Required<Pick<MysteryEncounterOption, "secondaryPokemonRequirements">> {
|
||||
withSecondaryPokemonRequirement(requirement: EncounterPokemonRequirement, excludePrimaryFromSecondaryRequirements: boolean = true): this & Required<Pick<IMysteryEncounterOption, "secondaryPokemonRequirements">> {
|
||||
if (requirement instanceof EncounterSceneRequirement) {
|
||||
Error("Incorrectly added scene requirement as pokemon requirement.");
|
||||
}
|
||||
|
@ -244,7 +254,7 @@ export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOp
|
|||
return this;
|
||||
}
|
||||
|
||||
build(this: MysteryEncounterOption) {
|
||||
build(this: IMysteryEncounterOption) {
|
||||
return new MysteryEncounterOption(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -275,10 +275,10 @@ export class MoneyRequirement extends EncounterSceneRequirement {
|
|||
requiredMoney: number; // Static value
|
||||
scalingMultiplier: number; // Calculates required money based off wave index
|
||||
|
||||
constructor(requiredMoney: number, scalingMultiplier?: number) {
|
||||
constructor(requiredMoney?: number, scalingMultiplier?: number) {
|
||||
super();
|
||||
this.requiredMoney = requiredMoney;
|
||||
this.scalingMultiplier = scalingMultiplier ? scalingMultiplier : 0;
|
||||
this.requiredMoney = requiredMoney ?? 0;
|
||||
this.scalingMultiplier = scalingMultiplier ?? 0;
|
||||
}
|
||||
|
||||
meetsRequirement(scene: BattleScene): boolean {
|
||||
|
@ -287,14 +287,14 @@ export class MoneyRequirement extends EncounterSceneRequirement {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (this?.scalingMultiplier > 0) {
|
||||
if (this.scalingMultiplier > 0) {
|
||||
this.requiredMoney = scene.getWaveMoneyAmount(this.scalingMultiplier);
|
||||
}
|
||||
return !(this?.requiredMoney > 0 && this.requiredMoney > money);
|
||||
return !(this.requiredMoney > 0 && this.requiredMoney > money);
|
||||
}
|
||||
|
||||
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
const value = this?.scalingMultiplier > 0 ? scene.getWaveMoneyAmount(this.scalingMultiplier).toString() : this.requiredMoney.toString();
|
||||
const value = this.scalingMultiplier > 0 ? scene.getWaveMoneyAmount(this.scalingMultiplier).toString() : this.requiredMoney.toString();
|
||||
return ["money", value];
|
||||
}
|
||||
}
|
||||
|
@ -367,10 +367,10 @@ export class NatureRequirement extends EncounterPokemonRequirement {
|
|||
}
|
||||
|
||||
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
if (this.requiredNature.includes(pokemon.nature)) {
|
||||
return ["nature", Nature[pokemon.nature]];
|
||||
if (!isNullOrUndefined(pokemon?.nature) && this.requiredNature.includes(pokemon!.nature)) {
|
||||
return ["nature", Nature[pokemon!.nature]];
|
||||
}
|
||||
return null;
|
||||
return ["nature", ""];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -537,9 +537,9 @@ export class EvolutionTargetSpeciesRequirement extends EncounterPokemonRequireme
|
|||
getMatchingDialogueToken(str:string, pokemon: PlayerPokemon): [RegExp, string] {
|
||||
const evos = this.requiredEvolutionTargetSpecies.filter((evolutionTargetSpecies) => pokemon.getEvolution().speciesId === evolutionTargetSpecies);
|
||||
if (evos.length > 0) {
|
||||
return ["Evolution", Species[evos[0]]];
|
||||
return ["evolution", Species[evos[0]]];
|
||||
}
|
||||
return null;
|
||||
return ["evolution", ""];
|
||||
}
|
||||
|
||||
}*/
|
||||
|
@ -622,7 +622,7 @@ export class StatusEffectRequirement extends EncounterPokemonRequirement {
|
|||
return !this.requiredStatusEffect.some((statusEffect) => {
|
||||
if (statusEffect === StatusEffect.NONE) {
|
||||
// StatusEffect.NONE also checks for null or undefined status
|
||||
return isNullOrUndefined(pokemon.status) || isNullOrUndefined(pokemon.status.effect) || pokemon.status?.effect === statusEffect;
|
||||
return isNullOrUndefined(pokemon.status) || isNullOrUndefined(pokemon.status!.effect) || pokemon.status?.effect === statusEffect;
|
||||
} else {
|
||||
return pokemon.status?.effect === statusEffect;
|
||||
}
|
||||
|
@ -634,9 +634,9 @@ export class StatusEffectRequirement extends EncounterPokemonRequirement {
|
|||
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
const reqStatus = this.requiredStatusEffect.filter((a) => {
|
||||
if (a === StatusEffect.NONE) {
|
||||
return isNullOrUndefined(pokemon.status) || isNullOrUndefined(pokemon.status.effect) || pokemon.status?.effect === a;
|
||||
return isNullOrUndefined(pokemon?.status) || isNullOrUndefined(pokemon!.status!.effect) || pokemon!.status!.effect === a;
|
||||
}
|
||||
return pokemon.status?.effect === a;
|
||||
return pokemon!.status?.effect === a;
|
||||
});
|
||||
if (reqStatus.length > 0) {
|
||||
return ["status", StatusEffect[reqStatus[0]]];
|
||||
|
@ -698,7 +698,7 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen
|
|||
if (requiredItems.length > 0) {
|
||||
return ["formChangeItem", FormChangeItem[requiredItems[0]]];
|
||||
}
|
||||
return null;
|
||||
return ["formChangeItem", ""];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -748,7 +748,7 @@ export class CanEvolveWithItemRequirement extends EncounterPokemonRequirement {
|
|||
if (requiredItems.length > 0) {
|
||||
return ["evolutionItem", EvolutionItem[requiredItems[0]]];
|
||||
}
|
||||
return null;
|
||||
return ["evolutionItem", ""];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -789,18 +789,18 @@ export class HeldItemRequirement extends EncounterPokemonRequirement {
|
|||
}
|
||||
|
||||
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
const requiredItems = pokemon.getHeldItems().filter((it) => {
|
||||
const requiredItems = pokemon?.getHeldItems().filter((it) => {
|
||||
return this.requiredHeldItemModifiers.some(heldItem => it.constructor.name === heldItem);
|
||||
});
|
||||
if (requiredItems.length > 0) {
|
||||
if (requiredItems && requiredItems.length > 0) {
|
||||
return ["heldItem", requiredItems[0].type.name];
|
||||
}
|
||||
return null;
|
||||
return ["heldItem", ""];
|
||||
}
|
||||
}
|
||||
|
||||
export class LevelRequirement extends EncounterPokemonRequirement {
|
||||
requiredLevelRange?: [number, number];
|
||||
requiredLevelRange: [number, number];
|
||||
minNumberOfPokemon: number;
|
||||
invertQuery: boolean;
|
||||
|
||||
|
@ -809,12 +809,11 @@ export class LevelRequirement extends EncounterPokemonRequirement {
|
|||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredLevelRange = requiredLevelRange;
|
||||
|
||||
}
|
||||
|
||||
meetsRequirement(scene: BattleScene): boolean {
|
||||
// Party Pokemon inside required level range
|
||||
if (!isNullOrUndefined(this?.requiredLevelRange) && this.requiredLevelRange?.[0] <= this.requiredLevelRange?.[1]) {
|
||||
if (!isNullOrUndefined(this.requiredLevelRange) && this.requiredLevelRange[0] <= this.requiredLevelRange[1]) {
|
||||
const partyPokemon = scene.getParty();
|
||||
const pokemonInRange = this.queryParty(partyPokemon);
|
||||
if (pokemonInRange.length < this.minNumberOfPokemon) {
|
||||
|
@ -834,12 +833,12 @@ export class LevelRequirement extends EncounterPokemonRequirement {
|
|||
}
|
||||
|
||||
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["level", pokemon.level.toString()];
|
||||
return ["level", pokemon?.level.toString() ?? ""];
|
||||
}
|
||||
}
|
||||
|
||||
export class FriendshipRequirement extends EncounterPokemonRequirement {
|
||||
requiredFriendshipRange?: [number, number];
|
||||
requiredFriendshipRange: [number, number];
|
||||
minNumberOfPokemon: number;
|
||||
invertQuery: boolean;
|
||||
|
||||
|
@ -852,7 +851,7 @@ export class FriendshipRequirement extends EncounterPokemonRequirement {
|
|||
|
||||
meetsRequirement(scene: BattleScene): boolean {
|
||||
// Party Pokemon inside required friendship range
|
||||
if (!isNullOrUndefined(this?.requiredFriendshipRange) && this.requiredFriendshipRange?.[0] <= this.requiredFriendshipRange?.[1]) {
|
||||
if (!isNullOrUndefined(this.requiredFriendshipRange) && this.requiredFriendshipRange[0] <= this.requiredFriendshipRange[1]) {
|
||||
const partyPokemon = scene.getParty();
|
||||
const pokemonInRange = this.queryParty(partyPokemon);
|
||||
if (pokemonInRange.length < this.minNumberOfPokemon) {
|
||||
|
@ -872,7 +871,7 @@ export class FriendshipRequirement extends EncounterPokemonRequirement {
|
|||
}
|
||||
|
||||
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["friendship", pokemon.friendship.toString()];
|
||||
return ["friendship", pokemon?.friendship.toString() ?? ""];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -882,7 +881,7 @@ export class FriendshipRequirement extends EncounterPokemonRequirement {
|
|||
* 1 -> 100% hp
|
||||
*/
|
||||
export class HealthRatioRequirement extends EncounterPokemonRequirement {
|
||||
requiredHealthRange?: [number, number];
|
||||
requiredHealthRange: [number, number];
|
||||
minNumberOfPokemon: number;
|
||||
invertQuery: boolean;
|
||||
|
||||
|
@ -895,7 +894,7 @@ export class HealthRatioRequirement extends EncounterPokemonRequirement {
|
|||
|
||||
meetsRequirement(scene: BattleScene): boolean {
|
||||
// Party Pokemon inside required level range
|
||||
if (!isNullOrUndefined(this?.requiredHealthRange) && this.requiredHealthRange?.[0] <= this.requiredHealthRange?.[1]) {
|
||||
if (!isNullOrUndefined(this.requiredHealthRange) && this.requiredHealthRange[0] <= this.requiredHealthRange[1]) {
|
||||
const partyPokemon = scene.getParty();
|
||||
const pokemonInRange = this.queryParty(partyPokemon);
|
||||
if (pokemonInRange.length < this.minNumberOfPokemon) {
|
||||
|
@ -917,12 +916,15 @@ export class HealthRatioRequirement extends EncounterPokemonRequirement {
|
|||
}
|
||||
|
||||
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["healthRatio", Math.floor(pokemon.getHpRatio() * 100).toString() + "%"];
|
||||
if (!isNullOrUndefined(pokemon?.getHpRatio())) {
|
||||
return ["healthRatio", Math.floor(pokemon!.getHpRatio() * 100).toString() + "%"];
|
||||
}
|
||||
return ["healthRatio", ""];
|
||||
}
|
||||
}
|
||||
|
||||
export class WeightRequirement extends EncounterPokemonRequirement {
|
||||
requiredWeightRange?: [number, number];
|
||||
requiredWeightRange: [number, number];
|
||||
minNumberOfPokemon: number;
|
||||
invertQuery: boolean;
|
||||
|
||||
|
@ -935,7 +937,7 @@ export class WeightRequirement extends EncounterPokemonRequirement {
|
|||
|
||||
meetsRequirement(scene: BattleScene): boolean {
|
||||
// Party Pokemon inside required friendship range
|
||||
if (!isNullOrUndefined(this?.requiredWeightRange) && this.requiredWeightRange?.[0] <= this.requiredWeightRange?.[1]) {
|
||||
if (!isNullOrUndefined(this.requiredWeightRange) && this.requiredWeightRange[0] <= this.requiredWeightRange[1]) {
|
||||
const partyPokemon = scene.getParty();
|
||||
const pokemonInRange = this.queryParty(partyPokemon);
|
||||
if (pokemonInRange.length < this.minNumberOfPokemon) {
|
||||
|
@ -955,7 +957,7 @@ export class WeightRequirement extends EncounterPokemonRequirement {
|
|||
}
|
||||
|
||||
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["weight", pokemon.getWeight().toString()];
|
||||
return ["weight", pokemon?.getWeight().toString() ?? ""];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,14 +24,41 @@ export interface EncounterStartOfBattleEffect {
|
|||
followUp?: boolean;
|
||||
}
|
||||
|
||||
interface IMysteryEncounter {
|
||||
meetsRequirements(scene: BattleScene): boolean;
|
||||
pokemonMeetsPrimaryRequirements(scene: BattleScene, pokemon: Pokemon): boolean;
|
||||
initIntroVisuals(scene: BattleScene): void;
|
||||
populateDialogueTokensFromRequirements(scene: BattleScene): void;
|
||||
setDialogueToken(key: string, value: string): void;
|
||||
getSeedOffset(): number;
|
||||
updateSeedOffset(scene: BattleScene): void;
|
||||
/**
|
||||
* Used by {@link MysteryEncounterBuilder} class to define required/optional properties on the {@link MysteryEncounter} class when building.
|
||||
*
|
||||
* Should ONLY contain properties that are necessary for {@link MysteryEncounter} construction.
|
||||
* Post-construct and flag data properties are defined in the {@link MysteryEncounter} class itself.
|
||||
*/
|
||||
export interface IMysteryEncounter {
|
||||
encounterType: MysteryEncounterType;
|
||||
options: [MysteryEncounterOption, MysteryEncounterOption, ...MysteryEncounterOption[]];
|
||||
spriteConfigs: MysteryEncounterSpriteConfig[];
|
||||
encounterTier: MysteryEncounterTier;
|
||||
encounterAnimations?: EncounterAnim[];
|
||||
hideBattleIntroMessage: boolean;
|
||||
autoHideIntroVisuals: boolean;
|
||||
enterIntroVisualsFromRight: boolean;
|
||||
catchAllowed: boolean;
|
||||
continuousEncounter: boolean;
|
||||
maxAllowedEncounters: number;
|
||||
|
||||
onInit?: (scene: BattleScene) => boolean;
|
||||
onVisualsStart?: (scene: BattleScene) => boolean;
|
||||
doEncounterExp?: (scene: BattleScene) => boolean;
|
||||
doEncounterRewards?: (scene: BattleScene) => boolean;
|
||||
doContinueEncounter?: (scene: BattleScene) => Promise<void>;
|
||||
|
||||
requirements: EncounterSceneRequirement[];
|
||||
primaryPokemonRequirements: EncounterPokemonRequirement[];
|
||||
secondaryPokemonRequirements: EncounterPokemonRequirement[];
|
||||
excludePrimaryFromSupportRequirements: boolean;
|
||||
|
||||
dialogue: MysteryEncounterDialogue;
|
||||
enemyPartyConfigs: EnemyPartyConfig[];
|
||||
|
||||
dialogueTokens: Record<string, string>;
|
||||
expMultiplier: number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,7 +174,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||
* Can be set for uses programatic dialogue during an encounter (storing the name of one of the party's pokemon, etc.)
|
||||
* Example use: see MYSTERIOUS_CHEST
|
||||
*/
|
||||
dialogueTokens: Map<string, string>;
|
||||
dialogueTokens: Record<string, string>;
|
||||
/**
|
||||
* Should be set depending upon option selected as part of an encounter
|
||||
* For example, if there is no battle as part of the encounter/selected option, should be set to NO_BATTLE
|
||||
|
@ -171,7 +198,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||
/**
|
||||
* Will be set by option select handlers automatically, and can be used to refer to which option was chosen by later phases
|
||||
*/
|
||||
startOfBattleEffects?: EncounterStartOfBattleEffect[];
|
||||
startOfBattleEffects: EncounterStartOfBattleEffect[] = [];
|
||||
/**
|
||||
* Can be set higher or lower based on the type of battle or exp gained for an option/encounter
|
||||
* Defaults to 1
|
||||
|
@ -188,7 +215,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||
*/
|
||||
private seedOffset?: any;
|
||||
|
||||
constructor(encounter: MysteryEncounter | null) {
|
||||
constructor(encounter: IMysteryEncounter | null) {
|
||||
if (!isNullOrUndefined(encounter)) {
|
||||
Object.assign(this, encounter);
|
||||
}
|
||||
|
@ -207,9 +234,9 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||
// Reset any dirty flags or encounter data
|
||||
this.startOfBattleEffectsComplete = false;
|
||||
this.lockEncounterRewardTiers = true;
|
||||
this.dialogueTokens = new Map<string, string>();
|
||||
this.dialogueTokens = {};
|
||||
this.enemyPartyConfigs = [];
|
||||
this.startOfBattleEffects = [];
|
||||
// this.startOfBattleEffects = [];
|
||||
this.introVisuals = undefined;
|
||||
this.misc = null;
|
||||
this.expMultiplier = 1;
|
||||
|
@ -361,7 +388,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||
const opt = this.options[i];
|
||||
opt.meetsRequirements(scene);
|
||||
const j = i + 1;
|
||||
if (opt.requirements?.length > 0) {
|
||||
if (opt.requirements.length > 0) {
|
||||
for (const req of opt.requirements) {
|
||||
const dialogueToken = req.getDialogueToken(scene);
|
||||
if (dialogueToken?.length === 2) {
|
||||
|
@ -369,7 +396,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (opt.primaryPokemonRequirements?.length > 0 && opt.primaryPokemon && opt.primaryPokemon.length > 0) {
|
||||
if (opt.primaryPokemonRequirements.length > 0 && opt.primaryPokemon) {
|
||||
this.setDialogueToken("option" + j + "PrimaryName", opt.primaryPokemon.getNameToRender());
|
||||
for (const req of opt.primaryPokemonRequirements) {
|
||||
if (!req.invertQuery) {
|
||||
|
@ -424,26 +451,16 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||
* Builder class for creating a MysteryEncounter
|
||||
* must call `build()` at the end after specifying all params for the MysteryEncounter
|
||||
*/
|
||||
export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
||||
encounterType: MysteryEncounterType;
|
||||
encounterMode: MysteryEncounterMode;
|
||||
options: [MysteryEncounterOption, MysteryEncounterOption, ...MysteryEncounterOption[]] = [new MysteryEncounterOption(null), new MysteryEncounterOption(null)];
|
||||
spriteConfigs: MysteryEncounterSpriteConfig[];
|
||||
export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
options: [MysteryEncounterOption, MysteryEncounterOption, ...MysteryEncounterOption[]];
|
||||
enemyPartyConfigs: EnemyPartyConfig[] = [];
|
||||
|
||||
dialogue: MysteryEncounterDialogue = {};
|
||||
encounterTier: MysteryEncounterTier;
|
||||
encounterAnimations: EncounterAnim[];
|
||||
requirements: EncounterSceneRequirement[] = [];
|
||||
primaryPokemonRequirements: EncounterPokemonRequirement[] = [];
|
||||
secondaryPokemonRequirements: EncounterPokemonRequirement[] = [];
|
||||
excludePrimaryFromSupportRequirements: boolean;
|
||||
dialogueTokens: Map<string, string> = new Map<string, string>();
|
||||
|
||||
doEncounterExp?: (scene: BattleScene) => boolean;
|
||||
doEncounterRewards?: (scene: BattleScene) => boolean;
|
||||
onInit?: (scene: BattleScene) => boolean;
|
||||
onVisualsStart?: (scene: BattleScene) => boolean;
|
||||
excludePrimaryFromSupportRequirements: boolean = true;
|
||||
dialogueTokens: Record<string, string> = {};
|
||||
|
||||
hideBattleIntroMessage: boolean = false;
|
||||
autoHideIntroVisuals: boolean = true;
|
||||
|
@ -455,21 +472,6 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
maxAllowedEncounters: number = 3;
|
||||
expMultiplier: number = 1;
|
||||
|
||||
/**
|
||||
* Builder class has to re-declare the {@link MysteryEncounter} class functions so
|
||||
* the compiler does not yell about user not defining a non-optional property
|
||||
*/
|
||||
|
||||
meetsRequirements = MysteryEncounter.prototype["meetsRequirements"];
|
||||
pokemonMeetsPrimaryRequirements = MysteryEncounter.prototype["pokemonMeetsPrimaryRequirements"];
|
||||
initIntroVisuals = MysteryEncounter.prototype["initIntroVisuals"];
|
||||
populateDialogueTokensFromRequirements = MysteryEncounter.prototype["populateDialogueTokensFromRequirements"];
|
||||
setDialogueToken = MysteryEncounter.prototype["setDialogueToken"];
|
||||
getSeedOffset = MysteryEncounter.prototype["getSeedOffset"];
|
||||
updateSeedOffset = MysteryEncounter.prototype["updateSeedOffset"];
|
||||
meetsPrimaryRequirementAndPrimaryPokemonSelected = MysteryEncounter.prototype["meetsPrimaryRequirementAndPrimaryPokemonSelected"];
|
||||
meetsSecondaryRequirementAndSecondaryPokemonSelected = MysteryEncounter.prototype["meetsSecondaryRequirementAndSecondaryPokemonSelected"];
|
||||
|
||||
/**
|
||||
* REQUIRED
|
||||
*/
|
||||
|
@ -480,7 +482,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param encounterType
|
||||
* @returns this
|
||||
*/
|
||||
static withEncounterType(encounterType: MysteryEncounterType): MysteryEncounterBuilder & Pick<MysteryEncounter, "encounterType"> {
|
||||
static withEncounterType(encounterType: MysteryEncounterType): MysteryEncounterBuilder & Pick<IMysteryEncounter, "encounterType"> {
|
||||
return Object.assign(new MysteryEncounterBuilder(), { encounterType });
|
||||
}
|
||||
|
||||
|
@ -492,14 +494,13 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param option - MysteryEncounterOption to add, can use MysteryEncounterOptionBuilder to create instance
|
||||
* @returns
|
||||
*/
|
||||
withOption(option: MysteryEncounterOption): this & Pick<MysteryEncounter, "options"> {
|
||||
if (this.options[0] === null) {
|
||||
return Object.assign(this, { options: [option, this.options[0]] });
|
||||
} else if (this.options[1] === null) {
|
||||
return Object.assign(this, { options: [this.options[0], option] });
|
||||
withOption(option: MysteryEncounterOption): this & Pick<IMysteryEncounter, "options"> {
|
||||
if (!this.options) {
|
||||
const options = [option];
|
||||
return Object.assign(this, { options });
|
||||
} else {
|
||||
this.options.push(option);
|
||||
return Object.assign(this, { options: this.options });
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -514,7 +515,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param callback - {@linkcode OptionPhaseCallback}
|
||||
* @returns
|
||||
*/
|
||||
withSimpleOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback): this & Pick<MysteryEncounter, "options"> {
|
||||
withSimpleOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback): this & Pick<IMysteryEncounter, "options"> {
|
||||
return this.withOption(MysteryEncounterOptionBuilder.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT).withDialogue(dialogue).withOptionPhase(callback).build());
|
||||
}
|
||||
|
||||
|
@ -528,7 +529,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param callback - {@linkcode OptionPhaseCallback}
|
||||
* @returns
|
||||
*/
|
||||
withSimpleDexProgressOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback): this & Pick<MysteryEncounter, "options"> {
|
||||
withSimpleDexProgressOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback): this & Pick<IMysteryEncounter, "options"> {
|
||||
return this.withOption(MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withHasDexProgress(true)
|
||||
|
@ -542,7 +543,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param spriteConfigs
|
||||
* @returns
|
||||
*/
|
||||
withIntroSpriteConfigs(spriteConfigs: MysteryEncounterSpriteConfig[]): this & Pick<MysteryEncounter, "spriteConfigs"> {
|
||||
withIntroSpriteConfigs(spriteConfigs: MysteryEncounterSpriteConfig[]): this & Pick<IMysteryEncounter, "spriteConfigs"> {
|
||||
return Object.assign(this, { spriteConfigs: spriteConfigs });
|
||||
}
|
||||
|
||||
|
@ -571,7 +572,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param encounterTier
|
||||
* @returns
|
||||
*/
|
||||
withEncounterTier(encounterTier: MysteryEncounterTier): this & Pick<MysteryEncounter, "encounterTier"> {
|
||||
withEncounterTier(encounterTier: MysteryEncounterTier): this & Pick<IMysteryEncounter, "encounterTier"> {
|
||||
return Object.assign(this, { encounterTier: encounterTier });
|
||||
}
|
||||
|
||||
|
@ -582,7 +583,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param encounterAnimations
|
||||
* @returns
|
||||
*/
|
||||
withAnimations(...encounterAnimations: EncounterAnim[]): this & Required<Pick<MysteryEncounter, "encounterAnimations">> {
|
||||
withAnimations(...encounterAnimations: EncounterAnim[]): this & Required<Pick<IMysteryEncounter, "encounterAnimations">> {
|
||||
const animations = Array.isArray(encounterAnimations) ? encounterAnimations : [encounterAnimations];
|
||||
return Object.assign(this, { encounterAnimations: animations });
|
||||
}
|
||||
|
@ -593,7 +594,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* Default false
|
||||
* @param continuousEncounter
|
||||
*/
|
||||
withContinuousEncounter(continuousEncounter: boolean): this & Required<Pick<MysteryEncounter, "continuousEncounter">> {
|
||||
withContinuousEncounter(continuousEncounter: boolean): this & Required<Pick<IMysteryEncounter, "continuousEncounter">> {
|
||||
return Object.assign(this, { continuousEncounter: continuousEncounter });
|
||||
}
|
||||
|
||||
|
@ -602,7 +603,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param maxAllowedEncounters
|
||||
* @returns
|
||||
*/
|
||||
withMaxAllowedEncounters(maxAllowedEncounters: number): this & Required<Pick<MysteryEncounter, "maxAllowedEncounters">> {
|
||||
withMaxAllowedEncounters(maxAllowedEncounters: number): this & Required<Pick<IMysteryEncounter, "maxAllowedEncounters">> {
|
||||
return Object.assign(this, { maxAllowedEncounters: maxAllowedEncounters });
|
||||
}
|
||||
|
||||
|
@ -613,12 +614,12 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param requirement
|
||||
* @returns
|
||||
*/
|
||||
withSceneRequirement(requirement: EncounterSceneRequirement): this & Required<Pick<MysteryEncounter, "requirements">> {
|
||||
withSceneRequirement(requirement: EncounterSceneRequirement): this & Required<Pick<IMysteryEncounter, "requirements">> {
|
||||
if (requirement instanceof EncounterPokemonRequirement) {
|
||||
Error("Incorrectly added pokemon requirement as scene requirement.");
|
||||
}
|
||||
this.requirements.push(requirement);
|
||||
return Object.assign(this, { requirements: this.requirements });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -628,7 +629,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param max optional max wave. If not given, defaults to min => exact wave
|
||||
* @returns
|
||||
*/
|
||||
withSceneWaveRangeRequirement(min: number, max?: number): this & Required<Pick<MysteryEncounter, "requirements">> {
|
||||
withSceneWaveRangeRequirement(min: number, max?: number): this & Required<Pick<IMysteryEncounter, "requirements">> {
|
||||
return this.withSceneRequirement(new WaveRangeRequirement([min, max ?? min]));
|
||||
}
|
||||
|
||||
|
@ -640,7 +641,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param excludeFainted - if true, only counts unfainted mons
|
||||
* @returns
|
||||
*/
|
||||
withScenePartySizeRequirement(min: number, max?: number, excludeFainted: boolean = false): this & Required<Pick<MysteryEncounter, "requirements">> {
|
||||
withScenePartySizeRequirement(min: number, max?: number, excludeFainted: boolean = false): this & Required<Pick<IMysteryEncounter, "requirements">> {
|
||||
return this.withSceneRequirement(new PartySizeRequirement([min, max ?? min], excludeFainted));
|
||||
}
|
||||
|
||||
|
@ -650,7 +651,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param requirement {@linkcode EncounterPokemonRequirement}
|
||||
* @returns
|
||||
*/
|
||||
withPrimaryPokemonRequirement(requirement: EncounterPokemonRequirement): this & Required<Pick<MysteryEncounter, "primaryPokemonRequirements">> {
|
||||
withPrimaryPokemonRequirement(requirement: EncounterPokemonRequirement): this & Required<Pick<IMysteryEncounter, "primaryPokemonRequirements">> {
|
||||
if (requirement instanceof EncounterSceneRequirement) {
|
||||
Error("Incorrectly added scene requirement as pokemon requirement.");
|
||||
}
|
||||
|
@ -667,7 +668,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param invertQuery if true will invert the query
|
||||
* @returns
|
||||
*/
|
||||
withPrimaryPokemonStatusEffectRequirement(statusEffect: StatusEffect | StatusEffect[], minNumberOfPokemon: number = 1, invertQuery: boolean = false): this & Required<Pick<MysteryEncounter, "primaryPokemonRequirements">> {
|
||||
withPrimaryPokemonStatusEffectRequirement(statusEffect: StatusEffect | StatusEffect[], minNumberOfPokemon: number = 1, invertQuery: boolean = false): this & Required<Pick<IMysteryEncounter, "primaryPokemonRequirements">> {
|
||||
return this.withPrimaryPokemonRequirement(new StatusEffectRequirement(statusEffect, minNumberOfPokemon, invertQuery));
|
||||
}
|
||||
|
||||
|
@ -679,14 +680,14 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param invertQuery if true will invert the query
|
||||
* @returns
|
||||
*/
|
||||
withPrimaryPokemonHealthRatioRequirement(requiredHealthRange: [number, number], minNumberOfPokemon: number = 1, invertQuery: boolean = false): this & Required<Pick<MysteryEncounter, "primaryPokemonRequirements">> {
|
||||
withPrimaryPokemonHealthRatioRequirement(requiredHealthRange: [number, number], minNumberOfPokemon: number = 1, invertQuery: boolean = false): this & Required<Pick<IMysteryEncounter, "primaryPokemonRequirements">> {
|
||||
return this.withPrimaryPokemonRequirement(new HealthRatioRequirement(requiredHealthRange, minNumberOfPokemon, invertQuery));
|
||||
}
|
||||
|
||||
// TODO: Maybe add an optional parameter for excluding primary pokemon from the support cast?
|
||||
// ex. if your only grass type pokemon, a snivy, is chosen as primary, if the support pokemon requires a grass type, the event won't trigger because
|
||||
// it's already been
|
||||
withSecondaryPokemonRequirement(requirement: EncounterPokemonRequirement, excludePrimaryFromSecondaryRequirements: boolean = false): this & Required<Pick<MysteryEncounter, "secondaryPokemonRequirements">> {
|
||||
withSecondaryPokemonRequirement(requirement: EncounterPokemonRequirement, excludePrimaryFromSecondaryRequirements: boolean = false): this & Required<Pick<IMysteryEncounter, "secondaryPokemonRequirements">> {
|
||||
if (requirement instanceof EncounterSceneRequirement) {
|
||||
Error("Incorrectly added scene requirement as pokemon requirement.");
|
||||
}
|
||||
|
@ -706,7 +707,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param doEncounterRewards - synchronous callback function to perform during rewards phase of the encounter
|
||||
* @returns
|
||||
*/
|
||||
withRewards(doEncounterRewards: (scene: BattleScene) => boolean): this & Required<Pick<MysteryEncounter, "doEncounterRewards">> {
|
||||
withRewards(doEncounterRewards: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "doEncounterRewards">> {
|
||||
return Object.assign(this, { doEncounterRewards: doEncounterRewards });
|
||||
}
|
||||
|
||||
|
@ -720,7 +721,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param doEncounterExp - synchronous callback function to perform during rewards phase of the encounter
|
||||
* @returns
|
||||
*/
|
||||
withExp(doEncounterExp: (scene: BattleScene) => boolean): this & Required<Pick<MysteryEncounter, "doEncounterExp">> {
|
||||
withExp(doEncounterExp: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "doEncounterExp">> {
|
||||
return Object.assign(this, { doEncounterExp: doEncounterExp });
|
||||
}
|
||||
|
||||
|
@ -731,8 +732,8 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param onInit - synchronous callback function to perform as soon as the encounter is selected for the next phase
|
||||
* @returns
|
||||
*/
|
||||
withOnInit(onInit: (scene: BattleScene) => boolean): this & Required<Pick<MysteryEncounter, "onInit">> {
|
||||
return Object.assign(this, { onInit: onInit });
|
||||
withOnInit(onInit: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "onInit">> {
|
||||
return Object.assign(this, { onInit });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -741,7 +742,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param onVisualsStart - synchronous callback function to perform as soon as the enemy field finishes sliding in
|
||||
* @returns
|
||||
*/
|
||||
withOnVisualsStart(onVisualsStart: (scene: BattleScene) => boolean): this & Required<Pick<MysteryEncounter, "onVisualsStart">> {
|
||||
withOnVisualsStart(onVisualsStart: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "onVisualsStart">> {
|
||||
return Object.assign(this, { onVisualsStart: onVisualsStart });
|
||||
}
|
||||
|
||||
|
@ -751,7 +752,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param catchAllowed - if true, allows enemy pokemon to be caught during the encounter
|
||||
* @returns
|
||||
*/
|
||||
withCatchAllowed(catchAllowed: boolean): this & Required<Pick<MysteryEncounter, "catchAllowed">> {
|
||||
withCatchAllowed(catchAllowed: boolean): this & Required<Pick<IMysteryEncounter, "catchAllowed">> {
|
||||
return Object.assign(this, { catchAllowed: catchAllowed });
|
||||
}
|
||||
|
||||
|
@ -759,7 +760,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param hideBattleIntroMessage - if true, will not show the trainerAppeared/wildAppeared/bossAppeared message for an encounter
|
||||
* @returns
|
||||
*/
|
||||
withHideWildIntroMessage(hideBattleIntroMessage: boolean): this & Required<Pick<MysteryEncounter, "hideBattleIntroMessage">> {
|
||||
withHideWildIntroMessage(hideBattleIntroMessage: boolean): this & Required<Pick<IMysteryEncounter, "hideBattleIntroMessage">> {
|
||||
return Object.assign(this, { hideBattleIntroMessage: hideBattleIntroMessage });
|
||||
}
|
||||
|
||||
|
@ -767,7 +768,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* @param autoHideIntroVisuals - if false, will not hide the intro visuals that are displayed at the beginning of encounter
|
||||
* @returns
|
||||
*/
|
||||
withAutoHideIntroVisuals(autoHideIntroVisuals: boolean): this & Required<Pick<MysteryEncounter, "autoHideIntroVisuals">> {
|
||||
withAutoHideIntroVisuals(autoHideIntroVisuals: boolean): this & Required<Pick<IMysteryEncounter, "autoHideIntroVisuals">> {
|
||||
return Object.assign(this, { autoHideIntroVisuals: autoHideIntroVisuals });
|
||||
}
|
||||
|
||||
|
@ -776,7 +777,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
* Default false
|
||||
* @returns
|
||||
*/
|
||||
withEnterIntroVisualsFromRight(enterIntroVisualsFromRight: boolean): this & Required<Pick<MysteryEncounter, "enterIntroVisualsFromRight">> {
|
||||
withEnterIntroVisualsFromRight(enterIntroVisualsFromRight: boolean): this & Required<Pick<IMysteryEncounter, "enterIntroVisualsFromRight">> {
|
||||
return Object.assign(this, { enterIntroVisualsFromRight: enterIntroVisualsFromRight });
|
||||
}
|
||||
|
||||
|
@ -856,7 +857,7 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
|
|||
*
|
||||
* @returns
|
||||
*/
|
||||
build(this: MysteryEncounter): MysteryEncounter {
|
||||
build(this: IMysteryEncounter): MysteryEncounter {
|
||||
return new MysteryEncounter(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -278,7 +278,7 @@ export function initMysteryEncounters() {
|
|||
extremeBiomeEncounters.forEach(encounter => {
|
||||
EXTREME_ENCOUNTER_BIOMES.forEach(biome => {
|
||||
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
||||
if (!encountersForBiome.includes(encounter)) {
|
||||
if (encountersForBiome && !encountersForBiome.includes(encounter)) {
|
||||
encountersForBiome.push(encounter);
|
||||
}
|
||||
});
|
||||
|
@ -287,7 +287,7 @@ export function initMysteryEncounters() {
|
|||
nonExtremeBiomeEncounters.forEach(encounter => {
|
||||
NON_EXTREME_ENCOUNTER_BIOMES.forEach(biome => {
|
||||
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
||||
if (!encountersForBiome.includes(encounter)) {
|
||||
if (encountersForBiome && !encountersForBiome.includes(encounter)) {
|
||||
encountersForBiome.push(encounter);
|
||||
}
|
||||
});
|
||||
|
@ -296,7 +296,7 @@ export function initMysteryEncounters() {
|
|||
humanTransitableBiomeEncounters.forEach(encounter => {
|
||||
HUMAN_TRANSITABLE_BIOMES.forEach(biome => {
|
||||
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
||||
if (!encountersForBiome.includes(encounter)) {
|
||||
if (encountersForBiome && !encountersForBiome.includes(encounter)) {
|
||||
encountersForBiome.push(encounter);
|
||||
}
|
||||
});
|
||||
|
@ -305,7 +305,7 @@ export function initMysteryEncounters() {
|
|||
civilizationBiomeEncounters.forEach(encounter => {
|
||||
CIVILIZATION_ENCOUNTER_BIOMES.forEach(biome => {
|
||||
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
||||
if (!encountersForBiome.includes(encounter)) {
|
||||
if (encountersForBiome && !encountersForBiome.includes(encounter)) {
|
||||
encountersForBiome.push(encounter);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import BattleScene from "#app/battle-scene";
|
||||
import { Moves } from "#app/enums/moves";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { isNullOrUndefined } from "#app/utils";
|
||||
import { EncounterPokemonRequirement } from "../mystery-encounter-requirements";
|
||||
|
||||
|
@ -37,7 +37,7 @@ export class CanLearnMoveRequirement extends EncounterPokemonRequirement {
|
|||
this.excludeEggMoves = excludeEggMoves ?? false;
|
||||
this.includeFainted = includeFainted ?? false;
|
||||
this.minNumberOfPokemon = minNumberOfPokemon ?? 1;
|
||||
this.invertQuery = invertQuery;
|
||||
this.invertQuery = invertQuery ?? false;
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
|
@ -66,7 +66,7 @@ export class CanLearnMoveRequirement extends EncounterPokemonRequirement {
|
|||
}
|
||||
|
||||
override getDialogueToken(_scene: BattleScene, _pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["requiredMoves", this.requiredMoves.join(", ")];
|
||||
return ["requiredMoves", this.requiredMoves.map(m => new PokemonMove(m).getName()).join(", ")];
|
||||
}
|
||||
|
||||
private getPokemonLevelMoves(pkm: PlayerPokemon): Moves[] {
|
||||
|
|
|
@ -4,34 +4,37 @@ import { UiTheme } from "#enums/ui-theme";
|
|||
import { isNullOrUndefined } from "#app/utils";
|
||||
import i18next from "i18next";
|
||||
|
||||
export function getEncounterText(scene: BattleScene, keyOrString: string, primaryStyle?: TextStyle, uiTheme: UiTheme = UiTheme.DEFAULT): string {
|
||||
export function getEncounterText(scene: BattleScene, keyOrString?: string, primaryStyle?: TextStyle, uiTheme: UiTheme = UiTheme.DEFAULT): string | null {
|
||||
if (isNullOrUndefined(keyOrString)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let textString: string = getTextWithDialogueTokens(scene, keyOrString);
|
||||
let textString: string | null = getTextWithDialogueTokens(scene, keyOrString);
|
||||
|
||||
// Can only color the text if a Primary Style is defined
|
||||
// primaryStyle is applied to all text that does not have its own specified style
|
||||
if (primaryStyle) {
|
||||
if (primaryStyle && textString) {
|
||||
textString = getTextWithColors(textString, primaryStyle, uiTheme);
|
||||
}
|
||||
|
||||
return textString;
|
||||
}
|
||||
|
||||
function getTextWithDialogueTokens(scene: BattleScene, keyOrString: string): string {
|
||||
function getTextWithDialogueTokens(scene: BattleScene, keyOrString?: string): string | null {
|
||||
if (isNullOrUndefined(keyOrString)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (i18next.exists(keyOrString, scene.currentBattle?.mysteryEncounter?.dialogueTokens)) {
|
||||
const tokens = scene.currentBattle?.mysteryEncounter?.dialogueTokens;
|
||||
// @ts-ignore
|
||||
if (i18next.exists(keyOrString, tokens)) {
|
||||
const stringArray = [`${keyOrString}`] as any;
|
||||
stringArray.raw = [`${keyOrString}`];
|
||||
return i18next.t(stringArray, scene.currentBattle?.mysteryEncounter?.dialogueTokens);
|
||||
// @ts-ignore
|
||||
return i18next.t(stringArray, tokens) as string;
|
||||
}
|
||||
|
||||
return keyOrString;
|
||||
return keyOrString ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,8 +43,8 @@ function getTextWithDialogueTokens(scene: BattleScene, keyOrString: string): str
|
|||
* @param contentKey
|
||||
*/
|
||||
export function queueEncounterMessage(scene: BattleScene, contentKey: string): void {
|
||||
const text: string = getEncounterText(scene, contentKey);
|
||||
scene.queueMessage(text, null, true);
|
||||
const text: string | null = getEncounterText(scene, contentKey);
|
||||
scene.queueMessage(text ?? "", null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,8 +56,8 @@ export function queueEncounterMessage(scene: BattleScene, contentKey: string): v
|
|||
*/
|
||||
export function showEncounterText(scene: BattleScene, contentKey: string, callbackDelay: number = 0, prompt: boolean = true): Promise<void> {
|
||||
return new Promise<void>(resolve => {
|
||||
const text: string = getEncounterText(scene, contentKey);
|
||||
scene.ui.showText(text, null, () => resolve(), callbackDelay, prompt);
|
||||
const text: string | null = getEncounterText(scene, contentKey);
|
||||
scene.ui.showText(text ?? "", null, () => resolve(), callbackDelay, prompt);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -67,8 +70,8 @@ export function showEncounterText(scene: BattleScene, contentKey: string, callba
|
|||
*/
|
||||
export function showEncounterDialogue(scene: BattleScene, textContentKey: string, speakerContentKey: string, callbackDelay: number = 0): Promise<void> {
|
||||
return new Promise<void>(resolve => {
|
||||
const text: string = getEncounterText(scene, textContentKey);
|
||||
const speaker: string = getEncounterText(scene, speakerContentKey);
|
||||
scene.ui.showDialogue(text, speaker, null, () => resolve(), callbackDelay);
|
||||
const text: string | null = getEncounterText(scene, textContentKey);
|
||||
const speaker: string | null = getEncounterText(scene, speakerContentKey);
|
||||
scene.ui.showDialogue(text ?? "", speaker ?? "", null, () => resolve(), callbackDelay);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { BattlerIndex, BattleType } from "#app/battle";
|
||||
import Battle, { BattlerIndex, BattleType } from "#app/battle";
|
||||
import { biomeLinks, BiomePoolTier } from "#app/data/biomes";
|
||||
import MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
|
@ -10,7 +10,7 @@ import { BattleEndPhase, EggLapsePhase, ExpPhase, GameOverPhase, MovePhase, Sele
|
|||
import { MysteryEncounterBattlePhase, MysteryEncounterBattleStartCleanupPhase, MysteryEncounterPhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phases";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||
import { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler";
|
||||
import { PartyOption, PartyUiMode, PokemonSelectFilter } from "#app/ui/party-ui-handler";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import * as Utils from "#app/utils";
|
||||
import { isNullOrUndefined } from "#app/utils";
|
||||
|
@ -101,29 +101,30 @@ export interface EnemyPartyConfig {
|
|||
* @param partyConfig - Can pass various customizable attributes for the enemy party, see EnemyPartyConfig
|
||||
*/
|
||||
export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig: EnemyPartyConfig): Promise<void> {
|
||||
const loaded = false;
|
||||
const loadEnemyAssets = [];
|
||||
const loaded: boolean = false;
|
||||
const loadEnemyAssets: Promise<void>[] = [];
|
||||
|
||||
const battle = scene.currentBattle;
|
||||
const battle: Battle = scene.currentBattle;
|
||||
|
||||
let doubleBattle = partyConfig?.doubleBattle;
|
||||
let doubleBattle: boolean = partyConfig?.doubleBattle ?? false;
|
||||
|
||||
// Trainer
|
||||
const trainerType = partyConfig?.trainerType;
|
||||
let trainerConfig = partyConfig?.trainerConfig;
|
||||
if (trainerType || trainerConfig) {
|
||||
const partyTrainerConfig = partyConfig?.trainerConfig;
|
||||
let trainerConfig: TrainerConfig;
|
||||
if (!isNullOrUndefined(trainerType) || partyTrainerConfig) {
|
||||
scene.currentBattle.mysteryEncounter.encounterMode = MysteryEncounterMode.TRAINER_BATTLE;
|
||||
if (scene.currentBattle.trainer) {
|
||||
scene.currentBattle.trainer.setVisible(false);
|
||||
scene.currentBattle.trainer.destroy();
|
||||
}
|
||||
|
||||
trainerConfig = partyConfig?.trainerConfig ? partyConfig?.trainerConfig : trainerConfigs[trainerType];
|
||||
trainerConfig = partyConfig?.trainerConfig ? partyConfig?.trainerConfig : trainerConfigs[trainerType!];
|
||||
|
||||
const doubleTrainer = trainerConfig.doubleOnly || (trainerConfig.hasDouble && partyConfig.doubleBattle);
|
||||
const doubleTrainer = trainerConfig.doubleOnly || (trainerConfig.hasDouble && !!partyConfig.doubleBattle);
|
||||
doubleBattle = doubleTrainer;
|
||||
const trainerFemale = isNullOrUndefined(partyConfig.female) ? !!(Utils.randSeedInt(2)) : partyConfig.female;
|
||||
const newTrainer = new Trainer(scene, trainerConfig.trainerType, doubleTrainer ? TrainerVariant.DOUBLE : trainerFemale ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT, null, null, null, trainerConfig);
|
||||
const newTrainer = new Trainer(scene, trainerConfig.trainerType, doubleTrainer ? TrainerVariant.DOUBLE : trainerFemale ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT, undefined, undefined, undefined, trainerConfig);
|
||||
newTrainer.x += 300;
|
||||
newTrainer.setVisible(false);
|
||||
scene.field.add(newTrainer);
|
||||
|
@ -134,7 +135,8 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
} else {
|
||||
// Wild
|
||||
scene.currentBattle.mysteryEncounter.encounterMode = MysteryEncounterMode.WILD_BATTLE;
|
||||
battle.enemyLevels = new Array(partyConfig?.pokemonConfigs?.length > 0 ? partyConfig?.pokemonConfigs?.length : doubleBattle ? 2 : 1).fill(null).map(() => scene.currentBattle.getLevelForWave());
|
||||
const numEnemies = partyConfig?.pokemonConfigs && partyConfig.pokemonConfigs.length > 0 ? partyConfig?.pokemonConfigs?.length : doubleBattle ? 2 : 1;
|
||||
battle.enemyLevels = new Array(numEnemies).fill(null).map(() => scene.currentBattle.getLevelForWave());
|
||||
}
|
||||
|
||||
scene.getEnemyParty().forEach(enemyPokemon => enemyPokemon.destroy());
|
||||
|
@ -146,7 +148,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
// This can be amplified or counteracted by setting levelAdditiveMultiplier in config
|
||||
// levelAdditiveMultiplier value of 0.5 will halve the modifier scaling, 2 will double it, etc.
|
||||
// Leaving null/undefined will disable level scaling
|
||||
const mult = !isNullOrUndefined(partyConfig.levelAdditiveMultiplier) ? partyConfig.levelAdditiveMultiplier : 0;
|
||||
const mult: number = !isNullOrUndefined(partyConfig.levelAdditiveMultiplier) ? partyConfig.levelAdditiveMultiplier! : 0;
|
||||
const additive = Math.max(Math.round((scene.currentBattle.waveIndex / 10) * mult), 0);
|
||||
battle.enemyLevels = battle.enemyLevels.map(level => level + additive);
|
||||
|
||||
|
@ -155,10 +157,10 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
let dataSource;
|
||||
let isBoss = false;
|
||||
if (!loaded) {
|
||||
if (trainerType || trainerConfig) {
|
||||
if ((!isNullOrUndefined(trainerType) || trainerConfig) && battle.trainer) {
|
||||
// Allows overriding a trainer's pokemon to use specific species/data
|
||||
if (e < partyConfig?.pokemonConfigs?.length) {
|
||||
const config = partyConfig?.pokemonConfigs?.[e];
|
||||
if (partyConfig?.pokemonConfigs && e < partyConfig.pokemonConfigs.length) {
|
||||
const config = partyConfig.pokemonConfigs[e];
|
||||
level = config.level ? config.level : level;
|
||||
dataSource = config.dataSource;
|
||||
enemySpecies = config.species;
|
||||
|
@ -168,8 +170,8 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
battle.enemyParty[e] = battle.trainer.genPartyMember(e);
|
||||
}
|
||||
} else {
|
||||
if (e < partyConfig?.pokemonConfigs?.length) {
|
||||
const config = partyConfig?.pokemonConfigs?.[e];
|
||||
if (partyConfig?.pokemonConfigs && e < partyConfig.pokemonConfigs.length) {
|
||||
const config = partyConfig.pokemonConfigs[e];
|
||||
level = config.level ? config.level : level;
|
||||
dataSource = config.dataSource;
|
||||
enemySpecies = config.species;
|
||||
|
@ -201,8 +203,8 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
scene.gameData.setPokemonSeen(enemyPokemon, true, !!(trainerType || trainerConfig));
|
||||
}
|
||||
|
||||
if (e < partyConfig?.pokemonConfigs?.length) {
|
||||
const config = partyConfig?.pokemonConfigs?.[e];
|
||||
if (partyConfig?.pokemonConfigs && e < partyConfig.pokemonConfigs.length) {
|
||||
const config = partyConfig.pokemonConfigs[e];
|
||||
|
||||
// Generate new id, reset status and HP in case using data source
|
||||
if (config.dataSource) {
|
||||
|
@ -211,24 +213,24 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
|
||||
// Set form
|
||||
if (!isNullOrUndefined(config.formIndex)) {
|
||||
enemyPokemon.formIndex = config.formIndex;
|
||||
enemyPokemon.formIndex = config.formIndex!;
|
||||
}
|
||||
|
||||
// Set shiny
|
||||
if (!isNullOrUndefined(config.shiny)) {
|
||||
enemyPokemon.shiny = config.shiny;
|
||||
enemyPokemon.shiny = config.shiny!;
|
||||
}
|
||||
|
||||
// Set custom mystery encounter data fields (such as sprite scale, custom abilities, types, etc.)
|
||||
if (!isNullOrUndefined(config.mysteryEncounterData)) {
|
||||
enemyPokemon.mysteryEncounterData = config.mysteryEncounterData;
|
||||
enemyPokemon.mysteryEncounterData = config.mysteryEncounterData!;
|
||||
}
|
||||
|
||||
// Set Boss
|
||||
if (config.isBoss) {
|
||||
let segments = !isNullOrUndefined(config.bossSegments) ? config.bossSegments : scene.getEncounterBossSegments(scene.currentBattle.waveIndex, level, enemySpecies, true);
|
||||
let segments = !isNullOrUndefined(config.bossSegments) ? config.bossSegments! : scene.getEncounterBossSegments(scene.currentBattle.waveIndex, level, enemySpecies, true);
|
||||
if (!isNullOrUndefined(config.bossSegmentModifier)) {
|
||||
segments += config.bossSegmentModifier;
|
||||
segments += config.bossSegmentModifier!;
|
||||
}
|
||||
enemyPokemon.setBoss(true, segments);
|
||||
}
|
||||
|
@ -253,7 +255,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
if (statusEffects) {
|
||||
// Default to cureturn 3 for sleep
|
||||
const status = Array.isArray(statusEffects) ? statusEffects[0] : statusEffects;
|
||||
const cureTurn = Array.isArray(statusEffects) ? statusEffects[1] : statusEffects === StatusEffect.SLEEP ? 3 : null;
|
||||
const cureTurn = Array.isArray(statusEffects) ? statusEffects[1] : statusEffects === StatusEffect.SLEEP ? 3 : undefined;
|
||||
enemyPokemon.status = new Status(status, 0, cureTurn);
|
||||
}
|
||||
|
||||
|
@ -264,24 +266,24 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
|
||||
// Set ability
|
||||
if (!isNullOrUndefined(config.abilityIndex)) {
|
||||
enemyPokemon.abilityIndex = config.abilityIndex;
|
||||
enemyPokemon.abilityIndex = config.abilityIndex!;
|
||||
}
|
||||
|
||||
// Set gender
|
||||
if (!isNullOrUndefined(config.gender)) {
|
||||
enemyPokemon.gender = config.gender;
|
||||
enemyPokemon.summonData.gender = config.gender;
|
||||
enemyPokemon.gender = config.gender!;
|
||||
enemyPokemon.summonData.gender = config.gender!;
|
||||
}
|
||||
|
||||
// Set moves
|
||||
if (config?.moveSet?.length > 0) {
|
||||
if (config?.moveSet && config.moveSet.length > 0) {
|
||||
const moves = config.moveSet.map(m => new PokemonMove(m));
|
||||
enemyPokemon.moveset = moves;
|
||||
enemyPokemon.summonData.moveset = moves;
|
||||
}
|
||||
|
||||
// Set tags
|
||||
if (config.tags?.length > 0) {
|
||||
if (config.tags && config.tags.length > 0) {
|
||||
const tags = config.tags;
|
||||
tags.forEach(tag => enemyPokemon.addTag(tag));
|
||||
}
|
||||
|
@ -319,8 +321,12 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
});
|
||||
if (!loaded) {
|
||||
regenerateModifierPoolThresholds(scene.getEnemyField(), battle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD);
|
||||
const customModifierTypes = partyConfig?.pokemonConfigs?.map(config => config?.modifierConfigs);
|
||||
scene.generateEnemyModifiers(customModifierTypes);
|
||||
const customModifierTypes = partyConfig?.pokemonConfigs
|
||||
?.filter(config => config?.modifierConfigs)
|
||||
.map(config => config.modifierConfigs!);
|
||||
if (customModifierTypes) {
|
||||
scene.generateEnemyModifiers(customModifierTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,7 +374,7 @@ export function updatePlayerMoney(scene: BattleScene, changeValue: number, playS
|
|||
* @param pregenArgs - can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc.
|
||||
*/
|
||||
export function generateModifierType(scene: BattleScene, modifier: () => ModifierType, pregenArgs?: any[]): ModifierType {
|
||||
const modifierId = Object.keys(modifierTypes).find(k => modifierTypes[k] === modifier);
|
||||
const modifierId = Object.keys(modifierTypes).find(k => modifierTypes[k] === modifier)!;
|
||||
let result: ModifierType = modifierTypes[modifierId]?.();
|
||||
|
||||
// Populates item id and tier (order matters)
|
||||
|
@ -376,8 +382,8 @@ export function generateModifierType(scene: BattleScene, modifier: () => Modifie
|
|||
.withIdFromFunc(modifierTypes[modifierId])
|
||||
.withTierFromPool();
|
||||
|
||||
result = result instanceof ModifierTypeGenerator ? result.generateType(scene.getParty(), pregenArgs) : result;
|
||||
return result;
|
||||
const generatedResult = result instanceof ModifierTypeGenerator ? result.generateType(scene.getParty(), pregenArgs) : result;
|
||||
return generatedResult ?? result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -399,7 +405,7 @@ export function generateModifierTypeOption(scene: BattleScene, modifier: () => M
|
|||
* @param onPokemonNotSelected - Any logic that needs to be performed if no Pokemon is chosen
|
||||
* @param selectablePokemonFilter
|
||||
*/
|
||||
export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (pokemon: PlayerPokemon) => void | OptionSelectItem[], onPokemonNotSelected?: () => void, selectablePokemonFilter?: (pokemon: PlayerPokemon) => string): Promise<boolean> {
|
||||
export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (pokemon: PlayerPokemon) => void | OptionSelectItem[], onPokemonNotSelected?: () => void, selectablePokemonFilter?: PokemonSelectFilter): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
const modeToSetOnExit = scene.ui.getMode();
|
||||
|
||||
|
@ -451,7 +457,7 @@ export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (p
|
|||
scene.ui.setModeWithoutClear(Mode.OPTION_SELECT, config, null, true);
|
||||
};
|
||||
|
||||
const textPromptKey = scene.currentBattle.mysteryEncounter.selectedOption.dialogue.secondOptionPrompt;
|
||||
const textPromptKey = scene.currentBattle.mysteryEncounter?.selectedOption?.dialogue?.secondOptionPrompt;
|
||||
if (!textPromptKey) {
|
||||
displayOptions();
|
||||
} else {
|
||||
|
@ -486,7 +492,7 @@ export function setEncounterRewards(scene: BattleScene, customShopRewards?: Cust
|
|||
}
|
||||
|
||||
if (customShopRewards) {
|
||||
scene.unshiftPhase(new SelectModifierPhase(scene, 0, null, customShopRewards));
|
||||
scene.unshiftPhase(new SelectModifierPhase(scene, 0, undefined, customShopRewards));
|
||||
} else {
|
||||
scene.tryRemovePhase(p => p instanceof SelectModifierPhase);
|
||||
}
|
||||
|
@ -530,7 +536,7 @@ export function setEncounterExp(scene: BattleScene, participantId: integer | int
|
|||
const multipleParticipantExpBonusModifier = scene.findModifier(m => m instanceof MultipleParticipantExpBonusModifier) as MultipleParticipantExpBonusModifier;
|
||||
const nonFaintedPartyMembers = party.filter(p => p.hp);
|
||||
const expPartyMembers = nonFaintedPartyMembers.filter(p => p.level < scene.getMaxExpLevel());
|
||||
const partyMemberExp = [];
|
||||
const partyMemberExp: number[] = [];
|
||||
// EXP value calculation is based off Pokemon.getExpValue
|
||||
let expValue = Math.floor(baseExpValue * (useWaveIndex ? scene.currentBattle.waveIndex : 1) / 5 + 1);
|
||||
|
||||
|
@ -581,7 +587,7 @@ export function setEncounterExp(scene: BattleScene, participantId: integer | int
|
|||
|
||||
const medianLevel = Math.floor(totalLevel / expPartyMembers.length);
|
||||
|
||||
const recipientExpPartyMemberIndexes = [];
|
||||
const recipientExpPartyMemberIndexes: number[] = [];
|
||||
expPartyMembers.forEach((expPartyMember, epm) => {
|
||||
if (expPartyMember.level <= medianLevel) {
|
||||
recipientExpPartyMemberIndexes.push(epm);
|
||||
|
@ -720,7 +726,7 @@ export function transitionMysteryEncounterIntroVisuals(scene: BattleScene, hide:
|
|||
scene.field.remove(pokemon, true);
|
||||
});
|
||||
|
||||
scene.currentBattle.mysteryEncounter.introVisuals = null;
|
||||
scene.currentBattle.mysteryEncounter.introVisuals = undefined;
|
||||
}
|
||||
resolve(true);
|
||||
}
|
||||
|
@ -808,11 +814,13 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
|
|||
})
|
||||
.map(b => !Array.isArray(b) ? b : b[0]);
|
||||
}, i * 100);
|
||||
const specialBiomes = biomes.filter(b => alwaysPickTheseBiomes.includes(b));
|
||||
if (specialBiomes.length > 0) {
|
||||
currentBiome = specialBiomes[Utils.randSeedInt(specialBiomes.length)];
|
||||
} else {
|
||||
currentBiome = biomes[Utils.randSeedInt(biomes.length)];
|
||||
if (biomes! && biomes.length > 0) {
|
||||
const specialBiomes = biomes.filter(b => alwaysPickTheseBiomes.includes(b));
|
||||
if (specialBiomes.length > 0) {
|
||||
currentBiome = specialBiomes[Utils.randSeedInt(specialBiomes.length)];
|
||||
} else {
|
||||
currentBiome = biomes[Utils.randSeedInt(biomes.length)];
|
||||
}
|
||||
}
|
||||
} else if (biomeLinks.hasOwnProperty(currentBiome)) {
|
||||
currentBiome = (biomeLinks[currentBiome] as Biome);
|
||||
|
@ -840,7 +848,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
|
|||
// Otherwise, roll encounter
|
||||
|
||||
const roll = Utils.randSeedInt(256);
|
||||
validMEfloorsByBiome.set(Biome[currentBiome], validMEfloorsByBiome.get(Biome[currentBiome]) + 1);
|
||||
validMEfloorsByBiome.set(Biome[currentBiome], (validMEfloorsByBiome.get(Biome[currentBiome]) ?? 0) + 1);
|
||||
|
||||
// If total number of encounters is lower than expected for the run, slightly favor a new encounter
|
||||
// Do the reverse as well
|
||||
|
@ -866,7 +874,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
|
|||
const rareThreshold = totalWeight - tierWeights[0] - tierWeights[1] - tierWeights[2]; // 64 - 32 - 16 - 10 = 6
|
||||
|
||||
tierValue > commonThreshold ? ++numEncounters[0] : tierValue > uncommonThreshold ? ++numEncounters[1] : tierValue > rareThreshold ? ++numEncounters[2] : ++numEncounters[3];
|
||||
encountersByBiome.set(Biome[currentBiome], encountersByBiome.get(Biome[currentBiome]) + 1);
|
||||
encountersByBiome.set(Biome[currentBiome], (encountersByBiome.get(Biome[currentBiome]) ?? 0) + 1);
|
||||
} else {
|
||||
encounterRate += WEIGHT_INCREMENT_ON_SPAWN_MISS;
|
||||
}
|
||||
|
@ -899,7 +907,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
|
|||
|
||||
const encountersPerRunPerBiome = encountersByBiomeRuns.reduce((a, b) => {
|
||||
for (const biome of a.keys()) {
|
||||
a.set(biome, a.get(biome) + b.get(biome));
|
||||
a.set(biome, a.get(biome)! + b.get(biome)!);
|
||||
}
|
||||
return a;
|
||||
});
|
||||
|
@ -910,7 +918,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
|
|||
|
||||
const validMEFloorsPerRunPerBiome = validFloorsByBiome.reduce((a, b) => {
|
||||
for (const biome of a.keys()) {
|
||||
a.set(biome, a.get(biome) + b.get(biome));
|
||||
a.set(biome, a.get(biome)! + b.get(biome)!);
|
||||
}
|
||||
return a;
|
||||
});
|
||||
|
|
|
@ -52,13 +52,13 @@ export function getRandomPlayerPokemon(scene: BattleScene, isAllowedInBattle: bo
|
|||
|
||||
if (doNotReturnLastAbleMon && unfaintedMons.length === 1) {
|
||||
chosenIndex = randSeedInt(faintedMons.length);
|
||||
chosenPokemon = faintedMons.at(chosenIndex);
|
||||
chosenPokemon = faintedMons[chosenIndex];
|
||||
} else if (isAllowedInBattle) {
|
||||
chosenIndex = randSeedInt(unfaintedMons.length);
|
||||
chosenPokemon = unfaintedMons.at(chosenIndex);
|
||||
chosenPokemon = unfaintedMons[chosenIndex];
|
||||
} else {
|
||||
chosenIndex = randSeedInt(party.length);
|
||||
chosenPokemon = party.at(chosenIndex);
|
||||
chosenPokemon = party[chosenIndex];
|
||||
}
|
||||
|
||||
return chosenPokemon;
|
||||
|
@ -72,17 +72,17 @@ export function getRandomPlayerPokemon(scene: BattleScene, isAllowedInBattle: bo
|
|||
*/
|
||||
export function getHighestLevelPlayerPokemon(scene: BattleScene, unfainted: boolean = false): PlayerPokemon {
|
||||
const party = scene.getParty();
|
||||
let pokemon: PlayerPokemon;
|
||||
party.every(p => {
|
||||
let pokemon: PlayerPokemon | null = null;
|
||||
|
||||
for (const p of party) {
|
||||
if (unfainted && p.isFainted()) {
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
pokemon = pokemon ? pokemon?.level < p?.level ? p : pokemon : p;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return pokemon;
|
||||
return pokemon!;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,17 +94,17 @@ export function getHighestLevelPlayerPokemon(scene: BattleScene, unfainted: bool
|
|||
*/
|
||||
export function getHighestStatPlayerPokemon(scene: BattleScene, stat: Stat, unfainted: boolean = false): PlayerPokemon {
|
||||
const party = scene.getParty();
|
||||
let pokemon: PlayerPokemon;
|
||||
party.every(p => {
|
||||
let pokemon: PlayerPokemon | null = null;
|
||||
|
||||
for (const p of party) {
|
||||
if (unfainted && p.isFainted()) {
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
pokemon = pokemon ? pokemon.getStat(stat) < p?.getStat(stat) ? p : pokemon : p;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return pokemon;
|
||||
return pokemon!;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,17 +115,17 @@ export function getHighestStatPlayerPokemon(scene: BattleScene, stat: Stat, unfa
|
|||
*/
|
||||
export function getLowestLevelPlayerPokemon(scene: BattleScene, unfainted: boolean = false): PlayerPokemon {
|
||||
const party = scene.getParty();
|
||||
let pokemon: PlayerPokemon;
|
||||
party.every(p => {
|
||||
let pokemon: PlayerPokemon | null = null;
|
||||
|
||||
for (const p of party) {
|
||||
if (unfainted && p.isFainted()) {
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
pokemon = pokemon ? pokemon?.level > p?.level ? p : pokemon : p;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return pokemon;
|
||||
return pokemon!;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,17 +136,17 @@ export function getLowestLevelPlayerPokemon(scene: BattleScene, unfainted: boole
|
|||
*/
|
||||
export function getHighestStatTotalPlayerPokemon(scene: BattleScene, unfainted: boolean = false): PlayerPokemon {
|
||||
const party = scene.getParty();
|
||||
let pokemon: PlayerPokemon;
|
||||
party.every(p => {
|
||||
let pokemon: PlayerPokemon | null = null;
|
||||
|
||||
for (const p of party) {
|
||||
if (unfainted && p.isFainted()) {
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
pokemon = pokemon ? pokemon?.stats.reduce((a, b) => a + b) < p?.stats.reduce((a, b) => a + b) ? p : pokemon : p;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return pokemon;
|
||||
return pokemon!;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -166,8 +166,8 @@ export function getRandomSpeciesByStarterTier(starterTiers: number | [number, nu
|
|||
.filter(s => getPokemonSpecies(s[0]) && (!excludedSpecies || !excludedSpecies.includes(s[0])))
|
||||
.map(s => [getPokemonSpecies(s[0]), s[1]]);
|
||||
|
||||
if (!isNullOrUndefined(types) && types.length > 0) {
|
||||
filteredSpecies = filteredSpecies.filter(s => types.includes(s[0].type1) || types.includes(s[0].type2));
|
||||
if (types && types.length > 0) {
|
||||
filteredSpecies = filteredSpecies.filter(s => types.includes(s[0].type1) || (!isNullOrUndefined(s[0].type2) && types.includes(s[0].type2!)));
|
||||
}
|
||||
|
||||
// If no filtered mons exist at specified starter tiers, will expand starter search range until there are
|
||||
|
@ -260,10 +260,12 @@ export function applyHealToPokemon(scene: BattleScene, pokemon: PlayerPokemon, h
|
|||
* @param value
|
||||
*/
|
||||
export async function modifyPlayerPokemonBST(pokemon: PlayerPokemon, value: number) {
|
||||
const modType = modifierTypes.MYSTERY_ENCOUNTER_SHUCKLE_JUICE().generateType(null, [value]);
|
||||
const modifier = modType.newModifier(pokemon);
|
||||
await pokemon.scene.addModifier(modifier, false, false, false, true);
|
||||
pokemon.calculateStats();
|
||||
const modType = modifierTypes.MYSTERY_ENCOUNTER_SHUCKLE_JUICE().generateType(pokemon.scene.getParty(), [value]);
|
||||
const modifier = modType?.newModifier(pokemon);
|
||||
if (modifier) {
|
||||
await pokemon.scene.addModifier(modifier, false, false, false, true);
|
||||
pokemon.calculateStats();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -479,7 +481,7 @@ function failCatch(scene: BattleScene, pokemon: EnemyPokemon, originalY: number,
|
|||
* @param showCatchObtainMessage
|
||||
* @param isObtain
|
||||
*/
|
||||
export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, pokeball: Phaser.GameObjects.Sprite, pokeballType: PokeballType, showCatchObtainMessage: boolean = true, isObtain: boolean = false): Promise<void> {
|
||||
export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, pokeball: Phaser.GameObjects.Sprite | null, pokeballType: PokeballType, showCatchObtainMessage: boolean = true, isObtain: boolean = false): Promise<void> {
|
||||
scene.unshiftPhase(new VictoryPhase(scene, BattlerIndex.ENEMY, true));
|
||||
|
||||
const speciesForm = !pokemon.fusionSpecies ? pokemon.getSpeciesForm() : pokemon.getFusionSpeciesForm();
|
||||
|
@ -508,7 +510,9 @@ export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, po
|
|||
const doPokemonCatchMenu = () => {
|
||||
const end = () => {
|
||||
scene.pokemonInfoContainer.hide();
|
||||
removePb(scene, pokeball);
|
||||
if (pokeball) {
|
||||
removePb(scene, pokeball);
|
||||
}
|
||||
resolve();
|
||||
};
|
||||
const removePokemon = () => {
|
||||
|
|
|
@ -146,7 +146,7 @@ export class Arena {
|
|||
return this.randomSpecies(waveIndex, level, (attempt || 0) + 1);
|
||||
}
|
||||
|
||||
const newSpeciesId = ret.getWildSpeciesForLevel(level, true, isBoss, this.scene.gameMode);
|
||||
const newSpeciesId = ret.getWildSpeciesForLevel(level, true, !!isBoss, this.scene.gameMode);
|
||||
if (newSpeciesId !== ret.speciesId) {
|
||||
console.log("Replaced", Species[ret.speciesId], "with", Species[newSpeciesId]);
|
||||
ret = getPokemonSpecies(newSpeciesId);
|
||||
|
|
|
@ -4,6 +4,7 @@ import MysteryEncounter from "../data/mystery-encounters/mystery-encounter";
|
|||
import { Species } from "#enums/species";
|
||||
import { isNullOrUndefined } from "#app/utils";
|
||||
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import PlayAnimationConfig = Phaser.Types.Animations.PlayAnimationConfig;
|
||||
|
||||
type KnownFileRoot =
|
||||
| "arenas"
|
||||
|
@ -85,7 +86,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
|
|||
};
|
||||
|
||||
if (!isNullOrUndefined(result.species)) {
|
||||
const keys = getSpriteKeysFromSpecies(result.species);
|
||||
const keys = getSpriteKeysFromSpecies(result.species!);
|
||||
result.spriteKey = keys.spriteKey;
|
||||
result.fileRoot = keys.fileRoot;
|
||||
result.isPokemon = true;
|
||||
|
@ -164,7 +165,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
|
|||
}
|
||||
}
|
||||
|
||||
if (!isNaN(alpha)) {
|
||||
if (!isNullOrUndefined(alpha)) {
|
||||
sprite.setAlpha(alpha);
|
||||
tintSprite.setAlpha(alpha);
|
||||
}
|
||||
|
@ -290,7 +291,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
|
|||
const tintSprites = this.getTintSprites();
|
||||
this.spriteConfigs.forEach((config, i) => {
|
||||
if (!config.disableAnimation) {
|
||||
const trainerAnimConfig = {
|
||||
const trainerAnimConfig: PlayAnimationConfig = {
|
||||
key: config.spriteKey,
|
||||
repeat: config?.repeat ? -1 : 0,
|
||||
startFrame: config?.startFrame ?? 0
|
||||
|
@ -307,7 +308,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
|
|||
*/
|
||||
getSpriteAtIndex(index: number): Phaser.GameObjects.Sprite[] {
|
||||
if (!this.spriteConfigs) {
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
const ret: Phaser.GameObjects.Sprite[] = [];
|
||||
|
@ -319,7 +320,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
|
|||
|
||||
getSprites(): Phaser.GameObjects.Sprite[] {
|
||||
if (!this.spriteConfigs) {
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
const ret: Phaser.GameObjects.Sprite[] = [];
|
||||
|
@ -331,7 +332,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
|
|||
|
||||
getTintSprites(): Phaser.GameObjects.Sprite[] {
|
||||
if (!this.spriteConfigs) {
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
const ret: Phaser.GameObjects.Sprite[] = [];
|
||||
|
|
|
@ -108,7 +108,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
public mysteryEncounterData: MysteryEncounterPokemonData;
|
||||
|
||||
/** Used by Mystery Encounters to execute pokemon-specific logic (such as stat boosts) at start of battle */
|
||||
public mysteryEncounterBattleEffects: (pokemon: Pokemon) => void = null;
|
||||
public mysteryEncounterBattleEffects?: (pokemon: Pokemon) => void;
|
||||
|
||||
public fieldPosition: FieldPosition;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export const delibirdyDialogue = {
|
||||
intro: "A pack of Delibird have appeared!",
|
||||
title: "Delibird-y",
|
||||
title: "Delibir-dy",
|
||||
description: "The Delibirds are looking at you expectantly, as if they want something. Perhaps giving them an item or some money would satisfy them?",
|
||||
query: "What will you give them?",
|
||||
invalid_selection: "Pokémon doesn't have that kind of item.",
|
||||
|
|
|
@ -28,7 +28,6 @@ import { BerryType } from "#enums/berry-type";
|
|||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { getPokemonNameWithAffix } from "#app/messages.js";
|
||||
import { isNullOrUndefined } from "../utils";
|
||||
|
||||
const outputModifierData = false;
|
||||
const useMaxWeightForOutput = false;
|
||||
|
@ -120,26 +119,6 @@ export class ModifierType {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the tier field by performing a reverse lookup on the modifier pool specified by {@linkcode poolType} using the
|
||||
* {@linkcode ModifierType}'s id.
|
||||
* @param poolType the {@linkcode ModifierPoolType} to look into to derive the item's tier; defaults to {@linkcode ModifierPoolType.PLAYER}
|
||||
*/
|
||||
withTierFromPool(poolType: ModifierPoolType = ModifierPoolType.PLAYER): ModifierType {
|
||||
for (const tier of Object.values(getModifierPoolForType(poolType))) {
|
||||
for (const modifier of tier) {
|
||||
if (this.id === modifier.modifierType.id) {
|
||||
this.tier = modifier.modifierType.tier;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.tier) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates item tier for ModifierType instance
|
||||
* Tier is a necessary field for items that appear in player shop (determines the Pokeball visual they use)
|
||||
|
@ -2113,10 +2092,10 @@ function getModifierTypeOptionWithRetry(existingOptions: ModifierTypeOption[], r
|
|||
allowLuckUpgrades = allowLuckUpgrades ?? true;
|
||||
let candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, tier, undefined, 0, allowLuckUpgrades);
|
||||
let r = 0;
|
||||
while (existingOptions.length && ++r < retryCount && existingOptions.filter(o => o.type.name === candidate.type.name || o.type.group === candidate.type.group).length) {
|
||||
candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, candidate.type.tier, candidate.upgradeCount, 0, allowLuckUpgrades);
|
||||
while (existingOptions.length && ++r < retryCount && existingOptions.filter(o => o.type.name === candidate?.type.name || o.type.group === candidate?.type.group).length) {
|
||||
candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, candidate?.type.tier ?? tier, candidate?.upgradeCount, 0, allowLuckUpgrades);
|
||||
}
|
||||
return candidate;
|
||||
return candidate!;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -826,7 +826,7 @@ export class PokemonIncrementingStatModifier extends PokemonHeldItemModifier {
|
|||
args[1].forEach((v, i) => {
|
||||
const isHp = i === 0;
|
||||
let mult = 1;
|
||||
if (this.stackCount === this.getMaxHeldItemCount(null)) {
|
||||
if (this.stackCount === this.getMaxHeldItemCount()) {
|
||||
mult = isHp ? 1.05 : 1.1;
|
||||
}
|
||||
const newVal = Math.floor((v + this.stackCount * (isHp ? 1 : 2)) * mult);
|
||||
|
@ -840,7 +840,7 @@ export class PokemonIncrementingStatModifier extends PokemonHeldItemModifier {
|
|||
return 1.2;
|
||||
}
|
||||
|
||||
getMaxHeldItemCount(pokemon: Pokemon): integer {
|
||||
getMaxHeldItemCount(pokemon?: Pokemon): integer {
|
||||
return 50;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMov
|
|||
import { Mode } from "./ui/ui";
|
||||
import { Command } from "./ui/command-ui-handler";
|
||||
import { Stat } from "./data/pokemon-stat";
|
||||
import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, overrideModifiers, overrideHeldItems, BypassSpeedChanceModifier, TurnStatusEffectModifier, PokemonResetNegativeStatStageModifier } from "./modifier/modifier";
|
||||
import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, overrideModifiers, overrideHeldItems, BypassSpeedChanceModifier, TurnStatusEffectModifier, PokemonResetNegativeStatStageModifier, PokemonIncrementingStatModifier } from "./modifier/modifier";
|
||||
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
|
||||
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball";
|
||||
import { CommonAnim, CommonBattleAnim, initEncounterAnims, initMoveAnim, loadEncounterAnimAssets, loadMoveAnimAssets, MoveAnim } from "./data/battle-anims";
|
||||
|
@ -19,7 +19,7 @@ import { biomeLinks, getBiomeName } from "./data/biomes";
|
|||
import { ModifierTier } from "./modifier/modifier-tier";
|
||||
import { CustomModifierSettings, FusePokemonModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, modifierTypes, PokemonModifierType, PokemonMoveModifierType, PokemonPpRestoreModifierType, PokemonPpUpModifierType, regenerateModifierPoolThresholds, RememberMoveModifierType, TmModifierType } from "./modifier/modifier-type";
|
||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { BattlerTagLapseType, CenterOfAttentionTag, EncoreTag, ProtectedTag, SemiInvulnerableTag, TrappedTag } from "./data/battler-tags";
|
||||
import { BattlerTagLapseType, CenterOfAttentionTag, EncoreTag, MysteryEncounterPostSummonTag, ProtectedTag, SemiInvulnerableTag, TrappedTag } from "./data/battler-tags";
|
||||
import { getPokemonNameWithAffix } from "./messages";
|
||||
import { Starter } from "./ui/starter-select-ui-handler";
|
||||
import { Gender } from "./data/gender";
|
||||
|
@ -70,6 +70,7 @@ import { doTrainerExclamation, handleMysteryEncounterBattleStartEffects, handleM
|
|||
import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "#app/ui/modifier-select-ui-handler";
|
||||
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
import { isNullOrUndefined } from "./utils";
|
||||
|
||||
const { t } = i18next;
|
||||
|
||||
|
@ -865,7 +866,7 @@ export class EncounterPhase extends BattlePhase {
|
|||
|
||||
// Add intro visuals for mystery encounter
|
||||
mysteryEncounter.initIntroVisuals(this.scene);
|
||||
this.scene.field.add(mysteryEncounter.introVisuals);
|
||||
this.scene.field.add(mysteryEncounter.introVisuals!);
|
||||
}
|
||||
|
||||
let totalBst = 0;
|
||||
|
@ -930,7 +931,7 @@ export class EncounterPhase extends BattlePhase {
|
|||
const newEncounter = this.scene.getMysteryEncounter(mysteryEncounter);
|
||||
battle.mysteryEncounter = newEncounter;
|
||||
}
|
||||
loadEnemyAssets.push(battle.mysteryEncounter.introVisuals.loadAssets().then(() => battle.mysteryEncounter.introVisuals.initSprite()));
|
||||
loadEnemyAssets.push(battle.mysteryEncounter.introVisuals!.loadAssets().then(() => battle.mysteryEncounter.introVisuals!.initSprite()));
|
||||
// Load Mystery Encounter Exclamation bubble and sfx
|
||||
loadEnemyAssets.push(new Promise<void>(resolve => {
|
||||
this.scene.loadSe("GEN8- Exclaim", "battle_anims", "GEN8- Exclaim.wav");
|
||||
|
@ -1130,7 +1131,7 @@ export class EncounterPhase extends BattlePhase {
|
|||
}
|
||||
}
|
||||
} else if (this.scene.currentBattle.battleType === BattleType.MYSTERY_ENCOUNTER) {
|
||||
const introVisuals = this.scene.currentBattle.mysteryEncounter.introVisuals;
|
||||
const introVisuals = this.scene.currentBattle.mysteryEncounter.introVisuals!;
|
||||
introVisuals.playAnim();
|
||||
|
||||
if (this.scene.currentBattle.mysteryEncounter.onVisualsStart) {
|
||||
|
@ -1148,23 +1149,27 @@ export class EncounterPhase extends BattlePhase {
|
|||
|
||||
if (showEncounterMessage) {
|
||||
const introDialogue = this.scene.currentBattle.mysteryEncounter.dialogue.intro;
|
||||
const FIRST_DIALOGUE_PROMPT_DELAY = 750;
|
||||
let i = 0;
|
||||
const showNextDialogue = () => {
|
||||
const nextAction = i === introDialogue.length - 1 ? doShowEncounterOptions : showNextDialogue;
|
||||
const dialogue = introDialogue[i];
|
||||
const title = getEncounterText(this.scene, dialogue.speaker);
|
||||
const text = getEncounterText(this.scene, dialogue.text);
|
||||
i++;
|
||||
if (title) {
|
||||
this.scene.ui.showDialogue(text, title, null, nextAction, 0, i === 1 ? FIRST_DIALOGUE_PROMPT_DELAY : 0);
|
||||
} else {
|
||||
this.scene.ui.showText(text, null, nextAction, i === 1 ? FIRST_DIALOGUE_PROMPT_DELAY : 0, true);
|
||||
}
|
||||
};
|
||||
if (!introDialogue) {
|
||||
doShowEncounterOptions();
|
||||
} else {
|
||||
const FIRST_DIALOGUE_PROMPT_DELAY = 750;
|
||||
let i = 0;
|
||||
const showNextDialogue = () => {
|
||||
const nextAction = i === introDialogue.length - 1 ? doShowEncounterOptions : showNextDialogue;
|
||||
const dialogue = introDialogue[i];
|
||||
const title = getEncounterText(this.scene, dialogue?.speaker);
|
||||
const text = getEncounterText(this.scene, dialogue.text)!;
|
||||
i++;
|
||||
if (title) {
|
||||
this.scene.ui.showDialogue(text, title, null, nextAction, 0, i === 1 ? FIRST_DIALOGUE_PROMPT_DELAY : 0);
|
||||
} else {
|
||||
this.scene.ui.showText(text, null, nextAction, i === 1 ? FIRST_DIALOGUE_PROMPT_DELAY : 0, true);
|
||||
}
|
||||
};
|
||||
|
||||
if (introDialogue.length > 0) {
|
||||
showNextDialogue();
|
||||
if (introDialogue.length > 0) {
|
||||
showNextDialogue();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doShowEncounterOptions();
|
||||
|
@ -1330,7 +1335,7 @@ export class NextEncounterPhase extends EncounterPhase {
|
|||
}
|
||||
if (lastEncounterVisuals) {
|
||||
this.scene.field.remove(lastEncounterVisuals, true);
|
||||
this.scene.lastMysteryEncounter.introVisuals = null;
|
||||
this.scene.lastMysteryEncounter.introVisuals = undefined;
|
||||
}
|
||||
|
||||
if (!this.tryOverrideForBattleSpec()) {
|
||||
|
@ -4378,7 +4383,7 @@ export class VictoryPhase extends PokemonPhase {
|
|||
if (participated) {
|
||||
partyMember.addFriendship(2);
|
||||
const machoBraceModifier = partyMember.getHeldItems().find(m => m instanceof PokemonIncrementingStatModifier);
|
||||
if (!isNullOrUndefined(machoBraceModifier) && machoBraceModifier.stackCount < machoBraceModifier.getMaxStackCount(this.scene)) {
|
||||
if (machoBraceModifier && machoBraceModifier.stackCount < machoBraceModifier.getMaxStackCount(this.scene)) {
|
||||
machoBraceModifier.stackCount++;
|
||||
this.scene.updateModifiers(true, true);
|
||||
partyMember.updateInfo();
|
||||
|
@ -5857,7 +5862,7 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
} else {
|
||||
baseValue = 250;
|
||||
}
|
||||
const multiplier = !isNullOrUndefined(this.customModifierSettings?.rerollMultiplier) ? this.customModifierSettings.rerollMultiplier : 1;
|
||||
const multiplier = !isNullOrUndefined(this.customModifierSettings?.rerollMultiplier) ? this.customModifierSettings!.rerollMultiplier! : 1;
|
||||
return Math.min(Math.ceil(this.scene.currentBattle.waveIndex / 10) * baseValue * Math.pow(2, this.rerollCount) * multiplier, Number.MAX_SAFE_INTEGER);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
|||
*/
|
||||
export class MysteryEncounterPhase extends Phase {
|
||||
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 300;
|
||||
optionSelectSettings: OptionSelectSettings;
|
||||
optionSelectSettings?: OptionSelectSettings;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -72,7 +72,7 @@ export class MysteryEncounterPhase extends Phase {
|
|||
|
||||
if (option.onPreOptionPhase) {
|
||||
this.scene.executeWithSeedOffset(async () => {
|
||||
return await option.onPreOptionPhase(this.scene)
|
||||
return await option.onPreOptionPhase!(this.scene)
|
||||
.then((result) => {
|
||||
if (isNullOrUndefined(result) || result) {
|
||||
this.continueEncounter();
|
||||
|
@ -93,7 +93,7 @@ export class MysteryEncounterPhase extends Phase {
|
|||
};
|
||||
|
||||
const optionSelectDialogue = this.scene.currentBattle?.mysteryEncounter?.selectedOption?.dialogue;
|
||||
if (optionSelectDialogue?.selected?.length > 0) {
|
||||
if (optionSelectDialogue?.selected && optionSelectDialogue.selected.length > 0) {
|
||||
// Handle intermediate dialogue (between player selection event and the onOptionSelect logic)
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
const selectedDialogue = optionSelectDialogue.selected;
|
||||
|
@ -101,17 +101,17 @@ export class MysteryEncounterPhase extends Phase {
|
|||
const showNextDialogue = () => {
|
||||
const nextAction = i === selectedDialogue.length - 1 ? endDialogueAndContinueEncounter : showNextDialogue;
|
||||
const dialogue = selectedDialogue[i];
|
||||
let title: string = null;
|
||||
const text: string = getEncounterText(this.scene, dialogue.text);
|
||||
let title: string | null = null;
|
||||
const text: string | null = getEncounterText(this.scene, dialogue.text);
|
||||
if (dialogue.speaker) {
|
||||
title = getEncounterText(this.scene, dialogue.speaker);
|
||||
}
|
||||
|
||||
i++;
|
||||
if (title) {
|
||||
this.scene.ui.showDialogue(text, title, null, nextAction, 0, i === 1 ? this.FIRST_DIALOGUE_PROMPT_DELAY : 0);
|
||||
this.scene.ui.showDialogue(text ?? "", title, null, nextAction, 0, i === 1 ? this.FIRST_DIALOGUE_PROMPT_DELAY : 0);
|
||||
} else {
|
||||
this.scene.ui.showText(text, null, nextAction, i === 1 ? this.FIRST_DIALOGUE_PROMPT_DELAY : 0, true);
|
||||
this.scene.ui.showText(text ?? "", null, nextAction, i === 1 ? this.FIRST_DIALOGUE_PROMPT_DELAY : 0, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -142,7 +142,7 @@ export class MysteryEncounterOptionSelectedPhase extends Phase {
|
|||
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene);
|
||||
this.onOptionSelect = this.scene.currentBattle.mysteryEncounter.selectedOption.onOptionPhase;
|
||||
this.onOptionSelect = this.scene.currentBattle.mysteryEncounter.selectedOption!.onOptionPhase;
|
||||
}
|
||||
|
||||
start() {
|
||||
|
@ -223,10 +223,10 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||
|
||||
if (encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||
if (scene.currentBattle.double) {
|
||||
return i18next.t("battle:trainerAppearedDouble", { trainerName: scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) });
|
||||
return i18next.t("battle:trainerAppearedDouble", { trainerName: scene.currentBattle.trainer?.getName(TrainerSlot.NONE, true) });
|
||||
|
||||
} else {
|
||||
return i18next.t("battle:trainerAppeared", { trainerName: scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) });
|
||||
return i18next.t("battle:trainerAppeared", { trainerName: scene.currentBattle.trainer?.getName(TrainerSlot.NONE, true) });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,22 +276,22 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||
}
|
||||
};
|
||||
|
||||
const encounterMessages = scene.currentBattle.trainer.getEncounterMessages();
|
||||
const encounterMessages = scene.currentBattle.trainer?.getEncounterMessages();
|
||||
|
||||
if (!encounterMessages?.length) {
|
||||
if (!encounterMessages || !encounterMessages.length) {
|
||||
doSummon();
|
||||
} else {
|
||||
const trainer = this.scene.currentBattle.trainer;
|
||||
let message: string;
|
||||
scene.executeWithSeedOffset(() => message = Utils.randSeedItem(encounterMessages), this.scene.currentBattle.mysteryEncounter.getSeedOffset());
|
||||
|
||||
message = message!; // tell TS compiler it's defined now
|
||||
const showDialogueAndSummon = () => {
|
||||
scene.ui.showDialogue(message, trainer.getName(TrainerSlot.NONE, true), null, () => {
|
||||
scene.ui.showDialogue(message, trainer?.getName(TrainerSlot.NONE, true), null, () => {
|
||||
scene.charSprite.hide().then(() => scene.hideFieldOverlay(250).then(() => doSummon()));
|
||||
});
|
||||
};
|
||||
if (scene.currentBattle.trainer.config.hasCharSprite && !scene.ui.shouldSkipDialogue(message)) {
|
||||
scene.showFieldOverlay(500).then(() => scene.charSprite.showCharacter(trainer.getKey(), getCharVariantFromDialogue(encounterMessages[0])).then(() => showDialogueAndSummon()));
|
||||
if (this.scene.currentBattle.trainer?.config.hasCharSprite && !this.scene.ui.shouldSkipDialogue(message)) {
|
||||
this.scene.showFieldOverlay(500).then(() => this.scene.charSprite.showCharacter(trainer?.getKey()!, getCharVariantFromDialogue(encounterMessages[0])).then(() => showDialogueAndSummon())); // TODO: is this bang correct?
|
||||
} else {
|
||||
showDialogueAndSummon();
|
||||
}
|
||||
|
@ -349,6 +349,9 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||
showEnemyTrainer(): void {
|
||||
// Show enemy trainer
|
||||
const trainer = this.scene.currentBattle.trainer;
|
||||
if (!trainer) {
|
||||
return;
|
||||
}
|
||||
trainer.alpha = 0;
|
||||
trainer.x += 16;
|
||||
trainer.y -= 16;
|
||||
|
@ -416,7 +419,7 @@ export class MysteryEncounterRewardsPhase extends Phase {
|
|||
this.scene.currentBattle.mysteryEncounter.doEncounterRewards(this.scene);
|
||||
} else if (this.addHealPhase) {
|
||||
this.scene.tryRemovePhase(p => p instanceof SelectModifierPhase);
|
||||
this.scene.unshiftPhase(new SelectModifierPhase(this.scene, 0, null, { fillRemaining: false, rerollMultiplier: 0 }));
|
||||
this.scene.unshiftPhase(new SelectModifierPhase(this.scene, 0, undefined, { fillRemaining: false, rerollMultiplier: 0 }));
|
||||
}
|
||||
// Do not use ME's seedOffset for rewards, these should always be consistent with waveIndex (once per wave)
|
||||
}, this.scene.currentBattle.waveIndex * 1000);
|
||||
|
@ -436,11 +439,11 @@ export class MysteryEncounterRewardsPhase extends Phase {
|
|||
*/
|
||||
export class PostMysteryEncounterPhase extends Phase {
|
||||
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 750;
|
||||
onPostOptionSelect: OptionPhaseCallback;
|
||||
onPostOptionSelect?: OptionPhaseCallback;
|
||||
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene);
|
||||
this.onPostOptionSelect = this.scene.currentBattle.mysteryEncounter.selectedOption.onPostOptionPhase;
|
||||
this.onPostOptionSelect = this.scene.currentBattle.mysteryEncounter.selectedOption?.onPostOptionPhase;
|
||||
}
|
||||
|
||||
start() {
|
||||
|
@ -448,7 +451,7 @@ export class PostMysteryEncounterPhase extends Phase {
|
|||
|
||||
if (this.onPostOptionSelect) {
|
||||
this.scene.executeWithSeedOffset(async () => {
|
||||
return await this.onPostOptionSelect(this.scene)
|
||||
return await this.onPostOptionSelect!(this.scene)
|
||||
.then((result) => {
|
||||
if (isNullOrUndefined(result) || result) {
|
||||
this.continueEncounter();
|
||||
|
@ -467,13 +470,13 @@ export class PostMysteryEncounterPhase extends Phase {
|
|||
};
|
||||
|
||||
const outroDialogue = this.scene.currentBattle?.mysteryEncounter?.dialogue?.outro;
|
||||
if (outroDialogue?.length > 0) {
|
||||
if (outroDialogue && outroDialogue.length > 0) {
|
||||
let i = 0;
|
||||
const showNextDialogue = () => {
|
||||
const nextAction = i === outroDialogue.length - 1 ? endPhase : showNextDialogue;
|
||||
const dialogue = outroDialogue[i];
|
||||
let title: string = null;
|
||||
const text: string = getEncounterText(this.scene, dialogue.text);
|
||||
let title: string | null = null;
|
||||
const text: string | null = getEncounterText(this.scene, dialogue.text);
|
||||
if (dialogue.speaker) {
|
||||
title = getEncounterText(this.scene, dialogue.speaker);
|
||||
}
|
||||
|
@ -481,9 +484,9 @@ export class PostMysteryEncounterPhase extends Phase {
|
|||
i++;
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
if (title) {
|
||||
this.scene.ui.showDialogue(text, title, null, nextAction, 0, i === 1 ? this.FIRST_DIALOGUE_PROMPT_DELAY : 0);
|
||||
this.scene.ui.showDialogue(text ?? "", title, null, nextAction, 0, i === 1 ? this.FIRST_DIALOGUE_PROMPT_DELAY : 0);
|
||||
} else {
|
||||
this.scene.ui.showText(text, null, nextAction, i === 1 ? this.FIRST_DIALOGUE_PROMPT_DELAY : 0, true);
|
||||
this.scene.ui.showText(text ?? "", null, nextAction, i === 1 ? this.FIRST_DIALOGUE_PROMPT_DELAY : 0, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import { expect, vi } from "vitest";
|
|||
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import PartyUiHandler from "#app/ui/party-ui-handler";
|
||||
import OptionSelectUiHandler from "#app/ui/settings/option-select-ui-handler";
|
||||
import { isNullOrUndefined } from "#app/utils";
|
||||
|
||||
/**
|
||||
* Runs a MysteryEncounter to either the start of a battle, or to the MysteryEncounterRewardsPhase, depending on the option selected
|
||||
|
@ -18,7 +19,7 @@ import OptionSelectUiHandler from "#app/ui/settings/option-select-ui-handler";
|
|||
* @param secondaryOptionSelect -
|
||||
* @param isBattle - if selecting option should lead to battle, set to true
|
||||
*/
|
||||
export async function runMysteryEncounterToEnd(game: GameManager, optionNo: number, secondaryOptionSelect: { pokemonNo: number, optionNo?: number } = null, isBattle: boolean = false) {
|
||||
export async function runMysteryEncounterToEnd(game: GameManager, optionNo: number, secondaryOptionSelect?: { pokemonNo: number, optionNo?: number }, isBattle: boolean = false) {
|
||||
vi.spyOn(EncounterPhaseUtils, "selectPokemonForOption");
|
||||
await runSelectMysteryEncounterOption(game, optionNo, secondaryOptionSelect);
|
||||
|
||||
|
@ -65,7 +66,7 @@ export async function runMysteryEncounterToEnd(game: GameManager, optionNo: numb
|
|||
}
|
||||
}
|
||||
|
||||
export async function runSelectMysteryEncounterOption(game: GameManager, optionNo: number, secondaryOptionSelect: { pokemonNo: number, optionNo?: number } = null) {
|
||||
export async function runSelectMysteryEncounterOption(game: GameManager, optionNo: number, secondaryOptionSelect?: { pokemonNo: number, optionNo?: number }) {
|
||||
// Handle any eventual queued messages (e.g. weather phase, etc.)
|
||||
game.onNextPrompt("MessagePhase", Mode.MESSAGE, () => {
|
||||
const uiHandler = game.scene.ui.getHandler<MessageUiHandler>();
|
||||
|
@ -107,8 +108,8 @@ export async function runSelectMysteryEncounterOption(game: GameManager, optionN
|
|||
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
|
||||
if (!isNaN(secondaryOptionSelect?.pokemonNo)) {
|
||||
await handleSecondaryOptionSelect(game, secondaryOptionSelect.pokemonNo, secondaryOptionSelect.optionNo);
|
||||
if (!isNullOrUndefined(secondaryOptionSelect?.pokemonNo)) {
|
||||
await handleSecondaryOptionSelect(game, secondaryOptionSelect!.pokemonNo, secondaryOptionSelect!.optionNo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,14 +129,14 @@ async function handleSecondaryOptionSelect(game: GameManager, pokemonNo: number,
|
|||
partyUiHandler.processInput(Button.ACTION);
|
||||
|
||||
// If there is a second choice to make after selecting a Pokemon
|
||||
if (!isNaN(optionNo)) {
|
||||
if (!isNullOrUndefined(optionNo)) {
|
||||
// Wait for Summary menu to close and second options to spawn
|
||||
const secondOptionUiHandler = game.scene.ui.handlers[Mode.OPTION_SELECT] as OptionSelectUiHandler;
|
||||
vi.spyOn(secondOptionUiHandler, "show");
|
||||
await vi.waitFor(() => expect(secondOptionUiHandler.show).toHaveBeenCalled());
|
||||
|
||||
// Navigate down to the correct option
|
||||
for (let i = 1; i < optionNo; i++) {
|
||||
for (let i = 1; i < optionNo!; i++) {
|
||||
secondOptionUiHandler.processInput(Button.DOWN);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ describe("A Trainer's Test - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
const biomeMap = new Map<Biome, MysteryEncounterType[]>([
|
||||
[Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]],
|
||||
|
@ -59,11 +59,11 @@ describe("A Trainer's Test - Mystery Encounter", () => {
|
|||
expect(ATrainersTestEncounter.encounterTier).toBe(MysteryEncounterTier.ROGUE);
|
||||
expect(ATrainersTestEncounter.dialogue).toBeDefined();
|
||||
expect(ATrainersTestEncounter.dialogue.intro).toBeDefined();
|
||||
expect(ATrainersTestEncounter.dialogue.intro[0].speaker).toBeDefined();
|
||||
expect(ATrainersTestEncounter.dialogue.intro[0].text).toBeDefined();
|
||||
expect(ATrainersTestEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(ATrainersTestEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(ATrainersTestEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(ATrainersTestEncounter.dialogue.intro?.[0].speaker).toBeDefined();
|
||||
expect(ATrainersTestEncounter.dialogue.intro?.[0].text).toBeDefined();
|
||||
expect(ATrainersTestEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(ATrainersTestEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(ATrainersTestEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(ATrainersTestEncounter.options.length).toBe(2);
|
||||
});
|
||||
|
||||
|
@ -92,14 +92,14 @@ describe("A Trainer's Test - Mystery Encounter", () => {
|
|||
expect(ATrainersTestEncounter.onInit).toBeDefined();
|
||||
|
||||
ATrainersTestEncounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
expect(ATrainersTestEncounter.dialogueTokens?.statTrainerName).toBeDefined();
|
||||
expect(ATrainersTestEncounter.misc.trainerType).toBeDefined();
|
||||
expect(ATrainersTestEncounter.misc.trainerNameKey).toBeDefined();
|
||||
expect(ATrainersTestEncounter.misc.trainerEggDescription).toBeDefined();
|
||||
expect(ATrainersTestEncounter.dialogue.intro).toBeDefined();
|
||||
expect(ATrainersTestEncounter.options[1].dialogue.selected).toBeDefined();
|
||||
expect(ATrainersTestEncounter.options[1].dialogue?.selected).toBeDefined();
|
||||
expect(onInitResult).toBe(true);
|
||||
});
|
||||
|
||||
|
@ -108,19 +108,19 @@ describe("A Trainer's Test - Mystery Encounter", () => {
|
|||
const option = ATrainersTestEncounter.options[0];
|
||||
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
||||
expect(option.dialogue).toBeDefined();
|
||||
expect(option.dialogue.buttonLabel).toStrictEqual(`${namespace}.option.1.label`);
|
||||
expect(option.dialogue.buttonTooltip).toStrictEqual(`${namespace}.option.1.tooltip`);
|
||||
expect(option.dialogue!.buttonLabel).toStrictEqual(`${namespace}.option.1.label`);
|
||||
expect(option.dialogue!.buttonTooltip).toStrictEqual(`${namespace}.option.1.tooltip`);
|
||||
});
|
||||
|
||||
it("Should start battle against the trainer", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.A_TRAINERS_TEST, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
|
||||
const enemyField = scene.getEnemyField();
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(enemyField.length).toBe(1);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(["buck", "cheryl", "marley", "mira", "riley"].includes(scene.currentBattle.trainer.config.name.toLowerCase())).toBeTruthy();
|
||||
expect(["buck", "cheryl", "marley", "mira", "riley"].includes(scene.currentBattle.trainer!.config.name.toLowerCase())).toBeTruthy();
|
||||
expect(enemyField[0]).toBeDefined();
|
||||
});
|
||||
|
||||
|
@ -131,10 +131,10 @@ describe("A Trainer's Test - Mystery Encounter", () => {
|
|||
expect(eggsBefore).toBeDefined();
|
||||
const eggsBeforeLength = eggsBefore.length;
|
||||
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
|
||||
const eggsAfter = scene.gameData.eggs;
|
||||
expect(eggsAfter).toBeDefined();
|
||||
|
@ -151,7 +151,7 @@ describe("A Trainer's Test - Mystery Encounter", () => {
|
|||
return {
|
||||
totalDuration: 1,
|
||||
destroy: () => null
|
||||
} as Phaser.Sound.NoAudioSound;
|
||||
} as any;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -159,8 +159,8 @@ describe("A Trainer's Test - Mystery Encounter", () => {
|
|||
const option = ATrainersTestEncounter.options[1];
|
||||
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
||||
expect(option.dialogue).toBeDefined();
|
||||
expect(option.dialogue.buttonLabel).toStrictEqual(`${namespace}.option.2.label`);
|
||||
expect(option.dialogue.buttonTooltip).toStrictEqual(`${namespace}.option.2.tooltip`);
|
||||
expect(option.dialogue?.buttonLabel).toStrictEqual(`${namespace}.option.2.label`);
|
||||
expect(option.dialogue?.buttonTooltip).toStrictEqual(`${namespace}.option.2.tooltip`);
|
||||
});
|
||||
|
||||
it("Should fully heal the party", async () => {
|
||||
|
@ -182,7 +182,7 @@ describe("A Trainer's Test - Mystery Encounter", () => {
|
|||
|
||||
await runMysteryEncounterToEnd(game, 2);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
|
||||
const eggsAfter = scene.gameData.eggs;
|
||||
expect(eggsAfter).toBeDefined();
|
||||
|
|
|
@ -35,7 +35,7 @@ describe("Absolute Avarice - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
|
@ -58,9 +58,9 @@ describe("Absolute Avarice - Mystery Encounter", () => {
|
|||
expect(AbsoluteAvariceEncounter.encounterTier).toBe(MysteryEncounterTier.GREAT);
|
||||
expect(AbsoluteAvariceEncounter.dialogue).toBeDefined();
|
||||
expect(AbsoluteAvariceEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}.intro` }]);
|
||||
expect(AbsoluteAvariceEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(AbsoluteAvariceEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(AbsoluteAvariceEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(AbsoluteAvariceEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(AbsoluteAvariceEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(AbsoluteAvariceEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(AbsoluteAvariceEncounter.options.length).toBe(3);
|
||||
});
|
||||
|
||||
|
@ -98,7 +98,7 @@ describe("Absolute Avarice - Mystery Encounter", () => {
|
|||
|
||||
it("should spawn if player has enough berries", async () => {
|
||||
game.override.mysteryEncounterTier(MysteryEncounterTier.GREAT);
|
||||
game.override.starterHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}]);
|
||||
game.override.startingHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}]);
|
||||
|
||||
await game.runToMysteryEncounter();
|
||||
|
||||
|
@ -106,7 +106,7 @@ describe("Absolute Avarice - Mystery Encounter", () => {
|
|||
});
|
||||
|
||||
it("should remove all player's berries at the start of the encounter", async () => {
|
||||
game.override.starterHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}]);
|
||||
game.override.startingHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}]);
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.ABSOLUTE_AVARICE, defaultParty);
|
||||
|
||||
|
@ -134,13 +134,13 @@ describe("Absolute Avarice - Mystery Encounter", () => {
|
|||
const phaseSpy = vi.spyOn(scene, "pushPhase");
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.ABSOLUTE_AVARICE, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
|
||||
const enemyField = scene.getEnemyField();
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(enemyField.length).toBe(1);
|
||||
expect(enemyField[0].species.speciesId).toBe(Species.GREEDENT);
|
||||
const moveset = enemyField[0].moveset.map(m => m.moveId);
|
||||
const moveset = enemyField[0].moveset.map(m => m?.moveId);
|
||||
expect(moveset?.length).toBe(4);
|
||||
expect(moveset).toEqual([Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.SLACK_OFF]);
|
||||
|
||||
|
@ -151,10 +151,10 @@ describe("Absolute Avarice - Mystery Encounter", () => {
|
|||
|
||||
it("should give reviver seed to each pokemon after battle", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.ABSOLUTE_AVARICE, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
|
||||
for (const partyPokemon of scene.getParty()) {
|
||||
const pokemonId = partyPokemon.id;
|
||||
|
@ -162,7 +162,7 @@ describe("Absolute Avarice - Mystery Encounter", () => {
|
|||
&& (m as PokemonHeldItemModifier).pokemonId === pokemonId, true) as PokemonHeldItemModifier[];
|
||||
const revSeed = pokemonItems.find(i => i.type.name === "Reviver Seed");
|
||||
expect(revSeed).toBeDefined;
|
||||
expect(revSeed.stackCount).toBe(1);
|
||||
expect(revSeed?.stackCount).toBe(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -184,7 +184,7 @@ describe("Absolute Avarice - Mystery Encounter", () => {
|
|||
});
|
||||
|
||||
it("Should return 3 (2/5ths floored) berries if 8 were stolen", async () => {
|
||||
game.override.starterHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}, {name: "BERRY", count: 3, type: BerryType.APICOT}]);
|
||||
game.override.startingHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}, {name: "BERRY", count: 3, type: BerryType.APICOT}]);
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.ABSOLUTE_AVARICE, defaultParty);
|
||||
|
||||
|
@ -200,7 +200,7 @@ describe("Absolute Avarice - Mystery Encounter", () => {
|
|||
});
|
||||
|
||||
it("Should return 2 (2/5ths floored) berries if 7 were stolen", async () => {
|
||||
game.override.starterHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}, {name: "BERRY", count: 2, type: BerryType.APICOT}]);
|
||||
game.override.startingHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}, {name: "BERRY", count: 2, type: BerryType.APICOT}]);
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.ABSOLUTE_AVARICE, defaultParty);
|
||||
|
||||
|
@ -251,7 +251,7 @@ describe("Absolute Avarice - Mystery Encounter", () => {
|
|||
expect(partyCountBefore + 1).toBe(partyCountAfter);
|
||||
const greedent = scene.getParty()[scene.getParty().length - 1];
|
||||
expect(greedent.species.speciesId).toBe(Species.GREEDENT);
|
||||
const moveset = greedent.moveset.map(m => m.moveId);
|
||||
const moveset = greedent.moveset.map(m => m?.moveId);
|
||||
expect(moveset?.length).toBe(4);
|
||||
expect(moveset).toEqual([Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.SLACK_OFF]);
|
||||
});
|
||||
|
|
|
@ -38,7 +38,7 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
const biomeMap = new Map<Biome, MysteryEncounterType[]>([
|
||||
[Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]],
|
||||
|
@ -65,9 +65,9 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => {
|
|||
{ text: `${namespace}.intro` },
|
||||
{ speaker: `${namespace}.speaker`, text: `${namespace}.intro_dialogue` }
|
||||
]);
|
||||
expect(AnOfferYouCantRefuseEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(AnOfferYouCantRefuseEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(AnOfferYouCantRefuseEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(AnOfferYouCantRefuseEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(AnOfferYouCantRefuseEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(AnOfferYouCantRefuseEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(AnOfferYouCantRefuseEncounter.options.length).toBe(3);
|
||||
});
|
||||
|
||||
|
@ -104,7 +104,7 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => {
|
|||
expect(AnOfferYouCantRefuseEncounter.onInit).toBeDefined();
|
||||
|
||||
AnOfferYouCantRefuseEncounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
expect(AnOfferYouCantRefuseEncounter.dialogueTokens?.strongestPokemon).toBeDefined();
|
||||
expect(AnOfferYouCantRefuseEncounter.dialogueTokens?.price).toBeDefined();
|
||||
|
@ -153,7 +153,7 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => {
|
|||
const itemModifier = scene.findModifier(m => m instanceof ShinyRateBoosterModifier) as ShinyRateBoosterModifier;
|
||||
|
||||
expect(itemModifier).toBeDefined();
|
||||
expect(itemModifier.stackCount).toBe(1);
|
||||
expect(itemModifier?.stackCount).toBe(1);
|
||||
});
|
||||
|
||||
it("Should remove the Pokemon from the party", async () => {
|
||||
|
@ -199,7 +199,7 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => {
|
|||
it("should award EXP to a pokemon with an ability in EXTORTION_ABILITIES", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, defaultParty);
|
||||
const party = scene.getParty();
|
||||
const gyarados = party.find((pkm) => pkm.species.speciesId === Species.GYARADOS);
|
||||
const gyarados = party.find((pkm) => pkm.species.speciesId === Species.GYARADOS)!;
|
||||
const expBefore = gyarados.exp;
|
||||
|
||||
await runMysteryEncounterToEnd(game, 2);
|
||||
|
@ -210,7 +210,7 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => {
|
|||
it("should award EXP to a pokemon with a move in EXTORTION_MOVES", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, [Species.ABRA]);
|
||||
const party = scene.getParty();
|
||||
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA);
|
||||
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA)!;
|
||||
abra.moveset = [new PokemonMove(Moves.BEAT_UP)];
|
||||
const expBefore = abra.exp;
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ describe("Berries Abound - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
|
@ -59,9 +59,9 @@ describe("Berries Abound - Mystery Encounter", () => {
|
|||
expect(BerriesAboundEncounter.encounterTier).toBe(MysteryEncounterTier.COMMON);
|
||||
expect(BerriesAboundEncounter.dialogue).toBeDefined();
|
||||
expect(BerriesAboundEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}.intro` }]);
|
||||
expect(BerriesAboundEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(BerriesAboundEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(BerriesAboundEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(BerriesAboundEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(BerriesAboundEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(BerriesAboundEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(BerriesAboundEncounter.options.length).toBe(3);
|
||||
});
|
||||
|
||||
|
@ -90,12 +90,12 @@ describe("Berries Abound - Mystery Encounter", () => {
|
|||
expect(BerriesAboundEncounter.onInit).toBeDefined();
|
||||
|
||||
BerriesAboundEncounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
const config = BerriesAboundEncounter.enemyPartyConfigs[0];
|
||||
expect(config).toBeDefined();
|
||||
expect(config.levelAdditiveMultiplier).toBe(1);
|
||||
expect(config.pokemonConfigs[0].isBoss).toBe(true);
|
||||
expect(config.pokemonConfigs?.[0].isBoss).toBe(true);
|
||||
expect(onInitResult).toBe(true);
|
||||
});
|
||||
|
||||
|
@ -119,12 +119,12 @@ describe("Berries Abound - Mystery Encounter", () => {
|
|||
await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty);
|
||||
|
||||
const config = game.scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0];
|
||||
const speciesToSpawn = config.pokemonConfigs[0].species.speciesId;
|
||||
const speciesToSpawn = config.pokemonConfigs?.[0].species.speciesId;
|
||||
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
|
||||
const enemyField = scene.getEnemyField();
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(enemyField.length).toBe(1);
|
||||
expect(enemyField[0].species.speciesId).toBe(speciesToSpawn);
|
||||
});
|
||||
|
@ -133,11 +133,12 @@ describe("Berries Abound - Mystery Encounter", () => {
|
|||
await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty);
|
||||
|
||||
const numBerries = game.scene.currentBattle.mysteryEncounter.misc.numBerries;
|
||||
scene.modifiers = [];
|
||||
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
|
||||
const berriesAfter = scene.findModifiers(m => m instanceof BerryModifier) as BerryModifier[];
|
||||
const berriesAfterCount = berriesAfter.reduce((a, b) => a + b.stackCount, 0);
|
||||
|
@ -147,10 +148,10 @@ describe("Berries Abound - Mystery Encounter", () => {
|
|||
|
||||
it("should spawn a shop with 5 berries", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
@ -178,14 +179,14 @@ describe("Berries Abound - Mystery Encounter", () => {
|
|||
await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty);
|
||||
|
||||
const config = game.scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0];
|
||||
const speciesToSpawn = config.pokemonConfigs[0].species.speciesId;
|
||||
const speciesToSpawn = config.pokemonConfigs?.[0].species.speciesId;
|
||||
// Setting enemy's level arbitrarily high to outspeed
|
||||
config.pokemonConfigs[0].dataSource.level = 1000;
|
||||
config.pokemonConfigs![0].dataSource!.level = 1000;
|
||||
|
||||
await runMysteryEncounterToEnd(game, 2, null, true);
|
||||
await runMysteryEncounterToEnd(game, 2, undefined, true);
|
||||
|
||||
const enemyField = scene.getEnemyField();
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(enemyField.length).toBe(1);
|
||||
expect(enemyField[0].species.speciesId).toBe(speciesToSpawn);
|
||||
|
||||
|
@ -207,7 +208,7 @@ describe("Berries Abound - Mystery Encounter", () => {
|
|||
|
||||
await runMysteryEncounterToEnd(game, 2);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
|
|
@ -50,7 +50,7 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
|
@ -78,9 +78,9 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
text: `${namespace}.intro_dialogue`,
|
||||
},
|
||||
]);
|
||||
expect(ClowningAroundEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(ClowningAroundEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(ClowningAroundEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(ClowningAroundEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(ClowningAroundEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(ClowningAroundEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(ClowningAroundEncounter.options.length).toBe(3);
|
||||
});
|
||||
|
||||
|
@ -111,23 +111,23 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
expect(ClowningAroundEncounter.onInit).toBeDefined();
|
||||
|
||||
ClowningAroundEncounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
const config = ClowningAroundEncounter.enemyPartyConfigs[0];
|
||||
|
||||
expect(config.doubleBattle).toBe(true);
|
||||
expect(config.trainerConfig.trainerType).toBe(TrainerType.HARLEQUIN);
|
||||
expect(config.pokemonConfigs[0]).toEqual({
|
||||
expect(config.trainerConfig?.trainerType).toBe(TrainerType.HARLEQUIN);
|
||||
expect(config.pokemonConfigs?.[0]).toEqual({
|
||||
species: getPokemonSpecies(Species.MR_MIME),
|
||||
isBoss: true,
|
||||
moveSet: [Moves.TEETER_DANCE, Moves.ALLY_SWITCH, Moves.DAZZLING_GLEAM, Moves.PSYCHIC]
|
||||
});
|
||||
expect(config.pokemonConfigs[1]).toEqual({
|
||||
expect(config.pokemonConfigs?.[1]).toEqual({
|
||||
species: getPokemonSpecies(Species.BLACEPHALON),
|
||||
mysteryEncounterData: expect.anything(),
|
||||
isBoss: true,
|
||||
moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN]
|
||||
});
|
||||
expect(config.pokemonConfigs[1].mysteryEncounterData.types.length).toBe(2);
|
||||
expect(config.pokemonConfigs?.[1].mysteryEncounterData?.types.length).toBe(2);
|
||||
expect([
|
||||
Abilities.STURDY,
|
||||
Abilities.PICKUP,
|
||||
|
@ -144,8 +144,8 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
Abilities.MAGICIAN,
|
||||
Abilities.SHEER_FORCE,
|
||||
Abilities.PRANKSTER
|
||||
]).toContain(config.pokemonConfigs[1].mysteryEncounterData.ability);
|
||||
expect(ClowningAroundEncounter.misc.ability).toBe(config.pokemonConfigs[1].mysteryEncounterData.ability);
|
||||
]).toContain(config.pokemonConfigs?.[1].mysteryEncounterData?.ability);
|
||||
expect(ClowningAroundEncounter.misc.ability).toBe(config.pokemonConfigs?.[1].mysteryEncounterData?.ability);
|
||||
await vi.waitFor(() => expect(moveInitSpy).toHaveBeenCalled());
|
||||
await vi.waitFor(() => expect(moveLoadSpy).toHaveBeenCalled());
|
||||
expect(onInitResult).toBe(true);
|
||||
|
@ -172,10 +172,10 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
const phaseSpy = vi.spyOn(scene, "pushPhase");
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
|
||||
const enemyField = scene.getEnemyField();
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(enemyField.length).toBe(2);
|
||||
expect(enemyField[0].species.speciesId).toBe(Species.MR_MIME);
|
||||
expect(enemyField[0].moveset).toEqual([new PokemonMove(Moves.TEETER_DANCE), new PokemonMove(Moves.ALLY_SWITCH), new PokemonMove(Moves.DAZZLING_GLEAM), new PokemonMove(Moves.PSYCHIC)]);
|
||||
|
@ -191,10 +191,10 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
|
||||
it("should let the player gain the ability after battle completion", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
const abilityToTrain = scene.currentBattle.mysteryEncounter.misc.ability;
|
||||
|
||||
|
@ -209,7 +209,7 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
vi.spyOn(partyUiHandler, "show");
|
||||
game.endPhase();
|
||||
await game.phaseInterceptor.to(PostMysteryEncounterPhase);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(PostMysteryEncounterPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(PostMysteryEncounterPhase.name);
|
||||
|
||||
// Wait for Yes/No confirmation to appear
|
||||
await vi.waitFor(() => expect(optionSelectUiHandler.show).toHaveBeenCalled());
|
||||
|
@ -224,7 +224,7 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(NewBattlePhase, false);
|
||||
|
||||
const leadPokemon = scene.getParty()[0];
|
||||
expect(leadPokemon.mysteryEncounterData.ability).toBe(abilityToTrain);
|
||||
expect(leadPokemon.mysteryEncounterData?.ability).toBe(abilityToTrain);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -255,6 +255,9 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
it("should randomize held items of the Pokemon with the most items, and not the held items of other pokemon", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty);
|
||||
|
||||
// Set some moves on party for attack type booster generation
|
||||
scene.getParty()[0].moveset = [new PokemonMove(Moves.TACKLE), new PokemonMove(Moves.THIEF)];
|
||||
|
||||
// 2 Sitrus Berries on lead
|
||||
scene.modifiers = [];
|
||||
let itemType = generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType;
|
||||
|
@ -294,8 +297,8 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
const secondItemsAfter = scene.getParty()[1].getHeldItems();
|
||||
expect(secondItemsAfter.length).toBe(1);
|
||||
expect(secondItemsAfter[0].type.id).toBe("SOUL_DEW");
|
||||
expect(secondItemsAfter[0].stackCount).toBe(5);
|
||||
});
|
||||
expect(secondItemsAfter[0]?.stackCount).toBe(5);
|
||||
}, 2000000);
|
||||
|
||||
it("should leave encounter without battle", async () => {
|
||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
|
@ -342,9 +345,9 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
scene.getParty()[2].moveset = [];
|
||||
await runMysteryEncounterToEnd(game, 3);
|
||||
|
||||
const leadTypesAfter = scene.getParty()[0].mysteryEncounterData.types;
|
||||
const secondaryTypesAfter = scene.getParty()[1].mysteryEncounterData.types;
|
||||
const thirdTypesAfter = scene.getParty()[2].mysteryEncounterData.types;
|
||||
const leadTypesAfter = scene.getParty()[0].mysteryEncounterData?.types;
|
||||
const secondaryTypesAfter = scene.getParty()[1].mysteryEncounterData?.types;
|
||||
const thirdTypesAfter = scene.getParty()[2].mysteryEncounterData?.types;
|
||||
|
||||
expect(leadTypesAfter.length).toBe(2);
|
||||
expect(leadTypesAfter).not.toBe([Type.ICE, Type.WATER]);
|
||||
|
|
|
@ -37,7 +37,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
|
@ -60,9 +60,9 @@ describe("Dancing Lessons - Mystery Encounter", () => {
|
|||
expect(DancingLessonsEncounter.encounterTier).toBe(MysteryEncounterTier.GREAT);
|
||||
expect(DancingLessonsEncounter.dialogue).toBeDefined();
|
||||
expect(DancingLessonsEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}.intro` }]);
|
||||
expect(DancingLessonsEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(DancingLessonsEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(DancingLessonsEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(DancingLessonsEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(DancingLessonsEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(DancingLessonsEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(DancingLessonsEncounter.options.length).toBe(3);
|
||||
});
|
||||
|
||||
|
@ -110,14 +110,14 @@ describe("Dancing Lessons - Mystery Encounter", () => {
|
|||
const phaseSpy = vi.spyOn(scene, "pushPhase");
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
|
||||
const enemyField = scene.getEnemyField();
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(enemyField.length).toBe(1);
|
||||
expect(enemyField[0].species.speciesId).toBe(Species.ORICORIO);
|
||||
expect(enemyField[0].summonData.battleStats).toEqual([1, 1, 1, 1, 1, 0, 0]);
|
||||
const moveset = enemyField[0].moveset.map(m => m.moveId);
|
||||
const moveset = enemyField[0].moveset.map(m => m?.moveId);
|
||||
expect(moveset.some(m => m === Moves.REVELATION_DANCE)).toBeTruthy();
|
||||
|
||||
const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]);
|
||||
|
@ -127,10 +127,10 @@ describe("Dancing Lessons - Mystery Encounter", () => {
|
|||
|
||||
it("should have a Baton in the rewards after battle", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
@ -205,7 +205,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
|
|||
expect(partyCountBefore + 1).toBe(partyCountAfter);
|
||||
const oricorio = scene.getParty()[scene.getParty().length - 1];
|
||||
expect(oricorio.species.speciesId).toBe(Species.ORICORIO);
|
||||
const moveset = oricorio.moveset.map(m => m.moveId);
|
||||
const moveset = oricorio.moveset.map(m => m?.moveId);
|
||||
expect(moveset?.some(m => m === Moves.REVELATION_DANCE)).toBeTruthy();
|
||||
expect(moveset?.some(m => m === Moves.DRAGON_DANCE)).toBeTruthy();
|
||||
});
|
||||
|
@ -217,7 +217,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
|
||||
const encounterPhase = scene.getCurrentPhase();
|
||||
expect(encounterPhase.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
const mysteryEncounterPhase = encounterPhase as MysteryEncounterPhase;
|
||||
vi.spyOn(mysteryEncounterPhase, "continueEncounter");
|
||||
vi.spyOn(mysteryEncounterPhase, "handleOptionSelect");
|
||||
|
@ -226,7 +226,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
|
|||
await runSelectMysteryEncounterOption(game, 3);
|
||||
const partyCountAfter = scene.getParty().length;
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled
|
||||
expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled();
|
||||
expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled();
|
||||
|
|
|
@ -37,7 +37,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
|
@ -60,9 +60,9 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
expect(DelibirdyEncounter.dialogue).toBeDefined();
|
||||
expect(DelibirdyEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}.intro` }]);
|
||||
expect(DelibirdyEncounter.dialogue.outro).toStrictEqual([{ text: `${namespace}.outro` }]);
|
||||
expect(DelibirdyEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(DelibirdyEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(DelibirdyEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(DelibirdyEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(DelibirdyEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(DelibirdyEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(DelibirdyEncounter.options.length).toBe(3);
|
||||
});
|
||||
|
||||
|
@ -128,7 +128,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
const itemModifier = scene.findModifier(m => m instanceof HiddenAbilityRateBoosterModifier) as HiddenAbilityRateBoosterModifier;
|
||||
|
||||
expect(itemModifier).toBeDefined();
|
||||
expect(itemModifier.stackCount).toBe(1);
|
||||
expect(itemModifier?.stackCount).toBe(1);
|
||||
});
|
||||
|
||||
it("Should give the player a Shell Bell if they have max stacks of Berry Pouches", async () => {
|
||||
|
@ -148,9 +148,9 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
const shellBellAfter = scene.findModifier(m => m instanceof HitHealModifier);
|
||||
|
||||
expect(abilityCharmAfter).toBeDefined();
|
||||
expect(abilityCharmAfter.stackCount).toBe(4);
|
||||
expect(abilityCharmAfter?.stackCount).toBe(4);
|
||||
expect(shellBellAfter).toBeDefined();
|
||||
expect(shellBellAfter.stackCount).toBe(1);
|
||||
expect(shellBellAfter?.stackCount).toBe(1);
|
||||
});
|
||||
|
||||
it("should be disabled if player does not have enough money", async () => {
|
||||
|
@ -159,7 +159,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
|
||||
const encounterPhase = scene.getCurrentPhase();
|
||||
expect(encounterPhase.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
const mysteryEncounterPhase = encounterPhase as MysteryEncounterPhase;
|
||||
vi.spyOn(mysteryEncounterPhase, "continueEncounter");
|
||||
vi.spyOn(mysteryEncounterPhase, "handleOptionSelect");
|
||||
|
@ -167,7 +167,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
|
||||
await runSelectMysteryEncounterOption(game, 1);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled
|
||||
expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled();
|
||||
expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled();
|
||||
|
@ -217,9 +217,9 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
const sitrusAfter = scene.findModifier(m => m instanceof BerryModifier);
|
||||
const candyJarAfter = scene.findModifier(m => m instanceof LevelIncrementBoosterModifier);
|
||||
|
||||
expect(sitrusAfter.stackCount).toBe(1);
|
||||
expect(sitrusAfter?.stackCount).toBe(1);
|
||||
expect(candyJarAfter).toBeDefined();
|
||||
expect(candyJarAfter.stackCount).toBe(1);
|
||||
expect(candyJarAfter?.stackCount).toBe(1);
|
||||
});
|
||||
|
||||
it("Should remove Reviver Seed and give the player a Healing Charm", async () => {
|
||||
|
@ -240,7 +240,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
|
||||
expect(reviverSeedAfter).toBeUndefined();
|
||||
expect(healingCharmAfter).toBeDefined();
|
||||
expect(healingCharmAfter.stackCount).toBe(1);
|
||||
expect(healingCharmAfter?.stackCount).toBe(1);
|
||||
});
|
||||
|
||||
it("Should give the player a Shell Bell if they have max stacks of Candy Jars", async () => {
|
||||
|
@ -265,11 +265,11 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
const candyJarAfter = scene.findModifier(m => m instanceof LevelIncrementBoosterModifier);
|
||||
const shellBellAfter = scene.findModifier(m => m instanceof HitHealModifier);
|
||||
|
||||
expect(sitrusAfter.stackCount).toBe(1);
|
||||
expect(sitrusAfter?.stackCount).toBe(1);
|
||||
expect(candyJarAfter).toBeDefined();
|
||||
expect(candyJarAfter.stackCount).toBe(99);
|
||||
expect(candyJarAfter?.stackCount).toBe(99);
|
||||
expect(shellBellAfter).toBeDefined();
|
||||
expect(shellBellAfter.stackCount).toBe(1);
|
||||
expect(shellBellAfter?.stackCount).toBe(1);
|
||||
});
|
||||
|
||||
it("Should give the player a Shell Bell if they have max stacks of Healing Charms", async () => {
|
||||
|
@ -296,9 +296,9 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
|
||||
expect(reviverSeedAfter).toBeUndefined();
|
||||
expect(healingCharmAfter).toBeDefined();
|
||||
expect(healingCharmAfter.stackCount).toBe(5);
|
||||
expect(healingCharmAfter?.stackCount).toBe(5);
|
||||
expect(shellBellAfter).toBeDefined();
|
||||
expect(shellBellAfter.stackCount).toBe(1);
|
||||
expect(shellBellAfter?.stackCount).toBe(1);
|
||||
});
|
||||
|
||||
it("should be disabled if player does not have any proper items", async () => {
|
||||
|
@ -314,7 +314,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
|
||||
const encounterPhase = scene.getCurrentPhase();
|
||||
expect(encounterPhase.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
const mysteryEncounterPhase = encounterPhase as MysteryEncounterPhase;
|
||||
vi.spyOn(mysteryEncounterPhase, "continueEncounter");
|
||||
vi.spyOn(mysteryEncounterPhase, "handleOptionSelect");
|
||||
|
@ -322,7 +322,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
|
||||
await runSelectMysteryEncounterOption(game, 2);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled
|
||||
expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled();
|
||||
expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled();
|
||||
|
@ -379,9 +379,9 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
const soulDewAfter = scene.findModifier(m => m instanceof PokemonNatureWeightModifier);
|
||||
const berryPouchAfter = scene.findModifier(m => m instanceof PreserveBerryModifier);
|
||||
|
||||
expect(soulDewAfter.stackCount).toBe(1);
|
||||
expect(soulDewAfter?.stackCount).toBe(1);
|
||||
expect(berryPouchAfter).toBeDefined();
|
||||
expect(berryPouchAfter.stackCount).toBe(1);
|
||||
expect(berryPouchAfter?.stackCount).toBe(1);
|
||||
});
|
||||
|
||||
it("Should remove held item and give the player a Berry Pouch", async () => {
|
||||
|
@ -402,7 +402,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
|
||||
expect(soulDewAfter).toBeUndefined();
|
||||
expect(berryPouchAfter).toBeDefined();
|
||||
expect(berryPouchAfter.stackCount).toBe(1);
|
||||
expect(berryPouchAfter?.stackCount).toBe(1);
|
||||
});
|
||||
|
||||
it("Should give the player a Shell Bell if they have max stacks of Berry Pouches", async () => {
|
||||
|
@ -429,9 +429,9 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
|
||||
expect(soulDewAfter).toBeUndefined();
|
||||
expect(berryPouchAfter).toBeDefined();
|
||||
expect(berryPouchAfter.stackCount).toBe(3);
|
||||
expect(berryPouchAfter?.stackCount).toBe(3);
|
||||
expect(shellBellAfter).toBeDefined();
|
||||
expect(shellBellAfter.stackCount).toBe(1);
|
||||
expect(shellBellAfter?.stackCount).toBe(1);
|
||||
});
|
||||
|
||||
it("should be disabled if player does not have any proper items", async () => {
|
||||
|
@ -447,7 +447,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
|
||||
const encounterPhase = scene.getCurrentPhase();
|
||||
expect(encounterPhase.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
const mysteryEncounterPhase = encounterPhase as MysteryEncounterPhase;
|
||||
vi.spyOn(mysteryEncounterPhase, "continueEncounter");
|
||||
vi.spyOn(mysteryEncounterPhase, "handleOptionSelect");
|
||||
|
@ -455,7 +455,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
|||
|
||||
await runSelectMysteryEncounterOption(game, 3);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled
|
||||
expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled();
|
||||
expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled();
|
||||
|
|
|
@ -35,7 +35,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
const biomeMap = new Map<Biome, MysteryEncounterType[]>([
|
||||
[Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]],
|
||||
|
@ -65,9 +65,9 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||
text: `${namespace}.intro_dialogue`,
|
||||
}
|
||||
]);
|
||||
expect(DepartmentStoreSaleEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(DepartmentStoreSaleEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(DepartmentStoreSaleEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(DepartmentStoreSaleEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(DepartmentStoreSaleEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(DepartmentStoreSaleEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(DepartmentStoreSaleEncounter.options.length).toBe(4);
|
||||
});
|
||||
|
||||
|
@ -109,7 +109,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||
it("should have shop with only TMs", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
@ -144,7 +144,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||
it("should have shop with only Vitamins", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 2);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
@ -180,7 +180,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||
it("should have shop with only X Items", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 3);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
@ -216,7 +216,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||
it("should have shop with only Pokeballs", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 4);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
|
|
@ -42,7 +42,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
|
@ -65,9 +65,9 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||
expect(FieryFalloutEncounter.encounterTier).toBe(MysteryEncounterTier.COMMON);
|
||||
expect(FieryFalloutEncounter.dialogue).toBeDefined();
|
||||
expect(FieryFalloutEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}.intro` }]);
|
||||
expect(FieryFalloutEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(FieryFalloutEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(FieryFalloutEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(FieryFalloutEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(FieryFalloutEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(FieryFalloutEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(FieryFalloutEncounter.options.length).toBe(3);
|
||||
});
|
||||
|
||||
|
@ -106,7 +106,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||
expect(FieryFalloutEncounter.onInit).toBeDefined();
|
||||
|
||||
FieryFalloutEncounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
expect(FieryFalloutEncounter.enemyPartyConfigs).toEqual([
|
||||
{
|
||||
|
@ -152,10 +152,10 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||
const phaseSpy = vi.spyOn(scene, "pushPhase");
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
|
||||
const enemyField = scene.getEnemyField();
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
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);
|
||||
|
@ -169,10 +169,10 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||
|
||||
it("should give charcoal to lead pokemon", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
|
||||
const leadPokemonId = scene.getParty()?.[0].id;
|
||||
const leadPokemonItems = scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||
|
@ -202,9 +202,9 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
||||
|
||||
const party = scene.getParty();
|
||||
const lapras = party.find((pkm) => pkm.species.speciesId === Species.LAPRAS);
|
||||
const lapras = party.find((pkm) => pkm.species.speciesId === Species.LAPRAS)!;
|
||||
lapras.status = new Status(StatusEffect.POISON);
|
||||
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA);
|
||||
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA)!;
|
||||
vi.spyOn(abra, "isAllowedInBattle").mockReturnValue(false);
|
||||
|
||||
await runMysteryEncounterToEnd(game, 2);
|
||||
|
@ -251,7 +251,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||
await runMysteryEncounterToEnd(game, 3);
|
||||
// await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
|
||||
const leadPokemonId = scene.getParty()?.[0].id;
|
||||
const leadPokemonItems = scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||
|
@ -274,12 +274,12 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
|
||||
const encounterPhase = scene.getCurrentPhase();
|
||||
expect(encounterPhase.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
const continueEncounterSpy = vi.spyOn((encounterPhase as MysteryEncounterPhase), "continueEncounter");
|
||||
|
||||
await runSelectMysteryEncounterOption(game, 3);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(continueEncounterSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -38,7 +38,7 @@ describe("Fight or Flight - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
|
@ -60,9 +60,9 @@ describe("Fight or Flight - Mystery Encounter", () => {
|
|||
expect(FightOrFlightEncounter.encounterTier).toBe(MysteryEncounterTier.COMMON);
|
||||
expect(FightOrFlightEncounter.dialogue).toBeDefined();
|
||||
expect(FightOrFlightEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}.intro` }]);
|
||||
expect(FightOrFlightEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(FightOrFlightEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(FightOrFlightEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(FightOrFlightEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(FightOrFlightEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(FightOrFlightEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(FightOrFlightEncounter.options.length).toBe(3);
|
||||
});
|
||||
|
||||
|
@ -91,12 +91,12 @@ describe("Fight or Flight - Mystery Encounter", () => {
|
|||
expect(FightOrFlightEncounter.onInit).toBeDefined();
|
||||
|
||||
FightOrFlightEncounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
const config = FightOrFlightEncounter.enemyPartyConfigs[0];
|
||||
expect(config).toBeDefined();
|
||||
expect(config.levelAdditiveMultiplier).toBe(1);
|
||||
expect(config.pokemonConfigs[0].isBoss).toBe(true);
|
||||
expect(config.pokemonConfigs?.[0].isBoss).toBe(true);
|
||||
expect(onInitResult).toBe(true);
|
||||
});
|
||||
|
||||
|
@ -120,12 +120,12 @@ describe("Fight or Flight - Mystery Encounter", () => {
|
|||
await game.runToMysteryEncounter(MysteryEncounterType.FIGHT_OR_FLIGHT, defaultParty);
|
||||
|
||||
const config = game.scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0];
|
||||
const speciesToSpawn = config.pokemonConfigs[0].species.speciesId;
|
||||
const speciesToSpawn = config.pokemonConfigs?.[0].species.speciesId;
|
||||
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
|
||||
const enemyField = scene.getEnemyField();
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(enemyField.length).toBe(1);
|
||||
expect(enemyField[0].species.speciesId).toBe(speciesToSpawn);
|
||||
});
|
||||
|
@ -135,10 +135,10 @@ describe("Fight or Flight - Mystery Encounter", () => {
|
|||
|
||||
const item = game.scene.currentBattle.mysteryEncounter.misc;
|
||||
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
||||
|
@ -171,7 +171,7 @@ describe("Fight or Flight - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
|
||||
const encounterPhase = scene.getCurrentPhase();
|
||||
expect(encounterPhase.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
const mysteryEncounterPhase = encounterPhase as MysteryEncounterPhase;
|
||||
vi.spyOn(mysteryEncounterPhase, "continueEncounter");
|
||||
vi.spyOn(mysteryEncounterPhase, "handleOptionSelect");
|
||||
|
@ -179,7 +179,7 @@ describe("Fight or Flight - Mystery Encounter", () => {
|
|||
|
||||
await runSelectMysteryEncounterOption(game, 2);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled
|
||||
expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled();
|
||||
expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled();
|
||||
|
@ -196,7 +196,7 @@ describe("Fight or Flight - Mystery Encounter", () => {
|
|||
|
||||
await runMysteryEncounterToEnd(game, 2);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
|
@ -59,9 +59,9 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
expect(LostAtSeaEncounter.encounterTier).toBe(MysteryEncounterTier.COMMON);
|
||||
expect(LostAtSeaEncounter.dialogue).toBeDefined();
|
||||
expect(LostAtSeaEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}.intro` }]);
|
||||
expect(LostAtSeaEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(LostAtSeaEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(LostAtSeaEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(LostAtSeaEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(LostAtSeaEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(LostAtSeaEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(LostAtSeaEncounter.options.length).toBe(3);
|
||||
});
|
||||
|
||||
|
@ -98,7 +98,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
expect(LostAtSeaEncounter.onInit).toBeDefined();
|
||||
|
||||
LostAtSeaEncounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
expect(LostAtSeaEncounter.dialogueTokens?.damagePercentage).toBe("25");
|
||||
expect(LostAtSeaEncounter.dialogueTokens?.option1RequiredMove).toBe(Moves[Moves.SURF]);
|
||||
|
@ -129,12 +129,12 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, defaultParty);
|
||||
const party = game.scene.getParty();
|
||||
const blastoise = party.find((pkm) => pkm.species.speciesId === Species.PIDGEOT);
|
||||
const expBefore = blastoise.exp;
|
||||
const blastoise = party.find((pkm) => pkm.species.speciesId === Species.BLASTOISE);
|
||||
const expBefore = blastoise!.exp;
|
||||
|
||||
await runMysteryEncounterToEnd(game, 2);
|
||||
await runMysteryEncounterToEnd(game, 1);
|
||||
|
||||
expect(blastoise.exp).toBe(expBefore + Math.floor(laprasSpecies.baseExp * defaultWave / 5 + 1));
|
||||
expect(blastoise?.exp).toBe(expBefore + Math.floor(laprasSpecies.baseExp * defaultWave / 5 + 1));
|
||||
});
|
||||
|
||||
it("should leave encounter without battle", async () => {
|
||||
|
@ -152,7 +152,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
|
||||
const encounterPhase = scene.getCurrentPhase();
|
||||
expect(encounterPhase.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
const mysteryEncounterPhase = encounterPhase as MysteryEncounterPhase;
|
||||
vi.spyOn(mysteryEncounterPhase, "continueEncounter");
|
||||
vi.spyOn(mysteryEncounterPhase, "handleOptionSelect");
|
||||
|
@ -160,7 +160,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
|
||||
await runSelectMysteryEncounterOption(game, 1);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled
|
||||
expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled();
|
||||
expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled();
|
||||
|
@ -194,11 +194,11 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, defaultParty);
|
||||
const party = game.scene.getParty();
|
||||
const pidgeot = party.find((pkm) => pkm.species.speciesId === Species.PIDGEOT);
|
||||
const expBefore = pidgeot.exp;
|
||||
const expBefore = pidgeot!.exp;
|
||||
|
||||
await runMysteryEncounterToEnd(game, 2);
|
||||
|
||||
expect(pidgeot.exp).toBe(expBefore + Math.floor(laprasBaseExp * defaultWave / 5 + 1));
|
||||
expect(pidgeot!.exp).toBe(expBefore + Math.floor(laprasBaseExp * defaultWave / 5 + 1));
|
||||
});
|
||||
|
||||
it("should leave encounter without battle", async () => {
|
||||
|
@ -216,7 +216,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
|
||||
const encounterPhase = scene.getCurrentPhase();
|
||||
expect(encounterPhase.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
const mysteryEncounterPhase = encounterPhase as MysteryEncounterPhase;
|
||||
vi.spyOn(mysteryEncounterPhase, "continueEncounter");
|
||||
vi.spyOn(mysteryEncounterPhase, "handleOptionSelect");
|
||||
|
@ -224,7 +224,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
|
||||
await runSelectMysteryEncounterOption(game, 2);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled
|
||||
expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled();
|
||||
expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled();
|
||||
|
@ -254,7 +254,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, defaultParty);
|
||||
|
||||
const party = game.scene.getParty();
|
||||
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA);
|
||||
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA)!;
|
||||
vi.spyOn(abra, "isAllowedInBattle").mockReturnValue(false);
|
||||
|
||||
await runMysteryEncounterToEnd(game, 3);
|
||||
|
|
|
@ -40,7 +40,7 @@ describe("Mysterious Challengers - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
const biomeMap = new Map<Biome, MysteryEncounterType[]>([
|
||||
[Biome.VOLCANO, [MysteryEncounterType.FIGHT_OR_FLIGHT]],
|
||||
|
@ -64,9 +64,9 @@ describe("Mysterious Challengers - Mystery Encounter", () => {
|
|||
expect(MysteriousChallengersEncounter.encounterTier).toBe(MysteryEncounterTier.GREAT);
|
||||
expect(MysteriousChallengersEncounter.dialogue).toBeDefined();
|
||||
expect(MysteriousChallengersEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}.intro` }]);
|
||||
expect(MysteriousChallengersEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(MysteriousChallengersEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(MysteriousChallengersEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(MysteriousChallengersEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(MysteriousChallengersEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(MysteriousChallengersEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(MysteriousChallengersEncounter.options.length).toBe(3);
|
||||
});
|
||||
|
||||
|
@ -105,7 +105,7 @@ describe("Mysterious Challengers - Mystery Encounter", () => {
|
|||
expect(encounter.onInit).toBeDefined();
|
||||
|
||||
encounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
expect(encounter.enemyPartyConfigs).toBeDefined();
|
||||
expect(encounter.enemyPartyConfigs.length).toBe(3);
|
||||
|
@ -125,11 +125,11 @@ describe("Mysterious Challengers - Mystery Encounter", () => {
|
|||
female: expect.any(Boolean),
|
||||
}
|
||||
]);
|
||||
expect(encounter.enemyPartyConfigs[1].trainerConfig.partyTemplates[0]).toEqual(new TrainerPartyCompoundTemplate(
|
||||
expect(encounter.enemyPartyConfigs[1].trainerConfig?.partyTemplates[0]).toEqual(new TrainerPartyCompoundTemplate(
|
||||
new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER, false, true),
|
||||
new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE, false, true)
|
||||
));
|
||||
expect(encounter.enemyPartyConfigs[2].trainerConfig.partyTemplates[0]).toEqual(new TrainerPartyCompoundTemplate(
|
||||
expect(encounter.enemyPartyConfigs[2].trainerConfig?.partyTemplates[0]).toEqual(new TrainerPartyCompoundTemplate(
|
||||
new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE),
|
||||
new TrainerPartyTemplate(3, PartyMemberStrength.STRONG),
|
||||
new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER))
|
||||
|
@ -157,19 +157,19 @@ describe("Mysterious Challengers - Mystery Encounter", () => {
|
|||
|
||||
it("should start battle against the trainer", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(scene.currentBattle.mysteryEncounter.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE);
|
||||
});
|
||||
|
||||
it("should have normal trainer rewards after battle", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
@ -199,19 +199,19 @@ describe("Mysterious Challengers - Mystery Encounter", () => {
|
|||
|
||||
it("should start battle against the trainer", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 2, null, true);
|
||||
await runMysteryEncounterToEnd(game, 2, undefined, true);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(scene.currentBattle.mysteryEncounter.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE);
|
||||
});
|
||||
|
||||
it("should have hard trainer rewards after battle", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 2, null, true);
|
||||
await runMysteryEncounterToEnd(game, 2, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
@ -242,19 +242,19 @@ describe("Mysterious Challengers - Mystery Encounter", () => {
|
|||
|
||||
it("should start battle against the trainer", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 3, null, true);
|
||||
await runMysteryEncounterToEnd(game, 3, undefined, true);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(scene.currentBattle.mysteryEncounter.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE);
|
||||
});
|
||||
|
||||
it("should have brutal trainer rewards after battle", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 3, null, true);
|
||||
await runMysteryEncounterToEnd(game, 3, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
|
|
@ -36,7 +36,7 @@ describe("Part-Timer - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
const biomeMap = new Map<Biome, MysteryEncounterType[]>([
|
||||
[Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]],
|
||||
|
@ -66,9 +66,9 @@ describe("Part-Timer - Mystery Encounter", () => {
|
|||
text: `${namespace}.intro_dialogue`,
|
||||
}
|
||||
]);
|
||||
expect(PartTimerEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(PartTimerEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(PartTimerEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(PartTimerEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(PartTimerEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(PartTimerEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(PartTimerEncounter.options.length).toBe(3);
|
||||
});
|
||||
|
||||
|
@ -127,7 +127,7 @@ describe("Part-Timer - Mystery Encounter", () => {
|
|||
// Expect PP of mon's moves to have been reduced to 2
|
||||
const moves = scene.getParty()[0].moveset;
|
||||
for (const move of moves) {
|
||||
expect(move.getMovePp() - move.ppUsed).toBe(2);
|
||||
expect((move?.getMovePp() ?? 0) - (move?.ppUsed ?? 0)).toBe(2);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -147,7 +147,7 @@ describe("Part-Timer - Mystery Encounter", () => {
|
|||
// Expect PP of mon's moves to have been reduced to 2
|
||||
const moves = scene.getParty()[1].moveset;
|
||||
for (const move of moves) {
|
||||
expect(move.getMovePp() - move.ppUsed).toBe(2);
|
||||
expect((move?.getMovePp() ?? 0) - (move?.ppUsed ?? 0)).toBe(2);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -192,7 +192,7 @@ describe("Part-Timer - Mystery Encounter", () => {
|
|||
// Expect PP of mon's moves to have been reduced to 2
|
||||
const moves = scene.getParty()[2].moveset;
|
||||
for (const move of moves) {
|
||||
expect(move.getMovePp() - move.ppUsed).toBe(2);
|
||||
expect((move?.getMovePp() ?? 0) - (move?.ppUsed ?? 0)).toBe(2);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -212,7 +212,7 @@ describe("Part-Timer - Mystery Encounter", () => {
|
|||
// Expect PP of mon's moves to have been reduced to 2
|
||||
const moves = scene.getParty()[3].moveset;
|
||||
for (const move of moves) {
|
||||
expect(move.getMovePp() - move.ppUsed).toBe(2);
|
||||
expect((move?.getMovePp() ?? 0) - (move?.ppUsed ?? 0)).toBe(2);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -252,7 +252,7 @@ describe("Part-Timer - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
|
||||
const encounterPhase = scene.getCurrentPhase();
|
||||
expect(encounterPhase.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
const mysteryEncounterPhase = encounterPhase as MysteryEncounterPhase;
|
||||
vi.spyOn(mysteryEncounterPhase, "continueEncounter");
|
||||
vi.spyOn(mysteryEncounterPhase, "handleOptionSelect");
|
||||
|
@ -260,7 +260,7 @@ describe("Part-Timer - Mystery Encounter", () => {
|
|||
|
||||
await runSelectMysteryEncounterOption(game, 3);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled
|
||||
expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled();
|
||||
expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled();
|
||||
|
@ -279,7 +279,7 @@ describe("Part-Timer - Mystery Encounter", () => {
|
|||
// Expect PP of mon's moves to have been reduced to 2
|
||||
const moves = scene.getParty()[0].moveset;
|
||||
for (const move of moves) {
|
||||
expect(move.getMovePp() - move.ppUsed).toBe(2);
|
||||
expect((move?.getMovePp() ?? 0) - (move?.ppUsed ?? 0)).toBe(2);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
const biomeMap = new Map<Biome, MysteryEncounterType[]>([
|
||||
[Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]],
|
||||
|
@ -62,9 +62,9 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||
{ text: `${namespace}.intro` },
|
||||
{ speaker: `${namespace}.speaker`, text: `${namespace}.intro_dialogue` }
|
||||
]);
|
||||
expect(ThePokemonSalesmanEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(ThePokemonSalesmanEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(ThePokemonSalesmanEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(ThePokemonSalesmanEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(ThePokemonSalesmanEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(ThePokemonSalesmanEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(ThePokemonSalesmanEncounter.options.length).toBe(2);
|
||||
});
|
||||
|
||||
|
@ -101,7 +101,7 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||
expect(ThePokemonSalesmanEncounter.onInit).toBeDefined();
|
||||
|
||||
ThePokemonSalesmanEncounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
expect(ThePokemonSalesmanEncounter.dialogueTokens?.purchasePokemon).toBeDefined();
|
||||
expect(ThePokemonSalesmanEncounter.dialogueTokens?.price).toBeDefined();
|
||||
|
@ -167,7 +167,7 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
|
||||
const encounterPhase = scene.getCurrentPhase();
|
||||
expect(encounterPhase.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
const mysteryEncounterPhase = encounterPhase as MysteryEncounterPhase;
|
||||
vi.spyOn(mysteryEncounterPhase, "continueEncounter");
|
||||
vi.spyOn(mysteryEncounterPhase, "handleOptionSelect");
|
||||
|
@ -175,7 +175,7 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||
|
||||
await runSelectMysteryEncounterOption(game, 1);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled
|
||||
expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled();
|
||||
expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled();
|
||||
|
|
|
@ -11,7 +11,6 @@ import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } f
|
|||
import { CommandPhase, MovePhase, SelectModifierPhase } from "#app/phases";
|
||||
import { Moves } from "#enums/moves";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import * as Modifiers from "#app/modifier/modifier";
|
||||
import { TheStrongStuffEncounter } from "#app/data/mystery-encounters/encounters/the-strong-stuff-encounter";
|
||||
import { Nature } from "#app/data/nature";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
|
@ -19,7 +18,7 @@ import { BattlerTagType } from "#enums/battler-tag-type";
|
|||
import { PokemonMove } from "#app/field/pokemon";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
||||
import { PokemonBaseStatTotalModifier } from "#app/modifier/modifier";
|
||||
import { BerryModifier, PokemonBaseStatTotalModifier } from "#app/modifier/modifier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils";
|
||||
|
@ -45,7 +44,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
|
@ -68,9 +67,9 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||
expect(TheStrongStuffEncounter.encounterTier).toBe(MysteryEncounterTier.COMMON);
|
||||
expect(TheStrongStuffEncounter.dialogue).toBeDefined();
|
||||
expect(TheStrongStuffEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}.intro` }]);
|
||||
expect(TheStrongStuffEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(TheStrongStuffEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(TheStrongStuffEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(TheStrongStuffEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(TheStrongStuffEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(TheStrongStuffEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(TheStrongStuffEncounter.options.length).toBe(2);
|
||||
});
|
||||
|
||||
|
@ -109,7 +108,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||
expect(TheStrongStuffEncounter.onInit).toBeDefined();
|
||||
|
||||
TheStrongStuffEncounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
expect(TheStrongStuffEncounter.enemyPartyConfigs).toEqual([
|
||||
{
|
||||
|
@ -198,19 +197,19 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||
const phaseSpy = vi.spyOn(scene, "pushPhase");
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.THE_STRONG_STUFF, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 2, null, true);
|
||||
await runMysteryEncounterToEnd(game, 2, undefined, true);
|
||||
|
||||
const enemyField = scene.getEnemyField();
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(enemyField.length).toBe(1);
|
||||
expect(enemyField[0].species.speciesId).toBe(Species.SHUCKLE);
|
||||
expect(enemyField[0].summonData.battleStats).toEqual([0, 2, 0, 2, 0, 0, 0]);
|
||||
const shuckleItems = scene.getModifiers(Modifiers.BerryModifier, false);
|
||||
const shuckleItems = enemyField[0].getHeldItems();
|
||||
expect(shuckleItems.length).toBe(4);
|
||||
expect(shuckleItems.find(m => m.berryType === BerryType.SITRUS)?.stackCount).toBe(1);
|
||||
expect(shuckleItems.find(m => m.berryType === BerryType.GANLON)?.stackCount).toBe(1);
|
||||
expect(shuckleItems.find(m => m.berryType === BerryType.APICOT)?.stackCount).toBe(1);
|
||||
expect(shuckleItems.find(m => m.berryType === BerryType.LUM)?.stackCount).toBe(2);
|
||||
expect(shuckleItems.find(m => m instanceof BerryModifier && m.berryType === BerryType.SITRUS)?.stackCount).toBe(1);
|
||||
expect(shuckleItems.find(m => m instanceof BerryModifier && m.berryType === BerryType.GANLON)?.stackCount).toBe(1);
|
||||
expect(shuckleItems.find(m => m instanceof BerryModifier && m.berryType === BerryType.APICOT)?.stackCount).toBe(1);
|
||||
expect(shuckleItems.find(m => m instanceof BerryModifier && m.berryType === BerryType.LUM)?.stackCount).toBe(2);
|
||||
expect(enemyField[0].moveset).toEqual([new PokemonMove(Moves.INFESTATION), new PokemonMove(Moves.SALT_CURE), new PokemonMove(Moves.GASTRO_ACID), new PokemonMove(Moves.HEAL_ORDER)]);
|
||||
|
||||
// Should have used moves pre-battle
|
||||
|
@ -222,10 +221,10 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||
|
||||
it("should have Soul Dew in rewards", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.THE_STRONG_STUFF, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 2, null, true);
|
||||
await runMysteryEncounterToEnd(game, 2, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
|
|
@ -43,7 +43,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
const biomeMap = new Map<Biome, MysteryEncounterType[]>([
|
||||
[Biome.VOLCANO, [MysteryEncounterType.FIGHT_OR_FLIGHT]],
|
||||
|
@ -73,9 +73,9 @@ describe("The Winstrate Challenge - Mystery Encounter", () => {
|
|||
text: `${namespace}.intro_dialogue`,
|
||||
}
|
||||
]);
|
||||
expect(TheWinstrateChallengeEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(TheWinstrateChallengeEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(TheWinstrateChallengeEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(TheWinstrateChallengeEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(TheWinstrateChallengeEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(TheWinstrateChallengeEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(TheWinstrateChallengeEncounter.options.length).toBe(2);
|
||||
});
|
||||
|
||||
|
@ -114,7 +114,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => {
|
|||
expect(encounter.onInit).toBeDefined();
|
||||
|
||||
encounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
expect(encounter.enemyPartyConfigs).toBeDefined();
|
||||
expect(encounter.enemyPartyConfigs.length).toBe(5);
|
||||
|
@ -273,42 +273,42 @@ describe("The Winstrate Challenge - Mystery Encounter", () => {
|
|||
|
||||
it("should battle all 5 trainers for a Macho Brace reward", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.THE_WINSTRATE_CHALLENGE, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1, null, true);
|
||||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(scene.currentBattle.trainer.config.trainerType).toBe(TrainerType.VICTOR);
|
||||
expect(scene.currentBattle.trainer!.config.trainerType).toBe(TrainerType.VICTOR);
|
||||
expect(scene.currentBattle.mysteryEncounter.enemyPartyConfigs.length).toBe(4);
|
||||
expect(scene.currentBattle.mysteryEncounter.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE);
|
||||
|
||||
await skipBattleToNextBattle(game);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(scene.currentBattle.trainer.config.trainerType).toBe(TrainerType.VICTORIA);
|
||||
expect(scene.currentBattle.trainer!.config.trainerType).toBe(TrainerType.VICTORIA);
|
||||
expect(scene.currentBattle.mysteryEncounter.enemyPartyConfigs.length).toBe(3);
|
||||
expect(scene.currentBattle.mysteryEncounter.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE);
|
||||
|
||||
await skipBattleToNextBattle(game);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(scene.currentBattle.trainer.config.trainerType).toBe(TrainerType.VIVI);
|
||||
expect(scene.currentBattle.trainer!.config.trainerType).toBe(TrainerType.VIVI);
|
||||
expect(scene.currentBattle.mysteryEncounter.enemyPartyConfigs.length).toBe(2);
|
||||
expect(scene.currentBattle.mysteryEncounter.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE);
|
||||
|
||||
await skipBattleToNextBattle(game);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(scene.currentBattle.trainer.config.trainerType).toBe(TrainerType.VICKY);
|
||||
expect(scene.currentBattle.trainer!.config.trainerType).toBe(TrainerType.VICKY);
|
||||
expect(scene.currentBattle.mysteryEncounter.enemyPartyConfigs.length).toBe(1);
|
||||
expect(scene.currentBattle.mysteryEncounter.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE);
|
||||
|
||||
await skipBattleToNextBattle(game);
|
||||
expect(scene.currentBattle.trainer).toBeDefined();
|
||||
expect(scene.currentBattle.trainer.config.trainerType).toBe(TrainerType.VITO);
|
||||
expect(scene.currentBattle.trainer!.config.trainerType).toBe(TrainerType.VITO);
|
||||
expect(scene.currentBattle.mysteryEncounter.enemyPartyConfigs.length).toBe(0);
|
||||
expect(scene.currentBattle.mysteryEncounter.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE);
|
||||
|
||||
// Should have Macho Brace in the rewards
|
||||
await skipBattleToNextBattle(game, true);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
@ -348,7 +348,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => {
|
|||
it("should have a Rarer Candy in the rewards", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.THE_WINSTRATE_CHALLENGE, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 2);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
|
|
@ -41,7 +41,7 @@ describe("Trash to Treasure - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
|
@ -63,9 +63,9 @@ describe("Trash to Treasure - Mystery Encounter", () => {
|
|||
expect(TrashToTreasureEncounter.encounterTier).toBe(MysteryEncounterTier.ULTRA);
|
||||
expect(TrashToTreasureEncounter.dialogue).toBeDefined();
|
||||
expect(TrashToTreasureEncounter.dialogue.intro).toStrictEqual([{ text: `${namespace}.intro` }]);
|
||||
expect(TrashToTreasureEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(TrashToTreasureEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(TrashToTreasureEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(TrashToTreasureEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(TrashToTreasureEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(TrashToTreasureEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(TrashToTreasureEncounter.options.length).toBe(2);
|
||||
});
|
||||
|
||||
|
@ -96,7 +96,7 @@ describe("Trash to Treasure - Mystery Encounter", () => {
|
|||
expect(TrashToTreasureEncounter.onInit).toBeDefined();
|
||||
|
||||
TrashToTreasureEncounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
expect(TrashToTreasureEncounter.enemyPartyConfigs).toEqual([
|
||||
{
|
||||
|
@ -138,19 +138,19 @@ describe("Trash to Treasure - Mystery Encounter", () => {
|
|||
await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
|
||||
const leftovers = scene.findModifier(m => m instanceof TurnHealModifier) as TurnHealModifier;
|
||||
expect(leftovers).toBeDefined();
|
||||
expect(leftovers.stackCount).toBe(2);
|
||||
expect(leftovers?.stackCount).toBe(2);
|
||||
|
||||
const shellBell = scene.findModifier(m => m instanceof HitHealModifier) as HitHealModifier;
|
||||
expect(shellBell).toBeDefined();
|
||||
expect(shellBell.stackCount).toBe(2);
|
||||
expect(shellBell?.stackCount).toBe(2);
|
||||
|
||||
const blackSludge = scene.findModifier(m => m instanceof RemoveHealShopModifier) as RemoveHealShopModifier;
|
||||
expect(blackSludge).toBeDefined();
|
||||
expect(blackSludge.stackCount).toBe(1);
|
||||
expect(blackSludge?.stackCount).toBe(1);
|
||||
});
|
||||
|
||||
it("should leave encounter without battle", async () => {
|
||||
|
@ -183,10 +183,10 @@ describe("Trash to Treasure - Mystery Encounter", () => {
|
|||
const phaseSpy = vi.spyOn(scene, "pushPhase");
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 2, null, true);
|
||||
await runMysteryEncounterToEnd(game, 2, undefined, true);
|
||||
|
||||
const enemyField = scene.getEnemyField();
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(enemyField.length).toBe(1);
|
||||
expect(enemyField[0].species.speciesId).toBe(Species.GARBODOR);
|
||||
expect(enemyField[0].moveset).toEqual([new PokemonMove(Moves.PAYBACK), new PokemonMove(Moves.GUNK_SHOT), new PokemonMove(Moves.STOMPING_TANTRUM), new PokemonMove(Moves.DRAIN_PUNCH)]);
|
||||
|
@ -200,10 +200,10 @@ describe("Trash to Treasure - Mystery Encounter", () => {
|
|||
|
||||
it("should have 2 Rogue, 1 Ultra, 1 Great in rewards", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 2, null, true);
|
||||
await runMysteryEncounterToEnd(game, 2, undefined, true);
|
||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
|
|
@ -36,7 +36,7 @@ describe("Weird Dream - Mystery Encounter", () => {
|
|||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves(true);
|
||||
game.override.disableTrainerWaves();
|
||||
vi.spyOn(EncounterTransformationSequence, "doPokemonTransformationSequence").mockImplementation(() => new Promise<void>(resolve => resolve()));
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
|
@ -67,9 +67,9 @@ describe("Weird Dream - Mystery Encounter", () => {
|
|||
text: `${namespace}.intro_dialogue`,
|
||||
},
|
||||
]);
|
||||
expect(WeirdDreamEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}.title`);
|
||||
expect(WeirdDreamEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}.description`);
|
||||
expect(WeirdDreamEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}.query`);
|
||||
expect(WeirdDreamEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
|
||||
expect(WeirdDreamEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
|
||||
expect(WeirdDreamEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
|
||||
expect(WeirdDreamEncounter.options.length).toBe(2);
|
||||
});
|
||||
|
||||
|
@ -99,7 +99,7 @@ describe("Weird Dream - Mystery Encounter", () => {
|
|||
expect(WeirdDreamEncounter.onInit).toBeDefined();
|
||||
|
||||
WeirdDreamEncounter.populateDialogueTokensFromRequirements(scene);
|
||||
const onInitResult = onInit(scene);
|
||||
const onInitResult = onInit!(scene);
|
||||
|
||||
expect(loadBgmSpy).toHaveBeenCalled();
|
||||
expect(onInitResult).toBe(true);
|
||||
|
@ -129,7 +129,7 @@ describe("Weird Dream - Mystery Encounter", () => {
|
|||
|
||||
await runMysteryEncounterToEnd(game, 1);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
|
||||
const pokemonAfter = scene.getParty();
|
||||
const bstsAfter = pokemonAfter.map(pokemon => pokemon.getSpeciesForm().getBaseStatTotal());
|
||||
|
@ -138,7 +138,7 @@ describe("Weird Dream - Mystery Encounter", () => {
|
|||
for (let i = 0; i < pokemonAfter.length; i++) {
|
||||
const newPokemon = pokemonAfter[i];
|
||||
expect(newPokemon.getSpeciesForm().speciesId).not.toBe(pokemonPrior[i].getSpeciesForm().speciesId);
|
||||
expect(newPokemon.mysteryEncounterData.types.length).toBe(2);
|
||||
expect(newPokemon.mysteryEncounterData?.types.length).toBe(2);
|
||||
}
|
||||
|
||||
const plus90To110 = bstDiff.filter(bst => bst > 80);
|
||||
|
@ -152,7 +152,7 @@ describe("Weird Dream - Mystery Encounter", () => {
|
|||
await game.runToMysteryEncounter(MysteryEncounterType.WEIRD_DREAM, defaultParty);
|
||||
await runMysteryEncounterToEnd(game, 1);
|
||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
|
|
|
@ -230,7 +230,7 @@ describe("Mystery Encounter Utils", () => {
|
|||
|
||||
it("gets species of specified types", () => {
|
||||
// Only 9 tiers are: Koraidon, Miraidon, Arceus, Rayquaza, Kyogre, Groudon, Zacian
|
||||
const result = getRandomSpeciesByStarterTier(9, null, [Type.GROUND]);
|
||||
const result = getRandomSpeciesByStarterTier(9, undefined, [Type.GROUND]);
|
||||
const pokeSpecies = getPokemonSpecies(result);
|
||||
expect(pokeSpecies.speciesId).toBe(Species.GROUDON);
|
||||
});
|
||||
|
|
|
@ -29,14 +29,14 @@ describe("Mystery Encounters", () => {
|
|||
await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, [Species.CHARIZARD, Species.VOLCARONA]);
|
||||
|
||||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
expect(game.scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(game.scene.getCurrentPhase()!.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
});
|
||||
|
||||
it("", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, [Species.CHARIZARD, Species.VOLCARONA]);
|
||||
|
||||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
expect(game.scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(game.scene.getCurrentPhase()!.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
});
|
||||
|
||||
it("spawns mysterious challengers encounter", async () => {
|
||||
|
|
|
@ -37,7 +37,7 @@ describe("Mystery Encounter Phases", () => {
|
|||
await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, [Species.CHARIZARD, Species.VOLCARONA]);
|
||||
|
||||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
expect(game.scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
expect(game.scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||
});
|
||||
|
||||
it("Runs MysteryEncounterPhase", async() => {
|
||||
|
@ -73,7 +73,7 @@ describe("Mystery Encounter Phases", () => {
|
|||
handler.processInput(Button.ACTION);
|
||||
|
||||
// Waitfor required so that option select messages and preOptionPhase logic are handled
|
||||
await vi.waitFor(() => expect(game.scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterOptionSelectedPhase.name));
|
||||
await vi.waitFor(() => expect(game.scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterOptionSelectedPhase.name));
|
||||
expect(game.scene.ui.getMode()).toBe(Mode.MESSAGE);
|
||||
expect(dialogueSpy).toHaveBeenCalledTimes(1);
|
||||
expect(messageSpy).toHaveBeenCalledTimes(2);
|
||||
|
|
|
@ -28,12 +28,6 @@ describe("SelectModifierPhase", () => {
|
|||
game = new GameManager(phaserGame);
|
||||
scene = game.scene;
|
||||
|
||||
vi.spyOn(scene, "resetSeed").mockImplementation(() => {
|
||||
scene.waveSeed = "test";
|
||||
Phaser.Math.RND.sow([scene.waveSeed]);
|
||||
scene.rngCounter = 0;
|
||||
});
|
||||
|
||||
initSceneWithoutEncounterPhase(scene, [Species.ABRA, Species.VOLCARONA]);
|
||||
});
|
||||
|
||||
|
@ -49,7 +43,7 @@ describe("SelectModifierPhase", () => {
|
|||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
}, 20000);
|
||||
});
|
||||
|
||||
it("should generate random modifiers", async () => {
|
||||
const selectModifierPhase = new SelectModifierPhase(scene);
|
||||
|
@ -60,10 +54,7 @@ describe("SelectModifierPhase", () => {
|
|||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler;
|
||||
expect(modifierSelectHandler.options.length).toEqual(3);
|
||||
expect(modifierSelectHandler.options[0].modifierTypeOption.type.id).toEqual("TEMP_STAT_BOOSTER");
|
||||
expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toEqual("POKEBALL");
|
||||
expect(modifierSelectHandler.options[2].modifierTypeOption.type.id).toEqual("BERRY");
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
it("should modify reroll cost", async () => {
|
||||
const options = [
|
||||
|
@ -73,12 +64,12 @@ describe("SelectModifierPhase", () => {
|
|||
];
|
||||
|
||||
const selectModifierPhase1 = new SelectModifierPhase(scene);
|
||||
const selectModifierPhase2 = new SelectModifierPhase(scene, 0, null, { rerollMultiplier: 2 });
|
||||
const selectModifierPhase2 = new SelectModifierPhase(scene, 0, undefined, { rerollMultiplier: 2 });
|
||||
|
||||
const cost1 = selectModifierPhase1.getRerollCost(options, false);
|
||||
const cost2 = selectModifierPhase2.getRerollCost(options, false);
|
||||
expect(cost2).toEqual(cost1 * 2);
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
it("should generate random modifiers from reroll", async () => {
|
||||
let selectModifierPhase = new SelectModifierPhase(scene);
|
||||
|
@ -88,9 +79,6 @@ describe("SelectModifierPhase", () => {
|
|||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler;
|
||||
expect(modifierSelectHandler.options.length).toEqual(3);
|
||||
expect(modifierSelectHandler.options[0].modifierTypeOption.type.id).toEqual("TEMP_STAT_BOOSTER");
|
||||
expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toEqual("POKEBALL");
|
||||
expect(modifierSelectHandler.options[2].modifierTypeOption.type.id).toEqual("BERRY");
|
||||
|
||||
// Simulate selecting reroll
|
||||
selectModifierPhase = new SelectModifierPhase(scene, 1, [ModifierTier.COMMON, ModifierTier.COMMON, ModifierTier.COMMON]);
|
||||
|
@ -100,10 +88,7 @@ describe("SelectModifierPhase", () => {
|
|||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
expect(modifierSelectHandler.options.length).toEqual(3);
|
||||
expect(modifierSelectHandler.options[0].modifierTypeOption.type.id).toEqual("TM_COMMON");
|
||||
expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toEqual("LURE");
|
||||
expect(modifierSelectHandler.options[2].modifierTypeOption.type.id).toEqual("PP_UP");
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
it("should generate random modifiers of same tier for reroll with reroll lock", async () => {
|
||||
// Just use fully random seed for this test
|
||||
|
@ -137,13 +122,13 @@ describe("SelectModifierPhase", () => {
|
|||
expect(modifierSelectHandler.options[0].modifierTypeOption.type.tier - modifierSelectHandler.options[0].modifierTypeOption.upgradeCount).toEqual(firstRollTiers[0]);
|
||||
expect(modifierSelectHandler.options[1].modifierTypeOption.type.tier - modifierSelectHandler.options[1].modifierTypeOption.upgradeCount).toEqual(firstRollTiers[1]);
|
||||
expect(modifierSelectHandler.options[2].modifierTypeOption.type.tier - modifierSelectHandler.options[2].modifierTypeOption.upgradeCount).toEqual(firstRollTiers[2]);
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
it("should generate custom modifiers", async () => {
|
||||
const customModifiers: CustomModifierSettings = {
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.MEMORY_MUSHROOM, modifierTypes.TM_ULTRA, modifierTypes.LEFTOVERS, modifierTypes.AMULET_COIN, modifierTypes.GOLDEN_PUNCH]
|
||||
};
|
||||
const selectModifierPhase = new SelectModifierPhase(scene, 0, null, customModifiers);
|
||||
const selectModifierPhase = new SelectModifierPhase(scene, 0, undefined, customModifiers);
|
||||
scene.pushPhase(selectModifierPhase);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
|
@ -156,7 +141,7 @@ describe("SelectModifierPhase", () => {
|
|||
expect(modifierSelectHandler.options[2].modifierTypeOption.type.id).toEqual("LEFTOVERS");
|
||||
expect(modifierSelectHandler.options[3].modifierTypeOption.type.id).toEqual("AMULET_COIN");
|
||||
expect(modifierSelectHandler.options[4].modifierTypeOption.type.id).toEqual("GOLDEN_PUNCH");
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
it("should generate custom modifier tiers that can upgrade from luck", async () => {
|
||||
const customModifiers: CustomModifierSettings = {
|
||||
|
@ -170,7 +155,7 @@ describe("SelectModifierPhase", () => {
|
|||
}
|
||||
scene.getParty().push(pokemon, pokemon, pokemon, pokemon, pokemon, pokemon);
|
||||
|
||||
const selectModifierPhase = new SelectModifierPhase(scene, 0, null, customModifiers);
|
||||
const selectModifierPhase = new SelectModifierPhase(scene, 0, undefined, customModifiers);
|
||||
scene.pushPhase(selectModifierPhase);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
|
@ -183,14 +168,14 @@ describe("SelectModifierPhase", () => {
|
|||
expect(modifierSelectHandler.options[2].modifierTypeOption.type.tier - modifierSelectHandler.options[2].modifierTypeOption.upgradeCount).toEqual(ModifierTier.ULTRA);
|
||||
expect(modifierSelectHandler.options[3].modifierTypeOption.type.tier - modifierSelectHandler.options[3].modifierTypeOption.upgradeCount).toEqual(ModifierTier.ROGUE);
|
||||
expect(modifierSelectHandler.options[4].modifierTypeOption.type.tier - modifierSelectHandler.options[4].modifierTypeOption.upgradeCount).toEqual(ModifierTier.MASTER);
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
it("should generate custom modifiers and modifier tiers together", async () => {
|
||||
const customModifiers: CustomModifierSettings = {
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.MEMORY_MUSHROOM, modifierTypes.TM_COMMON],
|
||||
guaranteedModifierTiers: [ModifierTier.MASTER, ModifierTier.MASTER]
|
||||
};
|
||||
const selectModifierPhase = new SelectModifierPhase(scene, 0, null, customModifiers);
|
||||
const selectModifierPhase = new SelectModifierPhase(scene, 0, undefined, customModifiers);
|
||||
scene.pushPhase(selectModifierPhase);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
|
@ -202,7 +187,7 @@ describe("SelectModifierPhase", () => {
|
|||
expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toEqual("TM_COMMON");
|
||||
expect(modifierSelectHandler.options[2].modifierTypeOption.type.tier).toEqual(ModifierTier.MASTER);
|
||||
expect(modifierSelectHandler.options[3].modifierTypeOption.type.tier).toEqual(ModifierTier.MASTER);
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
it("should fill remaining modifiers if fillRemaining is true with custom modifiers", async () => {
|
||||
const customModifiers: CustomModifierSettings = {
|
||||
|
@ -210,7 +195,7 @@ describe("SelectModifierPhase", () => {
|
|||
guaranteedModifierTiers: [ModifierTier.MASTER],
|
||||
fillRemaining: true
|
||||
};
|
||||
const selectModifierPhase = new SelectModifierPhase(scene, 0, null, customModifiers);
|
||||
const selectModifierPhase = new SelectModifierPhase(scene, 0, undefined, customModifiers);
|
||||
scene.pushPhase(selectModifierPhase);
|
||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||
|
||||
|
@ -220,5 +205,5 @@ describe("SelectModifierPhase", () => {
|
|||
expect(modifierSelectHandler.options.length).toEqual(3);
|
||||
expect(modifierSelectHandler.options[0].modifierTypeOption.type.id).toEqual("MEMORY_MUSHROOM");
|
||||
expect(modifierSelectHandler.options[1].modifierTypeOption.type.tier).toEqual(ModifierTier.MASTER);
|
||||
}, 5000);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -171,8 +171,8 @@ export default class GameManager {
|
|||
*/
|
||||
async runToMysteryEncounter(encounterType?: MysteryEncounterType, species?: Species[]) {
|
||||
if (!isNullOrUndefined(encounterType)) {
|
||||
this.override.disableTrainerWaves(true);
|
||||
this.override.mysteryEncounter(encounterType);
|
||||
this.override.disableTrainerWaves();
|
||||
this.override.mysteryEncounter(encounterType!);
|
||||
}
|
||||
|
||||
await this.runToTitle();
|
||||
|
|
|
@ -108,5 +108,5 @@ export function initSceneWithoutEncounterPhase(scene, species?: Species[]) {
|
|||
scene.getParty().push(starterPokemon);
|
||||
});
|
||||
|
||||
scene.currentBattle = new Battle(getGameMode(GameModes.CLASSIC), 5, BattleType.WILD, null, false);
|
||||
scene.currentBattle = new Battle(getGameMode(GameModes.CLASSIC), 5, BattleType.WILD, undefined, false);
|
||||
}
|
||||
|
|
|
@ -8,8 +8,10 @@ import * as GameMode from "#app/game-mode";
|
|||
import { GameModes, getGameMode } from "#app/game-mode";
|
||||
import { ModifierOverride } from "#app/modifier/modifier-type.js";
|
||||
import Overrides from "#app/overrides";
|
||||
import { vi } from "vitest";
|
||||
import { MockInstance, vi } from "vitest";
|
||||
import { GameManagerHelper } from "./gameManagerHelper";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
|
||||
/**
|
||||
* Helper to handle overrides in tests
|
||||
|
@ -281,6 +283,41 @@ export class OverridesHelper extends GameManagerHelper {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the encounter chance for a mystery encounter.
|
||||
* @param percentage the encounter chance in %
|
||||
* @returns spy instance
|
||||
*/
|
||||
mysteryEncounterChance(percentage: number) {
|
||||
const maxRate: number = 256; // 100%
|
||||
const rate = maxRate * (percentage / 100);
|
||||
const spy = vi.spyOn(Overrides, "MYSTERY_ENCOUNTER_RATE_OVERRIDE", "get").mockReturnValue(rate);
|
||||
this.log(`Mystery encounter chance set to ${percentage}% (=${rate})!`);
|
||||
return spy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the encounter chance for a mystery encounter.
|
||||
* @returns spy instance
|
||||
* @param tier
|
||||
*/
|
||||
mysteryEncounterTier(tier: MysteryEncounterTier): MockInstance {
|
||||
const spy = vi.spyOn(Overrides, "MYSTERY_ENCOUNTER_TIER_OVERRIDE", "get").mockReturnValue(tier);
|
||||
this.log(`Mystery encounter tier set to ${tier}!`);
|
||||
return spy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the encounter that spawns for the scene
|
||||
* @param encounterType
|
||||
* @returns spy instance
|
||||
*/
|
||||
mysteryEncounter(encounterType: MysteryEncounterType) {
|
||||
const spy = vi.spyOn(Overrides, "MYSTERY_ENCOUNTER_OVERRIDE", "get").mockReturnValue(encounterType);
|
||||
this.log(`Mystery encounter override set to ${encounterType}!`);
|
||||
return spy;
|
||||
}
|
||||
|
||||
private log(...params: any[]) {
|
||||
console.log("Overrides:", ...params);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export interface MockGameObject {
|
||||
|
||||
name: string;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ export default class MockContainer implements MockGameObject {
|
|||
public frame;
|
||||
protected textureManager;
|
||||
public list: MockGameObject[] = [];
|
||||
private name?: string;
|
||||
name: string;
|
||||
|
||||
constructor(textureManager: MockTextureManager, x, y) {
|
||||
this.x = x;
|
||||
|
|
|
@ -3,6 +3,7 @@ import { MockGameObject } from "../mockGameObject";
|
|||
export default class MockGraphics implements MockGameObject {
|
||||
private scene;
|
||||
public list: MockGameObject[] = [];
|
||||
name: string;
|
||||
constructor(textureManager, config) {
|
||||
this.scene = textureManager.scene;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ export default class MockRectangle implements MockGameObject {
|
|||
private fillColor;
|
||||
private scene;
|
||||
public list: MockGameObject[] = [];
|
||||
name: string;
|
||||
|
||||
constructor(textureManager, x, y, width, height, fillColor) {
|
||||
this.fillColor = fillColor;
|
||||
|
|
|
@ -14,6 +14,7 @@ export default class MockSprite implements MockGameObject {
|
|||
public scene;
|
||||
public anims;
|
||||
public list: MockGameObject[] = [];
|
||||
name: string;
|
||||
constructor(textureManager, x, y, texture) {
|
||||
this.textureManager = textureManager;
|
||||
this.scene = textureManager.scene;
|
||||
|
|
|
@ -11,7 +11,7 @@ export default class MockText implements MockGameObject {
|
|||
public list: MockGameObject[] = [];
|
||||
public style;
|
||||
public text = "";
|
||||
private name?: string;
|
||||
name: string;
|
||||
public color?: string;
|
||||
|
||||
constructor(textureManager, x, y, content, styleOptions) {
|
||||
|
|
|
@ -12,6 +12,7 @@ export default class MockTexture implements MockGameObject {
|
|||
public source;
|
||||
public frames: object;
|
||||
public firstFrame: string;
|
||||
name: string;
|
||||
|
||||
constructor(manager, key: string, source) {
|
||||
this.manager = manager;
|
||||
|
|
|
@ -336,7 +336,7 @@ export default class PhaseInterceptor {
|
|||
const actionForNextPrompt = this.prompts[0];
|
||||
const expireFn = actionForNextPrompt.expireFn && actionForNextPrompt.expireFn();
|
||||
const currentMode = this.scene.ui.getMode();
|
||||
const currentPhase = this.scene.getCurrentPhase().constructor.name;
|
||||
const currentPhase = this.scene.getCurrentPhase()?.constructor.name;
|
||||
const currentHandler = this.scene.ui.getHandler();
|
||||
if (expireFn) {
|
||||
this.prompts.shift();
|
||||
|
|
|
@ -18,24 +18,24 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
|||
|
||||
export default class MysteryEncounterUiHandler extends UiHandler {
|
||||
private cursorContainer: Phaser.GameObjects.Container;
|
||||
private cursorObj: Phaser.GameObjects.Image;
|
||||
private cursorObj?: Phaser.GameObjects.Image;
|
||||
|
||||
private optionsContainer: Phaser.GameObjects.Container;
|
||||
|
||||
private tooltipWindow: Phaser.GameObjects.NineSlice;
|
||||
private tooltipContainer: Phaser.GameObjects.Container;
|
||||
private tooltipScrollTween: Phaser.Tweens.Tween;
|
||||
private tooltipScrollTween?: Phaser.Tweens.Tween;
|
||||
|
||||
private descriptionWindow: Phaser.GameObjects.NineSlice;
|
||||
private descriptionContainer: Phaser.GameObjects.Container;
|
||||
private descriptionScrollTween: Phaser.Tweens.Tween;
|
||||
private descriptionScrollTween?: Phaser.Tweens.Tween;
|
||||
private rarityBall: Phaser.GameObjects.Sprite;
|
||||
|
||||
private dexProgressWindow: Phaser.GameObjects.NineSlice;
|
||||
private dexProgressContainer: Phaser.GameObjects.Container;
|
||||
private showDexProgress: boolean = false;
|
||||
|
||||
private overrideSettings: OptionSelectSettings;
|
||||
private overrideSettings?: OptionSelectSettings;
|
||||
private encounterOptions: MysteryEncounterOption[] = [];
|
||||
private optionsMeetsReqs: boolean[];
|
||||
|
||||
|
@ -330,9 +330,9 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||
this.encounterOptions = this.overrideSettings?.overrideOptions ?? mysteryEncounter.options;
|
||||
this.optionsMeetsReqs = [];
|
||||
|
||||
const titleText: string = getEncounterText(this.scene, mysteryEncounter.dialogue.encounterOptionsDialogue.title, TextStyle.TOOLTIP_TITLE);
|
||||
const descriptionText: string = getEncounterText(this.scene, mysteryEncounter.dialogue.encounterOptionsDialogue.description, TextStyle.TOOLTIP_CONTENT);
|
||||
const queryText: string = getEncounterText(this.scene, mysteryEncounter.dialogue.encounterOptionsDialogue.query, TextStyle.TOOLTIP_CONTENT);
|
||||
const titleText: string | null = getEncounterText(this.scene, mysteryEncounter.dialogue.encounterOptionsDialogue?.title, TextStyle.TOOLTIP_TITLE);
|
||||
const descriptionText: string | null = getEncounterText(this.scene, mysteryEncounter.dialogue.encounterOptionsDialogue?.description, TextStyle.TOOLTIP_CONTENT);
|
||||
const queryText: string | null = getEncounterText(this.scene, mysteryEncounter.dialogue.encounterOptionsDialogue?.query, TextStyle.TOOLTIP_CONTENT);
|
||||
|
||||
// Clear options container (except cursor)
|
||||
this.optionsContainer.removeAll(true);
|
||||
|
@ -355,9 +355,9 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||
}
|
||||
|
||||
this.optionsMeetsReqs.push(option.meetsRequirements(this.scene));
|
||||
const optionDialogue = option.dialogue;
|
||||
const optionDialogue = option.dialogue!;
|
||||
const label = !this.optionsMeetsReqs[i] && optionDialogue.disabledButtonLabel ? optionDialogue.disabledButtonLabel : optionDialogue.buttonLabel;
|
||||
let text: string;
|
||||
let text: string | null;
|
||||
if (option.hasRequirements() && this.optionsMeetsReqs[i] && (option.optionMode === MysteryEncounterOptionMode.DEFAULT_OR_SPECIAL || option.optionMode === MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)) {
|
||||
// Options with special requirements that are met are automatically colored green
|
||||
text = getEncounterText(this.scene, label, TextStyle.SUMMARY_GREEN);
|
||||
|
@ -383,7 +383,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||
this.optionsContainer.add(viewPartyText);
|
||||
|
||||
// Description Window
|
||||
const titleTextObject = addBBCodeTextObject(this.scene, 0, 0, titleText, TextStyle.TOOLTIP_TITLE, { wordWrap: { width: 750 }, align: "center", lineSpacing: -8 });
|
||||
const titleTextObject = addBBCodeTextObject(this.scene, 0, 0, titleText ?? "", TextStyle.TOOLTIP_TITLE, { wordWrap: { width: 750 }, align: "center", lineSpacing: -8 });
|
||||
this.descriptionContainer.add(titleTextObject);
|
||||
titleTextObject.setPosition(72 - titleTextObject.displayWidth / 2, 5.5);
|
||||
|
||||
|
@ -395,7 +395,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||
const ballType = getPokeballAtlasKey(index);
|
||||
this.rarityBall.setTexture("pb", ballType);
|
||||
|
||||
const descriptionTextObject = addBBCodeTextObject(this.scene, 6, 25, descriptionText, TextStyle.TOOLTIP_CONTENT, { wordWrap: { width: 830 } });
|
||||
const descriptionTextObject = addBBCodeTextObject(this.scene, 6, 25, descriptionText ?? "", TextStyle.TOOLTIP_CONTENT, { wordWrap: { width: 830 } });
|
||||
|
||||
// Sets up the mask that hides the description text to give an illusion of scrolling
|
||||
const descriptionTextMaskRect = this.scene.make.graphics({});
|
||||
|
@ -412,7 +412,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||
|
||||
if (this.descriptionScrollTween) {
|
||||
this.descriptionScrollTween.remove();
|
||||
this.descriptionScrollTween = null;
|
||||
this.descriptionScrollTween = undefined;
|
||||
}
|
||||
|
||||
// Animates the description text moving upwards
|
||||
|
@ -429,7 +429,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||
|
||||
this.descriptionContainer.add(descriptionTextObject);
|
||||
|
||||
const queryTextObject = addBBCodeTextObject(this.scene, 0, 0, queryText, TextStyle.TOOLTIP_CONTENT, { wordWrap: { width: 830 } });
|
||||
const queryTextObject = addBBCodeTextObject(this.scene, 0, 0, queryText ?? "", TextStyle.TOOLTIP_CONTENT, { wordWrap: { width: 830 } });
|
||||
this.descriptionContainer.add(queryTextObject);
|
||||
queryTextObject.setPosition(75 - queryTextObject.displayWidth / 2, 90);
|
||||
|
||||
|
@ -460,9 +460,9 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
let text: string;
|
||||
let text: string | null;
|
||||
const cursorOption = this.encounterOptions[cursor];
|
||||
const optionDialogue = cursorOption.dialogue;
|
||||
const optionDialogue = cursorOption.dialogue!;
|
||||
if (!this.optionsMeetsReqs[cursor] && (cursorOption.optionMode === MysteryEncounterOptionMode.DISABLED_OR_DEFAULT || cursorOption.optionMode === MysteryEncounterOptionMode.DISABLED_OR_SPECIAL) && optionDialogue.disabledButtonTooltip) {
|
||||
text = getEncounterText(this.scene, optionDialogue.disabledButtonTooltip, TextStyle.TOOLTIP_CONTENT);
|
||||
} else {
|
||||
|
@ -470,9 +470,11 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||
}
|
||||
|
||||
// Auto-color options green/blue for good/bad by looking for (+)/(-)
|
||||
const primaryStyleString = [...text.match(new RegExp(/\[color=[^\[]*\]\[shadow=[^\[]*\]/i))][0];
|
||||
text = text.replace(/(\(\+\)[^\(\[]*)/gi, substring => "[/color][/shadow]" + getBBCodeFrag(substring, TextStyle.SUMMARY_GREEN) + "[/color][/shadow]" + primaryStyleString);
|
||||
text = text.replace(/(\(\-\)[^\(\[]*)/gi, substring => "[/color][/shadow]" + getBBCodeFrag(substring, TextStyle.SUMMARY_BLUE) + "[/color][/shadow]" + primaryStyleString);
|
||||
if (text) {
|
||||
const primaryStyleString = [...text.match(new RegExp(/\[color=[^\[]*\]\[shadow=[^\[]*\]/i))!][0];
|
||||
text = text.replace(/(\(\+\)[^\(\[]*)/gi, substring => "[/color][/shadow]" + getBBCodeFrag(substring, TextStyle.SUMMARY_GREEN) + "[/color][/shadow]" + primaryStyleString);
|
||||
text = text.replace(/(\(\-\)[^\(\[]*)/gi, substring => "[/color][/shadow]" + getBBCodeFrag(substring, TextStyle.SUMMARY_BLUE) + "[/color][/shadow]" + primaryStyleString);
|
||||
}
|
||||
|
||||
if (text) {
|
||||
const tooltipTextObject = addBBCodeTextObject(this.scene, 6, 7, text, TextStyle.TOOLTIP_CONTENT, { wordWrap: { width: 600 }, fontSize: "72px" });
|
||||
|
@ -492,7 +494,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||
|
||||
if (this.tooltipScrollTween) {
|
||||
this.tooltipScrollTween.remove();
|
||||
this.tooltipScrollTween = null;
|
||||
this.tooltipScrollTween = undefined;
|
||||
}
|
||||
|
||||
// Animates the tooltip text moving upwards
|
||||
|
@ -518,7 +520,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||
|
||||
clear(): void {
|
||||
super.clear();
|
||||
this.overrideSettings = null;
|
||||
this.overrideSettings = undefined;
|
||||
this.optionsContainer.setVisible(false);
|
||||
this.optionsContainer.removeAll(true);
|
||||
this.dexProgressContainer.setVisible(false);
|
||||
|
@ -534,7 +536,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||
if (this.cursorObj) {
|
||||
this.cursorObj.destroy();
|
||||
}
|
||||
this.cursorObj = null;
|
||||
this.cursorObj = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -243,7 +243,7 @@ export function getBBCodeFrag(content: string, textStyle: TextStyle, uiTheme: Ui
|
|||
export function getTextWithColors(content: string, primaryStyle: TextStyle, uiTheme: UiTheme = UiTheme.DEFAULT): string {
|
||||
// Apply primary styling before anything else
|
||||
let text = getBBCodeFrag(content, primaryStyle, uiTheme) + "[/color][/shadow]";
|
||||
const primaryStyleString = [...text.match(new RegExp(/\[color=[^\[]*\]\[shadow=[^\[]*\]/i))][0];
|
||||
const primaryStyleString = [...text.match(new RegExp(/\[color=[^\[]*\]\[shadow=[^\[]*\]/i))!][0];
|
||||
|
||||
// Set custom colors
|
||||
text = text.replace(/@\[([^{]*)\]{([^}]*)}/gi, (substring, textStyle: string, textToColor: string) => {
|
||||
|
|
Loading…
Reference in New Issue