mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2024-11-27 01:06:09 +00:00
Merge pull request #3850 from pagefaultgames/bug-type-superfan
Bug-Type Superfan Mystery Encounter
This commit is contained in:
commit
b27e093252
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 |
BIN
public/images/items/golden_net.png
Normal file
BIN
public/images/items/golden_net.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 561 B |
1469
public/images/trainer/bug_type_superfan.json
Normal file
1469
public/images/trainer/bug_type_superfan.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
public/images/trainer/bug_type_superfan.png
Normal file
BIN
public/images/trainer/bug_type_superfan.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
@ -13,7 +13,17 @@ import { Arena, ArenaBase } from "./field/arena";
|
||||
import { GameData } from "./system/game-data";
|
||||
import { addTextObject, getTextColor, TextStyle } from "./ui/text";
|
||||
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 { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, ChangeMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability";
|
||||
import { allAbilities } from "./data/ability";
|
||||
|
@ -19,7 +19,7 @@ const namespace = "mysteryEncounter:aTrainersTest";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const ATrainersTestEncounter: MysteryEncounter =
|
||||
|
@ -29,7 +29,7 @@ const namespace = "mysteryEncounter:absoluteAvarice";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
@ -249,8 +249,10 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
const givePartyPokemonReviverSeeds = () => {
|
||||
const party = scene.getParty();
|
||||
party.forEach(p => {
|
||||
if (revSeed) {
|
||||
const seedModifier = revSeed.newModifier(p);
|
||||
scene.addModifier(seedModifier, false, false, false, true);
|
||||
}
|
||||
});
|
||||
queueEncounterMessage(scene, `${namespace}.option.1.food_stash`);
|
||||
};
|
||||
@ -349,7 +351,7 @@ function doGreedentSpriteSteal(scene: BattleScene) {
|
||||
|
||||
const greedentSprites = scene.currentBattle.mysteryEncounter.introVisuals?.getSpriteAtIndex(1);
|
||||
|
||||
scene.playSound("Follow Me");
|
||||
scene.playSound("battle-anims/Follow Me");
|
||||
scene.tweens.chain({
|
||||
targets: greedentSprites,
|
||||
tweens: [
|
||||
@ -431,11 +433,11 @@ function doGreedentEatBerries(scene: BattleScene) {
|
||||
y: "-=8",
|
||||
loop: 5,
|
||||
onStart: () => {
|
||||
scene.playSound("PRSFX- Bug Bite");
|
||||
scene.playSound("battle_anims/PRSFX- Bug Bite");
|
||||
},
|
||||
onLoop: () => {
|
||||
if (index % 2 === 0) {
|
||||
scene.playSound("PRSFX- Bug Bite");
|
||||
scene.playSound("battle_anims/PRSFX- Bug Bite");
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ const namespace = "mysteryEncounter:offerYouCantRefuse";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
||||
|
@ -37,7 +37,7 @@ const namespace = "mysteryEncounter:berriesAbound";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const BerriesAboundEncounter: MysteryEncounter =
|
||||
@ -131,7 +131,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
const doBerryRewards = async () => {
|
||||
const berryText = numBerries + " " + i18next.t(`${namespace}.berries`);
|
||||
|
||||
scene.playSound("item_fanfare");
|
||||
scene.playSound("bgm/item_fanfare");
|
||||
queueEncounterMessage(scene, i18next.t("battle:rewardGain", { modifierName: berryText }));
|
||||
|
||||
// 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[] = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
// 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);
|
||||
@ -168,7 +171,10 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
const shopOptions: ModifierTypeOption[] = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
// Generate shop berries
|
||||
shopOptions.push(generateModifierTypeOption(scene, modifierTypes.BERRY));
|
||||
const mod = generateModifierTypeOption(scene, modifierTypes.BERRY);
|
||||
if (mod) {
|
||||
shopOptions.push(mod);
|
||||
}
|
||||
}
|
||||
|
||||
if (speedDiff < 1) {
|
||||
@ -176,7 +182,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
const doBerryRewards = async () => {
|
||||
const berryText = numBerries + " " + i18next.t(`${namespace}.berries`);
|
||||
|
||||
scene.playSound("item_fanfare");
|
||||
scene.playSound("bgm/item_fanfare");
|
||||
queueEncounterMessage(scene, i18next.t("battle:rewardGain", { modifierName: berryText }));
|
||||
|
||||
// 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 berryText = numBerriesGrabbed + " " + i18next.t(`${namespace}.berries`);
|
||||
|
||||
scene.playSound("item_fanfare");
|
||||
scene.playSound("bgm/item_fanfare");
|
||||
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)
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
@ -53,7 +53,7 @@ const RANDOM_ABILITY_POOL = [
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const ClowningAroundEncounter: MysteryEncounter =
|
||||
@ -334,13 +334,13 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
randSeedShuffle(priorityTypes);
|
||||
}
|
||||
|
||||
let newTypes;
|
||||
let newTypes: Type[];
|
||||
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 {
|
||||
newTypes = originalTypes.map(m => {
|
||||
if (priorityTypes?.length > 0) {
|
||||
const ret = priorityTypes.pop();
|
||||
if (priorityTypes && priorityTypes.length > 0) {
|
||||
const ret = priorityTypes.pop()!;
|
||||
randSeedShuffle(priorityTypes);
|
||||
return ret;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ const SENSU_STYLE_BIOMES = [
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const DancingLessonsEncounter: MysteryEncounter =
|
||||
|
@ -71,7 +71,7 @@ const excludedBosses = [
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const DarkDealEncounter: MysteryEncounter =
|
||||
|
@ -33,7 +33,7 @@ const OPTION_3_DISALLOWED_MODIFIERS = [
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const DelibirdyEncounter: MysteryEncounter =
|
||||
@ -115,7 +115,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
||||
// At max stacks, give the first party pokemon a Shell Bell instead
|
||||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
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);
|
||||
} else {
|
||||
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
|
||||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
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);
|
||||
} else {
|
||||
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
|
||||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
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);
|
||||
} else {
|
||||
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
|
||||
const shellBell = generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType;
|
||||
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);
|
||||
} else {
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.BERRY_POUCH));
|
||||
|
@ -17,7 +17,7 @@ const namespace = "mysteryEncounter:departmentStoreSale";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
||||
|
@ -16,7 +16,7 @@ const namespace = "mysteryEncounter:fieldTrip";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const FieldTripEncounter: MysteryEncounter =
|
||||
@ -126,10 +126,10 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.ATK]),
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.DEF]),
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD]),
|
||||
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT),
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.ATK])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.DEF])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!,
|
||||
];
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });
|
||||
@ -218,10 +218,10 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPATK]),
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPDEF]),
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD]),
|
||||
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT),
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPATK])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPDEF])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!,
|
||||
];
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });
|
||||
@ -304,10 +304,10 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.ACC]),
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD]),
|
||||
generateModifierTypeOption(scene, modifierTypes.GREAT_BALL),
|
||||
generateModifierTypeOption(scene, modifierTypes.IV_SCANNER),
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.ACC])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.GREAT_BALL)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.IV_SCANNER)!,
|
||||
];
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });
|
||||
|
@ -33,7 +33,7 @@ const DAMAGE_PERCENTAGE: number = 20;
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const FieryFalloutEncounter: MysteryEncounter =
|
||||
|
@ -30,7 +30,7 @@ const namespace = "mysteryEncounter:fightOrFlight";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const FightOrFlightEncounter: MysteryEncounter =
|
||||
|
@ -23,7 +23,7 @@ const namespace = "mysteryEncounter:lostAtSea";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param scene Battle scene
|
||||
* @param guidePokemon pokemon choosen as a guide
|
||||
*/
|
||||
async function handlePokemonGuidingYouPhase(scene: BattleScene) {
|
||||
const laprasSpecies = getPokemonSpecies(Species.LAPRAS);
|
||||
|
@ -23,7 +23,7 @@ const namespace = "mysteryEncounter:mysteriousChallengers";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
|
@ -15,7 +15,7 @@ const namespace = "mysteryEncounter:mysteriousChest";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const MysteriousChestEncounter: MysteryEncounter =
|
||||
|
@ -17,7 +17,7 @@ const namespace = "mysteryEncounter:partTimer";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const PartTimerEncounter: MysteryEncounter =
|
||||
@ -140,7 +140,7 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
}
|
||||
const moneyChange = scene.getWaveMoneyAmount(moneyMultiplier);
|
||||
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`);
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true });
|
||||
@ -221,7 +221,7 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
}
|
||||
const moneyChange = scene.getWaveMoneyAmount(moneyMultiplier);
|
||||
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`);
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true });
|
||||
@ -273,7 +273,7 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
await showEncounterDialogue(scene, `${namespace}.job_complete_good`, `${namespace}.speaker`);
|
||||
const moneyChange = scene.getWaveMoneyAmount(2.5);
|
||||
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`);
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true });
|
||||
@ -290,50 +290,50 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
.build();
|
||||
|
||||
function doStrongWorkSfx(scene: BattleScene) {
|
||||
scene.playSound("PRSFX- Horn Drill1");
|
||||
scene.playSound("PRSFX- Horn Drill1");
|
||||
scene.playSound("battle_anims/PRSFX- Horn Drill1");
|
||||
scene.playSound("battle_anims/PRSFX- Horn Drill1");
|
||||
|
||||
scene.time.delayedCall(1000, () => {
|
||||
scene.playSound("PRSFX- Guillotine2");
|
||||
scene.playSound("battle_anims/PRSFX- Guillotine2");
|
||||
});
|
||||
|
||||
scene.time.delayedCall(2000, () => {
|
||||
scene.playSound("PRSFX- Heavy Slam2");
|
||||
scene.playSound("battle_anims/PRSFX- Heavy Slam2");
|
||||
});
|
||||
|
||||
scene.time.delayedCall(2500, () => {
|
||||
scene.playSound("PRSFX- Guillotine2");
|
||||
scene.playSound("battle_anims/PRSFX- Guillotine2");
|
||||
});
|
||||
}
|
||||
|
||||
function doDeliverySfx(scene: BattleScene) {
|
||||
scene.playSound("PRSFX- Accelerock1");
|
||||
scene.playSound("battle_anims/PRSFX- Accelerock1");
|
||||
|
||||
scene.time.delayedCall(1500, () => {
|
||||
scene.playSound("PRSFX- Extremespeed1");
|
||||
scene.playSound("battle_anims/PRSFX- Extremespeed1");
|
||||
});
|
||||
|
||||
scene.time.delayedCall(2000, () => {
|
||||
scene.playSound("PRSFX- Extremespeed1");
|
||||
scene.playSound("battle_anims/PRSFX- Extremespeed1");
|
||||
});
|
||||
|
||||
scene.time.delayedCall(2250, () => {
|
||||
scene.playSound("PRSFX- Agility");
|
||||
scene.playSound("battle_anims/PRSFX- Agility");
|
||||
});
|
||||
}
|
||||
|
||||
function doSalesSfx(scene: BattleScene) {
|
||||
scene.playSound("PRSFX- Captivate");
|
||||
scene.playSound("battle_anims/PRSFX- Captivate");
|
||||
|
||||
scene.time.delayedCall(1500, () => {
|
||||
scene.playSound("PRSFX- Attract2");
|
||||
scene.playSound("battle_anims/PRSFX- Attract2");
|
||||
});
|
||||
|
||||
scene.time.delayedCall(2000, () => {
|
||||
scene.playSound("PRSFX- Aurora Veil2");
|
||||
scene.playSound("battle_anims/PRSFX- Aurora Veil2");
|
||||
});
|
||||
|
||||
scene.time.delayedCall(3000, () => {
|
||||
scene.playSound("PRSFX- Attract2");
|
||||
scene.playSound("battle_anims/PRSFX- Attract2");
|
||||
});
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ const TRAINER_THROW_ANIMATION_TIMES = [512, 184, 768];
|
||||
|
||||
/**
|
||||
* Safari Zone encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/39 | GitHub Issue #39}
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3800 | GitHub Issue #3800}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const SafariZoneEncounter: MysteryEncounter =
|
||||
@ -322,7 +322,7 @@ async function throwBait(scene: BattleScene, pokemon: EnemyPokemon): Promise<boo
|
||||
return new Promise(resolve => {
|
||||
scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`);
|
||||
scene.time.delayedCall(TRAINER_THROW_ANIMATION_TIMES[0], () => {
|
||||
scene.playSound("pb_throw");
|
||||
scene.playSound("se/pb_throw");
|
||||
|
||||
// Trainer throw frames
|
||||
scene.trainer.setFrame("2");
|
||||
@ -351,12 +351,12 @@ async function throwBait(scene: BattleScene, pokemon: EnemyPokemon): Promise<boo
|
||||
y: originalY - 5,
|
||||
loop: 6,
|
||||
onStart: () => {
|
||||
scene.playSound("PRSFX- Bug Bite");
|
||||
scene.playSound("battle-anims/PRSFX- Bug Bite");
|
||||
bait.setFrame("0002.png");
|
||||
},
|
||||
onLoop: () => {
|
||||
if (index % 2 === 0) {
|
||||
scene.playSound("PRSFX- Bug Bite");
|
||||
scene.playSound("battle-anims/PRSFX- Bug Bite");
|
||||
}
|
||||
if (index === 4) {
|
||||
bait.setFrame("0003.png");
|
||||
@ -388,7 +388,7 @@ async function throwMud(scene: BattleScene, pokemon: EnemyPokemon): Promise<bool
|
||||
return new Promise(resolve => {
|
||||
scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`);
|
||||
scene.time.delayedCall(TRAINER_THROW_ANIMATION_TIMES[0], () => {
|
||||
scene.playSound("pb_throw");
|
||||
scene.playSound("se/pb_throw");
|
||||
|
||||
// Trainer throw frames
|
||||
scene.trainer.setFrame("2");
|
||||
@ -407,7 +407,7 @@ async function throwMud(scene: BattleScene, pokemon: EnemyPokemon): Promise<bool
|
||||
duration: 500,
|
||||
onComplete: () => {
|
||||
// Mud frame 2
|
||||
scene.playSound("PRSFX- Sludge Bomb2");
|
||||
scene.playSound("battle-anims/PRSFX- Sludge Bomb2");
|
||||
mud.setFrame("0002.png");
|
||||
// Mud splat
|
||||
scene.time.delayedCall(200, () => {
|
||||
@ -433,10 +433,10 @@ async function throwMud(scene: BattleScene, pokemon: EnemyPokemon): Promise<bool
|
||||
y: originalY - 20,
|
||||
loop: 1,
|
||||
onStart: () => {
|
||||
scene.playSound("PRSFX- Taunt2");
|
||||
scene.playSound("battle-anims/PRSFX- Taunt2");
|
||||
},
|
||||
onLoop: () => {
|
||||
scene.playSound("PRSFX- Taunt2");
|
||||
scene.playSound("battle-anims/PRSFX- Taunt2");
|
||||
},
|
||||
onComplete: () => {
|
||||
resolve(true);
|
||||
|
@ -19,7 +19,7 @@ const namespace = "mysteryEncounter:shadyVitaminDealer";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
@ -79,8 +79,8 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
updatePlayerMoney(scene, -(encounter.options[0].requirements[0] as MoneyRequirement).requiredMoney);
|
||||
// Calculate modifiers and dialogue tokens
|
||||
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("boost2", modifiers[1].name);
|
||||
@ -162,8 +162,8 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
updatePlayerMoney(scene, -(encounter.options[1].requirements[0] as MoneyRequirement).requiredMoney);
|
||||
// Calculate modifiers and dialogue tokens
|
||||
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("boost2", modifiers[1].name);
|
||||
|
@ -22,7 +22,7 @@ const namespace = "mysteryEncounter:slumberingSnorlax";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
|
@ -29,7 +29,7 @@ const MACHINE_INTERFACING_TYPES = [Type.ELECTRIC, Type.STEEL];
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||
@ -140,10 +140,9 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||
}],
|
||||
};
|
||||
|
||||
const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.STEEL]);
|
||||
const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.ELECTRIC]);
|
||||
const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.STEEL])!;
|
||||
const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.ELECTRIC])!;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [magnet, metalCoat], fillRemaining: true });
|
||||
setEncounterExp(scene, encounter.selectedOption!.primaryPokemon!.id, 100);
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ const MAX_POKEMON_PRICE_MULTIPLIER = 6;
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
||||
|
@ -23,7 +23,7 @@ const namespace = "mysteryEncounter:theStrongStuff";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const TheStrongStuffEncounter: MysteryEncounter =
|
||||
|
@ -26,7 +26,7 @@ const namespace = "mysteryEncounter:theWinstrateChallenge";
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const TheWinstrateChallengeEncounter: MysteryEncounter =
|
||||
|
@ -24,7 +24,7 @@ const namespace = "mysteryEncounter:trainingSession";
|
||||
|
||||
/**
|
||||
* Training Session encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/43 | GitHub Issue #43}
|
||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3802 | GitHub Issue #3802}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const TrainingSessionEncounter: MysteryEncounter =
|
||||
|
@ -25,7 +25,7 @@ const SOUND_EFFECT_WAIT_TIME = 700;
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
async function doGarbageDig(scene: BattleScene) {
|
||||
scene.playSound("PRSFX- Dig2");
|
||||
scene.playSound("battle-anims/PRSFX- Dig2");
|
||||
scene.time.delayedCall(SOUND_EFFECT_WAIT_TIME, () => {
|
||||
scene.playSound("PRSFX- Dig2");
|
||||
scene.playSound("PRSFX- Venom Drench", { volume: 2 });
|
||||
scene.playSound("battle-anims/PRSFX- Dig2");
|
||||
scene.playSound("battle-anims/PRSFX- Venom Drench", { volume: 2 });
|
||||
});
|
||||
scene.time.delayedCall(SOUND_EFFECT_WAIT_TIME * 2, () => {
|
||||
scene.playSound("PRSFX- Dig2");
|
||||
scene.playSound("battle-anims/PRSFX- Dig2");
|
||||
});
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ import { getLevelTotalExp } from "#app/data/exp";
|
||||
/** i18n namespace for encounter */
|
||||
const namespace = "mysteryEncounter:weirdDream";
|
||||
|
||||
/** Exclude Ultra Beasts (inludes Cosmog/Solgaleo/Lunala/Necrozma), Paradox (includes Miraidon/Koraidon), Eternatus, Urshifu, the Poison Chain trio, Ogerpon */
|
||||
const excludedPokemon = [
|
||||
/** Exclude Ultra Beasts, Paradox, Eternatus, and all legendary/mythical/trio pokemon that are below 570 BST */
|
||||
const EXCLUDED_TRANSFORMATION_SPECIES = [
|
||||
Species.ETERNATUS,
|
||||
/** UBs */
|
||||
Species.NIHILEGO,
|
||||
@ -77,9 +77,18 @@ const excludedPokemon = [
|
||||
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.
|
||||
* @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}
|
||||
*/
|
||||
export const WeirdDreamEncounter: MysteryEncounter =
|
||||
@ -225,9 +234,9 @@ function getTeamTransformations(scene: BattleScene): PokemonTransformation[] {
|
||||
});
|
||||
|
||||
// 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
|
||||
let hasPokemonBstBetween570And600 = false;
|
||||
let hasPokemonInLegendaryBstThreshold = false;
|
||||
|
||||
// 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
|
||||
@ -241,19 +250,19 @@ function getTeamTransformations(scene: BattleScene): PokemonTransformation[] {
|
||||
const bst = getOriginalBst(scene, removed);
|
||||
let newBstRange;
|
||||
if (i < 2) {
|
||||
newBstRange = [90, 110];
|
||||
newBstRange = HIGH_BST_TRANSFORM_BASE_VALUES;
|
||||
} 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();
|
||||
if (newSpeciesBst > 600) {
|
||||
hasPokemonBstHigherThan600 = true;
|
||||
if (newSpeciesBst > SUPER_LEGENDARY_BST_THRESHOLD) {
|
||||
hasPokemonInSuperLegendaryBstThreshold = true;
|
||||
}
|
||||
if (newSpeciesBst <= 600 && newSpeciesBst >= 570) {
|
||||
hasPokemonBstBetween570And600 = true;
|
||||
if (newSpeciesBst <= SUPER_LEGENDARY_BST_THRESHOLD && newSpeciesBst >= NON_LEGENDARY_BST_THRESHOLD) {
|
||||
hasPokemonInLegendaryBstThreshold = true;
|
||||
}
|
||||
|
||||
|
||||
@ -299,9 +308,8 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
|
||||
return newValue > iv ? newValue : iv;
|
||||
});
|
||||
|
||||
|
||||
// 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) {
|
||||
scene.validateAchv(achvs.HIDDEN_ABILITY);
|
||||
}
|
||||
@ -372,8 +380,8 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
|
||||
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
|
||||
if (newPokemon.getSpeciesForm().getBaseStatTotal() <= 450) {
|
||||
// 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() <= GAIN_OLD_GATEAU_ITEM_BST_THRESHOLD) {
|
||||
const stats: Stat[] = [Stat.HP];
|
||||
const baseStats = newPokemon.getSpeciesForm().baseStats.slice(0);
|
||||
// Attack or SpAtk
|
||||
@ -435,9 +443,9 @@ function getTransformedSpecies(originalBst: number, bstSearchRange: [number, num
|
||||
const speciesBst = s.getBaseStatTotal();
|
||||
const bstInRange = speciesBst >= bstMin && speciesBst <= bstCap;
|
||||
// Checks that a Pokemon has not already been added in the +600 or 570-600 slots;
|
||||
const validBst = (!hasPokemonBstBetween570And600 || (speciesBst < 570 || speciesBst > 600)) &&
|
||||
(!hasPokemonBstHigherThan600 || speciesBst <= 600);
|
||||
return bstInRange && validBst && !excludedPokemon.includes(s.speciesId);
|
||||
const validBst = (!hasPokemonBstBetween570And600 || (speciesBst < NON_LEGENDARY_BST_THRESHOLD || speciesBst > SUPER_LEGENDARY_BST_THRESHOLD)) &&
|
||||
(!hasPokemonBstHigherThan600 || speciesBst <= SUPER_LEGENDARY_BST_THRESHOLD);
|
||||
return bstInRange && validBst && !EXCLUDED_TRANSFORMATION_SPECIES.includes(s.speciesId);
|
||||
});
|
||||
|
||||
// There must be at least 20 species available before it will choose one
|
||||
|
@ -81,7 +81,7 @@ export default class MysteryEncounterOption implements IMysteryEncounterOption {
|
||||
}
|
||||
|
||||
meetsPrimaryRequirementAndPrimaryPokemonSelected(scene: BattleScene) {
|
||||
if (!this.primaryPokemonRequirements) {
|
||||
if (!this.primaryPokemonRequirements || this.primaryPokemonRequirements.length === 0) {
|
||||
return true;
|
||||
}
|
||||
let qualified: PlayerPokemon[] = scene.getParty();
|
||||
@ -101,7 +101,7 @@ export default class MysteryEncounterOption implements IMysteryEncounterOption {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.excludePrimaryFromSecondaryRequirements && this.secondaryPokemon) {
|
||||
if (this.excludePrimaryFromSecondaryRequirements && this.secondaryPokemon && this.secondaryPokemon.length > 0) {
|
||||
const truePrimaryPool: PlayerPokemon[] = [];
|
||||
const overlap: PlayerPokemon[] = [];
|
||||
for (const qp of qualified) {
|
||||
@ -135,7 +135,7 @@ export default class MysteryEncounterOption implements IMysteryEncounterOption {
|
||||
}
|
||||
|
||||
meetsSupportingRequirementAndSupportingPokemonSelected(scene: BattleScene) {
|
||||
if (!this.secondaryPokemonRequirements) {
|
||||
if (!this.secondaryPokemonRequirements || this.secondaryPokemonRequirements.length === 0) {
|
||||
this.secondaryPokemon = [];
|
||||
return true;
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ import { StatusEffect } from "../status-effect";
|
||||
import { Type } from "../type";
|
||||
import { WeatherType } from "../weather";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { AttackTypeBoosterModifier } from "#app/modifier/modifier";
|
||||
import { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type";
|
||||
|
||||
export interface EncounterRequirement {
|
||||
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 {
|
||||
let partyPokemon = scene.getParty();
|
||||
|
||||
if (isNullOrUndefined(partyPokemon) || this?.requiredType?.length < 0) {
|
||||
if (isNullOrUndefined(partyPokemon)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.excludeFainted) {
|
||||
if (this.excludeFainted) {
|
||||
partyPokemon = partyPokemon.filter((pokemon) => !pokemon.isFainted());
|
||||
}
|
||||
|
||||
@ -795,7 +797,7 @@ export class HeldItemRequirement extends EncounterPokemonRequirement {
|
||||
|
||||
meetsRequirement(scene: BattleScene): boolean {
|
||||
const partyPokemon = scene.getParty();
|
||||
if (isNullOrUndefined(partyPokemon) || this?.requiredHeldItemModifiers?.length < 0) {
|
||||
if (isNullOrUndefined(partyPokemon)) {
|
||||
return false;
|
||||
}
|
||||
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 {
|
||||
requiredLevelRange: [number, number];
|
||||
minNumberOfPokemon: number;
|
||||
|
@ -122,6 +122,8 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
||||
onInit?: (scene: BattleScene) => boolean;
|
||||
/** Event when battlefield visuals have finished sliding in and the encounter dialogue begins */
|
||||
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 */
|
||||
doEncounterExp?: (scene: BattleScene) => boolean;
|
||||
/** Will provide the player a rewards shop for that wave */
|
||||
@ -261,7 +263,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
||||
}
|
||||
|
||||
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));
|
||||
if (activeMon.length > 0) {
|
||||
this.primaryPokemon = activeMon[0];
|
||||
@ -284,7 +286,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.excludePrimaryFromSupportRequirements && this.secondaryPokemon) {
|
||||
if (this.excludePrimaryFromSupportRequirements && this.secondaryPokemon && this.secondaryPokemon.length > 0) {
|
||||
const truePrimaryPool: PlayerPokemon[] = [];
|
||||
const overlap: PlayerPokemon[] = [];
|
||||
for (const qp of qualified) {
|
||||
@ -318,7 +320,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
||||
}
|
||||
|
||||
meetsSecondaryRequirementAndSecondaryPokemonSelected(scene: BattleScene): boolean {
|
||||
if (!this.secondaryPokemonRequirements) {
|
||||
if (!this.secondaryPokemonRequirements || this.secondaryPokemonRequirements.length === 0) {
|
||||
this.secondaryPokemon = [];
|
||||
return true;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import { DancingLessonsEncounter } from "#app/data/mystery-encounters/encounters
|
||||
import { WeirdDreamEncounter } from "#app/data/mystery-encounters/encounters/weird-dream-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 { 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
|
||||
export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 1;
|
||||
@ -171,7 +172,8 @@ const anyBiomeEncounters: MysteryEncounterType[] = [
|
||||
MysteryEncounterType.BERRIES_ABOUND,
|
||||
MysteryEncounterType.CLOWNING_AROUND,
|
||||
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.THE_WINSTRATE_CHALLENGE] = TheWinstrateChallengeEncounter;
|
||||
allMysteryEncounters[MysteryEncounterType.TELEPORTING_HIJINKS] = TeleportingHijinksEncounter;
|
||||
allMysteryEncounters[MysteryEncounterType.BUG_TYPE_SUPERFAN] = BugTypeSuperfanEncounter;
|
||||
|
||||
// Add extreme encounters to biome map
|
||||
extremeBiomeEncounters.forEach(encounter => {
|
||||
|
@ -36,8 +36,7 @@ export const DANCING_MOVES = [
|
||||
Moves.QUIVER_DANCE,
|
||||
Moves.SWORDS_DANCE,
|
||||
Moves.TEETER_DANCE,
|
||||
Moves.VICTORY_DANCE,
|
||||
Moves.KNOCK_OFF
|
||||
Moves.VICTORY_DANCE
|
||||
];
|
||||
|
||||
export const DISTRACTION_MOVES = [
|
||||
|
@ -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 {
|
||||
@ -363,13 +363,13 @@ export function updatePlayerMoney(scene: BattleScene, changeValue: number, playS
|
||||
scene.updateMoneyText();
|
||||
scene.animateMoneyChanged(false);
|
||||
if (playSound) {
|
||||
scene.playSound("buy");
|
||||
scene.playSound("se/buy");
|
||||
}
|
||||
if (showMessage) {
|
||||
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 {
|
||||
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 pregenArgs - can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc.
|
||||
*/
|
||||
export function generateModifierType(scene: BattleScene, modifier: () => ModifierType, pregenArgs?: any[]): ModifierType {
|
||||
const modifierId = Object.keys(modifierTypes).find(k => modifierTypes[k] === modifier)!;
|
||||
let result: ModifierType = modifierTypes[modifierId]?.();
|
||||
export function generateModifierType(scene: BattleScene, modifier: () => ModifierType, pregenArgs?: any[]): ModifierType | null {
|
||||
const modifierId = Object.keys(modifierTypes).find(k => modifierTypes[k] === modifier);
|
||||
if (!modifierId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let result: ModifierType = modifierTypes[modifierId]();
|
||||
|
||||
// Populates item id and tier (order matters)
|
||||
result = result
|
||||
.withIdFromFunc(modifierTypes[modifierId])
|
||||
.withTierFromPool();
|
||||
|
||||
const generatedResult = result instanceof ModifierTypeGenerator ? result.generateType(scene.getParty(), pregenArgs) : result;
|
||||
return generatedResult ?? result;
|
||||
return result instanceof ModifierTypeGenerator ? result.generateType(scene.getParty(), pregenArgs) : result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -399,10 +402,13 @@ export function generateModifierType(scene: BattleScene, modifier: () => Modifie
|
||||
* @param modifier
|
||||
* @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);
|
||||
if (result) {
|
||||
return new ModifierTypeOption(result, 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is intended for use inside onPreOptionPhase() of an encounter option
|
||||
@ -416,7 +422,7 @@ export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (p
|
||||
return new Promise(resolve => {
|
||||
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) => {
|
||||
if (slotIndex < scene.getParty().length) {
|
||||
scene.ui.setMode(modeToSetOnExit).then(() => {
|
||||
@ -446,12 +452,12 @@ export function selectPokemonForOption(scene: BattleScene, onPokemonSelected: (p
|
||||
label: i18next.t("menu:cancel"),
|
||||
handler: () => {
|
||||
scene.ui.clearText();
|
||||
scene.ui.setMode(Mode.MYSTERY_ENCOUNTER);
|
||||
scene.ui.setMode(modeToSetOnExit);
|
||||
resolve(false);
|
||||
return true;
|
||||
},
|
||||
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,
|
||||
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);
|
||||
};
|
||||
|
||||
@ -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
|
||||
* Can have shop displayed or skipped
|
||||
|
@ -335,7 +335,7 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
|
||||
return new Promise(resolve => {
|
||||
scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`);
|
||||
scene.time.delayedCall(512, () => {
|
||||
scene.playSound("pb_throw");
|
||||
scene.playSound("se/pb_throw");
|
||||
|
||||
// Trainer throw frames
|
||||
scene.trainer.setFrame("2");
|
||||
@ -355,7 +355,7 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
|
||||
onComplete: () => {
|
||||
pokeball.setTexture("pb", `${pokeballAtlasKey}_opening`);
|
||||
scene.time.delayedCall(17, () => pokeball.setTexture("pb", `${pokeballAtlasKey}_open`));
|
||||
scene.playSound("pb_rel");
|
||||
scene.playSound("se/pb_rel");
|
||||
pokemon.tint(getPokeballTintColor(pokeballType));
|
||||
|
||||
addPokeballOpenParticles(scene, pokeball.x, pokeball.y, pokeballType);
|
||||
@ -369,7 +369,7 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
|
||||
onComplete: () => {
|
||||
pokeball.setTexture("pb", `${pokeballAtlasKey}_opening`);
|
||||
pokemon.setVisible(false);
|
||||
scene.playSound("pb_catch");
|
||||
scene.playSound("se/pb_catch");
|
||||
scene.time.delayedCall(17, () => pokeball.setTexture("pb", `${pokeballAtlasKey}`));
|
||||
|
||||
const doShake = () => {
|
||||
@ -397,13 +397,13 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
|
||||
failCatch(scene, pokemon, originalY, pokeball, pokeballType).then(() => resolve(false));
|
||||
} else if (shakeCount++ < 3) {
|
||||
if (randSeedInt(65536) < ballTwitchRate) {
|
||||
scene.playSound("pb_move");
|
||||
scene.playSound("se/pb_move");
|
||||
} else {
|
||||
shakeCounter.stop();
|
||||
failCatch(scene, pokemon, originalY, pokeball, pokeballType).then(() => resolve(false));
|
||||
}
|
||||
} else {
|
||||
scene.playSound("pb_lock");
|
||||
scene.playSound("se/pb_lock");
|
||||
addPokeballCaptureStars(scene, pokeball);
|
||||
|
||||
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) {
|
||||
return new Promise<void>(resolve => {
|
||||
scene.playSound("pb_rel");
|
||||
scene.playSound("se/pb_rel");
|
||||
pokemon.setY(originalY);
|
||||
if (pokemon.status?.effect !== StatusEffect.SLEEP) {
|
||||
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> {
|
||||
await new Promise<void>(resolve => {
|
||||
scene.playSound("flee");
|
||||
scene.playSound("se/flee");
|
||||
// Ease pokemon out
|
||||
scene.tweens.add({
|
||||
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]);
|
||||
}
|
||||
|
@ -2104,5 +2104,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyTemplates(trainerPartyTemplates.ONE_AVG),
|
||||
[TrainerType.VITO]: new TrainerConfig(++t).setName("Vito").setTitle("The Winstrates")
|
||||
.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))
|
||||
};
|
||||
|
@ -24,5 +24,6 @@ export enum MysteryEncounterType {
|
||||
DANCING_LESSONS,
|
||||
WEIRD_DREAM,
|
||||
THE_WINSTRATE_CHALLENGE,
|
||||
TELEPORTING_HIJINKS
|
||||
TELEPORTING_HIJINKS,
|
||||
BUG_TYPE_SUPERFAN
|
||||
}
|
||||
|
@ -94,6 +94,7 @@ export enum TrainerType {
|
||||
VIVI,
|
||||
VICKY,
|
||||
VITO,
|
||||
BUG_TYPE_SUPERFAN,
|
||||
|
||||
BROCK = 200,
|
||||
MISTY,
|
||||
|
@ -59,6 +59,7 @@ import modifierSelectUiHandler from "./modifier-select-ui-handler.json";
|
||||
import moveTriggers from "./move-trigger.json";
|
||||
import runHistory from "./run-history.json";
|
||||
import { mysteryEncounter } from "#app/locales/en/mystery-encounter";
|
||||
import mysteryEncounterMessages from "./mystery-encounter-messages.json";
|
||||
|
||||
export const enConfig = {
|
||||
ability,
|
||||
@ -121,5 +122,6 @@ export const enConfig = {
|
||||
modifierSelectUiHandler,
|
||||
moveTriggers,
|
||||
runHistory,
|
||||
mysteryEncounter: mysteryEncounter
|
||||
mysteryEncounter: mysteryEncounter,
|
||||
mysteryEncounterMessages
|
||||
};
|
||||
|
@ -841,7 +841,7 @@
|
||||
"2": "We're pulling out all the stops to put your Pokémon down."
|
||||
},
|
||||
"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": {
|
||||
"1": "You put up quite the display.\nBetter luck next time."
|
||||
@ -857,7 +857,7 @@
|
||||
},
|
||||
"winstrates_victoria": {
|
||||
"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": {
|
||||
"1": "Uwah! Just how strong are you?!"
|
||||
@ -865,7 +865,7 @@
|
||||
},
|
||||
"winstrates_vivi": {
|
||||
"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": {
|
||||
"1": "Huh? Did I really lose?\nSnivel... Grandmaaa!"
|
||||
@ -873,7 +873,7 @@
|
||||
},
|
||||
"winstrates_vicky": {
|
||||
"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": {
|
||||
"1": "Whoa! So strong!\nMy granddaughter wasn't lying."
|
||||
@ -881,7 +881,7 @@
|
||||
},
|
||||
"winstrates_vito": {
|
||||
"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": {
|
||||
"1": "I was better than everyone in my family.\nI've never lost before..."
|
||||
|
@ -841,7 +841,7 @@
|
||||
"2": "We're pulling out all the stops to put your Pokémon down."
|
||||
},
|
||||
"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": {
|
||||
"1": "You put up quite the display.\nBetter luck next time."
|
||||
@ -857,7 +857,7 @@
|
||||
},
|
||||
"winstrates_victoria": {
|
||||
"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": {
|
||||
"1": "Uwah! Just how strong are you?!"
|
||||
@ -865,7 +865,7 @@
|
||||
},
|
||||
"winstrates_vivi": {
|
||||
"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": {
|
||||
"1": "Huh? Did I really lose?\nSnivel... Grandmaaa!"
|
||||
@ -873,7 +873,7 @@
|
||||
},
|
||||
"winstrates_vicky": {
|
||||
"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": {
|
||||
"1": "Whoa! So strong!\nMy granddaughter wasn't lying."
|
||||
@ -881,7 +881,7 @@
|
||||
},
|
||||
"winstrates_vito": {
|
||||
"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": {
|
||||
"1": "I was better than everyone in my family.\nI've never lost before..."
|
||||
|
@ -259,9 +259,10 @@
|
||||
"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_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_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": {
|
||||
"LIGHT_BALL": { "name": "Light Ball", "description": "It's a mysterious orb that boosts Pikachu's Attack and Sp. Atk stats." },
|
||||
|
6
src/locales/en/mystery-encounter-messages.json
Normal file
6
src/locales/en/mystery-encounter-messages.json
Normal 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."
|
||||
}
|
@ -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 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 bugTypeSuperfanDialogue from "#app/locales/en/mystery-encounters/bug-type-superfan-dialogue.json";
|
||||
|
||||
/**
|
||||
* Injection patterns that can be used:
|
||||
@ -44,12 +45,6 @@ export const mysteryEncounter = {
|
||||
// DO NOT REMOVE
|
||||
"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,
|
||||
mysteriousChest: mysteriousChestDialogue,
|
||||
darkDeal: darkDealDialogue,
|
||||
@ -75,5 +70,6 @@ export const mysteryEncounter = {
|
||||
dancingLessons: dancingLessonsDialogue,
|
||||
weirdDream: weirdDreamDialogue,
|
||||
theWinstrateChallenge: theWinstrateChallengeDialogue,
|
||||
teleportingHijinks: teleportingHijinksDialogue
|
||||
teleportingHijinks: teleportingHijinksDialogue,
|
||||
bugTypeSuperfan: bugTypeSuperfanDialogue
|
||||
} as const;
|
||||
|
@ -1,29 +1,29 @@
|
||||
{
|
||||
"intro": "An extremely strong trainer approaches you...",
|
||||
"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!",
|
||||
"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": {
|
||||
"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!",
|
||||
"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": {
|
||||
"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.",
|
||||
"decline": "... I see.\n $Your Pokémon look hurt...\nLet me help."
|
||||
"decline": "... I see.$Your Pokémon look hurt...\nLet me help."
|
||||
},
|
||||
"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!",
|
||||
"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": {
|
||||
"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.",
|
||||
"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",
|
||||
"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.",
|
||||
|
@ -9,17 +9,17 @@
|
||||
"tooltip": "(-) Tough Battle\n(+) Rewards from its Berry Hoard",
|
||||
"selected": "The Greedent stuffs its cheeks\nand prepares for battle!",
|
||||
"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": {
|
||||
"label": "Reason with It",
|
||||
"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": {
|
||||
"label": "Let It Have the Food",
|
||||
"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!"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"intro": "You're stopped by a rich looking 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",
|
||||
"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?",
|
||||
@ -9,7 +9,7 @@
|
||||
"1": {
|
||||
"label": "Accept the Deal",
|
||||
"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": {
|
||||
"label": "Extort the Kid",
|
||||
@ -20,7 +20,7 @@
|
||||
"3": {
|
||||
"label": "Leave",
|
||||
"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."
|
||||
}
|
||||
}
|
||||
}
|
@ -13,8 +13,8 @@
|
||||
"2": {
|
||||
"label": "Race to the Bush",
|
||||
"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_bad": "Your {{fastestPokemon}} races for the berry bush!\n $Oh no! The {{enemyPokemon}} was faster and blocked off the approach!",
|
||||
"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!$Oh no! The {{enemyPokemon}} was faster and blocked off the approach!",
|
||||
"boss_enraged": "The opposing {{enemyPokemon}} has become enraged!"
|
||||
},
|
||||
"3": {
|
||||
|
@ -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!"
|
||||
}
|
@ -13,14 +13,14 @@
|
||||
"2": {
|
||||
"label": "Learn Its 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": {
|
||||
"label": "Show It a Dance",
|
||||
"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.",
|
||||
"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"
|
||||
|
@ -3,7 +3,7 @@
|
||||
{
|
||||
"intro": "A strange man in a tattered coat\nstands in your way...",
|
||||
"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",
|
||||
"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?",
|
||||
@ -11,8 +11,8 @@
|
||||
"1": {
|
||||
"label": "Accept",
|
||||
"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_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_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.${{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": {
|
||||
"label": "Refuse",
|
||||
|
@ -10,20 +10,20 @@
|
||||
"1": {
|
||||
"label": "Give Money",
|
||||
"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": {
|
||||
"label": "Give Food",
|
||||
"tooltip": "(-) Give the Delibirds a Berry or Reviver Seed\n(+) Receive a Gift Item",
|
||||
"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": {
|
||||
"label": "Give an Item",
|
||||
"tooltip": "(-) Give the Delibirds a Held Item\n(+) Receive a Gift Item",
|
||||
"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!"
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"intro": "It's a lady with a ton of shopping bags.",
|
||||
"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",
|
||||
"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?",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"intro": "It's a teacher and some school children!",
|
||||
"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",
|
||||
"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?",
|
||||
@ -19,8 +19,8 @@
|
||||
"tooltip": "(+) Status Item Rewards"
|
||||
},
|
||||
"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.",
|
||||
"lesson_learned": "Looks like you learned a valuable lesson?\n $Your Pokémon also gained some knowledge."
|
||||
"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?$Your Pokémon also gained some knowledge."
|
||||
},
|
||||
"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!",
|
||||
|
@ -7,20 +7,20 @@
|
||||
"1": {
|
||||
"label": "Find the Source",
|
||||
"tooltip": "(?) Discover the source\n(-) Hard Battle",
|
||||
"selected": "You push through the storm, and find two Volcarona in the middle of a mating dance!\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": {
|
||||
"label": "Hunker Down",
|
||||
"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!"
|
||||
},
|
||||
"3": {
|
||||
"label": "Your Fire Types Help",
|
||||
"tooltip": "(+) End the conditions\n(+) Gain a Charcoal",
|
||||
"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!"
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
"label": "Steal the Item",
|
||||
"disabled_tooltip": "Your Pokémon need to know certain moves to choose this",
|
||||
"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": {
|
||||
"label": "Leave",
|
||||
|
@ -9,19 +9,19 @@
|
||||
"label_disabled": "Can't {{option1RequiredMove}}",
|
||||
"tooltip": "(+) {{option1PrimaryName}} saves you\n(+) {{option1PrimaryName}} gains some EXP",
|
||||
"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": {
|
||||
"label": "{{option2PrimaryName}} Might Help",
|
||||
"label_disabled": "Can't {{option2RequiredMove}}",
|
||||
"tooltip": "(+) {{option2PrimaryName}} saves you\n(+) {{option2PrimaryName}} gains some EXP",
|
||||
"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": {
|
||||
"label": "Wander Aimlessly",
|
||||
"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."
|
||||
|
@ -12,7 +12,7 @@
|
||||
"good": "Some pretty nice tools and items.",
|
||||
"great": "A couple great tools and items!",
|
||||
"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": {
|
||||
"label": "Too Risky, Leave",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"intro": "A busy worker flags you down.",
|
||||
"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",
|
||||
"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?",
|
||||
@ -24,8 +24,8 @@
|
||||
"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_bad": "Your {{selectedPokemon}} helped us out a bit!\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!$Here's your check for the day.",
|
||||
"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!"
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"intro": "A man in a dark coat approaches you.",
|
||||
"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",
|
||||
"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?",
|
||||
@ -20,10 +20,10 @@
|
||||
"tooltip": "(-) No Rewards",
|
||||
"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...",
|
||||
"bad_poison": "But the medicine had some side effects!\n $Your {{selectedPokemon}} takes some damage\nand becomes badly poisoned...",
|
||||
"poison": "But the medicine had some side effects!\n $Your {{selectedPokemon}} becomes poisoned...",
|
||||
"damage_only": "But the medicine had some side effects!$Your {{selectedPokemon}} takes some damage...",
|
||||
"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!$Your {{selectedPokemon}} becomes poisoned...",
|
||||
"no_bad_effects": "Looks like there were no side-effects this time."
|
||||
}
|
@ -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",
|
||||
"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?",
|
||||
@ -12,14 +12,14 @@
|
||||
"2": {
|
||||
"label": "Wait for It to Move",
|
||||
"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!"
|
||||
},
|
||||
"3": {
|
||||
"label": "Steal Its Item",
|
||||
"tooltip": "(+) {{option3PrimaryName}} uses {{option3PrimaryMove}}\n(+) Special Reward",
|
||||
"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!"
|
||||
}
|
||||
}
|
||||
}
|
@ -13,15 +13,15 @@
|
||||
"label": "A Pokémon Helps",
|
||||
"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",
|
||||
"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": {
|
||||
"label": "Inspect the Machine",
|
||||
"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.",
|
||||
"attacked": "You step out into a completely new area, startling a wild Pokémon!\n $The wild Pokémon attacks!",
|
||||
"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!$The wild Pokémon attacks!",
|
||||
"boss_enraged": "The opposing {{enemyPokemon}} has become enraged!"
|
||||
}
|
@ -12,12 +12,12 @@
|
||||
"tooltip": "(-) Pay {{price, money}}\n(+) Gain a {{purchasePokemon}} with its Hidden Ability",
|
||||
"tooltip_shiny": "(-) Pay {{price, money}}\n(+) Gain a shiny {{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": {
|
||||
"label": "Refuse",
|
||||
"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!"
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
"label": "Let It Touch You",
|
||||
"tooltip": "(?) Something awful or amazing might happen",
|
||||
"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": {
|
||||
"label": "Battle the Shuckle",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"intro": "It's a family standing outside their house!",
|
||||
"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",
|
||||
"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?",
|
||||
@ -17,5 +17,5 @@
|
||||
"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!"
|
||||
}
|
@ -8,19 +8,19 @@
|
||||
"1": {
|
||||
"label": "Light Training",
|
||||
"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": {
|
||||
"label": "Moderate Training",
|
||||
"tooltip": "(-) Moderate Battle\n(+) Change Pokémon's Nature",
|
||||
"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": {
|
||||
"label": "Heavy Training",
|
||||
"tooltip": "(-) Harsh Battle\n(+) Change Pokémon's Ability",
|
||||
"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..."
|
||||
},
|
||||
|
@ -7,7 +7,7 @@
|
||||
"1": {
|
||||
"label": "Dig for Valuables",
|
||||
"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": {
|
||||
"label": "Investigate Further",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"intro": "A shadowy woman blocks your path.\nSomething about her is unsettling...",
|
||||
"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": "???",
|
||||
"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?",
|
||||
@ -9,14 +9,14 @@
|
||||
"1": {
|
||||
"label": "\"I See Them\"",
|
||||
"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}",
|
||||
"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": {
|
||||
"label": "Quickly Leave",
|
||||
"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!"
|
||||
}
|
||||
}
|
||||
}
|
@ -117,15 +117,5 @@
|
||||
"plasma_grunts": "Plasma Grunts",
|
||||
"flare_grunt": "Flare Grunt",
|
||||
"flare_grunt_female": "Flare Grunt",
|
||||
"flare_grunts": "Flare Grunts",
|
||||
"buck": "Buck",
|
||||
"cheryl": "Cheryl",
|
||||
"marley": "Marley",
|
||||
"mira": "Mira",
|
||||
"riley": "Riley",
|
||||
"victor": "Victor",
|
||||
"victoria": "Victoria",
|
||||
"vivi": "Vivi",
|
||||
"vicky": "Vicky",
|
||||
"vito": "Vito"
|
||||
"flare_grunts": "Flare Grunts"
|
||||
}
|
@ -152,5 +152,16 @@
|
||||
"alder_iris_double": "Alder & Iris",
|
||||
"iris_alder_double": "Iris & Alder",
|
||||
"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"
|
||||
}
|
@ -1536,8 +1536,9 @@ export const modifierTypes = {
|
||||
}
|
||||
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_GOLDEN_BUG_NET: () => new ModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET", "golden_net", (type, _args) => new Modifiers.BoostBugSpawnModifier(type)),
|
||||
};
|
||||
|
||||
interface ModifierPool {
|
||||
|
@ -734,7 +734,8 @@ export class PokemonBaseStatTotalModifier extends PokemonHeldItemModifier {
|
||||
apply(args: any[]): boolean {
|
||||
// Modifies the passed in baseStats[] array
|
||||
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);
|
||||
});
|
||||
|
||||
@ -2366,17 +2367,41 @@ export class LockModifierTiersModifier extends PersistentModifier {
|
||||
}
|
||||
}
|
||||
|
||||
export class RemoveHealShopModifier extends PersistentModifier {
|
||||
export class HealShopCostModifier extends PersistentModifier {
|
||||
constructor(type: ModifierType, stackCount?: integer) {
|
||||
super(type, stackCount);
|
||||
}
|
||||
|
||||
match(modifier: Modifier): boolean {
|
||||
return modifier instanceof RemoveHealShopModifier;
|
||||
return modifier instanceof HealShopCostModifier;
|
||||
}
|
||||
|
||||
clone(): RemoveHealShopModifier {
|
||||
return new RemoveHealShopModifier(this.type, this.stackCount);
|
||||
clone(): HealShopCostModifier {
|
||||
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 {
|
||||
|
@ -130,7 +130,8 @@ class DefaultOverrides {
|
||||
// -------------------------
|
||||
// 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_TIER_OVERRIDE: MysteryEncounterTier | null = null;
|
||||
readonly MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType | null = null;
|
||||
|
@ -31,6 +31,8 @@ import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
import { doTrainerExclamation } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
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 {
|
||||
private loaded: boolean;
|
||||
@ -89,7 +91,11 @@ export class EncounterPhase extends BattlePhase {
|
||||
if (battle.battleType === BattleType.TRAINER) {
|
||||
battle.enemyParty[e] = battle.trainer?.genPartyMember(e)!; // TODO:: is the bang correct here?
|
||||
} 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));
|
||||
if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) {
|
||||
battle.enemyParty[e].ivs = new Array(6).fill(31);
|
||||
|
@ -22,7 +22,7 @@ export class ModifierRewardPhase extends BattlePhase {
|
||||
return new Promise<void>(resolve => {
|
||||
const newModifier = this.modifierType.newModifier();
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
@ -418,24 +418,36 @@ export class MysteryEncounterRewardsPhase extends Phase {
|
||||
});
|
||||
} else {
|
||||
this.scene.executeWithSeedOffset(() => {
|
||||
if (this.scene.currentBattle.mysteryEncounter.doEncounterExp) {
|
||||
this.scene.currentBattle.mysteryEncounter.doEncounterExp(this.scene);
|
||||
if (encounter.onRewards) {
|
||||
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) {
|
||||
this.scene.currentBattle.mysteryEncounter.doEncounterRewards(this.scene);
|
||||
doEncounterRewardsAndContinue() {
|
||||
const encounter = this.scene.currentBattle.mysteryEncounter;
|
||||
|
||||
if (encounter.doEncounterExp) {
|
||||
encounter.doEncounterExp(this.scene);
|
||||
}
|
||||
|
||||
if (encounter.doEncounterRewards) {
|
||||
encounter.doEncounterRewards(this.scene);
|
||||
} else if (this.addHealPhase) {
|
||||
this.scene.tryRemovePhase(p => p instanceof SelectModifierPhase);
|
||||
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.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will handle (in order):
|
||||
|
@ -53,7 +53,7 @@ describe("Final Boss", () => {
|
||||
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);
|
||||
|
||||
const eternatus = game.scene.getEnemyPokemon();
|
||||
|
@ -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
|
||||
* @param game
|
||||
* @param runRewardsPhase
|
||||
*/
|
||||
export async function skipBattleRunMysteryEncounterRewardsPhase(game: GameManager) {
|
||||
export async function skipBattleRunMysteryEncounterRewardsPhase(game: GameManager, runRewardsPhase: boolean = true) {
|
||||
game.scene.clearPhaseQueue();
|
||||
game.scene.clearPhaseQueueSplice();
|
||||
game.scene.getEnemyParty().forEach(p => {
|
||||
@ -161,5 +162,5 @@ export async function skipBattleRunMysteryEncounterRewardsPhase(game: GameManage
|
||||
});
|
||||
game.scene.pushPhase(new VictoryPhase(game.scene, 0));
|
||||
game.phaseInterceptor.superEndPhase();
|
||||
await game.phaseInterceptor.to(MysteryEncounterRewardsPhase, true);
|
||||
await game.phaseInterceptor.to(MysteryEncounterRewardsPhase, runRewardsPhase);
|
||||
}
|
@ -6,7 +6,7 @@ import { Species } from "#app/enums/species";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
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 { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
|
@ -4,7 +4,7 @@ import { Species } from "#app/enums/species";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
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 { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
|
@ -6,7 +6,7 @@ import { Species } from "#app/enums/species";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
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 { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { AnOfferYouCantRefuseEncounter } from "#app/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter";
|
||||
|
@ -4,7 +4,7 @@ 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, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils";
|
||||
import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
@ -8,7 +8,7 @@ import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import * as BattleAnims from "#app/data/battle-anims";
|
||||
import * as EncounterPhaseUtils 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 BattleScene from "#app/battle-scene";
|
||||
import Pokemon, { PokemonMove } from "#app/field/pokemon";
|
||||
@ -301,7 +301,7 @@ describe("Clowning Around - Mystery Encounter", () => {
|
||||
expect(secondItemsAfter.length).toBe(1);
|
||||
expect(secondItemsAfter[0].type.id).toBe("SOUL_DEW");
|
||||
expect(secondItemsAfter[0]?.stackCount).toBe(5);
|
||||
}, 2000000);
|
||||
});
|
||||
|
||||
it("should leave encounter without battle", async () => {
|
||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
|
@ -4,7 +4,7 @@ import { Species } from "#app/enums/species";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
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 { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
|
@ -4,7 +4,7 @@ import { Species } from "#app/enums/species";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
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 { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
@ -137,7 +137,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
|
||||
// 5 Healing Charms
|
||||
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;
|
||||
await scene.addModifier(abilityCharm, true, false, false, true);
|
||||
await scene.updateModifiers(true);
|
||||
@ -206,7 +206,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
|
||||
// Set 2 Sitrus berries on party lead
|
||||
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;
|
||||
sitrusMod.stackCount = 2;
|
||||
await scene.addModifier(sitrusMod, true, false, false, true);
|
||||
@ -227,7 +227,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
|
||||
// Set 1 Reviver Seed on party lead
|
||||
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;
|
||||
modifier.stackCount = 1;
|
||||
await scene.addModifier(modifier, true, false, false, true);
|
||||
@ -248,10 +248,10 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
|
||||
// 99 Candy Jars
|
||||
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;
|
||||
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
|
||||
const sitrusMod = sitrus.newModifier(scene.getParty()[0]) as BerryModifier;
|
||||
@ -277,12 +277,12 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
|
||||
// 5 Healing Charms
|
||||
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;
|
||||
await scene.addModifier(healingCharm, true, false, false, true);
|
||||
|
||||
// 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;
|
||||
modifier.stackCount = 1;
|
||||
await scene.addModifier(modifier, true, false, false, true);
|
||||
@ -306,7 +306,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
|
||||
// Set 1 Soul Dew on party lead
|
||||
scene.modifiers = [];
|
||||
const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW);
|
||||
const soulDew = generateModifierType(scene, modifierTypes.SOUL_DEW)!;
|
||||
const modifier = soulDew.newModifier(scene.getParty()[0]);
|
||||
await scene.addModifier(modifier, true, false, false, true);
|
||||
await scene.updateModifiers(true);
|
||||
@ -334,7 +334,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.DELIBIRDY, defaultParty);
|
||||
|
||||
// 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;
|
||||
modifier.stackCount = 1;
|
||||
await scene.addModifier(modifier, true, false, false, true);
|
||||
@ -368,7 +368,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
|
||||
// Set 2 Soul Dew on party lead
|
||||
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;
|
||||
modifier.stackCount = 2;
|
||||
await scene.addModifier(modifier, true, false, false, true);
|
||||
@ -389,7 +389,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
|
||||
// Set 1 Soul Dew on party lead
|
||||
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;
|
||||
modifier.stackCount = 1;
|
||||
await scene.addModifier(modifier, true, false, false, true);
|
||||
@ -410,12 +410,12 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
|
||||
// 5 Healing Charms
|
||||
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;
|
||||
await scene.addModifier(healingCharm, true, false, false, true);
|
||||
|
||||
// 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;
|
||||
modifier.stackCount = 1;
|
||||
await scene.addModifier(modifier, true, false, false, true);
|
||||
@ -439,7 +439,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
|
||||
// Set 1 Reviver Seed on party lead
|
||||
scene.modifiers = [];
|
||||
const revSeed = generateModifierType(scene, modifierTypes.REVIVER_SEED);
|
||||
const revSeed = generateModifierType(scene, modifierTypes.REVIVER_SEED)!;
|
||||
const modifier = revSeed.newModifier(scene.getParty()[0]);
|
||||
await scene.addModifier(modifier, true, false, false, true);
|
||||
await scene.updateModifiers(true);
|
||||
@ -468,7 +468,7 @@ describe("Delibird-y - Mystery Encounter", () => {
|
||||
|
||||
// Set 1 Soul Dew on party lead
|
||||
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;
|
||||
modifier.stackCount = 1;
|
||||
await scene.addModifier(modifier, true, false, false, true);
|
||||
|
@ -5,7 +5,7 @@ import { Species } from "#app/enums/species";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
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 { Mode } from "#app/ui/ui";
|
||||
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
||||
|
@ -9,7 +9,7 @@ import { Gender } from "#app/data/gender";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import * as BattleAnims from "#app/data/battle-anims";
|
||||
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 BattleScene from "#app/battle-scene";
|
||||
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
|
@ -4,7 +4,7 @@ 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/encounterTestUtils";
|
||||
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";
|
||||
|
@ -8,7 +8,7 @@ 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 } from "../encounterTestUtils";
|
||||
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption } from "../encounter-test-utils";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils";
|
||||
|
@ -5,7 +5,7 @@ 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, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils";
|
||||
import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
|
@ -5,7 +5,7 @@ import { Species } from "#app/enums/species";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
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 { CIVILIZATION_ENCOUNTER_BIOMES } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
|
@ -4,7 +4,7 @@ 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/encounterTestUtils";
|
||||
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
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 () => {
|
||||
game.scene.money = 0;
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty);
|
||||
scene.getParty().forEach(p => p.moveset = []);
|
||||
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||
|
||||
const encounterPhase = scene.getCurrentPhase();
|
||||
|
@ -5,7 +5,7 @@ import { Species } from "#app/enums/species";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
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 { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { HUMAN_TRANSITABLE_BIOMES } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
|
@ -7,7 +7,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import * as BattleAnims from "#app/data/battle-anims";
|
||||
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 BattleScene from "#app/battle-scene";
|
||||
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);
|
||||
});
|
||||
|
||||
expect(bstsAfter[0]).toEqual(bstsPrior[0] - 20 * 6);
|
||||
expect(bstsAfter[1]).toEqual(bstsPrior[1] + 10 * 6);
|
||||
expect(bstsAfter[2]).toEqual(bstsPrior[2] + 10 * 6);
|
||||
// HP stat changes are halved compared to other values
|
||||
expect(bstsAfter[0]).toEqual(bstsPrior[0] - 20 * 5 - 10);
|
||||
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 () => {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user