From ef4222cbfaf869f2aedd01efc7cd6b1ee5cf3281 Mon Sep 17 00:00:00 2001 From: Felix Staud Date: Thu, 11 Jul 2024 07:57:41 -0700 Subject: [PATCH] Lost at sea myster encounter MVP.... - filled some dialogue - add placeholders for the pokemons that can help - rename it to `Lost at Sea` (from Getting lost at the sea - add damage calculation for 3rd option --- ...ea-dialogue.ts => lost-at-sea-dialogue.ts} | 4 +- .../getting-lost-at-the-sea-encounter.ts | 45 -------- .../encounters/lost-at-sea-encounter.ts | 102 ++++++++++++++++++ .../mystery-encounter-dialogue.ts | 4 +- .../mystery-encounter-option.ts | 17 ++- .../mystery-encounter-requirements.ts | 12 ++- .../mystery-encounters/mystery-encounters.ts | 6 +- src/enums/mystery-encounter-type.ts | 2 +- src/locales/en/mystery-encounter.ts | 4 +- .../getting-lost-at-the-sea.ts | 25 ----- .../en/mystery-encounters/lost-at-sea.ts | 29 +++++ src/overrides.ts | 2 +- 12 files changed, 168 insertions(+), 84 deletions(-) rename src/data/mystery-encounters/dialogue/{getting-lost-at-the-sea-dialogue.ts => lost-at-sea-dialogue.ts} (89%) delete mode 100644 src/data/mystery-encounters/encounters/getting-lost-at-the-sea-encounter.ts create mode 100644 src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts delete mode 100644 src/locales/en/mystery-encounters/getting-lost-at-the-sea.ts create mode 100644 src/locales/en/mystery-encounters/lost-at-sea.ts diff --git a/src/data/mystery-encounters/dialogue/getting-lost-at-the-sea-dialogue.ts b/src/data/mystery-encounters/dialogue/lost-at-sea-dialogue.ts similarity index 89% rename from src/data/mystery-encounters/dialogue/getting-lost-at-the-sea-dialogue.ts rename to src/data/mystery-encounters/dialogue/lost-at-sea-dialogue.ts index 9e008c93c57..1bfea19d83e 100644 --- a/src/data/mystery-encounters/dialogue/getting-lost-at-the-sea-dialogue.ts +++ b/src/data/mystery-encounters/dialogue/lost-at-sea-dialogue.ts @@ -1,8 +1,8 @@ import MysteryEncounterDialogue from "#app/data/mystery-encounters/mystery-encounter-dialogue"; -const namepsace = "mysteryEncounter:gettingLostAtTheSea"; +const namepsace = "mysteryEncounter:lostAtSea"; -export const GettingLostAtTheSeaDialogue: MysteryEncounterDialogue = { +export const LostAtSeaDialogue: MysteryEncounterDialogue = { intro: [ { text: `${namepsace}:intro` diff --git a/src/data/mystery-encounters/encounters/getting-lost-at-the-sea-encounter.ts b/src/data/mystery-encounters/encounters/getting-lost-at-the-sea-encounter.ts deleted file mode 100644 index 3b9b2366158..00000000000 --- a/src/data/mystery-encounters/encounters/getting-lost-at-the-sea-encounter.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { MysteryEncounterType } from "#enums/mystery-encounter-type"; -import BattleScene from "../../../battle-scene"; -import MysteryEncounter, { - MysteryEncounterBuilder, - MysteryEncounterTier, -} from "../mystery-encounter"; - -/** - * Getting lost at the sea encounter. - * @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/9|GitHub Issue #9} - * @see {@linkcode MysteryEncounter|Dialogues} - * @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts) - */ -export const GettingLostAtTheSeaEncounter: MysteryEncounter = - MysteryEncounterBuilder.withEncounterType( - MysteryEncounterType.GETTING_LOST_AT_THE_SEA - ) - .withEncounterTier(MysteryEncounterTier.COMMON) - .withIntroSpriteConfigs([ - { - fileRoot: "pokemon", - spriteKey: "130", // gyarados for now - hasShadow: false, - scale: 4, - y: 100, - x: 130, - tint: .25 - }, - ]) - .withSceneWaveRangeRequirement(11, 179) - .withOnInit((_scene: BattleScene) => { - console.log("GettingLostAtTheSeaEncounter OnInit"); - return true; - }) - .withOptionPhase(async (scene: BattleScene) => { - // OPTION 1 - }) - .withOptionPhase(async (scene: BattleScene) => { - // OPTION 2 - }) - .withOptionPhase(async (scene: BattleScene) => { - // OPTION 3 - return true; - }) - .build(); diff --git a/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts b/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts new file mode 100644 index 00000000000..d2c60762b2d --- /dev/null +++ b/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts @@ -0,0 +1,102 @@ +import { Type } from "#app/data/type.js"; +import { Species } from "#app/enums/species.js"; +import { PlayerPokemon } from "#app/field/pokemon.js"; +import { MysteryEncounterType } from "#enums/mystery-encounter-type"; +import BattleScene from "../../../battle-scene"; +import MysteryEncounter, { + MysteryEncounterBuilder, + MysteryEncounterTier, +} from "../mystery-encounter"; +import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option"; +import { leaveEncounterWithoutBattle } from "../mystery-encounter-utils"; + +const DAMAGE_PERCENTAGE: number = 30; // 0 - 100 + +/** + * Lost at sea encounter. + * @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/9|GitHub Issue #9} + * @see For biome requirements check [mysteryEncountersByBiome](../mystery-encounters.ts) + */ +export const LostAtSeaEncounter: MysteryEncounter = + MysteryEncounterBuilder.withEncounterType( + MysteryEncounterType.LOST_AT_SEA + ) + .withEncounterTier(MysteryEncounterTier.COMMON) + .withIntroSpriteConfigs([ + { + fileRoot: "pokemon", + spriteKey: `${Species.GYARADOS}`, + hasShadow: false, + scale: 4, + y: 100, + x: 130, + tint: 0.75, + alpha: 0.25, + }, + ]) + .withSceneWaveRangeRequirement(11, 179) + .withOnInit((scene: BattleScene) => { + const party = scene.getParty(); + const { mysteryEncounter } = scene.currentBattle; + + mysteryEncounter.setDialogueToken( + "damagePercentage", + String(DAMAGE_PERCENTAGE) + ); + + // check for water pokemon + const waterPkm = findPokemonByType(party, Type.WATER); + mysteryEncounter.setDialogueToken("waterPkm", waterPkm?.name ?? ""); + + // check for flying pokemon + const flyingPkm = findPokemonByType(party, Type.FLYING); + mysteryEncounter.setDialogueToken( + "flyingPkm", + flyingPkm?.name ?? "" + ); + + return true; + }) + /** + * Option 1: Use a (non fainted) water pokemon to guide you back. + * Receives EXP similar to defeating a Lapras + */ + .withOption( + new MysteryEncounterOptionBuilder() + .withPokemonTypeRequirement(Type.WATER, true, 1) + .withOptionPhase(async (scene: BattleScene) => { + console.debug("Lost at sea: Option 1 - Water Pokemon"); + leaveEncounterWithoutBattle(scene); + }) + .build() + ) + /** + * Option 2: Use a (non fainted) flying pokemon to guide you back. + * Receives EXP similar to defeating a Lapras + */ + .withOption( + new MysteryEncounterOptionBuilder() + .withPokemonTypeRequirement(Type.FLYING, true, 1) + .withOptionPhase(async (scene: BattleScene) => { + console.debug("Lost at sea: Option 2 - Flying Pokemon"); + leaveEncounterWithoutBattle(scene); + }) + .build() + ) + /** + * Option 3: Wander aimlessly. All pokemons lose 30% of their HP (or KO on 0 HP). + */ + .withOptionPhase(async (scene: BattleScene) => { + const party = scene.getParty().filter((p) => !p.isFainted()); + party.forEach((pkm) => { + const damage = Math.round(pkm.getMaxHp() / 3); + pkm.hp = Math.min(pkm.hp, damage); + }); + leaveEncounterWithoutBattle(scene); + return true; + }) + .build(); + +const findPokemonByType = (party: PlayerPokemon[], type: Type) => { + return party.find((p) => p.getTypes(true).includes(type)); +}; diff --git a/src/data/mystery-encounters/mystery-encounter-dialogue.ts b/src/data/mystery-encounters/mystery-encounter-dialogue.ts index 6f8f6a844ed..aa04ea89e73 100644 --- a/src/data/mystery-encounters/mystery-encounter-dialogue.ts +++ b/src/data/mystery-encounters/mystery-encounter-dialogue.ts @@ -8,7 +8,7 @@ import { SleepingSnorlaxDialogue } from "./dialogue/sleeping-snorlax-dialogue"; import { DepartmentStoreSaleDialogue } from "#app/data/mystery-encounters/dialogue/department-store-sale-dialogue"; import { ShadyVitaminDealerDialogue } from "#app/data/mystery-encounters/dialogue/shady-vitamin-dealer"; import { TextStyle } from "#app/ui/text"; -import { GettingLostAtTheSeaDialogue } from "./dialogue/getting-lost-at-the-sea-dialogue"; +import { LostAtSeaDialogue } from "./dialogue/lost-at-sea-dialogue"; export class TextDisplay { speaker?: TemplateStringsArray | `mysteryEncounter:${string}`; @@ -93,5 +93,5 @@ export function initMysteryEncounterDialogue() { allMysteryEncounterDialogue[MysteryEncounterType.SLEEPING_SNORLAX] = SleepingSnorlaxDialogue; allMysteryEncounterDialogue[MysteryEncounterType.DEPARTMENT_STORE_SALE] = DepartmentStoreSaleDialogue; allMysteryEncounterDialogue[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerDialogue; - allMysteryEncounterDialogue[MysteryEncounterType.GETTING_LOST_AT_THE_SEA] = GettingLostAtTheSeaDialogue; + allMysteryEncounterDialogue[MysteryEncounterType.LOST_AT_SEA] = LostAtSeaDialogue; } diff --git a/src/data/mystery-encounters/mystery-encounter-option.ts b/src/data/mystery-encounters/mystery-encounter-option.ts index f1316ff64f1..3fc04213d44 100644 --- a/src/data/mystery-encounters/mystery-encounter-option.ts +++ b/src/data/mystery-encounters/mystery-encounter-option.ts @@ -2,7 +2,8 @@ import { OptionTextDisplay } from "#app/data/mystery-encounters/mystery-encounte import { PlayerPokemon } from "#app/field/pokemon"; import BattleScene from "../../battle-scene"; import * as Utils from "../../utils"; -import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequirement } from "./mystery-encounter-requirements"; +import { Type } from "../type"; +import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequirement, TypeRequirement } from "./mystery-encounter-requirements"; export type OptionPhaseCallback = (scene: BattleScene) => Promise; @@ -158,6 +159,20 @@ export class MysteryEncounterOptionBuilder implements Partial> { this.secondaryPokemonRequirements.push(requirement); this.excludePrimaryFromSecondaryRequirements = excludePrimaryFromSecondaryRequirements; diff --git a/src/data/mystery-encounters/mystery-encounter-requirements.ts b/src/data/mystery-encounters/mystery-encounter-requirements.ts index 8781e5a4cdc..f31b37118ee 100644 --- a/src/data/mystery-encounters/mystery-encounter-requirements.ts +++ b/src/data/mystery-encounters/mystery-encounter-requirements.ts @@ -331,11 +331,13 @@ export class NatureRequirement extends EncounterPokemonRequirement { export class TypeRequirement extends EncounterPokemonRequirement { requiredType: Type[]; + excludeFainted: boolean; minNumberOfPokemon: number; invertQuery: boolean; - constructor(type: Type | Type[], minNumberOfPokemon: number = 1, invertQuery: boolean = false) { + constructor(type: Type | Type[], excludeFainted: boolean = true, minNumberOfPokemon: number = 1, invertQuery: boolean = false) { super(); + this.excludeFainted = excludeFainted; this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; if (type instanceof Array) { @@ -347,10 +349,16 @@ export class TypeRequirement extends EncounterPokemonRequirement { } meetsRequirement(scene: BattleScene): boolean { - const partyPokemon = scene.getParty(); + let partyPokemon = scene.getParty(); + if (isNullOrUndefined(partyPokemon) || this?.requiredType?.length < 0) { return false; } + + if (!this.excludeFainted) { + partyPokemon = partyPokemon.filter((pokemon) => !pokemon.isFainted()); + } + return this.queryParty(partyPokemon).length >= this.minNumberOfPokemon; } diff --git a/src/data/mystery-encounters/mystery-encounters.ts b/src/data/mystery-encounters/mystery-encounters.ts index bb27426d798..e74101763fe 100644 --- a/src/data/mystery-encounters/mystery-encounters.ts +++ b/src/data/mystery-encounters/mystery-encounters.ts @@ -9,7 +9,7 @@ import { SleepingSnorlaxEncounter } from "./encounters/sleeping-snorlax"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { DepartmentStoreSaleEncounter } from "#app/data/mystery-encounters/encounters/department-store-sale"; import { ShadyVitaminDealerEncounter } from "#app/data/mystery-encounters/encounters/shady-vitamin-dealer"; -import { GettingLostAtTheSeaEncounter } from "./encounters/getting-lost-at-the-sea-encounter"; +import { LostAtSeaEncounter } from "./encounters/lost-at-sea-encounter"; // Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * ) / 256 export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 1; @@ -42,7 +42,7 @@ export const mysteryEncountersByBiome = new Map([ ]], [Biome.SEA, [ - MysteryEncounterType.GETTING_LOST_AT_THE_SEA + MysteryEncounterType.LOST_AT_SEA ]], [Biome.SWAMP, []], [Biome.BEACH, [ @@ -98,7 +98,7 @@ export function initMysteryEncounters() { allMysteryEncounters[MysteryEncounterType.SLEEPING_SNORLAX] = SleepingSnorlaxEncounter; allMysteryEncounters[MysteryEncounterType.DEPARTMENT_STORE_SALE] = DepartmentStoreSaleEncounter; allMysteryEncounters[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerEncounter; - allMysteryEncounters[MysteryEncounterType.GETTING_LOST_AT_THE_SEA] = GettingLostAtTheSeaEncounter; + allMysteryEncounters[MysteryEncounterType.LOST_AT_SEA] = LostAtSeaEncounter; // Append encounters that can occur in any biome to biome map const anyBiomeEncounters: MysteryEncounterType[] = Object.keys(MysteryEncounterType).filter(e => !isNaN(Number(e))).map(k => Number(k) as MysteryEncounterType); diff --git a/src/enums/mystery-encounter-type.ts b/src/enums/mystery-encounter-type.ts index 9a78bf1b3ea..2c467dc0873 100644 --- a/src/enums/mystery-encounter-type.ts +++ b/src/enums/mystery-encounter-type.ts @@ -7,5 +7,5 @@ export enum MysteryEncounterType { TRAINING_SESSION, DEPARTMENT_STORE_SALE, SHADY_VITAMIN_DEALER, - GETTING_LOST_AT_THE_SEA //might be generalized later on + LOST_AT_SEA //might be generalized later on } diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index 3ff720dae0b..180aa6dd2d8 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -1,4 +1,4 @@ -import { gettingLostAtTheSea } from "./mystery-encounters/getting-lost-at-the-sea"; +import { lostAtSea } from "./mystery-encounters/lost-at-sea"; /** * Patterns that can be used: @@ -181,5 +181,5 @@ export const mysteryEncounter = { "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_outro_win": "The mysterious challengers were defeated!", - gettingLostAtTheSea, + lostAtSea, } as const; diff --git a/src/locales/en/mystery-encounters/getting-lost-at-the-sea.ts b/src/locales/en/mystery-encounters/getting-lost-at-the-sea.ts deleted file mode 100644 index a9640a20490..00000000000 --- a/src/locales/en/mystery-encounters/getting-lost-at-the-sea.ts +++ /dev/null @@ -1,25 +0,0 @@ - -export const gettingLostAtTheSea = { - intro: "TBA: INTRO MESSAGE", - "title": "Getting lost at the sea", - "description": "You get lost. Certain Pokémons can help you get back on track unharmed.", - "query": "What will you do?", - option: { - 1: { - label: "Let (Water type) guide you back", //TODO: replace (Water type) with pokemon in team - tooltip: "Needs a Water type in the party. That PKMN earns EXP as if having defeated a Lapras.", - selected: "TBA: OPTION 1 SELECTED TEXT " - }, - 2: { - label: " Let (Flying type) guide you back", //TODO: replace (Flying type) with pokemon in team - tooltip: "Needs a Flying type in the party. That PKMN earns EXP as if having defeated a Lapras.", - selected: "TBA: OPTION 2 SELECTED TEXT " - }, - 3: { - label: "Wander aimlessly until you're back", - tooltip: "All your Pokémon lose 30% of their HP. Any below that are KO'd.", - selected: "TBA: OPTION 3 SELECTED TEXT " - } - }, - "outro": "TBA GETTING LOST AT SEA OUTRO MESSAGE", -}; diff --git a/src/locales/en/mystery-encounters/lost-at-sea.ts b/src/locales/en/mystery-encounters/lost-at-sea.ts new file mode 100644 index 00000000000..a5846acf058 --- /dev/null +++ b/src/locales/en/mystery-encounters/lost-at-sea.ts @@ -0,0 +1,29 @@ +export const lostAtSea = { + intro: "You are halucinating and starting to loose your bearings.", + title: "Lost at sea", + description: + "You get lost at sea. All you \"sea\" is water everywhere and the sun is burning bright. Certain Pokémons can help you get back on track unharmed.", + query: "What will you do?", + option: { + 1: { + label: "Use @ec{waterPkm}", // pkm has to be of type water + tooltip: + "Use @ec{waterPkm} to guide you back. @ec{waterPkm} earns EXP as if having defeated a Lapras.", + selected: "@ec{waterPkm} guides you back and earns EXP.", + }, + 2: { + label: "Use @ec{flyingPkm}", // pkm has to be of type water + tooltip: + "Use @ec{flyingPkm} to guide you back. @ec{flyingPkm} earns EXP as if having defeated a Lapras.", + selected: "@ec{flyingPkm} guides you back and earns EXP.", + }, + 3: { + label: "Wander aimlessly", + tooltip: + "Wander aimlessly until you're back. All your Pokémon lose @ec{damagePercentage}% of their HP. Any below that are KO'd.", + selected: + "You wander aimlessly around. After hours of wandering, you find your way back. You and your team take the toll.", + }, + }, + // outro: "TBA: OUTRO MESSAGE", +}; diff --git a/src/overrides.ts b/src/overrides.ts index 596ee8f20f1..0f2ff365ae1 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -120,7 +120,7 @@ export const EGG_GACHA_PULL_COUNT_OVERRIDE: number = 0; // 1 to 256, set to null to ignore export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = 100000; export const MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null; -export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.GETTING_LOST_AT_THE_SEA; +export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.LOST_AT_SEA; /** * MODIFIER / ITEM OVERRIDES