From 74125ef1cfd0db811a2d3e35c0b8cc90f5dffbad Mon Sep 17 00:00:00 2001 From: Felix Staud Date: Thu, 11 Jul 2024 12:56:15 -0700 Subject: [PATCH] WIP: add option to use dialogues in builder --- .../dialogue/dark-deal-dialogue.ts | 68 +++--- .../encounters/dark-deal.ts | 197 ++++++++++++------ .../mystery-encounter-dialogue.ts | 2 +- .../mystery-encounter-option.ts | 6 + .../mystery-encounters/mystery-encounter.ts | 19 +- src/overrides.ts | 6 +- src/phases.ts | 2 +- src/ui/mystery-encounter-ui-handler.ts | 6 +- 8 files changed, 195 insertions(+), 111 deletions(-) diff --git a/src/data/mystery-encounters/dialogue/dark-deal-dialogue.ts b/src/data/mystery-encounters/dialogue/dark-deal-dialogue.ts index 25b31f79a50..9ee7ce5472b 100644 --- a/src/data/mystery-encounters/dialogue/dark-deal-dialogue.ts +++ b/src/data/mystery-encounters/dialogue/dark-deal-dialogue.ts @@ -1,44 +1,44 @@ import MysteryEncounterDialogue from "#app/data/mystery-encounters/mystery-encounter-dialogue"; export const DarkDealDialogue: MysteryEncounterDialogue = { - intro: [ - { - text: "mysteryEncounter:dark_deal_intro_message" - }, - { - speaker: "mysteryEncounter:dark_deal_speaker", - text: "mysteryEncounter:dark_deal_intro_dialogue" - } - ], + // intro: [ + // { + // text: "mysteryEncounter:dark_deal_intro_message" + // }, + // { + // speaker: "mysteryEncounter:dark_deal_speaker", + // text: "mysteryEncounter:dark_deal_intro_dialogue" + // } + // ], encounterOptionsDialogue: { title: "mysteryEncounter:dark_deal_title", description: "mysteryEncounter:dark_deal_description", query: "mysteryEncounter:dark_deal_query", - options: [ - { - buttonLabel: "mysteryEncounter:dark_deal_option_1_label", - buttonTooltip: "mysteryEncounter:dark_deal_option_1_tooltip", - selected: [ - { - speaker: "mysteryEncounter:dark_deal_speaker", - text: "mysteryEncounter:dark_deal_option_1_selected" - }, - { - text: "mysteryEncounter:dark_deal_option_1_selected_message" - } - ] - }, - { - buttonLabel: "mysteryEncounter:dark_deal_option_2_label", - buttonTooltip: "mysteryEncounter:dark_deal_option_2_tooltip", - selected: [ - { - speaker: "mysteryEncounter:dark_deal_speaker", - text: "mysteryEncounter:dark_deal_option_2_selected" - } - ] - } - ] + // options: [ + // { + // buttonLabel: "mysteryEncounter:dark_deal_option_1_label", + // buttonTooltip: "mysteryEncounter:dark_deal_option_1_tooltip", + // selected: [ + // { + // speaker: "mysteryEncounter:dark_deal_speaker", + // text: "mysteryEncounter:dark_deal_option_1_selected" + // }, + // { + // text: "mysteryEncounter:dark_deal_option_1_selected_message" + // } + // ] + // }, + // { + // buttonLabel: "mysteryEncounter:dark_deal_option_2_label", + // buttonTooltip: "mysteryEncounter:dark_deal_option_2_tooltip", + // selected: [ + // { + // speaker: "mysteryEncounter:dark_deal_speaker", + // text: "mysteryEncounter:dark_deal_option_2_selected" + // } + // ] + // } + // ] }, outro: [ { diff --git a/src/data/mystery-encounters/encounters/dark-deal.ts b/src/data/mystery-encounters/encounters/dark-deal.ts index 1985ffcf8dd..c1651aa8dec 100644 --- a/src/data/mystery-encounters/encounters/dark-deal.ts +++ b/src/data/mystery-encounters/encounters/dark-deal.ts @@ -7,14 +7,18 @@ import BattleScene from "../../../battle-scene"; import { AddPokeballModifierType } from "../../../modifier/modifier-type"; import { PokeballType } from "../../pokeball"; import { getPokemonSpecies } from "../../pokemon-species"; -import MysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier } from "../mystery-encounter"; +import MysteryEncounter, { + MysteryEncounterBuilder, + MysteryEncounterTier, +} from "../mystery-encounter"; import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option"; import { - EnemyPartyConfig, EnemyPokemonConfig, + EnemyPartyConfig, + EnemyPokemonConfig, getRandomPlayerPokemon, getRandomSpeciesByStarterTier, initBattleWithEnemyConfig, - leaveEncounterWithoutBattle + leaveEncounterWithoutBattle, } from "../mystery-encounter-utils"; // Exclude Ultra Beasts, Paradox, Necrozma, Eternatus, and egg-locked mythicals @@ -63,71 +67,132 @@ const excludedBosses = [ Species.ARCEUS, Species.VICTINI, Species.MELTAN, - Species.PECHARUNT + Species.PECHARUNT, ]; -export const DarkDealEncounter: MysteryEncounter = MysteryEncounterBuilder - .withEncounterType(MysteryEncounterType.DARK_DEAL) - .withEncounterTier(MysteryEncounterTier.ROGUE) - .withIntroSpriteConfigs([ - { - spriteKey: "mad_scientist_m", - fileRoot: "mystery-encounters", - hasShadow: true - }, - { - spriteKey: "dark_deal_porygon", - fileRoot: "mystery-encounters", - hasShadow: true, - repeat: true - } - ]) - .withSceneWaveRangeRequirement(30, 180) // waves 30 to 180 - .withScenePartySizeRequirement(2, 6) // Must have at least 2 pokemon in party - .withCatchAllowed(true) - .withOption(new MysteryEncounterOptionBuilder() - .withPreOptionPhase(async (scene: BattleScene) => { - // Removes random pokemon (including fainted) from party and adds name to dialogue data tokens - // Will never return last battle able mon and instead pick fainted/unable to battle - const removedPokemon = getRandomPlayerPokemon(scene, false, true); - scene.removePokemonFromPlayerParty(removedPokemon); +export const DarkDealEncounter: MysteryEncounter = + MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DARK_DEAL) + .withEncounterTier(MysteryEncounterTier.ROGUE) + .withIntroSpriteConfigs([ + { + spriteKey: "mad_scientist_m", + fileRoot: "mystery-encounters", + hasShadow: true, + }, + { + spriteKey: "dark_deal_porygon", + fileRoot: "mystery-encounters", + hasShadow: true, + repeat: true, + }, + ]) + .withIntroDialogue([ + { + text: "mysteryEncounter:dark_deal_intro_message", + }, + { + speaker: "mysteryEncounter:dark_deal_speaker", + text: "mysteryEncounter:dark_deal_intro_dialogue", + }, + ]) + .withSceneWaveRangeRequirement(30, 180) // waves 30 to 180 + .withScenePartySizeRequirement(2, 6) // Must have at least 2 pokemon in party + .withCatchAllowed(true) + .withOption( + new MysteryEncounterOptionBuilder() + .withDialogue({ + buttonLabel: "mysteryEncounter:dark_deal_option_1_label", + buttonTooltip: "mysteryEncounter:dark_deal_option_1_tooltip", + selected: [ + { + speaker: "mysteryEncounter:dark_deal_speaker", + text: "mysteryEncounter:dark_deal_option_1_selected", + }, + { + text: "mysteryEncounter:dark_deal_option_1_selected_message", + }, + ], + }) + .withPreOptionPhase(async (scene: BattleScene) => { + // Removes random pokemon (including fainted) from party and adds name to dialogue data tokens + // Will never return last battle able mon and instead pick fainted/unable to battle + const removedPokemon = getRandomPlayerPokemon(scene, false, true); + scene.removePokemonFromPlayerParty(removedPokemon); - scene.currentBattle.mysteryEncounter.setDialogueToken("pokeName", removedPokemon.name); + scene.currentBattle.mysteryEncounter.setDialogueToken( + "pokeName", + removedPokemon.name + ); - // Store removed pokemon types - scene.currentBattle.mysteryEncounter.misc = [removedPokemon.species.type1]; - if (removedPokemon.species.type2) { - scene.currentBattle.mysteryEncounter.misc.push(removedPokemon.species.type2); - } - }) - .withOptionPhase(async (scene: BattleScene) => { - // Give the player 5 Rogue Balls - scene.unshiftPhase(new ModifierRewardPhase(scene, () => new AddPokeballModifierType("rb", PokeballType.ROGUE_BALL, 5))); + // Store removed pokemon types + scene.currentBattle.mysteryEncounter.misc = [ + removedPokemon.species.type1, + ]; + if (removedPokemon.species.type2) { + scene.currentBattle.mysteryEncounter.misc.push( + removedPokemon.species.type2 + ); + } + }) + .withOptionPhase(async (scene: BattleScene) => { + // Give the player 5 Rogue Balls + scene.unshiftPhase( + new ModifierRewardPhase( + scene, + () => + new AddPokeballModifierType("rb", PokeballType.ROGUE_BALL, 5) + ) + ); - // Start encounter with random legendary (7-10 starter strength) that has level additive - const bossTypes = scene.currentBattle.mysteryEncounter.misc as Type[]; - // Starter egg tier, 35/50/10/5 %odds for tiers 6/7/8/9+ - const roll = randSeedInt(100); - const starterTier: number | [number, number] = roll > 65 ? 6 : roll > 15 ? 7 : roll > 5 ? 8 : [9, 10]; - const bossSpecies = getPokemonSpecies(getRandomSpeciesByStarterTier(starterTier, excludedBosses, bossTypes)); - const pokemonConfig: EnemyPokemonConfig = { - species: bossSpecies, - isBoss: true - }; - if (!isNullOrUndefined(bossSpecies.forms) && bossSpecies.forms.length > 0) { - pokemonConfig.formIndex = 0; - } - const config: EnemyPartyConfig = { - levelAdditiveMultiplier: 0.75, - pokemonConfigs: [pokemonConfig] - }; - return initBattleWithEnemyConfig(scene, config); - }) - .build() - ) - .withOptionPhase(async (scene: BattleScene) => { - // Leave encounter with no rewards or exp - leaveEncounterWithoutBattle(scene, true); - return true; - }) - .build(); + // Start encounter with random legendary (7-10 starter strength) that has level additive + const bossTypes = scene.currentBattle.mysteryEncounter.misc as Type[]; + // Starter egg tier, 35/50/10/5 %odds for tiers 6/7/8/9+ + const roll = randSeedInt(100); + const starterTier: number | [number, number] = + roll > 65 ? 6 : roll > 15 ? 7 : roll > 5 ? 8 : [9, 10]; + const bossSpecies = getPokemonSpecies( + getRandomSpeciesByStarterTier( + starterTier, + excludedBosses, + bossTypes + ) + ); + const pokemonConfig: EnemyPokemonConfig = { + species: bossSpecies, + isBoss: true, + }; + if ( + !isNullOrUndefined(bossSpecies.forms) && + bossSpecies.forms.length > 0 + ) { + pokemonConfig.formIndex = 0; + } + const config: EnemyPartyConfig = { + levelAdditiveMultiplier: 0.75, + pokemonConfigs: [pokemonConfig], + }; + return initBattleWithEnemyConfig(scene, config); + }) + .build() + ) + .withOption( + new MysteryEncounterOptionBuilder() + .withDialogue({ + buttonLabel: "mysteryEncounter:dark_deal_option_2_label", + buttonTooltip: "mysteryEncounter:dark_deal_option_2_tooltip", + selected: [ + { + speaker: "mysteryEncounter:dark_deal_speaker", + text: "mysteryEncounter:dark_deal_option_2_selected", + }, + ], + }) + .withOptionPhase(async (scene: BattleScene) => { + // Leave encounter with no rewards or exp + + leaveEncounterWithoutBattle(scene, true); + return true; + }) + .build() + ) + .build(); diff --git a/src/data/mystery-encounters/mystery-encounter-dialogue.ts b/src/data/mystery-encounters/mystery-encounter-dialogue.ts index 1e2dfe85045..7a9427a5d4a 100644 --- a/src/data/mystery-encounters/mystery-encounter-dialogue.ts +++ b/src/data/mystery-encounters/mystery-encounter-dialogue.ts @@ -28,7 +28,7 @@ export class EncounterOptionsDialogue { title: TemplateStringsArray | `mysteryEncounter:${string}`; description: TemplateStringsArray | `mysteryEncounter:${string}`; query?: TemplateStringsArray | `mysteryEncounter:${string}`; - options: [OptionTextDisplay, OptionTextDisplay, ...OptionTextDisplay[]]; // Options array with minimum 2 options + options?: [...OptionTextDisplay[]]; // Options array with minimum 2 options } export default class MysteryEncounterDialogue { diff --git a/src/data/mystery-encounters/mystery-encounter-option.ts b/src/data/mystery-encounters/mystery-encounter-option.ts index f1316ff64f1..2d1b4e5cfb9 100644 --- a/src/data/mystery-encounters/mystery-encounter-option.ts +++ b/src/data/mystery-encounters/mystery-encounter-option.ts @@ -127,6 +127,7 @@ export class MysteryEncounterOptionBuilder implements Partial> { this.requirements.push(requirement); @@ -163,4 +164,9 @@ export class MysteryEncounterOptionBuilder implements Partial o.dialogue = this.dialogue.encounterOptionsDialogue.options[i]); + if (this.dialogue?.encounterOptionsDialogue) { + // this.options.forEach((o, i) => o.dialogue = this.dialogue.encounterOptionsDialogue.options[i]); } // Reset any dirty flags or encounter data @@ -408,9 +410,20 @@ export class MysteryEncounterBuilder implements Partial { * @returns */ withIntroSpriteConfigs(spriteConfigs: MysteryEncounterSpriteConfig[]): this & Pick { + console.debug("with intro sprite configs: ", spriteConfigs); return Object.assign(this, { spriteConfigs: spriteConfigs }); } + withIntroDialogue(dialogue: MysteryEncounterDialogue["intro"] = []): this { + console.debug("with intro dialogue: ", dialogue); + this.dialogue = {...this.dialogue, intro: dialogue }; + return this; + } + + withIntro({spriteConfigs, dialogue} : {spriteConfigs: MysteryEncounterSpriteConfig[], dialogue?: MysteryEncounterDialogue["intro"]}) { + return this.withIntroSpriteConfigs(spriteConfigs).withIntroDialogue(dialogue); + } + /** * OPTIONAL */ diff --git a/src/overrides.ts b/src/overrides.ts index ce706173691..f6a3778c4da 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -35,7 +35,7 @@ export const SEED_OVERRIDE: string = ""; export const WEATHER_OVERRIDE: WeatherType = WeatherType.NONE; export const DOUBLE_BATTLE_OVERRIDE: boolean = false; export const SINGLE_BATTLE_OVERRIDE: boolean = false; -export const STARTING_WAVE_OVERRIDE: integer = 0; +export const STARTING_WAVE_OVERRIDE: integer = 33; export const STARTING_BIOME_OVERRIDE: Biome = Biome.TOWN; export const ARENA_TINT_OVERRIDE: TimeOfDay = null; // Multiplies XP gained by this value including 0. Set to null to ignore the override @@ -118,9 +118,9 @@ export const EGG_GACHA_PULL_COUNT_OVERRIDE: number = 0; */ // 1 to 256, set to null to ignore -export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = null; +export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = 10000; export const MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null; -export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = null; +export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.DARK_DEAL; /** * MODIFIER / ITEM OVERRIDES diff --git a/src/phases.ts b/src/phases.ts index 091629b31d5..2233763dc7f 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -828,7 +828,7 @@ export class EncounterPhase extends BattlePhase { if (mysteryEncounter.onInit) { mysteryEncounter.onInit(this.scene); } - mysteryEncounter.populateDialogueTokensFromRequirements(this.scene); + // mysteryEncounter.populateDialogueTokensFromRequirements(this.scene); }, this.scene.currentBattle.waveIndex); // Add intro visuals for mystery encounter diff --git a/src/ui/mystery-encounter-ui-handler.ts b/src/ui/mystery-encounter-ui-handler.ts index 163d79784f8..7be7f16e8bc 100644 --- a/src/ui/mystery-encounter-ui-handler.ts +++ b/src/ui/mystery-encounter-ui-handler.ts @@ -319,13 +319,13 @@ export default class MysteryEncounterUiHandler extends UiHandler { optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, i < 2 ? 0 : 16, "-", TextStyle.WINDOW, { wordWrap: { width: 558 }, fontSize: "80px", lineSpacing: -8 }); break; } - const option = mysteryEncounter.dialogue.encounterOptionsDialogue.options[i]; - const text = getEncounterText(this.scene, option.buttonLabel, option.style ? option.style : TextStyle.WINDOW); + const option = this.filteredEncounterOptions[i]; + const text = getEncounterText(this.scene, option.dialogue?.buttonLabel, option.dialogue?.style ? option.dialogue?.style : TextStyle.WINDOW); if (text) { optionText.setText(text); } - this.optionsMeetsReqs.push(this.filteredEncounterOptions[i].meetsRequirements(this.scene)); + this.optionsMeetsReqs.push(option.meetsRequirements(this.scene)); if (!this.optionsMeetsReqs[i]) { optionText.setAlpha(0.5);