mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2024-12-01 19:26:16 +00:00
Merge branch 'beta' into evil-team-monogen
This commit is contained in:
commit
62042bf826
@ -1,6 +1,6 @@
|
||||
VITE_BYPASS_LOGIN=0
|
||||
VITE_BYPASS_TUTORIAL=0
|
||||
VITE_SERVER_URL=https://api.beta.pokerogue.net
|
||||
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/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1 +1 @@
|
||||
github: patapancakes
|
||||
github: pagefaultgames
|
||||
|
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);
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,11 @@ export default [
|
||||
"keyword-spacing": ["error", { "before": true, "after": true }], // Enforces spacing before and after keywords
|
||||
"comma-spacing": ["error", { "before": false, "after": true }], // Enforces spacing after comma
|
||||
"import-x/extensions": ["error", "never", { "json": "always" }], // Enforces no extension for imports unless json
|
||||
"array-bracket-spacing": ["error", "always", { "objectsInArrays": false, "arraysInArrays": false }], // Enforces consistent spacing inside array brackets
|
||||
"object-curly-spacing": ["error", "always", { "arraysInObjects": false, "objectsInObjects": false }], // Enforces consistent spacing inside braces of object literals, destructuring assignments, and import/export specifiers
|
||||
"computed-property-spacing": ["error", "never" ], // Enforces consistent spacing inside computed property brackets
|
||||
"space-infix-ops": ["error", { "int32Hint": false }], // Enforces spacing around infix operators
|
||||
"no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }], // Disallows multiple empty lines
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -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
|
51
package-lock.json
generated
51
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",
|
||||
@ -37,7 +38,7 @@
|
||||
"typedoc": "^0.26.4",
|
||||
"typescript": "^5.5.3",
|
||||
"typescript-eslint": "^8.0.0-alpha.54",
|
||||
"vite": "^5.3.5",
|
||||
"vite": "^5.4.8",
|
||||
"vite-tsconfig-paths": "^4.3.2",
|
||||
"vitest": "^2.0.4",
|
||||
"vitest-canvas-mock": "^0.3.3"
|
||||
@ -3650,7 +3651,6 @@
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
@ -4004,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"
|
||||
}
|
||||
@ -5042,7 +5043,6 @@
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
@ -5441,9 +5441,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.39",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz",
|
||||
"integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==",
|
||||
"version": "8.4.47",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
|
||||
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -5459,16 +5459,21 @@
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.7",
|
||||
"picocolors": "^1.0.1",
|
||||
"source-map-js": "^1.2.0"
|
||||
"picocolors": "^1.1.0",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss/node_modules/picocolors": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
|
||||
"integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
@ -5865,11 +5870,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
|
||||
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -6469,15 +6473,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.3.5",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.3.5.tgz",
|
||||
"integrity": "sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==",
|
||||
"version": "5.4.8",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
|
||||
"integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "^0.21.3",
|
||||
"postcss": "^8.4.39",
|
||||
"rollup": "^4.13.0"
|
||||
"postcss": "^8.4.43",
|
||||
"rollup": "^4.20.0"
|
||||
},
|
||||
"bin": {
|
||||
"vite": "bin/vite.js"
|
||||
@ -6496,6 +6499,7 @@
|
||||
"less": "*",
|
||||
"lightningcss": "^1.21.0",
|
||||
"sass": "*",
|
||||
"sass-embedded": "*",
|
||||
"stylus": "*",
|
||||
"sugarss": "*",
|
||||
"terser": "^5.4.0"
|
||||
@ -6513,6 +6517,9 @@
|
||||
"sass": {
|
||||
"optional": true
|
||||
},
|
||||
"sass-embedded": {
|
||||
"optional": true
|
||||
},
|
||||
"stylus": {
|
||||
"optional": true
|
||||
},
|
||||
|
@ -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",
|
||||
@ -41,7 +42,7 @@
|
||||
"typedoc": "^0.26.4",
|
||||
"typescript": "^5.5.3",
|
||||
"typescript-eslint": "^8.0.0-alpha.54",
|
||||
"vite": "^5.3.5",
|
||||
"vite": "^5.4.8",
|
||||
"vite-tsconfig-paths": "^4.3.2",
|
||||
"vitest": "^2.0.4",
|
||||
"vitest-canvas-mock": "^0.3.3"
|
||||
@ -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
|
14
src/@types/i18next.d.ts
vendored
14
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;
|
||||
}
|
||||
(key: string | string[], options?: TOptions & Record<string, unknown>): string;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ export function initLoggedInUser(): void {
|
||||
export function updateUserInfo(): Promise<[boolean, integer]> {
|
||||
return new Promise<[boolean, integer]>(resolve => {
|
||||
if (bypassLogin) {
|
||||
loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: "", hasAdminRole: false};
|
||||
loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: "", hasAdminRole: false };
|
||||
let lastSessionSlot = -1;
|
||||
for (let s = 0; s < 5; s++) {
|
||||
if (localStorage.getItem(`sessionData${s ? s : ""}_${loggedInUser.username}`)) {
|
||||
|
@ -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";
|
||||
@ -1040,10 +1040,6 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
this.gameMode = getGameMode(GameModes.CLASSIC);
|
||||
|
||||
this.setSeed(Overrides.SEED_OVERRIDE || Utils.randomString(24));
|
||||
console.log("Seed:", this.seed);
|
||||
this.resetSeed(); // Properly resets RNG after saving and quitting a session
|
||||
|
||||
this.disableMenu = false;
|
||||
|
||||
this.score = 0;
|
||||
@ -1078,6 +1074,12 @@ export default class BattleScene extends SceneBase {
|
||||
//@ts-ignore - allowing `null` for currentBattle causes a lot of trouble
|
||||
this.currentBattle = null; // TODO: resolve ts-ignore
|
||||
|
||||
// Reset RNG after end of game or save & quit.
|
||||
// This needs to happen after clearing this.currentBattle or the seed will be affected by the last wave played
|
||||
this.setSeed(Overrides.SEED_OVERRIDE || Utils.randomString(24));
|
||||
console.log("Seed:", this.seed);
|
||||
this.resetSeed();
|
||||
|
||||
this.biomeWaveText.setText(startingWave.toString());
|
||||
this.biomeWaveText.setVisible(false);
|
||||
|
||||
@ -1259,7 +1261,7 @@ export default class BattleScene extends SceneBase {
|
||||
const isEndlessFifthWave = this.gameMode.hasShortBiomes && (lastBattle.waveIndex % 5) === 0;
|
||||
const isWaveIndexMultipleOfFiftyMinusOne = (lastBattle.waveIndex % 50) === 49;
|
||||
const isNewBiome = isWaveIndexMultipleOfTen || isEndlessFifthWave || (isEndlessOrDaily && isWaveIndexMultipleOfFiftyMinusOne);
|
||||
const resetArenaState = isNewBiome || [BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(this.currentBattle.battleType) || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS;
|
||||
const resetArenaState = isNewBiome || [ BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER ].includes(this.currentBattle.battleType) || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS;
|
||||
this.getEnemyParty().forEach(enemyPokemon => enemyPokemon.destroy());
|
||||
this.trySpreadPokerus();
|
||||
if (!isNewBiome && (newWaveIndex % 10) === 5) {
|
||||
@ -1756,14 +1758,14 @@ export default class BattleScene extends SceneBase {
|
||||
if (fromArenaPool) {
|
||||
return this.arena.randomSpecies(waveIndex, level, undefined, getPartyLuckValue(this.party));
|
||||
}
|
||||
const filteredSpecies = speciesFilter ? [...new Set(allSpecies.filter(s => s.isCatchable()).filter(speciesFilter).map(s => {
|
||||
const filteredSpecies = speciesFilter ? [ ...new Set(allSpecies.filter(s => s.isCatchable()).filter(speciesFilter).map(s => {
|
||||
if (!filterAllEvolutions) {
|
||||
while (pokemonPrevolutions.hasOwnProperty(s.speciesId)) {
|
||||
s = getPokemonSpecies(pokemonPrevolutions[s.speciesId]);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}))] : allSpecies.filter(s => s.isCatchable());
|
||||
})) ] : allSpecies.filter(s => s.isCatchable());
|
||||
return filteredSpecies[Utils.randSeedInt(filteredSpecies.length)];
|
||||
}
|
||||
|
||||
@ -1883,14 +1885,14 @@ export default class BattleScene extends SceneBase {
|
||||
case "battle_anims":
|
||||
case "cry":
|
||||
if (soundDetails[1].startsWith("PRSFX- ")) {
|
||||
sound.setVolume(this.masterVolume*this.fieldVolume*0.5);
|
||||
sound.setVolume(this.masterVolume * this.fieldVolume * 0.5);
|
||||
} else {
|
||||
sound.setVolume(this.masterVolume*this.fieldVolume);
|
||||
sound.setVolume(this.masterVolume * this.fieldVolume);
|
||||
}
|
||||
break;
|
||||
case "se":
|
||||
case "ui":
|
||||
sound.setVolume(this.masterVolume*this.seVolume);
|
||||
sound.setVolume(this.masterVolume * this.seVolume);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2219,7 +2221,7 @@ export default class BattleScene extends SceneBase {
|
||||
*
|
||||
*/
|
||||
pushConditionalPhase(phase: Phase, condition: () => boolean): void {
|
||||
this.conditionalQueue.push([condition, phase]);
|
||||
this.conditionalQueue.push([ condition, phase ]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2443,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);
|
||||
@ -2470,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);
|
||||
@ -2483,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 {
|
||||
@ -2493,11 +2498,11 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.allSettled([this.party.map(p => p.updateInfo(instant)), ...modifierPromises]).then(() => resolve(success));
|
||||
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 {
|
||||
@ -2519,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);
|
||||
@ -2753,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;
|
||||
}
|
||||
@ -2771,38 +2782,66 @@ 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) {
|
||||
return mods;
|
||||
}
|
||||
const rand = Utils.randSeedInt(mods.length);
|
||||
return [mods[rand], ...shuffleModifiers(mods.filter((_, i) => i !== rand))];
|
||||
return [ mods[rand], ...shuffleModifiers(mods.filter((_, i) => i !== rand)) ];
|
||||
};
|
||||
modifiers = shuffleModifiers(modifiers);
|
||||
}, scene.currentBattle.turn << 4, scene.waveSeed);
|
||||
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);
|
||||
}
|
||||
@ -2811,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;
|
||||
}
|
||||
@ -2880,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);
|
||||
@ -2893,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);
|
||||
@ -2932,7 +2978,7 @@ export default class BattleScene extends SceneBase {
|
||||
keys.push(p.getBattleSpriteKey(true, true));
|
||||
keys.push("cry/" + p.species.getCryKey(p.formIndex));
|
||||
if (p.fusionSpecies) {
|
||||
keys.push("cry/"+p.fusionSpecies.getCryKey(p.fusionFormIndex));
|
||||
keys.push("cry/" + p.fusionSpecies.getCryKey(p.fusionFormIndex));
|
||||
}
|
||||
});
|
||||
// enemyParty has to be operated on separately from playerParty because playerPokemon =/= enemyPokemon
|
||||
@ -2941,7 +2987,7 @@ export default class BattleScene extends SceneBase {
|
||||
keys.push(p.getSpriteKey(true));
|
||||
keys.push("cry/" + p.species.getCryKey(p.formIndex));
|
||||
if (p.fusionSpecies) {
|
||||
keys.push("cry/"+p.fusionSpecies.getCryKey(p.fusionFormIndex));
|
||||
keys.push("cry/" + p.fusionSpecies.getCryKey(p.fusionFormIndex));
|
||||
}
|
||||
});
|
||||
return keys;
|
||||
@ -3089,13 +3135,8 @@ export default class BattleScene extends SceneBase {
|
||||
* @param sessionDataEncounterType
|
||||
*/
|
||||
private isWaveMysteryEncounter(newBattleType: BattleType, waveIndex: number, sessionDataEncounterType?: MysteryEncounterType): boolean {
|
||||
const [lowestMysteryEncounterWave, highestMysteryEncounterWave] = this.gameMode.getMysteryEncounterLegalWaves();
|
||||
const [ lowestMysteryEncounterWave, highestMysteryEncounterWave ] = this.gameMode.getMysteryEncounterLegalWaves();
|
||||
if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(waveIndex) && waveIndex < highestMysteryEncounterWave && waveIndex > lowestMysteryEncounterWave) {
|
||||
// If ME type is already defined in session data, no need to roll RNG check
|
||||
if (!isNullOrUndefined(sessionDataEncounterType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Base spawn weight is BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT/256, and increases by WEIGHT_INCREMENT_ON_SPAWN_MISS/256 for each missed attempt at spawning an encounter on a valid floor
|
||||
const sessionEncounterRate = this.mysteryEncounterSaveData.encounterSpawnChance;
|
||||
const encounteredEvents = this.mysteryEncounterSaveData.encounteredEvents;
|
||||
@ -3160,7 +3201,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
// See Enum values for base tier weights
|
||||
const tierWeights = [MysteryEncounterTier.COMMON, MysteryEncounterTier.GREAT, MysteryEncounterTier.ULTRA, MysteryEncounterTier.ROGUE];
|
||||
const tierWeights = [ MysteryEncounterTier.COMMON, MysteryEncounterTier.GREAT, MysteryEncounterTier.ULTRA, MysteryEncounterTier.ROGUE ];
|
||||
|
||||
// Adjust tier weights by previously encountered events to lower odds of only Common/Great in run
|
||||
this.mysteryEncounterSaveData.encounteredEvents.forEach(seenEncounterData => {
|
||||
|
@ -497,7 +497,7 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], rand
|
||||
}
|
||||
|
||||
/* 1/3 chance for evil team grunts to be double battles */
|
||||
const evilTeamGrunts = [TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT];
|
||||
const evilTeamGrunts = [ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ];
|
||||
const isEvilTeamGrunt = evilTeamGrunts.includes(trainerTypes[rand]);
|
||||
|
||||
if (trainerConfigs[trainerTypes[rand]].hasDouble && isEvilTeamGrunt) {
|
||||
@ -527,34 +527,34 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||
[25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }),
|
||||
[35]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)),
|
||||
[55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }),
|
||||
[62]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)),
|
||||
[64]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)),
|
||||
[66]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ] ], true)),
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true)),
|
||||
[95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }),
|
||||
[112]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)),
|
||||
[114]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ] ], true, 1)),
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true, 1)),
|
||||
[ClassicFixedBossWaves.EVIL_BOSS_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE, TrainerType.PENNY ]))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }),
|
||||
[145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }),
|
||||
[ClassicFixedBossWaves.EVIL_BOSS_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2, TrainerType.LUSAMINE_2, TrainerType.GUZMA_2, TrainerType.ROSE_2, TrainerType.PENNY_2 ]))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }),
|
||||
[182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])),
|
||||
[184]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182)
|
||||
@ -567,5 +567,5 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN ])),
|
||||
[195]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_6, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false })
|
||||
.setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false })
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {Button} from "#enums/buttons";
|
||||
import {SettingKeyboard} from "#app/system/settings/settings-keyboard";
|
||||
import { Button } from "#enums/buttons";
|
||||
import { SettingKeyboard } from "#app/system/settings/settings-keyboard";
|
||||
|
||||
const cfg_keyboard_qwerty = {
|
||||
padID: "default",
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Device} from "#enums/devices";
|
||||
import { Device } from "#enums/devices";
|
||||
|
||||
/**
|
||||
* Retrieves the key associated with the specified keycode from the mapping.
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {SettingGamepad} from "../../system/settings/settings-gamepad";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { SettingGamepad } from "../../system/settings/settings-gamepad";
|
||||
import { Button } from "#enums/buttons";
|
||||
|
||||
/**
|
||||
* Dualshock mapping
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {SettingGamepad} from "../../system/settings/settings-gamepad";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { SettingGamepad } from "../../system/settings/settings-gamepad";
|
||||
import { Button } from "#enums/buttons";
|
||||
|
||||
/**
|
||||
* Generic pad mapping
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {SettingGamepad} from "#app/system/settings/settings-gamepad";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { SettingGamepad } from "#app/system/settings/settings-gamepad";
|
||||
import { Button } from "#enums/buttons";
|
||||
|
||||
/**
|
||||
* Nintendo Pro Controller mapping
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {SettingGamepad} from "../../system/settings/settings-gamepad";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { SettingGamepad } from "../../system/settings/settings-gamepad";
|
||||
import { Button } from "#enums/buttons";
|
||||
|
||||
/**
|
||||
* 081f-e401 - UnlicensedSNES
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {SettingGamepad} from "../../system/settings/settings-gamepad";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { SettingGamepad } from "../../system/settings/settings-gamepad";
|
||||
import { Button } from "#enums/buttons";
|
||||
|
||||
/**
|
||||
* Generic pad mapping
|
||||
|
@ -4,7 +4,7 @@ import { Constructor } from "#app/utils";
|
||||
import * as Utils from "../utils";
|
||||
import { getPokemonNameWithAffix } from "../messages";
|
||||
import { Weather, WeatherType } from "./weather";
|
||||
import { BattlerTag, GroundedTag, GulpMissileTag, SemiInvulnerableTag } from "./battler-tags";
|
||||
import { BattlerTag, GroundedTag } from "./battler-tags";
|
||||
import { StatusEffect, getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText } from "./status-effect";
|
||||
import { Gender } from "./gender";
|
||||
import Move, { AttackMove, MoveCategory, MoveFlags, MoveTarget, FlinchAttr, OneHitKOAttr, HitHealAttr, allMoves, StatusMove, SelfStatusMove, VariablePowerAttr, applyMoveAttrs, IncrementMovePriorityAttr, VariableMoveTypeAttr, RandomMovesetMoveAttr, RandomMoveAttr, NaturePowerAttr, CopyMoveAttr, MoveAttr, MultiHitAttr, ChargeAttr, SacrificialAttr, SacrificialAttrOnHit, NeutralDamageAgainstFlyingTypeMultiplierAttr, FixedDamageAttr } from "./move";
|
||||
@ -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;
|
||||
@ -161,7 +162,7 @@ export class BlockRecoilDamageAttr extends AbAttr {
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]) {
|
||||
return i18next.t("abilityTriggers:blockRecoilDamage", {pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName});
|
||||
return i18next.t("abilityTriggers:blockRecoilDamage", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName });
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -536,53 +538,6 @@ export class PostDefendAbAttr extends AbAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the effects of Gulp Missile when the user is hit by an attack.
|
||||
* @extends PostDefendAbAttr
|
||||
*/
|
||||
export class PostDefendGulpMissileAbAttr extends PostDefendAbAttr {
|
||||
constructor() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Damages the attacker and triggers the secondary effect based on the form or the BattlerTagType.
|
||||
* @param {Pokemon} pokemon - The defending Pokemon.
|
||||
* @param passive - n/a
|
||||
* @param {Pokemon} attacker - The attacking Pokemon.
|
||||
* @param {Move} move - The move being used.
|
||||
* @param {HitResult} hitResult - n/a
|
||||
* @param {any[]} args - n/a
|
||||
* @returns Whether the effects of the ability are applied.
|
||||
*/
|
||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean | Promise<boolean> {
|
||||
const battlerTag = pokemon.getTag(GulpMissileTag);
|
||||
if (!battlerTag || move.category === MoveCategory.STATUS || pokemon.getTag(SemiInvulnerableTag)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (simulated) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
applyAbAttrs(BlockNonDirectDamageAbAttr, attacker, cancelled);
|
||||
|
||||
if (!cancelled.value) {
|
||||
attacker.damageAndUpdate(Math.max(1, Math.floor(attacker.getMaxHp() / 4)), HitResult.OTHER);
|
||||
}
|
||||
|
||||
if (battlerTag.tagType === BattlerTagType.GULP_MISSILE_ARROKUDA) {
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, attacker.getBattlerIndex(), false, [ Stat.DEF ], -1));
|
||||
} else {
|
||||
attacker.trySetStatus(StatusEffect.PARALYSIS, true, pokemon);
|
||||
}
|
||||
|
||||
pokemon.removeTag(battlerTag.tagType);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr {
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
const attackPriority = new Utils.IntegerHolder(move.priority);
|
||||
@ -1009,7 +964,7 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr {
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
return i18next.t("abilityTriggers:perishBody", {pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName});
|
||||
return i18next.t("abilityTriggers:perishBody", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1313,7 +1268,7 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr {
|
||||
if (pokemon.getTypes().some((t) => t !== moveType)) {
|
||||
if (!simulated) {
|
||||
this.moveType = moveType;
|
||||
pokemon.summonData.types = [moveType];
|
||||
pokemon.summonData.types = [ moveType ];
|
||||
pokemon.updateInfo();
|
||||
}
|
||||
|
||||
@ -2479,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();
|
||||
|
||||
|
||||
@ -2859,7 +2814,7 @@ export class PreApplyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr {
|
||||
constructor(immuneTagTypes: BattlerTagType | BattlerTagType[]) {
|
||||
super();
|
||||
|
||||
this.immuneTagTypes = Array.isArray(immuneTagTypes) ? immuneTagTypes : [immuneTagTypes];
|
||||
this.immuneTagTypes = Array.isArray(immuneTagTypes) ? immuneTagTypes : [ immuneTagTypes ];
|
||||
}
|
||||
|
||||
applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, simulated: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
@ -3144,17 +3099,17 @@ function getAnticipationCondition(): AbAttrCondition {
|
||||
// edge case for hidden power, type is computed
|
||||
if (move.getMove().id === Moves.HIDDEN_POWER) {
|
||||
const iv_val = Math.floor(((opponent.ivs[Stat.HP] & 1)
|
||||
+(opponent.ivs[Stat.ATK] & 1) * 2
|
||||
+(opponent.ivs[Stat.DEF] & 1) * 4
|
||||
+(opponent.ivs[Stat.SPD] & 1) * 8
|
||||
+(opponent.ivs[Stat.SPATK] & 1) * 16
|
||||
+(opponent.ivs[Stat.SPDEF] & 1) * 32) * 15/63);
|
||||
+ (opponent.ivs[Stat.ATK] & 1) * 2
|
||||
+ (opponent.ivs[Stat.DEF] & 1) * 4
|
||||
+ (opponent.ivs[Stat.SPD] & 1) * 8
|
||||
+ (opponent.ivs[Stat.SPATK] & 1) * 16
|
||||
+ (opponent.ivs[Stat.SPDEF] & 1) * 32) * 15 / 63);
|
||||
|
||||
const type = [
|
||||
Type.FIGHTING, Type.FLYING, Type.POISON, Type.GROUND,
|
||||
Type.ROCK, Type.BUG, Type.GHOST, Type.STEEL,
|
||||
Type.FIRE, Type.WATER, Type.GRASS, Type.ELECTRIC,
|
||||
Type.PSYCHIC, Type.ICE, Type.DRAGON, Type.DARK][iv_val];
|
||||
Type.PSYCHIC, Type.ICE, Type.DRAGON, Type.DARK ][iv_val];
|
||||
|
||||
if (pokemon.getAttackTypeEffectiveness(type, opponent) >= 2) {
|
||||
return true;
|
||||
@ -3199,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() ?? "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3689,7 +3644,7 @@ export class PostTurnHurtIfSleepingAbAttr extends PostTurnAbAttr {
|
||||
if ((opp.status?.effect === StatusEffect.SLEEP || opp.hasAbility(Abilities.COMATOSE)) && !opp.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) {
|
||||
if (!simulated) {
|
||||
opp.damageAndUpdate(Utils.toDmgValue(opp.getMaxHp() / 8), HitResult.OTHER);
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:badDreams", {pokemonName: getPokemonNameWithAffix(opp)}));
|
||||
pokemon.scene.queueMessage(i18next.t("abilityTriggers:badDreams", { pokemonName: getPokemonNameWithAffix(opp) }));
|
||||
}
|
||||
hadEffect = true;
|
||||
}
|
||||
@ -3800,8 +3755,8 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
|
||||
*/
|
||||
applyPostMoveUsed(dancer: Pokemon, move: PokemonMove, source: Pokemon, targets: BattlerIndex[], simulated: boolean, args: any[]): boolean | Promise<boolean> {
|
||||
// List of tags that prevent the Dancer from replicating the move
|
||||
const forbiddenTags = [BattlerTagType.FLYING, BattlerTagType.UNDERWATER,
|
||||
BattlerTagType.UNDERGROUND, BattlerTagType.HIDDEN];
|
||||
const forbiddenTags = [ BattlerTagType.FLYING, BattlerTagType.UNDERWATER,
|
||||
BattlerTagType.UNDERGROUND, BattlerTagType.HIDDEN ];
|
||||
// The move to replicate cannot come from the Dancer
|
||||
if (source.getBattlerIndex() !== dancer.getBattlerIndex()
|
||||
&& !dancer.summonData.tags.some(tag => forbiddenTags.includes(tag.tagType))) {
|
||||
@ -3812,7 +3767,7 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
|
||||
dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, target, move, true, true));
|
||||
} else if (move.getMove() instanceof SelfStatusMove) {
|
||||
// If the move is a SelfStatusMove (ie. Swords Dance) the Dancer should replicate it on itself
|
||||
dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, [dancer.getBattlerIndex()], move, true, true));
|
||||
dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, [ dancer.getBattlerIndex() ], move, true, true));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -3829,9 +3784,9 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
|
||||
*/
|
||||
getTarget(dancer: Pokemon, source: Pokemon, targets: BattlerIndex[]) : BattlerIndex[] {
|
||||
if (dancer.isPlayer()) {
|
||||
return source.isPlayer() ? targets : [source.getBattlerIndex()];
|
||||
return source.isPlayer() ? targets : [ source.getBattlerIndex() ];
|
||||
}
|
||||
return source.isPlayer() ? [source.getBattlerIndex()] : targets;
|
||||
return source.isPlayer() ? [ source.getBattlerIndex() ] : targets;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4606,7 +4561,7 @@ export class BypassSpeedChanceAbAttr extends AbAttr {
|
||||
const turnCommand =
|
||||
pokemon.scene.currentBattle.turnCommands[pokemon.getBattlerIndex()];
|
||||
const isCommandFight = turnCommand?.command === Command.FIGHT;
|
||||
const move = turnCommand?.move?.move ?allMoves[turnCommand.move.move] : null;
|
||||
const move = turnCommand?.move?.move ? allMoves[turnCommand.move.move] : null;
|
||||
const isDamageMove = move?.category === MoveCategory.PHYSICAL || move?.category === MoveCategory.SPECIAL;
|
||||
|
||||
if (isCommandFight && isDamageMove) {
|
||||
@ -4619,7 +4574,7 @@ export class BypassSpeedChanceAbAttr extends AbAttr {
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
return i18next.t("abilityTriggers:quickDraw", {pokemonName: getPokemonNameWithAffix(pokemon)});
|
||||
return i18next.t("abilityTriggers:quickDraw", { pokemonName: getPokemonNameWithAffix(pokemon) });
|
||||
}
|
||||
}
|
||||
|
||||
@ -4667,7 +4622,7 @@ async function applyAbAttrsInternal<TAttr extends AbAttr>(
|
||||
simulated: boolean = false,
|
||||
messages: string[] = [],
|
||||
) {
|
||||
for (const passive of [false, true]) {
|
||||
for (const passive of [ false, true ]) {
|
||||
if (!pokemon?.canApplyAbility(passive)) {
|
||||
continue;
|
||||
}
|
||||
@ -4917,7 +4872,7 @@ export function initAbilities() {
|
||||
.attr(TypeImmunityHealAbAttr, Type.WATER)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.OBLIVIOUS, 3)
|
||||
.attr(BattlerTagImmunityAbAttr, [BattlerTagType.INFATUATED, BattlerTagType.TAUNT])
|
||||
.attr(BattlerTagImmunityAbAttr, [ BattlerTagType.INFATUATED, BattlerTagType.TAUNT ])
|
||||
.attr(IntimidateImmunityAbAttr)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.CLOUD_NINE, 3)
|
||||
@ -5062,10 +5017,10 @@ export function initAbilities() {
|
||||
new Ability(Abilities.CUTE_CHARM, 3)
|
||||
.attr(PostDefendContactApplyTagChanceAbAttr, 30, BattlerTagType.INFATUATED),
|
||||
new Ability(Abilities.PLUS, 3)
|
||||
.conditionalAttr(p => p.scene.currentBattle.double && [Abilities.PLUS, Abilities.MINUS].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5)
|
||||
.conditionalAttr(p => p.scene.currentBattle.double && [ Abilities.PLUS, Abilities.MINUS ].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.MINUS, 3)
|
||||
.conditionalAttr(p => p.scene.currentBattle.double && [Abilities.PLUS, Abilities.MINUS].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5)
|
||||
.conditionalAttr(p => p.scene.currentBattle.double && [ Abilities.PLUS, Abilities.MINUS ].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.FORECAST, 3)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
@ -5183,7 +5138,7 @@ export function initAbilities() {
|
||||
.conditionalAttr(pokemon => !!pokemon.status || pokemon.hasAbility(Abilities.COMATOSE), StatMultiplierAbAttr, Stat.SPD, 1.5),
|
||||
new Ability(Abilities.NORMALIZE, 4)
|
||||
.attr(MoveTypeChangeAbAttr, Type.NORMAL, 1.2, (user, target, move) => {
|
||||
return ![Moves.HIDDEN_POWER, Moves.WEATHER_BALL, Moves.NATURAL_GIFT, Moves.JUDGMENT, Moves.TECHNO_BLAST].includes(move.id);
|
||||
return ![ Moves.HIDDEN_POWER, Moves.WEATHER_BALL, Moves.NATURAL_GIFT, Moves.JUDGMENT, Moves.TECHNO_BLAST ].includes(move.id);
|
||||
}),
|
||||
new Ability(Abilities.SNIPER, 4)
|
||||
.attr(MultCritAbAttr, 1.5),
|
||||
@ -5210,8 +5165,7 @@ export function initAbilities() {
|
||||
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonMoldBreaker", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
||||
.attr(MoveAbilityBypassAbAttr),
|
||||
new Ability(Abilities.SUPER_LUCK, 4)
|
||||
.attr(BonusCritAbAttr)
|
||||
.partial(),
|
||||
.attr(BonusCritAbAttr),
|
||||
new Ability(Abilities.AFTERMATH, 4)
|
||||
.attr(PostFaintContactDamageAbAttr, 4)
|
||||
.bypassFaint(),
|
||||
@ -5223,15 +5177,14 @@ 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(),
|
||||
new Ability(Abilities.SLOW_START, 4)
|
||||
.attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.SLOW_START, 5),
|
||||
new Ability(Abilities.SCRAPPY, 4)
|
||||
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [Type.NORMAL, Type.FIGHTING])
|
||||
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ])
|
||||
.attr(IntimidateImmunityAbAttr),
|
||||
new Ability(Abilities.STORM_DRAIN, 4)
|
||||
.attr(RedirectTypeMoveAbAttr, Type.WATER)
|
||||
@ -5272,7 +5225,7 @@ export function initAbilities() {
|
||||
.attr(PostDefendStealHeldItemAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT))
|
||||
.condition(getSheerForceHitDisableAbCondition()),
|
||||
new Ability(Abilities.SHEER_FORCE, 5)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 5461/4096)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 5461 / 4096)
|
||||
.attr(MoveEffectChanceMultiplierAbAttr, 0)
|
||||
.partial(),
|
||||
new Ability(Abilities.CONTRARY, 5)
|
||||
@ -5281,7 +5234,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.UNNERVE, 5)
|
||||
.attr(PreventBerryUseAbAttr),
|
||||
new Ability(Abilities.DEFIANT, 5)
|
||||
.attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [Stat.ATK], 2),
|
||||
.attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [ Stat.ATK ], 2),
|
||||
new Ability(Abilities.DEFEATIST, 5)
|
||||
.attr(StatMultiplierAbAttr, Stat.ATK, 0.5)
|
||||
.attr(StatMultiplierAbAttr, Stat.SPATK, 0.5)
|
||||
@ -5342,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)
|
||||
@ -5366,7 +5320,7 @@ export function initAbilities() {
|
||||
return move.category !== MoveCategory.STATUS
|
||||
&& (moveType === Type.DARK || moveType === Type.BUG || moveType === Type.GHOST);
|
||||
}, Stat.SPD, 1)
|
||||
.attr(PostIntimidateStatStageChangeAbAttr, [Stat.SPD], 1),
|
||||
.attr(PostIntimidateStatStageChangeAbAttr, [ Stat.SPD ], 1),
|
||||
new Ability(Abilities.MAGIC_BOUNCE, 5)
|
||||
.ignorable()
|
||||
.unimplemented(),
|
||||
@ -5403,12 +5357,12 @@ export function initAbilities() {
|
||||
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonTeravolt", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
||||
.attr(MoveAbilityBypassAbAttr),
|
||||
new Ability(Abilities.AROMA_VEIL, 6)
|
||||
.attr(UserFieldBattlerTagImmunityAbAttr, [BattlerTagType.INFATUATED, BattlerTagType.TAUNT, BattlerTagType.DISABLED, BattlerTagType.TORMENT, BattlerTagType.HEAL_BLOCK]),
|
||||
.attr(UserFieldBattlerTagImmunityAbAttr, [ BattlerTagType.INFATUATED, BattlerTagType.TAUNT, BattlerTagType.DISABLED, BattlerTagType.TORMENT, BattlerTagType.HEAL_BLOCK ]),
|
||||
new Ability(Abilities.FLOWER_VEIL, 6)
|
||||
.ignorable()
|
||||
.unimplemented(),
|
||||
new Ability(Abilities.CHEEK_POUCH, 6)
|
||||
.attr(HealFromBerryUseAbAttr, 1/3),
|
||||
.attr(HealFromBerryUseAbAttr, 1 / 3),
|
||||
new Ability(Abilities.PROTEAN, 6)
|
||||
.attr(PokemonTypeChangeAbAttr),
|
||||
//.condition((p) => !p.summonData?.abilitiesApplied.includes(Abilities.PROTEAN)), //Gen 9 Implementation
|
||||
@ -5421,7 +5375,7 @@ export function initAbilities() {
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.BALLBOMB_MOVE))
|
||||
.ignorable(),
|
||||
new Ability(Abilities.COMPETITIVE, 6)
|
||||
.attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [Stat.SPATK], 2),
|
||||
.attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [ Stat.SPATK ], 2),
|
||||
new Ability(Abilities.STRONG_JAW, 6)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.BITING_MOVE), 1.5),
|
||||
new Ability(Abilities.REFRIGERATE, 6)
|
||||
@ -5508,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)
|
||||
@ -5518,7 +5471,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.STEELWORKER, 7)
|
||||
.attr(MoveTypePowerBoostAbAttr, Type.STEEL),
|
||||
new Ability(Abilities.BERSERK, 7)
|
||||
.attr(PostDefendHpGatedStatStageChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [Stat.SPATK], 1)
|
||||
.attr(PostDefendHpGatedStatStageChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [ Stat.SPATK ], 1)
|
||||
.condition(getSheerForceHitDisableAbCondition()),
|
||||
new Ability(Abilities.SLUSH_RUSH, 7)
|
||||
.attr(StatMultiplierAbAttr, Stat.SPD, 2)
|
||||
@ -5575,7 +5528,7 @@ export function initAbilities() {
|
||||
.bypassFaint()
|
||||
.partial(),
|
||||
new Ability(Abilities.CORROSION, 7) // TODO: Test Corrosion against Magic Bounce once it is implemented
|
||||
.attr(IgnoreTypeStatusEffectImmunityAbAttr, [StatusEffect.POISON, StatusEffect.TOXIC], [Type.STEEL, Type.POISON])
|
||||
.attr(IgnoreTypeStatusEffectImmunityAbAttr, [ StatusEffect.POISON, StatusEffect.TOXIC ], [ Type.STEEL, Type.POISON ])
|
||||
.partial(),
|
||||
new Ability(Abilities.COMATOSE, 7)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
@ -5592,7 +5545,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.DANCER, 7)
|
||||
.attr(PostDancingMoveAbAttr),
|
||||
new Ability(Abilities.BATTERY, 7)
|
||||
.attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL], 1.3),
|
||||
.attr(AllyMoveCategoryPowerBoostAbAttr, [ MoveCategory.SPECIAL ], 1.3),
|
||||
new Ability(Abilities.FLUFFY, 7)
|
||||
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 0.5)
|
||||
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => user.getMoveType(move) === Type.FIRE, 2)
|
||||
@ -5647,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)),
|
||||
@ -5669,13 +5621,19 @@ export function initAbilities() {
|
||||
new Ability(Abilities.MIRROR_ARMOR, 8)
|
||||
.ignorable()
|
||||
.unimplemented(),
|
||||
/**
|
||||
* Right now, the logic is attached to Surf and Dive moves. Ideally, the post-defend/hit should be an
|
||||
* ability attribute but the current implementation of move effects for BattlerTag does not support this- in the case
|
||||
* where Cramorant is fainted.
|
||||
* @see {@linkcode GulpMissileTagAttr} and {@linkcode GulpMissileTag} for Gulp Missile implementation
|
||||
*/
|
||||
new Ability(Abilities.GULP_MISSILE, 8)
|
||||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(PostDefendGulpMissileAbAttr),
|
||||
.bypassFaint(),
|
||||
new Ability(Abilities.STALWART, 8)
|
||||
.attr(BlockRedirectAbAttr),
|
||||
new Ability(Abilities.STEAM_ENGINE, 8)
|
||||
@ -5713,11 +5671,11 @@ export function initAbilities() {
|
||||
.bypassFaint()
|
||||
.ignorable(),
|
||||
new Ability(Abilities.POWER_SPOT, 8)
|
||||
.attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL], 1.3),
|
||||
.attr(AllyMoveCategoryPowerBoostAbAttr, [ MoveCategory.SPECIAL, MoveCategory.PHYSICAL ], 1.3),
|
||||
new Ability(Abilities.MIMICRY, 8)
|
||||
.unimplemented(),
|
||||
new Ability(Abilities.SCREEN_CLEANER, 8)
|
||||
.attr(PostSummonRemoveArenaTagAbAttr, [ArenaTagType.AURORA_VEIL, ArenaTagType.LIGHT_SCREEN, ArenaTagType.REFLECT]),
|
||||
.attr(PostSummonRemoveArenaTagAbAttr, [ ArenaTagType.AURORA_VEIL, ArenaTagType.LIGHT_SCREEN, ArenaTagType.REFLECT ]),
|
||||
new Ability(Abilities.STEELY_SPIRIT, 8)
|
||||
.attr(UserFieldMoveTypePowerBoostAbAttr, Type.STEEL),
|
||||
new Ability(Abilities.PERISH_BODY, 8)
|
||||
@ -5740,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)
|
||||
@ -5802,7 +5758,7 @@ export function initAbilities() {
|
||||
.attr(PostSummonStatStageChangeOnArenaAbAttr, ArenaTagType.TAILWIND)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.GUARD_DOG, 9)
|
||||
.attr(PostIntimidateStatStageChangeAbAttr, [Stat.ATK], 1, true)
|
||||
.attr(PostIntimidateStatStageChangeAbAttr, [ Stat.ATK ], 1, true)
|
||||
.attr(ForceSwitchOutImmunityAbAttr)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.ROCKY_PAYLOAD, 9)
|
||||
@ -5891,7 +5847,7 @@ export function initAbilities() {
|
||||
.attr(PreventBypassSpeedChanceAbAttr, (pokemon, move) => move.category === MoveCategory.STATUS)
|
||||
.attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS),
|
||||
new Ability(Abilities.MINDS_EYE, 9)
|
||||
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [Type.NORMAL, Type.FIGHTING])
|
||||
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ])
|
||||
.attr(ProtectStatAbAttr, Stat.ACC)
|
||||
.attr(IgnoreOpponentStatStagesAbAttr, [ Stat.EVA ])
|
||||
.ignorable(),
|
||||
|
@ -135,7 +135,7 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
||||
*/
|
||||
apply(arena: Arena, args: any[]): boolean {
|
||||
if (this.weakenedCategories.includes((args[0] as MoveCategory))) {
|
||||
(args[2] as Utils.NumberHolder).value = (args[1] as boolean) ? 2732/4096 : 0.5;
|
||||
(args[2] as Utils.NumberHolder).value = (args[1] as boolean) ? 2732 / 4096 : 0.5;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -148,7 +148,7 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
||||
*/
|
||||
class ReflectTag extends WeakenMoveScreenTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side, [MoveCategory.PHYSICAL]);
|
||||
super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side, [ MoveCategory.PHYSICAL ]);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
@ -164,7 +164,7 @@ class ReflectTag extends WeakenMoveScreenTag {
|
||||
*/
|
||||
class LightScreenTag extends WeakenMoveScreenTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side, [MoveCategory.SPECIAL]);
|
||||
super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side, [ MoveCategory.SPECIAL ]);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
@ -180,7 +180,7 @@ class LightScreenTag extends WeakenMoveScreenTag {
|
||||
*/
|
||||
class AuroraVeilTag extends WeakenMoveScreenTag {
|
||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
||||
super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL]);
|
||||
super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side, [ MoveCategory.SPECIAL, MoveCategory.PHYSICAL ]);
|
||||
}
|
||||
|
||||
onAdd(arena: Arena, quiet: boolean = false): void {
|
||||
@ -511,6 +511,39 @@ class WaterSportTag extends WeakenMoveTypeTag {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Arena Tag class for the secondary effect of {@link https://bulbapedia.bulbagarden.net/wiki/Plasma_Fists_(move) | Plasma Fists}.
|
||||
* Converts Normal-type moves to Electric type for the rest of the turn.
|
||||
*/
|
||||
export class PlasmaFistsTag extends ArenaTag {
|
||||
constructor() {
|
||||
super(ArenaTagType.PLASMA_FISTS, 1, Moves.PLASMA_FISTS);
|
||||
}
|
||||
|
||||
/** Queues Plasma Fists' on-add message */
|
||||
onAdd(arena: Arena): void {
|
||||
arena.scene.queueMessage(i18next.t("arenaTag:plasmaFistsOnAdd"));
|
||||
}
|
||||
|
||||
onRemove(arena: Arena): void { } // Removes default on-remove message
|
||||
|
||||
/**
|
||||
* Converts Normal-type moves to Electric type
|
||||
* @param arena n/a
|
||||
* @param args
|
||||
* - `[0]` {@linkcode Utils.NumberHolder} A container with a move's {@linkcode Type}
|
||||
* @returns `true` if the given move type changed; `false` otherwise.
|
||||
*/
|
||||
apply(arena: Arena, args: any[]): boolean {
|
||||
const moveType = args[0];
|
||||
if (moveType instanceof Utils.NumberHolder && moveType.value === Type.NORMAL) {
|
||||
moveType.value = Type.ELECTRIC;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract class to implement arena traps.
|
||||
*/
|
||||
@ -955,7 +988,7 @@ class ImprisonTag extends ArenaTrapTag {
|
||||
party?.forEach((p: PlayerPokemon | EnemyPokemon ) => {
|
||||
p.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId);
|
||||
});
|
||||
scene.queueMessage(i18next.t("battlerTags:imprisonOnAdd", {pokemonNameWithAffix: getPokemonNameWithAffix(this.source)}));
|
||||
scene.queueMessage(i18next.t("battlerTags:imprisonOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(this.source) }));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1010,6 +1043,8 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov
|
||||
return new MudSportTag(turnCount, sourceId);
|
||||
case ArenaTagType.WATER_SPORT:
|
||||
return new WaterSportTag(turnCount, sourceId);
|
||||
case ArenaTagType.PLASMA_FISTS:
|
||||
return new PlasmaFistsTag();
|
||||
case ArenaTagType.SPIKES:
|
||||
return new SpikesTag(sourceId, side);
|
||||
case ArenaTagType.TOXIC_SPIKES:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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";
|
||||
|
||||
@ -81,7 +81,7 @@ export const speciesEggMoves = {
|
||||
[Species.LEDYBA]: [ Moves.POLLEN_PUFF, Moves.THIEF, Moves.PARTING_SHOT, Moves.SPORE ],
|
||||
[Species.SPINARAK]: [ Moves.PARTING_SHOT, Moves.ATTACK_ORDER, Moves.GASTRO_ACID, Moves.STRENGTH_SAP ],
|
||||
[Species.CHINCHOU]: [ Moves.THUNDERCLAP, Moves.BOUNCY_BUBBLE, Moves.THUNDER_CAGE, Moves.TAIL_GLOW ],
|
||||
[Species.PICHU]: [ Moves.MOONBLAST, Moves.WAVE_CRASH, Moves.AIR_SLASH, Moves.AURA_WHEEL ],
|
||||
[Species.PICHU]: [ Moves.MOONBLAST, Moves.TRIPLE_AXEL, Moves.FIERY_DANCE, Moves.AURA_WHEEL ],
|
||||
[Species.CLEFFA]: [ Moves.CALM_MIND, Moves.EARTH_POWER, Moves.WISH, Moves.LIGHT_OF_RUIN ],
|
||||
[Species.IGGLYBUFF]: [ Moves.DRAIN_PUNCH, Moves.GRAV_APPLE, Moves.SOFT_BOILED, Moves.EXTREME_SPEED ],
|
||||
[Species.TOGEPI]: [ Moves.SCORCHING_SANDS, Moves.ROOST, Moves.RELIC_SONG, Moves.FIERY_DANCE ],
|
||||
@ -195,7 +195,7 @@ export const speciesEggMoves = {
|
||||
[Species.REGISTEEL]: [ Moves.BODY_PRESS, Moves.SIZZLY_SLIDE, Moves.RECOVER, Moves.GIGATON_HAMMER ],
|
||||
[Species.LATIAS]: [ Moves.CORE_ENFORCER, Moves.FUSION_FLARE, Moves.SPARKLY_SWIRL, Moves.MYSTICAL_POWER ],
|
||||
[Species.LATIOS]: [ Moves.CORE_ENFORCER, Moves.BLUE_FLARE, Moves.NASTY_PLOT, Moves.TACHYON_CUTTER ],
|
||||
[Species.KYOGRE]: [ Moves.RECOVER, Moves.HURRICANE, Moves.FLIP_TURN, Moves.WILDBOLT_STORM ],
|
||||
[Species.KYOGRE]: [ Moves.RECOVER, Moves.HURRICANE, Moves.FREEZY_FROST, Moves.WILDBOLT_STORM ],
|
||||
[Species.GROUDON]: [ Moves.STONE_AXE, Moves.SOLAR_BLADE, Moves.MORNING_SUN, Moves.SACRED_FIRE ],
|
||||
[Species.RAYQUAZA]: [ Moves.V_CREATE, Moves.DRAGON_DARTS, Moves.CORE_ENFORCER, Moves.OBLIVION_WING ],
|
||||
[Species.JIRACHI]: [ Moves.TACHYON_CUTTER, Moves.TRIPLE_ARROWS, Moves.ROCK_SLIDE, Moves.SHELL_SMASH ],
|
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,16 +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,
|
||||
@ -1647,8 +1649,14 @@ export const pokemonEvolutions: PokemonEvolutions = {
|
||||
new SpeciesEvolution(Species.FROSMOTH, 1, null, new SpeciesFriendshipEvolutionCondition(90, p => p.scene.arena.getTimeOfDay() === TimeOfDay.DUSK || p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT), SpeciesWildEvolutionDelay.MEDIUM)
|
||||
],
|
||||
[Species.GIMMIGHOUL]: [
|
||||
new SpeciesFormEvolution(Species.GHOLDENGO, "chest", "", 1, null, new SpeciesEvolutionCondition( p => p.evoCounter > 9 ), SpeciesWildEvolutionDelay.VERY_LONG),
|
||||
new SpeciesFormEvolution(Species.GHOLDENGO, "roaming", "", 1, null, new SpeciesEvolutionCondition( p => p.evoCounter > 9 ), SpeciesWildEvolutionDelay.VERY_LONG)
|
||||
new SpeciesFormEvolution(Species.GHOLDENGO, "chest", "", 1, null, new SpeciesEvolutionCondition(p => p.evoCounter
|
||||
+ p.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length
|
||||
+ p.scene.findModifiers(m => m instanceof MoneyMultiplierModifier
|
||||
|| m instanceof ExtraModifierModifier).length > 9), SpeciesWildEvolutionDelay.VERY_LONG),
|
||||
new SpeciesFormEvolution(Species.GHOLDENGO, "roaming", "", 1, null, new SpeciesEvolutionCondition(p => p.evoCounter
|
||||
+ p.getHeldItems().filter(m => m instanceof DamageMoneyRewardModifier).length
|
||||
+ p.scene.findModifiers(m => m instanceof MoneyMultiplierModifier
|
||||
|| m instanceof ExtraModifierModifier).length > 9), SpeciesWildEvolutionDelay.VERY_LONG)
|
||||
]
|
||||
};
|
||||
|
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";
|
||||
|
@ -556,7 +556,7 @@ function logMissingMoveAnim(move: Moves, ...optionalParams: any[]) {
|
||||
* @param encounterAnim one or more animations to fetch
|
||||
*/
|
||||
export async function initEncounterAnims(scene: BattleScene, encounterAnim: EncounterAnim | EncounterAnim[]): Promise<void> {
|
||||
const anims = Array.isArray(encounterAnim) ? encounterAnim : [encounterAnim];
|
||||
const anims = Array.isArray(encounterAnim) ? encounterAnim : [ encounterAnim ];
|
||||
const encounterAnimNames = Utils.getEnumKeys(EncounterAnim);
|
||||
const encounterAnimFetches: Promise<Map<EncounterAnim, AnimConfig>>[] = [];
|
||||
for (const anim of anims) {
|
||||
@ -774,9 +774,9 @@ export abstract class BattleAnim {
|
||||
|
||||
private getGraphicFrameData(scene: BattleScene, frames: AnimFrame[], onSubstitute?: boolean): Map<integer, Map<AnimFrameTarget, GraphicFrameData>> {
|
||||
const ret: Map<integer, Map<AnimFrameTarget, GraphicFrameData>> = new Map([
|
||||
[AnimFrameTarget.GRAPHIC, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[AnimFrameTarget.USER, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[AnimFrameTarget.TARGET, new Map<AnimFrameTarget, GraphicFrameData>() ]
|
||||
[ AnimFrameTarget.GRAPHIC, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[ AnimFrameTarget.USER, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[ AnimFrameTarget.TARGET, new Map<AnimFrameTarget, GraphicFrameData>() ]
|
||||
]);
|
||||
|
||||
const isOppAnim = this.isOppAnim();
|
||||
@ -1093,9 +1093,9 @@ export abstract class BattleAnim {
|
||||
|
||||
private getGraphicFrameDataWithoutTarget(frames: AnimFrame[], targetInitialX: number, targetInitialY: number): Map<integer, Map<AnimFrameTarget, GraphicFrameData>> {
|
||||
const ret: Map<integer, Map<AnimFrameTarget, GraphicFrameData>> = new Map([
|
||||
[AnimFrameTarget.GRAPHIC, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[AnimFrameTarget.USER, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[AnimFrameTarget.TARGET, new Map<AnimFrameTarget, GraphicFrameData>() ]
|
||||
[ AnimFrameTarget.GRAPHIC, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[ AnimFrameTarget.USER, new Map<AnimFrameTarget, GraphicFrameData>() ],
|
||||
[ AnimFrameTarget.TARGET, new Map<AnimFrameTarget, GraphicFrameData>() ]
|
||||
]);
|
||||
|
||||
let g = 0;
|
||||
|
@ -363,7 +363,7 @@ export class RechargingTag extends BattlerTag {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
// Queue a placeholder move for the Pokemon to "use" next turn
|
||||
pokemon.getMoveQueue().push({ move: Moves.NONE, targets: [] });
|
||||
pokemon.getMoveQueue().push({ move: Moves.NONE, targets: []});
|
||||
}
|
||||
|
||||
/** Cancels the source's move this turn and queues a "__ must recharge!" message */
|
||||
@ -569,7 +569,7 @@ export class InterruptedTag extends BattlerTag {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.getMoveQueue().shift();
|
||||
pokemon.pushMoveHistory({move: Moves.NONE, result: MoveResult.OTHER});
|
||||
pokemon.pushMoveHistory({ move: Moves.NONE, result: MoveResult.OTHER });
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
@ -1935,10 +1935,10 @@ export class RoostedTag extends BattlerTag {
|
||||
modifiedTypes = currentTypes.filter(type => type !== Type.NORMAL);
|
||||
modifiedTypes.push(Type.FLYING);
|
||||
} else {
|
||||
modifiedTypes = [Type.FLYING];
|
||||
modifiedTypes = [ Type.FLYING ];
|
||||
}
|
||||
} else {
|
||||
modifiedTypes = [...currentTypes];
|
||||
modifiedTypes = [ ...currentTypes ];
|
||||
modifiedTypes.push(Type.FLYING);
|
||||
}
|
||||
pokemon.summonData.types = modifiedTypes;
|
||||
@ -1958,10 +1958,10 @@ export class RoostedTag extends BattlerTag {
|
||||
if (this.isBaseFlying) {
|
||||
let modifiedTypes: Type[];
|
||||
if (this.isBasePureFlying && !isCurrentlyDualType) {
|
||||
modifiedTypes = [Type.NORMAL];
|
||||
modifiedTypes = [ Type.NORMAL ];
|
||||
} else {
|
||||
if (!!pokemon.getTag(RemovedTypeTag) && isOriginallyDualType && !isCurrentlyDualType) {
|
||||
modifiedTypes = [Type.UNKNOWN];
|
||||
modifiedTypes = [ Type.UNKNOWN ];
|
||||
} else {
|
||||
modifiedTypes = currentTypes.filter(type => type !== Type.FLYING);
|
||||
}
|
||||
@ -2067,8 +2067,8 @@ export class StockpilingTag extends BattlerTag {
|
||||
super.loadTag(source);
|
||||
this.stockpiledCount = source.stockpiledCount || 0;
|
||||
this.statChangeCounts = {
|
||||
[ Stat.DEF ]: source.statChangeCounts?.[ Stat.DEF ] ?? 0,
|
||||
[ Stat.SPDEF ]: source.statChangeCounts?.[ Stat.SPDEF ] ?? 0,
|
||||
[Stat.DEF]: source.statChangeCounts?.[Stat.DEF] ?? 0,
|
||||
[Stat.SPDEF]: source.statChangeCounts?.[Stat.SPDEF] ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
@ -2090,7 +2090,7 @@ export class StockpilingTag extends BattlerTag {
|
||||
// Attempt to increase DEF and SPDEF by one stage, keeping track of successful changes.
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(
|
||||
pokemon.scene, pokemon.getBattlerIndex(), true,
|
||||
[Stat.SPDEF, Stat.DEF], 1, true, false, true, this.onStatStagesChanged
|
||||
[ Stat.SPDEF, Stat.DEF ], 1, true, false, true, this.onStatStagesChanged
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -2123,7 +2123,36 @@ export class StockpilingTag extends BattlerTag {
|
||||
*/
|
||||
export class GulpMissileTag extends BattlerTag {
|
||||
constructor(tagType: BattlerTagType, sourceMove: Moves) {
|
||||
super(tagType, BattlerTagLapseType.CUSTOM, 0, sourceMove);
|
||||
super(tagType, BattlerTagLapseType.HIT, 0, sourceMove);
|
||||
}
|
||||
|
||||
override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
if (pokemon.getTag(BattlerTagType.UNDERWATER)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const moveEffectPhase = pokemon.scene.getCurrentPhase();
|
||||
if (moveEffectPhase instanceof MoveEffectPhase) {
|
||||
const attacker = moveEffectPhase.getUserPokemon();
|
||||
|
||||
if (!attacker) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
applyAbAttrs(BlockNonDirectDamageAbAttr, attacker, cancelled);
|
||||
|
||||
if (!cancelled.value) {
|
||||
attacker.damageAndUpdate(Math.max(1, Math.floor(attacker.getMaxHp() / 4)), HitResult.OTHER);
|
||||
}
|
||||
|
||||
if (this.tagType === BattlerTagType.GULP_MISSILE_ARROKUDA) {
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, attacker.getBattlerIndex(), false, [ Stat.DEF ], -1));
|
||||
} else {
|
||||
attacker.trySetStatus(StatusEffect.PARALYSIS, true, pokemon);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2238,7 +2267,7 @@ export class HealBlockTag extends MoveRestrictionBattlerTag {
|
||||
* Uses DisabledTag's selectionDeniedText() message
|
||||
*/
|
||||
override selectionDeniedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveDisabled", { moveName: allMoves[move].name });
|
||||
return i18next.t("battle:moveDisabledHealBlock", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name, healBlockName: allMoves[Moves.HEAL_BLOCK].name });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2248,7 +2277,7 @@ export class HealBlockTag extends MoveRestrictionBattlerTag {
|
||||
* @returns {string} text to display when the move is interrupted
|
||||
*/
|
||||
override interruptedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:disableInterruptedMove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
return i18next.t("battle:moveDisabledHealBlock", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name, healBlockName: allMoves[Moves.HEAL_BLOCK].name });
|
||||
}
|
||||
|
||||
override onRemove(pokemon: Pokemon): void {
|
||||
@ -2325,7 +2354,7 @@ export class SubstituteTag extends BattlerTag {
|
||||
public sourceInFocus: boolean;
|
||||
|
||||
constructor(sourceMove: Moves, sourceId: integer) {
|
||||
super(BattlerTagType.SUBSTITUTE, [BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE, BattlerTagLapseType.HIT], 0, sourceMove, sourceId, true);
|
||||
super(BattlerTagType.SUBSTITUTE, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE, BattlerTagLapseType.HIT ], 0, sourceMove, sourceId, true);
|
||||
}
|
||||
|
||||
/** Sets the Substitute's HP and queues an on-add battle animation that initializes the Substitute's sprite. */
|
||||
@ -2349,7 +2378,7 @@ export class SubstituteTag extends BattlerTag {
|
||||
onRemove(pokemon: Pokemon): void {
|
||||
// Only play the animation if the cause of removal isn't from the source's own move
|
||||
if (!this.sourceInFocus) {
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_REMOVE, [this.sprite]);
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_REMOVE, [ this.sprite ]);
|
||||
} else {
|
||||
this.sprite.destroy();
|
||||
}
|
||||
@ -2373,13 +2402,13 @@ export class SubstituteTag extends BattlerTag {
|
||||
|
||||
/** Triggers an animation that brings the Pokemon into focus before it uses a move */
|
||||
onPreMove(pokemon: Pokemon): void {
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_PRE_MOVE, [this.sprite]);
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_PRE_MOVE, [ this.sprite ]);
|
||||
this.sourceInFocus = true;
|
||||
}
|
||||
|
||||
/** Triggers an animation that brings the Pokemon out of focus after it uses a move */
|
||||
onAfterMove(pokemon: Pokemon): void {
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_POST_MOVE, [this.sprite]);
|
||||
pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_POST_MOVE, [ this.sprite ]);
|
||||
this.sourceInFocus = false;
|
||||
}
|
||||
|
||||
@ -2501,8 +2530,8 @@ export class TormentTag extends MoveRestrictionBattlerTag {
|
||||
return false;
|
||||
}
|
||||
|
||||
override selectionDeniedText(_pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveCannotBeSelected", { moveName: allMoves[move].name });
|
||||
override selectionDeniedText(pokemon: Pokemon, _move: Moves): string {
|
||||
return i18next.t("battle:moveDisabledTorment", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
|
||||
}
|
||||
}
|
||||
|
||||
@ -2513,7 +2542,7 @@ export class TormentTag extends MoveRestrictionBattlerTag {
|
||||
*/
|
||||
export class TauntTag extends MoveRestrictionBattlerTag {
|
||||
constructor() {
|
||||
super(BattlerTagType.TAUNT, [BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE], 4, Moves.TAUNT);
|
||||
super(BattlerTagType.TAUNT, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE ], 4, Moves.TAUNT);
|
||||
}
|
||||
|
||||
override onAdd(pokemon: Pokemon) {
|
||||
@ -2530,12 +2559,12 @@ export class TauntTag extends MoveRestrictionBattlerTag {
|
||||
return allMoves[move].category === MoveCategory.STATUS;
|
||||
}
|
||||
|
||||
override selectionDeniedText(_pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveCannotBeSelected", { moveName: allMoves[move].name });
|
||||
override selectionDeniedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveDisabledTaunt", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
}
|
||||
|
||||
override interruptedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:disableInterruptedMove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
return i18next.t("battle:moveDisabledTaunt", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
}
|
||||
}
|
||||
|
||||
@ -2548,7 +2577,7 @@ export class ImprisonTag extends MoveRestrictionBattlerTag {
|
||||
private source: Pokemon | null;
|
||||
|
||||
constructor(sourceId: number) {
|
||||
super(BattlerTagType.IMPRISON, [BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE], 1, Moves.IMPRISON, sourceId);
|
||||
super(BattlerTagType.IMPRISON, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE ], 1, Moves.IMPRISON, sourceId);
|
||||
}
|
||||
|
||||
override onAdd(pokemon: Pokemon) {
|
||||
@ -2580,15 +2609,52 @@ export class ImprisonTag extends MoveRestrictionBattlerTag {
|
||||
return false;
|
||||
}
|
||||
|
||||
override selectionDeniedText(_pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveCannotBeSelected", { moveName: allMoves[move].name });
|
||||
override selectionDeniedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveDisabledImprison", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
}
|
||||
|
||||
override interruptedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:disableInterruptedMove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
return i18next.t("battle:moveDisabledImprison", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Battler Tag that applies the effects of Syrup Bomb to the target Pokemon.
|
||||
* For three turns, starting from the turn of hit, at the end of each turn, the target Pokemon's speed will decrease by 1.
|
||||
* The tag can also expire by taking the target Pokemon off the field.
|
||||
*/
|
||||
export class SyrupBombTag extends BattlerTag {
|
||||
constructor() {
|
||||
super(BattlerTagType.SYRUP_BOMB, BattlerTagLapseType.TURN_END, 3, Moves.SYRUP_BOMB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the Syrup Bomb battler tag to the target Pokemon.
|
||||
* @param {Pokemon} pokemon the target Pokemon
|
||||
*/
|
||||
override onAdd(pokemon: Pokemon) {
|
||||
super.onAdd(pokemon);
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:syrupBombOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the single-stage speed down to the target Pokemon and decrements the tag's turn count
|
||||
* @param {Pokemon} pokemon the target Pokemon
|
||||
* @param {BattlerTagLapseType} _lapseType
|
||||
* @returns `true` if the turnCount is still greater than 0 | `false` if the turnCount is 0 or the target Pokemon has been removed from the field
|
||||
*/
|
||||
override lapse(pokemon: Pokemon, _lapseType: BattlerTagLapseType): boolean {
|
||||
if (!pokemon.isActive(true)) {
|
||||
return false;
|
||||
}
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:syrupBombLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); // Custom message in lieu of an animation in mainline
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(
|
||||
pokemon.scene, pokemon.getBattlerIndex(), true,
|
||||
[ Stat.SPD ], -1, true, false, true
|
||||
));
|
||||
return --this.turnCount > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a {@linkcode BattlerTag} based on the provided tag type, turn count, source move, and source ID.
|
||||
@ -2737,9 +2803,9 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||
case BattlerTagType.DISABLED:
|
||||
return new DisabledTag(sourceId);
|
||||
case BattlerTagType.IGNORE_GHOST:
|
||||
return new ExposedTag(tagType, sourceMove, Type.GHOST, [Type.NORMAL, Type.FIGHTING]);
|
||||
return new ExposedTag(tagType, sourceMove, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ]);
|
||||
case BattlerTagType.IGNORE_DARK:
|
||||
return new ExposedTag(tagType, sourceMove, Type.DARK, [Type.PSYCHIC]);
|
||||
return new ExposedTag(tagType, sourceMove, Type.DARK, [ Type.PSYCHIC ]);
|
||||
case BattlerTagType.GULP_MISSILE_ARROKUDA:
|
||||
case BattlerTagType.GULP_MISSILE_PIKACHU:
|
||||
return new GulpMissileTag(tagType, sourceMove);
|
||||
@ -2763,6 +2829,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||
return new TauntTag();
|
||||
case BattlerTagType.IMPRISON:
|
||||
return new ImprisonTag(sourceId);
|
||||
case BattlerTagType.SYRUP_BOMB:
|
||||
return new SyrupBombTag();
|
||||
case BattlerTagType.NONE:
|
||||
default:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||
|
@ -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";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
|
||||
/** A constant for the default max cost of the starting party before a run */
|
||||
@ -185,7 +186,7 @@ export abstract class Challenge {
|
||||
*/
|
||||
getDescription(overrideValue?: number): string {
|
||||
const value = overrideValue ?? this.value;
|
||||
return `${i18next.t([`challenges:${this.geti18nKey()}.desc.${value}`, `challenges:${this.geti18nKey()}.desc`])}`;
|
||||
return `${i18next.t([ `challenges:${this.geti18nKey()}.desc.${value}`, `challenges:${this.geti18nKey()}.desc` ])}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -414,9 +415,9 @@ export class SingleGenerationChallenge extends Challenge {
|
||||
}
|
||||
|
||||
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
|
||||
const generations = [pokemon.generation];
|
||||
const generations = [ pokemon.generation ];
|
||||
if (soft) {
|
||||
const speciesToCheck = [pokemon.speciesId];
|
||||
const speciesToCheck = [ pokemon.speciesId ];
|
||||
while (speciesToCheck.length) {
|
||||
const checking = speciesToCheck.pop();
|
||||
if (checking && pokemonEvolutions.hasOwnProperty(checking)) {
|
||||
@ -631,7 +632,7 @@ export class SingleGenerationChallenge extends Challenge {
|
||||
trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ];
|
||||
break;
|
||||
case 186:
|
||||
trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE]), TrainerType.LARRY_ELITE ];
|
||||
trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([ TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE ]), TrainerType.LARRY_ELITE ];
|
||||
break;
|
||||
case 188:
|
||||
trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ];
|
||||
@ -704,10 +705,10 @@ interface monotypeOverride {
|
||||
*/
|
||||
export class SingleTypeChallenge extends Challenge {
|
||||
private static TYPE_OVERRIDES: monotypeOverride[] = [
|
||||
{species: Species.CASTFORM, type: Type.NORMAL, fusion: false},
|
||||
{ species: Species.CASTFORM, type: Type.NORMAL, fusion: false },
|
||||
];
|
||||
// TODO: Find a solution for all Pokemon with this ssui issue, including Basculin and Burmy
|
||||
private static SPECIES_OVERRIDES: Species[] = [Species.MELOETTA];
|
||||
private static SPECIES_OVERRIDES: Species[] = [ Species.MELOETTA ];
|
||||
|
||||
constructor() {
|
||||
super(Challenges.SINGLE_TYPE, 18);
|
||||
@ -715,9 +716,9 @@ export class SingleTypeChallenge extends Challenge {
|
||||
|
||||
override applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
|
||||
const speciesForm = getPokemonSpeciesForm(pokemon.speciesId, dexAttr.formIndex);
|
||||
const types = [speciesForm.type1, speciesForm.type2];
|
||||
const types = [ speciesForm.type1, speciesForm.type2 ];
|
||||
if (soft && !SingleTypeChallenge.SPECIES_OVERRIDES.includes(pokemon.speciesId)) {
|
||||
const speciesToCheck = [pokemon.speciesId];
|
||||
const speciesToCheck = [ pokemon.speciesId ];
|
||||
while (speciesToCheck.length) {
|
||||
const checking = speciesToCheck.pop();
|
||||
if (checking && pokemonEvolutions.hasOwnProperty(checking)) {
|
||||
@ -782,9 +783,9 @@ export class SingleTypeChallenge extends Challenge {
|
||||
overrideValue = this.value;
|
||||
}
|
||||
const type = i18next.t(`pokemonInfo:Type.${Type[this.value - 1]}`);
|
||||
const typeColor = `[color=${TypeColor[Type[this.value-1]]}][shadow=${TypeShadow[Type[this.value-1]]}]${type}[/shadow][/color]`;
|
||||
const typeColor = `[color=${TypeColor[Type[this.value - 1]]}][shadow=${TypeShadow[Type[this.value - 1]]}]${type}[/shadow][/color]`;
|
||||
const defaultDesc = i18next.t("challenges:singleType.desc_default");
|
||||
const typeDesc = i18next.t("challenges:singleType.desc", {type: typeColor});
|
||||
const typeDesc = i18next.t("challenges:singleType.desc", { type: typeColor });
|
||||
return this.value === 0 ? defaultDesc : typeDesc;
|
||||
}
|
||||
|
||||
@ -814,7 +815,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;
|
||||
@ -829,7 +830,7 @@ export class FreshStartChallenge extends Challenge {
|
||||
pokemon.shiny = false; // Not shiny
|
||||
pokemon.variant = 0; // Not shiny
|
||||
pokemon.formIndex = 0; // Froakie should be base form
|
||||
pokemon.ivs = [10, 10, 10, 10, 10, 10]; // Default IVs of 10 for all stats
|
||||
pokemon.ivs = [ 10, 10, 10, 10, 10, 10 ]; // Default IVs of 10 for all stats
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -896,7 +897,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));
|
||||
|
@ -3123,44 +3123,44 @@ export const trainerTypeDialogue: TrainerTypeDialogue = {
|
||||
|
||||
export const doubleBattleDialogue = {
|
||||
"blue_red_double": {
|
||||
encounter: ["doubleBattleDialogue:blue_red_double.encounter.1"],
|
||||
victory: ["doubleBattleDialogue:blue_red_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:blue_red_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:blue_red_double.victory.1" ]
|
||||
},
|
||||
"red_blue_double": {
|
||||
encounter: ["doubleBattleDialogue:red_blue_double.encounter.1"],
|
||||
victory: ["doubleBattleDialogue:red_blue_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:red_blue_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:red_blue_double.victory.1" ]
|
||||
},
|
||||
"tate_liza_double": {
|
||||
encounter: ["doubleBattleDialogue:tate_liza_double.encounter.1"],
|
||||
victory: ["doubleBattleDialogue:tate_liza_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:tate_liza_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:tate_liza_double.victory.1" ]
|
||||
},
|
||||
"liza_tate_double": {
|
||||
encounter: ["doubleBattleDialogue:liza_tate_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:liza_tate_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:liza_tate_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:liza_tate_double.victory.1" ]
|
||||
},
|
||||
"wallace_steven_double": {
|
||||
encounter: [ "doubleBattleDialogue:wallace_steven_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:wallace_steven_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:wallace_steven_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:wallace_steven_double.victory.1" ]
|
||||
},
|
||||
"steven_wallace_double": {
|
||||
encounter: [ "doubleBattleDialogue:steven_wallace_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:steven_wallace_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:steven_wallace_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:steven_wallace_double.victory.1" ]
|
||||
},
|
||||
"alder_iris_double": {
|
||||
encounter: [ "doubleBattleDialogue:alder_iris_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:alder_iris_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:alder_iris_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:alder_iris_double.victory.1" ]
|
||||
},
|
||||
"iris_alder_double": {
|
||||
encounter: [ "doubleBattleDialogue:iris_alder_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:iris_alder_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:iris_alder_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:iris_alder_double.victory.1" ]
|
||||
},
|
||||
"marnie_piers_double": {
|
||||
encounter: [ "doubleBattleDialogue:marnie_piers_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:marnie_piers_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:marnie_piers_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:marnie_piers_double.victory.1" ]
|
||||
},
|
||||
"piers_marnie_double": {
|
||||
encounter: [ "doubleBattleDialogue:piers_marnie_double.encounter.1"],
|
||||
victory: [ "doubleBattleDialogue:piers_marnie_double.victory.1"]
|
||||
encounter: [ "doubleBattleDialogue:piers_marnie_double.encounter.1" ],
|
||||
victory: [ "doubleBattleDialogue:piers_marnie_double.victory.1" ]
|
||||
},
|
||||
|
||||
|
||||
@ -3193,7 +3193,7 @@ export function initTrainerTypeDialogue(): void {
|
||||
const trainerTypes = Object.keys(trainerTypeDialogue).map(t => parseInt(t) as TrainerType);
|
||||
for (const trainerType of trainerTypes) {
|
||||
const messages = trainerTypeDialogue[trainerType];
|
||||
const messageTypes = ["encounter", "victory", "defeat"];
|
||||
const messageTypes = [ "encounter", "victory", "defeat" ];
|
||||
for (const messageType of messageTypes) {
|
||||
if (Array.isArray(messages)) {
|
||||
if (messages[0][messageType]) {
|
||||
|
@ -48,7 +48,7 @@ export class EggHatchData {
|
||||
seenCount: currDexEntry.seenCount,
|
||||
caughtCount: currDexEntry.caughtCount,
|
||||
hatchedCount: currDexEntry.hatchedCount,
|
||||
ivs: [...currDexEntry.ivs]
|
||||
ivs: [ ...currDexEntry.ivs ]
|
||||
};
|
||||
this.starterDataEntryBeforeUpdate = {
|
||||
moveset: currStarterDataEntry.moveset,
|
||||
|
@ -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) */
|
||||
@ -299,7 +288,7 @@ export class Egg {
|
||||
public getEggTypeDescriptor(scene: BattleScene): string {
|
||||
switch (this.sourceType) {
|
||||
case EggSourceType.SAME_SPECIES_EGG:
|
||||
return this._eggDescriptor ?? i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName()});
|
||||
return this._eggDescriptor ?? i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName() });
|
||||
case EggSourceType.GACHA_LEGENDARY:
|
||||
return this._eggDescriptor ?? `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp)).getName()})`;
|
||||
case EggSourceType.GACHA_SHINY:
|
||||
@ -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 {
|
||||
@ -407,10 +396,10 @@ export class Egg {
|
||||
break;
|
||||
}
|
||||
|
||||
const ignoredSpecies = [Species.PHIONE, Species.MANAPHY, Species.ETERNATUS];
|
||||
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) {
|
||||
|
507
src/data/move.ts
507
src/data/move.ts
File diff suppressed because it is too large
Load Diff
@ -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`));
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH], guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA], fillRemaining: true }, [eggOptions]);
|
||||
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`));
|
||||
setEncounterRewards(scene, { fillRemaining: false, rerollMultiplier: -1 }, [eggOptions]);
|
||||
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!;
|
||||
|
||||
@ -195,7 +195,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
// Can't define stack count on a ModifierType, have to just create separate instances for each stack
|
||||
// Overflow berries will be "lost" on the boss, but it's un-catchable anyway
|
||||
for (let i = 0; i < berryMod.stackCount; i++) {
|
||||
const modifierType = generateModifierType(scene, modifierTypes.BERRY, [berryMod.berryType]) as PokemonHeldItemModifierType;
|
||||
const modifierType = generateModifierType(scene, modifierTypes.BERRY, [ berryMod.berryType ]) as PokemonHeldItemModifierType;
|
||||
bossModifierConfigs.push({ modifier: modifierType });
|
||||
}
|
||||
});
|
||||
@ -204,8 +204,8 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
|
||||
// SpDef buff below wave 50, +1 to all stats otherwise
|
||||
const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ?
|
||||
[Stat.SPDEF] :
|
||||
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD];
|
||||
[ Stat.SPDEF ] :
|
||||
[ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ];
|
||||
|
||||
// Calculate boss mon
|
||||
const config: EnemyPartyConfig = {
|
||||
@ -215,18 +215,18 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
species: getPokemonSpecies(Species.GREEDENT),
|
||||
isBoss: true,
|
||||
bossSegments: 3,
|
||||
moveSet: [Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH],
|
||||
moveSet: [ Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH ],
|
||||
modifierConfigs: bossModifierConfigs,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
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));
|
||||
}
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
encounter.setDialogueToken("greedentName", getPokemonSpecies(Species.GREEDENT).getName());
|
||||
|
||||
return true;
|
||||
@ -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,13 +274,13 @@ 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);
|
||||
encounter.startOfBattleEffects.push({
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY],
|
||||
targets: [ BattlerIndex.ENEMY ],
|
||||
move: new PokemonMove(Moves.STUFF_CHEEKS),
|
||||
ignorePp: true
|
||||
});
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -320,7 +320,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
Phaser.Math.RND.shuffle(berryTypesAsArray);
|
||||
const randBerryType = berryTypesAsArray.pop();
|
||||
|
||||
const berryModType = generateModifierType(scene, modifierTypes.BERRY, [randBerryType]) as BerryModifierType;
|
||||
const berryModType = generateModifierType(scene, modifierTypes.BERRY, [ randBerryType ]) as BerryModifierType;
|
||||
applyModifierTypeToPlayerPokemon(scene, pokemon, berryModType);
|
||||
}
|
||||
}
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -355,7 +355,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||
// Greedent joins the team, level equal to 2 below highest party member
|
||||
const level = getHighestLevelPlayerPokemon(scene, false, true).level - 2;
|
||||
const greedent = new EnemyPokemon(scene, getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false);
|
||||
greedent.moveset = [new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF)];
|
||||
greedent.moveset = [ new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF) ];
|
||||
greedent.passive = true;
|
||||
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||
@ -472,7 +472,7 @@ function doGreedentEatBerries(scene: BattleScene) {
|
||||
*/
|
||||
function doBerrySpritePile(scene: BattleScene, isEat: boolean = false) {
|
||||
const berryAddDelay = 150;
|
||||
let animationOrder = ["starf", "sitrus", "lansat", "salac", "apicot", "enigma", "liechi", "ganlon", "lum", "petaya", "leppa"];
|
||||
let animationOrder = [ "starf", "sitrus", "lansat", "salac", "apicot", "enigma", "liechi", "ganlon", "lum", "petaya", "leppa" ];
|
||||
if (isEat) {
|
||||
animationOrder = animationOrder.reverse();
|
||||
}
|
||||
@ -496,7 +496,7 @@ function doBerrySpritePile(scene: BattleScene, isEat: boolean = false) {
|
||||
// Animate Petaya berry falling off the pile
|
||||
if (berry === "petaya" && sprite && tintSprite && !isEat) {
|
||||
scene.time.delayedCall(200, () => {
|
||||
doBerryBounce(scene, [sprite, tintSprite], 30, 500);
|
||||
doBerryBounce(scene, [ sprite, tintSprite ], 30, 500);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -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) => {
|
||||
@ -69,7 +69,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
isBoss: true
|
||||
}],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
// Calculate the number of extra berries that player receives
|
||||
// 10-40: 2, 40-120: 4, 120-160: 5, 160-180: 7
|
||||
@ -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 }));
|
||||
@ -193,25 +193,25 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
|
||||
// Defense/Spd buffs below wave 50, +1 to all stats otherwise
|
||||
const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ?
|
||||
[Stat.DEF, Stat.SPDEF, Stat.SPD] :
|
||||
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD];
|
||||
[ Stat.DEF, Stat.SPDEF, Stat.SPD ] :
|
||||
[ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ];
|
||||
|
||||
const config = scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0];
|
||||
config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
||||
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 {
|
||||
// Gains 1 berry for every 10% faster the player's pokemon is than the enemy, up to a max of numBerries, minimum of 2
|
||||
const numBerriesGrabbed = Math.max(Math.min(Math.round((speedDiff - 1)/0.08), numBerries), 2);
|
||||
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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -250,7 +250,7 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
||||
|
||||
function tryGiveBerry(scene: BattleScene, prioritizedPokemon?: PlayerPokemon) {
|
||||
const berryType = randSeedInt(Object.keys(BerryType).filter(s => !isNaN(Number(s))).length) as BerryType;
|
||||
const berry = generateModifierType(scene, modifierTypes.BERRY, [berryType]) as BerryModifierType;
|
||||
const berry = generateModifierType(scene, modifierTypes.BERRY, [ berryType ]) as BerryModifierType;
|
||||
|
||||
const party = scene.getParty();
|
||||
|
||||
|
@ -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,
|
||||
@ -181,7 +181,7 @@ const MISC_TUTOR_MOVES = [
|
||||
/**
|
||||
* Wave breakpoints that determine how strong to make the Bug-Type Superfan's team
|
||||
*/
|
||||
const WAVE_LEVEL_BREAKPOINTS = [30, 50, 70, 100, 120, 140, 160];
|
||||
const WAVE_LEVEL_BREAKPOINTS = [ 30, 50, 70, 100, 120, 140, 160 ];
|
||||
|
||||
/**
|
||||
* Bug Type Superfan encounter.
|
||||
@ -193,7 +193,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
||||
// Must have at least 1 Bug type on team, OR have a bug item somewhere on the team
|
||||
new HeldItemRequirement(["BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier"], 1),
|
||||
new HeldItemRequirement([ "BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier" ], 1),
|
||||
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1),
|
||||
new TypeRequirement(Type.BUG, false, 1)
|
||||
))
|
||||
@ -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) => {
|
||||
@ -268,7 +268,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
const requiredItems = [
|
||||
generateModifierType(scene, modifierTypes.QUICK_CLAW),
|
||||
generateModifierType(scene, modifierTypes.GRIP_CLAW),
|
||||
generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.BUG]),
|
||||
generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.BUG ]),
|
||||
];
|
||||
|
||||
const requiredItemString = requiredItems.map(m => m?.name ?? "unknown").join("/");
|
||||
@ -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,36 +327,36 @@ 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 });
|
||||
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 });
|
||||
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 });
|
||||
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 {
|
||||
// If player has any evolution/form change items that are valid for their party, will spawn one of those items in addition to a Master Ball
|
||||
const modifierOptions: ModifierTypeOption[] = [generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)!, generateModifierTypeOption(scene, modifierTypes.MAX_LURE)!];
|
||||
const modifierOptions: ModifierTypeOption[] = [ generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)!, generateModifierTypeOption(scene, modifierTypes.MAX_LURE)! ];
|
||||
const specialOptions: ModifierTypeOption[] = [];
|
||||
|
||||
const nonRareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.EVOLUTION_ITEM);
|
||||
@ -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`,
|
||||
},
|
||||
];
|
||||
}
|
||||
@ -397,23 +397,23 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
||||
// Meets one or both of the below reqs
|
||||
new HeldItemRequirement(["BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier"], 1),
|
||||
new HeldItemRequirement([ "BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier" ], 1),
|
||||
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;
|
||||
@ -474,13 +474,13 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||
const bugNet = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET)!;
|
||||
bugNet.type.tier = ModifierTier.ROGUE;
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [bugNet], guaranteedModifierTypeFuncs: [modifierTypes.REVIVER_SEED], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ bugNet ], guaranteedModifierTypeFuncs: [ modifierTypes.REVIVER_SEED ], fillRemaining: false });
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build())
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`,
|
||||
text: `${namespace}:outro`,
|
||||
},
|
||||
])
|
||||
.build();
|
||||
@ -535,7 +535,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -558,14 +558,14 @@ function getTrainerConfigForWave(waveIndex: number) {
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([pool3Mon2.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ pool3Mon2.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon2.formIndex)) {
|
||||
p.formIndex = pool3Mon2.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -586,7 +586,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -611,14 +611,14 @@ function getTrainerConfigForWave(waveIndex: number) {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon.formIndex)) {
|
||||
p.formIndex = pool3Mon.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon2.species], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ pool3Mon2.species ], TrainerSlot.TRAINER, true, p => {
|
||||
if (!isNullOrUndefined(pool3Mon2.formIndex)) {
|
||||
p.formIndex = pool3Mon2.formIndex;
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -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) => {
|
||||
@ -129,38 +129,38 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
{
|
||||
species: getPokemonSpecies(Species.MR_MIME),
|
||||
isBoss: true,
|
||||
moveSet: [Moves.TEETER_DANCE, Moves.ALLY_SWITCH, Moves.DAZZLING_GLEAM, Moves.PSYCHIC]
|
||||
moveSet: [ Moves.TEETER_DANCE, Moves.ALLY_SWITCH, Moves.DAZZLING_GLEAM, Moves.PSYCHIC ]
|
||||
},
|
||||
{ // Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter
|
||||
species: getPokemonSpecies(Species.BLACEPHALON),
|
||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ ability: ability, types: [randSeedInt(18), randSeedInt(18)] }),
|
||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ ability: ability, types: [ randSeedInt(18), randSeedInt(18) ]}),
|
||||
isBoss: true,
|
||||
moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN]
|
||||
moveSet: [ Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN ]
|
||||
},
|
||||
],
|
||||
doubleBattle: true
|
||||
});
|
||||
|
||||
// Load animations/sfx for start of fight moves
|
||||
loadCustomMovesForEncounter(scene, [Moves.ROLE_PLAY, Moves.TAUNT]);
|
||||
loadCustomMovesForEncounter(scene, [ Moves.ROLE_PLAY, Moves.TAUNT ]);
|
||||
|
||||
encounter.setDialogueToken("blacephalonName", getPokemonSpecies(Species.BLACEPHALON).getName());
|
||||
|
||||
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`
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -175,19 +175,19 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
encounter.startOfBattleEffects.push(
|
||||
{ // Mr. Mime copies the Blacephalon's random ability
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY_2],
|
||||
targets: [ BattlerIndex.ENEMY_2 ],
|
||||
move: new PokemonMove(Moves.ROLE_PLAY),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.TAUNT),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.PLAYER_2],
|
||||
targets: [ BattlerIndex.PLAYER_2 ],
|
||||
move: new PokemonMove(Moves.TAUNT),
|
||||
ignorePp: true
|
||||
});
|
||||
@ -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`
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -336,11 +336,11 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||
.filter(move => move && !originalTypes.includes(move.getMove().type) && move.getMove().category !== MoveCategory.STATUS)
|
||||
.map(move => move!.getMove().type);
|
||||
if (priorityTypes?.length > 0) {
|
||||
priorityTypes = [...new Set(priorityTypes)].sort();
|
||||
priorityTypes = [ ...new Set(priorityTypes) ].sort();
|
||||
priorityTypes = randSeedShuffle(priorityTypes);
|
||||
}
|
||||
|
||||
const newTypes = [originalTypes[0]];
|
||||
const newTypes = [ originalTypes[0] ];
|
||||
let secondType: Type | null = null;
|
||||
while (secondType === null || secondType === newTypes[0] || originalTypes.includes(secondType)) {
|
||||
if (priorityTypes.length > 0) {
|
||||
@ -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"),
|
||||
@ -453,37 +453,37 @@ function generateItemsOfTier(scene: BattleScene, pokemon: PlayerPokemon, numItem
|
||||
// Pools have instances of the modifier type equal to the max stacks that modifier can be applied to any one pokemon
|
||||
// This is to prevent "over-generating" a random item of a certain type during item swaps
|
||||
const ultraPool = [
|
||||
[modifierTypes.REVIVER_SEED, 1],
|
||||
[modifierTypes.GOLDEN_PUNCH, 5],
|
||||
[modifierTypes.ATTACK_TYPE_BOOSTER, 99],
|
||||
[modifierTypes.QUICK_CLAW, 3],
|
||||
[modifierTypes.WIDE_LENS, 3]
|
||||
[ modifierTypes.REVIVER_SEED, 1 ],
|
||||
[ modifierTypes.GOLDEN_PUNCH, 5 ],
|
||||
[ modifierTypes.ATTACK_TYPE_BOOSTER, 99 ],
|
||||
[ modifierTypes.QUICK_CLAW, 3 ],
|
||||
[ modifierTypes.WIDE_LENS, 3 ]
|
||||
];
|
||||
|
||||
const roguePool = [
|
||||
[modifierTypes.LEFTOVERS, 4],
|
||||
[modifierTypes.SHELL_BELL, 4],
|
||||
[modifierTypes.SOUL_DEW, 10],
|
||||
[modifierTypes.SOOTHE_BELL, 3],
|
||||
[modifierTypes.SCOPE_LENS, 1],
|
||||
[modifierTypes.BATON, 1],
|
||||
[modifierTypes.FOCUS_BAND, 5],
|
||||
[modifierTypes.KINGS_ROCK, 3],
|
||||
[modifierTypes.GRIP_CLAW, 5]
|
||||
[ modifierTypes.LEFTOVERS, 4 ],
|
||||
[ modifierTypes.SHELL_BELL, 4 ],
|
||||
[ modifierTypes.SOUL_DEW, 10 ],
|
||||
[ modifierTypes.SOOTHE_BELL, 3 ],
|
||||
[ modifierTypes.SCOPE_LENS, 1 ],
|
||||
[ modifierTypes.BATON, 1 ],
|
||||
[ modifierTypes.FOCUS_BAND, 5 ],
|
||||
[ modifierTypes.KINGS_ROCK, 3 ],
|
||||
[ modifierTypes.GRIP_CLAW, 5 ]
|
||||
];
|
||||
|
||||
const berryPool = [
|
||||
[BerryType.APICOT, 3],
|
||||
[BerryType.ENIGMA, 2],
|
||||
[BerryType.GANLON, 3],
|
||||
[BerryType.LANSAT, 3],
|
||||
[BerryType.LEPPA, 2],
|
||||
[BerryType.LIECHI, 3],
|
||||
[BerryType.LUM, 2],
|
||||
[BerryType.PETAYA, 3],
|
||||
[BerryType.SALAC, 2],
|
||||
[BerryType.SITRUS, 2],
|
||||
[BerryType.STARF, 3]
|
||||
[ BerryType.APICOT, 3 ],
|
||||
[ BerryType.ENIGMA, 2 ],
|
||||
[ BerryType.GANLON, 3 ],
|
||||
[ BerryType.LANSAT, 3 ],
|
||||
[ BerryType.LEPPA, 2 ],
|
||||
[ BerryType.LIECHI, 3 ],
|
||||
[ BerryType.LUM, 2 ],
|
||||
[ BerryType.PETAYA, 3 ],
|
||||
[ BerryType.SALAC, 2 ],
|
||||
[ BerryType.SITRUS, 2 ],
|
||||
[ BerryType.STARF, 3 ]
|
||||
];
|
||||
|
||||
let pool: any[];
|
||||
@ -502,7 +502,7 @@ function generateItemsOfTier(scene: BattleScene, pokemon: PlayerPokemon, numItem
|
||||
const newItemType = pool[randIndex];
|
||||
let newMod: PokemonHeldItemModifierType;
|
||||
if (tier === "Berries") {
|
||||
newMod = generateModifierType(scene, modifierTypes.BERRY, [newItemType[0]]) as PokemonHeldItemModifierType;
|
||||
newMod = generateModifierType(scene, modifierTypes.BERRY, [ newItemType[0] ]) as PokemonHeldItemModifierType;
|
||||
} else {
|
||||
newMod = generateModifierType(scene, newItemType[0]) as PokemonHeldItemModifierType;
|
||||
}
|
||||
|
@ -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!;
|
||||
|
||||
@ -141,7 +141,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
scene.getEnemyParty().forEach(enemyPokemon => {
|
||||
scene.field.remove(enemyPokemon, true);
|
||||
});
|
||||
scene.currentBattle.enemyParty = [oricorio];
|
||||
scene.currentBattle.enemyParty = [ oricorio ];
|
||||
scene.field.add(oricorio);
|
||||
// Spawns on offscreen field
|
||||
oricorio.x -= 300;
|
||||
@ -153,14 +153,14 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
dataSource: oricorioData,
|
||||
isBoss: true,
|
||||
// Gets +1 to all stats except SPD on battle start
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
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));
|
||||
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));
|
||||
}
|
||||
}],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
encounter.misc = {
|
||||
oricorioData
|
||||
};
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -187,13 +187,13 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||
|
||||
encounter.startOfBattleEffects.push({
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.REVELATION_DANCE),
|
||||
ignorePp: true
|
||||
});
|
||||
|
||||
await hideOricorioPokemon(scene);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.BATON], fillRemaining: true });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.BATON ], fillRemaining: true });
|
||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||
})
|
||||
.build()
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -164,7 +164,7 @@ export const DarkDealEncounter: MysteryEncounter =
|
||||
// Starter egg tier, 35/50/10/5 %odds for tiers 6/7/8/9+
|
||||
const roll = randSeedInt(100);
|
||||
const starterTier: number | [number, number] =
|
||||
roll >= 65 ? 6 : roll >= 15 ? 7 : roll >= 5 ? 8 : [9, 10];
|
||||
roll >= 65 ? 6 : roll >= 15 ? 7 : roll >= 5 ? 8 : [ 9, 10 ];
|
||||
const bossSpecies = getPokemonSpecies(getRandomSpeciesByStarterTier(starterTier, excludedBosses, bossTypes));
|
||||
const pokemonConfig: EnemyPokemonConfig = {
|
||||
species: bossSpecies,
|
||||
@ -179,7 +179,7 @@ export const DarkDealEncounter: MysteryEncounter =
|
||||
pokemonConfig.formIndex = 0;
|
||||
}
|
||||
const config: EnemyPartyConfig = {
|
||||
pokemonConfigs: [pokemonConfig],
|
||||
pokemonConfigs: [ pokemonConfig ],
|
||||
};
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
@ -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,10 +19,10 @@ 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"];
|
||||
const OPTION_2_ALLOWED_MODIFIERS = [ "BerryModifier", "PokemonInstantReviveModifier" ];
|
||||
|
||||
/** Disallowed items are berries, Reviver Seeds, and Vitamins (form change items and fusion items are not PokemonHeldItemModifiers) */
|
||||
const OPTION_3_DISALLOWED_MODIFIERS = [
|
||||
@ -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;
|
||||
},
|
||||
@ -87,9 +87,9 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.ATK])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.DEF])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.ATK ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.DEF ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPD ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!,
|
||||
];
|
||||
@ -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;
|
||||
},
|
||||
@ -133,9 +133,9 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPATK])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPDEF])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPATK ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPDEF ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPD ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!,
|
||||
];
|
||||
@ -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;
|
||||
},
|
||||
@ -179,8 +179,8 @@ export const FieldTripEncounter: MysteryEncounter =
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.ACC])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.ACC ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPD ])!,
|
||||
generateModifierTypeOption(scene, modifierTypes.GREAT_BALL)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.IV_SCANNER)!,
|
||||
generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!,
|
||||
@ -203,31 +203,31 @@ 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);
|
||||
setEncounterExp(scene, [ pokemon.id ], 100);
|
||||
}
|
||||
encounter.misc = {
|
||||
correctMove: correctMove,
|
||||
|
@ -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) => {
|
||||
@ -73,7 +73,7 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
doubleBattle: true,
|
||||
disableSwitch: true
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
// Load hidden Volcarona sprites
|
||||
encounter.spriteConfigs = [
|
||||
@ -99,7 +99,7 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
];
|
||||
|
||||
// Load animations/sfx for Volcarona moves
|
||||
loadCustomMovesForEncounter(scene, [Moves.FIRE_SPIN, Moves.QUIVER_DANCE]);
|
||||
loadCustomMovesForEncounter(scene, [ Moves.FIRE_SPIN, Moves.QUIVER_DANCE ]);
|
||||
|
||||
scene.arena.trySetWeather(WeatherType.SUNNY, true);
|
||||
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -143,25 +143,25 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
encounter.startOfBattleEffects.push(
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.FIRE_SPIN),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.PLAYER_2],
|
||||
targets: [ BattlerIndex.PLAYER_2 ],
|
||||
move: new PokemonMove(Moves.FIRE_SPIN),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY],
|
||||
targets: [ BattlerIndex.ENEMY ],
|
||||
move: new PokemonMove(Moves.QUIVER_DANCE),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||
targets: [BattlerIndex.ENEMY_2],
|
||||
targets: [ BattlerIndex.ENEMY_2 ],
|
||||
move: new PokemonMove(Moves.QUIVER_DANCE),
|
||||
ignorePp: true
|
||||
});
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -237,7 +237,7 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||
const primary = encounter.options[2].primaryPokemon!;
|
||||
const secondary = encounter.options[2].secondaryPokemon![0];
|
||||
|
||||
setEncounterExp(scene, [primary.id, secondary.id], getPokemonSpecies(Species.VOLCARONA).baseExp * 2);
|
||||
setEncounterExp(scene, [ primary.id, secondary.id ], getPokemonSpecies(Species.VOLCARONA).baseExp * 2);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
})
|
||||
.build()
|
||||
@ -248,9 +248,9 @@ function giveLeadPokemonCharcoal(scene: BattleScene) {
|
||||
// Give first party pokemon Charcoal for free at end of battle
|
||||
const leadPokemon = scene.getParty()?.[0];
|
||||
if (leadPokemon) {
|
||||
const charcoal = generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.FIRE]) as AttackTypeBoosterModifierType;
|
||||
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) => {
|
||||
@ -65,16 +65,16 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
species: bossSpecies,
|
||||
dataSource: new PokemonData(bossPokemon),
|
||||
isBoss: true,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
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));
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randSeedInt(4, 1) ], 2));
|
||||
}
|
||||
}],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
// Calculate item
|
||||
// Waves 10-40 GREAT, 60-120 ULTRA, 120-160 ROGUE, 160-180 MASTER
|
||||
@ -90,7 +90,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
let item: ModifierTypeOption | null = null;
|
||||
// TMs and Candy Jar excluded from possible rewards as they're too swingy in value for a singular item reward
|
||||
while (!item || item.type.id.includes("TM_") || item.type.id === "CANDY_JAR") {
|
||||
item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [tier], allowLuckUpgrades: false })[0];
|
||||
item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [ tier ], allowLuckUpgrades: false })[0];
|
||||
}
|
||||
encounter.setDialogueToken("itemName", item.type.name);
|
||||
encounter.misc = item;
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -137,7 +137,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
// Pick battle
|
||||
// Pokemon will randomly boost 1 stat by 2 stages
|
||||
const item = scene.currentBattle.mysteryEncounter!.misc as ModifierTypeOption;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ item ], fillRemaining: false });
|
||||
await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]);
|
||||
}
|
||||
)
|
||||
@ -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`
|
||||
}
|
||||
]
|
||||
})
|
||||
@ -159,7 +159,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||
// Pick steal
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const item = scene.currentBattle.mysteryEncounter!.misc as ModifierTypeOption;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ item ], fillRemaining: false });
|
||||
|
||||
// Use primaryPokemon to execute the thievery
|
||||
const primaryPokemon = encounter.options[1].primaryPokemon!;
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -197,7 +197,7 @@ async function summonPlayerPokemon(scene: BattleScene) {
|
||||
const enemySpecies = getPokemonSpecies(Species.WOBBUFFET);
|
||||
scene.currentBattle.enemyParty = [];
|
||||
const wobbuffet = scene.addEnemyPokemon(enemySpecies, encounter.misc.playerPokemon.level, TrainerSlot.NONE, false);
|
||||
wobbuffet.ivs = [0, 0, 0, 0, 0, 0];
|
||||
wobbuffet.ivs = [ 0, 0, 0, 0, 0, 0 ];
|
||||
wobbuffet.setNature(Nature.MILD);
|
||||
wobbuffet.setAlpha(0);
|
||||
wobbuffet.setVisible(false);
|
||||
@ -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);
|
||||
}
|
||||
@ -256,20 +256,20 @@ function handleNextTurn(scene: BattleScene) {
|
||||
let isHealPhase = false;
|
||||
if (healthRatio < 0.03) {
|
||||
// Grand prize
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.MULTI_LENS], fillRemaining: false });
|
||||
resultMessageKey = `${namespace}.best_result`;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.MULTI_LENS ], fillRemaining: false });
|
||||
resultMessageKey = `${namespace}:best_result`;
|
||||
} else if (healthRatio < 0.15) {
|
||||
// 2nd prize
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SCOPE_LENS], fillRemaining: false });
|
||||
resultMessageKey = `${namespace}.great_result`;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.SCOPE_LENS ], fillRemaining: false });
|
||||
resultMessageKey = `${namespace}:great_result`;
|
||||
} else if (healthRatio < 0.33) {
|
||||
// 3rd prize
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.WIDE_LENS], fillRemaining: false });
|
||||
resultMessageKey = `${namespace}.good_result`;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.WIDE_LENS ], fillRemaining: false });
|
||||
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--;
|
||||
}
|
||||
|
||||
@ -411,7 +411,7 @@ function hideShowmanIntroSprite(scene: BattleScene) {
|
||||
|
||||
// Slide the Wobbuffet and Game over slightly
|
||||
scene.tweens.add({
|
||||
targets: [wobbuffet, carnivalGame],
|
||||
targets: [ wobbuffet, carnivalGame ],
|
||||
x: "+=16",
|
||||
ease: "Sine.easeInOut",
|
||||
duration: 750
|
||||
|
@ -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;
|
||||
@ -35,15 +35,15 @@ const WONDER_TRADE_SHINY_CHANCE = 512;
|
||||
const MAX_WONDER_TRADE_SHINY_CHANCE = 4096;
|
||||
|
||||
const LEGENDARY_TRADE_POOLS = {
|
||||
1: [Species.RATTATA, Species.PIDGEY, Species.WEEDLE],
|
||||
2: [Species.SENTRET, Species.HOOTHOOT, Species.LEDYBA],
|
||||
3: [Species.POOCHYENA, Species.ZIGZAGOON, Species.TAILLOW],
|
||||
4: [Species.BIDOOF, Species.STARLY, Species.KRICKETOT],
|
||||
5: [Species.PATRAT, Species.PURRLOIN, Species.PIDOVE],
|
||||
6: [Species.BUNNELBY, Species.LITLEO, Species.SCATTERBUG],
|
||||
7: [Species.PIKIPEK, Species.YUNGOOS, Species.ROCKRUFF],
|
||||
8: [Species.SKWOVET, Species.WOOLOO, Species.ROOKIDEE],
|
||||
9: [Species.LECHONK, Species.FIDOUGH, Species.TAROUNTULA]
|
||||
1: [ Species.RATTATA, Species.PIDGEY, Species.WEEDLE ],
|
||||
2: [ Species.SENTRET, Species.HOOTHOOT, Species.LEDYBA ],
|
||||
3: [ Species.POOCHYENA, Species.ZIGZAGOON, Species.TAILLOW ],
|
||||
4: [ Species.BIDOOF, Species.STARLY, Species.KRICKETOT ],
|
||||
5: [ Species.PATRAT, Species.PURRLOIN, Species.PIDOVE ],
|
||||
6: [ Species.BUNNELBY, Species.LITLEO, Species.SCATTERBUG ],
|
||||
7: [ Species.PIKIPEK, Species.YUNGOOS, Species.ROCKRUFF ],
|
||||
8: [ Species.SKWOVET, Species.WOOLOO, Species.ROOKIDEE ],
|
||||
9: [ Species.LECHONK, Species.FIDOUGH, Species.TAROUNTULA ]
|
||||
};
|
||||
|
||||
/** Exclude Paradox mons as they aren't considered legendary/mythical */
|
||||
@ -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!;
|
||||
@ -159,7 +159,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
return true;
|
||||
},
|
||||
onHover: () => {
|
||||
const formName = tradePokemon.species.forms && tradePokemon.species.forms.length > tradePokemon.formIndex ? tradePokemon.species.forms[pokemon.formIndex].formName : null;
|
||||
const formName = tradePokemon.species.forms && tradePokemon.species.forms.length > tradePokemon.formIndex ? tradePokemon.species.forms[tradePokemon.formIndex].formName : null;
|
||||
const line1 = i18next.t("pokemonInfoContainer:ability") + " " + tradePokemon.getAbility().name + (tradePokemon.getGender() !== Gender.GENDERLESS ? " | " + i18next.t("pokemonInfoContainer:gender") + " " + getGenderSymbol(tradePokemon.getGender()) : "");
|
||||
const line2 = i18next.t("pokemonInfoContainer:nature") + " " + getNatureName(tradePokemon.getNature()) + (formName ? " | " + i18next.t("pokemonInfoContainer:form") + " " + formName : "");
|
||||
showEncounterText(scene, `${line1}\n${line2}`, 0, 0, false);
|
||||
@ -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;
|
||||
@ -387,11 +387,11 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||
let item: ModifierTypeOption | null = null;
|
||||
// TMs excluded from possible rewards
|
||||
while (!item || item.type.id.includes("TM_")) {
|
||||
item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [tier], allowLuckUpgrades: false })[0];
|
||||
item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [ tier ], allowLuckUpgrades: false })[0];
|
||||
}
|
||||
|
||||
encounter.setDialogueToken("itemName", item.type.name);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ item ], fillRemaining: false });
|
||||
|
||||
// Remove the chosen modifier if its stacks go to 0
|
||||
modifier.stackCount -= 1;
|
||||
@ -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);
|
||||
@ -650,7 +650,7 @@ function doPokemonTradeSequence(scene: BattleScene, tradedPokemon: PlayerPokemon
|
||||
// addPokeballOpenParticles(scene, tradedPokemon.x, tradedPokemon.y, tradedPokemon.pokeball);
|
||||
|
||||
scene.tweens.add({
|
||||
targets: [tradedPokemonTintSprite, tradedPokemonSprite],
|
||||
targets: [ tradedPokemonTintSprite, tradedPokemonSprite ],
|
||||
duration: 500,
|
||||
ease: "Sine.easeIn",
|
||||
scale: 0.25,
|
||||
@ -726,7 +726,7 @@ function doPokemonTradeFlyBySequence(scene: BattleScene, tradedPokemonSprite: Ph
|
||||
duration: FADE_DELAY,
|
||||
onComplete: () => {
|
||||
scene.tweens.add({
|
||||
targets: [receivedPokemonSprite, tradedPokemonSprite],
|
||||
targets: [ receivedPokemonSprite, tradedPokemonSprite ],
|
||||
y: tradeBaseBg.displayWidth / 2 - 100,
|
||||
ease: "Cubic.easeInOut",
|
||||
duration: BASE_ANIM_DURATION * 3,
|
||||
|
@ -10,7 +10,7 @@ import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encount
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import {PokemonMove} from "#app/field/pokemon";
|
||||
import { PokemonMove } from "#app/field/pokemon";
|
||||
|
||||
const OPTION_1_REQUIRED_MOVE = Moves.SURF;
|
||||
const OPTION_2_REQUIRED_MOVE = Moves.FLY;
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -143,7 +143,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
// Spawn standard trainer battle with memory mushroom reward
|
||||
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM], fillRemaining: true });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM ], fillRemaining: true });
|
||||
|
||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||
let ret;
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -168,7 +168,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
// Spawn hard fight
|
||||
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[1];
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], fillRemaining: true });
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], fillRemaining: true });
|
||||
|
||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||
let ret;
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -196,7 +196,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||
// To avoid player level snowballing from picking this option
|
||||
encounter.expMultiplier = 0.9;
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT], fillRemaining: true });
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT ], fillRemaining: true });
|
||||
|
||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||
let ret;
|
||||
@ -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!;
|
||||
|
||||
@ -76,12 +76,12 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
||||
species: getPokemonSpecies(Species.GIMMIGHOUL),
|
||||
formIndex: 0,
|
||||
isBoss: true,
|
||||
moveSet: [Moves.NASTY_PLOT, Moves.SHADOW_BALL, Moves.POWER_GEM, Moves.THIEF]
|
||||
moveSet: [ Moves.NASTY_PLOT, Moves.SHADOW_BALL, Moves.POWER_GEM, Moves.THIEF ]
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
encounter.setDialogueToken("gimmighoulName", getPokemonSpecies(Species.GIMMIGHOUL).getName());
|
||||
encounter.setDialogueToken("trapPercent", TRAP_PERCENT.toString());
|
||||
@ -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] });
|
||||
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] });
|
||||
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`
|
||||
}
|
||||
]
|
||||
})
|
||||
@ -94,7 +94,7 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||
// Calculation from Pokemon.calculateStats
|
||||
const baselineValue = Math.floor(((2 * 90 + 16) * pokemon.level) * 0.01) + 5;
|
||||
const percentDiff = (pokemon.getStat(Stat.SPD) - baselineValue) / baselineValue;
|
||||
const moneyMultiplier = Math.min(Math.max(2.5 * (1+ percentDiff), 1), 4);
|
||||
const moneyMultiplier = Math.min(Math.max(2.5 * (1 + percentDiff), 1), 4);
|
||||
|
||||
encounter.misc = {
|
||||
moneyMultiplier
|
||||
@ -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,9 +21,9 @@ 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];
|
||||
const TRAINER_THROW_ANIMATION_TIMES = [ 512, 184, 768 ];
|
||||
|
||||
const SAFARI_MONEY_MULTIPLIER = 2;
|
||||
|
||||
@ -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,14 +253,14 @@ 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
|
||||
let enemySpecies;
|
||||
let pokemon;
|
||||
scene.executeWithSeedOffset(() => {
|
||||
enemySpecies = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false));
|
||||
enemySpecies = getPokemonSpecies(getRandomSpeciesByStarterTier([ 0, 5 ], undefined, undefined, false, false, false));
|
||||
const level = scene.currentBattle.getLevelForWave();
|
||||
enemySpecies = getPokemonSpecies(enemySpecies.getWildSpeciesForLevel(level, true, false, scene.gameMode));
|
||||
pokemon = scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.NONE, false);
|
||||
@ -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;
|
||||
@ -33,7 +33,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withSceneRequirement(new MoneyRequirement(0, VITAMIN_DEALER_CHEAP_PRICE_MULTIPLIER)) // Must have the money for at least the cheap deal
|
||||
.withPrimaryPokemonHealthRatioRequirement([0.51, 1]) // At least 1 Pokemon must have above half HP
|
||||
.withPrimaryPokemonHealthRatioRequirement([ 0.51, 1 ]) // At least 1 Pokemon must have above half HP
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: Species.KROOKODILE.toString(),
|
||||
@ -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,8 +139,8 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
|
||||
chosenPokemon.nature = newNature;
|
||||
encounter.setDialogueToken("newNature", getNatureName(newNature));
|
||||
queueEncounterMessage(scene, `${namespace}.cheap_side_effects`);
|
||||
setEncounterExp(scene, [chosenPokemon.id], 100);
|
||||
queueEncounterMessage(scene, `${namespace}:cheap_side_effects`);
|
||||
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
||||
chosenPokemon.updateInfo();
|
||||
})
|
||||
.build()
|
||||
@ -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,8 +200,8 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
const chosenPokemon = encounter.misc.chosenPokemon;
|
||||
|
||||
queueEncounterMessage(scene, `${namespace}.no_bad_effects`);
|
||||
setEncounterExp(scene, [chosenPokemon.id], 100);
|
||||
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) => {
|
||||
@ -60,15 +60,15 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
const pokemonConfig: EnemyPokemonConfig = {
|
||||
species: bossSpecies,
|
||||
isBoss: true,
|
||||
status: [StatusEffect.SLEEP, 5], // Extra turns on timer for Snorlax's start of fight moves
|
||||
moveSet: [Moves.REST, Moves.SLEEP_TALK, Moves.CRUNCH, Moves.GIGA_IMPACT],
|
||||
status: [ StatusEffect.SLEEP, 5 ], // Extra turns on timer for Snorlax's start of fight moves
|
||||
moveSet: [ Moves.REST, Moves.SLEEP_TALK, Moves.CRUNCH, Moves.GIGA_IMPACT ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SITRUS ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.ENIGMA]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.ENIGMA ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2
|
||||
},
|
||||
],
|
||||
@ -77,44 +77,44 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||
};
|
||||
const config: EnemyPartyConfig = {
|
||||
levelAdditiveModifier: 0.5,
|
||||
pokemonConfigs: [pokemonConfig],
|
||||
pokemonConfigs: [ pokemonConfig ],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
// Load animations/sfx for Snorlax fight start moves
|
||||
loadCustomMovesForEncounter(scene, [Moves.SNORE]);
|
||||
loadCustomMovesForEncounter(scene, [ Moves.SNORE ]);
|
||||
|
||||
encounter.setDialogueToken("snorlaxName", getPokemonSpecies(Species.SNORLAX).getName());
|
||||
|
||||
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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Pick battle
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS], fillRemaining: true});
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.LEFTOVERS ], fillRemaining: true });
|
||||
encounter.startOfBattleEffects.push(
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.SNORE),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.SNORE),
|
||||
ignorePp: true
|
||||
});
|
||||
@ -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,19 +144,19 @@ 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`
|
||||
}
|
||||
]
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Steal the Snorlax's Leftovers
|
||||
const instance = scene.currentBattle.mysteryEncounter!;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.LEFTOVERS ], fillRemaining: false });
|
||||
// Snorlax exp to Pokemon that did the stealing
|
||||
setEncounterExp(scene, instance.primaryPokemon!.id, getPokemonSpecies(Species.SNORLAX).baseExp);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
|
@ -23,11 +23,11 @@ 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];
|
||||
const MACHINE_INTERFACING_TYPES = [Type.ELECTRIC, Type.STEEL];
|
||||
const BIOME_CANDIDATES = [ Biome.SPACE, Biome.FAIRY_CAVE, Biome.LABORATORY, Biome.ISLAND, Biome.WASTELAND, Biome.DOJO ];
|
||||
const MACHINE_INTERFACING_TYPES = [ Type.ELECTRIC, Type.STEEL ];
|
||||
|
||||
/**
|
||||
* Teleporting Hijinks encounter.
|
||||
@ -38,7 +38,7 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.TELEPORTING_HIJINKS)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withSceneRequirement(new WaveModulusRequirement([1, 2, 3], 10)) // Must be in first 3 waves after boss wave
|
||||
.withSceneRequirement(new WaveModulusRequirement([ 1, 2, 3 ], 10)) // Must be in first 3 waves after boss wave
|
||||
.withSceneRequirement(new MoneyRequirement(0, MONEY_COST_MULTIPLIER)) // Must be able to pay teleport cost
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withCatchAllowed(true)
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -145,9 +145,9 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||
}],
|
||||
};
|
||||
|
||||
const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.STEEL])!;
|
||||
const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.ELECTRIC])!;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [magnet, metalCoat], fillRemaining: true });
|
||||
const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.STEEL ])!;
|
||||
const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.ELECTRIC ])!;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ magnet, metalCoat ], fillRemaining: true });
|
||||
transitionMysteryEncounterIntroVisuals(scene, true, true);
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
}
|
||||
@ -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 Promise.all([animateBiomeChange(scene, newBiome), transitionMysteryEncounterIntroVisuals(scene)]);
|
||||
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);
|
||||
@ -175,8 +175,8 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) {
|
||||
|
||||
// Defense/Spd buffs below wave 50, +1 to all stats otherwise
|
||||
const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ?
|
||||
[Stat.DEF, Stat.SPDEF, Stat.SPD] :
|
||||
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD];
|
||||
[ Stat.DEF, Stat.SPDEF, Stat.SPD ] :
|
||||
[ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ];
|
||||
|
||||
const config: EnemyPartyConfig = {
|
||||
pokemonConfigs: [{
|
||||
@ -184,9 +184,9 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) {
|
||||
species: bossSpecies,
|
||||
dataSource: new PokemonData(bossPokemon),
|
||||
isBoss: true,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
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));
|
||||
}
|
||||
}],
|
||||
@ -198,7 +198,7 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) {
|
||||
async function animateBiomeChange(scene: BattleScene, nextBiome: Biome) {
|
||||
return new Promise<void>(resolve => {
|
||||
scene.tweens.add({
|
||||
targets: [scene.arenaEnemy, scene.lastEnemyTrainer],
|
||||
targets: [ scene.arenaEnemy, scene.lastEnemyTrainer ],
|
||||
x: "+=300",
|
||||
duration: 2000,
|
||||
onComplete: () => {
|
||||
@ -214,7 +214,7 @@ async function animateBiomeChange(scene: BattleScene, nextBiome: Biome) {
|
||||
scene.arenaPlayerTransition.setVisible(true);
|
||||
|
||||
scene.tweens.add({
|
||||
targets: [scene.arenaPlayer, scene.arenaBgTransition, scene.arenaPlayerTransition],
|
||||
targets: [ scene.arenaPlayer, scene.arenaBgTransition, scene.arenaPlayerTransition ],
|
||||
duration: 1000,
|
||||
ease: "Sine.easeInOut",
|
||||
alpha: (target: any) => target === scene.arenaPlayer ? 0 : 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";
|
||||
|
||||
@ -47,29 +48,29 @@ class BreederSpeciesEvolution {
|
||||
}
|
||||
|
||||
const POOL_1_POKEMON: (Species | BreederSpeciesEvolution)[][] = [
|
||||
[Species.MUNCHLAX, new BreederSpeciesEvolution(Species.SNORLAX, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.HAPPINY, new BreederSpeciesEvolution(Species.CHANSEY, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.BLISSEY, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.MAGBY, new BreederSpeciesEvolution(Species.MAGMAR, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MAGMORTAR, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.ELEKID, new BreederSpeciesEvolution(Species.ELECTABUZZ, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ELECTIVIRE, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.RIOLU, new BreederSpeciesEvolution(Species.LUCARIO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.BUDEW, new BreederSpeciesEvolution(Species.ROSELIA, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ROSERADE, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.TOXEL, new BreederSpeciesEvolution(Species.TOXTRICITY, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.MIME_JR, new BreederSpeciesEvolution(Species.GALAR_MR_MIME, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MR_RIME, FINAL_STAGE_EVOLUTION_WAVE)]
|
||||
[ Species.MUNCHLAX, new BreederSpeciesEvolution(Species.SNORLAX, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.HAPPINY, new BreederSpeciesEvolution(Species.CHANSEY, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.BLISSEY, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.MAGBY, new BreederSpeciesEvolution(Species.MAGMAR, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MAGMORTAR, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.ELEKID, new BreederSpeciesEvolution(Species.ELECTABUZZ, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ELECTIVIRE, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.RIOLU, new BreederSpeciesEvolution(Species.LUCARIO, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.BUDEW, new BreederSpeciesEvolution(Species.ROSELIA, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ROSERADE, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.TOXEL, new BreederSpeciesEvolution(Species.TOXTRICITY, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.MIME_JR, new BreederSpeciesEvolution(Species.GALAR_MR_MIME, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MR_RIME, FINAL_STAGE_EVOLUTION_WAVE) ]
|
||||
];
|
||||
|
||||
const POOL_2_POKEMON: (Species | BreederSpeciesEvolution)[][] = [
|
||||
[Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.RAICHU, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.JYNX],
|
||||
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.IGGLYBUFF, new BreederSpeciesEvolution(Species.JIGGLYPUFF, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.WIGGLYTUFF, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.AZURILL, new BreederSpeciesEvolution(Species.MARILL, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.AZUMARILL, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.WYNAUT, new BreederSpeciesEvolution(Species.WOBBUFFET, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.CHINGLING, new BreederSpeciesEvolution(Species.CHIMECHO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.BONSLY, new BreederSpeciesEvolution(Species.SUDOWOODO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||
[Species.MANTYKE, new BreederSpeciesEvolution(Species.MANTINE, SECOND_STAGE_EVOLUTION_WAVE)]
|
||||
[ Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.RAICHU, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.JYNX ],
|
||||
[ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.IGGLYBUFF, new BreederSpeciesEvolution(Species.JIGGLYPUFF, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.WIGGLYTUFF, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.AZURILL, new BreederSpeciesEvolution(Species.MARILL, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.AZUMARILL, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.WYNAUT, new BreederSpeciesEvolution(Species.WOBBUFFET, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.CHINGLING, new BreederSpeciesEvolution(Species.CHIMECHO, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.BONSLY, new BreederSpeciesEvolution(Species.SUDOWOODO, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||
[ Species.MANTYKE, new BreederSpeciesEvolution(Species.MANTINE, SECOND_STAGE_EVOLUTION_WAVE) ]
|
||||
];
|
||||
|
||||
/**
|
||||
@ -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) => {
|
||||
@ -137,46 +138,46 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||
encounter.setDialogueToken("pokemon3Name", pokemon3.getNameToRender());
|
||||
|
||||
// Dialogue and egg calcs for Pokemon 1
|
||||
const [pokemon1CommonEggs, pokemon1RareEggs] = calculateEggRewardsForPokemon(pokemon1);
|
||||
let pokemon1Tooltip = getEncounterText(scene, `${namespace}.option.1.tooltip_base`)!;
|
||||
const [ pokemon1CommonEggs, pokemon1RareEggs ] = calculateEggRewardsForPokemon(pokemon1);
|
||||
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`)!;
|
||||
const [ pokemon2CommonEggs, pokemon2RareEggs ] = calculateEggRewardsForPokemon(pokemon2);
|
||||
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`)!;
|
||||
const [ pokemon3CommonEggs, pokemon3RareEggs ] = calculateEggRewardsForPokemon(pokemon3);
|
||||
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,17 +375,17 @@ 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
|
||||
shiny: false,
|
||||
nature: Nature.ADAMANT,
|
||||
moveSet: [Moves.METEOR_MASH, Moves.FIRE_PUNCH, Moves.ICE_PUNCH, Moves.THUNDER_PUNCH],
|
||||
ivs: [31, 31, 31, 31, 31, 31],
|
||||
moveSet: [ Moves.METEOR_MASH, Moves.FIRE_PUNCH, Moves.ICE_PUNCH, Moves.THUNDER_PUNCH ],
|
||||
ivs: [ 31, 31, 31, 31, 31, 31 ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.TERA_SHARD, [Type.STEEL]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.TERA_SHARD, [ Type.STEEL ]) as PokemonHeldItemModifierType,
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -394,26 +395,26 @@ 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
|
||||
shiny: true,
|
||||
variant: 1,
|
||||
nature: Nature.MODEST,
|
||||
moveSet: [Moves.MOONBLAST, Moves.MYSTICAL_FIRE, Moves.ICE_BEAM, Moves.THUNDERBOLT],
|
||||
ivs: [31, 31, 31, 31, 31, 31]
|
||||
moveSet: [ Moves.MOONBLAST, Moves.MYSTICAL_FIRE, Moves.ICE_BEAM, Moves.THUNDERBOLT ],
|
||||
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
|
||||
shiny: true,
|
||||
variant: 2,
|
||||
nature: Nature.BOLD,
|
||||
moveSet: [Moves.TRI_ATTACK, Moves.STORED_POWER, Moves.TAKE_HEART, Moves.MOONLIGHT],
|
||||
ivs: [31, 31, 31, 31, 31, 31]
|
||||
moveSet: [ Moves.TRI_ATTACK, Moves.STORED_POWER, Moves.TAKE_HEART, Moves.MOONLIGHT ],
|
||||
ivs: [ 31, 31, 31, 31, 31, 31 ]
|
||||
});
|
||||
} else {
|
||||
// Second member from pool 1
|
||||
@ -424,12 +425,12 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
baseConfig.pokemonConfigs!.push({
|
||||
species: getPokemonSpecies(pool1Species),
|
||||
isBoss: false,
|
||||
ivs: [31, 31, 31, 31, 31, 31]
|
||||
ivs: [ 31, 31, 31, 31, 31, 31 ]
|
||||
},
|
||||
{
|
||||
species: getPokemonSpecies(pool2Species),
|
||||
isBoss: false,
|
||||
ivs: [31, 31, 31, 31, 31, 31]
|
||||
ivs: [ 31, 31, 31, 31, 31, 31 ]
|
||||
});
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -467,11 +468,11 @@ function calculateEggRewardsForPokemon(pokemon: PlayerPokemon): [number, number]
|
||||
// 1 Common egg for every point leftover
|
||||
const numCommons = totalPoints % 6;
|
||||
|
||||
return [numCommons, numRares];
|
||||
return [ numCommons, numRares ];
|
||||
}
|
||||
|
||||
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`,
|
||||
},
|
||||
];
|
||||
|
||||
@ -558,6 +559,10 @@ function onGameOver(scene: BattleScene) {
|
||||
// Revert BGM
|
||||
scene.playBgm(scene.arena.bgm);
|
||||
|
||||
// Clear any leftover battle phases
|
||||
scene.clearPhaseQueue();
|
||||
scene.clearPhaseQueueSplice();
|
||||
|
||||
// Return enemy Pokemon
|
||||
const pokemon = scene.getEnemyPokemon();
|
||||
if (pokemon) {
|
||||
|
@ -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,25 +46,25 @@ 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!;
|
||||
|
||||
let species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false));
|
||||
let species = getPokemonSpecies(getRandomSpeciesByStarterTier([ 0, 5 ], undefined, undefined, false, false, false));
|
||||
let tries = 0;
|
||||
|
||||
// Reroll any species that don't have HAs
|
||||
while ((isNullOrUndefined(species.abilityHidden) || species.abilityHidden === Abilities.NONE) && tries < 5) {
|
||||
species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false));
|
||||
species = getPokemonSpecies(getRandomSpeciesByStarterTier([ 0, 5 ], undefined, undefined, false, false, false));
|
||||
tries++;
|
||||
}
|
||||
|
||||
@ -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) => {
|
||||
@ -81,52 +81,52 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
||||
bossSegments: 5,
|
||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }),
|
||||
nature: Nature.BOLD,
|
||||
moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER],
|
||||
moveSet: [ Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SITRUS ]) as PokemonHeldItemModifierType
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.ENIGMA]) as PokemonHeldItemModifierType
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.ENIGMA ]) as PokemonHeldItemModifierType
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.APICOT]) as PokemonHeldItemModifierType
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.APICOT ]) as PokemonHeldItemModifierType
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.GANLON]) as PokemonHeldItemModifierType
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.GANLON ]) as PokemonHeldItemModifierType
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LUM]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LUM ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2
|
||||
}
|
||||
],
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.2.stat_boost`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.DEF, Stat.SPDEF], 2));
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}:option.2.stat_boost`);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ Stat.DEF, Stat.SPDEF ], 2));
|
||||
}
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
loadCustomMovesForEncounter(scene, [Moves.GASTRO_ACID, Moves.STEALTH_ROCK]);
|
||||
loadCustomMovesForEncounter(scene, [ Moves.GASTRO_ACID, Moves.STEALTH_ROCK ]);
|
||||
|
||||
encounter.setDialogueToken("shuckleName", getPokemonSpecies(Species.SHUCKLE).getName());
|
||||
|
||||
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,28 +173,28 @@ 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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Pick battle
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SOUL_DEW], fillRemaining: true });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.SOUL_DEW ], fillRemaining: true });
|
||||
encounter.startOfBattleEffects.push(
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.GASTRO_ACID),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.STEALTH_ROCK),
|
||||
ignorePp: true
|
||||
});
|
||||
|
@ -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,19 +119,19 @@ 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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Refuse the challenge, they full heal the party and give the player a Rarer Candy
|
||||
scene.unshiftPhase(new PartyHealPhase(scene, true));
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.RARER_CANDY], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.RARER_CANDY ], fillRemaining: false });
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
)
|
||||
@ -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,11 +150,11 @@ 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;
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [machoBrace], fillRemaining: false });
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ machoBrace ], fillRemaining: false });
|
||||
encounter.doContinueEncounter = undefined;
|
||||
leaveEncounterWithoutBattle(scene, false, MysteryEncounterMode.NO_BATTLE);
|
||||
} else {
|
||||
@ -232,7 +232,7 @@ function getVictorTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
abilityIndex: 0, // Guts
|
||||
nature: Nature.ADAMANT,
|
||||
moveSet: [Moves.FACADE, Moves.BRAVE_BIRD, Moves.PROTECT, Moves.QUICK_ATTACK],
|
||||
moveSet: [ Moves.FACADE, Moves.BRAVE_BIRD, Moves.PROTECT, Moves.QUICK_ATTACK ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.FLAME_ORB) as PokemonHeldItemModifierType,
|
||||
@ -250,7 +250,7 @@ function getVictorTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
abilityIndex: 1, // Guts
|
||||
nature: Nature.ADAMANT,
|
||||
moveSet: [Moves.FACADE, Moves.OBSTRUCT, Moves.NIGHT_SLASH, Moves.FIRE_PUNCH],
|
||||
moveSet: [ Moves.FACADE, Moves.OBSTRUCT, Moves.NIGHT_SLASH, Moves.FIRE_PUNCH ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.FLAME_ORB) as PokemonHeldItemModifierType,
|
||||
@ -276,7 +276,7 @@ function getVictoriaTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
abilityIndex: 0, // Natural Cure
|
||||
nature: Nature.CALM,
|
||||
moveSet: [Moves.SYNTHESIS, Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.SLEEP_POWDER],
|
||||
moveSet: [ Moves.SYNTHESIS, Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.SLEEP_POWDER ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.SOUL_DEW) as PokemonHeldItemModifierType,
|
||||
@ -294,15 +294,15 @@ function getVictoriaTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
formIndex: 1,
|
||||
nature: Nature.TIMID,
|
||||
moveSet: [Moves.PSYSHOCK, Moves.MOONBLAST, Moves.SHADOW_BALL, Moves.WILL_O_WISP],
|
||||
moveSet: [ Moves.PSYSHOCK, Moves.MOONBLAST, Moves.SHADOW_BALL, Moves.WILL_O_WISP ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.PSYCHIC]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.PSYCHIC ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 1,
|
||||
isTransferable: false
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.FAIRY]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.FAIRY ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 1,
|
||||
isTransferable: false
|
||||
}
|
||||
@ -321,15 +321,15 @@ function getViviTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
abilityIndex: 3, // Lightning Rod
|
||||
nature: Nature.ADAMANT,
|
||||
moveSet: [Moves.WATERFALL, Moves.MEGAHORN, Moves.KNOCK_OFF, Moves.REST],
|
||||
moveSet: [ Moves.WATERFALL, Moves.MEGAHORN, Moves.KNOCK_OFF, Moves.REST ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LUM]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LUM ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
isTransferable: false
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [Stat.HP]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [ Stat.HP ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 4,
|
||||
isTransferable: false
|
||||
}
|
||||
@ -340,10 +340,10 @@ function getViviTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
abilityIndex: 1, // Poison Heal
|
||||
nature: Nature.JOLLY,
|
||||
moveSet: [Moves.SPORE, Moves.SWORDS_DANCE, Moves.SEED_BOMB, Moves.DRAIN_PUNCH],
|
||||
moveSet: [ Moves.SPORE, Moves.SWORDS_DANCE, Moves.SEED_BOMB, Moves.DRAIN_PUNCH ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [Stat.HP]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [ Stat.HP ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 4,
|
||||
isTransferable: false
|
||||
},
|
||||
@ -358,7 +358,7 @@ function getViviTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
formIndex: 1,
|
||||
nature: Nature.CALM,
|
||||
moveSet: [Moves.EARTH_POWER, Moves.FIRE_BLAST, Moves.YAWN, Moves.PROTECT],
|
||||
moveSet: [ Moves.EARTH_POWER, Moves.FIRE_BLAST, Moves.YAWN, Moves.PROTECT ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.QUICK_CLAW) as PokemonHeldItemModifierType,
|
||||
@ -380,7 +380,7 @@ function getVickyTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
formIndex: 1,
|
||||
nature: Nature.IMPISH,
|
||||
moveSet: [Moves.AXE_KICK, Moves.ICE_PUNCH, Moves.ZEN_HEADBUTT, Moves.BULLET_PUNCH],
|
||||
moveSet: [ Moves.AXE_KICK, Moves.ICE_PUNCH, Moves.ZEN_HEADBUTT, Moves.BULLET_PUNCH ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType,
|
||||
@ -401,10 +401,10 @@ function getVitoTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
abilityIndex: 0, // Soundproof
|
||||
nature: Nature.MODEST,
|
||||
moveSet: [Moves.THUNDERBOLT, Moves.GIGA_DRAIN, Moves.FOUL_PLAY, Moves.THUNDER_WAVE],
|
||||
moveSet: [ Moves.THUNDERBOLT, Moves.GIGA_DRAIN, Moves.FOUL_PLAY, Moves.THUNDER_WAVE ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [Stat.SPD]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [ Stat.SPD ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
isTransferable: false
|
||||
}
|
||||
@ -415,50 +415,50 @@ function getVitoTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
abilityIndex: 2, // Gluttony
|
||||
nature: Nature.QUIET,
|
||||
moveSet: [Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.ICE_BEAM, Moves.EARTHQUAKE],
|
||||
moveSet: [ Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.ICE_BEAM, Moves.EARTHQUAKE ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SITRUS ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.APICOT]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.APICOT ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.GANLON]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.GANLON ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.STARF]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.STARF ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.SALAC]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SALAC ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LUM]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LUM ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LANSAT]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LANSAT ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LIECHI]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LIECHI ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.PETAYA]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.PETAYA ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.ENIGMA]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.ENIGMA ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
},
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LEPPA]) as PokemonHeldItemModifierType,
|
||||
modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LEPPA ]) as PokemonHeldItemModifierType,
|
||||
stackCount: 2,
|
||||
}
|
||||
]
|
||||
@ -468,7 +468,7 @@ function getVitoTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
abilityIndex: 2, // Tangled Feet
|
||||
nature: Nature.JOLLY,
|
||||
moveSet: [Moves.DRILL_PECK, Moves.QUICK_ATTACK, Moves.THRASH, Moves.KNOCK_OFF],
|
||||
moveSet: [ Moves.DRILL_PECK, Moves.QUICK_ATTACK, Moves.THRASH, Moves.KNOCK_OFF ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.KINGS_ROCK) as PokemonHeldItemModifierType,
|
||||
@ -482,7 +482,7 @@ function getVitoTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
formIndex: 1,
|
||||
nature: Nature.BOLD,
|
||||
moveSet: [Moves.PSYCHIC, Moves.SHADOW_BALL, Moves.FOCUS_BLAST, Moves.THUNDERBOLT],
|
||||
moveSet: [ Moves.PSYCHIC, Moves.SHADOW_BALL, Moves.FOCUS_BLAST, Moves.THUNDERBOLT ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.WIDE_LENS) as PokemonHeldItemModifierType,
|
||||
@ -496,7 +496,7 @@ function getVitoTrainerConfig(scene: BattleScene): EnemyPartyConfig {
|
||||
isBoss: false,
|
||||
abilityIndex: 0, // Sheer Force
|
||||
nature: Nature.IMPISH,
|
||||
moveSet: [Moves.EARTHQUAKE, Moves.U_TURN, Moves.FLARE_BLITZ, Moves.ROCK_SLIDE],
|
||||
moveSet: [ Moves.EARTHQUAKE, Moves.U_TURN, Moves.FLARE_BLITZ, Moves.ROCK_SLIDE ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(scene, modifierTypes.QUICK_CLAW) as PokemonHeldItemModifierType,
|
||||
|
@ -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!;
|
||||
|
||||
@ -67,17 +67,17 @@ export const TrashToTreasureEncounter: MysteryEncounter =
|
||||
isBoss: true,
|
||||
formIndex: 1, // Gmax
|
||||
bossSegmentModifier: 1, // +1 Segment from normal
|
||||
moveSet: [Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH]
|
||||
moveSet: [ Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH ]
|
||||
};
|
||||
const config: EnemyPartyConfig = {
|
||||
levelAdditiveModifier: 1,
|
||||
pokemonConfigs: [pokemonConfig],
|
||||
pokemonConfigs: [ pokemonConfig ],
|
||||
disableSwitch: true
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
// Load animations/sfx for Garbodor fight start moves
|
||||
loadCustomMovesForEncounter(scene, [Moves.TOXIC, Moves.AMNESIA]);
|
||||
loadCustomMovesForEncounter(scene, [ Moves.TOXIC, Moves.AMNESIA ]);
|
||||
|
||||
scene.loadSe("PRSFX- Dig2", "battle_anims", "PRSFX- Dig2.wav");
|
||||
scene.loadSe("PRSFX- Venom Drench", "battle_anims", "PRSFX- Venom Drench.wav");
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -107,7 +107,7 @@ export const TrashToTreasureEncounter: MysteryEncounter =
|
||||
transitionMysteryEncounterIntroVisuals(scene);
|
||||
await tryApplyDigRewardItems(scene);
|
||||
|
||||
const blackSludge = generateModifierType(scene, modifierTypes.MYSTERY_ENCOUNTER_BLACK_SLUDGE, [SHOP_ITEM_COST_MULTIPLIER]);
|
||||
const blackSludge = generateModifierType(scene, modifierTypes.MYSTERY_ENCOUNTER_BLACK_SLUDGE, [ SHOP_ITEM_COST_MULTIPLIER ]);
|
||||
const modifier = blackSludge?.newModifier();
|
||||
if (modifier) {
|
||||
await scene.addModifier(modifier, false, false, false, true);
|
||||
@ -123,33 +123,33 @@ 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!;
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT], fillRemaining: true });
|
||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT ], fillRemaining: true });
|
||||
encounter.startOfBattleEffects.push(
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.PLAYER],
|
||||
targets: [ BattlerIndex.PLAYER ],
|
||||
move: new PokemonMove(Moves.TOXIC),
|
||||
ignorePp: true
|
||||
},
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [BattlerIndex.ENEMY],
|
||||
targets: [ BattlerIndex.ENEMY ],
|
||||
move: new PokemonMove(Moves.AMNESIA),
|
||||
ignorePp: true
|
||||
});
|
||||
|
@ -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) => {
|
||||
@ -74,8 +74,8 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
||||
|
||||
// Defense/Spd buffs below wave 50, +1 to all stats otherwise
|
||||
const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ?
|
||||
[Stat.DEF, Stat.SPDEF, Stat.SPD] :
|
||||
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD];
|
||||
[ Stat.DEF, Stat.SPDEF, Stat.SPD ] :
|
||||
[ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ];
|
||||
|
||||
const config: EnemyPartyConfig = {
|
||||
pokemonConfigs: [{
|
||||
@ -83,14 +83,14 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
||||
species: species,
|
||||
dataSource: new PokemonData(pokemon),
|
||||
isBoss: false,
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
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));
|
||||
}
|
||||
}],
|
||||
};
|
||||
encounter.enemyPartyConfigs = [config];
|
||||
encounter.enemyPartyConfigs = [ config ];
|
||||
|
||||
const { spriteKey, fileRoot } = getSpriteKeysFromPokemon(pokemon);
|
||||
encounter.spriteConfigs = [
|
||||
@ -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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -152,7 +152,7 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
||||
encounter.startOfBattleEffects.push(
|
||||
{
|
||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||
targets: [target],
|
||||
targets: [ target ],
|
||||
move: pokemonMove,
|
||||
ignorePp: true
|
||||
});
|
||||
@ -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`
|
||||
}
|
||||
]
|
||||
})
|
||||
@ -181,7 +181,7 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
||||
|
||||
// Remove 4 random berries from player's party
|
||||
// Get all player berry items, remove from party, and store reference
|
||||
const berryItems: BerryModifier[]= scene.findModifiers(m => m instanceof BerryModifier) as BerryModifier[];
|
||||
const berryItems: BerryModifier[] = scene.findModifiers(m => m instanceof BerryModifier) as BerryModifier[];
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const index = randSeedInt(berryItems.length);
|
||||
const randBerry = berryItems[index];
|
||||
@ -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 = [
|
||||
@ -89,12 +89,12 @@ const PERCENT_LEVEL_LOSS_ON_REFUSE = 12.5;
|
||||
* Value ranges of the resulting species BST transformations after adding values to original species
|
||||
* 2 Pokemon in the party use this range
|
||||
*/
|
||||
const HIGH_BST_TRANSFORM_BASE_VALUES: [number, number] = [90, 110];
|
||||
const HIGH_BST_TRANSFORM_BASE_VALUES: [number, number] = [ 90, 110 ];
|
||||
/**
|
||||
* Value ranges of the resulting species BST transformations after adding values to original species
|
||||
* All remaining Pokemon in the party use this range
|
||||
*/
|
||||
const STANDARD_BST_TRANSFORM_BASE_VALUES: [number, number] = [40, 50];
|
||||
const STANDARD_BST_TRANSFORM_BASE_VALUES: [number, number] = [ 40, 50 ];
|
||||
|
||||
/**
|
||||
* Weird Dream encounter.
|
||||
@ -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,21 +189,21 @@ 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]});
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.MEMORY_MUSHROOM, modifierTypes.ROGUE_BALL, modifierTypes.MINT, modifierTypes.MINT ]});
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -372,7 +372,7 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
|
||||
|
||||
// Randomize the second type of the pokemon
|
||||
// If the pokemon does not normally have a second type, it will gain 1
|
||||
const newTypes = [newPokemon.getTypes()[0]];
|
||||
const newTypes = [ newPokemon.getTypes()[0] ];
|
||||
let newType = randSeedInt(18) as Type;
|
||||
while (newType === newTypes[0]) {
|
||||
newType = randSeedInt(18) as Type;
|
||||
@ -390,14 +390,14 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
|
||||
|
||||
// Any pokemon that is at or below 450 BST gets +20 permanent BST to 3 stats: HP (halved, +10), lowest of Atk/SpAtk, and lowest of Def/SpDef
|
||||
if (newPokemon.getSpeciesForm().getBaseStatTotal() <= GAIN_OLD_GATEAU_ITEM_BST_THRESHOLD) {
|
||||
const stats: Stat[] = [Stat.HP];
|
||||
const stats: Stat[] = [ Stat.HP ];
|
||||
const baseStats = newPokemon.getSpeciesForm().baseStats.slice(0);
|
||||
// Attack or SpAtk
|
||||
stats.push(baseStats[Stat.ATK] < baseStats[Stat.SPATK] ? Stat.ATK : Stat.SPATK);
|
||||
// Def or SpDef
|
||||
stats.push(baseStats[Stat.DEF] < baseStats[Stat.SPDEF] ? Stat.DEF : Stat.SPDEF);
|
||||
const modType = modifierTypes.MYSTERY_ENCOUNTER_OLD_GATEAU()
|
||||
.generateType(scene.getParty(), [20, stats])
|
||||
.generateType(scene.getParty(), [ 20, stats ])
|
||||
?.withIdFromFunc(modifierTypes.MYSTERY_ENCOUNTER_OLD_GATEAU);
|
||||
const modifier = modType?.newModifier(newPokemon);
|
||||
if (modifier) {
|
||||
@ -553,7 +553,7 @@ async function addEggMoveToNewPokemonMoveset(scene: BattleScene, newPokemon: Pla
|
||||
let eggMoveIndex: null | number = null;
|
||||
const eggMoves = newPokemon.getEggMoves()?.slice(0);
|
||||
if (eggMoves) {
|
||||
const eggMoveIndices = randSeedShuffle([0, 1, 2, 3]);
|
||||
const eggMoveIndices = randSeedShuffle([ 0, 1, 2, 3 ]);
|
||||
let randomEggMoveIndex = eggMoveIndices.pop();
|
||||
let randomEggMove = !isNullOrUndefined(randomEggMoveIndex) ? eggMoves[randomEggMoveIndex] : null;
|
||||
let retries = 0;
|
||||
|
@ -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
|
||||
@ -147,7 +147,7 @@ export class PreviousEncounterRequirement extends EncounterSceneRequirement {
|
||||
}
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["previousEncounter", scene.mysteryEncounterSaveData.encounteredEvents.find(e => e.type === this.previousEncounterRequirement)?.[0].toString() ?? ""];
|
||||
return [ "previousEncounter", scene.mysteryEncounterSaveData.encounteredEvents.find(e => e.type === this.previousEncounterRequirement)?.[0].toString() ?? "" ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ export class WaveRangeRequirement extends EncounterSceneRequirement {
|
||||
}
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["waveIndex", scene.currentBattle.waveIndex.toString()];
|
||||
return [ "waveIndex", scene.currentBattle.waveIndex.toString() ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,7 +204,7 @@ export class WaveModulusRequirement extends EncounterSceneRequirement {
|
||||
}
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["waveIndex", scene.currentBattle.waveIndex.toString()];
|
||||
return [ "waveIndex", scene.currentBattle.waveIndex.toString() ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ export class TimeOfDayRequirement extends EncounterSceneRequirement {
|
||||
|
||||
constructor(timeOfDay: TimeOfDay | TimeOfDay[]) {
|
||||
super();
|
||||
this.requiredTimeOfDay = Array.isArray(timeOfDay) ? timeOfDay : [timeOfDay];
|
||||
this.requiredTimeOfDay = Array.isArray(timeOfDay) ? timeOfDay : [ timeOfDay ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -226,7 +226,7 @@ export class TimeOfDayRequirement extends EncounterSceneRequirement {
|
||||
}
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["timeOfDay", TimeOfDay[scene.arena.getTimeOfDay()].toLocaleLowerCase()];
|
||||
return [ "timeOfDay", TimeOfDay[scene.arena.getTimeOfDay()].toLocaleLowerCase() ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,7 +235,7 @@ export class WeatherRequirement extends EncounterSceneRequirement {
|
||||
|
||||
constructor(weather: WeatherType | WeatherType[]) {
|
||||
super();
|
||||
this.requiredWeather = Array.isArray(weather) ? weather : [weather];
|
||||
this.requiredWeather = Array.isArray(weather) ? weather : [ weather ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -253,7 +253,7 @@ export class WeatherRequirement extends EncounterSceneRequirement {
|
||||
if (!isNullOrUndefined(currentWeather)) {
|
||||
token = WeatherType[currentWeather].replace("_", " ").toLocaleLowerCase();
|
||||
}
|
||||
return ["weather", token];
|
||||
return [ "weather", token ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,7 +285,7 @@ export class PartySizeRequirement extends EncounterSceneRequirement {
|
||||
}
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["partySize", scene.getParty().length.toString()];
|
||||
return [ "partySize", scene.getParty().length.toString() ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,7 +296,7 @@ export class PersistentModifierRequirement extends EncounterSceneRequirement {
|
||||
constructor(heldItem: string | string[], minNumberOfItems: number = 1) {
|
||||
super();
|
||||
this.minNumberOfItems = minNumberOfItems;
|
||||
this.requiredHeldItemModifiers = Array.isArray(heldItem) ? heldItem : [heldItem];
|
||||
this.requiredHeldItemModifiers = Array.isArray(heldItem) ? heldItem : [ heldItem ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -318,7 +318,7 @@ export class PersistentModifierRequirement extends EncounterSceneRequirement {
|
||||
}
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["requiredItem", this.requiredHeldItemModifiers[0]];
|
||||
return [ "requiredItem", this.requiredHeldItemModifiers[0] ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,7 +346,7 @@ export class MoneyRequirement extends EncounterSceneRequirement {
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
const value = this.scalingMultiplier > 0 ? scene.getWaveMoneyAmount(this.scalingMultiplier).toString() : this.requiredMoney.toString();
|
||||
return ["money", value];
|
||||
return [ "money", value ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -359,7 +359,7 @@ export class SpeciesRequirement extends EncounterPokemonRequirement {
|
||||
super();
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredSpecies = Array.isArray(species) ? species : [species];
|
||||
this.requiredSpecies = Array.isArray(species) ? species : [ species ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -381,9 +381,9 @@ export class SpeciesRequirement extends EncounterPokemonRequirement {
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
if (pokemon?.species.speciesId && this.requiredSpecies.includes(pokemon.species.speciesId)) {
|
||||
return ["species", Species[pokemon.species.speciesId]];
|
||||
return [ "species", Species[pokemon.species.speciesId] ];
|
||||
}
|
||||
return ["species", ""];
|
||||
return [ "species", "" ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -397,7 +397,7 @@ export class NatureRequirement extends EncounterPokemonRequirement {
|
||||
super();
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredNature = Array.isArray(nature) ? nature : [nature];
|
||||
this.requiredNature = Array.isArray(nature) ? nature : [ nature ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -419,9 +419,9 @@ export class NatureRequirement extends EncounterPokemonRequirement {
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
if (!isNullOrUndefined(pokemon?.nature) && this.requiredNature.includes(pokemon.nature)) {
|
||||
return ["nature", Nature[pokemon.nature]];
|
||||
return [ "nature", Nature[pokemon.nature] ];
|
||||
}
|
||||
return ["nature", ""];
|
||||
return [ "nature", "" ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,7 +436,7 @@ export class TypeRequirement extends EncounterPokemonRequirement {
|
||||
this.excludeFainted = excludeFainted;
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredType = Array.isArray(type) ? type : [type];
|
||||
this.requiredType = Array.isArray(type) ? type : [ type ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -465,9 +465,9 @@ export class TypeRequirement extends EncounterPokemonRequirement {
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
const includedTypes = this.requiredType.filter((ty) => pokemon?.getTypes().includes(ty));
|
||||
if (includedTypes.length > 0) {
|
||||
return ["type", Type[includedTypes[0]]];
|
||||
return [ "type", Type[includedTypes[0]] ];
|
||||
}
|
||||
return ["type", ""];
|
||||
return [ "type", "" ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -481,7 +481,7 @@ export class MoveRequirement extends EncounterPokemonRequirement {
|
||||
super();
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredMoves = Array.isArray(moves) ? moves : [moves];
|
||||
this.requiredMoves = Array.isArray(moves) ? moves : [ moves ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -504,9 +504,9 @@ export class MoveRequirement extends EncounterPokemonRequirement {
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
const includedMoves = pokemon?.moveset.filter((move) => move?.moveId && this.requiredMoves.includes(move.moveId));
|
||||
if (includedMoves && includedMoves.length > 0 && includedMoves[0]) {
|
||||
return ["move", includedMoves[0].getName()];
|
||||
return [ "move", includedMoves[0].getName() ];
|
||||
}
|
||||
return ["move", ""];
|
||||
return [ "move", "" ];
|
||||
}
|
||||
|
||||
}
|
||||
@ -525,7 +525,7 @@ export class CompatibleMoveRequirement extends EncounterPokemonRequirement {
|
||||
super();
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredMoves = Array.isArray(learnableMove) ? learnableMove : [learnableMove];
|
||||
this.requiredMoves = Array.isArray(learnableMove) ? learnableMove : [ learnableMove ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -548,9 +548,9 @@ export class CompatibleMoveRequirement extends EncounterPokemonRequirement {
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
const includedCompatMoves = this.requiredMoves.filter((reqMove) => pokemon?.compatibleTms.filter((tm) => !pokemon.moveset.find(m => m?.moveId === tm)).includes(reqMove));
|
||||
if (includedCompatMoves.length > 0) {
|
||||
return ["compatibleMove", Moves[includedCompatMoves[0]]];
|
||||
return [ "compatibleMove", Moves[includedCompatMoves[0]] ];
|
||||
}
|
||||
return ["compatibleMove", ""];
|
||||
return [ "compatibleMove", "" ];
|
||||
}
|
||||
|
||||
}
|
||||
@ -564,7 +564,7 @@ export class AbilityRequirement extends EncounterPokemonRequirement {
|
||||
super();
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredAbilities = Array.isArray(abilities) ? abilities : [abilities];
|
||||
this.requiredAbilities = Array.isArray(abilities) ? abilities : [ abilities ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -586,9 +586,9 @@ export class AbilityRequirement extends EncounterPokemonRequirement {
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
if (pokemon?.getAbility().id && this.requiredAbilities.some(a => pokemon.getAbility().id === a)) {
|
||||
return ["ability", pokemon.getAbility().name];
|
||||
return [ "ability", pokemon.getAbility().name ];
|
||||
}
|
||||
return ["ability", ""];
|
||||
return [ "ability", "" ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -601,7 +601,7 @@ export class StatusEffectRequirement extends EncounterPokemonRequirement {
|
||||
super();
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredStatusEffect = Array.isArray(statusEffect) ? statusEffect : [statusEffect];
|
||||
this.requiredStatusEffect = Array.isArray(statusEffect) ? statusEffect : [ statusEffect ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -649,9 +649,9 @@ export class StatusEffectRequirement extends EncounterPokemonRequirement {
|
||||
return pokemon!.status?.effect === a;
|
||||
});
|
||||
if (reqStatus.length > 0) {
|
||||
return ["status", StatusEffect[reqStatus[0]]];
|
||||
return [ "status", StatusEffect[reqStatus[0]] ];
|
||||
}
|
||||
return ["status", ""];
|
||||
return [ "status", "" ];
|
||||
}
|
||||
|
||||
}
|
||||
@ -670,7 +670,7 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen
|
||||
super();
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredFormChangeItem = Array.isArray(formChangeItem) ? formChangeItem : [formChangeItem];
|
||||
this.requiredFormChangeItem = Array.isArray(formChangeItem) ? formChangeItem : [ formChangeItem ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -706,9 +706,9 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
const requiredItems = this.requiredFormChangeItem.filter((formChangeItem) => this.filterByForm(pokemon, formChangeItem));
|
||||
if (requiredItems.length > 0) {
|
||||
return ["formChangeItem", FormChangeItem[requiredItems[0]]];
|
||||
return [ "formChangeItem", FormChangeItem[requiredItems[0]] ];
|
||||
}
|
||||
return ["formChangeItem", ""];
|
||||
return [ "formChangeItem", "" ];
|
||||
}
|
||||
|
||||
}
|
||||
@ -722,7 +722,7 @@ export class CanEvolveWithItemRequirement extends EncounterPokemonRequirement {
|
||||
super();
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredEvolutionItem = Array.isArray(evolutionItems) ? evolutionItems : [evolutionItems];
|
||||
this.requiredEvolutionItem = Array.isArray(evolutionItems) ? evolutionItems : [ evolutionItems ];
|
||||
}
|
||||
|
||||
override meetsRequirement(scene: BattleScene): boolean {
|
||||
@ -756,9 +756,9 @@ export class CanEvolveWithItemRequirement extends EncounterPokemonRequirement {
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
const requiredItems = this.requiredEvolutionItem.filter((evoItem) => this.filterByEvo(pokemon, evoItem));
|
||||
if (requiredItems.length > 0) {
|
||||
return ["evolutionItem", EvolutionItem[requiredItems[0]]];
|
||||
return [ "evolutionItem", EvolutionItem[requiredItems[0]] ];
|
||||
}
|
||||
return ["evolutionItem", ""];
|
||||
return [ "evolutionItem", "" ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -772,7 +772,7 @@ export class HeldItemRequirement extends EncounterPokemonRequirement {
|
||||
super();
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredHeldItemModifiers = Array.isArray(heldItem) ? heldItem : [heldItem];
|
||||
this.requiredHeldItemModifiers = Array.isArray(heldItem) ? heldItem : [ heldItem ];
|
||||
this.requireTransferable = requireTransferable;
|
||||
}
|
||||
|
||||
@ -807,9 +807,9 @@ export class HeldItemRequirement extends EncounterPokemonRequirement {
|
||||
&& (!this.requireTransferable || it.isTransferable);
|
||||
});
|
||||
if (requiredItems && requiredItems.length > 0) {
|
||||
return ["heldItem", requiredItems[0].type.name];
|
||||
return [ "heldItem", requiredItems[0].type.name ];
|
||||
}
|
||||
return ["heldItem", ""];
|
||||
return [ "heldItem", "" ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -823,7 +823,7 @@ export class AttackTypeBoosterHeldItemTypeRequirement extends EncounterPokemonRe
|
||||
super();
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredHeldItemTypes = Array.isArray(heldItemTypes) ? heldItemTypes : [heldItemTypes];
|
||||
this.requiredHeldItemTypes = Array.isArray(heldItemTypes) ? heldItemTypes : [ heldItemTypes ];
|
||||
this.requireTransferable = requireTransferable;
|
||||
}
|
||||
|
||||
@ -864,9 +864,9 @@ export class AttackTypeBoosterHeldItemTypeRequirement extends EncounterPokemonRe
|
||||
&& (!this.requireTransferable || it.isTransferable);
|
||||
});
|
||||
if (requiredItems && requiredItems.length > 0) {
|
||||
return ["heldItem", requiredItems[0].type.name];
|
||||
return [ "heldItem", requiredItems[0].type.name ];
|
||||
}
|
||||
return ["heldItem", ""];
|
||||
return [ "heldItem", "" ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -904,7 +904,7 @@ export class LevelRequirement extends EncounterPokemonRequirement {
|
||||
}
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["level", pokemon?.level.toString() ?? ""];
|
||||
return [ "level", pokemon?.level.toString() ?? "" ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -942,7 +942,7 @@ export class FriendshipRequirement extends EncounterPokemonRequirement {
|
||||
}
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["friendship", pokemon?.friendship.toString() ?? ""];
|
||||
return [ "friendship", pokemon?.friendship.toString() ?? "" ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -989,9 +989,9 @@ export class HealthRatioRequirement extends EncounterPokemonRequirement {
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
const hpRatio = pokemon?.getHpRatio();
|
||||
if (!isNullOrUndefined(hpRatio)) {
|
||||
return ["healthRatio", Math.floor(hpRatio * 100).toString() + "%"];
|
||||
return [ "healthRatio", Math.floor(hpRatio * 100).toString() + "%" ];
|
||||
}
|
||||
return ["healthRatio", ""];
|
||||
return [ "healthRatio", "" ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1029,8 +1029,7 @@ export class WeightRequirement extends EncounterPokemonRequirement {
|
||||
}
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["weight", pokemon?.getWeight().toString() ?? ""];
|
||||
return [ "weight", pokemon?.getWeight().toString() ?? "" ];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -265,7 +265,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
||||
}
|
||||
this.encounterTier = this.encounterTier ?? MysteryEncounterTier.COMMON;
|
||||
this.dialogue = this.dialogue ?? {};
|
||||
this.spriteConfigs = this.spriteConfigs ? [...this.spriteConfigs] : [];
|
||||
this.spriteConfigs = this.spriteConfigs ? [ ...this.spriteConfigs ] : [];
|
||||
// Default max is 1 for ROGUE encounters, 2 for others
|
||||
this.maxAllowedEncounters = this.maxAllowedEncounters ?? this.encounterTier === MysteryEncounterTier.ROGUE ? DEFAULT_MAX_ALLOWED_ROGUE_ENCOUNTERS : DEFAULT_MAX_ALLOWED_ENCOUNTERS;
|
||||
this.encounterMode = MysteryEncounterMode.DEFAULT;
|
||||
@ -573,7 +573,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
*/
|
||||
withOption(option: MysteryEncounterOption): this & Pick<IMysteryEncounter, "options"> {
|
||||
if (!this.options) {
|
||||
const options = [option];
|
||||
const options = [ option ];
|
||||
return Object.assign(this, { options });
|
||||
} else {
|
||||
this.options.push(option);
|
||||
@ -624,11 +624,11 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
}
|
||||
|
||||
withIntroDialogue(dialogue: MysteryEncounterDialogue["intro"] = []): this {
|
||||
this.dialogue = {...this.dialogue, intro: dialogue };
|
||||
this.dialogue = { ...this.dialogue, intro: dialogue };
|
||||
return this;
|
||||
}
|
||||
|
||||
withIntro({spriteConfigs, dialogue} : {spriteConfigs: MysteryEncounterSpriteConfig[], dialogue?: MysteryEncounterDialogue["intro"]}) {
|
||||
withIntro({ spriteConfigs, dialogue } : {spriteConfigs: MysteryEncounterSpriteConfig[], dialogue?: MysteryEncounterDialogue["intro"]}) {
|
||||
return this.withIntroSpriteConfigs(spriteConfigs).withIntroDialogue(dialogue);
|
||||
}
|
||||
|
||||
@ -660,7 +660,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
* @returns
|
||||
*/
|
||||
withAnimations(...encounterAnimations: EncounterAnim[]): this & Required<Pick<IMysteryEncounter, "encounterAnimations">> {
|
||||
const animations = Array.isArray(encounterAnimations) ? encounterAnimations : [encounterAnimations];
|
||||
const animations = Array.isArray(encounterAnimations) ? encounterAnimations : [ encounterAnimations ];
|
||||
return Object.assign(this, { encounterAnimations: animations });
|
||||
}
|
||||
|
||||
@ -670,7 +670,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
* @param disallowedGameModes
|
||||
*/
|
||||
withDisallowedGameModes(...disallowedGameModes: GameModes[]): this & Required<Pick<IMysteryEncounter, "disallowedGameModes">> {
|
||||
const gameModes = Array.isArray(disallowedGameModes) ? disallowedGameModes : [disallowedGameModes];
|
||||
const gameModes = Array.isArray(disallowedGameModes) ? disallowedGameModes : [ disallowedGameModes ];
|
||||
return Object.assign(this, { disallowedGameModes: gameModes });
|
||||
}
|
||||
|
||||
@ -680,7 +680,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
* @param disallowedChallenges
|
||||
*/
|
||||
withDisallowedChallenges(...disallowedChallenges: Challenges[]): this & Required<Pick<IMysteryEncounter, "disallowedChallenges">> {
|
||||
const challenges = Array.isArray(disallowedChallenges) ? disallowedChallenges : [disallowedChallenges];
|
||||
const challenges = Array.isArray(disallowedChallenges) ? disallowedChallenges : [ disallowedChallenges ];
|
||||
return Object.assign(this, { disallowedChallenges: challenges });
|
||||
}
|
||||
|
||||
@ -755,7 +755,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
* @returns
|
||||
*/
|
||||
withSceneWaveRangeRequirement(min: number, max?: number): this & Required<Pick<IMysteryEncounter, "requirements">> {
|
||||
return this.withSceneRequirement(new WaveRangeRequirement([min, max ?? min]));
|
||||
return this.withSceneRequirement(new WaveRangeRequirement([ min, max ?? min ]));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -767,7 +767,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
* @returns
|
||||
*/
|
||||
withScenePartySizeRequirement(min: number, max?: number, excludeDisallowedPokemon: boolean = false): this & Required<Pick<IMysteryEncounter, "requirements">> {
|
||||
return this.withSceneRequirement(new PartySizeRequirement([min, max ?? min], excludeDisallowedPokemon));
|
||||
return this.withSceneRequirement(new PartySizeRequirement([ min, max ?? min ], excludeDisallowedPokemon));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -982,7 +982,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
* @returns
|
||||
*/
|
||||
withOutroDialogue(dialogue: MysteryEncounterDialogue["outro"] = []): this {
|
||||
this.dialogue = {...this.dialogue, outro: dialogue };
|
||||
this.dialogue = { ...this.dialogue, outro: dialogue };
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
@ -224,72 +224,72 @@ const anyBiomeEncounters: MysteryEncounterType[] = [
|
||||
* that biome groups do not cover
|
||||
*/
|
||||
export const mysteryEncountersByBiome = new Map<Biome, MysteryEncounterType[]>([
|
||||
[Biome.TOWN, []],
|
||||
[Biome.PLAINS, [
|
||||
[ Biome.TOWN, []],
|
||||
[ Biome.PLAINS, [
|
||||
MysteryEncounterType.SLUMBERING_SNORLAX,
|
||||
MysteryEncounterType.ABSOLUTE_AVARICE
|
||||
]],
|
||||
[Biome.GRASS, [
|
||||
[ Biome.GRASS, [
|
||||
MysteryEncounterType.SLUMBERING_SNORLAX,
|
||||
MysteryEncounterType.ABSOLUTE_AVARICE
|
||||
]],
|
||||
[Biome.TALL_GRASS, [
|
||||
[ Biome.TALL_GRASS, [
|
||||
MysteryEncounterType.ABSOLUTE_AVARICE
|
||||
]],
|
||||
[Biome.METROPOLIS, []],
|
||||
[Biome.FOREST, [
|
||||
[ Biome.METROPOLIS, []],
|
||||
[ Biome.FOREST, [
|
||||
MysteryEncounterType.SAFARI_ZONE,
|
||||
MysteryEncounterType.ABSOLUTE_AVARICE
|
||||
]],
|
||||
[Biome.SEA, [
|
||||
[ Biome.SEA, [
|
||||
MysteryEncounterType.LOST_AT_SEA
|
||||
]],
|
||||
[Biome.SWAMP, [
|
||||
[ Biome.SWAMP, [
|
||||
MysteryEncounterType.SAFARI_ZONE
|
||||
]],
|
||||
[Biome.BEACH, []],
|
||||
[Biome.LAKE, []],
|
||||
[Biome.SEABED, []],
|
||||
[Biome.MOUNTAIN, []],
|
||||
[Biome.BADLANDS, [
|
||||
[ Biome.BEACH, []],
|
||||
[ Biome.LAKE, []],
|
||||
[ Biome.SEABED, []],
|
||||
[ Biome.MOUNTAIN, []],
|
||||
[ Biome.BADLANDS, [
|
||||
MysteryEncounterType.DANCING_LESSONS
|
||||
]],
|
||||
[Biome.CAVE, [
|
||||
[ Biome.CAVE, [
|
||||
MysteryEncounterType.THE_STRONG_STUFF
|
||||
]],
|
||||
[Biome.DESERT, [
|
||||
[ Biome.DESERT, [
|
||||
MysteryEncounterType.DANCING_LESSONS
|
||||
]],
|
||||
[Biome.ICE_CAVE, []],
|
||||
[Biome.MEADOW, []],
|
||||
[Biome.POWER_PLANT, []],
|
||||
[Biome.VOLCANO, [
|
||||
[ Biome.ICE_CAVE, []],
|
||||
[ Biome.MEADOW, []],
|
||||
[ Biome.POWER_PLANT, []],
|
||||
[ Biome.VOLCANO, [
|
||||
MysteryEncounterType.FIERY_FALLOUT,
|
||||
MysteryEncounterType.DANCING_LESSONS
|
||||
]],
|
||||
[Biome.GRAVEYARD, []],
|
||||
[Biome.DOJO, []],
|
||||
[Biome.FACTORY, []],
|
||||
[Biome.RUINS, []],
|
||||
[Biome.WASTELAND, [
|
||||
[ Biome.GRAVEYARD, []],
|
||||
[ Biome.DOJO, []],
|
||||
[ Biome.FACTORY, []],
|
||||
[ Biome.RUINS, []],
|
||||
[ Biome.WASTELAND, [
|
||||
MysteryEncounterType.DANCING_LESSONS
|
||||
]],
|
||||
[Biome.ABYSS, [
|
||||
[ Biome.ABYSS, [
|
||||
MysteryEncounterType.DANCING_LESSONS
|
||||
]],
|
||||
[Biome.SPACE, [
|
||||
[ Biome.SPACE, [
|
||||
MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER
|
||||
]],
|
||||
[Biome.CONSTRUCTION_SITE, []],
|
||||
[Biome.JUNGLE, [
|
||||
[ Biome.CONSTRUCTION_SITE, []],
|
||||
[ Biome.JUNGLE, [
|
||||
MysteryEncounterType.SAFARI_ZONE
|
||||
]],
|
||||
[Biome.FAIRY_CAVE, []],
|
||||
[Biome.TEMPLE, []],
|
||||
[Biome.SLUM, []],
|
||||
[Biome.SNOWY_FOREST, []],
|
||||
[Biome.ISLAND, []],
|
||||
[Biome.LABORATORY, []]
|
||||
[ Biome.FAIRY_CAVE, []],
|
||||
[ Biome.TEMPLE, []],
|
||||
[ Biome.SLUM, []],
|
||||
[ Biome.SNOWY_FOREST, []],
|
||||
[ Biome.ISLAND, []],
|
||||
[ Biome.LABORATORY, []]
|
||||
]);
|
||||
|
||||
export function initMysteryEncounters() {
|
||||
@ -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);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ export class CanLearnMoveRequirement extends EncounterPokemonRequirement {
|
||||
|
||||
constructor(requiredMoves: Moves | Moves[], options: CanLearnMoveRequirementOptions = {}) {
|
||||
super();
|
||||
this.requiredMoves = Array.isArray(requiredMoves) ? requiredMoves : [requiredMoves];
|
||||
this.requiredMoves = Array.isArray(requiredMoves) ? requiredMoves : [ requiredMoves ];
|
||||
|
||||
this.excludeLevelMoves = options.excludeLevelMoves ?? false;
|
||||
this.excludeTmMoves = options.excludeTmMoves ?? false;
|
||||
@ -64,11 +64,11 @@ export class CanLearnMoveRequirement extends EncounterPokemonRequirement {
|
||||
}
|
||||
|
||||
override getDialogueToken(_scene: BattleScene, _pokemon?: PlayerPokemon): [string, string] {
|
||||
return ["requiredMoves", this.requiredMoves.map(m => new PokemonMove(m).getName()).join(", ")];
|
||||
return [ "requiredMoves", this.requiredMoves.map(m => new PokemonMove(m).getName()).join(", ") ];
|
||||
}
|
||||
|
||||
private getPokemonLevelMoves(pkm: PlayerPokemon): Moves[] {
|
||||
return pkm.getLevelMoves().map(([_level, move]) => move);
|
||||
return pkm.getLevelMoves().map(([ _level, move ]) => move);
|
||||
}
|
||||
|
||||
private getAllPokemonMoves(pkm: PlayerPokemon): Moves[] {
|
||||
|
@ -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";
|
||||
@ -373,7 +373,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
||||
* @param moves
|
||||
*/
|
||||
export function loadCustomMovesForEncounter(scene: BattleScene, moves: Moves | Moves[]) {
|
||||
moves = Array.isArray(moves) ? moves : [moves];
|
||||
moves = Array.isArray(moves) ? moves : [ moves ];
|
||||
return Promise.all(moves.map(move => initMoveAnim(scene, move)))
|
||||
.then(() => loadMoveAnimAssets(scene, moves));
|
||||
}
|
||||
@ -663,7 +663,7 @@ export function setEncounterRewards(scene: BattleScene, customShopRewards?: Cust
|
||||
* @param useWaveIndex - set to false when directly passing the the full exp value instead of baseExpValue
|
||||
*/
|
||||
export function setEncounterExp(scene: BattleScene, participantId: number | number[], baseExpValue: number, useWaveIndex: boolean = true) {
|
||||
const participantIds = Array.isArray(participantId) ? participantId : [participantId];
|
||||
const participantIds = Array.isArray(participantId) ? participantId : [ participantId ];
|
||||
|
||||
scene.currentBattle.mysteryEncounter!.doEncounterExp = (scene: BattleScene) => {
|
||||
scene.unshiftPhase(new PartyExpPhase(scene, baseExpValue, useWaveIndex, new Set(participantIds)));
|
||||
@ -800,8 +800,8 @@ export function transitionMysteryEncounterIntroVisuals(scene: BattleScene, hide:
|
||||
|
||||
// Transition
|
||||
scene.tweens.add({
|
||||
targets: [introVisuals, enemyPokemon],
|
||||
x: `${hide? "+" : "-"}=16`,
|
||||
targets: [ introVisuals, enemyPokemon ],
|
||||
x: `${hide ? "+" : "-"}=16`,
|
||||
y: `${hide ? "-" : "+"}=16`,
|
||||
alpha: hide ? 0 : 1,
|
||||
ease: "Sine.easeInOut",
|
||||
@ -888,14 +888,14 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
|
||||
const numRuns = 1000;
|
||||
let run = 0;
|
||||
const biomes = Object.keys(Biome).filter(key => isNaN(Number(key)));
|
||||
const alwaysPickTheseBiomes = [Biome.ISLAND, Biome.ABYSS, Biome.WASTELAND, Biome.FAIRY_CAVE, Biome.TEMPLE, Biome.LABORATORY, Biome.SPACE, Biome.WASTELAND];
|
||||
const alwaysPickTheseBiomes = [ Biome.ISLAND, Biome.ABYSS, Biome.WASTELAND, Biome.FAIRY_CAVE, Biome.TEMPLE, Biome.LABORATORY, Biome.SPACE, Biome.WASTELAND ];
|
||||
|
||||
const calculateNumEncounters = (): any[] => {
|
||||
let encounterRate = baseSpawnWeight; // BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT
|
||||
const numEncounters = [0, 0, 0, 0];
|
||||
const numEncounters = [ 0, 0, 0, 0 ];
|
||||
let mostRecentEncounterWave = 0;
|
||||
const encountersByBiome = new Map<string, number>(biomes.map(b => [b, 0]));
|
||||
const validMEfloorsByBiome = new Map<string, number>(biomes.map(b => [b, 0]));
|
||||
const encountersByBiome = new Map<string, number>(biomes.map(b => [ b, 0 ]));
|
||||
const validMEfloorsByBiome = new Map<string, number>(biomes.map(b => [ b, 0 ]));
|
||||
let currentBiome = Biome.TOWN;
|
||||
let currentArena = scene.newArena(currentBiome);
|
||||
scene.setSeed(Utils.randomString(24));
|
||||
@ -968,7 +968,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
|
||||
|
||||
// Calculate encounter rarity
|
||||
// Common / Uncommon / Rare / Super Rare (base is out of 128)
|
||||
const tierWeights = [66, 40, 19, 3];
|
||||
const tierWeights = [ 66, 40, 19, 3 ];
|
||||
|
||||
// Adjust tier weights by currently encountered events (pity system that lowers odds of multiple Common/Great)
|
||||
tierWeights[0] = tierWeights[0] - 6 * numEncounters[0];
|
||||
@ -987,7 +987,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
|
||||
}
|
||||
}
|
||||
|
||||
return [numEncounters, encountersByBiome, validMEfloorsByBiome];
|
||||
return [ numEncounters, encountersByBiome, validMEfloorsByBiome ];
|
||||
};
|
||||
|
||||
const encounterRuns: number[][] = [];
|
||||
@ -995,7 +995,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
|
||||
const validFloorsByBiome: Map<string, number>[] = [];
|
||||
while (run < numRuns) {
|
||||
scene.executeWithSeedOffset(() => {
|
||||
const [numEncounters, encountersByBiome, validMEfloorsByBiome] = calculateNumEncounters();
|
||||
const [ numEncounters, encountersByBiome, validMEfloorsByBiome ] = calculateNumEncounters();
|
||||
encounterRuns.push(numEncounters);
|
||||
encountersByBiomeRuns.push(encountersByBiome);
|
||||
validFloorsByBiome.push(validMEfloorsByBiome);
|
||||
@ -1036,7 +1036,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
|
||||
|
||||
let stats = `Starting weight: ${baseSpawnWeight}\nAverage MEs per run: ${totalMean}\nStandard Deviation: ${totalStd}\nAvg Commons: ${commonMean}\nAvg Greats: ${uncommonMean}\nAvg Ultras: ${rareMean}\nAvg Rogues: ${superRareMean}\n`;
|
||||
|
||||
const meanEncountersPerRunPerBiomeSorted = [...meanEncountersPerRunPerBiome.entries()].sort((e1, e2) => e2[1] - e1[1]);
|
||||
const meanEncountersPerRunPerBiomeSorted = [ ...meanEncountersPerRunPerBiome.entries() ].sort((e1, e2) => e2[1] - e1[1]);
|
||||
meanEncountersPerRunPerBiomeSorted.forEach(value => stats = stats + `${value[0]}: avg valid floors ${meanMEFloorsPerRunPerBiome.get(value[0])}, avg MEs ${value[1]},\n`);
|
||||
|
||||
console.log(stats);
|
||||
@ -1054,7 +1054,7 @@ export function calculateRareSpawnAggregateStats(scene: BattleScene, luckValue:
|
||||
let run = 0;
|
||||
|
||||
const calculateNumRareEncounters = (): any[] => {
|
||||
const bossEncountersByRarity = [0, 0, 0, 0];
|
||||
const bossEncountersByRarity = [ 0, 0, 0, 0 ];
|
||||
scene.setSeed(Utils.randomString(24));
|
||||
scene.resetSeed();
|
||||
// There are 12 wild boss floors
|
||||
|
@ -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]))
|
||||
@ -215,7 +216,7 @@ export function getRandomSpeciesByStarterTier(starterTiers: number | [number, nu
|
||||
&& (allowLegendary || !pokemonSpecies.legendary)
|
||||
&& (allowMythical || !pokemonSpecies.mythical);
|
||||
})
|
||||
.map(s => [getPokemonSpecies(s[0]), s[1]]);
|
||||
.map(s => [ getPokemonSpecies(s[0]), s[1] ]);
|
||||
|
||||
if (types && types.length > 0) {
|
||||
filteredSpecies = filteredSpecies.filter(s => types.includes(s[0].type1) || (!isNullOrUndefined(s[0].type2) && types.includes(s[0].type2)));
|
||||
@ -224,7 +225,7 @@ export function getRandomSpeciesByStarterTier(starterTiers: number | [number, nu
|
||||
// If no filtered mons exist at specified starter tiers, will expand starter search range until there are
|
||||
// Starts by decrementing starter tier min until it is 0, then increments tier max up to 10
|
||||
let tryFilterStarterTiers: [PokemonSpecies, number][] = filteredSpecies.filter(s => (s[1] >= min && s[1] <= max));
|
||||
while (tryFilterStarterTiers.length === 0 && (min !== 0 && max !== 10)) {
|
||||
while (tryFilterStarterTiers.length === 0 && !(min === 0 && max === 10)) {
|
||||
if (min > 0) {
|
||||
min--;
|
||||
} else {
|
||||
@ -312,7 +313,7 @@ export function applyHealToPokemon(scene: BattleScene, pokemon: PlayerPokemon, h
|
||||
*/
|
||||
export async function modifyPlayerPokemonBST(pokemon: PlayerPokemon, value: number) {
|
||||
const modType = modifierTypes.MYSTERY_ENCOUNTER_SHUCKLE_JUICE()
|
||||
.generateType(pokemon.scene.getParty(), [value])
|
||||
.generateType(pokemon.scene.getParty(), [ value ])
|
||||
?.withIdFromFunc(modifierTypes.MYSTERY_ENCOUNTER_SHUCKLE_JUICE);
|
||||
const modifier = modType?.newModifier(pokemon);
|
||||
if (modifier) {
|
||||
@ -601,7 +602,7 @@ export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, po
|
||||
}
|
||||
});
|
||||
};
|
||||
Promise.all([pokemon.hideInfo(), scene.gameData.setPokemonCaught(pokemon)]).then(() => {
|
||||
Promise.all([ pokemon.hideInfo(), scene.gameData.setPokemonCaught(pokemon) ]).then(() => {
|
||||
if (scene.getParty().length === 6) {
|
||||
const promptRelease = () => {
|
||||
scene.ui.showText(i18next.t("battle:partyFull", { pokemonName: pokemon.getNameToRender() }), null, () => {
|
||||
@ -727,33 +728,33 @@ export function doPlayerFlee(scene: BattleScene, pokemon: EnemyPokemon): Promise
|
||||
* Bug Species and their corresponding weights
|
||||
*/
|
||||
const GOLDEN_BUG_NET_SPECIES_POOL: [Species, number][] = [
|
||||
[Species.SCYTHER, 40],
|
||||
[Species.SCIZOR, 40],
|
||||
[Species.KLEAVOR, 40],
|
||||
[Species.PINSIR, 40],
|
||||
[Species.HERACROSS, 40],
|
||||
[Species.YANMA, 40],
|
||||
[Species.YANMEGA, 40],
|
||||
[Species.SHUCKLE, 40],
|
||||
[Species.ANORITH, 40],
|
||||
[Species.ARMALDO, 40],
|
||||
[Species.ESCAVALIER, 40],
|
||||
[Species.ACCELGOR, 40],
|
||||
[Species.JOLTIK, 40],
|
||||
[Species.GALVANTULA, 40],
|
||||
[Species.DURANT, 40],
|
||||
[Species.LARVESTA, 40],
|
||||
[Species.VOLCARONA, 40],
|
||||
[Species.DEWPIDER, 40],
|
||||
[Species.ARAQUANID, 40],
|
||||
[Species.WIMPOD, 40],
|
||||
[Species.GOLISOPOD, 40],
|
||||
[Species.SIZZLIPEDE, 40],
|
||||
[Species.CENTISKORCH, 40],
|
||||
[Species.NYMBLE, 40],
|
||||
[Species.LOKIX, 40],
|
||||
[Species.BUZZWOLE, 1],
|
||||
[Species.PHEROMOSA, 1],
|
||||
[ Species.SCYTHER, 40 ],
|
||||
[ Species.SCIZOR, 40 ],
|
||||
[ Species.KLEAVOR, 40 ],
|
||||
[ Species.PINSIR, 40 ],
|
||||
[ Species.HERACROSS, 40 ],
|
||||
[ Species.YANMA, 40 ],
|
||||
[ Species.YANMEGA, 40 ],
|
||||
[ Species.SHUCKLE, 40 ],
|
||||
[ Species.ANORITH, 40 ],
|
||||
[ Species.ARMALDO, 40 ],
|
||||
[ Species.ESCAVALIER, 40 ],
|
||||
[ Species.ACCELGOR, 40 ],
|
||||
[ Species.JOLTIK, 40 ],
|
||||
[ Species.GALVANTULA, 40 ],
|
||||
[ Species.DURANT, 40 ],
|
||||
[ Species.LARVESTA, 40 ],
|
||||
[ Species.VOLCARONA, 40 ],
|
||||
[ Species.DEWPIDER, 40 ],
|
||||
[ Species.ARAQUANID, 40 ],
|
||||
[ Species.WIMPOD, 40 ],
|
||||
[ Species.GOLISOPOD, 40 ],
|
||||
[ Species.SIZZLIPEDE, 40 ],
|
||||
[ Species.CENTISKORCH, 40 ],
|
||||
[ Species.NYMBLE, 40 ],
|
||||
[ Species.LOKIX, 40 ],
|
||||
[ Species.BUZZWOLE, 1 ],
|
||||
[ Species.PHEROMOSA, 1 ],
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -640,18 +640,18 @@ export const pokemonFormChanges: PokemonFormChanges = {
|
||||
new SpeciesFormChange(Species.ALTARIA, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.ALTARIANITE))
|
||||
],
|
||||
[Species.CASTFORM]: [
|
||||
new SpeciesFormChange(Species.CASTFORM, "", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "rainy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "snowy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "sunny", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "snowy", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "sunny", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "rainy", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.SUNNY, WeatherType.HARSH_SUN ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "rainy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.SUNNY, WeatherType.HARSH_SUN ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "snowy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.SUNNY, WeatherType.HARSH_SUN ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.RAIN, WeatherType.HEAVY_RAIN ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "sunny", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.RAIN, WeatherType.HEAVY_RAIN ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "snowy", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.RAIN, WeatherType.HEAVY_RAIN ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.HAIL, WeatherType.SNOW ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "sunny", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.HAIL, WeatherType.SNOW ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "rainy", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.HAIL, WeatherType.SNOW ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [ WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [ WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [ WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG ]), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeActiveTrigger(), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeActiveTrigger(), true),
|
||||
new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeActiveTrigger(), true)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -185,26 +185,26 @@ const seasonalSplashMessages: Season[] = [
|
||||
name: "Halloween",
|
||||
start: "09-15",
|
||||
end: "10-31",
|
||||
messages: ["halloween.pumpkabooAbout", "halloween.mayContainSpiders", "halloween.spookyScarySkeledirge", "halloween.gourgeistUsedTrickOrTreat", "halloween.letsSnuggleForever"],
|
||||
messages: [ "halloween.pumpkabooAbout", "halloween.mayContainSpiders", "halloween.spookyScarySkeledirge", "halloween.gourgeistUsedTrickOrTreat", "halloween.letsSnuggleForever" ],
|
||||
},
|
||||
{
|
||||
name: "XMAS",
|
||||
start: "12-01",
|
||||
end: "12-26",
|
||||
messages: ["xmas.happyHolidays", "xmas.unaffilicatedWithDelibirdServices", "xmas.delibirdSeason", "xmas.diamondsFromTheSky", "xmas.holidayStylePikachuNotIncluded"],
|
||||
messages: [ "xmas.happyHolidays", "xmas.unaffilicatedWithDelibirdServices", "xmas.delibirdSeason", "xmas.diamondsFromTheSky", "xmas.holidayStylePikachuNotIncluded" ],
|
||||
},
|
||||
{
|
||||
name: "New Year's",
|
||||
start: "01-01",
|
||||
end: "01-31",
|
||||
messages: ["newYears.happyNewYear"],
|
||||
messages: [ "newYears.happyNewYear" ],
|
||||
},
|
||||
];
|
||||
|
||||
//#endregion
|
||||
|
||||
export function getSplashMessages(): string[] {
|
||||
const splashMessages: string[] = [...commonSplashMessages];
|
||||
const splashMessages: string[] = [ ...commonSplashMessages ];
|
||||
console.log("use seasonal splash messages", USE_SEASONAL_SPLASH_MESSAGES);
|
||||
if (USE_SEASONAL_SPLASH_MESSAGES) {
|
||||
// add seasonal splash messages if the season is active
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -75,56 +75,56 @@ const trainerNameConfigs: TrainerNameConfigs = {
|
||||
};
|
||||
|
||||
export const trainerNamePools = {
|
||||
[TrainerType.ACE_TRAINER]: [["Aaron", "Allen", "Blake", "Brian", "Gaven", "Jake", "Kevin", "Mike", "Nick", "Paul", "Ryan", "Sean", "Darin", "Albert", "Berke", "Clyde", "Edgar", "George", "Leroy", "Owen", "Parker", "Randall", "Ruben", "Samuel", "Vincent", "Warren", "Wilton", "Zane", "Alfred", "Braxton", "Felix", "Gerald", "Jonathan", "Leonel", "Marcel", "Mitchell", "Quincy", "Roderick", "Colby", "Rolando", "Yuji", "Abel", "Anton", "Arthur", "Cesar", "Dalton", "Dennis", "Ernest", "Garrett", "Graham", "Henry", "Isaiah", "Jonah", "Jose", "Keenan", "Micah", "Omar", "Quinn", "Rodolfo", "Saul", "Sergio", "Skylar", "Stefan", "Zachery", "Alton", "Arabella", "Bonita", "Cal", "Cody", "French", "Kobe", "Paulo", "Shaye", "Austin", "Beckett", "Charlie", "Corky", "David", "Dwayne", "Elmer", "Jesse", "Jared", "Johan", "Jordan", "Kipp", "Lou", "Terry", "Tom", "Webster", "Billy", "Doyle", "Enzio", "Geoff", "Grant", "Kelsey", "Miguel", "Pierce", "Ray", "Santino", "Shel", "Adelbert", "Bence", "Emil", "Evan", "Mathis", "Maxim", "Neil", "Rico", "Robbie", "Theo", "Viktor", "Benedict", "Cornelius", "Hisato", "Leopold", "Neville", "Vito", "Chase", "Cole", "Hiroshi", "Jackson", "Jim", "Kekoa", "Makana", "Yuki", "Elwood", "Seth", "Alvin", "Arjun", "Arnold", "Cameron", "Carl", "Carlton", "Christopher", "Dave", "Dax", "Dominic", "Edmund", "Finn", "Fred", "Garret", "Grayson", "Jace", "Jaxson", "Jay", "Jirard", "Johnson", "Kayden", "Kite", "Louis", "Mac", "Marty", "Percy", "Raymond", "Ronnie", "Satch", "Tim", "Zach", "Conner", "Vince", "Bedro", "Boda", "Botan", "Daras", "Dury", "Herton", "Rewn", "Stum", "Tock", "Trilo", "Berki", "Cruik", "Dazon", "Desid", "Dillot", "Farfin", "Forgon", "Hebel", "Morfon", "Moril", "Shadd", "Vanhub", "Bardo", "Carben", "Degin", "Gorps", "Klept", "Lask", "Malex", "Mopar", "Niled", "Noxon", "Teslor", "Tetil"], ["Beth", "Carol", "Cybil", "Emma", "Fran", "Gwen", "Irene", "Jenn", "Joyce", "Kate", "Kelly", "Lois", "Lola", "Megan", "Quinn", "Reena", "Cara", "Alexa", "Brooke", "Caroline", "Elaine", "Hope", "Jennifer", "Jody", "Julie", "Lori", "Mary", "Michelle", "Shannon", "Wendy", "Alexia", "Alicia", "Athena", "Carolina", "Cristin", "Darcy", "Dianne", "Halle", "Jazmyn", "Katelynn", "Keira", "Marley", "Allyson", "Kathleen", "Naomi", "Alyssa", "Ariana", "Brandi", "Breanna", "Brenda", "Brenna", "Catherine", "Clarice", "Dana", "Deanna", "Destiny", "Jamie", "Jasmin", "Kassandra", "Laura", "Maria", "Mariah", "Maya", "Meagan", "Mikayla", "Monique", "Natasha", "Olivia", "Sandra", "Savannah", "Sydney", "Moira", "Piper", "Salma", "Allison", "Beverly", "Cathy", "Cheyenne", "Clara", "Dara", "Eileen", "Glinda", "Junko", "Lena", "Lucille", "Mariana", "Olwen", "Shanta", "Stella", "Angi", "Belle", "Chandra", "Cora", "Eve", "Jacqueline", "Jeanne", "Juliet", "Kathrine", "Layla", "Lucca", "Melina", "Miki", "Nina", "Sable", "Shelly", "Summer", "Trish", "Vicki", "Alanza", "Cordelia", "Hilde", "Imelda", "Michele", "Mireille", "Claudia", "Constance", "Harriet", "Honor", "Melba", "Portia", "Alexis", "Angela", "Karla", "Lindsey", "Tori", "Sheri", "Jada", "Kailee", "Amanda", "Annie", "Kindra", "Kyla", "Sofia", "Yvette", "Becky", "Flora", "Gloria", "Buna", "Ferda", "Lehan", "Liqui", "Lomen", "Neira", "Atilo", "Detta", "Gilly", "Gosney", "Levens", "Moden", "Rask", "Rateis", "Rosno", "Tynan", "Veron", "Zoel", "Cida", "Dibsin", "Dodin", "Ebson", "Equin", "Flostin", "Gabsen", "Halsion", "Hileon", "Quelor", "Rapeel", "Roze", "Tensin"]],
|
||||
[TrainerType.ARTIST]: [["Ismael", "William", "Horton", "Pierre", "Zach", "Gough", "Salvador", "Vincent", "Duncan"], ["Georgia"]],
|
||||
[TrainerType.BACKERS]: [["Alf & Fred", "Hawk & Dar", "Joe & Ross", "Les & Web", "Masa & Yas", "Stu & Art"], ["Ai & Ciel", "Ami & Eira", "Cam & Abby", "Fey & Sue", "Kat & Phae", "Kay & Ali", "Ava & Aya", "Cleo & Rio", "May & Mal"]],
|
||||
[TrainerType.BACKPACKER]: [["Alexander", "Carlos", "Herman", "Jerome", "Keane", "Kelsey", "Kiyo", "Michael", "Nate", "Peter", "Sam", "Stephen", "Talon", "Terrance", "Toru", "Waylon", "Boone", "Clifford", "Ivan", "Kendall", "Lowell", "Randall", "Reece", "Roland", "Shane", "Walt", "Farid", "Heike", "Joren", "Lane", "Roderick", "Darnell", "Deon", "Emory", "Graeme", "Grayson", "Aitor", "Alex", "Arturo", "Asier", "Jaime", "Jonathan", "Julio", "Kevin", "Kosuke", "Lander", "Markel", "Mateo", "Nil", "Pau", "Samuel"], ["Anna", "Corin", "Elaine", "Emi", "Jill", "Kumiko", "Liz", "Lois", "Lora", "Molly", "Patty", "Ruth", "Vicki", "Annie", "Blossom", "Clara", "Eileen", "Mae", "Myra", "Rachel", "Tami", "Ashley", "Mikiko", "Kiana", "Perdy", "Maria", "Yuho", "Peren", "Barbara", "Diane"]],
|
||||
[TrainerType.BAKER]: ["Chris", "Jenn", "Lilly"],
|
||||
[TrainerType.BEAUTY]: ["Cassie", "Julia", "Olivia", "Samantha", "Valerie", "Victoria", "Bridget", "Connie", "Jessica", "Johanna", "Melissa", "Sheila", "Shirley", "Tiffany", "Namiko", "Thalia", "Grace", "Lola", "Lori", "Maura", "Tamia", "Cyndy", "Devon", "Gabriella", "Harley", "Lindsay", "Nicola", "Callie", "Charlotte", "Kassandra", "December", "Fleming", "Nikola", "Aimee", "Anais", "Brigitte", "Cassandra", "Andrea", "Brittney", "Carolyn", "Krystal", "Alexis", "Alice", "Aina", "Anya", "Arianna", "Aubrey", "Beverly", "Camille", "Beauty", "Evette", "Hansol", "Haruka", "Jill", "Jo", "Lana", "Lois", "Lucy", "Mai", "Nickie", "Nicole", "Prita", "Rose", "Shelly", "Suzy", "Tessa", "Anita", "Alissa", "Rita", "Cudsy", "Eloff", "Miru", "Minot", "Nevah", "Niven", "Ogoin"],
|
||||
[TrainerType.BIKER]: ["Charles", "Dwayne", "Glenn", "Harris", "Joel", "Riley", "Zeke", "Alex", "Billy", "Ernest", "Gerald", "Hideo", "Isaac", "Jared", "Jaren", "Jaxon", "Jordy", "Lao", "Lukas", "Malik", "Nikolas", "Ricardo", "Ruben", "Virgil", "William", "Aiden", "Dale", "Dan", "Jacob", "Markey", "Reese", "Teddy", "Theron", "Jeremy", "Morgann", "Phillip", "Philip", "Stanley", "Dillon"],
|
||||
[TrainerType.BLACK_BELT]: [["Kenji", "Lao", "Lung", "Nob", "Wai", "Yoshi", "Atsushi", "Daisuke", "Hideki", "Hitoshi", "Kiyo", "Koichi", "Koji", "Yuji", "Cristian", "Rhett", "Takao", "Theodore", "Zander", "Aaron", "Hugh", "Mike", "Nicolas", "Shea", "Takashi", "Adam", "Carl", "Colby", "Darren", "David", "Davon", "Derek", "Eddie", "Gregory", "Griffin", "Jarrett", "Jeffery", "Kendal", "Kyle", "Luke", "Miles", "Nathaniel", "Philip", "Rafael", "Ray", "Ricky", "Sean", "Willie", "Ander", "Manford", "Benjamin", "Corey", "Edward", "Grant", "Jay", "Kendrew", "Kentaro", "Ryder", "Teppei", "Thomas", "Tyrone", "Andrey", "Donny", "Drago", "Gordon", "Grigor", "Jeriel", "Kenneth", "Martell", "Mathis", "Rich", "Rocky", "Rodrigo", "Wesley", "Zachery", "Alonzo", "Cadoc", "Gunnar", "Igor", "Killian", "Markus", "Ricardo", "Yanis", "Banting", "Clayton", "Duane", "Earl", "Greg", "Roy", "Terry", "Tracy", "Walter", "Alvaro", "Curtis", "Francis", "Ross", "Brice", "Cheng", "Dudley", "Eric", "Kano", "Masahiro", "Randy", "Ryuji", "Steve", "Tadashi", "Wong", "Yuen", "Brian", "Carter", "Reece", "Nick", "Yang"], ["Cora", "Cyndy", "Jill", "Laura", "Sadie", "Tessa", "Vivian", "Aisha", "Callie", "Danielle", "Helene", "Jocelyn", "Lilith", "Paula", "Reyna", "Helen", "Kelsey", "Tyler", "Amy", "Chandra", "Hillary", "Janie", "Lee", "Maggie", "Mikiko", "Miriam", "Sharon", "Susie", "Xiao", "Alize", "Azra", "Brenda", "Chalina", "Chan", "Glinda", "Maki", "Tia", "Tiffany", "Wendy", "Andrea", "Gabrielle", "Gerardine", "Hailey", "Hedvig", "Justine", "Kinsey", "Sigrid", "Veronique", "Tess"]],
|
||||
[TrainerType.BREEDER]: [["Isaac", "Myles", "Salvadore", "Albert", "Kahlil", "Eustace", "Galen", "Owen", "Addison", "Marcus", "Foster", "Cory", "Glenn", "Jay", "Wesley", "William", "Adrian", "Bradley", "Jaime"], ["Allison", "Alize", "Bethany", "Lily", "Lydia", "Gabrielle", "Jayden", "Pat", "Veronica", "Amber", "Jennifer", "Kaylee", "Adelaide", "Brooke", "Ethel", "April", "Irene", "Magnolia", "Amala", "Mercy", "Amanda", "Ikue", "Savannah", "Yuka", "Chloe", "Debra", "Denise", "Elena"]],
|
||||
[TrainerType.CLERK]: [["Chaz", "Clemens", "Doug", "Fredric", "Ivan", "Isaac", "Nelson", "Wade", "Warren", "Augustin", "Gilligan", "Cody", "Jeremy", "Shane", "Dugal", "Royce", "Ronald"], ["Alberta", "Ingrid", "Katie", "Piper", "Trisha", "Wren", "Britney", "Lana", "Jessica", "Kristen", "Michelle", "Gabrielle"]],
|
||||
[TrainerType.CYCLIST]: [["Axel", "James", "John", "Ryan", "Hector", "Jeremiah"], ["Kayla", "Megan", "Nicole", "Rachel", "Krissa", "Adelaide"]],
|
||||
[TrainerType.DANCER]: ["Brian", "Davey", "Dirk", "Edmond", "Mickey", "Raymond", "Cara", "Julia", "Maika", "Mireille", "Ronda", "Zoe"],
|
||||
[TrainerType.DEPOT_AGENT]: ["Josh", "Hank", "Vincent"],
|
||||
[TrainerType.DOCTOR]: [["Hank", "Jerry", "Jules", "Logan", "Wayne", "Braid", "Derek", "Heath", "Julius", "Kit", "Graham"], ["Kirsten", "Sachiko", "Shery", "Carol", "Dixie", "Mariah"]],
|
||||
[TrainerType.FIREBREATHER]: ["Bill", "Burt", "Cliff", "Dick", "Lyle", "Ned", "Otis", "Ray", "Richard", "Walt"],
|
||||
[TrainerType.FISHERMAN]: ["Andre", "Arnold", "Barney", "Chris", "Edgar", "Henry", "Jonah", "Justin", "Kyle", "Martin", "Marvin", "Ralph", "Raymond", "Scott", "Stephen", "Wilton", "Tully", "Andrew", "Barny", "Carter", "Claude", "Dale", "Elliot", "Eugene", "Ivan", "Ned", "Nolan", "Roger", "Ronald", "Wade", "Wayne", "Darian", "Kai", "Chip", "Hank", "Kaden", "Tommy", "Tylor", "Alec", "Brett", "Cameron", "Cody", "Cole", "Cory", "Erick", "George", "Joseph", "Juan", "Kenneth", "Luc", "Miguel", "Travis", "Walter", "Zachary", "Josh", "Gideon", "Kyler", "Liam", "Murphy", "Bruce", "Damon", "Devon", "Hubert", "Jones", "Lydon", "Mick", "Pete", "Sean", "Sid", "Vince", "Bucky", "Dean", "Eustace", "Kenzo", "Leroy", "Mack", "Ryder", "Ewan", "Finn", "Murray", "Seward", "Shad", "Wharton", "Finley", "Fisher", "Fisk", "River", "Sheaffer", "Timin", "Carl", "Ernest", "Hal", "Herbert", "Hisato", "Mike", "Vernon", "Harriet", "Marina", "Chase"],
|
||||
[TrainerType.GUITARIST]: ["Anna", "Beverly", "January", "Tina", "Alicia", "Claudia", "Julia", "Lidia", "Mireia", "Noelia", "Sara", "Sheila", "Tatiana"],
|
||||
[TrainerType.HARLEQUIN]: ["Charley", "Ian", "Jack", "Kerry", "Louis", "Pat", "Paul", "Rick", "Anders", "Clarence", "Gary"],
|
||||
[TrainerType.HIKER]: ["Anthony", "Bailey", "Benjamin", "Daniel", "Erik", "Jim", "Kenny", "Leonard", "Michael", "Parry", "Phillip", "Russell", "Sidney", "Tim", "Timothy", "Alan", "Brice", "Clark", "Eric", "Lenny", "Lucas", "Mike", "Trent", "Devan", "Eli", "Marc", "Sawyer", "Allen", "Daryl", "Dudley", "Earl", "Franklin", "Jeremy", "Marcos", "Nob", "Oliver", "Wayne", "Alexander", "Damon", "Jonathan", "Justin", "Kevin", "Lorenzo", "Louis", "Maurice", "Nicholas", "Reginald", "Robert", "Theodore", "Bruce", "Clarke", "Devin", "Dwight", "Edwin", "Eoin", "Noland", "Russel", "Andy", "Bret", "Darrell", "Gene", "Hardy", "Hugh", "Jebediah", "Jeremiah", "Kit", "Neil", "Terrell", "Don", "Doug", "Hunter", "Jared", "Jerome", "Keith", "Manuel", "Markus", "Otto", "Shelby", "Stephen", "Teppei", "Tobias", "Wade", "Zaiem", "Aaron", "Alain", "Bergin", "Bernard", "Brent", "Corwin", "Craig", "Delmon", "Dunstan", "Orestes", "Ross", "Davian", "Calhoun", "David", "Gabriel", "Ryan", "Thomas", "Travis", "Zachary", "Anuhea", "Barnaby", "Claus", "Collin", "Colson", "Dexter", "Dillan", "Eugine", "Farkas", "Hisato", "Julius", "Kenji", "Irwin", "Lionel", "Paul", "Richter", "Valentino", "Donald", "Douglas", "Kevyn", "Chester"], //["Angela","Carla","Celia","Daniela","Estela","Fatima","Helena","Leire","Lucia","Luna","Manuela","Mar","Marina","Miyu","Nancy","Nerea","Paula","Rocio","Yanira"]
|
||||
[TrainerType.HOOLIGANS]: ["Jim & Cas", "Rob & Sal"],
|
||||
[TrainerType.HOOPSTER]: ["Bobby", "John", "Lamarcus", "Derrick", "Nicolas"],
|
||||
[TrainerType.INFIELDER]: ["Alex", "Connor", "Todd"],
|
||||
[TrainerType.JANITOR]: ["Caleb", "Geoff", "Brady", "Felix", "Orville", "Melvin", "Shawn"],
|
||||
[TrainerType.LINEBACKER]: ["Bob", "Dan", "Jonah"],
|
||||
[TrainerType.MAID]: ["Belinda", "Sophie", "Emily", "Elena", "Clare", "Alica", "Tanya", "Tammy"],
|
||||
[TrainerType.MUSICIAN]: ["Boris", "Preston", "Charles", "Clyde", "Vincent", "Dalton", "Kirk", "Shawn", "Fabian", "Fernando", "Joseph", "Marcos", "Arturo", "Jerry", "Lonnie", "Tony"],
|
||||
[TrainerType.NURSERY_AIDE]: ["Autumn", "Briana", "Leah", "Miho", "Ethel", "Hollie", "Ilse", "June", "Kimya", "Rosalyn"],
|
||||
[TrainerType.OFFICER]: ["Dirk", "Keith", "Alex", "Bobby", "Caleb", "Danny", "Dylan", "Thomas", "Daniel", "Jeff", "Braven", "Dell", "Neagle", "Haruki", "Mitchell", "Raymond"],
|
||||
[TrainerType.PARASOL_LADY]: ["Angelica", "Clarissa", "Madeline", "Akari", "Annabell", "Kayley", "Rachel", "Alexa", "Sabrina", "April", "Gwyneth", "Laura", "Lumi", "Mariah", "Melita", "Nicole", "Tihana", "Ingrid", "Tyra"],
|
||||
[TrainerType.PILOT]: ["Chase", "Leonard", "Ted", "Elron", "Ewing", "Flynn", "Winslow"],
|
||||
[TrainerType.POKEFAN]: [["Alex", "Allan", "Brandon", "Carter", "Colin", "Derek", "Jeremy", "Joshua", "Rex", "Robert", "Trevor", "William", "Colton", "Miguel", "Francisco", "Kaleb", "Leonard", "Boone", "Elliot", "Jude", "Norbert", "Corey", "Gabe", "Baxter"], ["Beverly", "Georgia", "Jaime", "Ruth", "Isabel", "Marissa", "Vanessa", "Annika", "Bethany", "Kimberly", "Meredith", "Rebekah", "Eleanor", "Darcy", "Lydia", "Sachiko", "Abigail", "Agnes", "Lydie", "Roisin", "Tara", "Carmen", "Janet"]],
|
||||
[TrainerType.PRESCHOOLER]: [["Billy", "Doyle", "Evan", "Homer", "Tully", "Albert", "Buster", "Greg", "Ike", "Jojo", "Tyrone", "Adrian", "Oliver", "Hayden", "Hunter", "Kaleb", "Liam", "Dylan"], ["Juliet", "Mia", "Sarah", "Wendy", "Winter", "Chrissy", "Eva", "Lin", "Samantha", "Ella", "Lily", "Natalie", "Ailey", "Hannah", "Malia", "Kindra", "Nancy"]],
|
||||
[TrainerType.PSYCHIC]: [["Fidel", "Franklin", "Gilbert", "Greg", "Herman", "Jared", "Mark", "Nathan", "Norman", "Phil", "Richard", "Rodney", "Cameron", "Edward", "Fritz", "Joshua", "Preston", "Virgil", "William", "Alvaro", "Blake", "Cedric", "Keenan", "Nicholas", "Dario", "Johan", "Lorenzo", "Tyron", "Bryce", "Corbin", "Deandre", "Elijah", "Kody", "Landon", "Maxwell", "Mitchell", "Sterling", "Eli", "Nelson", "Vernon", "Gaven", "Gerard", "Low", "Micki", "Perry", "Rudolf", "Tommy", "Al", "Nandor", "Tully", "Arthur", "Emanuel", "Franz", "Harry", "Paschal", "Robert", "Sayid", "Angelo", "Anton", "Arin", "Avery", "Danny", "Frasier", "Harrison", "Jaime", "Ross", "Rui", "Vlad", "Mason"], ["Alexis", "Hannah", "Jacki", "Jaclyn", "Kayla", "Maura", "Samantha", "Alix", "Brandi", "Edie", "Macey", "Mariella", "Marlene", "Laura", "Rodette", "Abigail", "Brittney", "Chelsey", "Daisy", "Desiree", "Kendra", "Lindsey", "Rachael", "Valencia", "Belle", "Cybil", "Doreen", "Dua", "Future", "Lin", "Madhu", "Alia", "Ena", "Joyce", "Lynette", "Olesia", "Sarah"]],
|
||||
[TrainerType.RANGER]: [["Carlos", "Jackson", "Sebastian", "Gav", "Lorenzo", "Logan", "Nicolas", "Trenton", "Deshawn", "Dwayne", "Jeffery", "Kyler", "Taylor", "Alain", "Claude", "Crofton", "Forrest", "Harry", "Jaden", "Keith", "Lewis", "Miguel", "Pedro", "Ralph", "Richard", "Bret", "Daryl", "Eddie", "Johan", "Leaf", "Louis", "Maxwell", "Parker", "Rick", "Steve", "Bjorn", "Chaise", "Dean", "Lee", "Maurice", "Nash", "Ralf", "Reed", "Shinobu", "Silas"], ["Catherine", "Jenna", "Sophia", "Merdith", "Nora", "Beth", "Chelsea", "Katelyn", "Madeline", "Allison", "Ashlee", "Felicia", "Krista", "Annie", "Audra", "Brenda", "Chloris", "Eliza", "Heidi", "Irene", "Mary", "Mylene", "Shanti", "Shelly", "Thalia", "Anja", "Briana", "Dianna", "Elaine", "Elle", "Hillary", "Katie", "Lena", "Lois", "Malory", "Melita", "Mikiko", "Naoko", "Serenity", "Ambre", "Brooke", "Clementine", "Melina", "Petra", "Twiggy"]],
|
||||
[TrainerType.RICH]: [["Alfred", "Edward", "Gregory", "Preston", "Thomas", "Tucker", "Walter", "Clifford", "Everett", "Micah", "Nate", "Pierre", "Terrance", "Arthur", "Brooks", "Emanuel", "Lamar", "Jeremy", "Leonardo", "Milton", "Frederic", "Renaud", "Robert", "Yan", "Daniel", "Sheldon", "Stonewall", "Gerald", "Ronald", "Smith", "Stanley", "Reginald", "Orson", "Wilco", "Caden", "Glenn"], ["Rebecca", "Reina", "Cassandra", "Emilia", "Grace", "Marian", "Elizabeth", "Kathleen", "Sayuri", "Caroline", "Judy"]],
|
||||
[TrainerType.RICH_KID]: [["Garret", "Winston", "Dawson", "Enrique", "Jason", "Roman", "Trey", "Liam", "Anthony", "Brad", "Cody", "Manuel", "Martin", "Pierce", "Rolan", "Keenan", "Filbert", "Antoin", "Cyus", "Diek", "Dugo", "Flitz", "Jurek", "Lond", "Perd", "Quint", "Basto", "Benit", "Brot", "Denc", "Guyit", "Marcon", "Perc", "Puros", "Roex", "Sainz", "Symin", "Tark", "Venak"], ["Anette", "Brianna", "Cindy", "Colleen", "Daphne", "Elizabeth", "Naomi", "Sarah", "Charlotte", "Gillian", "Jacki", "Lady", "Melissa", "Celeste", "Colette", "Elizandra", "Isabel", "Lynette", "Magnolia", "Sophie", "Lina", "Dulcie", "Auro", "Brin", "Caril", "Eloos", "Gwin", "Illa", "Kowly", "Rima", "Ristin", "Vesey", "Brena", "Deasy", "Denslon", "Kylet", "Nemi", "Rene", "Sanol", "Stouner", "Sturk", "Talmen", "Zoila"]],
|
||||
[TrainerType.ROUGHNECK]: ["Camron", "Corey", "Gabriel", "Isaiah", "Jamal", "Koji", "Luke", "Paxton", "Raul", "Zeek", "Kirby", "Chance", "Dave", "Fletcher", "Johnny", "Reese", "Joey", "Ricky", "Silvester", "Martin"],
|
||||
[TrainerType.SAILOR]: ["Alberto", "Bost", "Brennan", "Brenden", "Claude", "Cory", "Damian", "Dirk", "Duncan", "Dwayne", "Dylan", "Eddie", "Edmond", "Elijah", "Ernest", "Eugene", "Garrett", "Golos", "Gratin", "Grestly", "Harry", "Hols", "Hudson", "Huey", "Jebol", "Jeff", "Leonald", "Luther", "Kelvin", "Kenneth", "Kent", "Knook", "Marc", "Mifis", "Monar", "Morkor", "Ordes", "Oxlin", "Parker", "Paul", "Philip", "Roberto", "Samson", "Skyler", "Stanly", "Tebu", "Terrell", "Trevor", "Yasu", "Zachariah"],
|
||||
[TrainerType.SCIENTIST]: [["Jed", "Marc", "Mitch", "Rich", "Ross", "Beau", "Braydon", "Connor", "Ed", "Ivan", "Jerry", "Jose", "Joshua", "Parker", "Rodney", "Taylor", "Ted", "Travis", "Zackery", "Darrius", "Emilio", "Fredrick", "Shaun", "Stefano", "Travon", "Daniel", "Garett", "Gregg", "Linden", "Lowell", "Trenton", "Dudley", "Luke", "Markus", "Nathan", "Orville", "Randall", "Ron", "Ronald", "Simon", "Steve", "William", "Franklin", "Clarke", "Jacques", "Terrance", "Ernst", "Justus", "Ikaika", "Jayson", "Kyle", "Reid", "Tyrone", "Adam", "Albert", "Alphonse", "Cory", "Donnie", "Elton", "Francis", "Gordon", "Herbert", "Humphrey", "Jordan", "Julian", "Keaton", "Levi", "Melvin", "Murray", "West", "Craig", "Coren", "Dubik", "Kotan", "Lethco", "Mante", "Mort", "Myron", "Odlow", "Ribek", "Roeck", "Vogi", "Vonder", "Zogo", "Doimo", "Doton", "Durel", "Hildon", "Kukla", "Messa", "Nanot", "Platen", "Raburn", "Reman", "Acrod", "Coffy", "Elrok", "Foss", "Hardig", "Hombol", "Hospel", "Kaller", "Klots", "Krilok", "Limar", "Loket", "Mesak", "Morbit", "Newin", "Orill", "Tabor", "Tekot"], ["Blythe", "Chan", "Kathrine", "Marie", "Maria", "Naoko", "Samantha", "Satomi", "Shannon", "Athena", "Caroline", "Lumi", "Lumina", "Marissa", "Sonia"]],
|
||||
[TrainerType.SMASHER]: ["Aspen", "Elena", "Mari", "Amy", "Lizzy"],
|
||||
[TrainerType.SNOW_WORKER]: [["Braden", "Brendon", "Colin", "Conrad", "Dillan", "Gary", "Gerardo", "Holden", "Jackson", "Mason", "Quentin", "Willy", "Noel", "Arnold", "Brady", "Brand", "Cairn", "Cliff", "Don", "Eddie", "Felix", "Filipe", "Glenn", "Gus", "Heath", "Matthew", "Patton", "Rich", "Rob", "Ryan", "Scott", "Shelby", "Sterling", "Tyler", "Victor", "Zack", "Friedrich", "Herman", "Isaac", "Leo", "Maynard", "Mitchell", "Morgann", "Nathan", "Niel", "Pasqual", "Paul", "Tavarius", "Tibor", "Dimitri", "Narek", "Yusif", "Frank", "Jeff", "Vaclav", "Ovid", "Francis", "Keith", "Russel", "Sangon", "Toway", "Bomber", "Chean", "Demit", "Hubor", "Kebile", "Laber", "Ordo", "Retay", "Ronix", "Wagel", "Dobit", "Kaster", "Lobel", "Releo", "Saken", "Rustix"], ["Georgia", "Sandra", "Yvonne"]],
|
||||
[TrainerType.STRIKER]: ["Marco", "Roberto", "Tony"],
|
||||
[TrainerType.SCHOOL_KID]: [["Alan", "Billy", "Chad", "Danny", "Dudley", "Jack", "Joe", "Johnny", "Kipp", "Nate", "Ricky", "Tommy", "Jerry", "Paul", "Ted", "Chance", "Esteban", "Forrest", "Harrison", "Connor", "Sherman", "Torin", "Travis", "Al", "Carter", "Edgar", "Jem", "Sammy", "Shane", "Shayne", "Alvin", "Keston", "Neil", "Seymour", "William", "Carson", "Clark", "Nolan"], ["Georgia", "Karen", "Meiko", "Christine", "Mackenzie", "Tiera", "Ann", "Gina", "Lydia", "Marsha", "Millie", "Sally", "Serena", "Silvia", "Alberta", "Cassie", "Mara", "Rita", "Georgie", "Meena", "Nitzel"]],
|
||||
[TrainerType.SWIMMER]: [["Berke", "Cameron", "Charlie", "George", "Harold", "Jerome", "Kirk", "Mathew", "Parker", "Randall", "Seth", "Simon", "Tucker", "Austin", "Barry", "Chad", "Cody", "Darrin", "David", "Dean", "Douglas", "Franklin", "Gilbert", "Herman", "Jack", "Luis", "Matthew", "Reed", "Richard", "Rodney", "Roland", "Spencer", "Stan", "Tony", "Clarence", "Declan", "Dominik", "Harrison", "Kevin", "Leonardo", "Nolen", "Pete", "Santiago", "Axle", "Braden", "Finn", "Garrett", "Mymo", "Reece", "Samir", "Toby", "Adrian", "Colton", "Dillon", "Erik", "Evan", "Francisco", "Glenn", "Kurt", "Oscar", "Ricardo", "Sam", "Sheltin", "Troy", "Vincent", "Wade", "Wesley", "Duane", "Elmo", "Esteban", "Frankie", "Ronald", "Tyson", "Bart", "Matt", "Tim", "Wright", "Jeffery", "Kyle", "Alessandro", "Estaban", "Kieran", "Ramses", "Casey", "Dakota", "Jared", "Kalani", "Keoni", "Lawrence", "Logan", "Robert", "Roddy", "Yasu", "Derek", "Jacob", "Bruce", "Clayton"], ["Briana", "Dawn", "Denise", "Diana", "Elaine", "Kara", "Kaylee", "Lori", "Nicole", "Nikki", "Paula", "Susie", "Wendy", "Alice", "Beth", "Beverly", "Brenda", "Dana", "Debra", "Grace", "Jenny", "Katie", "Laurel", "Linda", "Missy", "Sharon", "Tanya", "Tara", "Tisha", "Carlee", "Imani", "Isabelle", "Kyla", "Sienna", "Abigail", "Amara", "Anya", "Connie", "Maria", "Melissa", "Nora", "Shirley", "Shania", "Tiffany", "Aubree", "Cassandra", "Claire", "Crystal", "Erica", "Gabrielle", "Haley", "Jessica", "Joanna", "Lydia", "Mallory", "Mary", "Miranda", "Paige", "Sophia", "Vanessa", "Chelan", "Debbie", "Joy", "Kendra", "Leona", "Mina", "Caroline", "Joyce", "Larissa", "Rebecca", "Tyra", "Dara", "Desiree", "Kaoru", "Ruth", "Coral", "Genevieve", "Isla", "Marissa", "Romy", "Sheryl", "Alexandria", "Alicia", "Chelsea", "Jade", "Kelsie", "Laura", "Portia", "Shelby", "Sara", "Tiare", "Kyra", "Natasha", "Layla", "Scarlett", "Cora"]],
|
||||
[TrainerType.TWINS]: ["Amy & May", "Jo & Zoe", "Meg & Peg", "Ann & Anne", "Lea & Pia", "Amy & Liv", "Gina & Mia", "Miu & Yuki", "Tori & Tia", "Eli & Anne", "Jen & Kira", "Joy & Meg", "Kiri & Jan", "Miu & Mia", "Emma & Lil", "Liv & Liz", "Teri & Tia", "Amy & Mimi", "Clea & Gil", "Day & Dani", "Kay & Tia", "Tori & Til", "Saya & Aya", "Emy & Lin", "Kumi & Amy", "Mayo & May", "Ally & Amy", "Lia & Lily", "Rae & Ula", "Sola & Ana", "Tara & Val", "Faith & Joy", "Nana & Nina"],
|
||||
[TrainerType.VETERAN]: [["Armando", "Brenden", "Brian", "Clayton", "Edgar", "Emanuel", "Grant", "Harlan", "Terrell", "Arlen", "Chester", "Hugo", "Martell", "Ray", "Shaun", "Abraham", "Carter", "Claude", "Jerry", "Lucius", "Murphy", "Rayne", "Ron", "Sinan", "Sterling", "Vincent", "Zach", "Gerard", "Gilles", "Louis", "Timeo", "Akira", "Don", "Eric", "Harry", "Leon", "Roger", "Angus", "Aristo", "Brone", "Johnny"], ["Julia", "Karla", "Kim", "Sayuri", "Tiffany", "Cathy", "Cecile", "Chloris", "Denae", "Gina", "Maya", "Oriana", "Portia", "Rhona", "Rosaline", "Catrina", "Inga", "Trisha", "Heather", "Lynn", "Sheri", "Alonsa", "Ella", "Leticia", "Kiara"]],
|
||||
[TrainerType.WAITER]: [["Bert", "Clint", "Maxwell", "Lou"], ["Kati", "Aurora", "Bonita", "Flo", "Tia", "Jan", "Olwen", "Paget", "Paula", "Talia"]],
|
||||
[TrainerType.WORKER]: [["Braden", "Brendon", "Colin", "Conrad", "Dillan", "Gary", "Gerardo", "Holden", "Jackson", "Mason", "Quentin", "Willy", "Noel", "Arnold", "Brady", "Brand", "Cairn", "Cliff", "Don", "Eddie", "Felix", "Filipe", "Glenn", "Gus", "Heath", "Matthew", "Patton", "Rich", "Rob", "Ryan", "Scott", "Shelby", "Sterling", "Tyler", "Victor", "Zack", "Friedrich", "Herman", "Isaac", "Leo", "Maynard", "Mitchell", "Morgann", "Nathan", "Niel", "Pasqual", "Paul", "Tavarius", "Tibor", "Dimitri", "Narek", "Yusif", "Frank", "Jeff", "Vaclav", "Ovid", "Francis", "Keith", "Russel", "Sangon", "Toway", "Bomber", "Chean", "Demit", "Hubor", "Kebile", "Laber", "Ordo", "Retay", "Ronix", "Wagel", "Dobit", "Kaster", "Lobel", "Releo", "Saken", "Rustix"], ["Georgia", "Sandra", "Yvonne"]],
|
||||
[TrainerType.YOUNGSTER]: [["Albert", "Gordon", "Ian", "Jason", "Jimmy", "Mikey", "Owen", "Samuel", "Warren", "Allen", "Ben", "Billy", "Calvin", "Dillion", "Eddie", "Joey", "Josh", "Neal", "Timmy", "Tommy", "Breyden", "Deandre", "Demetrius", "Dillon", "Jaylen", "Johnson", "Shigenobu", "Chad", "Cole", "Cordell", "Dan", "Dave", "Destin", "Nash", "Tyler", "Yasu", "Austin", "Dallas", "Darius", "Donny", "Jonathon", "Logan", "Michael", "Oliver", "Sebastian", "Tristan", "Wayne", "Norman", "Roland", "Regis", "Abe", "Astor", "Keita", "Kenneth", "Kevin", "Kyle", "Lester", "Masao", "Nicholas", "Parker", "Wes", "Zachary", "Cody", "Henley", "Jaye", "Karl", "Kenny", "Masahiro", "Pedro", "Petey", "Sinclair", "Terrell", "Waylon", "Aidan", "Anthony", "David", "Jacob", "Jayden", "Cutler", "Ham", "Caleb", "Kai", "Honus", "Kenway", "Bret", "Chris", "Cid", "Dennis", "Easton", "Ken", "Robby", "Ronny", "Shawn", "Benjamin", "Jake", "Travis", "Adan", "Aday", "Beltran", "Elian", "Hernan", "Julen", "Luka", "Roi", "Bernie", "Dustin", "Jonathan", "Wyatt"], ["Alice", "Bridget", "Carrie", "Connie", "Dana", "Ellen", "Krise", "Laura", "Linda", "Michelle", "Shannon", "Andrea", "Crissy", "Janice", "Robin", "Sally", "Tiana", "Haley", "Ali", "Ann", "Dalia", "Dawn", "Iris", "Joana", "Julia", "Kay", "Lisa", "Megan", "Mikaela", "Miriam", "Paige", "Reli", "Blythe", "Briana", "Caroline", "Cassidy", "Kaitlin", "Madeline", "Molly", "Natalie", "Samantha", "Sarah", "Cathy", "Dye", "Eri", "Eva", "Fey", "Kara", "Lurleen", "Maki", "Mali", "Maya", "Miki", "Sibyl", "Daya", "Diana", "Flo", "Helia", "Henrietta", "Isabel", "Mai", "Persephone", "Serena", "Anna", "Charlotte", "Elin", "Elsa", "Lise", "Sara", "Suzette", "Audrey", "Emmy", "Isabella", "Madison", "Rika", "Rylee", "Salla", "Ellie", "Alexandra", "Amy", "Lass", "Brittany", "Chel", "Cindy", "Dianne", "Emily", "Emma", "Evelyn", "Hana", "Harleen", "Hazel", "Jocelyn", "Katrina", "Kimberly", "Lina", "Marge", "Mila", "Mizuki", "Rena", "Sal", "Satoko", "Summer", "Tomoe", "Vicky", "Yue", "Yumi", "Lauren", "Rei", "Riley", "Lois", "Nancy", "Tammy", "Terry"]],
|
||||
[TrainerType.HEX_MANIAC]: ["Kindra", "Patricia", "Tammy", "Tasha", "Valerie", "Alaina", "Kathleen", "Leah", "Makie", "Sylvia", "Anina", "Arachna", "Carrie", "Desdemona", "Josette", "Luna", "Melanie", "Osanna", "Raziah"],
|
||||
[TrainerType.ACE_TRAINER]: [[ "Aaron", "Allen", "Blake", "Brian", "Gaven", "Jake", "Kevin", "Mike", "Nick", "Paul", "Ryan", "Sean", "Darin", "Albert", "Berke", "Clyde", "Edgar", "George", "Leroy", "Owen", "Parker", "Randall", "Ruben", "Samuel", "Vincent", "Warren", "Wilton", "Zane", "Alfred", "Braxton", "Felix", "Gerald", "Jonathan", "Leonel", "Marcel", "Mitchell", "Quincy", "Roderick", "Colby", "Rolando", "Yuji", "Abel", "Anton", "Arthur", "Cesar", "Dalton", "Dennis", "Ernest", "Garrett", "Graham", "Henry", "Isaiah", "Jonah", "Jose", "Keenan", "Micah", "Omar", "Quinn", "Rodolfo", "Saul", "Sergio", "Skylar", "Stefan", "Zachery", "Alton", "Arabella", "Bonita", "Cal", "Cody", "French", "Kobe", "Paulo", "Shaye", "Austin", "Beckett", "Charlie", "Corky", "David", "Dwayne", "Elmer", "Jesse", "Jared", "Johan", "Jordan", "Kipp", "Lou", "Terry", "Tom", "Webster", "Billy", "Doyle", "Enzio", "Geoff", "Grant", "Kelsey", "Miguel", "Pierce", "Ray", "Santino", "Shel", "Adelbert", "Bence", "Emil", "Evan", "Mathis", "Maxim", "Neil", "Rico", "Robbie", "Theo", "Viktor", "Benedict", "Cornelius", "Hisato", "Leopold", "Neville", "Vito", "Chase", "Cole", "Hiroshi", "Jackson", "Jim", "Kekoa", "Makana", "Yuki", "Elwood", "Seth", "Alvin", "Arjun", "Arnold", "Cameron", "Carl", "Carlton", "Christopher", "Dave", "Dax", "Dominic", "Edmund", "Finn", "Fred", "Garret", "Grayson", "Jace", "Jaxson", "Jay", "Jirard", "Johnson", "Kayden", "Kite", "Louis", "Mac", "Marty", "Percy", "Raymond", "Ronnie", "Satch", "Tim", "Zach", "Conner", "Vince", "Bedro", "Boda", "Botan", "Daras", "Dury", "Herton", "Rewn", "Stum", "Tock", "Trilo", "Berki", "Cruik", "Dazon", "Desid", "Dillot", "Farfin", "Forgon", "Hebel", "Morfon", "Moril", "Shadd", "Vanhub", "Bardo", "Carben", "Degin", "Gorps", "Klept", "Lask", "Malex", "Mopar", "Niled", "Noxon", "Teslor", "Tetil" ], [ "Beth", "Carol", "Cybil", "Emma", "Fran", "Gwen", "Irene", "Jenn", "Joyce", "Kate", "Kelly", "Lois", "Lola", "Megan", "Quinn", "Reena", "Cara", "Alexa", "Brooke", "Caroline", "Elaine", "Hope", "Jennifer", "Jody", "Julie", "Lori", "Mary", "Michelle", "Shannon", "Wendy", "Alexia", "Alicia", "Athena", "Carolina", "Cristin", "Darcy", "Dianne", "Halle", "Jazmyn", "Katelynn", "Keira", "Marley", "Allyson", "Kathleen", "Naomi", "Alyssa", "Ariana", "Brandi", "Breanna", "Brenda", "Brenna", "Catherine", "Clarice", "Dana", "Deanna", "Destiny", "Jamie", "Jasmin", "Kassandra", "Laura", "Maria", "Mariah", "Maya", "Meagan", "Mikayla", "Monique", "Natasha", "Olivia", "Sandra", "Savannah", "Sydney", "Moira", "Piper", "Salma", "Allison", "Beverly", "Cathy", "Cheyenne", "Clara", "Dara", "Eileen", "Glinda", "Junko", "Lena", "Lucille", "Mariana", "Olwen", "Shanta", "Stella", "Angi", "Belle", "Chandra", "Cora", "Eve", "Jacqueline", "Jeanne", "Juliet", "Kathrine", "Layla", "Lucca", "Melina", "Miki", "Nina", "Sable", "Shelly", "Summer", "Trish", "Vicki", "Alanza", "Cordelia", "Hilde", "Imelda", "Michele", "Mireille", "Claudia", "Constance", "Harriet", "Honor", "Melba", "Portia", "Alexis", "Angela", "Karla", "Lindsey", "Tori", "Sheri", "Jada", "Kailee", "Amanda", "Annie", "Kindra", "Kyla", "Sofia", "Yvette", "Becky", "Flora", "Gloria", "Buna", "Ferda", "Lehan", "Liqui", "Lomen", "Neira", "Atilo", "Detta", "Gilly", "Gosney", "Levens", "Moden", "Rask", "Rateis", "Rosno", "Tynan", "Veron", "Zoel", "Cida", "Dibsin", "Dodin", "Ebson", "Equin", "Flostin", "Gabsen", "Halsion", "Hileon", "Quelor", "Rapeel", "Roze", "Tensin" ]],
|
||||
[TrainerType.ARTIST]: [[ "Ismael", "William", "Horton", "Pierre", "Zach", "Gough", "Salvador", "Vincent", "Duncan" ], [ "Georgia" ]],
|
||||
[TrainerType.BACKERS]: [[ "Alf & Fred", "Hawk & Dar", "Joe & Ross", "Les & Web", "Masa & Yas", "Stu & Art" ], [ "Ai & Ciel", "Ami & Eira", "Cam & Abby", "Fey & Sue", "Kat & Phae", "Kay & Ali", "Ava & Aya", "Cleo & Rio", "May & Mal" ]],
|
||||
[TrainerType.BACKPACKER]: [[ "Alexander", "Carlos", "Herman", "Jerome", "Keane", "Kelsey", "Kiyo", "Michael", "Nate", "Peter", "Sam", "Stephen", "Talon", "Terrance", "Toru", "Waylon", "Boone", "Clifford", "Ivan", "Kendall", "Lowell", "Randall", "Reece", "Roland", "Shane", "Walt", "Farid", "Heike", "Joren", "Lane", "Roderick", "Darnell", "Deon", "Emory", "Graeme", "Grayson", "Aitor", "Alex", "Arturo", "Asier", "Jaime", "Jonathan", "Julio", "Kevin", "Kosuke", "Lander", "Markel", "Mateo", "Nil", "Pau", "Samuel" ], [ "Anna", "Corin", "Elaine", "Emi", "Jill", "Kumiko", "Liz", "Lois", "Lora", "Molly", "Patty", "Ruth", "Vicki", "Annie", "Blossom", "Clara", "Eileen", "Mae", "Myra", "Rachel", "Tami", "Ashley", "Mikiko", "Kiana", "Perdy", "Maria", "Yuho", "Peren", "Barbara", "Diane" ]],
|
||||
[TrainerType.BAKER]: [ "Chris", "Jenn", "Lilly" ],
|
||||
[TrainerType.BEAUTY]: [ "Cassie", "Julia", "Olivia", "Samantha", "Valerie", "Victoria", "Bridget", "Connie", "Jessica", "Johanna", "Melissa", "Sheila", "Shirley", "Tiffany", "Namiko", "Thalia", "Grace", "Lola", "Lori", "Maura", "Tamia", "Cyndy", "Devon", "Gabriella", "Harley", "Lindsay", "Nicola", "Callie", "Charlotte", "Kassandra", "December", "Fleming", "Nikola", "Aimee", "Anais", "Brigitte", "Cassandra", "Andrea", "Brittney", "Carolyn", "Krystal", "Alexis", "Alice", "Aina", "Anya", "Arianna", "Aubrey", "Beverly", "Camille", "Beauty", "Evette", "Hansol", "Haruka", "Jill", "Jo", "Lana", "Lois", "Lucy", "Mai", "Nickie", "Nicole", "Prita", "Rose", "Shelly", "Suzy", "Tessa", "Anita", "Alissa", "Rita", "Cudsy", "Eloff", "Miru", "Minot", "Nevah", "Niven", "Ogoin" ],
|
||||
[TrainerType.BIKER]: [ "Charles", "Dwayne", "Glenn", "Harris", "Joel", "Riley", "Zeke", "Alex", "Billy", "Ernest", "Gerald", "Hideo", "Isaac", "Jared", "Jaren", "Jaxon", "Jordy", "Lao", "Lukas", "Malik", "Nikolas", "Ricardo", "Ruben", "Virgil", "William", "Aiden", "Dale", "Dan", "Jacob", "Markey", "Reese", "Teddy", "Theron", "Jeremy", "Morgann", "Phillip", "Philip", "Stanley", "Dillon" ],
|
||||
[TrainerType.BLACK_BELT]: [[ "Kenji", "Lao", "Lung", "Nob", "Wai", "Yoshi", "Atsushi", "Daisuke", "Hideki", "Hitoshi", "Kiyo", "Koichi", "Koji", "Yuji", "Cristian", "Rhett", "Takao", "Theodore", "Zander", "Aaron", "Hugh", "Mike", "Nicolas", "Shea", "Takashi", "Adam", "Carl", "Colby", "Darren", "David", "Davon", "Derek", "Eddie", "Gregory", "Griffin", "Jarrett", "Jeffery", "Kendal", "Kyle", "Luke", "Miles", "Nathaniel", "Philip", "Rafael", "Ray", "Ricky", "Sean", "Willie", "Ander", "Manford", "Benjamin", "Corey", "Edward", "Grant", "Jay", "Kendrew", "Kentaro", "Ryder", "Teppei", "Thomas", "Tyrone", "Andrey", "Donny", "Drago", "Gordon", "Grigor", "Jeriel", "Kenneth", "Martell", "Mathis", "Rich", "Rocky", "Rodrigo", "Wesley", "Zachery", "Alonzo", "Cadoc", "Gunnar", "Igor", "Killian", "Markus", "Ricardo", "Yanis", "Banting", "Clayton", "Duane", "Earl", "Greg", "Roy", "Terry", "Tracy", "Walter", "Alvaro", "Curtis", "Francis", "Ross", "Brice", "Cheng", "Dudley", "Eric", "Kano", "Masahiro", "Randy", "Ryuji", "Steve", "Tadashi", "Wong", "Yuen", "Brian", "Carter", "Reece", "Nick", "Yang" ], [ "Cora", "Cyndy", "Jill", "Laura", "Sadie", "Tessa", "Vivian", "Aisha", "Callie", "Danielle", "Helene", "Jocelyn", "Lilith", "Paula", "Reyna", "Helen", "Kelsey", "Tyler", "Amy", "Chandra", "Hillary", "Janie", "Lee", "Maggie", "Mikiko", "Miriam", "Sharon", "Susie", "Xiao", "Alize", "Azra", "Brenda", "Chalina", "Chan", "Glinda", "Maki", "Tia", "Tiffany", "Wendy", "Andrea", "Gabrielle", "Gerardine", "Hailey", "Hedvig", "Justine", "Kinsey", "Sigrid", "Veronique", "Tess" ]],
|
||||
[TrainerType.BREEDER]: [[ "Isaac", "Myles", "Salvadore", "Albert", "Kahlil", "Eustace", "Galen", "Owen", "Addison", "Marcus", "Foster", "Cory", "Glenn", "Jay", "Wesley", "William", "Adrian", "Bradley", "Jaime" ], [ "Allison", "Alize", "Bethany", "Lily", "Lydia", "Gabrielle", "Jayden", "Pat", "Veronica", "Amber", "Jennifer", "Kaylee", "Adelaide", "Brooke", "Ethel", "April", "Irene", "Magnolia", "Amala", "Mercy", "Amanda", "Ikue", "Savannah", "Yuka", "Chloe", "Debra", "Denise", "Elena" ]],
|
||||
[TrainerType.CLERK]: [[ "Chaz", "Clemens", "Doug", "Fredric", "Ivan", "Isaac", "Nelson", "Wade", "Warren", "Augustin", "Gilligan", "Cody", "Jeremy", "Shane", "Dugal", "Royce", "Ronald" ], [ "Alberta", "Ingrid", "Katie", "Piper", "Trisha", "Wren", "Britney", "Lana", "Jessica", "Kristen", "Michelle", "Gabrielle" ]],
|
||||
[TrainerType.CYCLIST]: [[ "Axel", "James", "John", "Ryan", "Hector", "Jeremiah" ], [ "Kayla", "Megan", "Nicole", "Rachel", "Krissa", "Adelaide" ]],
|
||||
[TrainerType.DANCER]: [ "Brian", "Davey", "Dirk", "Edmond", "Mickey", "Raymond", "Cara", "Julia", "Maika", "Mireille", "Ronda", "Zoe" ],
|
||||
[TrainerType.DEPOT_AGENT]: [ "Josh", "Hank", "Vincent" ],
|
||||
[TrainerType.DOCTOR]: [[ "Hank", "Jerry", "Jules", "Logan", "Wayne", "Braid", "Derek", "Heath", "Julius", "Kit", "Graham" ], [ "Kirsten", "Sachiko", "Shery", "Carol", "Dixie", "Mariah" ]],
|
||||
[TrainerType.FIREBREATHER]: [ "Bill", "Burt", "Cliff", "Dick", "Lyle", "Ned", "Otis", "Ray", "Richard", "Walt" ],
|
||||
[TrainerType.FISHERMAN]: [ "Andre", "Arnold", "Barney", "Chris", "Edgar", "Henry", "Jonah", "Justin", "Kyle", "Martin", "Marvin", "Ralph", "Raymond", "Scott", "Stephen", "Wilton", "Tully", "Andrew", "Barny", "Carter", "Claude", "Dale", "Elliot", "Eugene", "Ivan", "Ned", "Nolan", "Roger", "Ronald", "Wade", "Wayne", "Darian", "Kai", "Chip", "Hank", "Kaden", "Tommy", "Tylor", "Alec", "Brett", "Cameron", "Cody", "Cole", "Cory", "Erick", "George", "Joseph", "Juan", "Kenneth", "Luc", "Miguel", "Travis", "Walter", "Zachary", "Josh", "Gideon", "Kyler", "Liam", "Murphy", "Bruce", "Damon", "Devon", "Hubert", "Jones", "Lydon", "Mick", "Pete", "Sean", "Sid", "Vince", "Bucky", "Dean", "Eustace", "Kenzo", "Leroy", "Mack", "Ryder", "Ewan", "Finn", "Murray", "Seward", "Shad", "Wharton", "Finley", "Fisher", "Fisk", "River", "Sheaffer", "Timin", "Carl", "Ernest", "Hal", "Herbert", "Hisato", "Mike", "Vernon", "Harriet", "Marina", "Chase" ],
|
||||
[TrainerType.GUITARIST]: [ "Anna", "Beverly", "January", "Tina", "Alicia", "Claudia", "Julia", "Lidia", "Mireia", "Noelia", "Sara", "Sheila", "Tatiana" ],
|
||||
[TrainerType.HARLEQUIN]: [ "Charley", "Ian", "Jack", "Kerry", "Louis", "Pat", "Paul", "Rick", "Anders", "Clarence", "Gary" ],
|
||||
[TrainerType.HIKER]: [ "Anthony", "Bailey", "Benjamin", "Daniel", "Erik", "Jim", "Kenny", "Leonard", "Michael", "Parry", "Phillip", "Russell", "Sidney", "Tim", "Timothy", "Alan", "Brice", "Clark", "Eric", "Lenny", "Lucas", "Mike", "Trent", "Devan", "Eli", "Marc", "Sawyer", "Allen", "Daryl", "Dudley", "Earl", "Franklin", "Jeremy", "Marcos", "Nob", "Oliver", "Wayne", "Alexander", "Damon", "Jonathan", "Justin", "Kevin", "Lorenzo", "Louis", "Maurice", "Nicholas", "Reginald", "Robert", "Theodore", "Bruce", "Clarke", "Devin", "Dwight", "Edwin", "Eoin", "Noland", "Russel", "Andy", "Bret", "Darrell", "Gene", "Hardy", "Hugh", "Jebediah", "Jeremiah", "Kit", "Neil", "Terrell", "Don", "Doug", "Hunter", "Jared", "Jerome", "Keith", "Manuel", "Markus", "Otto", "Shelby", "Stephen", "Teppei", "Tobias", "Wade", "Zaiem", "Aaron", "Alain", "Bergin", "Bernard", "Brent", "Corwin", "Craig", "Delmon", "Dunstan", "Orestes", "Ross", "Davian", "Calhoun", "David", "Gabriel", "Ryan", "Thomas", "Travis", "Zachary", "Anuhea", "Barnaby", "Claus", "Collin", "Colson", "Dexter", "Dillan", "Eugine", "Farkas", "Hisato", "Julius", "Kenji", "Irwin", "Lionel", "Paul", "Richter", "Valentino", "Donald", "Douglas", "Kevyn", "Chester" ], //["Angela","Carla","Celia","Daniela","Estela","Fatima","Helena","Leire","Lucia","Luna","Manuela","Mar","Marina","Miyu","Nancy","Nerea","Paula","Rocio","Yanira"]
|
||||
[TrainerType.HOOLIGANS]: [ "Jim & Cas", "Rob & Sal" ],
|
||||
[TrainerType.HOOPSTER]: [ "Bobby", "John", "Lamarcus", "Derrick", "Nicolas" ],
|
||||
[TrainerType.INFIELDER]: [ "Alex", "Connor", "Todd" ],
|
||||
[TrainerType.JANITOR]: [ "Caleb", "Geoff", "Brady", "Felix", "Orville", "Melvin", "Shawn" ],
|
||||
[TrainerType.LINEBACKER]: [ "Bob", "Dan", "Jonah" ],
|
||||
[TrainerType.MAID]: [ "Belinda", "Sophie", "Emily", "Elena", "Clare", "Alica", "Tanya", "Tammy" ],
|
||||
[TrainerType.MUSICIAN]: [ "Boris", "Preston", "Charles", "Clyde", "Vincent", "Dalton", "Kirk", "Shawn", "Fabian", "Fernando", "Joseph", "Marcos", "Arturo", "Jerry", "Lonnie", "Tony" ],
|
||||
[TrainerType.NURSERY_AIDE]: [ "Autumn", "Briana", "Leah", "Miho", "Ethel", "Hollie", "Ilse", "June", "Kimya", "Rosalyn" ],
|
||||
[TrainerType.OFFICER]: [ "Dirk", "Keith", "Alex", "Bobby", "Caleb", "Danny", "Dylan", "Thomas", "Daniel", "Jeff", "Braven", "Dell", "Neagle", "Haruki", "Mitchell", "Raymond" ],
|
||||
[TrainerType.PARASOL_LADY]: [ "Angelica", "Clarissa", "Madeline", "Akari", "Annabell", "Kayley", "Rachel", "Alexa", "Sabrina", "April", "Gwyneth", "Laura", "Lumi", "Mariah", "Melita", "Nicole", "Tihana", "Ingrid", "Tyra" ],
|
||||
[TrainerType.PILOT]: [ "Chase", "Leonard", "Ted", "Elron", "Ewing", "Flynn", "Winslow" ],
|
||||
[TrainerType.POKEFAN]: [[ "Alex", "Allan", "Brandon", "Carter", "Colin", "Derek", "Jeremy", "Joshua", "Rex", "Robert", "Trevor", "William", "Colton", "Miguel", "Francisco", "Kaleb", "Leonard", "Boone", "Elliot", "Jude", "Norbert", "Corey", "Gabe", "Baxter" ], [ "Beverly", "Georgia", "Jaime", "Ruth", "Isabel", "Marissa", "Vanessa", "Annika", "Bethany", "Kimberly", "Meredith", "Rebekah", "Eleanor", "Darcy", "Lydia", "Sachiko", "Abigail", "Agnes", "Lydie", "Roisin", "Tara", "Carmen", "Janet" ]],
|
||||
[TrainerType.PRESCHOOLER]: [[ "Billy", "Doyle", "Evan", "Homer", "Tully", "Albert", "Buster", "Greg", "Ike", "Jojo", "Tyrone", "Adrian", "Oliver", "Hayden", "Hunter", "Kaleb", "Liam", "Dylan" ], [ "Juliet", "Mia", "Sarah", "Wendy", "Winter", "Chrissy", "Eva", "Lin", "Samantha", "Ella", "Lily", "Natalie", "Ailey", "Hannah", "Malia", "Kindra", "Nancy" ]],
|
||||
[TrainerType.PSYCHIC]: [[ "Fidel", "Franklin", "Gilbert", "Greg", "Herman", "Jared", "Mark", "Nathan", "Norman", "Phil", "Richard", "Rodney", "Cameron", "Edward", "Fritz", "Joshua", "Preston", "Virgil", "William", "Alvaro", "Blake", "Cedric", "Keenan", "Nicholas", "Dario", "Johan", "Lorenzo", "Tyron", "Bryce", "Corbin", "Deandre", "Elijah", "Kody", "Landon", "Maxwell", "Mitchell", "Sterling", "Eli", "Nelson", "Vernon", "Gaven", "Gerard", "Low", "Micki", "Perry", "Rudolf", "Tommy", "Al", "Nandor", "Tully", "Arthur", "Emanuel", "Franz", "Harry", "Paschal", "Robert", "Sayid", "Angelo", "Anton", "Arin", "Avery", "Danny", "Frasier", "Harrison", "Jaime", "Ross", "Rui", "Vlad", "Mason" ], [ "Alexis", "Hannah", "Jacki", "Jaclyn", "Kayla", "Maura", "Samantha", "Alix", "Brandi", "Edie", "Macey", "Mariella", "Marlene", "Laura", "Rodette", "Abigail", "Brittney", "Chelsey", "Daisy", "Desiree", "Kendra", "Lindsey", "Rachael", "Valencia", "Belle", "Cybil", "Doreen", "Dua", "Future", "Lin", "Madhu", "Alia", "Ena", "Joyce", "Lynette", "Olesia", "Sarah" ]],
|
||||
[TrainerType.RANGER]: [[ "Carlos", "Jackson", "Sebastian", "Gav", "Lorenzo", "Logan", "Nicolas", "Trenton", "Deshawn", "Dwayne", "Jeffery", "Kyler", "Taylor", "Alain", "Claude", "Crofton", "Forrest", "Harry", "Jaden", "Keith", "Lewis", "Miguel", "Pedro", "Ralph", "Richard", "Bret", "Daryl", "Eddie", "Johan", "Leaf", "Louis", "Maxwell", "Parker", "Rick", "Steve", "Bjorn", "Chaise", "Dean", "Lee", "Maurice", "Nash", "Ralf", "Reed", "Shinobu", "Silas" ], [ "Catherine", "Jenna", "Sophia", "Merdith", "Nora", "Beth", "Chelsea", "Katelyn", "Madeline", "Allison", "Ashlee", "Felicia", "Krista", "Annie", "Audra", "Brenda", "Chloris", "Eliza", "Heidi", "Irene", "Mary", "Mylene", "Shanti", "Shelly", "Thalia", "Anja", "Briana", "Dianna", "Elaine", "Elle", "Hillary", "Katie", "Lena", "Lois", "Malory", "Melita", "Mikiko", "Naoko", "Serenity", "Ambre", "Brooke", "Clementine", "Melina", "Petra", "Twiggy" ]],
|
||||
[TrainerType.RICH]: [[ "Alfred", "Edward", "Gregory", "Preston", "Thomas", "Tucker", "Walter", "Clifford", "Everett", "Micah", "Nate", "Pierre", "Terrance", "Arthur", "Brooks", "Emanuel", "Lamar", "Jeremy", "Leonardo", "Milton", "Frederic", "Renaud", "Robert", "Yan", "Daniel", "Sheldon", "Stonewall", "Gerald", "Ronald", "Smith", "Stanley", "Reginald", "Orson", "Wilco", "Caden", "Glenn" ], [ "Rebecca", "Reina", "Cassandra", "Emilia", "Grace", "Marian", "Elizabeth", "Kathleen", "Sayuri", "Caroline", "Judy" ]],
|
||||
[TrainerType.RICH_KID]: [[ "Garret", "Winston", "Dawson", "Enrique", "Jason", "Roman", "Trey", "Liam", "Anthony", "Brad", "Cody", "Manuel", "Martin", "Pierce", "Rolan", "Keenan", "Filbert", "Antoin", "Cyus", "Diek", "Dugo", "Flitz", "Jurek", "Lond", "Perd", "Quint", "Basto", "Benit", "Brot", "Denc", "Guyit", "Marcon", "Perc", "Puros", "Roex", "Sainz", "Symin", "Tark", "Venak" ], [ "Anette", "Brianna", "Cindy", "Colleen", "Daphne", "Elizabeth", "Naomi", "Sarah", "Charlotte", "Gillian", "Jacki", "Lady", "Melissa", "Celeste", "Colette", "Elizandra", "Isabel", "Lynette", "Magnolia", "Sophie", "Lina", "Dulcie", "Auro", "Brin", "Caril", "Eloos", "Gwin", "Illa", "Kowly", "Rima", "Ristin", "Vesey", "Brena", "Deasy", "Denslon", "Kylet", "Nemi", "Rene", "Sanol", "Stouner", "Sturk", "Talmen", "Zoila" ]],
|
||||
[TrainerType.ROUGHNECK]: [ "Camron", "Corey", "Gabriel", "Isaiah", "Jamal", "Koji", "Luke", "Paxton", "Raul", "Zeek", "Kirby", "Chance", "Dave", "Fletcher", "Johnny", "Reese", "Joey", "Ricky", "Silvester", "Martin" ],
|
||||
[TrainerType.SAILOR]: [ "Alberto", "Bost", "Brennan", "Brenden", "Claude", "Cory", "Damian", "Dirk", "Duncan", "Dwayne", "Dylan", "Eddie", "Edmond", "Elijah", "Ernest", "Eugene", "Garrett", "Golos", "Gratin", "Grestly", "Harry", "Hols", "Hudson", "Huey", "Jebol", "Jeff", "Leonald", "Luther", "Kelvin", "Kenneth", "Kent", "Knook", "Marc", "Mifis", "Monar", "Morkor", "Ordes", "Oxlin", "Parker", "Paul", "Philip", "Roberto", "Samson", "Skyler", "Stanly", "Tebu", "Terrell", "Trevor", "Yasu", "Zachariah" ],
|
||||
[TrainerType.SCIENTIST]: [[ "Jed", "Marc", "Mitch", "Rich", "Ross", "Beau", "Braydon", "Connor", "Ed", "Ivan", "Jerry", "Jose", "Joshua", "Parker", "Rodney", "Taylor", "Ted", "Travis", "Zackery", "Darrius", "Emilio", "Fredrick", "Shaun", "Stefano", "Travon", "Daniel", "Garett", "Gregg", "Linden", "Lowell", "Trenton", "Dudley", "Luke", "Markus", "Nathan", "Orville", "Randall", "Ron", "Ronald", "Simon", "Steve", "William", "Franklin", "Clarke", "Jacques", "Terrance", "Ernst", "Justus", "Ikaika", "Jayson", "Kyle", "Reid", "Tyrone", "Adam", "Albert", "Alphonse", "Cory", "Donnie", "Elton", "Francis", "Gordon", "Herbert", "Humphrey", "Jordan", "Julian", "Keaton", "Levi", "Melvin", "Murray", "West", "Craig", "Coren", "Dubik", "Kotan", "Lethco", "Mante", "Mort", "Myron", "Odlow", "Ribek", "Roeck", "Vogi", "Vonder", "Zogo", "Doimo", "Doton", "Durel", "Hildon", "Kukla", "Messa", "Nanot", "Platen", "Raburn", "Reman", "Acrod", "Coffy", "Elrok", "Foss", "Hardig", "Hombol", "Hospel", "Kaller", "Klots", "Krilok", "Limar", "Loket", "Mesak", "Morbit", "Newin", "Orill", "Tabor", "Tekot" ], [ "Blythe", "Chan", "Kathrine", "Marie", "Maria", "Naoko", "Samantha", "Satomi", "Shannon", "Athena", "Caroline", "Lumi", "Lumina", "Marissa", "Sonia" ]],
|
||||
[TrainerType.SMASHER]: [ "Aspen", "Elena", "Mari", "Amy", "Lizzy" ],
|
||||
[TrainerType.SNOW_WORKER]: [[ "Braden", "Brendon", "Colin", "Conrad", "Dillan", "Gary", "Gerardo", "Holden", "Jackson", "Mason", "Quentin", "Willy", "Noel", "Arnold", "Brady", "Brand", "Cairn", "Cliff", "Don", "Eddie", "Felix", "Filipe", "Glenn", "Gus", "Heath", "Matthew", "Patton", "Rich", "Rob", "Ryan", "Scott", "Shelby", "Sterling", "Tyler", "Victor", "Zack", "Friedrich", "Herman", "Isaac", "Leo", "Maynard", "Mitchell", "Morgann", "Nathan", "Niel", "Pasqual", "Paul", "Tavarius", "Tibor", "Dimitri", "Narek", "Yusif", "Frank", "Jeff", "Vaclav", "Ovid", "Francis", "Keith", "Russel", "Sangon", "Toway", "Bomber", "Chean", "Demit", "Hubor", "Kebile", "Laber", "Ordo", "Retay", "Ronix", "Wagel", "Dobit", "Kaster", "Lobel", "Releo", "Saken", "Rustix" ], [ "Georgia", "Sandra", "Yvonne" ]],
|
||||
[TrainerType.STRIKER]: [ "Marco", "Roberto", "Tony" ],
|
||||
[TrainerType.SCHOOL_KID]: [[ "Alan", "Billy", "Chad", "Danny", "Dudley", "Jack", "Joe", "Johnny", "Kipp", "Nate", "Ricky", "Tommy", "Jerry", "Paul", "Ted", "Chance", "Esteban", "Forrest", "Harrison", "Connor", "Sherman", "Torin", "Travis", "Al", "Carter", "Edgar", "Jem", "Sammy", "Shane", "Shayne", "Alvin", "Keston", "Neil", "Seymour", "William", "Carson", "Clark", "Nolan" ], [ "Georgia", "Karen", "Meiko", "Christine", "Mackenzie", "Tiera", "Ann", "Gina", "Lydia", "Marsha", "Millie", "Sally", "Serena", "Silvia", "Alberta", "Cassie", "Mara", "Rita", "Georgie", "Meena", "Nitzel" ]],
|
||||
[TrainerType.SWIMMER]: [[ "Berke", "Cameron", "Charlie", "George", "Harold", "Jerome", "Kirk", "Mathew", "Parker", "Randall", "Seth", "Simon", "Tucker", "Austin", "Barry", "Chad", "Cody", "Darrin", "David", "Dean", "Douglas", "Franklin", "Gilbert", "Herman", "Jack", "Luis", "Matthew", "Reed", "Richard", "Rodney", "Roland", "Spencer", "Stan", "Tony", "Clarence", "Declan", "Dominik", "Harrison", "Kevin", "Leonardo", "Nolen", "Pete", "Santiago", "Axle", "Braden", "Finn", "Garrett", "Mymo", "Reece", "Samir", "Toby", "Adrian", "Colton", "Dillon", "Erik", "Evan", "Francisco", "Glenn", "Kurt", "Oscar", "Ricardo", "Sam", "Sheltin", "Troy", "Vincent", "Wade", "Wesley", "Duane", "Elmo", "Esteban", "Frankie", "Ronald", "Tyson", "Bart", "Matt", "Tim", "Wright", "Jeffery", "Kyle", "Alessandro", "Estaban", "Kieran", "Ramses", "Casey", "Dakota", "Jared", "Kalani", "Keoni", "Lawrence", "Logan", "Robert", "Roddy", "Yasu", "Derek", "Jacob", "Bruce", "Clayton" ], [ "Briana", "Dawn", "Denise", "Diana", "Elaine", "Kara", "Kaylee", "Lori", "Nicole", "Nikki", "Paula", "Susie", "Wendy", "Alice", "Beth", "Beverly", "Brenda", "Dana", "Debra", "Grace", "Jenny", "Katie", "Laurel", "Linda", "Missy", "Sharon", "Tanya", "Tara", "Tisha", "Carlee", "Imani", "Isabelle", "Kyla", "Sienna", "Abigail", "Amara", "Anya", "Connie", "Maria", "Melissa", "Nora", "Shirley", "Shania", "Tiffany", "Aubree", "Cassandra", "Claire", "Crystal", "Erica", "Gabrielle", "Haley", "Jessica", "Joanna", "Lydia", "Mallory", "Mary", "Miranda", "Paige", "Sophia", "Vanessa", "Chelan", "Debbie", "Joy", "Kendra", "Leona", "Mina", "Caroline", "Joyce", "Larissa", "Rebecca", "Tyra", "Dara", "Desiree", "Kaoru", "Ruth", "Coral", "Genevieve", "Isla", "Marissa", "Romy", "Sheryl", "Alexandria", "Alicia", "Chelsea", "Jade", "Kelsie", "Laura", "Portia", "Shelby", "Sara", "Tiare", "Kyra", "Natasha", "Layla", "Scarlett", "Cora" ]],
|
||||
[TrainerType.TWINS]: [ "Amy & May", "Jo & Zoe", "Meg & Peg", "Ann & Anne", "Lea & Pia", "Amy & Liv", "Gina & Mia", "Miu & Yuki", "Tori & Tia", "Eli & Anne", "Jen & Kira", "Joy & Meg", "Kiri & Jan", "Miu & Mia", "Emma & Lil", "Liv & Liz", "Teri & Tia", "Amy & Mimi", "Clea & Gil", "Day & Dani", "Kay & Tia", "Tori & Til", "Saya & Aya", "Emy & Lin", "Kumi & Amy", "Mayo & May", "Ally & Amy", "Lia & Lily", "Rae & Ula", "Sola & Ana", "Tara & Val", "Faith & Joy", "Nana & Nina" ],
|
||||
[TrainerType.VETERAN]: [[ "Armando", "Brenden", "Brian", "Clayton", "Edgar", "Emanuel", "Grant", "Harlan", "Terrell", "Arlen", "Chester", "Hugo", "Martell", "Ray", "Shaun", "Abraham", "Carter", "Claude", "Jerry", "Lucius", "Murphy", "Rayne", "Ron", "Sinan", "Sterling", "Vincent", "Zach", "Gerard", "Gilles", "Louis", "Timeo", "Akira", "Don", "Eric", "Harry", "Leon", "Roger", "Angus", "Aristo", "Brone", "Johnny" ], [ "Julia", "Karla", "Kim", "Sayuri", "Tiffany", "Cathy", "Cecile", "Chloris", "Denae", "Gina", "Maya", "Oriana", "Portia", "Rhona", "Rosaline", "Catrina", "Inga", "Trisha", "Heather", "Lynn", "Sheri", "Alonsa", "Ella", "Leticia", "Kiara" ]],
|
||||
[TrainerType.WAITER]: [[ "Bert", "Clint", "Maxwell", "Lou" ], [ "Kati", "Aurora", "Bonita", "Flo", "Tia", "Jan", "Olwen", "Paget", "Paula", "Talia" ]],
|
||||
[TrainerType.WORKER]: [[ "Braden", "Brendon", "Colin", "Conrad", "Dillan", "Gary", "Gerardo", "Holden", "Jackson", "Mason", "Quentin", "Willy", "Noel", "Arnold", "Brady", "Brand", "Cairn", "Cliff", "Don", "Eddie", "Felix", "Filipe", "Glenn", "Gus", "Heath", "Matthew", "Patton", "Rich", "Rob", "Ryan", "Scott", "Shelby", "Sterling", "Tyler", "Victor", "Zack", "Friedrich", "Herman", "Isaac", "Leo", "Maynard", "Mitchell", "Morgann", "Nathan", "Niel", "Pasqual", "Paul", "Tavarius", "Tibor", "Dimitri", "Narek", "Yusif", "Frank", "Jeff", "Vaclav", "Ovid", "Francis", "Keith", "Russel", "Sangon", "Toway", "Bomber", "Chean", "Demit", "Hubor", "Kebile", "Laber", "Ordo", "Retay", "Ronix", "Wagel", "Dobit", "Kaster", "Lobel", "Releo", "Saken", "Rustix" ], [ "Georgia", "Sandra", "Yvonne" ]],
|
||||
[TrainerType.YOUNGSTER]: [[ "Albert", "Gordon", "Ian", "Jason", "Jimmy", "Mikey", "Owen", "Samuel", "Warren", "Allen", "Ben", "Billy", "Calvin", "Dillion", "Eddie", "Joey", "Josh", "Neal", "Timmy", "Tommy", "Breyden", "Deandre", "Demetrius", "Dillon", "Jaylen", "Johnson", "Shigenobu", "Chad", "Cole", "Cordell", "Dan", "Dave", "Destin", "Nash", "Tyler", "Yasu", "Austin", "Dallas", "Darius", "Donny", "Jonathon", "Logan", "Michael", "Oliver", "Sebastian", "Tristan", "Wayne", "Norman", "Roland", "Regis", "Abe", "Astor", "Keita", "Kenneth", "Kevin", "Kyle", "Lester", "Masao", "Nicholas", "Parker", "Wes", "Zachary", "Cody", "Henley", "Jaye", "Karl", "Kenny", "Masahiro", "Pedro", "Petey", "Sinclair", "Terrell", "Waylon", "Aidan", "Anthony", "David", "Jacob", "Jayden", "Cutler", "Ham", "Caleb", "Kai", "Honus", "Kenway", "Bret", "Chris", "Cid", "Dennis", "Easton", "Ken", "Robby", "Ronny", "Shawn", "Benjamin", "Jake", "Travis", "Adan", "Aday", "Beltran", "Elian", "Hernan", "Julen", "Luka", "Roi", "Bernie", "Dustin", "Jonathan", "Wyatt" ], [ "Alice", "Bridget", "Carrie", "Connie", "Dana", "Ellen", "Krise", "Laura", "Linda", "Michelle", "Shannon", "Andrea", "Crissy", "Janice", "Robin", "Sally", "Tiana", "Haley", "Ali", "Ann", "Dalia", "Dawn", "Iris", "Joana", "Julia", "Kay", "Lisa", "Megan", "Mikaela", "Miriam", "Paige", "Reli", "Blythe", "Briana", "Caroline", "Cassidy", "Kaitlin", "Madeline", "Molly", "Natalie", "Samantha", "Sarah", "Cathy", "Dye", "Eri", "Eva", "Fey", "Kara", "Lurleen", "Maki", "Mali", "Maya", "Miki", "Sibyl", "Daya", "Diana", "Flo", "Helia", "Henrietta", "Isabel", "Mai", "Persephone", "Serena", "Anna", "Charlotte", "Elin", "Elsa", "Lise", "Sara", "Suzette", "Audrey", "Emmy", "Isabella", "Madison", "Rika", "Rylee", "Salla", "Ellie", "Alexandra", "Amy", "Lass", "Brittany", "Chel", "Cindy", "Dianne", "Emily", "Emma", "Evelyn", "Hana", "Harleen", "Hazel", "Jocelyn", "Katrina", "Kimberly", "Lina", "Marge", "Mila", "Mizuki", "Rena", "Sal", "Satoko", "Summer", "Tomoe", "Vicky", "Yue", "Yumi", "Lauren", "Rei", "Riley", "Lois", "Nancy", "Tammy", "Terry" ]],
|
||||
[TrainerType.HEX_MANIAC]: [ "Kindra", "Patricia", "Tammy", "Tasha", "Valerie", "Alaina", "Kathleen", "Leah", "Makie", "Sylvia", "Anina", "Arachna", "Carrie", "Desdemona", "Josette", "Luna", "Melanie", "Osanna", "Raziah" ],
|
||||
};
|
||||
|
||||
// function used in a commented code
|
||||
@ -140,7 +140,7 @@ function fetchAndPopulateTrainerNames(url: string, parser: DOMParser, trainerNam
|
||||
if (!trainerListHeader) {
|
||||
return [];
|
||||
}
|
||||
const elements = [...(trainerListHeader?.parentElement?.childNodes ?? [])];
|
||||
const elements = [ ...(trainerListHeader?.parentElement?.childNodes ?? []) ];
|
||||
const startChildIndex = elements.indexOf(trainerListHeader);
|
||||
const endChildIndex = elements.findIndex(h => h.nodeName === "H2" && elements.indexOf(h) > startChildIndex);
|
||||
const tables = elements.filter(t => {
|
||||
@ -152,7 +152,7 @@ function fetchAndPopulateTrainerNames(url: string, parser: DOMParser, trainerNam
|
||||
}).map(t => t as Element);
|
||||
console.log(url, tables);
|
||||
for (const table of tables) {
|
||||
const trainerRows = [...table.querySelectorAll("tr:not(:first-child)")].filter(r => r.children.length === 9);
|
||||
const trainerRows = [ ...table.querySelectorAll("tr:not(:first-child)") ].filter(r => r.children.length === 9);
|
||||
for (const row of trainerRows) {
|
||||
const nameCell = row.firstElementChild;
|
||||
if (!nameCell) {
|
||||
|
@ -171,9 +171,9 @@ export function getWeatherLapseMessage(weatherType: WeatherType): string | null
|
||||
export function getWeatherDamageMessage(weatherType: WeatherType, pokemon: Pokemon): string | null {
|
||||
switch (weatherType) {
|
||||
case WeatherType.SANDSTORM:
|
||||
return i18next.t("weather:sandstormDamageMessage", {pokemonNameWithAffix: getPokemonNameWithAffix(pokemon)});
|
||||
return i18next.t("weather:sandstormDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
|
||||
case WeatherType.HAIL:
|
||||
return i18next.t("weather:hailDamageMessage", {pokemonNameWithAffix: getPokemonNameWithAffix(pokemon)});
|
||||
return i18next.t("weather:hailDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -238,9 +238,9 @@ export function getTerrainClearMessage(terrainType: TerrainType): string | null
|
||||
|
||||
export function getTerrainBlockMessage(pokemon: Pokemon, terrainType: TerrainType): string {
|
||||
if (terrainType === TerrainType.MISTY) {
|
||||
return i18next.t("terrain:mistyBlockMessage", {pokemonNameWithAffix: getPokemonNameWithAffix(pokemon)});
|
||||
return i18next.t("terrain:mistyBlockMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
|
||||
}
|
||||
return i18next.t("terrain:defaultBlockMessage", {pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), terrainName: getTerrainName(terrainType)});
|
||||
return i18next.t("terrain:defaultBlockMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), terrainName: getTerrainName(terrainType) });
|
||||
}
|
||||
|
||||
interface WeatherPoolEntry {
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
export enum ArenaTagType {
|
||||
NONE = "NONE",
|
||||
MUD_SPORT = "MUD_SPORT",
|
||||
@ -25,4 +24,5 @@ export enum ArenaTagType {
|
||||
SAFEGUARD = "SAFEGUARD",
|
||||
NO_CRIT = "NO_CRIT",
|
||||
IMPRISON = "IMPRISON",
|
||||
PLASMA_FISTS = "PLASMA_FISTS",
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
export enum BattlerTagType {
|
||||
NONE = "NONE",
|
||||
RECHARGING = "RECHARGING",
|
||||
@ -85,4 +84,5 @@ export enum BattlerTagType {
|
||||
TORMENT = "TORMENT",
|
||||
TAUNT = "TAUNT",
|
||||
IMPRISON = "IMPRISON",
|
||||
SYRUP_BOMB = "SYRUP_BOMB",
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
export enum BerryType {
|
||||
SITRUS,
|
||||
LUM,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
export enum Biome {
|
||||
TOWN,
|
||||
PLAINS,
|
||||
|
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,4 +1,3 @@
|
||||
|
||||
export enum TimeOfDay {
|
||||
ALL = -1,
|
||||
DAWN,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user