mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-01 05:52:17 +02:00
Merge branch 'beta' into moveTelekinesis
This commit is contained in:
commit
cbff3a955e
@ -3,4 +3,4 @@ VITE_BYPASS_TUTORIAL=0
|
||||
VITE_SERVER_URL=https://apibeta.pokerogue.net
|
||||
VITE_DISCORD_CLIENT_ID=1248062921129459756
|
||||
VITE_GOOGLE_CLIENT_ID=955345393540-2k6lfftf0fdnb0krqmpthjnqavfvvf73.apps.googleusercontent.com
|
||||
VITE_I18N_DEBUG=1
|
||||
VITE_I18N_DEBUG=0
|
||||
|
@ -3,5 +3,5 @@ VITE_BYPASS_TUTORIAL=0
|
||||
VITE_SERVER_URL=http://localhost:8001
|
||||
VITE_DISCORD_CLIENT_ID=1234567890
|
||||
VITE_GOOGLE_CLIENT_ID=1234567890
|
||||
VITE_I18N_DEBUG=1
|
||||
VITE_I18N_DEBUG=0
|
||||
VITE_PORT=8000
|
||||
|
38
.github/CODEOWNERS
vendored
38
.github/CODEOWNERS
vendored
@ -5,41 +5,3 @@
|
||||
|
||||
# github actions/templates etc. - Dev Leads
|
||||
/.github @pagefaultgames/dev-leads
|
||||
|
||||
# --- Translations ---
|
||||
|
||||
# all translations - Translation Leads
|
||||
/src/locales @pagefaultgames/translation-leads
|
||||
|
||||
# Catalan (Spain/Spanish)
|
||||
/src/locales/ca_ES @pagefaultgames/catalan-translation-team
|
||||
|
||||
# German
|
||||
/src/locales/de @pagefaultgames/german-translation-team
|
||||
|
||||
# English
|
||||
/src/locales/en @pagefaultgames/english-translation-team
|
||||
|
||||
# Spanish
|
||||
/src/locales/es @pagefaultgames/spanish-translation-team
|
||||
|
||||
# French
|
||||
/src/locales/fr @pagefaultgames/french-translation-team
|
||||
|
||||
# Italian
|
||||
/src/locales/it @pagefaultgames/italian-translation-team
|
||||
|
||||
# Japenese
|
||||
/src/locales/ja @pagefaultgames/japanese-translation-team
|
||||
|
||||
# Korean
|
||||
/src/locales/ko @pagefaultgames/korean-translation-team
|
||||
|
||||
# Brasilian (Brasil/Portuguese)
|
||||
/src/locales/pt_BR @pagefaultgames/portuguese_br-translation-team
|
||||
|
||||
# Chinese (simplified)
|
||||
/src/locales/zh_CN @pagefaultgames/chinese_simplified-translation-team
|
||||
|
||||
# Chinese (traditional)
|
||||
/src/locales/zh_TW @pagefaultgames/chinese_traditional-translation-team
|
||||
|
2
.github/workflows/deploy-beta.yml
vendored
2
.github/workflows/deploy-beta.yml
vendored
@ -11,6 +11,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
|
2
.github/workflows/deploy.yml
vendored
2
.github/workflows/deploy.yml
vendored
@ -10,6 +10,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
|
2
.github/workflows/eslint.yml
vendored
2
.github/workflows/eslint.yml
vendored
@ -22,6 +22,8 @@ jobs:
|
||||
steps:
|
||||
- name: Check out Git repository # Step to check out the repository
|
||||
uses: actions/checkout@v4 # Use the checkout action version 4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Set up Node.js # Step to set up Node.js environment
|
||||
uses: actions/setup-node@v4 # Use the setup-node action version 4
|
||||
|
1
.github/workflows/github-pages.yml
vendored
1
.github/workflows/github-pages.yml
vendored
@ -26,6 +26,7 @@ jobs:
|
||||
- name: Checkout repository for Typedoc
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
path: pokerogue_docs
|
||||
|
||||
- name: Install OS package
|
||||
|
2
.github/workflows/test-shard-template.yml
vendored
2
.github/workflows/test-shard-template.yml
vendored
@ -20,6 +20,8 @@ jobs:
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
|
1
.github/workflows/tests.yml
vendored
1
.github/workflows/tests.yml
vendored
@ -22,6 +22,7 @@ jobs:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
path: tests-action
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "public/locales"]
|
||||
path = public/locales
|
||||
url = https://github.com/pagefaultgames/pokerogue-locales
|
@ -24,6 +24,9 @@ We're using ESLint as our common linter and formatter. It will run automatically
|
||||
**How do I test a new _______?**
|
||||
- In the `src/overrides.ts` file there are overrides for most values you'll need to change for testing
|
||||
|
||||
**How do I retrieve the translations?**
|
||||
- The translations were moved to the [dedicated translation repository](https://github.com/pagefaultgames/pokerogue-locales) and are now applied as a submodule in this project.
|
||||
- The command to retrieve the translations is `git submodule update --init --recursive`. If you still struggle to get it working, please reach out to #dev-corner channel in Discord.
|
||||
|
||||
## 🪧 To Do
|
||||
Check out [Github Issues](https://github.com/pagefaultgames/pokerogue/issues) to see how can you help us!
|
||||
|
@ -1,9 +1,7 @@
|
||||
/**
|
||||
* This script creates a test boilerplate file for a move or ability.
|
||||
* @param {string} type - The type of test to create. Either "move", "ability",
|
||||
* or "item".
|
||||
* @param {string} fileName - The name of the file to create.
|
||||
* @example npm run create-test move tackle
|
||||
* This script creates a test boilerplate file in the appropriate
|
||||
* directory based on the type selected.
|
||||
* @example npm run create-test
|
||||
*/
|
||||
|
||||
import fs from "fs";
|
||||
@ -34,7 +32,7 @@ async function promptTestType() {
|
||||
console.log("Exiting...");
|
||||
return process.exit();
|
||||
} else if (!typeChoices.includes(typeAnswer.selectedOption)) {
|
||||
console.error('Please provide a valid type ("move", "ability", or "item")!');
|
||||
console.error(`Please provide a valid type (${typeChoices.join(", ")})!`);
|
||||
return await promptTestType();
|
||||
}
|
||||
|
||||
@ -102,7 +100,7 @@ async function runInteractive() {
|
||||
description = `Mystery Encounter - ${formattedName}`;
|
||||
break;
|
||||
default:
|
||||
console.error('Invalid type. Please use "move", "ability", or "item".');
|
||||
console.error(`Invalid type. Please use one of the following: ${typeChoices.join(", ")}.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
@ -14,3 +14,8 @@ pre-push:
|
||||
eslint:
|
||||
glob: "*.{js,ts,jsx,tsx}"
|
||||
run: npx eslint --fix {push_files}
|
||||
|
||||
post-merge:
|
||||
commands:
|
||||
update-submodules:
|
||||
run: git submodule update --init --recursive
|
8
package-lock.json
generated
8
package-lock.json
generated
@ -12,6 +12,7 @@
|
||||
"crypto-js": "^4.2.0",
|
||||
"i18next": "^23.11.1",
|
||||
"i18next-browser-languagedetector": "^7.2.1",
|
||||
"i18next-http-backend": "^2.6.1",
|
||||
"i18next-korean-postposition-processor": "^1.0.0",
|
||||
"json-stable-stringify": "^1.1.0",
|
||||
"phaser": "^3.70.0",
|
||||
@ -4003,9 +4004,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/i18next-http-backend": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.5.2.tgz",
|
||||
"integrity": "sha512-+K8HbDfrvc1/2X8jpb7RLhI9ZxBDpx3xogYkQwGKlWAUXLSEGXzgdt3EcUjLlBCdMwdQY+K+EUF6oh8oB6rwHw==",
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.6.1.tgz",
|
||||
"integrity": "sha512-rCilMAnlEQNeKOZY1+x8wLM5IpYOj10guGvEpeC59tNjj6MMreLIjIW8D1RclhD3ifLwn6d/Y9HEM1RUE6DSog==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-fetch": "4.0.0"
|
||||
}
|
||||
|
@ -19,7 +19,8 @@
|
||||
"docs": "typedoc",
|
||||
"depcruise": "depcruise src",
|
||||
"depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg",
|
||||
"create-test": "node ./create-test-boilerplate.js"
|
||||
"create-test": "node ./create-test-boilerplate.js",
|
||||
"postinstall": "npx lefthook install && npx lefthook run post-merge"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.3.0",
|
||||
@ -51,6 +52,7 @@
|
||||
"crypto-js": "^4.2.0",
|
||||
"i18next": "^23.11.1",
|
||||
"i18next-browser-languagedetector": "^7.2.1",
|
||||
"i18next-http-backend": "^2.6.1",
|
||||
"i18next-korean-postposition-processor": "^1.0.0",
|
||||
"json-stable-stringify": "^1.1.0",
|
||||
"phaser": "^3.70.0",
|
||||
|
BIN
public/images/ui/friendship.png
Normal file
BIN
public/images/ui/friendship.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 B |
BIN
public/images/ui/friendship_overlay.png
Normal file
BIN
public/images/ui/friendship_overlay.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 182 B |
BIN
public/images/ui/legacy/friendship.png
Normal file
BIN
public/images/ui/legacy/friendship.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 B |
BIN
public/images/ui/legacy/friendship_overlay.png
Normal file
BIN
public/images/ui/legacy/friendship_overlay.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 182 B |
1
public/locales
Submodule
1
public/locales
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 3ccef8472dd7cc7c362538489954cb8fdad27e5f
|
16
src/@types/i18next.d.ts
vendored
16
src/@types/i18next.d.ts
vendored
@ -1,18 +1,8 @@
|
||||
import { type enConfig } from "#app/locales/en/config";
|
||||
import { TOptions } from "i18next";
|
||||
|
||||
//TODO: this needs to be type properly in the future
|
||||
// Module declared to make referencing keys in the localization files type-safe.
|
||||
declare module "i18next" {
|
||||
interface CustomTypeOptions {
|
||||
defaultNS: "menu", // needed here as well for typedoc
|
||||
resources: typeof enConfig
|
||||
}
|
||||
|
||||
interface TFunction {
|
||||
(
|
||||
key: string | string[],
|
||||
options?: TOptions & Record<string, unknown>
|
||||
): string;
|
||||
}
|
||||
interface TFunction {
|
||||
(key: string | string[], options?: TOptions & Record<string, unknown>): string;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import { trainerConfigs, TrainerSlot } from "./data/trainer-config";
|
||||
import Trainer, { TrainerVariant } from "./field/trainer";
|
||||
import TrainerData from "./system/trainer-data";
|
||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { pokemonPrevolutions } from "./data/pokemon-evolutions";
|
||||
import { pokemonPrevolutions } from "./data/balance/pokemon-evolutions";
|
||||
import PokeballTray from "./ui/pokeball-tray";
|
||||
import InvertPostFX from "./pipelines/invert";
|
||||
import { Achv, achvs, ModifierAchv, MoneyAchv } from "./system/achv";
|
||||
@ -42,7 +42,7 @@ import PokemonSpriteSparkleHandler from "./field/pokemon-sprite-sparkle-handler"
|
||||
import CharSprite from "./ui/char-sprite";
|
||||
import DamageNumberHandler from "./field/damage-number-handler";
|
||||
import PokemonInfoContainer from "./ui/pokemon-info-container";
|
||||
import { biomeDepths, getBiomeName } from "./data/biomes";
|
||||
import { biomeDepths, getBiomeName } from "./data/balance/biomes";
|
||||
import { SceneBase } from "./scene-base";
|
||||
import CandyBar from "./ui/candy-bar";
|
||||
import { Variant, variantData } from "./data/variant";
|
||||
@ -2445,7 +2445,10 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
if ((modifier as PersistentModifier).add(this.modifiers, !!virtual, this)) {
|
||||
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) {
|
||||
success = modifier.apply([ this.getPokemonById(modifier.pokemonId), true ]);
|
||||
const pokemon = this.getPokemonById(modifier.pokemonId);
|
||||
if (pokemon) {
|
||||
success = modifier.apply(pokemon, true);
|
||||
}
|
||||
}
|
||||
if (playSound && !this.sound.get(soundName)) {
|
||||
this.playSound(soundName);
|
||||
@ -2472,7 +2475,7 @@ export default class BattleScene extends SceneBase {
|
||||
for (const p in this.party) {
|
||||
const pokemon = this.party[p];
|
||||
|
||||
const args: any[] = [ pokemon ];
|
||||
const args: unknown[] = [];
|
||||
if (modifier instanceof PokemonHpRestoreModifier) {
|
||||
if (!(modifier as PokemonHpRestoreModifier).fainted) {
|
||||
const hpRestoreMultiplier = new Utils.IntegerHolder(1);
|
||||
@ -2485,8 +2488,8 @@ export default class BattleScene extends SceneBase {
|
||||
args.push(this.getPokemonById(modifier.fusePokemonId) as PlayerPokemon);
|
||||
}
|
||||
|
||||
if (modifier.shouldApply(args)) {
|
||||
const result = modifier.apply(args);
|
||||
if (modifier.shouldApply(pokemon, ...args)) {
|
||||
const result = modifier.apply(pokemon, ...args);
|
||||
if (result instanceof Promise) {
|
||||
modifierPromises.push(result.then(s => success ||= s));
|
||||
} else {
|
||||
@ -2498,8 +2501,8 @@ export default class BattleScene extends SceneBase {
|
||||
return Promise.allSettled([this.party.map(p => p.updateInfo(instant)), ...modifierPromises]).then(() => resolve(success));
|
||||
} else {
|
||||
const args = [ this ];
|
||||
if (modifier.shouldApply(args)) {
|
||||
const result = modifier.apply(args);
|
||||
if (modifier.shouldApply(...args)) {
|
||||
const result = modifier.apply(...args);
|
||||
if (result instanceof Promise) {
|
||||
return result.then(success => resolve(success));
|
||||
} else {
|
||||
@ -2521,7 +2524,10 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
if ((modifier as PersistentModifier).add(this.enemyModifiers, false, this)) {
|
||||
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) {
|
||||
modifier.apply([ this.getPokemonById(modifier.pokemonId), true ]);
|
||||
const pokemon = this.getPokemonById(modifier.pokemonId);
|
||||
if (pokemon) {
|
||||
modifier.apply(pokemon, true);
|
||||
}
|
||||
}
|
||||
for (const rm of modifiersToRemove) {
|
||||
this.removeModifier(rm, true);
|
||||
@ -2755,7 +2761,10 @@ export default class BattleScene extends SceneBase {
|
||||
if (modifierIndex > -1) {
|
||||
modifiers.splice(modifierIndex, 1);
|
||||
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) {
|
||||
modifier.apply([ this.getPokemonById(modifier.pokemonId), false ]);
|
||||
const pokemon = this.getPokemonById(modifier.pokemonId);
|
||||
if (pokemon) {
|
||||
modifier.apply(pokemon, false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -2773,16 +2782,36 @@ export default class BattleScene extends SceneBase {
|
||||
return (player ? this.modifiers : this.enemyModifiers).filter((m): m is T => m instanceof modifierType);
|
||||
}
|
||||
|
||||
findModifiers(modifierFilter: ModifierPredicate, player: boolean = true): PersistentModifier[] {
|
||||
return (player ? this.modifiers : this.enemyModifiers).filter(m => (modifierFilter as ModifierPredicate)(m));
|
||||
/**
|
||||
* Get all of the modifiers that pass the `modifierFilter` function
|
||||
* @param modifierFilter The function used to filter a target's modifiers
|
||||
* @param isPlayer Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
|
||||
* @returns the list of all modifiers that passed the `modifierFilter` function
|
||||
*/
|
||||
findModifiers(modifierFilter: ModifierPredicate, isPlayer: boolean = true): PersistentModifier[] {
|
||||
return (isPlayer ? this.modifiers : this.enemyModifiers).filter(modifierFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first modifier that pass the `modifierFilter` function
|
||||
* @param modifierFilter The function used to filter a target's modifiers
|
||||
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
|
||||
* @returns the first modifier that passed the `modifierFilter` function; `undefined` if none passed
|
||||
*/
|
||||
findModifier(modifierFilter: ModifierPredicate, player: boolean = true): PersistentModifier | undefined {
|
||||
return (player ? this.modifiers : this.enemyModifiers).find(m => (modifierFilter as ModifierPredicate)(m));
|
||||
return (player ? this.modifiers : this.enemyModifiers).find(modifierFilter);
|
||||
}
|
||||
|
||||
applyShuffledModifiers(scene: BattleScene, modifierType: Constructor<Modifier>, player: boolean = true, ...args: any[]): PersistentModifier[] {
|
||||
let modifiers = (player ? this.modifiers : this.enemyModifiers).filter(m => m instanceof modifierType && m.shouldApply(args));
|
||||
/**
|
||||
* Apply all modifiers that match `modifierType` in a random order
|
||||
* @param scene {@linkcode BattleScene} used to randomize the order of modifiers
|
||||
* @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier}
|
||||
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
|
||||
* @param ...args The list of arguments needed to invoke `modifierType.apply`
|
||||
* @returns the list of all modifiers that matched `modifierType` and were applied.
|
||||
*/
|
||||
applyShuffledModifiers<T extends PersistentModifier>(scene: BattleScene, modifierType: Constructor<T>, player: boolean = true, ...args: Parameters<T["apply"]>): T[] {
|
||||
let modifiers = (player ? this.modifiers : this.enemyModifiers).filter((m): m is T => m instanceof modifierType && m.shouldApply(...args));
|
||||
scene.executeWithSeedOffset(() => {
|
||||
const shuffleModifiers = mods => {
|
||||
if (mods.length < 1) {
|
||||
@ -2796,15 +2825,23 @@ export default class BattleScene extends SceneBase {
|
||||
return this.applyModifiersInternal(modifiers, player, args);
|
||||
}
|
||||
|
||||
applyModifiers(modifierType: Constructor<Modifier>, player: boolean = true, ...args: any[]): PersistentModifier[] {
|
||||
const modifiers = (player ? this.modifiers : this.enemyModifiers).filter(m => m instanceof modifierType && m.shouldApply(args));
|
||||
/**
|
||||
* Apply all modifiers that match `modifierType`
|
||||
* @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier}
|
||||
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
|
||||
* @param ...args The list of arguments needed to invoke `modifierType.apply`
|
||||
* @returns the list of all modifiers that matched `modifierType` and were applied.
|
||||
*/
|
||||
applyModifiers<T extends PersistentModifier>(modifierType: Constructor<T>, player: boolean = true, ...args: Parameters<T["apply"]>): T[] {
|
||||
const modifiers = (player ? this.modifiers : this.enemyModifiers).filter((m): m is T => m instanceof modifierType && m.shouldApply(...args));
|
||||
return this.applyModifiersInternal(modifiers, player, args);
|
||||
}
|
||||
|
||||
applyModifiersInternal(modifiers: PersistentModifier[], player: boolean, args: any[]): PersistentModifier[] {
|
||||
const appliedModifiers: PersistentModifier[] = [];
|
||||
/** Helper function to apply all passed modifiers */
|
||||
applyModifiersInternal<T extends PersistentModifier>(modifiers: T[], player: boolean, args: Parameters<T["apply"]>): T[] {
|
||||
const appliedModifiers: T[] = [];
|
||||
for (const modifier of modifiers) {
|
||||
if (modifier.apply(args)) {
|
||||
if (modifier.apply(...args)) {
|
||||
console.log("Applied", modifier.type.name, !player ? "(enemy)" : "");
|
||||
appliedModifiers.push(modifier);
|
||||
}
|
||||
@ -2813,10 +2850,17 @@ export default class BattleScene extends SceneBase {
|
||||
return appliedModifiers;
|
||||
}
|
||||
|
||||
applyModifier(modifierType: Constructor<Modifier>, player: boolean = true, ...args: any[]): PersistentModifier | null {
|
||||
const modifiers = (player ? this.modifiers : this.enemyModifiers).filter(m => m instanceof modifierType && m.shouldApply(args));
|
||||
/**
|
||||
* Apply the first modifier that matches `modifierType`
|
||||
* @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier}
|
||||
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
|
||||
* @param ...args The list of arguments needed to invoke `modifierType.apply`
|
||||
* @returns the first modifier that matches `modifierType` and was applied; return `null` if none matched
|
||||
*/
|
||||
applyModifier<T extends PersistentModifier>(modifierType: Constructor<T>, player: boolean = true, ...args: Parameters<T["apply"]>): T | null {
|
||||
const modifiers = (player ? this.modifiers : this.enemyModifiers).filter((m): m is T => m instanceof modifierType && m.shouldApply(...args));
|
||||
for (const modifier of modifiers) {
|
||||
if (modifier.apply(args)) {
|
||||
if (modifier.apply(...args)) {
|
||||
console.log("Applied", modifier.type.name, !player ? "(enemy)" : "");
|
||||
return modifier;
|
||||
}
|
||||
@ -2882,7 +2926,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
}
|
||||
|
||||
validateAchv(achv: Achv, args?: any[]): boolean {
|
||||
validateAchv(achv: Achv, args?: unknown[]): boolean {
|
||||
if (!this.gameData.achvUnlocks.hasOwnProperty(achv.id) && achv.validate(this, args)) {
|
||||
this.gameData.achvUnlocks[achv.id] = new Date().getTime();
|
||||
this.ui.achvBar.showAchv(achv);
|
||||
@ -2895,7 +2939,7 @@ export default class BattleScene extends SceneBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
validateVoucher(voucher: Voucher, args?: any[]): boolean {
|
||||
validateVoucher(voucher: Voucher, args?: unknown[]): boolean {
|
||||
if (!this.gameData.voucherUnlocks.hasOwnProperty(voucher.id) && voucher.validate(this, args)) {
|
||||
this.gameData.voucherUnlocks[voucher.id] = new Date().getTime();
|
||||
this.ui.achvBar.showAchv(voucher);
|
||||
|
@ -123,6 +123,7 @@ export class Ability implements Localizable {
|
||||
type AbAttrApplyFunc<TAttr extends AbAttr> = (attr: TAttr, passive: boolean) => boolean | Promise<boolean>;
|
||||
type AbAttrCondition = (pokemon: Pokemon) => boolean;
|
||||
|
||||
// TODO: Can this be improved?
|
||||
type PokemonAttackCondition = (user: Pokemon | null, target: Pokemon | null, move: Move) => boolean;
|
||||
type PokemonDefendCondition = (target: Pokemon, user: Pokemon, move: Move) => boolean;
|
||||
type PokemonStatStageChangeCondition = (target: Pokemon, statsChanged: BattleStat[], stages: number) => boolean;
|
||||
@ -518,6 +519,7 @@ export class FullHpResistTypeAbAttr extends PreDefendAbAttr {
|
||||
|
||||
if (pokemon.isFullHp() && typeMultiplier.value > 0.5) {
|
||||
typeMultiplier.value = 0.5;
|
||||
pokemon.turnData.moveEffectiveness = 0.5;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -2432,7 +2434,7 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr {
|
||||
pokemon.setStatStage(s, target.getStatStage(s));
|
||||
}
|
||||
|
||||
pokemon.summonData.moveset = target.getMoveset().map(m => new PokemonMove(m!.moveId, m!.ppUsed, m!.ppUp)); // TODO: are those bangs correct?
|
||||
pokemon.summonData.moveset = target.getMoveset().map(m => new PokemonMove(m?.moveId ?? Moves.NONE, m?.ppUsed, m?.ppUp));
|
||||
pokemon.summonData.types = target.getTypes();
|
||||
|
||||
|
||||
@ -3152,12 +3154,12 @@ export class ForewarnAbAttr extends PostSummonAbAttr {
|
||||
} else if (move?.getMove().power === -1) {
|
||||
movePower = 80;
|
||||
} else {
|
||||
movePower = move!.getMove().power; // TODO: is this bang correct?
|
||||
movePower = move?.getMove().power ?? 0;
|
||||
}
|
||||
|
||||
if (movePower > maxPowerSeen) {
|
||||
maxPowerSeen = movePower;
|
||||
maxMove = move!.getName(); // TODO: is this bang correct?
|
||||
maxMove = move?.getName() ?? "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5175,8 +5177,7 @@ export function initAbilities() {
|
||||
.attr(IgnoreOpponentStatStagesAbAttr)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.TINTED_LENS, 4)
|
||||
//@ts-ignore
|
||||
.attr(DamageBoostAbAttr, 2, (user, target, move) => target?.getMoveEffectiveness(user, move) <= 0.5), // TODO: fix TS issues
|
||||
.attr(DamageBoostAbAttr, 2, (user, target, move) => (target?.getMoveEffectiveness(user!, move) ?? 1) <= 0.5),
|
||||
new Ability(Abilities.FILTER, 4)
|
||||
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => target.getMoveEffectiveness(user, move) >= 2, 0.75)
|
||||
.ignorable(),
|
||||
@ -5294,8 +5295,9 @@ export function initAbilities() {
|
||||
.attr(WonderSkinAbAttr)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.ANALYTIC, 5)
|
||||
//@ts-ignore
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => !!target?.getLastXMoves(1).find(m => m.turn === target?.scene.currentBattle.turn) || user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command !== Command.FIGHT, 1.3), // TODO fix TS issues
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) =>
|
||||
!!target?.getLastXMoves(1).find(m => m.turn === target?.scene.currentBattle.turn)
|
||||
|| user?.scene.currentBattle.turnCommands[target?.getBattlerIndex() ?? BattlerIndex.ATTACKER]?.command !== Command.FIGHT, 1.3),
|
||||
new Ability(Abilities.ILLUSION, 5)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
@ -5460,8 +5462,7 @@ export function initAbilities() {
|
||||
.bypassFaint()
|
||||
.partial(),
|
||||
new Ability(Abilities.STAKEOUT, 7)
|
||||
//@ts-ignore
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.POKEMON, 2), // TODO: fix TS issues
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => user?.scene.currentBattle.turnCommands[target?.getBattlerIndex() ?? BattlerIndex.ATTACKER]?.command === Command.POKEMON, 2),
|
||||
new Ability(Abilities.WATER_BUBBLE, 7)
|
||||
.attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5)
|
||||
.attr(MoveTypePowerBoostAbAttr, Type.WATER, 2)
|
||||
@ -5599,8 +5600,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.PRISM_ARMOR, 7)
|
||||
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => target.getMoveEffectiveness(user, move) >= 2, 0.75),
|
||||
new Ability(Abilities.NEUROFORCE, 7)
|
||||
//@ts-ignore
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => target?.getMoveEffectiveness(user, move) >= 2, 1.25), // TODO: fix TS issues
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => (target?.getMoveEffectiveness(user!, move) ?? 1) >= 2, 1.25),
|
||||
new Ability(Abilities.INTREPID_SWORD, 8)
|
||||
.attr(PostSummonStatStageChangeAbAttr, [ Stat.ATK ], 1, true)
|
||||
.condition(getOncePerBattleCondition(Abilities.INTREPID_SWORD)),
|
||||
@ -5698,10 +5698,8 @@ export function initAbilities() {
|
||||
.attr(UserFieldStatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.HUNGER_SWITCH, 8)
|
||||
//@ts-ignore
|
||||
.attr(PostTurnFormChangeAbAttr, p => p.getFormKey ? 0 : 1) // TODO: fix ts-ignore
|
||||
//@ts-ignore
|
||||
.attr(PostTurnFormChangeAbAttr, p => p.getFormKey ? 1 : 0) // TODO: fix ts-ignore
|
||||
.attr(PostTurnFormChangeAbAttr, p => p.getFormKey() ? 0 : 1)
|
||||
.attr(PostTurnFormChangeAbAttr, p => p.getFormKey() ? 1 : 0)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Type } from "./type";
|
||||
import * as Utils from "../utils";
|
||||
import { pokemonEvolutions, SpeciesFormEvolution } from "./pokemon-evolutions";
|
||||
import { Type } from "#app/data/type";
|
||||
import * as Utils from "#app/utils";
|
||||
import { pokemonEvolutions, SpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
|
||||
import i18next from "i18next";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { Species } from "#enums/species";
|
@ -1,5 +1,5 @@
|
||||
import { allMoves } from "./move";
|
||||
import * as Utils from "../utils";
|
||||
import { allMoves } from "#app/data/move";
|
||||
import * as Utils from "#app/utils";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
|
574
src/data/balance/passives.ts
Normal file
574
src/data/balance/passives.ts
Normal file
@ -0,0 +1,574 @@
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import { Species } from "#app/enums/species";
|
||||
|
||||
export const starterPassiveAbilities = {
|
||||
[Species.BULBASAUR]: Abilities.GRASSY_SURGE,
|
||||
[Species.CHARMANDER]: Abilities.BEAST_BOOST,
|
||||
[Species.SQUIRTLE]: Abilities.STURDY,
|
||||
[Species.CATERPIE]: Abilities.MAGICIAN,
|
||||
[Species.WEEDLE]: Abilities.TINTED_LENS,
|
||||
[Species.PIDGEY]: Abilities.SHEER_FORCE,
|
||||
[Species.RATTATA]: Abilities.STRONG_JAW,
|
||||
[Species.SPEAROW]: Abilities.MOXIE,
|
||||
[Species.EKANS]: Abilities.REGENERATOR,
|
||||
[Species.SANDSHREW]: Abilities.TOUGH_CLAWS,
|
||||
[Species.NIDORAN_F]: Abilities.FLARE_BOOST,
|
||||
[Species.NIDORAN_M]: Abilities.GUTS,
|
||||
[Species.VULPIX]: Abilities.FUR_COAT,
|
||||
[Species.ZUBAT]: Abilities.INTIMIDATE,
|
||||
[Species.ODDISH]: Abilities.TRIAGE,
|
||||
[Species.PARAS]: Abilities.TRIAGE,
|
||||
[Species.VENONAT]: Abilities.SIMPLE,
|
||||
[Species.DIGLETT]: Abilities.STURDY,
|
||||
[Species.MEOWTH]: Abilities.TOUGH_CLAWS,
|
||||
[Species.PSYDUCK]: Abilities.SIMPLE,
|
||||
[Species.MANKEY]: Abilities.IRON_FIST,
|
||||
[Species.GROWLITHE]: Abilities.SPEED_BOOST,
|
||||
[Species.POLIWAG]: Abilities.NO_GUARD,
|
||||
[Species.ABRA]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.MACHOP]: Abilities.QUICK_FEET,
|
||||
[Species.BELLSPROUT]: Abilities.FLOWER_GIFT,
|
||||
[Species.TENTACOOL]: Abilities.TOXIC_CHAIN,
|
||||
[Species.GEODUDE]: Abilities.DRY_SKIN,
|
||||
[Species.PONYTA]: Abilities.MAGIC_GUARD,
|
||||
[Species.SLOWPOKE]: Abilities.UNAWARE,
|
||||
[Species.MAGNEMITE]: Abilities.LEVITATE,
|
||||
[Species.FARFETCHD]: Abilities.SNIPER,
|
||||
[Species.DODUO]: Abilities.PARENTAL_BOND,
|
||||
[Species.SEEL]: Abilities.WATER_BUBBLE,
|
||||
[Species.GRIMER]: Abilities.WATER_ABSORB,
|
||||
[Species.SHELLDER]: Abilities.ICE_SCALES,
|
||||
[Species.GASTLY]: Abilities.SHADOW_SHIELD,
|
||||
[Species.ONIX]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.DROWZEE]: Abilities.MAGICIAN,
|
||||
[Species.KRABBY]: Abilities.THERMAL_EXCHANGE,
|
||||
[Species.VOLTORB]: Abilities.TRANSISTOR,
|
||||
[Species.EXEGGCUTE]: Abilities.RIPEN,
|
||||
[Species.CUBONE]: Abilities.PARENTAL_BOND,
|
||||
[Species.LICKITUNG]: Abilities.CHEEK_POUCH,
|
||||
[Species.KOFFING]: Abilities.PARENTAL_BOND,
|
||||
[Species.RHYHORN]: Abilities.FILTER,
|
||||
[Species.TANGELA]: Abilities.SEED_SOWER,
|
||||
[Species.KANGASKHAN]: Abilities.GUTS,
|
||||
[Species.HORSEA]: Abilities.DRAGONS_MAW,
|
||||
[Species.GOLDEEN]: Abilities.MULTISCALE,
|
||||
[Species.STARYU]: Abilities.REGENERATOR,
|
||||
[Species.SCYTHER]: Abilities.TINTED_LENS,
|
||||
[Species.PINSIR]: Abilities.TINTED_LENS,
|
||||
[Species.TAUROS]: Abilities.STAMINA,
|
||||
[Species.MAGIKARP]: Abilities.MULTISCALE,
|
||||
[Species.LAPRAS]: Abilities.LIGHTNING_ROD,
|
||||
[Species.DITTO]: Abilities.ADAPTABILITY,
|
||||
[Species.EEVEE]: Abilities.PICKUP,
|
||||
[Species.PORYGON]: Abilities.PROTEAN,
|
||||
[Species.OMANYTE]: Abilities.STURDY,
|
||||
[Species.KABUTO]: Abilities.TOUGH_CLAWS,
|
||||
[Species.AERODACTYL]: Abilities.ORICHALCUM_PULSE,
|
||||
[Species.ARTICUNO]: Abilities.SNOW_WARNING,
|
||||
[Species.ZAPDOS]: Abilities.DRIZZLE,
|
||||
[Species.MOLTRES]: Abilities.DROUGHT,
|
||||
[Species.DRATINI]: Abilities.AERILATE,
|
||||
[Species.MEWTWO]: Abilities.NEUROFORCE,
|
||||
[Species.MEW]: Abilities.PROTEAN,
|
||||
[Species.CHIKORITA]: Abilities.THICK_FAT,
|
||||
[Species.CYNDAQUIL]: Abilities.DROUGHT,
|
||||
[Species.TOTODILE]: Abilities.TOUGH_CLAWS,
|
||||
[Species.SENTRET]: Abilities.PICKUP,
|
||||
[Species.HOOTHOOT]: Abilities.AERILATE,
|
||||
[Species.LEDYBA]: Abilities.PRANKSTER,
|
||||
[Species.SPINARAK]: Abilities.PRANKSTER,
|
||||
[Species.CHINCHOU]: Abilities.WATER_BUBBLE,
|
||||
[Species.PICHU]: Abilities.ELECTRIC_SURGE,
|
||||
[Species.CLEFFA]: Abilities.ANALYTIC,
|
||||
[Species.IGGLYBUFF]: Abilities.HUGE_POWER,
|
||||
[Species.TOGEPI]: Abilities.PIXILATE,
|
||||
[Species.NATU]: Abilities.TINTED_LENS,
|
||||
[Species.MAREEP]: Abilities.ELECTROMORPHOSIS,
|
||||
[Species.HOPPIP]: Abilities.FLUFFY,
|
||||
[Species.AIPOM]: Abilities.SCRAPPY,
|
||||
[Species.SUNKERN]: Abilities.DROUGHT,
|
||||
[Species.YANMA]: Abilities.SHEER_FORCE,
|
||||
[Species.WOOPER]: Abilities.COMATOSE,
|
||||
[Species.MURKROW]: Abilities.DARK_AURA,
|
||||
[Species.MISDREAVUS]: Abilities.BEADS_OF_RUIN,
|
||||
[Species.UNOWN]: Abilities.PICKUP,
|
||||
[Species.GIRAFARIG]: Abilities.PARENTAL_BOND,
|
||||
[Species.PINECO]: Abilities.IRON_BARBS,
|
||||
[Species.DUNSPARCE]: Abilities.UNAWARE,
|
||||
[Species.GLIGAR]: Abilities.TOXIC_BOOST,
|
||||
[Species.SNUBBULL]: Abilities.PIXILATE,
|
||||
[Species.QWILFISH]: Abilities.TOXIC_DEBRIS,
|
||||
[Species.SHUCKLE]: Abilities.HARVEST,
|
||||
[Species.HERACROSS]: Abilities.TECHNICIAN,
|
||||
[Species.SNEASEL]: Abilities.TOUGH_CLAWS,
|
||||
[Species.TEDDIURSA]: Abilities.THICK_FAT,
|
||||
[Species.SLUGMA]: Abilities.DESOLATE_LAND,
|
||||
[Species.SWINUB]: Abilities.SLUSH_RUSH,
|
||||
[Species.CORSOLA]: Abilities.STORM_DRAIN,
|
||||
[Species.REMORAID]: Abilities.SIMPLE,
|
||||
[Species.DELIBIRD]: Abilities.HUGE_POWER,
|
||||
[Species.SKARMORY]: Abilities.LIGHTNING_ROD,
|
||||
[Species.HOUNDOUR]: Abilities.DROUGHT,
|
||||
[Species.PHANPY]: Abilities.SPEED_BOOST,
|
||||
[Species.STANTLER]: Abilities.SPEED_BOOST,
|
||||
[Species.SMEARGLE]: Abilities.PRANKSTER,
|
||||
[Species.TYROGUE]: Abilities.MOXIE,
|
||||
[Species.SMOOCHUM]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.ELEKID]: Abilities.SHEER_FORCE,
|
||||
[Species.MAGBY]: Abilities.CONTRARY,
|
||||
[Species.MILTANK]: Abilities.STAMINA,
|
||||
[Species.RAIKOU]: Abilities.TRANSISTOR,
|
||||
[Species.ENTEI]: Abilities.MOXIE,
|
||||
[Species.SUICUNE]: Abilities.UNAWARE,
|
||||
[Species.LARVITAR]: Abilities.SAND_RUSH,
|
||||
[Species.LUGIA]: Abilities.DELTA_STREAM,
|
||||
[Species.HO_OH]: Abilities.MAGIC_GUARD,
|
||||
[Species.CELEBI]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.TREECKO]: Abilities.TINTED_LENS,
|
||||
[Species.TORCHIC]: Abilities.RECKLESS,
|
||||
[Species.MUDKIP]: Abilities.DRIZZLE,
|
||||
[Species.POOCHYENA]: Abilities.TOUGH_CLAWS,
|
||||
[Species.ZIGZAGOON]: Abilities.RUN_AWAY,
|
||||
[Species.WURMPLE]: Abilities.SIMPLE,
|
||||
[Species.LOTAD]: Abilities.DRIZZLE,
|
||||
[Species.SEEDOT]: Abilities.SHARPNESS,
|
||||
[Species.TAILLOW]: Abilities.AERILATE,
|
||||
[Species.WINGULL]: Abilities.SWIFT_SWIM,
|
||||
[Species.RALTS]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.SURSKIT]: Abilities.WATER_BUBBLE,
|
||||
[Species.SHROOMISH]: Abilities.GUTS,
|
||||
[Species.SLAKOTH]: Abilities.GUTS,
|
||||
[Species.NINCADA]: Abilities.MAGIC_GUARD,
|
||||
[Species.WHISMUR]: Abilities.PUNK_ROCK,
|
||||
[Species.MAKUHITA]: Abilities.STAMINA,
|
||||
[Species.AZURILL]: Abilities.MISTY_SURGE,
|
||||
[Species.NOSEPASS]: Abilities.LEVITATE,
|
||||
[Species.SKITTY]: Abilities.SCRAPPY,
|
||||
[Species.SABLEYE]: Abilities.UNNERVE,
|
||||
[Species.MAWILE]: Abilities.UNNERVE,
|
||||
[Species.ARON]: Abilities.EARTH_EATER,
|
||||
[Species.MEDITITE]: Abilities.MINDS_EYE,
|
||||
[Species.ELECTRIKE]: Abilities.ELECTRIC_SURGE,
|
||||
[Species.PLUSLE]: Abilities.POWER_SPOT,
|
||||
[Species.MINUN]: Abilities.POWER_SPOT,
|
||||
[Species.VOLBEAT]: Abilities.HONEY_GATHER,
|
||||
[Species.ILLUMISE]: Abilities.HONEY_GATHER,
|
||||
[Species.GULPIN]: Abilities.EARTH_EATER,
|
||||
[Species.CARVANHA]: Abilities.SHEER_FORCE,
|
||||
[Species.WAILMER]: Abilities.LEVITATE,
|
||||
[Species.NUMEL]: Abilities.FUR_COAT,
|
||||
[Species.TORKOAL]: Abilities.ANALYTIC,
|
||||
[Species.SPOINK]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.SPINDA]: Abilities.SIMPLE,
|
||||
[Species.TRAPINCH]: Abilities.ADAPTABILITY,
|
||||
[Species.CACNEA]: Abilities.SAND_RUSH,
|
||||
[Species.SWABLU]: Abilities.ADAPTABILITY,
|
||||
[Species.ZANGOOSE]: Abilities.POISON_HEAL,
|
||||
[Species.SEVIPER]: Abilities.MULTISCALE,
|
||||
[Species.LUNATONE]: Abilities.SHADOW_SHIELD,
|
||||
[Species.SOLROCK]: Abilities.DROUGHT,
|
||||
[Species.BARBOACH]: Abilities.SIMPLE,
|
||||
[Species.CORPHISH]: Abilities.TOUGH_CLAWS,
|
||||
[Species.BALTOY]: Abilities.WELL_BAKED_BODY,
|
||||
[Species.LILEEP]: Abilities.SEED_SOWER,
|
||||
[Species.ANORITH]: Abilities.WATER_ABSORB,
|
||||
[Species.FEEBAS]: Abilities.MAGIC_GUARD,
|
||||
[Species.CASTFORM]: Abilities.ADAPTABILITY,
|
||||
[Species.KECLEON]: Abilities.ADAPTABILITY,
|
||||
[Species.SHUPPET]: Abilities.SHADOW_SHIELD,
|
||||
[Species.DUSKULL]: Abilities.UNNERVE,
|
||||
[Species.TROPIUS]: Abilities.RIPEN,
|
||||
[Species.ABSOL]: Abilities.SHARPNESS,
|
||||
[Species.WYNAUT]: Abilities.STURDY,
|
||||
[Species.SNORUNT]: Abilities.SNOW_WARNING,
|
||||
[Species.SPHEAL]: Abilities.UNAWARE,
|
||||
[Species.CLAMPERL]: Abilities.DRIZZLE,
|
||||
[Species.RELICANTH]: Abilities.PRIMORDIAL_SEA,
|
||||
[Species.LUVDISC]: Abilities.MULTISCALE,
|
||||
[Species.BAGON]: Abilities.DRAGONS_MAW,
|
||||
[Species.BELDUM]: Abilities.LEVITATE,
|
||||
[Species.REGIROCK]: Abilities.SAND_STREAM,
|
||||
[Species.REGICE]: Abilities.SNOW_WARNING,
|
||||
[Species.REGISTEEL]: Abilities.FILTER,
|
||||
[Species.LATIAS]: Abilities.PRISM_ARMOR,
|
||||
[Species.LATIOS]: Abilities.TINTED_LENS,
|
||||
[Species.KYOGRE]: Abilities.MOLD_BREAKER,
|
||||
[Species.GROUDON]: Abilities.TURBOBLAZE,
|
||||
[Species.RAYQUAZA]: Abilities.UNNERVE,
|
||||
[Species.JIRACHI]: Abilities.COMATOSE,
|
||||
[Species.DEOXYS]: Abilities.PROTEAN,
|
||||
[Species.TURTWIG]: Abilities.THICK_FAT,
|
||||
[Species.CHIMCHAR]: Abilities.BEAST_BOOST,
|
||||
[Species.PIPLUP]: Abilities.DRIZZLE,
|
||||
[Species.STARLY]: Abilities.ROCK_HEAD,
|
||||
[Species.BIDOOF]: Abilities.SAP_SIPPER,
|
||||
[Species.KRICKETOT]: Abilities.SHARPNESS,
|
||||
[Species.SHINX]: Abilities.SPEED_BOOST,
|
||||
[Species.BUDEW]: Abilities.GRASSY_SURGE,
|
||||
[Species.CRANIDOS]: Abilities.ROCK_HEAD,
|
||||
[Species.SHIELDON]: Abilities.EARTH_EATER,
|
||||
[Species.BURMY]: Abilities.STURDY,
|
||||
[Species.COMBEE]: Abilities.INTIMIDATE,
|
||||
[Species.PACHIRISU]: Abilities.HONEY_GATHER,
|
||||
[Species.BUIZEL]: Abilities.MOXIE,
|
||||
[Species.CHERUBI]: Abilities.ORICHALCUM_PULSE,
|
||||
[Species.SHELLOS]: Abilities.REGENERATOR,
|
||||
[Species.DRIFLOON]: Abilities.MAGIC_GUARD,
|
||||
[Species.BUNEARY]: Abilities.ADAPTABILITY,
|
||||
[Species.GLAMEOW]: Abilities.INTIMIDATE,
|
||||
[Species.CHINGLING]: Abilities.PUNK_ROCK,
|
||||
[Species.STUNKY]: Abilities.NEUTRALIZING_GAS,
|
||||
[Species.BRONZOR]: Abilities.BULLETPROOF,
|
||||
[Species.BONSLY]: Abilities.SAP_SIPPER,
|
||||
[Species.MIME_JR]: Abilities.OPPORTUNIST,
|
||||
[Species.HAPPINY]: Abilities.FUR_COAT,
|
||||
[Species.CHATOT]: Abilities.PUNK_ROCK,
|
||||
[Species.SPIRITOMB]: Abilities.VESSEL_OF_RUIN,
|
||||
[Species.GIBLE]: Abilities.SAND_STREAM,
|
||||
[Species.MUNCHLAX]: Abilities.RIPEN,
|
||||
[Species.RIOLU]: Abilities.MINDS_EYE,
|
||||
[Species.HIPPOPOTAS]: Abilities.UNAWARE,
|
||||
[Species.SKORUPI]: Abilities.SUPER_LUCK,
|
||||
[Species.CROAGUNK]: Abilities.MOXIE,
|
||||
[Species.CARNIVINE]: Abilities.ARENA_TRAP,
|
||||
[Species.FINNEON]: Abilities.WATER_BUBBLE,
|
||||
[Species.MANTYKE]: Abilities.UNAWARE,
|
||||
[Species.SNOVER]: Abilities.THICK_FAT,
|
||||
[Species.ROTOM]: Abilities.HADRON_ENGINE,
|
||||
[Species.UXIE]: Abilities.UNAWARE,
|
||||
[Species.MESPRIT]: Abilities.MOODY,
|
||||
[Species.AZELF]: Abilities.NEUROFORCE,
|
||||
[Species.DIALGA]: Abilities.LEVITATE,
|
||||
[Species.PALKIA]: Abilities.SPEED_BOOST,
|
||||
[Species.HEATRAN]: Abilities.EARTH_EATER,
|
||||
[Species.REGIGIGAS]: Abilities.SCRAPPY,
|
||||
[Species.GIRATINA]: Abilities.SHADOW_SHIELD,
|
||||
[Species.CRESSELIA]: Abilities.SHADOW_SHIELD,
|
||||
[Species.PHIONE]: Abilities.SIMPLE,
|
||||
[Species.MANAPHY]: Abilities.PRIMORDIAL_SEA,
|
||||
[Species.DARKRAI]: Abilities.UNNERVE,
|
||||
[Species.SHAYMIN]: Abilities.WIND_RIDER,
|
||||
[Species.ARCEUS]: Abilities.ADAPTABILITY,
|
||||
[Species.VICTINI]: Abilities.SHEER_FORCE,
|
||||
[Species.SNIVY]: Abilities.MULTISCALE,
|
||||
[Species.TEPIG]: Abilities.ROCK_HEAD,
|
||||
[Species.OSHAWOTT]: Abilities.INTREPID_SWORD,
|
||||
[Species.PATRAT]: Abilities.NO_GUARD,
|
||||
[Species.LILLIPUP]: Abilities.FUR_COAT,
|
||||
[Species.PURRLOIN]: Abilities.PICKUP,
|
||||
[Species.PANSAGE]: Abilities.WELL_BAKED_BODY,
|
||||
[Species.PANSEAR]: Abilities.WATER_ABSORB,
|
||||
[Species.PANPOUR]: Abilities.SAP_SIPPER,
|
||||
[Species.MUNNA]: Abilities.NEUTRALIZING_GAS,
|
||||
[Species.PIDOVE]: Abilities.SNIPER,
|
||||
[Species.BLITZLE]: Abilities.ELECTRIC_SURGE,
|
||||
[Species.ROGGENROLA]: Abilities.SOLID_ROCK,
|
||||
[Species.WOOBAT]: Abilities.OPPORTUNIST,
|
||||
[Species.DRILBUR]: Abilities.SAND_STREAM,
|
||||
[Species.AUDINO]: Abilities.FRIEND_GUARD,
|
||||
[Species.TIMBURR]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.TYMPOLE]: Abilities.POISON_HEAL,
|
||||
[Species.THROH]: Abilities.STAMINA,
|
||||
[Species.SAWK]: Abilities.SCRAPPY,
|
||||
[Species.SEWADDLE]: Abilities.SHARPNESS,
|
||||
[Species.VENIPEDE]: Abilities.STAMINA,
|
||||
[Species.COTTONEE]: Abilities.FLUFFY,
|
||||
[Species.PETILIL]: Abilities.SIMPLE,
|
||||
[Species.BASCULIN]: Abilities.SUPREME_OVERLORD,
|
||||
[Species.SANDILE]: Abilities.TOUGH_CLAWS,
|
||||
[Species.DARUMAKA]: Abilities.GORILLA_TACTICS,
|
||||
[Species.MARACTUS]: Abilities.WELL_BAKED_BODY,
|
||||
[Species.DWEBBLE]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.SCRAGGY]: Abilities.PROTEAN,
|
||||
[Species.SIGILYPH]: Abilities.FLARE_BOOST,
|
||||
[Species.YAMASK]: Abilities.PURIFYING_SALT,
|
||||
[Species.TIRTOUGA]: Abilities.WATER_ABSORB,
|
||||
[Species.ARCHEN]: Abilities.MULTISCALE,
|
||||
[Species.TRUBBISH]: Abilities.NEUTRALIZING_GAS,
|
||||
[Species.ZORUA]: Abilities.DARK_AURA,
|
||||
[Species.MINCCINO]: Abilities.FUR_COAT,
|
||||
[Species.GOTHITA]: Abilities.UNNERVE,
|
||||
[Species.SOLOSIS]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.DUCKLETT]: Abilities.DRIZZLE,
|
||||
[Species.VANILLITE]: Abilities.SLUSH_RUSH,
|
||||
[Species.DEERLING]: Abilities.FUR_COAT,
|
||||
[Species.EMOLGA]: Abilities.TRANSISTOR,
|
||||
[Species.KARRABLAST]: Abilities.QUICK_DRAW,
|
||||
[Species.FOONGUS]: Abilities.THICK_FAT,
|
||||
[Species.FRILLISH]: Abilities.POISON_HEAL,
|
||||
[Species.ALOMOMOLA]: Abilities.MULTISCALE,
|
||||
[Species.JOLTIK]: Abilities.TRANSISTOR,
|
||||
[Species.FERROSEED]: Abilities.ROUGH_SKIN,
|
||||
[Species.KLINK]: Abilities.STEELY_SPIRIT,
|
||||
[Species.TYNAMO]: Abilities.POISON_HEAL,
|
||||
[Species.ELGYEM]: Abilities.PRISM_ARMOR,
|
||||
[Species.LITWICK]: Abilities.SOUL_HEART,
|
||||
[Species.AXEW]: Abilities.DRAGONS_MAW,
|
||||
[Species.CUBCHOO]: Abilities.TOUGH_CLAWS,
|
||||
[Species.CRYOGONAL]: Abilities.SNOW_WARNING,
|
||||
[Species.SHELMET]: Abilities.PROTEAN,
|
||||
[Species.STUNFISK]: Abilities.STORM_DRAIN,
|
||||
[Species.MIENFOO]: Abilities.NO_GUARD,
|
||||
[Species.DRUDDIGON]: Abilities.INTIMIDATE,
|
||||
[Species.GOLETT]: Abilities.SHADOW_SHIELD,
|
||||
[Species.PAWNIARD]: Abilities.SWORD_OF_RUIN,
|
||||
[Species.BOUFFALANT]: Abilities.ROCK_HEAD,
|
||||
[Species.RUFFLET]: Abilities.SPEED_BOOST,
|
||||
[Species.VULLABY]: Abilities.THICK_FAT,
|
||||
[Species.HEATMOR]: Abilities.CONTRARY,
|
||||
[Species.DURANT]: Abilities.COMPOUND_EYES,
|
||||
[Species.DEINO]: Abilities.PARENTAL_BOND,
|
||||
[Species.LARVESTA]: Abilities.DROUGHT,
|
||||
[Species.COBALION]: Abilities.INTREPID_SWORD,
|
||||
[Species.TERRAKION]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.VIRIZION]: Abilities.SHARPNESS,
|
||||
[Species.TORNADUS]: Abilities.DRIZZLE,
|
||||
[Species.THUNDURUS]: Abilities.DRIZZLE,
|
||||
[Species.RESHIRAM]: Abilities.ORICHALCUM_PULSE,
|
||||
[Species.ZEKROM]: Abilities.HADRON_ENGINE,
|
||||
[Species.LANDORUS]: Abilities.STORM_DRAIN,
|
||||
[Species.KYUREM]: Abilities.SNOW_WARNING,
|
||||
[Species.KELDEO]: Abilities.GRIM_NEIGH,
|
||||
[Species.MELOETTA]: Abilities.MINDS_EYE,
|
||||
[Species.GENESECT]: Abilities.PROTEAN,
|
||||
[Species.CHESPIN]: Abilities.DAUNTLESS_SHIELD,
|
||||
[Species.FENNEKIN]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.FROAKIE]: Abilities.STAKEOUT,
|
||||
[Species.BUNNELBY]: Abilities.GUTS,
|
||||
[Species.FLETCHLING]: Abilities.MAGIC_GUARD,
|
||||
[Species.SCATTERBUG]: Abilities.PRANKSTER,
|
||||
[Species.LITLEO]: Abilities.BEAST_BOOST,
|
||||
[Species.FLABEBE]: Abilities.GRASSY_SURGE,
|
||||
[Species.SKIDDO]: Abilities.SEED_SOWER,
|
||||
[Species.PANCHAM]: Abilities.FUR_COAT,
|
||||
[Species.FURFROU]: Abilities.FLUFFY,
|
||||
[Species.ESPURR]: Abilities.FUR_COAT,
|
||||
[Species.HONEDGE]: Abilities.SHARPNESS,
|
||||
[Species.SPRITZEE]: Abilities.FUR_COAT,
|
||||
[Species.SWIRLIX]: Abilities.WELL_BAKED_BODY,
|
||||
[Species.INKAY]: Abilities.UNNERVE,
|
||||
[Species.BINACLE]: Abilities.SAP_SIPPER,
|
||||
[Species.SKRELP]: Abilities.DRAGONS_MAW,
|
||||
[Species.CLAUNCHER]: Abilities.SWIFT_SWIM,
|
||||
[Species.HELIOPTILE]: Abilities.PROTEAN,
|
||||
[Species.TYRUNT]: Abilities.RECKLESS,
|
||||
[Species.AMAURA]: Abilities.ICE_SCALES,
|
||||
[Species.HAWLUCHA]: Abilities.MOXIE,
|
||||
[Species.DEDENNE]: Abilities.PIXILATE,
|
||||
[Species.CARBINK]: Abilities.SOLID_ROCK,
|
||||
[Species.GOOMY]: Abilities.REGENERATOR,
|
||||
[Species.KLEFKI]: Abilities.LEVITATE,
|
||||
[Species.PHANTUMP]: Abilities.SHADOW_TAG,
|
||||
[Species.PUMPKABOO]: Abilities.WELL_BAKED_BODY,
|
||||
[Species.BERGMITE]: Abilities.ICE_SCALES,
|
||||
[Species.NOIBAT]: Abilities.PUNK_ROCK,
|
||||
[Species.XERNEAS]: Abilities.HARVEST,
|
||||
[Species.YVELTAL]: Abilities.SOUL_HEART,
|
||||
[Species.ZYGARDE]: Abilities.HUGE_POWER,
|
||||
[Species.DIANCIE]: Abilities.LEVITATE,
|
||||
[Species.HOOPA]: Abilities.OPPORTUNIST,
|
||||
[Species.VOLCANION]: Abilities.FILTER,
|
||||
[Species.ROWLET]: Abilities.SNIPER,
|
||||
[Species.LITTEN]: Abilities.OPPORTUNIST,
|
||||
[Species.POPPLIO]: Abilities.PUNK_ROCK,
|
||||
[Species.PIKIPEK]: Abilities.TECHNICIAN,
|
||||
[Species.YUNGOOS]: Abilities.TOUGH_CLAWS,
|
||||
[Species.GRUBBIN]: Abilities.SPEED_BOOST,
|
||||
[Species.CRABRAWLER]: Abilities.WATER_BUBBLE,
|
||||
[Species.ORICORIO]: Abilities.ADAPTABILITY,
|
||||
[Species.CUTIEFLY]: Abilities.TINTED_LENS,
|
||||
[Species.ROCKRUFF]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.WISHIWASHI]: Abilities.REGENERATOR,
|
||||
[Species.MAREANIE]: Abilities.TOXIC_DEBRIS,
|
||||
[Species.MUDBRAY]: Abilities.CUD_CHEW,
|
||||
[Species.DEWPIDER]: Abilities.TINTED_LENS,
|
||||
[Species.FOMANTIS]: Abilities.SHARPNESS,
|
||||
[Species.MORELULL]: Abilities.TRIAGE,
|
||||
[Species.SALANDIT]: Abilities.DRAGONS_MAW,
|
||||
[Species.STUFFUL]: Abilities.SCRAPPY,
|
||||
[Species.BOUNSWEET]: Abilities.MOXIE,
|
||||
[Species.COMFEY]: Abilities.FRIEND_GUARD,
|
||||
[Species.ORANGURU]: Abilities.POWER_SPOT,
|
||||
[Species.PASSIMIAN]: Abilities.LIBERO,
|
||||
[Species.WIMPOD]: Abilities.REGENERATOR,
|
||||
[Species.SANDYGAST]: Abilities.SAND_SPIT,
|
||||
[Species.PYUKUMUKU]: Abilities.PURIFYING_SALT,
|
||||
[Species.TYPE_NULL]: Abilities.ADAPTABILITY,
|
||||
[Species.MINIOR]: Abilities.STURDY,
|
||||
[Species.KOMALA]: Abilities.GUTS,
|
||||
[Species.TURTONATOR]: Abilities.DAUNTLESS_SHIELD,
|
||||
[Species.TOGEDEMARU]: Abilities.ROUGH_SKIN,
|
||||
[Species.MIMIKYU]: Abilities.TOUGH_CLAWS,
|
||||
[Species.BRUXISH]: Abilities.MULTISCALE,
|
||||
[Species.DRAMPA]: Abilities.THICK_FAT,
|
||||
[Species.DHELMISE]: Abilities.WATER_BUBBLE,
|
||||
[Species.JANGMO_O]: Abilities.DAUNTLESS_SHIELD,
|
||||
[Species.TAPU_KOKO]: Abilities.TRANSISTOR,
|
||||
[Species.TAPU_LELE]: Abilities.SHEER_FORCE,
|
||||
[Species.TAPU_BULU]: Abilities.TRIAGE,
|
||||
[Species.TAPU_FINI]: Abilities.FAIRY_AURA,
|
||||
[Species.COSMOG]: Abilities.BEAST_BOOST,
|
||||
[Species.NIHILEGO]: Abilities.LEVITATE,
|
||||
[Species.BUZZWOLE]: Abilities.MOXIE,
|
||||
[Species.PHEROMOSA]: Abilities.TINTED_LENS,
|
||||
[Species.XURKITREE]: Abilities.TRANSISTOR,
|
||||
[Species.CELESTEELA]: Abilities.HEATPROOF,
|
||||
[Species.KARTANA]: Abilities.SHARPNESS,
|
||||
[Species.GUZZLORD]: Abilities.POISON_HEAL,
|
||||
[Species.NECROZMA]: Abilities.BEAST_BOOST,
|
||||
[Species.MAGEARNA]: Abilities.STEELY_SPIRIT,
|
||||
[Species.MARSHADOW]: Abilities.IRON_FIST,
|
||||
[Species.POIPOLE]: Abilities.SHEER_FORCE,
|
||||
[Species.STAKATAKA]: Abilities.SOLID_ROCK,
|
||||
[Species.BLACEPHALON]: Abilities.MAGIC_GUARD,
|
||||
[Species.ZERAORA]: Abilities.TOUGH_CLAWS,
|
||||
[Species.MELTAN]: Abilities.STEELY_SPIRIT,
|
||||
[Species.GROOKEY]: Abilities.GRASS_PELT,
|
||||
[Species.SCORBUNNY]: Abilities.NO_GUARD,
|
||||
[Species.SOBBLE]: Abilities.SUPER_LUCK,
|
||||
[Species.SKWOVET]: Abilities.HARVEST,
|
||||
[Species.ROOKIDEE]: Abilities.IRON_BARBS,
|
||||
[Species.BLIPBUG]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.NICKIT]: Abilities.MAGICIAN,
|
||||
[Species.GOSSIFLEUR]: Abilities.GRASSY_SURGE,
|
||||
[Species.WOOLOO]: Abilities.SIMPLE,
|
||||
[Species.CHEWTLE]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.YAMPER]: Abilities.SHEER_FORCE,
|
||||
[Species.ROLYCOLY]: Abilities.SOLID_ROCK,
|
||||
[Species.APPLIN]: Abilities.DRAGONS_MAW,
|
||||
[Species.SILICOBRA]: Abilities.SAND_RUSH,
|
||||
[Species.CRAMORANT]: Abilities.LIGHTNING_ROD,
|
||||
[Species.ARROKUDA]: Abilities.INTIMIDATE,
|
||||
[Species.TOXEL]: Abilities.ELECTRIC_SURGE,
|
||||
[Species.SIZZLIPEDE]: Abilities.SPEED_BOOST,
|
||||
[Species.CLOBBOPUS]: Abilities.WATER_BUBBLE,
|
||||
[Species.SINISTEA]: Abilities.SHADOW_SHIELD,
|
||||
[Species.HATENNA]: Abilities.FAIRY_AURA,
|
||||
[Species.IMPIDIMP]: Abilities.FUR_COAT,
|
||||
[Species.MILCERY]: Abilities.REGENERATOR,
|
||||
[Species.FALINKS]: Abilities.PARENTAL_BOND,
|
||||
[Species.PINCURCHIN]: Abilities.ELECTROMORPHOSIS,
|
||||
[Species.SNOM]: Abilities.SNOW_WARNING,
|
||||
[Species.STONJOURNER]: Abilities.STURDY,
|
||||
[Species.EISCUE]: Abilities.ICE_SCALES,
|
||||
[Species.INDEEDEE]: Abilities.FRIEND_GUARD,
|
||||
[Species.MORPEKO]: Abilities.MOODY,
|
||||
[Species.CUFANT]: Abilities.EARTH_EATER,
|
||||
[Species.DRACOZOLT]: Abilities.NO_GUARD,
|
||||
[Species.ARCTOZOLT]: Abilities.TRANSISTOR,
|
||||
[Species.DRACOVISH]: Abilities.SWIFT_SWIM,
|
||||
[Species.ARCTOVISH]: Abilities.STRONG_JAW,
|
||||
[Species.DURALUDON]: Abilities.STEELWORKER,
|
||||
[Species.DREEPY]: Abilities.PARENTAL_BOND,
|
||||
[Species.ZACIAN]: Abilities.UNNERVE,
|
||||
[Species.ZAMAZENTA]: Abilities.UNNERVE,
|
||||
[Species.ETERNATUS]: Abilities.NEUTRALIZING_GAS,
|
||||
[Species.KUBFU]: Abilities.IRON_FIST,
|
||||
[Species.ZARUDE]: Abilities.TOUGH_CLAWS,
|
||||
[Species.REGIELEKI]: Abilities.ELECTRIC_SURGE,
|
||||
[Species.REGIDRAGO]: Abilities.MULTISCALE,
|
||||
[Species.GLASTRIER]: Abilities.FILTER,
|
||||
[Species.SPECTRIER]: Abilities.SHADOW_SHIELD,
|
||||
[Species.CALYREX]: Abilities.HARVEST,
|
||||
[Species.ENAMORUS]: Abilities.FAIRY_AURA,
|
||||
[Species.SPRIGATITO]: Abilities.MAGICIAN,
|
||||
[Species.FUECOCO]: Abilities.PUNK_ROCK,
|
||||
[Species.QUAXLY]: Abilities.OPPORTUNIST,
|
||||
[Species.LECHONK]: Abilities.SIMPLE,
|
||||
[Species.TAROUNTULA]: Abilities.HONEY_GATHER,
|
||||
[Species.NYMBLE]: Abilities.GUTS,
|
||||
[Species.PAWMI]: Abilities.TRANSISTOR,
|
||||
[Species.TANDEMAUS]: Abilities.SCRAPPY,
|
||||
[Species.FIDOUGH]: Abilities.WATER_ABSORB,
|
||||
[Species.SMOLIV]: Abilities.RIPEN,
|
||||
[Species.SQUAWKABILLY]: Abilities.MOXIE,
|
||||
[Species.NACLI]: Abilities.SOLID_ROCK,
|
||||
[Species.CHARCADET]: Abilities.PRISM_ARMOR,
|
||||
[Species.TADBULB]: Abilities.STAMINA,
|
||||
[Species.WATTREL]: Abilities.SHEER_FORCE,
|
||||
[Species.MASCHIFF]: Abilities.STRONG_JAW,
|
||||
[Species.SHROODLE]: Abilities.CORROSION,
|
||||
[Species.BRAMBLIN]: Abilities.SHADOW_SHIELD,
|
||||
[Species.TOEDSCOOL]: Abilities.PRANKSTER,
|
||||
[Species.KLAWF]: Abilities.WATER_ABSORB,
|
||||
[Species.CAPSAKID]: Abilities.PARENTAL_BOND,
|
||||
[Species.RELLOR]: Abilities.PRANKSTER,
|
||||
[Species.FLITTLE]: Abilities.DAZZLING,
|
||||
[Species.TINKATINK]: Abilities.STEELWORKER,
|
||||
[Species.WIGLETT]: Abilities.STURDY,
|
||||
[Species.BOMBIRDIER]: Abilities.UNBURDEN,
|
||||
[Species.FINIZEN]: Abilities.IRON_FIST,
|
||||
[Species.VAROOM]: Abilities.LEVITATE,
|
||||
[Species.CYCLIZAR]: Abilities.PROTEAN,
|
||||
[Species.ORTHWORM]: Abilities.REGENERATOR,
|
||||
[Species.GLIMMET]: Abilities.LEVITATE,
|
||||
[Species.GREAVARD]: Abilities.FUR_COAT,
|
||||
[Species.FLAMIGO]: Abilities.MOXIE,
|
||||
[Species.CETODDLE]: Abilities.ICE_SCALES,
|
||||
[Species.VELUZA]: Abilities.SUPER_LUCK,
|
||||
[Species.DONDOZO]: Abilities.PARENTAL_BOND,
|
||||
[Species.TATSUGIRI]: Abilities.ADAPTABILITY,
|
||||
[Species.GREAT_TUSK]: Abilities.INTIMIDATE,
|
||||
[Species.SCREAM_TAIL]: Abilities.UNAWARE,
|
||||
[Species.BRUTE_BONNET]: Abilities.CHLOROPHYLL,
|
||||
[Species.FLUTTER_MANE]: Abilities.DAZZLING,
|
||||
[Species.SLITHER_WING]: Abilities.SCRAPPY,
|
||||
[Species.SANDY_SHOCKS]: Abilities.EARTH_EATER,
|
||||
[Species.IRON_TREADS]: Abilities.STEELY_SPIRIT,
|
||||
[Species.IRON_BUNDLE]: Abilities.SNOW_WARNING,
|
||||
[Species.IRON_HANDS]: Abilities.IRON_FIST,
|
||||
[Species.IRON_JUGULIS]: Abilities.LIGHTNING_ROD,
|
||||
[Species.IRON_MOTH]: Abilities.LEVITATE,
|
||||
[Species.IRON_THORNS]: Abilities.SAND_STREAM,
|
||||
[Species.FRIGIBAX]: Abilities.SNOW_WARNING,
|
||||
[Species.GIMMIGHOUL]: Abilities.HONEY_GATHER,
|
||||
[Species.WO_CHIEN]: Abilities.VESSEL_OF_RUIN,
|
||||
[Species.CHIEN_PAO]: Abilities.INTIMIDATE,
|
||||
[Species.TING_LU]: Abilities.STAMINA,
|
||||
[Species.CHI_YU]: Abilities.BERSERK,
|
||||
[Species.ROARING_MOON]: Abilities.TOUGH_CLAWS,
|
||||
[Species.IRON_VALIANT]: Abilities.ADAPTABILITY,
|
||||
[Species.KORAIDON]: Abilities.OPPORTUNIST,
|
||||
[Species.MIRAIDON]: Abilities.OPPORTUNIST,
|
||||
[Species.WALKING_WAKE]: Abilities.BEAST_BOOST,
|
||||
[Species.IRON_LEAVES]: Abilities.SHARPNESS,
|
||||
[Species.POLTCHAGEIST]: Abilities.TRIAGE,
|
||||
[Species.OKIDOGI]: Abilities.FUR_COAT,
|
||||
[Species.MUNKIDORI]: Abilities.NEUROFORCE,
|
||||
[Species.FEZANDIPITI]: Abilities.LEVITATE,
|
||||
[Species.OGERPON]: Abilities.OPPORTUNIST,
|
||||
[Species.GOUGING_FIRE]: Abilities.BEAST_BOOST,
|
||||
[Species.RAGING_BOLT]: Abilities.BEAST_BOOST,
|
||||
[Species.IRON_BOULDER]: Abilities.SHARPNESS,
|
||||
[Species.IRON_CROWN]: Abilities.SHARPNESS,
|
||||
[Species.TERAPAGOS]: Abilities.SOUL_HEART,
|
||||
[Species.PECHARUNT]: Abilities.TOXIC_CHAIN,
|
||||
[Species.ALOLA_RATTATA]: Abilities.ADAPTABILITY,
|
||||
[Species.ALOLA_SANDSHREW]: Abilities.ICE_SCALES,
|
||||
[Species.ALOLA_VULPIX]: Abilities.SHEER_FORCE,
|
||||
[Species.ALOLA_DIGLETT]: Abilities.STURDY,
|
||||
[Species.ALOLA_MEOWTH]: Abilities.DARK_AURA,
|
||||
[Species.ALOLA_GEODUDE]: Abilities.DRY_SKIN,
|
||||
[Species.ALOLA_GRIMER]: Abilities.TOXIC_DEBRIS,
|
||||
[Species.ETERNAL_FLOETTE]: Abilities.MAGIC_GUARD,
|
||||
[Species.GALAR_MEOWTH]: Abilities.STEELWORKER,
|
||||
[Species.GALAR_PONYTA]: Abilities.MOXIE,
|
||||
[Species.GALAR_SLOWPOKE]: Abilities.UNAWARE,
|
||||
[Species.GALAR_FARFETCHD]: Abilities.INTREPID_SWORD,
|
||||
[Species.GALAR_ARTICUNO]: Abilities.SERENE_GRACE,
|
||||
[Species.GALAR_ZAPDOS]: Abilities.TOUGH_CLAWS,
|
||||
[Species.GALAR_MOLTRES]: Abilities.DARK_AURA,
|
||||
[Species.GALAR_CORSOLA]: Abilities.SHADOW_SHIELD,
|
||||
[Species.GALAR_ZIGZAGOON]: Abilities.POISON_HEAL,
|
||||
[Species.GALAR_DARUMAKA]: Abilities.FLASH_FIRE,
|
||||
[Species.GALAR_YAMASK]: Abilities.TABLETS_OF_RUIN,
|
||||
[Species.GALAR_STUNFISK]: Abilities.ARENA_TRAP,
|
||||
[Species.HISUI_GROWLITHE]: Abilities.RECKLESS,
|
||||
[Species.HISUI_VOLTORB]: Abilities.TRANSISTOR,
|
||||
[Species.HISUI_QWILFISH]: Abilities.MERCILESS,
|
||||
[Species.HISUI_SNEASEL]: Abilities.SCRAPPY,
|
||||
[Species.HISUI_ZORUA]: Abilities.ADAPTABILITY,
|
||||
[Species.PALDEA_TAUROS]: Abilities.ADAPTABILITY,
|
||||
[Species.PALDEA_WOOPER]: Abilities.THICK_FAT,
|
||||
[Species.BLOODMOON_URSALUNA]: Abilities.BERSERK
|
||||
};
|
@ -1,17 +1,18 @@
|
||||
import { Gender } from "./gender";
|
||||
import { PokeballType } from "./pokeball";
|
||||
import Pokemon from "../field/pokemon";
|
||||
import { Gender } from "#app/data/gender";
|
||||
import { PokeballType } from "#app/data/pokeball";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { Type } from "./type";
|
||||
import * as Utils from "../utils";
|
||||
import { SpeciesFormKey } from "./pokemon-species";
|
||||
import { WeatherType } from "./weather";
|
||||
import { Nature } from "./nature";
|
||||
import { Type } from "#app/data/type";
|
||||
import * as Utils from "#app/utils";
|
||||
import { WeatherType } from "#app/data/weather";
|
||||
import { Nature } from "#app/data/nature";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { TimeOfDay } from "#enums/time-of-day";
|
||||
import { DamageMoneyRewardModifier, ExtraModifierModifier, MoneyMultiplierModifier } from "#app/modifier/modifier";
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
|
||||
|
||||
export enum SpeciesWildEvolutionDelay {
|
||||
NONE,
|
53
src/data/balance/rates.ts
Normal file
53
src/data/balance/rates.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Rates for shinies and other random properties are defined in this file.
|
||||
* CHANCE is defined as x/65536
|
||||
* RATE is defined as 1/x
|
||||
*/
|
||||
|
||||
// #region Encounterable properties
|
||||
/** `64/65536 -> 1/1024` */
|
||||
export const BASE_SHINY_CHANCE = 64;
|
||||
|
||||
/** `256/65536 -> 1/256` */
|
||||
export const BASE_HIDDEN_ABILITY_CHANCE = 256;
|
||||
|
||||
// #region Egg properties
|
||||
|
||||
// Threshold x at which a gacha egg is determined to be a certain tier
|
||||
// Specifically, the tier is determined by the highest threshold a random value between 0-255 meets or exceeds
|
||||
// Legendary Up Gacha raises these thresholds by 1, thereby giving Legendary eggs 2/256 chance
|
||||
export const GACHA_DEFAULT_COMMON_EGG_THRESHOLD = 52; // Default 204/256 chance, 203/256 chance in Legendary Up Gacha
|
||||
export const GACHA_DEFAULT_RARE_EGG_THRESHOLD = 8; // Default 44/256 chance
|
||||
export const GACHA_DEFAULT_EPIC_EGG_THRESHOLD = 1; // Default 7/256 chance, leaving Legendary as 1/256 chance
|
||||
export const GACHA_LEGENDARY_UP_THRESHOLD_OFFSET = 1; // The offset to threshold for Legendary Up gacha eggs. +x/256 Legendary Egg chance, -x/256 Common Egg chance
|
||||
|
||||
// The number of eggs without finding a certain tier egg it takes for egg pity to kick in and that tier to be forced
|
||||
// These numbers are roughly the 80% mark. That is, 80% of the time you'll get an egg before this gets triggered.
|
||||
export const EGG_PITY_LEGENDARY_THRESHOLD = 412;
|
||||
export const EGG_PITY_EPIC_THRESHOLD = 59;
|
||||
export const EGG_PITY_RARE_THRESHOLD = 9;
|
||||
|
||||
// Waves to hatch an egg of a given tier
|
||||
export const HATCH_WAVES_COMMON_EGG = 10;
|
||||
export const HATCH_WAVES_RARE_EGG = 25;
|
||||
export const HATCH_WAVES_EPIC_EGG = 50;
|
||||
export const HATCH_WAVES_LEGENDARY_EGG = 100;
|
||||
export const HATCH_WAVES_MANAPHY_EGG = 50;
|
||||
|
||||
// Rates for specific random properties in 1/x
|
||||
export const GACHA_DEFAULT_SHINY_RATE = 128;
|
||||
export const GACHA_SHINY_UP_SHINY_RATE = 64;
|
||||
export const SAME_SPECIES_EGG_SHINY_RATE = 12;
|
||||
export const SAME_SPECIES_EGG_HA_RATE = 8;
|
||||
export const MANAPHY_EGG_MANAPHY_RATE = 8;
|
||||
export const GACHA_EGG_HA_RATE = 192;
|
||||
|
||||
// 1/x for legendary eggs, 1/x*2 for epic eggs, 1/x*4 for rare eggs, and 1/x*8 for common eggs
|
||||
export const GACHA_DEFAULT_RARE_EGGMOVE_RATE = 6;
|
||||
export const SAME_SPECIES_EGG_RARE_EGGMOVE_RATE = 3;
|
||||
export const GACHA_MOVE_UP_RARE_EGGMOVE_RATE = 3;
|
||||
|
||||
// #region Variant properties
|
||||
// The chance x/10 of a shiny being a variant, then of being specifically an epic variant
|
||||
export const SHINY_VARIANT_CHANCE = 4;
|
||||
export const SHINY_EPIC_CHANCE = 1;
|
671
src/data/balance/starters.ts
Normal file
671
src/data/balance/starters.ts
Normal file
@ -0,0 +1,671 @@
|
||||
import { Species } from "#enums/species";
|
||||
|
||||
export const POKERUS_STARTER_COUNT = 5;
|
||||
|
||||
/**
|
||||
* Function to get the cumulative friendship threshold at which a candy is earned
|
||||
* @param starterCost The cost of the starter, found in {@linkcode speciesStarterCosts}
|
||||
* @returns aforementioned threshold
|
||||
*/
|
||||
export function getStarterValueFriendshipCap(starterCost: number): number {
|
||||
switch (starterCost) {
|
||||
case 1:
|
||||
return 20;
|
||||
case 2:
|
||||
return 40;
|
||||
case 3:
|
||||
return 60;
|
||||
case 4:
|
||||
return 100;
|
||||
case 5:
|
||||
return 140;
|
||||
case 6:
|
||||
return 200;
|
||||
case 7:
|
||||
return 280;
|
||||
case 8:
|
||||
case 9:
|
||||
return 450;
|
||||
default:
|
||||
return 600;
|
||||
}
|
||||
}
|
||||
|
||||
export const speciesStarterCosts = {
|
||||
[Species.BULBASAUR]: 3,
|
||||
[Species.CHARMANDER]: 3,
|
||||
[Species.SQUIRTLE]: 3,
|
||||
[Species.CATERPIE]: 2,
|
||||
[Species.WEEDLE]: 1,
|
||||
[Species.PIDGEY]: 1,
|
||||
[Species.RATTATA]: 1,
|
||||
[Species.SPEAROW]: 1,
|
||||
[Species.EKANS]: 2,
|
||||
[Species.PIKACHU]: 3,
|
||||
[Species.SANDSHREW]: 2,
|
||||
[Species.NIDORAN_F]: 3,
|
||||
[Species.NIDORAN_M]: 3,
|
||||
[Species.CLEFAIRY]: 3,
|
||||
[Species.VULPIX]: 3,
|
||||
[Species.JIGGLYPUFF]: 2,
|
||||
[Species.ZUBAT]: 3,
|
||||
[Species.ODDISH]: 3,
|
||||
[Species.PARAS]: 2,
|
||||
[Species.VENONAT]: 2,
|
||||
[Species.DIGLETT]: 2,
|
||||
[Species.MEOWTH]: 3,
|
||||
[Species.PSYDUCK]: 2,
|
||||
[Species.MANKEY]: 4,
|
||||
[Species.GROWLITHE]: 4,
|
||||
[Species.POLIWAG]: 2,
|
||||
[Species.ABRA]: 4,
|
||||
[Species.MACHOP]: 3,
|
||||
[Species.BELLSPROUT]: 2,
|
||||
[Species.TENTACOOL]: 3,
|
||||
[Species.GEODUDE]: 3,
|
||||
[Species.PONYTA]: 2,
|
||||
[Species.SLOWPOKE]: 3,
|
||||
[Species.MAGNEMITE]: 4,
|
||||
[Species.FARFETCHD]: 2,
|
||||
[Species.DODUO]: 3,
|
||||
[Species.SEEL]: 1,
|
||||
[Species.GRIMER]: 2,
|
||||
[Species.SHELLDER]: 5,
|
||||
[Species.GASTLY]: 4,
|
||||
[Species.ONIX]: 3,
|
||||
[Species.DROWZEE]: 2,
|
||||
[Species.KRABBY]: 3,
|
||||
[Species.VOLTORB]: 2,
|
||||
[Species.EXEGGCUTE]: 3,
|
||||
[Species.CUBONE]: 3,
|
||||
[Species.HITMONLEE]: 4,
|
||||
[Species.HITMONCHAN]: 4,
|
||||
[Species.LICKITUNG]: 3,
|
||||
[Species.KOFFING]: 2,
|
||||
[Species.RHYHORN]: 3,
|
||||
[Species.CHANSEY]: 3,
|
||||
[Species.TANGELA]: 3,
|
||||
[Species.KANGASKHAN]: 4,
|
||||
[Species.HORSEA]: 3,
|
||||
[Species.GOLDEEN]: 2,
|
||||
[Species.STARYU]: 3,
|
||||
[Species.MR_MIME]: 3,
|
||||
[Species.SCYTHER]: 5,
|
||||
[Species.JYNX]: 4,
|
||||
[Species.ELECTABUZZ]: 4,
|
||||
[Species.MAGMAR]: 4,
|
||||
[Species.PINSIR]: 4,
|
||||
[Species.TAUROS]: 4,
|
||||
[Species.MAGIKARP]: 4,
|
||||
[Species.LAPRAS]: 4,
|
||||
[Species.DITTO]: 2,
|
||||
[Species.EEVEE]: 3,
|
||||
[Species.PORYGON]: 4,
|
||||
[Species.OMANYTE]: 3,
|
||||
[Species.KABUTO]: 3,
|
||||
[Species.AERODACTYL]: 5,
|
||||
[Species.SNORLAX]: 5,
|
||||
[Species.ARTICUNO]: 6,
|
||||
[Species.ZAPDOS]: 6,
|
||||
[Species.MOLTRES]: 6,
|
||||
[Species.DRATINI]: 4,
|
||||
[Species.MEWTWO]: 8,
|
||||
[Species.MEW]: 6,
|
||||
|
||||
[Species.CHIKORITA]: 2,
|
||||
[Species.CYNDAQUIL]: 3,
|
||||
[Species.TOTODILE]: 3,
|
||||
[Species.SENTRET]: 1,
|
||||
[Species.HOOTHOOT]: 2,
|
||||
[Species.LEDYBA]: 1,
|
||||
[Species.SPINARAK]: 1,
|
||||
[Species.CHINCHOU]: 2,
|
||||
[Species.PICHU]: 2,
|
||||
[Species.CLEFFA]: 2,
|
||||
[Species.IGGLYBUFF]: 1,
|
||||
[Species.TOGEPI]: 3,
|
||||
[Species.NATU]: 2,
|
||||
[Species.MAREEP]: 2,
|
||||
[Species.MARILL]: 4,
|
||||
[Species.SUDOWOODO]: 3,
|
||||
[Species.HOPPIP]: 2,
|
||||
[Species.AIPOM]: 2,
|
||||
[Species.SUNKERN]: 1,
|
||||
[Species.YANMA]: 3,
|
||||
[Species.WOOPER]: 2,
|
||||
[Species.MURKROW]: 3,
|
||||
[Species.MISDREAVUS]: 2,
|
||||
[Species.UNOWN]: 1,
|
||||
[Species.WOBBUFFET]: 2,
|
||||
[Species.GIRAFARIG]: 3,
|
||||
[Species.PINECO]: 2,
|
||||
[Species.DUNSPARCE]: 3,
|
||||
[Species.GLIGAR]: 3,
|
||||
[Species.SNUBBULL]: 2,
|
||||
[Species.QWILFISH]: 3,
|
||||
[Species.SHUCKLE]: 3,
|
||||
[Species.HERACROSS]: 5,
|
||||
[Species.SNEASEL]: 4,
|
||||
[Species.TEDDIURSA]: 4,
|
||||
[Species.SLUGMA]: 2,
|
||||
[Species.SWINUB]: 3,
|
||||
[Species.CORSOLA]: 2,
|
||||
[Species.REMORAID]: 2,
|
||||
[Species.DELIBIRD]: 2,
|
||||
[Species.MANTINE]: 3,
|
||||
[Species.SKARMORY]: 4,
|
||||
[Species.HOUNDOUR]: 3,
|
||||
[Species.PHANPY]: 3,
|
||||
[Species.STANTLER]: 3,
|
||||
[Species.SMEARGLE]: 1,
|
||||
[Species.TYROGUE]: 3,
|
||||
[Species.SMOOCHUM]: 3,
|
||||
[Species.ELEKID]: 3,
|
||||
[Species.MAGBY]: 3,
|
||||
[Species.MILTANK]: 4,
|
||||
[Species.RAIKOU]: 6,
|
||||
[Species.ENTEI]: 6,
|
||||
[Species.SUICUNE]: 6,
|
||||
[Species.LARVITAR]: 4,
|
||||
[Species.LUGIA]: 8,
|
||||
[Species.HO_OH]: 8,
|
||||
[Species.CELEBI]: 6,
|
||||
|
||||
[Species.TREECKO]: 3,
|
||||
[Species.TORCHIC]: 4,
|
||||
[Species.MUDKIP]: 3,
|
||||
[Species.POOCHYENA]: 2,
|
||||
[Species.ZIGZAGOON]: 2,
|
||||
[Species.WURMPLE]: 1,
|
||||
[Species.LOTAD]: 3,
|
||||
[Species.SEEDOT]: 2,
|
||||
[Species.TAILLOW]: 3,
|
||||
[Species.WINGULL]: 2,
|
||||
[Species.RALTS]: 3,
|
||||
[Species.SURSKIT]: 2,
|
||||
[Species.SHROOMISH]: 3,
|
||||
[Species.SLAKOTH]: 4,
|
||||
[Species.NINCADA]: 4,
|
||||
[Species.WHISMUR]: 2,
|
||||
[Species.MAKUHITA]: 3,
|
||||
[Species.AZURILL]: 4,
|
||||
[Species.NOSEPASS]: 2,
|
||||
[Species.SKITTY]: 1,
|
||||
[Species.SABLEYE]: 2,
|
||||
[Species.MAWILE]: 3,
|
||||
[Species.ARON]: 3,
|
||||
[Species.MEDITITE]: 3,
|
||||
[Species.ELECTRIKE]: 2,
|
||||
[Species.PLUSLE]: 2,
|
||||
[Species.MINUN]: 2,
|
||||
[Species.VOLBEAT]: 2,
|
||||
[Species.ILLUMISE]: 2,
|
||||
[Species.ROSELIA]: 3,
|
||||
[Species.GULPIN]: 1,
|
||||
[Species.CARVANHA]: 3,
|
||||
[Species.WAILMER]: 2,
|
||||
[Species.NUMEL]: 2,
|
||||
[Species.TORKOAL]: 3,
|
||||
[Species.SPOINK]: 2,
|
||||
[Species.SPINDA]: 1,
|
||||
[Species.TRAPINCH]: 3,
|
||||
[Species.CACNEA]: 2,
|
||||
[Species.SWABLU]: 2,
|
||||
[Species.ZANGOOSE]: 4,
|
||||
[Species.SEVIPER]: 3,
|
||||
[Species.LUNATONE]: 3,
|
||||
[Species.SOLROCK]: 3,
|
||||
[Species.BARBOACH]: 2,
|
||||
[Species.CORPHISH]: 3,
|
||||
[Species.BALTOY]: 2,
|
||||
[Species.LILEEP]: 3,
|
||||
[Species.ANORITH]: 3,
|
||||
[Species.FEEBAS]: 4,
|
||||
[Species.CASTFORM]: 1,
|
||||
[Species.KECLEON]: 2,
|
||||
[Species.SHUPPET]: 2,
|
||||
[Species.DUSKULL]: 3,
|
||||
[Species.TROPIUS]: 3,
|
||||
[Species.CHIMECHO]: 3,
|
||||
[Species.ABSOL]: 4,
|
||||
[Species.WYNAUT]: 2,
|
||||
[Species.SNORUNT]: 2,
|
||||
[Species.SPHEAL]: 2,
|
||||
[Species.CLAMPERL]: 3,
|
||||
[Species.RELICANTH]: 3,
|
||||
[Species.LUVDISC]: 1,
|
||||
[Species.BAGON]: 4,
|
||||
[Species.BELDUM]: 4,
|
||||
[Species.REGIROCK]: 6,
|
||||
[Species.REGICE]: 6,
|
||||
[Species.REGISTEEL]: 6,
|
||||
[Species.LATIAS]: 7,
|
||||
[Species.LATIOS]: 7,
|
||||
[Species.KYOGRE]: 9,
|
||||
[Species.GROUDON]: 9,
|
||||
[Species.RAYQUAZA]: 9,
|
||||
[Species.JIRACHI]: 7,
|
||||
[Species.DEOXYS]: 7,
|
||||
|
||||
[Species.TURTWIG]: 3,
|
||||
[Species.CHIMCHAR]: 3,
|
||||
[Species.PIPLUP]: 3,
|
||||
[Species.STARLY]: 3,
|
||||
[Species.BIDOOF]: 2,
|
||||
[Species.KRICKETOT]: 1,
|
||||
[Species.SHINX]: 2,
|
||||
[Species.BUDEW]: 3,
|
||||
[Species.CRANIDOS]: 3,
|
||||
[Species.SHIELDON]: 3,
|
||||
[Species.BURMY]: 2,
|
||||
[Species.COMBEE]: 2,
|
||||
[Species.PACHIRISU]: 2,
|
||||
[Species.BUIZEL]: 2,
|
||||
[Species.CHERUBI]: 1,
|
||||
[Species.SHELLOS]: 3,
|
||||
[Species.DRIFLOON]: 2,
|
||||
[Species.BUNEARY]: 2,
|
||||
[Species.GLAMEOW]: 2,
|
||||
[Species.CHINGLING]: 2,
|
||||
[Species.STUNKY]: 2,
|
||||
[Species.BRONZOR]: 3,
|
||||
[Species.BONSLY]: 2,
|
||||
[Species.MIME_JR]: 2,
|
||||
[Species.HAPPINY]: 2,
|
||||
[Species.CHATOT]: 2,
|
||||
[Species.SPIRITOMB]: 4,
|
||||
[Species.GIBLE]: 4,
|
||||
[Species.MUNCHLAX]: 4,
|
||||
[Species.RIOLU]: 3,
|
||||
[Species.HIPPOPOTAS]: 3,
|
||||
[Species.SKORUPI]: 3,
|
||||
[Species.CROAGUNK]: 2,
|
||||
[Species.CARNIVINE]: 2,
|
||||
[Species.FINNEON]: 1,
|
||||
[Species.MANTYKE]: 2,
|
||||
[Species.SNOVER]: 2,
|
||||
[Species.ROTOM]: 5,
|
||||
[Species.UXIE]: 6,
|
||||
[Species.MESPRIT]: 6,
|
||||
[Species.AZELF]: 6,
|
||||
[Species.DIALGA]: 8,
|
||||
[Species.PALKIA]: 8,
|
||||
[Species.HEATRAN]: 6,
|
||||
[Species.REGIGIGAS]: 7,
|
||||
[Species.GIRATINA]: 8,
|
||||
[Species.CRESSELIA]: 6,
|
||||
[Species.PHIONE]: 4,
|
||||
[Species.MANAPHY]: 7,
|
||||
[Species.DARKRAI]: 7,
|
||||
[Species.SHAYMIN]: 6,
|
||||
[Species.ARCEUS]: 9,
|
||||
|
||||
[Species.VICTINI]: 7,
|
||||
[Species.SNIVY]: 3,
|
||||
[Species.TEPIG]: 3,
|
||||
[Species.OSHAWOTT]: 3,
|
||||
[Species.PATRAT]: 1,
|
||||
[Species.LILLIPUP]: 3,
|
||||
[Species.PURRLOIN]: 2,
|
||||
[Species.PANSAGE]: 2,
|
||||
[Species.PANSEAR]: 2,
|
||||
[Species.PANPOUR]: 2,
|
||||
[Species.MUNNA]: 2,
|
||||
[Species.PIDOVE]: 1,
|
||||
[Species.BLITZLE]: 2,
|
||||
[Species.ROGGENROLA]: 3,
|
||||
[Species.WOOBAT]: 3,
|
||||
[Species.DRILBUR]: 4,
|
||||
[Species.AUDINO]: 3,
|
||||
[Species.TIMBURR]: 4,
|
||||
[Species.TYMPOLE]: 3,
|
||||
[Species.THROH]: 4,
|
||||
[Species.SAWK]: 4,
|
||||
[Species.SEWADDLE]: 2,
|
||||
[Species.VENIPEDE]: 3,
|
||||
[Species.COTTONEE]: 3,
|
||||
[Species.PETILIL]: 3,
|
||||
[Species.BASCULIN]: 4,
|
||||
[Species.SANDILE]: 4,
|
||||
[Species.DARUMAKA]: 4,
|
||||
[Species.MARACTUS]: 2,
|
||||
[Species.DWEBBLE]: 2,
|
||||
[Species.SCRAGGY]: 3,
|
||||
[Species.SIGILYPH]: 4,
|
||||
[Species.YAMASK]: 3,
|
||||
[Species.TIRTOUGA]: 3,
|
||||
[Species.ARCHEN]: 3,
|
||||
[Species.TRUBBISH]: 2,
|
||||
[Species.ZORUA]: 3,
|
||||
[Species.MINCCINO]: 3,
|
||||
[Species.GOTHITA]: 3,
|
||||
[Species.SOLOSIS]: 3,
|
||||
[Species.DUCKLETT]: 2,
|
||||
[Species.VANILLITE]: 3,
|
||||
[Species.DEERLING]: 2,
|
||||
[Species.EMOLGA]: 2,
|
||||
[Species.KARRABLAST]: 3,
|
||||
[Species.FOONGUS]: 2,
|
||||
[Species.FRILLISH]: 3,
|
||||
[Species.ALOMOMOLA]: 4,
|
||||
[Species.JOLTIK]: 3,
|
||||
[Species.FERROSEED]: 3,
|
||||
[Species.KLINK]: 3,
|
||||
[Species.TYNAMO]: 2,
|
||||
[Species.ELGYEM]: 2,
|
||||
[Species.LITWICK]: 3,
|
||||
[Species.AXEW]: 4,
|
||||
[Species.CUBCHOO]: 2,
|
||||
[Species.CRYOGONAL]: 4,
|
||||
[Species.SHELMET]: 2,
|
||||
[Species.STUNFISK]: 3,
|
||||
[Species.MIENFOO]: 3,
|
||||
[Species.DRUDDIGON]: 4,
|
||||
[Species.GOLETT]: 3,
|
||||
[Species.PAWNIARD]: 4,
|
||||
[Species.BOUFFALANT]: 4,
|
||||
[Species.RUFFLET]: 3,
|
||||
[Species.VULLABY]: 3,
|
||||
[Species.HEATMOR]: 3,
|
||||
[Species.DURANT]: 4,
|
||||
[Species.DEINO]: 4,
|
||||
[Species.LARVESTA]: 4,
|
||||
[Species.COBALION]: 6,
|
||||
[Species.TERRAKION]: 6,
|
||||
[Species.VIRIZION]: 6,
|
||||
[Species.TORNADUS]: 7,
|
||||
[Species.THUNDURUS]: 7,
|
||||
[Species.RESHIRAM]: 8,
|
||||
[Species.ZEKROM]: 8,
|
||||
[Species.LANDORUS]: 7,
|
||||
[Species.KYUREM]: 8,
|
||||
[Species.KELDEO]: 6,
|
||||
[Species.MELOETTA]: 7,
|
||||
[Species.GENESECT]: 6,
|
||||
|
||||
[Species.CHESPIN]: 3,
|
||||
[Species.FENNEKIN]: 3,
|
||||
[Species.FROAKIE]: 4,
|
||||
[Species.BUNNELBY]: 3,
|
||||
[Species.FLETCHLING]: 3,
|
||||
[Species.SCATTERBUG]: 2,
|
||||
[Species.LITLEO]: 2,
|
||||
[Species.FLABEBE]: 3,
|
||||
[Species.SKIDDO]: 2,
|
||||
[Species.PANCHAM]: 3,
|
||||
[Species.FURFROU]: 3,
|
||||
[Species.ESPURR]: 2,
|
||||
[Species.HONEDGE]: 4,
|
||||
[Species.SPRITZEE]: 2,
|
||||
[Species.SWIRLIX]: 3,
|
||||
[Species.INKAY]: 3,
|
||||
[Species.BINACLE]: 3,
|
||||
[Species.SKRELP]: 2,
|
||||
[Species.CLAUNCHER]: 3,
|
||||
[Species.HELIOPTILE]: 3,
|
||||
[Species.TYRUNT]: 3,
|
||||
[Species.AMAURA]: 3,
|
||||
[Species.HAWLUCHA]: 4,
|
||||
[Species.DEDENNE]: 2,
|
||||
[Species.CARBINK]: 2,
|
||||
[Species.GOOMY]: 4,
|
||||
[Species.KLEFKI]: 3,
|
||||
[Species.PHANTUMP]: 2,
|
||||
[Species.PUMPKABOO]: 2,
|
||||
[Species.BERGMITE]: 3,
|
||||
[Species.NOIBAT]: 3,
|
||||
[Species.XERNEAS]: 8,
|
||||
[Species.YVELTAL]: 8,
|
||||
[Species.ZYGARDE]: 8,
|
||||
[Species.DIANCIE]: 7,
|
||||
[Species.HOOPA]: 7,
|
||||
[Species.VOLCANION]: 6,
|
||||
[Species.ETERNAL_FLOETTE]: 4,
|
||||
|
||||
[Species.ROWLET]: 3,
|
||||
[Species.LITTEN]: 3,
|
||||
[Species.POPPLIO]: 4,
|
||||
[Species.PIKIPEK]: 2,
|
||||
[Species.YUNGOOS]: 2,
|
||||
[Species.GRUBBIN]: 3,
|
||||
[Species.CRABRAWLER]: 3,
|
||||
[Species.ORICORIO]: 3,
|
||||
[Species.CUTIEFLY]: 3,
|
||||
[Species.ROCKRUFF]: 3,
|
||||
[Species.WISHIWASHI]: 2,
|
||||
[Species.MAREANIE]: 2,
|
||||
[Species.MUDBRAY]: 3,
|
||||
[Species.DEWPIDER]: 3,
|
||||
[Species.FOMANTIS]: 2,
|
||||
[Species.MORELULL]: 2,
|
||||
[Species.SALANDIT]: 3,
|
||||
[Species.STUFFUL]: 3,
|
||||
[Species.BOUNSWEET]: 3,
|
||||
[Species.COMFEY]: 4,
|
||||
[Species.ORANGURU]: 4,
|
||||
[Species.PASSIMIAN]: 4,
|
||||
[Species.WIMPOD]: 3,
|
||||
[Species.SANDYGAST]: 3,
|
||||
[Species.PYUKUMUKU]: 2,
|
||||
[Species.TYPE_NULL]: 5,
|
||||
[Species.MINIOR]: 4,
|
||||
[Species.KOMALA]: 3,
|
||||
[Species.TURTONATOR]: 4,
|
||||
[Species.TOGEDEMARU]: 3,
|
||||
[Species.MIMIKYU]: 4,
|
||||
[Species.BRUXISH]: 4,
|
||||
[Species.DRAMPA]: 4,
|
||||
[Species.DHELMISE]: 4,
|
||||
[Species.JANGMO_O]: 4,
|
||||
[Species.TAPU_KOKO]: 6,
|
||||
[Species.TAPU_LELE]: 6,
|
||||
[Species.TAPU_BULU]: 6,
|
||||
[Species.TAPU_FINI]: 6,
|
||||
[Species.COSMOG]: 7,
|
||||
[Species.NIHILEGO]: 6,
|
||||
[Species.BUZZWOLE]: 6,
|
||||
[Species.PHEROMOSA]: 7,
|
||||
[Species.XURKITREE]: 6,
|
||||
[Species.CELESTEELA]: 6,
|
||||
[Species.KARTANA]: 7,
|
||||
[Species.GUZZLORD]: 6,
|
||||
[Species.NECROZMA]: 8,
|
||||
[Species.MAGEARNA]: 7,
|
||||
[Species.MARSHADOW]: 7,
|
||||
[Species.POIPOLE]: 7,
|
||||
[Species.STAKATAKA]: 6,
|
||||
[Species.BLACEPHALON]: 7,
|
||||
[Species.ZERAORA]: 6,
|
||||
[Species.MELTAN]: 6,
|
||||
[Species.ALOLA_RATTATA]: 1,
|
||||
[Species.ALOLA_SANDSHREW]: 2,
|
||||
[Species.ALOLA_VULPIX]: 3,
|
||||
[Species.ALOLA_DIGLETT]: 2,
|
||||
[Species.ALOLA_MEOWTH]: 3,
|
||||
[Species.ALOLA_GEODUDE]: 3,
|
||||
[Species.ALOLA_GRIMER]: 3,
|
||||
|
||||
[Species.GROOKEY]: 3,
|
||||
[Species.SCORBUNNY]: 4,
|
||||
[Species.SOBBLE]: 3,
|
||||
[Species.SKWOVET]: 2,
|
||||
[Species.ROOKIDEE]: 3,
|
||||
[Species.BLIPBUG]: 2,
|
||||
[Species.NICKIT]: 1,
|
||||
[Species.GOSSIFLEUR]: 2,
|
||||
[Species.WOOLOO]: 2,
|
||||
[Species.CHEWTLE]: 3,
|
||||
[Species.YAMPER]: 2,
|
||||
[Species.ROLYCOLY]: 3,
|
||||
[Species.APPLIN]: 3,
|
||||
[Species.SILICOBRA]: 3,
|
||||
[Species.CRAMORANT]: 3,
|
||||
[Species.ARROKUDA]: 3,
|
||||
[Species.TOXEL]: 3,
|
||||
[Species.SIZZLIPEDE]: 3,
|
||||
[Species.CLOBBOPUS]: 2,
|
||||
[Species.SINISTEA]: 3,
|
||||
[Species.HATENNA]: 3,
|
||||
[Species.IMPIDIMP]: 3,
|
||||
[Species.MILCERY]: 3,
|
||||
[Species.FALINKS]: 4,
|
||||
[Species.PINCURCHIN]: 3,
|
||||
[Species.SNOM]: 3,
|
||||
[Species.STONJOURNER]: 3,
|
||||
[Species.EISCUE]: 3,
|
||||
[Species.INDEEDEE]: 4,
|
||||
[Species.MORPEKO]: 3,
|
||||
[Species.CUFANT]: 3,
|
||||
[Species.DRACOZOLT]: 5,
|
||||
[Species.ARCTOZOLT]: 4,
|
||||
[Species.DRACOVISH]: 5,
|
||||
[Species.ARCTOVISH]: 4,
|
||||
[Species.DURALUDON]: 5,
|
||||
[Species.DREEPY]: 4,
|
||||
[Species.ZACIAN]: 9,
|
||||
[Species.ZAMAZENTA]: 8,
|
||||
[Species.ETERNATUS]: 10,
|
||||
[Species.KUBFU]: 6,
|
||||
[Species.ZARUDE]: 6,
|
||||
[Species.REGIELEKI]: 6,
|
||||
[Species.REGIDRAGO]: 6,
|
||||
[Species.GLASTRIER]: 6,
|
||||
[Species.SPECTRIER]: 7,
|
||||
[Species.CALYREX]: 8,
|
||||
[Species.GALAR_MEOWTH]: 3,
|
||||
[Species.GALAR_PONYTA]: 2,
|
||||
[Species.GALAR_SLOWPOKE]: 3,
|
||||
[Species.GALAR_FARFETCHD]: 3,
|
||||
[Species.GALAR_CORSOLA]: 3,
|
||||
[Species.GALAR_ZIGZAGOON]: 3,
|
||||
[Species.GALAR_DARUMAKA]: 4,
|
||||
[Species.GALAR_YAMASK]: 3,
|
||||
[Species.GALAR_STUNFISK]: 2,
|
||||
[Species.GALAR_MR_MIME]: 3,
|
||||
[Species.GALAR_ARTICUNO]: 6,
|
||||
[Species.GALAR_ZAPDOS]: 6,
|
||||
[Species.GALAR_MOLTRES]: 6,
|
||||
[Species.HISUI_GROWLITHE]: 4,
|
||||
[Species.HISUI_VOLTORB]: 3,
|
||||
[Species.HISUI_QWILFISH]: 4,
|
||||
[Species.HISUI_SNEASEL]: 5,
|
||||
[Species.HISUI_ZORUA]: 3,
|
||||
[Species.ENAMORUS]: 7,
|
||||
|
||||
[Species.SPRIGATITO]: 4,
|
||||
[Species.FUECOCO]: 4,
|
||||
[Species.QUAXLY]: 4,
|
||||
[Species.LECHONK]: 2,
|
||||
[Species.TAROUNTULA]: 1,
|
||||
[Species.NYMBLE]: 3,
|
||||
[Species.PAWMI]: 3,
|
||||
[Species.TANDEMAUS]: 4,
|
||||
[Species.FIDOUGH]: 2,
|
||||
[Species.SMOLIV]: 3,
|
||||
[Species.SQUAWKABILLY]: 2,
|
||||
[Species.NACLI]: 4,
|
||||
[Species.CHARCADET]: 4,
|
||||
[Species.TADBULB]: 3,
|
||||
[Species.WATTREL]: 3,
|
||||
[Species.MASCHIFF]: 3,
|
||||
[Species.SHROODLE]: 2,
|
||||
[Species.BRAMBLIN]: 3,
|
||||
[Species.TOEDSCOOL]: 3,
|
||||
[Species.KLAWF]: 3,
|
||||
[Species.CAPSAKID]: 3,
|
||||
[Species.RELLOR]: 2,
|
||||
[Species.FLITTLE]: 3,
|
||||
[Species.TINKATINK]: 4,
|
||||
[Species.WIGLETT]: 2,
|
||||
[Species.BOMBIRDIER]: 3,
|
||||
[Species.FINIZEN]: 3,
|
||||
[Species.VAROOM]: 4,
|
||||
[Species.CYCLIZAR]: 4,
|
||||
[Species.ORTHWORM]: 4,
|
||||
[Species.GLIMMET]: 4,
|
||||
[Species.GREAVARD]: 3,
|
||||
[Species.FLAMIGO]: 4,
|
||||
[Species.CETODDLE]: 3,
|
||||
[Species.VELUZA]: 4,
|
||||
[Species.DONDOZO]: 4,
|
||||
[Species.TATSUGIRI]: 4,
|
||||
[Species.GREAT_TUSK]: 6,
|
||||
[Species.SCREAM_TAIL]: 6,
|
||||
[Species.BRUTE_BONNET]: 6,
|
||||
[Species.FLUTTER_MANE]: 7,
|
||||
[Species.SLITHER_WING]: 6,
|
||||
[Species.SANDY_SHOCKS]: 6,
|
||||
[Species.IRON_TREADS]: 6,
|
||||
[Species.IRON_BUNDLE]: 6,
|
||||
[Species.IRON_HANDS]: 6,
|
||||
[Species.IRON_JUGULIS]: 6,
|
||||
[Species.IRON_MOTH]: 6,
|
||||
[Species.IRON_THORNS]: 6,
|
||||
[Species.FRIGIBAX]: 4,
|
||||
[Species.GIMMIGHOUL]: 4,
|
||||
[Species.WO_CHIEN]: 6,
|
||||
[Species.CHIEN_PAO]: 7,
|
||||
[Species.TING_LU]: 6,
|
||||
[Species.CHI_YU]: 7,
|
||||
[Species.ROARING_MOON]: 6,
|
||||
[Species.IRON_VALIANT]: 6,
|
||||
[Species.KORAIDON]: 9,
|
||||
[Species.MIRAIDON]: 9,
|
||||
[Species.WALKING_WAKE]: 6,
|
||||
[Species.IRON_LEAVES]: 6,
|
||||
[Species.POLTCHAGEIST]: 4,
|
||||
[Species.OKIDOGI]: 6,
|
||||
[Species.MUNKIDORI]: 6,
|
||||
[Species.FEZANDIPITI]: 6,
|
||||
[Species.OGERPON]: 7,
|
||||
[Species.GOUGING_FIRE]: 7,
|
||||
[Species.RAGING_BOLT]: 6,
|
||||
[Species.IRON_BOULDER]: 7,
|
||||
[Species.IRON_CROWN]: 6,
|
||||
[Species.TERAPAGOS]: 8,
|
||||
[Species.PECHARUNT]: 6,
|
||||
[Species.PALDEA_TAUROS]: 5,
|
||||
[Species.PALDEA_WOOPER]: 3,
|
||||
[Species.BLOODMOON_URSALUNA]: 6,
|
||||
};
|
||||
|
||||
const starterCandyCosts: { passive: number; costReduction: [number, number]; egg: number; }[] = [
|
||||
{ passive: 40, costReduction: [25, 60], egg: 30 }, // 1 Cost
|
||||
{ passive: 40, costReduction: [25, 60], egg: 30 }, // 2 Cost
|
||||
{ passive: 35, costReduction: [20, 50], egg: 25 }, // 3 Cost
|
||||
{ passive: 30, costReduction: [15, 40], egg: 20 }, // 4 Cost
|
||||
{ passive: 25, costReduction: [12, 35], egg: 18 }, // 5 Cost
|
||||
{ passive: 20, costReduction: [10, 30], egg: 15 }, // 6 Cost
|
||||
{ passive: 15, costReduction: [8, 20], egg: 12 }, // 7 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 8 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 9 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 10 Cost
|
||||
];
|
||||
|
||||
/**
|
||||
* Getter for {@linkcode starterCandyCosts} for passive unlock candy cost based on initial point cost
|
||||
* @param starterCost the default point cost of the starter found in {@linkcode speciesStarterCosts}
|
||||
* @returns the candy cost for passive unlock
|
||||
*/
|
||||
export function getPassiveCandyCount(starterCost: number): number {
|
||||
return starterCandyCosts[starterCost - 1].passive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for {@linkcode starterCandyCosts} for value reduction unlock candy cost based on initial point cost
|
||||
* @param starterCost the default point cost of the starter found in {@linkcode speciesStarterCosts}
|
||||
* @returns respective candy cost for the two cost reductions as an array 2 numbers
|
||||
*/
|
||||
export function getValueReductionCandyCounts(starterCost: number): [number, number] {
|
||||
return starterCandyCosts[starterCost - 1].costReduction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for {@linkcode starterCandyCosts} for egg purchase candy cost based on initial point cost
|
||||
* @param starterCost the default point cost of the starter found in {@linkcode speciesStarterCosts}
|
||||
* @returns the candy cost for the purchasable egg
|
||||
*/
|
||||
export function getSameSpeciesEggCandyCounts(starterCost: number): number {
|
||||
return starterCandyCosts[starterCost - 1].egg;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ModifierTier } from "../modifier/modifier-tier";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
|
@ -1,20 +1,21 @@
|
||||
import * as Utils from "../utils";
|
||||
import * as Utils from "#app/utils";
|
||||
import i18next from "i18next";
|
||||
import { defaultStarterSpecies, DexAttrProps, GameData } from "#app/system/game-data";
|
||||
import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./pokemon-species";
|
||||
import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import Pokemon, { PokemonMove } from "#app/field/pokemon";
|
||||
import { BattleType, FixedBattleConfig } from "#app/battle";
|
||||
import Trainer, { TrainerVariant } from "#app/field/trainer";
|
||||
import { GameMode } from "#app/game-mode";
|
||||
import { Type } from "./type";
|
||||
import { Type } from "#app/data/type";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { Species } from "#enums/species";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { Nature } from "./nature";
|
||||
import { Moves } from "#app/enums/moves";
|
||||
import { TypeColor, TypeShadow } from "#app/enums/color";
|
||||
import { pokemonEvolutions } from "./pokemon-evolutions";
|
||||
import { pokemonFormChanges } from "./pokemon-forms";
|
||||
import { Nature } from "#app/data/nature";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { TypeColor, TypeShadow } from "#enums/color";
|
||||
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { pokemonFormChanges } from "#app/data/pokemon-forms";
|
||||
|
||||
/** A constant for the default max cost of the starting party before a run */
|
||||
const DEFAULT_PARTY_MAX_COST = 10;
|
||||
@ -637,7 +638,7 @@ export class FreshStartChallenge extends Challenge {
|
||||
|
||||
applyStarterCost(species: Species, cost: Utils.NumberHolder): boolean {
|
||||
if (defaultStarterSpecies.includes(species)) {
|
||||
cost.value = speciesStarters[species];
|
||||
cost.value = speciesStarterCosts[species];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -719,7 +720,7 @@ export class LowerStarterMaxCostChallenge extends Challenge {
|
||||
}
|
||||
|
||||
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder): boolean {
|
||||
if (speciesStarters[pokemon.speciesId] > DEFAULT_PARTY_MAX_COST - this.value) {
|
||||
if (speciesStarterCosts[pokemon.speciesId] > DEFAULT_PARTY_MAX_COST - this.value) {
|
||||
valid.value = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { Species } from "#enums/species";
|
||||
import BattleScene from "../battle-scene";
|
||||
import { PlayerPokemon } from "../field/pokemon";
|
||||
import { Starter } from "../ui/starter-select-ui-handler";
|
||||
import * as Utils from "../utils";
|
||||
import PokemonSpecies, { PokemonSpeciesForm, getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./pokemon-species";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { Starter } from "#app/ui/starter-select-ui-handler";
|
||||
import * as Utils from "#app/utils";
|
||||
import PokemonSpecies, { PokemonSpeciesForm, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
|
||||
export interface DailyRunConfig {
|
||||
seed: integer;
|
||||
@ -46,9 +47,9 @@ export function getDailyRunStarters(scene: BattleScene, seed: string): Starter[]
|
||||
|
||||
for (let c = 0; c < starterCosts.length; c++) {
|
||||
const cost = starterCosts[c];
|
||||
const costSpecies = Object.keys(speciesStarters)
|
||||
const costSpecies = Object.keys(speciesStarterCosts)
|
||||
.map(s => parseInt(s) as Species)
|
||||
.filter(s => speciesStarters[s] === cost);
|
||||
.filter(s => speciesStarterCosts[s] === cost);
|
||||
const randPkmSpecies = getPokemonSpecies(Utils.randSeedItem(costSpecies));
|
||||
const starterSpecies = getPokemonSpecies(randPkmSpecies.getTrainerSpeciesForLevel(startingLevel, true, PartyMemberStrength.STRONGER));
|
||||
starters.push(getDailyRunStarter(scene, starterSpecies, startingLevel));
|
||||
|
@ -1,30 +1,19 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species";
|
||||
import { VariantTier } from "../enums/variant-tier";
|
||||
import * as Utils from "../utils";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { VariantTier } from "#enums/variant-tier";
|
||||
import * as Utils from "#app/utils";
|
||||
import Overrides from "#app/overrides";
|
||||
import { pokemonPrevolutions } from "./pokemon-evolutions";
|
||||
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
import i18next from "i18next";
|
||||
import { EggTier } from "#enums/egg-type";
|
||||
import { Species } from "#enums/species";
|
||||
import { EggSourceType } from "#app/enums/egg-source-types";
|
||||
import { EggSourceType } from "#enums/egg-source-types";
|
||||
import { MANAPHY_EGG_MANAPHY_RATE, SAME_SPECIES_EGG_HA_RATE, GACHA_EGG_HA_RATE, GACHA_DEFAULT_RARE_EGGMOVE_RATE, SAME_SPECIES_EGG_RARE_EGGMOVE_RATE, GACHA_MOVE_UP_RARE_EGGMOVE_RATE, GACHA_DEFAULT_SHINY_RATE, GACHA_SHINY_UP_SHINY_RATE, SAME_SPECIES_EGG_SHINY_RATE, EGG_PITY_LEGENDARY_THRESHOLD, EGG_PITY_EPIC_THRESHOLD, EGG_PITY_RARE_THRESHOLD, SHINY_VARIANT_CHANCE, SHINY_EPIC_CHANCE, GACHA_DEFAULT_COMMON_EGG_THRESHOLD, GACHA_DEFAULT_RARE_EGG_THRESHOLD, GACHA_DEFAULT_EPIC_EGG_THRESHOLD, GACHA_LEGENDARY_UP_THRESHOLD_OFFSET, HATCH_WAVES_MANAPHY_EGG, HATCH_WAVES_COMMON_EGG, HATCH_WAVES_RARE_EGG, HATCH_WAVES_EPIC_EGG, HATCH_WAVES_LEGENDARY_EGG } from "#app/data/balance/rates";
|
||||
|
||||
export const EGG_SEED = 1073741824;
|
||||
|
||||
// Rates for specific random properties in 1/x
|
||||
const DEFAULT_SHINY_RATE = 128;
|
||||
const GACHA_SHINY_UP_SHINY_RATE = 64;
|
||||
const SAME_SPECIES_EGG_SHINY_RATE = 12;
|
||||
const SAME_SPECIES_EGG_HA_RATE = 8;
|
||||
const MANAPHY_EGG_MANAPHY_RATE = 8;
|
||||
const GACHA_EGG_HA_RATE = 192;
|
||||
|
||||
// 1/x for legendary eggs, 1/x*2 for epic eggs, 1/x*4 for rare eggs, and 1/x*8 for common eggs
|
||||
const DEFAULT_RARE_EGGMOVE_RATE = 6;
|
||||
const SAME_SPECIES_EGG_RARE_EGGMOVE_RATE = 3;
|
||||
const GACHA_MOVE_UP_RARE_EGGMOVE_RATE = 3;
|
||||
|
||||
/** Egg options to override egg properties */
|
||||
export interface IEggOptions {
|
||||
/** Id. Used to check if egg type will be manaphy (id % 204 === 0) */
|
||||
@ -323,7 +312,7 @@ export class Egg {
|
||||
////
|
||||
|
||||
private rollEggMoveIndex() {
|
||||
let baseChance = DEFAULT_RARE_EGGMOVE_RATE;
|
||||
let baseChance = GACHA_DEFAULT_RARE_EGGMOVE_RATE;
|
||||
switch (this._sourceType) {
|
||||
case EggSourceType.SAME_SPECIES_EGG:
|
||||
baseChance = SAME_SPECIES_EGG_RARE_EGGMOVE_RATE;
|
||||
@ -341,24 +330,24 @@ export class Egg {
|
||||
|
||||
private getEggTierDefaultHatchWaves(eggTier?: EggTier): number {
|
||||
if (this._species === Species.PHIONE || this._species === Species.MANAPHY) {
|
||||
return 50;
|
||||
return HATCH_WAVES_MANAPHY_EGG;
|
||||
}
|
||||
|
||||
switch (eggTier ?? this._tier) {
|
||||
case EggTier.COMMON:
|
||||
return 10;
|
||||
return HATCH_WAVES_COMMON_EGG;
|
||||
case EggTier.GREAT:
|
||||
return 25;
|
||||
return HATCH_WAVES_RARE_EGG;
|
||||
case EggTier.ULTRA:
|
||||
return 50;
|
||||
return HATCH_WAVES_EPIC_EGG;
|
||||
}
|
||||
return 100;
|
||||
return HATCH_WAVES_LEGENDARY_EGG;
|
||||
}
|
||||
|
||||
private rollEggTier(): EggTier {
|
||||
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? 1 : 0;
|
||||
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? GACHA_LEGENDARY_UP_THRESHOLD_OFFSET : 0;
|
||||
const tierValue = Utils.randInt(256);
|
||||
return tierValue >= 52 + tierValueOffset ? EggTier.COMMON : tierValue >= 8 + tierValueOffset ? EggTier.GREAT : tierValue >= 1 + tierValueOffset ? EggTier.ULTRA : EggTier.MASTER;
|
||||
return tierValue >= GACHA_DEFAULT_COMMON_EGG_THRESHOLD + tierValueOffset ? EggTier.COMMON : tierValue >= GACHA_DEFAULT_RARE_EGG_THRESHOLD + tierValueOffset ? EggTier.GREAT : tierValue >= GACHA_DEFAULT_EPIC_EGG_THRESHOLD + tierValueOffset ? EggTier.ULTRA : EggTier.MASTER;
|
||||
}
|
||||
|
||||
private rollSpecies(scene: BattleScene): Species | null {
|
||||
@ -409,8 +398,8 @@ export class Egg {
|
||||
|
||||
const ignoredSpecies = [Species.PHIONE, Species.MANAPHY, Species.ETERNATUS];
|
||||
|
||||
let speciesPool = Object.keys(speciesStarters)
|
||||
.filter(s => speciesStarters[s] >= minStarterValue && speciesStarters[s] <= maxStarterValue)
|
||||
let speciesPool = Object.keys(speciesStarterCosts)
|
||||
.filter(s => speciesStarterCosts[s] >= minStarterValue && speciesStarterCosts[s] <= maxStarterValue)
|
||||
.map(s => parseInt(s) as Species)
|
||||
.filter(s => !pokemonPrevolutions.hasOwnProperty(s) && getPokemonSpecies(s).isObtainable() && ignoredSpecies.indexOf(s) === -1);
|
||||
|
||||
@ -441,7 +430,7 @@ export class Egg {
|
||||
let totalWeight = 0;
|
||||
const speciesWeights : number[] = [];
|
||||
for (const speciesId of speciesPool) {
|
||||
let weight = Math.floor((((maxStarterValue - speciesStarters[speciesId]) / ((maxStarterValue - minStarterValue) + 1)) * 1.5 + 1) * 100);
|
||||
let weight = Math.floor((((maxStarterValue - speciesStarterCosts[speciesId]) / ((maxStarterValue - minStarterValue) + 1)) * 1.5 + 1) * 100);
|
||||
const species = getPokemonSpecies(speciesId);
|
||||
if (species.isRegional()) {
|
||||
weight = Math.floor(weight / 2);
|
||||
@ -475,7 +464,7 @@ export class Egg {
|
||||
* @returns True if the egg is shiny
|
||||
**/
|
||||
private rollShiny(): boolean {
|
||||
let shinyChance = DEFAULT_SHINY_RATE;
|
||||
let shinyChance = GACHA_DEFAULT_SHINY_RATE;
|
||||
switch (this._sourceType) {
|
||||
case EggSourceType.GACHA_SHINY:
|
||||
shinyChance = GACHA_SHINY_UP_SHINY_RATE;
|
||||
@ -498,9 +487,9 @@ export class Egg {
|
||||
}
|
||||
|
||||
const rand = Utils.randSeedInt(10);
|
||||
if (rand >= 4) {
|
||||
if (rand >= SHINY_VARIANT_CHANCE) {
|
||||
return VariantTier.STANDARD; // 6/10
|
||||
} else if (rand >= 1) {
|
||||
} else if (rand >= SHINY_EPIC_CHANCE) {
|
||||
return VariantTier.RARE; // 3/10
|
||||
} else {
|
||||
return VariantTier.EPIC; // 1/10
|
||||
@ -508,16 +497,16 @@ export class Egg {
|
||||
}
|
||||
|
||||
private checkForPityTierOverrides(scene: BattleScene): void {
|
||||
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? 1 : 0;
|
||||
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? GACHA_LEGENDARY_UP_THRESHOLD_OFFSET : 0;
|
||||
scene.gameData.eggPity[EggTier.GREAT] += 1;
|
||||
scene.gameData.eggPity[EggTier.ULTRA] += 1;
|
||||
scene.gameData.eggPity[EggTier.MASTER] += 1 + tierValueOffset;
|
||||
// These numbers are roughly the 80% mark. That is, 80% of the time you'll get an egg before this gets triggered.
|
||||
if (scene.gameData.eggPity[EggTier.MASTER] >= 412 && this._tier === EggTier.COMMON) {
|
||||
if (scene.gameData.eggPity[EggTier.MASTER] >= EGG_PITY_LEGENDARY_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.MASTER;
|
||||
} else if (scene.gameData.eggPity[EggTier.ULTRA] >= 59 && this._tier === EggTier.COMMON) {
|
||||
} else if (scene.gameData.eggPity[EggTier.ULTRA] >= EGG_PITY_EPIC_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.ULTRA;
|
||||
} else if (scene.gameData.eggPity[EggTier.GREAT] >= 9 && this._tier === EggTier.COMMON) {
|
||||
} else if (scene.gameData.eggPity[EggTier.GREAT] >= EGG_PITY_RARE_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.GREAT;
|
||||
}
|
||||
scene.gameData.eggPity[this._tier] = 0;
|
||||
@ -544,7 +533,7 @@ export class Egg {
|
||||
}
|
||||
|
||||
private getEggTierFromSpeciesStarterValue(): EggTier {
|
||||
const speciesStartValue = speciesStarters[this.species];
|
||||
const speciesStartValue = speciesStarterCosts[this.species];
|
||||
if (speciesStartValue >= 1 && speciesStartValue <= 3) {
|
||||
return EggTier.COMMON;
|
||||
}
|
||||
@ -567,7 +556,7 @@ export class Egg {
|
||||
}
|
||||
|
||||
export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timestamp: number): Species {
|
||||
const legendarySpecies = Object.entries(speciesStarters)
|
||||
const legendarySpecies = Object.entries(speciesStarterCosts)
|
||||
.filter(s => s[1] >= 8 && s[1] <= 9)
|
||||
.map(s => parseInt(s[0]))
|
||||
.filter(s => getPokemonSpecies(s).isObtainable());
|
||||
@ -594,7 +583,7 @@ export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timesta
|
||||
* @returns The egg tier of a given pokemon species
|
||||
*/
|
||||
export function getEggTierForSpecies(pokemonSpecies :PokemonSpecies): EggTier {
|
||||
const speciesBaseValue = speciesStarters[pokemonSpecies.getRootSpeciesId()];
|
||||
const speciesBaseValue = speciesStarterCosts[pokemonSpecies.getRootSpeciesId()];
|
||||
if (speciesBaseValue <= 3) {
|
||||
return EggTier.COMMON;
|
||||
} else if (speciesBaseValue <= 5) {
|
||||
|
255
src/data/move.ts
255
src/data/move.ts
@ -25,7 +25,6 @@ import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { MoveUsedEvent } from "#app/events/battle-scene";
|
||||
import { BATTLE_STATS, type BattleStat, EFFECTIVE_STATS, type EffectiveStat, getStatKey, Stat } from "#app/enums/stat";
|
||||
import { PartyStatusCurePhase } from "#app/phases/party-status-cure-phase";
|
||||
import { BattleEndPhase } from "#app/phases/battle-end-phase";
|
||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
@ -34,6 +33,7 @@ import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { SwitchPhase } from "#app/phases/switch-phase";
|
||||
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
||||
import { SpeciesFormChangeRevertWeatherFormTrigger } from "./pokemon-forms";
|
||||
import { GameMode } from "#app/game-mode";
|
||||
import { applyChallenges, ChallengeType } from "./challenge";
|
||||
@ -341,7 +341,8 @@ export default class Move implements Localizable {
|
||||
* @returns `true` if the move can bypass the target's Substitute; `false` otherwise.
|
||||
*/
|
||||
hitsSubstitute(user: Pokemon, target: Pokemon | null): boolean {
|
||||
if (this.moveTarget === MoveTarget.USER || !target?.getTag(BattlerTagType.SUBSTITUTE)) {
|
||||
if ([MoveTarget.USER, MoveTarget.USER_SIDE, MoveTarget.ENEMY_SIDE, MoveTarget.BOTH_SIDES].includes(this.moveTarget)
|
||||
|| !target?.getTag(BattlerTagType.SUBSTITUTE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -398,220 +399,202 @@ export default class Move implements Localizable {
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.MAKES_CONTACT} flag for the calling Move
|
||||
* @param makesContact The value (boolean) to set the flag to
|
||||
* @param setFlag Default `true`, set to `false` if the move doesn't make contact
|
||||
* @see {@linkcode Abilities.STATIC}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
makesContact(makesContact: boolean = true): this {
|
||||
this.setFlag(MoveFlags.MAKES_CONTACT, makesContact);
|
||||
makesContact(setFlag: boolean = true): this {
|
||||
this.setFlag(MoveFlags.MAKES_CONTACT, setFlag);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.IGNORE_PROTECT} flag for the calling Move
|
||||
* @param ignoresProtect The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.CURSE}
|
||||
* @see {@linkcode Moves.CURSE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
ignoresProtect(ignoresProtect: boolean = true): this {
|
||||
this.setFlag(MoveFlags.IGNORE_PROTECT, ignoresProtect);
|
||||
ignoresProtect(): this {
|
||||
this.setFlag(MoveFlags.IGNORE_PROTECT, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.IGNORE_VIRTUAL} flag for the calling Move
|
||||
* @param ignoresVirtual The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.NATURE_POWER}
|
||||
* @see {@linkcode Moves.NATURE_POWER}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
ignoresVirtual(ignoresVirtual: boolean = true): this {
|
||||
this.setFlag(MoveFlags.IGNORE_VIRTUAL, ignoresVirtual);
|
||||
ignoresVirtual(): this {
|
||||
this.setFlag(MoveFlags.IGNORE_VIRTUAL, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.SOUND_BASED} flag for the calling Move
|
||||
* @param soundBased The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.UPROAR}
|
||||
* @see {@linkcode Moves.UPROAR}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
soundBased(soundBased: boolean = true): this {
|
||||
this.setFlag(MoveFlags.SOUND_BASED, soundBased);
|
||||
soundBased(): this {
|
||||
this.setFlag(MoveFlags.SOUND_BASED, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.HIDE_USER} flag for the calling Move
|
||||
* @param hidesUser The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.TELEPORT}
|
||||
* @see {@linkcode Moves.TELEPORT}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
hidesUser(hidesUser: boolean = true): this {
|
||||
this.setFlag(MoveFlags.HIDE_USER, hidesUser);
|
||||
hidesUser(): this {
|
||||
this.setFlag(MoveFlags.HIDE_USER, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.HIDE_TARGET} flag for the calling Move
|
||||
* @param hidesTarget The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.WHIRLWIND}
|
||||
* @see {@linkcode Moves.WHIRLWIND}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
hidesTarget(hidesTarget: boolean = true): this {
|
||||
this.setFlag(MoveFlags.HIDE_TARGET, hidesTarget);
|
||||
hidesTarget(): this {
|
||||
this.setFlag(MoveFlags.HIDE_TARGET, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.BITING_MOVE} flag for the calling Move
|
||||
* @param bitingMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.BITE}
|
||||
* @see {@linkcode Moves.BITE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
bitingMove(bitingMove: boolean = true): this {
|
||||
this.setFlag(MoveFlags.BITING_MOVE, bitingMove);
|
||||
bitingMove(): this {
|
||||
this.setFlag(MoveFlags.BITING_MOVE, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.PULSE_MOVE} flag for the calling Move
|
||||
* @param pulseMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.WATER_PULSE}
|
||||
* @see {@linkcode Moves.WATER_PULSE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
pulseMove(pulseMove: boolean = true): this {
|
||||
this.setFlag(MoveFlags.PULSE_MOVE, pulseMove);
|
||||
pulseMove(): this {
|
||||
this.setFlag(MoveFlags.PULSE_MOVE, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.PUNCHING_MOVE} flag for the calling Move
|
||||
* @param punchingMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.DRAIN_PUNCH}
|
||||
* @see {@linkcode Moves.DRAIN_PUNCH}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
punchingMove(punchingMove: boolean = true): this {
|
||||
this.setFlag(MoveFlags.PUNCHING_MOVE, punchingMove);
|
||||
punchingMove(): this {
|
||||
this.setFlag(MoveFlags.PUNCHING_MOVE, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.SLICING_MOVE} flag for the calling Move
|
||||
* @param slicingMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.X_SCISSOR}
|
||||
* @see {@linkcode Moves.X_SCISSOR}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
slicingMove(slicingMove: boolean = true): this {
|
||||
this.setFlag(MoveFlags.SLICING_MOVE, slicingMove);
|
||||
slicingMove(): this {
|
||||
this.setFlag(MoveFlags.SLICING_MOVE, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.RECKLESS_MOVE} flag for the calling Move
|
||||
* @see {@linkcode Abilities.RECKLESS}
|
||||
* @param recklessMove The value to set the flag to
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
recklessMove(recklessMove: boolean = true): this {
|
||||
this.setFlag(MoveFlags.RECKLESS_MOVE, recklessMove);
|
||||
recklessMove(): this {
|
||||
this.setFlag(MoveFlags.RECKLESS_MOVE, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.BALLBOMB_MOVE} flag for the calling Move
|
||||
* @param ballBombMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.ELECTRO_BALL}
|
||||
* @see {@linkcode Moves.ELECTRO_BALL}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
ballBombMove(ballBombMove: boolean = true): this {
|
||||
this.setFlag(MoveFlags.BALLBOMB_MOVE, ballBombMove);
|
||||
ballBombMove(): this {
|
||||
this.setFlag(MoveFlags.BALLBOMB_MOVE, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.POWDER_MOVE} flag for the calling Move
|
||||
* @param powderMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.STUN_SPORE}
|
||||
* @see {@linkcode Moves.STUN_SPORE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
powderMove(powderMove: boolean = true): this {
|
||||
this.setFlag(MoveFlags.POWDER_MOVE, powderMove);
|
||||
powderMove(): this {
|
||||
this.setFlag(MoveFlags.POWDER_MOVE, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.DANCE_MOVE} flag for the calling Move
|
||||
* @param danceMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.PETAL_DANCE}
|
||||
* @see {@linkcode Moves.PETAL_DANCE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
danceMove(danceMove: boolean = true): this {
|
||||
this.setFlag(MoveFlags.DANCE_MOVE, danceMove);
|
||||
danceMove(): this {
|
||||
this.setFlag(MoveFlags.DANCE_MOVE, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.WIND_MOVE} flag for the calling Move
|
||||
* @param windMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.HURRICANE}
|
||||
* @see {@linkcode Moves.HURRICANE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
windMove(windMove: boolean = true): this {
|
||||
this.setFlag(MoveFlags.WIND_MOVE, windMove);
|
||||
windMove(): this {
|
||||
this.setFlag(MoveFlags.WIND_MOVE, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.TRIAGE_MOVE} flag for the calling Move
|
||||
* @param triageMove The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.ABSORB}
|
||||
* @see {@linkcode Moves.ABSORB}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
triageMove(triageMove: boolean = true): this {
|
||||
this.setFlag(MoveFlags.TRIAGE_MOVE, triageMove);
|
||||
triageMove(): this {
|
||||
this.setFlag(MoveFlags.TRIAGE_MOVE, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.IGNORE_ABILITIES} flag for the calling Move
|
||||
* @param ignoresAbilities sThe value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.SUNSTEEL_STRIKE}
|
||||
* @see {@linkcode Moves.SUNSTEEL_STRIKE}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
ignoresAbilities(ignoresAbilities: boolean = true): this {
|
||||
this.setFlag(MoveFlags.IGNORE_ABILITIES, ignoresAbilities);
|
||||
ignoresAbilities(): this {
|
||||
this.setFlag(MoveFlags.IGNORE_ABILITIES, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.CHECK_ALL_HITS} flag for the calling Move
|
||||
* @param checkAllHits The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.TRIPLE_AXEL}
|
||||
* @see {@linkcode Moves.TRIPLE_AXEL}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
checkAllHits(checkAllHits: boolean = true): this {
|
||||
this.setFlag(MoveFlags.CHECK_ALL_HITS, checkAllHits);
|
||||
checkAllHits(): this {
|
||||
this.setFlag(MoveFlags.CHECK_ALL_HITS, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.IGNORE_SUBSTITUTE} flag for the calling Move
|
||||
* @param ignoresSubstitute The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.WHIRLWIND}
|
||||
* @see {@linkcode Moves.WHIRLWIND}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
ignoresSubstitute(ignoresSubstitute: boolean = true): this {
|
||||
this.setFlag(MoveFlags.IGNORE_SUBSTITUTE, ignoresSubstitute);
|
||||
ignoresSubstitute(): this {
|
||||
this.setFlag(MoveFlags.IGNORE_SUBSTITUTE, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@linkcode MoveFlags.REDIRECT_COUNTER} flag for the calling Move
|
||||
* @param redirectCounter The value (boolean) to set the flag to
|
||||
* example: @see {@linkcode Moves.METAL_BURST}
|
||||
* @see {@linkcode Moves.METAL_BURST}
|
||||
* @returns The {@linkcode Move} that called this function
|
||||
*/
|
||||
redirectCounter(redirectCounter: boolean = true): this {
|
||||
this.setFlag(MoveFlags.REDIRECT_COUNTER, redirectCounter);
|
||||
redirectCounter(): this {
|
||||
this.setFlag(MoveFlags.REDIRECT_COUNTER, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1602,12 +1585,31 @@ export class PartyStatusCureAttr extends MoveEffectAttr {
|
||||
if (!this.canApply(user, target, move, args)) {
|
||||
return false;
|
||||
}
|
||||
this.addPartyCurePhase(user);
|
||||
const partyPokemon = user.isPlayer() ? user.scene.getParty() : user.scene.getEnemyParty();
|
||||
partyPokemon.forEach(p => this.cureStatus(p, user.id));
|
||||
|
||||
if (this.message) {
|
||||
user.scene.queueMessage(this.message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
addPartyCurePhase(user: Pokemon) {
|
||||
user.scene.unshiftPhase(new PartyStatusCurePhase(user.scene, user, this.message, this.abilityCondition));
|
||||
/**
|
||||
* Tries to cure the status of the given {@linkcode Pokemon}
|
||||
* @param pokemon The {@linkcode Pokemon} to cure.
|
||||
* @param userId The ID of the (move) {@linkcode Pokemon | user}.
|
||||
*/
|
||||
public cureStatus(pokemon: Pokemon, userId: number) {
|
||||
if (!pokemon.isOnField() || pokemon.id === userId) { // user always cures its own status, regardless of ability
|
||||
pokemon.resetStatus(false);
|
||||
pokemon.updateInfo();
|
||||
} else if (!pokemon.hasAbility(this.abilityCondition)) {
|
||||
pokemon.resetStatus();
|
||||
pokemon.updateInfo();
|
||||
} else {
|
||||
pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id, pokemon.getPassiveAbility()?.id === this.abilityCondition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2685,20 +2687,42 @@ export class DelayedAttackAttr extends OverrideMoveEffectAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute used for moves that change stat stages
|
||||
* @param stats {@linkcode BattleStat} array of stats to be changed
|
||||
* @param stages stages by which to change the stats, from -6 to 6
|
||||
* @param selfTarget whether the changes are applied to the user (true) or the target (false)
|
||||
* @param condition {@linkcode MoveConditionFunc} optional condition to trigger the stat change
|
||||
* @param firstHitOnly whether the stat change only applies on the first hit of a multi hit move
|
||||
* @param moveEffectTrigger {@linkcode MoveEffectTrigger} the trigger for the effect to take place
|
||||
* @param firstTargetOnly whether, if this is a multi target move, to only apply the effect after the first target is hit, rather than once for each target
|
||||
* @param lastHitOnly whether the effect should only apply after the last hit of a multi hit move
|
||||
*
|
||||
* @extends MoveEffectAttr
|
||||
* @see {@linkcode apply}
|
||||
*/
|
||||
export class StatStageChangeAttr extends MoveEffectAttr {
|
||||
public stats: BattleStat[];
|
||||
public stages: integer;
|
||||
private condition: MoveConditionFunc | null;
|
||||
private showMessage: boolean;
|
||||
|
||||
constructor(stats: BattleStat[], stages: integer, selfTarget?: boolean, condition?: MoveConditionFunc | null, showMessage: boolean = true, firstHitOnly: boolean = false, moveEffectTrigger: MoveEffectTrigger = MoveEffectTrigger.HIT, firstTargetOnly: boolean = false) {
|
||||
super(selfTarget, moveEffectTrigger, firstHitOnly, false, firstTargetOnly);
|
||||
constructor(stats: BattleStat[], stages: integer, selfTarget?: boolean, condition?: MoveConditionFunc | null, showMessage: boolean = true, firstHitOnly: boolean = false, moveEffectTrigger: MoveEffectTrigger = MoveEffectTrigger.HIT, firstTargetOnly: boolean = false, lastHitOnly: boolean = false) {
|
||||
super(selfTarget, moveEffectTrigger, firstHitOnly, lastHitOnly, firstTargetOnly);
|
||||
this.stats = stats;
|
||||
this.stages = stages;
|
||||
this.condition = condition!; // TODO: is this bang correct?
|
||||
this.showMessage = showMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to change stats of the user or target (depending on value of selfTarget) if conditions are met
|
||||
* @param user {@linkcode Pokemon} the user of the move
|
||||
* @param target {@linkcode Pokemon} the target of the move
|
||||
* @param move {@linkcode Move} the move
|
||||
* @param args unused
|
||||
* @returns whether stat stages were changed
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args?: any[]): boolean | Promise<boolean> {
|
||||
if (!super.apply(user, target, move, args) || (this.condition && !this.condition(user, target, move))) {
|
||||
return false;
|
||||
@ -3918,7 +3942,14 @@ export class PhotonGeyserCategoryAttr extends VariableMoveCategoryAttr {
|
||||
}
|
||||
}
|
||||
|
||||
export class TeraBlastCategoryAttr extends VariableMoveCategoryAttr {
|
||||
/**
|
||||
* Attribute used for tera moves that change category based on the user's Atk and SpAtk stats
|
||||
* Note: Currently, `getEffectiveStat` does not ignore all abilities that affect stats except those
|
||||
* with the attribute of `StatMultiplierAbAttr`
|
||||
* TODO: Remove the `.partial()` tag from Tera Blast and Tera Starstorm when the above issue is resolved
|
||||
* @extends VariableMoveCategoryAttr
|
||||
*/
|
||||
export class TeraMoveCategoryAttr extends VariableMoveCategoryAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const category = (args[0] as Utils.NumberHolder);
|
||||
|
||||
@ -4007,6 +4038,30 @@ export class VariableMoveTypeAttr extends MoveAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute used for Tera Starstorm that changes the move type to Stellar
|
||||
* @extends VariableMoveTypeAttr
|
||||
*/
|
||||
export class TeraStarstormTypeAttr extends VariableMoveTypeAttr {
|
||||
/**
|
||||
*
|
||||
* @param user the {@linkcode Pokemon} using the move
|
||||
* @param target n/a
|
||||
* @param move n/a
|
||||
* @param args[0] {@linkcode Utils.NumberHolder} the move type
|
||||
* @returns `true` if the move type is changed to {@linkcode Type.STELLAR}, `false` otherwise
|
||||
*/
|
||||
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (user.isTerastallized() && (user.hasFusionSpecies(Species.TERAPAGOS) || user.species.speciesId === Species.TERAPAGOS)) {
|
||||
const moveType = args[0] as Utils.NumberHolder;
|
||||
|
||||
moveType.value = Type.STELLAR;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class FormChangeItemTypeAttr extends VariableMoveTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const moveType = args[0];
|
||||
@ -4544,6 +4599,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
|
||||
case BattlerTagType.DROWSY:
|
||||
case BattlerTagType.DISABLED:
|
||||
case BattlerTagType.HEAL_BLOCK:
|
||||
case BattlerTagType.RECEIVE_DOUBLE_DAMAGE:
|
||||
return -5;
|
||||
case BattlerTagType.SEEDED:
|
||||
case BattlerTagType.SALT_CURED:
|
||||
@ -4564,6 +4620,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
|
||||
case BattlerTagType.ENCORE:
|
||||
return -2;
|
||||
case BattlerTagType.MINIMIZED:
|
||||
case BattlerTagType.ALWAYS_GET_HIT:
|
||||
return 0;
|
||||
case BattlerTagType.INGRAIN:
|
||||
case BattlerTagType.IGNORE_ACCURACY:
|
||||
@ -5348,7 +5405,7 @@ export class ChillyReceptionAttr extends ForceSwitchOutAttr {
|
||||
|
||||
getCondition(): MoveConditionFunc {
|
||||
// chilly reception move will go through if the weather is change-able to snow, or the user can switch out, else move will fail
|
||||
return (user, target, move) => user.scene.arena.trySetWeather(WeatherType.SNOW, true) || super.getSwitchOutCondition()(user, target, move);
|
||||
return (user, target, move) => user.scene.arena.weather?.weatherType !== WeatherType.SNOW || super.getSwitchOutCondition()(user, target, move);
|
||||
}
|
||||
}
|
||||
export class RemoveTypeAttr extends MoveEffectAttr {
|
||||
@ -6589,7 +6646,7 @@ export class MoveCondition {
|
||||
|
||||
export class FirstMoveCondition extends MoveCondition {
|
||||
constructor() {
|
||||
super((user, target, move) => user.battleSummonData?.turnCount === 1);
|
||||
super((user, target, move) => user.battleSummonData?.waveTurnCount === 1);
|
||||
}
|
||||
|
||||
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
|
||||
@ -7266,7 +7323,7 @@ export function initMoves() {
|
||||
new StatusMove(Moves.CURSE, Type.GHOST, -1, 10, -1, 0, 2)
|
||||
.attr(CurseAttr)
|
||||
.ignoresSubstitute()
|
||||
.ignoresProtect(true)
|
||||
.ignoresProtect()
|
||||
.target(MoveTarget.CURSE),
|
||||
new AttackMove(Moves.FLAIL, Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 15, -1, 0, 2)
|
||||
.attr(LowHpPowerAttr),
|
||||
@ -9168,16 +9225,15 @@ export function initMoves() {
|
||||
.attr(HalfSacrificialAttr),
|
||||
new AttackMove(Moves.EXPANDING_FORCE, Type.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 8)
|
||||
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.PSYCHIC && user.isGrounded() ? 1.5 : 1)
|
||||
.attr(VariableTargetAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.PSYCHIC && user.isGrounded() ? 6 : 3),
|
||||
.attr(VariableTargetAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.PSYCHIC && user.isGrounded() ? MoveTarget.ALL_NEAR_ENEMIES : MoveTarget.NEAR_OTHER),
|
||||
new AttackMove(Moves.STEEL_ROLLER, Type.STEEL, MoveCategory.PHYSICAL, 130, 100, 5, -1, 0, 8)
|
||||
.attr(ClearTerrainAttr)
|
||||
.condition((user, target, move) => !!user.scene.arena.terrain),
|
||||
new AttackMove(Moves.SCALE_SHOT, Type.DRAGON, MoveCategory.PHYSICAL, 25, 90, 20, -1, 0, 8)
|
||||
//.attr(StatStageChangeAttr, Stat.SPD, 1, true) // TODO: Have boosts only apply at end of move, not after every hit
|
||||
//.attr(StatStageChangeAttr, Stat.DEF, -1, true)
|
||||
.attr(StatStageChangeAttr, [Stat.SPD], 1, true, null, true, false, MoveEffectTrigger.HIT, false, true)
|
||||
.attr(StatStageChangeAttr, [Stat.DEF], -1, true, null, true, false, MoveEffectTrigger.HIT, false, true)
|
||||
.attr(MultiHitAttr)
|
||||
.makesContact(false)
|
||||
.partial(),
|
||||
.makesContact(false),
|
||||
new AttackMove(Moves.METEOR_BEAM, Type.ROCK, MoveCategory.SPECIAL, 120, 90, 10, 100, 0, 8)
|
||||
.attr(ChargeAttr, ChargeAnim.METEOR_BEAM_CHARGING, i18next.t("moveTriggers:isOverflowingWithSpacePower", {pokemonName: "{USER}"}), null, true)
|
||||
.attr(StatStageChangeAttr, [ Stat.SPATK ], 1, true)
|
||||
@ -9443,10 +9499,11 @@ export function initMoves() {
|
||||
.unimplemented(),
|
||||
End Unused */
|
||||
new AttackMove(Moves.TERA_BLAST, Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 9)
|
||||
.attr(TeraBlastCategoryAttr)
|
||||
.attr(TeraMoveCategoryAttr)
|
||||
.attr(TeraBlastTypeAttr)
|
||||
.attr(TeraBlastPowerAttr)
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, true, (user, target, move) => user.isTerastallized() && user.isOfType(Type.STELLAR)),
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, true, (user, target, move) => user.isTerastallized() && user.isOfType(Type.STELLAR))
|
||||
.partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */
|
||||
new SelfStatusMove(Moves.SILK_TRAP, Type.BUG, -1, 10, -1, 4, 9)
|
||||
.attr(ProtectAttr, BattlerTagType.SILK_TRAP)
|
||||
.condition(failIfLastCondition),
|
||||
@ -9636,8 +9693,10 @@ export function initMoves() {
|
||||
.attr(ElectroShotChargeAttr)
|
||||
.ignoresVirtual(),
|
||||
new AttackMove(Moves.TERA_STARSTORM, Type.NORMAL, MoveCategory.SPECIAL, 120, 100, 5, -1, 0, 9)
|
||||
.attr(TeraBlastCategoryAttr)
|
||||
.partial(),
|
||||
.attr(TeraMoveCategoryAttr)
|
||||
.attr(TeraStarstormTypeAttr)
|
||||
.attr(VariableTargetAttr, (user, target, move) => (user.hasFusionSpecies(Species.TERAPAGOS) || user.species.speciesId === Species.TERAPAGOS) && user.isTerastallized() ? MoveTarget.ALL_NEAR_ENEMIES : MoveTarget.NEAR_OTHER)
|
||||
.partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */
|
||||
new AttackMove(Moves.FICKLE_BEAM, Type.DRAGON, MoveCategory.SPECIAL, 80, 100, 5, 30, 0, 9)
|
||||
.attr(PreMoveMessageAttr, doublePowerChanceMessageFunc)
|
||||
.attr(DoublePowerChanceAttr),
|
||||
|
@ -18,7 +18,7 @@ import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:aTrainersTest";
|
||||
const namespace = "mysteryEncounters/aTrainersTest";
|
||||
|
||||
/**
|
||||
* A Trainer's Test encounter.
|
||||
@ -32,7 +32,7 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
||||
.withIntroSpriteConfigs([]) // These are set in onInit()
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
])
|
||||
.withAutoHideIntroVisuals(false)
|
||||
@ -76,24 +76,24 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
||||
encounter.dialogue.intro = [
|
||||
{
|
||||
speaker: `trainerNames:${trainerNameKey}`,
|
||||
text: `${namespace}.${trainerNameKey}.intro_dialogue`
|
||||
text: `${namespace}:${trainerNameKey}.intro_dialogue`
|
||||
}
|
||||
];
|
||||
encounter.options[0].dialogue!.selected = [
|
||||
{
|
||||
speaker: `trainerNames:${trainerNameKey}`,
|
||||
text: `${namespace}.${trainerNameKey}.accept`
|
||||
text: `${namespace}:${trainerNameKey}.accept`
|
||||
}
|
||||
];
|
||||
encounter.options[1].dialogue!.selected = [
|
||||
{
|
||||
speaker: `trainerNames:${trainerNameKey}`,
|
||||
text: `${namespace}.${trainerNameKey}.decline`
|
||||
text: `${namespace}:${trainerNameKey}.decline`
|
||||
}
|
||||
];
|
||||
|
||||
encounter.setDialogueToken("statTrainerName", i18next.t(`trainerNames:${trainerNameKey}`));
|
||||
const eggDescription = i18next.t(`${namespace}.title`) + ":\n" + i18next.t(`trainerNames:${trainerNameKey}`);
|
||||
const eggDescription = i18next.t(`${namespace}:title`) + ":\n" + i18next.t(`trainerNames:${trainerNameKey}`);
|
||||
encounter.misc = { trainerType, trainerNameKey, trainerEggDescription: eggDescription };
|
||||
|
||||
// Trainer config
|
||||
@ -128,14 +128,14 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withIntroDialogue()
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
@ -151,15 +151,15 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
||||
eggDescriptor: encounter.misc.trainerEggDescription,
|
||||
tier: EggTier.ULTRA
|
||||
};
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}.eggTypes.epic`));
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}:eggTypes.epic`));
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH], guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA], fillRemaining: true }, [eggOptions]);
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
}
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
@ -173,14 +173,14 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
||||
eggDescriptor: encounter.misc.trainerEggDescription,
|
||||
tier: EggTier.GREAT
|
||||
};
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}.eggTypes.rare`));
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}:eggTypes.rare`));
|
||||
setEncounterRewards(scene, { fillRemaining: false, rerollMultiplier: -1 }, [eggOptions]);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`
|
||||
text: `${namespace}:outro`
|
||||
}
|
||||
])
|
||||
.build();
|
||||
|
@ -27,7 +27,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import i18next from "i18next";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:absoluteAvarice";
|
||||
const namespace = "mysteryEncounters/absoluteAvarice";
|
||||
|
||||
/**
|
||||
* Absolute Avarice encounter.
|
||||
@ -163,12 +163,12 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
@ -219,7 +219,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
modifierConfigs: bossModifierConfigs,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.boss_enraged`);
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:option.1.boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
|
||||
}
|
||||
}
|
||||
@ -250,11 +250,11 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -274,7 +274,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
scene.addModifier(seedModifier, false, false, false, true);
|
||||
}
|
||||
});
|
||||
queueEncounterMessage(scene, `${namespace}.option.1.food_stash`);
|
||||
queueEncounterMessage(scene, `${namespace}:option.1.food_stash`);
|
||||
};
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, givePartyPokemonReviverSeeds);
|
||||
@ -294,11 +294,11 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -336,11 +336,11 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
text: `${namespace}:option.3.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
@ -8,14 +8,15 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/myst
|
||||
import { AbilityRequirement, CombinationPokemonRequirement, MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||
import { getHighestStatTotalPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { EXTORTION_ABILITIES, EXTORTION_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:offerYouCantRefuse";
|
||||
const namespace = "mysteryEncounters/anOfferYouCantRefuse";
|
||||
|
||||
/**
|
||||
* Money offered starts at base value of Relic Gold, increasing linearly up to 3x Relic Gold based on the starter tier of the Pokemon being purchased
|
||||
@ -56,22 +57,22 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const pokemon = getHighestStatTotalPlayerPokemon(scene, true, true);
|
||||
|
||||
const baseSpecies = pokemon.getSpeciesForm().getRootSpeciesId();
|
||||
const starterValue: number = speciesStarters[baseSpecies] ?? 1;
|
||||
const starterValue: number = speciesStarterCosts[baseSpecies] ?? 1;
|
||||
const multiplier = Math.max(MONEY_MAXIMUM_MULTIPLIER / 10 * starterValue, MONEY_MINIMUM_MULTIPLIER);
|
||||
const price = scene.getWaveMoneyAmount(multiplier);
|
||||
|
||||
@ -104,12 +105,12 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -135,13 +136,13 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
||||
new AbilityRequirement(EXTORTION_ABILITIES))
|
||||
)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.2.tooltip_disabled`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.2.tooltip_disabled`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -159,12 +160,12 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.3.selected`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.3.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -33,7 +33,7 @@ import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:berriesAbound";
|
||||
const namespace = "mysteryEncounters/berriesAbound";
|
||||
|
||||
/**
|
||||
* Berries Abound encounter.
|
||||
@ -50,7 +50,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
.withIntroSpriteConfigs([]) // Set in onInit()
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -110,16 +110,16 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -129,7 +129,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
const numBerries = encounter.misc.numBerries;
|
||||
|
||||
const doBerryRewards = () => {
|
||||
const berryText = i18next.t(`${namespace}.berries`);
|
||||
const berryText = i18next.t(`${namespace}:berries`);
|
||||
|
||||
scene.playSound("item_fanfare");
|
||||
queueEncounterMessage(scene, i18next.t("battle:rewardGainCount", { modifierName: berryText, count: numBerries }));
|
||||
@ -157,8 +157,8 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Pick race for berries
|
||||
@ -180,7 +180,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
if (speedDiff < 1) {
|
||||
// Caught and attacked by boss, gets +1 to all stats at start of fight
|
||||
const doBerryRewards = () => {
|
||||
const berryText = i18next.t(`${namespace}.berries`);
|
||||
const berryText = i18next.t(`${namespace}:berries`);
|
||||
|
||||
scene.playSound("item_fanfare");
|
||||
queueEncounterMessage(scene, i18next.t("battle:rewardGainCount", { modifierName: berryText, count: numBerries }));
|
||||
@ -199,11 +199,11 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
const config = scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0];
|
||||
config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
||||
config.pokemonConfigs![0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.2.boss_enraged`);
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:option.2.boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
|
||||
};
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, undefined, doBerryRewards);
|
||||
await showEncounterText(scene, `${namespace}.option.2.selected_bad`);
|
||||
await showEncounterText(scene, `${namespace}:option.2.selected_bad`);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
return;
|
||||
} else {
|
||||
@ -211,7 +211,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
const numBerriesGrabbed = Math.max(Math.min(Math.round((speedDiff - 1)/0.08), numBerries), 2);
|
||||
encounter.setDialogueToken("numBerries", String(numBerriesGrabbed));
|
||||
const doFasterBerryRewards = () => {
|
||||
const berryText = i18next.t(`${namespace}.berries`);
|
||||
const berryText = i18next.t(`${namespace}:berries`);
|
||||
|
||||
scene.playSound("item_fanfare");
|
||||
queueEncounterMessage(scene, i18next.t("battle:rewardGainCount", { modifierName: berryText, count: numBerriesGrabbed }));
|
||||
@ -224,7 +224,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
|
||||
setEncounterExp(scene, fastestPokemon.id, encounter.enemyPartyConfigs[0].pokemonConfigs![0].species.baseExp);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: shopOptions, fillRemaining: false }, undefined, doFasterBerryRewards);
|
||||
await showEncounterText(scene, `${namespace}.option.2.selected`);
|
||||
await showEncounterText(scene, `${namespace}:option.2.selected`);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
})
|
||||
@ -232,11 +232,11 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
text: `${namespace}:option.3.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -52,7 +52,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:bugTypeSuperfan";
|
||||
const namespace = "mysteryEncounters/bugTypeSuperfan";
|
||||
|
||||
const POOL_1_POKEMON = [
|
||||
Species.PARASECT,
|
||||
@ -203,11 +203,11 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -276,17 +276,17 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.1.selected`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -317,9 +317,9 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withPrimaryPokemonRequirement(new TypeRequirement(Type.BUG, false, 1)) // Must have 1 Bug type on team
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.2.disabled_tooltip`
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||
// Player shows off their bug types
|
||||
@ -327,31 +327,31 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
|
||||
// Player gets different rewards depending on the number of bug types they have
|
||||
const numBugTypes = scene.getParty().filter(p => p.isOfType(Type.BUG, true)).length;
|
||||
const numBugTypesText = i18next.t(`${namespace}.numBugTypes`, { count: numBugTypes });
|
||||
const numBugTypesText = i18next.t(`${namespace}:numBugTypes`, { count: numBugTypes });
|
||||
encounter.setDialogueToken("numBugTypes", numBugTypesText);
|
||||
|
||||
if (numBugTypes < 2) {
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SUPER_LURE, modifierTypes.GREAT_BALL], fillRemaining: false });
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected_0_to_1`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.2.selected_0_to_1`,
|
||||
},
|
||||
];
|
||||
} else if (numBugTypes < 4) {
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.QUICK_CLAW, modifierTypes.MAX_LURE, modifierTypes.ULTRA_BALL], fillRemaining: false });
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected_2_to_3`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.2.selected_2_to_3`,
|
||||
},
|
||||
];
|
||||
} else if (numBugTypes < 6) {
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.GRIP_CLAW, modifierTypes.MAX_LURE, modifierTypes.ROGUE_BALL], fillRemaining: false });
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected_4_to_5`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.2.selected_4_to_5`,
|
||||
},
|
||||
];
|
||||
} else {
|
||||
@ -382,8 +382,8 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifierOptions, fillRemaining: false });
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected_6`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.2.selected_6`,
|
||||
},
|
||||
];
|
||||
}
|
||||
@ -401,19 +401,19 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1)
|
||||
))
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.3.disabled_tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
text: `${namespace}:option.3.selected`,
|
||||
},
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.3.selected_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.3.selected_dialogue`,
|
||||
},
|
||||
],
|
||||
secondOptionPrompt: `${namespace}.option.3.select_prompt`,
|
||||
secondOptionPrompt: `${namespace}:option.3.select_prompt`,
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
@ -452,7 +452,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
(item instanceof AttackTypeBoosterModifier && (item.type as AttackTypeBoosterModifierType).moveType === Type.BUG);
|
||||
});
|
||||
if (!hasValidItem) {
|
||||
return getEncounterText(scene, `${namespace}.option.3.invalid_selection`) ?? null;
|
||||
return getEncounterText(scene, `${namespace}:option.3.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -480,7 +480,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
.build())
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
},
|
||||
])
|
||||
.build();
|
||||
@ -634,7 +634,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
||||
function doBugTypeMoveTutor(scene: BattleScene): Promise<void> {
|
||||
return new Promise<void>(async resolve => {
|
||||
const moveOptions = scene.currentBattle.mysteryEncounter!.misc.moveTutorOptions;
|
||||
await showEncounterDialogue(scene, `${namespace}.battle_won`, `${namespace}.speaker`);
|
||||
await showEncounterDialogue(scene, `${namespace}:battle_won`, `${namespace}:speaker`);
|
||||
|
||||
const overlayScale = 1;
|
||||
const moveInfoOverlay = new MoveInfoOverlay(scene, {
|
||||
@ -669,7 +669,7 @@ function doBugTypeMoveTutor(scene: BattleScene): Promise<void> {
|
||||
moveInfoOverlay.setVisible(false);
|
||||
};
|
||||
|
||||
const result = await selectOptionThenPokemon(scene, optionSelectItems, `${namespace}.teach_move_prompt`, undefined, onHoverOverCancel);
|
||||
const result = await selectOptionThenPokemon(scene, optionSelectItems, `${namespace}:teach_move_prompt`, undefined, onHoverOverCancel);
|
||||
// let forceExit = !!result;
|
||||
if (!result) {
|
||||
moveInfoOverlay.active = false;
|
||||
|
@ -34,7 +34,7 @@ import { EncounterAnim } from "#enums/encounter-anims";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:clowningAround";
|
||||
const namespace = "mysteryEncounters/clowningAround";
|
||||
|
||||
const RANDOM_ABILITY_POOL = [
|
||||
Abilities.STURDY,
|
||||
@ -98,11 +98,11 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}.speaker`
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -148,19 +148,19 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
speaker: `${namespace}.speaker`
|
||||
text: `${namespace}:option.1.selected`,
|
||||
speaker: `${namespace}:speaker`
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -199,7 +199,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
// After the battle, offer the player the opportunity to permanently swap ability
|
||||
const abilityWasSwapped = await handleSwapAbility(scene);
|
||||
if (abilityWasSwapped) {
|
||||
await showEncounterText(scene, `${namespace}.option.1.ability_gained`);
|
||||
await showEncounterText(scene, `${namespace}:option.1.ability_gained`);
|
||||
}
|
||||
|
||||
// Play animations once ability swap is complete
|
||||
@ -222,19 +222,19 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
speaker: `${namespace}.speaker`
|
||||
text: `${namespace}:option.2.selected`,
|
||||
speaker: `${namespace}:speaker`
|
||||
},
|
||||
{
|
||||
text: `${namespace}.option.2.selected_2`,
|
||||
text: `${namespace}:option.2.selected_2`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.option.2.selected_3`,
|
||||
speaker: `${namespace}.speaker`
|
||||
text: `${namespace}:option.2.selected_3`,
|
||||
speaker: `${namespace}:speaker`
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -308,19 +308,19 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
speaker: `${namespace}.speaker`
|
||||
text: `${namespace}:option.3.selected`,
|
||||
speaker: `${namespace}:speaker`
|
||||
},
|
||||
{
|
||||
text: `${namespace}.option.3.selected_2`,
|
||||
text: `${namespace}:option.3.selected_2`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.option.3.selected_3`,
|
||||
speaker: `${namespace}.speaker`
|
||||
text: `${namespace}:option.3.selected_3`,
|
||||
speaker: `${namespace}:speaker`
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -377,15 +377,15 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
},
|
||||
])
|
||||
.build();
|
||||
|
||||
async function handleSwapAbility(scene: BattleScene) {
|
||||
return new Promise<boolean>(async resolve => {
|
||||
await showEncounterDialogue(scene, `${namespace}.option.1.apply_ability_dialogue`, `${namespace}.speaker`);
|
||||
await showEncounterText(scene, `${namespace}.option.1.apply_ability_message`);
|
||||
await showEncounterDialogue(scene, `${namespace}:option.1.apply_ability_dialogue`, `${namespace}:speaker`);
|
||||
await showEncounterText(scene, `${namespace}:option.1.apply_ability_message`);
|
||||
|
||||
scene.ui.setMode(Mode.MESSAGE).then(() => {
|
||||
displayYesNoOptions(scene, resolve);
|
||||
@ -394,7 +394,7 @@ async function handleSwapAbility(scene: BattleScene) {
|
||||
}
|
||||
|
||||
function displayYesNoOptions(scene: BattleScene, resolve) {
|
||||
showEncounterText(scene, `${namespace}.option.1.ability_prompt`, null, 500, false);
|
||||
showEncounterText(scene, `${namespace}:option.1.ability_prompt`, null, 500, false);
|
||||
const fullOptions = [
|
||||
{
|
||||
label: i18next.t("menu:yes"),
|
||||
|
@ -30,7 +30,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import i18next from "i18next";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:dancingLessons";
|
||||
const namespace = "mysteryEncounters/dancingLessons";
|
||||
|
||||
// Fire form
|
||||
const BAILE_STYLE_BIOMES = [
|
||||
@ -99,12 +99,12 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
})
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
@ -155,7 +155,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
// Gets +1 to all stats except SPD on battle start
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.boss_enraged`);
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:option.1.boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF], 1));
|
||||
}
|
||||
}],
|
||||
@ -173,11 +173,11 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -202,11 +202,11 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -237,13 +237,13 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(DANCING_MOVES)) // Will set option3PrimaryName and option3PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.3.disabled_tooltip`,
|
||||
secondOptionPrompt: `${namespace}.option.3.select_prompt`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`,
|
||||
secondOptionPrompt: `${namespace}:option.3.select_prompt`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
text: `${namespace}:option.3.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -278,7 +278,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
}
|
||||
const meetsReqs = encounter.options[2].pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
return getEncounterText(scene, `${namespace}:invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -16,7 +16,7 @@ import { PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/mod
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** i18n namespace for encounter */
|
||||
const namespace = "mysteryEncounter:darkDeal";
|
||||
const namespace = "mysteryEncounters/darkDeal";
|
||||
|
||||
/** Exclude Ultra Beasts (inludes Cosmog/Solgaleo/Lunala/Necrozma), Paradox (includes Miraidon/Koraidon), Eternatus, and Mythicals */
|
||||
const excludedBosses = [
|
||||
@ -107,32 +107,32 @@ export const DarkDealEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
},
|
||||
])
|
||||
.withSceneWaveRangeRequirement(30, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1])
|
||||
.withScenePartySizeRequirement(2, 6, true) // Must have at least 2 pokemon in party
|
||||
.withCatchAllowed(true)
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.1.selected_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.1.selected_dialogue`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.option.1.selected_message`,
|
||||
text: `${namespace}:option.1.selected_message`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -187,12 +187,12 @@ export const DarkDealEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -204,7 +204,7 @@ export const DarkDealEncounter: MysteryEncounter =
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`
|
||||
text: `${namespace}:outro`
|
||||
}
|
||||
])
|
||||
.build();
|
||||
|
@ -19,7 +19,7 @@ import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:delibirdy";
|
||||
const namespace = "mysteryEncounters/delibirdy";
|
||||
|
||||
/** Berries only */
|
||||
const OPTION_2_ALLOWED_MODIFIERS = ["BerryModifier", "PokemonInstantReviveModifier"];
|
||||
@ -81,15 +81,15 @@ export const DelibirdyEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
}
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -108,11 +108,11 @@ export const DelibirdyEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withSceneMoneyRequirement(0, DELIBIRDY_MONEY_PRICE_MULTIPLIER) // Must have money to spawn
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -145,12 +145,12 @@ export const DelibirdyEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withPrimaryPokemonRequirement(new HeldItemRequirement(OPTION_2_ALLOWED_MODIFIERS))
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.option.2.select_prompt`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
secondOptionPrompt: `${namespace}:option.2.select_prompt`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -183,7 +183,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
||||
// If pokemon has valid item, it can be selected
|
||||
const meetsReqs = encounter.options[1].pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
return getEncounterText(scene, `${namespace}:invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -193,7 +193,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const modifier = encounter.misc.chosenModifier;
|
||||
const modifier: BerryModifier | HealingBoosterModifier = encounter.misc.chosenModifier;
|
||||
|
||||
// Give the player a Candy Jar if they gave a Berry, and a Healing Charm for Reviver Seed
|
||||
if (modifier instanceof BerryModifier) {
|
||||
@ -239,12 +239,12 @@ export const DelibirdyEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withPrimaryPokemonRequirement(new HeldItemRequirement(OPTION_3_DISALLOWED_MODIFIERS, 1, true))
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.option.3.select_prompt`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
secondOptionPrompt: `${namespace}:option.3.select_prompt`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
text: `${namespace}:option.3.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -277,7 +277,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
||||
// If pokemon has valid item, it can be selected
|
||||
const meetsReqs = encounter.options[2].pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
return getEncounterText(scene, `${namespace}:invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -14,7 +14,7 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** i18n namespace for encounter */
|
||||
const namespace = "mysteryEncounter:departmentStoreSale";
|
||||
const namespace = "mysteryEncounters/departmentStoreSale";
|
||||
|
||||
/**
|
||||
* Department Store Sale encounter.
|
||||
@ -43,21 +43,21 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
])
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose TMs
|
||||
@ -82,8 +82,8 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose Vitamins
|
||||
@ -106,8 +106,8 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose X Items
|
||||
@ -130,8 +130,8 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.4.label`,
|
||||
buttonTooltip: `${namespace}.option.4.tooltip`,
|
||||
buttonLabel: `${namespace}:option.4.label`,
|
||||
buttonTooltip: `${namespace}:option.4.tooltip`,
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose Pokeballs
|
||||
@ -158,7 +158,7 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter =
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
}
|
||||
])
|
||||
.build();
|
||||
|
@ -14,7 +14,7 @@ import i18next from "i18next";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:fieldTrip";
|
||||
const namespace = "mysteryEncounters/fieldTrip";
|
||||
|
||||
/**
|
||||
* Field Trip encounter.
|
||||
@ -44,24 +44,24 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
])
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.second_option_prompt`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
secondOptionPrompt: `${namespace}:second_option_prompt`,
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
@ -72,7 +72,7 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
label: move.getName(),
|
||||
handler: () => {
|
||||
// Pokemon and move selected
|
||||
encounter.setDialogueToken("moveCategory", i18next.t(`${namespace}.physical`));
|
||||
encounter.setDialogueToken("moveCategory", i18next.t(`${namespace}:physical`));
|
||||
pokemonAndMoveChosen(scene, pokemon, move, MoveCategory.PHYSICAL);
|
||||
return true;
|
||||
},
|
||||
@ -105,9 +105,9 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.second_option_prompt`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
secondOptionPrompt: `${namespace}:second_option_prompt`,
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
@ -118,7 +118,7 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
label: move.getName(),
|
||||
handler: () => {
|
||||
// Pokemon and move selected
|
||||
encounter.setDialogueToken("moveCategory", i18next.t(`${namespace}.special`));
|
||||
encounter.setDialogueToken("moveCategory", i18next.t(`${namespace}:special`));
|
||||
pokemonAndMoveChosen(scene, pokemon, move, MoveCategory.SPECIAL);
|
||||
return true;
|
||||
},
|
||||
@ -151,9 +151,9 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.second_option_prompt`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
secondOptionPrompt: `${namespace}:second_option_prompt`,
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
@ -164,7 +164,7 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
label: move.getName(),
|
||||
handler: () => {
|
||||
// Pokemon and move selected
|
||||
encounter.setDialogueToken("moveCategory", i18next.t(`${namespace}.status`));
|
||||
encounter.setDialogueToken("moveCategory", i18next.t(`${namespace}:status`));
|
||||
pokemonAndMoveChosen(scene, pokemon, move, MoveCategory.STATUS);
|
||||
return true;
|
||||
},
|
||||
@ -203,28 +203,28 @@ function pokemonAndMoveChosen(scene: BattleScene, pokemon: PlayerPokemon, move:
|
||||
if (!correctMove) {
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.incorrect`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}:incorrect`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.incorrect_exp`,
|
||||
text: `${namespace}:incorrect_exp`,
|
||||
},
|
||||
];
|
||||
setEncounterExp(scene, scene.getParty().map((p) => p.id), 50);
|
||||
} else {
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.correct`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}:correct`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.correct_exp`,
|
||||
text: `${namespace}:correct_exp`,
|
||||
},
|
||||
];
|
||||
setEncounterExp(scene, [pokemon.id], 100);
|
||||
|
@ -24,7 +24,7 @@ import { EncounterAnim } from "#enums/encounter-anims";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:fieryFallout";
|
||||
const namespace = "mysteryEncounters/fieryFallout";
|
||||
|
||||
/**
|
||||
* Damage percentage taken when suffering the heat.
|
||||
@ -49,7 +49,7 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
.withFleeAllowed(false)
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -122,16 +122,16 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -170,11 +170,11 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -197,7 +197,7 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
if (chosenPokemon.trySetStatus(StatusEffect.BURN)) {
|
||||
// Burn applied
|
||||
encounter.setDialogueToken("burnedPokemon", chosenPokemon.getNameToRender());
|
||||
queueEncounterMessage(scene, `${namespace}.option.2.target_burned`);
|
||||
queueEncounterMessage(scene, `${namespace}:option.2.target_burned`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,12 +211,12 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
.withPrimaryPokemonRequirement(new TypeRequirement(Type.FIRE, true, 1)) // Will set option3PrimaryName dialogue token automatically
|
||||
.withSecondaryPokemonRequirement(new TypeRequirement(Type.FIRE, true, 1)) // Will set option3SecondaryName dialogue token automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.3.disabled_tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
text: `${namespace}:option.3.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -251,6 +251,6 @@ function giveLeadPokemonCharcoal(scene: BattleScene) {
|
||||
const charcoal = generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.FIRE]) as AttackTypeBoosterModifierType;
|
||||
applyModifierTypeToPlayerPokemon(scene, leadPokemon, charcoal);
|
||||
scene.currentBattle.mysteryEncounter!.setDialogueToken("leadPokemon", leadPokemon.getNameToRender());
|
||||
queueEncounterMessage(scene, `${namespace}.found_charcoal`);
|
||||
queueEncounterMessage(scene, `${namespace}:found_charcoal`);
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:fightOrFlight";
|
||||
const namespace = "mysteryEncounters/fightOrFlight";
|
||||
|
||||
/**
|
||||
* Fight or Flight encounter.
|
||||
@ -48,7 +48,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
.withIntroSpriteConfigs([]) // Set in onInit()
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -67,7 +67,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
isBoss: true,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.stat_boost`);
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:option.1.stat_boost`);
|
||||
// Randomly boost 1 stat 2 stages
|
||||
// Cannot boost Spd, Acc, or Evasion
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [randSeedInt(4, 1)], 2));
|
||||
@ -120,16 +120,16 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -146,12 +146,12 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.2.disabled_tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`
|
||||
text: `${namespace}:option.2.selected`
|
||||
}
|
||||
]
|
||||
})
|
||||
@ -170,11 +170,11 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
text: `${namespace}:option.3.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -25,7 +25,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import { isPokemonValidForEncounterOptionSelection } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:funAndGames";
|
||||
const namespace = "mysteryEncounters/funAndGames";
|
||||
|
||||
/**
|
||||
* Fun and Games! encounter.
|
||||
@ -72,13 +72,13 @@ export const FunAndGamesEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
},
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
scene.loadBgm("mystery_encounter_fun_and_games", "mystery_encounter_fun_and_games.mp3");
|
||||
@ -93,11 +93,11 @@ export const FunAndGamesEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withSceneRequirement(new MoneyRequirement(0, 1.5)) // Cost equal to 1 Max Potion
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -112,7 +112,7 @@ export const FunAndGamesEncounter: MysteryEncounter =
|
||||
|
||||
// Only Pokemon that are not KOed/legal can be selected
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`);
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}:invalid_selection`);
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
@ -141,11 +141,11 @@ export const FunAndGamesEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -231,7 +231,7 @@ function handleLoseMinigame(scene: BattleScene) {
|
||||
scene.currentBattle.enemyParty = [];
|
||||
scene.currentBattle.mysteryEncounter!.doContinueEncounter = undefined;
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
await showEncounterText(scene, `${namespace}.ko`);
|
||||
await showEncounterText(scene, `${namespace}:ko`);
|
||||
const reviveCost = scene.getWaveMoneyAmount(1.5);
|
||||
updatePlayerMoney(scene, -reviveCost, true, false);
|
||||
}
|
||||
@ -257,19 +257,19 @@ function handleNextTurn(scene: BattleScene) {
|
||||
if (healthRatio < 0.03) {
|
||||
// Grand prize
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.MULTI_LENS], fillRemaining: false });
|
||||
resultMessageKey = `${namespace}.best_result`;
|
||||
resultMessageKey = `${namespace}:best_result`;
|
||||
} else if (healthRatio < 0.15) {
|
||||
// 2nd prize
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SCOPE_LENS], fillRemaining: false });
|
||||
resultMessageKey = `${namespace}.great_result`;
|
||||
resultMessageKey = `${namespace}:great_result`;
|
||||
} else if (healthRatio < 0.33) {
|
||||
// 3rd prize
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.WIDE_LENS], fillRemaining: false });
|
||||
resultMessageKey = `${namespace}.good_result`;
|
||||
resultMessageKey = `${namespace}:good_result`;
|
||||
} else {
|
||||
// No prize
|
||||
isHealPhase = true;
|
||||
resultMessageKey = `${namespace}.bad_result`;
|
||||
resultMessageKey = `${namespace}:bad_result`;
|
||||
}
|
||||
|
||||
// End the battle
|
||||
@ -279,7 +279,7 @@ function handleNextTurn(scene: BattleScene) {
|
||||
scene.currentBattle.mysteryEncounter!.doContinueEncounter = undefined;
|
||||
leaveEncounterWithoutBattle(scene, isHealPhase);
|
||||
// Must end the TurnInit phase prematurely so battle phases aren't added to queue
|
||||
queueEncounterMessage(scene, `${namespace}.end_game`);
|
||||
queueEncounterMessage(scene, `${namespace}:end_game`);
|
||||
queueEncounterMessage(scene, resultMessageKey);
|
||||
|
||||
// Skip remainder of TurnInitPhase
|
||||
@ -287,9 +287,9 @@ function handleNextTurn(scene: BattleScene) {
|
||||
} else {
|
||||
if (encounter.misc.turnsRemaining < 3) {
|
||||
// Display charging messages on turns that aren't the initial turn
|
||||
queueEncounterMessage(scene, `${namespace}.charging_continue`);
|
||||
queueEncounterMessage(scene, `${namespace}:charging_continue`);
|
||||
}
|
||||
queueEncounterMessage(scene, `${namespace}.turn_remaining_${encounter.misc.turnsRemaining}`);
|
||||
queueEncounterMessage(scene, `${namespace}:turn_remaining_${encounter.misc.turnsRemaining}`);
|
||||
encounter.misc.turnsRemaining--;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import { addPokemonDataToDexAndValidateAchievements } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:globalTradeSystem";
|
||||
const namespace = "mysteryEncounters/globalTradeSystem";
|
||||
|
||||
/** Base shiny chance of 512/65536 -> 1/128 odds, affected by events and Shiny Charms. Cannot exceed 1/16 odds. */
|
||||
const WONDER_TRADE_SHINY_CHANCE = 512;
|
||||
@ -93,12 +93,12 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
@ -133,9 +133,9 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withHasDexProgress(true)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.option.1.trade_options_prompt`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
secondOptionPrompt: `${namespace}:option.1.trade_options_prompt`,
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
@ -201,7 +201,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
// Show the trade animation
|
||||
await showTradeBackground(scene);
|
||||
await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon);
|
||||
await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000);
|
||||
await showEncounterText(scene, `${namespace}:trade_received`, null, 0, true, 4000);
|
||||
scene.playBgm(encounter.misc.bgmKey);
|
||||
await addPokemonDataToDexAndValidateAchievements(scene, newPlayerPokemon);
|
||||
await hideTradeBackground(scene);
|
||||
@ -216,8 +216,8 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withHasDexProgress(true)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
@ -309,7 +309,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
// Show the trade animation
|
||||
await showTradeBackground(scene);
|
||||
await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon);
|
||||
await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000);
|
||||
await showEncounterText(scene, `${namespace}:trade_received`, null, 0, true, 4000);
|
||||
scene.playBgm(encounter.misc.bgmKey);
|
||||
await addPokemonDataToDexAndValidateAchievements(scene, newPlayerPokemon);
|
||||
await hideTradeBackground(scene);
|
||||
@ -323,9 +323,9 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.option.3.trade_options_prompt`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
secondOptionPrompt: `${namespace}:option.3.trade_options_prompt`,
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
@ -355,7 +355,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
return it.isTransferable;
|
||||
}).length > 0;
|
||||
if (!meetsReqs) {
|
||||
return getEncounterText(scene, `${namespace}.option.3.invalid_selection`) ?? null;
|
||||
return getEncounterText(scene, `${namespace}:option.3.invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -403,18 +403,18 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
// Generate a trainer name
|
||||
const traderName = generateRandomTraderName();
|
||||
encounter.setDialogueToken("tradeTrainerName", traderName.trim());
|
||||
await showEncounterText(scene, `${namespace}.item_trade_selected`);
|
||||
await showEncounterText(scene, `${namespace}:item_trade_selected`);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.4.label`,
|
||||
buttonTooltip: `${namespace}.option.4.tooltip`,
|
||||
buttonLabel: `${namespace}:option.4.label`,
|
||||
buttonTooltip: `${namespace}:option.4.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.4.selected`,
|
||||
text: `${namespace}:option.4.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -628,10 +628,10 @@ function doPokemonTradeSequence(scene: BattleScene, tradedPokemon: PlayerPokemon
|
||||
duration: 500,
|
||||
onComplete: async () => {
|
||||
scene.fadeOutBgm(1000, false);
|
||||
await showEncounterText(scene, `${namespace}.pokemon_trade_selected`);
|
||||
await showEncounterText(scene, `${namespace}:pokemon_trade_selected`);
|
||||
tradedPokemon.cry();
|
||||
scene.playBgm("evolution");
|
||||
await showEncounterText(scene, `${namespace}.pokemon_trade_goodbye`);
|
||||
await showEncounterText(scene, `${namespace}:pokemon_trade_goodbye`);
|
||||
|
||||
tradedPokeball.setAlpha(0);
|
||||
tradedPokeball.setVisible(true);
|
||||
|
@ -21,7 +21,7 @@ const OPTION_2_REQUIRED_MOVE = Moves.FLY;
|
||||
*/
|
||||
const DAMAGE_PERCENTAGE: number = 25;
|
||||
/** The i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:lostAtSea";
|
||||
const namespace = "mysteryEncounters/lostAtSea";
|
||||
|
||||
/**
|
||||
* Lost at sea encounter.
|
||||
@ -40,7 +40,7 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
y: 3,
|
||||
},
|
||||
])
|
||||
.withIntroDialogue([{ text: `${namespace}.intro` }])
|
||||
.withIntroDialogue([{ text: `${namespace}:intro` }])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
@ -50,22 +50,22 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOption(
|
||||
// Option 1: Use a (non fainted) pokemon that can learn Surf to guide you back/
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withPokemonCanLearnMoveRequirement(OPTION_1_REQUIRED_MOVE)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
disabledButtonLabel: `${namespace}.option.1.label_disabled`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.1.tooltip_disabled`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
disabledButtonLabel: `${namespace}:option.1.label_disabled`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.1.tooltip_disabled`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -78,13 +78,13 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withPokemonCanLearnMoveRequirement(OPTION_2_REQUIRED_MOVE)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
disabledButtonLabel: `${namespace}.option.2.label_disabled`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.2.tooltip_disabled`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
disabledButtonLabel: `${namespace}:option.2.label_disabled`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.2.tooltip_disabled`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -94,11 +94,11 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
.withSimpleOption(
|
||||
// Option 3: Wander aimlessly
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
text: `${namespace}:option.3.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -118,7 +118,7 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
},
|
||||
])
|
||||
.build();
|
||||
|
@ -20,7 +20,7 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:mysteriousChallengers";
|
||||
const namespace = "mysteryEncounters/mysteriousChallengers";
|
||||
|
||||
/**
|
||||
* Mysterious Challengers encounter.
|
||||
@ -34,7 +34,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
.withIntroSpriteConfigs([]) // These are set in onInit()
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -125,16 +125,16 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -155,11 +155,11 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -180,11 +180,11 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -208,7 +208,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
},
|
||||
])
|
||||
.build();
|
||||
|
@ -16,7 +16,7 @@ import { GameOverPhase } from "#app/phases/game-over-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** i18n namespace for encounter */
|
||||
const namespace = "mysteryEncounter:mysteriousChest";
|
||||
const namespace = "mysteryEncounters/mysteriousChest";
|
||||
|
||||
const RAND_LENGTH = 100;
|
||||
const TRAP_PERCENT = 35;
|
||||
@ -58,12 +58,12 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
@ -96,11 +96,11 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -141,7 +141,7 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
||||
],
|
||||
});
|
||||
// Display result message then proceed to rewards
|
||||
queueEncounterMessage(scene, `${namespace}.option.1.normal`);
|
||||
queueEncounterMessage(scene, `${namespace}:option.1.normal`);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
} else if (roll >= RAND_LENGTH - COMMON_REWARDS_PERCENT - ULTRA_REWARDS_PERCENT) {
|
||||
// Choose between 3 ULTRA tier items (30%)
|
||||
@ -153,19 +153,19 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
||||
],
|
||||
});
|
||||
// Display result message then proceed to rewards
|
||||
queueEncounterMessage(scene, `${namespace}.option.1.good`);
|
||||
queueEncounterMessage(scene, `${namespace}:option.1.good`);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
} else if (roll >= RAND_LENGTH - COMMON_REWARDS_PERCENT - ULTRA_REWARDS_PERCENT - ROGUE_REWARDS_PERCENT) {
|
||||
// Choose between 2 ROGUE tier items (10%)
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE] });
|
||||
// Display result message then proceed to rewards
|
||||
queueEncounterMessage(scene, `${namespace}.option.1.great`);
|
||||
queueEncounterMessage(scene, `${namespace}:option.1.great`);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
} else if (roll >= RAND_LENGTH - COMMON_REWARDS_PERCENT - ULTRA_REWARDS_PERCENT - ROGUE_REWARDS_PERCENT - MASTER_REWARDS_PERCENT) {
|
||||
// Choose 1 MASTER tier item (5%)
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.MASTER] });
|
||||
// Display result message then proceed to rewards
|
||||
queueEncounterMessage(scene, `${namespace}.option.1.amazing`);
|
||||
queueEncounterMessage(scene, `${namespace}:option.1.amazing`);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
} else {
|
||||
// Your highest level unfainted Pokemon gets OHKO. Start battle against a Gimmighoul (35%)
|
||||
@ -173,7 +173,7 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
||||
koPlayerPokemon(scene, highestLevelPokemon);
|
||||
|
||||
encounter.setDialogueToken("pokeName", highestLevelPokemon.getNameToRender());
|
||||
await showEncounterText(scene, `${namespace}.option.1.bad`);
|
||||
await showEncounterText(scene, `${namespace}:option.1.bad`);
|
||||
|
||||
// Handle game over edge case
|
||||
const allowedPokemon = scene.getParty().filter(p => p.isAllowedInBattle());
|
||||
@ -193,11 +193,11 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -15,7 +15,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import { isPokemonValidForEncounterOptionSelection } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:partTimer";
|
||||
const namespace = "mysteryEncounters/partTimer";
|
||||
|
||||
/**
|
||||
* Part Timer encounter.
|
||||
@ -45,11 +45,11 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -69,17 +69,17 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOption(MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`
|
||||
text: `${namespace}:option.1.selected`
|
||||
}
|
||||
]
|
||||
})
|
||||
@ -118,7 +118,7 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
|
||||
// Only Pokemon non-KOd pokemon can be selected
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`);
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}:invalid_selection`);
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
@ -132,14 +132,14 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
|
||||
// Give money and do dialogue
|
||||
if (moneyMultiplier > 2.5) {
|
||||
await showEncounterDialogue(scene, `${namespace}.job_complete_good`, `${namespace}.speaker`);
|
||||
await showEncounterDialogue(scene, `${namespace}:job_complete_good`, `${namespace}:speaker`);
|
||||
} else {
|
||||
await showEncounterDialogue(scene, `${namespace}.job_complete_bad`, `${namespace}.speaker`);
|
||||
await showEncounterDialogue(scene, `${namespace}:job_complete_bad`, `${namespace}:speaker`);
|
||||
}
|
||||
const moneyChange = scene.getWaveMoneyAmount(moneyMultiplier);
|
||||
updatePlayerMoney(scene, moneyChange, true, false);
|
||||
await showEncounterText(scene, i18next.t("mysteryEncounterMessages:receive_money", { amount: moneyChange }));
|
||||
await showEncounterText(scene, `${namespace}.pokemon_tired`);
|
||||
await showEncounterText(scene, `${namespace}:pokemon_tired`);
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true });
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
@ -149,11 +149,11 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
.withOption(MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`
|
||||
text: `${namespace}:option.2.selected`
|
||||
}
|
||||
]
|
||||
})
|
||||
@ -195,7 +195,7 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
|
||||
// Only Pokemon non-KOd pokemon can be selected
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`);
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}:invalid_selection`);
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
@ -209,14 +209,14 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
|
||||
// Give money and do dialogue
|
||||
if (moneyMultiplier > 2.5) {
|
||||
await showEncounterDialogue(scene, `${namespace}.job_complete_good`, `${namespace}.speaker`);
|
||||
await showEncounterDialogue(scene, `${namespace}:job_complete_good`, `${namespace}:speaker`);
|
||||
} else {
|
||||
await showEncounterDialogue(scene, `${namespace}.job_complete_bad`, `${namespace}.speaker`);
|
||||
await showEncounterDialogue(scene, `${namespace}:job_complete_bad`, `${namespace}:speaker`);
|
||||
}
|
||||
const moneyChange = scene.getWaveMoneyAmount(moneyMultiplier);
|
||||
updatePlayerMoney(scene, moneyChange, true, false);
|
||||
await showEncounterText(scene, i18next.t("mysteryEncounterMessages:receive_money", { amount: moneyChange }));
|
||||
await showEncounterText(scene, `${namespace}.pokemon_tired`);
|
||||
await showEncounterText(scene, `${namespace}:pokemon_tired`);
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true });
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
@ -228,12 +228,12 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(CHARMING_MOVES)) // Will set option3PrimaryName and option3PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.3.disabled_tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
text: `${namespace}:option.3.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -264,11 +264,11 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
await transitionMysteryEncounterIntroVisuals(scene, false, false);
|
||||
|
||||
// Give money and do dialogue
|
||||
await showEncounterDialogue(scene, `${namespace}.job_complete_good`, `${namespace}.speaker`);
|
||||
await showEncounterDialogue(scene, `${namespace}:job_complete_good`, `${namespace}:speaker`);
|
||||
const moneyChange = scene.getWaveMoneyAmount(2.5);
|
||||
updatePlayerMoney(scene, moneyChange, true, false);
|
||||
await showEncounterText(scene, i18next.t("mysteryEncounterMessages:receive_money", { amount: moneyChange }));
|
||||
await showEncounterText(scene, `${namespace}.pokemon_tired`);
|
||||
await showEncounterText(scene, `${namespace}:pokemon_tired`);
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true });
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
@ -277,8 +277,8 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.outro`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:outro`,
|
||||
}
|
||||
])
|
||||
.build();
|
||||
|
@ -21,7 +21,7 @@ import { SummonPhase } from "#app/phases/summon-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:safariZone";
|
||||
const namespace = "mysteryEncounters/safariZone";
|
||||
|
||||
const TRAINER_THROW_ANIMATION_TIMES = [512, 184, 768];
|
||||
|
||||
@ -51,12 +51,12 @@ export const SafariZoneEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
scene.currentBattle.mysteryEncounter?.setDialogueToken("numEncounters", NUM_SAFARI_ENCOUNTERS.toString());
|
||||
return true;
|
||||
@ -65,11 +65,11 @@ export const SafariZoneEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withSceneRequirement(new MoneyRequirement(0, SAFARI_MONEY_MULTIPLIER)) // Cost equal to 1 Max Revive
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -98,11 +98,11 @@ export const SafariZoneEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -133,11 +133,11 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.safari.1.label`,
|
||||
buttonTooltip: `${namespace}.safari.1.tooltip`,
|
||||
buttonLabel: `${namespace}:safari.1.label`,
|
||||
buttonTooltip: `${namespace}:safari.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.safari.1.selected`,
|
||||
text: `${namespace}:safari.1.selected`,
|
||||
}
|
||||
],
|
||||
})
|
||||
@ -168,11 +168,11 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.safari.2.label`,
|
||||
buttonTooltip: `${namespace}.safari.2.tooltip`,
|
||||
buttonLabel: `${namespace}:safari.2.label`,
|
||||
buttonTooltip: `${namespace}:safari.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.safari.2.selected`,
|
||||
text: `${namespace}:safari.2.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -186,9 +186,9 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [
|
||||
// 80% chance to increase flee stage +1
|
||||
const fleeChangeResult = tryChangeFleeStage(scene, 1, 8);
|
||||
if (!fleeChangeResult) {
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.busy_eating`) ?? "", null, 1000, false );
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}:safari.busy_eating`) ?? "", null, 1000, false );
|
||||
} else {
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.eating`) ?? "", null, 1000, false);
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}:safari.eating`) ?? "", null, 1000, false);
|
||||
}
|
||||
|
||||
await doEndTurn(scene, 1);
|
||||
@ -198,11 +198,11 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.safari.3.label`,
|
||||
buttonTooltip: `${namespace}.safari.3.tooltip`,
|
||||
buttonLabel: `${namespace}:safari.3.label`,
|
||||
buttonTooltip: `${namespace}:safari.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.safari.3.selected`,
|
||||
text: `${namespace}:safari.3.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -215,9 +215,9 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [
|
||||
// 80% chance to decrease catch stage -1
|
||||
const catchChangeResult = tryChangeCatchStage(scene, -1, 8);
|
||||
if (!catchChangeResult) {
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.beside_itself_angry`) ?? "", null, 1000, false );
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}:safari.beside_itself_angry`) ?? "", null, 1000, false );
|
||||
} else {
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}.safari.angry`) ?? "", null, 1000, false );
|
||||
await showEncounterText(scene, getEncounterText(scene, `${namespace}:safari.angry`) ?? "", null, 1000, false );
|
||||
}
|
||||
|
||||
await doEndTurn(scene, 2);
|
||||
@ -227,8 +227,8 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.safari.4.label`,
|
||||
buttonTooltip: `${namespace}.safari.4.tooltip`,
|
||||
buttonLabel: `${namespace}:safari.4.label`,
|
||||
buttonTooltip: `${namespace}:safari.4.tooltip`,
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Flee option
|
||||
@ -253,7 +253,7 @@ async function summonSafariPokemon(scene: BattleScene) {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
// Message pokemon remaining
|
||||
encounter.setDialogueToken("remainingCount", encounter.misc.safariPokemonRemaining);
|
||||
scene.queueMessage(getEncounterText(scene, `${namespace}.safari.remaining_count`) ?? "", null, true);
|
||||
scene.queueMessage(getEncounterText(scene, `${namespace}:safari.remaining_count`) ?? "", null, true);
|
||||
|
||||
// Generate pokemon using safariPokemonRemaining so they are always the same pokemon no matter how many turns are taken
|
||||
// Safari pokemon roll twice on shiny and HA chances, but are otherwise normal
|
||||
@ -518,7 +518,7 @@ async function doEndTurn(scene: BattleScene, cursorIndex: number) {
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
}
|
||||
} else {
|
||||
scene.queueMessage(getEncounterText(scene, `${namespace}.safari.watching`) ?? "", 0, null, 1000);
|
||||
scene.queueMessage(getEncounterText(scene, `${namespace}:safari.watching`) ?? "", 0, null, 1000);
|
||||
initSubsequentOptionSelect(scene, { overrideOptions: safariZoneGameOptions, startingCursorIndex: cursorIndex, hideDescription: true });
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import i18next from "i18next";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:shadyVitaminDealer";
|
||||
const namespace = "mysteryEncounters/shadyVitaminDealer";
|
||||
|
||||
const VITAMIN_DEALER_CHEAP_PRICE_MULTIPLIER = 1.5;
|
||||
const VITAMIN_DEALER_EXPENSIVE_PRICE_MULTIPLIER = 3.5;
|
||||
@ -55,26 +55,26 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withSceneMoneyRequirement(0, VITAMIN_DEALER_CHEAP_PRICE_MULTIPLIER)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -103,7 +103,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
return i18next.t("partyUiHandler:cantBeUsed", { pokemonName: pokemon.getNameToRender() }) ?? null;
|
||||
}
|
||||
if (!encounter.pokemonMeetsPrimaryRequirements(scene, pokemon)) {
|
||||
return getEncounterText(scene, `${namespace}.invalid_selection`) ?? null;
|
||||
return getEncounterText(scene, `${namespace}:invalid_selection`) ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -139,7 +139,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
|
||||
chosenPokemon.nature = newNature;
|
||||
encounter.setDialogueToken("newNature", getNatureName(newNature));
|
||||
queueEncounterMessage(scene, `${namespace}.cheap_side_effects`);
|
||||
queueEncounterMessage(scene, `${namespace}:cheap_side_effects`);
|
||||
setEncounterExp(scene, [chosenPokemon.id], 100);
|
||||
chosenPokemon.updateInfo();
|
||||
})
|
||||
@ -150,11 +150,11 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withSceneMoneyRequirement(0, VITAMIN_DEALER_EXPENSIVE_PRICE_MULTIPLIER)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -178,7 +178,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
|
||||
// Only Pokemon that can gain benefits are unfainted
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`);
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}:invalid_selection`);
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
@ -200,7 +200,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const chosenPokemon = encounter.misc.chosenPokemon;
|
||||
|
||||
queueEncounterMessage(scene, `${namespace}.no_bad_effects`);
|
||||
queueEncounterMessage(scene, `${namespace}:no_bad_effects`);
|
||||
setEncounterExp(scene, [chosenPokemon.id], 100);
|
||||
|
||||
chosenPokemon.updateInfo();
|
||||
@ -209,12 +209,12 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
speaker: `${namespace}.speaker`
|
||||
text: `${namespace}:option.3.selected`,
|
||||
speaker: `${namespace}:speaker`
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -21,7 +21,7 @@ import { BerryType } from "#enums/berry-type";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
|
||||
/** i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:slumberingSnorlax";
|
||||
const namespace = "mysteryEncounters/slumberingSnorlax";
|
||||
|
||||
/**
|
||||
* Sleeping Snorlax encounter.
|
||||
@ -48,7 +48,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -88,16 +88,16 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -123,11 +123,11 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -135,7 +135,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
// Fall asleep waiting for Snorlax
|
||||
// Full heal party
|
||||
scene.unshiftPhase(new PartyHealPhase(scene, true));
|
||||
queueEncounterMessage(scene, `${namespace}.option.2.rest_result`);
|
||||
queueEncounterMessage(scene, `${namespace}:option.2.rest_result`);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
)
|
||||
@ -144,12 +144,12 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES))
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.3.disabled_tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`
|
||||
text: `${namespace}:option.3.selected`
|
||||
}
|
||||
]
|
||||
})
|
||||
|
@ -23,7 +23,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import { getEncounterPokemonLevelForWave, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:teleportingHijinks";
|
||||
const namespace = "mysteryEncounters/teleportingHijinks";
|
||||
|
||||
const MONEY_COST_MULTIPLIER = 1.75;
|
||||
const BIOME_CANDIDATES = [Biome.SPACE, Biome.FAIRY_CAVE, Biome.LABORATORY, Biome.ISLAND, Biome.WASTELAND, Biome.DOJO];
|
||||
@ -55,12 +55,12 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const price = scene.getWaveMoneyAmount(MONEY_COST_MULTIPLIER);
|
||||
@ -76,11 +76,11 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withSceneMoneyRequirement(0, MONEY_COST_MULTIPLIER) // Must be able to pay teleport cost
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
}
|
||||
],
|
||||
})
|
||||
@ -100,12 +100,12 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPokemonTypeRequirement(MACHINE_INTERFACING_TYPES, true, 1) // Must have Steel or Electric type
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.2.disabled_tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
}
|
||||
],
|
||||
})
|
||||
@ -119,11 +119,11 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`,
|
||||
text: `${namespace}:option.3.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -162,10 +162,10 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) {
|
||||
const newBiome = filteredBiomes[randSeedInt(filteredBiomes.length)];
|
||||
|
||||
// Show dialogue and transition biome
|
||||
await showEncounterText(scene, `${namespace}.transport`);
|
||||
await showEncounterText(scene, `${namespace}:transport`);
|
||||
await Promise.all([animateBiomeChange(scene, newBiome), transitionMysteryEncounterIntroVisuals(scene)]);
|
||||
scene.playBgm();
|
||||
await showEncounterText(scene, `${namespace}.attacked`);
|
||||
await showEncounterText(scene, `${namespace}:attacked`);
|
||||
|
||||
// Init enemy
|
||||
const level = getEncounterPokemonLevelForWave(scene, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER);
|
||||
@ -186,7 +186,7 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) {
|
||||
isBoss: true,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.boss_enraged`);
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
|
||||
}
|
||||
}],
|
||||
|
@ -10,7 +10,8 @@ import { Biome } from "#enums/biome";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import i18next from "i18next";
|
||||
import { Species } from "#enums/species";
|
||||
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { Nature } from "#enums/nature";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
@ -26,7 +27,7 @@ import { Type } from "#app/data/type";
|
||||
import { getPokeballTintColor } from "#app/data/pokeball";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:expertPokemonBreeder";
|
||||
const namespace = "mysteryEncounters/theExpertPokemonBreeder";
|
||||
|
||||
const trainerNameKey = "trainerNames:expert_pokemon_breeder";
|
||||
|
||||
@ -85,11 +86,11 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
.withIntroSpriteConfigs([]) // These are set in onInit()
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -138,45 +139,45 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
|
||||
// Dialogue and egg calcs for Pokemon 1
|
||||
const [pokemon1CommonEggs, pokemon1RareEggs] = calculateEggRewardsForPokemon(pokemon1);
|
||||
let pokemon1Tooltip = getEncounterText(scene, `${namespace}.option.1.tooltip_base`)!;
|
||||
let pokemon1Tooltip = getEncounterText(scene, `${namespace}:option.1.tooltip_base`)!;
|
||||
if (pokemon1RareEggs > 0) {
|
||||
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon1RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||
pokemon1Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon1RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||
pokemon1Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText });
|
||||
encounter.setDialogueToken("pokemon1RareEggs", eggsText);
|
||||
}
|
||||
if (pokemon1CommonEggs > 0) {
|
||||
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon1CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||
pokemon1Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon1CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||
pokemon1Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText });
|
||||
encounter.setDialogueToken("pokemon1CommonEggs", eggsText);
|
||||
}
|
||||
encounter.options[0].dialogue!.buttonTooltip = pokemon1Tooltip;
|
||||
|
||||
// Dialogue and egg calcs for Pokemon 2
|
||||
const [pokemon2CommonEggs, pokemon2RareEggs] = calculateEggRewardsForPokemon(pokemon2);
|
||||
let pokemon2Tooltip = getEncounterText(scene, `${namespace}.option.2.tooltip_base`)!;
|
||||
let pokemon2Tooltip = getEncounterText(scene, `${namespace}:option.2.tooltip_base`)!;
|
||||
if (pokemon2RareEggs > 0) {
|
||||
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon2RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||
pokemon2Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon2RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||
pokemon2Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText });
|
||||
encounter.setDialogueToken("pokemon2RareEggs", eggsText);
|
||||
}
|
||||
if (pokemon2CommonEggs > 0) {
|
||||
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon2CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||
pokemon2Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon2CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||
pokemon2Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText });
|
||||
encounter.setDialogueToken("pokemon1CommonEggs", eggsText);
|
||||
}
|
||||
encounter.options[1].dialogue!.buttonTooltip = pokemon2Tooltip;
|
||||
|
||||
// Dialogue and egg calcs for Pokemon 3
|
||||
const [pokemon3CommonEggs, pokemon3RareEggs] = calculateEggRewardsForPokemon(pokemon3);
|
||||
let pokemon3Tooltip = getEncounterText(scene, `${namespace}.option.3.tooltip_base`)!;
|
||||
let pokemon3Tooltip = getEncounterText(scene, `${namespace}:option.3.tooltip_base`)!;
|
||||
if (pokemon3RareEggs > 0) {
|
||||
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon3RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||
pokemon3Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon3RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||
pokemon3Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText });
|
||||
encounter.setDialogueToken("pokemon3RareEggs", eggsText);
|
||||
}
|
||||
if (pokemon3CommonEggs > 0) {
|
||||
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon3CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||
pokemon3Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon3CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||
pokemon3Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText });
|
||||
encounter.setDialogueToken("pokemon3CommonEggs", eggsText);
|
||||
}
|
||||
encounter.options[2].dialogue!.buttonTooltip = pokemon3Tooltip;
|
||||
@ -195,18 +196,18 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
selected: [
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -228,17 +229,17 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
encounter.dialogue.outro = [
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
},
|
||||
];
|
||||
if (encounter.dialogueTokens.hasOwnProperty("pokemon1CommonEggs")) {
|
||||
encounter.dialogue.outro.push({
|
||||
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon1CommonEggs"] }),
|
||||
text: i18next.t(`${namespace}:gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon1CommonEggs"] }),
|
||||
});
|
||||
}
|
||||
if (encounter.dialogueTokens.hasOwnProperty("pokemon1RareEggs")) {
|
||||
encounter.dialogue.outro.push({
|
||||
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon1RareEggs"] }),
|
||||
text: i18next.t(`${namespace}:gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon1RareEggs"] }),
|
||||
});
|
||||
}
|
||||
|
||||
@ -254,11 +255,11 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
selected: [
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -280,17 +281,17 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
encounter.dialogue.outro = [
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
},
|
||||
];
|
||||
if (encounter.dialogueTokens.hasOwnProperty("pokemon2CommonEggs")) {
|
||||
encounter.dialogue.outro.push({
|
||||
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon2CommonEggs"] }),
|
||||
text: i18next.t(`${namespace}:gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon2CommonEggs"] }),
|
||||
});
|
||||
}
|
||||
if (encounter.dialogueTokens.hasOwnProperty("pokemon2RareEggs")) {
|
||||
encounter.dialogue.outro.push({
|
||||
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon2RareEggs"] }),
|
||||
text: i18next.t(`${namespace}:gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon2RareEggs"] }),
|
||||
});
|
||||
}
|
||||
|
||||
@ -306,11 +307,11 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
selected: [
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -332,17 +333,17 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
encounter.dialogue.outro = [
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
},
|
||||
];
|
||||
if (encounter.dialogueTokens.hasOwnProperty("pokemon3CommonEggs")) {
|
||||
encounter.dialogue.outro.push({
|
||||
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon3CommonEggs"] }),
|
||||
text: i18next.t(`${namespace}:gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon3CommonEggs"] }),
|
||||
});
|
||||
}
|
||||
if (encounter.dialogueTokens.hasOwnProperty("pokemon3RareEggs")) {
|
||||
encounter.dialogue.outro.push({
|
||||
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon3RareEggs"] }),
|
||||
text: i18next.t(`${namespace}:gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon3RareEggs"] }),
|
||||
});
|
||||
}
|
||||
|
||||
@ -357,7 +358,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
.withOutroDialogue([
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
},
|
||||
])
|
||||
.build();
|
||||
@ -374,7 +375,7 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
trainerType: TrainerType.EXPERT_POKEMON_BREEDER,
|
||||
pokemonConfigs: [
|
||||
{
|
||||
nickname: i18next.t(`${namespace}.cleffa_1_nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName() }),
|
||||
nickname: i18next.t(`${namespace}:cleffa_1_nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName() }),
|
||||
species: getPokemonSpecies(cleffaSpecies),
|
||||
isBoss: false,
|
||||
abilityIndex: 1, // Magic Guard
|
||||
@ -394,7 +395,7 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
if (scene.arena.biomeType === Biome.SPACE) {
|
||||
// All 3 members always Cleffa line, but different configs
|
||||
baseConfig.pokemonConfigs!.push({
|
||||
nickname: i18next.t(`${namespace}.cleffa_2_nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName() }),
|
||||
nickname: i18next.t(`${namespace}:cleffa_2_nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName() }),
|
||||
species: getPokemonSpecies(cleffaSpecies),
|
||||
isBoss: false,
|
||||
abilityIndex: 1, // Magic Guard
|
||||
@ -405,7 +406,7 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
ivs: [31, 31, 31, 31, 31, 31]
|
||||
},
|
||||
{
|
||||
nickname: i18next.t(`${namespace}.cleffa_3_nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName() }),
|
||||
nickname: i18next.t(`${namespace}:cleffa_3_nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName() }),
|
||||
species: getPokemonSpecies(cleffaSpecies),
|
||||
isBoss: false,
|
||||
abilityIndex: 2, // Friend Guard / Unaware
|
||||
@ -454,8 +455,8 @@ function calculateEggRewardsForPokemon(pokemon: PlayerPokemon): [number, number]
|
||||
const rootSpecies = pokemon.species.getRootSpeciesId();
|
||||
let pointsFromStarterTier = 0;
|
||||
// 2 points for every 1 below 7 that the pokemon's starter tier is (max 12, min 0)
|
||||
if (speciesStarters.hasOwnProperty(rootSpecies)) {
|
||||
const starterTier = speciesStarters[rootSpecies];
|
||||
if (speciesStarterCosts.hasOwnProperty(rootSpecies)) {
|
||||
const starterTier = speciesStarterCosts[rootSpecies];
|
||||
pointsFromStarterTier = Math.min(Math.max(Math.floor(7 - starterTier) * 2, 0), 12);
|
||||
}
|
||||
|
||||
@ -471,7 +472,7 @@ function calculateEggRewardsForPokemon(pokemon: PlayerPokemon): [number, number]
|
||||
}
|
||||
|
||||
function getEggOptions(scene: BattleScene, commonEggs: number, rareEggs: number) {
|
||||
const eggDescription = i18next.t(`${namespace}.title`) + ":\n" + i18next.t(trainerNameKey);
|
||||
const eggDescription = i18next.t(`${namespace}:title`) + ":\n" + i18next.t(trainerNameKey);
|
||||
const eggOptions: IEggOptions[] = [];
|
||||
|
||||
if (commonEggs > 0) {
|
||||
@ -540,7 +541,7 @@ function onGameOver(scene: BattleScene) {
|
||||
encounter.dialogue.outro = [
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
text: `${namespace}.outro_failed`,
|
||||
text: `${namespace}:outro_failed`,
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -5,7 +5,8 @@ import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||
import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||
import { catchPokemon, getRandomSpeciesByStarterTier, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { Species } from "#enums/species";
|
||||
import { PokeballType } from "#app/data/pokeball";
|
||||
import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
|
||||
@ -18,7 +19,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:pokemonSalesman";
|
||||
const namespace = "mysteryEncounters/thePokemonSalesman";
|
||||
|
||||
const MAX_POKEMON_PRICE_MULTIPLIER = 4;
|
||||
|
||||
@ -45,16 +46,16 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
@ -88,15 +89,15 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
||||
isPokemon: true
|
||||
});
|
||||
|
||||
const starterTier = speciesStarters[species.speciesId];
|
||||
const starterTier = speciesStarterCosts[species.speciesId];
|
||||
// Prices decrease by starter tier less than 5, but only reduces cost by half at max
|
||||
let priceMultiplier = MAX_POKEMON_PRICE_MULTIPLIER * (Math.max(starterTier, 2.5) / 5);
|
||||
if (pokemon.shiny) {
|
||||
// Always max price for shiny (flip HA back to normal), and add special messaging
|
||||
priceMultiplier = MAX_POKEMON_PRICE_MULTIPLIER;
|
||||
pokemon.abilityIndex = 0;
|
||||
encounter.dialogue.encounterOptionsDialogue!.description = `${namespace}.description_shiny`;
|
||||
encounter.options[0].dialogue!.buttonTooltip = `${namespace}.option.1.tooltip_shiny`;
|
||||
encounter.dialogue.encounterOptionsDialogue!.description = `${namespace}:description_shiny`;
|
||||
encounter.options[0].dialogue!.buttonTooltip = `${namespace}:option.1.tooltip_shiny`;
|
||||
}
|
||||
const price = scene.getWaveMoneyAmount(priceMultiplier);
|
||||
encounter.setDialogueToken("purchasePokemon", pokemon.getNameToRender());
|
||||
@ -116,11 +117,11 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
||||
.withHasDexProgress(true)
|
||||
.withSceneMoneyRequirement(0, MAX_POKEMON_PRICE_MULTIPLIER) // Wave scaling money multiplier of 2
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected_message`,
|
||||
text: `${namespace}:option.1.selected_message`,
|
||||
}
|
||||
],
|
||||
})
|
||||
@ -133,7 +134,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
||||
updatePlayerMoney(scene, -price, true, false);
|
||||
|
||||
// Show dialogue
|
||||
await showEncounterDialogue(scene, `${namespace}.option.1.selected_dialogue`, `${namespace}.speaker`);
|
||||
await showEncounterDialogue(scene, `${namespace}:option.1.selected_dialogue`, `${namespace}:speaker`);
|
||||
await transitionMysteryEncounterIntroVisuals(scene);
|
||||
|
||||
// "Catch" purchased pokemon
|
||||
@ -147,11 +148,11 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -20,7 +20,7 @@ import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:theStrongStuff";
|
||||
const namespace = "mysteryEncounters/theStrongStuff";
|
||||
|
||||
// Halved for HP stat
|
||||
const HIGH_BST_REDUCTION_VALUE = 15;
|
||||
@ -64,7 +64,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
||||
]) // Set in onInit()
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -102,7 +102,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
||||
],
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.2.stat_boost`);
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:option.2.stat_boost`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.DEF, Stat.SPDEF], 2));
|
||||
}
|
||||
}
|
||||
@ -117,16 +117,16 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`
|
||||
text: `${namespace}:option.1.selected`
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -159,11 +159,11 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
||||
|
||||
encounter.setDialogueToken("reductionValue", HIGH_BST_REDUCTION_VALUE.toString());
|
||||
encounter.setDialogueToken("increaseValue", BST_INCREASE_VALUE.toString());
|
||||
await showEncounterText(scene, `${namespace}.option.1.selected_2`, null, undefined, true);
|
||||
await showEncounterText(scene, `${namespace}:option.1.selected_2`, null, undefined, true);
|
||||
|
||||
encounter.dialogue.outro = [
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
}
|
||||
];
|
||||
setEncounterRewards(scene, { fillRemaining: true });
|
||||
@ -173,11 +173,11 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -25,7 +25,7 @@ import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:theWinstrateChallenge";
|
||||
const namespace = "mysteryEncounters/theWinstrateChallenge";
|
||||
|
||||
/**
|
||||
* The Winstrate Challenge encounter.
|
||||
@ -74,11 +74,11 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
},
|
||||
])
|
||||
.withAutoHideIntroVisuals(false)
|
||||
@ -94,17 +94,17 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter =
|
||||
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.1.selected`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -119,12 +119,12 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.option.2.selected`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -142,7 +142,7 @@ async function spawnNextTrainerOrEndEncounter(scene: BattleScene) {
|
||||
const nextConfig = encounter.enemyPartyConfigs.pop();
|
||||
if (!nextConfig) {
|
||||
await transitionMysteryEncounterIntroVisuals(scene, false, false);
|
||||
await showEncounterDialogue(scene, `${namespace}.victory`, `${namespace}.speaker`);
|
||||
await showEncounterDialogue(scene, `${namespace}:victory`, `${namespace}:speaker`);
|
||||
|
||||
// Give 10x Voucher
|
||||
const newModifier = modifierTypes.VOUCHER_PREMIUM().newModifier();
|
||||
@ -150,7 +150,7 @@ async function spawnNextTrainerOrEndEncounter(scene: BattleScene) {
|
||||
scene.playSound("item_fanfare");
|
||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: newModifier?.type.name }));
|
||||
|
||||
await showEncounterDialogue(scene, `${namespace}.victory_2`, `${namespace}.speaker`);
|
||||
await showEncounterDialogue(scene, `${namespace}:victory_2`, `${namespace}:speaker`);
|
||||
scene.ui.clearText(); // Clears "Winstrate" title from screen as rewards get animated in
|
||||
const machoBrace = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_MACHO_BRACE)!;
|
||||
machoBrace.type.tier = ModifierTier.MASTER;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Ability, allAbilities } from "#app/data/ability";
|
||||
import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { getNatureName, Nature } from "#app/data/nature";
|
||||
import { speciesStarters } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
import { AbilityAttr } from "#app/system/game-data";
|
||||
@ -23,7 +23,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import { isPokemonValidForEncounterOptionSelection } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
|
||||
/** The i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:trainingSession";
|
||||
const namespace = "mysteryEncounters/trainingSession";
|
||||
|
||||
/**
|
||||
* Training Session encounter.
|
||||
@ -49,22 +49,22 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
}
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withHasDexProgress(true)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -78,7 +78,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
|
||||
// Only Pokemon that are not KOed/legal can be trained
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`);
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}:invalid_selection`);
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
@ -156,7 +156,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
scene.addModifier(mod, true, false, false, true);
|
||||
}
|
||||
scene.updateModifiers(true);
|
||||
queueEncounterMessage(scene, `${namespace}.option.1.finished`);
|
||||
queueEncounterMessage(scene, `${namespace}:option.1.finished`);
|
||||
};
|
||||
|
||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
||||
@ -170,12 +170,12 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withHasDexProgress(true)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.option.2.select_prompt`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
secondOptionPrompt: `${namespace}:option.2.select_prompt`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -204,7 +204,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
|
||||
// Only Pokemon that are not KOed/legal can be trained
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`);
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}:invalid_selection`);
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
@ -221,7 +221,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
||||
|
||||
const onBeforeRewardsPhase = () => {
|
||||
queueEncounterMessage(scene, `${namespace}.option.2.finished`);
|
||||
queueEncounterMessage(scene, `${namespace}:option.2.finished`);
|
||||
// Add the pokemon back to party with Nature change
|
||||
playerPokemon.setNature(encounter.misc.chosenNature);
|
||||
scene.gameData.setPokemonCaught(playerPokemon, false);
|
||||
@ -246,12 +246,12 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withHasDexProgress(true)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
secondOptionPrompt: `${namespace}.option.3.select_prompt`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
secondOptionPrompt: `${namespace}:option.3.select_prompt`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.selected`,
|
||||
text: `${namespace}:option.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -295,7 +295,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
|
||||
// Only Pokemon that are not KOed/legal can be trained
|
||||
const selectableFilter = (pokemon: Pokemon) => {
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}.invalid_selection`);
|
||||
return isPokemonValidForEncounterOptionSelection(pokemon, scene, `${namespace}:invalid_selection`);
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, undefined, selectableFilter);
|
||||
@ -316,7 +316,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
||||
|
||||
const onBeforeRewardsPhase = () => {
|
||||
queueEncounterMessage(scene, `${namespace}.option.3.finished`);
|
||||
queueEncounterMessage(scene, `${namespace}:option.3.finished`);
|
||||
// Add the pokemon back to party with ability change
|
||||
const abilityIndex = encounter.misc.abilityIndex;
|
||||
|
||||
@ -326,7 +326,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
// Only update the fusion's dex data if the Pokemon is already caught in dex (ignore rentals)
|
||||
const rootFusionSpecies = playerPokemon.fusionSpecies?.getRootSpeciesId();
|
||||
if (!isNullOrUndefined(rootFusionSpecies)
|
||||
&& speciesStarters.hasOwnProperty(rootFusionSpecies)
|
||||
&& speciesStarterCosts.hasOwnProperty(rootFusionSpecies)
|
||||
&& !!scene.gameData.dexData[rootFusionSpecies].caughtAttr) {
|
||||
scene.gameData.starterData[rootFusionSpecies].abilityAttr |= playerPokemon.fusionAbilityIndex !== 1 || playerPokemon.fusionSpecies?.ability2
|
||||
? 1 << playerPokemon.fusionAbilityIndex
|
||||
@ -356,11 +356,11 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.4.label`,
|
||||
buttonTooltip: `${namespace}.option.4.tooltip`,
|
||||
buttonLabel: `${namespace}:option.4.label`,
|
||||
buttonTooltip: `${namespace}:option.4.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.4.selected`,
|
||||
text: `${namespace}:option.4.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -19,7 +19,7 @@ import { PokemonMove } from "#app/field/pokemon";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:trashToTreasure";
|
||||
const namespace = "mysteryEncounters/trashToTreasure";
|
||||
|
||||
const SOUND_EFFECT_WAIT_TIME = 700;
|
||||
|
||||
@ -51,12 +51,12 @@ export const TrashToTreasureEncounter: MysteryEncounter =
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
||||
@ -90,11 +90,11 @@ export const TrashToTreasureEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -123,18 +123,18 @@ export const TrashToTreasureEncounter: MysteryEncounter =
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Investigate garbage, battle Gmax Garbodor
|
||||
scene.setFieldScale(0.75);
|
||||
await showEncounterText(scene, `${namespace}.option.2.selected_2`);
|
||||
await showEncounterText(scene, `${namespace}:option.2.selected_2`);
|
||||
transitionMysteryEncounterIntroVisuals(scene);
|
||||
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
|
@ -25,7 +25,7 @@ import { Stat } from "#enums/stat";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:uncommonBreed";
|
||||
const namespace = "mysteryEncounters/uncommonBreed";
|
||||
|
||||
/**
|
||||
* Uncommon Breed encounter.
|
||||
@ -42,7 +42,7 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
||||
.withIntroSpriteConfigs([]) // Set in onInit()
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
])
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
@ -85,7 +85,7 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
||||
isBoss: false,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.stat_boost`);
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:option.1.stat_boost`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
|
||||
}
|
||||
}],
|
||||
@ -125,16 +125,16 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
||||
scene.time.delayedCall(500, () => scene.playSound("battle_anims/PRSFX- Spotlight2"));
|
||||
return true;
|
||||
})
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -167,12 +167,12 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withSceneRequirement(new PersistentModifierRequirement("BerryModifier", 4)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.2.disabled_tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`
|
||||
text: `${namespace}:option.2.selected`
|
||||
}
|
||||
]
|
||||
})
|
||||
@ -211,12 +211,12 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(CHARMING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.3.label`,
|
||||
buttonTooltip: `${namespace}.option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}.option.3.disabled_tooltip`,
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.3.selected`
|
||||
text: `${namespace}:option.3.selected`
|
||||
}
|
||||
]
|
||||
})
|
||||
|
@ -23,7 +23,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
|
||||
/** i18n namespace for encounter */
|
||||
const namespace = "mysteryEncounter:weirdDream";
|
||||
const namespace = "mysteryEncounters/weirdDream";
|
||||
|
||||
/** Exclude Ultra Beasts, Paradox, Eternatus, and all legendary/mythical/trio pokemon that are below 570 BST */
|
||||
const EXCLUDED_TRANSFORMATION_SPECIES = [
|
||||
@ -118,16 +118,16 @@ export const WeirdDreamEncounter: MysteryEncounter =
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}.intro`,
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
speaker: `${namespace}.speaker`,
|
||||
text: `${namespace}.intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
},
|
||||
])
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
scene.loadBgm("mystery_encounter_weird_dream", "mystery_encounter_weird_dream.mp3");
|
||||
return true;
|
||||
@ -141,11 +141,11 @@ export const WeirdDreamEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||
.withHasDexProgress(true)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
buttonLabel: `${namespace}:option.1.label`,
|
||||
buttonTooltip: `${namespace}:option.1.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.1.selected`,
|
||||
text: `${namespace}:option.1.selected`,
|
||||
}
|
||||
],
|
||||
})
|
||||
@ -165,7 +165,7 @@ export const WeirdDreamEncounter: MysteryEncounter =
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Starts cutscene dialogue, but does not await so that cutscene plays as player goes through dialogue
|
||||
const cutsceneDialoguePromise = showEncounterText(scene, `${namespace}.option.1.cutscene`);
|
||||
const cutsceneDialoguePromise = showEncounterText(scene, `${namespace}:option.1.cutscene`);
|
||||
|
||||
// Change the entire player's party
|
||||
// Wait for all new Pokemon assets to be loaded before showing transformation animations
|
||||
@ -189,7 +189,7 @@ export const WeirdDreamEncounter: MysteryEncounter =
|
||||
await cutsceneDialoguePromise;
|
||||
|
||||
doHideDreamBackground(scene);
|
||||
await showEncounterText(scene, `${namespace}.option.1.dream_complete`);
|
||||
await showEncounterText(scene, `${namespace}:option.1.dream_complete`);
|
||||
|
||||
await doNewTeamPostProcess(scene, transformations);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.MEMORY_MUSHROOM, modifierTypes.ROGUE_BALL, modifierTypes.MINT, modifierTypes.MINT]});
|
||||
@ -199,11 +199,11 @@ export const WeirdDreamEncounter: MysteryEncounter =
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}.option.2.label`,
|
||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}.option.2.selected`,
|
||||
text: `${namespace}:option.2.selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -5,16 +5,16 @@ import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { TimeOfDay } from "#enums/time-of-day";
|
||||
import { Nature } from "../nature";
|
||||
import { EvolutionItem, pokemonEvolutions } from "../pokemon-evolutions";
|
||||
import { FormChangeItem, pokemonFormChanges, SpeciesFormChangeItemTrigger } from "../pokemon-forms";
|
||||
import { SpeciesFormKey } from "../pokemon-species";
|
||||
import { StatusEffect } from "../status-effect";
|
||||
import { Type } from "../type";
|
||||
import { WeatherType } from "../weather";
|
||||
import { Nature } from "#app/data/nature";
|
||||
import { EvolutionItem, pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { FormChangeItem, pokemonFormChanges, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms";
|
||||
import { StatusEffect } from "#app/data/status-effect";
|
||||
import { Type } from "#app/data/type";
|
||||
import { WeatherType } from "#app/data/weather";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { AttackTypeBoosterModifier } from "#app/modifier/modifier";
|
||||
import { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type";
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
|
||||
export interface EncounterRequirement {
|
||||
meetsRequirement(scene: BattleScene): boolean; // Boolean to see if a requirement is met
|
||||
|
@ -32,7 +32,7 @@ import { FunAndGamesEncounter } from "#app/data/mystery-encounters/encounters/fu
|
||||
import { UncommonBreedEncounter } from "#app/data/mystery-encounters/encounters/uncommon-breed-encounter";
|
||||
import { GlobalTradeSystemEncounter } from "#app/data/mystery-encounters/encounters/global-trade-system-encounter";
|
||||
import { TheExpertPokemonBreederEncounter } from "#app/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter";
|
||||
import { getBiomeName } from "#app/data/biomes";
|
||||
import { getBiomeName } from "#app/data/balance/biomes";
|
||||
|
||||
/**
|
||||
* Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT
|
||||
@ -363,6 +363,7 @@ export function initMysteryEncounters() {
|
||||
});
|
||||
|
||||
// Add ANY biome encounters to biome map
|
||||
// eslint-disable-next-line
|
||||
let encounterBiomeTableLog = "";
|
||||
mysteryEncountersByBiome.forEach((biomeEncounters, biome) => {
|
||||
anyBiomeEncounters.forEach(encounter => {
|
||||
@ -374,5 +375,5 @@ export function initMysteryEncounters() {
|
||||
encounterBiomeTableLog += `${getBiomeName(biome).toUpperCase()}: [${biomeEncounters.map(type => MysteryEncounterType[type].toString().toLowerCase()).sort().join(", ")}]\n`;
|
||||
});
|
||||
|
||||
console.debug("All Mystery Encounters by Biome:\n" + encounterBiomeTableLog);
|
||||
//console.debug("All Mystery Encounters by Biome:\n" + encounterBiomeTableLog);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Battle, { BattlerIndex, BattleType } from "#app/battle";
|
||||
import { biomeLinks, BiomePoolTier } from "#app/data/biomes";
|
||||
import { biomeLinks, BiomePoolTier } from "#app/data/balance/biomes";
|
||||
import MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { AVERAGE_ENCOUNTERS_PER_RUN_TARGET, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
|
@ -12,7 +12,8 @@ import { Mode } from "#app/ui/ui";
|
||||
import { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler";
|
||||
import { Species } from "#enums/species";
|
||||
import { Type } from "#app/data/type";
|
||||
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { getEncounterText, queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
@ -206,8 +207,8 @@ export function getRandomSpeciesByStarterTier(starterTiers: number | [number, nu
|
||||
let min = Array.isArray(starterTiers) ? starterTiers[0] : starterTiers;
|
||||
let max = Array.isArray(starterTiers) ? starterTiers[1] : starterTiers;
|
||||
|
||||
let filteredSpecies: [PokemonSpecies, number][] = Object.keys(speciesStarters)
|
||||
.map(s => [parseInt(s) as Species, speciesStarters[s] as number])
|
||||
let filteredSpecies: [PokemonSpecies, number][] = Object.keys(speciesStarterCosts)
|
||||
.map(s => [parseInt(s) as Species, speciesStarterCosts[s] as number])
|
||||
.filter(s => {
|
||||
const pokemonSpecies = getPokemonSpecies(s[0]);
|
||||
return pokemonSpecies && (!excludedSpecies || !excludedSpecies.includes(s[0]))
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { PokemonFormChangeItemModifier, TerastallizeModifier } from "../modifier/modifier";
|
||||
import Pokemon from "../field/pokemon";
|
||||
import { SpeciesFormKey } from "./pokemon-species";
|
||||
import { StatusEffect } from "./status-effect";
|
||||
import { MoveCategory, allMoves } from "./move";
|
||||
import { Type } from "./type";
|
||||
import { Constructor } from "#app/utils";
|
||||
import { Constructor, nil } from "#app/utils";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
@ -13,6 +12,7 @@ import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import i18next from "i18next";
|
||||
import { WeatherType } from "./weather";
|
||||
import { Challenges } from "#app/enums/challenges";
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
|
||||
export enum FormChangeItem {
|
||||
NONE,
|
||||
@ -185,7 +185,7 @@ export class SpeciesFormChange {
|
||||
return true;
|
||||
}
|
||||
|
||||
findTrigger(triggerType: Constructor<SpeciesFormChangeTrigger>): SpeciesFormChangeTrigger | null {
|
||||
findTrigger(triggerType: Constructor<SpeciesFormChangeTrigger>): SpeciesFormChangeTrigger | nil {
|
||||
if (!this.trigger.hasTriggerType(triggerType)) {
|
||||
return null;
|
||||
}
|
||||
@ -193,7 +193,7 @@ export class SpeciesFormChange {
|
||||
const trigger = this.trigger;
|
||||
|
||||
if (trigger instanceof SpeciesFormChangeCompoundTrigger) {
|
||||
return trigger.triggers.find(t => t.hasTriggerType(triggerType))!; // TODO: is this bang correct?
|
||||
return trigger.triggers.find(t => t.hasTriggerType(triggerType));
|
||||
}
|
||||
|
||||
return trigger;
|
||||
@ -202,11 +202,11 @@ export class SpeciesFormChange {
|
||||
|
||||
export class SpeciesFormChangeCondition {
|
||||
public predicate: SpeciesFormChangeConditionPredicate;
|
||||
public enforceFunc: SpeciesFormChangeConditionEnforceFunc | null;
|
||||
public enforceFunc: SpeciesFormChangeConditionEnforceFunc | nil;
|
||||
|
||||
constructor(predicate: SpeciesFormChangeConditionPredicate, enforceFunc?: SpeciesFormChangeConditionEnforceFunc) {
|
||||
this.predicate = predicate;
|
||||
this.enforceFunc = enforceFunc!; // TODO: is this bang correct?
|
||||
this.enforceFunc = enforceFunc;
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,22 +1,27 @@
|
||||
import BattleScene, { startingWave } from "../battle-scene";
|
||||
import { ModifierTypeFunc, modifierTypes } from "../modifier/modifier-type";
|
||||
import { EnemyPokemon, PokemonMove } from "../field/pokemon";
|
||||
import * as Utils from "../utils";
|
||||
import { PokeballType } from "./pokeball";
|
||||
import { pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions";
|
||||
import PokemonSpecies, { getPokemonSpecies, PokemonSpeciesFilter } from "./pokemon-species";
|
||||
import { tmSpecies } from "./tms";
|
||||
import { Type } from "./type";
|
||||
import { doubleBattleDialogue } from "./dialogue";
|
||||
import { PersistentModifier } from "../modifier/modifier";
|
||||
import { TrainerVariant } from "../field/trainer";
|
||||
import BattleScene, { startingWave } from "#app/battle-scene";
|
||||
import { ModifierTypeFunc, modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import * as Utils from "#app/utils";
|
||||
import { PokeballType } from "#app/data/pokeball";
|
||||
import { pokemonEvolutions, pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import PokemonSpecies, { getPokemonSpecies, PokemonSpeciesFilter } from "#app/data/pokemon-species";
|
||||
import { tmSpecies } from "#app/data/balance/tms";
|
||||
import { Type } from "#app/data/type";
|
||||
import { doubleBattleDialogue } from "#app/data/dialogue";
|
||||
import { PersistentModifier } from "#app/modifier/modifier";
|
||||
import { TrainerVariant } from "#app/field/trainer";
|
||||
import { getIsInitialized, initI18n } from "#app/plugins/i18n";
|
||||
import i18next from "i18next";
|
||||
import {Moves} from "#enums/moves";
|
||||
import {PartyMemberStrength} from "#enums/party-member-strength";
|
||||
import {Species} from "#enums/species";
|
||||
import {TrainerType} from "#enums/trainer-type";
|
||||
import {Gender} from "./gender";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { Species } from "#enums/species";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { Gender } from "#app/data/gender";
|
||||
|
||||
/** Minimum BST for Pokemon generated onto the Elite Four's teams */
|
||||
const ELITE_FOUR_MINIMUM_BST = 460;
|
||||
/** Minimum BST for Pokemon generated onto the E4 Champion's team */
|
||||
const CHAMPION_MINIMUM_BST = 508;
|
||||
|
||||
export enum TrainerPoolTier {
|
||||
COMMON,
|
||||
@ -860,10 +865,10 @@ export class TrainerConfig {
|
||||
|
||||
// Set species filter and specialty types if provided, otherwise filter by base total.
|
||||
if (specialtyTypes.length) {
|
||||
this.setSpeciesFilter(p => specialtyTypes.some(t => p.isOfType(t)) && p.baseTotal >= 450);
|
||||
this.setSpeciesFilter(p => specialtyTypes.some(t => p.isOfType(t)) && p.baseTotal >= ELITE_FOUR_MINIMUM_BST);
|
||||
this.setSpecialtyTypes(...specialtyTypes);
|
||||
} else {
|
||||
this.setSpeciesFilter(p => p.baseTotal >= 450);
|
||||
this.setSpeciesFilter(p => p.baseTotal >= ELITE_FOUR_MINIMUM_BST);
|
||||
}
|
||||
|
||||
// Localize the trainer's name by converting it to lowercase and replacing spaces with underscores.
|
||||
@ -913,8 +918,7 @@ export class TrainerConfig {
|
||||
this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool));
|
||||
});
|
||||
|
||||
// Set species filter to only include species with a base total of 470 or higher.
|
||||
this.setSpeciesFilter(p => p.baseTotal >= 470);
|
||||
this.setSpeciesFilter(p => p.baseTotal >= CHAMPION_MINIMUM_BST);
|
||||
|
||||
// Localize the trainer's name by converting it to lowercase and replacing spaces with underscores.
|
||||
const nameForCall = this.name.toLowerCase().replace(/\s/g, "_");
|
||||
|
13
src/enums/species-form-key.ts
Normal file
13
src/enums/species-form-key.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export enum SpeciesFormKey {
|
||||
MEGA = "mega",
|
||||
MEGA_X = "mega-x",
|
||||
MEGA_Y = "mega-y",
|
||||
PRIMAL = "primal",
|
||||
ORIGIN = "origin",
|
||||
INCARNATE = "incarnate",
|
||||
THERIAN = "therian",
|
||||
GIGANTAMAX = "gigantamax",
|
||||
GIGANTAMAX_SINGLE = "gigantamax-single",
|
||||
GIGANTAMAX_RAPID = "gigantamax-rapid",
|
||||
ETERNAMAX = "eternamax",
|
||||
}
|
@ -1,26 +1,26 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import { biomePokemonPools, BiomePoolTier, BiomeTierTrainerPools, biomeTrainerPools, PokemonPools } from "../data/biomes";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { biomePokemonPools, BiomePoolTier, BiomeTierTrainerPools, biomeTrainerPools, PokemonPools } from "#app/data/balance/biomes";
|
||||
import { Constructor } from "#app/utils";
|
||||
import * as Utils from "../utils";
|
||||
import PokemonSpecies, { getPokemonSpecies } from "../data/pokemon-species";
|
||||
import { getTerrainClearMessage, getTerrainStartMessage, getWeatherClearMessage, getWeatherStartMessage, Weather, WeatherType } from "../data/weather";
|
||||
import { CommonAnim } from "../data/battle-anims";
|
||||
import { Type } from "../data/type";
|
||||
import Move from "../data/move";
|
||||
import { ArenaTag, ArenaTagSide, ArenaTrapTag, getArenaTag } from "../data/arena-tag";
|
||||
import { BattlerIndex } from "../battle";
|
||||
import { Terrain, TerrainType } from "../data/terrain";
|
||||
import { applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs, PostTerrainChangeAbAttr, PostWeatherChangeAbAttr } from "../data/ability";
|
||||
import Pokemon from "./pokemon";
|
||||
import * as Utils from "#app/utils";
|
||||
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { getTerrainClearMessage, getTerrainStartMessage, getWeatherClearMessage, getWeatherStartMessage, Weather, WeatherType } from "#app/data/weather";
|
||||
import { CommonAnim } from "#app/data/battle-anims";
|
||||
import { Type } from "#app/data/type";
|
||||
import Move from "#app/data/move";
|
||||
import { ArenaTag, ArenaTagSide, ArenaTrapTag, getArenaTag } from "#app/data/arena-tag";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { Terrain, TerrainType } from "#app/data/terrain";
|
||||
import { applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs, PostTerrainChangeAbAttr, PostWeatherChangeAbAttr } from "#app/data/ability";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
import Overrides from "#app/overrides";
|
||||
import { TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "../events/arena";
|
||||
import { TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena";
|
||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { TimeOfDay } from "#enums/time-of-day";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "#app/data/pokemon-forms";
|
||||
import { CommonAnimPhase } from "#app/phases/common-anim-phase";
|
||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
||||
|
@ -1,43 +1,45 @@
|
||||
import Phaser from "phaser";
|
||||
import BattleScene, { AnySound } from "../battle-scene";
|
||||
import BattleScene, { AnySound } from "#app/battle-scene";
|
||||
import { Variant, VariantSet, variantColorCache } from "#app/data/variant";
|
||||
import { variantData } from "#app/data/variant";
|
||||
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "../ui/battle-info";
|
||||
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget } from "../data/move";
|
||||
import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species";
|
||||
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "#app/ui/battle-info";
|
||||
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget } from "#app/data/move";
|
||||
import { default as PokemonSpecies, PokemonSpeciesForm, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||
import { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { starterPassiveAbilities } from "#app/data/balance/passives";
|
||||
import { Constructor, isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||
import * as Utils from "../utils";
|
||||
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "../data/type";
|
||||
import { getLevelTotalExp } from "../data/exp";
|
||||
import * as Utils from "#app/utils";
|
||||
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "#app/data/type";
|
||||
import { getLevelTotalExp } from "#app/data/exp";
|
||||
import { Stat, type PermanentStat, type BattleStat, type EffectiveStat, PERMANENT_STATS, BATTLE_STATS, EFFECTIVE_STATS } from "#enums/stat";
|
||||
import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, BaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempStatStageBoosterModifier, TempCritBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier, PokemonBaseStatFlatModifier, PokemonBaseStatTotalModifier, PokemonIncrementingStatModifier, EvoTrackerModifier } from "../modifier/modifier";
|
||||
import { PokeballType } from "../data/pokeball";
|
||||
import { Gender } from "../data/gender";
|
||||
import { initMoveAnim, loadMoveAnimAssets } from "../data/battle-anims";
|
||||
import { Status, StatusEffect, getRandomStatus } from "../data/status-effect";
|
||||
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "../data/pokemon-evolutions";
|
||||
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms";
|
||||
import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, BaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempStatStageBoosterModifier, TempCritBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier, PokemonBaseStatFlatModifier, PokemonBaseStatTotalModifier, PokemonIncrementingStatModifier, EvoTrackerModifier } from "#app/modifier/modifier";
|
||||
import { PokeballType } from "#app/data/pokeball";
|
||||
import { Gender } from "#app/data/gender";
|
||||
import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims";
|
||||
import { Status, StatusEffect, getRandomStatus } from "#app/data/status-effect";
|
||||
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
|
||||
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "#app/data/balance/tms";
|
||||
import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, SubstituteTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, MoveRestrictionBattlerTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag, TarShotTag, AutotomizedTag } from "../data/battler-tags";
|
||||
import { WeatherType } from "../data/weather";
|
||||
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "../data/arena-tag";
|
||||
import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr, PostSetStatusAbAttr, applyPostSetStatusAbAttrs } from "../data/ability";
|
||||
import PokemonData from "../system/pokemon-data";
|
||||
import { BattlerIndex } from "../battle";
|
||||
import { Mode } from "../ui/ui";
|
||||
import PartyUiHandler, { PartyOption, PartyUiMode } from "../ui/party-ui-handler";
|
||||
import { WeatherType } from "#app/data/weather";
|
||||
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "#app/data/arena-tag";
|
||||
import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr, PostSetStatusAbAttr, applyPostSetStatusAbAttrs } from "#app/data/ability";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import PartyUiHandler, { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler";
|
||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { LevelMoves } from "../data/pokemon-level-moves";
|
||||
import { DamageAchv, achvs } from "../system/achv";
|
||||
import { DexAttr, StarterDataEntry, StarterMoveset } from "../system/game-data";
|
||||
import { LevelMoves } from "#app/data/balance/pokemon-level-moves";
|
||||
import { DamageAchv, achvs } from "#app/system/achv";
|
||||
import { DexAttr, StarterDataEntry, StarterMoveset } from "#app/system/game-data";
|
||||
import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities";
|
||||
import { Nature, getNatureStatMultiplier } from "../data/nature";
|
||||
import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from "../data/pokemon-forms";
|
||||
import { TerrainType } from "../data/terrain";
|
||||
import { TrainerSlot } from "../data/trainer-config";
|
||||
import { Nature, getNatureStatMultiplier } from "#app/data/nature";
|
||||
import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from "#app/data/pokemon-forms";
|
||||
import { TerrainType } from "#app/data/terrain";
|
||||
import { TrainerSlot } from "#app/data/trainer-config";
|
||||
import Overrides from "#app/overrides";
|
||||
import i18next from "i18next";
|
||||
import { speciesEggMoves } from "../data/egg-moves";
|
||||
import { ModifierTier } from "../modifier/modifier-tier";
|
||||
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { applyChallenges, ChallengeType } from "#app/data/challenge";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||
@ -58,16 +60,12 @@ import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
||||
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { PokemonAnimType } from "#app/enums/pokemon-anim-type";
|
||||
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
import { SwitchType } from "#enums/switch-type";
|
||||
|
||||
/** `64/65536 -> 1/1024` */
|
||||
const BASE_SHINY_CHANCE = 64;
|
||||
|
||||
/** `1/256` */
|
||||
const BASE_HIDDEN_ABILITY_CHANCE = 256;
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
import { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE, SHINY_EPIC_CHANCE, SHINY_VARIANT_CHANCE } from "#app/data/balance/rates";
|
||||
|
||||
export enum FieldPosition {
|
||||
CENTER,
|
||||
@ -1089,6 +1087,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return !!this.fusionSpecies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the {@linkcode Pokemon} has a fusion with the specified {@linkcode Species}.
|
||||
* @param species the pokemon {@linkcode Species} to check
|
||||
* @returns `true` if the {@linkcode Pokemon} has a fusion with the specified {@linkcode Species}, `false` otherwise
|
||||
*/
|
||||
hasFusionSpecies(species: Species): boolean {
|
||||
return this.fusionSpecies?.speciesId === species;
|
||||
}
|
||||
|
||||
abstract isBoss(): boolean;
|
||||
|
||||
getMoveset(ignoreOverride?: boolean): (PokemonMove | null)[] {
|
||||
@ -1537,6 +1544,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* @returns The type damage multiplier, indicating the effectiveness of the move
|
||||
*/
|
||||
getMoveEffectiveness(source: Pokemon, move: Move, ignoreAbility: boolean = false, simulated: boolean = true, cancelled?: Utils.BooleanHolder): TypeDamageMultiplier {
|
||||
if (!Utils.isNullOrUndefined(this.turnData?.moveEffectiveness)) {
|
||||
return this.turnData?.moveEffectiveness;
|
||||
}
|
||||
|
||||
if (move.hasAttr(TypelessAttr)) {
|
||||
return 1;
|
||||
}
|
||||
@ -1925,9 +1936,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.scene.executeWithSeedOffset(() => {
|
||||
rand.value = Utils.randSeedInt(10);
|
||||
}, this.id, this.scene.waveSeed);
|
||||
if (rand.value >= 4) {
|
||||
if (rand.value >= SHINY_VARIANT_CHANCE) {
|
||||
return 0; // 6/10
|
||||
} else if (rand.value >= 1) {
|
||||
} else if (rand.value >= SHINY_EPIC_CHANCE) {
|
||||
return 1; // 3/10
|
||||
} else {
|
||||
return 2; // 1/10
|
||||
@ -4052,7 +4063,7 @@ export class PlayerPokemon extends Pokemon {
|
||||
starterData.forEach((sd: StarterDataEntry, i: integer) => {
|
||||
const speciesId = !i ? starterSpeciesId : fusionStarterSpeciesId as Species;
|
||||
sd.friendship = (sd.friendship || 0) + starterAmount.value;
|
||||
if (sd.friendship >= getStarterValueFriendshipCap(speciesStarters[speciesId])) {
|
||||
if (sd.friendship >= getStarterValueFriendshipCap(speciesStarterCosts[speciesId])) {
|
||||
this.scene.gameData.addStarterCandy(getPokemonSpecies(speciesId), 1);
|
||||
sd.friendship = 0;
|
||||
}
|
||||
@ -5000,6 +5011,8 @@ export class PokemonBattleData {
|
||||
export class PokemonBattleSummonData {
|
||||
/** The number of turns the pokemon has passed since entering the battle */
|
||||
public turnCount: number = 1;
|
||||
/** The number of turns the pokemon has passed since the start of the wave */
|
||||
public waveTurnCount: number = 1;
|
||||
/** The list of moves the pokemon has used since entering the battle */
|
||||
public moveHistory: TurnMove[] = [];
|
||||
}
|
||||
@ -5016,6 +5029,7 @@ export class PokemonTurnData {
|
||||
public order: number;
|
||||
public statStagesIncreased: boolean = false;
|
||||
public statStagesDecreased: boolean = false;
|
||||
public moveEffectiveness: TypeDamageMultiplier | null = null;
|
||||
}
|
||||
|
||||
export enum AiType {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import {pokemonPrevolutions} from "../data/pokemon-evolutions";
|
||||
import PokemonSpecies, {getPokemonSpecies} from "../data/pokemon-species";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import {pokemonPrevolutions} from "#app/data/balance/pokemon-evolutions";
|
||||
import PokemonSpecies, {getPokemonSpecies} from "#app/data/pokemon-species";
|
||||
import {
|
||||
TrainerConfig,
|
||||
TrainerPartyCompoundTemplate,
|
||||
@ -10,13 +10,13 @@ import {
|
||||
trainerConfigs,
|
||||
trainerPartyTemplates,
|
||||
signatureSpecies
|
||||
} from "../data/trainer-config";
|
||||
import {EnemyPokemon} from "./pokemon";
|
||||
import * as Utils from "../utils";
|
||||
import {PersistentModifier} from "../modifier/modifier";
|
||||
import {trainerNamePools} from "../data/trainer-names";
|
||||
import {ArenaTagSide, ArenaTrapTag} from "#app/data/arena-tag";
|
||||
import {getIsInitialized, initI18n} from "#app/plugins/i18n";
|
||||
} from "#app/data/trainer-config";
|
||||
import {EnemyPokemon} from "#app/field/pokemon";
|
||||
import * as Utils from "#app/utils";
|
||||
import { PersistentModifier } from "#app/modifier/modifier";
|
||||
import { trainerNamePools } from "#app/data/trainer-names";
|
||||
import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag";
|
||||
import { getIsInitialized, initI18n } from "#app/plugins/i18n";
|
||||
import i18next from "i18next";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { Species } from "#enums/species";
|
||||
|
@ -1,24 +1,23 @@
|
||||
import { GachaType } from "./enums/gacha-types";
|
||||
import { getBiomeHasProps } from "./field/arena";
|
||||
import CacheBustedLoaderPlugin from "./plugins/cache-busted-loader-plugin";
|
||||
import { SceneBase } from "./scene-base";
|
||||
import { WindowVariant, getWindowVariantSuffix } from "./ui/ui-theme";
|
||||
import { isMobile } from "./touch-controls";
|
||||
import * as Utils from "./utils";
|
||||
import { initI18n } from "./plugins/i18n";
|
||||
import { initPokemonPrevolutions } from "#app/data/pokemon-evolutions";
|
||||
import { initBiomes } from "#app/data/biomes";
|
||||
import { initEggMoves } from "#app/data/egg-moves";
|
||||
import { GachaType } from "#enums/gacha-types";
|
||||
import { getBiomeHasProps } from "#app/field/arena";
|
||||
import CacheBustedLoaderPlugin from "#app/plugins/cache-busted-loader-plugin";
|
||||
import { SceneBase } from "#app/scene-base";
|
||||
import { WindowVariant, getWindowVariantSuffix } from "#app/ui/ui-theme";
|
||||
import { isMobile } from "#app/touch-controls";
|
||||
import * as Utils from "#app/utils";
|
||||
import { initPokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { initBiomes } from "#app/data/balance/biomes";
|
||||
import { initEggMoves } from "#app/data/balance/egg-moves";
|
||||
import { initPokemonForms } from "#app/data/pokemon-forms";
|
||||
import { initSpecies } from "#app/data/pokemon-species";
|
||||
import { initMoves } from "#app/data/move";
|
||||
import { initAbilities } from "#app/data/ability";
|
||||
import { initAchievements } from "#app/system/achv";
|
||||
import { initTrainerTypeDialogue } from "#app/data/dialogue";
|
||||
import { initChallenges } from "./data/challenge";
|
||||
import { initChallenges } from "#app/data/challenge";
|
||||
import i18next from "i18next";
|
||||
import { initStatsKeys } from "./ui/game-stats-ui-handler";
|
||||
import { initVouchers } from "./system/voucher";
|
||||
import { initStatsKeys } from "#app/ui/game-stats-ui-handler";
|
||||
import { initVouchers } from "#app/system/voucher";
|
||||
import { Biome } from "#enums/biome";
|
||||
import {initMysteryEncounters} from "#app/data/mystery-encounters/mystery-encounters";
|
||||
|
||||
@ -31,7 +30,6 @@ export class LoadingScene extends SceneBase {
|
||||
super(LoadingScene.KEY);
|
||||
|
||||
Phaser.Plugins.PluginCache.register("Loader", CacheBustedLoaderPlugin, "load");
|
||||
initI18n();
|
||||
}
|
||||
|
||||
preload() {
|
||||
@ -46,6 +44,8 @@ export class LoadingScene extends SceneBase {
|
||||
this.loadAtlas("prompt", "ui");
|
||||
this.loadImage("candy", "ui");
|
||||
this.loadImage("candy_overlay", "ui");
|
||||
this.loadImage("friendship", "ui");
|
||||
this.loadImage("friendship_overlay", "ui");
|
||||
this.loadImage("cursor", "ui");
|
||||
this.loadImage("cursor_reverse", "ui");
|
||||
for (const wv of Utils.getEnumValues(WindowVariant)) {
|
||||
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1,40 +0,0 @@
|
||||
{
|
||||
"activeBattleEffects": "Efectes d'Arena Activa",
|
||||
"player": "Jugador",
|
||||
"neutral": "Neutre",
|
||||
"enemy": "Enemic",
|
||||
"sunny": "Assolellat",
|
||||
"rain": "Plujós",
|
||||
"sandstorm": "Tempesta Sorra",
|
||||
"hail": "Calamarsa",
|
||||
"snow": "Neu",
|
||||
"fog": "Boira",
|
||||
"heavyRain": "Diluvi",
|
||||
"harshSun": "Sol Abrasador",
|
||||
"strongWinds": "Vents Forts",
|
||||
"misty": "Camp de Boira",
|
||||
"electric": "Camp Elèctric",
|
||||
"grassy": "Camp d'Herba",
|
||||
"psychic": "Camp Psíquic",
|
||||
"mudSport": "Xipollejo Fang",
|
||||
"waterSport": "Hidrorraig",
|
||||
"spikes": "Pues",
|
||||
"toxicSpikes": "Pues Tòxiques",
|
||||
"mist": "Boirina",
|
||||
"futureSight": "Premonició",
|
||||
"doomDesire": "Desig Ocult",
|
||||
"wish": "Desig",
|
||||
"stealthRock": "Trampa Roques",
|
||||
"stickyWeb": "Xarxa Viscosa",
|
||||
"trickRoom": "Espai Rar",
|
||||
"gravity": "Gravetat",
|
||||
"reflect": "Reflex",
|
||||
"lightScreen": "Pantalla de Llum",
|
||||
"auroraVeil": "Vel Aurora",
|
||||
"quickGuard": "Anticipi",
|
||||
"wideGuard": "Vasta Guàrdia",
|
||||
"matBlock": "Escut Tatami",
|
||||
"craftyShield": "Truc Defensa",
|
||||
"tailwind": "Vent Afí",
|
||||
"happyHour": "Paga Extra"
|
||||
}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1,38 +0,0 @@
|
||||
{
|
||||
"unknownLocation": "En algun lloc que no recordes",
|
||||
"TOWN": "Poble",
|
||||
"PLAINS": "Vall",
|
||||
"GRASS": "Camp",
|
||||
"TALL_GRASS": "Herba Alta",
|
||||
"METROPOLIS": "Metròpoli",
|
||||
"FOREST": "Bosc",
|
||||
"SEA": "Mar",
|
||||
"SWAMP": "Pantà",
|
||||
"BEACH": "Platja",
|
||||
"LAKE": "Llac",
|
||||
"SEABED": "Fons Marí",
|
||||
"MOUNTAIN": "Muntanya",
|
||||
"BADLANDS": "Badlands",
|
||||
"CAVE": "Cova",
|
||||
"DESERT": "Desert",
|
||||
"ICE_CAVE": "Cova Gelada",
|
||||
"MEADOW": "Prat",
|
||||
"POWER_PLANT": "Planta d'Energia",
|
||||
"VOLCANO": "Volcà",
|
||||
"GRAVEYARD": "Cementiri",
|
||||
"DOJO": "Dojo",
|
||||
"FACTORY": "Fàbrica",
|
||||
"RUINS": "Ruïnes Antigues",
|
||||
"WASTELAND": "Terra Erma",
|
||||
"ABYSS": "Avenc",
|
||||
"SPACE": "Espai",
|
||||
"CONSTRUCTION_SITE": "Obra",
|
||||
"JUNGLE": "Jungla",
|
||||
"FAIRY_CAVE": "Cova de Fades",
|
||||
"TEMPLE": "Temple",
|
||||
"SLUM": "Suburbi",
|
||||
"SNOWY_FOREST": "Bosc Nevat",
|
||||
"ISLAND": "Illa",
|
||||
"LABORATORY": "Laboratori",
|
||||
"END": "???"
|
||||
}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"start": "Començar",
|
||||
"luckIndicator": "Sort:",
|
||||
"shinyOnHover": "Variocolor",
|
||||
"commonShiny": "Comú",
|
||||
"rareShiny": "Rar",
|
||||
"epicShiny": "Èpica"
|
||||
}
|
@ -1,191 +0,0 @@
|
||||
import common from "./common.json";
|
||||
import settings from "./settings.json";
|
||||
import ability from "./ability.json";
|
||||
import abilityTriggers from "./ability-trigger.json";
|
||||
import arenaFlyout from "./arena-flyout.json";
|
||||
import arenaTag from "./arena-tag.json";
|
||||
import achv from "./achv.json";
|
||||
import battle from "./battle.json";
|
||||
import battleScene from "./battle-scene.json";
|
||||
import battleInfo from "./battle-info.json";
|
||||
import battleMessageUiHandler from "./battle-message-ui-handler.json";
|
||||
import battlerTags from "./battler-tags.json";
|
||||
import berry from "./berry.json";
|
||||
import bgmName from "./bgm-name.json";
|
||||
import biome from "./biome.json";
|
||||
import challenges from "./challenges.json";
|
||||
import commandUiHandler from "./command-ui-handler.json";
|
||||
import dialogue from "./dialogue.json";
|
||||
import battleSpecDialogue from "./dialogue-final-boss.json";
|
||||
import miscDialogue from "./dialogue-misc.json";
|
||||
import doubleBattleDialogue from "./dialogue-double-battle.json";
|
||||
import egg from "./egg.json";
|
||||
import fightUiHandler from "./fight-ui-handler.json";
|
||||
import filterBar from "./filter-bar.json";
|
||||
import gameMode from "./game-mode.json";
|
||||
import gameStatsUiHandler from "./game-stats-ui-handler.json";
|
||||
import growth from "./growth.json";
|
||||
import menu from "./menu.json";
|
||||
import menuUiHandler from "./menu-ui-handler.json";
|
||||
import modifier from "./modifier.json";
|
||||
import modifierType from "./modifier-type.json";
|
||||
import move from "./move.json";
|
||||
import nature from "./nature.json";
|
||||
import partyUiHandler from "./party-ui-handler.json";
|
||||
import pokeball from "./pokeball.json";
|
||||
import pokemon from "./pokemon.json";
|
||||
import pokemonForm from "./pokemon-form.json";
|
||||
import battlePokemonForm from "./pokemon-form-battle.json";
|
||||
import pokemonInfo from "./pokemon-info.json";
|
||||
import pokemonInfoContainer from "./pokemon-info-container.json";
|
||||
import pokemonSummary from "./pokemon-summary.json";
|
||||
import saveSlotSelectUiHandler from "./save-slot-select-ui-handler.json";
|
||||
import splashMessages from "./splash-messages.json";
|
||||
import starterSelectUiHandler from "./starter-select-ui-handler.json";
|
||||
import statusEffect from "./status-effect.json";
|
||||
import trainerTitles from "./trainer-titles.json";
|
||||
import trainerClasses from "./trainer-classes.json";
|
||||
import trainerNames from "./trainer-names.json";
|
||||
import tutorial from "./tutorial.json";
|
||||
import voucher from "./voucher.json";
|
||||
import weather from "./weather.json";
|
||||
import terrain from "./terrain.json";
|
||||
import modifierSelectUiHandler from "./modifier-select-ui-handler.json";
|
||||
import moveTriggers from "./move-trigger.json";
|
||||
import runHistory from "./run-history.json";
|
||||
import mysteryEncounterMessages from "./mystery-encounter-messages.json";
|
||||
import lostAtSea from "./mystery-encounters/lost-at-sea-dialogue.json";
|
||||
import mysteriousChest from "./mystery-encounters/mysterious-chest-dialogue.json";
|
||||
import mysteriousChallengers from "./mystery-encounters/mysterious-challengers-dialogue.json";
|
||||
import darkDeal from "./mystery-encounters/dark-deal-dialogue.json";
|
||||
import departmentStoreSale from "./mystery-encounters/department-store-sale-dialogue.json";
|
||||
import fieldTrip from "./mystery-encounters/field-trip-dialogue.json";
|
||||
import fieryFallout from "./mystery-encounters/fiery-fallout-dialogue.json";
|
||||
import fightOrFlight from "./mystery-encounters/fight-or-flight-dialogue.json";
|
||||
import safariZone from "./mystery-encounters/safari-zone-dialogue.json";
|
||||
import shadyVitaminDealer from "./mystery-encounters/shady-vitamin-dealer-dialogue.json";
|
||||
import slumberingSnorlax from "./mystery-encounters/slumbering-snorlax-dialogue.json";
|
||||
import trainingSession from "./mystery-encounters/training-session-dialogue.json";
|
||||
import theStrongStuff from "./mystery-encounters/the-strong-stuff-dialogue.json";
|
||||
import pokemonSalesman from "./mystery-encounters/the-pokemon-salesman-dialogue.json";
|
||||
import offerYouCantRefuse from "./mystery-encounters/an-offer-you-cant-refuse-dialogue.json";
|
||||
import delibirdy from "./mystery-encounters/delibirdy-dialogue.json";
|
||||
import absoluteAvarice from "./mystery-encounters/absolute-avarice-dialogue.json";
|
||||
import aTrainersTest from "./mystery-encounters/a-trainers-test-dialogue.json";
|
||||
import trashToTreasure from "./mystery-encounters/trash-to-treasure-dialogue.json";
|
||||
import berriesAbound from "./mystery-encounters/berries-abound-dialogue.json";
|
||||
import clowningAround from "./mystery-encounters/clowning-around-dialogue.json";
|
||||
import partTimer from "./mystery-encounters/part-timer-dialogue.json";
|
||||
import dancingLessons from "./mystery-encounters/dancing-lessons-dialogue.json";
|
||||
import weirdDream from "./mystery-encounters/weird-dream-dialogue.json";
|
||||
import theWinstrateChallenge from "./mystery-encounters/the-winstrate-challenge-dialogue.json";
|
||||
import teleportingHijinks from "./mystery-encounters/teleporting-hijinks-dialogue.json";
|
||||
import bugTypeSuperfan from "./mystery-encounters/bug-type-superfan-dialogue.json";
|
||||
import funAndGames from "./mystery-encounters/fun-and-games-dialogue.json";
|
||||
import uncommonBreed from "./mystery-encounters/uncommon-breed-dialogue.json";
|
||||
import globalTradeSystem from "./mystery-encounters/global-trade-system-dialogue.json";
|
||||
import expertPokemonBreeder from "./mystery-encounters/the-expert-pokemon-breeder-dialogue.json";
|
||||
|
||||
/**
|
||||
* Dialogue/Text token injection patterns that can be used:
|
||||
* - `$` will be treated as a new line for Message and Dialogue strings.
|
||||
* - `@d{<number>}` will add a time delay to text animation for Message and Dialogue strings.
|
||||
* - `@s{<sound_effect_key>}` will play a specified sound effect for Message and Dialogue strings.
|
||||
* - `@f{<number>}` will fade the screen to black for the given duration, then fade back in for Message and Dialogue strings.
|
||||
* - `{{<token>}}` (MYSTERY ENCOUNTERS ONLY) will auto-inject the matching dialogue token value that is stored in {@link IMysteryEncounter.dialogueTokens}.
|
||||
* - (see [i18next interpolations](https://www.i18next.com/translation-function/interpolation)) for more details.
|
||||
* - `@[<TextStyle>]{<text>}` (STATIC TEXT ONLY, NOT USEABLE WITH {@link UI.showText()} OR {@link UI.showDialogue()}) will auto-color the given text to a specified {@link TextStyle} (e.g. `TextStyle.SUMMARY_GREEN`).
|
||||
*/
|
||||
export const caEsConfig = {
|
||||
ability,
|
||||
abilityTriggers,
|
||||
arenaFlyout,
|
||||
arenaTag,
|
||||
battle,
|
||||
battleScene,
|
||||
battleInfo,
|
||||
battleMessageUiHandler,
|
||||
battlePokemonForm,
|
||||
battlerTags,
|
||||
berry,
|
||||
bgmName,
|
||||
biome,
|
||||
challenges,
|
||||
commandUiHandler,
|
||||
common,
|
||||
achv,
|
||||
dialogue,
|
||||
battleSpecDialogue,
|
||||
miscDialogue,
|
||||
doubleBattleDialogue,
|
||||
egg,
|
||||
fightUiHandler,
|
||||
filterBar,
|
||||
gameMode,
|
||||
gameStatsUiHandler,
|
||||
growth,
|
||||
menu,
|
||||
menuUiHandler,
|
||||
modifier,
|
||||
modifierType,
|
||||
move,
|
||||
nature,
|
||||
pokeball,
|
||||
pokemon,
|
||||
pokemonForm,
|
||||
pokemonInfo,
|
||||
pokemonInfoContainer,
|
||||
pokemonSummary,
|
||||
saveSlotSelectUiHandler,
|
||||
settings,
|
||||
splashMessages,
|
||||
starterSelectUiHandler,
|
||||
statusEffect,
|
||||
terrain,
|
||||
titles: trainerTitles,
|
||||
trainerClasses,
|
||||
trainerNames,
|
||||
tutorial,
|
||||
voucher,
|
||||
weather,
|
||||
partyUiHandler,
|
||||
modifierSelectUiHandler,
|
||||
moveTriggers,
|
||||
runHistory,
|
||||
mysteryEncounter: {
|
||||
// DO NOT REMOVE
|
||||
"unit_test_dialogue": "{{test}}{{test}} {{test{{test}}}} {{test1}} {{test\}} {{test\\}} {{test\\\}} {test}}",
|
||||
mysteriousChallengers,
|
||||
mysteriousChest,
|
||||
darkDeal,
|
||||
fightOrFlight,
|
||||
slumberingSnorlax,
|
||||
trainingSession,
|
||||
departmentStoreSale,
|
||||
shadyVitaminDealer,
|
||||
fieldTrip,
|
||||
safariZone,
|
||||
lostAtSea,
|
||||
fieryFallout,
|
||||
theStrongStuff,
|
||||
pokemonSalesman,
|
||||
offerYouCantRefuse,
|
||||
delibirdy,
|
||||
absoluteAvarice,
|
||||
aTrainersTest,
|
||||
trashToTreasure,
|
||||
berriesAbound,
|
||||
clowningAround,
|
||||
partTimer,
|
||||
dancingLessons,
|
||||
weirdDream,
|
||||
theWinstrateChallenge,
|
||||
teleportingHijinks,
|
||||
bugTypeSuperfan,
|
||||
funAndGames,
|
||||
uncommonBreed,
|
||||
globalTradeSystem,
|
||||
expertPokemonBreeder
|
||||
},
|
||||
mysteryEncounterMessages
|
||||
};
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user