Merge branch 'mystery-battle-events' into event/getting-lost-at-the-sea

This commit is contained in:
Felix Staud 2024-07-12 14:08:52 -07:00
commit b95e9cbfa4
10 changed files with 96 additions and 104 deletions

View File

@ -162,11 +162,7 @@ export const TrainingSessionEncounter: IMysteryEncounter =
scene.addModifier(mod, true, false, false, true);
}
scene.updateModifiers(true);
scene.queueMessage(
getEncounterText(scene, `${namespace}_battle_finished_1`),
null,
true
);
scene.queueMessage(getEncounterText(scene, `${namespace}_battle_finished_1`), null, true);
};
setEncounterRewards(
@ -337,11 +333,7 @@ export const TrainingSessionEncounter: IMysteryEncounter =
scene.removePokemonFromPlayerParty(playerPokemon, false);
const onBeforeRewardsPhase = () => {
scene.queueMessage(
getEncounterText(scene, `${namespace}_battle_finished_3`),
null,
true
);
scene.queueMessage(getEncounterText(scene, `${namespace}_battle_finished_3`), null, true);
// Add the pokemon back to party with ability change
const abilityIndex = encounter.misc.abilityIndex;
if (!!playerPokemon.getFusionSpeciesForm()) {

View File

@ -1,24 +1,24 @@
import { TextStyle } from "#app/ui/text";
export class TextDisplay {
speaker?: TemplateStringsArray | `mysteryEncounter:${string}`;
text: TemplateStringsArray | `mysteryEncounter:${string}`;
speaker?: string;
text: string;
style?: TextStyle;
}
export class OptionTextDisplay {
buttonLabel: TemplateStringsArray | `mysteryEncounter:${string}`;
buttonTooltip?: TemplateStringsArray | `mysteryEncounter:${string}`;
disabledTooltip?: TemplateStringsArray | `mysteryEncounter:${string}`;
secondOptionPrompt?: TemplateStringsArray | `mysteryEncounter:${string}`;
buttonLabel: string;
buttonTooltip?: string;
disabledTooltip?: string;
secondOptionPrompt?: string;
selected?: TextDisplay[];
style?: TextStyle;
}
export class EncounterOptionsDialogue {
title?: TemplateStringsArray | `mysteryEncounter:${string}`;
description?: TemplateStringsArray | `mysteryEncounter:${string}`;
query?: TemplateStringsArray | `mysteryEncounter:${string}`;
title?: string;
description?: string;
query?: string;
options?: [...OptionTextDisplay[]]; // Options array with minimum 2 options
}

View File

@ -36,13 +36,14 @@ export abstract class EncounterPokemonRequirement implements EncounterRequiremen
abstract meetsRequirement(scene: BattleScene): boolean;
// 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
*/
queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
return [];
}
// Doesn't require the "@ec" as prefix, just the string; populates the token with the attribute
// ex. @ec{primarySpecies} if strPrefix is simply "primary"
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
return ["", ""];
}
@ -237,8 +238,7 @@ export class MoneyRequirement extends EncounterSceneRequirement {
getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
const value = this?.scalingMultiplier > 0 ? scene.getWaveMoneyAmount(this.scalingMultiplier).toString() : this.requiredMoney.toString();
// Colors money text
return ["money", "@[MONEY]{₽" + value + "}"];
return ["money", value];
}
}

View File

@ -1,32 +1,32 @@
import i18next, { ParseKeys } from "i18next";
import { BattleType } from "#app/battle";
import BattleScene from "../../battle-scene";
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "../pokemon-species";
import { MysteryEncounterVariant } from "./mystery-encounter";
import { Status, StatusEffect } from "../status-effect";
import { TrainerConfig, trainerConfigs, TrainerSlot } from "../trainer-config";
import { biomeLinks } from "#app/data/biomes";
import { WIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
import { Type } from "#app/data/type";
import Pokemon, { FieldPosition, PlayerPokemon } from "#app/field/pokemon";
import Trainer, { TrainerVariant } from "../../field/trainer";
import { ExpBalanceModifier, ExpShareModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier } from "#app/modifier/modifier";
import { CustomModifierSettings, getModifierPoolForType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeGenerator, ModifierTypeOption, modifierTypes, PokemonHeldItemModifierType, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
import { CustomModifierSettings, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeGenerator, ModifierTypeOption, PokemonHeldItemModifierType, getModifierPoolForType, modifierTypes, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
import * as Overrides from "#app/overrides";
import { BattleEndPhase, EggLapsePhase, ExpPhase, ModifierRewardPhase, SelectModifierPhase, ShowPartyExpBarPhase, TrainerVictoryPhase } from "#app/phases";
import { MysteryEncounterBattlePhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phase";
import * as Utils from "../../utils";
import { isNullOrUndefined } from "#app/utils";
import { TrainerType } from "#enums/trainer-type";
import { Species } from "#enums/species";
import { Type } from "#app/data/type";
import { BattlerTagType } from "#enums/battler-tag-type";
import PokemonData from "#app/system/pokemon-data";
import { Biome } from "#enums/biome";
import { biomeLinks } from "#app/data/biomes";
import { Mode } from "#app/ui/ui";
import { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler";
import { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import { WIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
import { getTextWithColors, TextStyle } from "#app/ui/text";
import * as Overrides from "#app/overrides";
import { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler";
import { TextStyle, getTextWithColors } from "#app/ui/text";
import { Mode } from "#app/ui/ui";
import { isNullOrUndefined } from "#app/utils";
import { BattlerTagType } from "#enums/battler-tag-type";
import { Biome } from "#enums/biome";
import { Species } from "#enums/species";
import { TrainerType } from "#enums/trainer-type";
import { UiTheme } from "#enums/ui-theme";
import i18next from "i18next";
import BattleScene from "../../battle-scene";
import Trainer, { TrainerVariant } from "../../field/trainer";
import * as Utils from "../../utils";
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "../pokemon-species";
import { Status, StatusEffect } from "../status-effect";
import { TrainerConfig, TrainerSlot, trainerConfigs } from "../trainer-config";
import { MysteryEncounterVariant } from "./mystery-encounter";
/**
*
@ -158,12 +158,14 @@ export function koPlayerPokemon(pokemon: PlayerPokemon) {
pokemon.updateInfo();
}
export function getEncounterText(scene: BattleScene, textKey: TemplateStringsArray | `mysteryEncounter:${string}`, primaryStyle?: TextStyle, uiTheme: UiTheme = UiTheme.DEFAULT): string {
export function getEncounterText(scene: BattleScene, textKey: string, primaryStyle?: TextStyle, uiTheme: UiTheme = UiTheme.DEFAULT): string {
if (isNullOrUndefined(textKey)) {
return null;
}
let textString: string = getTextWithDialogueTokens(scene, textKey);
const stringArray = [`${textKey}`] as any;
stringArray.raw = [`${textKey}`];
let textString: string = getTextWithDialogueTokens(scene, stringArray);
// Can only color the text if a Primary Style is defined
// primaryStyle is applied to all text that does not have its own specified style
@ -174,22 +176,12 @@ export function getEncounterText(scene: BattleScene, textKey: TemplateStringsArr
return textString;
}
function getTextWithDialogueTokens(scene: BattleScene, textKey: TemplateStringsArray | `mysteryEncounter:${string}`): string {
function getTextWithDialogueTokens(scene: BattleScene, textKey: TemplateStringsArray): string {
if (isNullOrUndefined(textKey)) {
return null;
}
let textString: string = i18next.t(textKey as ParseKeys);
// Apply dialogue tokens
const dialogueTokens = scene.currentBattle?.mysteryEncounter?.dialogueTokens;
if (dialogueTokens) {
dialogueTokens.forEach((value) => {
textString = textString.replace(value[0], value[1]);
});
}
return textString;
return i18next.t(textKey, scene.currentBattle?.mysteryEncounter?.dialogueTokens);
}
/**
@ -197,7 +189,7 @@ function getTextWithDialogueTokens(scene: BattleScene, textKey: TemplateStringsA
* @param scene
* @param contentKey
*/
export function queueEncounterMessage(scene: BattleScene, contentKey: TemplateStringsArray | `mysteryEncounter:${string}`): void {
export function queueEncounterMessage(scene: BattleScene, contentKey: string): void {
const text: string = getEncounterText(scene, contentKey);
scene.queueMessage(text, null, true);
}
@ -207,7 +199,7 @@ export function queueEncounterMessage(scene: BattleScene, contentKey: TemplateSt
* @param scene
* @param contentKey
*/
export function showEncounterText(scene: BattleScene, contentKey: TemplateStringsArray | `mysteryEncounter:${string}`): Promise<void> {
export function showEncounterText(scene: BattleScene, contentKey: string): Promise<void> {
return new Promise<void>(resolve => {
const text: string = getEncounterText(scene, contentKey);
scene.ui.showText(text, null, () => resolve(), 0, true);
@ -221,7 +213,7 @@ export function showEncounterText(scene: BattleScene, contentKey: TemplateString
* @param speakerContentKey
* @param callback
*/
export function showEncounterDialogue(scene: BattleScene, textContentKey: TemplateStringsArray | `mysteryEncounter:${string}`, speakerContentKey: TemplateStringsArray | `mysteryEncounter:${string}`, callback?: Function) {
export function showEncounterDialogue(scene: BattleScene, textContentKey: string, speakerContentKey: string, callback?: Function) {
const text: string = getEncounterText(scene, textContentKey);
const speaker: string = getEncounterText(scene, speakerContentKey);
scene.ui.showDialogue(text, speaker, null, callback, 0, 0);

View File

@ -95,7 +95,7 @@ export default interface IMysteryEncounter {
* Can be set for uses programatic dialogue during an encounter (storing the name of one of the party's pokemon, etc.)
* Example use: see MYSTERIOUS_CHEST
*/
dialogueTokens?: Map<string, [RegExp, string]>;
dialogueTokens?: Record<string, string>;
/**
* Should be set depending upon option selected as part of an encounter
* For example, if there is no battle as part of the encounter/selected option, should be set to NO_BATTLE
@ -144,7 +144,7 @@ export default class IMysteryEncounter implements IMysteryEncounter {
// Reset any dirty flags or encounter data
this.lockEncounterRewardTiers = true;
this.dialogueTokens = new Map<string, [RegExp, string]>;
this.dialogueTokens = {};
this.enemyPartyConfigs = [];
this.introVisuals = null;
this.misc = null;
@ -331,7 +331,7 @@ export default class IMysteryEncounter implements IMysteryEncounter {
}
setDialogueToken?(key: string, value: string) {
this.dialogueTokens.set(key, [new RegExp("@ec\{" + key + "\\}", "gi"), value]);
this.dialogueTokens[key] = value;
}
private capitalizeFirstLetter?(str: string) {
@ -350,7 +350,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
primaryPokemonRequirements?: EncounterPokemonRequirement[] = [];
secondaryPokemonRequirements ?: EncounterPokemonRequirement[] = [];
excludePrimaryFromSupportRequirements?: boolean;
dialogueTokens?: Map<string, [RegExp, string]>;
dialogueTokens?: Record<string, string>;
doEncounterExp?: (scene: BattleScene) => boolean;
doEncounterRewards?: (scene: BattleScene) => boolean;
onInit?: (scene: BattleScene) => boolean;
@ -607,7 +607,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
* @param title - title of the encounter
* @returns
*/
withTitle(title: TemplateStringsArray | `mysteryEncounter:${string}`) {
withTitle(title: string) {
const encounterOptionsDialogue = this.dialogue.encounterOptionsDialogue ?? {};
this.dialogue = {
@ -627,7 +627,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
* @param description - description of the encounter
* @returns
*/
withDescription(description: TemplateStringsArray | `mysteryEncounter:${string}`) {
withDescription(description: string) {
const encounterOptionsDialogue = this.dialogue.encounterOptionsDialogue ?? {};
this.dialogue = {
@ -647,7 +647,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
* @param query - query to use for the encounter
* @returns
*/
withQuery(query: TemplateStringsArray | `mysteryEncounter:${string}`) {
withQuery(query: string) {
const encounterOptionsDialogue = this.dialogue.encounterOptionsDialogue ?? {};
this.dialogue = {

View File

@ -5,7 +5,8 @@ import { lostAtSea } from "./mystery-encounters/lost-at-sea";
* '$' will be treated as a new line for Message and Dialogue strings
* '@d{<number>}' will add a time delay to text animation for Message and Dialogue strings
*
* '@ec{<token>}' will auto-inject the matching token value for the specified Encounter
* '{{<token>}}' will auto-inject the matching token value for the specified Encounter that is stored in dialogueTokens
* (see [i18next interpolations](https://www.i18next.com/translation-function/interpolation))
*
* '@[<TextStyle>]{<text>}' will auto-color the given text to a specified TextStyle (e.g. TextStyle.SUMMARY_GREEN)
*
@ -14,7 +15,7 @@ import { lostAtSea } from "./mystery-encounters/lost-at-sea";
*/
export const mysteryEncounter = {
// DO NOT REMOVE
"unit_test_dialogue": "@ec{test}@ec{test} @ec{test@ec{test}} @ec{test1} @ec{test\} @ec{test\\} @ec{test\\\} {test}",
"unit_test_dialogue": "{{test}}{{test}} {{test{{test}}}} {{test1}} {{test\}} {{test\\}} {{test\\\}} {test}}",
// Mystery Encounters -- Common Tier
@ -33,7 +34,7 @@ export const mysteryEncounter = {
"mysterious_chest_option_1_great_result": "A couple great tools and items!",
"mysterious_chest_option_1_amazing_result": "Whoa! An amazing item!",
"mysterious_chest_option_1_bad_result": `Oh no!@d{32}\nThe chest was trapped!
$Your @ec{pokeName} jumps in front of you\nbut is KOed in the process.`,
$Your {{pokeName}} jumps in front of you\nbut is KOed in the process.`,
"fight_or_flight_intro_message": "Something shiny is sparkling\non the ground near that Pokémon!",
"fight_or_flight_title": "Fight or Flight",
@ -43,18 +44,18 @@ export const mysteryEncounter = {
"fight_or_flight_option_1_tooltip": "(-) Hard Battle\n(+) New Item",
"fight_or_flight_option_2_label": "Steal the item",
"fight_or_flight_option_2_tooltip": "@[SUMMARY_GREEN]{(35%) Steal Item}\n@[SUMMARY_BLUE]{(65%) Harder Battle}",
"fight_or_flight_option_2_steal_tooltip": "(+) @ec{option2PrimaryName} uses @ec{option2PrimaryMove}",
"fight_or_flight_option_2_steal_tooltip": "(+) {{option2PrimaryName}} uses {{option2PrimaryMove}}",
"fight_or_flight_option_3_label": "Leave",
"fight_or_flight_option_3_tooltip": "(-) No Rewards",
"fight_or_flight_option_1_selected_message": "You approach the\nPokémon without fear.",
"fight_or_flight_option_2_good_result": `.@d{32}.@d{32}.@d{32}
$You manage to sneak your way\npast and grab the item!`,
"fight_or_flight_option_2_steal_result": `.@d{32}.@d{32}.@d{32}
$Your @ec{option2PrimaryName} helps you out and uses @ec{option2PrimaryMove}!
$Your {{option2PrimaryName}} helps you out and uses {{option2PrimaryMove}}!
$ You nabbed the item!`,
"fight_or_flight_option_2_bad_result": `.@d{32}.@d{32}.@d{32}
$The Pokémon catches you\nas you try to sneak around!`,
"fight_or_flight_boss_enraged": "The opposing @ec{enemyPokemon} has become enraged!",
"fight_or_flight_boss_enraged": "The opposing {{enemyPokemon}} has become enraged!",
"fight_or_flight_option_3_selected": "You leave the strong Pokémon\nwith its prize and continue on.",
"department_store_sale_intro_message": "It's a lady with a ton of shopping bags.",
@ -85,17 +86,17 @@ export const mysteryEncounter = {
"shady_vitamin_dealer_query": "Which deal will choose?",
"shady_vitamin_dealer_invalid_selection": "Pokémon must be healthy enough.",
"shady_vitamin_dealer_option_1_label": "The Cheap Deal",
"shady_vitamin_dealer_option_1_tooltip": "(-) Pay @ec{option1Money}\n(-) Side Effects?\n(+) Chosen Pokémon Gains 2 Random Vitamins",
"shady_vitamin_dealer_option_1_tooltip": "(-) Pay {{option1Money, money}}\n(-) Side Effects?\n(+) Chosen Pokémon Gains 2 Random Vitamins",
"shady_vitamin_dealer_option_2_label": "The Pricey Deal",
"shady_vitamin_dealer_option_2_tooltip": "(-) Pay @ec{option2Money}\n(-) Side Effects?\n(+) Chosen Pokémon Gains 2 Random Vitamins",
"shady_vitamin_dealer_option_2_tooltip": "(-) Pay {{option2Money, money}}\n(-) Side Effects?\n(+) Chosen Pokémon Gains 2 Random Vitamins",
"shady_vitamin_dealer_option_selected": `The man hands you two bottles and quickly disappears.
$@ec{selectedPokemon} gained @ec{boost1} and @ec{boost2} boosts!`,
\${{selectedPokemon}} gained {{boost1}} and {{boost2}} boosts!`,
"shady_vitamin_dealer_damage_only": `But the medicine had some side effects!
$Your @ec{selectedPokemon} takes some damage...`,
$Your {{selectedPokemon}} takes some damage...`,
"shady_vitamin_dealer_bad_poison": `But the medicine had some side effects!
$Your @ec{selectedPokemon} takes some damage\nand becomes badly poisoned...`,
$Your {{selectedPokemon}} takes some damage\nand becomes badly poisoned...`,
"shady_vitamin_dealer_poison": `But the medicine had some side effects!
$Your @ec{selectedPokemon} becomes poisoned...`,
$Your {{selectedPokemon}} becomes poisoned...`,
"shady_vitamin_dealer_no_bad_effects": "Looks like there were no side-effects this time.",
"shady_vitamin_dealer_option_3_label": "Leave",
"shady_vitamin_dealer_option_3_tooltip": "(-) No Rewards",
@ -115,9 +116,9 @@ export const mysteryEncounter = {
"field_trip_option_3_label": "A Status Move",
"field_trip_option_3_tooltip": "(+) Status Item Rewards",
"field_trip_second_option_prompt": "Choose a move for your Pokémon to use.",
"field_trip_option_selected": "@ec{pokeName} shows off an awesome display of @ec{move}!",
"field_trip_option_selected": "{{pokeName}} shows off an awesome display of {{move}}!",
"field_trip_option_incorrect": `...
$That isn't a @ec{moveCategory} move!
$That isn't a {{moveCategory}} move!
$I'm sorry, but I can't give you anything.`,
"field_trip_lesson_learned": `Looks like you learned a valuable lesson?
$Your Pokémon also gained some knowledge.`,
@ -153,13 +154,13 @@ export const mysteryEncounter = {
"training_session_option_3_label": "Heavy Training",
"training_session_option_3_tooltip": "(-) Harsh Battle\n(+) Change Pokémon's Ability",
"training_session_option_3_select_prompt": "Select a new ability\nto train your Pokémon in.",
"training_session_option_selected_message": "@ec{selectedPokemon} moves across\nthe clearing to face you...",
"training_session_battle_finished_1": `@ec{selectedPokemon} returns, feeling\nworn out but accomplished!
$Its @ec{stat1} and @ec{stat2} IVs were improved!`,
"training_session_battle_finished_2": `@ec{selectedPokemon} returns, feeling\nworn out but accomplished!
$Its nature was changed to @ec{nature}!`,
"training_session_battle_finished_3": `@ec{selectedPokemon} returns, feeling\nworn out but accomplished!
$Its ability was changed to @ec{ability}!`,
"training_session_option_selected_message": "{{selectedPokemon}} moves across\nthe clearing to face you...",
"training_session_battle_finished_1": `{{selectedPokemon}} returns, feeling\nworn out but accomplished!
$Its {{stat1}} and {{stat2}} IVs were improved!`,
"training_session_battle_finished_2": `{{selectedPokemon}} returns, feeling\nworn out but accomplished!
$Its nature was changed to {{nature}}!`,
"training_session_battle_finished_3": `{{selectedPokemon}} returns, feeling\nworn out but accomplished!
$Its ability was changed to {{ability}}!`,
"training_session_outro_win": "That was a successful training session!",
// Mystery Encounters -- Super Rare Tier
@ -177,10 +178,10 @@ export const mysteryEncounter = {
"dark_deal_option_1_tooltip": "(+) 5 Rogue Balls\n(?) Enhance a Random Pokémon",
"dark_deal_option_2_label": "Refuse",
"dark_deal_option_2_tooltip": "(-) No Rewards",
"dark_deal_option_1_selected": `Let's see, that @ec{pokeName} will do nicely!
"dark_deal_option_1_selected": `Let's see, that {{pokeName}} will do nicely!
$Remember, I'm not responsible\nif anything bad happens!@d{32} Hehe...`,
"dark_deal_option_1_selected_message": `The man hands you 5 Rogue Balls.
$@ec{pokeName} hops into the strange machine...
\${{pokeName}} hops into the strange machine...
$Flashing lights and weird noises\nstart coming from the machine!
$...@d{96} Something emerges\nfrom the device, raging wildly!`,
"dark_deal_option_2_selected": "Not gonna help a poor fellow out?\nPah!",
@ -196,16 +197,16 @@ export const mysteryEncounter = {
"sleeping_snorlax_option_2_label": "Wait for it to move",
"sleeping_snorlax_option_2_tooltip": "@[SUMMARY_BLUE]{(75%) Wait a short time}\n@[SUMMARY_BLUE]{(25%) Wait a long time}",
"sleeping_snorlax_option_3_label": "Steal its item",
"sleeping_snorlax_option_3_tooltip": "(+) @ec{option3PrimaryName} uses @ec{option3PrimaryMove}\n(+) Leftovers",
"sleeping_snorlax_option_3_tooltip": "(+) {{option3PrimaryName}} uses {{option3PrimaryMove}}\n(+) Leftovers",
"sleeping_snorlax_option_3_disabled_tooltip": "Your Pokémon need to know certain moves to choose this",
"sleeping_snorlax_option_1_selected_message": "You approach the\nPokémon without fear.",
"sleeping_snorlax_option_2_selected_message": `.@d{32}.@d{32}.@d{32}
$You wait for a time, but the Snorlax's yawns make your party sleepy.`,
"sleeping_snorlax_option_2_good_result": "When you all awaken, the Snorlax is no where to be found - but your Pokémon are all healed!",
"sleeping_snorlax_option_2_bad_result": `Your @ec{primaryName} is still asleep...
"sleeping_snorlax_option_2_bad_result": `Your {{primaryName}} is still asleep...
$But on the bright side, the Snorlax left something behind...
$@s{item_fanfare}You gained a Berry!`,
"sleeping_snorlax_option_3_good_result": "Your @ec{option3PrimaryName} uses @ec{option3PrimaryMove}! @s{item_fanfare}It steals Leftovers off the sleeping Snorlax and you make out like bandits!",
"sleeping_snorlax_option_3_good_result": "Your {{option3PrimaryName}} uses {{option3PrimaryMove}}! @s{item_fanfare}It steals Leftovers off the sleeping Snorlax and you make out like bandits!",
lostAtSea,
} as const;

View File

@ -78,7 +78,7 @@ export class MysteryEncounterPhase extends Phase {
this.end();
};
const optionSelectDialogue = this.scene.currentBattle?.mysteryEncounter?.dialogue?.encounterOptionsDialogue?.options?.[optionIndex];
const optionSelectDialogue = this.scene.currentBattle?.mysteryEncounter?.options?.[optionIndex]?.dialogue;
if (optionSelectDialogue?.selected?.length > 0) {
// Handle intermediate dialogue (between player selection event and the onOptionSelect logic)
this.scene.ui.setMode(Mode.MESSAGE);

View File

@ -136,6 +136,14 @@ export async function initI18n(): Promise<void> {
postProcess: ["korean-postposition"],
});
// Input: {{myMoneyValue, money}}
// Output: @[MONEY]{₽100,000,000} (useful for BBCode coloring of text)
// If you don't want the BBCode tag applied, just use 'number' formatter
i18next.services.formatter.add("money", (value, lng, options) => {
const numberFormattedString = Intl.NumberFormat(lng, options).format(value);
return `@[MONEY]{₽${numberFormattedString}}`;
});
await initFonts();
}

View File

@ -277,7 +277,7 @@ describe("Mystery Encounter Utils", () => {
scene.currentBattle.mysteryEncounter.setDialogueToken("test", "value");
const result = getEncounterText(scene, "mysteryEncounter:unit_test_dialogue");
expect(result).toEqual("valuevalue @ec{testvalue} @ec{test1} value @ec{test\\} @ec{test\\} {test}");
expect(result).toEqual("valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}");
});
it("can perform nested dialogue token injection", () => {
@ -286,7 +286,7 @@ describe("Mystery Encounter Utils", () => {
scene.currentBattle.mysteryEncounter.setDialogueToken("testvalue", "new");
const result = getEncounterText(scene, "mysteryEncounter:unit_test_dialogue");
expect(result).toEqual("valuevalue new @ec{test1} value @ec{test\\} @ec{test\\} {test}");
expect(result).toEqual("valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}");
});
});
@ -298,7 +298,7 @@ describe("Mystery Encounter Utils", () => {
const phaseSpy = vi.spyOn(game.scene, "unshiftPhase");
queueEncounterMessage(scene, "mysteryEncounter:unit_test_dialogue");
expect(spy).toHaveBeenCalledWith("valuevalue @ec{testvalue} @ec{test1} value @ec{test\\} @ec{test\\} {test}", null, true);
expect(spy).toHaveBeenCalledWith("valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}", null, true);
expect(phaseSpy).toHaveBeenCalledWith(expect.any(MessagePhase));
});
});
@ -310,7 +310,7 @@ describe("Mystery Encounter Utils", () => {
const spy = vi.spyOn(game.scene.ui, "showText");
showEncounterText(scene, "mysteryEncounter:unit_test_dialogue");
expect(spy).toHaveBeenCalledWith("valuevalue @ec{testvalue} @ec{test1} value @ec{test\\} @ec{test\\} {test}", null, expect.any(Function), 0, true);
expect(spy).toHaveBeenCalledWith("valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}", null, expect.any(Function), 0, true);
});
});
@ -321,7 +321,7 @@ describe("Mystery Encounter Utils", () => {
const spy = vi.spyOn(game.scene.ui, "showDialogue");
showEncounterDialogue(scene, "mysteryEncounter:unit_test_dialogue", "mysteryEncounter:unit_test_dialogue");
expect(spy).toHaveBeenCalledWith("valuevalue @ec{testvalue} @ec{test1} value @ec{test\\} @ec{test\\} {test}", "valuevalue @ec{testvalue} @ec{test1} value @ec{test\\} @ec{test\\} {test}", null, undefined, 0, 0);
expect(spy).toHaveBeenCalledWith("valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}", "valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}", null, undefined, 0, 0);
});
});

View File

@ -289,13 +289,12 @@ export default class PhaseInterceptor {
* @param phase - The phase to start.
*/
setMode(mode: Mode, ...args: any[]): Promise<void> {
const currentPhase = this.
scene.getCurrentPhase();
const currentPhase = this.scene.getCurrentPhase();
const instance = this.scene.ui;
console.log("setMode", mode, args);
const ret = this.originalSetMode.apply(instance, [mode, ...args]);
if (!this.phases[currentPhase.constructor.name]) {
throw new Error(`missing ${currentPhase.constructor.name} in phaseInterceptior PHASES list`);
throw new Error(`missing ${currentPhase.constructor.name} in phaseInterceptor PHASES list`);
}
if (this.phases[currentPhase.constructor.name].endBySetMode) {
this.inProgress?.callback();