mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2024-11-27 17:26:11 +00:00
add unit tests for offer you can't refuse encounter
This commit is contained in:
parent
065ac0e779
commit
c2e5a58f59
@ -66,10 +66,12 @@ import { Species } from "#enums/species";
|
|||||||
import { UiTheme } from "#enums/ui-theme";
|
import { UiTheme } from "#enums/ui-theme";
|
||||||
import { TimedEventManager } from "#app/timed-event-manager.js";
|
import { TimedEventManager } from "#app/timed-event-manager.js";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import IMysteryEncounter, { MysteryEncounterTier, MysteryEncounterVariant } from "./data/mystery-encounters/mystery-encounter";
|
import IMysteryEncounter from "./data/mystery-encounters/mystery-encounter";
|
||||||
import { allMysteryEncounters, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "./data/mystery-encounters/mystery-encounters";
|
import { allMysteryEncounters, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "./data/mystery-encounters/mystery-encounters";
|
||||||
import { MysteryEncounterData } from "#app/data/mystery-encounters/mystery-encounter-data";
|
import { MysteryEncounterData } from "#app/data/mystery-encounters/mystery-encounter-data";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
|
||||||
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
||||||
|
|
||||||
@ -1184,7 +1186,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
this.arena.removeAllTags();
|
this.arena.removeAllTags();
|
||||||
|
|
||||||
// If last battle was mystery encounter and no battle occurred, skip return phases
|
// If last battle was mystery encounter and no battle occurred, skip return phases
|
||||||
if (lastBattle?.mysteryEncounter?.encounterVariant !== MysteryEncounterVariant.NO_BATTLE) {
|
if (lastBattle?.mysteryEncounter?.encounterMode !== MysteryEncounterMode.NO_BATTLE) {
|
||||||
playerField.forEach((_, p) => this.unshiftPhase(new ReturnPhase(this, p)));
|
playerField.forEach((_, p) => this.unshiftPhase(new ReturnPhase(this, p)));
|
||||||
|
|
||||||
for (const pokemon of this.getParty()) {
|
for (const pokemon of this.getParty()) {
|
||||||
|
@ -14,7 +14,8 @@ import { PlayerGender } from "#enums/player-gender";
|
|||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import i18next from "#app/plugins/i18n";
|
import i18next from "#app/plugins/i18n";
|
||||||
import IMysteryEncounter, { MysteryEncounterVariant } from "./data/mystery-encounters/mystery-encounter";
|
import IMysteryEncounter from "./data/mystery-encounters/mystery-encounter";
|
||||||
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
|
|
||||||
export enum BattleType {
|
export enum BattleType {
|
||||||
WILD,
|
WILD,
|
||||||
@ -205,7 +206,7 @@ export default class Battle {
|
|||||||
|
|
||||||
getBgmOverride(scene: BattleScene): string {
|
getBgmOverride(scene: BattleScene): string {
|
||||||
const battlers = this.enemyParty.slice(0, this.getBattlerCount());
|
const battlers = this.enemyParty.slice(0, this.getBattlerCount());
|
||||||
if (this.battleType === BattleType.TRAINER || this.mysteryEncounter?.encounterVariant === MysteryEncounterVariant.TRAINER_BATTLE) {
|
if (this.battleType === BattleType.TRAINER || this.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
if (!this.started && this.trainer.config.encounterBgm && this.trainer.getEncounterMessages().length) {
|
if (!this.started && this.trainer.config.encounterBgm && this.trainer.getEncounterMessages().length) {
|
||||||
return `encounter_${this.trainer.getEncounterBgm()}`;
|
return `encounter_${this.trainer.getEncounterBgm()}`;
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,15 @@ import { ModifierRewardPhase } from "#app/phases";
|
|||||||
import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { getPokemonSpecies } from "../../pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } from "../mystery-encounter";
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||||
import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, } from "../utils/encounter-phase-utils";
|
import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, } from "../utils/encounter-phase-utils";
|
||||||
import { getRandomPlayerPokemon, getRandomSpeciesByStarterTier } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { getRandomPlayerPokemon, getRandomSpeciesByStarterTier } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
|
||||||
/** i18n namespace for encounter */
|
/** i18n namespace for encounter */
|
||||||
const namespace = "mysteryEncounter:darkDeal";
|
const namespace = "mysteryEncounter:darkDeal";
|
||||||
@ -105,7 +107,7 @@ export const DarkDealEncounter: IMysteryEncounter =
|
|||||||
.withQuery(`${namespace}:query`)
|
.withQuery(`${namespace}:query`)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
buttonTooltip: `${namespace}:option:1:tooltip`,
|
buttonTooltip: `${namespace}:option:1:tooltip`,
|
||||||
|
@ -6,11 +6,11 @@ import { modifierTypes } from "#app/modifier/modifier-type";
|
|||||||
import { randSeedInt } from "#app/utils";
|
import { randSeedInt } from "#app/utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import IMysteryEncounter, {
|
import IMysteryEncounter, {
|
||||||
MysteryEncounterBuilder,
|
MysteryEncounterBuilder,
|
||||||
MysteryEncounterTier,
|
|
||||||
} from "../mystery-encounter";
|
} from "../mystery-encounter";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
|
||||||
/** i18n namespace for encounter */
|
/** i18n namespace for encounter */
|
||||||
const namespace = "mysteryEncounter:departmentStoreSale";
|
const namespace = "mysteryEncounter:departmentStoreSale";
|
||||||
|
@ -1,22 +1,15 @@
|
|||||||
import { MoveCategory } from "#app/data/move";
|
import { MoveCategory } from "#app/data/move";
|
||||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import {
|
import { generateModifierTypeOption, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
generateModifierTypeOption,
|
|
||||||
leaveEncounterWithoutBattle,
|
|
||||||
selectPokemonForOption,
|
|
||||||
setEncounterExp,
|
|
||||||
setEncounterRewards,
|
|
||||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
|
||||||
import { TempBattleStat } from "#app/data/temp-battle-stat";
|
import { TempBattleStat } from "#app/data/temp-battle-stat";
|
||||||
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import IMysteryEncounter, {
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
MysteryEncounterBuilder,
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
MysteryEncounterTier,
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
} from "../mystery-encounter";
|
|
||||||
|
|
||||||
/** i18n namespace for the encounter */
|
/** i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounter:fieldTrip";
|
const namespace = "mysteryEncounter:fieldTrip";
|
||||||
@ -62,7 +55,7 @@ export const FieldTripEncounter: IMysteryEncounter =
|
|||||||
.withQuery(`${namespace}:query`)
|
.withQuery(`${namespace}:query`)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
buttonTooltip: `${namespace}:option:1:tooltip`,
|
buttonTooltip: `${namespace}:option:1:tooltip`,
|
||||||
@ -88,7 +81,7 @@ export const FieldTripEncounter: IMysteryEncounter =
|
|||||||
encounter.options[0].dialogue.selected = [
|
encounter.options[0].dialogue.selected = [
|
||||||
{
|
{
|
||||||
text: `${namespace}:option:incorrect`,
|
text: `${namespace}:option:incorrect`,
|
||||||
speaker: `${namespace}:option:speaker`,
|
speaker: `${namespace}:speaker`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: `${namespace}:option:lesson_learned`,
|
text: `${namespace}:option:lesson_learned`,
|
||||||
@ -148,7 +141,7 @@ export const FieldTripEncounter: IMysteryEncounter =
|
|||||||
)
|
)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:2:label`,
|
buttonLabel: `${namespace}:option:2:label`,
|
||||||
buttonTooltip: `${namespace}:option:2:tooltip`,
|
buttonTooltip: `${namespace}:option:2:tooltip`,
|
||||||
@ -174,7 +167,7 @@ export const FieldTripEncounter: IMysteryEncounter =
|
|||||||
encounter.options[1].dialogue.selected = [
|
encounter.options[1].dialogue.selected = [
|
||||||
{
|
{
|
||||||
text: `${namespace}:option:incorrect`,
|
text: `${namespace}:option:incorrect`,
|
||||||
speaker: `${namespace}:option:speaker`,
|
speaker: `${namespace}:speaker`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: `${namespace}:option:lesson_learned`,
|
text: `${namespace}:option:lesson_learned`,
|
||||||
@ -240,7 +233,7 @@ export const FieldTripEncounter: IMysteryEncounter =
|
|||||||
)
|
)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:3:label`,
|
buttonLabel: `${namespace}:option:3:label`,
|
||||||
buttonTooltip: `${namespace}:option:3:tooltip`,
|
buttonTooltip: `${namespace}:option:3:tooltip`,
|
||||||
@ -266,7 +259,7 @@ export const FieldTripEncounter: IMysteryEncounter =
|
|||||||
encounter.options[2].dialogue.selected = [
|
encounter.options[2].dialogue.selected = [
|
||||||
{
|
{
|
||||||
text: `${namespace}:option:incorrect`,
|
text: `${namespace}:option:incorrect`,
|
||||||
speaker: `${namespace}:option:speaker`,
|
speaker: `${namespace}:speaker`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: `${namespace}:option:lesson_learned`,
|
text: `${namespace}:option:lesson_learned`,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, initCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, initCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { modifierTypes, } from "#app/modifier/modifier-type";
|
import { modifierTypes, } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } from "../mystery-encounter";
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import { TypeRequirement } from "../mystery-encounter-requirements";
|
import { TypeRequirement } from "../mystery-encounter-requirements";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
@ -18,6 +18,8 @@ import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
|||||||
import { StatusEffect } from "#app/data/status-effect";
|
import { StatusEffect } from "#app/data/status-effect";
|
||||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounter:fieryFallout";
|
const namespace = "mysteryEncounter:fieryFallout";
|
||||||
@ -202,7 +204,7 @@ export const FieryFalloutEncounter: IMysteryEncounter =
|
|||||||
)
|
)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_SPECIAL)
|
.withOptionMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new TypeRequirement(Type.FIRE, true, 1)) // Will set option3PrimaryName dialogue token automatically
|
.withPrimaryPokemonRequirement(new TypeRequirement(Type.FIRE, true, 1)) // Will set option3PrimaryName dialogue token automatically
|
||||||
.withSecondaryPokemonRequirement(new TypeRequirement(Type.FIRE, true, 1)) // Will set option3SecondaryName dialogue token automatically
|
.withSecondaryPokemonRequirement(new TypeRequirement(Type.FIRE, true, 1)) // Will set option3SecondaryName dialogue token automatically
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { BattleStat } from "#app/data/battle-stat";
|
import { BattleStat } from "#app/data/battle-stat";
|
||||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import {
|
import {
|
||||||
EnemyPartyConfig,
|
EnemyPartyConfig,
|
||||||
initBattleWithEnemyConfig,
|
initBattleWithEnemyConfig,
|
||||||
@ -20,14 +20,13 @@ import { StatChangePhase } from "#app/phases";
|
|||||||
import { randSeedInt } from "#app/utils";
|
import { randSeedInt } from "#app/utils";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import IMysteryEncounter, {
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
MysteryEncounterBuilder,
|
|
||||||
MysteryEncounterTier,
|
|
||||||
} from "../mystery-encounter";
|
|
||||||
import { MoveRequirement } from "../mystery-encounter-requirements";
|
import { MoveRequirement } from "../mystery-encounter-requirements";
|
||||||
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounter:fightOrFlight";
|
const namespace = "mysteryEncounter:fightOrFlight";
|
||||||
@ -132,7 +131,7 @@ export const FightOrFlightEncounter: IMysteryEncounter =
|
|||||||
)
|
)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT_OR_SPECIAL)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:2:label`,
|
buttonLabel: `${namespace}:option:2:label`,
|
||||||
|
@ -2,11 +2,13 @@ import { getPokemonSpecies } from "#app/data/pokemon-species.js";
|
|||||||
import { Moves } from "#app/enums/moves";
|
import { Moves } from "#app/enums/moves";
|
||||||
import { Species } from "#app/enums/species.js";
|
import { Species } from "#app/enums/species.js";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||||
import { leaveEncounterWithoutBattle, setEncounterExp } from "../utils/encounter-phase-utils";
|
import { leaveEncounterWithoutBattle, setEncounterExp } from "../utils/encounter-phase-utils";
|
||||||
import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
|
||||||
const OPTION_1_REQUIRED_MOVE = Moves.SURF;
|
const OPTION_1_REQUIRED_MOVE = Moves.SURF;
|
||||||
const OPTION_2_REQUIRED_MOVE = Moves.FLY;
|
const OPTION_2_REQUIRED_MOVE = Moves.FLY;
|
||||||
@ -53,7 +55,7 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
// Option 1: Use a (non fainted) pokemon that can learn Surf to guide you back/
|
// Option 1: Use a (non fainted) pokemon that can learn Surf to guide you back/
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withPokemonCanLearnMoveRequirement(OPTION_1_REQUIRED_MOVE)
|
.withPokemonCanLearnMoveRequirement(OPTION_1_REQUIRED_MOVE)
|
||||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
disabledButtonLabel: `${namespace}:option:1:label_disabled`,
|
disabledButtonLabel: `${namespace}:option:1:label_disabled`,
|
||||||
@ -72,7 +74,7 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
//Option 2: Use a (non fainted) pokemon that can learn fly to guide you back.
|
//Option 2: Use a (non fainted) pokemon that can learn fly to guide you back.
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withPokemonCanLearnMoveRequirement(OPTION_2_REQUIRED_MOVE)
|
.withPokemonCanLearnMoveRequirement(OPTION_2_REQUIRED_MOVE)
|
||||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:2:label`,
|
buttonLabel: `${namespace}:option:2:label`,
|
||||||
disabledButtonLabel: `${namespace}:option:2:label_disabled`,
|
disabledButtonLabel: `${namespace}:option:2:label_disabled`,
|
||||||
|
@ -13,12 +13,10 @@ import { ModifierTier } from "#app/modifier/modifier-tier";
|
|||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import * as Utils from "../../../utils";
|
import * as Utils from "#app/utils";
|
||||||
import IMysteryEncounter, {
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
MysteryEncounterBuilder,
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
MysteryEncounterTier,
|
|
||||||
} from "../mystery-encounter";
|
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounter:mysteriousChallengers";
|
const namespace = "mysteryEncounter:mysteriousChallengers";
|
||||||
|
@ -4,9 +4,11 @@ import { getHighestLevelPlayerPokemon, koPlayerPokemon } from "#app/data/mystery
|
|||||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
import { randSeedInt } from "#app/utils.js";
|
import { randSeedInt } from "#app/utils.js";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } from "../mystery-encounter";
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
|
||||||
/** i18n namespace for encounter */
|
/** i18n namespace for encounter */
|
||||||
const namespace = "mysteryEncounter:mysteriousChest";
|
const namespace = "mysteryEncounter:mysteriousChest";
|
||||||
@ -42,7 +44,7 @@ export const MysteriousChestEncounter: IMysteryEncounter =
|
|||||||
.withQuery(`${namespace}:query`)
|
.withQuery(`${namespace}:query`)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
buttonTooltip: `${namespace}:option:1:tooltip`,
|
buttonTooltip: `${namespace}:option:1:tooltip`,
|
||||||
|
@ -2,14 +2,16 @@ import { leaveEncounterWithoutBattle, setEncounterExp, updatePlayerMoney, } from
|
|||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } from "../mystery-encounter";
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||||
import { MoveRequirement } from "../mystery-encounter-requirements";
|
import { AbilityRequirement, CombinationPokemonRequirement, MoveRequirement } from "../mystery-encounter-requirements";
|
||||||
import { getHighestStatTotalPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { getHighestStatTotalPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { ModifierRewardPhase } from "#app/phases";
|
import { ModifierRewardPhase } from "#app/phases";
|
||||||
import { EXTORTION_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
import { EXTORTION_ABILITIES, EXTORTION_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
|
||||||
/** the i18n namespace for this encounter */
|
/** the i18n namespace for this encounter */
|
||||||
const namespace = "mysteryEncounter:offerYouCantRefuse";
|
const namespace = "mysteryEncounter:offerYouCantRefuse";
|
||||||
@ -56,22 +58,36 @@ export const OfferYouCantRefuseEncounter: IMysteryEncounter =
|
|||||||
.withDescription(`${namespace}:description`)
|
.withDescription(`${namespace}:description`)
|
||||||
.withQuery(`${namespace}:query`)
|
.withQuery(`${namespace}:query`)
|
||||||
.withOnInit((scene: BattleScene) => {
|
.withOnInit((scene: BattleScene) => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
const pokemon = getHighestStatTotalPlayerPokemon(scene, false);
|
const pokemon = getHighestStatTotalPlayerPokemon(scene, false);
|
||||||
const price = scene.getWaveMoneyAmount(10);
|
const price = scene.getWaveMoneyAmount(10);
|
||||||
|
|
||||||
scene.currentBattle.mysteryEncounter.setDialogueToken("strongestPokemon", pokemon.name);
|
encounter.setDialogueToken("strongestPokemon", pokemon.name);
|
||||||
scene.currentBattle.mysteryEncounter.setDialogueToken("price", price.toString());
|
encounter.setDialogueToken("price", price.toString());
|
||||||
|
|
||||||
// Store pokemon and price
|
// Store pokemon and price
|
||||||
scene.currentBattle.mysteryEncounter.misc = {
|
encounter.misc = {
|
||||||
pokemon: pokemon,
|
pokemon: pokemon,
|
||||||
price: price
|
price: price
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If player meets the combo OR requirements for option 2, populate the token
|
||||||
|
const opt2Req = encounter.options[1].primaryPokemonRequirements[0];
|
||||||
|
if (opt2Req.meetsRequirement(scene)) {
|
||||||
|
const abilityToken = encounter.dialogueTokens["option2PrimaryAbility"];
|
||||||
|
const moveToken = encounter.dialogueTokens["option2PrimaryMove"];
|
||||||
|
if (abilityToken) {
|
||||||
|
encounter.setDialogueToken("moveOrAbility", abilityToken);
|
||||||
|
} else if (moveToken) {
|
||||||
|
encounter.setDialogueToken("moveOrAbility", moveToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
buttonTooltip: `${namespace}:option:1:tooltip`,
|
buttonTooltip: `${namespace}:option:1:tooltip`,
|
||||||
@ -98,14 +114,18 @@ export const OfferYouCantRefuseEncounter: IMysteryEncounter =
|
|||||||
)
|
)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new MoveRequirement(EXTORTION_MOVES))
|
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
||||||
|
new MoveRequirement(EXTORTION_MOVES),
|
||||||
|
new AbilityRequirement(EXTORTION_ABILITIES))
|
||||||
|
)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:2:label`,
|
buttonLabel: `${namespace}:option:2:label`,
|
||||||
buttonTooltip: `${namespace}:option:2:tooltip`,
|
buttonTooltip: `${namespace}:option:2:tooltip`,
|
||||||
disabledButtonTooltip: `${namespace}:option:2:tooltip_disabled`,
|
disabledButtonTooltip: `${namespace}:option:2:tooltip_disabled`,
|
||||||
selected: [
|
selected: [
|
||||||
{
|
{
|
||||||
|
speaker: `${namespace}:speaker`,
|
||||||
text: `${namespace}:option:2:selected`,
|
text: `${namespace}:option:2:selected`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -129,7 +149,7 @@ export const OfferYouCantRefuseEncounter: IMysteryEncounter =
|
|||||||
selected: [
|
selected: [
|
||||||
{
|
{
|
||||||
speaker: `${namespace}:speaker`,
|
speaker: `${namespace}:speaker`,
|
||||||
text: `${namespace}:option:2:selected`,
|
text: `${namespace}:option:3:selected`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
import { leaveEncounterWithoutBattle, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import { leaveEncounterWithoutBattle, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } from "../mystery-encounter";
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import { MoneyRequirement } from "../mystery-encounter-requirements";
|
import { MoneyRequirement } from "../mystery-encounter-requirements";
|
||||||
import { catchPokemon, getRandomSpeciesByStarterTier } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { catchPokemon, getRandomSpeciesByStarterTier } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { PokeballType } from "#app/data/pokeball";
|
import { PokeballType } from "#app/data/pokeball";
|
||||||
import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
|
import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { showEncounterDialogue } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { showEncounterDialogue } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
|
||||||
/** the i18n namespace for this encounter */
|
/** the i18n namespace for this encounter */
|
||||||
const namespace = "mysteryEncounter:pokemonSalesman";
|
const namespace = "mysteryEncounter:pokemonSalesman";
|
||||||
@ -104,7 +106,7 @@ export const PokemonSalesmanEncounter: IMysteryEncounter =
|
|||||||
})
|
})
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT_OR_SPECIAL)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT_OR_SPECIAL)
|
||||||
.withHasDexProgress(true)
|
.withHasDexProgress(true)
|
||||||
.withSceneMoneyRequirement(null, MAX_POKEMON_PRICE_MULTIPLIER) // Wave scaling money multiplier of 2
|
.withSceneMoneyRequirement(null, MAX_POKEMON_PRICE_MULTIPLIER) // Wave scaling money multiplier of 2
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { initSubsequentOptionSelect, leaveEncounterWithoutBattle, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import { initSubsequentOptionSelect, leaveEncounterWithoutBattle, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, MysteryEncounterVariant } from "../mystery-encounter";
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import MysteryEncounterOption, { EncounterOptionMode, MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import MysteryEncounterOption, { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { TrainerSlot } from "#app/data/trainer-config";
|
import { TrainerSlot } from "#app/data/trainer-config";
|
||||||
import { ScanIvsPhase, SummonPhase, VictoryPhase } from "#app/phases";
|
import { ScanIvsPhase, SummonPhase, VictoryPhase } from "#app/phases";
|
||||||
import { HiddenAbilityRateBoosterModifier, IvScannerModifier } from "#app/modifier/modifier";
|
import { HiddenAbilityRateBoosterModifier, IvScannerModifier } from "#app/modifier/modifier";
|
||||||
@ -15,6 +15,9 @@ import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter
|
|||||||
import { doPlayerFlee, doPokemonFlee, getRandomSpeciesByStarterTier, trainerThrowPokeball } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { doPlayerFlee, doPokemonFlee, getRandomSpeciesByStarterTier, trainerThrowPokeball } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounter:safariZone";
|
const namespace = "mysteryEncounter:safariZone";
|
||||||
@ -50,7 +53,7 @@ export const SafariZoneEncounter: IMysteryEncounter =
|
|||||||
.withDescription(`${namespace}:description`)
|
.withDescription(`${namespace}:description`)
|
||||||
.withQuery(`${namespace}:query`)
|
.withQuery(`${namespace}:query`)
|
||||||
.withOption(new MysteryEncounterOptionBuilder()
|
.withOption(new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||||
.withSceneRequirement(new MoneyRequirement(0, 2.75)) // Cost equal to 1 Max Revive
|
.withSceneRequirement(new MoneyRequirement(0, 2.75)) // Cost equal to 1 Max Revive
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
@ -64,7 +67,7 @@ export const SafariZoneEncounter: IMysteryEncounter =
|
|||||||
.withOptionPhase(async (scene: BattleScene) => {
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
// Start safari encounter
|
// Start safari encounter
|
||||||
const encounter = scene.currentBattle.mysteryEncounter;
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
encounter.encounterVariant = MysteryEncounterVariant.CONTINUOUS_ENCOUNTER;
|
encounter.encounterMode = MysteryEncounterMode.CONTINUOUS_ENCOUNTER;
|
||||||
encounter.misc = {
|
encounter.misc = {
|
||||||
safariPokemonRemaining: 3
|
safariPokemonRemaining: 3
|
||||||
};
|
};
|
||||||
@ -116,7 +119,7 @@ export const SafariZoneEncounter: IMysteryEncounter =
|
|||||||
*/
|
*/
|
||||||
const safariZoneGameOptions: MysteryEncounterOption[] = [
|
const safariZoneGameOptions: MysteryEncounterOption[] = [
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:safari:1:label`,
|
buttonLabel: `${namespace}:safari:1:label`,
|
||||||
buttonTooltip: `${namespace}:safari:1:tooltip`,
|
buttonTooltip: `${namespace}:safari:1:tooltip`,
|
||||||
@ -150,7 +153,7 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [
|
|||||||
})
|
})
|
||||||
.build(),
|
.build(),
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:safari:2:label`,
|
buttonLabel: `${namespace}:safari:2:label`,
|
||||||
buttonTooltip: `${namespace}:safari:2:tooltip`,
|
buttonTooltip: `${namespace}:safari:2:tooltip`,
|
||||||
@ -180,7 +183,7 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [
|
|||||||
})
|
})
|
||||||
.build(),
|
.build(),
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:safari:3:label`,
|
buttonLabel: `${namespace}:safari:3:label`,
|
||||||
buttonTooltip: `${namespace}:safari:3:tooltip`,
|
buttonTooltip: `${namespace}:safari:3:tooltip`,
|
||||||
@ -209,7 +212,7 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [
|
|||||||
})
|
})
|
||||||
.build(),
|
.build(),
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:safari:4:label`,
|
buttonLabel: `${namespace}:safari:4:label`,
|
||||||
buttonTooltip: `${namespace}:safari:4:tooltip`,
|
buttonTooltip: `${namespace}:safari:4:tooltip`,
|
||||||
|
@ -5,12 +5,14 @@ import { modifierTypes } from "#app/modifier/modifier-type";
|
|||||||
import { randSeedInt } from "#app/utils";
|
import { randSeedInt } from "#app/utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } from "../mystery-encounter";
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||||
import { MoneyRequirement } from "../mystery-encounter-requirements";
|
import { MoneyRequirement } from "../mystery-encounter-requirements";
|
||||||
import { getEncounterText, queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText, queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
|
||||||
/** the i18n namespace for this encounter */
|
/** the i18n namespace for this encounter */
|
||||||
const namespace = "mysteryEncounter:shadyVitaminDealer";
|
const namespace = "mysteryEncounter:shadyVitaminDealer";
|
||||||
@ -59,7 +61,7 @@ export const ShadyVitaminDealerEncounter: IMysteryEncounter =
|
|||||||
.withQuery(`${namespace}:query`)
|
.withQuery(`${namespace}:query`)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||||
.withSceneMoneyRequirement(0, 2) // Wave scaling money multiplier of 2
|
.withSceneMoneyRequirement(0, 2) // Wave scaling money multiplier of 2
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
@ -144,7 +146,7 @@ export const ShadyVitaminDealerEncounter: IMysteryEncounter =
|
|||||||
)
|
)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||||
.withSceneMoneyRequirement(0, 5) // Wave scaling money multiplier of 5
|
.withSceneMoneyRequirement(0, 5) // Wave scaling money multiplier of 5
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:2:label`,
|
buttonLabel: `${namespace}:option:2:label`,
|
||||||
|
@ -4,8 +4,8 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
|||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import { StatusEffect } from "#app/data/status-effect";
|
import { StatusEffect } from "#app/data/status-effect";
|
||||||
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } from "../mystery-encounter";
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||||
import { MoveRequirement } from "../mystery-encounter-requirements";
|
import { MoveRequirement } from "../mystery-encounter-requirements";
|
||||||
import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, initCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, } from "../utils/encounter-phase-utils";
|
import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, initCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, } from "../utils/encounter-phase-utils";
|
||||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
@ -14,6 +14,8 @@ import { BattlerIndex } from "#app/battle";
|
|||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/field/pokemon";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { PartyHealPhase } from "#app/phases";
|
import { PartyHealPhase } from "#app/phases";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
|
||||||
/** i18n namespace for the encounter */
|
/** i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounter:slumberingSnorlax";
|
const namespace = "mysteryEncounter:slumberingSnorlax";
|
||||||
@ -121,7 +123,7 @@ export const SlumberingSnorlaxEncounter: IMysteryEncounter =
|
|||||||
)
|
)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_SPECIAL)
|
.withOptionMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES))
|
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES))
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:3:label`,
|
buttonLabel: `${namespace}:option:3:label`,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, initCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, initCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { modifierTypes, PokemonHeldItemModifierType, } from "#app/modifier/modifier-type";
|
import { modifierTypes, PokemonHeldItemModifierType, } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } from "../mystery-encounter";
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { Nature } from "#app/data/nature";
|
import { Nature } from "#app/data/nature";
|
||||||
@ -15,6 +15,7 @@ import { StatChangePhase } from "#app/phases";
|
|||||||
import { BattleStat } from "#app/data/battle-stat";
|
import { BattleStat } from "#app/data/battle-stat";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounter:theStrongStuff";
|
const namespace = "mysteryEncounter:theStrongStuff";
|
||||||
|
@ -13,10 +13,12 @@ import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
|||||||
import { randSeedShuffle } from "#app/utils";
|
import { randSeedShuffle } from "#app/utils";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } from "../mystery-encounter";
|
import IMysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||||
import { getEncounterText, queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText, queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
|
||||||
/** The i18n namespace for the encounter */
|
/** The i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounter:trainingSession";
|
const namespace = "mysteryEncounter:trainingSession";
|
||||||
@ -52,7 +54,7 @@ export const TrainingSessionEncounter: IMysteryEncounter =
|
|||||||
.withQuery(`${namespace}:query`)
|
.withQuery(`${namespace}:query`)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withHasDexProgress(true)
|
.withHasDexProgress(true)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
@ -196,7 +198,7 @@ export const TrainingSessionEncounter: IMysteryEncounter =
|
|||||||
)
|
)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withHasDexProgress(true)
|
.withHasDexProgress(true)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:2:label`,
|
buttonLabel: `${namespace}:option:2:label`,
|
||||||
@ -289,7 +291,7 @@ export const TrainingSessionEncounter: IMysteryEncounter =
|
|||||||
)
|
)
|
||||||
.withOption(
|
.withOption(
|
||||||
new MysteryEncounterOptionBuilder()
|
new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withHasDexProgress(true)
|
.withHasDexProgress(true)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option:3:label`,
|
buttonLabel: `${namespace}:option:3:label`,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encounter";
|
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT } from "#app/data/mystery-encounters/mystery-encounters";
|
import { BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT } from "#app/data/mystery-encounters/mystery-encounters";
|
||||||
import { isNullOrUndefined } from "#app/utils";
|
import { isNullOrUndefined } from "#app/utils";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
|
||||||
export class MysteryEncounterData {
|
export class MysteryEncounterData {
|
||||||
encounteredEvents: [MysteryEncounterType, MysteryEncounterTier][] = [];
|
encounteredEvents: [MysteryEncounterType, MysteryEncounterTier][] = [];
|
||||||
|
@ -1,29 +1,19 @@
|
|||||||
import { OptionTextDisplay } from "#app/data/mystery-encounters/mystery-encounter-dialogue";
|
import { OptionTextDisplay } from "#app/data/mystery-encounters/mystery-encounter-dialogue";
|
||||||
import { Moves } from "#app/enums/moves";
|
import { Moves } from "#app/enums/moves";
|
||||||
import { PlayerPokemon } from "#app/field/pokemon";
|
import { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import BattleScene from "../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import * as Utils from "../../utils";
|
import * as Utils from "#app/utils";
|
||||||
import { Type } from "../type";
|
import { Type } from "../type";
|
||||||
import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequirement, TypeRequirement } from "./mystery-encounter-requirements";
|
import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequirement, TypeRequirement } from "./mystery-encounter-requirements";
|
||||||
import { CanLearnMoveRequirement, CanLearnMoveRequirementOptions } from "./requirements/can-learn-move-requirement";
|
import { CanLearnMoveRequirement, CanLearnMoveRequirementOptions } from "./requirements/can-learn-move-requirement";
|
||||||
import { isNullOrUndefined } from "../../utils";
|
import { isNullOrUndefined } from "#app/utils";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
export enum EncounterOptionMode {
|
|
||||||
/** Default style */
|
|
||||||
DEFAULT,
|
|
||||||
/** Disabled on requirements not met, default style on requirements met */
|
|
||||||
DISABLED_OR_DEFAULT,
|
|
||||||
/** Default style on requirements not met, special style on requirements met */
|
|
||||||
DEFAULT_OR_SPECIAL,
|
|
||||||
/** Disabled on requirements not met, special style on requirements met */
|
|
||||||
DISABLED_OR_SPECIAL
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export type OptionPhaseCallback = (scene: BattleScene) => Promise<void | boolean>;
|
export type OptionPhaseCallback = (scene: BattleScene) => Promise<void | boolean>;
|
||||||
|
|
||||||
export default interface MysteryEncounterOption {
|
export default interface MysteryEncounterOption {
|
||||||
optionMode: EncounterOptionMode;
|
optionMode: MysteryEncounterOptionMode;
|
||||||
|
|
||||||
hasDexProgress?: boolean;
|
hasDexProgress?: boolean;
|
||||||
|
|
||||||
@ -114,8 +104,8 @@ export default class MysteryEncounterOption implements MysteryEncounterOption {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// this means we CAN have the same pokemon be a primary and secondary pokemon, so just choose any qualifying one randomly.
|
// Just pick the first qualifying Pokemon
|
||||||
this.primaryPokemon = qualified[Utils.randSeedInt(qualified.length, 0)];
|
this.primaryPokemon = qualified[0];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +135,7 @@ export default class MysteryEncounterOption implements MysteryEncounterOption {
|
|||||||
|
|
||||||
|
|
||||||
export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOption> {
|
export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOption> {
|
||||||
optionMode?: EncounterOptionMode;
|
optionMode?: MysteryEncounterOptionMode;
|
||||||
requirements?: EncounterSceneRequirement[] = [];
|
requirements?: EncounterSceneRequirement[] = [];
|
||||||
primaryPokemonRequirements?: EncounterPokemonRequirement[] = [];
|
primaryPokemonRequirements?: EncounterPokemonRequirement[] = [];
|
||||||
secondaryPokemonRequirements ?: EncounterPokemonRequirement[] = [];
|
secondaryPokemonRequirements ?: EncounterPokemonRequirement[] = [];
|
||||||
@ -156,7 +146,7 @@ export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOp
|
|||||||
onPostOptionPhase?: OptionPhaseCallback;
|
onPostOptionPhase?: OptionPhaseCallback;
|
||||||
dialogue?: OptionTextDisplay;
|
dialogue?: OptionTextDisplay;
|
||||||
|
|
||||||
withOptionMode(optionMode: EncounterOptionMode): this & Pick<MysteryEncounterOption, "optionMode"> {
|
withOptionMode(optionMode: MysteryEncounterOptionMode): this & Pick<MysteryEncounterOption, "optionMode"> {
|
||||||
return Object.assign(this, { optionMode });
|
return Object.assign(this, { optionMode });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,6 +155,10 @@ export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
withSceneRequirement(requirement: EncounterSceneRequirement): this & Required<Pick<MysteryEncounterOption, "requirements">> {
|
withSceneRequirement(requirement: EncounterSceneRequirement): this & Required<Pick<MysteryEncounterOption, "requirements">> {
|
||||||
|
if (requirement instanceof EncounterPokemonRequirement) {
|
||||||
|
Error("Incorrectly added pokemon requirement as scene requirement.");
|
||||||
|
}
|
||||||
|
|
||||||
this.requirements.push(requirement);
|
this.requirements.push(requirement);
|
||||||
return Object.assign(this, { requirements: this.requirements });
|
return Object.assign(this, { requirements: this.requirements });
|
||||||
}
|
}
|
||||||
@ -190,6 +184,10 @@ export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
withPrimaryPokemonRequirement(requirement: EncounterPokemonRequirement): this & Required<Pick<MysteryEncounterOption, "primaryPokemonRequirements">> {
|
withPrimaryPokemonRequirement(requirement: EncounterPokemonRequirement): this & Required<Pick<MysteryEncounterOption, "primaryPokemonRequirements">> {
|
||||||
|
if (requirement instanceof EncounterSceneRequirement) {
|
||||||
|
Error("Incorrectly added scene requirement as pokemon requirement.");
|
||||||
|
}
|
||||||
|
|
||||||
this.primaryPokemonRequirements.push(requirement);
|
this.primaryPokemonRequirements.push(requirement);
|
||||||
return Object.assign(this, { primaryPokemonRequirements: this.primaryPokemonRequirements });
|
return Object.assign(this, { primaryPokemonRequirements: this.primaryPokemonRequirements });
|
||||||
}
|
}
|
||||||
@ -218,7 +216,11 @@ export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOp
|
|||||||
return this.withPrimaryPokemonRequirement(new CanLearnMoveRequirement(move, options));
|
return this.withPrimaryPokemonRequirement(new CanLearnMoveRequirement(move, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
withSecondaryPokemonRequirement(requirement: EncounterPokemonRequirement, excludePrimaryFromSecondaryRequirements?: boolean): this & Required<Pick<MysteryEncounterOption, "secondaryPokemonRequirements">> {
|
withSecondaryPokemonRequirement(requirement: EncounterPokemonRequirement, excludePrimaryFromSecondaryRequirements: boolean = true): this & Required<Pick<MysteryEncounterOption, "secondaryPokemonRequirements">> {
|
||||||
|
if (requirement instanceof EncounterSceneRequirement) {
|
||||||
|
Error("Incorrectly added scene requirement as pokemon requirement.");
|
||||||
|
}
|
||||||
|
|
||||||
this.secondaryPokemonRequirements.push(requirement);
|
this.secondaryPokemonRequirements.push(requirement);
|
||||||
this.excludePrimaryFromSecondaryRequirements = excludePrimaryFromSecondaryRequirements;
|
this.excludePrimaryFromSecondaryRequirements = excludePrimaryFromSecondaryRequirements;
|
||||||
return Object.assign(this, { secondaryPokemonRequirements: this.secondaryPokemonRequirements });
|
return Object.assign(this, { secondaryPokemonRequirements: this.secondaryPokemonRequirements });
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { PlayerPokemon } from "#app/field/pokemon";
|
import { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { ModifierType, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
import { ModifierType, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||||
import BattleScene from "../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import { isNullOrUndefined } from "#app/utils";
|
import { isNullOrUndefined } from "#app/utils";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { Abilities } from "#enums/abilities";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
@ -21,12 +21,35 @@ export interface EncounterRequirement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export abstract class EncounterSceneRequirement implements EncounterRequirement {
|
export abstract class EncounterSceneRequirement implements EncounterRequirement {
|
||||||
|
abstract meetsRequirement(scene: BattleScene): boolean;
|
||||||
|
abstract getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CombinationSceneRequirement extends EncounterSceneRequirement {
|
||||||
|
orRequirements: EncounterSceneRequirement[];
|
||||||
|
|
||||||
|
constructor(... orRequirements: EncounterSceneRequirement[]) {
|
||||||
|
super();
|
||||||
|
this.orRequirements = orRequirements;
|
||||||
|
}
|
||||||
|
|
||||||
meetsRequirement(scene: BattleScene): boolean {
|
meetsRequirement(scene: BattleScene): boolean {
|
||||||
throw new Error("Method not implemented.");
|
for (const req of this.orRequirements) {
|
||||||
|
if (req.meetsRequirement(scene)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||||
return ["", ""];
|
for (const req of this.orRequirements) {
|
||||||
|
if (req.meetsRequirement(scene)) {
|
||||||
|
return req.getDialogueToken(scene, pokemon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,12 +63,49 @@ export abstract class EncounterPokemonRequirement implements EncounterRequiremen
|
|||||||
* Returns all party members that are compatible with this requirement. For non pokemon related requirements, the entire party is returned.
|
* Returns all party members that are compatible with this requirement. For non pokemon related requirements, the entire party is returned.
|
||||||
* @param partyPokemon
|
* @param partyPokemon
|
||||||
*/
|
*/
|
||||||
|
abstract queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[];
|
||||||
|
|
||||||
|
abstract getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CombinationPokemonRequirement extends EncounterPokemonRequirement {
|
||||||
|
orRequirements: EncounterPokemonRequirement[];
|
||||||
|
|
||||||
|
constructor(...orRequirements: EncounterPokemonRequirement[]) {
|
||||||
|
super();
|
||||||
|
this.invertQuery = false;
|
||||||
|
this.minNumberOfPokemon = 1;
|
||||||
|
this.orRequirements = orRequirements;
|
||||||
|
}
|
||||||
|
|
||||||
|
meetsRequirement(scene: BattleScene): boolean {
|
||||||
|
for (const req of this.orRequirements) {
|
||||||
|
if (req.meetsRequirement(scene)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||||
|
for (const req of this.orRequirements) {
|
||||||
|
const result = req.queryParty(partyPokemon);
|
||||||
|
if (result?.length > 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||||
return ["", ""];
|
for (const req of this.orRequirements) {
|
||||||
|
if (req.meetsRequirement(scene)) {
|
||||||
|
return req.getDialogueToken(scene, pokemon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +116,7 @@ export class PreviousEncounterRequirement extends EncounterSceneRequirement {
|
|||||||
* Used for specifying an encounter that must be seen before this encounter can spawn
|
* Used for specifying an encounter that must be seen before this encounter can spawn
|
||||||
* @param previousEncounterRequirement
|
* @param previousEncounterRequirement
|
||||||
*/
|
*/
|
||||||
constructor(previousEncounterRequirement) {
|
constructor(previousEncounterRequirement: MysteryEncounterType) {
|
||||||
super();
|
super();
|
||||||
this.previousEncounterRequirement = previousEncounterRequirement;
|
this.previousEncounterRequirement = previousEncounterRequirement;
|
||||||
}
|
}
|
||||||
@ -497,19 +557,16 @@ export class AbilityRequirement extends EncounterPokemonRequirement {
|
|||||||
|
|
||||||
queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||||
if (!this.invertQuery) {
|
if (!this.invertQuery) {
|
||||||
return partyPokemon.filter((pokemon) => this.requiredAbilities.filter((abilities) => pokemon.hasAbility(abilities)).length > 0);
|
return partyPokemon.filter((pokemon) => this.requiredAbilities.some((ability) => pokemon.getAbility().id === ability));
|
||||||
} else {
|
} else {
|
||||||
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed abilitiess
|
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed abilitiess
|
||||||
return partyPokemon.filter((pokemon) => this.requiredAbilities.filter((abilities) => pokemon.hasAbility(abilities)).length === 0);
|
return partyPokemon.filter((pokemon) => this.requiredAbilities.filter((ability) => pokemon.getAbility().id === ability).length === 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||||
const reqAbilities = this.requiredAbilities.filter((a) => {
|
if (this.requiredAbilities.some(a => pokemon.getAbility().id === a)) {
|
||||||
pokemon.hasAbility(a);
|
return ["ability", pokemon.getAbility().name];
|
||||||
});
|
|
||||||
if (reqAbilities.length > 0) {
|
|
||||||
return ["ability", Abilities[reqAbilities[0]]];
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,14 @@ import { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-p
|
|||||||
import Pokemon, { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
import Pokemon, { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||||
import { isNullOrUndefined } from "#app/utils";
|
import { isNullOrUndefined } from "#app/utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounterIntroVisuals, { MysteryEncounterSpriteConfig } from "../../field/mystery-encounter-intro";
|
import MysteryEncounterIntroVisuals, { MysteryEncounterSpriteConfig } from "#app/field/mystery-encounter-intro";
|
||||||
import * as Utils from "../../utils";
|
import * as Utils from "#app/utils";
|
||||||
import { StatusEffect } from "../status-effect";
|
import { StatusEffect } from "../status-effect";
|
||||||
import MysteryEncounterDialogue, {
|
import MysteryEncounterDialogue, {
|
||||||
OptionTextDisplay
|
OptionTextDisplay
|
||||||
} from "./mystery-encounter-dialogue";
|
} from "./mystery-encounter-dialogue";
|
||||||
import MysteryEncounterOption, { EncounterOptionMode, MysteryEncounterOptionBuilder, OptionPhaseCallback } from "./mystery-encounter-option";
|
import MysteryEncounterOption, { MysteryEncounterOptionBuilder, OptionPhaseCallback } from "./mystery-encounter-option";
|
||||||
import {
|
import {
|
||||||
EncounterPokemonRequirement,
|
EncounterPokemonRequirement,
|
||||||
EncounterSceneRequirement,
|
EncounterSceneRequirement,
|
||||||
@ -20,27 +20,9 @@ import {
|
|||||||
} from "./mystery-encounter-requirements";
|
} from "./mystery-encounter-requirements";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#app/battle";
|
||||||
import { EncounterAnim } from "#app/data/battle-anims";
|
import { EncounterAnim } from "#app/data/battle-anims";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
export enum MysteryEncounterVariant {
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
DEFAULT,
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
TRAINER_BATTLE,
|
|
||||||
WILD_BATTLE,
|
|
||||||
BOSS_BATTLE,
|
|
||||||
NO_BATTLE,
|
|
||||||
/** For spawning new encounter queries instead of continuing to next wave */
|
|
||||||
CONTINUOUS_ENCOUNTER
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enum values are base spawn weights of each tier
|
|
||||||
*/
|
|
||||||
export enum MysteryEncounterTier {
|
|
||||||
COMMON = 64,
|
|
||||||
GREAT = 40,
|
|
||||||
ULTRA = 21,
|
|
||||||
ROGUE = 3,
|
|
||||||
MASTER = 0 // Not currently used
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface StartOfBattleEffect {
|
export interface StartOfBattleEffect {
|
||||||
sourcePokemon?: Pokemon;
|
sourcePokemon?: Pokemon;
|
||||||
@ -130,7 +112,7 @@ export default interface IMysteryEncounter {
|
|||||||
* For example, if there is no battle as part of the encounter/selected option, should be set to NO_BATTLE
|
* For example, if there is no battle as part of the encounter/selected option, should be set to NO_BATTLE
|
||||||
* Defaults to DEFAULT
|
* Defaults to DEFAULT
|
||||||
*/
|
*/
|
||||||
encounterVariant?: MysteryEncounterVariant;
|
encounterMode?: MysteryEncounterMode;
|
||||||
/**
|
/**
|
||||||
* Flag for checking if it's the first time a shop is being shown for an encounter.
|
* Flag for checking if it's the first time a shop is being shown for an encounter.
|
||||||
* Defaults to true so that the first shop does not override the specified rewards.
|
* Defaults to true so that the first shop does not override the specified rewards.
|
||||||
@ -181,7 +163,7 @@ export default class IMysteryEncounter implements IMysteryEncounter {
|
|||||||
this.dialogue = this.dialogue ?? {};
|
this.dialogue = this.dialogue ?? {};
|
||||||
// Default max is 1 for ROGUE encounters, 3 for others
|
// Default max is 1 for ROGUE encounters, 3 for others
|
||||||
this.maxAllowedEncounters = this.maxAllowedEncounters ?? this.encounterTier === MysteryEncounterTier.ROGUE ? 1 : 3;
|
this.maxAllowedEncounters = this.maxAllowedEncounters ?? this.encounterTier === MysteryEncounterTier.ROGUE ? 1 : 3;
|
||||||
this.encounterVariant = MysteryEncounterVariant.DEFAULT;
|
this.encounterMode = MysteryEncounterMode.DEFAULT;
|
||||||
this.requirements = this.requirements ? this.requirements : [];
|
this.requirements = this.requirements ? this.requirements : [];
|
||||||
this.hideBattleIntroMessage = !isNullOrUndefined(this.hideBattleIntroMessage) ? this.hideBattleIntroMessage : false;
|
this.hideBattleIntroMessage = !isNullOrUndefined(this.hideBattleIntroMessage) ? this.hideBattleIntroMessage : false;
|
||||||
this.autoHideIntroVisuals = !isNullOrUndefined(this.autoHideIntroVisuals) ? this.autoHideIntroVisuals : true;
|
this.autoHideIntroVisuals = !isNullOrUndefined(this.autoHideIntroVisuals) ? this.autoHideIntroVisuals : true;
|
||||||
@ -314,7 +296,9 @@ export default class IMysteryEncounter implements IMysteryEncounter {
|
|||||||
if (this.requirements?.length > 0) {
|
if (this.requirements?.length > 0) {
|
||||||
for (const req of this.requirements) {
|
for (const req of this.requirements) {
|
||||||
const dialogueToken = req.getDialogueToken(scene);
|
const dialogueToken = req.getDialogueToken(scene);
|
||||||
this.setDialogueToken(...dialogueToken);
|
if (dialogueToken?.length === 2) {
|
||||||
|
this.setDialogueToken(...dialogueToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.primaryPokemon?.length > 0) {
|
if (this.primaryPokemon?.length > 0) {
|
||||||
@ -322,7 +306,9 @@ export default class IMysteryEncounter implements IMysteryEncounter {
|
|||||||
for (const req of this.primaryPokemonRequirements) {
|
for (const req of this.primaryPokemonRequirements) {
|
||||||
if (!req.invertQuery) {
|
if (!req.invertQuery) {
|
||||||
const value = req.getDialogueToken(scene, this.primaryPokemon);
|
const value = req.getDialogueToken(scene, this.primaryPokemon);
|
||||||
this.setDialogueToken("primary" + this.capitalizeFirstLetter(value[0]), value[1]);
|
if (value?.length === 2) {
|
||||||
|
this.setDialogueToken("primary" + this.capitalizeFirstLetter(value[0]), value[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,6 +317,9 @@ export default class IMysteryEncounter implements IMysteryEncounter {
|
|||||||
for (const req of this.secondaryPokemonRequirements) {
|
for (const req of this.secondaryPokemonRequirements) {
|
||||||
if (!req.invertQuery) {
|
if (!req.invertQuery) {
|
||||||
const value = req.getDialogueToken(scene, this.secondaryPokemon[0]);
|
const value = req.getDialogueToken(scene, this.secondaryPokemon[0]);
|
||||||
|
if (value?.length === 2) {
|
||||||
|
this.setDialogueToken("primary" + this.capitalizeFirstLetter(value[0]), value[1]);
|
||||||
|
}
|
||||||
this.setDialogueToken("secondary" + this.capitalizeFirstLetter(value[0]), value[1]);
|
this.setDialogueToken("secondary" + this.capitalizeFirstLetter(value[0]), value[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -344,7 +333,9 @@ export default class IMysteryEncounter implements IMysteryEncounter {
|
|||||||
if (opt.requirements?.length > 0) {
|
if (opt.requirements?.length > 0) {
|
||||||
for (const req of opt.requirements) {
|
for (const req of opt.requirements) {
|
||||||
const dialogueToken = req.getDialogueToken(scene);
|
const dialogueToken = req.getDialogueToken(scene);
|
||||||
this.setDialogueToken("option" + j + this.capitalizeFirstLetter(dialogueToken[0]), dialogueToken[1]);
|
if (dialogueToken?.length === 2) {
|
||||||
|
this.setDialogueToken("option" + j + this.capitalizeFirstLetter(dialogueToken[0]), dialogueToken[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (opt.primaryPokemonRequirements?.length > 0 && opt.primaryPokemon?.length > 0) {
|
if (opt.primaryPokemonRequirements?.length > 0 && opt.primaryPokemon?.length > 0) {
|
||||||
@ -352,7 +343,9 @@ export default class IMysteryEncounter implements IMysteryEncounter {
|
|||||||
for (const req of opt.primaryPokemonRequirements) {
|
for (const req of opt.primaryPokemonRequirements) {
|
||||||
if (!req.invertQuery) {
|
if (!req.invertQuery) {
|
||||||
const value = req.getDialogueToken(scene, opt.primaryPokemon);
|
const value = req.getDialogueToken(scene, opt.primaryPokemon);
|
||||||
this.setDialogueToken("option" + j + "Primary" + this.capitalizeFirstLetter(value[0]), value[1]);
|
if (value?.length === 2) {
|
||||||
|
this.setDialogueToken("option" + j + "Primary" + this.capitalizeFirstLetter(value[0]), value[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,7 +354,9 @@ export default class IMysteryEncounter implements IMysteryEncounter {
|
|||||||
for (const req of opt.secondaryPokemonRequirements) {
|
for (const req of opt.secondaryPokemonRequirements) {
|
||||||
if (!req.invertQuery) {
|
if (!req.invertQuery) {
|
||||||
const value = req.getDialogueToken(scene, opt.secondaryPokemon[0]);
|
const value = req.getDialogueToken(scene, opt.secondaryPokemon[0]);
|
||||||
this.setDialogueToken("option" + j + "Secondary" + this.capitalizeFirstLetter(value[0]), value[1]);
|
if (value?.length === 2) {
|
||||||
|
this.setDialogueToken("option" + j + "Secondary" + this.capitalizeFirstLetter(value[0]), value[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -373,7 +368,7 @@ export default class IMysteryEncounter implements IMysteryEncounter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If an encounter uses {@link MysteryEncounterVariant.CONTINUOUS_ENCOUNTER},
|
* If an encounter uses {@link MysteryEncounterMode.CONTINUOUS_ENCOUNTER},
|
||||||
* should rely on this value for seed offset instead of wave index.
|
* should rely on this value for seed offset instead of wave index.
|
||||||
*
|
*
|
||||||
* This offset is incremented for each new {@link MysteryEncounterPhase} that occurs,
|
* This offset is incremented for each new {@link MysteryEncounterPhase} that occurs,
|
||||||
@ -466,7 +461,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withSimpleOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback): this & Pick<IMysteryEncounter, "options"> {
|
withSimpleOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback): this & Pick<IMysteryEncounter, "options"> {
|
||||||
return this.withOption(new MysteryEncounterOptionBuilder().withOptionMode(EncounterOptionMode.DEFAULT).withDialogue(dialogue).withOptionPhase(callback).build());
|
return this.withOption(new MysteryEncounterOptionBuilder().withOptionMode(MysteryEncounterOptionMode.DEFAULT).withDialogue(dialogue).withOptionPhase(callback).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -481,7 +476,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
*/
|
*/
|
||||||
withSimpleDexProgressOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback): this & Pick<IMysteryEncounter, "options"> {
|
withSimpleDexProgressOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback): this & Pick<IMysteryEncounter, "options"> {
|
||||||
return this.withOption(new MysteryEncounterOptionBuilder()
|
return this.withOption(new MysteryEncounterOptionBuilder()
|
||||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
.withOptionMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
.withHasDexProgress(true)
|
.withHasDexProgress(true)
|
||||||
.withDialogue(dialogue)
|
.withDialogue(dialogue)
|
||||||
.withOptionPhase(callback).build());
|
.withOptionPhase(callback).build());
|
||||||
@ -592,6 +587,10 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withPrimaryPokemonRequirement(requirement: EncounterPokemonRequirement): this & Required<Pick<IMysteryEncounter, "primaryPokemonRequirements">> {
|
withPrimaryPokemonRequirement(requirement: EncounterPokemonRequirement): this & Required<Pick<IMysteryEncounter, "primaryPokemonRequirements">> {
|
||||||
|
if (requirement instanceof EncounterSceneRequirement) {
|
||||||
|
Error("Incorrectly added scene requirement as pokemon requirement.");
|
||||||
|
}
|
||||||
|
|
||||||
this.primaryPokemonRequirements.push(requirement);
|
this.primaryPokemonRequirements.push(requirement);
|
||||||
return Object.assign(this, { primaryPokemonRequirements: this.primaryPokemonRequirements });
|
return Object.assign(this, { primaryPokemonRequirements: this.primaryPokemonRequirements });
|
||||||
}
|
}
|
||||||
@ -624,6 +623,10 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
// ex. if your only grass type pokemon, a snivy, is chosen as primary, if the support pokemon requires a grass type, the event won't trigger because
|
// ex. if your only grass type pokemon, a snivy, is chosen as primary, if the support pokemon requires a grass type, the event won't trigger because
|
||||||
// it's already been
|
// it's already been
|
||||||
withSecondaryPokemonRequirement(requirement: EncounterPokemonRequirement, excludePrimaryFromSecondaryRequirements: boolean = false): this & Required<Pick<IMysteryEncounter, "secondaryPokemonRequirements">> {
|
withSecondaryPokemonRequirement(requirement: EncounterPokemonRequirement, excludePrimaryFromSecondaryRequirements: boolean = false): this & Required<Pick<IMysteryEncounter, "secondaryPokemonRequirements">> {
|
||||||
|
if (requirement instanceof EncounterSceneRequirement) {
|
||||||
|
Error("Incorrectly added scene requirement as pokemon requirement.");
|
||||||
|
}
|
||||||
|
|
||||||
this.secondaryPokemonRequirements.push(requirement);
|
this.secondaryPokemonRequirements.push(requirement);
|
||||||
this.excludePrimaryFromSupportRequirements = excludePrimaryFromSecondaryRequirements;
|
this.excludePrimaryFromSupportRequirements = excludePrimaryFromSecondaryRequirements;
|
||||||
return Object.assign(this, { excludePrimaryFromSecondaryRequirements: this.excludePrimaryFromSupportRequirements, secondaryPokemonRequirements: this.secondaryPokemonRequirements });
|
return Object.assign(this, { excludePrimaryFromSecondaryRequirements: this.excludePrimaryFromSupportRequirements, secondaryPokemonRequirements: this.secondaryPokemonRequirements });
|
||||||
|
@ -61,7 +61,7 @@ export const EXTORTION_MOVES = [
|
|||||||
Moves.BEAT_UP,
|
Moves.BEAT_UP,
|
||||||
Moves.COIL,
|
Moves.COIL,
|
||||||
Moves.WRING_OUT,
|
Moves.WRING_OUT,
|
||||||
Moves.STRING_SHOT
|
Moves.STRING_SHOT,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const EXTORTION_ABILITIES = [
|
export const EXTORTION_ABILITIES = [
|
||||||
@ -69,5 +69,5 @@ export const EXTORTION_ABILITIES = [
|
|||||||
Abilities.ARENA_TRAP,
|
Abilities.ARENA_TRAP,
|
||||||
Abilities.SHADOW_TAG,
|
Abilities.SHADOW_TAG,
|
||||||
Abilities.SUCTION_CUPS,
|
Abilities.SUCTION_CUPS,
|
||||||
Abilities.STICKY_HOLD,
|
Abilities.STICKY_HOLD
|
||||||
];
|
];
|
||||||
|
@ -18,17 +18,17 @@ import { BattlerTagType } from "#enums/battler-tag-type";
|
|||||||
import { Biome } from "#enums/biome";
|
import { Biome } from "#enums/biome";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import Trainer, { TrainerVariant } from "../../../field/trainer";
|
import Trainer, { TrainerVariant } from "#app/field/trainer";
|
||||||
import * as Utils from "../../../utils";
|
import * as Utils from "#app/utils";
|
||||||
import PokemonSpecies from "../../pokemon-species";
|
|
||||||
import { Status, StatusEffect } from "../../status-effect";
|
|
||||||
import { TrainerConfig, trainerConfigs, TrainerSlot } from "../../trainer-config";
|
|
||||||
import { MysteryEncounterVariant } from "../mystery-encounter";
|
|
||||||
import { Gender } from "#app/data/gender";
|
import { Gender } from "#app/data/gender";
|
||||||
import { Nature } from "#app/data/nature";
|
import { Nature } from "#app/data/nature";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims";
|
import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims";
|
||||||
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
|
import { Status, StatusEffect } from "#app/data/status-effect";
|
||||||
|
import { TrainerConfig, trainerConfigs, TrainerSlot } from "#app/data/trainer-config";
|
||||||
|
import PokemonSpecies from "#app/data/pokemon-species";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Animates exclamation sprite over trainer's head at start of encounter
|
* Animates exclamation sprite over trainer's head at start of encounter
|
||||||
@ -107,7 +107,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||||||
const trainerType = partyConfig?.trainerType;
|
const trainerType = partyConfig?.trainerType;
|
||||||
let trainerConfig = partyConfig?.trainerConfig;
|
let trainerConfig = partyConfig?.trainerConfig;
|
||||||
if (trainerType || trainerConfig) {
|
if (trainerType || trainerConfig) {
|
||||||
scene.currentBattle.mysteryEncounter.encounterVariant = MysteryEncounterVariant.TRAINER_BATTLE;
|
scene.currentBattle.mysteryEncounter.encounterMode = MysteryEncounterMode.TRAINER_BATTLE;
|
||||||
if (scene.currentBattle.trainer) {
|
if (scene.currentBattle.trainer) {
|
||||||
scene.currentBattle.trainer.setVisible(false);
|
scene.currentBattle.trainer.setVisible(false);
|
||||||
scene.currentBattle.trainer.destroy();
|
scene.currentBattle.trainer.destroy();
|
||||||
@ -128,7 +128,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||||||
battle.enemyLevels = scene.currentBattle.trainer.getPartyLevels(scene.currentBattle.waveIndex);
|
battle.enemyLevels = scene.currentBattle.trainer.getPartyLevels(scene.currentBattle.waveIndex);
|
||||||
} else {
|
} else {
|
||||||
// Wild
|
// Wild
|
||||||
scene.currentBattle.mysteryEncounter.encounterVariant = MysteryEncounterVariant.WILD_BATTLE;
|
scene.currentBattle.mysteryEncounter.encounterMode = MysteryEncounterMode.WILD_BATTLE;
|
||||||
battle.enemyLevels = new Array(partyConfig?.pokemonConfigs?.length > 0 ? partyConfig?.pokemonConfigs?.length : doubleBattle ? 2 : 1).fill(null).map(() => scene.currentBattle.getLevelForWave());
|
battle.enemyLevels = new Array(partyConfig?.pokemonConfigs?.length > 0 ? partyConfig?.pokemonConfigs?.length : doubleBattle ? 2 : 1).fill(null).map(() => scene.currentBattle.getLevelForWave());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||||||
enemySpecies = config.species;
|
enemySpecies = config.species;
|
||||||
isBoss = config.isBoss;
|
isBoss = config.isBoss;
|
||||||
if (isBoss) {
|
if (isBoss) {
|
||||||
scene.currentBattle.mysteryEncounter.encounterVariant = MysteryEncounterVariant.BOSS_BATTLE;
|
scene.currentBattle.mysteryEncounter.encounterMode = MysteryEncounterMode.BOSS_BATTLE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
enemySpecies = scene.randomSpecies(battle.waveIndex, level, true);
|
enemySpecies = scene.randomSpecies(battle.waveIndex, level, true);
|
||||||
@ -508,7 +508,7 @@ export function setEncounterExp(scene: BattleScene, participantId: integer | int
|
|||||||
let expValue = Math.floor(baseExpValue * (useWaveIndex ? scene.currentBattle.waveIndex : 1) / 5 + 1);
|
let expValue = Math.floor(baseExpValue * (useWaveIndex ? scene.currentBattle.waveIndex : 1) / 5 + 1);
|
||||||
|
|
||||||
if (participantIds?.length > 0) {
|
if (participantIds?.length > 0) {
|
||||||
if (scene.currentBattle.mysteryEncounter.encounterVariant === MysteryEncounterVariant.TRAINER_BATTLE) {
|
if (scene.currentBattle.mysteryEncounter.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
expValue = Math.floor(expValue * 1.5);
|
expValue = Math.floor(expValue * 1.5);
|
||||||
}
|
}
|
||||||
for (const partyMember of nonFaintedPartyMembers) {
|
for (const partyMember of nonFaintedPartyMembers) {
|
||||||
@ -609,7 +609,7 @@ export function initSubsequentOptionSelect(scene: BattleScene, optionSelectSetti
|
|||||||
* @param addHealPhase - when true, will add a shop phase to end of encounter with 0 rewards but healing items are available
|
* @param addHealPhase - when true, will add a shop phase to end of encounter with 0 rewards but healing items are available
|
||||||
*/
|
*/
|
||||||
export function leaveEncounterWithoutBattle(scene: BattleScene, addHealPhase: boolean = false) {
|
export function leaveEncounterWithoutBattle(scene: BattleScene, addHealPhase: boolean = false) {
|
||||||
scene.currentBattle.mysteryEncounter.encounterVariant = MysteryEncounterVariant.NO_BATTLE;
|
scene.currentBattle.mysteryEncounter.encounterMode = MysteryEncounterMode.NO_BATTLE;
|
||||||
scene.clearPhaseQueue();
|
scene.clearPhaseQueue();
|
||||||
scene.clearPhaseQueueSplice();
|
scene.clearPhaseQueueSplice();
|
||||||
handleMysteryEncounterVictory(scene, addHealPhase);
|
handleMysteryEncounterVictory(scene, addHealPhase);
|
||||||
@ -626,14 +626,14 @@ export function handleMysteryEncounterVictory(scene: BattleScene, addHealPhase:
|
|||||||
|
|
||||||
// If in repeated encounter variant, do nothing
|
// If in repeated encounter variant, do nothing
|
||||||
// Variant must eventually be swapped in order to handle "true" end of the encounter
|
// Variant must eventually be swapped in order to handle "true" end of the encounter
|
||||||
if (scene.currentBattle.mysteryEncounter.encounterVariant === MysteryEncounterVariant.CONTINUOUS_ENCOUNTER) {
|
if (scene.currentBattle.mysteryEncounter.encounterMode === MysteryEncounterMode.CONTINUOUS_ENCOUNTER) {
|
||||||
return;
|
return;
|
||||||
} else if (scene.currentBattle.mysteryEncounter.encounterVariant === MysteryEncounterVariant.NO_BATTLE) {
|
} else if (scene.currentBattle.mysteryEncounter.encounterMode === MysteryEncounterMode.NO_BATTLE) {
|
||||||
scene.pushPhase(new EggLapsePhase(scene));
|
scene.pushPhase(new EggLapsePhase(scene));
|
||||||
scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase));
|
scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase));
|
||||||
} else if (!scene.getEnemyParty().find(p => scene.currentBattle.mysteryEncounter.encounterVariant !== MysteryEncounterVariant.TRAINER_BATTLE ? p.isOnField() : !p?.isFainted(true))) {
|
} else if (!scene.getEnemyParty().find(p => scene.currentBattle.mysteryEncounter.encounterMode !== MysteryEncounterMode.TRAINER_BATTLE ? p.isOnField() : !p?.isFainted(true))) {
|
||||||
scene.pushPhase(new BattleEndPhase(scene));
|
scene.pushPhase(new BattleEndPhase(scene));
|
||||||
if (scene.currentBattle.mysteryEncounter.encounterVariant === MysteryEncounterVariant.TRAINER_BATTLE) {
|
if (scene.currentBattle.mysteryEncounter.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
scene.pushPhase(new TrainerVictoryPhase(scene));
|
scene.pushPhase(new TrainerVictoryPhase(scene));
|
||||||
}
|
}
|
||||||
if (scene.gameMode.isEndless || !scene.gameMode.isWaveFinal(scene.currentBattle.waveIndex)) {
|
if (scene.gameMode.isEndless || !scene.gameMode.isWaveFinal(scene.currentBattle.waveIndex)) {
|
||||||
@ -693,7 +693,7 @@ export function transitionMysteryEncounterIntroVisuals(scene: BattleScene, hide:
|
|||||||
*/
|
*/
|
||||||
export function handleMysteryEncounterBattleStartEffects(scene: BattleScene) {
|
export function handleMysteryEncounterBattleStartEffects(scene: BattleScene) {
|
||||||
const encounter = scene.currentBattle?.mysteryEncounter;
|
const encounter = scene.currentBattle?.mysteryEncounter;
|
||||||
if (scene.currentBattle.battleType === BattleType.MYSTERY_ENCOUNTER && encounter.encounterVariant !== MysteryEncounterVariant.NO_BATTLE && !encounter.startOfBattleEffectsComplete) {
|
if (scene.currentBattle.battleType === BattleType.MYSTERY_ENCOUNTER && encounter.encounterMode !== MysteryEncounterMode.NO_BATTLE && !encounter.startOfBattleEffectsComplete) {
|
||||||
const effects = encounter.startOfBattleEffects;
|
const effects = encounter.startOfBattleEffects;
|
||||||
effects.forEach(effect => {
|
effects.forEach(effect => {
|
||||||
let source;
|
let source;
|
||||||
|
9
src/enums/mystery-encounter-mode.ts
Normal file
9
src/enums/mystery-encounter-mode.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export enum MysteryEncounterMode {
|
||||||
|
DEFAULT,
|
||||||
|
TRAINER_BATTLE,
|
||||||
|
WILD_BATTLE,
|
||||||
|
BOSS_BATTLE,
|
||||||
|
NO_BATTLE,
|
||||||
|
/** For spawning new encounter queries instead of continuing to next wave */
|
||||||
|
CONTINUOUS_ENCOUNTER
|
||||||
|
}
|
10
src/enums/mystery-encounter-option-mode.ts
Normal file
10
src/enums/mystery-encounter-option-mode.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export enum MysteryEncounterOptionMode {
|
||||||
|
/** Default style */
|
||||||
|
DEFAULT,
|
||||||
|
/** Disabled on requirements not met, default style on requirements met */
|
||||||
|
DISABLED_OR_DEFAULT,
|
||||||
|
/** Default style on requirements not met, special style on requirements met */
|
||||||
|
DEFAULT_OR_SPECIAL,
|
||||||
|
/** Disabled on requirements not met, special style on requirements met */
|
||||||
|
DISABLED_OR_SPECIAL
|
||||||
|
}
|
10
src/enums/mystery-encounter-tier.ts
Normal file
10
src/enums/mystery-encounter-tier.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Enum values are base spawn weights of each tier
|
||||||
|
*/
|
||||||
|
export enum MysteryEncounterTier {
|
||||||
|
COMMON = 64,
|
||||||
|
GREAT = 40,
|
||||||
|
ULTRA = 21,
|
||||||
|
ROGUE = 3,
|
||||||
|
MASTER = 0 // Not currently used
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
export const offerYouCantRefuseDialogue = {
|
export const offerYouCantRefuseDialogue = {
|
||||||
intro: "You're stopped by a rich looking boy.",
|
intro: "You're stopped by a rich looking boy.",
|
||||||
speaker: "Rich Kid",
|
speaker: "Rich Boy",
|
||||||
intro_dialogue: `Good day to you.
|
intro_dialogue: `Good day to you.
|
||||||
$I can't help but notice that your\n{{strongestPokemon}} looks positively divine!
|
$I can't help but notice that your\n{{strongestPokemon}} looks positively divine!
|
||||||
$I've always wanted to have a pet like that!
|
$I've always wanted to have a pet like that!
|
||||||
$I'd pay you handsomely, and\nI'll even give you this old bauble!`,
|
$I'd pay you handsomely,\nand also give you this old bauble!`,
|
||||||
title: "An Offer You Can't Refuse",
|
title: "An Offer You Can't Refuse",
|
||||||
description: "You're being offered a @[TOOLTIP_TITLE]{Shiny Charm} and {{price, money}} for your {{strongestPokemon}}!\n\nIt's is an extremely good deal, but can you really bear to part with such a strong team member?",
|
description: "You're being offered a @[TOOLTIP_TITLE]{Shiny Charm} and {{price, money}} for your {{strongestPokemon}}!\n\nIt's is an extremely good deal, but can you really bear to part with such a strong team member?",
|
||||||
query: "What will you do?",
|
query: "What will you do?",
|
||||||
@ -18,11 +18,10 @@ export const offerYouCantRefuseDialogue = {
|
|||||||
},
|
},
|
||||||
2: {
|
2: {
|
||||||
label: "Extort the Kid",
|
label: "Extort the Kid",
|
||||||
tooltip: "(+) Gain {{price, money}}",
|
tooltip: "(+) {{option2PrimaryName}} uses {{moveOrAbility}}\n(+) Gain {{price, money}}",
|
||||||
tooltip_disabled: "Your Pokémon need to have certain moves or abilities to choose this",
|
tooltip_disabled: "Your Pokémon need to have certain moves or abilities to choose this",
|
||||||
selected: `My word, we're being robbed, Liepard!
|
selected: `My word, we're being robbed, Liepard!
|
||||||
$How wonderful!
|
$You'll be hearing from my lawyers for this!`,
|
||||||
$Now I'll have an amazing\nstory for the yacht club!`,
|
|
||||||
},
|
},
|
||||||
3: {
|
3: {
|
||||||
label: "Leave",
|
label: "Leave",
|
||||||
|
@ -9,7 +9,7 @@ import { PokeballType } from "./data/pokeball";
|
|||||||
import { Gender } from "./data/gender";
|
import { Gender } from "./data/gender";
|
||||||
import { StatusEffect } from "./data/status-effect";
|
import { StatusEffect } from "./data/status-effect";
|
||||||
import { modifierTypes, SpeciesStatBoosterItem } from "./modifier/modifier-type";
|
import { modifierTypes, SpeciesStatBoosterItem } from "./modifier/modifier-type";
|
||||||
import { VariantTier } from "./enums/variant-tiers";
|
import { VariantTier } from "#enums/variant-tiers";
|
||||||
import { EggTier } from "#enums/egg-type";
|
import { EggTier } from "#enums/egg-type";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { Abilities } from "#enums/abilities";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
@ -18,7 +18,7 @@ import { Moves } from "#enums/moves";
|
|||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { TimeOfDay } from "#enums/time-of-day";
|
import { TimeOfDay } from "#enums/time-of-day";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||||
import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encounter"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides for testing different in game situations
|
* Overrides for testing different in game situations
|
||||||
@ -117,9 +117,9 @@ export const EGG_GACHA_PULL_COUNT_OVERRIDE: number = 0;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// 1 to 256, set to null to ignore
|
// 1 to 256, set to null to ignore
|
||||||
export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = 256;
|
export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = null;
|
||||||
export const MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null;
|
export const MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null;
|
||||||
export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.OFFER_YOU_CANT_REFUSE;
|
export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MODIFIER / ITEM OVERRIDES
|
* MODIFIER / ITEM OVERRIDES
|
||||||
|
@ -65,11 +65,11 @@ import { Moves } from "#enums/moves";
|
|||||||
import { PlayerGender } from "#enums/player-gender";
|
import { PlayerGender } from "#enums/player-gender";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { MysteryEncounterVariant } from "#app/data/mystery-encounters/mystery-encounter";
|
|
||||||
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
|
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
|
||||||
import { doTrainerExclamation, handleMysteryEncounterBattleStartEffects, handleMysteryEncounterVictory } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import { doTrainerExclamation, handleMysteryEncounterBattleStartEffects, handleMysteryEncounterVictory } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "#app/ui/modifier-select-ui-handler";
|
import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "#app/ui/modifier-select-ui-handler";
|
||||||
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
|
|
||||||
const { t } = i18next;
|
const { t } = i18next;
|
||||||
|
|
||||||
@ -866,7 +866,7 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.loaded) {
|
if (!this.loaded) {
|
||||||
this.scene.gameData.setPokemonSeen(enemyPokemon, true, battle.battleType === BattleType.TRAINER || battle?.mysteryEncounter?.encounterVariant === MysteryEncounterVariant.TRAINER_BATTLE);
|
this.scene.gameData.setPokemonSeen(enemyPokemon, true, battle.battleType === BattleType.TRAINER || battle?.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enemyPokemon.species.speciesId === Species.ETERNATUS) {
|
if (enemyPokemon.species.speciesId === Species.ETERNATUS) {
|
||||||
@ -1550,7 +1550,7 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
|||||||
onComplete: () => this.scene.trainer.setVisible(false)
|
onComplete: () => this.scene.trainer.setVisible(false)
|
||||||
});
|
});
|
||||||
this.scene.time.delayedCall(750, () => this.summon());
|
this.scene.time.delayedCall(750, () => this.summon());
|
||||||
} else if (this.scene.currentBattle.battleType === BattleType.TRAINER || this.scene?.currentBattle?.mysteryEncounter?.encounterVariant === MysteryEncounterVariant.TRAINER_BATTLE) {
|
} else if (this.scene.currentBattle.battleType === BattleType.TRAINER || this.scene?.currentBattle?.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
const trainerName = this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER);
|
const trainerName = this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER);
|
||||||
const pokemonName = this.getPokemon().name;
|
const pokemonName = this.getPokemon().name;
|
||||||
const message = i18next.t("battle:trainerSendOut", { trainerName, pokemonName });
|
const message = i18next.t("battle:trainerSendOut", { trainerName, pokemonName });
|
||||||
|
@ -5,7 +5,6 @@ import { Mode } from "../ui/ui";
|
|||||||
import { transitionMysteryEncounterIntroVisuals, OptionSelectSettings } from "../data/mystery-encounters/utils/encounter-phase-utils";
|
import { transitionMysteryEncounterIntroVisuals, OptionSelectSettings } from "../data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { CheckSwitchPhase, NewBattlePhase, ReturnPhase, ScanIvsPhase, SelectModifierPhase, SummonPhase, ToggleDoublePositionPhase } from "../phases";
|
import { CheckSwitchPhase, NewBattlePhase, ReturnPhase, ScanIvsPhase, SelectModifierPhase, SummonPhase, ToggleDoublePositionPhase } from "../phases";
|
||||||
import MysteryEncounterOption, { OptionPhaseCallback } from "../data/mystery-encounters/mystery-encounter-option";
|
import MysteryEncounterOption, { OptionPhaseCallback } from "../data/mystery-encounters/mystery-encounter-option";
|
||||||
import { MysteryEncounterVariant } from "../data/mystery-encounters/mystery-encounter";
|
|
||||||
import { getCharVariantFromDialogue } from "../data/dialogue";
|
import { getCharVariantFromDialogue } from "../data/dialogue";
|
||||||
import { TrainerSlot } from "../data/trainer-config";
|
import { TrainerSlot } from "../data/trainer-config";
|
||||||
import { BattleSpec } from "#enums/battle-spec";
|
import { BattleSpec } from "#enums/battle-spec";
|
||||||
@ -15,6 +14,7 @@ import * as Utils from "../utils";
|
|||||||
import { isNullOrUndefined } from "../utils";
|
import { isNullOrUndefined } from "../utils";
|
||||||
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { BattlerTagLapseType } from "#app/data/battler-tags";
|
import { BattlerTagLapseType } from "#app/data/battler-tags";
|
||||||
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will handle (in order):
|
* Will handle (in order):
|
||||||
@ -210,13 +210,13 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||||||
|
|
||||||
getBattleMessage(scene: BattleScene): string {
|
getBattleMessage(scene: BattleScene): string {
|
||||||
const enemyField = scene.getEnemyField();
|
const enemyField = scene.getEnemyField();
|
||||||
const encounterVariant = scene.currentBattle.mysteryEncounter.encounterVariant;
|
const encounterMode = scene.currentBattle.mysteryEncounter.encounterMode;
|
||||||
|
|
||||||
if (scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) {
|
if (scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) {
|
||||||
return i18next.t("battle:bossAppeared", { bossName: enemyField[0].name });
|
return i18next.t("battle:bossAppeared", { bossName: enemyField[0].name });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encounterVariant === MysteryEncounterVariant.TRAINER_BATTLE) {
|
if (encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
if (scene.currentBattle.double) {
|
if (scene.currentBattle.double) {
|
||||||
return i18next.t("battle:trainerAppearedDouble", { trainerName: scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) });
|
return i18next.t("battle:trainerAppearedDouble", { trainerName: scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) });
|
||||||
|
|
||||||
@ -231,10 +231,10 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
doMysteryEncounterBattle(scene: BattleScene) {
|
doMysteryEncounterBattle(scene: BattleScene) {
|
||||||
const encounterVariant = scene.currentBattle.mysteryEncounter.encounterVariant;
|
const encounterMode = scene.currentBattle.mysteryEncounter.encounterMode;
|
||||||
if (encounterVariant === MysteryEncounterVariant.WILD_BATTLE || encounterVariant === MysteryEncounterVariant.BOSS_BATTLE) {
|
if (encounterMode === MysteryEncounterMode.WILD_BATTLE || encounterMode === MysteryEncounterMode.BOSS_BATTLE) {
|
||||||
// Summons the wild/boss Pokemon
|
// Summons the wild/boss Pokemon
|
||||||
if (encounterVariant === MysteryEncounterVariant.BOSS_BATTLE) {
|
if (encounterMode === MysteryEncounterMode.BOSS_BATTLE) {
|
||||||
scene.playBgm(undefined);
|
scene.playBgm(undefined);
|
||||||
}
|
}
|
||||||
const availablePartyMembers = scene.getEnemyParty().filter(p => !p.isFainted()).length;
|
const availablePartyMembers = scene.getEnemyParty().filter(p => !p.isFainted()).length;
|
||||||
@ -248,7 +248,7 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||||||
} else {
|
} else {
|
||||||
this.endBattleSetup(scene);
|
this.endBattleSetup(scene);
|
||||||
}
|
}
|
||||||
} else if (encounterVariant === MysteryEncounterVariant.TRAINER_BATTLE) {
|
} else if (encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
this.showEnemyTrainer();
|
this.showEnemyTrainer();
|
||||||
const doSummon = () => {
|
const doSummon = () => {
|
||||||
scene.currentBattle.started = true;
|
scene.currentBattle.started = true;
|
||||||
@ -296,11 +296,11 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||||||
|
|
||||||
endBattleSetup(scene: BattleScene) {
|
endBattleSetup(scene: BattleScene) {
|
||||||
const enemyField = scene.getEnemyField();
|
const enemyField = scene.getEnemyField();
|
||||||
const encounterVariant = scene.currentBattle.mysteryEncounter.encounterVariant;
|
const encounterMode = scene.currentBattle.mysteryEncounter.encounterMode;
|
||||||
|
|
||||||
// PostSummon and ShinySparkle phases are handled by SummonPhase
|
// PostSummon and ShinySparkle phases are handled by SummonPhase
|
||||||
|
|
||||||
if (encounterVariant !== MysteryEncounterVariant.TRAINER_BATTLE) {
|
if (encounterMode !== MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
const ivScannerModifier = this.scene.findModifier(m => m instanceof IvScannerModifier);
|
const ivScannerModifier = this.scene.findModifier(m => m instanceof IvScannerModifier);
|
||||||
if (ivScannerModifier) {
|
if (ivScannerModifier) {
|
||||||
enemyField.map(p => this.scene.pushPhase(new ScanIvsPhase(this.scene, p.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6))));
|
enemyField.map(p => this.scene.pushPhase(new ScanIvsPhase(this.scene, p.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6))));
|
||||||
@ -327,7 +327,7 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||||||
scene.pushPhase(new ToggleDoublePositionPhase(scene, false));
|
scene.pushPhase(new ToggleDoublePositionPhase(scene, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encounterVariant !== MysteryEncounterVariant.TRAINER_BATTLE && !this.disableSwitch) {
|
if (encounterMode !== MysteryEncounterMode.TRAINER_BATTLE && !this.disableSwitch) {
|
||||||
const minPartySize = scene.currentBattle.double ? 2 : 1;
|
const minPartySize = scene.currentBattle.double ? 2 : 1;
|
||||||
if (availablePartyMembers.length > minPartySize) {
|
if (availablePartyMembers.length > minPartySize) {
|
||||||
scene.pushPhase(new CheckSwitchPhase(scene, 0, scene.currentBattle.double));
|
scene.pushPhase(new CheckSwitchPhase(scene, 0, scene.currentBattle.double));
|
||||||
|
@ -13,6 +13,53 @@ import { Status, StatusEffect } from "#app/data/status-effect";
|
|||||||
* @param optionNo - human number, not index
|
* @param optionNo - human number, not index
|
||||||
* @param isBattle - if selecting option should lead to battle, set to true
|
* @param isBattle - if selecting option should lead to battle, set to true
|
||||||
*/
|
*/
|
||||||
|
export async function runMysteryEncounterToEnd(game: GameManager, optionNo: number, isBattle: boolean = false) {
|
||||||
|
await runSelectMysteryEncounterOption(game, optionNo, isBattle);
|
||||||
|
|
||||||
|
// run the selected options phase
|
||||||
|
game.onNextPrompt("MysteryEncounterOptionSelectedPhase", Mode.MESSAGE, () => {
|
||||||
|
const uiHandler = game.scene.ui.getHandler<MysteryEncounterUiHandler>();
|
||||||
|
uiHandler.processInput(Button.ACTION);
|
||||||
|
});
|
||||||
|
|
||||||
|
// If a battle is started, fast forward to end of the battle
|
||||||
|
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
||||||
|
game.scene.clearPhaseQueue();
|
||||||
|
game.scene.clearPhaseQueueSplice();
|
||||||
|
game.scene.unshiftPhase(new VictoryPhase(game.scene, 0));
|
||||||
|
game.endPhase();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle end of battle trainer messages
|
||||||
|
game.onNextPrompt("TrainerVictoryPhase", Mode.MESSAGE, () => {
|
||||||
|
const uiHandler = game.scene.ui.getHandler<MessageUiHandler>();
|
||||||
|
uiHandler.processInput(Button.ACTION);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle egg hatch dialogue
|
||||||
|
game.onNextPrompt("EggLapsePhase", Mode.MESSAGE, () => {
|
||||||
|
const uiHandler = game.scene.ui.getHandler<MessageUiHandler>();
|
||||||
|
uiHandler.processInput(Button.ACTION);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle modifier reward dialogue
|
||||||
|
game.onNextPrompt("ModifierRewardPhase", Mode.MESSAGE, () => {
|
||||||
|
const uiHandler = game.scene.ui.getHandler<MessageUiHandler>();
|
||||||
|
uiHandler.processInput(Button.ACTION);
|
||||||
|
});
|
||||||
|
|
||||||
|
game.onNextPrompt("SelectModifier", Mode.MODIFIER_SELECT, () => {
|
||||||
|
const uiHandler = game.scene.ui.getHandler<MessageUiHandler>();
|
||||||
|
uiHandler.processInput(Button.ACTION);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isBattle) {
|
||||||
|
await game.phaseInterceptor.to(CommandPhase);
|
||||||
|
} else {
|
||||||
|
await game.phaseInterceptor.to(MysteryEncounterRewardsPhase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function runSelectMysteryEncounterOption(game: GameManager, optionNo: number, isBattle: boolean = false) {
|
export async function runSelectMysteryEncounterOption(game: GameManager, optionNo: number, isBattle: boolean = false) {
|
||||||
// Handle any eventual queued messages (e.g. weather phase, etc.)
|
// Handle any eventual queued messages (e.g. weather phase, etc.)
|
||||||
game.onNextPrompt("MessagePhase", Mode.MESSAGE, () => {
|
game.onNextPrompt("MessagePhase", Mode.MESSAGE, () => {
|
||||||
@ -53,38 +100,6 @@ export async function runSelectMysteryEncounterOption(game: GameManager, optionN
|
|||||||
}
|
}
|
||||||
|
|
||||||
uiHandler.processInput(Button.ACTION);
|
uiHandler.processInput(Button.ACTION);
|
||||||
|
|
||||||
// run the selected options phase
|
|
||||||
game.onNextPrompt("MysteryEncounterOptionSelectedPhase", Mode.MESSAGE, () => {
|
|
||||||
const uiHandler = game.scene.ui.getHandler<MysteryEncounterUiHandler>();
|
|
||||||
uiHandler.processInput(Button.ACTION);
|
|
||||||
});
|
|
||||||
|
|
||||||
// If a battle is started, fast forward to end of the battle
|
|
||||||
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
|
||||||
game.scene.clearPhaseQueue();
|
|
||||||
game.scene.clearPhaseQueueSplice();
|
|
||||||
game.scene.unshiftPhase(new VictoryPhase(game.scene, 0));
|
|
||||||
game.endPhase();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle end of battle trainer messages
|
|
||||||
game.onNextPrompt("TrainerVictoryPhase", Mode.MESSAGE, () => {
|
|
||||||
const uiHandler = game.scene.ui.getHandler<MessageUiHandler>();
|
|
||||||
uiHandler.processInput(Button.ACTION);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle egg hatch dialogue
|
|
||||||
game.onNextPrompt("EggLapsePhase", Mode.MESSAGE, () => {
|
|
||||||
const uiHandler = game.scene.ui.getHandler<MessageUiHandler>();
|
|
||||||
uiHandler.processInput(Button.ACTION);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isBattle) {
|
|
||||||
await game.phaseInterceptor.to(CommandPhase);
|
|
||||||
} else {
|
|
||||||
await game.phaseInterceptor.to(MysteryEncounterRewardsPhase);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,15 +5,15 @@ import { Species } from "#app/enums/species";
|
|||||||
import GameManager from "#app/test/utils/gameManager";
|
import GameManager from "#app/test/utils/gameManager";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { EncounterOptionMode } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounterTestUtils";
|
||||||
import { runSelectMysteryEncounterOption } from "#test/mystery-encounter/encounterTestUtils";
|
|
||||||
import { SelectModifierPhase } from "#app/phases";
|
import { SelectModifierPhase } from "#app/phases";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encounter";
|
|
||||||
import { Mode } from "#app/ui/ui";
|
import { Mode } from "#app/ui/ui";
|
||||||
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
||||||
import { DepartmentStoreSaleEncounter } from "#app/data/mystery-encounters/encounters/department-store-sale-encounter";
|
import { DepartmentStoreSaleEncounter } from "#app/data/mystery-encounters/encounters/department-store-sale-encounter";
|
||||||
import { CIVILIZATION_ENCOUNTER_BIOMES } from "#app/data/mystery-encounters/mystery-encounters";
|
import { CIVILIZATION_ENCOUNTER_BIOMES } from "#app/data/mystery-encounters/mystery-encounters";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
|
||||||
const namespace = "mysteryEncounter:departmentStoreSale";
|
const namespace = "mysteryEncounter:departmentStoreSale";
|
||||||
const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA];
|
const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA];
|
||||||
@ -98,7 +98,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
describe("Option 1 - TM Shop", () => {
|
describe("Option 1 - TM Shop", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option = DepartmentStoreSaleEncounter.options[0];
|
const option = DepartmentStoreSaleEncounter.options[0];
|
||||||
expect(option.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
||||||
expect(option.dialogue).toBeDefined();
|
expect(option.dialogue).toBeDefined();
|
||||||
expect(option.dialogue).toStrictEqual({
|
expect(option.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
@ -108,7 +108,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
|
|
||||||
it("should have shop with only TMs", async () => {
|
it("should have shop with only TMs", async () => {
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 1);
|
await runMysteryEncounterToEnd(game, 1);
|
||||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 1);
|
await runMysteryEncounterToEnd(game, 1);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
@ -133,7 +133,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
describe("Option 2 - Vitamin Shop", () => {
|
describe("Option 2 - Vitamin Shop", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option = DepartmentStoreSaleEncounter.options[1];
|
const option = DepartmentStoreSaleEncounter.options[1];
|
||||||
expect(option.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
||||||
expect(option.dialogue).toBeDefined();
|
expect(option.dialogue).toBeDefined();
|
||||||
expect(option.dialogue).toStrictEqual({
|
expect(option.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:2:label`,
|
buttonLabel: `${namespace}:option:2:label`,
|
||||||
@ -143,7 +143,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
|
|
||||||
it("should have shop with only Vitamins", async () => {
|
it("should have shop with only Vitamins", async () => {
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 2);
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 2);
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
@ -169,7 +169,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
describe("Option 3 - X Item Shop", () => {
|
describe("Option 3 - X Item Shop", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option = DepartmentStoreSaleEncounter.options[2];
|
const option = DepartmentStoreSaleEncounter.options[2];
|
||||||
expect(option.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
||||||
expect(option.dialogue).toBeDefined();
|
expect(option.dialogue).toBeDefined();
|
||||||
expect(option.dialogue).toStrictEqual({
|
expect(option.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:3:label`,
|
buttonLabel: `${namespace}:option:3:label`,
|
||||||
@ -179,7 +179,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
|
|
||||||
it("should have shop with only X Items", async () => {
|
it("should have shop with only X Items", async () => {
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 3);
|
await runMysteryEncounterToEnd(game, 3);
|
||||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 3);
|
await runMysteryEncounterToEnd(game, 3);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
@ -205,7 +205,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
describe("Option 4 - Pokeball Shop", () => {
|
describe("Option 4 - Pokeball Shop", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option = DepartmentStoreSaleEncounter.options[3];
|
const option = DepartmentStoreSaleEncounter.options[3];
|
||||||
expect(option.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
||||||
expect(option.dialogue).toBeDefined();
|
expect(option.dialogue).toBeDefined();
|
||||||
expect(option.dialogue).toStrictEqual({
|
expect(option.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:4:label`,
|
buttonLabel: `${namespace}:option:4:label`,
|
||||||
@ -215,7 +215,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
|
|
||||||
it("should have shop with only Pokeballs", async () => {
|
it("should have shop with only Pokeballs", async () => {
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 4);
|
await runMysteryEncounterToEnd(game, 4);
|
||||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||||
await game.phaseInterceptor.run(SelectModifierPhase);
|
await game.phaseInterceptor.run(SelectModifierPhase);
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ describe("Department Store Sale - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 4);
|
await runMysteryEncounterToEnd(game, 4);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
|
@ -5,20 +5,21 @@ import { Species } from "#app/enums/species";
|
|||||||
import GameManager from "#app/test/utils/gameManager";
|
import GameManager from "#app/test/utils/gameManager";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import { FieryFalloutEncounter } from "#app/data/mystery-encounters/encounters/fiery-fallout-encounter";
|
import { FieryFalloutEncounter } from "#app/data/mystery-encounters/encounters/fiery-fallout-encounter";
|
||||||
import Battle from "#app/battle";
|
|
||||||
import { Gender } from "#app/data/gender";
|
import { Gender } from "#app/data/gender";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import * as BattleAnims from "#app/data/battle-anims";
|
import * as BattleAnims from "#app/data/battle-anims";
|
||||||
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { EncounterOptionMode } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils";
|
||||||
import { runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils";
|
|
||||||
import { CommandPhase, MovePhase, SelectModifierPhase } from "#app/phases";
|
import { CommandPhase, MovePhase, SelectModifierPhase } from "#app/phases";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
import { Type } from "#app/data/type";
|
import { Type } from "#app/data/type";
|
||||||
import { Status, StatusEffect } from "#app/data/status-effect";
|
import { Status, StatusEffect } from "#app/data/status-effect";
|
||||||
import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils";
|
||||||
|
|
||||||
const namespace = "mysteryEncounter:fieryFallout";
|
const namespace = "mysteryEncounter:fieryFallout";
|
||||||
/** Arcanine and Ninetails for 2 Fire types. Lapras, Gengar, Abra for burnable mon. */
|
/** Arcanine and Ninetails for 2 Fire types. Lapras, Gengar, Abra for burnable mon. */
|
||||||
@ -94,7 +95,8 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should initialize fully ", async () => {
|
it("should initialize fully ", async () => {
|
||||||
vi.spyOn(scene, "currentBattle", "get").mockReturnValue({ mysteryEncounter: FieryFalloutEncounter } as Battle);
|
initSceneWithoutEncounterPhase(scene, defaultParty);
|
||||||
|
scene.currentBattle.mysteryEncounter = FieryFalloutEncounter;
|
||||||
const weatherSpy = vi.spyOn(scene.arena, "trySetWeather").mockReturnValue(true);
|
const weatherSpy = vi.spyOn(scene.arena, "trySetWeather").mockReturnValue(true);
|
||||||
const moveInitSpy = vi.spyOn(BattleAnims, "initMoveAnim");
|
const moveInitSpy = vi.spyOn(BattleAnims, "initMoveAnim");
|
||||||
const moveLoadSpy = vi.spyOn(BattleAnims, "loadMoveAnimAssets");
|
const moveLoadSpy = vi.spyOn(BattleAnims, "loadMoveAnimAssets");
|
||||||
@ -103,6 +105,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||||||
|
|
||||||
expect(FieryFalloutEncounter.onInit).toBeDefined();
|
expect(FieryFalloutEncounter.onInit).toBeDefined();
|
||||||
|
|
||||||
|
FieryFalloutEncounter.populateDialogueTokensFromRequirements(scene);
|
||||||
const onInitResult = onInit(scene);
|
const onInitResult = onInit(scene);
|
||||||
|
|
||||||
expect(FieryFalloutEncounter.enemyPartyConfigs).toEqual([
|
expect(FieryFalloutEncounter.enemyPartyConfigs).toEqual([
|
||||||
@ -132,7 +135,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||||||
describe("Option 1 - Fight 2 Volcarona", () => {
|
describe("Option 1 - Fight 2 Volcarona", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option1 = FieryFalloutEncounter.options[0];
|
const option1 = FieryFalloutEncounter.options[0];
|
||||||
expect(option1.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
expect(option1.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
||||||
expect(option1.dialogue).toBeDefined();
|
expect(option1.dialogue).toBeDefined();
|
||||||
expect(option1.dialogue).toStrictEqual({
|
expect(option1.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
@ -149,7 +152,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||||||
const phaseSpy = vi.spyOn(scene, "pushPhase");
|
const phaseSpy = vi.spyOn(scene, "pushPhase");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 1, true);
|
await runMysteryEncounterToEnd(game, 1, true);
|
||||||
|
|
||||||
const enemyField = scene.getEnemyField();
|
const enemyField = scene.getEnemyField();
|
||||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
@ -166,7 +169,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||||||
|
|
||||||
it("should give charcoal to lead pokemon", async () => {
|
it("should give charcoal to lead pokemon", async () => {
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 1, true);
|
await runMysteryEncounterToEnd(game, 1, true);
|
||||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||||
@ -182,7 +185,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||||||
describe("Option 2 - Suffer the weather", () => {
|
describe("Option 2 - Suffer the weather", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option1 = FieryFalloutEncounter.options[1];
|
const option1 = FieryFalloutEncounter.options[1];
|
||||||
expect(option1.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
expect(option1.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
||||||
expect(option1.dialogue).toBeDefined();
|
expect(option1.dialogue).toBeDefined();
|
||||||
expect(option1.dialogue).toStrictEqual({
|
expect(option1.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:2:label`,
|
buttonLabel: `${namespace}:option:2:label`,
|
||||||
@ -204,7 +207,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||||||
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA);
|
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA);
|
||||||
vi.spyOn(abra, "isAllowedInBattle").mockReturnValue(false);
|
vi.spyOn(abra, "isAllowedInBattle").mockReturnValue(false);
|
||||||
|
|
||||||
await runSelectMysteryEncounterOption(game, 2);
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
|
|
||||||
const burnablePokemon = party.filter((pkm) => pkm.isAllowedInBattle() && !pkm.getTypes().includes(Type.FIRE));
|
const burnablePokemon = party.filter((pkm) => pkm.isAllowedInBattle() && !pkm.getTypes().includes(Type.FIRE));
|
||||||
const notBurnablePokemon = party.filter((pkm) => !pkm.isAllowedInBattle() || pkm.getTypes().includes(Type.FIRE));
|
const notBurnablePokemon = party.filter((pkm) => !pkm.isAllowedInBattle() || pkm.getTypes().includes(Type.FIRE));
|
||||||
@ -220,7 +223,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 2);
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
@ -229,7 +232,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||||||
describe("Option 3 - use FIRE types", () => {
|
describe("Option 3 - use FIRE types", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option1 = FieryFalloutEncounter.options[2];
|
const option1 = FieryFalloutEncounter.options[2];
|
||||||
expect(option1.optionMode).toBe(EncounterOptionMode.DISABLED_OR_SPECIAL);
|
expect(option1.optionMode).toBe(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL);
|
||||||
expect(option1.dialogue).toBeDefined();
|
expect(option1.dialogue).toBeDefined();
|
||||||
expect(option1.dialogue).toStrictEqual({
|
expect(option1.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:3:label`,
|
buttonLabel: `${namespace}:option:3:label`,
|
||||||
@ -245,7 +248,7 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||||||
|
|
||||||
it("should give charcoal to lead pokemon", async () => {
|
it("should give charcoal to lead pokemon", async () => {
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 3);
|
await runMysteryEncounterToEnd(game, 3);
|
||||||
// await skipBattleRunMysteryEncounterRewardsPhase(game);
|
// await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||||
@ -261,9 +264,23 @@ describe("Fiery Fallout - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 3);
|
await runMysteryEncounterToEnd(game, 3);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should be disabled if not enough FIRE types are in party", async () => {
|
||||||
|
await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, [Species.MAGIKARP, Species.ARCANINE]);
|
||||||
|
await game.phaseInterceptor.to(MysteryEncounterPhase, false);
|
||||||
|
|
||||||
|
const encounterPhase = scene.getCurrentPhase();
|
||||||
|
expect(encounterPhase.constructor.name).toBe(MysteryEncounterPhase.name);
|
||||||
|
const continueEncounterSpy = vi.spyOn((encounterPhase as MysteryEncounterPhase), "continueEncounter");
|
||||||
|
|
||||||
|
await runSelectMysteryEncounterOption(game, 3);
|
||||||
|
|
||||||
|
expect(scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterPhase.name);
|
||||||
|
expect(continueEncounterSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import Battle from "#app/battle";
|
|
||||||
import { LostAtSeaEncounter } from "#app/data/mystery-encounters/encounters/lost-at-sea-encounter";
|
import { LostAtSeaEncounter } from "#app/data/mystery-encounters/encounters/lost-at-sea-encounter";
|
||||||
import { EncounterOptionMode } from "#app/data/mystery-encounters/mystery-encounter-option";
|
|
||||||
import * as MysteryEncounters from "#app/data/mystery-encounters/mystery-encounters";
|
import * as MysteryEncounters from "#app/data/mystery-encounters/mystery-encounters";
|
||||||
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species.js";
|
import { getPokemonSpecies } from "#app/data/pokemon-species.js";
|
||||||
@ -10,8 +8,11 @@ import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
|
|||||||
import { Species } from "#app/enums/species";
|
import { Species } from "#app/enums/species";
|
||||||
import GameManager from "#app/test/utils/gameManager";
|
import GameManager from "#app/test/utils/gameManager";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import { runSelectMysteryEncounterOption } from "../encounterTestUtils";
|
import { runMysteryEncounterToEnd } from "../encounterTestUtils";
|
||||||
import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils";
|
||||||
|
import BattleScene from "#app/battle-scene";
|
||||||
|
|
||||||
const namespace = "mysteryEncounter:lostAtSea";
|
const namespace = "mysteryEncounter:lostAtSea";
|
||||||
/** Blastoise for surf. Pidgeot for fly. Abra for none. */
|
/** Blastoise for surf. Pidgeot for fly. Abra for none. */
|
||||||
@ -22,6 +23,7 @@ const defaultWave = 33;
|
|||||||
describe("Lost at Sea - Mystery Encounter", () => {
|
describe("Lost at Sea - Mystery Encounter", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
let game: GameManager;
|
let game: GameManager;
|
||||||
|
let scene: BattleScene;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
phaserGame = new Phaser.Game({ type: Phaser.HEADLESS });
|
phaserGame = new Phaser.Game({ type: Phaser.HEADLESS });
|
||||||
@ -29,6 +31,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
|
scene = game.scene;
|
||||||
game.override.mysteryEncounterChance(100);
|
game.override.mysteryEncounterChance(100);
|
||||||
game.override.startingWave(defaultWave);
|
game.override.startingWave(defaultWave);
|
||||||
game.override.startingBiome(defaultBiome);
|
game.override.startingBiome(defaultBiome);
|
||||||
@ -83,14 +86,16 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||||||
expect(game.scene.currentBattle.mysteryEncounter).toBeUndefined();
|
expect(game.scene.currentBattle.mysteryEncounter).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set the correct dialog tokens during initialization", () => {
|
it("should initialize fully", () => {
|
||||||
vi.spyOn(game.scene, "currentBattle", "get").mockReturnValue({ mysteryEncounter: LostAtSeaEncounter } as Battle);
|
initSceneWithoutEncounterPhase(scene, defaultParty);
|
||||||
|
scene.currentBattle.mysteryEncounter = LostAtSeaEncounter;
|
||||||
|
|
||||||
const { onInit } = LostAtSeaEncounter;
|
const { onInit } = LostAtSeaEncounter;
|
||||||
|
|
||||||
expect(LostAtSeaEncounter.onInit).toBeDefined();
|
expect(LostAtSeaEncounter.onInit).toBeDefined();
|
||||||
|
|
||||||
const onInitResult = onInit(game.scene);
|
LostAtSeaEncounter.populateDialogueTokensFromRequirements(scene);
|
||||||
|
const onInitResult = onInit(scene);
|
||||||
|
|
||||||
expect(LostAtSeaEncounter.dialogueTokens?.damagePercentage).toBe("25");
|
expect(LostAtSeaEncounter.dialogueTokens?.damagePercentage).toBe("25");
|
||||||
expect(LostAtSeaEncounter.dialogueTokens?.option1RequiredMove).toBe(Moves[Moves.SURF]);
|
expect(LostAtSeaEncounter.dialogueTokens?.option1RequiredMove).toBe(Moves[Moves.SURF]);
|
||||||
@ -101,7 +106,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||||||
describe("Option 1 - Surf", () => {
|
describe("Option 1 - Surf", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option1 = LostAtSeaEncounter.options[0];
|
const option1 = LostAtSeaEncounter.options[0];
|
||||||
expect(option1.optionMode).toBe(EncounterOptionMode.DISABLED_OR_DEFAULT);
|
expect(option1.optionMode).toBe(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT);
|
||||||
expect(option1.dialogue).toBeDefined();
|
expect(option1.dialogue).toBeDefined();
|
||||||
expect(option1.dialogue).toStrictEqual({
|
expect(option1.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
@ -124,7 +129,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||||||
const blastoise = party.find((pkm) => pkm.species.speciesId === Species.PIDGEOT);
|
const blastoise = party.find((pkm) => pkm.species.speciesId === Species.PIDGEOT);
|
||||||
const expBefore = blastoise.exp;
|
const expBefore = blastoise.exp;
|
||||||
|
|
||||||
await runSelectMysteryEncounterOption(game, 2);
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
|
|
||||||
expect(blastoise.exp).toBe(expBefore + Math.floor(laprasSpecies.baseExp * defaultWave / 5 + 1));
|
expect(blastoise.exp).toBe(expBefore + Math.floor(laprasSpecies.baseExp * defaultWave / 5 + 1));
|
||||||
});
|
});
|
||||||
@ -134,7 +139,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 1);
|
await runMysteryEncounterToEnd(game, 1);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
@ -148,7 +153,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option2 = LostAtSeaEncounter.options[1];
|
const option2 = LostAtSeaEncounter.options[1];
|
||||||
|
|
||||||
expect(option2.optionMode).toBe(EncounterOptionMode.DISABLED_OR_DEFAULT);
|
expect(option2.optionMode).toBe(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT);
|
||||||
expect(option2.dialogue).toBeDefined();
|
expect(option2.dialogue).toBeDefined();
|
||||||
expect(option2.dialogue).toStrictEqual({
|
expect(option2.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:2:label`,
|
buttonLabel: `${namespace}:option:2:label`,
|
||||||
@ -173,7 +178,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||||||
const pidgeot = party.find((pkm) => pkm.species.speciesId === Species.PIDGEOT);
|
const pidgeot = party.find((pkm) => pkm.species.speciesId === Species.PIDGEOT);
|
||||||
const expBefore = pidgeot.exp;
|
const expBefore = pidgeot.exp;
|
||||||
|
|
||||||
await runSelectMysteryEncounterOption(game, 2);
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
|
|
||||||
expect(pidgeot.exp).toBe(expBefore + Math.floor(laprasBaseExp * defaultWave / 5 + 1));
|
expect(pidgeot.exp).toBe(expBefore + Math.floor(laprasBaseExp * defaultWave / 5 + 1));
|
||||||
});
|
});
|
||||||
@ -183,7 +188,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 2);
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
@ -197,7 +202,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option3 = LostAtSeaEncounter.options[2];
|
const option3 = LostAtSeaEncounter.options[2];
|
||||||
|
|
||||||
expect(option3.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
expect(option3.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
||||||
expect(option3.dialogue).toBeDefined();
|
expect(option3.dialogue).toBeDefined();
|
||||||
expect(option3.dialogue).toStrictEqual({
|
expect(option3.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:3:label`,
|
buttonLabel: `${namespace}:option:3:label`,
|
||||||
@ -219,7 +224,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||||||
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA);
|
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA);
|
||||||
vi.spyOn(abra, "isAllowedInBattle").mockReturnValue(false);
|
vi.spyOn(abra, "isAllowedInBattle").mockReturnValue(false);
|
||||||
|
|
||||||
await runSelectMysteryEncounterOption(game, 3);
|
await runMysteryEncounterToEnd(game, 3);
|
||||||
|
|
||||||
const allowedPkm = party.filter((pkm) => pkm.isAllowedInBattle());
|
const allowedPkm = party.filter((pkm) => pkm.isAllowedInBattle());
|
||||||
const notAllowedPkm = party.filter((pkm) => !pkm.isAllowedInBattle());
|
const notAllowedPkm = party.filter((pkm) => !pkm.isAllowedInBattle());
|
||||||
@ -235,7 +240,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 3);
|
await runMysteryEncounterToEnd(game, 3);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,244 @@
|
|||||||
|
import * as MysteryEncounters from "#app/data/mystery-encounters/mystery-encounters";
|
||||||
|
import { HUMAN_TRANSITABLE_BIOMES } 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 * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
|
import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounterTestUtils";
|
||||||
|
import BattleScene from "#app/battle-scene";
|
||||||
|
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||||
|
import { OfferYouCantRefuseEncounter } from "#app/data/mystery-encounters/encounters/offer-you-cant-refuse-encounter";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils";
|
||||||
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
|
||||||
|
const namespace = "mysteryEncounter:offerYouCantRefuse";
|
||||||
|
/** Gyarados for Indimidate */
|
||||||
|
const defaultParty = [Species.GYARADOS, Species.GENGAR, Species.ABRA];
|
||||||
|
const defaultBiome = Biome.CAVE;
|
||||||
|
const defaultWave = 45;
|
||||||
|
|
||||||
|
describe("An Offer You Can't Refuse - 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.mysteryEncounterTier(MysteryEncounterTier.COMMON);
|
||||||
|
game.override.startingWave(defaultWave);
|
||||||
|
game.override.startingBiome(defaultBiome);
|
||||||
|
|
||||||
|
const biomeMap = new Map<Biome, MysteryEncounterType[]>([
|
||||||
|
[Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]],
|
||||||
|
]);
|
||||||
|
HUMAN_TRANSITABLE_BIOMES.forEach(biome => {
|
||||||
|
biomeMap.set(biome, [MysteryEncounterType.OFFER_YOU_CANT_REFUSE]);
|
||||||
|
});
|
||||||
|
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
vi.clearAllMocks();
|
||||||
|
vi.resetAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have the correct properties", async () => {
|
||||||
|
await game.runToMysteryEncounter(MysteryEncounterType.OFFER_YOU_CANT_REFUSE, defaultParty);
|
||||||
|
|
||||||
|
expect(OfferYouCantRefuseEncounter.encounterType).toBe(MysteryEncounterType.OFFER_YOU_CANT_REFUSE);
|
||||||
|
expect(OfferYouCantRefuseEncounter.encounterTier).toBe(MysteryEncounterTier.GREAT);
|
||||||
|
expect(OfferYouCantRefuseEncounter.dialogue).toBeDefined();
|
||||||
|
expect(OfferYouCantRefuseEncounter.dialogue.intro).toStrictEqual([
|
||||||
|
{ text: `${namespace}:intro` },
|
||||||
|
{ speaker: `${namespace}:speaker`, text: `${namespace}:intro_dialogue` }
|
||||||
|
]);
|
||||||
|
expect(OfferYouCantRefuseEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}:title`);
|
||||||
|
expect(OfferYouCantRefuseEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}:description`);
|
||||||
|
expect(OfferYouCantRefuseEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}:query`);
|
||||||
|
expect(OfferYouCantRefuseEncounter.options.length).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not spawn outside of HUMAN_TRANSITABLE_BIOMES", async () => {
|
||||||
|
game.override.startingBiome(Biome.VOLCANO);
|
||||||
|
await game.runToMysteryEncounter();
|
||||||
|
|
||||||
|
expect(scene.currentBattle?.mysteryEncounter?.encounterType).not.toBe(MysteryEncounterType.OFFER_YOU_CANT_REFUSE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not run below wave 10", async () => {
|
||||||
|
game.override.startingWave(9);
|
||||||
|
|
||||||
|
await game.runToMysteryEncounter();
|
||||||
|
|
||||||
|
expect(scene.currentBattle?.mysteryEncounter?.encounterType).not.toBe(MysteryEncounterType.OFFER_YOU_CANT_REFUSE);
|
||||||
|
});
|
||||||
|
|
||||||
|
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 = OfferYouCantRefuseEncounter;
|
||||||
|
|
||||||
|
const { onInit } = OfferYouCantRefuseEncounter;
|
||||||
|
|
||||||
|
expect(OfferYouCantRefuseEncounter.onInit).toBeDefined();
|
||||||
|
|
||||||
|
OfferYouCantRefuseEncounter.populateDialogueTokensFromRequirements(scene);
|
||||||
|
const onInitResult = onInit(scene);
|
||||||
|
|
||||||
|
expect(OfferYouCantRefuseEncounter.dialogueTokens?.strongestPokemon).toBeDefined();
|
||||||
|
expect(OfferYouCantRefuseEncounter.dialogueTokens?.price).toBeDefined();
|
||||||
|
expect(OfferYouCantRefuseEncounter.dialogueTokens?.option2PrimaryAbility).toBe("Intimidate");
|
||||||
|
expect(OfferYouCantRefuseEncounter.dialogueTokens?.moveOrAbility).toBe("Intimidate");
|
||||||
|
expect(OfferYouCantRefuseEncounter.misc.pokemon instanceof PlayerPokemon).toBeTruthy();
|
||||||
|
expect(OfferYouCantRefuseEncounter.misc?.price?.toString()).toBe(OfferYouCantRefuseEncounter.dialogueTokens?.price);
|
||||||
|
expect(onInitResult).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Option 1 - Sell your Pokemon for money and a Shiny Charm", () => {
|
||||||
|
it("should have the correct properties", () => {
|
||||||
|
const option = OfferYouCantRefuseEncounter.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 update the player's money properly", async () => {
|
||||||
|
const initialMoney = 20000;
|
||||||
|
scene.money = initialMoney;
|
||||||
|
const updateMoneySpy = vi.spyOn(EncounterPhaseUtils, "updatePlayerMoney");
|
||||||
|
|
||||||
|
await game.runToMysteryEncounter(MysteryEncounterType.OFFER_YOU_CANT_REFUSE, defaultParty);
|
||||||
|
await runMysteryEncounterToEnd(game, 1);
|
||||||
|
|
||||||
|
const price = scene.currentBattle.mysteryEncounter.misc.price;
|
||||||
|
|
||||||
|
expect(updateMoneySpy).toHaveBeenCalledWith(scene, price);
|
||||||
|
expect(scene.money).toBe(initialMoney + price);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should remove the Pokemon from the party", async () => {
|
||||||
|
await game.runToMysteryEncounter(MysteryEncounterType.OFFER_YOU_CANT_REFUSE, defaultParty);
|
||||||
|
|
||||||
|
const initialPartySize = scene.getParty().length;
|
||||||
|
const pokemonName = scene.currentBattle.mysteryEncounter.misc.pokemon.name;
|
||||||
|
|
||||||
|
await runMysteryEncounterToEnd(game, 1);
|
||||||
|
|
||||||
|
expect(scene.getParty().length).toBe(initialPartySize - 1);
|
||||||
|
expect(scene.getParty().find(p => p.name === pokemonName)).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should leave encounter without battle", async () => {
|
||||||
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
|
await game.runToMysteryEncounter(MysteryEncounterType.OFFER_YOU_CANT_REFUSE, defaultParty);
|
||||||
|
await runMysteryEncounterToEnd(game, 1);
|
||||||
|
|
||||||
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Option 2 - Extort the Kid", () => {
|
||||||
|
it("should have the correct properties", () => {
|
||||||
|
const option = OfferYouCantRefuseEncounter.options[1];
|
||||||
|
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL);
|
||||||
|
expect(option.dialogue).toBeDefined();
|
||||||
|
expect(option.dialogue).toStrictEqual({
|
||||||
|
buttonLabel: `${namespace}:option:2:label`,
|
||||||
|
buttonTooltip: `${namespace}:option:2:tooltip`,
|
||||||
|
disabledButtonTooltip: `${namespace}:option:2:tooltip_disabled`,
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
speaker: `${namespace}:speaker`,
|
||||||
|
text: `${namespace}:option:2:selected`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should award EXP to a pokemon with an ability in EXTORTION_ABILITIES", async () => {
|
||||||
|
await game.runToMysteryEncounter(MysteryEncounterType.OFFER_YOU_CANT_REFUSE, defaultParty);
|
||||||
|
const party = scene.getParty();
|
||||||
|
const gyarados = party.find((pkm) => pkm.species.speciesId === Species.GYARADOS);
|
||||||
|
const expBefore = gyarados.exp;
|
||||||
|
|
||||||
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
|
|
||||||
|
expect(gyarados.exp).toBe(expBefore + Math.floor(getPokemonSpecies(Species.LIEPARD).baseExp * defaultWave / 5 + 1));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should award EXP to a pokemon with a move in EXTORTION_MOVES", async () => {
|
||||||
|
await game.runToMysteryEncounter(MysteryEncounterType.OFFER_YOU_CANT_REFUSE, [Species.ABRA]);
|
||||||
|
const party = scene.getParty();
|
||||||
|
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA);
|
||||||
|
abra.moveset = [new PokemonMove(Moves.BEAT_UP)];
|
||||||
|
const expBefore = abra.exp;
|
||||||
|
|
||||||
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
|
|
||||||
|
expect(abra.exp).toBe(expBefore + Math.floor(getPokemonSpecies(Species.LIEPARD).baseExp * defaultWave / 5 + 1));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should update the player's money properly", async () => {
|
||||||
|
const initialMoney = 20000;
|
||||||
|
scene.money = initialMoney;
|
||||||
|
const updateMoneySpy = vi.spyOn(EncounterPhaseUtils, "updatePlayerMoney");
|
||||||
|
|
||||||
|
await game.runToMysteryEncounter(MysteryEncounterType.OFFER_YOU_CANT_REFUSE, defaultParty);
|
||||||
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
|
|
||||||
|
const price = scene.currentBattle.mysteryEncounter.misc.price;
|
||||||
|
|
||||||
|
expect(updateMoneySpy).toHaveBeenCalledWith(scene, price);
|
||||||
|
expect(scene.money).toBe(initialMoney + price);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should leave encounter without battle", async () => {
|
||||||
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
|
await game.runToMysteryEncounter(MysteryEncounterType.OFFER_YOU_CANT_REFUSE, defaultParty);
|
||||||
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
|
|
||||||
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Option 3 - Leave", () => {
|
||||||
|
it("should leave encounter without battle", async () => {
|
||||||
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
|
await game.runToMysteryEncounter(MysteryEncounterType.OFFER_YOU_CANT_REFUSE, defaultParty);
|
||||||
|
await runMysteryEncounterToEnd(game, 3);
|
||||||
|
|
||||||
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -4,15 +4,15 @@ import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
|
|||||||
import { Species } from "#app/enums/species";
|
import { Species } from "#app/enums/species";
|
||||||
import GameManager from "#app/test/utils/gameManager";
|
import GameManager from "#app/test/utils/gameManager";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import Battle from "#app/battle";
|
|
||||||
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { EncounterOptionMode } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounterTestUtils";
|
||||||
import { runSelectMysteryEncounterOption } from "#test/mystery-encounter/encounterTestUtils";
|
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encounter";
|
|
||||||
import { PlayerPokemon } from "#app/field/pokemon";
|
import { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { HUMAN_TRANSITABLE_BIOMES } from "#app/data/mystery-encounters/mystery-encounters";
|
import { HUMAN_TRANSITABLE_BIOMES } from "#app/data/mystery-encounters/mystery-encounters";
|
||||||
import { PokemonSalesmanEncounter } from "#app/data/mystery-encounters/encounters/pokemon-salesman-encounter";
|
import { PokemonSalesmanEncounter } from "#app/data/mystery-encounters/encounters/pokemon-salesman-encounter";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils";
|
||||||
|
|
||||||
const namespace = "mysteryEncounter:pokemonSalesman";
|
const namespace = "mysteryEncounter:pokemonSalesman";
|
||||||
const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA];
|
const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA];
|
||||||
@ -59,7 +59,7 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||||||
expect(PokemonSalesmanEncounter.dialogue).toBeDefined();
|
expect(PokemonSalesmanEncounter.dialogue).toBeDefined();
|
||||||
expect(PokemonSalesmanEncounter.dialogue.intro).toStrictEqual([
|
expect(PokemonSalesmanEncounter.dialogue.intro).toStrictEqual([
|
||||||
{ text: `${namespace}:intro` },
|
{ text: `${namespace}:intro` },
|
||||||
{ speaker: "mysteryEncounter:pokemonSalesman:speaker", text: "mysteryEncounter:pokemonSalesman:intro_dialogue" }
|
{ speaker: `${namespace}:speaker`, text: `${namespace}:intro_dialogue` }
|
||||||
]);
|
]);
|
||||||
expect(PokemonSalesmanEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}:title`);
|
expect(PokemonSalesmanEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}:title`);
|
||||||
expect(PokemonSalesmanEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}:description`);
|
expect(PokemonSalesmanEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}:description`);
|
||||||
@ -91,12 +91,14 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should initialize fully ", async () => {
|
it("should initialize fully ", async () => {
|
||||||
vi.spyOn(scene, "currentBattle", "get").mockReturnValue({ mysteryEncounter: PokemonSalesmanEncounter } as Battle);
|
initSceneWithoutEncounterPhase(scene, defaultParty);
|
||||||
|
scene.currentBattle.mysteryEncounter = PokemonSalesmanEncounter;
|
||||||
|
|
||||||
const { onInit } = PokemonSalesmanEncounter;
|
const { onInit } = PokemonSalesmanEncounter;
|
||||||
|
|
||||||
expect(PokemonSalesmanEncounter.onInit).toBeDefined();
|
expect(PokemonSalesmanEncounter.onInit).toBeDefined();
|
||||||
|
|
||||||
|
PokemonSalesmanEncounter.populateDialogueTokensFromRequirements(scene);
|
||||||
const onInitResult = onInit(scene);
|
const onInitResult = onInit(scene);
|
||||||
|
|
||||||
expect(PokemonSalesmanEncounter.dialogueTokens?.purchasePokemon).toBeDefined();
|
expect(PokemonSalesmanEncounter.dialogueTokens?.purchasePokemon).toBeDefined();
|
||||||
@ -109,7 +111,7 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||||||
describe("Option 1 - Purchase the pokemon", () => {
|
describe("Option 1 - Purchase the pokemon", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option1 = PokemonSalesmanEncounter.options[0];
|
const option1 = PokemonSalesmanEncounter.options[0];
|
||||||
expect(option1.optionMode).toBe(EncounterOptionMode.DEFAULT_OR_SPECIAL);
|
expect(option1.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT_OR_SPECIAL);
|
||||||
expect(option1.dialogue).toBeDefined();
|
expect(option1.dialogue).toBeDefined();
|
||||||
expect(option1.dialogue).toStrictEqual({
|
expect(option1.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
@ -128,7 +130,7 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||||||
const updateMoneySpy = vi.spyOn(EncounterPhaseUtils, "updatePlayerMoney");
|
const updateMoneySpy = vi.spyOn(EncounterPhaseUtils, "updatePlayerMoney");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.POKEMON_SALESMAN, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.POKEMON_SALESMAN, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 1);
|
await runMysteryEncounterToEnd(game, 1);
|
||||||
|
|
||||||
const price = scene.currentBattle.mysteryEncounter.misc.price;
|
const price = scene.currentBattle.mysteryEncounter.misc.price;
|
||||||
|
|
||||||
@ -142,7 +144,7 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||||||
const initialPartySize = scene.getParty().length;
|
const initialPartySize = scene.getParty().length;
|
||||||
const pokemonName = scene.currentBattle.mysteryEncounter.misc.pokemon.name;
|
const pokemonName = scene.currentBattle.mysteryEncounter.misc.pokemon.name;
|
||||||
|
|
||||||
await runSelectMysteryEncounterOption(game, 1);
|
await runMysteryEncounterToEnd(game, 1);
|
||||||
|
|
||||||
expect(scene.getParty().length).toBe(initialPartySize + 1);
|
expect(scene.getParty().length).toBe(initialPartySize + 1);
|
||||||
expect(scene.getParty().find(p => p.name === pokemonName) instanceof PlayerPokemon).toBeTruthy();
|
expect(scene.getParty().find(p => p.name === pokemonName) instanceof PlayerPokemon).toBeTruthy();
|
||||||
@ -152,7 +154,7 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.POKEMON_SALESMAN, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.POKEMON_SALESMAN, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 1);
|
await runMysteryEncounterToEnd(game, 1);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
@ -163,7 +165,7 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.POKEMON_SALESMAN, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.POKEMON_SALESMAN, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 2);
|
await runMysteryEncounterToEnd(game, 2);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
|
@ -4,17 +4,14 @@ import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
|
|||||||
import { Species } from "#app/enums/species";
|
import { Species } from "#app/enums/species";
|
||||||
import GameManager from "#app/test/utils/gameManager";
|
import GameManager from "#app/test/utils/gameManager";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import Battle from "#app/battle";
|
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import * as BattleAnims from "#app/data/battle-anims";
|
import * as BattleAnims from "#app/data/battle-anims";
|
||||||
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { EncounterOptionMode } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils";
|
||||||
import { runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounterTestUtils";
|
|
||||||
import { CommandPhase, MovePhase, SelectModifierPhase } from "#app/phases";
|
import { CommandPhase, MovePhase, SelectModifierPhase } from "#app/phases";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import * as Modifiers from "#app/modifier/modifier";
|
import * as Modifiers from "#app/modifier/modifier";
|
||||||
import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encounter";
|
|
||||||
import { TheStrongStuffEncounter } from "#app/data/mystery-encounters/encounters/the-strong-stuff-encounter";
|
import { TheStrongStuffEncounter } from "#app/data/mystery-encounters/encounters/the-strong-stuff-encounter";
|
||||||
import { Nature } from "#app/data/nature";
|
import { Nature } from "#app/data/nature";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
@ -23,6 +20,9 @@ import { PokemonMove } from "#app/field/pokemon";
|
|||||||
import { Mode } from "#app/ui/ui";
|
import { Mode } from "#app/ui/ui";
|
||||||
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
||||||
import { PokemonBaseStatTotalModifier } from "#app/modifier/modifier";
|
import { PokemonBaseStatTotalModifier } from "#app/modifier/modifier";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils";
|
||||||
|
|
||||||
const namespace = "mysteryEncounter:theStrongStuff";
|
const namespace = "mysteryEncounter:theStrongStuff";
|
||||||
const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA];
|
const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA];
|
||||||
@ -97,7 +97,8 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should initialize fully ", async () => {
|
it("should initialize fully ", async () => {
|
||||||
vi.spyOn(scene, "currentBattle", "get").mockReturnValue({ mysteryEncounter: TheStrongStuffEncounter } as Battle);
|
initSceneWithoutEncounterPhase(scene, defaultParty);
|
||||||
|
scene.currentBattle.mysteryEncounter = TheStrongStuffEncounter;
|
||||||
const moveInitSpy = vi.spyOn(BattleAnims, "loadMoveAnimAssets");
|
const moveInitSpy = vi.spyOn(BattleAnims, "loadMoveAnimAssets");
|
||||||
const moveLoadSpy = vi.spyOn(BattleAnims, "loadMoveAnimAssets");
|
const moveLoadSpy = vi.spyOn(BattleAnims, "loadMoveAnimAssets");
|
||||||
|
|
||||||
@ -105,6 +106,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||||||
|
|
||||||
expect(TheStrongStuffEncounter.onInit).toBeDefined();
|
expect(TheStrongStuffEncounter.onInit).toBeDefined();
|
||||||
|
|
||||||
|
TheStrongStuffEncounter.populateDialogueTokensFromRequirements(scene);
|
||||||
const onInitResult = onInit(scene);
|
const onInitResult = onInit(scene);
|
||||||
|
|
||||||
expect(TheStrongStuffEncounter.enemyPartyConfigs).toEqual([
|
expect(TheStrongStuffEncounter.enemyPartyConfigs).toEqual([
|
||||||
@ -134,7 +136,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||||||
describe("Option 1 - Power Swap BSTs", () => {
|
describe("Option 1 - Power Swap BSTs", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option1 = TheStrongStuffEncounter.options[0];
|
const option1 = TheStrongStuffEncounter.options[0];
|
||||||
expect(option1.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
expect(option1.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
||||||
expect(option1.dialogue).toBeDefined();
|
expect(option1.dialogue).toBeDefined();
|
||||||
expect(option1.dialogue).toStrictEqual({
|
expect(option1.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:1:label`,
|
buttonLabel: `${namespace}:option:1:label`,
|
||||||
@ -151,7 +153,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||||||
await game.runToMysteryEncounter(MysteryEncounterType.THE_STRONG_STUFF, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.THE_STRONG_STUFF, defaultParty);
|
||||||
|
|
||||||
const bstsPrior = scene.getParty().map(p => p.getSpeciesForm().getBaseStatTotal());
|
const bstsPrior = scene.getParty().map(p => p.getSpeciesForm().getBaseStatTotal());
|
||||||
await runSelectMysteryEncounterOption(game, 1);
|
await runMysteryEncounterToEnd(game, 1);
|
||||||
|
|
||||||
const bstsAfter = scene.getParty().map(p => {
|
const bstsAfter = scene.getParty().map(p => {
|
||||||
const baseStats = p.getSpeciesForm().baseStats.slice(0);
|
const baseStats = p.getSpeciesForm().baseStats.slice(0);
|
||||||
@ -168,7 +170,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.THE_STRONG_STUFF, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.THE_STRONG_STUFF, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 1);
|
await runMysteryEncounterToEnd(game, 1);
|
||||||
|
|
||||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||||
});
|
});
|
||||||
@ -177,7 +179,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||||||
describe("Option 2 - battle the Shuckle", () => {
|
describe("Option 2 - battle the Shuckle", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option1 = TheStrongStuffEncounter.options[1];
|
const option1 = TheStrongStuffEncounter.options[1];
|
||||||
expect(option1.optionMode).toBe(EncounterOptionMode.DEFAULT);
|
expect(option1.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
||||||
expect(option1.dialogue).toBeDefined();
|
expect(option1.dialogue).toBeDefined();
|
||||||
expect(option1.dialogue).toStrictEqual({
|
expect(option1.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option:2:label`,
|
buttonLabel: `${namespace}:option:2:label`,
|
||||||
@ -194,7 +196,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||||||
const phaseSpy = vi.spyOn(scene, "pushPhase");
|
const phaseSpy = vi.spyOn(scene, "pushPhase");
|
||||||
|
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.THE_STRONG_STUFF, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.THE_STRONG_STUFF, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 2, true);
|
await runMysteryEncounterToEnd(game, 2, true);
|
||||||
|
|
||||||
const enemyField = scene.getEnemyField();
|
const enemyField = scene.getEnemyField();
|
||||||
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
expect(scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
@ -218,7 +220,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||||||
|
|
||||||
it("should have Soul Dew in rewards", async () => {
|
it("should have Soul Dew in rewards", async () => {
|
||||||
await game.runToMysteryEncounter(MysteryEncounterType.THE_STRONG_STUFF, defaultParty);
|
await game.runToMysteryEncounter(MysteryEncounterType.THE_STRONG_STUFF, defaultParty);
|
||||||
await runSelectMysteryEncounterOption(game, 2, true);
|
await runMysteryEncounterToEnd(game, 2, true);
|
||||||
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
await skipBattleRunMysteryEncounterRewardsPhase(game);
|
||||||
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
await game.phaseInterceptor.to(SelectModifierPhase, false);
|
||||||
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
expect(scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
||||||
|
@ -7,8 +7,8 @@ import {Mode} from "#app/ui/ui";
|
|||||||
import {Button} from "#enums/buttons";
|
import {Button} from "#enums/buttons";
|
||||||
import MysteryEncounterUiHandler from "#app/ui/mystery-encounter-ui-handler";
|
import MysteryEncounterUiHandler from "#app/ui/mystery-encounter-ui-handler";
|
||||||
import {MysteryEncounterType} from "#enums/mystery-encounter-type";
|
import {MysteryEncounterType} from "#enums/mystery-encounter-type";
|
||||||
import {MysteryEncounterTier} from "#app/data/mystery-encounters/mystery-encounter";
|
|
||||||
import MessageUiHandler from "#app/ui/message-ui-handler";
|
import MessageUiHandler from "#app/ui/message-ui-handler";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
|
||||||
describe("Mystery Encounter Phases", () => {
|
describe("Mystery Encounter Phases", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
|
@ -5,9 +5,9 @@ import { MockInstance, vi } from "vitest";
|
|||||||
import GameManager from "#test/utils/gameManager";
|
import GameManager from "#test/utils/gameManager";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import * as overrides from "#app/overrides";
|
import * as overrides from "#app/overrides";
|
||||||
import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encounter";
|
|
||||||
import * as GameMode from "#app/game-mode";
|
import * as GameMode from "#app/game-mode";
|
||||||
import { GameModes, getGameMode } from "#app/game-mode";
|
import { GameModes, getGameMode } from "#app/game-mode";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to handle overrides in tests
|
* Helper to handle overrides in tests
|
||||||
|
@ -11,13 +11,15 @@ import {
|
|||||||
LearnMovePhase,
|
LearnMovePhase,
|
||||||
LoginPhase,
|
LoginPhase,
|
||||||
MessagePhase,
|
MessagePhase,
|
||||||
|
ModifierRewardPhase,
|
||||||
MoveEffectPhase,
|
MoveEffectPhase,
|
||||||
MoveEndPhase,
|
MoveEndPhase,
|
||||||
MovePhase,
|
MovePhase,
|
||||||
NewBattlePhase,
|
NewBattlePhase,
|
||||||
NextEncounterPhase,
|
NextEncounterPhase,
|
||||||
PostSummonPhase,
|
PostSummonPhase,
|
||||||
SelectGenderPhase, SelectModifierPhase,
|
SelectGenderPhase,
|
||||||
|
SelectModifierPhase,
|
||||||
SelectStarterPhase,
|
SelectStarterPhase,
|
||||||
SelectTargetPhase,
|
SelectTargetPhase,
|
||||||
ShinySparklePhase,
|
ShinySparklePhase,
|
||||||
@ -105,6 +107,7 @@ export default class PhaseInterceptor {
|
|||||||
[MysteryEncounterRewardsPhase, this.startPhase],
|
[MysteryEncounterRewardsPhase, this.startPhase],
|
||||||
[PostMysteryEncounterPhase, this.startPhase],
|
[PostMysteryEncounterPhase, this.startPhase],
|
||||||
[LearnMovePhase, this.startPhase],
|
[LearnMovePhase, this.startPhase],
|
||||||
|
[ModifierRewardPhase, this.startPhase],
|
||||||
// [CommonAnimPhase, this.startPhase]
|
// [CommonAnimPhase, this.startPhase]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -6,14 +6,15 @@ import { Button } from "#enums/buttons";
|
|||||||
import { addWindow, WindowVariant } from "./ui-theme";
|
import { addWindow, WindowVariant } from "./ui-theme";
|
||||||
import { MysteryEncounterPhase } from "../phases/mystery-encounter-phases";
|
import { MysteryEncounterPhase } from "../phases/mystery-encounter-phases";
|
||||||
import { PartyUiMode } from "./party-ui-handler";
|
import { PartyUiMode } from "./party-ui-handler";
|
||||||
import MysteryEncounterOption, { EncounterOptionMode } from "../data/mystery-encounters/mystery-encounter-option";
|
import MysteryEncounterOption from "../data/mystery-encounters/mystery-encounter-option";
|
||||||
import * as Utils from "../utils";
|
import * as Utils from "../utils";
|
||||||
import { isNullOrUndefined } from "../utils";
|
import { isNullOrUndefined } from "../utils";
|
||||||
import { getPokeballAtlasKey } from "../data/pokeball";
|
import { getPokeballAtlasKey } from "../data/pokeball";
|
||||||
import { OptionSelectSettings } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import { OptionSelectSettings } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encounter";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
|
||||||
export default class MysteryEncounterUiHandler extends UiHandler {
|
export default class MysteryEncounterUiHandler extends UiHandler {
|
||||||
private cursorContainer: Phaser.GameObjects.Container;
|
private cursorContainer: Phaser.GameObjects.Container;
|
||||||
@ -146,7 +147,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||||||
this.unblockInput();
|
this.unblockInput();
|
||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
} else if (this.blockInput || (!this.optionsMeetsReqs[cursor] && (selected.optionMode === EncounterOptionMode.DISABLED_OR_DEFAULT || selected.optionMode === EncounterOptionMode.DISABLED_OR_SPECIAL))) {
|
} else if (this.blockInput || (!this.optionsMeetsReqs[cursor] && (selected.optionMode === MysteryEncounterOptionMode.DISABLED_OR_DEFAULT || selected.optionMode === MysteryEncounterOptionMode.DISABLED_OR_SPECIAL))) {
|
||||||
success = false;
|
success = false;
|
||||||
} else {
|
} else {
|
||||||
if ((this.scene.getCurrentPhase() as MysteryEncounterPhase).handleOptionSelect(selected, cursor)) {
|
if ((this.scene.getCurrentPhase() as MysteryEncounterPhase).handleOptionSelect(selected, cursor)) {
|
||||||
@ -290,7 +291,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||||||
this.blockInput = false;
|
this.blockInput = false;
|
||||||
for (let i = 0; i < this.optionsContainer.length - 1; i++) {
|
for (let i = 0; i < this.optionsContainer.length - 1; i++) {
|
||||||
const optionMode = this.encounterOptions[i].optionMode;
|
const optionMode = this.encounterOptions[i].optionMode;
|
||||||
if (!this.optionsMeetsReqs[i] && (optionMode === EncounterOptionMode.DISABLED_OR_DEFAULT || optionMode === EncounterOptionMode.DISABLED_OR_SPECIAL)) {
|
if (!this.optionsMeetsReqs[i] && (optionMode === MysteryEncounterOptionMode.DISABLED_OR_DEFAULT || optionMode === MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(this.optionsContainer.getAt(i) as Phaser.GameObjects.Text).setAlpha(1);
|
(this.optionsContainer.getAt(i) as Phaser.GameObjects.Text).setAlpha(1);
|
||||||
@ -363,7 +364,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||||||
const optionDialogue = option.dialogue;
|
const optionDialogue = option.dialogue;
|
||||||
const label = !this.optionsMeetsReqs[i] && optionDialogue.disabledButtonLabel ? optionDialogue.disabledButtonLabel : optionDialogue.buttonLabel;
|
const label = !this.optionsMeetsReqs[i] && optionDialogue.disabledButtonLabel ? optionDialogue.disabledButtonLabel : optionDialogue.buttonLabel;
|
||||||
let text: string;
|
let text: string;
|
||||||
if (option.hasRequirements() && this.optionsMeetsReqs[i] && (option.optionMode === EncounterOptionMode.DEFAULT_OR_SPECIAL || option.optionMode === EncounterOptionMode.DISABLED_OR_SPECIAL)) {
|
if (option.hasRequirements() && this.optionsMeetsReqs[i] && (option.optionMode === MysteryEncounterOptionMode.DEFAULT_OR_SPECIAL || option.optionMode === MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)) {
|
||||||
// Options with special requirements that are met are automatically colored green
|
// Options with special requirements that are met are automatically colored green
|
||||||
text = getEncounterText(this.scene, label, TextStyle.SUMMARY_GREEN);
|
text = getEncounterText(this.scene, label, TextStyle.SUMMARY_GREEN);
|
||||||
} else {
|
} else {
|
||||||
@ -374,7 +375,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||||||
optionText.setText(text);
|
optionText.setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.optionsMeetsReqs[i] && (option.optionMode === EncounterOptionMode.DISABLED_OR_DEFAULT || option.optionMode === EncounterOptionMode.DISABLED_OR_SPECIAL)) {
|
if (!this.optionsMeetsReqs[i] && (option.optionMode === MysteryEncounterOptionMode.DISABLED_OR_DEFAULT || option.optionMode === MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)) {
|
||||||
optionText.setAlpha(0.5);
|
optionText.setAlpha(0.5);
|
||||||
}
|
}
|
||||||
if (this.blockInput) {
|
if (this.blockInput) {
|
||||||
@ -468,7 +469,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||||||
let text: string;
|
let text: string;
|
||||||
const cursorOption = this.encounterOptions[cursor];
|
const cursorOption = this.encounterOptions[cursor];
|
||||||
const optionDialogue = cursorOption.dialogue;
|
const optionDialogue = cursorOption.dialogue;
|
||||||
if (!this.optionsMeetsReqs[cursor] && (cursorOption.optionMode === EncounterOptionMode.DISABLED_OR_DEFAULT || cursorOption.optionMode === EncounterOptionMode.DISABLED_OR_SPECIAL) && optionDialogue.disabledButtonTooltip) {
|
if (!this.optionsMeetsReqs[cursor] && (cursorOption.optionMode === MysteryEncounterOptionMode.DISABLED_OR_DEFAULT || cursorOption.optionMode === MysteryEncounterOptionMode.DISABLED_OR_SPECIAL) && optionDialogue.disabledButtonTooltip) {
|
||||||
text = getEncounterText(this.scene, optionDialogue.disabledButtonTooltip, TextStyle.TOOLTIP_CONTENT);
|
text = getEncounterText(this.scene, optionDialogue.disabledButtonTooltip, TextStyle.TOOLTIP_CONTENT);
|
||||||
} else {
|
} else {
|
||||||
text = getEncounterText(this.scene, optionDialogue.buttonTooltip, TextStyle.TOOLTIP_CONTENT);
|
text = getEncounterText(this.scene, optionDialogue.buttonTooltip, TextStyle.TOOLTIP_CONTENT);
|
||||||
|
Loading…
Reference in New Issue
Block a user