Merge pull request #3850 from pagefaultgames/bug-type-superfan

Bug-Type Superfan Mystery Encounter
This commit is contained in:
ImperialSympathizer 2024-08-27 12:52:57 -04:00 committed by GitHub
commit b27e093252
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
105 changed files with 7789 additions and 4732 deletions

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -13,7 +13,17 @@ import { Arena, ArenaBase } from "./field/arena";
import { GameData } from "./system/game-data"; import { GameData } from "./system/game-data";
import { addTextObject, getTextColor, TextStyle } from "./ui/text"; import { addTextObject, getTextColor, TextStyle } from "./ui/text";
import { allMoves } from "./data/move"; import { allMoves } from "./data/move";
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getModifierType, getPartyLuckValue, modifierTypes } from "./modifier/modifier-type"; import {
ModifierPoolType,
getDefaultModifierTypeForTier,
getEnemyModifierTypesForWave,
getLuckString,
getLuckTextTint,
getModifierPoolForType,
getModifierType,
getPartyLuckValue,
modifierTypes
} from "./modifier/modifier-type";
import AbilityBar from "./ui/ability-bar"; import AbilityBar from "./ui/ability-bar";
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, ChangeMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability"; import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, ChangeMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability";
import { allAbilities } from "./data/ability"; import { allAbilities } from "./data/ability";

View File

@ -19,7 +19,7 @@ const namespace = "mysteryEncounter:aTrainersTest";
/** /**
* A Trainer's Test encounter. * A Trainer's Test encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/115 | GitHub Issue #115} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3816 | GitHub Issue #3816}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const ATrainersTestEncounter: MysteryEncounter = export const ATrainersTestEncounter: MysteryEncounter =

View File

@ -29,7 +29,7 @@ const namespace = "mysteryEncounter:absoluteAvarice";
/** /**
* Absolute Avarice encounter. * Absolute Avarice encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/58 | GitHub Issue #58} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3805 | GitHub Issue #3805}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const AbsoluteAvariceEncounter: MysteryEncounter = export const AbsoluteAvariceEncounter: MysteryEncounter =
@ -249,8 +249,10 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
const givePartyPokemonReviverSeeds = () => { const givePartyPokemonReviverSeeds = () => {
const party = scene.getParty(); const party = scene.getParty();
party.forEach(p => { party.forEach(p => {
if (revSeed) {
const seedModifier = revSeed.newModifier(p); const seedModifier = revSeed.newModifier(p);
scene.addModifier(seedModifier, false, false, false, true); scene.addModifier(seedModifier, false, false, false, true);
}
}); });
queueEncounterMessage(scene, `${namespace}.option.1.food_stash`); queueEncounterMessage(scene, `${namespace}.option.1.food_stash`);
}; };
@ -349,7 +351,7 @@ function doGreedentSpriteSteal(scene: BattleScene) {
const greedentSprites = scene.currentBattle.mysteryEncounter.introVisuals?.getSpriteAtIndex(1); const greedentSprites = scene.currentBattle.mysteryEncounter.introVisuals?.getSpriteAtIndex(1);
scene.playSound("Follow Me"); scene.playSound("battle-anims/Follow Me");
scene.tweens.chain({ scene.tweens.chain({
targets: greedentSprites, targets: greedentSprites,
tweens: [ tweens: [
@ -431,11 +433,11 @@ function doGreedentEatBerries(scene: BattleScene) {
y: "-=8", y: "-=8",
loop: 5, loop: 5,
onStart: () => { onStart: () => {
scene.playSound("PRSFX- Bug Bite"); scene.playSound("battle_anims/PRSFX- Bug Bite");
}, },
onLoop: () => { onLoop: () => {
if (index % 2 === 0) { if (index % 2 === 0) {
scene.playSound("PRSFX- Bug Bite"); scene.playSound("battle_anims/PRSFX- Bug Bite");
} }
index++; index++;
} }

View File

@ -18,7 +18,7 @@ const namespace = "mysteryEncounter:offerYouCantRefuse";
/** /**
* An Offer You Can't Refuse encounter. * An Offer You Can't Refuse encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/72 | GitHub Issue #72} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3808 | GitHub Issue #3808}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const AnOfferYouCantRefuseEncounter: MysteryEncounter = export const AnOfferYouCantRefuseEncounter: MysteryEncounter =

View File

@ -37,7 +37,7 @@ const namespace = "mysteryEncounter:berriesAbound";
/** /**
* Berries Abound encounter. * Berries Abound encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/24 | GitHub Issue #24} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3810 | GitHub Issue #3810}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const BerriesAboundEncounter: MysteryEncounter = export const BerriesAboundEncounter: MysteryEncounter =
@ -131,7 +131,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
const doBerryRewards = async () => { const doBerryRewards = async () => {
const berryText = numBerries + " " + i18next.t(`${namespace}.berries`); const berryText = numBerries + " " + i18next.t(`${namespace}.berries`);
scene.playSound("item_fanfare"); scene.playSound("bgm/item_fanfare");
queueEncounterMessage(scene, i18next.t("battle:rewardGain", { modifierName: berryText })); queueEncounterMessage(scene, i18next.t("battle:rewardGain", { modifierName: berryText }));
// Generate a random berry and give it to the first Pokemon with room for it // Generate a random berry and give it to the first Pokemon with room for it
@ -143,7 +143,10 @@ export const BerriesAboundEncounter: MysteryEncounter =
const shopOptions: ModifierTypeOption[] = []; const shopOptions: ModifierTypeOption[] = [];
for (let i = 0; i < 5; i++) { for (let i = 0; i < 5; i++) {
// Generate shop berries // Generate shop berries
shopOptions.push(generateModifierTypeOption(scene, modifierTypes.BERRY)); const mod = generateModifierTypeOption(scene, modifierTypes.BERRY);
if (mod) {
shopOptions.push(mod);
}
} }
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, undefined, doBerryRewards); setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, undefined, doBerryRewards);
@ -168,7 +171,10 @@ export const BerriesAboundEncounter: MysteryEncounter =
const shopOptions: ModifierTypeOption[] = []; const shopOptions: ModifierTypeOption[] = [];
for (let i = 0; i < 5; i++) { for (let i = 0; i < 5; i++) {
// Generate shop berries // Generate shop berries
shopOptions.push(generateModifierTypeOption(scene, modifierTypes.BERRY)); const mod = generateModifierTypeOption(scene, modifierTypes.BERRY);
if (mod) {
shopOptions.push(mod);
}
} }
if (speedDiff < 1) { if (speedDiff < 1) {
@ -176,7 +182,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
const doBerryRewards = async () => { const doBerryRewards = async () => {
const berryText = numBerries + " " + i18next.t(`${namespace}.berries`); const berryText = numBerries + " " + i18next.t(`${namespace}.berries`);
scene.playSound("item_fanfare"); scene.playSound("bgm/item_fanfare");
queueEncounterMessage(scene, i18next.t("battle:rewardGain", { modifierName: berryText })); queueEncounterMessage(scene, i18next.t("battle:rewardGain", { modifierName: berryText }));
// Generate a random berry and give it to the first Pokemon with room for it // Generate a random berry and give it to the first Pokemon with room for it
@ -202,7 +208,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
const doFasterBerryRewards = async () => { const doFasterBerryRewards = async () => {
const berryText = numBerriesGrabbed + " " + i18next.t(`${namespace}.berries`); const berryText = numBerriesGrabbed + " " + i18next.t(`${namespace}.berries`);
scene.playSound("item_fanfare"); scene.playSound("bgm/item_fanfare");
queueEncounterMessage(scene, i18next.t("battle:rewardGain", { modifierName: berryText })); queueEncounterMessage(scene, i18next.t("battle:rewardGain", { modifierName: berryText }));
// Generate a random berry and give it to the first Pokemon with room for it (trying to give to fastest first) // Generate a random berry and give it to the first Pokemon with room for it (trying to give to fastest first)

View File

@ -0,0 +1,659 @@
import {
EnemyPartyConfig,
generateModifierTypeOption,
initBattleWithEnemyConfig,
leaveEncounterWithoutBattle,
selectOptionThenPokemon,
selectPokemonForOption,
setEncounterRewards,
transitionMysteryEncounterIntroVisuals,
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import {
trainerConfigs,
TrainerPartyCompoundTemplate,
TrainerPartyTemplate,
TrainerSlot,
} from "#app/data/trainer-config";
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { PartyMemberStrength } from "#enums/party-member-strength";
import BattleScene from "#app/battle-scene";
import * as Utils from "#app/utils";
import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils";
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { TrainerType } from "#enums/trainer-type";
import { Species } from "#enums/species";
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { getPokemonSpecies } from "#app/data/pokemon-species";
import { getEncounterText, showEncounterDialogue } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
import { LearnMovePhase } from "#app/phases/learn-move-phase";
import { Moves } from "#enums/moves";
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import {
AttackTypeBoosterHeldItemTypeRequirement,
CombinationPokemonRequirement,
HeldItemRequirement,
TypeRequirement
} from "#app/data/mystery-encounters/mystery-encounter-requirements";
import { Type } from "#app/data/type";
import { AttackTypeBoosterModifierType, ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type";
import {
AttackTypeBoosterModifier,
BypassSpeedChanceModifier,
ContactHeldItemTransferChanceModifier,
PokemonHeldItemModifier
} from "#app/modifier/modifier";
import i18next from "i18next";
import MoveInfoOverlay from "#app/ui/move-info-overlay";
import { allMoves } from "#app/data/move";
import { ModifierTier } from "#app/modifier/modifier-tier";
/** the i18n namespace for the encounter */
const namespace = "mysteryEncounter:bugTypeSuperfan";
const POOL_1_POKEMON = [
Species.PARASECT,
Species.VENOMOTH,
Species.LEDIAN,
Species.ARIADOS,
Species.YANMA,
Species.BEAUTIFLY,
Species.DUSTOX,
Species.MASQUERAIN,
Species.NINJASK,
Species.VOLBEAT,
Species.ILLUMISE,
Species.ANORITH,
Species.KRICKETUNE,
Species.WORMADAM,
Species.MOTHIM,
Species.SKORUPI,
Species.JOLTIK,
Species.LARVESTA,
Species.VIVILLON,
Species.CHARJABUG,
Species.RIBOMBEE,
Species.SPIDOPS,
Species.LOKIX
];
const POOL_2_POKEMON = [
Species.SCYTHER,
Species.PINSIR,
Species.HERACROSS,
Species.FORRETRESS,
Species.SCIZOR,
Species.SHUCKLE,
Species.SHEDINJA,
Species.ARMALDO,
Species.VESPIQUEN,
Species.DRAPION,
Species.YANMEGA,
Species.LEAVANNY,
Species.SCOLIPEDE,
Species.CRUSTLE,
Species.ESCAVALIER,
Species.ACCELGOR,
Species.GALVANTULA,
Species.VIKAVOLT,
Species.ARAQUANID,
Species.ORBEETLE,
Species.CENTISKORCH,
Species.FROSMOTH,
Species.KLEAVOR,
];
const POOL_3_POKEMON: { species: Species, formIndex?: number }[] = [
{
species: Species.PINSIR,
formIndex: 1
},
{
species: Species.SCIZOR,
formIndex: 1
},
{
species: Species.HERACROSS,
formIndex: 1
},
{
species: Species.ORBEETLE,
formIndex: 1
},
{
species: Species.CENTISKORCH,
formIndex: 1
},
{
species: Species.DURANT,
},
{
species: Species.VOLCARONA,
},
{
species: Species.GOLISOPOD,
},
];
const POOL_4_POKEMON = [
Species.GENESECT,
Species.SLITHER_WING,
Species.BUZZWOLE,
Species.PHEROMOSA
];
const PHYSICAL_TUTOR_MOVES = [
Moves.MEGAHORN,
Moves.X_SCISSOR,
Moves.ATTACK_ORDER,
Moves.PIN_MISSILE,
Moves.FIRST_IMPRESSION
];
const SPECIAL_TUTOR_MOVES = [
Moves.SILVER_WIND,
Moves.BUG_BUZZ,
Moves.SIGNAL_BEAM,
Moves.POLLEN_PUFF
];
const STATUS_TUTOR_MOVES = [
Moves.STRING_SHOT,
Moves.STICKY_WEB,
Moves.SILK_TRAP,
Moves.RAGE_POWDER,
Moves.HEAL_ORDER
];
const MISC_TUTOR_MOVES = [
Moves.BUG_BITE,
Moves.LEECH_LIFE,
Moves.DEFEND_ORDER,
Moves.QUIVER_DANCE,
Moves.TAIL_GLOW,
Moves.INFESTATION,
Moves.U_TURN
];
/**
* Bug Type Superfan encounter.
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3810 | GitHub Issue #3810}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/
export const BugTypeSuperfanEncounter: MysteryEncounter =
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.BUG_TYPE_SUPERFAN)
.withEncounterTier(MysteryEncounterTier.GREAT)
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
// Must have at least 1 Bug type on team, OR have a bug item somewhere on the team
new HeldItemRequirement(["BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier"], 1),
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1),
new TypeRequirement(Type.BUG, false, 1)
))
.withSceneWaveRangeRequirement(10, 180) // waves 10 to 180
.withIntroSpriteConfigs([]) // These are set in onInit()
.withAutoHideIntroVisuals(false)
.withIntroDialogue([
{
text: `${namespace}.intro`,
},
{
speaker: `${namespace}.speaker`,
text: `${namespace}.intro_dialogue`,
},
])
.withOnInit((scene: BattleScene) => {
const encounter = scene.currentBattle.mysteryEncounter;
// Calculates what trainers are available for battle in the encounter
// Bug type superfan trainer config
const config = getTrainerConfigForWave(scene.currentBattle.waveIndex);
const spriteKey = config.getSpriteKey();
encounter.enemyPartyConfigs.push({
trainerConfig: config,
female: true,
});
encounter.spriteConfigs = [
{
spriteKey: spriteKey,
fileRoot: "trainer",
hasShadow: true,
},
];
return true;
})
.withTitle(`${namespace}.title`)
.withDescription(`${namespace}.description`)
.withQuery(`${namespace}.query`)
.withSimpleOption(
{
buttonLabel: `${namespace}.option.1.label`,
buttonTooltip: `${namespace}.option.1.tooltip`,
selected: [
{
speaker: `${namespace}.speaker`,
text: `${namespace}.option.1.selected`,
},
],
},
async (scene: BattleScene) => {
// Select battle the bug trainer
const encounter = scene.currentBattle.mysteryEncounter;
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
// Init the moves available for tutor
const moveTutorOptions: PokemonMove[] = [];
moveTutorOptions.push(new PokemonMove(PHYSICAL_TUTOR_MOVES[randSeedInt(PHYSICAL_TUTOR_MOVES.length)]));
moveTutorOptions.push(new PokemonMove(SPECIAL_TUTOR_MOVES[randSeedInt(SPECIAL_TUTOR_MOVES.length)]));
moveTutorOptions.push(new PokemonMove(STATUS_TUTOR_MOVES[randSeedInt(STATUS_TUTOR_MOVES.length)]));
moveTutorOptions.push(new PokemonMove(MISC_TUTOR_MOVES[randSeedInt(MISC_TUTOR_MOVES.length)]));
encounter.misc = {
moveTutorOptions
};
// Assigns callback that teaches move before continuing to rewards
encounter.onRewards = doBugTypeMoveTutor;
setEncounterRewards(scene, { fillRemaining: true });
await transitionMysteryEncounterIntroVisuals(scene, true, true);
await initBattleWithEnemyConfig(scene, config);
}
)
.withOption(MysteryEncounterOptionBuilder
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
.withPrimaryPokemonRequirement(new TypeRequirement(Type.BUG, false, 1)) // Must have 1 Bug type on team
.withDialogue({
buttonLabel: `${namespace}.option.2.label`,
buttonTooltip: `${namespace}.option.2.tooltip`,
disabledButtonTooltip: `${namespace}.option.2.disabled_tooltip`
})
.withPreOptionPhase(async (scene: BattleScene) => {
// Player shows off their bug types
const encounter = scene.currentBattle.mysteryEncounter;
// Player gets different rewards depending on the number of bug types they have
const numBugTypes = scene.getParty().filter(p => p.isOfType(Type.BUG, true)).length;
encounter.setDialogueToken("numBugTypes", numBugTypes.toString());
if (numBugTypes < 2) {
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SUPER_LURE, modifierTypes.GREAT_BALL], fillRemaining: false });
encounter.selectedOption!.dialogue!.selected = [
{
speaker: `${namespace}.speaker`,
text: `${namespace}.option.2.selected_0_to_1`,
},
];
} else if (numBugTypes < 4) {
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.QUICK_CLAW, modifierTypes.MAX_LURE, modifierTypes.ULTRA_BALL], fillRemaining: false });
encounter.selectedOption!.dialogue!.selected = [
{
speaker: `${namespace}.speaker`,
text: `${namespace}.option.2.selected_2_to_3`,
},
];
} else if (numBugTypes < 6) {
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.GRIP_CLAW, modifierTypes.MAX_LURE, modifierTypes.ROGUE_BALL], fillRemaining: false });
encounter.selectedOption!.dialogue!.selected = [
{
speaker: `${namespace}.speaker`,
text: `${namespace}.option.2.selected_4_to_5`,
},
];
} else {
// If player has any evolution/form change items that are valid for their party, will spawn one of those items in addition to a Master Ball
const modifierOptions: ModifierTypeOption[] = [generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)!, generateModifierTypeOption(scene, modifierTypes.MAX_LURE)!];
const specialOptions: ModifierTypeOption[] = [];
const nonRareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.EVOLUTION_ITEM);
if (nonRareEvolutionModifier) {
specialOptions.push(nonRareEvolutionModifier);
}
const rareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.RARE_EVOLUTION_ITEM);
if (rareEvolutionModifier) {
specialOptions.push(rareEvolutionModifier);
}
const formChangeModifier = generateModifierTypeOption(scene, modifierTypes.FORM_CHANGE_ITEM);
if (formChangeModifier) {
specialOptions.push(formChangeModifier);
}
if (specialOptions.length > 0) {
modifierOptions.push(specialOptions[randSeedInt(specialOptions.length)]);
}
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifierOptions, fillRemaining: false });
encounter.selectedOption!.dialogue!.selected = [
{
speaker: `${namespace}.speaker`,
text: `${namespace}.option.2.selected_6`,
},
];
}
})
.withOptionPhase(async (scene: BattleScene) => {
// Player shows off their bug types
leaveEncounterWithoutBattle(scene);
})
.build())
.withOption(MysteryEncounterOptionBuilder
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
// Meets one or both of the below reqs
new HeldItemRequirement(["BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier"], 1),
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1)
))
.withDialogue({
buttonLabel: `${namespace}.option.3.label`,
buttonTooltip: `${namespace}.option.3.tooltip`,
disabledButtonTooltip: `${namespace}.option.3.disabled_tooltip`,
selected: [
{
text: `${namespace}.option.3.selected`,
},
{
speaker: `${namespace}.speaker`,
text: `${namespace}.option.3.selected_dialogue`,
},
],
secondOptionPrompt: `${namespace}.option.3.select_prompt`,
})
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
const encounter = scene.currentBattle.mysteryEncounter;
const onPokemonSelected = (pokemon: PlayerPokemon) => {
// Get Pokemon held items and filter for valid ones
const validItems = pokemon.getHeldItems().filter(item => {
return item instanceof BypassSpeedChanceModifier ||
item instanceof ContactHeldItemTransferChanceModifier ||
(item instanceof AttackTypeBoosterModifier && (item.type as AttackTypeBoosterModifierType).moveType === Type.BUG);
});
return validItems.map((modifier: PokemonHeldItemModifier) => {
const option: OptionSelectItem = {
label: modifier.type.name,
handler: () => {
// Pokemon and item selected
encounter.setDialogueToken("selectedItem", modifier.type.name);
encounter.misc = {
chosenPokemon: pokemon,
chosenModifier: modifier,
};
return true;
},
};
return option;
});
};
const selectableFilter = (pokemon: Pokemon) => {
// If pokemon has valid item, it can be selected
const hasValidItem = pokemon.getHeldItems().some(item => {
return item instanceof BypassSpeedChanceModifier ||
item instanceof ContactHeldItemTransferChanceModifier ||
(item instanceof AttackTypeBoosterModifier && (item.type as AttackTypeBoosterModifierType).moveType === Type.BUG);
});
if (!hasValidItem) {
return getEncounterText(scene, `${namespace}.option.3.invalid_selection`) ?? null;
}
return null;
};
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
})
.withOptionPhase(async (scene: BattleScene) => {
const encounter = scene.currentBattle.mysteryEncounter;
const modifier = encounter.misc.chosenModifier;
// Remove the modifier if its stacks go to 0
modifier.stackCount -= 1;
if (modifier.stackCount === 0) {
scene.removeModifier(modifier);
}
scene.updateModifiers(true, true);
const bugNet = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET)!;
bugNet.type.tier = ModifierTier.MASTER;
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [bugNet], guaranteedModifierTypeFuncs: [modifierTypes.REVIVER_SEED], fillRemaining: false });
leaveEncounterWithoutBattle(scene, true);
})
.build())
.withOutroDialogue([
{
text: `${namespace}.outro`,
},
])
.build();
function getTrainerConfigForWave(waveIndex: number) {
// Bug type superfan trainer config
const config = trainerConfigs[TrainerType.BUG_TYPE_SUPERFAN].copy();
config.name = i18next.t("trainerNames:bug_type_superfan");
const pool3Copy = POOL_3_POKEMON.slice(0);
randSeedShuffle(pool3Copy);
const pool3Mon = pool3Copy.pop()!;
if (waveIndex < 30) {
// Use default template (2 AVG)
config
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true));
} else if (waveIndex < 50) {
config
.setPartyTemplates(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE))
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true));
} else if (waveIndex < 70) {
config
.setPartyTemplates(new TrainerPartyTemplate(4, PartyMemberStrength.AVERAGE))
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true))
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true));
} else if (waveIndex < 100) {
config
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true))
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
.setPartyMemberFunc(4, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true));
} else if (waveIndex < 120) {
config
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
p.generateName();
}))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
p.generateName();
}))
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
.setPartyMemberFunc(4, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
if (!isNullOrUndefined(pool3Mon.formIndex)) {
p.formIndex = pool3Mon.formIndex!;
p.generateAndPopulateMoveset();
p.generateName();
}
}));
} else if (waveIndex < 140) {
randSeedShuffle(pool3Copy);
const pool3Mon2 = pool3Copy.pop()!;
config
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
p.generateName();
}))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
p.generateName();
}))
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
if (!isNullOrUndefined(pool3Mon.formIndex)) {
p.formIndex = pool3Mon.formIndex!;
p.generateAndPopulateMoveset();
p.generateName();
}
}))
.setPartyMemberFunc(4, getRandomPartyMemberFunc([pool3Mon2.species], TrainerSlot.TRAINER, true, p => {
if (!isNullOrUndefined(pool3Mon2.formIndex)) {
p.formIndex = pool3Mon2.formIndex!;
p.generateAndPopulateMoveset();
p.generateName();
}
}));
} else if (waveIndex < 160) {
config
.setPartyTemplates(new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(4, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)))
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
p.generateName();
}))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true, p => {
p.formIndex = 1;
p.generateAndPopulateMoveset();
p.generateName();
}))
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
if (!isNullOrUndefined(pool3Mon.formIndex)) {
p.formIndex = pool3Mon.formIndex!;
p.generateAndPopulateMoveset();
p.generateName();
}
}))
.setPartyMemberFunc(4, getRandomPartyMemberFunc(POOL_4_POKEMON, TrainerSlot.TRAINER, true));
} else {
config
.setPartyTemplates(new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(4, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)))
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BEEDRILL ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.formIndex = 1;
p.generateAndPopulateMoveset();
p.generateName();
}))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUTTERFREE ], TrainerSlot.TRAINER, true, p => {
p.setBoss(true, 2);
p.formIndex = 1;
p.generateAndPopulateMoveset();
p.generateName();
}))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
if (!isNullOrUndefined(pool3Mon.formIndex)) {
p.formIndex = pool3Mon.formIndex!;
p.generateAndPopulateMoveset();
p.generateName();
}
}))
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
if (!isNullOrUndefined(pool3Mon.formIndex)) {
p.formIndex = pool3Mon.formIndex!;
p.generateAndPopulateMoveset();
p.generateName();
}
}))
.setPartyMemberFunc(4, getRandomPartyMemberFunc(POOL_4_POKEMON, TrainerSlot.TRAINER, true));
}
return config;
}
function getRandomPartyMemberFunc(speciesPool: Species[], trainerSlot: TrainerSlot = TrainerSlot.TRAINER, ignoreEvolution: boolean = false, postProcess?: (enemyPokemon: EnemyPokemon) => void) {
return (scene: BattleScene, level: integer, strength: PartyMemberStrength) => {
let species = Utils.randSeedItem(speciesPool);
if (!ignoreEvolution) {
species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength);
}
return scene.addEnemyPokemon(getPokemonSpecies(species), level, trainerSlot, undefined, undefined, postProcess);
};
}
function doBugTypeMoveTutor(scene: BattleScene): Promise<void> {
return new Promise<void>(async resolve => {
const moveOptions = scene.currentBattle.mysteryEncounter.misc.moveTutorOptions;
await showEncounterDialogue(scene, `${namespace}.battle_won`, `${namespace}.speaker`);
const overlayScale = 1;
const moveInfoOverlay = new MoveInfoOverlay(scene, {
delayVisibility: false,
scale: overlayScale,
onSide: true,
right: true,
x: 1,
y: -MoveInfoOverlay.getHeight(overlayScale, true) - 1,
width: (scene.game.canvas.width / 6) - 2,
});
scene.ui.add(moveInfoOverlay);
const optionSelectItems = moveOptions.map((move: PokemonMove) => {
const option: OptionSelectItem = {
label: move.getName(),
handler: () => {
moveInfoOverlay.active = false;
moveInfoOverlay.setVisible(false);
return true;
},
onHover: () => {
moveInfoOverlay.active = true;
moveInfoOverlay.show(allMoves[move.moveId]);
},
};
return option;
});
const onHoverOverCancel = () => {
moveInfoOverlay.active = false;
moveInfoOverlay.setVisible(false);
};
const result = await selectOptionThenPokemon(scene, optionSelectItems, `${namespace}.teach_move_prompt`, undefined, onHoverOverCancel);
// let forceExit = !!result;
if (!result) {
moveInfoOverlay.active = false;
moveInfoOverlay.setVisible(false);
}
// TODO: add menu to confirm player doesn't want to teach a move
// while (!result && !forceExit) {
// // Didn't teach a move, ask the player to confirm they don't want to teach a move
// await showEncounterDialogue(scene, `${namespace}.confirm_no_teach`, `${namespace}.speaker`);
// const confirm = await new Promise<boolean>(confirmResolve => {
// scene.ui.setMode(Mode.CONFIRM, () => confirmResolve(true), () => confirmResolve(false));
// });
// scene.ui.clearText();
// await scene.ui.setMode(Mode.MESSAGE);
// if (confirm) {
// // No teach, break out of loop
// forceExit = true;
// } else {
// // Re-show learn menu
// result = await selectOptionThenPokemon(scene, optionSelectItems, `${namespace}.teach_move_prompt`, undefined, onHoverOverCancel);
// if (!result) {
// moveInfoOverlay.active = false;
// moveInfoOverlay.setVisible(false);
// }
// }
// }
// Option select complete, handle if they are learning a move
if (result && result.selectedOptionIndex < moveOptions.length) {
scene.unshiftPhase(new LearnMovePhase(scene, result.selectedPokemonIndex, moveOptions[result.selectedOptionIndex].moveId));
}
// Complete battle and go to rewards
resolve();
});
}

View File

@ -53,7 +53,7 @@ const RANDOM_ABILITY_POOL = [
/** /**
* Clowning Around encounter. * Clowning Around encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/69 | GitHub Issue #69} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3807 | GitHub Issue #3807}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const ClowningAroundEncounter: MysteryEncounter = export const ClowningAroundEncounter: MysteryEncounter =
@ -334,13 +334,13 @@ export const ClowningAroundEncounter: MysteryEncounter =
randSeedShuffle(priorityTypes); randSeedShuffle(priorityTypes);
} }
let newTypes; let newTypes: Type[];
if (!originalTypes || originalTypes.length < 1) { if (!originalTypes || originalTypes.length < 1) {
newTypes = priorityTypes?.length > 0 ? [priorityTypes.pop()] : [(randSeedInt(18) as Type)]; newTypes = priorityTypes && priorityTypes.length > 0 ? [priorityTypes.pop()!] : [(randSeedInt(18) as Type)];
} else { } else {
newTypes = originalTypes.map(m => { newTypes = originalTypes.map(m => {
if (priorityTypes?.length > 0) { if (priorityTypes && priorityTypes.length > 0) {
const ret = priorityTypes.pop(); const ret = priorityTypes.pop()!;
randSeedShuffle(priorityTypes); randSeedShuffle(priorityTypes);
return ret; return ret;
} }

View File

@ -75,7 +75,7 @@ const SENSU_STYLE_BIOMES = [
/** /**
* Dancing Lessons encounter. * Dancing Lessons encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/130 | GitHub Issue #130} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3823 | GitHub Issue #3823}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const DancingLessonsEncounter: MysteryEncounter = export const DancingLessonsEncounter: MysteryEncounter =

View File

@ -71,7 +71,7 @@ const excludedBosses = [
/** /**
* Dark Deal encounter. * Dark Deal encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/61 | GitHub Issue #61} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3806 | GitHub Issue #3806}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const DarkDealEncounter: MysteryEncounter = export const DarkDealEncounter: MysteryEncounter =

View File

@ -33,7 +33,7 @@ const OPTION_3_DISALLOWED_MODIFIERS = [
/** /**
* Delibird-y encounter. * Delibird-y encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/57 | GitHub Issue #57} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3804 | GitHub Issue #3804}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const DelibirdyEncounter: MysteryEncounter = export const DelibirdyEncounter: MysteryEncounter =
@ -115,7 +115,7 @@ export const DelibirdyEncounter: MysteryEncounter =
// At max stacks, give the first party pokemon a Shell Bell instead // At max stacks, give the first party pokemon a Shell Bell instead
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType; const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell); await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
scene.playSound("item_fanfare"); scene.playSound("bgm/item_fanfare");
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true);
} else { } else {
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.ABILITY_CHARM)); scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.ABILITY_CHARM));
@ -190,7 +190,7 @@ export const DelibirdyEncounter: MysteryEncounter =
// At max stacks, give the first party pokemon a Shell Bell instead // At max stacks, give the first party pokemon a Shell Bell instead
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType; const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell); await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
scene.playSound("item_fanfare"); scene.playSound("bgm/item_fanfare");
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true);
} else { } else {
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.CANDY_JAR)); scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.CANDY_JAR));
@ -203,7 +203,7 @@ export const DelibirdyEncounter: MysteryEncounter =
// At max stacks, give the first party pokemon a Shell Bell instead // At max stacks, give the first party pokemon a Shell Bell instead
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType; const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell); await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
scene.playSound("item_fanfare"); scene.playSound("bgm/item_fanfare");
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true);
} else { } else {
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.HEALING_CHARM)); scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.HEALING_CHARM));
@ -283,7 +283,7 @@ export const DelibirdyEncounter: MysteryEncounter =
// At max stacks, give the first party pokemon a Shell Bell instead // At max stacks, give the first party pokemon a Shell Bell instead
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType; const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell); await applyModifierTypeToPlayerPokemon(scene, scene.getParty()[0], shellBell);
scene.playSound("item_fanfare"); scene.playSound("bgm/item_fanfare");
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: shellBell.name }), undefined, true);
} else { } else {
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.BERRY_POUCH)); scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.BERRY_POUCH));

View File

@ -17,7 +17,7 @@ const namespace = "mysteryEncounter:departmentStoreSale";
/** /**
* Department Store Sale encounter. * Department Store Sale encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/33 | GitHub Issue #33} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3797 | GitHub Issue #3797}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const DepartmentStoreSaleEncounter: MysteryEncounter = export const DepartmentStoreSaleEncounter: MysteryEncounter =

View File

@ -16,7 +16,7 @@ const namespace = "mysteryEncounter:fieldTrip";
/** /**
* Field Trip encounter. * Field Trip encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/17 | GitHub Issue #17} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3794 | GitHub Issue #3794}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const FieldTripEncounter: MysteryEncounter = export const FieldTripEncounter: MysteryEncounter =
@ -126,10 +126,10 @@ export const FieldTripEncounter: MysteryEncounter =
const encounter = scene.currentBattle.mysteryEncounter; const encounter = scene.currentBattle.mysteryEncounter;
if (encounter.misc.correctMove) { if (encounter.misc.correctMove) {
const modifiers = [ const modifiers = [
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.ATK]), generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.ATK])!,
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.DEF]), generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.DEF])!,
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD]), generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD])!,
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT), generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!,
]; ];
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false }); setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });
@ -218,10 +218,10 @@ export const FieldTripEncounter: MysteryEncounter =
const encounter = scene.currentBattle.mysteryEncounter; const encounter = scene.currentBattle.mysteryEncounter;
if (encounter.misc.correctMove) { if (encounter.misc.correctMove) {
const modifiers = [ const modifiers = [
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPATK]), generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPATK])!,
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPDEF]), generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPDEF])!,
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD]), generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD])!,
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT), generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!,
]; ];
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false }); setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });
@ -304,10 +304,10 @@ export const FieldTripEncounter: MysteryEncounter =
const encounter = scene.currentBattle.mysteryEncounter; const encounter = scene.currentBattle.mysteryEncounter;
if (encounter.misc.correctMove) { if (encounter.misc.correctMove) {
const modifiers = [ const modifiers = [
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.ACC]), generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.ACC])!,
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD]), generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD])!,
generateModifierTypeOption(scene, modifierTypes.GREAT_BALL), generateModifierTypeOption(scene, modifierTypes.GREAT_BALL)!,
generateModifierTypeOption(scene, modifierTypes.IV_SCANNER), generateModifierTypeOption(scene, modifierTypes.IV_SCANNER)!,
]; ];
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false }); setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });

View File

@ -33,7 +33,7 @@ const DAMAGE_PERCENTAGE: number = 20;
/** /**
* Fiery Fallout encounter. * Fiery Fallout encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/88 | GitHub Issue #88} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3814 | GitHub Issue #3814}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const FieryFalloutEncounter: MysteryEncounter = export const FieryFalloutEncounter: MysteryEncounter =

View File

@ -30,7 +30,7 @@ const namespace = "mysteryEncounter:fightOrFlight";
/** /**
* Fight or Flight encounter. * Fight or Flight encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/24 | GitHub Issue #24} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3795 | GitHub Issue #3795}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const FightOrFlightEncounter: MysteryEncounter = export const FightOrFlightEncounter: MysteryEncounter =

View File

@ -23,7 +23,7 @@ const namespace = "mysteryEncounter:lostAtSea";
/** /**
* Lost at sea encounter. * Lost at sea encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/9 | GitHub Issue #9} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3793 | GitHub Issue #3793}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.LOST_AT_SEA) export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.LOST_AT_SEA)
@ -125,7 +125,6 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
* Generic handler for using a guiding pokemon to guide you back. * Generic handler for using a guiding pokemon to guide you back.
* *
* @param scene Battle scene * @param scene Battle scene
* @param guidePokemon pokemon choosen as a guide
*/ */
async function handlePokemonGuidingYouPhase(scene: BattleScene) { async function handlePokemonGuidingYouPhase(scene: BattleScene) {
const laprasSpecies = getPokemonSpecies(Species.LAPRAS); const laprasSpecies = getPokemonSpecies(Species.LAPRAS);

View File

@ -23,7 +23,7 @@ const namespace = "mysteryEncounter:mysteriousChallengers";
/** /**
* Mysterious Challengers encounter. * Mysterious Challengers encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/41 | GitHub Issue #41} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3801 | GitHub Issue #3801}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const MysteriousChallengersEncounter: MysteryEncounter = export const MysteriousChallengersEncounter: MysteryEncounter =

View File

@ -15,7 +15,7 @@ const namespace = "mysteryEncounter:mysteriousChest";
/** /**
* Mysterious Chest encounter. * Mysterious Chest encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/32 | GitHub Issue #32} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3796 | GitHub Issue #3796}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const MysteriousChestEncounter: MysteryEncounter = export const MysteriousChestEncounter: MysteryEncounter =

View File

@ -17,7 +17,7 @@ const namespace = "mysteryEncounter:partTimer";
/** /**
* Part Timer encounter. * Part Timer encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/82 | GitHub Issue #82} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3813 | GitHub Issue #3813}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const PartTimerEncounter: MysteryEncounter = export const PartTimerEncounter: MysteryEncounter =
@ -140,7 +140,7 @@ export const PartTimerEncounter: MysteryEncounter =
} }
const moneyChange = scene.getWaveMoneyAmount(moneyMultiplier); const moneyChange = scene.getWaveMoneyAmount(moneyMultiplier);
updatePlayerMoney(scene, moneyChange, true, false); updatePlayerMoney(scene, moneyChange, true, false);
await showEncounterText(scene, i18next.t("mysteryEncounter:receive_money", { amount: moneyChange })); await showEncounterText(scene, i18next.t("mysteryEncounterMessages:receive_money", { amount: moneyChange }));
await showEncounterText(scene, `${namespace}.pokemon_tired`); await showEncounterText(scene, `${namespace}.pokemon_tired`);
setEncounterRewards(scene, { fillRemaining: true }); setEncounterRewards(scene, { fillRemaining: true });
@ -221,7 +221,7 @@ export const PartTimerEncounter: MysteryEncounter =
} }
const moneyChange = scene.getWaveMoneyAmount(moneyMultiplier); const moneyChange = scene.getWaveMoneyAmount(moneyMultiplier);
updatePlayerMoney(scene, moneyChange, true, false); updatePlayerMoney(scene, moneyChange, true, false);
await showEncounterText(scene, i18next.t("mysteryEncounter:receive_money", { amount: moneyChange })); await showEncounterText(scene, i18next.t("mysteryEncounterMessages:receive_money", { amount: moneyChange }));
await showEncounterText(scene, `${namespace}.pokemon_tired`); await showEncounterText(scene, `${namespace}.pokemon_tired`);
setEncounterRewards(scene, { fillRemaining: true }); setEncounterRewards(scene, { fillRemaining: true });
@ -273,7 +273,7 @@ export const PartTimerEncounter: MysteryEncounter =
await showEncounterDialogue(scene, `${namespace}.job_complete_good`, `${namespace}.speaker`); await showEncounterDialogue(scene, `${namespace}.job_complete_good`, `${namespace}.speaker`);
const moneyChange = scene.getWaveMoneyAmount(2.5); const moneyChange = scene.getWaveMoneyAmount(2.5);
updatePlayerMoney(scene, moneyChange, true, false); updatePlayerMoney(scene, moneyChange, true, false);
await showEncounterText(scene, i18next.t("mysteryEncounter:receive_money", { amount: moneyChange })); await showEncounterText(scene, i18next.t("mysteryEncounterMessages:receive_money", { amount: moneyChange }));
await showEncounterText(scene, `${namespace}.pokemon_tired`); await showEncounterText(scene, `${namespace}.pokemon_tired`);
setEncounterRewards(scene, { fillRemaining: true }); setEncounterRewards(scene, { fillRemaining: true });
@ -290,50 +290,50 @@ export const PartTimerEncounter: MysteryEncounter =
.build(); .build();
function doStrongWorkSfx(scene: BattleScene) { function doStrongWorkSfx(scene: BattleScene) {
scene.playSound("PRSFX- Horn Drill1"); scene.playSound("battle_anims/PRSFX- Horn Drill1");
scene.playSound("PRSFX- Horn Drill1"); scene.playSound("battle_anims/PRSFX- Horn Drill1");
scene.time.delayedCall(1000, () => { scene.time.delayedCall(1000, () => {
scene.playSound("PRSFX- Guillotine2"); scene.playSound("battle_anims/PRSFX- Guillotine2");
}); });
scene.time.delayedCall(2000, () => { scene.time.delayedCall(2000, () => {
scene.playSound("PRSFX- Heavy Slam2"); scene.playSound("battle_anims/PRSFX- Heavy Slam2");
}); });
scene.time.delayedCall(2500, () => { scene.time.delayedCall(2500, () => {
scene.playSound("PRSFX- Guillotine2"); scene.playSound("battle_anims/PRSFX- Guillotine2");
}); });
} }
function doDeliverySfx(scene: BattleScene) { function doDeliverySfx(scene: BattleScene) {
scene.playSound("PRSFX- Accelerock1"); scene.playSound("battle_anims/PRSFX- Accelerock1");
scene.time.delayedCall(1500, () => { scene.time.delayedCall(1500, () => {
scene.playSound("PRSFX- Extremespeed1"); scene.playSound("battle_anims/PRSFX- Extremespeed1");
}); });
scene.time.delayedCall(2000, () => { scene.time.delayedCall(2000, () => {
scene.playSound("PRSFX- Extremespeed1"); scene.playSound("battle_anims/PRSFX- Extremespeed1");
}); });
scene.time.delayedCall(2250, () => { scene.time.delayedCall(2250, () => {
scene.playSound("PRSFX- Agility"); scene.playSound("battle_anims/PRSFX- Agility");
}); });
} }
function doSalesSfx(scene: BattleScene) { function doSalesSfx(scene: BattleScene) {
scene.playSound("PRSFX- Captivate"); scene.playSound("battle_anims/PRSFX- Captivate");
scene.time.delayedCall(1500, () => { scene.time.delayedCall(1500, () => {
scene.playSound("PRSFX- Attract2"); scene.playSound("battle_anims/PRSFX- Attract2");
}); });
scene.time.delayedCall(2000, () => { scene.time.delayedCall(2000, () => {
scene.playSound("PRSFX- Aurora Veil2"); scene.playSound("battle_anims/PRSFX- Aurora Veil2");
}); });
scene.time.delayedCall(3000, () => { scene.time.delayedCall(3000, () => {
scene.playSound("PRSFX- Attract2"); scene.playSound("battle_anims/PRSFX- Attract2");
}); });
} }

View File

@ -26,7 +26,7 @@ const TRAINER_THROW_ANIMATION_TIMES = [512, 184, 768];
/** /**
* Safari Zone encounter. * Safari Zone encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/39 | GitHub Issue #39} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3800 | GitHub Issue #3800}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const SafariZoneEncounter: MysteryEncounter = export const SafariZoneEncounter: MysteryEncounter =
@ -322,7 +322,7 @@ async function throwBait(scene: BattleScene, pokemon: EnemyPokemon): Promise<boo
return new Promise(resolve => { return new Promise(resolve => {
scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`); scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`);
scene.time.delayedCall(TRAINER_THROW_ANIMATION_TIMES[0], () => { scene.time.delayedCall(TRAINER_THROW_ANIMATION_TIMES[0], () => {
scene.playSound("pb_throw"); scene.playSound("se/pb_throw");
// Trainer throw frames // Trainer throw frames
scene.trainer.setFrame("2"); scene.trainer.setFrame("2");
@ -351,12 +351,12 @@ async function throwBait(scene: BattleScene, pokemon: EnemyPokemon): Promise<boo
y: originalY - 5, y: originalY - 5,
loop: 6, loop: 6,
onStart: () => { onStart: () => {
scene.playSound("PRSFX- Bug Bite"); scene.playSound("battle-anims/PRSFX- Bug Bite");
bait.setFrame("0002.png"); bait.setFrame("0002.png");
}, },
onLoop: () => { onLoop: () => {
if (index % 2 === 0) { if (index % 2 === 0) {
scene.playSound("PRSFX- Bug Bite"); scene.playSound("battle-anims/PRSFX- Bug Bite");
} }
if (index === 4) { if (index === 4) {
bait.setFrame("0003.png"); bait.setFrame("0003.png");
@ -388,7 +388,7 @@ async function throwMud(scene: BattleScene, pokemon: EnemyPokemon): Promise<bool
return new Promise(resolve => { return new Promise(resolve => {
scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`); scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`);
scene.time.delayedCall(TRAINER_THROW_ANIMATION_TIMES[0], () => { scene.time.delayedCall(TRAINER_THROW_ANIMATION_TIMES[0], () => {
scene.playSound("pb_throw"); scene.playSound("se/pb_throw");
// Trainer throw frames // Trainer throw frames
scene.trainer.setFrame("2"); scene.trainer.setFrame("2");
@ -407,7 +407,7 @@ async function throwMud(scene: BattleScene, pokemon: EnemyPokemon): Promise<bool
duration: 500, duration: 500,
onComplete: () => { onComplete: () => {
// Mud frame 2 // Mud frame 2
scene.playSound("PRSFX- Sludge Bomb2"); scene.playSound("battle-anims/PRSFX- Sludge Bomb2");
mud.setFrame("0002.png"); mud.setFrame("0002.png");
// Mud splat // Mud splat
scene.time.delayedCall(200, () => { scene.time.delayedCall(200, () => {
@ -433,10 +433,10 @@ async function throwMud(scene: BattleScene, pokemon: EnemyPokemon): Promise<bool
y: originalY - 20, y: originalY - 20,
loop: 1, loop: 1,
onStart: () => { onStart: () => {
scene.playSound("PRSFX- Taunt2"); scene.playSound("battle-anims/PRSFX- Taunt2");
}, },
onLoop: () => { onLoop: () => {
scene.playSound("PRSFX- Taunt2"); scene.playSound("battle-anims/PRSFX- Taunt2");
}, },
onComplete: () => { onComplete: () => {
resolve(true); resolve(true);

View File

@ -19,7 +19,7 @@ const namespace = "mysteryEncounter:shadyVitaminDealer";
/** /**
* Shady Vitamin Dealer encounter. * Shady Vitamin Dealer encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/34 | GitHub Issue #34} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3798 | GitHub Issue #3798}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const ShadyVitaminDealerEncounter: MysteryEncounter = export const ShadyVitaminDealerEncounter: MysteryEncounter =
@ -79,8 +79,8 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
updatePlayerMoney(scene, -(encounter.options[0].requirements[0] as MoneyRequirement).requiredMoney); updatePlayerMoney(scene, -(encounter.options[0].requirements[0] as MoneyRequirement).requiredMoney);
// Calculate modifiers and dialogue tokens // Calculate modifiers and dialogue tokens
const modifiers = [ const modifiers = [
generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER), generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER)!,
generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER), generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER)!,
]; ];
encounter.setDialogueToken("boost1", modifiers[0].name); encounter.setDialogueToken("boost1", modifiers[0].name);
encounter.setDialogueToken("boost2", modifiers[1].name); encounter.setDialogueToken("boost2", modifiers[1].name);
@ -162,8 +162,8 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
updatePlayerMoney(scene, -(encounter.options[1].requirements[0] as MoneyRequirement).requiredMoney); updatePlayerMoney(scene, -(encounter.options[1].requirements[0] as MoneyRequirement).requiredMoney);
// Calculate modifiers and dialogue tokens // Calculate modifiers and dialogue tokens
const modifiers = [ const modifiers = [
generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER), generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER)!,
generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER), generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER)!,
]; ];
encounter.setDialogueToken("boost1", modifiers[0].name); encounter.setDialogueToken("boost1", modifiers[0].name);
encounter.setDialogueToken("boost2", modifiers[1].name); encounter.setDialogueToken("boost2", modifiers[1].name);

View File

@ -22,7 +22,7 @@ const namespace = "mysteryEncounter:slumberingSnorlax";
/** /**
* Sleeping Snorlax encounter. * Sleeping Snorlax encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/103 | GitHub Issue #103} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3815 | GitHub Issue #3815}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const SlumberingSnorlaxEncounter: MysteryEncounter = export const SlumberingSnorlaxEncounter: MysteryEncounter =

View File

@ -29,7 +29,7 @@ const MACHINE_INTERFACING_TYPES = [Type.ELECTRIC, Type.STEEL];
/** /**
* Teleporting Hijinks encounter. * Teleporting Hijinks encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/119 | GitHub Issue #119} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3817 | GitHub Issue #3817}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const TeleportingHijinksEncounter: MysteryEncounter = export const TeleportingHijinksEncounter: MysteryEncounter =
@ -140,10 +140,9 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
}], }],
}; };
const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.STEEL]); const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.STEEL])!;
const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.ELECTRIC]); const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.ELECTRIC])!;
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [magnet, metalCoat], fillRemaining: true }); setEncounterRewards(scene, { guaranteedModifierTypeOptions: [magnet, metalCoat], fillRemaining: true });
setEncounterExp(scene, encounter.selectedOption!.primaryPokemon!.id, 100);
transitionMysteryEncounterIntroVisuals(scene, true, true); transitionMysteryEncounterIntroVisuals(scene, true, true);
await initBattleWithEnemyConfig(scene, config); await initBattleWithEnemyConfig(scene, config);
} }

View File

@ -22,7 +22,7 @@ const MAX_POKEMON_PRICE_MULTIPLIER = 6;
/** /**
* Pokemon Salesman encounter. * Pokemon Salesman encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/36 | GitHub Issue #36} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3799 | GitHub Issue #3799}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const ThePokemonSalesmanEncounter: MysteryEncounter = export const ThePokemonSalesmanEncounter: MysteryEncounter =

View File

@ -23,7 +23,7 @@ const namespace = "mysteryEncounter:theStrongStuff";
/** /**
* The Strong Stuff encounter. * The Strong Stuff encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/54 | GitHub Issue #54} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3803 | GitHub Issue #3803}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const TheStrongStuffEncounter: MysteryEncounter = export const TheStrongStuffEncounter: MysteryEncounter =

View File

@ -26,7 +26,7 @@ const namespace = "mysteryEncounter:theWinstrateChallenge";
/** /**
* The Winstrate Challenge encounter. * The Winstrate Challenge encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/136 | GitHub Issue #136} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3821 | GitHub Issue #3821}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const TheWinstrateChallengeEncounter: MysteryEncounter = export const TheWinstrateChallengeEncounter: MysteryEncounter =

View File

@ -24,7 +24,7 @@ const namespace = "mysteryEncounter:trainingSession";
/** /**
* Training Session encounter. * Training Session encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/43 | GitHub Issue #43} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3802 | GitHub Issue #3802}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const TrainingSessionEncounter: MysteryEncounter = export const TrainingSessionEncounter: MysteryEncounter =

View File

@ -25,7 +25,7 @@ const SOUND_EFFECT_WAIT_TIME = 700;
/** /**
* Trash to Treasure encounter. * Trash to Treasure encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/74 | GitHub Issue #74} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3809 | GitHub Issue #3809}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const TrashToTreasureEncounter: MysteryEncounter = export const TrashToTreasureEncounter: MysteryEncounter =
@ -177,7 +177,7 @@ async function tryApplyDigRewardItems(scene: BattleScene) {
} }
} }
scene.playSound("item_fanfare"); scene.playSound("bgm/item_fanfare");
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: "2 " + leftovers.name }), undefined, true); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: "2 " + leftovers.name }), undefined, true);
// First Shell bell // First Shell bell
@ -204,17 +204,17 @@ async function tryApplyDigRewardItems(scene: BattleScene) {
} }
} }
scene.playSound("item_fanfare"); scene.playSound("bgm/item_fanfare");
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: "2 " + shellBell.name }), undefined, true); await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: "2 " + shellBell.name }), undefined, true);
} }
async function doGarbageDig(scene: BattleScene) { async function doGarbageDig(scene: BattleScene) {
scene.playSound("PRSFX- Dig2"); scene.playSound("battle-anims/PRSFX- Dig2");
scene.time.delayedCall(SOUND_EFFECT_WAIT_TIME, () => { scene.time.delayedCall(SOUND_EFFECT_WAIT_TIME, () => {
scene.playSound("PRSFX- Dig2"); scene.playSound("battle-anims/PRSFX- Dig2");
scene.playSound("PRSFX- Venom Drench", { volume: 2 }); scene.playSound("battle-anims/PRSFX- Venom Drench", { volume: 2 });
}); });
scene.time.delayedCall(SOUND_EFFECT_WAIT_TIME * 2, () => { scene.time.delayedCall(SOUND_EFFECT_WAIT_TIME * 2, () => {
scene.playSound("PRSFX- Dig2"); scene.playSound("battle-anims/PRSFX- Dig2");
}); });
} }

View File

@ -24,8 +24,8 @@ import { getLevelTotalExp } from "#app/data/exp";
/** i18n namespace for encounter */ /** i18n namespace for encounter */
const namespace = "mysteryEncounter:weirdDream"; const namespace = "mysteryEncounter:weirdDream";
/** Exclude Ultra Beasts (inludes Cosmog/Solgaleo/Lunala/Necrozma), Paradox (includes Miraidon/Koraidon), Eternatus, Urshifu, the Poison Chain trio, Ogerpon */ /** Exclude Ultra Beasts, Paradox, Eternatus, and all legendary/mythical/trio pokemon that are below 570 BST */
const excludedPokemon = [ const EXCLUDED_TRANSFORMATION_SPECIES = [
Species.ETERNATUS, Species.ETERNATUS,
/** UBs */ /** UBs */
Species.NIHILEGO, Species.NIHILEGO,
@ -77,9 +77,18 @@ const excludedPokemon = [
Species.FEZANDIPITI, Species.FEZANDIPITI,
]; ];
const SUPER_LEGENDARY_BST_THRESHOLD = 600;
const NON_LEGENDARY_BST_THRESHOLD = 570;
const GAIN_OLD_GATEAU_ITEM_BST_THRESHOLD = 450;
/** Value ranges of the resulting species BST transformations after adding values to original species */
const HIGH_BST_TRANSFORM_BASE_VALUES = [90, 110];
const STANDARD_BST_TRANSFORM_BASE_VALUES = [40, 50];
/** /**
* Weird Dream encounter. * Weird Dream encounter.
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/137 | GitHub Issue #137} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3822 | GitHub Issue #3822}
* @see For biome requirements check {@linkcode mysteryEncountersByBiome} * @see For biome requirements check {@linkcode mysteryEncountersByBiome}
*/ */
export const WeirdDreamEncounter: MysteryEncounter = export const WeirdDreamEncounter: MysteryEncounter =
@ -225,9 +234,9 @@ function getTeamTransformations(scene: BattleScene): PokemonTransformation[] {
}); });
// Only 1 Pokemon can be transformed into BST higher than 600 // Only 1 Pokemon can be transformed into BST higher than 600
let hasPokemonBstHigherThan600 = false; let hasPokemonInSuperLegendaryBstThreshold = false;
// Only 1 other Pokemon can be transformed into BST between 570-600 // Only 1 other Pokemon can be transformed into BST between 570-600
let hasPokemonBstBetween570And600 = false; let hasPokemonInLegendaryBstThreshold = false;
// First, roll 2 of the party members to new Pokemon at a +90 to +110 BST difference // First, roll 2 of the party members to new Pokemon at a +90 to +110 BST difference
// Then, roll the remainder of the party members at a +40 to +50 BST difference // Then, roll the remainder of the party members at a +40 to +50 BST difference
@ -241,19 +250,19 @@ function getTeamTransformations(scene: BattleScene): PokemonTransformation[] {
const bst = getOriginalBst(scene, removed); const bst = getOriginalBst(scene, removed);
let newBstRange; let newBstRange;
if (i < 2) { if (i < 2) {
newBstRange = [90, 110]; newBstRange = HIGH_BST_TRANSFORM_BASE_VALUES;
} else { } else {
newBstRange = [40, 50]; newBstRange = STANDARD_BST_TRANSFORM_BASE_VALUES;
} }
const newSpecies = getTransformedSpecies(bst, newBstRange, hasPokemonBstHigherThan600, hasPokemonBstBetween570And600, alreadyUsedSpecies); const newSpecies = getTransformedSpecies(bst, newBstRange, hasPokemonInSuperLegendaryBstThreshold, hasPokemonInLegendaryBstThreshold, alreadyUsedSpecies);
const newSpeciesBst = newSpecies.getBaseStatTotal(); const newSpeciesBst = newSpecies.getBaseStatTotal();
if (newSpeciesBst > 600) { if (newSpeciesBst > SUPER_LEGENDARY_BST_THRESHOLD) {
hasPokemonBstHigherThan600 = true; hasPokemonInSuperLegendaryBstThreshold = true;
} }
if (newSpeciesBst <= 600 && newSpeciesBst >= 570) { if (newSpeciesBst <= SUPER_LEGENDARY_BST_THRESHOLD && newSpeciesBst >= NON_LEGENDARY_BST_THRESHOLD) {
hasPokemonBstBetween570And600 = true; hasPokemonInLegendaryBstThreshold = true;
} }
@ -299,9 +308,8 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
return newValue > iv ? newValue : iv; return newValue > iv ? newValue : iv;
}); });
// For pokemon at/below 570 BST or any shiny pokemon, unlock it permanently as if you had caught it // For pokemon at/below 570 BST or any shiny pokemon, unlock it permanently as if you had caught it
if (newPokemon.getSpeciesForm().getBaseStatTotal() <= 570 || newPokemon.isShiny()) { if (newPokemon.getSpeciesForm().getBaseStatTotal() <= NON_LEGENDARY_BST_THRESHOLD || newPokemon.isShiny()) {
if (newPokemon.getSpeciesForm().abilityHidden && newPokemon.abilityIndex === newPokemon.getSpeciesForm().getAbilityCount() - 1) { if (newPokemon.getSpeciesForm().abilityHidden && newPokemon.abilityIndex === newPokemon.getSpeciesForm().getAbilityCount() - 1) {
scene.validateAchv(achvs.HIDDEN_ABILITY); scene.validateAchv(achvs.HIDDEN_ABILITY);
} }
@ -372,8 +380,8 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
scene.addModifier(item, false, false, false, true); scene.addModifier(item, false, false, false, true);
} }
// Any pokemon that is at or below 450 BST gets +20 permanent BST to 3 stats: HP, lowest of Atk/SpAtk, and lowest of Def/SpDef // Any pokemon that is at or below 450 BST gets +20 permanent BST to 3 stats: HP (halved, +10), lowest of Atk/SpAtk, and lowest of Def/SpDef
if (newPokemon.getSpeciesForm().getBaseStatTotal() <= 450) { if (newPokemon.getSpeciesForm().getBaseStatTotal() <= GAIN_OLD_GATEAU_ITEM_BST_THRESHOLD) {
const stats: Stat[] = [Stat.HP]; const stats: Stat[] = [Stat.HP];
const baseStats = newPokemon.getSpeciesForm().baseStats.slice(0); const baseStats = newPokemon.getSpeciesForm().baseStats.slice(0);
// Attack or SpAtk // Attack or SpAtk
@ -435,9 +443,9 @@ function getTransformedSpecies(originalBst: number, bstSearchRange: [number, num
const speciesBst = s.getBaseStatTotal(); const speciesBst = s.getBaseStatTotal();
const bstInRange = speciesBst >= bstMin && speciesBst <= bstCap; const bstInRange = speciesBst >= bstMin && speciesBst <= bstCap;
// Checks that a Pokemon has not already been added in the +600 or 570-600 slots; // Checks that a Pokemon has not already been added in the +600 or 570-600 slots;
const validBst = (!hasPokemonBstBetween570And600 || (speciesBst < 570 || speciesBst > 600)) && const validBst = (!hasPokemonBstBetween570And600 || (speciesBst < NON_LEGENDARY_BST_THRESHOLD || speciesBst > SUPER_LEGENDARY_BST_THRESHOLD)) &&
(!hasPokemonBstHigherThan600 || speciesBst <= 600); (!hasPokemonBstHigherThan600 || speciesBst <= SUPER_LEGENDARY_BST_THRESHOLD);
return bstInRange && validBst && !excludedPokemon.includes(s.speciesId); return bstInRange && validBst && !EXCLUDED_TRANSFORMATION_SPECIES.includes(s.speciesId);
}); });
// There must be at least 20 species available before it will choose one // There must be at least 20 species available before it will choose one

View File

@ -81,7 +81,7 @@ export default class MysteryEncounterOption implements IMysteryEncounterOption {
} }
meetsPrimaryRequirementAndPrimaryPokemonSelected(scene: BattleScene) { meetsPrimaryRequirementAndPrimaryPokemonSelected(scene: BattleScene) {
if (!this.primaryPokemonRequirements) { if (!this.primaryPokemonRequirements || this.primaryPokemonRequirements.length === 0) {
return true; return true;
} }
let qualified: PlayerPokemon[] = scene.getParty(); let qualified: PlayerPokemon[] = scene.getParty();
@ -101,7 +101,7 @@ export default class MysteryEncounterOption implements IMysteryEncounterOption {
return false; return false;
} }
if (this.excludePrimaryFromSecondaryRequirements && this.secondaryPokemon) { if (this.excludePrimaryFromSecondaryRequirements && this.secondaryPokemon && this.secondaryPokemon.length > 0) {
const truePrimaryPool: PlayerPokemon[] = []; const truePrimaryPool: PlayerPokemon[] = [];
const overlap: PlayerPokemon[] = []; const overlap: PlayerPokemon[] = [];
for (const qp of qualified) { for (const qp of qualified) {
@ -135,7 +135,7 @@ export default class MysteryEncounterOption implements IMysteryEncounterOption {
} }
meetsSupportingRequirementAndSupportingPokemonSelected(scene: BattleScene) { meetsSupportingRequirementAndSupportingPokemonSelected(scene: BattleScene) {
if (!this.secondaryPokemonRequirements) { if (!this.secondaryPokemonRequirements || this.secondaryPokemonRequirements.length === 0) {
this.secondaryPokemon = []; this.secondaryPokemon = [];
return true; return true;
} }

View File

@ -13,6 +13,8 @@ import { StatusEffect } from "../status-effect";
import { Type } from "../type"; import { Type } from "../type";
import { WeatherType } from "../weather"; import { WeatherType } from "../weather";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { AttackTypeBoosterModifier } from "#app/modifier/modifier";
import { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type";
export interface EncounterRequirement { export interface EncounterRequirement {
meetsRequirement(scene: BattleScene): boolean; // Boolean to see if a requirement is met meetsRequirement(scene: BattleScene): boolean; // Boolean to see if a requirement is met
@ -420,11 +422,11 @@ export class TypeRequirement extends EncounterPokemonRequirement {
meetsRequirement(scene: BattleScene): boolean { meetsRequirement(scene: BattleScene): boolean {
let partyPokemon = scene.getParty(); let partyPokemon = scene.getParty();
if (isNullOrUndefined(partyPokemon) || this?.requiredType?.length < 0) { if (isNullOrUndefined(partyPokemon)) {
return false; return false;
} }
if (!this.excludeFainted) { if (this.excludeFainted) {
partyPokemon = partyPokemon.filter((pokemon) => !pokemon.isFainted()); partyPokemon = partyPokemon.filter((pokemon) => !pokemon.isFainted());
} }
@ -795,7 +797,7 @@ export class HeldItemRequirement extends EncounterPokemonRequirement {
meetsRequirement(scene: BattleScene): boolean { meetsRequirement(scene: BattleScene): boolean {
const partyPokemon = scene.getParty(); const partyPokemon = scene.getParty();
if (isNullOrUndefined(partyPokemon) || this?.requiredHeldItemModifiers?.length < 0) { if (isNullOrUndefined(partyPokemon)) {
return false; return false;
} }
return this.queryParty(partyPokemon).length >= this.minNumberOfPokemon; return this.queryParty(partyPokemon).length >= this.minNumberOfPokemon;
@ -828,6 +830,53 @@ export class HeldItemRequirement extends EncounterPokemonRequirement {
} }
} }
export class AttackTypeBoosterHeldItemTypeRequirement extends EncounterPokemonRequirement {
requiredHeldItemTypes: Type[];
minNumberOfPokemon: number;
invertQuery: boolean;
constructor(heldItemTypes: Type | Type[], minNumberOfPokemon: number = 1, invertQuery: boolean = false) {
super();
this.minNumberOfPokemon = minNumberOfPokemon;
this.invertQuery = invertQuery;
this.requiredHeldItemTypes = Array.isArray(heldItemTypes) ? heldItemTypes : [heldItemTypes];
}
meetsRequirement(scene: BattleScene): boolean {
const partyPokemon = scene.getParty();
if (isNullOrUndefined(partyPokemon)) {
return false;
}
return this.queryParty(partyPokemon).length >= this.minNumberOfPokemon;
}
queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
if (!this.invertQuery) {
return partyPokemon.filter((pokemon) => this.requiredHeldItemTypes.some((heldItemType) => {
return pokemon.getHeldItems().some((it) => {
return it instanceof AttackTypeBoosterModifier && (it.type as AttackTypeBoosterModifierType).moveType === heldItemType;
});
}));
} else {
// for an inverted query, we only want to get the pokemon that have any held items that are NOT in requiredHeldItemModifiers
// E.g. functions as a blacklist
return partyPokemon.filter((pokemon) => pokemon.getHeldItems().filter((it) => {
return !this.requiredHeldItemTypes.some(heldItemType => it instanceof AttackTypeBoosterModifier && (it.type as AttackTypeBoosterModifierType).moveType === heldItemType);
}).length > 0);
}
}
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
const requiredItems = pokemon?.getHeldItems().filter((it) => {
return this.requiredHeldItemTypes.some(heldItemType => it instanceof AttackTypeBoosterModifier && (it.type as AttackTypeBoosterModifierType).moveType === heldItemType);
});
if (requiredItems && requiredItems.length > 0) {
return ["heldItem", requiredItems[0].type.name];
}
return ["heldItem", ""];
}
}
export class LevelRequirement extends EncounterPokemonRequirement { export class LevelRequirement extends EncounterPokemonRequirement {
requiredLevelRange: [number, number]; requiredLevelRange: [number, number];
minNumberOfPokemon: number; minNumberOfPokemon: number;

View File

@ -122,6 +122,8 @@ export default class MysteryEncounter implements IMysteryEncounter {
onInit?: (scene: BattleScene) => boolean; onInit?: (scene: BattleScene) => boolean;
/** Event when battlefield visuals have finished sliding in and the encounter dialogue begins */ /** Event when battlefield visuals have finished sliding in and the encounter dialogue begins */
onVisualsStart?: (scene: BattleScene) => boolean; onVisualsStart?: (scene: BattleScene) => boolean;
/** Event prior to any rewards logic in {@link MysteryEncounterRewardsPhase} */
onRewards?: (scene: BattleScene) => Promise<void>;
/** Will provide the player party EXP before rewards are displayed for that wave */ /** Will provide the player party EXP before rewards are displayed for that wave */
doEncounterExp?: (scene: BattleScene) => boolean; doEncounterExp?: (scene: BattleScene) => boolean;
/** Will provide the player a rewards shop for that wave */ /** Will provide the player a rewards shop for that wave */
@ -261,7 +263,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
} }
meetsPrimaryRequirementAndPrimaryPokemonSelected(scene: BattleScene): boolean { meetsPrimaryRequirementAndPrimaryPokemonSelected(scene: BattleScene): boolean {
if (this.primaryPokemonRequirements.length === 0) { if (!this.primaryPokemonRequirements || this.primaryPokemonRequirements.length === 0) {
const activeMon = scene.getParty().filter(p => p.isActive(true)); const activeMon = scene.getParty().filter(p => p.isActive(true));
if (activeMon.length > 0) { if (activeMon.length > 0) {
this.primaryPokemon = activeMon[0]; this.primaryPokemon = activeMon[0];
@ -284,7 +286,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
return false; return false;
} }
if (this.excludePrimaryFromSupportRequirements && this.secondaryPokemon) { if (this.excludePrimaryFromSupportRequirements && this.secondaryPokemon && this.secondaryPokemon.length > 0) {
const truePrimaryPool: PlayerPokemon[] = []; const truePrimaryPool: PlayerPokemon[] = [];
const overlap: PlayerPokemon[] = []; const overlap: PlayerPokemon[] = [];
for (const qp of qualified) { for (const qp of qualified) {
@ -318,7 +320,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
} }
meetsSecondaryRequirementAndSecondaryPokemonSelected(scene: BattleScene): boolean { meetsSecondaryRequirementAndSecondaryPokemonSelected(scene: BattleScene): boolean {
if (!this.secondaryPokemonRequirements) { if (!this.secondaryPokemonRequirements || this.secondaryPokemonRequirements.length === 0) {
this.secondaryPokemon = []; this.secondaryPokemon = [];
return true; return true;
} }

View File

@ -27,6 +27,7 @@ import { DancingLessonsEncounter } from "#app/data/mystery-encounters/encounters
import { WeirdDreamEncounter } from "#app/data/mystery-encounters/encounters/weird-dream-encounter"; import { WeirdDreamEncounter } from "#app/data/mystery-encounters/encounters/weird-dream-encounter";
import { TheWinstrateChallengeEncounter } from "#app/data/mystery-encounters/encounters/the-winstrate-challenge-encounter"; import { TheWinstrateChallengeEncounter } from "#app/data/mystery-encounters/encounters/the-winstrate-challenge-encounter";
import { TeleportingHijinksEncounter } from "#app/data/mystery-encounters/encounters/teleporting-hijinks-encounter"; import { TeleportingHijinksEncounter } from "#app/data/mystery-encounters/encounters/teleporting-hijinks-encounter";
import { BugTypeSuperfanEncounter } from "#app/data/mystery-encounters/encounters/bug-type-superfan-encounter";
// Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / 256 // Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / 256
export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 1; export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 1;
@ -171,7 +172,8 @@ const anyBiomeEncounters: MysteryEncounterType[] = [
MysteryEncounterType.BERRIES_ABOUND, MysteryEncounterType.BERRIES_ABOUND,
MysteryEncounterType.CLOWNING_AROUND, MysteryEncounterType.CLOWNING_AROUND,
MysteryEncounterType.WEIRD_DREAM, MysteryEncounterType.WEIRD_DREAM,
MysteryEncounterType.TELEPORTING_HIJINKS MysteryEncounterType.TELEPORTING_HIJINKS,
MysteryEncounterType.BUG_TYPE_SUPERFAN
]; ];
/** /**
@ -276,6 +278,7 @@ export function initMysteryEncounters() {
allMysteryEncounters[MysteryEncounterType.WEIRD_DREAM] = WeirdDreamEncounter; allMysteryEncounters[MysteryEncounterType.WEIRD_DREAM] = WeirdDreamEncounter;
allMysteryEncounters[MysteryEncounterType.THE_WINSTRATE_CHALLENGE] = TheWinstrateChallengeEncounter; allMysteryEncounters[MysteryEncounterType.THE_WINSTRATE_CHALLENGE] = TheWinstrateChallengeEncounter;
allMysteryEncounters[MysteryEncounterType.TELEPORTING_HIJINKS] = TeleportingHijinksEncounter; allMysteryEncounters[MysteryEncounterType.TELEPORTING_HIJINKS] = TeleportingHijinksEncounter;
allMysteryEncounters[MysteryEncounterType.BUG_TYPE_SUPERFAN] = BugTypeSuperfanEncounter;
// Add extreme encounters to biome map // Add extreme encounters to biome map
extremeBiomeEncounters.forEach(encounter => { extremeBiomeEncounters.forEach(encounter => {

View File

@ -36,8 +36,7 @@ export const DANCING_MOVES = [
Moves.QUIVER_DANCE, Moves.QUIVER_DANCE,
Moves.SWORDS_DANCE, Moves.SWORDS_DANCE,
Moves.TEETER_DANCE, Moves.TEETER_DANCE,
Moves.VICTORY_DANCE, Moves.VICTORY_DANCE
Moves.KNOCK_OFF
]; ];
export const DISTRACTION_MOVES = [ export const DISTRACTION_MOVES = [

View File

@ -64,7 +64,7 @@ export function doTrainerExclamation(scene: BattleScene) {
} }
}); });
scene.playSound("GEN8- Exclaim", { volume: 0.7 }); scene.playSound("battle_anims/GEN8- Exclaim", { volume: 0.7 });
} }
export interface EnemyPokemonConfig { export interface EnemyPokemonConfig {
@ -363,13 +363,13 @@ export function updatePlayerMoney(scene: BattleScene, changeValue: number, playS
scene.updateMoneyText(); scene.updateMoneyText();
scene.animateMoneyChanged(false); scene.animateMoneyChanged(false);
if (playSound) { if (playSound) {
scene.playSound("buy"); scene.playSound("se/buy");
} }
if (showMessage) { if (showMessage) {
if (changeValue < 0) { if (changeValue < 0) {
scene.queueMessage(i18next.t("mysteryEncounter:paid_money", { amount: -changeValue }), null, true); scene.queueMessage(i18next.t("mysteryEncounterMessages:paid_money", { amount: -changeValue }), null, true);
} else { } else {
scene.queueMessage(i18next.t("mysteryEncounter:receive_money", { amount: changeValue }), null, true); scene.queueMessage(i18next.t("mysteryEncounterMessages:receive_money", { amount: changeValue }), null, true);
} }
} }
} }
@ -380,17 +380,20 @@ export function updatePlayerMoney(scene: BattleScene, changeValue: number, playS
* @param modifier * @param modifier
* @param pregenArgs - can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc. * @param pregenArgs - can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc.
*/ */
export function generateModifierType(scene: BattleScene, modifier: () => ModifierType, pregenArgs?: any[]): ModifierType { export function generateModifierType(scene: BattleScene, modifier: () => ModifierType, pregenArgs?: any[]): ModifierType | null {
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]?.(); if (!modifierId) {
return null;
}
let result: ModifierType = modifierTypes[modifierId]();
// Populates item id and tier (order matters) // Populates item id and tier (order matters)
result = result result = result
.withIdFromFunc(modifierTypes[modifierId]) .withIdFromFunc(modifierTypes[modifierId])
.withTierFromPool(); .withTierFromPool();
const generatedResult = result instanceof ModifierTypeGenerator ? result.generateType(scene.getParty(), pregenArgs) : result; return result instanceof ModifierTypeGenerator ? result.generateType(scene.getParty(), pregenArgs) : result;
return generatedResult ?? result;
} }
/** /**
@ -399,9 +402,12 @@ export function generateModifierType(scene: BattleScene, modifier: () => Modifie
* @param modifier * @param modifier
* @param pregenArgs - can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc. * @param pregenArgs - can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc.
*/ */
export function generateModifierTypeOption(scene: BattleScene, modifier: () => ModifierType, pregenArgs?: any[]): ModifierTypeOption { export function generateModifierTypeOption(scene: BattleScene, modifier: () => ModifierType, pregenArgs?: any[]): ModifierTypeOption | null {
const result = generateModifierType(scene, modifier, pregenArgs); const result = generateModifierType(scene, modifier, pregenArgs);
if (result) {
return new ModifierTypeOption(result, 0); return new ModifierTypeOption(result, 0);
}
return result;
} }
/** /**
@ -416,7 +422,7 @@ export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (p
return new Promise(resolve => { return new Promise(resolve => {
const modeToSetOnExit = scene.ui.getMode(); const modeToSetOnExit = scene.ui.getMode();
// Open party screen to choose pokemon to train // Open party screen to choose pokemon
scene.ui.setMode(Mode.PARTY, PartyUiMode.SELECT, -1, (slotIndex: integer, option: PartyOption) => { scene.ui.setMode(Mode.PARTY, PartyUiMode.SELECT, -1, (slotIndex: integer, option: PartyOption) => {
if (slotIndex < scene.getParty().length) { if (slotIndex < scene.getParty().length) {
scene.ui.setMode(modeToSetOnExit).then(() => { scene.ui.setMode(modeToSetOnExit).then(() => {
@ -446,12 +452,12 @@ export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (p
label: i18next.t("menu:cancel"), label: i18next.t("menu:cancel"),
handler: () => { handler: () => {
scene.ui.clearText(); scene.ui.clearText();
scene.ui.setMode(Mode.MYSTERY_ENCOUNTER); scene.ui.setMode(modeToSetOnExit);
resolve(false); resolve(false);
return true; return true;
}, },
onHover: () => { onHover: () => {
scene.ui.showText(i18next.t("mysteryEncounter:cancel_option")); scene.ui.showText(i18next.t("mysteryEncounterMessages:cancel_option"));
} }
}); });
@ -461,6 +467,11 @@ export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (p
yOffset: 0, yOffset: 0,
supportHover: true supportHover: true
}; };
// Do hover over the starting selection option
if (fullOptions[0].onHover) {
fullOptions[0].onHover();
}
scene.ui.setModeWithoutClear(Mode.OPTION_SELECT, config, null, true); scene.ui.setModeWithoutClear(Mode.OPTION_SELECT, config, null, true);
}; };
@ -484,6 +495,97 @@ export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (p
}); });
} }
interface PokemonAndOptionSelected {
selectedPokemonIndex: number;
selectedOptionIndex: number;
}
/**
* This function is intended for use inside onPreOptionPhase() of an encounter option
* @param scene
* If a second option needs to be selected, onPokemonSelected should return a OptionSelectItem[] object
* @param options
* @param optionSelectPromptKey
* @param selectablePokemonFilter
* @param onHoverOverCancelOption
*/
export function selectOptionThenPokemon(scene: BattleScene, options: OptionSelectItem[], optionSelectPromptKey: string, selectablePokemonFilter?: PokemonSelectFilter, onHoverOverCancelOption?: () => void): Promise<PokemonAndOptionSelected | null> {
return new Promise<PokemonAndOptionSelected | null>(resolve => {
const modeToSetOnExit = scene.ui.getMode();
const displayOptions = (config: OptionSelectConfig) => {
scene.ui.setMode(Mode.MESSAGE).then(() => {
if (!optionSelectPromptKey) {
// Do hover over the starting selection option
if (fullOptions[0].onHover) {
fullOptions[0].onHover();
}
scene.ui.setMode(Mode.OPTION_SELECT, config);
} else {
showEncounterText(scene, optionSelectPromptKey).then(() => {
// Do hover over the starting selection option
if (fullOptions[0].onHover) {
fullOptions[0].onHover();
}
scene.ui.setMode(Mode.OPTION_SELECT, config);
});
}
});
};
const selectPokemonAfterOption = (selectedOptionIndex: number) => {
// Open party screen to choose a Pokemon
scene.ui.setMode(Mode.PARTY, PartyUiMode.SELECT, -1, (slotIndex: integer, option: PartyOption) => {
if (slotIndex < scene.getParty().length) {
// Pokemon and option selected
scene.ui.setMode(modeToSetOnExit).then(() => {
const result: PokemonAndOptionSelected = { selectedPokemonIndex: slotIndex, selectedOptionIndex: selectedOptionIndex };
resolve(result);
});
} else {
// Back to first option select screen
displayOptions(config);
}
}, selectablePokemonFilter);
};
// Always appends a cancel option to bottom of options
const fullOptions = options.map((option, index) => {
// Update handler to resolve promise
const onSelect = option.handler;
option.handler = () => {
onSelect();
selectPokemonAfterOption(index);
return true;
};
return option;
}).concat({
label: i18next.t("menu:cancel"),
handler: () => {
scene.ui.clearText();
scene.ui.setMode(modeToSetOnExit);
resolve(null);
return true;
},
onHover: () => {
if (onHoverOverCancelOption) {
onHoverOverCancelOption();
}
scene.ui.showText(i18next.t("mysteryEncounterMessages:cancel_option"));
}
});
const config: OptionSelectConfig = {
options: fullOptions,
maxOptions: 7,
yOffset: 0,
supportHover: true
};
displayOptions(config);
});
}
/** /**
* Will initialize reward phases to follow the mystery encounter * Will initialize reward phases to follow the mystery encounter
* Can have shop displayed or skipped * Can have shop displayed or skipped

View File

@ -335,7 +335,7 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
return new Promise(resolve => { return new Promise(resolve => {
scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`); scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`);
scene.time.delayedCall(512, () => { scene.time.delayedCall(512, () => {
scene.playSound("pb_throw"); scene.playSound("se/pb_throw");
// Trainer throw frames // Trainer throw frames
scene.trainer.setFrame("2"); scene.trainer.setFrame("2");
@ -355,7 +355,7 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
onComplete: () => { onComplete: () => {
pokeball.setTexture("pb", `${pokeballAtlasKey}_opening`); pokeball.setTexture("pb", `${pokeballAtlasKey}_opening`);
scene.time.delayedCall(17, () => pokeball.setTexture("pb", `${pokeballAtlasKey}_open`)); scene.time.delayedCall(17, () => pokeball.setTexture("pb", `${pokeballAtlasKey}_open`));
scene.playSound("pb_rel"); scene.playSound("se/pb_rel");
pokemon.tint(getPokeballTintColor(pokeballType)); pokemon.tint(getPokeballTintColor(pokeballType));
addPokeballOpenParticles(scene, pokeball.x, pokeball.y, pokeballType); addPokeballOpenParticles(scene, pokeball.x, pokeball.y, pokeballType);
@ -369,7 +369,7 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
onComplete: () => { onComplete: () => {
pokeball.setTexture("pb", `${pokeballAtlasKey}_opening`); pokeball.setTexture("pb", `${pokeballAtlasKey}_opening`);
pokemon.setVisible(false); pokemon.setVisible(false);
scene.playSound("pb_catch"); scene.playSound("se/pb_catch");
scene.time.delayedCall(17, () => pokeball.setTexture("pb", `${pokeballAtlasKey}`)); scene.time.delayedCall(17, () => pokeball.setTexture("pb", `${pokeballAtlasKey}`));
const doShake = () => { const doShake = () => {
@ -397,13 +397,13 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
failCatch(scene, pokemon, originalY, pokeball, pokeballType).then(() => resolve(false)); failCatch(scene, pokemon, originalY, pokeball, pokeballType).then(() => resolve(false));
} else if (shakeCount++ < 3) { } else if (shakeCount++ < 3) {
if (randSeedInt(65536) < ballTwitchRate) { if (randSeedInt(65536) < ballTwitchRate) {
scene.playSound("pb_move"); scene.playSound("se/pb_move");
} else { } else {
shakeCounter.stop(); shakeCounter.stop();
failCatch(scene, pokemon, originalY, pokeball, pokeballType).then(() => resolve(false)); failCatch(scene, pokemon, originalY, pokeball, pokeballType).then(() => resolve(false));
} }
} else { } else {
scene.playSound("pb_lock"); scene.playSound("se/pb_lock");
addPokeballCaptureStars(scene, pokeball); addPokeballCaptureStars(scene, pokeball);
const pbTint = scene.add.sprite(pokeball.x, pokeball.y, "pb", "pb"); const pbTint = scene.add.sprite(pokeball.x, pokeball.y, "pb", "pb");
@ -445,7 +445,7 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
function failCatch(scene: BattleScene, pokemon: EnemyPokemon, originalY: number, pokeball: Phaser.GameObjects.Sprite, pokeballType: PokeballType) { function failCatch(scene: BattleScene, pokemon: EnemyPokemon, originalY: number, pokeball: Phaser.GameObjects.Sprite, pokeballType: PokeballType) {
return new Promise<void>(resolve => { return new Promise<void>(resolve => {
scene.playSound("pb_rel"); scene.playSound("se/pb_rel");
pokemon.setY(originalY); pokemon.setY(originalY);
if (pokemon.status?.effect !== StatusEffect.SLEEP) { if (pokemon.status?.effect !== StatusEffect.SLEEP) {
pokemon.cry(pokemon.getHpRatio() > 0.25 ? undefined : { rate: 0.85 }); pokemon.cry(pokemon.getHpRatio() > 0.25 ? undefined : { rate: 0.85 });
@ -591,7 +591,7 @@ function removePb(scene: BattleScene, pokeball: Phaser.GameObjects.Sprite) {
export async function doPokemonFlee(scene: BattleScene, pokemon: EnemyPokemon): Promise<void> { export async function doPokemonFlee(scene: BattleScene, pokemon: EnemyPokemon): Promise<void> {
await new Promise<void>(resolve => { await new Promise<void>(resolve => {
scene.playSound("flee"); scene.playSound("se/flee");
// Ease pokemon out // Ease pokemon out
scene.tweens.add({ scene.tweens.add({
targets: pokemon, targets: pokemon,
@ -635,3 +635,50 @@ export function doPlayerFlee(scene: BattleScene, pokemon: EnemyPokemon): Promise
}); });
}); });
} }
// Bug Species and their corresponding weights
const GOLDEN_BUG_NET_SPECIES_POOL: [Species, number][] = [
[Species.SCYTHER, 40],
[Species.SCIZOR, 40],
[Species.KLEAVOR, 40],
[Species.PINSIR, 40],
[Species.HERACROSS, 40],
[Species.YANMA, 40],
[Species.YANMEGA, 40],
[Species.SHUCKLE, 40],
[Species.ANORITH, 40],
[Species.ARMALDO, 40],
[Species.ESCAVALIER, 40],
[Species.ACCELGOR, 40],
[Species.JOLTIK, 40],
[Species.GALVANTULA, 40],
[Species.DURANT, 40],
[Species.LARVESTA, 40],
[Species.VOLCARONA, 40],
[Species.DEWPIDER, 40],
[Species.ARAQUANID, 40],
[Species.WIMPOD, 40],
[Species.GOLISOPOD, 40],
[Species.SIZZLIPEDE, 40],
[Species.CENTISKORCH, 40],
[Species.NYMBLE, 40],
[Species.LOKIX, 40],
[Species.BUZZWOLE, 1],
[Species.PHEROMOSA, 1],
];
export function getGoldenBugNetSpecies(scene: BattleScene, waveIndex: integer, level: integer): PokemonSpecies {
const totalWeight = GOLDEN_BUG_NET_SPECIES_POOL.reduce((a, b) => a + b[1], 0);
const roll = randSeedInt(totalWeight);
let w = 0;
for (const species of GOLDEN_BUG_NET_SPECIES_POOL) {
w += species[1];
if (roll < w) {
return getPokemonSpecies(species);
}
}
// Defaults to Scyther
return getPokemonSpecies(GOLDEN_BUG_NET_SPECIES_POOL[0][0]);
}

View File

@ -2104,5 +2104,7 @@ export const trainerConfigs: TrainerConfigs = {
.setPartyTemplates(trainerPartyTemplates.ONE_AVG), .setPartyTemplates(trainerPartyTemplates.ONE_AVG),
[TrainerType.VITO]: new TrainerConfig(++t).setName("Vito").setTitle("The Winstrates") [TrainerType.VITO]: new TrainerConfig(++t).setName("Vito").setTitle("The Winstrates")
.setMoneyMultiplier(2) .setMoneyMultiplier(2)
.setPartyTemplates(new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, PartyMemberStrength.STRONG))) .setPartyTemplates(new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, PartyMemberStrength.STRONG))),
[TrainerType.BUG_TYPE_SUPERFAN]: new TrainerConfig(++t).setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.ACE_TRAINER)
.setPartyTemplates(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE))
}; };

View File

@ -24,5 +24,6 @@ export enum MysteryEncounterType {
DANCING_LESSONS, DANCING_LESSONS,
WEIRD_DREAM, WEIRD_DREAM,
THE_WINSTRATE_CHALLENGE, THE_WINSTRATE_CHALLENGE,
TELEPORTING_HIJINKS TELEPORTING_HIJINKS,
BUG_TYPE_SUPERFAN
} }

View File

@ -94,6 +94,7 @@ export enum TrainerType {
VIVI, VIVI,
VICKY, VICKY,
VITO, VITO,
BUG_TYPE_SUPERFAN,
BROCK = 200, BROCK = 200,
MISTY, MISTY,

View File

@ -59,6 +59,7 @@ import modifierSelectUiHandler from "./modifier-select-ui-handler.json";
import moveTriggers from "./move-trigger.json"; import moveTriggers from "./move-trigger.json";
import runHistory from "./run-history.json"; import runHistory from "./run-history.json";
import { mysteryEncounter } from "#app/locales/en/mystery-encounter"; import { mysteryEncounter } from "#app/locales/en/mystery-encounter";
import mysteryEncounterMessages from "./mystery-encounter-messages.json";
export const enConfig = { export const enConfig = {
ability, ability,
@ -121,5 +122,6 @@ export const enConfig = {
modifierSelectUiHandler, modifierSelectUiHandler,
moveTriggers, moveTriggers,
runHistory, runHistory,
mysteryEncounter: mysteryEncounter mysteryEncounter: mysteryEncounter,
mysteryEncounterMessages
}; };

View File

@ -841,7 +841,7 @@
"2": "We're pulling out all the stops to put your Pokémon down." "2": "We're pulling out all the stops to put your Pokémon down."
}, },
"victory": { "victory": {
"1": "At times we battle, and sometimes we team up...\n $It's great how Trainers can interact." "1": "At times we battle, and sometimes we team up...$It's great how Trainers can interact."
}, },
"defeat": { "defeat": {
"1": "You put up quite the display.\nBetter luck next time." "1": "You put up quite the display.\nBetter luck next time."
@ -857,7 +857,7 @@
}, },
"winstrates_victoria": { "winstrates_victoria": {
"encounter": { "encounter": {
"1": "My goodness! Aren't you young?\n $You must be quite the trainer to beat my husband, though.\n $Now I suppose it's my turn to battle!" "1": "My goodness! Aren't you young?$You must be quite the trainer to beat my husband, though.$Now I suppose it's my turn to battle!"
}, },
"victory": { "victory": {
"1": "Uwah! Just how strong are you?!" "1": "Uwah! Just how strong are you?!"
@ -865,7 +865,7 @@
}, },
"winstrates_vivi": { "winstrates_vivi": {
"encounter": { "encounter": {
"1": "You're stronger than Mom? Wow!\n $But I'm strong, too!\nReally! Honestly!" "1": "You're stronger than Mom? Wow!$But I'm strong, too!\nReally! Honestly!"
}, },
"victory": { "victory": {
"1": "Huh? Did I really lose?\nSnivel... Grandmaaa!" "1": "Huh? Did I really lose?\nSnivel... Grandmaaa!"
@ -873,7 +873,7 @@
}, },
"winstrates_vicky": { "winstrates_vicky": {
"encounter": { "encounter": {
"1": "How dare you make my precious\ngranddaughter cry!\n $I see I need to teach you a lesson.\nPrepare to feel the sting of defeat!" "1": "How dare you make my precious\ngranddaughter cry!$I see I need to teach you a lesson.\nPrepare to feel the sting of defeat!"
}, },
"victory": { "victory": {
"1": "Whoa! So strong!\nMy granddaughter wasn't lying." "1": "Whoa! So strong!\nMy granddaughter wasn't lying."
@ -881,7 +881,7 @@
}, },
"winstrates_vito": { "winstrates_vito": {
"encounter": { "encounter": {
"1": "I trained together with my whole family,\nevery one of us!\n $I'm not losing to anyone!" "1": "I trained together with my whole family,\nevery one of us!$I'm not losing to anyone!"
}, },
"victory": { "victory": {
"1": "I was better than everyone in my family.\nI've never lost before..." "1": "I was better than everyone in my family.\nI've never lost before..."

View File

@ -841,7 +841,7 @@
"2": "We're pulling out all the stops to put your Pokémon down." "2": "We're pulling out all the stops to put your Pokémon down."
}, },
"victory": { "victory": {
"1": "At times we battle, and sometimes we team up...\n $It's great how Trainers can interact." "1": "At times we battle, and sometimes we team up...$It's great how Trainers can interact."
}, },
"defeat": { "defeat": {
"1": "You put up quite the display.\nBetter luck next time." "1": "You put up quite the display.\nBetter luck next time."
@ -857,7 +857,7 @@
}, },
"winstrates_victoria": { "winstrates_victoria": {
"encounter": { "encounter": {
"1": "My goodness! Aren't you young?\n $You must be quite the trainer to beat my husband, though.\n $Now I suppose it's my turn to battle!" "1": "My goodness! Aren't you young?$You must be quite the trainer to beat my husband, though.$Now I suppose it's my turn to battle!"
}, },
"victory": { "victory": {
"1": "Uwah! Just how strong are you?!" "1": "Uwah! Just how strong are you?!"
@ -865,7 +865,7 @@
}, },
"winstrates_vivi": { "winstrates_vivi": {
"encounter": { "encounter": {
"1": "You're stronger than Mom? Wow!\n $But I'm strong, too!\nReally! Honestly!" "1": "You're stronger than Mom? Wow!$But I'm strong, too!\nReally! Honestly!"
}, },
"victory": { "victory": {
"1": "Huh? Did I really lose?\nSnivel... Grandmaaa!" "1": "Huh? Did I really lose?\nSnivel... Grandmaaa!"
@ -873,7 +873,7 @@
}, },
"winstrates_vicky": { "winstrates_vicky": {
"encounter": { "encounter": {
"1": "How dare you make my precious\ngranddaughter cry!\n $I see I need to teach you a lesson.\nPrepare to feel the sting of defeat!" "1": "How dare you make my precious\ngranddaughter cry!$I see I need to teach you a lesson.\nPrepare to feel the sting of defeat!"
}, },
"victory": { "victory": {
"1": "Whoa! So strong!\nMy granddaughter wasn't lying." "1": "Whoa! So strong!\nMy granddaughter wasn't lying."
@ -881,7 +881,7 @@
}, },
"winstrates_vito": { "winstrates_vito": {
"encounter": { "encounter": {
"1": "I trained together with my whole family,\nevery one of us!\n $I'm not losing to anyone!" "1": "I trained together with my whole family,\nevery one of us!$I'm not losing to anyone!"
}, },
"victory": { "victory": {
"1": "I was better than everyone in my family.\nI've never lost before..." "1": "I was better than everyone in my family.\nI've never lost before..."

View File

@ -259,9 +259,10 @@
"ENEMY_FUSED_CHANCE": { "name": "Fusion Token", "description": "Adds a 1% chance that a wild Pokémon will be a fusion." }, "ENEMY_FUSED_CHANCE": { "name": "Fusion Token", "description": "Adds a 1% chance that a wild Pokémon will be a fusion." },
"MYSTERY_ENCOUNTER_SHUCKLE_JUICE": { "name": "Shuckle Juice" }, "MYSTERY_ENCOUNTER_SHUCKLE_JUICE": { "name": "Shuckle Juice" },
"MYSTERY_ENCOUNTER_BLACK_SLUDGE": { "name": "Black Sludge", "description": "The stench is so powerful that healing items are no longer available to purchase in shops." }, "MYSTERY_ENCOUNTER_BLACK_SLUDGE": { "name": "Black Sludge", "description": "The stench is so powerful that shops will only sell you items at a steep cost increase." },
"MYSTERY_ENCOUNTER_MACHO_BRACE": { "name": "Macho Brace", "description": "Defeating a Pokémon grants the holder a Macho Brace stack. Each stack slightly boosts stats, with an extra bonus at max stacks." }, "MYSTERY_ENCOUNTER_MACHO_BRACE": { "name": "Macho Brace", "description": "Defeating a Pokémon grants the holder a Macho Brace stack. Each stack slightly boosts stats, with an extra bonus at max stacks." },
"MYSTERY_ENCOUNTER_OLD_GATEAU": { "name": "Old Gateau", "description": "Increases the holder's {{stats}} stats by {{statValue}}." } "MYSTERY_ENCOUNTER_OLD_GATEAU": { "name": "Old Gateau", "description": "Increases the holder's {{stats}} stats by {{statValue}}." },
"MYSTERY_ENCOUNTER_GOLDEN_BUG_NET": { "name": "Golden Bug Net", "description": "Imbues the owner with luck to find Bug Type Pokémon more often. Has a strange heft to it." }
}, },
"SpeciesBoosterItem": { "SpeciesBoosterItem": {
"LIGHT_BALL": { "name": "Light Ball", "description": "It's a mysterious orb that boosts Pikachu's Attack and Sp. Atk stats." }, "LIGHT_BALL": { "name": "Light Ball", "description": "It's a mysterious orb that boosts Pikachu's Attack and Sp. Atk stats." },

View File

@ -0,0 +1,6 @@
{
"paid_money": "You paid ₽{{amount, number}}.",
"receive_money": "You received ₽{{amount, number}}!",
"affects_pokedex": "Affects Pokédex Data",
"cancel_option": "Return to encounter option select."
}

View File

@ -24,6 +24,7 @@ import dancingLessonsDialogue from "#app/locales/en/mystery-encounters/dancing-l
import weirdDreamDialogue from "#app/locales/en/mystery-encounters/weird-dream-dialogue.json"; import weirdDreamDialogue from "#app/locales/en/mystery-encounters/weird-dream-dialogue.json";
import theWinstrateChallengeDialogue from "#app/locales/en/mystery-encounters/the-winstrate-challenge-dialogue.json"; import theWinstrateChallengeDialogue from "#app/locales/en/mystery-encounters/the-winstrate-challenge-dialogue.json";
import teleportingHijinksDialogue from "#app/locales/en/mystery-encounters/teleporting-hijinks-dialogue.json"; import teleportingHijinksDialogue from "#app/locales/en/mystery-encounters/teleporting-hijinks-dialogue.json";
import bugTypeSuperfanDialogue from "#app/locales/en/mystery-encounters/bug-type-superfan-dialogue.json";
/** /**
* Injection patterns that can be used: * Injection patterns that can be used:
@ -44,12 +45,6 @@ export const mysteryEncounter = {
// DO NOT REMOVE // DO NOT REMOVE
"unit_test_dialogue": "{{test}}{{test}} {{test{{test}}}} {{test1}} {{test\}} {{test\\}} {{test\\\}} {test}}", "unit_test_dialogue": "{{test}}{{test}} {{test{{test}}}} {{test1}} {{test\}} {{test\\}} {{test\\\}} {test}}",
// General use content
"paid_money": "You paid ₽{{amount, number}}.",
"receive_money": "You received ₽{{amount, number}}!",
"affects_pokedex": "Affects Pokédex Data",
"cancel_option": "Return to encounter option select.",
mysteriousChallengers: mysteriousChallengersDialogue, mysteriousChallengers: mysteriousChallengersDialogue,
mysteriousChest: mysteriousChestDialogue, mysteriousChest: mysteriousChestDialogue,
darkDeal: darkDealDialogue, darkDeal: darkDealDialogue,
@ -75,5 +70,6 @@ export const mysteryEncounter = {
dancingLessons: dancingLessonsDialogue, dancingLessons: dancingLessonsDialogue,
weirdDream: weirdDreamDialogue, weirdDream: weirdDreamDialogue,
theWinstrateChallenge: theWinstrateChallengeDialogue, theWinstrateChallenge: theWinstrateChallengeDialogue,
teleportingHijinks: teleportingHijinksDialogue teleportingHijinks: teleportingHijinksDialogue,
bugTypeSuperfan: bugTypeSuperfanDialogue
} as const; } as const;

View File

@ -1,29 +1,29 @@
{ {
"intro": "An extremely strong trainer approaches you...", "intro": "An extremely strong trainer approaches you...",
"buck": { "buck": {
"intro_dialogue": "Yo, trainer! My name's Buck.\n $I have a super awesome proposal\nfor a strong trainer such as yourself!\n $I'm carrying two rare Pokémon Eggs with me,\nbut I'd like someone else to care for one.\n $If you can prove your strength as a trainer to me,\nI'll give you the rarer egg!", "intro_dialogue": "Yo, trainer! My name's Buck.$I have a super awesome proposal\nfor a strong trainer such as yourself!$I'm carrying two rare Pokémon Eggs with me,\nbut I'd like someone else to care for one.$If you can prove your strength as a trainer to me,\nI'll give you the rarer egg!",
"accept": "Whoooo, I'm getting fired up!", "accept": "Whoooo, I'm getting fired up!",
"decline": "Darn, it looks like your\nteam isn't in peak condition.\n $Here, let me help with that." "decline": "Darn, it looks like your\nteam isn't in peak condition.$Here, let me help with that."
}, },
"cheryl": { "cheryl": {
"intro_dialogue": "Hello, my name's Cheryl.\n $I have a particularly interesting request,\nfor a strong trainer such as yourself.\n $I'm carrying two rare Pokémon Eggs with me,\nbut I'd like someone else to care for one.\n $If you can prove your strength as a trainer to me,\nI'll give you the rarer Egg!", "intro_dialogue": "Hello, my name's Cheryl.$I have a particularly interesting request,\nfor a strong trainer such as yourself.$I'm carrying two rare Pokémon Eggs with me,\nbut I'd like someone else to care for one.$If you can prove your strength as a trainer to me,\nI'll give you the rarer Egg!",
"accept": "I hope you're ready!", "accept": "I hope you're ready!",
"decline": "I understand, it looks like your team\nisn't in the best condition at the moment.\n $Here, let me help with that." "decline": "I understand, it looks like your team\nisn't in the best condition at the moment.$Here, let me help with that."
}, },
"marley": { "marley": {
"intro_dialogue": "...@d{64} I'm Marley.\n $I have an offer for you...\n $I'm carrying two Pokémon Eggs with me,\nbut I'd like someone else to care for one.\n $If you're stronger than me,\nI'll give you the rarer Egg.", "intro_dialogue": "...@d{64} I'm Marley.$I have an offer for you...$I'm carrying two Pokémon Eggs with me,\nbut I'd like someone else to care for one.$If you're stronger than me,\nI'll give you the rarer Egg.",
"accept": "... I see.", "accept": "... I see.",
"decline": "... I see.\n $Your Pokémon look hurt...\nLet me help." "decline": "... I see.$Your Pokémon look hurt...\nLet me help."
}, },
"mira": { "mira": {
"intro_dialogue": "Hi! I'm Mira!\n $Mira has a request\nfor a strong trainer like you!\n $Mira has two rare Pokémon Eggs,\nbut Mira wants someone else to take one!\n $If you show Mira that you're strong,\nMira will give you the rarer Egg!", "intro_dialogue": "Hi! I'm Mira!$Mira has a request\nfor a strong trainer like you!$Mira has two rare Pokémon Eggs,\nbut Mira wants someone else to take one!$If you show Mira that you're strong,\nMira will give you the rarer Egg!",
"accept": "You'll battle Mira?\nYay!", "accept": "You'll battle Mira?\nYay!",
"decline": "Aww, no battle?\nThat's okay!\n $Here, Mira will heal your team!" "decline": "Aww, no battle?\nThat's okay!$Here, Mira will heal your team!"
}, },
"riley": { "riley": {
"intro_dialogue": "I'm Riley.\n $I have an odd proposal\nfor a strong trainer such as yourself.\n $I'm carrying two rare Pokémon Eggs with me,\nbut I'd like to give one to another trainer.\n $If you can prove your strength to me,\nI'll give you the rarer Egg!", "intro_dialogue": "I'm Riley.$I have an odd proposal\nfor a strong trainer such as yourself.$I'm carrying two rare Pokémon Eggs with me,\nbut I'd like to give one to another trainer.$If you can prove your strength to me,\nI'll give you the rarer Egg!",
"accept": "That look you have...\nLet's do this.", "accept": "That look you have...\nLet's do this.",
"decline": "I understand, your team looks beat up.\n $Here, let me help with that." "decline": "I understand, your team looks beat up.$Here, let me help with that."
}, },
"title": "A Trainer's Test", "title": "A Trainer's Test",
"description": "It seems this trainer is willing to give you an Egg regardless of your decision. However, if you can manage to defeat this strong trainer, you'll receive a much rarer Egg.", "description": "It seems this trainer is willing to give you an Egg regardless of your decision. However, if you can manage to defeat this strong trainer, you'll receive a much rarer Egg.",

View File

@ -9,17 +9,17 @@
"tooltip": "(-) Tough Battle\n(+) Rewards from its Berry Hoard", "tooltip": "(-) Tough Battle\n(+) Rewards from its Berry Hoard",
"selected": "The Greedent stuffs its cheeks\nand prepares for battle!", "selected": "The Greedent stuffs its cheeks\nand prepares for battle!",
"boss_enraged": "Greedent's fierce love for food has it incensed!", "boss_enraged": "Greedent's fierce love for food has it incensed!",
"food_stash": "It looks like the Greedent was guarding an enormous stash of food!\n $@s{item_fanfare}Each Pokémon in your party gains 1x Reviver Seed!" "food_stash": "It looks like the Greedent was guarding an enormous stash of food!$@s{item_fanfare}Each Pokémon in your party gains 1x Reviver Seed!"
}, },
"2": { "2": {
"label": "Reason with It", "label": "Reason with It",
"tooltip": "(+) Regain Some Lost Berries", "tooltip": "(+) Regain Some Lost Berries",
"selected": "Your pleading strikes a chord with the Greedent.\n $It doesn't give all your berries back, but still tosses a few in your direction." "selected": "Your pleading strikes a chord with the Greedent.$It doesn't give all your berries back, but still tosses a few in your direction."
}, },
"3": { "3": {
"label": "Let It Have the Food", "label": "Let It Have the Food",
"tooltip": "(-) Lose All Berries\n(?) The Greedent Will Like You", "tooltip": "(-) Lose All Berries\n(?) The Greedent Will Like You",
"selected": "The Greedent devours the entire\nstash of berries in a flash!\n $Patting its stomach,\nit looks at you appreciatively.\n $Perhaps you could feed it\nmore berries on your adventure...\n $@s{level_up_fanfare}The Greedent wants to join your party!" "selected": "The Greedent devours the entire\nstash of berries in a flash!$Patting its stomach,\nit looks at you appreciatively.$Perhaps you could feed it\nmore berries on your adventure...$@s{level_up_fanfare}The Greedent wants to join your party!"
} }
} }
} }

View File

@ -1,7 +1,7 @@
{ {
"intro": "You're stopped by a rich looking boy.", "intro": "You're stopped by a rich looking boy.",
"speaker": "Rich Boy", "speaker": "Rich Boy",
"intro_dialogue": "Good day to you.\n $I can't help but notice that your\n{{strongestPokemon}} looks positively divine!\n $I've always wanted to have a pet like that!\n $I'd pay you handsomely,\nand also give you this old bauble!", "intro_dialogue": "Good day to you.$I can't help but notice that your\n{{strongestPokemon}} looks positively divine!$I've always wanted to have a pet like that!$I'd pay you handsomely,\nand also give you this old bauble!",
"title": "An Offer You Can't Refuse", "title": "An Offer You Can't Refuse",
"description": "You're being offered a @[TOOLTIP_TITLE]{Shiny Charm} and {{price, money}} for your {{strongestPokemon}}!\n\nIt's an extremely good deal, but can you really bear to part with such a strong team member?", "description": "You're being offered a @[TOOLTIP_TITLE]{Shiny Charm} and {{price, money}} for your {{strongestPokemon}}!\n\nIt's an extremely good deal, but can you really bear to part with such a strong team member?",
"query": "What will you do?", "query": "What will you do?",
@ -9,7 +9,7 @@
"1": { "1": {
"label": "Accept the Deal", "label": "Accept the Deal",
"tooltip": "(-) Lose {{strongestPokemon}}\n(+) Gain a @[TOOLTIP_TITLE]{Shiny Charm}\n(+) Gain {{price, money}}", "tooltip": "(-) Lose {{strongestPokemon}}\n(+) Gain a @[TOOLTIP_TITLE]{Shiny Charm}\n(+) Gain {{price, money}}",
"selected": "Wonderful!@d{32} Come along, {{strongestPokemon}}!\n $It's time to show you off to everyone at the yacht club!\n $They'll be so jealous!" "selected": "Wonderful!@d{32} Come along, {{strongestPokemon}}!$It's time to show you off to everyone at the yacht club!$They'll be so jealous!"
}, },
"2": { "2": {
"label": "Extort the Kid", "label": "Extort the Kid",
@ -20,7 +20,7 @@
"3": { "3": {
"label": "Leave", "label": "Leave",
"tooltip": "(-) No Rewards", "tooltip": "(-) No Rewards",
"selected": "What a rotten day...\n $Ah, well. Let's return to the yacht club then, Liepard." "selected": "What a rotten day...$Ah, well. Let's return to the yacht club then, Liepard."
} }
} }
} }

View File

@ -13,8 +13,8 @@
"2": { "2": {
"label": "Race to the Bush", "label": "Race to the Bush",
"tooltip": "(-) {{fastestPokemon}} Uses its Speed\n(+) Gain Berries", "tooltip": "(-) {{fastestPokemon}} Uses its Speed\n(+) Gain Berries",
"selected": "Your {{fastestPokemon}} races for the berry bush!\n $It manages to nab {{numBerries}} before the {{enemyPokemon}} can react!\n $You quickly retreat with your newfound prize.", "selected": "Your {{fastestPokemon}} races for the berry bush!$It manages to nab {{numBerries}} before the {{enemyPokemon}} can react!$You quickly retreat with your newfound prize.",
"selected_bad": "Your {{fastestPokemon}} races for the berry bush!\n $Oh no! The {{enemyPokemon}} was faster and blocked off the approach!", "selected_bad": "Your {{fastestPokemon}} races for the berry bush!$Oh no! The {{enemyPokemon}} was faster and blocked off the approach!",
"boss_enraged": "The opposing {{enemyPokemon}} has become enraged!" "boss_enraged": "The opposing {{enemyPokemon}} has become enraged!"
}, },
"3": { "3": {

View File

@ -0,0 +1,38 @@
{
"intro": "An unusual trainer with all kinds of Bug paraphernalia blocks your way!",
"intro_dialogue": "Hey, trainer! I'm on a mission to find the rarest Bug Pokémon in existence!$You must love Bug Pokémon too, right?\nEveryone loves Bug Pokémon!",
"title": "The Bug-Type Superfan",
"speaker": "Bug-Type Superfan",
"description": "The trainer prattles, not even waiting for a response...\n\nIt seems the only way to get out of this situation is by catching the trainer's attention!",
"query": "What will you do?",
"option": {
"1": {
"label": "Offer to Battle",
"tooltip": "(-) Challenging Battle\n(+) Teach a Pokémon a Bug Type Move",
"selected": "A challenge, eh?\nMy bugs are more than ready for you!"
},
"2": {
"label": "Show Your Bug Types",
"tooltip": "(+) Receive a Gift Item",
"disabled_tooltip": "You need at least 1 Bug Type Pokémon on your team to select this.",
"selected": "You show the trainer all your Bug Type Pokémon...",
"selected_0_to_1": "Huh? You only have {{numBugTypes}}...$Guess I'm wasting my breath on someone like you...",
"selected_2_3": "Hey, you've got {{numBugTypes}} Bug Types!\nNot bad.$Here, this might help you on your journey to catch more!",
"selected_4_to_5": "What? You have {{numBugTypes}} Bug Types?\nNice!$You're not quite at my level, but I can see shades of myself in you!\n$Take this, my young apprentice!",
"selected_6": "Whoa! {{numBugTypes}} Bug Types!\n$You must love Bug Types almost as much as I do!$Here, take this as a token of our camaraderie!"
},
"3": {
"label": "Gift a Bug Item",
"tooltip": "(-) Give the trainer a Quick Claw, Grip Claw, or Silver Powder\n(+) Receive a Gift Item",
"disabled_tooltip": "You need to have a Quick Claw, Grip Claw, or Silver Powder to select this.",
"select_prompt": "Select an item to give.",
"invalid_selection": "Pokémon doesn't have that kind of item.",
"selected": "You hand the trainer a {{selectedItem}}.",
"selected_dialogue": "Whoa! A {{selectedItem}}, for me?\nYou're not so bad, kid!$As a token of my appreciation,\nI want you to have this special gift!$It's been passed all through my family, and now I want you to have it!"
}
},
"battle_won": "Your knowledge and skill were perfect at exploiting our weaknesses!$In exchange for the valuable lesson,\nallow me to teach one of your Pokémon a Bug Type Move!",
"teach_move_prompt": "Select a move to teach a Pokémon.",
"confirm_no_teach": "You sure you don't want to learn one of these great moves?",
"outro": "I see great Bug Pokémon in your future!\nMay our paths cross again!$Bug out!"
}

View File

@ -13,14 +13,14 @@
"2": { "2": {
"label": "Learn Its Dance", "label": "Learn Its Dance",
"tooltip": "(+) Teach a Pokémon Revelation Dance", "tooltip": "(+) Teach a Pokémon Revelation Dance",
"selected": "You watch the Oricorio closely as it performs its dance...\n $@s{level_up_fanfare}Your {{selectedPokemon}} wants to learn Revelation Dance!" "selected": "You watch the Oricorio closely as it performs its dance...$@s{level_up_fanfare}Your {{selectedPokemon}} wants to learn Revelation Dance!"
}, },
"3": { "3": {
"label": "Show It a Dance", "label": "Show It a Dance",
"tooltip": "(-) Teach the Oricorio a Dance Move\n(+) The Oricorio Will Like You", "tooltip": "(-) Teach the Oricorio a Dance Move\n(+) The Oricorio Will Like You",
"disabled_tooltip": "Your Pokémon need to know a Dance move for this.", "disabled_tooltip": "Your Pokémon need to know a Dance move for this.",
"select_prompt": "Select a Dance type move to use.", "select_prompt": "Select a Dance type move to use.",
"selected": "The Oricorio watches in fascination as\n{{selectedPokemon}} shows off {{selectedMove}}!\n $It loves the display!\n $@s{level_up_fanfare}The Oricorio wants to join your party!" "selected": "The Oricorio watches in fascination as\n{{selectedPokemon}} shows off {{selectedMove}}!$It loves the display!$@s{level_up_fanfare}The Oricorio wants to join your party!"
} }
}, },
"invalid_selection": "This Pokémon doesn't know a Dance move" "invalid_selection": "This Pokémon doesn't know a Dance move"

View File

@ -3,7 +3,7 @@
{ {
"intro": "A strange man in a tattered coat\nstands in your way...", "intro": "A strange man in a tattered coat\nstands in your way...",
"speaker": "Shady Guy", "speaker": "Shady Guy",
"intro_dialogue": "Hey, you!\n $I've been working on a new device\nto bring out a Pokémon's latent power!\n $It completely rebinds the Pokémon's atoms\nat a molecular level into a far more powerful form.\n $Hehe...@d{64} I just need some sac-@d{32}\nErr, test subjects, to prove it works.", "intro_dialogue": "Hey, you!$I've been working on a new device\nto bring out a Pokémon's latent power!$It completely rebinds the Pokémon's atoms\nat a molecular level into a far more powerful form.$Hehe...@d{64} I just need some sac-@d{32}\nErr, test subjects, to prove it works.",
"title": "Dark Deal", "title": "Dark Deal",
"description": "The disturbing fellow holds up some Pokéballs.\n\"I'll make it worth your while! You can have these strong Pokéballs as payment, All I need is a Pokémon from your team! Hehe...\"", "description": "The disturbing fellow holds up some Pokéballs.\n\"I'll make it worth your while! You can have these strong Pokéballs as payment, All I need is a Pokémon from your team! Hehe...\"",
"query": "What will you do?", "query": "What will you do?",
@ -11,8 +11,8 @@
"1": { "1": {
"label": "Accept", "label": "Accept",
"tooltip": "(+) 5 Rogue Balls\n(?) Enhance a Random Pokémon", "tooltip": "(+) 5 Rogue Balls\n(?) Enhance a Random Pokémon",
"selected_dialogue": "Let's see, that {{pokeName}} will do nicely!\n $Remember, I'm not responsible\nif anything bad happens!@d{32} Hehe...", "selected_dialogue": "Let's see, that {{pokeName}} will do nicely!$Remember, I'm not responsible\nif anything bad happens!@d{32} Hehe...",
"selected_message": "The man hands you 5 Rogue Balls.\n ${{pokeName}} hops into the strange machine...\n $Flashing lights and weird noises\nstart coming from the machine!\n $...@d{96} Something emerges\nfrom the device, raging wildly!" "selected_message": "The man hands you 5 Rogue Balls.${{pokeName}} hops into the strange machine...$Flashing lights and weird noises\nstart coming from the machine!$...@d{96} Something emerges\nfrom the device, raging wildly!"
}, },
"2": { "2": {
"label": "Refuse", "label": "Refuse",

View File

@ -10,20 +10,20 @@
"1": { "1": {
"label": "Give Money", "label": "Give Money",
"tooltip": "(-) Give the Delibirds {{money, money}}\n(+) Receive a Gift Item", "tooltip": "(-) Give the Delibirds {{money, money}}\n(+) Receive a Gift Item",
"selected": "You toss the money to the Delibirds,\nwho chatter amongst themselves excitedly.\n $They turn back to you and happily give you a present!" "selected": "You toss the money to the Delibirds,\nwho chatter amongst themselves excitedly.$They turn back to you and happily give you a present!"
}, },
"2": { "2": {
"label": "Give Food", "label": "Give Food",
"tooltip": "(-) Give the Delibirds a Berry or Reviver Seed\n(+) Receive a Gift Item", "tooltip": "(-) Give the Delibirds a Berry or Reviver Seed\n(+) Receive a Gift Item",
"select_prompt": "Select an item to give.", "select_prompt": "Select an item to give.",
"selected": "You toss the {{chosenItem}} to the Delibirds,\nwho chatter amongst themselves excitedly.\n $They turn back to you and happily give you a present!" "selected": "You toss the {{chosenItem}} to the Delibirds,\nwho chatter amongst themselves excitedly.$They turn back to you and happily give you a present!"
}, },
"3": { "3": {
"label": "Give an Item", "label": "Give an Item",
"tooltip": "(-) Give the Delibirds a Held Item\n(+) Receive a Gift Item", "tooltip": "(-) Give the Delibirds a Held Item\n(+) Receive a Gift Item",
"select_prompt": "Select an item to give.", "select_prompt": "Select an item to give.",
"selected": "You toss the {{chosenItem}} to the Delibirds,\nwho chatter amongst themselves excitedly.\n $They turn back to you and happily give you a present!" "selected": "You toss the {{chosenItem}} to the Delibirds,\nwho chatter amongst themselves excitedly.$They turn back to you and happily give you a present!"
} }
}, },
"outro": "The Delibird pack happily waddles off into the distance.\n $What a curious little exchange!" "outro": "The Delibird pack happily waddles off into the distance.$What a curious little exchange!"
} }

View File

@ -1,7 +1,7 @@
{ {
"intro": "It's a lady with a ton of shopping bags.", "intro": "It's a lady with a ton of shopping bags.",
"speaker": "Shopper", "speaker": "Shopper",
"intro_dialogue": "Hello! Are you here for\nthe amazing sales too?\n $There's a special coupon that you can\nredeem for a free item during the sale!\n $I have an extra one. Here you go!", "intro_dialogue": "Hello! Are you here for\nthe amazing sales too?$There's a special coupon that you can\nredeem for a free item during the sale!$I have an extra one. Here you go!",
"title": "Department Store Sale", "title": "Department Store Sale",
"description": "There is merchandise in every direction! It looks like there are 4 counters where you can redeem the coupon for various items. The possibilities are endless!", "description": "There is merchandise in every direction! It looks like there are 4 counters where you can redeem the coupon for various items. The possibilities are endless!",
"query": "Which counter will you go to?", "query": "Which counter will you go to?",

View File

@ -1,7 +1,7 @@
{ {
"intro": "It's a teacher and some school children!", "intro": "It's a teacher and some school children!",
"speaker": "Teacher", "speaker": "Teacher",
"intro_dialogue": "Hello, there! Would you be able to\nspare a minute for my students?\n $I'm teaching them about Pokémon moves\nand would love to show them a demonstration.\n $Would you mind showing us one of\nthe moves your Pokémon can use?", "intro_dialogue": "Hello, there! Would you be able to\nspare a minute for my students?$I'm teaching them about Pokémon moves\nand would love to show them a demonstration.$Would you mind showing us one of\nthe moves your Pokémon can use?",
"title": "Field Trip", "title": "Field Trip",
"description": "A teacher is requesting a move demonstration from a Pokémon. Depending on the move you choose, she might have something useful for you in exchange.", "description": "A teacher is requesting a move demonstration from a Pokémon. Depending on the move you choose, she might have something useful for you in exchange.",
"query": "Which move category will you show off?", "query": "Which move category will you show off?",
@ -19,8 +19,8 @@
"tooltip": "(+) Status Item Rewards" "tooltip": "(+) Status Item Rewards"
}, },
"selected": "{{pokeName}} shows off an awesome display of {{move}}!", "selected": "{{pokeName}} shows off an awesome display of {{move}}!",
"incorrect": "...\n $That isn't a {{moveCategory}} move!\n $I'm sorry, but I can't give you anything.", "incorrect": "...$That isn't a {{moveCategory}} move!$I'm sorry, but I can't give you anything.",
"lesson_learned": "Looks like you learned a valuable lesson?\n $Your Pokémon also gained some knowledge." "lesson_learned": "Looks like you learned a valuable lesson?$Your Pokémon also gained some knowledge."
}, },
"second_option_prompt": "Choose a move for your Pokémon to use.", "second_option_prompt": "Choose a move for your Pokémon to use.",
"outro_good": "Thank you so much for your kindness!\nI hope the items I had were helpful!", "outro_good": "Thank you so much for your kindness!\nI hope the items I had were helpful!",

View File

@ -7,20 +7,20 @@
"1": { "1": {
"label": "Find the Source", "label": "Find the Source",
"tooltip": "(?) Discover the source\n(-) Hard Battle", "tooltip": "(?) Discover the source\n(-) Hard Battle",
"selected": "You push through the storm, and find two Volcarona in the middle of a mating dance!\n $They don't take kindly to the interruption and attack!" "selected": "You push through the storm, and find two Volcarona in the middle of a mating dance!$They don't take kindly to the interruption and attack!"
}, },
"2": { "2": {
"label": "Hunker Down", "label": "Hunker Down",
"tooltip": "(-) Suffer the effects of the weather", "tooltip": "(-) Suffer the effects of the weather",
"selected": "The weather effects cause significant\nharm as you struggle to find shelter!\n $Your party takes 20% Max HP damage!", "selected": "The weather effects cause significant\nharm as you struggle to find shelter!$Your party takes 20% Max HP damage!",
"target_burned": "Your {{burnedPokemon}} also became burned!" "target_burned": "Your {{burnedPokemon}} also became burned!"
}, },
"3": { "3": {
"label": "Your Fire Types Help", "label": "Your Fire Types Help",
"tooltip": "(+) End the conditions\n(+) Gain a Charcoal", "tooltip": "(+) End the conditions\n(+) Gain a Charcoal",
"disabled_tooltip": "You need at least 2 Fire Type Pokémon to choose this", "disabled_tooltip": "You need at least 2 Fire Type Pokémon to choose this",
"selected": "Your {{option3PrimaryName}} and {{option3SecondaryName}} guide you to where two Volcarona are in the middle of a mating dance!\n $Thankfully, your Pokémon are able to calm them,\nand they depart without issue." "selected": "Your {{option3PrimaryName}} and {{option3SecondaryName}} guide you to where two Volcarona are in the middle of a mating dance!$Thankfully, your Pokémon are able to calm them,\nand they depart without issue."
} }
}, },
"found_charcoal": "After the weather clears,\nyour {{leadPokemon}} spots something on the ground.\n $@s{item_fanfare}{{leadPokemon}} gained a Charcoal!" "found_charcoal": "After the weather clears,\nyour {{leadPokemon}} spots something on the ground.$@s{item_fanfare}{{leadPokemon}} gained a Charcoal!"
} }

View File

@ -13,7 +13,7 @@
"label": "Steal the Item", "label": "Steal the Item",
"disabled_tooltip": "Your Pokémon need to know certain moves to choose this", "disabled_tooltip": "Your Pokémon need to know certain moves to choose this",
"tooltip": "(+) {{option2PrimaryName}} uses {{option2PrimaryMove}}", "tooltip": "(+) {{option2PrimaryName}} uses {{option2PrimaryMove}}",
"selected": ".@d{32}.@d{32}.@d{32}\n $Your {{option2PrimaryName}} helps you out and uses {{option2PrimaryMove}}!\n $You nabbed the item!" "selected": ".@d{32}.@d{32}.@d{32}$Your {{option2PrimaryName}} helps you out and uses {{option2PrimaryMove}}!$You nabbed the item!"
}, },
"3": { "3": {
"label": "Leave", "label": "Leave",

View File

@ -9,19 +9,19 @@
"label_disabled": "Can't {{option1RequiredMove}}", "label_disabled": "Can't {{option1RequiredMove}}",
"tooltip": "(+) {{option1PrimaryName}} saves you\n(+) {{option1PrimaryName}} gains some EXP", "tooltip": "(+) {{option1PrimaryName}} saves you\n(+) {{option1PrimaryName}} gains some EXP",
"tooltip_disabled": "You have no Pokémon to {{option1RequiredMove}} on", "tooltip_disabled": "You have no Pokémon to {{option1RequiredMove}} on",
"selected": "{{option1PrimaryName}} swims ahead, guiding you back on track.\n ${{option1PrimaryName}} seems to also have gotten stronger in this time of need!" "selected": "{{option1PrimaryName}} swims ahead, guiding you back on track.${{option1PrimaryName}} seems to also have gotten stronger in this time of need!"
}, },
"2": { "2": {
"label": "{{option2PrimaryName}} Might Help", "label": "{{option2PrimaryName}} Might Help",
"label_disabled": "Can't {{option2RequiredMove}}", "label_disabled": "Can't {{option2RequiredMove}}",
"tooltip": "(+) {{option2PrimaryName}} saves you\n(+) {{option2PrimaryName}} gains some EXP", "tooltip": "(+) {{option2PrimaryName}} saves you\n(+) {{option2PrimaryName}} gains some EXP",
"tooltip_disabled": "You have no Pokémon to {{option2RequiredMove}} with", "tooltip_disabled": "You have no Pokémon to {{option2RequiredMove}} with",
"selected": "{{option2PrimaryName}} flies ahead of your boat, guiding you back on track.\n ${{option2PrimaryName}} seems to also have gotten stronger in this time of need!" "selected": "{{option2PrimaryName}} flies ahead of your boat, guiding you back on track.${{option2PrimaryName}} seems to also have gotten stronger in this time of need!"
}, },
"3": { "3": {
"label": "Wander Aimlessly", "label": "Wander Aimlessly",
"tooltip": "(-) Each of your Pokémon lose {{damagePercentage}}% of their total HP", "tooltip": "(-) Each of your Pokémon lose {{damagePercentage}}% of their total HP",
"selected": "You float about in the boat, steering without direction until you finally spot a landmark you remember.\n $You and your Pokémon are fatigued from the whole ordeal." "selected": "You float about in the boat, steering without direction until you finally spot a landmark you remember.$You and your Pokémon are fatigued from the whole ordeal."
} }
}, },
"outro": "You are back on track." "outro": "You are back on track."

View File

@ -12,7 +12,7 @@
"good": "Some pretty nice tools and items.", "good": "Some pretty nice tools and items.",
"great": "A couple great tools and items!", "great": "A couple great tools and items!",
"amazing": "Whoa! An amazing item!", "amazing": "Whoa! An amazing item!",
"bad": "Oh no!@d{32}\nThe chest was trapped!\n $Your {{pokeName}} jumps in front of you\nbut is KOed in the process." "bad": "Oh no!@d{32}\nThe chest was trapped!$Your {{pokeName}} jumps in front of you\nbut is KOed in the process."
}, },
"2": { "2": {
"label": "Too Risky, Leave", "label": "Too Risky, Leave",

View File

@ -1,7 +1,7 @@
{ {
"intro": "A busy worker flags you down.", "intro": "A busy worker flags you down.",
"speaker": "Worker", "speaker": "Worker",
"intro_dialogue": "You look like someone with lots of capable Pokémon!\n $We can pay you if you're able to help us with some part-time work!", "intro_dialogue": "You look like someone with lots of capable Pokémon!$We can pay you if you're able to help us with some part-time work!",
"title": "Part-Timer", "title": "Part-Timer",
"description": "Looks like there are plenty of tasks that need to be done. Depending how well-suited your Pokémon is to a task, they might earn more or less money.", "description": "Looks like there are plenty of tasks that need to be done. Depending how well-suited your Pokémon is to a task, they might earn more or less money.",
"query": "Which job will you choose?", "query": "Which job will you choose?",
@ -24,8 +24,8 @@
"selected": "Your {{option3PrimaryName}} spends the day using {{option3PrimaryMove}} to attract customers to the business!" "selected": "Your {{option3PrimaryName}} spends the day using {{option3PrimaryMove}} to attract customers to the business!"
} }
}, },
"job_complete_good": "Thanks for the assistance!\nYour {{selectedPokemon}} was incredibly helpful!\n $Here's your check for the day.", "job_complete_good": "Thanks for the assistance!\nYour {{selectedPokemon}} was incredibly helpful!$Here's your check for the day.",
"job_complete_bad": "Your {{selectedPokemon}} helped us out a bit!\n $Here's your check for the day.", "job_complete_bad": "Your {{selectedPokemon}} helped us out a bit!$Here's your check for the day.",
"pokemon_tired": "Your {{selectedPokemon}} is worn out!\nThe PP of all its moves was reduced to 2!", "pokemon_tired": "Your {{selectedPokemon}} is worn out!\nThe PP of all its moves was reduced to 2!",
"outro": "Come back and help out again sometime!" "outro": "Come back and help out again sometime!"
} }

View File

@ -1,7 +1,7 @@
{ {
"intro": "A man in a dark coat approaches you.", "intro": "A man in a dark coat approaches you.",
"speaker": "Shady Salesman", "speaker": "Shady Salesman",
"intro_dialogue": ".@d{16}.@d{16}.@d{16}\n $I've got the goods if you've got the money.\n $Make sure your Pokémon can handle it though.", "intro_dialogue": ".@d{16}.@d{16}.@d{16}$I've got the goods if you've got the money.$Make sure your Pokémon can handle it though.",
"title": "The Vitamin Dealer", "title": "The Vitamin Dealer",
"description": "The man opens his jacket to reveal some Pokémon vitamins. The numbers he quotes seem like a really good deal. Almost too good...\nHe offers two package deals to choose from.", "description": "The man opens his jacket to reveal some Pokémon vitamins. The numbers he quotes seem like a really good deal. Almost too good...\nHe offers two package deals to choose from.",
"query": "Which deal will choose?", "query": "Which deal will choose?",
@ -20,10 +20,10 @@
"tooltip": "(-) No Rewards", "tooltip": "(-) No Rewards",
"selected": "Heh, wouldn't have figured you for a coward." "selected": "Heh, wouldn't have figured you for a coward."
}, },
"selected": "The man hands you two bottles and quickly disappears.\n ${{selectedPokemon}} gained {{boost1}} and {{boost2}} boosts!" "selected": "The man hands you two bottles and quickly disappears.${{selectedPokemon}} gained {{boost1}} and {{boost2}} boosts!"
}, },
"damage_only": "But the medicine had some side effects!\n $Your {{selectedPokemon}} takes some damage...", "damage_only": "But the medicine had some side effects!$Your {{selectedPokemon}} takes some damage...",
"bad_poison": "But the medicine had some side effects!\n $Your {{selectedPokemon}} takes some damage\nand becomes badly poisoned...", "bad_poison": "But the medicine had some side effects!$Your {{selectedPokemon}} takes some damage\nand becomes badly poisoned...",
"poison": "But the medicine had some side effects!\n $Your {{selectedPokemon}} becomes poisoned...", "poison": "But the medicine had some side effects!$Your {{selectedPokemon}} becomes poisoned...",
"no_bad_effects": "Looks like there were no side-effects this time." "no_bad_effects": "Looks like there were no side-effects this time."
} }

View File

@ -1,5 +1,5 @@
{ {
"intro": "As you walk down a narrow pathway, you see a towering silhouette blocking your path.\n $You get closer to see a Snorlax sleeping peacefully.\nIt seems like there's no way around it.", "intro": "As you walk down a narrow pathway, you see a towering silhouette blocking your path.$You get closer to see a Snorlax sleeping peacefully.\nIt seems like there's no way around it.",
"title": "Slumbering Snorlax", "title": "Slumbering Snorlax",
"description": "You could attack it to try and get it to move, or simply wait for it to wake up. Who knows how long that could take, though...", "description": "You could attack it to try and get it to move, or simply wait for it to wake up. Who knows how long that could take, though...",
"query": "What will you do?", "query": "What will you do?",
@ -12,14 +12,14 @@
"2": { "2": {
"label": "Wait for It to Move", "label": "Wait for It to Move",
"tooltip": "(-) Wait a Long Time\n(+) Recover Party", "tooltip": "(-) Wait a Long Time\n(+) Recover Party",
"selected": ".@d{32}.@d{32}.@d{32}\n $You wait for a time, but the Snorlax's yawns make your party sleepy...", "selected": ".@d{32}.@d{32}.@d{32}$You wait for a time, but the Snorlax's yawns make your party sleepy...",
"rest_result": "When you all awaken, the Snorlax is no where to be found -\nbut your Pokémon are all healed!" "rest_result": "When you all awaken, the Snorlax is no where to be found -\nbut your Pokémon are all healed!"
}, },
"3": { "3": {
"label": "Steal Its Item", "label": "Steal Its Item",
"tooltip": "(+) {{option3PrimaryName}} uses {{option3PrimaryMove}}\n(+) Special Reward", "tooltip": "(+) {{option3PrimaryName}} uses {{option3PrimaryMove}}\n(+) Special Reward",
"disabled_tooltip": "Your Pokémon need to know certain moves to choose this", "disabled_tooltip": "Your Pokémon need to know certain moves to choose this",
"selected": "Your {{option3PrimaryName}} uses {{option3PrimaryMove}}!\n $@s{item_fanfare}It steals Leftovers off the sleeping\nSnorlax and you make out like bandits!" "selected": "Your {{option3PrimaryName}} uses {{option3PrimaryMove}}!$@s{item_fanfare}It steals Leftovers off the sleeping\nSnorlax and you make out like bandits!"
} }
} }
} }

View File

@ -13,15 +13,15 @@
"label": "A Pokémon Helps", "label": "A Pokémon Helps",
"tooltip": "(-) {{option2PrimaryName}} Helps\n(+) {{option2PrimaryName}} gains EXP\n(?) Teleport to New Biome", "tooltip": "(-) {{option2PrimaryName}} Helps\n(+) {{option2PrimaryName}} gains EXP\n(?) Teleport to New Biome",
"disabled_tooltip": "You need a Steel or Electric Type Pokémon to choose this", "disabled_tooltip": "You need a Steel or Electric Type Pokémon to choose this",
"selected": "{{option2PrimaryName}}'s Type allows it to bypass the machine's paywall!\n $The capsule opens, and you step inside..." "selected": "{{option2PrimaryName}}'s Type allows it to bypass the machine's paywall!$The capsule opens, and you step inside..."
}, },
"3": { "3": {
"label": "Inspect the Machine", "label": "Inspect the Machine",
"tooltip": "(-) Pokémon Battle", "tooltip": "(-) Pokémon Battle",
"selected": "You are drawn in by the blinking lights\nand strange noises coming from the machine...\n $You don't even notice as a wild\nPokémon sneaks up and ambushes you!" "selected": "You are drawn in by the blinking lights\nand strange noises coming from the machine...$You don't even notice as a wild\nPokémon sneaks up and ambushes you!"
} }
}, },
"transport": "The machine shakes violently,\nmaking all sorts of strange noises!\n $Just as soon as it had started, it quiets once more.", "transport": "The machine shakes violently,\nmaking all sorts of strange noises!$Just as soon as it had started, it quiets once more.",
"attacked": "You step out into a completely new area, startling a wild Pokémon!\n $The wild Pokémon attacks!", "attacked": "You step out into a completely new area, startling a wild Pokémon!$The wild Pokémon attacks!",
"boss_enraged": "The opposing {{enemyPokemon}} has become enraged!" "boss_enraged": "The opposing {{enemyPokemon}} has become enraged!"
} }

View File

@ -12,12 +12,12 @@
"tooltip": "(-) Pay {{price, money}}\n(+) Gain a {{purchasePokemon}} with its Hidden Ability", "tooltip": "(-) Pay {{price, money}}\n(+) Gain a {{purchasePokemon}} with its Hidden Ability",
"tooltip_shiny": "(-) Pay {{price, money}}\n(+) Gain a shiny {{purchasePokemon}}", "tooltip_shiny": "(-) Pay {{price, money}}\n(+) Gain a shiny {{purchasePokemon}}",
"selected_message": "You paid an outrageous sum and bought the {{purchasePokemon}}.", "selected_message": "You paid an outrageous sum and bought the {{purchasePokemon}}.",
"selected_dialogue": "Excellent choice!\n $I can see you've a keen eye for business.\n $Oh, yeah...@d{64} Returns not accepted, got that?" "selected_dialogue": "Excellent choice!$I can see you've a keen eye for business.$Oh, yeah...@d{64} Returns not accepted, got that?"
}, },
"2": { "2": {
"label": "Refuse", "label": "Refuse",
"tooltip": "(-) No Rewards", "tooltip": "(-) No Rewards",
"selected": "No?@d{32} You say no?\n $I'm only doing this as a favor to you!" "selected": "No?@d{32} You say no?$I'm only doing this as a favor to you!"
} }
} }
} }

View File

@ -8,7 +8,7 @@
"label": "Let It Touch You", "label": "Let It Touch You",
"tooltip": "(?) Something awful or amazing might happen", "tooltip": "(?) Something awful or amazing might happen",
"selected": "You black out.", "selected": "You black out.",
"selected_2": "@f{150}When you awaken, the Shuckle is gone\nand juice stash completely drained.\n $Your {{highBstPokemon}} feels a\nterrible lethargy come over it!\n $Its base stats were reduced by 20 in each stat!\n $Your remaining Pokémon feel an incredible vigor, though!\n $Their base stats are increased by 10 in each stat!" "selected_2": "@f{150}When you awaken, the Shuckle is gone\nand juice stash completely drained.$Your {{highBstPokemon}} feels a\nterrible lethargy come over it!$Its base stats were reduced by 20 in each stat!$Your remaining Pokémon feel an incredible vigor, though!$Their base stats are increased by 10 in each stat!"
}, },
"2": { "2": {
"label": "Battle the Shuckle", "label": "Battle the Shuckle",

View File

@ -1,7 +1,7 @@
{ {
"intro": "It's a family standing outside their house!", "intro": "It's a family standing outside their house!",
"speaker": "The Winstrates", "speaker": "The Winstrates",
"intro_dialogue": "We're the Winstrates!\n $What do you say to taking on our family in a series of Pokémon battles?", "intro_dialogue": "We're the Winstrates!$What do you say to taking on our family in a series of Pokémon battles?",
"title": "The Winstrate Challenge", "title": "The Winstrate Challenge",
"description": "The Winstrates are a family of 5 trainers, and they want to battle! If you beat all of them back-to-back, they'll give you a grand prize. But can you handle the heat?", "description": "The Winstrates are a family of 5 trainers, and they want to battle! If you beat all of them back-to-back, they'll give you a grand prize. But can you handle the heat?",
"query": "What will you do?", "query": "What will you do?",
@ -17,5 +17,5 @@
"selected": "That's too bad. Say, your team looks worn out, why don't you stay awhile and rest?" "selected": "That's too bad. Say, your team looks worn out, why don't you stay awhile and rest?"
} }
}, },
"victory": "Congratulations on beating our challenge!\n $Our family uses this Macho Brace to strengthen our Pokémon more effectively during their training.\n $You may not need it, considering that you beat the whole lot of us, but we hope you'll accept it anyway!" "victory": "Congratulations on beating our challenge!$Our family uses this Macho Brace to strengthen our Pokémon more effectively during their training.$You may not need it, considering that you beat the whole lot of us, but we hope you'll accept it anyway!"
} }

View File

@ -8,19 +8,19 @@
"1": { "1": {
"label": "Light Training", "label": "Light Training",
"tooltip": "(-) Light Battle\n(+) Improve 2 Random IVs of Pokémon", "tooltip": "(-) Light Battle\n(+) Improve 2 Random IVs of Pokémon",
"finished": "{{selectedPokemon}} returns, feeling\nworn out but accomplished!\n $Its {{stat1}} and {{stat2}} IVs were improved!" "finished": "{{selectedPokemon}} returns, feeling\nworn out but accomplished!$Its {{stat1}} and {{stat2}} IVs were improved!"
}, },
"2": { "2": {
"label": "Moderate Training", "label": "Moderate Training",
"tooltip": "(-) Moderate Battle\n(+) Change Pokémon's Nature", "tooltip": "(-) Moderate Battle\n(+) Change Pokémon's Nature",
"select_prompt": "Select a new nature\nto train your Pokémon in.", "select_prompt": "Select a new nature\nto train your Pokémon in.",
"finished": "{{selectedPokemon}} returns, feeling\nworn out but accomplished!\n $Its nature was changed to {{nature}}!" "finished": "{{selectedPokemon}} returns, feeling\nworn out but accomplished!$Its nature was changed to {{nature}}!"
}, },
"3": { "3": {
"label": "Heavy Training", "label": "Heavy Training",
"tooltip": "(-) Harsh Battle\n(+) Change Pokémon's Ability", "tooltip": "(-) Harsh Battle\n(+) Change Pokémon's Ability",
"select_prompt": "Select a new ability\nto train your Pokémon in.", "select_prompt": "Select a new ability\nto train your Pokémon in.",
"finished": "{{selectedPokemon}} returns, feeling\nworn out but accomplished!\n $Its ability was changed to {{ability}}!" "finished": "{{selectedPokemon}} returns, feeling\nworn out but accomplished!$Its ability was changed to {{ability}}!"
}, },
"selected": "{{selectedPokemon}} moves across\nthe clearing to face you..." "selected": "{{selectedPokemon}} moves across\nthe clearing to face you..."
}, },

View File

@ -7,7 +7,7 @@
"1": { "1": {
"label": "Dig for Valuables", "label": "Dig for Valuables",
"tooltip": "(-) Lose Healing Items in Shops\n(+) Gain Amazing Items", "tooltip": "(-) Lose Healing Items in Shops\n(+) Gain Amazing Items",
"selected": "You wade through the garbage pile, becoming mired in filth.\n $There's no way any respectable shopkeepers\nwill sell you anything in your grimy state!\n $You'll just have to make do without shop healing items.\n $However, you found some incredible items in the garbage!" "selected": "You wade through the garbage pile, becoming mired in filth.$There's no way any respectable shopkeepers\nwill sell you anything in your grimy state!$You'll just have to make do without shop healing items.$However, you found some incredible items in the garbage!"
}, },
"2": { "2": {
"label": "Investigate Further", "label": "Investigate Further",

View File

@ -1,7 +1,7 @@
{ {
"intro": "A shadowy woman blocks your path.\nSomething about her is unsettling...", "intro": "A shadowy woman blocks your path.\nSomething about her is unsettling...",
"speaker": "Woman", "speaker": "Woman",
"intro_dialogue": "I have seen your futures, your pasts...\n $Child, do you see them too?", "intro_dialogue": "I have seen your futures, your pasts...$Child, do you see them too?",
"title": "???", "title": "???",
"description": "The woman's words echo in your head. It wasn't just a singular voice, but a vast multitude, from all timelines and realities. You begin to feel dizzy, the question lingering on your mind...\n\n@[TOOLTIP_TITLE]{\"I have seen your futures, your pasts... Child, do you see them too?\"}", "description": "The woman's words echo in your head. It wasn't just a singular voice, but a vast multitude, from all timelines and realities. You begin to feel dizzy, the question lingering on your mind...\n\n@[TOOLTIP_TITLE]{\"I have seen your futures, your pasts... Child, do you see them too?\"}",
"query": "What will you do?", "query": "What will you do?",
@ -9,14 +9,14 @@
"1": { "1": {
"label": "\"I See Them\"", "label": "\"I See Them\"",
"tooltip": "@[SUMMARY_GREEN]{(?) Affects your Pokémon}", "tooltip": "@[SUMMARY_GREEN]{(?) Affects your Pokémon}",
"selected": "Her hand reaches out to touch you,\nand everything goes black.\n $Then...@d{64} You see everything.\nEvery timeline, all your different selves,\n past and future.\n $Everything that has made you,\neverything you will become...@d{64}", "selected": "Her hand reaches out to touch you,\nand everything goes black.$Then...@d{64} You see everything.\nEvery timeline, all your different selves,\n past and future.$Everything that has made you,\neverything you will become...@d{64}",
"cutscene": "You see your Pokémon,@d{32} converging from\nevery reality to become something new...@d{64}", "cutscene": "You see your Pokémon,@d{32} converging from\nevery reality to become something new...@d{64}",
"dream_complete": "When you awaken, the woman - was it a woman or a ghost? - is gone...\n $.@d{32}.@d{32}.@d{32}\n $Your Pokémon team has changed...\nOr is it the same team you've always had?" "dream_complete": "When you awaken, the woman - was it a woman or a ghost? - is gone...$.@d{32}.@d{32}.@d{32}$Your Pokémon team has changed...\nOr is it the same team you've always had?"
}, },
"2": { "2": {
"label": "Quickly Leave", "label": "Quickly Leave",
"tooltip": "(-) Affects your Pokémon", "tooltip": "(-) Affects your Pokémon",
"selected": "You tear your mind from a numbing grip, and hastily depart.\n $When you finally stop to collect yourself, you check the Pokémon in your team.\n $For some reason, all of their levels have decreased!" "selected": "You tear your mind from a numbing grip, and hastily depart.$When you finally stop to collect yourself, you check the Pokémon in your team.$For some reason, all of their levels have decreased!"
} }
} }
} }

View File

@ -117,15 +117,5 @@
"plasma_grunts": "Plasma Grunts", "plasma_grunts": "Plasma Grunts",
"flare_grunt": "Flare Grunt", "flare_grunt": "Flare Grunt",
"flare_grunt_female": "Flare Grunt", "flare_grunt_female": "Flare Grunt",
"flare_grunts": "Flare Grunts", "flare_grunts": "Flare Grunts"
"buck": "Buck",
"cheryl": "Cheryl",
"marley": "Marley",
"mira": "Mira",
"riley": "Riley",
"victor": "Victor",
"victoria": "Victoria",
"vivi": "Vivi",
"vicky": "Vicky",
"vito": "Vito"
} }

View File

@ -152,5 +152,16 @@
"alder_iris_double": "Alder & Iris", "alder_iris_double": "Alder & Iris",
"iris_alder_double": "Iris & Alder", "iris_alder_double": "Iris & Alder",
"marnie_piers_double": "Marnie & Piers", "marnie_piers_double": "Marnie & Piers",
"piers_marnie_double": "Piers & Marnie" "piers_marnie_double": "Piers & Marnie",
"buck": "Buck",
"cheryl": "Cheryl",
"marley": "Marley",
"mira": "Mira",
"riley": "Riley",
"victor": "Victor",
"victoria": "Victoria",
"vivi": "Vivi",
"vicky": "Vicky",
"vito": "Vito",
"bug_type_superfan": "Bug-Type Superfan"
} }

View File

@ -1536,8 +1536,9 @@ export const modifierTypes = {
} }
return new PokemonBaseStatFlatModifierType(Utils.randSeedInt(20), [Stat.HP, Stat.ATK, Stat.DEF]); return new PokemonBaseStatFlatModifierType(Utils.randSeedInt(20), [Stat.HP, Stat.ATK, Stat.DEF]);
}), }),
MYSTERY_ENCOUNTER_BLACK_SLUDGE: () => new ModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_BLACK_SLUDGE", "black_sludge", (type, _args) => new Modifiers.RemoveHealShopModifier(type)), MYSTERY_ENCOUNTER_BLACK_SLUDGE: () => new ModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_BLACK_SLUDGE", "black_sludge", (type, _args) => new Modifiers.HealShopCostModifier(type)),
MYSTERY_ENCOUNTER_MACHO_BRACE: () => new PokemonHeldItemModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_MACHO_BRACE", "macho_brace", (type, args) => new Modifiers.PokemonIncrementingStatModifier(type, (args[0] as Pokemon).id)), MYSTERY_ENCOUNTER_MACHO_BRACE: () => new PokemonHeldItemModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_MACHO_BRACE", "macho_brace", (type, args) => new Modifiers.PokemonIncrementingStatModifier(type, (args[0] as Pokemon).id)),
MYSTERY_ENCOUNTER_GOLDEN_BUG_NET: () => new ModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET", "golden_net", (type, _args) => new Modifiers.BoostBugSpawnModifier(type)),
}; };
interface ModifierPool { interface ModifierPool {

View File

@ -734,7 +734,8 @@ export class PokemonBaseStatTotalModifier extends PokemonHeldItemModifier {
apply(args: any[]): boolean { apply(args: any[]): boolean {
// Modifies the passed in baseStats[] array // Modifies the passed in baseStats[] array
args[1].forEach((v, i) => { args[1].forEach((v, i) => {
const newVal = Math.floor(v + this.statModifier); // HP is affected by half as much as other stats
const newVal = i === 0 ? Math.floor(v + this.statModifier / 2) : Math.floor(v + this.statModifier);
args[1][i] = Math.min(Math.max(newVal, 1), 999999); args[1][i] = Math.min(Math.max(newVal, 1), 999999);
}); });
@ -2366,17 +2367,41 @@ export class LockModifierTiersModifier extends PersistentModifier {
} }
} }
export class RemoveHealShopModifier extends PersistentModifier { export class HealShopCostModifier extends PersistentModifier {
constructor(type: ModifierType, stackCount?: integer) { constructor(type: ModifierType, stackCount?: integer) {
super(type, stackCount); super(type, stackCount);
} }
match(modifier: Modifier): boolean { match(modifier: Modifier): boolean {
return modifier instanceof RemoveHealShopModifier; return modifier instanceof HealShopCostModifier;
} }
clone(): RemoveHealShopModifier { clone(): HealShopCostModifier {
return new RemoveHealShopModifier(this.type, this.stackCount); return new HealShopCostModifier(this.type, this.stackCount);
}
apply(args: any[]): boolean {
(args[0] as Utils.IntegerHolder).value *= Math.pow(3, this.getStackCount());
return true;
}
getMaxStackCount(scene: BattleScene): integer {
return 1;
}
}
export class BoostBugSpawnModifier extends PersistentModifier {
constructor(type: ModifierType, stackCount?: integer) {
super(type, stackCount);
}
match(modifier: Modifier): boolean {
return modifier instanceof BoostBugSpawnModifier;
}
clone(): HealShopCostModifier {
return new BoostBugSpawnModifier(this.type, this.stackCount);
} }
apply(args: any[]): boolean { apply(args: any[]): boolean {

View File

@ -130,7 +130,8 @@ class DefaultOverrides {
// ------------------------- // -------------------------
// MYSTERY ENCOUNTER OVERRIDES // MYSTERY ENCOUNTER OVERRIDES
// ------------------------- // -------------------------
// 1 to 256, set to null to ignore
/** 1 to 256, set to null to ignore */
readonly MYSTERY_ENCOUNTER_RATE_OVERRIDE: number | null = null; readonly MYSTERY_ENCOUNTER_RATE_OVERRIDE: number | null = null;
readonly MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier | null = null; readonly MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier | null = null;
readonly MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType | null = null; readonly MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType | null = null;

View File

@ -31,6 +31,8 @@ import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
import { doTrainerExclamation } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { doTrainerExclamation } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
import { randSeedInt } from "#app/utils";
import { getGoldenBugNetSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
export class EncounterPhase extends BattlePhase { export class EncounterPhase extends BattlePhase {
private loaded: boolean; private loaded: boolean;
@ -89,7 +91,11 @@ export class EncounterPhase extends BattlePhase {
if (battle.battleType === BattleType.TRAINER) { if (battle.battleType === BattleType.TRAINER) {
battle.enemyParty[e] = battle.trainer?.genPartyMember(e)!; // TODO:: is the bang correct here? battle.enemyParty[e] = battle.trainer?.genPartyMember(e)!; // TODO:: is the bang correct here?
} else { } else {
const enemySpecies = this.scene.randomSpecies(battle.waveIndex, level, true); let enemySpecies = this.scene.randomSpecies(battle.waveIndex, level, true);
// If player has golden bug net, rolls 10% chance to replace with species from the golden bug net bug pool
if (randSeedInt(10) === 0) {
enemySpecies = getGoldenBugNetSpecies(this.scene, battle.waveIndex, level);
}
battle.enemyParty[e] = this.scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.NONE, !!this.scene.getEncounterBossSegments(battle.waveIndex, level, enemySpecies)); battle.enemyParty[e] = this.scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.NONE, !!this.scene.getEncounterBossSegments(battle.waveIndex, level, enemySpecies));
if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) { if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) {
battle.enemyParty[e].ivs = new Array(6).fill(31); battle.enemyParty[e].ivs = new Array(6).fill(31);

View File

@ -22,7 +22,7 @@ export class ModifierRewardPhase extends BattlePhase {
return new Promise<void>(resolve => { return new Promise<void>(resolve => {
const newModifier = this.modifierType.newModifier(); const newModifier = this.modifierType.newModifier();
this.scene.addModifier(newModifier).then(() => { this.scene.addModifier(newModifier).then(() => {
this.scene.playSound("item_fanfare"); this.scene.playSound("bgm/item_fanfare");
this.scene.ui.showText(i18next.t("battle:rewardGain", { modifierName: newModifier?.type.name }), null, () => resolve(), null, true); this.scene.ui.showText(i18next.t("battle:rewardGain", { modifierName: newModifier?.type.name }), null, () => resolve(), null, true);
}); });
}); });

View File

@ -418,23 +418,35 @@ export class MysteryEncounterRewardsPhase extends Phase {
}); });
} else { } else {
this.scene.executeWithSeedOffset(() => { this.scene.executeWithSeedOffset(() => {
if (this.scene.currentBattle.mysteryEncounter.doEncounterExp) { if (encounter.onRewards) {
this.scene.currentBattle.mysteryEncounter.doEncounterExp(this.scene); encounter.onRewards(this.scene).then(() => {
this.doEncounterRewardsAndContinue();
});
} else {
this.doEncounterRewardsAndContinue();
}
// Do not use ME's seedOffset for rewards, these should always be consistent with waveIndex (once per wave)
}, this.scene.currentBattle.waveIndex * 1000);
}
} }
if (this.scene.currentBattle.mysteryEncounter.doEncounterRewards) { doEncounterRewardsAndContinue() {
this.scene.currentBattle.mysteryEncounter.doEncounterRewards(this.scene); const encounter = this.scene.currentBattle.mysteryEncounter;
if (encounter.doEncounterExp) {
encounter.doEncounterExp(this.scene);
}
if (encounter.doEncounterRewards) {
encounter.doEncounterRewards(this.scene);
} else if (this.addHealPhase) { } else if (this.addHealPhase) {
this.scene.tryRemovePhase(p => p instanceof SelectModifierPhase); this.scene.tryRemovePhase(p => p instanceof SelectModifierPhase);
this.scene.unshiftPhase(new SelectModifierPhase(this.scene, 0, undefined, { 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);
this.scene.pushPhase(new PostMysteryEncounterPhase(this.scene)); this.scene.pushPhase(new PostMysteryEncounterPhase(this.scene));
this.end(); this.end();
} }
}
} }
/** /**

View File

@ -53,7 +53,7 @@ describe("Final Boss", () => {
expect(game.scene.getEnemyPokemon()!.species.speciesId).not.toBe(Species.ETERNATUS); expect(game.scene.getEnemyPokemon()!.species.speciesId).not.toBe(Species.ETERNATUS);
}); });
it("should not have passive enabled on Eternatus", async () => { it("should NOT have passive enabled on Eternatus", async () => {
await game.runToFinalBossEncounter(game, [Species.BIDOOF], GameModes.CLASSIC); await game.runToFinalBossEncounter(game, [Species.BIDOOF], GameModes.CLASSIC);
const eternatus = game.scene.getEnemyPokemon(); const eternatus = game.scene.getEnemyPokemon();

View File

@ -150,8 +150,9 @@ async function handleSecondaryOptionSelect(game: GameManager, pokemonNo: number,
/** /**
* For any MysteryEncounter that has a battle, can call this to skip battle and proceed to MysteryEncounterRewardsPhase * For any MysteryEncounter that has a battle, can call this to skip battle and proceed to MysteryEncounterRewardsPhase
* @param game * @param game
* @param runRewardsPhase
*/ */
export async function skipBattleRunMysteryEncounterRewardsPhase(game: GameManager) { export async function skipBattleRunMysteryEncounterRewardsPhase(game: GameManager, runRewardsPhase: boolean = true) {
game.scene.clearPhaseQueue(); game.scene.clearPhaseQueue();
game.scene.clearPhaseQueueSplice(); game.scene.clearPhaseQueueSplice();
game.scene.getEnemyParty().forEach(p => { game.scene.getEnemyParty().forEach(p => {
@ -161,5 +162,5 @@ export async function skipBattleRunMysteryEncounterRewardsPhase(game: GameManage
}); });
game.scene.pushPhase(new VictoryPhase(game.scene, 0)); game.scene.pushPhase(new VictoryPhase(game.scene, 0));
game.phaseInterceptor.superEndPhase(); game.phaseInterceptor.superEndPhase();
await game.phaseInterceptor.to(MysteryEncounterRewardsPhase, true); await game.phaseInterceptor.to(MysteryEncounterRewardsPhase, runRewardsPhase);
} }

View File

@ -6,7 +6,7 @@ import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";

View File

@ -4,7 +4,7 @@ import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";

View File

@ -6,7 +6,7 @@ import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounter-test-utils";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { AnOfferYouCantRefuseEncounter } from "#app/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter"; import { AnOfferYouCantRefuseEncounter } from "#app/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter";

View File

@ -4,7 +4,7 @@ import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
import { Species } from "#app/enums/species"; import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";

View File

@ -0,0 +1,585 @@
import * as MysteryEncounters from "#app/data/mystery-encounters/mystery-encounters";
import { Biome } from "#app/enums/biome";
import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
import { Moves } from "#enums/moves";
import BattleScene from "#app/battle-scene";
import { PokemonMove } from "#app/field/pokemon";
import { Mode } from "#app/ui/ui";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils";
import { TrainerType } from "#enums/trainer-type";
import { MysteryEncounterPhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phases";
import { ContactHeldItemTransferChanceModifier } from "#app/modifier/modifier";
import { CommandPhase } from "#app/phases/command-phase";
import { BugTypeSuperfanEncounter } from "#app/data/mystery-encounters/encounters/bug-type-superfan-encounter";
import * as encounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
const namespace = "mysteryEncounter:bugTypeSuperfan";
const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.WEEDLE];
const defaultBiome = Biome.CAVE;
const defaultWave = 24;
const POOL_1_POKEMON = [
Species.PARASECT,
Species.VENOMOTH,
Species.LEDIAN,
Species.ARIADOS,
Species.YANMA,
Species.BEAUTIFLY,
Species.DUSTOX,
Species.MASQUERAIN,
Species.NINJASK,
Species.VOLBEAT,
Species.ILLUMISE,
Species.ANORITH,
Species.KRICKETUNE,
Species.WORMADAM,
Species.MOTHIM,
Species.SKORUPI,
Species.JOLTIK,
Species.LARVESTA,
Species.VIVILLON,
Species.CHARJABUG,
Species.RIBOMBEE,
Species.SPIDOPS,
Species.LOKIX
];
const POOL_2_POKEMON = [
Species.SCYTHER,
Species.PINSIR,
Species.HERACROSS,
Species.FORRETRESS,
Species.SCIZOR,
Species.SHUCKLE,
Species.SHEDINJA,
Species.ARMALDO,
Species.VESPIQUEN,
Species.DRAPION,
Species.YANMEGA,
Species.LEAVANNY,
Species.SCOLIPEDE,
Species.CRUSTLE,
Species.ESCAVALIER,
Species.ACCELGOR,
Species.GALVANTULA,
Species.VIKAVOLT,
Species.ARAQUANID,
Species.ORBEETLE,
Species.CENTISKORCH,
Species.FROSMOTH,
Species.KLEAVOR,
];
const POOL_3_POKEMON: { species: Species, formIndex?: number }[] = [
{
species: Species.PINSIR,
formIndex: 1
},
{
species: Species.SCIZOR,
formIndex: 1
},
{
species: Species.HERACROSS,
formIndex: 1
},
{
species: Species.ORBEETLE,
formIndex: 1
},
{
species: Species.CENTISKORCH,
formIndex: 1
},
{
species: Species.DURANT,
},
{
species: Species.VOLCARONA,
},
{
species: Species.GOLISOPOD,
},
];
const POOL_4_POKEMON = [
Species.GENESECT,
Species.SLITHER_WING,
Species.BUZZWOLE,
Species.PHEROMOSA
];
const PHYSICAL_TUTOR_MOVES = [
Moves.MEGAHORN,
Moves.X_SCISSOR,
Moves.ATTACK_ORDER,
Moves.PIN_MISSILE,
Moves.FIRST_IMPRESSION
];
const SPECIAL_TUTOR_MOVES = [
Moves.SILVER_WIND,
Moves.BUG_BUZZ,
Moves.SIGNAL_BEAM,
Moves.POLLEN_PUFF
];
const STATUS_TUTOR_MOVES = [
Moves.STRING_SHOT,
Moves.STICKY_WEB,
Moves.SILK_TRAP,
Moves.RAGE_POWDER,
Moves.HEAL_ORDER
];
const MISC_TUTOR_MOVES = [
Moves.BUG_BITE,
Moves.LEECH_LIFE,
Moves.DEFEND_ORDER,
Moves.QUIVER_DANCE,
Moves.TAIL_GLOW,
Moves.INFESTATION,
Moves.U_TURN
];
describe("Bug-Type Superfan - Mystery Encounter", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
let scene: BattleScene;
beforeAll(() => {
phaserGame = new Phaser.Game({ type: Phaser.HEADLESS });
});
beforeEach(async () => {
game = new GameManager(phaserGame);
scene = game.scene;
game.override.mysteryEncounterChance(100);
game.override.startingWave(defaultWave);
game.override.startingBiome(defaultBiome);
game.override.disableTrainerWaves();
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
new Map<Biome, MysteryEncounterType[]>([
[Biome.CAVE, [MysteryEncounterType.BUG_TYPE_SUPERFAN]],
])
);
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
vi.clearAllMocks();
vi.resetAllMocks();
});
it("should have the correct properties", async () => {
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
expect(BugTypeSuperfanEncounter.encounterType).toBe(MysteryEncounterType.BUG_TYPE_SUPERFAN);
expect(BugTypeSuperfanEncounter.encounterTier).toBe(MysteryEncounterTier.GREAT);
expect(BugTypeSuperfanEncounter.dialogue).toBeDefined();
expect(BugTypeSuperfanEncounter.dialogue.intro).toStrictEqual([
{
text: `${namespace}.intro`,
},
{
speaker: `${namespace}.speaker`,
text: `${namespace}.intro_dialogue`,
},
]);
expect(BugTypeSuperfanEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}.title`);
expect(BugTypeSuperfanEncounter.dialogue.encounterOptionsDialogue?.description).toBe(`${namespace}.description`);
expect(BugTypeSuperfanEncounter.dialogue.encounterOptionsDialogue?.query).toBe(`${namespace}.query`);
expect(BugTypeSuperfanEncounter.options.length).toBe(3);
});
it("should not run below wave 10", async () => {
game.override.startingWave(9);
await game.runToMysteryEncounter();
expect(scene.currentBattle?.mysteryEncounter?.encounterType).not.toBe(MysteryEncounterType.BUG_TYPE_SUPERFAN);
});
it("should not run above wave 179", async () => {
game.override.startingWave(181);
await game.runToMysteryEncounter();
expect(scene.currentBattle.mysteryEncounter).toBeUndefined();
});
it("should initialize fully", async () => {
initSceneWithoutEncounterPhase(scene, defaultParty);
scene.currentBattle.mysteryEncounter = BugTypeSuperfanEncounter;
const { onInit } = BugTypeSuperfanEncounter;
expect(BugTypeSuperfanEncounter.onInit).toBeDefined();
BugTypeSuperfanEncounter.populateDialogueTokensFromRequirements(scene);
const onInitResult = onInit!(scene);
const config = BugTypeSuperfanEncounter.enemyPartyConfigs[0];
expect(config).toBeDefined();
expect(config.trainerConfig?.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN);
expect(config.trainerConfig?.partyTemplates).toBeDefined();
expect(config.female).toBe(true);
expect(onInitResult).toBe(true);
});
describe("Option 1 - Battle the Bug-Type Superfan", () => {
it("should have the correct properties", () => {
const option = BugTypeSuperfanEncounter.options[0];
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
expect(option.dialogue).toBeDefined();
expect(option.dialogue).toStrictEqual({
buttonLabel: `${namespace}.option.1.label`,
buttonTooltip: `${namespace}.option.1.tooltip`,
selected: [
{
speaker: `${namespace}.speaker`,
text: `${namespace}.option.1.selected`,
},
],
});
});
it("should start battle against the Bug-Type Superfan with wave 30 party template", async () => {
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await runMysteryEncounterToEnd(game, 1, undefined, true);
const enemyParty = scene.getEnemyParty();
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
expect(enemyParty.length).toBe(2);
expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN);
expect(enemyParty[0].species.speciesId).toBe(Species.BEEDRILL);
expect(enemyParty[1].species.speciesId).toBe(Species.BUTTERFREE);
});
it("should start battle against the Bug-Type Superfan with wave 50 party template", async () => {
game.override.startingWave(43);
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await runMysteryEncounterToEnd(game, 1, undefined, true);
const enemyParty = scene.getEnemyParty();
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
expect(enemyParty.length).toBe(3);
expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN);
expect(enemyParty[0].species.speciesId).toBe(Species.BEEDRILL);
expect(enemyParty[1].species.speciesId).toBe(Species.BUTTERFREE);
expect(POOL_1_POKEMON.includes(enemyParty[2].species.speciesId)).toBe(true);
});
it("should start battle against the Bug-Type Superfan with wave 70 party template", async () => {
game.override.startingWave(61);
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await runMysteryEncounterToEnd(game, 1, undefined, true);
const enemyParty = scene.getEnemyParty();
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
expect(enemyParty.length).toBe(4);
expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN);
expect(enemyParty[0].species.speciesId).toBe(Species.BEEDRILL);
expect(enemyParty[1].species.speciesId).toBe(Species.BUTTERFREE);
expect(POOL_1_POKEMON.includes(enemyParty[2].species.speciesId)).toBe(true);
expect(POOL_2_POKEMON.includes(enemyParty[3].species.speciesId)).toBe(true);
});
it("should start battle against the Bug-Type Superfan with wave 100 party template", async () => {
game.override.startingWave(81);
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await runMysteryEncounterToEnd(game, 1, undefined, true);
const enemyParty = scene.getEnemyParty();
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
expect(enemyParty.length).toBe(5);
expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN);
expect(enemyParty[0].species.speciesId).toBe(Species.BEEDRILL);
expect(enemyParty[1].species.speciesId).toBe(Species.BUTTERFREE);
expect(POOL_1_POKEMON.includes(enemyParty[2].species.speciesId)).toBe(true);
expect(POOL_2_POKEMON.includes(enemyParty[3].species.speciesId)).toBe(true);
expect(POOL_2_POKEMON.includes(enemyParty[4].species.speciesId)).toBe(true);
});
it("should start battle against the Bug-Type Superfan with wave 120 party template", async () => {
game.override.startingWave(111);
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await runMysteryEncounterToEnd(game, 1, undefined, true);
const enemyParty = scene.getEnemyParty();
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
expect(enemyParty.length).toBe(5);
expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN);
expect(enemyParty[0].species.speciesId).toBe(Species.BEEDRILL);
expect(enemyParty[0].formIndex).toBe(1);
expect(enemyParty[1].species.speciesId).toBe(Species.BUTTERFREE);
expect(enemyParty[1].formIndex).toBe(1);
expect(POOL_2_POKEMON.includes(enemyParty[2].species.speciesId)).toBe(true);
expect(POOL_2_POKEMON.includes(enemyParty[3].species.speciesId)).toBe(true);
expect(POOL_3_POKEMON.some(config => enemyParty[4].species.speciesId === config.species)).toBe(true);
});
it("should start battle against the Bug-Type Superfan with wave 140 party template", async () => {
game.override.startingWave(131);
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await runMysteryEncounterToEnd(game, 1, undefined, true);
const enemyParty = scene.getEnemyParty();
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
expect(enemyParty.length).toBe(5);
expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN);
expect(enemyParty[0].species.speciesId).toBe(Species.BEEDRILL);
expect(enemyParty[0].formIndex).toBe(1);
expect(enemyParty[1].species.speciesId).toBe(Species.BUTTERFREE);
expect(enemyParty[1].formIndex).toBe(1);
expect(POOL_2_POKEMON.includes(enemyParty[2].species.speciesId)).toBe(true);
expect(POOL_3_POKEMON.some(config => enemyParty[3].species.speciesId === config.species)).toBe(true);
expect(POOL_3_POKEMON.some(config => enemyParty[4].species.speciesId === config.species)).toBe(true);
});
it("should start battle against the Bug-Type Superfan with wave 160 party template", async () => {
game.override.startingWave(151);
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await runMysteryEncounterToEnd(game, 1, undefined, true);
const enemyParty = scene.getEnemyParty();
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
expect(enemyParty.length).toBe(5);
expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN);
expect(enemyParty[0].species.speciesId).toBe(Species.BEEDRILL);
expect(enemyParty[0].formIndex).toBe(1);
expect(enemyParty[1].species.speciesId).toBe(Species.BUTTERFREE);
expect(enemyParty[1].formIndex).toBe(1);
expect(POOL_2_POKEMON.includes(enemyParty[2].species.speciesId)).toBe(true);
expect(POOL_3_POKEMON.some(config => enemyParty[3].species.speciesId === config.species)).toBe(true);
expect(POOL_4_POKEMON.includes(enemyParty[4].species.speciesId)).toBe(true);
});
it("should start battle against the Bug-Type Superfan with wave 180 party template", async () => {
game.override.startingWave(171);
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await runMysteryEncounterToEnd(game, 1, undefined, true);
const enemyParty = scene.getEnemyParty();
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
expect(enemyParty.length).toBe(5);
expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN);
expect(enemyParty[0].species.speciesId).toBe(Species.BEEDRILL);
expect(enemyParty[0].formIndex).toBe(1);
expect(enemyParty[0].isBoss()).toBe(true);
expect(enemyParty[0].bossSegments).toBe(2);
expect(enemyParty[1].species.speciesId).toBe(Species.BUTTERFREE);
expect(enemyParty[1].formIndex).toBe(1);
expect(enemyParty[1].isBoss()).toBe(true);
expect(enemyParty[1].bossSegments).toBe(2);
expect(POOL_3_POKEMON.some(config => enemyParty[2].species.speciesId === config.species)).toBe(true);
expect(POOL_3_POKEMON.some(config => enemyParty[3].species.speciesId === config.species)).toBe(true);
expect(POOL_4_POKEMON.includes(enemyParty[4].species.speciesId)).toBe(true);
});
it("should let the player learn a Bug move after battle ends", async () => {
const selectOptionSpy = vi.spyOn(encounterPhaseUtils, "selectOptionThenPokemon");
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await runMysteryEncounterToEnd(game, 1, undefined, true);
await skipBattleRunMysteryEncounterRewardsPhase(game, false);
expect(scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterRewardsPhase.name);
game.phaseInterceptor["prompts"] = []; // Clear out prompt handlers
game.onNextPrompt("MysteryEncounterRewardsPhase", Mode.OPTION_SELECT, () => {
game.phaseInterceptor.superEndPhase();
});
await game.phaseInterceptor.run(MysteryEncounterRewardsPhase);
expect(selectOptionSpy).toHaveBeenCalledTimes(1);
const optionData = selectOptionSpy.mock.calls[0][1];
expect(PHYSICAL_TUTOR_MOVES.some(move => new PokemonMove(move).getName() === optionData[0].label)).toBe(true);
expect(SPECIAL_TUTOR_MOVES.some(move => new PokemonMove(move).getName() === optionData[1].label)).toBe(true);
expect(STATUS_TUTOR_MOVES.some(move => new PokemonMove(move).getName() === optionData[2].label)).toBe(true);
expect(MISC_TUTOR_MOVES.some(move => new PokemonMove(move).getName() === optionData[3].label)).toBe(true);
});
});
describe("Option 2 - Show off Bug Types", () => {
it("should have the correct properties", () => {
const option = BugTypeSuperfanEncounter.options[1];
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT);
expect(option.dialogue).toBeDefined();
expect(option.dialogue).toStrictEqual({
buttonLabel: `${namespace}.option.2.label`,
buttonTooltip: `${namespace}.option.2.tooltip`,
disabledButtonTooltip: `${namespace}.option.2.disabled_tooltip`
});
});
it("should NOT be selectable if the player doesn't have any Bug types", async () => {
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.ABRA]);
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
const encounterPhase = scene.getCurrentPhase();
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
const mysteryEncounterPhase = encounterPhase as MysteryEncounterPhase;
vi.spyOn(mysteryEncounterPhase, "continueEncounter");
vi.spyOn(mysteryEncounterPhase, "handleOptionSelect");
vi.spyOn(scene.ui, "playError");
await runSelectMysteryEncounterOption(game, 2);
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();
});
it("should proceed to rewards screen with 0-1 Bug Types reward options", async () => {
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await runMysteryEncounterToEnd(game, 2);
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
await game.phaseInterceptor.run(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(2);
expect(modifierSelectHandler.options[0].modifierTypeOption.type.id).toBe("SUPER_LURE");
expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toBe("GREAT_BALL");
});
it("should proceed to rewards screen with 2-3 Bug Types reward options", async () => {
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.BUTTERFREE, Species.BEEDRILL]);
await runMysteryEncounterToEnd(game, 2);
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
await game.phaseInterceptor.run(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).toBe("QUICK_CLAW");
expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toBe("MAX_LURE");
expect(modifierSelectHandler.options[2].modifierTypeOption.type.id).toBe("ULTRA_BALL");
});
it("should proceed to rewards screen with 4-5 Bug Types reward options", async () => {
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.BUTTERFREE, Species.BEEDRILL, Species.GALVANTULA, Species.VOLCARONA]);
await runMysteryEncounterToEnd(game, 2);
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
await game.phaseInterceptor.run(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).toBe("GRIP_CLAW");
expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toBe("MAX_LURE");
expect(modifierSelectHandler.options[2].modifierTypeOption.type.id).toBe("ROGUE_BALL");
});
it("should proceed to rewards screen with 6 Bug Types reward options (including form change item)", async () => {
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.BUTTERFREE, Species.BEEDRILL, Species.GALVANTULA, Species.VOLCARONA, Species.ANORITH, Species.GENESECT]);
await runMysteryEncounterToEnd(game, 2);
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
await game.phaseInterceptor.run(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).toBe("MASTER_BALL");
expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toBe("MAX_LURE");
expect(modifierSelectHandler.options[2].modifierTypeOption.type.id).toBe("FORM_CHANGE_ITEM");
});
it("should leave encounter without battle", async () => {
const leaveEncounterWithoutBattleSpy = vi.spyOn(encounterPhaseUtils, "leaveEncounterWithoutBattle");
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await runMysteryEncounterToEnd(game, 2);
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
});
});
describe("Option 3 - Give a Bug Item", () => {
it("should have the correct properties", () => {
const option = BugTypeSuperfanEncounter.options[2];
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT);
expect(option.dialogue).toBeDefined();
expect(option.dialogue).toStrictEqual({
buttonLabel: `${namespace}.option.3.label`,
buttonTooltip: `${namespace}.option.3.tooltip`,
disabledButtonTooltip: `${namespace}.option.3.disabled_tooltip`,
selected: [
{
text: `${namespace}.option.3.selected`,
},
{
speaker: `${namespace}.speaker`,
text: `${namespace}.option.3.selected_dialogue`,
},
],
secondOptionPrompt: `${namespace}.option.3.select_prompt`,
});
});
it("should NOT be selectable if the player doesn't have any Bug items", async () => {
game.scene.modifiers = [];
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty);
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
game.scene.modifiers = [];
const encounterPhase = scene.getCurrentPhase();
expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name);
const mysteryEncounterPhase = encounterPhase as MysteryEncounterPhase;
vi.spyOn(mysteryEncounterPhase, "continueEncounter");
vi.spyOn(mysteryEncounterPhase, "handleOptionSelect");
vi.spyOn(scene.ui, "playError");
await runSelectMysteryEncounterOption(game, 3);
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();
});
it("should remove the gifted item and proceed to rewards screen", async () => {
game.override.startingHeldItems([{name: "GRIP_CLAW", count: 1}]);
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.BUTTERFREE]);
const gripClawCountBefore = scene.findModifier(m => m instanceof ContactHeldItemTransferChanceModifier)?.stackCount ?? 0;
await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 });
expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name);
await game.phaseInterceptor.run(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(2);
expect(modifierSelectHandler.options[0].modifierTypeOption.type.id).toBe("MYSTERY_ENCOUNTER_GOLDEN_BUG_NET");
expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toBe("REVIVER_SEED");
const gripClawCountAfter = scene.findModifier(m => m instanceof ContactHeldItemTransferChanceModifier)?.stackCount ?? 0;
expect(gripClawCountBefore - 1).toBe(gripClawCountAfter);
});
it("should leave encounter without battle", async () => {
game.override.startingHeldItems([{name: "GRIP_CLAW", count: 1}]);
const leaveEncounterWithoutBattleSpy = vi.spyOn(encounterPhaseUtils, "leaveEncounterWithoutBattle");
await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.BUTTERFREE]);
await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 });
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
});
});
});

View File

@ -8,7 +8,7 @@ import { getPokemonSpecies } from "#app/data/pokemon-species";
import * as BattleAnims from "#app/data/battle-anims"; import * as BattleAnims from "#app/data/battle-anims";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { generateModifierType } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { generateModifierType } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import Pokemon, { PokemonMove } from "#app/field/pokemon"; import Pokemon, { PokemonMove } from "#app/field/pokemon";
@ -301,7 +301,7 @@ describe("Clowning Around - Mystery Encounter", () => {
expect(secondItemsAfter.length).toBe(1); expect(secondItemsAfter.length).toBe(1);
expect(secondItemsAfter[0].type.id).toBe("SOUL_DEW"); 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 () => { it("should leave encounter without battle", async () => {
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");

View File

@ -4,7 +4,7 @@ import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";

View File

@ -4,7 +4,7 @@ import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption } from "#test/mystery-encounter/encounter-test-utils";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
@ -137,7 +137,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// 5 Healing Charms // 5 Healing Charms
scene.modifiers = []; scene.modifiers = [];
const abilityCharm = generateModifierType(scene, modifierTypes.ABILITY_CHARM).newModifier() as HiddenAbilityRateBoosterModifier; const abilityCharm = generateModifierType(scene, modifierTypes.ABILITY_CHARM)!.newModifier() as HiddenAbilityRateBoosterModifier;
abilityCharm.stackCount = 4; abilityCharm.stackCount = 4;
await scene.addModifier(abilityCharm, true, false, false, true); await scene.addModifier(abilityCharm, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -206,7 +206,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 2 Sitrus berries on party lead // Set 2 Sitrus berries on party lead
scene.modifiers = []; scene.modifiers = [];
const sitrus = generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]); const sitrus = generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS])!;
const sitrusMod = sitrus.newModifier(scene.getParty()[0]) as BerryModifier; const sitrusMod = sitrus.newModifier(scene.getParty()[0]) as BerryModifier;
sitrusMod.stackCount = 2; sitrusMod.stackCount = 2;
await scene.addModifier(sitrusMod, true, false, false, true); await scene.addModifier(sitrusMod, true, false, false, true);
@ -227,7 +227,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Reviver Seed on party lead // Set 1 Reviver Seed on party lead
scene.modifiers = []; scene.modifiers = [];
const revSeed = generateModifierType(scene, modifierTypes.REVIVER_SEED); const revSeed = generateModifierType(scene, modifierTypes.REVIVER_SEED)!;
const modifier = revSeed.newModifier(scene.getParty()[0]) as PokemonInstantReviveModifier; const modifier = revSeed.newModifier(scene.getParty()[0]) as PokemonInstantReviveModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
await scene.addModifier(modifier, true, false, false, true); await scene.addModifier(modifier, true, false, false, true);
@ -248,10 +248,10 @@ describe("Delibird-y - Mystery Encounter", () => {
// 99 Candy Jars // 99 Candy Jars
scene.modifiers = []; scene.modifiers = [];
const candyJar = generateModifierType(scene, modifierTypes.CANDY_JAR).newModifier() as LevelIncrementBoosterModifier; const candyJar = generateModifierType(scene, modifierTypes.CANDY_JAR)!.newModifier() as LevelIncrementBoosterModifier;
candyJar.stackCount = 99; candyJar.stackCount = 99;
await scene.addModifier(candyJar, true, false, false, true); await scene.addModifier(candyJar, true, false, false, true);
const sitrus = generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]); const sitrus = generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS])!;
// Sitrus berries on party // Sitrus berries on party
const sitrusMod = sitrus.newModifier(scene.getParty()[0]) as BerryModifier; const sitrusMod = sitrus.newModifier(scene.getParty()[0]) as BerryModifier;
@ -277,12 +277,12 @@ describe("Delibird-y - Mystery Encounter", () => {
// 5 Healing Charms // 5 Healing Charms
scene.modifiers = []; scene.modifiers = [];
const healingCharm = generateModifierType(scene, modifierTypes.HEALING_CHARM).newModifier() as HealingBoosterModifier; const healingCharm = generateModifierType(scene, modifierTypes.HEALING_CHARM)!.newModifier() as HealingBoosterModifier;
healingCharm.stackCount = 5; healingCharm.stackCount = 5;
await scene.addModifier(healingCharm, true, false, false, true); await scene.addModifier(healingCharm, true, false, false, true);
// Set 1 Reviver Seed on party lead // Set 1 Reviver Seed on party lead
const revSeed = generateModifierType(scene, modifierTypes.REVIVER_SEED); const revSeed = generateModifierType(scene, modifierTypes.REVIVER_SEED)!;
const modifier = revSeed.newModifier(scene.getParty()[0]) as PokemonInstantReviveModifier; const modifier = revSeed.newModifier(scene.getParty()[0]) as PokemonInstantReviveModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
await scene.addModifier(modifier, true, false, false, true); await scene.addModifier(modifier, true, false, false, true);
@ -306,7 +306,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Soul Dew on party lead // Set 1 Soul Dew on party lead
scene.modifiers = []; scene.modifiers = [];
const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW); const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getParty()[0]); const modifier = soulDew.newModifier(scene.getParty()[0]);
await scene.addModifier(modifier, true, false, false, true); await scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -334,7 +334,7 @@ describe("Delibird-y - Mystery Encounter", () => {
await game.runToMysteryEncounter(MysteryEncounterType.DELIBIRDY, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.DELIBIRDY, defaultParty);
// Set 1 Reviver Seed on party lead // Set 1 Reviver Seed on party lead
const revSeed = generateModifierType(scene, modifierTypes.REVIVER_SEED); const revSeed = generateModifierType(scene, modifierTypes.REVIVER_SEED)!;
const modifier = revSeed.newModifier(scene.getParty()[0]) as PokemonInstantReviveModifier; const modifier = revSeed.newModifier(scene.getParty()[0]) as PokemonInstantReviveModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
await scene.addModifier(modifier, true, false, false, true); await scene.addModifier(modifier, true, false, false, true);
@ -368,7 +368,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 2 Soul Dew on party lead // Set 2 Soul Dew on party lead
scene.modifiers = []; scene.modifiers = [];
const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW); const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getParty()[0]) as PokemonNatureWeightModifier; const modifier = soulDew.newModifier(scene.getParty()[0]) as PokemonNatureWeightModifier;
modifier.stackCount = 2; modifier.stackCount = 2;
await scene.addModifier(modifier, true, false, false, true); await scene.addModifier(modifier, true, false, false, true);
@ -389,7 +389,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Soul Dew on party lead // Set 1 Soul Dew on party lead
scene.modifiers = []; scene.modifiers = [];
const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW); const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getParty()[0]) as PokemonNatureWeightModifier; const modifier = soulDew.newModifier(scene.getParty()[0]) as PokemonNatureWeightModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
await scene.addModifier(modifier, true, false, false, true); await scene.addModifier(modifier, true, false, false, true);
@ -410,12 +410,12 @@ describe("Delibird-y - Mystery Encounter", () => {
// 5 Healing Charms // 5 Healing Charms
scene.modifiers = []; scene.modifiers = [];
const healingCharm = generateModifierType(scene, modifierTypes.BERRY_POUCH).newModifier() as PreserveBerryModifier; const healingCharm = generateModifierType(scene, modifierTypes.BERRY_POUCH)!.newModifier() as PreserveBerryModifier;
healingCharm.stackCount = 3; healingCharm.stackCount = 3;
await scene.addModifier(healingCharm, true, false, false, true); await scene.addModifier(healingCharm, true, false, false, true);
// Set 1 Soul Dew on party lead // Set 1 Soul Dew on party lead
const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW); const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getParty()[0]) as PokemonNatureWeightModifier; const modifier = soulDew.newModifier(scene.getParty()[0]) as PokemonNatureWeightModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
await scene.addModifier(modifier, true, false, false, true); await scene.addModifier(modifier, true, false, false, true);
@ -439,7 +439,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Reviver Seed on party lead // Set 1 Reviver Seed on party lead
scene.modifiers = []; scene.modifiers = [];
const revSeed = generateModifierType(scene, modifierTypes.REVIVER_SEED); const revSeed = generateModifierType(scene, modifierTypes.REVIVER_SEED)!;
const modifier = revSeed.newModifier(scene.getParty()[0]); const modifier = revSeed.newModifier(scene.getParty()[0]);
await scene.addModifier(modifier, true, false, false, true); await scene.addModifier(modifier, true, false, false, true);
await scene.updateModifiers(true); await scene.updateModifiers(true);
@ -468,7 +468,7 @@ describe("Delibird-y - Mystery Encounter", () => {
// Set 1 Soul Dew on party lead // Set 1 Soul Dew on party lead
scene.modifiers = []; scene.modifiers = [];
const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW); const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW)!;
const modifier = soulDew.newModifier(scene.getParty()[0]) as PokemonNatureWeightModifier; const modifier = soulDew.newModifier(scene.getParty()[0]) as PokemonNatureWeightModifier;
modifier.stackCount = 1; modifier.stackCount = 1;
await scene.addModifier(modifier, true, false, false, true); await scene.addModifier(modifier, true, false, false, true);

View File

@ -5,7 +5,7 @@ import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounter-test-utils";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";

View File

@ -9,7 +9,7 @@ import { Gender } from "#app/data/gender";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import * as BattleAnims from "#app/data/battle-anims"; import * as BattleAnims from "#app/data/battle-anims";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { PokemonHeldItemModifier } from "#app/modifier/modifier"; import { PokemonHeldItemModifier } from "#app/modifier/modifier";

View File

@ -4,7 +4,7 @@ import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
import { Species } from "#app/enums/species"; import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { PokemonMove } from "#app/field/pokemon"; import { PokemonMove } from "#app/field/pokemon";

View File

@ -8,7 +8,7 @@ import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
import { Species } from "#app/enums/species"; import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption } from "../encounterTestUtils"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption } from "../encounter-test-utils";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils"; import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils";

View File

@ -5,7 +5,7 @@ import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
import { Species } from "#app/enums/species"; import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";

View File

@ -5,7 +5,7 @@ import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption } from "#test/mystery-encounter/encounter-test-utils";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { CIVILIZATION_ENCOUNTER_BIOMES } from "#app/data/mystery-encounters/mystery-encounters"; import { CIVILIZATION_ENCOUNTER_BIOMES } from "#app/data/mystery-encounters/mystery-encounters";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";

View File

@ -4,7 +4,7 @@ import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
import { Species } from "#app/enums/species"; import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
@ -151,7 +151,6 @@ describe("Teleporting Hijinks - Mystery Encounter", () => {
it("should NOT be selectable if the player doesn't have enough money", async () => { it("should NOT be selectable if the player doesn't have enough money", async () => {
game.scene.money = 0; game.scene.money = 0;
await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty); await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty);
scene.getParty().forEach(p => p.moveset = []);
await game.phaseInterceptor.to(MysteryEncounterPhase, false); await game.phaseInterceptor.to(MysteryEncounterPhase, false);
const encounterPhase = scene.getCurrentPhase(); const encounterPhase = scene.getCurrentPhase();

View File

@ -5,7 +5,7 @@ import { Species } from "#app/enums/species";
import GameManager from "#app/test/utils/gameManager"; import GameManager from "#app/test/utils/gameManager";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption } from "#test/mystery-encounter/encounter-test-utils";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { PlayerPokemon } from "#app/field/pokemon"; import { PlayerPokemon } from "#app/field/pokemon";
import { HUMAN_TRANSITABLE_BIOMES } from "#app/data/mystery-encounters/mystery-encounters"; import { HUMAN_TRANSITABLE_BIOMES } from "#app/data/mystery-encounters/mystery-encounters";

View File

@ -7,7 +7,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import * as BattleAnims from "#app/data/battle-anims"; import * as BattleAnims from "#app/data/battle-anims";
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { TheStrongStuffEncounter } from "#app/data/mystery-encounters/encounters/the-strong-stuff-encounter"; import { TheStrongStuffEncounter } from "#app/data/mystery-encounters/encounters/the-strong-stuff-encounter";
@ -164,9 +164,10 @@ describe("The Strong Stuff - Mystery Encounter", () => {
return baseStats.reduce((a, b) => a + b); return baseStats.reduce((a, b) => a + b);
}); });
expect(bstsAfter[0]).toEqual(bstsPrior[0] - 20 * 6); // HP stat changes are halved compared to other values
expect(bstsAfter[1]).toEqual(bstsPrior[1] + 10 * 6); expect(bstsAfter[0]).toEqual(bstsPrior[0] - 20 * 5 - 10);
expect(bstsAfter[2]).toEqual(bstsPrior[2] + 10 * 6); expect(bstsAfter[1]).toEqual(bstsPrior[1] + 10 * 5 + 5);
expect(bstsAfter[2]).toEqual(bstsPrior[2] + 10 * 5 + 5);
}); });
it("should leave encounter without battle", async () => { it("should leave encounter without battle", async () => {

Some files were not shown because too many files have changed in this diff Show More