diff --git a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts new file mode 100644 index 00000000000..e2dd7849a49 --- /dev/null +++ b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts @@ -0,0 +1,172 @@ +import { + getHighestLevelPlayerPokemon, + koPlayerPokemon, + leaveEncounterWithoutBattle, + queueEncounterMessage, + setEncounterRewards, + showEncounterText, +} from "#app/data/mystery-encounters/mystery-encounter-utils"; +import { ModifierTier } from "#app/modifier/modifier-tier"; +import { GameOverPhase } from "#app/phases"; +import { randSeedInt } from "#app/utils"; +import { MysteryEncounterType } from "#enums/mystery-encounter-type"; +import BattleScene from "../../../battle-scene"; +import IMysteryEncounter, { + MysteryEncounterBuilder, + MysteryEncounterTier, +} from "../mystery-encounter"; +import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option"; + +/** the i18n namespace for the encounter */ +const namespace = "mysteryEncounter:safari_zone"; + +export const SafariZoneEncounter: IMysteryEncounter = + MysteryEncounterBuilder.withEncounterType( + MysteryEncounterType.SAFARI_ZONE + ) + .withEncounterTier(MysteryEncounterTier.GREAT) + .withSceneWaveRangeRequirement(10, 180) // waves 2 to 180 + .withHideIntroVisuals(false) + .withIntroSpriteConfigs([ + { + spriteKey: "chest_blue", + fileRoot: "mystery-encounters", + hasShadow: true, + x: 4, + y: 8, + disableAnimation: true, // Re-enabled after option select + }, + ]) + .withIntroDialogue([ + { + text: `mysteryEncounter:${namespace}_intro_message`, + }, + ]) + .withTitle(`mysteryEncounter:${namespace}_title`) + .withDescription(`mysteryEncounter:${namespace}_description`) + .withQuery(`mysteryEncounter:${namespace}_query`) + .withOption( + new MysteryEncounterOptionBuilder() + .withOptionMode(EncounterOptionMode.DEFAULT) + .withDialogue({ + buttonLabel: "mysteryEncounter:${namespace}_option_1_label", + buttonTooltip: "mysteryEncounter:${namespace}_option_1_tooltip", + selected: [ + { + text: "mysteryEncounter:${namespace}_option_1_selected_message", + }, + ], + }) + .withPreOptionPhase(async (scene: BattleScene) => { + // Play animation + const introVisuals = + scene.currentBattle.mysteryEncounter.introVisuals; + introVisuals.spriteConfigs[0].disableAnimation = false; + introVisuals.playAnim(); + }) + .withOptionPhase(async (scene: BattleScene) => { + // Open the chest + const roll = randSeedInt(100); + if (roll > 60) { + // Choose between 2 COMMON / 2 GREAT tier items (40%) + setEncounterRewards(scene, { + guaranteedModifierTiers: [ + ModifierTier.COMMON, + ModifierTier.COMMON, + ModifierTier.GREAT, + ModifierTier.GREAT, + ], + }); + // Display result message then proceed to rewards + queueEncounterMessage( + scene, + "mysteryEncounter:${namespace}_option_1_normal_result" + ); + leaveEncounterWithoutBattle(scene); + } else if (roll > 40) { + // Choose between 3 ULTRA tier items (20%) + setEncounterRewards(scene, { + guaranteedModifierTiers: [ + ModifierTier.ULTRA, + ModifierTier.ULTRA, + ModifierTier.ULTRA, + ], + }); + // Display result message then proceed to rewards + queueEncounterMessage( + scene, + "mysteryEncounter:${namespace}_option_1_good_result" + ); + leaveEncounterWithoutBattle(scene); + } else if (roll > 36) { + // Choose between 2 ROGUE tier items (4%) + setEncounterRewards(scene, { + guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE], + }); + // Display result message then proceed to rewards + queueEncounterMessage( + scene, + "mysteryEncounter:${namespace}_option_1_great_result" + ); + leaveEncounterWithoutBattle(scene); + } else if (roll > 35) { + // Choose 1 MASTER tier item (1%) + setEncounterRewards(scene, { + guaranteedModifierTiers: [ModifierTier.MASTER], + }); + // Display result message then proceed to rewards + queueEncounterMessage( + scene, + "mysteryEncounter:${namespace}_option_1_amazing_result" + ); + leaveEncounterWithoutBattle(scene); + } else { + // Your highest level unfainted Pok�mon gets OHKO. Progress with no rewards (35%) + const highestLevelPokemon = getHighestLevelPlayerPokemon( + scene, + true + ); + koPlayerPokemon(highestLevelPokemon); + + scene.currentBattle.mysteryEncounter.setDialogueToken( + "pokeName", + highestLevelPokemon.name + ); + // Show which Pokemon was KOed, then leave encounter with no rewards + // Does this synchronously so that game over doesn't happen over result message + await showEncounterText( + scene, + "mysteryEncounter:${namespace}_option_1_bad_result" + ).then(() => { + if ( + scene.getParty().filter((p) => p.isAllowedInBattle()).length === + 0 + ) { + // All pokemon fainted, game over + scene.clearPhaseQueue(); + scene.unshiftPhase(new GameOverPhase(scene)); + } else { + leaveEncounterWithoutBattle(scene); + } + }); + } + }) + .build() + ) + .withSimpleOption( + { + buttonLabel: "mysteryEncounter:${namespace}_option_2_label", + buttonTooltip: "mysteryEncounter:${namespace}_option_2_tooltip", + selected: [ + { + text: "mysteryEncounter:${namespace}_option_2_selected_message", + }, + ], + }, + async (scene: BattleScene) => { + // Leave encounter with no rewards or exp + leaveEncounterWithoutBattle(scene, true); + return true; + } + ) + .build(); diff --git a/src/data/mystery-encounters/mystery-encounters.ts b/src/data/mystery-encounters/mystery-encounters.ts index 7a78c6edb4c..c384606f5e3 100644 --- a/src/data/mystery-encounters/mystery-encounters.ts +++ b/src/data/mystery-encounters/mystery-encounters.ts @@ -162,10 +162,13 @@ export const mysteryEncountersByBiome = new Map([ [Biome.TALL_GRASS, []], [Biome.METROPOLIS, []], [Biome.FOREST, [ - MysteryEncounterType.SLEEPING_SNORLAX + MysteryEncounterType.SLEEPING_SNORLAX, + MysteryEncounterType.SAFARI_ZONE ]], [Biome.SEA, []], - [Biome.SWAMP, []], + [Biome.SWAMP, [ + MysteryEncounterType.SAFARI_ZONE + ]], [Biome.BEACH, []], [Biome.LAKE, []], [Biome.SEABED, []], @@ -189,7 +192,9 @@ export const mysteryEncountersByBiome = new Map([ [Biome.ABYSS, []], [Biome.SPACE, []], [Biome.CONSTRUCTION_SITE, []], - [Biome.JUNGLE, []], + [Biome.JUNGLE, [ + MysteryEncounterType.SAFARI_ZONE + ]], [Biome.FAIRY_CAVE, []], [Biome.TEMPLE, []], [Biome.SLUM, []], diff --git a/src/enums/mystery-encounter-type.ts b/src/enums/mystery-encounter-type.ts index b5b0144c3be..2819b0eb6fb 100644 --- a/src/enums/mystery-encounter-type.ts +++ b/src/enums/mystery-encounter-type.ts @@ -7,5 +7,6 @@ export enum MysteryEncounterType { TRAINING_SESSION, DEPARTMENT_STORE_SALE, SHADY_VITAMIN_DEALER, - FIELD_TRIP + FIELD_TRIP, + SAFARI_ZONE }