From 60c26456f66f2cd1436d75112275f882638c89d2 Mon Sep 17 00:00:00 2001 From: ImperialSympathizer Date: Fri, 12 Jul 2024 15:40:30 -0400 Subject: [PATCH 1/4] move dialogue token injection to i18next --- .../encounters/training-session-encounter.ts | 8 +-- .../mystery-encounter-dialogue.ts | 18 +++---- .../mystery-encounter-requirements.ts | 7 +-- .../mystery-encounter-utils.ts | 30 +++++------ .../mystery-encounters/mystery-encounter.ts | 14 ++--- src/locales/en/mystery-encounter.ts | 52 +++++++++---------- src/phases/mystery-encounter-phase.ts | 2 +- .../mystery-encounter-utils.test.ts | 10 ++-- src/test/utils/phaseInterceptor.ts | 5 +- 9 files changed, 71 insertions(+), 75 deletions(-) diff --git a/src/data/mystery-encounters/encounters/training-session-encounter.ts b/src/data/mystery-encounters/encounters/training-session-encounter.ts index da76d8a2d64..062e8599823 100644 --- a/src/data/mystery-encounters/encounters/training-session-encounter.ts +++ b/src/data/mystery-encounters/encounters/training-session-encounter.ts @@ -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( @@ -338,7 +334,7 @@ export const TrainingSessionEncounter: IMysteryEncounter = const onBeforeRewardsPhase = () => { scene.queueMessage( - getEncounterText(scene, `${namespace}_battle_finished_3`), + getEncounterText(scene, [`${namespace}_battle_finished_3`]), null, true ); diff --git a/src/data/mystery-encounters/mystery-encounter-dialogue.ts b/src/data/mystery-encounters/mystery-encounter-dialogue.ts index d96aeb87ba6..3832aaa7cd3 100644 --- a/src/data/mystery-encounters/mystery-encounter-dialogue.ts +++ b/src/data/mystery-encounters/mystery-encounter-dialogue.ts @@ -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 } diff --git a/src/data/mystery-encounters/mystery-encounter-requirements.ts b/src/data/mystery-encounters/mystery-encounter-requirements.ts index 8781e5a4cdc..a6de641478c 100644 --- a/src/data/mystery-encounters/mystery-encounter-requirements.ts +++ b/src/data/mystery-encounters/mystery-encounter-requirements.ts @@ -38,13 +38,14 @@ export abstract class EncounterPokemonRequirement implements EncounterRequiremen throw new Error("Method not implemented."); } - // 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 ["", ""]; } diff --git a/src/data/mystery-encounters/mystery-encounter-utils.ts b/src/data/mystery-encounters/mystery-encounter-utils.ts index d2e1a5eba2f..20022bdca30 100644 --- a/src/data/mystery-encounters/mystery-encounter-utils.ts +++ b/src/data/mystery-encounters/mystery-encounter-utils.ts @@ -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,20 @@ 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); - // Apply dialogue tokens - const dialogueTokens = scene.currentBattle?.mysteryEncounter?.dialogueTokens; - if (dialogueTokens) { - dialogueTokens.forEach((value) => { - textString = textString.replace(value[0], value[1]); - }); - } + // 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 +197,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 +207,7 @@ export function queueEncounterMessage(scene: BattleScene, contentKey: TemplateSt * @param scene * @param contentKey */ -export function showEncounterText(scene: BattleScene, contentKey: TemplateStringsArray | `mysteryEncounter:${string}`): Promise { +export function showEncounterText(scene: BattleScene, contentKey: string): Promise { return new Promise(resolve => { const text: string = getEncounterText(scene, contentKey); scene.ui.showText(text, null, () => resolve(), 0, true); @@ -221,7 +221,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); diff --git a/src/data/mystery-encounters/mystery-encounter.ts b/src/data/mystery-encounters/mystery-encounter.ts index 6fee6e493cf..b54d0f17665 100644 --- a/src/data/mystery-encounters/mystery-encounter.ts +++ b/src/data/mystery-encounters/mystery-encounter.ts @@ -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; + dialogueTokens?: { [key: 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; + 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 { primaryPokemonRequirements?: EncounterPokemonRequirement[] = []; secondaryPokemonRequirements ?: EncounterPokemonRequirement[] = []; excludePrimaryFromSupportRequirements?: boolean; - dialogueTokens?: Map; + dialogueTokens?: { [key: string]: string; }; doEncounterExp?: (scene: BattleScene) => boolean; doEncounterRewards?: (scene: BattleScene) => boolean; onInit?: (scene: BattleScene) => boolean; @@ -601,7 +601,7 @@ export class MysteryEncounterBuilder implements Partial { * @param title - title of the encounter * @returns */ - withTitle(title: TemplateStringsArray | `mysteryEncounter:${string}`) { + withTitle(title: string) { const encounterOptionsDialogue = this.dialogue.encounterOptionsDialogue ?? {}; this.dialogue = { @@ -621,7 +621,7 @@ export class MysteryEncounterBuilder implements Partial { * @param description - description of the encounter * @returns */ - withDescription(description: TemplateStringsArray | `mysteryEncounter:${string}`) { + withDescription(description: string) { const encounterOptionsDialogue = this.dialogue.encounterOptionsDialogue ?? {}; this.dialogue = { @@ -641,7 +641,7 @@ export class MysteryEncounterBuilder implements Partial { * @param query - query to use for the encounter * @returns */ - withQuery(query: TemplateStringsArray | `mysteryEncounter:${string}`) { + withQuery(query: string) { const encounterOptionsDialogue = this.dialogue.encounterOptionsDialogue ?? {}; this.dialogue = { diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index f944615452a..55791ae3654 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -5,7 +5,7 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; * '$' will be treated as a new line for Message and Dialogue strings * '@d{}' will add a time delay to text animation for Message and Dialogue strings * - * '@ec{}' will auto-inject the matching token value for the specified Encounter + * '{{}}' will auto-inject the matching token value for the specified Encounter that is stored in dialogueTokens * * '@[]{}' will auto-color the given text to a specified TextStyle (e.g. TextStyle.SUMMARY_GREEN) * @@ -14,7 +14,7 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; */ export const mysteryEncounter: SimpleTranslationEntries = { // 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 +33,7 @@ export const mysteryEncounter: SimpleTranslationEntries = { "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 +43,18 @@ export const mysteryEncounter: SimpleTranslationEntries = { "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 +85,17 @@ export const mysteryEncounter: SimpleTranslationEntries = { "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}}\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}}\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 +115,9 @@ export const mysteryEncounter: SimpleTranslationEntries = { "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 +153,13 @@ export const mysteryEncounter: SimpleTranslationEntries = { "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 +177,10 @@ export const mysteryEncounter: SimpleTranslationEntries = { "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,15 +196,15 @@ export const mysteryEncounter: SimpleTranslationEntries = { "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!", } as const; diff --git a/src/phases/mystery-encounter-phase.ts b/src/phases/mystery-encounter-phase.ts index 3db7816387a..638f2c0b15d 100644 --- a/src/phases/mystery-encounter-phase.ts +++ b/src/phases/mystery-encounter-phase.ts @@ -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); diff --git a/src/test/mystery-encounter/mystery-encounter-utils.test.ts b/src/test/mystery-encounter/mystery-encounter-utils.test.ts index 50853c05a2e..31f930319bf 100644 --- a/src/test/mystery-encounter/mystery-encounter-utils.test.ts +++ b/src/test/mystery-encounter/mystery-encounter-utils.test.ts @@ -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); }); }); diff --git a/src/test/utils/phaseInterceptor.ts b/src/test/utils/phaseInterceptor.ts index 09e3df4dac8..cc593030b09 100644 --- a/src/test/utils/phaseInterceptor.ts +++ b/src/test/utils/phaseInterceptor.ts @@ -289,13 +289,12 @@ export default class PhaseInterceptor { * @param phase - The phase to start. */ setMode(mode: Mode, ...args: any[]): Promise { - 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(); From 2b855e58e37420c303e2ca60f2ba1fb0bd4ad43d Mon Sep 17 00:00:00 2001 From: ImperialSympathizer Date: Fri, 12 Jul 2024 15:44:34 -0400 Subject: [PATCH 2/4] move dialogue token injection to i18next --- .../encounters/training-session-encounter.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/data/mystery-encounters/encounters/training-session-encounter.ts b/src/data/mystery-encounters/encounters/training-session-encounter.ts index 062e8599823..6abb340469a 100644 --- a/src/data/mystery-encounters/encounters/training-session-encounter.ts +++ b/src/data/mystery-encounters/encounters/training-session-encounter.ts @@ -333,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()) { From b82e8674cc7251f9c7a77d20476fb2b941ef6e1b Mon Sep 17 00:00:00 2001 From: ImperialSympathizer Date: Fri, 12 Jul 2024 15:54:35 -0400 Subject: [PATCH 3/4] add number formatting to money strings --- src/data/mystery-encounters/mystery-encounter-requirements.ts | 3 +-- src/locales/en/mystery-encounter.ts | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/data/mystery-encounters/mystery-encounter-requirements.ts b/src/data/mystery-encounters/mystery-encounter-requirements.ts index a6de641478c..30e8c989ae8 100644 --- a/src/data/mystery-encounters/mystery-encounter-requirements.ts +++ b/src/data/mystery-encounters/mystery-encounter-requirements.ts @@ -240,8 +240,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]; } } diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index 55791ae3654..d68848e4a37 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -85,9 +85,9 @@ export const mysteryEncounter: SimpleTranslationEntries = { "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 {{option1Money}}\n(-) Side Effects?\n(+) Chosen Pokémon Gains 2 Random Vitamins", + "shady_vitamin_dealer_option_1_tooltip": "(-) Pay @[MONEY]{₽{{option1Money, number}}}\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 {{option2Money}}\n(-) Side Effects?\n(+) Chosen Pokémon Gains 2 Random Vitamins", + "shady_vitamin_dealer_option_2_tooltip": "(-) Pay @[MONEY]{₽{{option2Money, number}}}\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. \${{selectedPokemon}} gained {{boost1}} and {{boost2}} boosts!`, "shady_vitamin_dealer_damage_only": `But the medicine had some side effects! From 39f91167c7a72ee348527a563f76b14674e45b70 Mon Sep 17 00:00:00 2001 From: ImperialSympathizer Date: Fri, 12 Jul 2024 15:57:12 -0400 Subject: [PATCH 4/4] PR cleanup and commit suggestions --- src/data/mystery-encounters/mystery-encounter-utils.ts | 8 -------- src/data/mystery-encounters/mystery-encounter.ts | 4 ++-- src/locales/en/mystery-encounter.ts | 1 + 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/data/mystery-encounters/mystery-encounter-utils.ts b/src/data/mystery-encounters/mystery-encounter-utils.ts index 20022bdca30..5c6e7eefa8d 100644 --- a/src/data/mystery-encounters/mystery-encounter-utils.ts +++ b/src/data/mystery-encounters/mystery-encounter-utils.ts @@ -181,14 +181,6 @@ function getTextWithDialogueTokens(scene: BattleScene, textKey: TemplateStringsA return null; } - // Apply dialogue tokens - // const dialogueTokens = scene.currentBattle?.mysteryEncounter?.dialogueTokens; - // if (dialogueTokens) { - // dialogueTokens.forEach((value) => { - // textString = textString.replace(value[0], value[1]); - // }); - // } - return i18next.t(textKey, scene.currentBattle?.mysteryEncounter?.dialogueTokens); } diff --git a/src/data/mystery-encounters/mystery-encounter.ts b/src/data/mystery-encounters/mystery-encounter.ts index b54d0f17665..e02639939b8 100644 --- a/src/data/mystery-encounters/mystery-encounter.ts +++ b/src/data/mystery-encounters/mystery-encounter.ts @@ -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?: { [key: string]: string; }; + dialogueTokens?: Record; /** * 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 @@ -350,7 +350,7 @@ export class MysteryEncounterBuilder implements Partial { primaryPokemonRequirements?: EncounterPokemonRequirement[] = []; secondaryPokemonRequirements ?: EncounterPokemonRequirement[] = []; excludePrimaryFromSupportRequirements?: boolean; - dialogueTokens?: { [key: string]: string; }; + dialogueTokens?: Record; doEncounterExp?: (scene: BattleScene) => boolean; doEncounterRewards?: (scene: BattleScene) => boolean; onInit?: (scene: BattleScene) => boolean; diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index d68848e4a37..9101b22d520 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -6,6 +6,7 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; * '@d{}' will add a time delay to text animation for Message and Dialogue strings * * '{{}}' 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)) * * '@[]{}' will auto-color the given text to a specified TextStyle (e.g. TextStyle.SUMMARY_GREEN) *