mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2024-11-30 10:46:05 +00:00
lost-at-sea encounter - further progress
This commit is contained in:
parent
7164b0afe4
commit
c9cbdd7d44
@ -1,21 +1,12 @@
|
||||
import { Type } from "#app/data/type.js";
|
||||
import { Moves } from "#app/enums/moves.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 {
|
||||
EncounterOptionMode,
|
||||
MysteryEncounterOptionBuilder,
|
||||
} from "../mystery-encounter-option";
|
||||
import {
|
||||
applyDamageToPokemon,
|
||||
leaveEncounterWithoutBattle,
|
||||
setEncounterExp,
|
||||
} from "../mystery-encounter-utils";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier } from "../mystery-encounter";
|
||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||
import { applyDamageToPokemon, leaveEncounterWithoutBattle, setEncounterExp } from "../mystery-encounter-utils";
|
||||
|
||||
/**
|
||||
* Damage percentage taken when wandering aimlessly.
|
||||
@ -26,7 +17,7 @@ const DAMAGE_PERCENTAGE: number = 30; // 0 - 100
|
||||
/** The i18n namespace for the encounter */
|
||||
const namepsace = "mysteryEncounter:lostAtSea";
|
||||
|
||||
let waterPkm: PlayerPokemon;
|
||||
let surfablePkm: PlayerPokemon;
|
||||
let flyingPkm: PlayerPokemon;
|
||||
|
||||
/**
|
||||
@ -34,137 +25,108 @@ let flyingPkm: PlayerPokemon;
|
||||
* @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)
|
||||
.withSceneWaveRangeRequirement(11, 179)
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
fileRoot: "pokemon",
|
||||
spriteKey: `${Species.GYARADOS}`,
|
||||
hasShadow: false,
|
||||
scale: 4,
|
||||
y: 100,
|
||||
x: 130,
|
||||
tint: 0.75,
|
||||
alpha: 0.25,
|
||||
},
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namepsace}:intro`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const allowedPokemon = scene
|
||||
.getParty()
|
||||
.filter((p) => p.isAllowedInBattle());
|
||||
const { mysteryEncounter } = scene.currentBattle;
|
||||
export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.LOST_AT_SEA)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(11, 179)
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
fileRoot: "pokemon",
|
||||
spriteKey: `${Species.GYARADOS}`,
|
||||
hasShadow: false,
|
||||
scale: 4,
|
||||
y: 100,
|
||||
x: 130,
|
||||
tint: 0.75,
|
||||
alpha: 0.25,
|
||||
},
|
||||
])
|
||||
.withIntroDialogue([{ text: `${namepsace}:intro` }])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
// const allowedPokemon = scene.getParty().filter((p) => p.isAllowedInBattle());
|
||||
const { mysteryEncounter } = scene.currentBattle;
|
||||
|
||||
mysteryEncounter.setDialogueToken(
|
||||
"damagePercentage",
|
||||
String(DAMAGE_PERCENTAGE)
|
||||
);
|
||||
mysteryEncounter.setDialogueToken("damagePercentage", String(DAMAGE_PERCENTAGE));
|
||||
|
||||
// check for water pokemon
|
||||
waterPkm = findPokemonByType(allowedPokemon, Type.WATER);
|
||||
mysteryEncounter.setDialogueToken("waterPkm", waterPkm?.name ?? "<NONE>");
|
||||
// check for water pokemon
|
||||
// surfablePkm = findPokemonThatCanLearnMove(allowedPokemon, Type.WATER);
|
||||
// mysteryEncounter.setDialogueToken("waterPkm", surfablePkm?.name ?? "");
|
||||
|
||||
// check for flying pokemon
|
||||
flyingPkm = findPokemonByType(allowedPokemon, Type.FLYING);
|
||||
mysteryEncounter.setDialogueToken(
|
||||
"flyingPkm",
|
||||
flyingPkm?.name ?? "<NONE>"
|
||||
);
|
||||
// check for flying pokemon
|
||||
// flyingPkm = findPokemonThatCanLearnMove(allowedPokemon, Type.FLYING);
|
||||
// mysteryEncounter.setDialogueToken("flyingPkm", flyingPkm?.name ?? "");
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namepsace}:title`)
|
||||
.withDescription(`${namepsace}:description`)
|
||||
.withQuery(`${namepsace}:query`)
|
||||
.withOption(
|
||||
/**
|
||||
* Option 1: Use a (non fainted) water pokemon to guide you back.
|
||||
* Receives EXP similar to defeating a Lapras
|
||||
*/
|
||||
new MysteryEncounterOptionBuilder()
|
||||
.withPokemonTypeRequirement(Type.WATER, true, 1)
|
||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namepsace}:option:1:label`,
|
||||
buttonTooltip: `${namepsace}:option:1:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namepsace}:option:1:selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) =>
|
||||
handleGuidingOptionPhase(scene, waterPkm)
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
/**
|
||||
* Option 2: Use a (non fainted) flying pokemon to guide you back.
|
||||
* Receives EXP similar to defeating a Lapras
|
||||
*/
|
||||
new MysteryEncounterOptionBuilder()
|
||||
.withPokemonTypeRequirement(Type.FLYING, true, 1)
|
||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namepsace}:option:2:label`,
|
||||
buttonTooltip: `${namepsace}:option:2:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namepsace}:option:2:selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) =>
|
||||
handleGuidingOptionPhase(scene, flyingPkm)
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.withSimpleOption(
|
||||
/**
|
||||
* Option 3: Wander aimlessly. All pokemons lose {@linkcode DAMAGE_PERCENTAGE}}% of their HP (or KO on 0 HP).
|
||||
*/
|
||||
{
|
||||
buttonLabel: `${namepsace}:option:3:label`,
|
||||
buttonTooltip: `${namepsace}:option:3:tooltip`,
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namepsace}:title`)
|
||||
.withDescription(`${namepsace}:description`)
|
||||
.withQuery(`${namepsace}:query`)
|
||||
.withOption(
|
||||
/**
|
||||
* Option 1: Use a (non fainted) water pokemon to guide you back.
|
||||
* Receives EXP similar to defeating a Lapras
|
||||
*/
|
||||
new MysteryEncounterOptionBuilder()
|
||||
.withPokemonCanLearnMoveRequirement(Moves.SURF)
|
||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namepsace}:option:1:label`,
|
||||
buttonTooltip: `${namepsace}:option:1:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namepsace}:option:3:selected`,
|
||||
text: `${namepsace}:option:1:selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
const allowedPokemon = scene
|
||||
.getParty()
|
||||
.filter((p) => p.isAllowedInBattle());
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => handleGuidingOptionPhase(scene, surfablePkm))
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
/**
|
||||
* Option 2: Use a (non fainted) flying pokemon to guide you back.
|
||||
* Receives EXP similar to defeating a Lapras
|
||||
*/
|
||||
new MysteryEncounterOptionBuilder()
|
||||
.withPokemonTypeRequirement(Type.FLYING, true, 1)
|
||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namepsace}:option:2:label`,
|
||||
buttonTooltip: `${namepsace}:option:2:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namepsace}:option:2:selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => handleGuidingOptionPhase(scene, flyingPkm))
|
||||
.build()
|
||||
)
|
||||
.withSimpleOption(
|
||||
/**
|
||||
* Option 3: Wander aimlessly. All pokemons lose {@linkcode DAMAGE_PERCENTAGE}}% of their HP (or KO on 0 HP).
|
||||
*/
|
||||
{
|
||||
buttonLabel: `${namepsace}:option:3:label`,
|
||||
buttonTooltip: `${namepsace}:option:3:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namepsace}:option:3:selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
const allowedPokemon = scene.getParty().filter((p) => p.isAllowedInBattle());
|
||||
|
||||
allowedPokemon.forEach((pkm) => {
|
||||
const percentage = DAMAGE_PERCENTAGE / 100;
|
||||
const damage = Math.floor(pkm.getMaxHp() * percentage);
|
||||
return applyDamageToPokemon(pkm, damage);
|
||||
});
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
return true;
|
||||
}
|
||||
)
|
||||
.build();
|
||||
allowedPokemon.forEach((pkm) => {
|
||||
const percentage = DAMAGE_PERCENTAGE / 100;
|
||||
const damage = Math.floor(pkm.getMaxHp() * percentage);
|
||||
return applyDamageToPokemon(pkm, damage);
|
||||
});
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
|
||||
/**
|
||||
* Find a pokemon inside the given party by a given type
|
||||
*
|
||||
* @param party player pokemon party
|
||||
* @param type type to search for
|
||||
* @returns
|
||||
*/
|
||||
function findPokemonByType(party: PlayerPokemon[], type: Type) {
|
||||
return party.find((p) => p.getTypes(true).includes(type));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Generic handler for using a guiding pokemon to guide you back.
|
||||
@ -172,19 +134,14 @@ function findPokemonByType(party: PlayerPokemon[], type: Type) {
|
||||
* @param scene Battle scene
|
||||
* @param guidePokemon pokemon choosen as a guide
|
||||
*/
|
||||
function handleGuidingOptionPhase(
|
||||
scene: BattleScene,
|
||||
guidePokemon: PlayerPokemon
|
||||
) {
|
||||
function handleGuidingOptionPhase(scene: BattleScene, guidePokemon: PlayerPokemon) {
|
||||
/** Base EXP value for guiding pokemon. Currently Lapras base-value */
|
||||
const baseExpValue: number = 187;
|
||||
|
||||
if (guidePokemon) {
|
||||
setEncounterExp(scene, guidePokemon.id, baseExpValue, true);
|
||||
} else {
|
||||
console.warn(
|
||||
"Lost at sea: No guide pokemon found but pokemon guides player. huh!?"
|
||||
);
|
||||
console.warn("Lost at sea: No guide pokemon found but pokemon guides player. huh!?");
|
||||
}
|
||||
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { OptionTextDisplay } from "#app/data/mystery-encounters/mystery-encounter-dialogue";
|
||||
import { Moves } from "#app/enums/moves.js";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
import BattleScene from "../../battle-scene";
|
||||
import * as Utils from "../../utils";
|
||||
import { Type } from "../type";
|
||||
import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequirement, TypeRequirement } from "./mystery-encounter-requirements";
|
||||
import { CanLearnMoveRequirement, CanlearnMoveRequirementOptions } from "./requirements/can-learn-move-requirement";
|
||||
|
||||
export enum EncounterOptionMode {
|
||||
/** Default style */
|
||||
@ -194,8 +196,18 @@ export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOp
|
||||
* @returns
|
||||
*/
|
||||
withPokemonTypeRequirement(type: Type | Type[], excludeFainted?: boolean, minNumberOfPokemon?: number, invertQuery?: boolean) {
|
||||
const types = Array.isArray(type) ? type : [type];
|
||||
return this.withPrimaryPokemonRequirement(new TypeRequirement(types, excludeFainted, minNumberOfPokemon, invertQuery));
|
||||
return this.withPrimaryPokemonRequirement(new TypeRequirement(type, excludeFainted, minNumberOfPokemon, invertQuery));
|
||||
}
|
||||
|
||||
/**
|
||||
* Player is required to have a pokemon that can learn a certain move/moveset
|
||||
*
|
||||
* @param move the required move/moves
|
||||
* @param options see {@linkcode CanlearnMoveRequirementOptions}
|
||||
* @returns
|
||||
*/
|
||||
withPokemonCanLearnMoveRequirement(move: Moves | Moves[], options?: CanlearnMoveRequirementOptions) {
|
||||
return this.withPrimaryPokemonRequirement(new CanLearnMoveRequirement(move, options));
|
||||
}
|
||||
|
||||
withSecondaryPokemonRequirement(requirement: EncounterPokemonRequirement, excludePrimaryFromSecondaryRequirements?: boolean): this & Required<Pick<MysteryEncounterOption, "secondaryPokemonRequirements">> {
|
||||
|
@ -1,15 +1,16 @@
|
||||
import IMysteryEncounter from "./mystery-encounter";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { DarkDealEncounter } from "./encounters/dark-deal-encounter";
|
||||
import { DepartmentStoreSaleEncounter } from "./encounters/department-store-sale-encounter";
|
||||
import { FieldTripEncounter } from "./encounters/field-trip-encounter";
|
||||
import { FightOrFlightEncounter } from "./encounters/fight-or-flight-encounter";
|
||||
import { LostAtSeaEncounter } from "./encounters/lost-at-sea-encounter";
|
||||
import { MysteriousChallengersEncounter } from "./encounters/mysterious-challengers-encounter";
|
||||
import { MysteriousChestEncounter } from "./encounters/mysterious-chest-encounter";
|
||||
import { FightOrFlightEncounter } from "./encounters/fight-or-flight-encounter";
|
||||
import { TrainingSessionEncounter } from "./encounters/training-session-encounter";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { SleepingSnorlaxEncounter } from "./encounters/sleeping-snorlax-encounter";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { DepartmentStoreSaleEncounter } from "./encounters/department-store-sale-encounter";
|
||||
import { ShadyVitaminDealerEncounter } from "./encounters/shady-vitamin-dealer-encounter";
|
||||
import { LostAtSeaEncounter } from "./encounters/lost-at-sea-encounter";
|
||||
import { SleepingSnorlaxEncounter } from "./encounters/sleeping-snorlax-encounter";
|
||||
import { TrainingSessionEncounter } from "./encounters/training-session-encounter";
|
||||
import IMysteryEncounter from "./mystery-encounter";
|
||||
|
||||
// Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / 256
|
||||
export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 1;
|
||||
|
@ -7,7 +7,7 @@ import { EncounterPokemonRequirement } from "../mystery-encounter-requirements";
|
||||
/**
|
||||
* {@linkcode CanLearnMoveRequirement} options
|
||||
*/
|
||||
interface Options {
|
||||
export interface CanlearnMoveRequirementOptions {
|
||||
excludeLevelMoves?: boolean;
|
||||
excludeTmMoves?: boolean;
|
||||
excludeEggMoves?: boolean;
|
||||
@ -26,20 +26,11 @@ export class CanLearnMoveRequirement extends EncounterPokemonRequirement {
|
||||
private readonly excludeEggMoves?: boolean;
|
||||
private readonly includeFainted?: boolean;
|
||||
|
||||
constructor(requiredMoves: Moves | Moves[], options: Options = {}) {
|
||||
constructor(requiredMoves: Moves | Moves[], options: CanlearnMoveRequirementOptions = {}) {
|
||||
super();
|
||||
this.requiredMoves = Array.isArray(requiredMoves)
|
||||
? requiredMoves
|
||||
: [requiredMoves];
|
||||
this.requiredMoves = Array.isArray(requiredMoves) ? requiredMoves : [requiredMoves];
|
||||
|
||||
const {
|
||||
excludeLevelMoves,
|
||||
excludeTmMoves,
|
||||
excludeEggMoves,
|
||||
includeFainted,
|
||||
minNumberOfPokemon,
|
||||
invertQuery,
|
||||
} = options;
|
||||
const { excludeLevelMoves, excludeTmMoves, excludeEggMoves, includeFainted, minNumberOfPokemon, invertQuery } = options;
|
||||
|
||||
this.excludeLevelMoves = excludeLevelMoves ?? false;
|
||||
this.excludeTmMoves = excludeTmMoves ?? false;
|
||||
@ -50,11 +41,7 @@ export class CanLearnMoveRequirement extends EncounterPokemonRequirement {
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
const partyPokemon = scene
|
||||
.getParty()
|
||||
.filter((pkm) =>
|
||||
this.includeFainted ? pkm.isAllowed() : pkm.isAllowedInBattle()
|
||||
);
|
||||
const partyPokemon = scene.getParty().filter((pkm) => (this.includeFainted ? pkm.isAllowed() : pkm.isAllowedInBattle()));
|
||||
|
||||
if (isNullOrUndefined(partyPokemon) || this?.requiredMoves?.length < 0) {
|
||||
return false;
|
||||
@ -67,26 +54,19 @@ export class CanLearnMoveRequirement extends EncounterPokemonRequirement {
|
||||
if (!this.invertQuery) {
|
||||
return partyPokemon.filter((pokemon) =>
|
||||
// every required move should be included
|
||||
this.requiredMoves.every((requiredMove) =>
|
||||
this.getAllPokemonMoves(pokemon).includes(requiredMove)
|
||||
)
|
||||
this.requiredMoves.every((requiredMove) => this.getAllPokemonMoves(pokemon).includes(requiredMove))
|
||||
);
|
||||
} else {
|
||||
return partyPokemon.filter(
|
||||
(pokemon) =>
|
||||
// none of the "required" moves should be included
|
||||
!this.requiredMoves.some((requiredMove) =>
|
||||
this.getAllPokemonMoves(pokemon).includes(requiredMove)
|
||||
)
|
||||
!this.requiredMoves.some((requiredMove) => this.getAllPokemonMoves(pokemon).includes(requiredMove))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
override getDialogueToken(
|
||||
_scene: BattleScene,
|
||||
_pokemon?: PlayerPokemon
|
||||
): [string, string] {
|
||||
return ["requiredMoves", this.requiredMoves.join(", ")];
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return pokemon ? ["pokemonCanLearnMove", pokemon.name] : null;
|
||||
}
|
||||
|
||||
private getPokemonLevelMoves(pkm: PlayerPokemon): Moves[] {
|
||||
|
@ -6,10 +6,10 @@ export const lostAtSea = {
|
||||
query: "What will you do?",
|
||||
option: {
|
||||
1: {
|
||||
label: "Use @ec{waterPkm}", // pkm has to be of type water
|
||||
label: "Use @ec{pokemonCanLearnMove}", // 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.",
|
||||
"Use @ec{pokemonCanLearnMove} to guide you back. @ec{pokemonCanLearnMove} earns EXP as if having defeated a Lapras.",
|
||||
selected: "@ec{pokemonCanLearnMove} guides you back and earns EXP.",
|
||||
},
|
||||
2: {
|
||||
label: "Use @ec{flyingPkm}", // pkm has to be of type flying
|
||||
|
Loading…
Reference in New Issue
Block a user