commit latest beta merge updates

This commit is contained in:
ImperialSympathizer 2024-08-20 18:01:47 -04:00
parent 8899fce571
commit 0b698a04a2
8 changed files with 85 additions and 126 deletions

View File

@ -111,6 +111,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER));
clownConfig.setPartyTemplates(clownPartyTemplate);
clownConfig.setDoubleOnly();
// @ts-ignore
clownConfig.partyTemplateFunc = null; // Overrides party template func if it exists
// Generate random ability for Blacephalon from pool
@ -415,7 +416,7 @@ function onYesAbilitySwap(scene: BattleScene, resolve) {
const onPokemonSelected = (pokemon: PlayerPokemon) => {
// Do ability swap
if (!pokemon.mysteryEncounterData) {
pokemon.mysteryEncounterData = new MysteryEncounterPokemonData(null, Abilities.AERILATE);
pokemon.mysteryEncounterData = new MysteryEncounterPokemonData(undefined, Abilities.AERILATE);
}
pokemon.mysteryEncounterData.ability = scene.currentBattle.mysteryEncounter.misc.ability;
scene.currentBattle.mysteryEncounter.setDialogueToken("chosenPokemon", pokemon.getNameToRender());

View File

@ -54,8 +54,8 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
.withOption(
// Option 1: Use a (non fainted) pokemon that can learn Surf to guide you back/
MysteryEncounterOptionBuilder
.withPokemonCanLearnMoveRequirement(OPTION_1_REQUIRED_MOVE)
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
.withPokemonCanLearnMoveRequirement(OPTION_1_REQUIRED_MOVE)
.withDialogue({
buttonLabel: `${namespace}.option.1.label`,
disabledButtonLabel: `${namespace}.option.1.label_disabled`,
@ -73,8 +73,8 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
.withOption(
//Option 2: Use a (non fainted) pokemon that can learn fly to guide you back.
MysteryEncounterOptionBuilder
.withPokemonCanLearnMoveRequirement(OPTION_2_REQUIRED_MOVE)
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
.withPokemonCanLearnMoveRequirement(OPTION_2_REQUIRED_MOVE)
.withDialogue({
buttonLabel: `${namespace}.option.2.label`,
disabledButtonLabel: `${namespace}.option.2.label_disabled`,
@ -131,7 +131,7 @@ async function handlePokemonGuidingYouPhase(scene: BattleScene) {
const laprasSpecies = getPokemonSpecies(Species.LAPRAS);
const { mysteryEncounter } = scene.currentBattle;
if (mysteryEncounter.selectedOption) {
if (mysteryEncounter.selectedOption?.primaryPokemon?.id) {
setEncounterExp(scene, mysteryEncounter.selectedOption.primaryPokemon.id, laprasSpecies.baseExp, true);
} else {
console.warn("Lost at sea: No guide pokemon found but pokemon guides player. huh!?");

View File

@ -8,6 +8,7 @@ import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequiremen
import { CanLearnMoveRequirement, CanLearnMoveRequirementOptions } from "./requirements/can-learn-move-requirement";
import { isNullOrUndefined } from "#app/utils";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
export type OptionPhaseCallback = (scene: BattleScene) => Promise<void | boolean>;
@ -39,7 +40,7 @@ export default class MysteryEncounterOption {
/** Executes after the encounter is over. Usually this will be for calculating dialogueTokens or performing data updates */
onPostOptionPhase?: OptionPhaseCallback;
constructor(option: MysteryEncounterOption) {
constructor(option: MysteryEncounterOption | null) {
Object.assign(this, option);
this.hasDexProgress = !isNullOrUndefined(this.hasDexProgress) ? this.hasDexProgress : false;
this.requirements = this.requirements ? this.requirements : [];
@ -137,41 +138,27 @@ export default class MysteryEncounterOption {
}
}
const baseOption = {
optionMode: MysteryEncounterOptionMode.DEFAULT,
hasDexProgress: false,
requirements: [],
primaryPokemonRequirements: [],
secondaryPokemonRequirements: [],
excludePrimaryFromSecondaryRequirements: true,
};
/* Picks non-optional fields from an "object" type alias and returns a union of literal types (keys) */
type PickNonOptionalFieldsKeys<T> = Exclude<{ [K in Keys<T>]: T extends Record<K, T[K]> ? K : never; }[Keys<T>], undefined>;
// type NonFunctionFieldsKeys<T> = { [K in Keys<T>]: T[K] extends Function ? never : K; }[Keys<T>];
// type FunctionPropertyKeys<T> = { [K in Keys<T>]: T[K] extends Function ? K : never; }[Keys<T>];
/* Extracts keys from T */
type Keys<T> = keyof T;
/* Filters out all optional fields from an "object" type alias, and all function fields */
type PickNonOptionalFields<T> = Pick<T, PickNonOptionalFieldsKeys<T>>;
/* Omits keys that exist in the base object and optional keys on MysteryEncounter, as well as functions on MysteryEncounter */
type OmitBaseAndOptionalKeys<T, B> = Omit<PickNonOptionalFields<T>, Keys<B>>;
export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOption> {
optionMode: MysteryEncounterOptionMode;
optionMode: MysteryEncounterOptionMode = MysteryEncounterOptionMode.DEFAULT;
requirements: EncounterSceneRequirement[] = [];
primaryPokemonRequirements: EncounterPokemonRequirement[] = [];
secondaryPokemonRequirements: EncounterPokemonRequirement[] = [];
excludePrimaryFromSecondaryRequirements: boolean;
isDisabledOnRequirementsNotMet: boolean;
hasDexProgress: boolean;
excludePrimaryFromSecondaryRequirements: boolean = false;
isDisabledOnRequirementsNotMet: boolean = true;
hasDexProgress: boolean = false;
onPreOptionPhase?: OptionPhaseCallback;
onOptionPhase: OptionPhaseCallback;
onPostOptionPhase?: OptionPhaseCallback;
dialogue: OptionTextDisplay;
static newOptionWithMode(optionMode: MysteryEncounterOptionMode): MysteryEncounterOptionBuilder & OmitBaseAndOptionalKeys<MysteryEncounterOption, typeof baseOption> & Pick<MysteryEncounterOption, "optionMode"> {
return Object.assign(new MysteryEncounterOptionBuilder(), { ...baseOption, optionMode });
hasRequirements = MysteryEncounter.prototype["hasRequirements"];
meetsRequirements = MysteryEncounter.prototype["meetsRequirements"];
pokemonMeetsPrimaryRequirements = MysteryEncounter.prototype["pokemonMeetsPrimaryRequirements"];
meetsPrimaryRequirementAndPrimaryPokemonSelected = MysteryEncounter.prototype["meetsPrimaryRequirementAndPrimaryPokemonSelected"];
meetsSupportingRequirementAndSupportingPokemonSelected = MysteryEncounter.prototype["meetsSupportingRequirementAndSupportingPokemonSelected"];
static newOptionWithMode(optionMode: MysteryEncounterOptionMode): MysteryEncounterOptionBuilder & Pick<MysteryEncounterOption, "optionMode"> {
return Object.assign(new MysteryEncounterOptionBuilder(), { optionMode });
}
withHasDexProgress(hasDexProgress: boolean): this & Required<Pick<MysteryEncounterOption, "hasDexProgress">> {

View File

@ -2,15 +2,15 @@ import { Abilities } from "#enums/abilities";
import { Type } from "#app/data/type";
export class MysteryEncounterPokemonData {
public spriteScale: number;
public ability: Abilities;
public passive: Abilities;
public types: Type[] = [];
public spriteScale: number | undefined;
public ability: Abilities | undefined;
public passive: Abilities | undefined;
public types: Type[];
constructor(spriteScale?: number, ability?: Abilities, passive?: Abilities, types?: Type[]) {
this.spriteScale = spriteScale;
this.ability = ability;
this.passive = passive;
this.types = types;
this.types = types ?? [];
}
}

View File

@ -48,7 +48,7 @@ export class CombinationSceneRequirement extends EncounterSceneRequirement {
}
}
return null;
return this.orRequirements[0].getDialogueToken(scene, pokemon);
}
}
@ -104,7 +104,7 @@ export class CombinationPokemonRequirement extends EncounterPokemonRequirement {
}
}
return null;
return this.orRequirements[0].getDialogueToken(scene, pokemon);
}
}
@ -125,7 +125,7 @@ export class PreviousEncounterRequirement extends EncounterSceneRequirement {
}
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
return ["previousEncounter", scene.mysteryEncounterData.encounteredEvents.find(e => e[0] === this.previousEncounterRequirement)[0].toString()];
return ["previousEncounter", scene.mysteryEncounterData.encounteredEvents.find(e => e[0] === this.previousEncounterRequirement)?.[0].toString() ?? ""];
}
}
@ -158,7 +158,7 @@ export class WaveRangeRequirement extends EncounterSceneRequirement {
}
export class TimeOfDayRequirement extends EncounterSceneRequirement {
requiredTimeOfDay?: TimeOfDay[];
requiredTimeOfDay: TimeOfDay[];
constructor(timeOfDay: TimeOfDay | TimeOfDay[]) {
super();
@ -180,7 +180,7 @@ export class TimeOfDayRequirement extends EncounterSceneRequirement {
}
export class WeatherRequirement extends EncounterSceneRequirement {
requiredWeather?: WeatherType[];
requiredWeather: WeatherType[];
constructor(weather: WeatherType | WeatherType[]) {
super();
@ -188,8 +188,8 @@ export class WeatherRequirement extends EncounterSceneRequirement {
}
meetsRequirement(scene: BattleScene): boolean {
const currentWeather = scene.arena?.weather?.weatherType;
if (!isNullOrUndefined(currentWeather) && this?.requiredWeather?.length > 0 && !this.requiredWeather.includes(currentWeather)) {
const currentWeather = scene.arena.weather?.weatherType;
if (!isNullOrUndefined(currentWeather) && this?.requiredWeather?.length > 0 && !this.requiredWeather.includes(currentWeather!)) {
return false;
}
@ -197,7 +197,12 @@ export class WeatherRequirement extends EncounterSceneRequirement {
}
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
return ["weather", WeatherType[scene.arena?.weather?.weatherType].replace("_", " ").toLocaleLowerCase()];
const currentWeather = scene.arena.weather?.weatherType;
let token = "";
if (!isNullOrUndefined(currentWeather)) {
token = WeatherType[currentWeather!].replace("_", " ").toLocaleLowerCase();
}
return ["weather", token];
}
}
@ -262,10 +267,7 @@ export class PersistentModifierRequirement extends EncounterSceneRequirement {
}
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
if (this.requiredHeldItemModifiers.length > 0) {
return ["requiredItem", this.requiredHeldItemModifiers[0]];
}
return null;
return ["requiredItem", this.requiredHeldItemModifiers[0]];
}
}
@ -327,10 +329,10 @@ export class SpeciesRequirement extends EncounterPokemonRequirement {
}
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
if (this.requiredSpecies.includes(pokemon.species.speciesId)) {
if (pokemon?.species.speciesId && this.requiredSpecies.includes(pokemon.species.speciesId)) {
return ["species", Species[pokemon.species.speciesId]];
}
return null;
return ["species", ""];
}
}
@ -410,11 +412,11 @@ export class TypeRequirement extends EncounterPokemonRequirement {
}
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
const includedTypes = this.requiredType.filter((ty) => pokemon.getTypes().includes(ty));
const includedTypes = this.requiredType.filter((ty) => pokemon?.getTypes().includes(ty));
if (includedTypes.length > 0) {
return ["type", Type[includedTypes[0]]];
}
return null;
return ["type", ""];
}
}
@ -441,19 +443,19 @@ export class MoveRequirement extends EncounterPokemonRequirement {
queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
if (!this.invertQuery) {
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((reqMove) => pokemon.moveset.filter((move) => move.moveId === reqMove).length > 0).length > 0);
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((reqMove) => pokemon.moveset.filter((move) => move?.moveId === reqMove).length > 0).length > 0);
} else {
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed moves
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((reqMove) => pokemon.moveset.filter((move) => move.moveId === reqMove).length === 0).length === 0);
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((reqMove) => pokemon.moveset.filter((move) => move?.moveId === reqMove).length === 0).length === 0);
}
}
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
const includedMoves = pokemon.moveset.filter((move) => this.requiredMoves.includes(move.moveId));
if (includedMoves.length > 0) {
const includedMoves = pokemon?.moveset.filter((move) => move?.moveId && this.requiredMoves.includes(move.moveId));
if (includedMoves && includedMoves.length > 0 && includedMoves[0]) {
return ["move", includedMoves[0].getName()];
}
return null;
return ["move", ""];
}
}
@ -485,19 +487,19 @@ export class CompatibleMoveRequirement extends EncounterPokemonRequirement {
queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
if (!this.invertQuery) {
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((learnableMove) => pokemon.compatibleTms.filter(tm => !pokemon.moveset.find(m => m.moveId === tm)).includes(learnableMove)).length > 0);
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((learnableMove) => pokemon.compatibleTms.filter(tm => !pokemon.moveset.find(m => m?.moveId === tm)).includes(learnableMove)).length > 0);
} else {
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed learnableMoves
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((learnableMove) => pokemon.compatibleTms.filter(tm => !pokemon.moveset.find(m => m.moveId === tm)).includes(learnableMove)).length === 0);
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((learnableMove) => pokemon.compatibleTms.filter(tm => !pokemon.moveset.find(m => m?.moveId === tm)).includes(learnableMove)).length === 0);
}
}
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
const includedCompatMoves = this.requiredMoves.filter((reqMove) => pokemon.compatibleTms.filter((tm) => !pokemon.moveset.find(m => m.moveId === tm)).includes(reqMove));
const includedCompatMoves = this.requiredMoves.filter((reqMove) => pokemon?.compatibleTms.filter((tm) => !pokemon.moveset.find(m => m?.moveId === tm)).includes(reqMove));
if (includedCompatMoves.length > 0) {
return ["compatibleMove", Moves[includedCompatMoves[0]]];
}
return null;
return ["compatibleMove", ""];
}
}
@ -572,10 +574,10 @@ export class AbilityRequirement extends EncounterPokemonRequirement {
}
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
if (this.requiredAbilities.some(a => pokemon.getAbility().id === a)) {
if (pokemon?.getAbility().id && this.requiredAbilities.some(a => pokemon.getAbility().id === a)) {
return ["ability", pokemon.getAbility().name];
}
return null;
return ["ability", ""];
}
}
@ -607,7 +609,7 @@ export class StatusEffectRequirement extends EncounterPokemonRequirement {
return this.requiredStatusEffect.some((statusEffect) => {
if (statusEffect === StatusEffect.NONE) {
// StatusEffect.NONE also checks for null or undefined status
return isNullOrUndefined(pokemon.status) || isNullOrUndefined(pokemon.status.effect) || pokemon.status?.effect === statusEffect;
return isNullOrUndefined(pokemon.status) || isNullOrUndefined(pokemon.status!.effect) || pokemon.status?.effect === statusEffect;
} else {
return pokemon.status?.effect === statusEffect;
}
@ -639,7 +641,7 @@ export class StatusEffectRequirement extends EncounterPokemonRequirement {
if (reqStatus.length > 0) {
return ["status", StatusEffect[reqStatus[0]]];
}
return null;
return ["status", ""];
}
}

View File

@ -1,6 +1,6 @@
import { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import Pokemon, { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { isNullOrUndefined } from "#app/utils";
import { capitalizeFirstLetter, isNullOrUndefined } from "#app/utils";
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene";
import MysteryEncounterIntroVisuals, { MysteryEncounterSpriteConfig } from "#app/field/mystery-encounter-intro";
@ -125,17 +125,17 @@ export default class MysteryEncounter implements IMysteryEncounter {
/**
* Dialogue object containing all the dialogue, messages, tooltips, etc. for an encounter
*/
dialogue?: MysteryEncounterDialogue;
dialogue: MysteryEncounterDialogue;
/**
* Data used for setting up/initializing enemy party in battles
* Can store multiple configs so that one can be chosen based on option selected
* Should usually be defined in `onInit()` or `onPreOptionPhase()`
*/
enemyPartyConfigs?: EnemyPartyConfig[];
enemyPartyConfigs: EnemyPartyConfig[];
/**
* Object instance containing sprite data for an encounter when it is being spawned
* Otherwise, will be undefined
* You probably shouldn't do anything with this unless you have a very specific need
* You probably shouldn't do anything directly with this unless you have a very specific need
*/
introVisuals?: MysteryEncounterIntroVisuals;
@ -233,7 +233,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
return !this.primaryPokemonRequirements.some(req => !req.queryParty(scene.getParty()).map(p => p.id).includes(pokemon.id));
}
private meetsPrimaryRequirementAndPrimaryPokemonSelected(scene: BattleScene): boolean {
meetsPrimaryRequirementAndPrimaryPokemonSelected(scene: BattleScene): boolean {
if (this.primaryPokemonRequirements.length === 0) {
const activeMon = scene.getParty().filter(p => p.isActive(true));
if (activeMon.length > 0) {
@ -290,7 +290,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
}
}
private meetsSecondaryRequirementAndSecondaryPokemonSelected(scene: BattleScene): boolean {
meetsSecondaryRequirementAndSecondaryPokemonSelected(scene: BattleScene): boolean {
if (!this.secondaryPokemonRequirements) {
this.secondaryPokemon = [];
return true;
@ -338,7 +338,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
if (!req.invertQuery) {
const value = req.getDialogueToken(scene, this.primaryPokemon);
if (value?.length === 2) {
this.setDialogueToken("primary" + this.capitalizeFirstLetter(value[0]), value[1]);
this.setDialogueToken("primary" + capitalizeFirstLetter(value[0]), value[1]);
}
}
}
@ -349,9 +349,9 @@ export default class MysteryEncounter implements IMysteryEncounter {
if (!req.invertQuery) {
const value = req.getDialogueToken(scene, this.secondaryPokemon[0]);
if (value?.length === 2) {
this.setDialogueToken("primary" + this.capitalizeFirstLetter(value[0]), value[1]);
this.setDialogueToken("primary" + capitalizeFirstLetter(value[0]), value[1]);
}
this.setDialogueToken("secondary" + this.capitalizeFirstLetter(value[0]), value[1]);
this.setDialogueToken("secondary" + capitalizeFirstLetter(value[0]), value[1]);
}
}
}
@ -365,7 +365,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
for (const req of opt.requirements) {
const dialogueToken = req.getDialogueToken(scene);
if (dialogueToken?.length === 2) {
this.setDialogueToken("option" + j + this.capitalizeFirstLetter(dialogueToken[0]), dialogueToken[1]);
this.setDialogueToken("option" + j + capitalizeFirstLetter(dialogueToken[0]), dialogueToken[1]);
}
}
}
@ -375,7 +375,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
if (!req.invertQuery) {
const value = req.getDialogueToken(scene, opt.primaryPokemon);
if (value?.length === 2) {
this.setDialogueToken("option" + j + "Primary" + this.capitalizeFirstLetter(value[0]), value[1]);
this.setDialogueToken("option" + j + "Primary" + capitalizeFirstLetter(value[0]), value[1]);
}
}
}
@ -386,7 +386,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
if (!req.invertQuery) {
const value = req.getDialogueToken(scene, opt.secondaryPokemon[0]);
if (value?.length === 2) {
this.setDialogueToken("option" + j + "Secondary" + this.capitalizeFirstLetter(value[0]), value[1]);
this.setDialogueToken("option" + j + "Secondary" + capitalizeFirstLetter(value[0]), value[1]);
}
}
}
@ -418,42 +418,8 @@ export default class MysteryEncounter implements IMysteryEncounter {
const currentOffset = this.seedOffset ?? scene.currentBattle.waveIndex * 1000;
this.seedOffset = currentOffset + 512;
}
private capitalizeFirstLetter(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
}
const baseMysteryEncounter = {
hideBattleIntroMessage: false,
autoHideIntroVisuals: true,
enterIntroVisualsFromRight: false,
catchAllowed: false,
continuousEncounter: false,
maxAllowedEncounters: 3,
requirements: [],
primaryPokemonRequirements: [],
secondaryPokemonRequirements: [],
excludePrimaryFromSupportRequirements: true,
dialogueTokens: new Map<string, string>(),
encounterMode: MysteryEncounterMode.DEFAULT,
lockEncounterRewardTiers: false,
startOfBattleEffectsComplete: false,
expMultiplier: 1,
};
/* Picks non-optional fields from an "object" type alias and returns a union of literal types (keys) */
type PickNonOptionalFieldsKeys<T> = Exclude<{ [K in Keys<T>]: T extends Record<K, T[K]> ? K : never; }[Keys<T>], undefined>;
// type NonFunctionFieldsKeys<T> = { [K in Keys<T>]: T[K] extends Function ? never : K; }[Keys<T>];
// type FunctionPropertyKeys<T> = { [K in Keys<T>]: T[K] extends Function ? K : never; }[Keys<T>];
/* Extracts keys from T */
type Keys<T> = keyof T;
/* Filters out all optional fields from an "object" type alias, and all function fields */
type PickNonOptionalFields<T> = Pick<T, PickNonOptionalFieldsKeys<T>>;
/* Omits keys that exist in the base object and optional keys on MysteryEncounter, as well as functions on MysteryEncounter */
type OmitBaseAndOptionalKeys<T, B> = Omit<PickNonOptionalFields<T>, Keys<B>>;
// type OmitBaseSuppliedAndOptionalKeys<T, B, S> = Omit<OmitBaseAndOptionalKeys<T, B>, Keys<S>>;
/**
* Builder class for creating a MysteryEncounter
* must call `build()` at the end after specifying all params for the MysteryEncounter
@ -461,8 +427,9 @@ type OmitBaseAndOptionalKeys<T, B> = Omit<PickNonOptionalFields<T>, Keys<B>>;
export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
encounterType: MysteryEncounterType;
encounterMode: MysteryEncounterMode;
options: [MysteryEncounterOption, MysteryEncounterOption, ...MysteryEncounterOption[]];
options: [MysteryEncounterOption, MysteryEncounterOption, ...MysteryEncounterOption[]] = [new MysteryEncounterOption(null), new MysteryEncounterOption(null)];
spriteConfigs: MysteryEncounterSpriteConfig[];
enemyPartyConfigs: EnemyPartyConfig[] = [];
dialogue: MysteryEncounterDialogue = {};
encounterTier: MysteryEncounterTier;
@ -478,15 +445,15 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
onInit?: (scene: BattleScene) => boolean;
onVisualsStart?: (scene: BattleScene) => boolean;
hideBattleIntroMessage: boolean;
hideIntroVisuals: boolean;
enterIntroVisualsFromRight: boolean;
continuousEncounter: boolean;
catchAllowed: boolean;
lockEncounterRewardTiers: boolean;
startOfBattleEffectsComplete: boolean;
maxAllowedEncounters: number;
expMultiplier: number;
hideBattleIntroMessage: boolean = false;
autoHideIntroVisuals: boolean = true;
enterIntroVisualsFromRight: boolean = false;
continuousEncounter: boolean = false;
catchAllowed: boolean = false;
lockEncounterRewardTiers: boolean = false;
startOfBattleEffectsComplete: boolean = false;
maxAllowedEncounters: number = 3;
expMultiplier: number = 1;
/**
* Builder class has to re-declare the {@link MysteryEncounter} class functions so
@ -502,7 +469,6 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
updateSeedOffset = MysteryEncounter.prototype["updateSeedOffset"];
meetsPrimaryRequirementAndPrimaryPokemonSelected = MysteryEncounter.prototype["meetsPrimaryRequirementAndPrimaryPokemonSelected"];
meetsSecondaryRequirementAndSecondaryPokemonSelected = MysteryEncounter.prototype["meetsSecondaryRequirementAndSecondaryPokemonSelected"];
capitalizeFirstLetter = MysteryEncounter.prototype["capitalizeFirstLetter"];
/**
* REQUIRED
@ -514,15 +480,14 @@ export class MysteryEncounterBuilder implements Partial<MysteryEncounter> {
* @param encounterType
* @returns this
*/
static withEncounterType(encounterType: MysteryEncounterType): MysteryEncounterBuilder & OmitBaseAndOptionalKeys<MysteryEncounter, typeof baseMysteryEncounter> & Pick<MysteryEncounter, "encounterType"> {
return Object.assign(new MysteryEncounterBuilder(), { ...baseMysteryEncounter, encounterType });
static withEncounterType(encounterType: MysteryEncounterType): MysteryEncounterBuilder & Pick<MysteryEncounter, "encounterType"> {
return Object.assign(new MysteryEncounterBuilder(), { encounterType });
}
/**
* Defines an option for the encounter.
* Use for complex options.
* There should be at least 2 options defined and no more than 4.
* If easy/streamlined use {@linkcode MysteryEncounterBuilder.withOptionPhase}
*
* @param option - MysteryEncounterOption to add, can use MysteryEncounterOptionBuilder to create instance
* @returns

View File

@ -552,7 +552,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
duration: 750,
onComplete: () => {
this.dexProgressContainer.on("pointerover", () => {
(this.scene as BattleScene).ui.showTooltip(null, i18next.t("mysteryEncounter:affects_pokedex"), true);
(this.scene as BattleScene).ui.showTooltip("", i18next.t("mysteryEncounter:affects_pokedex"), true);
});
this.dexProgressContainer.on("pointerout", () => {
(this.scene as BattleScene).ui.hideTooltip();

View File

@ -560,3 +560,7 @@ export function capitalizeString(str: string, sep: string, lowerFirstChar: boole
export function isNullOrUndefined(object: any): boolean {
return null === object || undefined === object;
}
export function capitalizeFirstLetter(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
}