mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-01 14:02:18 +02:00
Merge remote-tracking branch 'upstream/beta' into intim-tests
This commit is contained in:
commit
929175f41e
@ -1,6 +1,17 @@
|
|||||||
/** @type {import('dependency-cruiser').IConfiguration} */
|
/** @type {import('dependency-cruiser').IConfiguration} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
forbidden: [
|
forbidden: [
|
||||||
|
{
|
||||||
|
name: "only-type-imports",
|
||||||
|
severity: "error",
|
||||||
|
comment: "Files in enums and @types may only use type imports.",
|
||||||
|
from: {
|
||||||
|
path: ["(^|/)src/@types", "(^|/)src/enums"],
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
dependencyTypesNot: ["type-only"],
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "no-circular-at-runtime",
|
name: "no-circular-at-runtime",
|
||||||
severity: "warn",
|
severity: "warn",
|
||||||
@ -31,6 +42,8 @@ module.exports = {
|
|||||||
"[.]d[.]ts$", // TypeScript declaration files
|
"[.]d[.]ts$", // TypeScript declaration files
|
||||||
"(^|/)tsconfig[.]json$", // TypeScript config
|
"(^|/)tsconfig[.]json$", // TypeScript config
|
||||||
"(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$", // other configs
|
"(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$", // other configs
|
||||||
|
// anything in src/@types
|
||||||
|
"(^|/)src/@types/",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
to: {},
|
to: {},
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
"src/overrides.ts",
|
"src/overrides.ts",
|
||||||
// TODO: these files are too big and complex, ignore them until their respective refactors
|
// TODO: these files are too big and complex, ignore them until their respective refactors
|
||||||
"src/data/moves/move.ts",
|
"src/data/moves/move.ts",
|
||||||
"src/data/abilities/ability.ts",
|
|
||||||
|
|
||||||
// this file is just too big:
|
// this file is just too big:
|
||||||
"src/data/balance/tms.ts"
|
"src/data/balance/tms.ts"
|
||||||
@ -42,9 +41,6 @@
|
|||||||
// TODO: Remove if we ever get down to 0 circular imports
|
// TODO: Remove if we ever get down to 0 circular imports
|
||||||
"organizeImports": { "enabled": false },
|
"organizeImports": { "enabled": false },
|
||||||
"linter": {
|
"linter": {
|
||||||
"ignore": [
|
|
||||||
"src/phases/move-effect-phase.ts" // TODO: unignore after move-effect-phase refactor
|
|
||||||
],
|
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"rules": {
|
"rules": {
|
||||||
"recommended": true,
|
"recommended": true,
|
||||||
|
@ -1,172 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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";
|
|
||||||
import inquirer from "inquirer";
|
|
||||||
import path from "path";
|
|
||||||
import { fileURLToPath } from "url";
|
|
||||||
|
|
||||||
// Get the directory name of the current module file
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
|
||||||
const __dirname = path.dirname(__filename);
|
|
||||||
const typeChoices = ["Move", "Ability", "Item", "Mystery Encounter"];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prompts the user to select a type via list.
|
|
||||||
* @returns {Promise<{selectedOption: string}>} the selected type
|
|
||||||
*/
|
|
||||||
async function promptTestType() {
|
|
||||||
const typeAnswer = await inquirer.prompt([
|
|
||||||
{
|
|
||||||
type: "list",
|
|
||||||
name: "selectedOption",
|
|
||||||
message: "What type of test would you like to create:",
|
|
||||||
choices: [...typeChoices, "EXIT"],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (typeAnswer.selectedOption === "EXIT") {
|
|
||||||
console.log("Exiting...");
|
|
||||||
return process.exit();
|
|
||||||
}
|
|
||||||
if (!typeChoices.includes(typeAnswer.selectedOption)) {
|
|
||||||
console.error(`Please provide a valid type (${typeChoices.join(", ")})!`);
|
|
||||||
return await promptTestType();
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeAnswer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prompts the user to provide a file name.
|
|
||||||
* @param {string} selectedType
|
|
||||||
* @returns {Promise<{userInput: string}>} the selected file name
|
|
||||||
*/
|
|
||||||
async function promptFileName(selectedType) {
|
|
||||||
const fileNameAnswer = await inquirer.prompt([
|
|
||||||
{
|
|
||||||
type: "input",
|
|
||||||
name: "userInput",
|
|
||||||
message: `Please provide the name of the ${selectedType}:`,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (!fileNameAnswer.userInput || fileNameAnswer.userInput.trim().length === 0) {
|
|
||||||
console.error("Please provide a valid file name!");
|
|
||||||
return await promptFileName(selectedType);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileNameAnswer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the interactive create-test "CLI"
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
async function runInteractive() {
|
|
||||||
const typeAnswer = await promptTestType();
|
|
||||||
const fileNameAnswer = await promptFileName(typeAnswer.selectedOption);
|
|
||||||
|
|
||||||
const type = typeAnswer.selectedOption.toLowerCase();
|
|
||||||
// Convert fileName from kebab-case or camelCase to snake_case
|
|
||||||
const fileName = fileNameAnswer.userInput
|
|
||||||
.replace(/-+/g, "_") // Convert kebab-case (dashes) to underscores
|
|
||||||
.replace(/([a-z])([A-Z])/g, "$1_$2") // Convert camelCase to snake_case
|
|
||||||
.replace(/\s+/g, "_") // Replace spaces with underscores
|
|
||||||
.toLowerCase(); // Ensure all lowercase
|
|
||||||
// Format the description for the test case
|
|
||||||
|
|
||||||
const formattedName = fileName.replace(/_/g, " ").replace(/\b\w/g, char => char.toUpperCase());
|
|
||||||
// Determine the directory based on the type
|
|
||||||
let dir;
|
|
||||||
let description;
|
|
||||||
switch (type) {
|
|
||||||
case "move":
|
|
||||||
dir = path.join(__dirname, "test", "moves");
|
|
||||||
description = `Moves - ${formattedName}`;
|
|
||||||
break;
|
|
||||||
case "ability":
|
|
||||||
dir = path.join(__dirname, "test", "abilities");
|
|
||||||
description = `Abilities - ${formattedName}`;
|
|
||||||
break;
|
|
||||||
case "item":
|
|
||||||
dir = path.join(__dirname, "test", "items");
|
|
||||||
description = `Items - ${formattedName}`;
|
|
||||||
break;
|
|
||||||
case "mystery encounter":
|
|
||||||
dir = path.join(__dirname, "test", "mystery-encounter", "encounters");
|
|
||||||
description = `Mystery Encounter - ${formattedName}`;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.error(`Invalid type. Please use one of the following: ${typeChoices.join(", ")}.`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define the content template
|
|
||||||
const content = `import { Abilities } from "#enums/abilities";
|
|
||||||
import { Moves } from "#enums/moves";
|
|
||||||
import { Species } from "#enums/species";
|
|
||||||
import GameManager from "#test/testUtils/gameManager";
|
|
||||||
import Phaser from "phaser";
|
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
|
||||||
|
|
||||||
describe("${description}", () => {
|
|
||||||
let phaserGame: Phaser.Game;
|
|
||||||
let game: GameManager;
|
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
phaserGame = new Phaser.Game({
|
|
||||||
type: Phaser.HEADLESS,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
game.phaseInterceptor.restoreOg();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
game = new GameManager(phaserGame);
|
|
||||||
game.override
|
|
||||||
.moveset([ Moves.SPLASH ])
|
|
||||||
.ability(Abilities.BALL_FETCH)
|
|
||||||
.battleType("single")
|
|
||||||
.disableCrits()
|
|
||||||
.enemySpecies(Species.MAGIKARP)
|
|
||||||
.enemyAbility(Abilities.BALL_FETCH)
|
|
||||||
.enemyMoveset(Moves.SPLASH);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should do X", async () => {
|
|
||||||
await game.classicMode.startBattle([ Species.FEEBAS ]);
|
|
||||||
|
|
||||||
game.move.select(Moves.SPLASH);
|
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
|
||||||
|
|
||||||
expect(true).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Ensure the directory exists
|
|
||||||
if (!fs.existsSync(dir)) {
|
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the file with the given name
|
|
||||||
const filePath = path.join(dir, `${fileName}.test.ts`);
|
|
||||||
|
|
||||||
if (fs.existsSync(filePath)) {
|
|
||||||
console.error(`File "${fileName}.test.ts" already exists.`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the template content to the file
|
|
||||||
fs.writeFileSync(filePath, content, "utf8");
|
|
||||||
|
|
||||||
console.log(`File created at: ${filePath}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
runInteractive();
|
|
@ -145,6 +145,5 @@
|
|||||||
</div>
|
</div>
|
||||||
<script type="module" src="./src/main.ts"></script>
|
<script type="module" src="./src/main.ts"></script>
|
||||||
<script src="./src/touch-controls.ts" type="module"></script>
|
<script src="./src/touch-controls.ts" type="module"></script>
|
||||||
<script src="./src/debug.js" type="module"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -9,6 +9,11 @@ pre-commit:
|
|||||||
- rebase
|
- rebase
|
||||||
|
|
||||||
post-merge:
|
post-merge:
|
||||||
|
commands:
|
||||||
|
update-submodules:
|
||||||
|
run: git submodule update --init --recursive
|
||||||
|
|
||||||
|
post-checkout:
|
||||||
commands:
|
commands:
|
||||||
update-submodules:
|
update-submodules:
|
||||||
run: git submodule update --init --recursive
|
run: git submodule update --init --recursive
|
@ -13,6 +13,7 @@
|
|||||||
"test:cov": "vitest run --coverage --no-isolate",
|
"test:cov": "vitest run --coverage --no-isolate",
|
||||||
"test:watch": "vitest watch --coverage --no-isolate",
|
"test:watch": "vitest watch --coverage --no-isolate",
|
||||||
"test:silent": "vitest run --silent --no-isolate",
|
"test:silent": "vitest run --silent --no-isolate",
|
||||||
|
"test:create": "node scripts/create-test/create-test.js",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"eslint": "eslint --fix .",
|
"eslint": "eslint --fix .",
|
||||||
"eslint-ci": "eslint .",
|
"eslint-ci": "eslint .",
|
||||||
@ -21,7 +22,6 @@
|
|||||||
"docs": "typedoc",
|
"docs": "typedoc",
|
||||||
"depcruise": "depcruise src",
|
"depcruise": "depcruise src",
|
||||||
"depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg",
|
"depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg",
|
||||||
"create-test": "node ./create-test-boilerplate.js",
|
|
||||||
"postinstall": "npx lefthook install && npx lefthook run post-merge",
|
"postinstall": "npx lefthook install && npx lefthook run post-merge",
|
||||||
"update-version:patch": "npm version patch --force --no-git-tag-version",
|
"update-version:patch": "npm version patch --force --no-git-tag-version",
|
||||||
"update-version:minor": "npm version minor --force --no-git-tag-version",
|
"update-version:minor": "npm version minor --force --no-git-tag-version",
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.7 KiB |
147
scripts/create-test/create-test.js
Normal file
147
scripts/create-test/create-test.js
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/**
|
||||||
|
* This script creates a test boilerplate file in the appropriate
|
||||||
|
* directory based on the type selected.
|
||||||
|
* @example npm run test:create
|
||||||
|
*/
|
||||||
|
|
||||||
|
import chalk from "chalk";
|
||||||
|
import inquirer from "inquirer";
|
||||||
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
//#region Constants
|
||||||
|
|
||||||
|
const version = "2.0.1";
|
||||||
|
// Get the directory name of the current module file
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const projectRoot = path.join(__dirname, "..", "..");
|
||||||
|
const boilerplateFilePath = path.join(__dirname, "test-boilerplate.ts");
|
||||||
|
const choices = [
|
||||||
|
{ label: "Move", dir: "moves" },
|
||||||
|
{ label: "Ability", dir: "abilities" },
|
||||||
|
{ label: "Item", dir: "items" },
|
||||||
|
{ label: "Mystery Encounter", dir: "mystery-encounter/encounters" },
|
||||||
|
{ label: "Utils", dir: "utils" },
|
||||||
|
{ label: "UI", dir: "ui" },
|
||||||
|
];
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
//#region Functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path to a given folder in the test directory
|
||||||
|
* @param {...string} folders the subfolders to append to the base path
|
||||||
|
* @returns {string} the path to the requested folder
|
||||||
|
*/
|
||||||
|
function getTestFolderPath(...folders) {
|
||||||
|
return path.join(projectRoot, "test", ...folders);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompts the user to select a type via list.
|
||||||
|
* @returns {Promise<{selectedOption: {label: string, dir: string}}>} the selected type
|
||||||
|
*/
|
||||||
|
async function promptTestType() {
|
||||||
|
const typeAnswer = await inquirer.prompt([
|
||||||
|
{
|
||||||
|
type: "list",
|
||||||
|
name: "selectedOption",
|
||||||
|
message: "What type of test would you like to create:",
|
||||||
|
choices: [...choices.map(choice => ({ name: choice.label, value: choice })), "EXIT"],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (typeAnswer.selectedOption === "EXIT") {
|
||||||
|
console.log("Exiting...");
|
||||||
|
return process.exit();
|
||||||
|
}
|
||||||
|
if (!choices.some(choice => choice.dir === typeAnswer.selectedOption.dir)) {
|
||||||
|
console.error(`Please provide a valid type: (${choices.map(choice => choice.label).join(", ")})!`);
|
||||||
|
return await promptTestType();
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeAnswer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompts the user to provide a file name.
|
||||||
|
* @param {string} selectedType
|
||||||
|
* @returns {Promise<{userInput: string}>} the selected file name
|
||||||
|
*/
|
||||||
|
async function promptFileName(selectedType) {
|
||||||
|
/** @type {{userInput: string}} */
|
||||||
|
const fileNameAnswer = await inquirer.prompt([
|
||||||
|
{
|
||||||
|
type: "input",
|
||||||
|
name: "userInput",
|
||||||
|
message: `Please provide the name of the ${selectedType}:`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!fileNameAnswer.userInput || fileNameAnswer.userInput.trim().length === 0) {
|
||||||
|
console.error("Please provide a valid file name!");
|
||||||
|
return await promptFileName(selectedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileNameAnswer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the interactive test:create "CLI"
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async function runInteractive() {
|
||||||
|
console.group(chalk.grey(`Create Test - v${version}\n`));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const typeAnswer = await promptTestType();
|
||||||
|
const fileNameAnswer = await promptFileName(typeAnswer.selectedOption.label);
|
||||||
|
|
||||||
|
const type = typeAnswer.selectedOption;
|
||||||
|
// Convert fileName from snake_case or camelCase to kebab-case
|
||||||
|
const fileName = fileNameAnswer.userInput
|
||||||
|
.replace(/_+/g, "-") // Convert snake_case (underscore) to kebab-case (dashes)
|
||||||
|
.replace(/([a-z])([A-Z])/g, "$1-$2") // Convert camelCase to kebab-case
|
||||||
|
.replace(/\s+/g, "-") // Replace spaces with dashes
|
||||||
|
.toLowerCase(); // Ensure all lowercase
|
||||||
|
// Format the description for the test case
|
||||||
|
|
||||||
|
const formattedName = fileName.replace(/-/g, " ").replace(/\b\w/g, char => char.toUpperCase());
|
||||||
|
// Determine the directory based on the type
|
||||||
|
const dir = getTestFolderPath(type.dir);
|
||||||
|
const description = `${type.label} - ${formattedName}`;
|
||||||
|
|
||||||
|
// Define the content template
|
||||||
|
const content = fs.readFileSync(boilerplateFilePath, "utf8").replace("{{description}}", description);
|
||||||
|
|
||||||
|
// Ensure the directory exists
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the file with the given name
|
||||||
|
const filePath = path.join(dir, `${fileName}.test.ts`);
|
||||||
|
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
console.error(chalk.red.bold(`\n✗ File "${fileName}.test.ts" already exists!\n`));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the template content to the file
|
||||||
|
fs.writeFileSync(filePath, content, "utf8");
|
||||||
|
|
||||||
|
console.log(chalk.green.bold(`\n✔ File created at: test/${type.dir}/${fileName}.test.ts\n`));
|
||||||
|
console.groupEnd();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(chalk.red("✗ Error: ", err.message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
//#region Run
|
||||||
|
|
||||||
|
runInteractive();
|
||||||
|
|
||||||
|
//#endregion
|
43
scripts/create-test/test-boilerplate.ts
Normal file
43
scripts/create-test/test-boilerplate.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { AbilityId } from "#enums/ability-id";
|
||||||
|
import { MoveId } from "#enums/move-id";
|
||||||
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
import GameManager from "#test/testUtils/gameManager";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
describe("{{description}}", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
game.override
|
||||||
|
.ability(AbilityId.BALL_FETCH)
|
||||||
|
.battleStyle("single")
|
||||||
|
.disableCrits()
|
||||||
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
|
.enemyMoveset(MoveId.SPLASH)
|
||||||
|
.startingLevel(100)
|
||||||
|
.enemyLevel(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should do XYZ", async () => {
|
||||||
|
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||||
|
|
||||||
|
game.move.use(MoveId.SPLASH);
|
||||||
|
await game.toEndOfTurn();
|
||||||
|
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
@ -1,6 +1,7 @@
|
|||||||
/**
|
export interface DexData {
|
||||||
* Dex entry for a single Pokemon Species
|
[key: number]: DexEntry;
|
||||||
*/
|
}
|
||||||
|
|
||||||
export interface DexEntry {
|
export interface DexEntry {
|
||||||
seenAttr: bigint;
|
seenAttr: bigint;
|
||||||
caughtAttr: bigint;
|
caughtAttr: bigint;
|
||||||
@ -10,7 +11,3 @@ export interface DexEntry {
|
|||||||
hatchedCount: number;
|
hatchedCount: number;
|
||||||
ivs: number[];
|
ivs: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DexData {
|
|
||||||
[key: number]: DexEntry;
|
|
||||||
}
|
|
@ -2,9 +2,6 @@ export interface Localizable {
|
|||||||
localize(): void;
|
localize(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TranslationEntries {
|
|
||||||
[key: string]: string | { [key: string]: string };
|
|
||||||
}
|
|
||||||
export interface SimpleTranslationEntries {
|
export interface SimpleTranslationEntries {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
}
|
}
|
56
src/@types/move-types.ts
Normal file
56
src/@types/move-types.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import type {
|
||||||
|
AttackMove,
|
||||||
|
StatusMove,
|
||||||
|
SelfStatusMove,
|
||||||
|
ChargingAttackMove,
|
||||||
|
ChargingSelfStatusMove,
|
||||||
|
MoveAttrConstructorMap,
|
||||||
|
MoveAttr,
|
||||||
|
} from "#app/data/moves/move";
|
||||||
|
|
||||||
|
export type MoveAttrFilter = (attr: MoveAttr) => boolean;
|
||||||
|
|
||||||
|
export type * from "#app/data/moves/move";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of move subclass names to their respective classes.
|
||||||
|
* Does not include the ChargeMove subclasses. For that, use `ChargingMoveClassMap`.
|
||||||
|
*
|
||||||
|
* @privateremarks
|
||||||
|
* The `never` field (`declare private _: never`) in some classes is necessary
|
||||||
|
* to ensure typescript does not improperly narrow a failed `is` guard to `never`.
|
||||||
|
*
|
||||||
|
* For example, if we did not have the never, and wrote
|
||||||
|
* ```
|
||||||
|
* function Foo(move: Move) {
|
||||||
|
* if (move.is("AttackMove")) {
|
||||||
|
*
|
||||||
|
* } else if (move.is("StatusMove")) { // typescript errors on the `is`, saying that `move` is `never`
|
||||||
|
*
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export type MoveClassMap = {
|
||||||
|
AttackMove: AttackMove;
|
||||||
|
StatusMove: StatusMove;
|
||||||
|
SelfStatusMove: SelfStatusMove;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Union type of all move subclass names
|
||||||
|
*/
|
||||||
|
export type MoveKindString = "AttackMove" | "StatusMove" | "SelfStatusMove";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of move attribute names to attribute instances.
|
||||||
|
*/
|
||||||
|
export type MoveAttrMap = {
|
||||||
|
[K in keyof MoveAttrConstructorMap]: InstanceType<MoveAttrConstructorMap[K]>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Union type of all move attribute names as strings.
|
||||||
|
*/
|
||||||
|
export type MoveAttrString = keyof MoveAttrMap;
|
||||||
|
|
||||||
|
export type ChargingMove = ChargingAttackMove | ChargingSelfStatusMove;
|
25
src/@types/phase-types.ts
Normal file
25
src/@types/phase-types.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import type { PhaseConstructorMap } from "#app/phase-manager";
|
||||||
|
|
||||||
|
// Intentionally export the types of everything in phase-manager, as this file is meant to be
|
||||||
|
// the centralized place for type definitions for the phase system.
|
||||||
|
export type * from "#app/phase-manager";
|
||||||
|
|
||||||
|
// This file includes helpful types for the phase system.
|
||||||
|
// It intentionally imports the phase constructor map from the phase manager (and re-exports it)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of phase names to constructors for said phase
|
||||||
|
*/
|
||||||
|
export type PhaseMap = {
|
||||||
|
[K in keyof PhaseConstructorMap]: InstanceType<PhaseConstructorMap[K]>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Union type of all phase constructors.
|
||||||
|
*/
|
||||||
|
export type PhaseClass = PhaseConstructorMap[keyof PhaseConstructorMap];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Union type of all phase names as strings.
|
||||||
|
*/
|
||||||
|
export type PhaseString = keyof PhaseMap;
|
@ -1,9 +1,9 @@
|
|||||||
import type { EnemyPokemon } from "#app/field/pokemon";
|
import type { EnemyPokemon } from "#app/field/pokemon";
|
||||||
import type { PersistentModifier } from "#app/modifier/modifier";
|
import type { PersistentModifier } from "#app/modifier/modifier";
|
||||||
import type { PartyMemberStrength } from "#enums/party-member-strength";
|
import type { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import type { Species } from "#enums/species";
|
import type { SpeciesId } from "#enums/species-id";
|
||||||
import type { TrainerConfig } from "./trainer-config";
|
import type { TrainerConfig } from "../data/trainers/trainer-config";
|
||||||
import type { TrainerPartyTemplate } from "./TrainerPartyTemplate";
|
import type { TrainerPartyTemplate } from "../data/trainers/TrainerPartyTemplate";
|
||||||
|
|
||||||
export type PartyTemplateFunc = () => TrainerPartyTemplate;
|
export type PartyTemplateFunc = () => TrainerPartyTemplate;
|
||||||
export type PartyMemberFunc = (level: number, strength: PartyMemberStrength) => EnemyPokemon;
|
export type PartyMemberFunc = (level: number, strength: PartyMemberStrength) => EnemyPokemon;
|
||||||
@ -11,7 +11,7 @@ export type GenModifiersFunc = (party: EnemyPokemon[]) => PersistentModifier[];
|
|||||||
export type GenAIFunc = (party: EnemyPokemon[]) => void;
|
export type GenAIFunc = (party: EnemyPokemon[]) => void;
|
||||||
|
|
||||||
export interface TrainerTierPools {
|
export interface TrainerTierPools {
|
||||||
[key: number]: Species[];
|
[key: number]: SpeciesId[];
|
||||||
}
|
}
|
||||||
export interface TrainerConfigs {
|
export interface TrainerConfigs {
|
||||||
[key: number]: TrainerConfig;
|
[key: number]: TrainerConfig;
|
@ -80,13 +80,15 @@ import type { FixedBattleConfig } from "#app/battle";
|
|||||||
import Battle from "#app/battle";
|
import Battle from "#app/battle";
|
||||||
import { BattleType } from "#enums/battle-type";
|
import { BattleType } from "#enums/battle-type";
|
||||||
import type { GameMode } from "#app/game-mode";
|
import type { GameMode } from "#app/game-mode";
|
||||||
import { GameModes, getGameMode } from "#app/game-mode";
|
import { getGameMode } from "#app/game-mode";
|
||||||
|
import { GameModes } from "#enums/game-modes";
|
||||||
import FieldSpritePipeline from "#app/pipelines/field-sprite";
|
import FieldSpritePipeline from "#app/pipelines/field-sprite";
|
||||||
import SpritePipeline from "#app/pipelines/sprite";
|
import SpritePipeline from "#app/pipelines/sprite";
|
||||||
import PartyExpBar from "#app/ui/party-exp-bar";
|
import PartyExpBar from "#app/ui/party-exp-bar";
|
||||||
import type { TrainerSlot } from "./enums/trainer-slot";
|
import type { TrainerSlot } from "./enums/trainer-slot";
|
||||||
import { trainerConfigs } from "#app/data/trainers/trainer-config";
|
import { trainerConfigs } from "#app/data/trainers/trainer-config";
|
||||||
import Trainer, { TrainerVariant } from "#app/field/trainer";
|
import Trainer from "#app/field/trainer";
|
||||||
|
import { TrainerVariant } from "#enums/trainer-variant";
|
||||||
import type TrainerData from "#app/system/trainer-data";
|
import type TrainerData from "#app/system/trainer-data";
|
||||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||||
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
||||||
@ -101,14 +103,12 @@ import type UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin";
|
|||||||
import { addUiThemeOverrides } from "#app/ui/ui-theme";
|
import { addUiThemeOverrides } from "#app/ui/ui-theme";
|
||||||
import type PokemonData from "#app/system/pokemon-data";
|
import type PokemonData from "#app/system/pokemon-data";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import type { SpeciesFormChange, SpeciesFormChangeTrigger } from "#app/data/pokemon-forms";
|
import type { SpeciesFormChange } from "#app/data/pokemon-forms";
|
||||||
import {
|
import type { SpeciesFormChangeTrigger } from "./data/pokemon-forms/form-change-triggers";
|
||||||
FormChangeItem,
|
import { pokemonFormChanges } from "#app/data/pokemon-forms";
|
||||||
pokemonFormChanges,
|
import { SpeciesFormChangeTimeOfDayTrigger } from "./data/pokemon-forms/form-change-triggers";
|
||||||
SpeciesFormChangeManualTrigger,
|
import { SpeciesFormChangeManualTrigger } from "./data/pokemon-forms/form-change-triggers";
|
||||||
SpeciesFormChangeTimeOfDayTrigger,
|
import { FormChangeItem } from "#enums/form-change-item";
|
||||||
} from "#app/data/pokemon-forms";
|
|
||||||
import { FormChangePhase } from "#app/phases/form-change-phase";
|
|
||||||
import { getTypeRgb } from "#app/data/type";
|
import { getTypeRgb } from "#app/data/type";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import PokemonSpriteSparkleHandler from "#app/field/pokemon-sprite-sparkle-handler";
|
import PokemonSpriteSparkleHandler from "#app/field/pokemon-sprite-sparkle-handler";
|
||||||
@ -120,7 +120,7 @@ import { SceneBase } from "#app/scene-base";
|
|||||||
import CandyBar from "#app/ui/candy-bar";
|
import CandyBar from "#app/ui/candy-bar";
|
||||||
import type { Variant } from "#app/sprites/variant";
|
import type { Variant } from "#app/sprites/variant";
|
||||||
import { variantData, clearVariantData } from "#app/sprites/variant";
|
import { variantData, clearVariantData } from "#app/sprites/variant";
|
||||||
import type { Localizable } from "#app/interfaces/locales";
|
import type { Localizable } from "#app/@types/locales";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
import { InputsController } from "#app/inputs-controller";
|
import { InputsController } from "#app/inputs-controller";
|
||||||
import { UiInputs } from "#app/ui-inputs";
|
import { UiInputs } from "#app/ui-inputs";
|
||||||
@ -129,12 +129,12 @@ import { ArenaFlyout } from "#app/ui/arena-flyout";
|
|||||||
import { EaseType } from "#enums/ease-type";
|
import { EaseType } from "#enums/ease-type";
|
||||||
import { BattleSpec } from "#enums/battle-spec";
|
import { BattleSpec } from "#enums/battle-spec";
|
||||||
import { BattleStyle } from "#enums/battle-style";
|
import { BattleStyle } from "#enums/battle-style";
|
||||||
import { Biome } from "#enums/biome";
|
import { BiomeId } from "#enums/biome-id";
|
||||||
import type { ExpNotification } from "#enums/exp-notification";
|
import type { ExpNotification } from "#enums/exp-notification";
|
||||||
import { MoneyFormat } from "#enums/money-format";
|
import { MoneyFormat } from "#enums/money-format";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { PlayerGender } from "#enums/player-gender";
|
import { PlayerGender } from "#enums/player-gender";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { UiTheme } from "#enums/ui-theme";
|
import { UiTheme } from "#enums/ui-theme";
|
||||||
import { TimedEventManager } from "#app/timed-event-manager";
|
import { TimedEventManager } from "#app/timed-event-manager";
|
||||||
import type { PokemonAnimType } from "#enums/pokemon-anim-type";
|
import type { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||||
@ -142,21 +142,7 @@ import i18next from "i18next";
|
|||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { battleSpecDialogue } from "#app/data/dialogue";
|
import { battleSpecDialogue } from "#app/data/dialogue";
|
||||||
import { LoadingScene } from "#app/loading-scene";
|
import { LoadingScene } from "#app/loading-scene";
|
||||||
import { LevelCapPhase } from "#app/phases/level-cap-phase";
|
import type { MovePhase } from "#app/phases/move-phase";
|
||||||
import { LoginPhase } from "#app/phases/login-phase";
|
|
||||||
import { MessagePhase } from "#app/phases/message-phase";
|
|
||||||
import { MovePhase } from "#app/phases/move-phase";
|
|
||||||
import { NewBiomeEncounterPhase } from "#app/phases/new-biome-encounter-phase";
|
|
||||||
import { NextEncounterPhase } from "#app/phases/next-encounter-phase";
|
|
||||||
import { PokemonAnimPhase } from "#app/phases/pokemon-anim-phase";
|
|
||||||
import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase";
|
|
||||||
import { ReturnPhase } from "#app/phases/return-phase";
|
|
||||||
import { ShowTrainerPhase } from "#app/phases/show-trainer-phase";
|
|
||||||
import { SummonPhase } from "#app/phases/summon-phase";
|
|
||||||
import { SwitchPhase } from "#app/phases/switch-phase";
|
|
||||||
import { TitlePhase } from "#app/phases/title-phase";
|
|
||||||
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
|
|
||||||
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
|
||||||
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
||||||
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import {
|
import {
|
||||||
@ -170,22 +156,19 @@ import {
|
|||||||
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||||
import { ExpPhase } from "#app/phases/exp-phase";
|
|
||||||
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
|
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
import { ExpGainsSpeed } from "#enums/exp-gains-speed";
|
import { ExpGainsSpeed } from "#enums/exp-gains-speed";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters";
|
import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import { initGlobalScene } from "#app/global-scene";
|
import { initGlobalScene } from "#app/global-scene";
|
||||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
|
||||||
import { HideAbilityPhase } from "#app/phases/hide-ability-phase";
|
|
||||||
import { expSpriteKeys } from "./sprites/sprite-keys";
|
import { expSpriteKeys } from "./sprites/sprite-keys";
|
||||||
import { hasExpSprite } from "./sprites/sprite-utils";
|
import { hasExpSprite } from "./sprites/sprite-utils";
|
||||||
import { timedEventManager } from "./global-event-manager";
|
import { timedEventManager } from "./global-event-manager";
|
||||||
import { starterColors } from "./global-vars/starter-colors";
|
import { starterColors } from "./global-vars/starter-colors";
|
||||||
import { startingWave } from "./starting-wave";
|
import { startingWave } from "./starting-wave";
|
||||||
|
import { PhaseManager } from "./phase-manager";
|
||||||
|
|
||||||
const DEBUG_RNG = false;
|
const DEBUG_RNG = false;
|
||||||
|
|
||||||
@ -298,18 +281,8 @@ export default class BattleScene extends SceneBase {
|
|||||||
public gameData: GameData;
|
public gameData: GameData;
|
||||||
public sessionSlotId: number;
|
public sessionSlotId: number;
|
||||||
|
|
||||||
/** PhaseQueue: dequeue/remove the first element to get the next phase */
|
/** Manager for the phases active in the battle scene */
|
||||||
public phaseQueue: Phase[];
|
public readonly phaseManager: PhaseManager;
|
||||||
public conditionalQueue: Array<[() => boolean, Phase]>;
|
|
||||||
/** PhaseQueuePrepend: is a temp storage of what will be added to PhaseQueue */
|
|
||||||
private phaseQueuePrepend: Phase[];
|
|
||||||
|
|
||||||
/** overrides default of inserting phases to end of phaseQueuePrepend array, useful or inserting Phases "out of order" */
|
|
||||||
private phaseQueuePrependSpliceIndex: number;
|
|
||||||
private nextCommandPhaseQueue: Phase[];
|
|
||||||
|
|
||||||
private currentPhase: Phase | null;
|
|
||||||
private standbyPhase: Phase | null;
|
|
||||||
public field: Phaser.GameObjects.Container;
|
public field: Phaser.GameObjects.Container;
|
||||||
public fieldUI: Phaser.GameObjects.Container;
|
public fieldUI: Phaser.GameObjects.Container;
|
||||||
public charSprite: CharSprite;
|
public charSprite: CharSprite;
|
||||||
@ -397,11 +370,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super("battle");
|
super("battle");
|
||||||
this.phaseQueue = [];
|
this.phaseManager = new PhaseManager();
|
||||||
this.phaseQueuePrepend = [];
|
|
||||||
this.conditionalQueue = [];
|
|
||||||
this.phaseQueuePrependSpliceIndex = -1;
|
|
||||||
this.nextCommandPhaseQueue = [];
|
|
||||||
this.eventManager = new TimedEventManager();
|
this.eventManager = new TimedEventManager();
|
||||||
this.updateGameInfo();
|
this.updateGameInfo();
|
||||||
initGlobalScene(this);
|
initGlobalScene(this);
|
||||||
@ -707,20 +676,20 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
ui.setup();
|
ui.setup();
|
||||||
|
|
||||||
const defaultMoves = [Moves.TACKLE, Moves.TAIL_WHIP, Moves.FOCUS_ENERGY, Moves.STRUGGLE];
|
const defaultMoves = [MoveId.TACKLE, MoveId.TAIL_WHIP, MoveId.FOCUS_ENERGY, MoveId.STRUGGLE];
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
Promise.all(loadPokemonAssets),
|
Promise.all(loadPokemonAssets),
|
||||||
initCommonAnims().then(() => loadCommonAnimAssets(true)),
|
initCommonAnims().then(() => loadCommonAnimAssets(true)),
|
||||||
Promise.all([Moves.TACKLE, Moves.TAIL_WHIP, Moves.FOCUS_ENERGY, Moves.STRUGGLE].map(m => initMoveAnim(m))).then(
|
Promise.all(
|
||||||
() => loadMoveAnimAssets(defaultMoves, true),
|
[MoveId.TACKLE, MoveId.TAIL_WHIP, MoveId.FOCUS_ENERGY, MoveId.STRUGGLE].map(m => initMoveAnim(m)),
|
||||||
),
|
).then(() => loadMoveAnimAssets(defaultMoves, true)),
|
||||||
this.initStarterColors(),
|
this.initStarterColors(),
|
||||||
]).then(() => {
|
]).then(() => {
|
||||||
this.pushPhase(new LoginPhase());
|
this.phaseManager.pushNew("LoginPhase");
|
||||||
this.pushPhase(new TitlePhase());
|
this.phaseManager.pushNew("TitlePhase");
|
||||||
|
|
||||||
this.shiftPhase();
|
this.phaseManager.shiftPhase();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -812,6 +781,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add a `getPartyOnSide` function for getting the party of a pokemon
|
||||||
public getPlayerParty(): PlayerPokemon[] {
|
public getPlayerParty(): PlayerPokemon[] {
|
||||||
return this.party;
|
return this.party;
|
||||||
}
|
}
|
||||||
@ -899,9 +869,9 @@ export default class BattleScene extends SceneBase {
|
|||||||
if (allyPokemon?.isActive(true)) {
|
if (allyPokemon?.isActive(true)) {
|
||||||
let targetingMovePhase: MovePhase;
|
let targetingMovePhase: MovePhase;
|
||||||
do {
|
do {
|
||||||
targetingMovePhase = this.findPhase(
|
targetingMovePhase = this.phaseManager.findPhase(
|
||||||
mp =>
|
mp =>
|
||||||
mp instanceof MovePhase &&
|
mp.is("MovePhase") &&
|
||||||
mp.targets.length === 1 &&
|
mp.targets.length === 1 &&
|
||||||
mp.targets[0] === removedPokemon.getBattlerIndex() &&
|
mp.targets[0] === removedPokemon.getBattlerIndex() &&
|
||||||
mp.pokemon.isPlayer() !== allyPokemon.isPlayer(),
|
mp.pokemon.isPlayer() !== allyPokemon.isPlayer(),
|
||||||
@ -1225,7 +1195,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
[this.luckLabelText, this.luckText].map(t => t.setVisible(false));
|
[this.luckLabelText, this.luckText].map(t => t.setVisible(false));
|
||||||
|
|
||||||
this.newArena(Overrides.STARTING_BIOME_OVERRIDE || Biome.TOWN);
|
this.newArena(Overrides.STARTING_BIOME_OVERRIDE || BiomeId.TOWN);
|
||||||
|
|
||||||
this.field.setVisible(true);
|
this.field.setVisible(true);
|
||||||
|
|
||||||
@ -1277,7 +1247,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
duration: 250,
|
duration: 250,
|
||||||
ease: "Sine.easeInOut",
|
ease: "Sine.easeInOut",
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
this.clearPhaseQueue();
|
this.phaseManager.clearPhaseQueue();
|
||||||
|
|
||||||
this.ui.freeUIData();
|
this.ui.freeUIData();
|
||||||
this.uiContainer.remove(this.ui, true);
|
this.uiContainer.remove(this.ui, true);
|
||||||
@ -1450,7 +1420,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lastBattle?.double && !newDouble) {
|
if (lastBattle?.double && !newDouble) {
|
||||||
this.tryRemovePhase(p => p instanceof SwitchPhase);
|
this.phaseManager.tryRemovePhase((p: Phase) => p.is("SwitchPhase"));
|
||||||
for (const p of this.getPlayerField()) {
|
for (const p of this.getPlayerField()) {
|
||||||
p.lapseTag(BattlerTagType.COMMANDED);
|
p.lapseTag(BattlerTagType.COMMANDED);
|
||||||
}
|
}
|
||||||
@ -1492,7 +1462,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
playerField.forEach((pokemon, p) => {
|
playerField.forEach((pokemon, p) => {
|
||||||
if (pokemon.isOnField()) {
|
if (pokemon.isOnField()) {
|
||||||
this.pushPhase(new ReturnPhase(p));
|
this.phaseManager.pushNew("ReturnPhase", p);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1501,7 +1471,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
pokemon.resetTera();
|
pokemon.resetTera();
|
||||||
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon);
|
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon);
|
||||||
if (
|
if (
|
||||||
pokemon.hasSpecies(Species.TERAPAGOS) ||
|
pokemon.hasSpecies(SpeciesId.TERAPAGOS) ||
|
||||||
(this.gameMode.isClassic && this.currentBattle.waveIndex > 180 && this.currentBattle.waveIndex <= 190)
|
(this.gameMode.isClassic && this.currentBattle.waveIndex > 180 && this.currentBattle.waveIndex <= 190)
|
||||||
) {
|
) {
|
||||||
this.arena.playerTerasUsed = 0;
|
this.arena.playerTerasUsed = 0;
|
||||||
@ -1509,7 +1479,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.trainer.visible) {
|
if (!this.trainer.visible) {
|
||||||
this.pushPhase(new ShowTrainerPhase());
|
this.phaseManager.pushNew("ShowTrainerPhase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1518,13 +1488,13 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.gameMode.hasRandomBiomes && !isNewBiome) {
|
if (!this.gameMode.hasRandomBiomes && !isNewBiome) {
|
||||||
this.pushPhase(new NextEncounterPhase());
|
this.phaseManager.pushNew("NextEncounterPhase");
|
||||||
} else {
|
} else {
|
||||||
this.pushPhase(new NewBiomeEncounterPhase());
|
this.phaseManager.pushNew("NewBiomeEncounterPhase");
|
||||||
|
|
||||||
const newMaxExpLevel = this.getMaxExpLevel();
|
const newMaxExpLevel = this.getMaxExpLevel();
|
||||||
if (newMaxExpLevel > maxExpLevel) {
|
if (newMaxExpLevel > maxExpLevel) {
|
||||||
this.pushPhase(new LevelCapPhase());
|
this.phaseManager.pushNew("LevelCapPhase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1532,8 +1502,8 @@ export default class BattleScene extends SceneBase {
|
|||||||
return this.currentBattle;
|
return this.currentBattle;
|
||||||
}
|
}
|
||||||
|
|
||||||
newArena(biome: Biome, playerFaints?: number): Arena {
|
newArena(biome: BiomeId, playerFaints?: number): Arena {
|
||||||
this.arena = new Arena(biome, Biome[biome].toLowerCase(), playerFaints);
|
this.arena = new Arena(biome, BiomeId[biome].toLowerCase(), playerFaints);
|
||||||
this.eventTarget.dispatchEvent(new NewArenaEvent());
|
this.eventTarget.dispatchEvent(new NewArenaEvent());
|
||||||
|
|
||||||
this.arenaBg.pipelineData = {
|
this.arenaBg.pipelineData = {
|
||||||
@ -1589,7 +1559,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isEggPhase: boolean = ["EggLapsePhase", "EggHatchPhase"].includes(
|
const isEggPhase: boolean = ["EggLapsePhase", "EggHatchPhase"].includes(
|
||||||
this.getCurrentPhase()?.constructor.name ?? "",
|
this.phaseManager.getCurrentPhase()?.phaseName ?? "",
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -1599,7 +1569,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
!isNullOrUndefined(this.currentBattle.trainer) &&
|
!isNullOrUndefined(this.currentBattle.trainer) &&
|
||||||
this.currentBattle.trainer.config.hasSpecialtyType()
|
this.currentBattle.trainer.config.hasSpecialtyType()
|
||||||
) {
|
) {
|
||||||
if (species.speciesId === Species.WORMADAM) {
|
if (species.speciesId === SpeciesId.WORMADAM) {
|
||||||
switch (this.currentBattle.trainer.config.specialtyType) {
|
switch (this.currentBattle.trainer.config.specialtyType) {
|
||||||
case PokemonType.GROUND:
|
case PokemonType.GROUND:
|
||||||
return 1; // Sandy Cloak
|
return 1; // Sandy Cloak
|
||||||
@ -1609,7 +1579,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
return 0; // Plant Cloak
|
return 0; // Plant Cloak
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (species.speciesId === Species.ROTOM) {
|
if (species.speciesId === SpeciesId.ROTOM) {
|
||||||
switch (this.currentBattle.trainer.config.specialtyType) {
|
switch (this.currentBattle.trainer.config.specialtyType) {
|
||||||
case PokemonType.FLYING:
|
case PokemonType.FLYING:
|
||||||
return 4; // Fan Rotom
|
return 4; // Fan Rotom
|
||||||
@ -1625,7 +1595,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
return 3; // Frost Rotom
|
return 3; // Frost Rotom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (species.speciesId === Species.ORICORIO) {
|
if (species.speciesId === SpeciesId.ORICORIO) {
|
||||||
switch (this.currentBattle.trainer.config.specialtyType) {
|
switch (this.currentBattle.trainer.config.specialtyType) {
|
||||||
case PokemonType.GHOST:
|
case PokemonType.GHOST:
|
||||||
return 3; // Sensu Style
|
return 3; // Sensu Style
|
||||||
@ -1637,7 +1607,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
return 2; // Pa'u Style
|
return 2; // Pa'u Style
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (species.speciesId === Species.PALDEA_TAUROS) {
|
if (species.speciesId === SpeciesId.PALDEA_TAUROS) {
|
||||||
switch (this.currentBattle.trainer.config.specialtyType) {
|
switch (this.currentBattle.trainer.config.specialtyType) {
|
||||||
case PokemonType.FIRE:
|
case PokemonType.FIRE:
|
||||||
return 1; // Blaze Breed
|
return 1; // Blaze Breed
|
||||||
@ -1645,41 +1615,41 @@ export default class BattleScene extends SceneBase {
|
|||||||
return 2; // Aqua Breed
|
return 2; // Aqua Breed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (species.speciesId === Species.SILVALLY || species.speciesId === Species.ARCEUS) {
|
if (species.speciesId === SpeciesId.SILVALLY || species.speciesId === SpeciesId.ARCEUS) {
|
||||||
// Would probably never happen, but might as well
|
// Would probably never happen, but might as well
|
||||||
return this.currentBattle.trainer.config.specialtyType;
|
return this.currentBattle.trainer.config.specialtyType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (species.speciesId) {
|
switch (species.speciesId) {
|
||||||
case Species.UNOWN:
|
case SpeciesId.UNOWN:
|
||||||
case Species.SHELLOS:
|
case SpeciesId.SHELLOS:
|
||||||
case Species.GASTRODON:
|
case SpeciesId.GASTRODON:
|
||||||
case Species.BASCULIN:
|
case SpeciesId.BASCULIN:
|
||||||
case Species.DEERLING:
|
case SpeciesId.DEERLING:
|
||||||
case Species.SAWSBUCK:
|
case SpeciesId.SAWSBUCK:
|
||||||
case Species.SCATTERBUG:
|
case SpeciesId.SCATTERBUG:
|
||||||
case Species.SPEWPA:
|
case SpeciesId.SPEWPA:
|
||||||
case Species.VIVILLON:
|
case SpeciesId.VIVILLON:
|
||||||
case Species.FLABEBE:
|
case SpeciesId.FLABEBE:
|
||||||
case Species.FLOETTE:
|
case SpeciesId.FLOETTE:
|
||||||
case Species.FLORGES:
|
case SpeciesId.FLORGES:
|
||||||
case Species.FURFROU:
|
case SpeciesId.FURFROU:
|
||||||
case Species.PUMPKABOO:
|
case SpeciesId.PUMPKABOO:
|
||||||
case Species.GOURGEIST:
|
case SpeciesId.GOURGEIST:
|
||||||
case Species.ORICORIO:
|
case SpeciesId.ORICORIO:
|
||||||
case Species.MAGEARNA:
|
case SpeciesId.MAGEARNA:
|
||||||
case Species.ZARUDE:
|
case SpeciesId.ZARUDE:
|
||||||
case Species.SQUAWKABILLY:
|
case SpeciesId.SQUAWKABILLY:
|
||||||
case Species.TATSUGIRI:
|
case SpeciesId.TATSUGIRI:
|
||||||
case Species.PALDEA_TAUROS:
|
case SpeciesId.PALDEA_TAUROS:
|
||||||
return randSeedInt(species.forms.length);
|
return randSeedInt(species.forms.length);
|
||||||
case Species.PIKACHU:
|
case SpeciesId.PIKACHU:
|
||||||
if (this.currentBattle?.battleType === BattleType.TRAINER && this.currentBattle?.waveIndex < 30) {
|
if (this.currentBattle?.battleType === BattleType.TRAINER && this.currentBattle?.waveIndex < 30) {
|
||||||
return 0; // Ban Cosplay and Partner Pika from Trainers before wave 30
|
return 0; // Ban Cosplay and Partner Pika from Trainers before wave 30
|
||||||
}
|
}
|
||||||
return randSeedInt(8);
|
return randSeedInt(8);
|
||||||
case Species.EEVEE:
|
case SpeciesId.EEVEE:
|
||||||
if (
|
if (
|
||||||
this.currentBattle?.battleType === BattleType.TRAINER &&
|
this.currentBattle?.battleType === BattleType.TRAINER &&
|
||||||
this.currentBattle?.waveIndex < 30 &&
|
this.currentBattle?.waveIndex < 30 &&
|
||||||
@ -1688,27 +1658,27 @@ export default class BattleScene extends SceneBase {
|
|||||||
return 0; // No Partner Eevee for Wave 12 Preschoolers
|
return 0; // No Partner Eevee for Wave 12 Preschoolers
|
||||||
}
|
}
|
||||||
return randSeedInt(2);
|
return randSeedInt(2);
|
||||||
case Species.FROAKIE:
|
case SpeciesId.FROAKIE:
|
||||||
case Species.FROGADIER:
|
case SpeciesId.FROGADIER:
|
||||||
case Species.GRENINJA:
|
case SpeciesId.GRENINJA:
|
||||||
if (this.currentBattle?.battleType === BattleType.TRAINER && !isEggPhase) {
|
if (this.currentBattle?.battleType === BattleType.TRAINER && !isEggPhase) {
|
||||||
return 0; // Don't give trainers Battle Bond Greninja, Froakie or Frogadier
|
return 0; // Don't give trainers Battle Bond Greninja, Froakie or Frogadier
|
||||||
}
|
}
|
||||||
return randSeedInt(2);
|
return randSeedInt(2);
|
||||||
case Species.URSHIFU:
|
case SpeciesId.URSHIFU:
|
||||||
return randSeedInt(2);
|
return randSeedInt(2);
|
||||||
case Species.ZYGARDE:
|
case SpeciesId.ZYGARDE:
|
||||||
return randSeedInt(4);
|
return randSeedInt(4);
|
||||||
case Species.MINIOR:
|
case SpeciesId.MINIOR:
|
||||||
return randSeedInt(7);
|
return randSeedInt(7);
|
||||||
case Species.ALCREMIE:
|
case SpeciesId.ALCREMIE:
|
||||||
return randSeedInt(9);
|
return randSeedInt(9);
|
||||||
case Species.MEOWSTIC:
|
case SpeciesId.MEOWSTIC:
|
||||||
case Species.INDEEDEE:
|
case SpeciesId.INDEEDEE:
|
||||||
case Species.BASCULEGION:
|
case SpeciesId.BASCULEGION:
|
||||||
case Species.OINKOLOGNE:
|
case SpeciesId.OINKOLOGNE:
|
||||||
return gender === Gender.FEMALE ? 1 : 0;
|
return gender === Gender.FEMALE ? 1 : 0;
|
||||||
case Species.TOXTRICITY: {
|
case SpeciesId.TOXTRICITY: {
|
||||||
const lowkeyNatures = [
|
const lowkeyNatures = [
|
||||||
Nature.LONELY,
|
Nature.LONELY,
|
||||||
Nature.BOLD,
|
Nature.BOLD,
|
||||||
@ -1728,7 +1698,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case Species.GIMMIGHOUL:
|
case SpeciesId.GIMMIGHOUL:
|
||||||
// Chest form can only be found in Mysterious Chest Encounter, if this is a game mode with MEs
|
// Chest form can only be found in Mysterious Chest Encounter, if this is a game mode with MEs
|
||||||
if (this.gameMode.hasMysteryEncounters && !isEggPhase) {
|
if (this.gameMode.hasMysteryEncounters && !isEggPhase) {
|
||||||
return 1; // Wandering form
|
return 1; // Wandering form
|
||||||
@ -1738,10 +1708,10 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
if (ignoreArena) {
|
if (ignoreArena) {
|
||||||
switch (species.speciesId) {
|
switch (species.speciesId) {
|
||||||
case Species.BURMY:
|
case SpeciesId.BURMY:
|
||||||
case Species.WORMADAM:
|
case SpeciesId.WORMADAM:
|
||||||
case Species.ROTOM:
|
case SpeciesId.ROTOM:
|
||||||
case Species.LYCANROC:
|
case SpeciesId.LYCANROC:
|
||||||
return randSeedInt(species.forms.length);
|
return randSeedInt(species.forms.length);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -2172,10 +2142,10 @@ export default class BattleScene extends SceneBase {
|
|||||||
return filteredSpecies[randSeedInt(filteredSpecies.length)];
|
return filteredSpecies[randSeedInt(filteredSpecies.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
generateRandomBiome(waveIndex: number): Biome {
|
generateRandomBiome(waveIndex: number): BiomeId {
|
||||||
const relWave = waveIndex % 250;
|
const relWave = waveIndex % 250;
|
||||||
const biomes = getEnumValues(Biome).filter(b => b !== Biome.TOWN && b !== Biome.END);
|
const biomes = getEnumValues(BiomeId).filter(b => b !== BiomeId.TOWN && b !== BiomeId.END);
|
||||||
const maxDepth = biomeDepths[Biome.END][0] - 2;
|
const maxDepth = biomeDepths[BiomeId.END][0] - 2;
|
||||||
const depthWeights = new Array(maxDepth + 1)
|
const depthWeights = new Array(maxDepth + 1)
|
||||||
.fill(null)
|
.fill(null)
|
||||||
.map((_, i: number) => ((1 - Math.min(Math.abs(i / (maxDepth - 1) - relWave / 250) + 0.25, 1)) / 0.75) * 250);
|
.map((_, i: number) => ((1 - Math.min(Math.abs(i / (maxDepth - 1) - relWave / 250) + 0.25, 1)) / 0.75) * 250);
|
||||||
@ -2617,286 +2587,6 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Phase Functions */
|
|
||||||
getCurrentPhase(): Phase | null {
|
|
||||||
return this.currentPhase;
|
|
||||||
}
|
|
||||||
|
|
||||||
getStandbyPhase(): Phase | null {
|
|
||||||
return this.standbyPhase;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a phase to the conditional queue and ensures it is executed only when the specified condition is met.
|
|
||||||
*
|
|
||||||
* This method allows deferring the execution of a phase until certain conditions are met, which is useful for handling
|
|
||||||
* situations like abilities and entry hazards that depend on specific game states.
|
|
||||||
*
|
|
||||||
* @param {Phase} phase - The phase to be added to the conditional queue.
|
|
||||||
* @param {() => boolean} condition - A function that returns a boolean indicating whether the phase should be executed.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
pushConditionalPhase(phase: Phase, condition: () => boolean): void {
|
|
||||||
this.conditionalQueue.push([condition, phase]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a phase to nextCommandPhaseQueue, as long as boolean passed in is false
|
|
||||||
* @param phase {@linkcode Phase} the phase to add
|
|
||||||
* @param defer boolean on which queue to add to, defaults to false, and adds to phaseQueue
|
|
||||||
*/
|
|
||||||
pushPhase(phase: Phase, defer = false): void {
|
|
||||||
(!defer ? this.phaseQueue : this.nextCommandPhaseQueue).push(phase);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds Phase(s) to the end of phaseQueuePrepend, or at phaseQueuePrependSpliceIndex
|
|
||||||
* @param phases {@linkcode Phase} the phase(s) to add
|
|
||||||
*/
|
|
||||||
unshiftPhase(...phases: Phase[]): void {
|
|
||||||
if (this.phaseQueuePrependSpliceIndex === -1) {
|
|
||||||
this.phaseQueuePrepend.push(...phases);
|
|
||||||
} else {
|
|
||||||
this.phaseQueuePrepend.splice(this.phaseQueuePrependSpliceIndex, 0, ...phases);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the phaseQueue
|
|
||||||
*/
|
|
||||||
clearPhaseQueue(): void {
|
|
||||||
this.phaseQueue.splice(0, this.phaseQueue.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears all phase-related stuff, including all phase queues, the current and standby phases, and a splice index
|
|
||||||
*/
|
|
||||||
clearAllPhases(): void {
|
|
||||||
for (const queue of [this.phaseQueue, this.phaseQueuePrepend, this.conditionalQueue, this.nextCommandPhaseQueue]) {
|
|
||||||
queue.splice(0, queue.length);
|
|
||||||
}
|
|
||||||
this.currentPhase = null;
|
|
||||||
this.standbyPhase = null;
|
|
||||||
this.clearPhaseQueueSplice();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by function unshiftPhase(), sets index to start inserting at current length instead of the end of the array, useful if phaseQueuePrepend gets longer with Phases
|
|
||||||
*/
|
|
||||||
setPhaseQueueSplice(): void {
|
|
||||||
this.phaseQueuePrependSpliceIndex = this.phaseQueuePrepend.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets phaseQueuePrependSpliceIndex to -1, implies that calls to unshiftPhase will insert at end of phaseQueuePrepend
|
|
||||||
*/
|
|
||||||
clearPhaseQueueSplice(): void {
|
|
||||||
this.phaseQueuePrependSpliceIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is called by each Phase implementations "end()" by default
|
|
||||||
* We dump everything from phaseQueuePrepend to the start of of phaseQueue
|
|
||||||
* then removes first Phase and starts it
|
|
||||||
*/
|
|
||||||
shiftPhase(): void {
|
|
||||||
if (this.standbyPhase) {
|
|
||||||
this.currentPhase = this.standbyPhase;
|
|
||||||
this.standbyPhase = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.phaseQueuePrependSpliceIndex > -1) {
|
|
||||||
this.clearPhaseQueueSplice();
|
|
||||||
}
|
|
||||||
if (this.phaseQueuePrepend.length) {
|
|
||||||
while (this.phaseQueuePrepend.length) {
|
|
||||||
const poppedPhase = this.phaseQueuePrepend.pop();
|
|
||||||
if (poppedPhase) {
|
|
||||||
this.phaseQueue.unshift(poppedPhase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!this.phaseQueue.length) {
|
|
||||||
this.populatePhaseQueue();
|
|
||||||
// Clear the conditionalQueue if there are no phases left in the phaseQueue
|
|
||||||
this.conditionalQueue = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currentPhase = this.phaseQueue.shift() ?? null;
|
|
||||||
|
|
||||||
// Check if there are any conditional phases queued
|
|
||||||
if (this.conditionalQueue?.length) {
|
|
||||||
// Retrieve the first conditional phase from the queue
|
|
||||||
const conditionalPhase = this.conditionalQueue.shift();
|
|
||||||
// Evaluate the condition associated with the phase
|
|
||||||
if (conditionalPhase?.[0]()) {
|
|
||||||
// If the condition is met, add the phase to the phase queue
|
|
||||||
this.pushPhase(conditionalPhase[1]);
|
|
||||||
} else if (conditionalPhase) {
|
|
||||||
// If the condition is not met, re-add the phase back to the front of the conditional queue
|
|
||||||
this.conditionalQueue.unshift(conditionalPhase);
|
|
||||||
} else {
|
|
||||||
console.warn("condition phase is undefined/null!", conditionalPhase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.currentPhase) {
|
|
||||||
console.log(`%cStart Phase ${this.currentPhase.constructor.name}`, "color:green;");
|
|
||||||
this.currentPhase.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
overridePhase(phase: Phase): boolean {
|
|
||||||
if (this.standbyPhase) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.standbyPhase = this.currentPhase;
|
|
||||||
this.currentPhase = phase;
|
|
||||||
console.log(`%cStart Phase ${phase.constructor.name}`, "color:green;");
|
|
||||||
phase.start();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a specific {@linkcode Phase} in the phase queue.
|
|
||||||
*
|
|
||||||
* @param phaseFilter filter function to use to find the wanted phase
|
|
||||||
* @returns the found phase or undefined if none found
|
|
||||||
*/
|
|
||||||
findPhase<P extends Phase = Phase>(phaseFilter: (phase: P) => boolean): P | undefined {
|
|
||||||
return this.phaseQueue.find(phaseFilter) as P;
|
|
||||||
}
|
|
||||||
|
|
||||||
tryReplacePhase(phaseFilter: (phase: Phase) => boolean, phase: Phase): boolean {
|
|
||||||
const phaseIndex = this.phaseQueue.findIndex(phaseFilter);
|
|
||||||
if (phaseIndex > -1) {
|
|
||||||
this.phaseQueue[phaseIndex] = phase;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tryRemovePhase(phaseFilter: (phase: Phase) => boolean): boolean {
|
|
||||||
const phaseIndex = this.phaseQueue.findIndex(phaseFilter);
|
|
||||||
if (phaseIndex > -1) {
|
|
||||||
this.phaseQueue.splice(phaseIndex, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Will search for a specific phase in {@linkcode phaseQueuePrepend} via filter, and remove the first result if a match is found.
|
|
||||||
* @param phaseFilter filter function
|
|
||||||
*/
|
|
||||||
tryRemoveUnshiftedPhase(phaseFilter: (phase: Phase) => boolean): boolean {
|
|
||||||
const phaseIndex = this.phaseQueuePrepend.findIndex(phaseFilter);
|
|
||||||
if (phaseIndex > -1) {
|
|
||||||
this.phaseQueuePrepend.splice(phaseIndex, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to add the input phase to index before target phase in the phaseQueue, else simply calls unshiftPhase()
|
|
||||||
* @param phase {@linkcode Phase} the phase to be added
|
|
||||||
* @param targetPhase {@linkcode Phase} the type of phase to search for in phaseQueue
|
|
||||||
* @returns boolean if a targetPhase was found and added
|
|
||||||
*/
|
|
||||||
prependToPhase(phase: Phase | Phase[], targetPhase: Constructor<Phase>): boolean {
|
|
||||||
if (!Array.isArray(phase)) {
|
|
||||||
phase = [phase];
|
|
||||||
}
|
|
||||||
const targetIndex = this.phaseQueue.findIndex(ph => ph instanceof targetPhase);
|
|
||||||
|
|
||||||
if (targetIndex !== -1) {
|
|
||||||
this.phaseQueue.splice(targetIndex, 0, ...phase);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
this.unshiftPhase(...phase);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to add the input phase(s) to index after target phase in the {@linkcode phaseQueue}, else simply calls {@linkcode unshiftPhase()}
|
|
||||||
* @param phase {@linkcode Phase} the phase(s) to be added
|
|
||||||
* @param targetPhase {@linkcode Phase} the type of phase to search for in {@linkcode phaseQueue}
|
|
||||||
* @returns `true` if a `targetPhase` was found to append to
|
|
||||||
*/
|
|
||||||
appendToPhase(phase: Phase | Phase[], targetPhase: Constructor<Phase>): boolean {
|
|
||||||
if (!Array.isArray(phase)) {
|
|
||||||
phase = [phase];
|
|
||||||
}
|
|
||||||
const targetIndex = this.phaseQueue.findIndex(ph => ph instanceof targetPhase);
|
|
||||||
|
|
||||||
if (targetIndex !== -1 && this.phaseQueue.length > targetIndex) {
|
|
||||||
this.phaseQueue.splice(targetIndex + 1, 0, ...phase);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
this.unshiftPhase(...phase);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a MessagePhase, either to PhaseQueuePrepend or nextCommandPhaseQueue
|
|
||||||
* @param message string for MessagePhase
|
|
||||||
* @param callbackDelay optional param for MessagePhase constructor
|
|
||||||
* @param prompt optional param for MessagePhase constructor
|
|
||||||
* @param promptDelay optional param for MessagePhase constructor
|
|
||||||
* @param defer boolean for which queue to add it to, false -> add to PhaseQueuePrepend, true -> nextCommandPhaseQueue
|
|
||||||
*/
|
|
||||||
queueMessage(
|
|
||||||
message: string,
|
|
||||||
callbackDelay?: number | null,
|
|
||||||
prompt?: boolean | null,
|
|
||||||
promptDelay?: number | null,
|
|
||||||
defer?: boolean | null,
|
|
||||||
) {
|
|
||||||
const phase = new MessagePhase(message, callbackDelay, prompt, promptDelay);
|
|
||||||
if (!defer) {
|
|
||||||
// adds to the end of PhaseQueuePrepend
|
|
||||||
this.unshiftPhase(phase);
|
|
||||||
} else {
|
|
||||||
//remember that pushPhase adds it to nextCommandPhaseQueue
|
|
||||||
this.pushPhase(phase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queues an ability bar flyout phase
|
|
||||||
* @param pokemon The pokemon who has the ability
|
|
||||||
* @param passive Whether the ability is a passive
|
|
||||||
* @param show Whether to show or hide the bar
|
|
||||||
*/
|
|
||||||
public queueAbilityDisplay(pokemon: Pokemon, passive: boolean, show: boolean): void {
|
|
||||||
this.unshiftPhase(show ? new ShowAbilityPhase(pokemon.getBattlerIndex(), passive) : new HideAbilityPhase());
|
|
||||||
this.clearPhaseQueueSplice();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hides the ability bar if it is currently visible
|
|
||||||
*/
|
|
||||||
public hideAbilityBar(): void {
|
|
||||||
if (this.abilityBar.isVisible()) {
|
|
||||||
this.unshiftPhase(new HideAbilityPhase());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves everything from nextCommandPhaseQueue to phaseQueue (keeping order)
|
|
||||||
*/
|
|
||||||
populatePhaseQueue(): void {
|
|
||||||
if (this.nextCommandPhaseQueue.length) {
|
|
||||||
this.phaseQueue.push(...this.nextCommandPhaseQueue);
|
|
||||||
this.nextCommandPhaseQueue.splice(0, this.nextCommandPhaseQueue.length);
|
|
||||||
}
|
|
||||||
this.phaseQueue.push(new TurnInitPhase());
|
|
||||||
}
|
|
||||||
|
|
||||||
addMoney(amount: number): void {
|
addMoney(amount: number): void {
|
||||||
this.money = Math.min(this.money + amount, Number.MAX_SAFE_INTEGER);
|
this.money = Math.min(this.money + amount, Number.MAX_SAFE_INTEGER);
|
||||||
this.updateMoneyText();
|
this.updateMoneyText();
|
||||||
@ -2944,7 +2634,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
} else if (!virtual) {
|
} else if (!virtual) {
|
||||||
const defaultModifierType = getDefaultModifierTypeForTier(modifier.type.tier);
|
const defaultModifierType = getDefaultModifierTypeForTier(modifier.type.tier);
|
||||||
this.queueMessage(
|
this.phaseManager.queueMessage(
|
||||||
i18next.t("battle:itemStackFull", {
|
i18next.t("battle:itemStackFull", {
|
||||||
fullItemName: modifier.type.name,
|
fullItemName: modifier.type.name,
|
||||||
itemName: defaultModifierType.name,
|
itemName: defaultModifierType.name,
|
||||||
@ -3089,9 +2779,9 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
const removeOld = itemModifier.stackCount === 0;
|
const removeOld = itemModifier.stackCount === 0;
|
||||||
|
|
||||||
if (!removeOld || !source || this.removeModifier(itemModifier, !source.isPlayer())) {
|
if (!removeOld || !source || this.removeModifier(itemModifier, source.isEnemy())) {
|
||||||
const addModifier = () => {
|
const addModifier = () => {
|
||||||
if (!matchingModifier || this.removeModifier(matchingModifier, !target.isPlayer())) {
|
if (!matchingModifier || this.removeModifier(matchingModifier, target.isEnemy())) {
|
||||||
if (target.isPlayer()) {
|
if (target.isPlayer()) {
|
||||||
this.addModifier(newItemModifier, ignoreUpdate, playSound, false, instant);
|
this.addModifier(newItemModifier, ignoreUpdate, playSound, false, instant);
|
||||||
if (source && itemLost) {
|
if (source && itemLost) {
|
||||||
@ -3475,7 +3165,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
fc => fc.findTrigger(formChangeTriggerType) && fc.canChange(pokemon),
|
fc => fc.findTrigger(formChangeTriggerType) && fc.canChange(pokemon),
|
||||||
);
|
);
|
||||||
let matchingFormChange: SpeciesFormChange | null;
|
let matchingFormChange: SpeciesFormChange | null;
|
||||||
if (pokemon.species.speciesId === Species.NECROZMA && matchingFormChangeOpts.length > 1) {
|
if (pokemon.species.speciesId === SpeciesId.NECROZMA && matchingFormChangeOpts.length > 1) {
|
||||||
// Ultra Necrozma is changing its form back, so we need to figure out into which form it devolves.
|
// Ultra Necrozma is changing its form back, so we need to figure out into which form it devolves.
|
||||||
const formChangeItemModifiers = (
|
const formChangeItemModifiers = (
|
||||||
this.findModifiers(
|
this.findModifiers(
|
||||||
@ -3495,17 +3185,17 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
if (matchingFormChange) {
|
if (matchingFormChange) {
|
||||||
let phase: Phase;
|
let phase: Phase;
|
||||||
if (pokemon instanceof PlayerPokemon && !matchingFormChange.quiet) {
|
if (pokemon.isPlayer() && !matchingFormChange.quiet) {
|
||||||
phase = new FormChangePhase(pokemon, matchingFormChange, modal);
|
phase = this.phaseManager.create("FormChangePhase", pokemon, matchingFormChange, modal);
|
||||||
} else {
|
} else {
|
||||||
phase = new QuietFormChangePhase(pokemon, matchingFormChange);
|
phase = this.phaseManager.create("QuietFormChangePhase", pokemon, matchingFormChange);
|
||||||
}
|
}
|
||||||
if (pokemon instanceof PlayerPokemon && !matchingFormChange.quiet && modal) {
|
if (pokemon.isPlayer() && !matchingFormChange.quiet && modal) {
|
||||||
this.overridePhase(phase);
|
this.phaseManager.overridePhase(phase);
|
||||||
} else if (delayed) {
|
} else if (delayed) {
|
||||||
this.pushPhase(phase);
|
this.phaseManager.pushPhase(phase);
|
||||||
} else {
|
} else {
|
||||||
this.unshiftPhase(phase);
|
this.phaseManager.unshiftPhase(phase);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3520,11 +3210,12 @@ export default class BattleScene extends SceneBase {
|
|||||||
fieldAssets?: Phaser.GameObjects.Sprite[],
|
fieldAssets?: Phaser.GameObjects.Sprite[],
|
||||||
delayed = false,
|
delayed = false,
|
||||||
): boolean {
|
): boolean {
|
||||||
const phase: Phase = new PokemonAnimPhase(battleAnimType, pokemon, fieldAssets);
|
const phaseManager = this.phaseManager;
|
||||||
|
const phase: Phase = phaseManager.create("PokemonAnimPhase", battleAnimType, pokemon, fieldAssets);
|
||||||
if (delayed) {
|
if (delayed) {
|
||||||
this.pushPhase(phase);
|
phaseManager.pushPhase(phase);
|
||||||
} else {
|
} else {
|
||||||
this.unshiftPhase(phase);
|
phaseManager.unshiftPhase(phase);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3569,21 +3260,18 @@ export default class BattleScene extends SceneBase {
|
|||||||
gameMode: this.currentBattle ? this.gameMode.getName() : "Title",
|
gameMode: this.currentBattle ? this.gameMode.getName() : "Title",
|
||||||
biome: this.currentBattle ? getBiomeName(this.arena.biomeType) : "",
|
biome: this.currentBattle ? getBiomeName(this.arena.biomeType) : "",
|
||||||
wave: this.currentBattle?.waveIndex ?? 0,
|
wave: this.currentBattle?.waveIndex ?? 0,
|
||||||
party: this.party
|
party:
|
||||||
? this.party.map(p => {
|
this.party?.map(p => ({
|
||||||
return {
|
name: p.name,
|
||||||
name: p.name,
|
form: p.getFormKey(),
|
||||||
form: p.getFormKey(),
|
types: p.getTypes().map(type => PokemonType[type]),
|
||||||
types: p.getTypes().map(type => PokemonType[type]),
|
teraType: PokemonType[p.getTeraType()],
|
||||||
teraType: PokemonType[p.getTeraType()],
|
isTerastallized: p.isTerastallized,
|
||||||
isTerastallized: p.isTerastallized,
|
level: p.level,
|
||||||
level: p.level,
|
currentHP: p.hp,
|
||||||
currentHP: p.hp,
|
maxHP: p.getMaxHp(),
|
||||||
maxHP: p.getMaxHp(),
|
status: p.status?.effect ? StatusEffect[p.status.effect] : "",
|
||||||
status: p.status?.effect ? StatusEffect[p.status.effect] : "",
|
})) ?? [], // TODO: review if this can be nullish
|
||||||
};
|
|
||||||
})
|
|
||||||
: [],
|
|
||||||
modeChain: this.ui?.getModeChain() ?? [],
|
modeChain: this.ui?.getModeChain() ?? [],
|
||||||
};
|
};
|
||||||
(window as any).gameInfo = gameInfo;
|
(window as any).gameInfo = gameInfo;
|
||||||
@ -3601,7 +3289,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
activePokemon = activePokemon.concat(this.getEnemyParty());
|
activePokemon = activePokemon.concat(this.getEnemyParty());
|
||||||
for (const p of activePokemon) {
|
for (const p of activePokemon) {
|
||||||
keys.push(p.getSpriteKey(true));
|
keys.push(p.getSpriteKey(true));
|
||||||
if (p instanceof PlayerPokemon) {
|
if (p.isPlayer()) {
|
||||||
keys.push(p.getBattleSpriteKey(true, true));
|
keys.push(p.getBattleSpriteKey(true, true));
|
||||||
}
|
}
|
||||||
keys.push(p.species.getCryKey(p.formIndex));
|
keys.push(p.species.getCryKey(p.formIndex));
|
||||||
@ -3617,7 +3305,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
* @param pokemon The (enemy) pokemon
|
* @param pokemon The (enemy) pokemon
|
||||||
*/
|
*/
|
||||||
initFinalBossPhaseTwo(pokemon: Pokemon): void {
|
initFinalBossPhaseTwo(pokemon: Pokemon): void {
|
||||||
if (pokemon instanceof EnemyPokemon && pokemon.isBoss() && !pokemon.formIndex && pokemon.bossSegmentIndex < 1) {
|
if (pokemon.isEnemy() && pokemon.isBoss() && !pokemon.formIndex && pokemon.bossSegmentIndex < 1) {
|
||||||
this.fadeOutBgm(fixedInt(2000), false);
|
this.fadeOutBgm(fixedInt(2000), false);
|
||||||
this.ui.showDialogue(
|
this.ui.showDialogue(
|
||||||
battleSpecDialogue[BattleSpec.FINAL_BOSS].firstStageWin,
|
battleSpecDialogue[BattleSpec.FINAL_BOSS].firstStageWin,
|
||||||
@ -3635,19 +3323,19 @@ export default class BattleScene extends SceneBase {
|
|||||||
this.currentBattle.double = true;
|
this.currentBattle.double = true;
|
||||||
const availablePartyMembers = this.getPlayerParty().filter(p => p.isAllowedInBattle());
|
const availablePartyMembers = this.getPlayerParty().filter(p => p.isAllowedInBattle());
|
||||||
if (availablePartyMembers.length > 1) {
|
if (availablePartyMembers.length > 1) {
|
||||||
this.pushPhase(new ToggleDoublePositionPhase(true));
|
this.phaseManager.pushNew("ToggleDoublePositionPhase", true);
|
||||||
if (!availablePartyMembers[1].isOnField()) {
|
if (!availablePartyMembers[1].isOnField()) {
|
||||||
this.pushPhase(new SummonPhase(1));
|
this.phaseManager.pushNew("SummonPhase", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.shiftPhase();
|
this.phaseManager.shiftPhase();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.shiftPhase();
|
this.phaseManager.shiftPhase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3759,10 +3447,10 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
if (exp) {
|
if (exp) {
|
||||||
const partyMemberIndex = party.indexOf(expPartyMembers[pm]);
|
const partyMemberIndex = party.indexOf(expPartyMembers[pm]);
|
||||||
this.unshiftPhase(
|
this.phaseManager.unshiftPhase(
|
||||||
expPartyMembers[pm].isOnField()
|
expPartyMembers[pm].isOnField()
|
||||||
? new ExpPhase(partyMemberIndex, exp)
|
? this.phaseManager.create("ExpPhase", partyMemberIndex, exp)
|
||||||
: new ShowPartyExpBarPhase(partyMemberIndex, exp),
|
: this.phaseManager.create("ShowPartyExpBarPhase", partyMemberIndex, exp),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3966,16 +3654,13 @@ export default class BattleScene extends SceneBase {
|
|||||||
if (previousEncounter !== null && encounterType === previousEncounter) {
|
if (previousEncounter !== null && encounterType === previousEncounter) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (
|
return !(
|
||||||
this.mysteryEncounterSaveData.encounteredEvents.length > 0 &&
|
this.mysteryEncounterSaveData.encounteredEvents.length > 0 &&
|
||||||
encounterCandidate.maxAllowedEncounters &&
|
encounterCandidate.maxAllowedEncounters &&
|
||||||
encounterCandidate.maxAllowedEncounters > 0 &&
|
encounterCandidate.maxAllowedEncounters > 0 &&
|
||||||
this.mysteryEncounterSaveData.encounteredEvents.filter(e => e.type === encounterType).length >=
|
this.mysteryEncounterSaveData.encounteredEvents.filter(e => e.type === encounterType).length >=
|
||||||
encounterCandidate.maxAllowedEncounters
|
encounterCandidate.maxAllowedEncounters
|
||||||
) {
|
);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
})
|
})
|
||||||
.map(m => allMysteryEncounters[m]);
|
.map(m => allMysteryEncounters[m]);
|
||||||
// Decrement tier
|
// Decrement tier
|
||||||
|
203
src/battle.ts
203
src/battle.ts
@ -1,5 +1,5 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { Command } from "./ui/command-ui-handler";
|
import type { Command } from "#enums/command";
|
||||||
import {
|
import {
|
||||||
randomString,
|
randomString,
|
||||||
getEnumValues,
|
getEnumValues,
|
||||||
@ -8,8 +8,10 @@ import {
|
|||||||
shiftCharCodes,
|
shiftCharCodes,
|
||||||
randSeedItem,
|
randSeedItem,
|
||||||
randInt,
|
randInt,
|
||||||
|
randSeedFloat,
|
||||||
} from "#app/utils/common";
|
} from "#app/utils/common";
|
||||||
import Trainer, { TrainerVariant } from "./field/trainer";
|
import Trainer from "./field/trainer";
|
||||||
|
import { TrainerVariant } from "#enums/trainer-variant";
|
||||||
import type { GameMode } from "./game-mode";
|
import type { GameMode } from "./game-mode";
|
||||||
import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier";
|
import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier";
|
||||||
import type { PokeballType } from "#enums/pokeball";
|
import type { PokeballType } from "#enums/pokeball";
|
||||||
@ -19,10 +21,10 @@ import type { EnemyPokemon, PlayerPokemon, TurnMove } from "#app/field/pokemon";
|
|||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||||
import { BattleSpec } from "#enums/battle-spec";
|
import { BattleSpec } from "#enums/battle-spec";
|
||||||
import type { Moves } from "#enums/moves";
|
import type { MoveId } from "#enums/move-id";
|
||||||
import { PlayerGender } from "#enums/player-gender";
|
import { PlayerGender } from "#enums/player-gender";
|
||||||
import { MusicPreference } from "#app/system/settings/settings";
|
import { MusicPreference } from "#app/system/settings/settings";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import i18next from "#app/plugins/i18n";
|
import i18next from "#app/plugins/i18n";
|
||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
@ -32,14 +34,7 @@ import { ModifierTier } from "#app/modifier/modifier-tier";
|
|||||||
import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { BattleType } from "#enums/battle-type";
|
import { BattleType } from "#enums/battle-type";
|
||||||
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
||||||
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
export enum BattlerIndex {
|
|
||||||
ATTACKER = -1,
|
|
||||||
PLAYER,
|
|
||||||
PLAYER_2,
|
|
||||||
ENEMY,
|
|
||||||
ENEMY_2,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TurnCommand {
|
export interface TurnCommand {
|
||||||
command: Command;
|
command: Command;
|
||||||
@ -78,7 +73,7 @@ export default class Battle {
|
|||||||
public battleScore = 0;
|
public battleScore = 0;
|
||||||
public postBattleLoot: PokemonHeldItemModifier[] = [];
|
public postBattleLoot: PokemonHeldItemModifier[] = [];
|
||||||
public escapeAttempts = 0;
|
public escapeAttempts = 0;
|
||||||
public lastMove: Moves;
|
public lastMove: MoveId;
|
||||||
public battleSeed: string = randomString(16, true);
|
public battleSeed: string = randomString(16, true);
|
||||||
private battleSeedState: string | null = null;
|
private battleSeedState: string | null = null;
|
||||||
public moneyScattered = 0;
|
public moneyScattered = 0;
|
||||||
@ -150,7 +145,7 @@ export default class Battle {
|
|||||||
randSeedGaussForLevel(value: number): number {
|
randSeedGaussForLevel(value: number): number {
|
||||||
let rand = 0;
|
let rand = 0;
|
||||||
for (let i = value; i > 0; i--) {
|
for (let i = value; i > 0; i--) {
|
||||||
rand += Phaser.Math.RND.realInRange(0, 1);
|
rand += randSeedFloat();
|
||||||
}
|
}
|
||||||
return rand / value;
|
return rand / value;
|
||||||
}
|
}
|
||||||
@ -205,7 +200,7 @@ export default class Battle {
|
|||||||
const message = i18next.t("battle:moneyPickedUp", {
|
const message = i18next.t("battle:moneyPickedUp", {
|
||||||
moneyAmount: formattedMoneyAmount,
|
moneyAmount: formattedMoneyAmount,
|
||||||
});
|
});
|
||||||
globalScene.queueMessage(message, undefined, true);
|
globalScene.phaseManager.queueMessage(message, undefined, true);
|
||||||
|
|
||||||
globalScene.currentBattle.moneyScattered = 0;
|
globalScene.currentBattle.moneyScattered = 0;
|
||||||
}
|
}
|
||||||
@ -264,14 +259,14 @@ export default class Battle {
|
|||||||
if (pokemon.species.legendary || pokemon.species.subLegendary || pokemon.species.mythical) {
|
if (pokemon.species.legendary || pokemon.species.subLegendary || pokemon.species.mythical) {
|
||||||
if (globalScene.musicPreference === MusicPreference.GENFIVE) {
|
if (globalScene.musicPreference === MusicPreference.GENFIVE) {
|
||||||
switch (pokemon.species.speciesId) {
|
switch (pokemon.species.speciesId) {
|
||||||
case Species.REGIROCK:
|
case SpeciesId.REGIROCK:
|
||||||
case Species.REGICE:
|
case SpeciesId.REGICE:
|
||||||
case Species.REGISTEEL:
|
case SpeciesId.REGISTEEL:
|
||||||
case Species.REGIGIGAS:
|
case SpeciesId.REGIGIGAS:
|
||||||
case Species.REGIDRAGO:
|
case SpeciesId.REGIDRAGO:
|
||||||
case Species.REGIELEKI:
|
case SpeciesId.REGIELEKI:
|
||||||
return "battle_legendary_regis_g5";
|
return "battle_legendary_regis_g5";
|
||||||
case Species.KYUREM:
|
case SpeciesId.KYUREM:
|
||||||
return "battle_legendary_kyurem";
|
return "battle_legendary_kyurem";
|
||||||
default:
|
default:
|
||||||
if (pokemon.species.legendary) {
|
if (pokemon.species.legendary) {
|
||||||
@ -282,80 +277,80 @@ export default class Battle {
|
|||||||
}
|
}
|
||||||
if (globalScene.musicPreference === MusicPreference.ALLGENS) {
|
if (globalScene.musicPreference === MusicPreference.ALLGENS) {
|
||||||
switch (pokemon.species.speciesId) {
|
switch (pokemon.species.speciesId) {
|
||||||
case Species.ARTICUNO:
|
case SpeciesId.ARTICUNO:
|
||||||
case Species.ZAPDOS:
|
case SpeciesId.ZAPDOS:
|
||||||
case Species.MOLTRES:
|
case SpeciesId.MOLTRES:
|
||||||
case Species.MEWTWO:
|
case SpeciesId.MEWTWO:
|
||||||
case Species.MEW:
|
case SpeciesId.MEW:
|
||||||
return "battle_legendary_kanto";
|
return "battle_legendary_kanto";
|
||||||
case Species.RAIKOU:
|
case SpeciesId.RAIKOU:
|
||||||
return "battle_legendary_raikou";
|
return "battle_legendary_raikou";
|
||||||
case Species.ENTEI:
|
case SpeciesId.ENTEI:
|
||||||
return "battle_legendary_entei";
|
return "battle_legendary_entei";
|
||||||
case Species.SUICUNE:
|
case SpeciesId.SUICUNE:
|
||||||
return "battle_legendary_suicune";
|
return "battle_legendary_suicune";
|
||||||
case Species.LUGIA:
|
case SpeciesId.LUGIA:
|
||||||
return "battle_legendary_lugia";
|
return "battle_legendary_lugia";
|
||||||
case Species.HO_OH:
|
case SpeciesId.HO_OH:
|
||||||
return "battle_legendary_ho_oh";
|
return "battle_legendary_ho_oh";
|
||||||
case Species.REGIROCK:
|
case SpeciesId.REGIROCK:
|
||||||
case Species.REGICE:
|
case SpeciesId.REGICE:
|
||||||
case Species.REGISTEEL:
|
case SpeciesId.REGISTEEL:
|
||||||
case Species.REGIGIGAS:
|
case SpeciesId.REGIGIGAS:
|
||||||
case Species.REGIDRAGO:
|
case SpeciesId.REGIDRAGO:
|
||||||
case Species.REGIELEKI:
|
case SpeciesId.REGIELEKI:
|
||||||
return "battle_legendary_regis_g6";
|
return "battle_legendary_regis_g6";
|
||||||
case Species.GROUDON:
|
case SpeciesId.GROUDON:
|
||||||
case Species.KYOGRE:
|
case SpeciesId.KYOGRE:
|
||||||
return "battle_legendary_gro_kyo";
|
return "battle_legendary_gro_kyo";
|
||||||
case Species.RAYQUAZA:
|
case SpeciesId.RAYQUAZA:
|
||||||
return "battle_legendary_rayquaza";
|
return "battle_legendary_rayquaza";
|
||||||
case Species.DEOXYS:
|
case SpeciesId.DEOXYS:
|
||||||
return "battle_legendary_deoxys";
|
return "battle_legendary_deoxys";
|
||||||
case Species.UXIE:
|
case SpeciesId.UXIE:
|
||||||
case Species.MESPRIT:
|
case SpeciesId.MESPRIT:
|
||||||
case Species.AZELF:
|
case SpeciesId.AZELF:
|
||||||
return "battle_legendary_lake_trio";
|
return "battle_legendary_lake_trio";
|
||||||
case Species.HEATRAN:
|
case SpeciesId.HEATRAN:
|
||||||
case Species.CRESSELIA:
|
case SpeciesId.CRESSELIA:
|
||||||
case Species.DARKRAI:
|
case SpeciesId.DARKRAI:
|
||||||
case Species.SHAYMIN:
|
case SpeciesId.SHAYMIN:
|
||||||
return "battle_legendary_sinnoh";
|
return "battle_legendary_sinnoh";
|
||||||
case Species.DIALGA:
|
case SpeciesId.DIALGA:
|
||||||
case Species.PALKIA:
|
case SpeciesId.PALKIA:
|
||||||
if (pokemon.species.getFormSpriteKey(pokemon.formIndex) === SpeciesFormKey.ORIGIN) {
|
if (pokemon.species.getFormSpriteKey(pokemon.formIndex) === SpeciesFormKey.ORIGIN) {
|
||||||
return "battle_legendary_origin_forme";
|
return "battle_legendary_origin_forme";
|
||||||
}
|
}
|
||||||
return "battle_legendary_dia_pal";
|
return "battle_legendary_dia_pal";
|
||||||
case Species.GIRATINA:
|
case SpeciesId.GIRATINA:
|
||||||
return "battle_legendary_giratina";
|
return "battle_legendary_giratina";
|
||||||
case Species.ARCEUS:
|
case SpeciesId.ARCEUS:
|
||||||
return "battle_legendary_arceus";
|
return "battle_legendary_arceus";
|
||||||
case Species.COBALION:
|
case SpeciesId.COBALION:
|
||||||
case Species.TERRAKION:
|
case SpeciesId.TERRAKION:
|
||||||
case Species.VIRIZION:
|
case SpeciesId.VIRIZION:
|
||||||
case Species.KELDEO:
|
case SpeciesId.KELDEO:
|
||||||
case Species.TORNADUS:
|
case SpeciesId.TORNADUS:
|
||||||
case Species.LANDORUS:
|
case SpeciesId.LANDORUS:
|
||||||
case Species.THUNDURUS:
|
case SpeciesId.THUNDURUS:
|
||||||
case Species.MELOETTA:
|
case SpeciesId.MELOETTA:
|
||||||
case Species.GENESECT:
|
case SpeciesId.GENESECT:
|
||||||
return "battle_legendary_unova";
|
return "battle_legendary_unova";
|
||||||
case Species.KYUREM:
|
case SpeciesId.KYUREM:
|
||||||
return "battle_legendary_kyurem";
|
return "battle_legendary_kyurem";
|
||||||
case Species.XERNEAS:
|
case SpeciesId.XERNEAS:
|
||||||
case Species.YVELTAL:
|
case SpeciesId.YVELTAL:
|
||||||
case Species.ZYGARDE:
|
case SpeciesId.ZYGARDE:
|
||||||
return "battle_legendary_xern_yvel";
|
return "battle_legendary_xern_yvel";
|
||||||
case Species.TAPU_KOKO:
|
case SpeciesId.TAPU_KOKO:
|
||||||
case Species.TAPU_LELE:
|
case SpeciesId.TAPU_LELE:
|
||||||
case Species.TAPU_BULU:
|
case SpeciesId.TAPU_BULU:
|
||||||
case Species.TAPU_FINI:
|
case SpeciesId.TAPU_FINI:
|
||||||
return "battle_legendary_tapu";
|
return "battle_legendary_tapu";
|
||||||
case Species.SOLGALEO:
|
case SpeciesId.SOLGALEO:
|
||||||
case Species.LUNALA:
|
case SpeciesId.LUNALA:
|
||||||
return "battle_legendary_sol_lun";
|
return "battle_legendary_sol_lun";
|
||||||
case Species.NECROZMA:
|
case SpeciesId.NECROZMA:
|
||||||
switch (pokemon.getFormKey()) {
|
switch (pokemon.getFormKey()) {
|
||||||
case "dusk-mane":
|
case "dusk-mane":
|
||||||
case "dawn-wings":
|
case "dawn-wings":
|
||||||
@ -365,50 +360,50 @@ export default class Battle {
|
|||||||
default:
|
default:
|
||||||
return "battle_legendary_sol_lun";
|
return "battle_legendary_sol_lun";
|
||||||
}
|
}
|
||||||
case Species.NIHILEGO:
|
case SpeciesId.NIHILEGO:
|
||||||
case Species.PHEROMOSA:
|
case SpeciesId.PHEROMOSA:
|
||||||
case Species.BUZZWOLE:
|
case SpeciesId.BUZZWOLE:
|
||||||
case Species.XURKITREE:
|
case SpeciesId.XURKITREE:
|
||||||
case Species.CELESTEELA:
|
case SpeciesId.CELESTEELA:
|
||||||
case Species.KARTANA:
|
case SpeciesId.KARTANA:
|
||||||
case Species.GUZZLORD:
|
case SpeciesId.GUZZLORD:
|
||||||
case Species.POIPOLE:
|
case SpeciesId.POIPOLE:
|
||||||
case Species.NAGANADEL:
|
case SpeciesId.NAGANADEL:
|
||||||
case Species.STAKATAKA:
|
case SpeciesId.STAKATAKA:
|
||||||
case Species.BLACEPHALON:
|
case SpeciesId.BLACEPHALON:
|
||||||
return "battle_legendary_ub";
|
return "battle_legendary_ub";
|
||||||
case Species.ZACIAN:
|
case SpeciesId.ZACIAN:
|
||||||
case Species.ZAMAZENTA:
|
case SpeciesId.ZAMAZENTA:
|
||||||
return "battle_legendary_zac_zam";
|
return "battle_legendary_zac_zam";
|
||||||
case Species.GLASTRIER:
|
case SpeciesId.GLASTRIER:
|
||||||
case Species.SPECTRIER:
|
case SpeciesId.SPECTRIER:
|
||||||
return "battle_legendary_glas_spec";
|
return "battle_legendary_glas_spec";
|
||||||
case Species.CALYREX:
|
case SpeciesId.CALYREX:
|
||||||
if (pokemon.getFormKey() === "ice" || pokemon.getFormKey() === "shadow") {
|
if (pokemon.getFormKey() === "ice" || pokemon.getFormKey() === "shadow") {
|
||||||
return "battle_legendary_riders";
|
return "battle_legendary_riders";
|
||||||
}
|
}
|
||||||
return "battle_legendary_calyrex";
|
return "battle_legendary_calyrex";
|
||||||
case Species.GALAR_ARTICUNO:
|
case SpeciesId.GALAR_ARTICUNO:
|
||||||
case Species.GALAR_ZAPDOS:
|
case SpeciesId.GALAR_ZAPDOS:
|
||||||
case Species.GALAR_MOLTRES:
|
case SpeciesId.GALAR_MOLTRES:
|
||||||
return "battle_legendary_birds_galar";
|
return "battle_legendary_birds_galar";
|
||||||
case Species.WO_CHIEN:
|
case SpeciesId.WO_CHIEN:
|
||||||
case Species.CHIEN_PAO:
|
case SpeciesId.CHIEN_PAO:
|
||||||
case Species.TING_LU:
|
case SpeciesId.TING_LU:
|
||||||
case Species.CHI_YU:
|
case SpeciesId.CHI_YU:
|
||||||
return "battle_legendary_ruinous";
|
return "battle_legendary_ruinous";
|
||||||
case Species.KORAIDON:
|
case SpeciesId.KORAIDON:
|
||||||
case Species.MIRAIDON:
|
case SpeciesId.MIRAIDON:
|
||||||
return "battle_legendary_kor_mir";
|
return "battle_legendary_kor_mir";
|
||||||
case Species.OKIDOGI:
|
case SpeciesId.OKIDOGI:
|
||||||
case Species.MUNKIDORI:
|
case SpeciesId.MUNKIDORI:
|
||||||
case Species.FEZANDIPITI:
|
case SpeciesId.FEZANDIPITI:
|
||||||
return "battle_legendary_loyal_three";
|
return "battle_legendary_loyal_three";
|
||||||
case Species.OGERPON:
|
case SpeciesId.OGERPON:
|
||||||
return "battle_legendary_ogerpon";
|
return "battle_legendary_ogerpon";
|
||||||
case Species.TERAPAGOS:
|
case SpeciesId.TERAPAGOS:
|
||||||
return "battle_legendary_terapagos";
|
return "battle_legendary_terapagos";
|
||||||
case Species.PECHARUNT:
|
case SpeciesId.PECHARUNT:
|
||||||
return "battle_legendary_pecharunt";
|
return "battle_legendary_pecharunt";
|
||||||
default:
|
default:
|
||||||
if (pokemon.species.legendary) {
|
if (pokemon.species.legendary) {
|
||||||
|
@ -197,10 +197,7 @@ export function canIAssignThisKey(config, key) {
|
|||||||
export function canIOverrideThisSetting(config, settingName) {
|
export function canIOverrideThisSetting(config, settingName) {
|
||||||
const key = getKeyWithSettingName(config, settingName);
|
const key = getKeyWithSettingName(config, settingName);
|
||||||
// || isTheLatestBind(config, settingName) no longer needed since action and cancel are protected
|
// || isTheLatestBind(config, settingName) no longer needed since action and cancel are protected
|
||||||
if (config.blacklist?.includes(key)) {
|
return !config.blacklist?.includes(key);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canIDeleteThisKey(config, key) {
|
export function canIDeleteThisKey(config, key) {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
|
||||||
/** The maximum size of the player's party */
|
/** The maximum size of the player's party */
|
||||||
export const PLAYER_PARTY_MAX_SIZE: number = 6;
|
export const PLAYER_PARTY_MAX_SIZE: number = 6;
|
||||||
|
|
||||||
@ -17,3 +19,38 @@ export const CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES: [number, number] = [10, 180
|
|||||||
|
|
||||||
/** The raw percentage power boost for type boost items*/
|
/** The raw percentage power boost for type boost items*/
|
||||||
export const TYPE_BOOST_ITEM_BOOST_PERCENT = 20;
|
export const TYPE_BOOST_ITEM_BOOST_PERCENT = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default species that a new player can choose from
|
||||||
|
*/
|
||||||
|
export const defaultStarterSpecies: SpeciesId[] = [
|
||||||
|
SpeciesId.BULBASAUR,
|
||||||
|
SpeciesId.CHARMANDER,
|
||||||
|
SpeciesId.SQUIRTLE,
|
||||||
|
SpeciesId.CHIKORITA,
|
||||||
|
SpeciesId.CYNDAQUIL,
|
||||||
|
SpeciesId.TOTODILE,
|
||||||
|
SpeciesId.TREECKO,
|
||||||
|
SpeciesId.TORCHIC,
|
||||||
|
SpeciesId.MUDKIP,
|
||||||
|
SpeciesId.TURTWIG,
|
||||||
|
SpeciesId.CHIMCHAR,
|
||||||
|
SpeciesId.PIPLUP,
|
||||||
|
SpeciesId.SNIVY,
|
||||||
|
SpeciesId.TEPIG,
|
||||||
|
SpeciesId.OSHAWOTT,
|
||||||
|
SpeciesId.CHESPIN,
|
||||||
|
SpeciesId.FENNEKIN,
|
||||||
|
SpeciesId.FROAKIE,
|
||||||
|
SpeciesId.ROWLET,
|
||||||
|
SpeciesId.LITTEN,
|
||||||
|
SpeciesId.POPPLIO,
|
||||||
|
SpeciesId.GROOKEY,
|
||||||
|
SpeciesId.SCORBUNNY,
|
||||||
|
SpeciesId.SOBBLE,
|
||||||
|
SpeciesId.SPRIGATITO,
|
||||||
|
SpeciesId.FUECOCO,
|
||||||
|
SpeciesId.QUAXLY,
|
||||||
|
];
|
||||||
|
|
||||||
|
export const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet necessary
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { Abilities } from "#enums/abilities";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import type { AbAttrCondition } from "#app/@types/ability-types";
|
import type { AbAttrCondition } from "#app/@types/ability-types";
|
||||||
import type { AbAttr } from "#app/data/abilities/ab-attrs/ab-attr";
|
import type { AbAttr } from "#app/data/abilities/ab-attrs/ab-attr";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type { Localizable } from "#app/interfaces/locales";
|
import type { Localizable } from "#app/@types/locales";
|
||||||
import type { Constructor } from "#app/utils/common";
|
import type { Constructor } from "#app/utils/common";
|
||||||
|
|
||||||
export class Ability implements Localizable {
|
export class Ability implements Localizable {
|
||||||
public id: Abilities;
|
public id: AbilityId;
|
||||||
|
|
||||||
private nameAppend: string;
|
private nameAppend: string;
|
||||||
public name: string;
|
public name: string;
|
||||||
@ -20,7 +20,7 @@ export class Ability implements Localizable {
|
|||||||
public attrs: AbAttr[];
|
public attrs: AbAttr[];
|
||||||
public conditions: AbAttrCondition[];
|
public conditions: AbAttrCondition[];
|
||||||
|
|
||||||
constructor(id: Abilities, generation: number) {
|
constructor(id: AbilityId, generation: number) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
||||||
this.nameAppend = "";
|
this.nameAppend = "";
|
||||||
@ -39,7 +39,7 @@ export class Ability implements Localizable {
|
|||||||
return this.isCopiable && this.isReplaceable;
|
return this.isCopiable && this.isReplaceable;
|
||||||
}
|
}
|
||||||
localize(): void {
|
localize(): void {
|
||||||
const i18nKey = Abilities[this.id]
|
const i18nKey = AbilityId[this.id]
|
||||||
.split("_")
|
.split("_")
|
||||||
.filter(f => f)
|
.filter(f => f)
|
||||||
.map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()))
|
.map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()))
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -7,9 +7,9 @@ import { MoveTarget } from "#enums/MoveTarget";
|
|||||||
import { MoveCategory } from "#enums/MoveCategory";
|
import { MoveCategory } from "#enums/MoveCategory";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { HitResult } from "#app/field/pokemon";
|
import { HitResult } from "#enums/hit-result";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import type { BattlerIndex } from "#app/battle";
|
import type { BattlerIndex } from "#enums/battler-index";
|
||||||
import {
|
import {
|
||||||
BlockNonDirectDamageAbAttr,
|
BlockNonDirectDamageAbAttr,
|
||||||
InfiltratorAbAttr,
|
InfiltratorAbAttr,
|
||||||
@ -20,28 +20,20 @@ import {
|
|||||||
applyOnLoseAbAttrs,
|
applyOnLoseAbAttrs,
|
||||||
} from "#app/data/abilities/ability";
|
} from "#app/data/abilities/ability";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { CommonAnim, CommonBattleAnim } from "#app/data/battle-anims";
|
import { CommonBattleAnim } from "#app/data/battle-anims";
|
||||||
|
import { CommonAnim } from "#enums/move-anims-common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
import { ArenaTagSide } from "#enums/arena-tag-side";
|
||||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { CommonAnimPhase } from "#app/phases/common-anim-phase";
|
|
||||||
|
|
||||||
export enum ArenaTagSide {
|
|
||||||
BOTH,
|
|
||||||
PLAYER,
|
|
||||||
ENEMY,
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class ArenaTag {
|
export abstract class ArenaTag {
|
||||||
constructor(
|
constructor(
|
||||||
public tagType: ArenaTagType,
|
public tagType: ArenaTagType,
|
||||||
public turnCount: number,
|
public turnCount: number,
|
||||||
public sourceMove?: Moves,
|
public sourceMove?: MoveId,
|
||||||
public sourceId?: number,
|
public sourceId?: number,
|
||||||
public side: ArenaTagSide = ArenaTagSide.BOTH,
|
public side: ArenaTagSide = ArenaTagSide.BOTH,
|
||||||
) {}
|
) {}
|
||||||
@ -54,7 +46,7 @@ export abstract class ArenaTag {
|
|||||||
|
|
||||||
onRemove(_arena: Arena, quiet = false): void {
|
onRemove(_arena: Arena, quiet = false): void {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:arenaOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:arenaOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
{ moveName: this.getMoveName() },
|
{ moveName: this.getMoveName() },
|
||||||
@ -116,7 +108,7 @@ export abstract class ArenaTag {
|
|||||||
*/
|
*/
|
||||||
export class MistTag extends ArenaTag {
|
export class MistTag extends ArenaTag {
|
||||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.MIST, turnCount, Moves.MIST, sourceId, side);
|
super(ArenaTagType.MIST, turnCount, MoveId.MIST, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(arena: Arena, quiet = false): void {
|
onAdd(arena: Arena, quiet = false): void {
|
||||||
@ -126,7 +118,7 @@ export class MistTag extends ArenaTag {
|
|||||||
const source = globalScene.getPokemonById(this.sourceId);
|
const source = globalScene.getPokemonById(this.sourceId);
|
||||||
|
|
||||||
if (!quiet && source) {
|
if (!quiet && source) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:mistOnAdd", {
|
i18next.t("arenaTag:mistOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
||||||
}),
|
}),
|
||||||
@ -161,7 +153,7 @@ export class MistTag extends ArenaTag {
|
|||||||
cancelled.value = true;
|
cancelled.value = true;
|
||||||
|
|
||||||
if (!simulated) {
|
if (!simulated) {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:mistApply"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:mistApply"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -188,7 +180,7 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
|||||||
constructor(
|
constructor(
|
||||||
tagType: ArenaTagType,
|
tagType: ArenaTagType,
|
||||||
turnCount: number,
|
turnCount: number,
|
||||||
sourceMove: Moves,
|
sourceMove: MoveId,
|
||||||
sourceId: number,
|
sourceId: number,
|
||||||
side: ArenaTagSide,
|
side: ArenaTagSide,
|
||||||
weakenedCategories: MoveCategory[],
|
weakenedCategories: MoveCategory[],
|
||||||
@ -230,16 +222,16 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reduces the damage of physical moves.
|
* Reduces the damage of physical moves.
|
||||||
* Used by {@linkcode Moves.REFLECT}
|
* Used by {@linkcode MoveId.REFLECT}
|
||||||
*/
|
*/
|
||||||
class ReflectTag extends WeakenMoveScreenTag {
|
class ReflectTag extends WeakenMoveScreenTag {
|
||||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side, [MoveCategory.PHYSICAL]);
|
super(ArenaTagType.REFLECT, turnCount, MoveId.REFLECT, sourceId, side, [MoveCategory.PHYSICAL]);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena, quiet = false): void {
|
onAdd(_arena: Arena, quiet = false): void {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:reflectOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:reflectOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -250,16 +242,16 @@ class ReflectTag extends WeakenMoveScreenTag {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reduces the damage of special moves.
|
* Reduces the damage of special moves.
|
||||||
* Used by {@linkcode Moves.LIGHT_SCREEN}
|
* Used by {@linkcode MoveId.LIGHT_SCREEN}
|
||||||
*/
|
*/
|
||||||
class LightScreenTag extends WeakenMoveScreenTag {
|
class LightScreenTag extends WeakenMoveScreenTag {
|
||||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side, [MoveCategory.SPECIAL]);
|
super(ArenaTagType.LIGHT_SCREEN, turnCount, MoveId.LIGHT_SCREEN, sourceId, side, [MoveCategory.SPECIAL]);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena, quiet = false): void {
|
onAdd(_arena: Arena, quiet = false): void {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:lightScreenOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:lightScreenOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -270,11 +262,11 @@ class LightScreenTag extends WeakenMoveScreenTag {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reduces the damage of physical and special moves.
|
* Reduces the damage of physical and special moves.
|
||||||
* Used by {@linkcode Moves.AURORA_VEIL}
|
* Used by {@linkcode MoveId.AURORA_VEIL}
|
||||||
*/
|
*/
|
||||||
class AuroraVeilTag extends WeakenMoveScreenTag {
|
class AuroraVeilTag extends WeakenMoveScreenTag {
|
||||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side, [
|
super(ArenaTagType.AURORA_VEIL, turnCount, MoveId.AURORA_VEIL, sourceId, side, [
|
||||||
MoveCategory.SPECIAL,
|
MoveCategory.SPECIAL,
|
||||||
MoveCategory.PHYSICAL,
|
MoveCategory.PHYSICAL,
|
||||||
]);
|
]);
|
||||||
@ -282,7 +274,7 @@ class AuroraVeilTag extends WeakenMoveScreenTag {
|
|||||||
|
|
||||||
onAdd(_arena: Arena, quiet = false): void {
|
onAdd(_arena: Arena, quiet = false): void {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:auroraVeilOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:auroraVeilOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -291,7 +283,7 @@ class AuroraVeilTag extends WeakenMoveScreenTag {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProtectConditionFunc = (arena: Arena, moveId: Moves) => boolean;
|
type ProtectConditionFunc = (arena: Arena, moveId: MoveId) => boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to implement conditional team protection
|
* Class to implement conditional team protection
|
||||||
@ -305,7 +297,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
tagType: ArenaTagType,
|
tagType: ArenaTagType,
|
||||||
sourceMove: Moves,
|
sourceMove: MoveId,
|
||||||
sourceId: number,
|
sourceId: number,
|
||||||
side: ArenaTagSide,
|
side: ArenaTagSide,
|
||||||
condition: ProtectConditionFunc,
|
condition: ProtectConditionFunc,
|
||||||
@ -318,7 +310,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:conditionalProtectOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:conditionalProtectOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
{ moveName: super.getMoveName() },
|
{ moveName: super.getMoveName() },
|
||||||
@ -337,7 +329,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
|||||||
* @param isProtected a {@linkcode BooleanHolder} used to flag if the move is protected against
|
* @param isProtected a {@linkcode BooleanHolder} used to flag if the move is protected against
|
||||||
* @param _attacker the attacking {@linkcode Pokemon}
|
* @param _attacker the attacking {@linkcode Pokemon}
|
||||||
* @param defender the defending {@linkcode Pokemon}
|
* @param defender the defending {@linkcode Pokemon}
|
||||||
* @param moveId the {@linkcode Moves | identifier} for the move being used
|
* @param moveId the {@linkcode MoveId | identifier} for the move being used
|
||||||
* @param ignoresProtectBypass a {@linkcode BooleanHolder} used to flag if a protection effect supercedes effects that ignore protection
|
* @param ignoresProtectBypass a {@linkcode BooleanHolder} used to flag if a protection effect supercedes effects that ignore protection
|
||||||
* @returns `true` if this tag protected against the attack; `false` otherwise
|
* @returns `true` if this tag protected against the attack; `false` otherwise
|
||||||
*/
|
*/
|
||||||
@ -347,7 +339,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
|||||||
isProtected: BooleanHolder,
|
isProtected: BooleanHolder,
|
||||||
_attacker: Pokemon,
|
_attacker: Pokemon,
|
||||||
defender: Pokemon,
|
defender: Pokemon,
|
||||||
moveId: Moves,
|
moveId: MoveId,
|
||||||
ignoresProtectBypass: BooleanHolder,
|
ignoresProtectBypass: BooleanHolder,
|
||||||
): boolean {
|
): boolean {
|
||||||
if ((this.side === ArenaTagSide.PLAYER) === defender.isPlayer() && this.protectConditionFunc(arena, moveId)) {
|
if ((this.side === ArenaTagSide.PLAYER) === defender.isPlayer() && this.protectConditionFunc(arena, moveId)) {
|
||||||
@ -355,7 +347,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
|||||||
isProtected.value = true;
|
isProtected.value = true;
|
||||||
if (!simulated) {
|
if (!simulated) {
|
||||||
new CommonBattleAnim(CommonAnim.PROTECT, defender).play();
|
new CommonBattleAnim(CommonAnim.PROTECT, defender).play();
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:conditionalProtectApply", {
|
i18next.t("arenaTag:conditionalProtectApply", {
|
||||||
moveName: super.getMoveName(),
|
moveName: super.getMoveName(),
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(defender),
|
pokemonNameWithAffix: getPokemonNameWithAffix(defender),
|
||||||
@ -375,15 +367,15 @@ export class ConditionalProtectTag extends ArenaTag {
|
|||||||
* Condition function for {@link https://bulbapedia.bulbagarden.net/wiki/Quick_Guard_(move) Quick Guard's}
|
* Condition function for {@link https://bulbapedia.bulbagarden.net/wiki/Quick_Guard_(move) Quick Guard's}
|
||||||
* protection effect.
|
* protection effect.
|
||||||
* @param _arena {@linkcode Arena} The arena containing the protection effect
|
* @param _arena {@linkcode Arena} The arena containing the protection effect
|
||||||
* @param moveId {@linkcode Moves} The move to check against this condition
|
* @param moveId {@linkcode MoveId} The move to check against this condition
|
||||||
* @returns `true` if the incoming move's priority is greater than 0.
|
* @returns `true` if the incoming move's priority is greater than 0.
|
||||||
* This includes moves with modified priorities from abilities (e.g. Prankster)
|
* This includes moves with modified priorities from abilities (e.g. Prankster)
|
||||||
*/
|
*/
|
||||||
const QuickGuardConditionFunc: ProtectConditionFunc = (_arena, moveId) => {
|
const QuickGuardConditionFunc: ProtectConditionFunc = (_arena, moveId) => {
|
||||||
const move = allMoves[moveId];
|
const move = allMoves[moveId];
|
||||||
const effectPhase = globalScene.getCurrentPhase();
|
const effectPhase = globalScene.phaseManager.getCurrentPhase();
|
||||||
|
|
||||||
if (effectPhase instanceof MoveEffectPhase) {
|
if (effectPhase?.is("MoveEffectPhase")) {
|
||||||
const attacker = effectPhase.getUserPokemon();
|
const attacker = effectPhase.getUserPokemon();
|
||||||
if (attacker) {
|
if (attacker) {
|
||||||
return move.getPriority(attacker) > 0;
|
return move.getPriority(attacker) > 0;
|
||||||
@ -398,7 +390,7 @@ const QuickGuardConditionFunc: ProtectConditionFunc = (_arena, moveId) => {
|
|||||||
*/
|
*/
|
||||||
class QuickGuardTag extends ConditionalProtectTag {
|
class QuickGuardTag extends ConditionalProtectTag {
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.QUICK_GUARD, Moves.QUICK_GUARD, sourceId, side, QuickGuardConditionFunc);
|
super(ArenaTagType.QUICK_GUARD, MoveId.QUICK_GUARD, sourceId, side, QuickGuardConditionFunc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +398,7 @@ class QuickGuardTag extends ConditionalProtectTag {
|
|||||||
* Condition function for {@link https://bulbapedia.bulbagarden.net/wiki/Wide_Guard_(move) Wide Guard's}
|
* Condition function for {@link https://bulbapedia.bulbagarden.net/wiki/Wide_Guard_(move) Wide Guard's}
|
||||||
* protection effect.
|
* protection effect.
|
||||||
* @param _arena {@linkcode Arena} The arena containing the protection effect
|
* @param _arena {@linkcode Arena} The arena containing the protection effect
|
||||||
* @param moveId {@linkcode Moves} The move to check against this condition
|
* @param moveId {@linkcode MoveId} The move to check against this condition
|
||||||
* @returns `true` if the incoming move is multi-targeted (even if it's only used against one Pokemon).
|
* @returns `true` if the incoming move is multi-targeted (even if it's only used against one Pokemon).
|
||||||
*/
|
*/
|
||||||
const WideGuardConditionFunc: ProtectConditionFunc = (_arena, moveId): boolean => {
|
const WideGuardConditionFunc: ProtectConditionFunc = (_arena, moveId): boolean => {
|
||||||
@ -429,7 +421,7 @@ const WideGuardConditionFunc: ProtectConditionFunc = (_arena, moveId): boolean =
|
|||||||
*/
|
*/
|
||||||
class WideGuardTag extends ConditionalProtectTag {
|
class WideGuardTag extends ConditionalProtectTag {
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.WIDE_GUARD, Moves.WIDE_GUARD, sourceId, side, WideGuardConditionFunc);
|
super(ArenaTagType.WIDE_GUARD, MoveId.WIDE_GUARD, sourceId, side, WideGuardConditionFunc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +429,7 @@ class WideGuardTag extends ConditionalProtectTag {
|
|||||||
* Condition function for {@link https://bulbapedia.bulbagarden.net/wiki/Mat_Block_(move) Mat Block's}
|
* Condition function for {@link https://bulbapedia.bulbagarden.net/wiki/Mat_Block_(move) Mat Block's}
|
||||||
* protection effect.
|
* protection effect.
|
||||||
* @param _arena {@linkcode Arena} The arena containing the protection effect.
|
* @param _arena {@linkcode Arena} The arena containing the protection effect.
|
||||||
* @param moveId {@linkcode Moves} The move to check against this condition.
|
* @param moveId {@linkcode MoveId} The move to check against this condition.
|
||||||
* @returns `true` if the incoming move is not a Status move.
|
* @returns `true` if the incoming move is not a Status move.
|
||||||
*/
|
*/
|
||||||
const MatBlockConditionFunc: ProtectConditionFunc = (_arena, moveId): boolean => {
|
const MatBlockConditionFunc: ProtectConditionFunc = (_arena, moveId): boolean => {
|
||||||
@ -451,14 +443,14 @@ const MatBlockConditionFunc: ProtectConditionFunc = (_arena, moveId): boolean =>
|
|||||||
*/
|
*/
|
||||||
class MatBlockTag extends ConditionalProtectTag {
|
class MatBlockTag extends ConditionalProtectTag {
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.MAT_BLOCK, Moves.MAT_BLOCK, sourceId, side, MatBlockConditionFunc);
|
super(ArenaTagType.MAT_BLOCK, MoveId.MAT_BLOCK, sourceId, side, MatBlockConditionFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena) {
|
onAdd(_arena: Arena) {
|
||||||
if (this.sourceId) {
|
if (this.sourceId) {
|
||||||
const source = globalScene.getPokemonById(this.sourceId);
|
const source = globalScene.getPokemonById(this.sourceId);
|
||||||
if (source) {
|
if (source) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:matBlockOnAdd", {
|
i18next.t("arenaTag:matBlockOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
||||||
}),
|
}),
|
||||||
@ -474,7 +466,7 @@ class MatBlockTag extends ConditionalProtectTag {
|
|||||||
* Condition function for {@link https://bulbapedia.bulbagarden.net/wiki/Crafty_Shield_(move) Crafty Shield's}
|
* Condition function for {@link https://bulbapedia.bulbagarden.net/wiki/Crafty_Shield_(move) Crafty Shield's}
|
||||||
* protection effect.
|
* protection effect.
|
||||||
* @param _arena {@linkcode Arena} The arena containing the protection effect
|
* @param _arena {@linkcode Arena} The arena containing the protection effect
|
||||||
* @param moveId {@linkcode Moves} The move to check against this condition
|
* @param moveId {@linkcode MoveId} The move to check against this condition
|
||||||
* @returns `true` if the incoming move is a Status move, is not a hazard, and does not target all
|
* @returns `true` if the incoming move is a Status move, is not a hazard, and does not target all
|
||||||
* Pokemon or sides of the field.
|
* Pokemon or sides of the field.
|
||||||
*/
|
*/
|
||||||
@ -495,7 +487,7 @@ const CraftyShieldConditionFunc: ProtectConditionFunc = (_arena, moveId) => {
|
|||||||
*/
|
*/
|
||||||
class CraftyShieldTag extends ConditionalProtectTag {
|
class CraftyShieldTag extends ConditionalProtectTag {
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.CRAFTY_SHIELD, Moves.CRAFTY_SHIELD, sourceId, side, CraftyShieldConditionFunc, true);
|
super(ArenaTagType.CRAFTY_SHIELD, MoveId.CRAFTY_SHIELD, sourceId, side, CraftyShieldConditionFunc, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,17 +499,17 @@ export class NoCritTag extends ArenaTag {
|
|||||||
/**
|
/**
|
||||||
* Constructor method for the NoCritTag class
|
* Constructor method for the NoCritTag class
|
||||||
* @param turnCount `number` the number of turns this effect lasts
|
* @param turnCount `number` the number of turns this effect lasts
|
||||||
* @param sourceMove {@linkcode Moves} the move that created this effect
|
* @param sourceMove {@linkcode MoveId} the move that created this effect
|
||||||
* @param sourceId `number` the ID of the {@linkcode Pokemon} that created this effect
|
* @param sourceId `number` the ID of the {@linkcode Pokemon} that created this effect
|
||||||
* @param side {@linkcode ArenaTagSide} the side to which this effect belongs
|
* @param side {@linkcode ArenaTagSide} the side to which this effect belongs
|
||||||
*/
|
*/
|
||||||
constructor(turnCount: number, sourceMove: Moves, sourceId: number, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceMove: MoveId, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.NO_CRIT, turnCount, sourceMove, sourceId, side);
|
super(ArenaTagType.NO_CRIT, turnCount, sourceMove, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Queues a message upon adding this effect to the field */
|
/** Queues a message upon adding this effect to the field */
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(`arenaTag:noCritOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : "Enemy"}`, {
|
i18next.t(`arenaTag:noCritOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : "Enemy"}`, {
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
}),
|
}),
|
||||||
@ -527,7 +519,7 @@ export class NoCritTag extends ArenaTag {
|
|||||||
/** Queues a message upon removing this effect from the field */
|
/** Queues a message upon removing this effect from the field */
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
const source = globalScene.getPokemonById(this.sourceId!); // TODO: is this bang correct?
|
const source = globalScene.getPokemonById(this.sourceId!); // TODO: is this bang correct?
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:noCritOnRemove", {
|
i18next.t("arenaTag:noCritOnRemove", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(source ?? undefined),
|
pokemonNameWithAffix: getPokemonNameWithAffix(source ?? undefined),
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
@ -546,7 +538,7 @@ class WishTag extends ArenaTag {
|
|||||||
private healHp: number;
|
private healHp: number;
|
||||||
|
|
||||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.WISH, turnCount, Moves.WISH, sourceId, side);
|
super(ArenaTagType.WISH, turnCount, MoveId.WISH, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
@ -567,8 +559,8 @@ class WishTag extends ArenaTag {
|
|||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
const target = globalScene.getField()[this.battlerIndex];
|
const target = globalScene.getField()[this.battlerIndex];
|
||||||
if (target?.isActive(true)) {
|
if (target?.isActive(true)) {
|
||||||
globalScene.queueMessage(this.triggerMessage);
|
globalScene.phaseManager.queueMessage(this.triggerMessage);
|
||||||
globalScene.unshiftPhase(new PokemonHealPhase(target.getBattlerIndex(), this.healHp, null, true, false));
|
globalScene.phaseManager.unshiftNew("PokemonHealPhase", target.getBattlerIndex(), this.healHp, null, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -588,7 +580,7 @@ export class WeakenMoveTypeTag extends ArenaTag {
|
|||||||
* @param sourceMove - The move that created the tag.
|
* @param sourceMove - The move that created the tag.
|
||||||
* @param sourceId - The ID of the source of the tag.
|
* @param sourceId - The ID of the source of the tag.
|
||||||
*/
|
*/
|
||||||
constructor(tagType: ArenaTagType, turnCount: number, type: PokemonType, sourceMove: Moves, sourceId: number) {
|
constructor(tagType: ArenaTagType, turnCount: number, type: PokemonType, sourceMove: MoveId, sourceId: number) {
|
||||||
super(tagType, turnCount, sourceMove, sourceId);
|
super(tagType, turnCount, sourceMove, sourceId);
|
||||||
|
|
||||||
this.weakenedType = type;
|
this.weakenedType = type;
|
||||||
@ -617,15 +609,15 @@ export class WeakenMoveTypeTag extends ArenaTag {
|
|||||||
*/
|
*/
|
||||||
class MudSportTag extends WeakenMoveTypeTag {
|
class MudSportTag extends WeakenMoveTypeTag {
|
||||||
constructor(turnCount: number, sourceId: number) {
|
constructor(turnCount: number, sourceId: number) {
|
||||||
super(ArenaTagType.MUD_SPORT, turnCount, PokemonType.ELECTRIC, Moves.MUD_SPORT, sourceId);
|
super(ArenaTagType.MUD_SPORT, turnCount, PokemonType.ELECTRIC, MoveId.MUD_SPORT, sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:mudSportOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:mudSportOnAdd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:mudSportOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:mudSportOnRemove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -635,15 +627,15 @@ class MudSportTag extends WeakenMoveTypeTag {
|
|||||||
*/
|
*/
|
||||||
class WaterSportTag extends WeakenMoveTypeTag {
|
class WaterSportTag extends WeakenMoveTypeTag {
|
||||||
constructor(turnCount: number, sourceId: number) {
|
constructor(turnCount: number, sourceId: number) {
|
||||||
super(ArenaTagType.WATER_SPORT, turnCount, PokemonType.FIRE, Moves.WATER_SPORT, sourceId);
|
super(ArenaTagType.WATER_SPORT, turnCount, PokemonType.FIRE, MoveId.WATER_SPORT, sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:waterSportOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:waterSportOnAdd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:waterSportOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:waterSportOnRemove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,13 +645,13 @@ class WaterSportTag extends WeakenMoveTypeTag {
|
|||||||
* Converts Normal-type moves to Electric type for the rest of the turn.
|
* Converts Normal-type moves to Electric type for the rest of the turn.
|
||||||
*/
|
*/
|
||||||
export class IonDelugeTag extends ArenaTag {
|
export class IonDelugeTag extends ArenaTag {
|
||||||
constructor(sourceMove?: Moves) {
|
constructor(sourceMove?: MoveId) {
|
||||||
super(ArenaTagType.ION_DELUGE, 1, sourceMove);
|
super(ArenaTagType.ION_DELUGE, 1, sourceMove);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Queues an on-add message */
|
/** Queues an on-add message */
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:plasmaFistsOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:plasmaFistsOnAdd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {} // Removes default on-remove message
|
onRemove(_arena: Arena): void {} // Removes default on-remove message
|
||||||
@ -696,7 +688,7 @@ export class ArenaTrapTag extends ArenaTag {
|
|||||||
* @param side - The side (player or enemy) the tag affects.
|
* @param side - The side (player or enemy) the tag affects.
|
||||||
* @param maxLayers - The maximum amount of layers this tag can have.
|
* @param maxLayers - The maximum amount of layers this tag can have.
|
||||||
*/
|
*/
|
||||||
constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: number, side: ArenaTagSide, maxLayers: number) {
|
constructor(tagType: ArenaTagType, sourceMove: MoveId, sourceId: number, side: ArenaTagSide, maxLayers: number) {
|
||||||
super(tagType, 0, sourceMove, sourceId, side);
|
super(tagType, 0, sourceMove, sourceId, side);
|
||||||
|
|
||||||
this.layers = 1;
|
this.layers = 1;
|
||||||
@ -750,7 +742,7 @@ export class ArenaTrapTag extends ArenaTag {
|
|||||||
*/
|
*/
|
||||||
class SpikesTag extends ArenaTrapTag {
|
class SpikesTag extends ArenaTrapTag {
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.SPIKES, Moves.SPIKES, sourceId, side, 3);
|
super(ArenaTagType.SPIKES, MoveId.SPIKES, sourceId, side, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(arena: Arena, quiet = false): void {
|
onAdd(arena: Arena, quiet = false): void {
|
||||||
@ -758,7 +750,7 @@ class SpikesTag extends ArenaTrapTag {
|
|||||||
|
|
||||||
const source = this.sourceId ? globalScene.getPokemonById(this.sourceId) : null;
|
const source = this.sourceId ? globalScene.getPokemonById(this.sourceId) : null;
|
||||||
if (!quiet && source) {
|
if (!quiet && source) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:spikesOnAdd", {
|
i18next.t("arenaTag:spikesOnAdd", {
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
opponentDesc: source.getOpponentDescriptor(),
|
opponentDesc: source.getOpponentDescriptor(),
|
||||||
@ -781,7 +773,7 @@ class SpikesTag extends ArenaTrapTag {
|
|||||||
const damageHpRatio = 1 / (10 - 2 * this.layers);
|
const damageHpRatio = 1 / (10 - 2 * this.layers);
|
||||||
const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
||||||
|
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:spikesActivateTrap", {
|
i18next.t("arenaTag:spikesActivateTrap", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
}),
|
}),
|
||||||
@ -802,7 +794,7 @@ class ToxicSpikesTag extends ArenaTrapTag {
|
|||||||
private neutralized: boolean;
|
private neutralized: boolean;
|
||||||
|
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.TOXIC_SPIKES, Moves.TOXIC_SPIKES, sourceId, side, 2);
|
super(ArenaTagType.TOXIC_SPIKES, MoveId.TOXIC_SPIKES, sourceId, side, 2);
|
||||||
this.neutralized = false;
|
this.neutralized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,7 +803,7 @@ class ToxicSpikesTag extends ArenaTrapTag {
|
|||||||
|
|
||||||
const source = this.sourceId ? globalScene.getPokemonById(this.sourceId) : null;
|
const source = this.sourceId ? globalScene.getPokemonById(this.sourceId) : null;
|
||||||
if (!quiet && source) {
|
if (!quiet && source) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:toxicSpikesOnAdd", {
|
i18next.t("arenaTag:toxicSpikesOnAdd", {
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
opponentDesc: source.getOpponentDescriptor(),
|
opponentDesc: source.getOpponentDescriptor(),
|
||||||
@ -834,7 +826,7 @@ class ToxicSpikesTag extends ArenaTrapTag {
|
|||||||
if (pokemon.isOfType(PokemonType.POISON)) {
|
if (pokemon.isOfType(PokemonType.POISON)) {
|
||||||
this.neutralized = true;
|
this.neutralized = true;
|
||||||
if (globalScene.arena.removeTag(this.tagType)) {
|
if (globalScene.arena.removeTag(this.tagType)) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:toxicSpikesActivateTrapPoison", {
|
i18next.t("arenaTag:toxicSpikesActivateTrapPoison", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
@ -867,7 +859,7 @@ class ToxicSpikesTag extends ArenaTrapTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Arena Tag class for delayed attacks, such as {@linkcode Moves.FUTURE_SIGHT} or {@linkcode Moves.DOOM_DESIRE}.
|
* Arena Tag class for delayed attacks, such as {@linkcode MoveId.FUTURE_SIGHT} or {@linkcode MoveId.DOOM_DESIRE}.
|
||||||
* Delays the attack's effect by a set amount of turns, usually 3 (including the turn the move is used),
|
* Delays the attack's effect by a set amount of turns, usually 3 (including the turn the move is used),
|
||||||
* and deals damage after the turn count is reached.
|
* and deals damage after the turn count is reached.
|
||||||
*/
|
*/
|
||||||
@ -876,7 +868,7 @@ export class DelayedAttackTag extends ArenaTag {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
tagType: ArenaTagType,
|
tagType: ArenaTagType,
|
||||||
sourceMove: Moves | undefined,
|
sourceMove: MoveId | undefined,
|
||||||
sourceId: number,
|
sourceId: number,
|
||||||
targetIndex: BattlerIndex,
|
targetIndex: BattlerIndex,
|
||||||
side: ArenaTagSide = ArenaTagSide.BOTH,
|
side: ArenaTagSide = ArenaTagSide.BOTH,
|
||||||
@ -891,8 +883,13 @@ export class DelayedAttackTag extends ArenaTag {
|
|||||||
const ret = super.lapse(arena);
|
const ret = super.lapse(arena);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new MoveEffectPhase(this.sourceId!, [this.targetIndex], allMoves[this.sourceMove!], false, true),
|
"MoveEffectPhase",
|
||||||
|
this.sourceId!,
|
||||||
|
[this.targetIndex],
|
||||||
|
allMoves[this.sourceMove!],
|
||||||
|
false,
|
||||||
|
true,
|
||||||
); // TODO: are those bangs correct?
|
); // TODO: are those bangs correct?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -909,7 +906,7 @@ export class DelayedAttackTag extends ArenaTag {
|
|||||||
*/
|
*/
|
||||||
class StealthRockTag extends ArenaTrapTag {
|
class StealthRockTag extends ArenaTrapTag {
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.STEALTH_ROCK, Moves.STEALTH_ROCK, sourceId, side, 1);
|
super(ArenaTagType.STEALTH_ROCK, MoveId.STEALTH_ROCK, sourceId, side, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(arena: Arena, quiet = false): void {
|
onAdd(arena: Arena, quiet = false): void {
|
||||||
@ -917,7 +914,7 @@ class StealthRockTag extends ArenaTrapTag {
|
|||||||
|
|
||||||
const source = this.sourceId ? globalScene.getPokemonById(this.sourceId) : null;
|
const source = this.sourceId ? globalScene.getPokemonById(this.sourceId) : null;
|
||||||
if (!quiet && source) {
|
if (!quiet && source) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:stealthRockOnAdd", {
|
i18next.t("arenaTag:stealthRockOnAdd", {
|
||||||
opponentDesc: source.getOpponentDescriptor(),
|
opponentDesc: source.getOpponentDescriptor(),
|
||||||
}),
|
}),
|
||||||
@ -971,7 +968,7 @@ class StealthRockTag extends ArenaTrapTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:stealthRockActivateTrap", {
|
i18next.t("arenaTag:stealthRockActivateTrap", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
}),
|
}),
|
||||||
@ -994,14 +991,14 @@ class StealthRockTag extends ArenaTrapTag {
|
|||||||
*/
|
*/
|
||||||
class StickyWebTag extends ArenaTrapTag {
|
class StickyWebTag extends ArenaTrapTag {
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.STICKY_WEB, Moves.STICKY_WEB, sourceId, side, 1);
|
super(ArenaTagType.STICKY_WEB, MoveId.STICKY_WEB, sourceId, side, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(arena: Arena, quiet = false): void {
|
onAdd(arena: Arena, quiet = false): void {
|
||||||
super.onAdd(arena);
|
super.onAdd(arena);
|
||||||
const source = this.sourceId ? globalScene.getPokemonById(this.sourceId) : null;
|
const source = this.sourceId ? globalScene.getPokemonById(this.sourceId) : null;
|
||||||
if (!quiet && source) {
|
if (!quiet && source) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:stickyWebOnAdd", {
|
i18next.t("arenaTag:stickyWebOnAdd", {
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
opponentDesc: source.getOpponentDescriptor(),
|
opponentDesc: source.getOpponentDescriptor(),
|
||||||
@ -1020,25 +1017,24 @@ class StickyWebTag extends ArenaTrapTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!cancelled.value) {
|
if (!cancelled.value) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:stickyWebActivateTrap", {
|
i18next.t("arenaTag:stickyWebActivateTrap", {
|
||||||
pokemonName: pokemon.getNameToRender(),
|
pokemonName: pokemon.getNameToRender(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
const stages = new NumberHolder(-1);
|
const stages = new NumberHolder(-1);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(
|
"StatStageChangePhase",
|
||||||
pokemon.getBattlerIndex(),
|
pokemon.getBattlerIndex(),
|
||||||
false,
|
false,
|
||||||
[Stat.SPD],
|
[Stat.SPD],
|
||||||
stages.value,
|
stages.value,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1055,7 +1051,7 @@ class StickyWebTag extends ArenaTrapTag {
|
|||||||
*/
|
*/
|
||||||
export class TrickRoomTag extends ArenaTag {
|
export class TrickRoomTag extends ArenaTag {
|
||||||
constructor(turnCount: number, sourceId: number) {
|
constructor(turnCount: number, sourceId: number) {
|
||||||
super(ArenaTagType.TRICK_ROOM, turnCount, Moves.TRICK_ROOM, sourceId);
|
super(ArenaTagType.TRICK_ROOM, turnCount, MoveId.TRICK_ROOM, sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1074,7 +1070,7 @@ export class TrickRoomTag extends ArenaTag {
|
|||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
const source = this.sourceId ? globalScene.getPokemonById(this.sourceId) : null;
|
const source = this.sourceId ? globalScene.getPokemonById(this.sourceId) : null;
|
||||||
if (source) {
|
if (source) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:trickRoomOnAdd", {
|
i18next.t("arenaTag:trickRoomOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
||||||
}),
|
}),
|
||||||
@ -1083,22 +1079,22 @@ export class TrickRoomTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:trickRoomOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:trickRoomOnRemove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Gravity_(move) Gravity}.
|
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Gravity_(move) Gravity}.
|
||||||
* Grounds all Pokémon on the field, including Flying-types and those with
|
* Grounds all Pokémon on the field, including Flying-types and those with
|
||||||
* {@linkcode Abilities.LEVITATE} for the duration of the arena tag, usually 5 turns.
|
* {@linkcode AbilityId.LEVITATE} for the duration of the arena tag, usually 5 turns.
|
||||||
*/
|
*/
|
||||||
export class GravityTag extends ArenaTag {
|
export class GravityTag extends ArenaTag {
|
||||||
constructor(turnCount: number) {
|
constructor(turnCount: number) {
|
||||||
super(ArenaTagType.GRAVITY, turnCount, Moves.GRAVITY);
|
super(ArenaTagType.GRAVITY, turnCount, MoveId.GRAVITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:gravityOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:gravityOnAdd"));
|
||||||
globalScene.getField(true).forEach(pokemon => {
|
globalScene.getField(true).forEach(pokemon => {
|
||||||
if (pokemon !== null) {
|
if (pokemon !== null) {
|
||||||
pokemon.removeTag(BattlerTagType.FLOATING);
|
pokemon.removeTag(BattlerTagType.FLOATING);
|
||||||
@ -1111,7 +1107,7 @@ export class GravityTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:gravityOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:gravityOnRemove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1122,12 +1118,12 @@ export class GravityTag extends ArenaTag {
|
|||||||
*/
|
*/
|
||||||
class TailwindTag extends ArenaTag {
|
class TailwindTag extends ArenaTag {
|
||||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side);
|
super(ArenaTagType.TAILWIND, turnCount, MoveId.TAILWIND, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena, quiet = false): void {
|
onAdd(_arena: Arena, quiet = false): void {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:tailwindOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:tailwindOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1136,31 +1132,33 @@ class TailwindTag extends ArenaTag {
|
|||||||
|
|
||||||
const source = globalScene.getPokemonById(this.sourceId!); //TODO: this bang is questionable!
|
const source = globalScene.getPokemonById(this.sourceId!); //TODO: this bang is questionable!
|
||||||
const party = (source?.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField()) ?? [];
|
const party = (source?.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField()) ?? [];
|
||||||
|
const phaseManager = globalScene.phaseManager;
|
||||||
|
|
||||||
for (const pokemon of party) {
|
for (const pokemon of party) {
|
||||||
// Apply the CHARGED tag to party members with the WIND_POWER ability
|
// Apply the CHARGED tag to party members with the WIND_POWER ability
|
||||||
if (pokemon.hasAbility(Abilities.WIND_POWER) && !pokemon.getTag(BattlerTagType.CHARGED)) {
|
if (pokemon.hasAbility(AbilityId.WIND_POWER) && !pokemon.getTag(BattlerTagType.CHARGED)) {
|
||||||
pokemon.addTag(BattlerTagType.CHARGED);
|
pokemon.addTag(BattlerTagType.CHARGED);
|
||||||
globalScene.queueMessage(
|
phaseManager.queueMessage(
|
||||||
i18next.t("abilityTriggers:windPowerCharged", {
|
i18next.t("abilityTriggers:windPowerCharged", {
|
||||||
pokemonName: getPokemonNameWithAffix(pokemon),
|
pokemonName: getPokemonNameWithAffix(pokemon),
|
||||||
moveName: this.getMoveName(),
|
moveName: this.getMoveName(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raise attack by one stage if party member has WIND_RIDER ability
|
// Raise attack by one stage if party member has WIND_RIDER ability
|
||||||
// TODO: Ability displays should be handled by the ability
|
// TODO: Ability displays should be handled by the ability
|
||||||
if (pokemon.hasAbility(Abilities.WIND_RIDER)) {
|
if (pokemon.hasAbility(AbilityId.WIND_RIDER)) {
|
||||||
globalScene.queueAbilityDisplay(pokemon, false, true);
|
phaseManager.queueAbilityDisplay(pokemon, false, true);
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [Stat.ATK], 1, true));
|
phaseManager.unshiftNew("StatStageChangePhase", pokemon.getBattlerIndex(), true, [Stat.ATK], 1, true);
|
||||||
globalScene.queueAbilityDisplay(pokemon, false, false);
|
phaseManager.queueAbilityDisplay(pokemon, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena, quiet = false): void {
|
onRemove(_arena: Arena, quiet = false): void {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:tailwindOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:tailwindOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1171,29 +1169,29 @@ class TailwindTag extends ArenaTag {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Happy_Hour_(move) Happy Hour}.
|
* Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Happy_Hour_(move) Happy Hour}.
|
||||||
* Doubles the prize money from trainers and money moves like {@linkcode Moves.PAY_DAY} and {@linkcode Moves.MAKE_IT_RAIN}.
|
* Doubles the prize money from trainers and money moves like {@linkcode MoveId.PAY_DAY} and {@linkcode MoveId.MAKE_IT_RAIN}.
|
||||||
*/
|
*/
|
||||||
class HappyHourTag extends ArenaTag {
|
class HappyHourTag extends ArenaTag {
|
||||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.HAPPY_HOUR, turnCount, Moves.HAPPY_HOUR, sourceId, side);
|
super(ArenaTagType.HAPPY_HOUR, turnCount, MoveId.HAPPY_HOUR, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:happyHourOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:happyHourOnAdd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:happyHourOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:happyHourOnRemove"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SafeguardTag extends ArenaTag {
|
class SafeguardTag extends ArenaTag {
|
||||||
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.SAFEGUARD, turnCount, Moves.SAFEGUARD, sourceId, side);
|
super(ArenaTagType.SAFEGUARD, turnCount, MoveId.SAFEGUARD, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:safeguardOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:safeguardOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1201,7 +1199,7 @@ class SafeguardTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRemove(_arena: Arena): void {
|
onRemove(_arena: Arena): void {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:safeguardOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:safeguardOnRemove${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1221,7 +1219,7 @@ class NoneTag extends ArenaTag {
|
|||||||
*/
|
*/
|
||||||
class ImprisonTag extends ArenaTrapTag {
|
class ImprisonTag extends ArenaTrapTag {
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.IMPRISON, Moves.IMPRISON, sourceId, side, 1);
|
super(ArenaTagType.IMPRISON, MoveId.IMPRISON, sourceId, side, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1234,10 +1232,10 @@ class ImprisonTag extends ArenaTrapTag {
|
|||||||
const party = this.getAffectedPokemon();
|
const party = this.getAffectedPokemon();
|
||||||
party?.forEach((p: Pokemon) => {
|
party?.forEach((p: Pokemon) => {
|
||||||
if (p.isAllowedInBattle()) {
|
if (p.isAllowedInBattle()) {
|
||||||
p.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId);
|
p.addTag(BattlerTagType.IMPRISON, 1, MoveId.IMPRISON, this.sourceId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("battlerTags:imprisonOnAdd", {
|
i18next.t("battlerTags:imprisonOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
pokemonNameWithAffix: getPokemonNameWithAffix(source),
|
||||||
}),
|
}),
|
||||||
@ -1263,7 +1261,7 @@ class ImprisonTag extends ArenaTrapTag {
|
|||||||
override activateTrap(pokemon: Pokemon): boolean {
|
override activateTrap(pokemon: Pokemon): boolean {
|
||||||
const source = this.getSourcePokemon();
|
const source = this.getSourcePokemon();
|
||||||
if (source?.isActive(true) && pokemon.isAllowedInBattle()) {
|
if (source?.isActive(true) && pokemon.isAllowedInBattle()) {
|
||||||
pokemon.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId);
|
pokemon.addTag(BattlerTagType.IMPRISON, 1, MoveId.IMPRISON, this.sourceId);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1289,12 +1287,12 @@ class ImprisonTag extends ArenaTrapTag {
|
|||||||
*/
|
*/
|
||||||
class FireGrassPledgeTag extends ArenaTag {
|
class FireGrassPledgeTag extends ArenaTag {
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.FIRE_GRASS_PLEDGE, 4, Moves.FIRE_PLEDGE, sourceId, side);
|
super(ArenaTagType.FIRE_GRASS_PLEDGE, 4, MoveId.FIRE_PLEDGE, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
override onAdd(_arena: Arena): void {
|
override onAdd(_arena: Arena): void {
|
||||||
// "A sea of fire enveloped your/the opposing team!"
|
// "A sea of fire enveloped your/the opposing team!"
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:fireGrassPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:fireGrassPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1309,14 +1307,17 @@ class FireGrassPledgeTag extends ArenaTag {
|
|||||||
.filter(pokemon => !pokemon.isOfType(PokemonType.FIRE) && !pokemon.switchOutStatus)
|
.filter(pokemon => !pokemon.isOfType(PokemonType.FIRE) && !pokemon.switchOutStatus)
|
||||||
.forEach(pokemon => {
|
.forEach(pokemon => {
|
||||||
// "{pokemonNameWithAffix} was hurt by the sea of fire!"
|
// "{pokemonNameWithAffix} was hurt by the sea of fire!"
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:fireGrassPledgeLapse", {
|
i18next.t("arenaTag:fireGrassPledgeLapse", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
// TODO: Replace this with a proper animation
|
// TODO: Replace this with a proper animation
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new CommonAnimPhase(pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.MAGMA_STORM),
|
"CommonAnimPhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
CommonAnim.MAGMA_STORM,
|
||||||
);
|
);
|
||||||
pokemon.damageAndUpdate(toDmgValue(pokemon.getMaxHp() / 8), { result: HitResult.INDIRECT });
|
pokemon.damageAndUpdate(toDmgValue(pokemon.getMaxHp() / 8), { result: HitResult.INDIRECT });
|
||||||
});
|
});
|
||||||
@ -1334,12 +1335,12 @@ class FireGrassPledgeTag extends ArenaTag {
|
|||||||
*/
|
*/
|
||||||
class WaterFirePledgeTag extends ArenaTag {
|
class WaterFirePledgeTag extends ArenaTag {
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.WATER_FIRE_PLEDGE, 4, Moves.WATER_PLEDGE, sourceId, side);
|
super(ArenaTagType.WATER_FIRE_PLEDGE, 4, MoveId.WATER_PLEDGE, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
override onAdd(_arena: Arena): void {
|
override onAdd(_arena: Arena): void {
|
||||||
// "A rainbow appeared in the sky on your/the opposing team's side!"
|
// "A rainbow appeared in the sky on your/the opposing team's side!"
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:waterFirePledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:waterFirePledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1368,12 +1369,12 @@ class WaterFirePledgeTag extends ArenaTag {
|
|||||||
*/
|
*/
|
||||||
class GrassWaterPledgeTag extends ArenaTag {
|
class GrassWaterPledgeTag extends ArenaTag {
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.GRASS_WATER_PLEDGE, 4, Moves.GRASS_PLEDGE, sourceId, side);
|
super(ArenaTagType.GRASS_WATER_PLEDGE, 4, MoveId.GRASS_PLEDGE, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
override onAdd(_arena: Arena): void {
|
override onAdd(_arena: Arena): void {
|
||||||
// "A swamp enveloped your/the opposing team!"
|
// "A swamp enveloped your/the opposing team!"
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t(
|
i18next.t(
|
||||||
`arenaTag:grassWaterPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
`arenaTag:grassWaterPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`,
|
||||||
),
|
),
|
||||||
@ -1390,11 +1391,11 @@ class GrassWaterPledgeTag extends ArenaTag {
|
|||||||
*/
|
*/
|
||||||
export class FairyLockTag extends ArenaTag {
|
export class FairyLockTag extends ArenaTag {
|
||||||
constructor(turnCount: number, sourceId: number) {
|
constructor(turnCount: number, sourceId: number) {
|
||||||
super(ArenaTagType.FAIRY_LOCK, turnCount, Moves.FAIRY_LOCK, sourceId);
|
super(ArenaTagType.FAIRY_LOCK, turnCount, MoveId.FAIRY_LOCK, sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(_arena: Arena): void {
|
onAdd(_arena: Arena): void {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:fairyLockOnAdd"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:fairyLockOnAdd"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1451,7 +1452,7 @@ export class SuppressAbilitiesTag extends ArenaTag {
|
|||||||
public override onRemove(_arena: Arena, quiet = false) {
|
public override onRemove(_arena: Arena, quiet = false) {
|
||||||
this.beingRemoved = true;
|
this.beingRemoved = true;
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
globalScene.queueMessage(i18next.t("arenaTag:neutralizingGasOnRemove"));
|
globalScene.phaseManager.queueMessage(i18next.t("arenaTag:neutralizingGasOnRemove"));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const pokemon of globalScene.getField(true)) {
|
for (const pokemon of globalScene.getField(true)) {
|
||||||
@ -1472,7 +1473,7 @@ export class SuppressAbilitiesTag extends ArenaTag {
|
|||||||
|
|
||||||
private playActivationMessage(pokemon: Pokemon | null) {
|
private playActivationMessage(pokemon: Pokemon | null) {
|
||||||
if (pokemon) {
|
if (pokemon) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("arenaTag:neutralizingGasOnAdd", {
|
i18next.t("arenaTag:neutralizingGasOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
}),
|
}),
|
||||||
@ -1485,7 +1486,7 @@ export class SuppressAbilitiesTag extends ArenaTag {
|
|||||||
export function getArenaTag(
|
export function getArenaTag(
|
||||||
tagType: ArenaTagType,
|
tagType: ArenaTagType,
|
||||||
turnCount: number,
|
turnCount: number,
|
||||||
sourceMove: Moves | undefined,
|
sourceMove: MoveId | undefined,
|
||||||
sourceId: number,
|
sourceId: number,
|
||||||
targetIndex?: BattlerIndex,
|
targetIndex?: BattlerIndex,
|
||||||
side: ArenaTagSide = ArenaTagSide.BOTH,
|
side: ArenaTagSide = ArenaTagSide.BOTH,
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
|
||||||
export type SignatureSpecies = {
|
export type SignatureSpecies = {
|
||||||
[key in string]: (Species | Species[])[];
|
[key in string]: (SpeciesId | SpeciesId[])[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,87 +18,87 @@ export type SignatureSpecies = {
|
|||||||
*/
|
*/
|
||||||
export const signatureSpecies: SignatureSpecies = new Proxy({
|
export const signatureSpecies: SignatureSpecies = new Proxy({
|
||||||
// Gym Leaders- Kanto
|
// Gym Leaders- Kanto
|
||||||
BROCK: [Species.ONIX, Species.GEODUDE, [Species.OMANYTE, Species.KABUTO], Species.AERODACTYL],
|
BROCK: [SpeciesId.ONIX, SpeciesId.GEODUDE, [SpeciesId.OMANYTE, SpeciesId.KABUTO], SpeciesId.AERODACTYL],
|
||||||
MISTY: [Species.STARYU, Species.PSYDUCK, Species.WOOPER, Species.LAPRAS],
|
MISTY: [SpeciesId.STARYU, SpeciesId.PSYDUCK, SpeciesId.WOOPER, SpeciesId.LAPRAS],
|
||||||
LT_SURGE: [Species.PICHU, Species.VOLTORB, Species.ELEKID, Species.JOLTEON],
|
LT_SURGE: [SpeciesId.PICHU, SpeciesId.VOLTORB, SpeciesId.ELEKID, SpeciesId.JOLTEON],
|
||||||
ERIKA: [Species.ODDISH, Species.BELLSPROUT, Species.TANGELA, Species.HOPPIP],
|
ERIKA: [SpeciesId.ODDISH, SpeciesId.BELLSPROUT, SpeciesId.TANGELA, SpeciesId.HOPPIP],
|
||||||
JANINE: [Species.VENONAT, Species.SPINARAK, Species.ZUBAT, Species.KOFFING],
|
JANINE: [SpeciesId.VENONAT, SpeciesId.SPINARAK, SpeciesId.ZUBAT, SpeciesId.KOFFING],
|
||||||
SABRINA: [Species.ABRA, Species.MR_MIME, Species.SMOOCHUM, Species.ESPEON],
|
SABRINA: [SpeciesId.ABRA, SpeciesId.MR_MIME, SpeciesId.SMOOCHUM, SpeciesId.ESPEON],
|
||||||
BLAINE: [Species.GROWLITHE, Species.PONYTA, Species.MAGBY, Species.VULPIX],
|
BLAINE: [SpeciesId.GROWLITHE, SpeciesId.PONYTA, SpeciesId.MAGBY, SpeciesId.VULPIX],
|
||||||
GIOVANNI: [Species.RHYHORN, Species.MEOWTH, [Species.NIDORAN_F, Species.NIDORAN_M], Species.DIGLETT], // Tera Ground Meowth
|
GIOVANNI: [SpeciesId.RHYHORN, SpeciesId.MEOWTH, [SpeciesId.NIDORAN_F, SpeciesId.NIDORAN_M], SpeciesId.DIGLETT], // Tera Ground Meowth
|
||||||
// Gym Leaders- Johto
|
// Gym Leaders- Johto
|
||||||
FALKNER: [Species.PIDGEY, Species.HOOTHOOT, Species.NATU, Species.MURKROW],
|
FALKNER: [SpeciesId.PIDGEY, SpeciesId.HOOTHOOT, SpeciesId.NATU, SpeciesId.MURKROW],
|
||||||
BUGSY: [Species.SCYTHER, Species.SHUCKLE, Species.YANMA, [Species.PINSIR, Species.HERACROSS]],
|
BUGSY: [SpeciesId.SCYTHER, SpeciesId.SHUCKLE, SpeciesId.YANMA, [SpeciesId.PINSIR, SpeciesId.HERACROSS]],
|
||||||
WHITNEY: [Species.MILTANK, Species.AIPOM, Species.IGGLYBUFF, [Species.GIRAFARIG, Species.STANTLER]],
|
WHITNEY: [SpeciesId.MILTANK, SpeciesId.AIPOM, SpeciesId.IGGLYBUFF, [SpeciesId.GIRAFARIG, SpeciesId.STANTLER]],
|
||||||
MORTY: [Species.GASTLY, Species.MISDREAVUS, Species.DUSKULL, Species.SABLEYE],
|
MORTY: [SpeciesId.GASTLY, SpeciesId.MISDREAVUS, SpeciesId.DUSKULL, SpeciesId.SABLEYE],
|
||||||
CHUCK: [Species.POLIWRATH, Species.MANKEY, Species.TYROGUE, Species.MACHOP],
|
CHUCK: [SpeciesId.POLIWRATH, SpeciesId.MANKEY, SpeciesId.TYROGUE, SpeciesId.MACHOP],
|
||||||
JASMINE: [Species.STEELIX, Species.MAGNEMITE, Species.PINECO, Species.SKARMORY],
|
JASMINE: [SpeciesId.STEELIX, SpeciesId.MAGNEMITE, SpeciesId.PINECO, SpeciesId.SKARMORY],
|
||||||
PRYCE: [Species.SWINUB, Species.SEEL, Species.SHELLDER, Species.SNEASEL],
|
PRYCE: [SpeciesId.SWINUB, SpeciesId.SEEL, SpeciesId.SHELLDER, SpeciesId.SNEASEL],
|
||||||
CLAIR: [Species.HORSEA, Species.DRATINI, Species.MAGIKARP, Species.DRUDDIGON], // Tera Dragon Magikarp
|
CLAIR: [SpeciesId.HORSEA, SpeciesId.DRATINI, SpeciesId.MAGIKARP, SpeciesId.DRUDDIGON], // Tera Dragon Magikarp
|
||||||
// Gym Leaders- Hoenn
|
// Gym Leaders- Hoenn
|
||||||
ROXANNE: [Species.NOSEPASS, Species.GEODUDE, [Species.LILEEP, Species.ANORITH], Species.ARON],
|
ROXANNE: [SpeciesId.NOSEPASS, SpeciesId.GEODUDE, [SpeciesId.LILEEP, SpeciesId.ANORITH], SpeciesId.ARON],
|
||||||
BRAWLY: [Species.MAKUHITA, Species.MACHOP, Species.MEDITITE, Species.SHROOMISH],
|
BRAWLY: [SpeciesId.MAKUHITA, SpeciesId.MACHOP, SpeciesId.MEDITITE, SpeciesId.SHROOMISH],
|
||||||
WATTSON: [Species.ELECTRIKE, Species.VOLTORB, Species.MAGNEMITE, [Species.PLUSLE, Species.MINUN]],
|
WATTSON: [SpeciesId.ELECTRIKE, SpeciesId.VOLTORB, SpeciesId.MAGNEMITE, [SpeciesId.PLUSLE, SpeciesId.MINUN]],
|
||||||
FLANNERY: [Species.TORKOAL, Species.SLUGMA, Species.NUMEL, Species.HOUNDOUR],
|
FLANNERY: [SpeciesId.TORKOAL, SpeciesId.SLUGMA, SpeciesId.NUMEL, SpeciesId.HOUNDOUR],
|
||||||
NORMAN: [Species.SLAKOTH, Species.KECLEON, Species.WHISMUR, Species.ZANGOOSE],
|
NORMAN: [SpeciesId.SLAKOTH, SpeciesId.KECLEON, SpeciesId.WHISMUR, SpeciesId.ZANGOOSE],
|
||||||
WINONA: [Species.SWABLU, Species.WINGULL, Species.TROPIUS, Species.SKARMORY],
|
WINONA: [SpeciesId.SWABLU, SpeciesId.WINGULL, SpeciesId.TROPIUS, SpeciesId.SKARMORY],
|
||||||
TATE: [Species.SOLROCK, Species.NATU, Species.CHINGLING, Species.GALLADE],
|
TATE: [SpeciesId.SOLROCK, SpeciesId.NATU, SpeciesId.CHINGLING, SpeciesId.GALLADE],
|
||||||
LIZA: [Species.LUNATONE, Species.BALTOY, Species.SPOINK, Species.GARDEVOIR],
|
LIZA: [SpeciesId.LUNATONE, SpeciesId.BALTOY, SpeciesId.SPOINK, SpeciesId.GARDEVOIR],
|
||||||
JUAN: [Species.HORSEA, Species.SPHEAL, Species.BARBOACH, Species.CORPHISH],
|
JUAN: [SpeciesId.HORSEA, SpeciesId.SPHEAL, SpeciesId.BARBOACH, SpeciesId.CORPHISH],
|
||||||
// Gym Leaders- Sinnoh
|
// Gym Leaders- Sinnoh
|
||||||
ROARK: [Species.CRANIDOS, Species.GEODUDE, Species.NOSEPASS, Species.LARVITAR],
|
ROARK: [SpeciesId.CRANIDOS, SpeciesId.GEODUDE, SpeciesId.NOSEPASS, SpeciesId.LARVITAR],
|
||||||
GARDENIA: [Species.BUDEW, Species.CHERUBI, Species.TURTWIG, Species.LEAFEON],
|
GARDENIA: [SpeciesId.BUDEW, SpeciesId.CHERUBI, SpeciesId.TURTWIG, SpeciesId.LEAFEON],
|
||||||
MAYLENE: [Species.RIOLU, Species.MEDITITE, Species.CHIMCHAR, Species.CROAGUNK],
|
MAYLENE: [SpeciesId.RIOLU, SpeciesId.MEDITITE, SpeciesId.CHIMCHAR, SpeciesId.CROAGUNK],
|
||||||
CRASHER_WAKE: [Species.BUIZEL, Species.WOOPER, Species.PIPLUP, Species.MAGIKARP],
|
CRASHER_WAKE: [SpeciesId.BUIZEL, SpeciesId.WOOPER, SpeciesId.PIPLUP, SpeciesId.MAGIKARP],
|
||||||
FANTINA: [Species.MISDREAVUS, Species.DRIFLOON, Species.DUSKULL, Species.SPIRITOMB],
|
FANTINA: [SpeciesId.MISDREAVUS, SpeciesId.DRIFLOON, SpeciesId.DUSKULL, SpeciesId.SPIRITOMB],
|
||||||
BYRON: [Species.SHIELDON, Species.BRONZOR, Species.ARON, Species.SKARMORY],
|
BYRON: [SpeciesId.SHIELDON, SpeciesId.BRONZOR, SpeciesId.ARON, SpeciesId.SKARMORY],
|
||||||
CANDICE: [Species.FROSLASS, Species.SNOVER, Species.SNEASEL, Species.GLACEON],
|
CANDICE: [SpeciesId.FROSLASS, SpeciesId.SNOVER, SpeciesId.SNEASEL, SpeciesId.GLACEON],
|
||||||
VOLKNER: [Species.ELEKID, Species.SHINX, Species.CHINCHOU, Species.ROTOM],
|
VOLKNER: [SpeciesId.ELEKID, SpeciesId.SHINX, SpeciesId.CHINCHOU, SpeciesId.ROTOM],
|
||||||
// Gym Leaders- Unova
|
// Gym Leaders- Unova
|
||||||
CILAN: [Species.PANSAGE, Species.SNIVY, Species.MARACTUS, Species.FERROSEED],
|
CILAN: [SpeciesId.PANSAGE, SpeciesId.SNIVY, SpeciesId.MARACTUS, SpeciesId.FERROSEED],
|
||||||
CHILI: [Species.PANSEAR, Species.TEPIG, Species.HEATMOR, Species.DARUMAKA],
|
CHILI: [SpeciesId.PANSEAR, SpeciesId.TEPIG, SpeciesId.HEATMOR, SpeciesId.DARUMAKA],
|
||||||
CRESS: [Species.PANPOUR, Species.OSHAWOTT, Species.BASCULIN, Species.TYMPOLE],
|
CRESS: [SpeciesId.PANPOUR, SpeciesId.OSHAWOTT, SpeciesId.BASCULIN, SpeciesId.TYMPOLE],
|
||||||
CHEREN: [Species.LILLIPUP, Species.MINCCINO, Species.PIDOVE, Species.BOUFFALANT],
|
CHEREN: [SpeciesId.LILLIPUP, SpeciesId.MINCCINO, SpeciesId.PIDOVE, SpeciesId.BOUFFALANT],
|
||||||
LENORA: [Species.PATRAT, Species.DEERLING, Species.AUDINO, Species.BRAVIARY],
|
LENORA: [SpeciesId.PATRAT, SpeciesId.DEERLING, SpeciesId.AUDINO, SpeciesId.BRAVIARY],
|
||||||
ROXIE: [Species.VENIPEDE, Species.KOFFING, Species.TRUBBISH, Species.TOXEL],
|
ROXIE: [SpeciesId.VENIPEDE, SpeciesId.KOFFING, SpeciesId.TRUBBISH, SpeciesId.TOXEL],
|
||||||
BURGH: [Species.SEWADDLE, Species.DWEBBLE, [Species.KARRABLAST, Species.SHELMET], Species.DURANT],
|
BURGH: [SpeciesId.SEWADDLE, SpeciesId.DWEBBLE, [SpeciesId.KARRABLAST, SpeciesId.SHELMET], SpeciesId.DURANT],
|
||||||
ELESA: [Species.BLITZLE, Species.EMOLGA, Species.JOLTIK, Species.TYNAMO],
|
ELESA: [SpeciesId.BLITZLE, SpeciesId.EMOLGA, SpeciesId.JOLTIK, SpeciesId.TYNAMO],
|
||||||
CLAY: [Species.DRILBUR, Species.SANDILE, Species.TYMPOLE, Species.GOLETT],
|
CLAY: [SpeciesId.DRILBUR, SpeciesId.SANDILE, SpeciesId.TYMPOLE, SpeciesId.GOLETT],
|
||||||
SKYLA: [Species.DUCKLETT, Species.WOOBAT, [Species.RUFFLET, Species.VULLABY], Species.ARCHEN],
|
SKYLA: [SpeciesId.DUCKLETT, SpeciesId.WOOBAT, [SpeciesId.RUFFLET, SpeciesId.VULLABY], SpeciesId.ARCHEN],
|
||||||
BRYCEN: [Species.CRYOGONAL, Species.VANILLITE, Species.CUBCHOO, Species.GALAR_DARUMAKA],
|
BRYCEN: [SpeciesId.CRYOGONAL, SpeciesId.VANILLITE, SpeciesId.CUBCHOO, SpeciesId.GALAR_DARUMAKA],
|
||||||
DRAYDEN: [Species.AXEW, Species.DRUDDIGON, Species.TRAPINCH, Species.DEINO],
|
DRAYDEN: [SpeciesId.AXEW, SpeciesId.DRUDDIGON, SpeciesId.TRAPINCH, SpeciesId.DEINO],
|
||||||
MARLON: [Species.FRILLISH, Species.TIRTOUGA, Species.WAILMER, Species.MANTYKE],
|
MARLON: [SpeciesId.FRILLISH, SpeciesId.TIRTOUGA, SpeciesId.WAILMER, SpeciesId.MANTYKE],
|
||||||
// Gym Leaders- Kalos
|
// Gym Leaders- Kalos
|
||||||
VIOLA: [Species.SCATTERBUG, Species.SURSKIT, Species.CUTIEFLY, Species.BLIPBUG],
|
VIOLA: [SpeciesId.SCATTERBUG, SpeciesId.SURSKIT, SpeciesId.CUTIEFLY, SpeciesId.BLIPBUG],
|
||||||
GRANT: [Species.TYRUNT, Species.AMAURA, Species.BINACLE, Species.DWEBBLE],
|
GRANT: [SpeciesId.TYRUNT, SpeciesId.AMAURA, SpeciesId.BINACLE, SpeciesId.DWEBBLE],
|
||||||
KORRINA: [Species.RIOLU, Species.MIENFOO, Species.HAWLUCHA, Species.PANCHAM],
|
KORRINA: [SpeciesId.RIOLU, SpeciesId.MIENFOO, SpeciesId.HAWLUCHA, SpeciesId.PANCHAM],
|
||||||
RAMOS: [Species.SKIDDO, Species.HOPPIP, Species.BELLSPROUT, [Species.PHANTUMP, Species.PUMPKABOO]],
|
RAMOS: [SpeciesId.SKIDDO, SpeciesId.HOPPIP, SpeciesId.BELLSPROUT, [SpeciesId.PHANTUMP, SpeciesId.PUMPKABOO]],
|
||||||
CLEMONT: [Species.HELIOPTILE, Species.MAGNEMITE, Species.DEDENNE, Species.ROTOM],
|
CLEMONT: [SpeciesId.HELIOPTILE, SpeciesId.MAGNEMITE, SpeciesId.DEDENNE, SpeciesId.ROTOM],
|
||||||
VALERIE: [Species.SYLVEON, Species.MAWILE, Species.MR_MIME, [Species.SPRITZEE, Species.SWIRLIX]],
|
VALERIE: [SpeciesId.SYLVEON, SpeciesId.MAWILE, SpeciesId.MR_MIME, [SpeciesId.SPRITZEE, SpeciesId.SWIRLIX]],
|
||||||
OLYMPIA: [Species.ESPURR, Species.SIGILYPH, Species.INKAY, Species.SLOWKING],
|
OLYMPIA: [SpeciesId.ESPURR, SpeciesId.SIGILYPH, SpeciesId.INKAY, SpeciesId.SLOWKING],
|
||||||
WULFRIC: [Species.BERGMITE, Species.SNOVER, Species.CRYOGONAL, Species.SWINUB],
|
WULFRIC: [SpeciesId.BERGMITE, SpeciesId.SNOVER, SpeciesId.CRYOGONAL, SpeciesId.SWINUB],
|
||||||
// Gym Leaders- Galar
|
// Gym Leaders- Galar
|
||||||
MILO: [Species.GOSSIFLEUR, Species.SEEDOT, Species.APPLIN, Species.LOTAD],
|
MILO: [SpeciesId.GOSSIFLEUR, SpeciesId.SEEDOT, SpeciesId.APPLIN, SpeciesId.LOTAD],
|
||||||
NESSA: [Species.CHEWTLE, Species.WIMPOD, Species.ARROKUDA, Species.MAREANIE],
|
NESSA: [SpeciesId.CHEWTLE, SpeciesId.WIMPOD, SpeciesId.ARROKUDA, SpeciesId.MAREANIE],
|
||||||
KABU: [Species.SIZZLIPEDE, Species.VULPIX, Species.GROWLITHE, Species.TORKOAL],
|
KABU: [SpeciesId.SIZZLIPEDE, SpeciesId.VULPIX, SpeciesId.GROWLITHE, SpeciesId.TORKOAL],
|
||||||
BEA: [Species.MACHOP, Species.GALAR_FARFETCHD, Species.CLOBBOPUS, Species.FALINKS],
|
BEA: [SpeciesId.MACHOP, SpeciesId.GALAR_FARFETCHD, SpeciesId.CLOBBOPUS, SpeciesId.FALINKS],
|
||||||
ALLISTER: [Species.GASTLY, Species.GALAR_YAMASK, Species.GALAR_CORSOLA, Species.SINISTEA],
|
ALLISTER: [SpeciesId.GASTLY, SpeciesId.GALAR_YAMASK, SpeciesId.GALAR_CORSOLA, SpeciesId.SINISTEA],
|
||||||
OPAL: [Species.MILCERY, Species.GALAR_WEEZING, Species.TOGEPI, Species.MAWILE],
|
OPAL: [SpeciesId.MILCERY, SpeciesId.GALAR_WEEZING, SpeciesId.TOGEPI, SpeciesId.MAWILE],
|
||||||
BEDE: [Species.HATENNA, Species.GALAR_PONYTA, Species.GARDEVOIR, Species.SYLVEON],
|
BEDE: [SpeciesId.HATENNA, SpeciesId.GALAR_PONYTA, SpeciesId.GARDEVOIR, SpeciesId.SYLVEON],
|
||||||
GORDIE: [Species.ROLYCOLY, [Species.SHUCKLE, Species.BINACLE], Species.STONJOURNER, Species.LARVITAR],
|
GORDIE: [SpeciesId.ROLYCOLY, [SpeciesId.SHUCKLE, SpeciesId.BINACLE], SpeciesId.STONJOURNER, SpeciesId.LARVITAR],
|
||||||
MELONY: [Species.LAPRAS, Species.SNOM, Species.EISCUE, [Species.GALAR_MR_MIME, Species.GALAR_DARUMAKA]],
|
MELONY: [SpeciesId.LAPRAS, SpeciesId.SNOM, SpeciesId.EISCUE, [SpeciesId.GALAR_MR_MIME, SpeciesId.GALAR_DARUMAKA]],
|
||||||
PIERS: [Species.GALAR_ZIGZAGOON, Species.SCRAGGY, Species.TOXEL, Species.INKAY], // Tera Dark Toxel
|
PIERS: [SpeciesId.GALAR_ZIGZAGOON, SpeciesId.SCRAGGY, SpeciesId.TOXEL, SpeciesId.INKAY], // Tera Dark Toxel
|
||||||
MARNIE: [Species.IMPIDIMP, Species.MORPEKO, Species.PURRLOIN, Species.CROAGUNK], // Tera Dark Croagunk
|
MARNIE: [SpeciesId.IMPIDIMP, SpeciesId.MORPEKO, SpeciesId.PURRLOIN, SpeciesId.CROAGUNK], // Tera Dark Croagunk
|
||||||
RAIHAN: [Species.DURALUDON, Species.TRAPINCH, Species.GOOMY, Species.TURTONATOR],
|
RAIHAN: [SpeciesId.DURALUDON, SpeciesId.TRAPINCH, SpeciesId.GOOMY, SpeciesId.TURTONATOR],
|
||||||
// Gym Leaders- Paldea; First slot is Tera
|
// Gym Leaders- Paldea; First slot is Tera
|
||||||
KATY: [Species.TEDDIURSA, Species.NYMBLE, Species.TAROUNTULA, Species.RELLOR], // Tera Bug Teddiursa
|
KATY: [SpeciesId.TEDDIURSA, SpeciesId.NYMBLE, SpeciesId.TAROUNTULA, SpeciesId.RELLOR], // Tera Bug Teddiursa
|
||||||
BRASSIUS: [Species.BONSLY, Species.SMOLIV, Species.BRAMBLIN, Species.SUNKERN], // Tera Grass Bonsly
|
BRASSIUS: [SpeciesId.BONSLY, SpeciesId.SMOLIV, SpeciesId.BRAMBLIN, SpeciesId.SUNKERN], // Tera Grass Bonsly
|
||||||
IONO: [Species.MISDREAVUS, Species.TADBULB, Species.WATTREL, Species.MAGNEMITE], // Tera Ghost Misdreavus
|
IONO: [SpeciesId.MISDREAVUS, SpeciesId.TADBULB, SpeciesId.WATTREL, SpeciesId.MAGNEMITE], // Tera Ghost Misdreavus
|
||||||
KOFU: [Species.CRABRAWLER, Species.VELUZA, Species.WIGLETT, Species.WINGULL], // Tera Water Crabrawler
|
KOFU: [SpeciesId.CRABRAWLER, SpeciesId.VELUZA, SpeciesId.WIGLETT, SpeciesId.WINGULL], // Tera Water Crabrawler
|
||||||
LARRY: [Species.STARLY, Species.DUNSPARCE, Species.LECHONK, Species.KOMALA], // Tera Normal Starly
|
LARRY: [SpeciesId.STARLY, SpeciesId.DUNSPARCE, SpeciesId.LECHONK, SpeciesId.KOMALA], // Tera Normal Starly
|
||||||
RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel
|
RYME: [SpeciesId.TOXEL, SpeciesId.GREAVARD, SpeciesId.SHUPPET, SpeciesId.MIMIKYU], // Tera Ghost Toxel
|
||||||
TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe
|
TULIP: [SpeciesId.FLABEBE, SpeciesId.FLITTLE, SpeciesId.RALTS, SpeciesId.GIRAFARIG], // Tera Psychic Flabebe
|
||||||
GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.SNOM, Species.CUBCHOO], // Tera Ice Swablu
|
GRUSHA: [SpeciesId.SWABLU, SpeciesId.CETODDLE, SpeciesId.SNOM, SpeciesId.CUBCHOO], // Tera Ice Swablu
|
||||||
}, {
|
}, {
|
||||||
get(target, prop: string) {
|
get(target, prop: string) {
|
||||||
return target[prop as keyof SignatureSpecies] ?? [];
|
return target[prop as keyof SignatureSpecies] ?? [];
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of all {@link https://bulbapedia.bulbagarden.net/wiki/Paradox_Pok%C3%A9mon | Paradox Pokemon}, NOT including the legendaries Miraidon and Koraidon.
|
* A list of all {@link https://bulbapedia.bulbagarden.net/wiki/Paradox_Pok%C3%A9mon | Paradox Pokemon}, NOT including the legendaries Miraidon and Koraidon.
|
||||||
*/
|
*/
|
||||||
export const NON_LEGEND_PARADOX_POKEMON = [
|
export const NON_LEGEND_PARADOX_POKEMON = [
|
||||||
Species.GREAT_TUSK,
|
SpeciesId.GREAT_TUSK,
|
||||||
Species.SCREAM_TAIL,
|
SpeciesId.SCREAM_TAIL,
|
||||||
Species.BRUTE_BONNET,
|
SpeciesId.BRUTE_BONNET,
|
||||||
Species.FLUTTER_MANE,
|
SpeciesId.FLUTTER_MANE,
|
||||||
Species.SLITHER_WING,
|
SpeciesId.SLITHER_WING,
|
||||||
Species.SANDY_SHOCKS,
|
SpeciesId.SANDY_SHOCKS,
|
||||||
Species.ROARING_MOON,
|
SpeciesId.ROARING_MOON,
|
||||||
Species.WALKING_WAKE,
|
SpeciesId.WALKING_WAKE,
|
||||||
Species.GOUGING_FIRE,
|
SpeciesId.GOUGING_FIRE,
|
||||||
Species.RAGING_BOLT,
|
SpeciesId.RAGING_BOLT,
|
||||||
Species.IRON_TREADS,
|
SpeciesId.IRON_TREADS,
|
||||||
Species.IRON_BUNDLE,
|
SpeciesId.IRON_BUNDLE,
|
||||||
Species.IRON_HANDS,
|
SpeciesId.IRON_HANDS,
|
||||||
Species.IRON_JUGULIS,
|
SpeciesId.IRON_JUGULIS,
|
||||||
Species.IRON_MOTH,
|
SpeciesId.IRON_MOTH,
|
||||||
Species.IRON_THORNS,
|
SpeciesId.IRON_THORNS,
|
||||||
Species.IRON_VALIANT,
|
SpeciesId.IRON_VALIANT,
|
||||||
Species.IRON_LEAVES,
|
SpeciesId.IRON_LEAVES,
|
||||||
Species.IRON_BOULDER,
|
SpeciesId.IRON_BOULDER,
|
||||||
Species.IRON_CROWN,
|
SpeciesId.IRON_CROWN,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,15 +32,15 @@ export const NON_LEGEND_PARADOX_POKEMON = [
|
|||||||
* Note that all of these Ultra Beasts are still considered Sub-Legendary.
|
* Note that all of these Ultra Beasts are still considered Sub-Legendary.
|
||||||
*/
|
*/
|
||||||
export const NON_LEGEND_ULTRA_BEASTS = [
|
export const NON_LEGEND_ULTRA_BEASTS = [
|
||||||
Species.NIHILEGO,
|
SpeciesId.NIHILEGO,
|
||||||
Species.BUZZWOLE,
|
SpeciesId.BUZZWOLE,
|
||||||
Species.PHEROMOSA,
|
SpeciesId.PHEROMOSA,
|
||||||
Species.XURKITREE,
|
SpeciesId.XURKITREE,
|
||||||
Species.CELESTEELA,
|
SpeciesId.CELESTEELA,
|
||||||
Species.KARTANA,
|
SpeciesId.KARTANA,
|
||||||
Species.GUZZLORD,
|
SpeciesId.GUZZLORD,
|
||||||
Species.POIPOLE,
|
SpeciesId.POIPOLE,
|
||||||
Species.NAGANADEL,
|
SpeciesId.NAGANADEL,
|
||||||
Species.STAKATAKA,
|
SpeciesId.STAKATAKA,
|
||||||
Species.BLACEPHALON,
|
SpeciesId.BLACEPHALON,
|
||||||
];
|
];
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
136103
src/data/balance/tms.ts
136103
src/data/balance/tms.ts
File diff suppressed because it is too large
Load Diff
@ -1,111 +1,15 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { AttackMove, BeakBlastHeaderAttr, DelayedAttackAttr, SelfStatusMove } from "./moves/move";
|
|
||||||
import { allMoves } from "./data-lists";
|
import { allMoves } from "./data-lists";
|
||||||
import { MoveFlags } from "#enums/MoveFlags";
|
import { MoveFlags } from "#enums/MoveFlags";
|
||||||
import type Pokemon from "../field/pokemon";
|
import type Pokemon from "../field/pokemon";
|
||||||
import { type nil, getFrameMs, getEnumKeys, getEnumValues, animationFileName } from "../utils/common";
|
import { type nil, getFrameMs, getEnumKeys, getEnumValues, animationFileName } from "../utils/common";
|
||||||
import type { BattlerIndex } from "../battle";
|
import type { BattlerIndex } from "#enums/battler-index";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { SubstituteTag } from "./battler-tags";
|
import { SubstituteTag } from "./battler-tags";
|
||||||
import { isNullOrUndefined } from "../utils/common";
|
import { isNullOrUndefined } from "../utils/common";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import { EncounterAnim } from "#enums/encounter-anims";
|
import { EncounterAnim } from "#enums/encounter-anims";
|
||||||
|
import { AnimBlendType, AnimFrameTarget, AnimFocus, ChargeAnim, CommonAnim } from "#enums/move-anims-common";
|
||||||
export enum AnimFrameTarget {
|
|
||||||
USER,
|
|
||||||
TARGET,
|
|
||||||
GRAPHIC,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AnimFocus {
|
|
||||||
TARGET = 1,
|
|
||||||
USER,
|
|
||||||
USER_TARGET,
|
|
||||||
SCREEN,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AnimBlendType {
|
|
||||||
NORMAL,
|
|
||||||
ADD,
|
|
||||||
SUBTRACT,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ChargeAnim {
|
|
||||||
FLY_CHARGING = 1000,
|
|
||||||
BOUNCE_CHARGING,
|
|
||||||
DIG_CHARGING,
|
|
||||||
FUTURE_SIGHT_CHARGING,
|
|
||||||
DIVE_CHARGING,
|
|
||||||
SOLAR_BEAM_CHARGING,
|
|
||||||
SHADOW_FORCE_CHARGING,
|
|
||||||
SKULL_BASH_CHARGING,
|
|
||||||
FREEZE_SHOCK_CHARGING,
|
|
||||||
SKY_DROP_CHARGING,
|
|
||||||
SKY_ATTACK_CHARGING,
|
|
||||||
ICE_BURN_CHARGING,
|
|
||||||
DOOM_DESIRE_CHARGING,
|
|
||||||
RAZOR_WIND_CHARGING,
|
|
||||||
PHANTOM_FORCE_CHARGING,
|
|
||||||
GEOMANCY_CHARGING,
|
|
||||||
SHADOW_BLADE_CHARGING,
|
|
||||||
SOLAR_BLADE_CHARGING,
|
|
||||||
BEAK_BLAST_CHARGING,
|
|
||||||
METEOR_BEAM_CHARGING,
|
|
||||||
ELECTRO_SHOT_CHARGING,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum CommonAnim {
|
|
||||||
USE_ITEM = 2000,
|
|
||||||
HEALTH_UP,
|
|
||||||
TERASTALLIZE,
|
|
||||||
POISON = 2010,
|
|
||||||
TOXIC,
|
|
||||||
PARALYSIS,
|
|
||||||
SLEEP,
|
|
||||||
FROZEN,
|
|
||||||
BURN,
|
|
||||||
CONFUSION,
|
|
||||||
ATTRACT,
|
|
||||||
BIND,
|
|
||||||
WRAP,
|
|
||||||
CURSE_NO_GHOST,
|
|
||||||
LEECH_SEED,
|
|
||||||
FIRE_SPIN,
|
|
||||||
PROTECT,
|
|
||||||
COVET,
|
|
||||||
WHIRLPOOL,
|
|
||||||
BIDE,
|
|
||||||
SAND_TOMB,
|
|
||||||
QUICK_GUARD,
|
|
||||||
WIDE_GUARD,
|
|
||||||
CURSE,
|
|
||||||
MAGMA_STORM,
|
|
||||||
CLAMP,
|
|
||||||
SNAP_TRAP,
|
|
||||||
THUNDER_CAGE,
|
|
||||||
INFESTATION,
|
|
||||||
ORDER_UP_CURLY,
|
|
||||||
ORDER_UP_DROOPY,
|
|
||||||
ORDER_UP_STRETCHY,
|
|
||||||
RAGING_BULL_FIRE,
|
|
||||||
RAGING_BULL_WATER,
|
|
||||||
SALT_CURE,
|
|
||||||
POWDER,
|
|
||||||
SUNNY = 2100,
|
|
||||||
RAIN,
|
|
||||||
SANDSTORM,
|
|
||||||
HAIL,
|
|
||||||
SNOW,
|
|
||||||
WIND,
|
|
||||||
HEAVY_RAIN,
|
|
||||||
HARSH_SUN,
|
|
||||||
STRONG_WINDS,
|
|
||||||
MISTY_TERRAIN = 2110,
|
|
||||||
ELECTRIC_TERRAIN,
|
|
||||||
GRASSY_TERRAIN,
|
|
||||||
PSYCHIC_TERRAIN,
|
|
||||||
LOCK_ON = 2120,
|
|
||||||
}
|
|
||||||
|
|
||||||
export class AnimConfig {
|
export class AnimConfig {
|
||||||
public id: number;
|
public id: number;
|
||||||
@ -498,7 +402,7 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const moveAnims = new Map<Moves, AnimConfig | [AnimConfig, AnimConfig] | null>();
|
export const moveAnims = new Map<MoveId, AnimConfig | [AnimConfig, AnimConfig] | null>();
|
||||||
export const chargeAnims = new Map<ChargeAnim, AnimConfig | [AnimConfig, AnimConfig] | null>();
|
export const chargeAnims = new Map<ChargeAnim, AnimConfig | [AnimConfig, AnimConfig] | null>();
|
||||||
export const commonAnims = new Map<CommonAnim, AnimConfig>();
|
export const commonAnims = new Map<CommonAnim, AnimConfig>();
|
||||||
export const encounterAnims = new Map<EncounterAnim, AnimConfig>();
|
export const encounterAnims = new Map<EncounterAnim, AnimConfig>();
|
||||||
@ -521,7 +425,7 @@ export function initCommonAnims(): Promise<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initMoveAnim(move: Moves): Promise<void> {
|
export function initMoveAnim(move: MoveId): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
if (moveAnims.has(move)) {
|
if (moveAnims.has(move)) {
|
||||||
if (moveAnims.get(move) !== null) {
|
if (moveAnims.get(move) !== null) {
|
||||||
@ -531,7 +435,7 @@ export function initMoveAnim(move: Moves): Promise<void> {
|
|||||||
if (moveAnims.get(move) !== null) {
|
if (moveAnims.get(move) !== null) {
|
||||||
const chargeAnimSource = allMoves[move].isChargingMove()
|
const chargeAnimSource = allMoves[move].isChargingMove()
|
||||||
? allMoves[move]
|
? allMoves[move]
|
||||||
: (allMoves[move].getAttrs(DelayedAttackAttr)[0] ?? allMoves[move].getAttrs(BeakBlastHeaderAttr)[0]);
|
: (allMoves[move].getAttrs("DelayedAttackAttr")[0] ?? allMoves[move].getAttrs("BeakBlastHeaderAttr")[0]);
|
||||||
if (chargeAnimSource && chargeAnims.get(chargeAnimSource.chargeAnim) === null) {
|
if (chargeAnimSource && chargeAnims.get(chargeAnimSource.chargeAnim) === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -542,14 +446,13 @@ export function initMoveAnim(move: Moves): Promise<void> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
moveAnims.set(move, null);
|
moveAnims.set(move, null);
|
||||||
const defaultMoveAnim =
|
const defaultMoveAnim = allMoves[move].is("AttackMove")
|
||||||
allMoves[move] instanceof AttackMove
|
? MoveId.TACKLE
|
||||||
? Moves.TACKLE
|
: allMoves[move].is("SelfStatusMove")
|
||||||
: allMoves[move] instanceof SelfStatusMove
|
? MoveId.FOCUS_ENERGY
|
||||||
? Moves.FOCUS_ENERGY
|
: MoveId.TAIL_WHIP;
|
||||||
: Moves.TAIL_WHIP;
|
|
||||||
|
|
||||||
const fetchAnimAndResolve = (move: Moves) => {
|
const fetchAnimAndResolve = (move: MoveId) => {
|
||||||
globalScene
|
globalScene
|
||||||
.cachedFetch(`./battle-anims/${animationFileName(move)}.json`)
|
.cachedFetch(`./battle-anims/${animationFileName(move)}.json`)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
@ -570,7 +473,7 @@ export function initMoveAnim(move: Moves): Promise<void> {
|
|||||||
}
|
}
|
||||||
const chargeAnimSource = allMoves[move].isChargingMove()
|
const chargeAnimSource = allMoves[move].isChargingMove()
|
||||||
? allMoves[move]
|
? allMoves[move]
|
||||||
: (allMoves[move].getAttrs(DelayedAttackAttr)[0] ?? allMoves[move].getAttrs(BeakBlastHeaderAttr)[0]);
|
: (allMoves[move].getAttrs("DelayedAttackAttr")[0] ?? allMoves[move].getAttrs("BeakBlastHeaderAttr")[0]);
|
||||||
if (chargeAnimSource) {
|
if (chargeAnimSource) {
|
||||||
initMoveChargeAnim(chargeAnimSource.chargeAnim).then(() => resolve());
|
initMoveChargeAnim(chargeAnimSource.chargeAnim).then(() => resolve());
|
||||||
} else {
|
} else {
|
||||||
@ -594,7 +497,7 @@ export function initMoveAnim(move: Moves): Promise<void> {
|
|||||||
* @param move the move to populate an animation for
|
* @param move the move to populate an animation for
|
||||||
* @param defaultMoveAnim the move to use as the default animation
|
* @param defaultMoveAnim the move to use as the default animation
|
||||||
*/
|
*/
|
||||||
function useDefaultAnim(move: Moves, defaultMoveAnim: Moves) {
|
function useDefaultAnim(move: MoveId, defaultMoveAnim: MoveId) {
|
||||||
populateMoveAnim(move, moveAnims.get(defaultMoveAnim));
|
populateMoveAnim(move, moveAnims.get(defaultMoveAnim));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,7 +509,7 @@ function useDefaultAnim(move: Moves, defaultMoveAnim: Moves) {
|
|||||||
*
|
*
|
||||||
* @remarks use {@linkcode useDefaultAnim} to use a default animation
|
* @remarks use {@linkcode useDefaultAnim} to use a default animation
|
||||||
*/
|
*/
|
||||||
function logMissingMoveAnim(move: Moves, ...optionalParams: any[]) {
|
function logMissingMoveAnim(move: MoveId, ...optionalParams: any[]) {
|
||||||
const moveName = animationFileName(move);
|
const moveName = animationFileName(move);
|
||||||
console.warn(`Could not load animation file for move '${moveName}'`, ...optionalParams);
|
console.warn(`Could not load animation file for move '${moveName}'`, ...optionalParams);
|
||||||
}
|
}
|
||||||
@ -664,7 +567,7 @@ export function initMoveChargeAnim(chargeAnim: ChargeAnim): Promise<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateMoveAnim(move: Moves, animSource: any): void {
|
function populateMoveAnim(move: MoveId, animSource: any): void {
|
||||||
const moveAnim = new AnimConfig(animSource);
|
const moveAnim = new AnimConfig(animSource);
|
||||||
if (moveAnims.get(move) === null) {
|
if (moveAnims.get(move) === null) {
|
||||||
moveAnims.set(move, moveAnim);
|
moveAnims.set(move, moveAnim);
|
||||||
@ -697,13 +600,13 @@ export async function loadEncounterAnimAssets(startLoad?: boolean): Promise<void
|
|||||||
await loadAnimAssets(Array.from(encounterAnims.values()), startLoad);
|
await loadAnimAssets(Array.from(encounterAnims.values()), startLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function loadMoveAnimAssets(moveIds: Moves[], startLoad?: boolean): Promise<void> {
|
export function loadMoveAnimAssets(moveIds: MoveId[], startLoad?: boolean): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const moveAnimations = moveIds.flatMap(m => moveAnims.get(m) as AnimConfig);
|
const moveAnimations = moveIds.flatMap(m => moveAnims.get(m) as AnimConfig);
|
||||||
for (const moveId of moveIds) {
|
for (const moveId of moveIds) {
|
||||||
const chargeAnimSource = allMoves[moveId].isChargingMove()
|
const chargeAnimSource = allMoves[moveId].isChargingMove()
|
||||||
? allMoves[moveId]
|
? allMoves[moveId]
|
||||||
: (allMoves[moveId].getAttrs(DelayedAttackAttr)[0] ?? allMoves[moveId].getAttrs(BeakBlastHeaderAttr)[0]);
|
: (allMoves[moveId].getAttrs("DelayedAttackAttr")[0] ?? allMoves[moveId].getAttrs("BeakBlastHeaderAttr")[0]);
|
||||||
if (chargeAnimSource) {
|
if (chargeAnimSource) {
|
||||||
const moveChargeAnims = chargeAnims.get(chargeAnimSource.chargeAnim);
|
const moveChargeAnims = chargeAnims.get(chargeAnimSource.chargeAnim);
|
||||||
moveAnimations.push(moveChargeAnims instanceof AnimConfig ? moveChargeAnims : moveChargeAnims![0]); // TODO: is the bang correct?
|
moveAnimations.push(moveChargeAnims instanceof AnimConfig ? moveChargeAnims : moveChargeAnims![0]); // TODO: is the bang correct?
|
||||||
@ -1425,9 +1328,9 @@ export class CommonBattleAnim extends BattleAnim {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MoveAnim extends BattleAnim {
|
export class MoveAnim extends BattleAnim {
|
||||||
public move: Moves;
|
public move: MoveId;
|
||||||
|
|
||||||
constructor(move: Moves, user: Pokemon, target: BattlerIndex, playOnEmptyField = false) {
|
constructor(move: MoveId, user: Pokemon, target: BattlerIndex, playOnEmptyField = false) {
|
||||||
// Set target to the user pokemon if no target is found to avoid crashes
|
// Set target to the user pokemon if no target is found to avoid crashes
|
||||||
super(user, globalScene.getField()[target] ?? user, playOnEmptyField);
|
super(user, globalScene.getField()[target] ?? user, playOnEmptyField);
|
||||||
|
|
||||||
@ -1456,7 +1359,7 @@ export class MoveAnim extends BattleAnim {
|
|||||||
export class MoveChargeAnim extends MoveAnim {
|
export class MoveChargeAnim extends MoveAnim {
|
||||||
private chargeAnim: ChargeAnim;
|
private chargeAnim: ChargeAnim;
|
||||||
|
|
||||||
constructor(chargeAnim: ChargeAnim, move: Moves, user: Pokemon) {
|
constructor(chargeAnim: ChargeAnim, move: MoveId, user: Pokemon) {
|
||||||
super(move, user, 0);
|
super(move, user, 0);
|
||||||
|
|
||||||
this.chargeAnim = chargeAnim;
|
this.chargeAnim = chargeAnim;
|
||||||
@ -1502,8 +1405,8 @@ export async function populateAnims() {
|
|||||||
const chargeAnimIds = getEnumValues(ChargeAnim) as ChargeAnim[];
|
const chargeAnimIds = getEnumValues(ChargeAnim) as ChargeAnim[];
|
||||||
const commonNamePattern = /name: (?:Common:)?(Opp )?(.*)/;
|
const commonNamePattern = /name: (?:Common:)?(Opp )?(.*)/;
|
||||||
const moveNameToId = {};
|
const moveNameToId = {};
|
||||||
for (const move of getEnumValues(Moves).slice(1)) {
|
for (const move of getEnumValues(MoveId).slice(1)) {
|
||||||
const moveName = Moves[move].toUpperCase().replace(/\_/g, "");
|
const moveName = MoveId[move].toUpperCase().replace(/\_/g, "");
|
||||||
moveNameToId[moveName] = move;
|
moveNameToId[moveName] = move;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,19 +1,13 @@
|
|||||||
import { getPokemonNameWithAffix } from "../messages";
|
import { getPokemonNameWithAffix } from "../messages";
|
||||||
import type Pokemon from "../field/pokemon";
|
import type Pokemon from "../field/pokemon";
|
||||||
import { HitResult } from "../field/pokemon";
|
import { HitResult } from "#enums/hit-result";
|
||||||
import { getStatusEffectHealText } from "./status-effect";
|
import { getStatusEffectHealText } from "./status-effect";
|
||||||
import { NumberHolder, toDmgValue, randSeedInt } from "#app/utils/common";
|
import { NumberHolder, toDmgValue, randSeedInt } from "#app/utils/common";
|
||||||
import {
|
import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./abilities/ability";
|
||||||
DoubleBerryEffectAbAttr,
|
|
||||||
ReduceBerryUseThresholdAbAttr,
|
|
||||||
applyAbAttrs,
|
|
||||||
} from "./abilities/ability";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { Stat, type BattleStat } from "#app/enums/stat";
|
import { Stat, type BattleStat } from "#app/enums/stat";
|
||||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
|
||||||
export function getBerryName(berryType: BerryType): string {
|
export function getBerryName(berryType: BerryType): string {
|
||||||
@ -79,23 +73,22 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
|||||||
{
|
{
|
||||||
const hpHealed = new NumberHolder(toDmgValue(consumer.getMaxHp() / 4));
|
const hpHealed = new NumberHolder(toDmgValue(consumer.getMaxHp() / 4));
|
||||||
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, hpHealed);
|
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, hpHealed);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new PokemonHealPhase(
|
"PokemonHealPhase",
|
||||||
consumer.getBattlerIndex(),
|
consumer.getBattlerIndex(),
|
||||||
hpHealed.value,
|
hpHealed.value,
|
||||||
i18next.t("battle:hpHealBerry", {
|
i18next.t("battle:hpHealBerry", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(consumer),
|
pokemonNameWithAffix: getPokemonNameWithAffix(consumer),
|
||||||
berryName: getBerryName(berryType),
|
berryName: getBerryName(berryType),
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BerryType.LUM:
|
case BerryType.LUM:
|
||||||
{
|
{
|
||||||
if (consumer.status) {
|
if (consumer.status) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
getStatusEffectHealText(consumer.status.effect, getPokemonNameWithAffix(consumer)),
|
getStatusEffectHealText(consumer.status.effect, getPokemonNameWithAffix(consumer)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -113,8 +106,12 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
|||||||
const stat: BattleStat = berryType - BerryType.ENIGMA;
|
const stat: BattleStat = berryType - BerryType.ENIGMA;
|
||||||
const statStages = new NumberHolder(1);
|
const statStages = new NumberHolder(1);
|
||||||
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, statStages);
|
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, statStages);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(consumer.getBattlerIndex(), true, [stat], statStages.value),
|
"StatStageChangePhase",
|
||||||
|
consumer.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[stat],
|
||||||
|
statStages.value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -130,8 +127,12 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
|||||||
const randStat = randSeedInt(Stat.SPD, Stat.ATK);
|
const randStat = randSeedInt(Stat.SPD, Stat.ATK);
|
||||||
const stages = new NumberHolder(2);
|
const stages = new NumberHolder(2);
|
||||||
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, stages);
|
applyAbAttrs(DoubleBerryEffectAbAttr, consumer, null, false, stages);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(consumer.getBattlerIndex(), true, [randStat], stages.value),
|
"StatStageChangePhase",
|
||||||
|
consumer.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[randStat],
|
||||||
|
stages.value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -144,7 +145,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
|||||||
consumer.getMoveset().find(m => m.ppUsed < m.getMovePp());
|
consumer.getMoveset().find(m => m.ppUsed < m.getMovePp());
|
||||||
if (ppRestoreMove) {
|
if (ppRestoreMove) {
|
||||||
ppRestoreMove.ppUsed = Math.max(ppRestoreMove.ppUsed - 10, 0);
|
ppRestoreMove.ppUsed = Math.max(ppRestoreMove.ppUsed - 10, 0);
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("battle:ppHealBerry", {
|
i18next.t("battle:ppHealBerry", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(consumer),
|
pokemonNameWithAffix: getPokemonNameWithAffix(consumer),
|
||||||
moveName: ppRestoreMove.getName(),
|
moveName: ppRestoreMove.getName(),
|
||||||
|
@ -2,115 +2,35 @@ import { BooleanHolder, type NumberHolder, randSeedItem } from "#app/utils/commo
|
|||||||
import { deepCopy } from "#app/utils/data";
|
import { deepCopy } from "#app/utils/data";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type { DexAttrProps, GameData } from "#app/system/game-data";
|
import type { DexAttrProps, GameData } from "#app/system/game-data";
|
||||||
import { defaultStarterSpecies } from "#app/system/game-data";
|
import { defaultStarterSpecies } from "#app/constants";
|
||||||
import type PokemonSpecies from "#app/data/pokemon-species";
|
import type PokemonSpecies from "#app/data/pokemon-species";
|
||||||
import { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
import { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "./moves/pokemon-move";
|
||||||
import type { FixedBattleConfig } from "#app/battle";
|
import type { FixedBattleConfig } from "#app/battle";
|
||||||
import { getRandomTrainerFunc } from "#app/battle";
|
import { getRandomTrainerFunc } from "#app/battle";
|
||||||
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
||||||
import { BattleType } from "#enums/battle-type";
|
import { BattleType } from "#enums/battle-type";
|
||||||
import Trainer, { TrainerVariant } from "#app/field/trainer";
|
import Trainer from "#app/field/trainer";
|
||||||
|
import { TrainerVariant } from "#enums/trainer-variant";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { Challenges } from "#enums/challenges";
|
import { Challenges } from "#enums/challenges";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import type { Moves } from "#enums/moves";
|
import type { MoveId } from "#enums/move-id";
|
||||||
import { TypeColor, TypeShadow } from "#enums/color";
|
import { TypeColor, TypeShadow } from "#enums/color";
|
||||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { pokemonFormChanges } from "./pokemon-forms";
|
import { pokemonFormChanges } from "./pokemon-forms";
|
||||||
import { pokemonEvolutions } from "./balance/pokemon-evolutions";
|
import { pokemonEvolutions } from "./balance/pokemon-evolutions";
|
||||||
|
import { ChallengeType } from "#enums/challenge-type";
|
||||||
|
import type { MoveSourceType } from "#enums/move-source-type";
|
||||||
|
|
||||||
/** A constant for the default max cost of the starting party before a run */
|
/** A constant for the default max cost of the starting party before a run */
|
||||||
const DEFAULT_PARTY_MAX_COST = 10;
|
const DEFAULT_PARTY_MAX_COST = 10;
|
||||||
|
|
||||||
/**
|
|
||||||
* An enum for all the challenge types. The parameter entries on these describe the
|
|
||||||
* parameters to use when calling the applyChallenges function.
|
|
||||||
*/
|
|
||||||
export enum ChallengeType {
|
|
||||||
/**
|
|
||||||
* Challenges which modify what starters you can choose
|
|
||||||
* @see {@link Challenge.applyStarterChoice}
|
|
||||||
*/
|
|
||||||
STARTER_CHOICE,
|
|
||||||
/**
|
|
||||||
* Challenges which modify how many starter points you have
|
|
||||||
* @see {@link Challenge.applyStarterPoints}
|
|
||||||
*/
|
|
||||||
STARTER_POINTS,
|
|
||||||
/**
|
|
||||||
* Challenges which modify how many starter points you have
|
|
||||||
* @see {@link Challenge.applyStarterPointCost}
|
|
||||||
*/
|
|
||||||
STARTER_COST,
|
|
||||||
/**
|
|
||||||
* Challenges which modify your starters in some way
|
|
||||||
* @see {@link Challenge.applyStarterModify}
|
|
||||||
*/
|
|
||||||
STARTER_MODIFY,
|
|
||||||
/**
|
|
||||||
* Challenges which limit which pokemon you can have in battle.
|
|
||||||
* @see {@link Challenge.applyPokemonInBattle}
|
|
||||||
*/
|
|
||||||
POKEMON_IN_BATTLE,
|
|
||||||
/**
|
|
||||||
* Adds or modifies the fixed battles in a run
|
|
||||||
* @see {@link Challenge.applyFixedBattle}
|
|
||||||
*/
|
|
||||||
FIXED_BATTLES,
|
|
||||||
/**
|
|
||||||
* Modifies the effectiveness of Type matchups in battle
|
|
||||||
* @see {@linkcode Challenge.applyTypeEffectiveness}
|
|
||||||
*/
|
|
||||||
TYPE_EFFECTIVENESS,
|
|
||||||
/**
|
|
||||||
* Modifies what level the AI pokemon are. UNIMPLEMENTED.
|
|
||||||
*/
|
|
||||||
AI_LEVEL,
|
|
||||||
/**
|
|
||||||
* Modifies how many move slots the AI has. UNIMPLEMENTED.
|
|
||||||
*/
|
|
||||||
AI_MOVE_SLOTS,
|
|
||||||
/**
|
|
||||||
* Modifies if a pokemon has its passive. UNIMPLEMENTED.
|
|
||||||
*/
|
|
||||||
PASSIVE_ACCESS,
|
|
||||||
/**
|
|
||||||
* Modifies the game mode settings in some way. UNIMPLEMENTED.
|
|
||||||
*/
|
|
||||||
GAME_MODE_MODIFY,
|
|
||||||
/**
|
|
||||||
* Modifies what level AI pokemon can access a move. UNIMPLEMENTED.
|
|
||||||
*/
|
|
||||||
MOVE_ACCESS,
|
|
||||||
/**
|
|
||||||
* Modifies what weight AI pokemon have when generating movesets. UNIMPLEMENTED.
|
|
||||||
*/
|
|
||||||
MOVE_WEIGHT,
|
|
||||||
/**
|
|
||||||
* Modifies what the pokemon stats for Flip Stat Mode.
|
|
||||||
*/
|
|
||||||
FLIP_STAT,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used for challenge types that modify movesets, these denote the various sources of moves for pokemon.
|
|
||||||
*/
|
|
||||||
export enum MoveSourceType {
|
|
||||||
LEVEL_UP, // Currently unimplemented for move access
|
|
||||||
RELEARNER, // Relearner moves currently unimplemented
|
|
||||||
COMMON_TM,
|
|
||||||
GREAT_TM,
|
|
||||||
ULTRA_TM,
|
|
||||||
COMMON_EGG,
|
|
||||||
RARE_EGG,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A challenge object. Exists only to serve as a base class.
|
* A challenge object. Exists only to serve as a base class.
|
||||||
*/
|
*/
|
||||||
@ -305,11 +225,11 @@ export abstract class Challenge {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* An apply function for STARTER_COST challenges. Derived classes should alter this.
|
* An apply function for STARTER_COST challenges. Derived classes should alter this.
|
||||||
* @param _species {@link Species} The pokemon to change the cost of.
|
* @param _species {@link SpeciesId} The pokemon to change the cost of.
|
||||||
* @param _cost {@link NumberHolder} The cost of the starter.
|
* @param _cost {@link NumberHolder} The cost of the starter.
|
||||||
* @returns {@link boolean} Whether this function did anything.
|
* @returns {@link boolean} Whether this function did anything.
|
||||||
*/
|
*/
|
||||||
applyStarterCost(_species: Species, _cost: NumberHolder): boolean {
|
applyStarterCost(_species: SpeciesId, _cost: NumberHolder): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,11 +315,11 @@ export abstract class Challenge {
|
|||||||
* An apply function for MOVE_ACCESS. Derived classes should alter this.
|
* An apply function for MOVE_ACCESS. Derived classes should alter this.
|
||||||
* @param _pokemon {@link Pokemon} What pokemon would learn the move.
|
* @param _pokemon {@link Pokemon} What pokemon would learn the move.
|
||||||
* @param _moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
* @param _moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
||||||
* @param _move {@link Moves} The move in question.
|
* @param _move {@link MoveId} The move in question.
|
||||||
* @param _level {@link NumberHolder} The level threshold for access.
|
* @param _level {@link NumberHolder} The level threshold for access.
|
||||||
* @returns {@link boolean} Whether this function did anything.
|
* @returns {@link boolean} Whether this function did anything.
|
||||||
*/
|
*/
|
||||||
applyMoveAccessLevel(_pokemon: Pokemon, _moveSource: MoveSourceType, _move: Moves, _level: NumberHolder): boolean {
|
applyMoveAccessLevel(_pokemon: Pokemon, _moveSource: MoveSourceType, _move: MoveId, _level: NumberHolder): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,11 +327,11 @@ export abstract class Challenge {
|
|||||||
* An apply function for MOVE_WEIGHT. Derived classes should alter this.
|
* An apply function for MOVE_WEIGHT. Derived classes should alter this.
|
||||||
* @param _pokemon {@link Pokemon} What pokemon would learn the move.
|
* @param _pokemon {@link Pokemon} What pokemon would learn the move.
|
||||||
* @param _moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
* @param _moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
||||||
* @param _move {@link Moves} The move in question.
|
* @param _move {@link MoveId} The move in question.
|
||||||
* @param _weight {@link NumberHolder} The base weight of the move
|
* @param _weight {@link NumberHolder} The base weight of the move
|
||||||
* @returns {@link boolean} Whether this function did anything.
|
* @returns {@link boolean} Whether this function did anything.
|
||||||
*/
|
*/
|
||||||
applyMoveWeight(_pokemon: Pokemon, _moveSource: MoveSourceType, _move: Moves, _level: NumberHolder): boolean {
|
applyMoveWeight(_pokemon: Pokemon, _moveSource: MoveSourceType, _move: MoveId, _level: NumberHolder): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -696,7 +616,7 @@ export class SingleGenerationChallenge extends Challenge {
|
|||||||
|
|
||||||
interface monotypeOverride {
|
interface monotypeOverride {
|
||||||
/** The species to override */
|
/** The species to override */
|
||||||
species: Species;
|
species: SpeciesId;
|
||||||
/** The type to count as */
|
/** The type to count as */
|
||||||
type: PokemonType;
|
type: PokemonType;
|
||||||
/** If part of a fusion, should we check the fused species instead of the base species? */
|
/** If part of a fusion, should we check the fused species instead of the base species? */
|
||||||
@ -708,7 +628,7 @@ interface monotypeOverride {
|
|||||||
*/
|
*/
|
||||||
export class SingleTypeChallenge extends Challenge {
|
export class SingleTypeChallenge extends Challenge {
|
||||||
private static TYPE_OVERRIDES: monotypeOverride[] = [
|
private static TYPE_OVERRIDES: monotypeOverride[] = [
|
||||||
{ species: Species.CASTFORM, type: PokemonType.NORMAL, fusion: false },
|
{ species: SpeciesId.CASTFORM, type: PokemonType.NORMAL, fusion: false },
|
||||||
];
|
];
|
||||||
// TODO: Find a solution for all Pokemon with this ssui issue, including Basculin and Burmy
|
// TODO: Find a solution for all Pokemon with this ssui issue, including Basculin and Burmy
|
||||||
|
|
||||||
@ -804,7 +724,7 @@ export class FreshStartChallenge extends Challenge {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyStarterCost(species: Species, cost: NumberHolder): boolean {
|
applyStarterCost(species: SpeciesId, cost: NumberHolder): boolean {
|
||||||
if (defaultStarterSpecies.includes(species)) {
|
if (defaultStarterSpecies.includes(species)) {
|
||||||
cost.value = speciesStarterCosts[species];
|
cost.value = speciesStarterCosts[species];
|
||||||
return true;
|
return true;
|
||||||
@ -992,13 +912,13 @@ export function applyChallenges(challengeType: ChallengeType.STARTER_POINTS, poi
|
|||||||
/**
|
/**
|
||||||
* Apply all challenges that modify the cost of a starter.
|
* Apply all challenges that modify the cost of a starter.
|
||||||
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_COST
|
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_COST
|
||||||
* @param species {@link Species} The pokemon to change the cost of.
|
* @param species {@link SpeciesId} The pokemon to change the cost of.
|
||||||
* @param points {@link NumberHolder} The cost of the pokemon.
|
* @param points {@link NumberHolder} The cost of the pokemon.
|
||||||
* @returns True if any challenge was successfully applied.
|
* @returns True if any challenge was successfully applied.
|
||||||
*/
|
*/
|
||||||
export function applyChallenges(
|
export function applyChallenges(
|
||||||
challengeType: ChallengeType.STARTER_COST,
|
challengeType: ChallengeType.STARTER_COST,
|
||||||
species: Species,
|
species: SpeciesId,
|
||||||
cost: NumberHolder,
|
cost: NumberHolder,
|
||||||
): boolean;
|
): boolean;
|
||||||
/**
|
/**
|
||||||
@ -1090,7 +1010,7 @@ export function applyChallenges(challengeType: ChallengeType.GAME_MODE_MODIFY):
|
|||||||
* @param challengeType {@link ChallengeType} ChallengeType.MOVE_ACCESS
|
* @param challengeType {@link ChallengeType} ChallengeType.MOVE_ACCESS
|
||||||
* @param pokemon {@link Pokemon} What pokemon would learn the move.
|
* @param pokemon {@link Pokemon} What pokemon would learn the move.
|
||||||
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
||||||
* @param move {@link Moves} The move in question.
|
* @param move {@link MoveId} The move in question.
|
||||||
* @param level {@link NumberHolder} The level threshold for access.
|
* @param level {@link NumberHolder} The level threshold for access.
|
||||||
* @returns True if any challenge was successfully applied.
|
* @returns True if any challenge was successfully applied.
|
||||||
*/
|
*/
|
||||||
@ -1098,7 +1018,7 @@ export function applyChallenges(
|
|||||||
challengeType: ChallengeType.MOVE_ACCESS,
|
challengeType: ChallengeType.MOVE_ACCESS,
|
||||||
pokemon: Pokemon,
|
pokemon: Pokemon,
|
||||||
moveSource: MoveSourceType,
|
moveSource: MoveSourceType,
|
||||||
move: Moves,
|
move: MoveId,
|
||||||
level: NumberHolder,
|
level: NumberHolder,
|
||||||
): boolean;
|
): boolean;
|
||||||
/**
|
/**
|
||||||
@ -1106,7 +1026,7 @@ export function applyChallenges(
|
|||||||
* @param challengeType {@link ChallengeType} ChallengeType.MOVE_WEIGHT
|
* @param challengeType {@link ChallengeType} ChallengeType.MOVE_WEIGHT
|
||||||
* @param pokemon {@link Pokemon} What pokemon would learn the move.
|
* @param pokemon {@link Pokemon} What pokemon would learn the move.
|
||||||
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
||||||
* @param move {@link Moves} The move in question.
|
* @param move {@link MoveId} The move in question.
|
||||||
* @param weight {@link NumberHolder} The weight of the move.
|
* @param weight {@link NumberHolder} The weight of the move.
|
||||||
* @returns True if any challenge was successfully applied.
|
* @returns True if any challenge was successfully applied.
|
||||||
*/
|
*/
|
||||||
@ -1114,7 +1034,7 @@ export function applyChallenges(
|
|||||||
challengeType: ChallengeType.MOVE_WEIGHT,
|
challengeType: ChallengeType.MOVE_WEIGHT,
|
||||||
pokemon: Pokemon,
|
pokemon: Pokemon,
|
||||||
moveSource: MoveSourceType,
|
moveSource: MoveSourceType,
|
||||||
move: Moves,
|
move: MoveId,
|
||||||
weight: NumberHolder,
|
weight: NumberHolder,
|
||||||
): boolean;
|
): boolean;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { Abilities } from "#enums/abilities";
|
import type { AbilityId } from "#enums/ability-id";
|
||||||
import type { PokemonType } from "#enums/pokemon-type";
|
import type { PokemonType } from "#enums/pokemon-type";
|
||||||
import type { Nature } from "#enums/nature";
|
import type { Nature } from "#enums/nature";
|
||||||
|
|
||||||
@ -12,8 +12,8 @@ export class CustomPokemonData {
|
|||||||
* The scale at which to render this Pokemon's sprite.
|
* The scale at which to render this Pokemon's sprite.
|
||||||
*/
|
*/
|
||||||
public spriteScale = -1;
|
public spriteScale = -1;
|
||||||
public ability: Abilities | -1;
|
public ability: AbilityId | -1;
|
||||||
public passive: Abilities | -1;
|
public passive: AbilityId | -1;
|
||||||
public nature: Nature | -1;
|
public nature: Nature | -1;
|
||||||
public types: PokemonType[];
|
public types: PokemonType[];
|
||||||
/** Deprecated but needed for session save migration */
|
/** Deprecated but needed for session save migration */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import type { Species } from "#enums/species";
|
import type { SpeciesId } from "#enums/species-id";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { PlayerPokemon } from "#app/field/pokemon";
|
import { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import type { Starter } from "#app/ui/starter-select-ui-handler";
|
import type { Starter } from "#app/ui/starter-select-ui-handler";
|
||||||
@ -8,7 +8,7 @@ import type { PokemonSpeciesForm } from "#app/data/pokemon-species";
|
|||||||
import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||||
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
|
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
|
||||||
import { Biome } from "#app/enums/biome";
|
import { BiomeId } from "#enums/biome-id";
|
||||||
|
|
||||||
export interface DailyRunConfig {
|
export interface DailyRunConfig {
|
||||||
seed: number;
|
seed: number;
|
||||||
@ -34,7 +34,7 @@ export function getDailyRunStarters(seed: string): Starter[] {
|
|||||||
for (let s = 0; s < 3; s++) {
|
for (let s = 0; s < 3; s++) {
|
||||||
const offset = 6 + s * 6;
|
const offset = 6 + s * 6;
|
||||||
const starterSpeciesForm = getPokemonSpeciesForm(
|
const starterSpeciesForm = getPokemonSpeciesForm(
|
||||||
Number.parseInt(seed.slice(offset, offset + 4)) as Species,
|
Number.parseInt(seed.slice(offset, offset + 4)) as SpeciesId,
|
||||||
Number.parseInt(seed.slice(offset + 4, offset + 6)),
|
Number.parseInt(seed.slice(offset + 4, offset + 6)),
|
||||||
);
|
);
|
||||||
starters.push(getDailyRunStarter(starterSpeciesForm, startingLevel));
|
starters.push(getDailyRunStarter(starterSpeciesForm, startingLevel));
|
||||||
@ -50,7 +50,7 @@ export function getDailyRunStarters(seed: string): Starter[] {
|
|||||||
for (let c = 0; c < starterCosts.length; c++) {
|
for (let c = 0; c < starterCosts.length; c++) {
|
||||||
const cost = starterCosts[c];
|
const cost = starterCosts[c];
|
||||||
const costSpecies = Object.keys(speciesStarterCosts)
|
const costSpecies = Object.keys(speciesStarterCosts)
|
||||||
.map(s => Number.parseInt(s) as Species)
|
.map(s => Number.parseInt(s) as SpeciesId)
|
||||||
.filter(s => speciesStarterCosts[s] === cost);
|
.filter(s => speciesStarterCosts[s] === cost);
|
||||||
const randPkmSpecies = getPokemonSpecies(randSeedItem(costSpecies));
|
const randPkmSpecies = getPokemonSpecies(randSeedItem(costSpecies));
|
||||||
const starterSpecies = getPokemonSpecies(
|
const starterSpecies = getPokemonSpecies(
|
||||||
@ -102,48 +102,48 @@ interface BiomeWeights {
|
|||||||
// Town and End are set to 0 however
|
// Town and End are set to 0 however
|
||||||
// And some other biomes were balanced +1/-1 based on average size of the total daily.
|
// And some other biomes were balanced +1/-1 based on average size of the total daily.
|
||||||
const dailyBiomeWeights: BiomeWeights = {
|
const dailyBiomeWeights: BiomeWeights = {
|
||||||
[Biome.CAVE]: 3,
|
[BiomeId.CAVE]: 3,
|
||||||
[Biome.LAKE]: 3,
|
[BiomeId.LAKE]: 3,
|
||||||
[Biome.PLAINS]: 3,
|
[BiomeId.PLAINS]: 3,
|
||||||
[Biome.SNOWY_FOREST]: 3,
|
[BiomeId.SNOWY_FOREST]: 3,
|
||||||
[Biome.SWAMP]: 3, // 2 -> 3
|
[BiomeId.SWAMP]: 3, // 2 -> 3
|
||||||
[Biome.TALL_GRASS]: 3, // 2 -> 3
|
[BiomeId.TALL_GRASS]: 3, // 2 -> 3
|
||||||
|
|
||||||
[Biome.ABYSS]: 2, // 3 -> 2
|
[BiomeId.ABYSS]: 2, // 3 -> 2
|
||||||
[Biome.RUINS]: 2,
|
[BiomeId.RUINS]: 2,
|
||||||
[Biome.BADLANDS]: 2,
|
[BiomeId.BADLANDS]: 2,
|
||||||
[Biome.BEACH]: 2,
|
[BiomeId.BEACH]: 2,
|
||||||
[Biome.CONSTRUCTION_SITE]: 2,
|
[BiomeId.CONSTRUCTION_SITE]: 2,
|
||||||
[Biome.DESERT]: 2,
|
[BiomeId.DESERT]: 2,
|
||||||
[Biome.DOJO]: 2, // 3 -> 2
|
[BiomeId.DOJO]: 2, // 3 -> 2
|
||||||
[Biome.FACTORY]: 2,
|
[BiomeId.FACTORY]: 2,
|
||||||
[Biome.FAIRY_CAVE]: 2,
|
[BiomeId.FAIRY_CAVE]: 2,
|
||||||
[Biome.FOREST]: 2,
|
[BiomeId.FOREST]: 2,
|
||||||
[Biome.GRASS]: 2, // 1 -> 2
|
[BiomeId.GRASS]: 2, // 1 -> 2
|
||||||
[Biome.MEADOW]: 2,
|
[BiomeId.MEADOW]: 2,
|
||||||
[Biome.MOUNTAIN]: 2, // 3 -> 2
|
[BiomeId.MOUNTAIN]: 2, // 3 -> 2
|
||||||
[Biome.SEA]: 2,
|
[BiomeId.SEA]: 2,
|
||||||
[Biome.SEABED]: 2,
|
[BiomeId.SEABED]: 2,
|
||||||
[Biome.SLUM]: 2,
|
[BiomeId.SLUM]: 2,
|
||||||
[Biome.TEMPLE]: 2, // 3 -> 2
|
[BiomeId.TEMPLE]: 2, // 3 -> 2
|
||||||
[Biome.VOLCANO]: 2,
|
[BiomeId.VOLCANO]: 2,
|
||||||
|
|
||||||
[Biome.GRAVEYARD]: 1,
|
[BiomeId.GRAVEYARD]: 1,
|
||||||
[Biome.ICE_CAVE]: 1,
|
[BiomeId.ICE_CAVE]: 1,
|
||||||
[Biome.ISLAND]: 1,
|
[BiomeId.ISLAND]: 1,
|
||||||
[Biome.JUNGLE]: 1,
|
[BiomeId.JUNGLE]: 1,
|
||||||
[Biome.LABORATORY]: 1,
|
[BiomeId.LABORATORY]: 1,
|
||||||
[Biome.METROPOLIS]: 1,
|
[BiomeId.METROPOLIS]: 1,
|
||||||
[Biome.POWER_PLANT]: 1,
|
[BiomeId.POWER_PLANT]: 1,
|
||||||
[Biome.SPACE]: 1,
|
[BiomeId.SPACE]: 1,
|
||||||
[Biome.WASTELAND]: 1,
|
[BiomeId.WASTELAND]: 1,
|
||||||
|
|
||||||
[Biome.TOWN]: 0,
|
[BiomeId.TOWN]: 0,
|
||||||
[Biome.END]: 0,
|
[BiomeId.END]: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getDailyStartingBiome(): Biome {
|
export function getDailyStartingBiome(): BiomeId {
|
||||||
const biomes = getEnumValues(Biome).filter(b => b !== Biome.TOWN && b !== Biome.END);
|
const biomes = getEnumValues(BiomeId).filter(b => b !== BiomeId.TOWN && b !== BiomeId.END);
|
||||||
|
|
||||||
let totalWeight = 0;
|
let totalWeight = 0;
|
||||||
const biomeThresholds: number[] = [];
|
const biomeThresholds: number[] = [];
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import type { DexEntry, StarterDataEntry } from "#app/system/game-data";
|
import type { StarterDataEntry } from "#app/system/game-data";
|
||||||
|
import type { DexEntry } from "#app/@types/dex-data";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores data associated with a specific egg and the hatched pokemon
|
* Stores data associated with a specific egg and the hatched pokemon
|
||||||
|
@ -10,7 +10,7 @@ import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
|||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { EggTier } from "#enums/egg-type";
|
import { EggTier } from "#enums/egg-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { EggSourceType } from "#enums/egg-source-types";
|
import { EggSourceType } from "#enums/egg-source-types";
|
||||||
import {
|
import {
|
||||||
MANAPHY_EGG_MANAPHY_RATE,
|
MANAPHY_EGG_MANAPHY_RATE,
|
||||||
@ -67,7 +67,7 @@ export interface IEggOptions {
|
|||||||
/** Sets how many waves it will take till this egg hatches. */
|
/** Sets how many waves it will take till this egg hatches. */
|
||||||
hatchWaves?: number;
|
hatchWaves?: number;
|
||||||
/** Sets the exact species that will hatch from this egg. */
|
/** Sets the exact species that will hatch from this egg. */
|
||||||
species?: Species;
|
species?: SpeciesId;
|
||||||
/** Defines if the hatched pokemon will be a shiny. */
|
/** Defines if the hatched pokemon will be a shiny. */
|
||||||
isShiny?: boolean;
|
isShiny?: boolean;
|
||||||
/** Defines the variant of the pokemon that will hatch from this egg. If no `variantTier` is given the normal variant rates will apply. */
|
/** Defines the variant of the pokemon that will hatch from this egg. If no `variantTier` is given the normal variant rates will apply. */
|
||||||
@ -94,7 +94,7 @@ export class Egg {
|
|||||||
private _hatchWaves: number;
|
private _hatchWaves: number;
|
||||||
private _timestamp: number;
|
private _timestamp: number;
|
||||||
|
|
||||||
private _species: Species;
|
private _species: SpeciesId;
|
||||||
private _isShiny: boolean;
|
private _isShiny: boolean;
|
||||||
private _variantTier: VariantTier;
|
private _variantTier: VariantTier;
|
||||||
private _eggMoveIndex: number;
|
private _eggMoveIndex: number;
|
||||||
@ -134,7 +134,7 @@ export class Egg {
|
|||||||
return this._timestamp;
|
return this._timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
get species(): Species {
|
get species(): SpeciesId {
|
||||||
return this._species;
|
return this._species;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,8 +221,8 @@ export class Egg {
|
|||||||
|
|
||||||
public isManaphyEgg(): boolean {
|
public isManaphyEgg(): boolean {
|
||||||
return (
|
return (
|
||||||
this._species === Species.PHIONE ||
|
this._species === SpeciesId.PHIONE ||
|
||||||
this._species === Species.MANAPHY ||
|
this._species === SpeciesId.MANAPHY ||
|
||||||
(this._tier === EggTier.COMMON && !(this._id % 204) && !this._species)
|
(this._tier === EggTier.COMMON && !(this._id % 204) && !this._species)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -247,8 +247,10 @@ export class Egg {
|
|||||||
|
|
||||||
let pokemonSpecies = getPokemonSpecies(this._species);
|
let pokemonSpecies = getPokemonSpecies(this._species);
|
||||||
// Special condition to have Phione eggs also have a chance of generating Manaphy
|
// Special condition to have Phione eggs also have a chance of generating Manaphy
|
||||||
if (this._species === Species.PHIONE && this._sourceType === EggSourceType.SAME_SPECIES_EGG) {
|
if (this._species === SpeciesId.PHIONE && this._sourceType === EggSourceType.SAME_SPECIES_EGG) {
|
||||||
pokemonSpecies = getPokemonSpecies(randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? Species.PHIONE : Species.MANAPHY);
|
pokemonSpecies = getPokemonSpecies(
|
||||||
|
randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? SpeciesId.PHIONE : SpeciesId.MANAPHY,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the hidden ability if a hidden ability exists and
|
// Sets the hidden ability if a hidden ability exists and
|
||||||
@ -371,7 +373,7 @@ export class Egg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getEggTierDefaultHatchWaves(eggTier?: EggTier): number {
|
private getEggTierDefaultHatchWaves(eggTier?: EggTier): number {
|
||||||
if (this._species === Species.PHIONE || this._species === Species.MANAPHY) {
|
if (this._species === SpeciesId.PHIONE || this._species === SpeciesId.MANAPHY) {
|
||||||
return HATCH_WAVES_MANAPHY_EGG;
|
return HATCH_WAVES_MANAPHY_EGG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,7 +401,7 @@ export class Egg {
|
|||||||
: EggTier.LEGENDARY;
|
: EggTier.LEGENDARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
private rollSpecies(): Species | null {
|
private rollSpecies(): SpeciesId | null {
|
||||||
if (!globalScene) {
|
if (!globalScene) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -415,7 +417,7 @@ export class Egg {
|
|||||||
* check pass when Utils.randSeedInt(8) = 0, we can tell them apart during tests.
|
* check pass when Utils.randSeedInt(8) = 0, we can tell them apart during tests.
|
||||||
*/
|
*/
|
||||||
const rand = randSeedInt(MANAPHY_EGG_MANAPHY_RATE) !== 1;
|
const rand = randSeedInt(MANAPHY_EGG_MANAPHY_RATE) !== 1;
|
||||||
return rand ? Species.PHIONE : Species.MANAPHY;
|
return rand ? SpeciesId.PHIONE : SpeciesId.MANAPHY;
|
||||||
}
|
}
|
||||||
if (this.tier === EggTier.LEGENDARY && this._sourceType === EggSourceType.GACHA_LEGENDARY) {
|
if (this.tier === EggTier.LEGENDARY && this._sourceType === EggSourceType.GACHA_LEGENDARY) {
|
||||||
if (!randSeedInt(2)) {
|
if (!randSeedInt(2)) {
|
||||||
@ -445,11 +447,11 @@ export class Egg {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ignoredSpecies = [Species.PHIONE, Species.MANAPHY, Species.ETERNATUS];
|
const ignoredSpecies = [SpeciesId.PHIONE, SpeciesId.MANAPHY, SpeciesId.ETERNATUS];
|
||||||
|
|
||||||
let speciesPool = Object.keys(speciesEggTiers)
|
let speciesPool = Object.keys(speciesEggTiers)
|
||||||
.filter(s => speciesEggTiers[s] === this.tier)
|
.filter(s => speciesEggTiers[s] === this.tier)
|
||||||
.map(s => Number.parseInt(s) as Species)
|
.map(s => Number.parseInt(s) as SpeciesId)
|
||||||
.filter(
|
.filter(
|
||||||
s =>
|
s =>
|
||||||
!pokemonPrevolutions.hasOwnProperty(s) &&
|
!pokemonPrevolutions.hasOwnProperty(s) &&
|
||||||
@ -496,7 +498,7 @@ export class Egg {
|
|||||||
totalWeight += weight;
|
totalWeight += weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
let species: Species;
|
let species: SpeciesId;
|
||||||
|
|
||||||
const rand = randSeedInt(totalWeight);
|
const rand = randSeedInt(totalWeight);
|
||||||
for (let s = 0; s < speciesWeights.length; s++) {
|
for (let s = 0; s < speciesWeights.length; s++) {
|
||||||
@ -606,17 +608,17 @@ export class Egg {
|
|||||||
////
|
////
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getValidLegendaryGachaSpecies(): Species[] {
|
export function getValidLegendaryGachaSpecies(): SpeciesId[] {
|
||||||
return Object.entries(speciesEggTiers)
|
return Object.entries(speciesEggTiers)
|
||||||
.filter(s => s[1] === EggTier.LEGENDARY)
|
.filter(s => s[1] === EggTier.LEGENDARY)
|
||||||
.map(s => Number.parseInt(s[0]))
|
.map(s => Number.parseInt(s[0]))
|
||||||
.filter(s => getPokemonSpecies(s).isObtainable() && s !== Species.ETERNATUS);
|
.filter(s => getPokemonSpecies(s).isObtainable() && s !== SpeciesId.ETERNATUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLegendaryGachaSpeciesForTimestamp(timestamp: number): Species {
|
export function getLegendaryGachaSpeciesForTimestamp(timestamp: number): SpeciesId {
|
||||||
const legendarySpecies = getValidLegendaryGachaSpecies();
|
const legendarySpecies = getValidLegendaryGachaSpecies();
|
||||||
|
|
||||||
let ret: Species;
|
let ret: SpeciesId;
|
||||||
|
|
||||||
// 86400000 is the number of miliseconds in one day
|
// 86400000 is the number of miliseconds in one day
|
||||||
const timeDate = new Date(timestamp);
|
const timeDate = new Date(timestamp);
|
||||||
|
58
src/data/moves/apply-attrs.ts
Normal file
58
src/data/moves/apply-attrs.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* Module holding functions to apply move attributes.
|
||||||
|
* Must not import anything that is not a type.
|
||||||
|
*/
|
||||||
|
import type Pokemon from "#app/field/pokemon";
|
||||||
|
import type { default as Move, MoveAttr } from "./move";
|
||||||
|
import type { ChargingMove } from "#app/@types/move-types";
|
||||||
|
import type { MoveAttrFilter, MoveAttrString } from "#app/@types/move-types";
|
||||||
|
|
||||||
|
function applyMoveAttrsInternal(
|
||||||
|
attrFilter: MoveAttrFilter,
|
||||||
|
user: Pokemon | null,
|
||||||
|
target: Pokemon | null,
|
||||||
|
move: Move,
|
||||||
|
args: any[],
|
||||||
|
): void {
|
||||||
|
move.attrs.filter(attr => attrFilter(attr)).forEach(attr => attr.apply(user, target, move, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyMoveChargeAttrsInternal(
|
||||||
|
attrFilter: MoveAttrFilter,
|
||||||
|
user: Pokemon | null,
|
||||||
|
target: Pokemon | null,
|
||||||
|
move: ChargingMove,
|
||||||
|
args: any[],
|
||||||
|
): void {
|
||||||
|
move.chargeAttrs.filter(attr => attrFilter(attr)).forEach(attr => attr.apply(user, target, move, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applyMoveAttrs(
|
||||||
|
attrType: MoveAttrString,
|
||||||
|
user: Pokemon | null,
|
||||||
|
target: Pokemon | null,
|
||||||
|
move: Move,
|
||||||
|
...args: any[]
|
||||||
|
): void {
|
||||||
|
applyMoveAttrsInternal((attr: MoveAttr) => attr.is(attrType), user, target, move, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applyFilteredMoveAttrs(
|
||||||
|
attrFilter: MoveAttrFilter,
|
||||||
|
user: Pokemon,
|
||||||
|
target: Pokemon | null,
|
||||||
|
move: Move,
|
||||||
|
...args: any[]
|
||||||
|
): void {
|
||||||
|
applyMoveAttrsInternal(attrFilter, user, target, move, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applyMoveChargeAttrs(
|
||||||
|
attrType: MoveAttrString,
|
||||||
|
user: Pokemon | null,
|
||||||
|
target: Pokemon | null,
|
||||||
|
move: ChargingMove,
|
||||||
|
...args: any[]
|
||||||
|
): void {
|
||||||
|
applyMoveChargeAttrsInternal((attr: MoveAttr) => attr.is(attrType), user, target, move, args);
|
||||||
|
}
|
@ -1,257 +1,257 @@
|
|||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
|
|
||||||
/** Set of moves that cannot be called by {@linkcode Moves.METRONOME Metronome} */
|
/** Set of moves that cannot be called by {@linkcode MoveId.METRONOME Metronome} */
|
||||||
export const invalidMetronomeMoves: ReadonlySet<Moves> = new Set([
|
export const invalidMetronomeMoves: ReadonlySet<MoveId> = new Set([
|
||||||
Moves.AFTER_YOU,
|
MoveId.AFTER_YOU,
|
||||||
Moves.ASSIST,
|
MoveId.ASSIST,
|
||||||
Moves.BANEFUL_BUNKER,
|
MoveId.BANEFUL_BUNKER,
|
||||||
Moves.BEAK_BLAST,
|
MoveId.BEAK_BLAST,
|
||||||
Moves.BELCH,
|
MoveId.BELCH,
|
||||||
Moves.BESTOW,
|
MoveId.BESTOW,
|
||||||
Moves.COMEUPPANCE,
|
MoveId.COMEUPPANCE,
|
||||||
Moves.COPYCAT,
|
MoveId.COPYCAT,
|
||||||
Moves.COUNTER,
|
MoveId.COUNTER,
|
||||||
Moves.CRAFTY_SHIELD,
|
MoveId.CRAFTY_SHIELD,
|
||||||
Moves.DESTINY_BOND,
|
MoveId.DESTINY_BOND,
|
||||||
Moves.DETECT,
|
MoveId.DETECT,
|
||||||
Moves.ENDURE,
|
MoveId.ENDURE,
|
||||||
Moves.FEINT,
|
MoveId.FEINT,
|
||||||
Moves.FOCUS_PUNCH,
|
MoveId.FOCUS_PUNCH,
|
||||||
Moves.FOLLOW_ME,
|
MoveId.FOLLOW_ME,
|
||||||
Moves.HELPING_HAND,
|
MoveId.HELPING_HAND,
|
||||||
Moves.INSTRUCT,
|
MoveId.INSTRUCT,
|
||||||
Moves.KINGS_SHIELD,
|
MoveId.KINGS_SHIELD,
|
||||||
Moves.MAT_BLOCK,
|
MoveId.MAT_BLOCK,
|
||||||
Moves.ME_FIRST,
|
MoveId.ME_FIRST,
|
||||||
Moves.METRONOME,
|
MoveId.METRONOME,
|
||||||
Moves.MIMIC,
|
MoveId.MIMIC,
|
||||||
Moves.MIRROR_COAT,
|
MoveId.MIRROR_COAT,
|
||||||
Moves.MIRROR_MOVE,
|
MoveId.MIRROR_MOVE,
|
||||||
Moves.OBSTRUCT,
|
MoveId.OBSTRUCT,
|
||||||
Moves.PROTECT,
|
MoveId.PROTECT,
|
||||||
Moves.QUASH,
|
MoveId.QUASH,
|
||||||
Moves.QUICK_GUARD,
|
MoveId.QUICK_GUARD,
|
||||||
Moves.RAGE_POWDER,
|
MoveId.RAGE_POWDER,
|
||||||
Moves.REVIVAL_BLESSING,
|
MoveId.REVIVAL_BLESSING,
|
||||||
Moves.SHELL_TRAP,
|
MoveId.SHELL_TRAP,
|
||||||
Moves.SILK_TRAP,
|
MoveId.SILK_TRAP,
|
||||||
Moves.SKETCH,
|
MoveId.SKETCH,
|
||||||
Moves.SLEEP_TALK,
|
MoveId.SLEEP_TALK,
|
||||||
Moves.SNATCH,
|
MoveId.SNATCH,
|
||||||
Moves.SNORE,
|
MoveId.SNORE,
|
||||||
Moves.SPIKY_SHIELD,
|
MoveId.SPIKY_SHIELD,
|
||||||
Moves.SPOTLIGHT,
|
MoveId.SPOTLIGHT,
|
||||||
Moves.STRUGGLE,
|
MoveId.STRUGGLE,
|
||||||
Moves.TRANSFORM,
|
MoveId.TRANSFORM,
|
||||||
Moves.WIDE_GUARD,
|
MoveId.WIDE_GUARD,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/** Set of moves that cannot be called by {@linkcode Moves.ASSIST Assist} */
|
/** Set of moves that cannot be called by {@linkcode MoveId.ASSIST Assist} */
|
||||||
export const invalidAssistMoves: ReadonlySet<Moves> = new Set([
|
export const invalidAssistMoves: ReadonlySet<MoveId> = new Set([
|
||||||
Moves.ASSIST,
|
MoveId.ASSIST,
|
||||||
Moves.BANEFUL_BUNKER,
|
MoveId.BANEFUL_BUNKER,
|
||||||
Moves.BEAK_BLAST,
|
MoveId.BEAK_BLAST,
|
||||||
Moves.BELCH,
|
MoveId.BELCH,
|
||||||
Moves.BESTOW,
|
MoveId.BESTOW,
|
||||||
Moves.BOUNCE,
|
MoveId.BOUNCE,
|
||||||
Moves.CELEBRATE,
|
MoveId.CELEBRATE,
|
||||||
Moves.CHATTER,
|
MoveId.CHATTER,
|
||||||
Moves.CIRCLE_THROW,
|
MoveId.CIRCLE_THROW,
|
||||||
Moves.COPYCAT,
|
MoveId.COPYCAT,
|
||||||
Moves.COUNTER,
|
MoveId.COUNTER,
|
||||||
Moves.DESTINY_BOND,
|
MoveId.DESTINY_BOND,
|
||||||
Moves.DETECT,
|
MoveId.DETECT,
|
||||||
Moves.DIG,
|
MoveId.DIG,
|
||||||
Moves.DIVE,
|
MoveId.DIVE,
|
||||||
Moves.DRAGON_TAIL,
|
MoveId.DRAGON_TAIL,
|
||||||
Moves.ENDURE,
|
MoveId.ENDURE,
|
||||||
Moves.FEINT,
|
MoveId.FEINT,
|
||||||
Moves.FLY,
|
MoveId.FLY,
|
||||||
Moves.FOCUS_PUNCH,
|
MoveId.FOCUS_PUNCH,
|
||||||
Moves.FOLLOW_ME,
|
MoveId.FOLLOW_ME,
|
||||||
Moves.HELPING_HAND,
|
MoveId.HELPING_HAND,
|
||||||
Moves.HOLD_HANDS,
|
MoveId.HOLD_HANDS,
|
||||||
Moves.KINGS_SHIELD,
|
MoveId.KINGS_SHIELD,
|
||||||
Moves.MAT_BLOCK,
|
MoveId.MAT_BLOCK,
|
||||||
Moves.ME_FIRST,
|
MoveId.ME_FIRST,
|
||||||
Moves.METRONOME,
|
MoveId.METRONOME,
|
||||||
Moves.MIMIC,
|
MoveId.MIMIC,
|
||||||
Moves.MIRROR_COAT,
|
MoveId.MIRROR_COAT,
|
||||||
Moves.MIRROR_MOVE,
|
MoveId.MIRROR_MOVE,
|
||||||
Moves.NATURE_POWER,
|
MoveId.NATURE_POWER,
|
||||||
Moves.PHANTOM_FORCE,
|
MoveId.PHANTOM_FORCE,
|
||||||
Moves.PROTECT,
|
MoveId.PROTECT,
|
||||||
Moves.RAGE_POWDER,
|
MoveId.RAGE_POWDER,
|
||||||
Moves.ROAR,
|
MoveId.ROAR,
|
||||||
Moves.SHADOW_FORCE,
|
MoveId.SHADOW_FORCE,
|
||||||
Moves.SHELL_TRAP,
|
MoveId.SHELL_TRAP,
|
||||||
Moves.SKETCH,
|
MoveId.SKETCH,
|
||||||
Moves.SKY_DROP,
|
MoveId.SKY_DROP,
|
||||||
Moves.SLEEP_TALK,
|
MoveId.SLEEP_TALK,
|
||||||
Moves.SNATCH,
|
MoveId.SNATCH,
|
||||||
Moves.SPIKY_SHIELD,
|
MoveId.SPIKY_SHIELD,
|
||||||
Moves.SPOTLIGHT,
|
MoveId.SPOTLIGHT,
|
||||||
Moves.STRUGGLE,
|
MoveId.STRUGGLE,
|
||||||
Moves.SWITCHEROO,
|
MoveId.SWITCHEROO,
|
||||||
Moves.TRANSFORM,
|
MoveId.TRANSFORM,
|
||||||
Moves.TRICK,
|
MoveId.TRICK,
|
||||||
Moves.WHIRLWIND,
|
MoveId.WHIRLWIND,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/** Set of moves that cannot be called by {@linkcode Moves.SLEEP_TALK Sleep Talk} */
|
/** Set of moves that cannot be called by {@linkcode MoveId.SLEEP_TALK Sleep Talk} */
|
||||||
export const invalidSleepTalkMoves: ReadonlySet<Moves> = new Set([
|
export const invalidSleepTalkMoves: ReadonlySet<MoveId> = new Set([
|
||||||
Moves.ASSIST,
|
MoveId.ASSIST,
|
||||||
Moves.BELCH,
|
MoveId.BELCH,
|
||||||
Moves.BEAK_BLAST,
|
MoveId.BEAK_BLAST,
|
||||||
Moves.BIDE,
|
MoveId.BIDE,
|
||||||
Moves.BOUNCE,
|
MoveId.BOUNCE,
|
||||||
Moves.COPYCAT,
|
MoveId.COPYCAT,
|
||||||
Moves.DIG,
|
MoveId.DIG,
|
||||||
Moves.DIVE,
|
MoveId.DIVE,
|
||||||
Moves.FREEZE_SHOCK,
|
MoveId.FREEZE_SHOCK,
|
||||||
Moves.FLY,
|
MoveId.FLY,
|
||||||
Moves.FOCUS_PUNCH,
|
MoveId.FOCUS_PUNCH,
|
||||||
Moves.GEOMANCY,
|
MoveId.GEOMANCY,
|
||||||
Moves.ICE_BURN,
|
MoveId.ICE_BURN,
|
||||||
Moves.ME_FIRST,
|
MoveId.ME_FIRST,
|
||||||
Moves.METRONOME,
|
MoveId.METRONOME,
|
||||||
Moves.MIRROR_MOVE,
|
MoveId.MIRROR_MOVE,
|
||||||
Moves.MIMIC,
|
MoveId.MIMIC,
|
||||||
Moves.PHANTOM_FORCE,
|
MoveId.PHANTOM_FORCE,
|
||||||
Moves.RAZOR_WIND,
|
MoveId.RAZOR_WIND,
|
||||||
Moves.SHADOW_FORCE,
|
MoveId.SHADOW_FORCE,
|
||||||
Moves.SHELL_TRAP,
|
MoveId.SHELL_TRAP,
|
||||||
Moves.SKETCH,
|
MoveId.SKETCH,
|
||||||
Moves.SKULL_BASH,
|
MoveId.SKULL_BASH,
|
||||||
Moves.SKY_ATTACK,
|
MoveId.SKY_ATTACK,
|
||||||
Moves.SKY_DROP,
|
MoveId.SKY_DROP,
|
||||||
Moves.SLEEP_TALK,
|
MoveId.SLEEP_TALK,
|
||||||
Moves.SOLAR_BLADE,
|
MoveId.SOLAR_BLADE,
|
||||||
Moves.SOLAR_BEAM,
|
MoveId.SOLAR_BEAM,
|
||||||
Moves.STRUGGLE,
|
MoveId.STRUGGLE,
|
||||||
Moves.UPROAR,
|
MoveId.UPROAR,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/** Set of moves that cannot be copied by {@linkcode Moves.COPYCAT Copycat} */
|
/** Set of moves that cannot be copied by {@linkcode MoveId.COPYCAT Copycat} */
|
||||||
export const invalidCopycatMoves: ReadonlySet<Moves> = new Set([
|
export const invalidCopycatMoves: ReadonlySet<MoveId> = new Set([
|
||||||
Moves.ASSIST,
|
MoveId.ASSIST,
|
||||||
Moves.BANEFUL_BUNKER,
|
MoveId.BANEFUL_BUNKER,
|
||||||
Moves.BEAK_BLAST,
|
MoveId.BEAK_BLAST,
|
||||||
Moves.BESTOW,
|
MoveId.BESTOW,
|
||||||
Moves.CELEBRATE,
|
MoveId.CELEBRATE,
|
||||||
Moves.CHATTER,
|
MoveId.CHATTER,
|
||||||
Moves.CIRCLE_THROW,
|
MoveId.CIRCLE_THROW,
|
||||||
Moves.COPYCAT,
|
MoveId.COPYCAT,
|
||||||
Moves.COUNTER,
|
MoveId.COUNTER,
|
||||||
Moves.DESTINY_BOND,
|
MoveId.DESTINY_BOND,
|
||||||
Moves.DETECT,
|
MoveId.DETECT,
|
||||||
Moves.DRAGON_TAIL,
|
MoveId.DRAGON_TAIL,
|
||||||
Moves.ENDURE,
|
MoveId.ENDURE,
|
||||||
Moves.FEINT,
|
MoveId.FEINT,
|
||||||
Moves.FOCUS_PUNCH,
|
MoveId.FOCUS_PUNCH,
|
||||||
Moves.FOLLOW_ME,
|
MoveId.FOLLOW_ME,
|
||||||
Moves.HELPING_HAND,
|
MoveId.HELPING_HAND,
|
||||||
Moves.HOLD_HANDS,
|
MoveId.HOLD_HANDS,
|
||||||
Moves.KINGS_SHIELD,
|
MoveId.KINGS_SHIELD,
|
||||||
Moves.MAT_BLOCK,
|
MoveId.MAT_BLOCK,
|
||||||
Moves.ME_FIRST,
|
MoveId.ME_FIRST,
|
||||||
Moves.METRONOME,
|
MoveId.METRONOME,
|
||||||
Moves.MIMIC,
|
MoveId.MIMIC,
|
||||||
Moves.MIRROR_COAT,
|
MoveId.MIRROR_COAT,
|
||||||
Moves.MIRROR_MOVE,
|
MoveId.MIRROR_MOVE,
|
||||||
Moves.PROTECT,
|
MoveId.PROTECT,
|
||||||
Moves.RAGE_POWDER,
|
MoveId.RAGE_POWDER,
|
||||||
Moves.ROAR,
|
MoveId.ROAR,
|
||||||
Moves.SHELL_TRAP,
|
MoveId.SHELL_TRAP,
|
||||||
Moves.SKETCH,
|
MoveId.SKETCH,
|
||||||
Moves.SLEEP_TALK,
|
MoveId.SLEEP_TALK,
|
||||||
Moves.SNATCH,
|
MoveId.SNATCH,
|
||||||
Moves.SPIKY_SHIELD,
|
MoveId.SPIKY_SHIELD,
|
||||||
Moves.SPOTLIGHT,
|
MoveId.SPOTLIGHT,
|
||||||
Moves.STRUGGLE,
|
MoveId.STRUGGLE,
|
||||||
Moves.SWITCHEROO,
|
MoveId.SWITCHEROO,
|
||||||
Moves.TRANSFORM,
|
MoveId.TRANSFORM,
|
||||||
Moves.TRICK,
|
MoveId.TRICK,
|
||||||
Moves.WHIRLWIND,
|
MoveId.WHIRLWIND,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const invalidMirrorMoveMoves: ReadonlySet<Moves> = new Set([
|
export const invalidMirrorMoveMoves: ReadonlySet<MoveId> = new Set([
|
||||||
Moves.ACUPRESSURE,
|
MoveId.ACUPRESSURE,
|
||||||
Moves.AFTER_YOU,
|
MoveId.AFTER_YOU,
|
||||||
Moves.AROMATIC_MIST,
|
MoveId.AROMATIC_MIST,
|
||||||
Moves.BEAK_BLAST,
|
MoveId.BEAK_BLAST,
|
||||||
Moves.BELCH,
|
MoveId.BELCH,
|
||||||
Moves.CHILLY_RECEPTION,
|
MoveId.CHILLY_RECEPTION,
|
||||||
Moves.COACHING,
|
MoveId.COACHING,
|
||||||
Moves.CONVERSION_2,
|
MoveId.CONVERSION_2,
|
||||||
Moves.COUNTER,
|
MoveId.COUNTER,
|
||||||
Moves.CRAFTY_SHIELD,
|
MoveId.CRAFTY_SHIELD,
|
||||||
Moves.CURSE,
|
MoveId.CURSE,
|
||||||
Moves.DECORATE,
|
MoveId.DECORATE,
|
||||||
Moves.DOODLE,
|
MoveId.DOODLE,
|
||||||
Moves.DOOM_DESIRE,
|
MoveId.DOOM_DESIRE,
|
||||||
Moves.DRAGON_CHEER,
|
MoveId.DRAGON_CHEER,
|
||||||
Moves.ELECTRIC_TERRAIN,
|
MoveId.ELECTRIC_TERRAIN,
|
||||||
Moves.FINAL_GAMBIT,
|
MoveId.FINAL_GAMBIT,
|
||||||
Moves.FLORAL_HEALING,
|
MoveId.FLORAL_HEALING,
|
||||||
Moves.FLOWER_SHIELD,
|
MoveId.FLOWER_SHIELD,
|
||||||
Moves.FOCUS_PUNCH,
|
MoveId.FOCUS_PUNCH,
|
||||||
Moves.FUTURE_SIGHT,
|
MoveId.FUTURE_SIGHT,
|
||||||
Moves.GEAR_UP,
|
MoveId.GEAR_UP,
|
||||||
Moves.GRASSY_TERRAIN,
|
MoveId.GRASSY_TERRAIN,
|
||||||
Moves.GRAVITY,
|
MoveId.GRAVITY,
|
||||||
Moves.GUARD_SPLIT,
|
MoveId.GUARD_SPLIT,
|
||||||
Moves.HAIL,
|
MoveId.HAIL,
|
||||||
Moves.HAZE,
|
MoveId.HAZE,
|
||||||
Moves.HEAL_PULSE,
|
MoveId.HEAL_PULSE,
|
||||||
Moves.HELPING_HAND,
|
MoveId.HELPING_HAND,
|
||||||
Moves.HOLD_HANDS,
|
MoveId.HOLD_HANDS,
|
||||||
Moves.INSTRUCT,
|
MoveId.INSTRUCT,
|
||||||
Moves.ION_DELUGE,
|
MoveId.ION_DELUGE,
|
||||||
Moves.MAGNETIC_FLUX,
|
MoveId.MAGNETIC_FLUX,
|
||||||
Moves.MAT_BLOCK,
|
MoveId.MAT_BLOCK,
|
||||||
Moves.ME_FIRST,
|
MoveId.ME_FIRST,
|
||||||
Moves.MIMIC,
|
MoveId.MIMIC,
|
||||||
Moves.MIRROR_COAT,
|
MoveId.MIRROR_COAT,
|
||||||
Moves.MIRROR_MOVE,
|
MoveId.MIRROR_MOVE,
|
||||||
Moves.MIST,
|
MoveId.MIST,
|
||||||
Moves.MISTY_TERRAIN,
|
MoveId.MISTY_TERRAIN,
|
||||||
Moves.MUD_SPORT,
|
MoveId.MUD_SPORT,
|
||||||
Moves.PERISH_SONG,
|
MoveId.PERISH_SONG,
|
||||||
Moves.POWER_SPLIT,
|
MoveId.POWER_SPLIT,
|
||||||
Moves.PSYCH_UP,
|
MoveId.PSYCH_UP,
|
||||||
Moves.PSYCHIC_TERRAIN,
|
MoveId.PSYCHIC_TERRAIN,
|
||||||
Moves.PURIFY,
|
MoveId.PURIFY,
|
||||||
Moves.QUICK_GUARD,
|
MoveId.QUICK_GUARD,
|
||||||
Moves.RAIN_DANCE,
|
MoveId.RAIN_DANCE,
|
||||||
Moves.REFLECT_TYPE,
|
MoveId.REFLECT_TYPE,
|
||||||
Moves.ROLE_PLAY,
|
MoveId.ROLE_PLAY,
|
||||||
Moves.ROTOTILLER,
|
MoveId.ROTOTILLER,
|
||||||
Moves.SANDSTORM,
|
MoveId.SANDSTORM,
|
||||||
Moves.SHELL_TRAP,
|
MoveId.SHELL_TRAP,
|
||||||
Moves.SKETCH,
|
MoveId.SKETCH,
|
||||||
Moves.SNOWSCAPE,
|
MoveId.SNOWSCAPE,
|
||||||
Moves.SPIT_UP,
|
MoveId.SPIT_UP,
|
||||||
Moves.SPOTLIGHT,
|
MoveId.SPOTLIGHT,
|
||||||
Moves.STRUGGLE,
|
MoveId.STRUGGLE,
|
||||||
Moves.SUNNY_DAY,
|
MoveId.SUNNY_DAY,
|
||||||
Moves.TEATIME,
|
MoveId.TEATIME,
|
||||||
Moves.TRANSFORM,
|
MoveId.TRANSFORM,
|
||||||
Moves.WATER_SPORT,
|
MoveId.WATER_SPORT,
|
||||||
Moves.WIDE_GUARD,
|
MoveId.WIDE_GUARD,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/** Set of moves that can never have their type overridden by an ability like Pixilate or Normalize
|
/** Set of moves that can never have their type overridden by an ability like Pixilate or Normalize
|
||||||
*
|
*
|
||||||
* Excludes tera blast and tera starstorm, as these are only conditionally forbidden
|
* Excludes tera blast and tera starstorm, as these are only conditionally forbidden
|
||||||
*/
|
*/
|
||||||
export const noAbilityTypeOverrideMoves: ReadonlySet<Moves> = new Set([
|
export const noAbilityTypeOverrideMoves: ReadonlySet<MoveId> = new Set([
|
||||||
Moves.WEATHER_BALL,
|
MoveId.WEATHER_BALL,
|
||||||
Moves.JUDGMENT,
|
MoveId.JUDGMENT,
|
||||||
Moves.REVELATION_DANCE,
|
MoveId.REVELATION_DANCE,
|
||||||
Moves.MULTI_ATTACK,
|
MoveId.MULTI_ATTACK,
|
||||||
Moves.TERRAIN_PULSE,
|
MoveId.TERRAIN_PULSE,
|
||||||
Moves.NATURAL_GIFT,
|
MoveId.NATURAL_GIFT,
|
||||||
Moves.TECHNO_BLAST,
|
MoveId.TECHNO_BLAST,
|
||||||
Moves.HIDDEN_POWER,
|
MoveId.HIDDEN_POWER,
|
||||||
]);
|
]);
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
import { MoveTarget } from "#enums/MoveTarget";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
|
import type { BattlerIndex } from "#enums/battler-index";
|
||||||
|
import type { MoveId } from "#enums/move-id";
|
||||||
|
import type { MoveTargetSet, UserMoveConditionFunc } from "./move";
|
||||||
import type Move from "./move";
|
import type Move from "./move";
|
||||||
|
import { NumberHolder, isNullOrUndefined } from "#app/utils/common";
|
||||||
|
import { MoveTarget } from "#enums/MoveTarget";
|
||||||
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
|
import { allMoves } from "#app/data/data-lists";
|
||||||
|
import { applyMoveAttrs } from "./apply-attrs";
|
||||||
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether the move targets the field
|
* Return whether the move targets the field
|
||||||
@ -18,3 +27,88 @@ export function isFieldTargeted(move: Move): boolean {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getMoveTargets(user: Pokemon, move: MoveId, replaceTarget?: MoveTarget): MoveTargetSet {
|
||||||
|
const variableTarget = new NumberHolder(0);
|
||||||
|
user.getOpponents(false).forEach(p => applyMoveAttrs("VariableTargetAttr", user, p, allMoves[move], variableTarget));
|
||||||
|
|
||||||
|
let moveTarget: MoveTarget | undefined;
|
||||||
|
if (allMoves[move].hasAttr("VariableTargetAttr")) {
|
||||||
|
moveTarget = variableTarget.value;
|
||||||
|
} else if (replaceTarget !== undefined) {
|
||||||
|
moveTarget = replaceTarget;
|
||||||
|
} else if (move) {
|
||||||
|
moveTarget = allMoves[move].moveTarget;
|
||||||
|
} else if (move === undefined) {
|
||||||
|
moveTarget = MoveTarget.NEAR_ENEMY;
|
||||||
|
}
|
||||||
|
const opponents = user.getOpponents(false);
|
||||||
|
|
||||||
|
let set: Pokemon[] = [];
|
||||||
|
let multiple = false;
|
||||||
|
const ally: Pokemon | undefined = user.getAlly();
|
||||||
|
|
||||||
|
switch (moveTarget) {
|
||||||
|
case MoveTarget.USER:
|
||||||
|
case MoveTarget.PARTY:
|
||||||
|
set = [user];
|
||||||
|
break;
|
||||||
|
case MoveTarget.NEAR_OTHER:
|
||||||
|
case MoveTarget.OTHER:
|
||||||
|
case MoveTarget.ALL_NEAR_OTHERS:
|
||||||
|
case MoveTarget.ALL_OTHERS:
|
||||||
|
set = !isNullOrUndefined(ally) ? opponents.concat([ally]) : opponents;
|
||||||
|
multiple = moveTarget === MoveTarget.ALL_NEAR_OTHERS || moveTarget === MoveTarget.ALL_OTHERS;
|
||||||
|
break;
|
||||||
|
case MoveTarget.NEAR_ENEMY:
|
||||||
|
case MoveTarget.ALL_NEAR_ENEMIES:
|
||||||
|
case MoveTarget.ALL_ENEMIES:
|
||||||
|
case MoveTarget.ENEMY_SIDE:
|
||||||
|
set = opponents;
|
||||||
|
multiple = moveTarget !== MoveTarget.NEAR_ENEMY;
|
||||||
|
break;
|
||||||
|
case MoveTarget.RANDOM_NEAR_ENEMY:
|
||||||
|
set = [opponents[user.randBattleSeedInt(opponents.length)]];
|
||||||
|
break;
|
||||||
|
case MoveTarget.ATTACKER:
|
||||||
|
return { targets: [-1 as BattlerIndex], multiple: false };
|
||||||
|
case MoveTarget.NEAR_ALLY:
|
||||||
|
case MoveTarget.ALLY:
|
||||||
|
set = !isNullOrUndefined(ally) ? [ally] : [];
|
||||||
|
break;
|
||||||
|
case MoveTarget.USER_OR_NEAR_ALLY:
|
||||||
|
case MoveTarget.USER_AND_ALLIES:
|
||||||
|
case MoveTarget.USER_SIDE:
|
||||||
|
set = !isNullOrUndefined(ally) ? [user, ally] : [user];
|
||||||
|
multiple = moveTarget !== MoveTarget.USER_OR_NEAR_ALLY;
|
||||||
|
break;
|
||||||
|
case MoveTarget.ALL:
|
||||||
|
case MoveTarget.BOTH_SIDES:
|
||||||
|
set = (!isNullOrUndefined(ally) ? [user, ally] : [user]).concat(opponents);
|
||||||
|
multiple = true;
|
||||||
|
break;
|
||||||
|
case MoveTarget.CURSE:
|
||||||
|
{
|
||||||
|
const extraTargets = !isNullOrUndefined(ally) ? [ally] : [];
|
||||||
|
set = user.getTypes(true).includes(PokemonType.GHOST) ? opponents.concat(extraTargets) : [user];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
targets: set
|
||||||
|
.filter(p => p?.isActive(true))
|
||||||
|
.map(p => p.getBattlerIndex())
|
||||||
|
.filter(t => t !== undefined),
|
||||||
|
multiple,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const frenzyMissFunc: UserMoveConditionFunc = (user: Pokemon, move: Move) => {
|
||||||
|
while (user.getMoveQueue().length && user.getMoveQueue()[0].move === move.id) {
|
||||||
|
user.getMoveQueue().shift();
|
||||||
|
}
|
||||||
|
user.removeTag(BattlerTagType.FRENZY); // FRENZY tag should be disrupted on miss/no effect
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
93
src/data/moves/pokemon-move.ts
Normal file
93
src/data/moves/pokemon-move.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import type Pokemon from "#app/field/pokemon";
|
||||||
|
import { toDmgValue } from "#app/utils/common";
|
||||||
|
import type { MoveId } from "#enums/move-id";
|
||||||
|
import { allMoves } from "../data-lists";
|
||||||
|
import type Move from "./move";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class for the {@linkcode Move} class for Pokemon to interact with.
|
||||||
|
* These are the moves assigned to a {@linkcode Pokemon} object.
|
||||||
|
* It links to {@linkcode Move} class via the move ID.
|
||||||
|
* Compared to {@linkcode Move}, this class also tracks things like
|
||||||
|
* PP Ups recieved, PP used, etc.
|
||||||
|
* @see {@linkcode isUsable} - checks if move is restricted, out of PP, or not implemented.
|
||||||
|
* @see {@linkcode getMove} - returns {@linkcode Move} object by looking it up via ID.
|
||||||
|
* @see {@linkcode usePp} - removes a point of PP from the move.
|
||||||
|
* @see {@linkcode getMovePp} - returns amount of PP a move currently has.
|
||||||
|
* @see {@linkcode getPpRatio} - returns the current PP amount / max PP amount.
|
||||||
|
* @see {@linkcode getName} - returns name of {@linkcode Move}.
|
||||||
|
**/
|
||||||
|
export class PokemonMove {
|
||||||
|
public moveId: MoveId;
|
||||||
|
public ppUsed: number;
|
||||||
|
public ppUp: number;
|
||||||
|
public virtual: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If defined and nonzero, overrides the maximum PP of the move (e.g., due to move being copied by Transform).
|
||||||
|
* This also nullifies all effects of `ppUp`.
|
||||||
|
*/
|
||||||
|
public maxPpOverride?: number;
|
||||||
|
|
||||||
|
constructor(moveId: MoveId, ppUsed = 0, ppUp = 0, virtual = false, maxPpOverride?: number) {
|
||||||
|
this.moveId = moveId;
|
||||||
|
this.ppUsed = ppUsed;
|
||||||
|
this.ppUp = ppUp;
|
||||||
|
this.virtual = virtual;
|
||||||
|
this.maxPpOverride = maxPpOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the move can be selected or performed by a Pokemon, without consideration for the move's targets.
|
||||||
|
* The move is unusable if it is out of PP, restricted by an effect, or unimplemented.
|
||||||
|
*
|
||||||
|
* @param pokemon - {@linkcode Pokemon} that would be using this move
|
||||||
|
* @param ignorePp - If `true`, skips the PP check
|
||||||
|
* @param ignoreRestrictionTags - If `true`, skips the check for move restriction tags (see {@link MoveRestrictionBattlerTag})
|
||||||
|
* @returns `true` if the move can be selected and used by the Pokemon, otherwise `false`.
|
||||||
|
*/
|
||||||
|
isUsable(pokemon: Pokemon, ignorePp = false, ignoreRestrictionTags = false): boolean {
|
||||||
|
if (this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId, pokemon)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getMove().name.endsWith(" (N)")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMove(): Move {
|
||||||
|
return allMoves[this.moveId];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets {@link ppUsed} for this move and ensures the value does not exceed {@link getMovePp}
|
||||||
|
* @param count Amount of PP to use
|
||||||
|
*/
|
||||||
|
usePp(count = 1) {
|
||||||
|
this.ppUsed = Math.min(this.ppUsed + count, this.getMovePp());
|
||||||
|
}
|
||||||
|
|
||||||
|
getMovePp(): number {
|
||||||
|
return this.maxPpOverride || this.getMove().pp + this.ppUp * toDmgValue(this.getMove().pp / 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPpRatio(): number {
|
||||||
|
return 1 - this.ppUsed / this.getMovePp();
|
||||||
|
}
|
||||||
|
|
||||||
|
getName(): string {
|
||||||
|
return this.getMove().name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies an existing move or creates a valid {@linkcode PokemonMove} object from json representing one
|
||||||
|
* @param source The data for the move to copy; can be a {@linkcode PokemonMove} or JSON object representing one
|
||||||
|
* @returns A valid {@linkcode PokemonMove} object
|
||||||
|
*/
|
||||||
|
static loadMove(source: PokemonMove | any): PokemonMove {
|
||||||
|
return new PokemonMove(source.moveId, source.ppUsed, source.ppUp, source.virtual, source.maxPpOverride);
|
||||||
|
}
|
||||||
|
}
|
@ -12,14 +12,13 @@ import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounte
|
|||||||
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { randSeedInt } from "#app/utils/common";
|
import { randSeedInt } from "#app/utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type { IEggOptions } from "#app/data/egg";
|
import type { IEggOptions } from "#app/data/egg";
|
||||||
import { EggSourceType } from "#enums/egg-source-types";
|
import { EggSourceType } from "#enums/egg-source-types";
|
||||||
import { EggTier } from "#enums/egg-type";
|
import { EggTier } from "#enums/egg-type";
|
||||||
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
|
||||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
@ -54,27 +53,27 @@ export const ATrainersTestEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
switch (randSeedInt(5)) {
|
switch (randSeedInt(5)) {
|
||||||
case 1:
|
case 1:
|
||||||
trainerType = TrainerType.CHERYL;
|
trainerType = TrainerType.CHERYL;
|
||||||
spriteKeys = getSpriteKeysFromSpecies(Species.BLISSEY);
|
spriteKeys = getSpriteKeysFromSpecies(SpeciesId.BLISSEY);
|
||||||
trainerNameKey = "cheryl";
|
trainerNameKey = "cheryl";
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
trainerType = TrainerType.MARLEY;
|
trainerType = TrainerType.MARLEY;
|
||||||
spriteKeys = getSpriteKeysFromSpecies(Species.ARCANINE);
|
spriteKeys = getSpriteKeysFromSpecies(SpeciesId.ARCANINE);
|
||||||
trainerNameKey = "marley";
|
trainerNameKey = "marley";
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
trainerType = TrainerType.MIRA;
|
trainerType = TrainerType.MIRA;
|
||||||
spriteKeys = getSpriteKeysFromSpecies(Species.ALAKAZAM, false, 1);
|
spriteKeys = getSpriteKeysFromSpecies(SpeciesId.ALAKAZAM, false, 1);
|
||||||
trainerNameKey = "mira";
|
trainerNameKey = "mira";
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
trainerType = TrainerType.RILEY;
|
trainerType = TrainerType.RILEY;
|
||||||
spriteKeys = getSpriteKeysFromSpecies(Species.LUCARIO, false, 1);
|
spriteKeys = getSpriteKeysFromSpecies(SpeciesId.LUCARIO, false, 1);
|
||||||
trainerNameKey = "riley";
|
trainerNameKey = "riley";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
trainerType = TrainerType.BUCK;
|
trainerType = TrainerType.BUCK;
|
||||||
spriteKeys = getSpriteKeysFromSpecies(Species.CLAYDOL);
|
spriteKeys = getSpriteKeysFromSpecies(SpeciesId.CLAYDOL);
|
||||||
trainerNameKey = "buck";
|
trainerNameKey = "buck";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -182,7 +181,7 @@ export const ATrainersTestEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
async () => {
|
async () => {
|
||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
// Full heal party
|
// Full heal party
|
||||||
globalScene.unshiftPhase(new PartyHealPhase(true));
|
globalScene.phaseManager.unshiftNew("PartyHealPhase", true);
|
||||||
|
|
||||||
const eggOptions: IEggOptions = {
|
const eggOptions: IEggOptions = {
|
||||||
pulled: false,
|
pulled: false,
|
||||||
|
@ -7,11 +7,12 @@ import {
|
|||||||
transitionMysteryEncounterIntroVisuals,
|
transitionMysteryEncounterIntroVisuals,
|
||||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
|
import { EnemyPokemon } from "#app/field/pokemon";
|
||||||
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import type { BerryModifierType, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
import type { BerryModifierType, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
@ -22,10 +23,10 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
|||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { BerryModifier, PokemonInstantReviveModifier } from "#app/modifier/modifier";
|
import { BerryModifier, PokemonInstantReviveModifier } from "#app/modifier/modifier";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { randInt } from "#app/utils/common";
|
import { randInt } from "#app/utils/common";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import {
|
import {
|
||||||
applyModifierTypeToPlayerPokemon,
|
applyModifierTypeToPlayerPokemon,
|
||||||
catchPokemon,
|
catchPokemon,
|
||||||
@ -33,9 +34,8 @@ import {
|
|||||||
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { TrainerSlot } from "#enums/trainer-slot";
|
import { TrainerSlot } from "#enums/trainer-slot";
|
||||||
import { PokeballType } from "#enums/pokeball";
|
import { PokeballType } from "#enums/pokeball";
|
||||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||||
import type { BerryType } from "#enums/berry-type";
|
import type { BerryType } from "#enums/berry-type";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
// This sprite has the shadow
|
// This sprite has the shadow
|
||||||
spriteKey: "",
|
spriteKey: "",
|
||||||
fileRoot: "",
|
fileRoot: "",
|
||||||
species: Species.GREEDENT,
|
species: SpeciesId.GREEDENT,
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
alpha: 0.001,
|
alpha: 0.001,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
@ -68,7 +68,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
{
|
{
|
||||||
spriteKey: "",
|
spriteKey: "",
|
||||||
fileRoot: "",
|
fileRoot: "",
|
||||||
species: Species.GREEDENT,
|
species: SpeciesId.GREEDENT,
|
||||||
hasShadow: false,
|
hasShadow: false,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
x: -5,
|
x: -5,
|
||||||
@ -228,17 +228,21 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
levelAdditiveModifier: 1,
|
levelAdditiveModifier: 1,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.GREEDENT),
|
species: getPokemonSpecies(SpeciesId.GREEDENT),
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
bossSegments: 3,
|
bossSegments: 3,
|
||||||
shiny: false, // Shiny lock because of consistency issues between the different options
|
shiny: false, // Shiny lock because of consistency issues between the different options
|
||||||
moveSet: [Moves.THRASH, Moves.CRUNCH, Moves.BODY_PRESS, Moves.SLACK_OFF],
|
moveSet: [MoveId.THRASH, MoveId.CRUNCH, MoveId.BODY_PRESS, MoveId.SLACK_OFF],
|
||||||
modifierConfigs: bossModifierConfigs,
|
modifierConfigs: bossModifierConfigs,
|
||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:option.1.boss_enraged`);
|
queueEncounterMessage(`${namespace}:option.1.boss_enraged`);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, statChangesForBattle, 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
statChangesForBattle,
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -246,7 +250,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
};
|
};
|
||||||
|
|
||||||
encounter.enemyPartyConfigs = [config];
|
encounter.enemyPartyConfigs = [config];
|
||||||
encounter.setDialogueToken("greedentName", getPokemonSpecies(Species.GREEDENT).getName());
|
encounter.setDialogueToken("greedentName", getPokemonSpecies(SpeciesId.GREEDENT).getName());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
@ -302,7 +306,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
encounter.startOfBattleEffects.push({
|
encounter.startOfBattleEffects.push({
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||||
targets: [BattlerIndex.ENEMY],
|
targets: [BattlerIndex.ENEMY],
|
||||||
move: new PokemonMove(Moves.STUFF_CHEEKS),
|
move: new PokemonMove(MoveId.STUFF_CHEEKS),
|
||||||
ignorePp: true,
|
ignorePp: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -373,12 +377,12 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
// Let it have the food
|
// Let it have the food
|
||||||
// Greedent joins the team, level equal to 2 below highest party member (shiny locked)
|
// Greedent joins the team, level equal to 2 below highest party member (shiny locked)
|
||||||
const level = getHighestLevelPlayerPokemon(false, true).level - 2;
|
const level = getHighestLevelPlayerPokemon(false, true).level - 2;
|
||||||
const greedent = new EnemyPokemon(getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false, true);
|
const greedent = new EnemyPokemon(getPokemonSpecies(SpeciesId.GREEDENT), level, TrainerSlot.NONE, false, true);
|
||||||
greedent.moveset = [
|
greedent.moveset = [
|
||||||
new PokemonMove(Moves.THRASH),
|
new PokemonMove(MoveId.THRASH),
|
||||||
new PokemonMove(Moves.BODY_PRESS),
|
new PokemonMove(MoveId.BODY_PRESS),
|
||||||
new PokemonMove(Moves.STUFF_CHEEKS),
|
new PokemonMove(MoveId.STUFF_CHEEKS),
|
||||||
new PokemonMove(Moves.SLACK_OFF),
|
new PokemonMove(MoveId.SLACK_OFF),
|
||||||
];
|
];
|
||||||
greedent.passive = true;
|
greedent.passive = true;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
@ -22,7 +22,6 @@ import { getPokemonSpecies } from "#app/data/pokemon-species";
|
|||||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
@ -50,7 +49,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = MysteryEncounterB
|
|||||||
.withScenePartySizeRequirement(2, 6, true) // Must have at least 2 pokemon in party
|
.withScenePartySizeRequirement(2, 6, true) // Must have at least 2 pokemon in party
|
||||||
.withIntroSpriteConfigs([
|
.withIntroSpriteConfigs([
|
||||||
{
|
{
|
||||||
spriteKey: Species.LIEPARD.toString(),
|
spriteKey: SpeciesId.LIEPARD.toString(),
|
||||||
fileRoot: "pokemon",
|
fileRoot: "pokemon",
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
@ -112,7 +111,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = MysteryEncounterB
|
|||||||
|
|
||||||
const shinyCharm = generateModifierType(modifierTypes.SHINY_CHARM);
|
const shinyCharm = generateModifierType(modifierTypes.SHINY_CHARM);
|
||||||
encounter.setDialogueToken("itemName", shinyCharm?.name ?? i18next.t("modifierType:ModifierType.SHINY_CHARM.name"));
|
encounter.setDialogueToken("itemName", shinyCharm?.name ?? i18next.t("modifierType:ModifierType.SHINY_CHARM.name"));
|
||||||
encounter.setDialogueToken("liepardName", getPokemonSpecies(Species.LIEPARD).getName());
|
encounter.setDialogueToken("liepardName", getPokemonSpecies(SpeciesId.LIEPARD).getName());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
@ -137,7 +136,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = MysteryEncounterB
|
|||||||
})
|
})
|
||||||
.withOptionPhase(async () => {
|
.withOptionPhase(async () => {
|
||||||
// Give the player a Shiny Charm
|
// Give the player a Shiny Charm
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.SHINY_CHARM));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.SHINY_CHARM);
|
||||||
leaveEncounterWithoutBattle(true);
|
leaveEncounterWithoutBattle(true);
|
||||||
})
|
})
|
||||||
.build(),
|
.build(),
|
||||||
@ -167,7 +166,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = MysteryEncounterB
|
|||||||
// Update money and remove pokemon from party
|
// Update money and remove pokemon from party
|
||||||
updatePlayerMoney(encounter.misc.price);
|
updatePlayerMoney(encounter.misc.price);
|
||||||
|
|
||||||
setEncounterExp(encounter.options[1].primaryPokemon!.id, getPokemonSpecies(Species.LIEPARD).baseExp, true);
|
setEncounterExp(encounter.options[1].primaryPokemon!.id, getPokemonSpecies(SpeciesId.LIEPARD).baseExp, true);
|
||||||
|
|
||||||
leaveEncounterWithoutBattle(true);
|
leaveEncounterWithoutBattle(true);
|
||||||
})
|
})
|
||||||
|
@ -35,7 +35,6 @@ import { BerryModifier } from "#app/modifier/modifier";
|
|||||||
import i18next from "#app/plugins/i18n";
|
import i18next from "#app/plugins/i18n";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { PERMANENT_STATS, Stat } from "#enums/stat";
|
import { PERMANENT_STATS, Stat } from "#enums/stat";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
@ -237,8 +236,12 @@ export const BerriesAboundEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
||||||
config.pokemonConfigs![0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
|
config.pokemonConfigs![0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:option.2.boss_enraged`);
|
queueEncounterMessage(`${namespace}:option.2.boss_enraged`);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, statChangesForBattle, 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
statChangesForBattle,
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
setEncounterRewards(
|
setEncounterRewards(
|
||||||
|
@ -21,13 +21,12 @@ import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounte
|
|||||||
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import { getEncounterText, showEncounterDialogue } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText, showEncounterDialogue } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { Moves } from "#enums/moves";
|
|
||||||
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
@ -59,110 +58,116 @@ import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/enc
|
|||||||
const namespace = "mysteryEncounters/bugTypeSuperfan";
|
const namespace = "mysteryEncounters/bugTypeSuperfan";
|
||||||
|
|
||||||
const POOL_1_POKEMON = [
|
const POOL_1_POKEMON = [
|
||||||
Species.PARASECT,
|
SpeciesId.PARASECT,
|
||||||
Species.VENOMOTH,
|
SpeciesId.VENOMOTH,
|
||||||
Species.LEDIAN,
|
SpeciesId.LEDIAN,
|
||||||
Species.ARIADOS,
|
SpeciesId.ARIADOS,
|
||||||
Species.YANMA,
|
SpeciesId.YANMA,
|
||||||
Species.BEAUTIFLY,
|
SpeciesId.BEAUTIFLY,
|
||||||
Species.DUSTOX,
|
SpeciesId.DUSTOX,
|
||||||
Species.MASQUERAIN,
|
SpeciesId.MASQUERAIN,
|
||||||
Species.NINJASK,
|
SpeciesId.NINJASK,
|
||||||
Species.VOLBEAT,
|
SpeciesId.VOLBEAT,
|
||||||
Species.ILLUMISE,
|
SpeciesId.ILLUMISE,
|
||||||
Species.ANORITH,
|
SpeciesId.ANORITH,
|
||||||
Species.KRICKETUNE,
|
SpeciesId.KRICKETUNE,
|
||||||
Species.WORMADAM,
|
SpeciesId.WORMADAM,
|
||||||
Species.MOTHIM,
|
SpeciesId.MOTHIM,
|
||||||
Species.SKORUPI,
|
SpeciesId.SKORUPI,
|
||||||
Species.JOLTIK,
|
SpeciesId.JOLTIK,
|
||||||
Species.LARVESTA,
|
SpeciesId.LARVESTA,
|
||||||
Species.VIVILLON,
|
SpeciesId.VIVILLON,
|
||||||
Species.CHARJABUG,
|
SpeciesId.CHARJABUG,
|
||||||
Species.RIBOMBEE,
|
SpeciesId.RIBOMBEE,
|
||||||
Species.SPIDOPS,
|
SpeciesId.SPIDOPS,
|
||||||
Species.LOKIX,
|
SpeciesId.LOKIX,
|
||||||
];
|
];
|
||||||
|
|
||||||
const POOL_2_POKEMON = [
|
const POOL_2_POKEMON = [
|
||||||
Species.SCYTHER,
|
SpeciesId.SCYTHER,
|
||||||
Species.PINSIR,
|
SpeciesId.PINSIR,
|
||||||
Species.HERACROSS,
|
SpeciesId.HERACROSS,
|
||||||
Species.FORRETRESS,
|
SpeciesId.FORRETRESS,
|
||||||
Species.SCIZOR,
|
SpeciesId.SCIZOR,
|
||||||
Species.SHUCKLE,
|
SpeciesId.SHUCKLE,
|
||||||
Species.SHEDINJA,
|
SpeciesId.SHEDINJA,
|
||||||
Species.ARMALDO,
|
SpeciesId.ARMALDO,
|
||||||
Species.VESPIQUEN,
|
SpeciesId.VESPIQUEN,
|
||||||
Species.DRAPION,
|
SpeciesId.DRAPION,
|
||||||
Species.YANMEGA,
|
SpeciesId.YANMEGA,
|
||||||
Species.LEAVANNY,
|
SpeciesId.LEAVANNY,
|
||||||
Species.SCOLIPEDE,
|
SpeciesId.SCOLIPEDE,
|
||||||
Species.CRUSTLE,
|
SpeciesId.CRUSTLE,
|
||||||
Species.ESCAVALIER,
|
SpeciesId.ESCAVALIER,
|
||||||
Species.ACCELGOR,
|
SpeciesId.ACCELGOR,
|
||||||
Species.GALVANTULA,
|
SpeciesId.GALVANTULA,
|
||||||
Species.VIKAVOLT,
|
SpeciesId.VIKAVOLT,
|
||||||
Species.ARAQUANID,
|
SpeciesId.ARAQUANID,
|
||||||
Species.ORBEETLE,
|
SpeciesId.ORBEETLE,
|
||||||
Species.CENTISKORCH,
|
SpeciesId.CENTISKORCH,
|
||||||
Species.FROSMOTH,
|
SpeciesId.FROSMOTH,
|
||||||
Species.KLEAVOR,
|
SpeciesId.KLEAVOR,
|
||||||
];
|
];
|
||||||
|
|
||||||
const POOL_3_POKEMON: { species: Species; formIndex?: number }[] = [
|
const POOL_3_POKEMON: { species: SpeciesId; formIndex?: number }[] = [
|
||||||
{
|
{
|
||||||
species: Species.PINSIR,
|
species: SpeciesId.PINSIR,
|
||||||
formIndex: 1,
|
formIndex: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: Species.SCIZOR,
|
species: SpeciesId.SCIZOR,
|
||||||
formIndex: 1,
|
formIndex: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: Species.HERACROSS,
|
species: SpeciesId.HERACROSS,
|
||||||
formIndex: 1,
|
formIndex: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: Species.ORBEETLE,
|
species: SpeciesId.ORBEETLE,
|
||||||
formIndex: 1,
|
formIndex: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: Species.CENTISKORCH,
|
species: SpeciesId.CENTISKORCH,
|
||||||
formIndex: 1,
|
formIndex: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: Species.DURANT,
|
species: SpeciesId.DURANT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: Species.VOLCARONA,
|
species: SpeciesId.VOLCARONA,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: Species.GOLISOPOD,
|
species: SpeciesId.GOLISOPOD,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const POOL_4_POKEMON = [Species.GENESECT, Species.SLITHER_WING, Species.BUZZWOLE, Species.PHEROMOSA];
|
const POOL_4_POKEMON = [SpeciesId.GENESECT, SpeciesId.SLITHER_WING, SpeciesId.BUZZWOLE, SpeciesId.PHEROMOSA];
|
||||||
|
|
||||||
const PHYSICAL_TUTOR_MOVES = [Moves.MEGAHORN, Moves.ATTACK_ORDER, Moves.BUG_BITE, Moves.FIRST_IMPRESSION, Moves.LUNGE];
|
const PHYSICAL_TUTOR_MOVES = [
|
||||||
|
MoveId.MEGAHORN,
|
||||||
|
MoveId.ATTACK_ORDER,
|
||||||
|
MoveId.BUG_BITE,
|
||||||
|
MoveId.FIRST_IMPRESSION,
|
||||||
|
MoveId.LUNGE,
|
||||||
|
];
|
||||||
|
|
||||||
const SPECIAL_TUTOR_MOVES = [
|
const SPECIAL_TUTOR_MOVES = [
|
||||||
Moves.SILVER_WIND,
|
MoveId.SILVER_WIND,
|
||||||
Moves.SIGNAL_BEAM,
|
MoveId.SIGNAL_BEAM,
|
||||||
Moves.BUG_BUZZ,
|
MoveId.BUG_BUZZ,
|
||||||
Moves.POLLEN_PUFF,
|
MoveId.POLLEN_PUFF,
|
||||||
Moves.STRUGGLE_BUG,
|
MoveId.STRUGGLE_BUG,
|
||||||
];
|
];
|
||||||
|
|
||||||
const STATUS_TUTOR_MOVES = [
|
const STATUS_TUTOR_MOVES = [
|
||||||
Moves.STRING_SHOT,
|
MoveId.STRING_SHOT,
|
||||||
Moves.DEFEND_ORDER,
|
MoveId.DEFEND_ORDER,
|
||||||
Moves.RAGE_POWDER,
|
MoveId.RAGE_POWDER,
|
||||||
Moves.STICKY_WEB,
|
MoveId.STICKY_WEB,
|
||||||
Moves.SILK_TRAP,
|
MoveId.SILK_TRAP,
|
||||||
];
|
];
|
||||||
|
|
||||||
const MISC_TUTOR_MOVES = [Moves.LEECH_LIFE, Moves.U_TURN, Moves.HEAL_ORDER, Moves.QUIVER_DANCE, Moves.INFESTATION];
|
const MISC_TUTOR_MOVES = [MoveId.LEECH_LIFE, MoveId.U_TURN, MoveId.HEAL_ORDER, MoveId.QUIVER_DANCE, MoveId.INFESTATION];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wave breakpoints that determine how strong to make the Bug-Type Superfan's team
|
* Wave breakpoints that determine how strong to make the Bug-Type Superfan's team
|
||||||
@ -213,12 +218,12 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
|
|
||||||
let beedrillKeys: { spriteKey: string; fileRoot: string }, butterfreeKeys: { spriteKey: string; fileRoot: string };
|
let beedrillKeys: { spriteKey: string; fileRoot: string }, butterfreeKeys: { spriteKey: string; fileRoot: string };
|
||||||
if (globalScene.currentBattle.waveIndex < WAVE_LEVEL_BREAKPOINTS[3]) {
|
if (globalScene.currentBattle.waveIndex < WAVE_LEVEL_BREAKPOINTS[3]) {
|
||||||
beedrillKeys = getSpriteKeysFromSpecies(Species.BEEDRILL, false);
|
beedrillKeys = getSpriteKeysFromSpecies(SpeciesId.BEEDRILL, false);
|
||||||
butterfreeKeys = getSpriteKeysFromSpecies(Species.BUTTERFREE, false);
|
butterfreeKeys = getSpriteKeysFromSpecies(SpeciesId.BUTTERFREE, false);
|
||||||
} else {
|
} else {
|
||||||
// Mega Beedrill/Gmax Butterfree
|
// Mega Beedrill/Gmax Butterfree
|
||||||
beedrillKeys = getSpriteKeysFromSpecies(Species.BEEDRILL, false, 1);
|
beedrillKeys = getSpriteKeysFromSpecies(SpeciesId.BEEDRILL, false, 1);
|
||||||
butterfreeKeys = getSpriteKeysFromSpecies(Species.BUTTERFREE, false, 1);
|
butterfreeKeys = getSpriteKeysFromSpecies(SpeciesId.BUTTERFREE, false, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
encounter.spriteConfigs = [
|
encounter.spriteConfigs = [
|
||||||
@ -519,26 +524,26 @@ function getTrainerConfigForWave(waveIndex: number) {
|
|||||||
if (waveIndex < WAVE_LEVEL_BREAKPOINTS[0]) {
|
if (waveIndex < WAVE_LEVEL_BREAKPOINTS[0]) {
|
||||||
// Use default template (2 AVG)
|
// Use default template (2 AVG)
|
||||||
config
|
config
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BEEDRILL], TrainerSlot.TRAINER, true))
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.BEEDRILL], TrainerSlot.TRAINER, true))
|
||||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.BUTTERFREE], TrainerSlot.TRAINER, true));
|
.setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.BUTTERFREE], TrainerSlot.TRAINER, true));
|
||||||
} else if (waveIndex < WAVE_LEVEL_BREAKPOINTS[1]) {
|
} else if (waveIndex < WAVE_LEVEL_BREAKPOINTS[1]) {
|
||||||
config
|
config
|
||||||
.setPartyTemplates(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE))
|
.setPartyTemplates(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE))
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BEEDRILL], TrainerSlot.TRAINER, true))
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.BEEDRILL], TrainerSlot.TRAINER, true))
|
||||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.BUTTERFREE], TrainerSlot.TRAINER, true))
|
.setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.BUTTERFREE], TrainerSlot.TRAINER, true))
|
||||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true));
|
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true));
|
||||||
} else if (waveIndex < WAVE_LEVEL_BREAKPOINTS[2]) {
|
} else if (waveIndex < WAVE_LEVEL_BREAKPOINTS[2]) {
|
||||||
config
|
config
|
||||||
.setPartyTemplates(new TrainerPartyTemplate(4, PartyMemberStrength.AVERAGE))
|
.setPartyTemplates(new TrainerPartyTemplate(4, PartyMemberStrength.AVERAGE))
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BEEDRILL], TrainerSlot.TRAINER, true))
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.BEEDRILL], TrainerSlot.TRAINER, true))
|
||||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.BUTTERFREE], TrainerSlot.TRAINER, true))
|
.setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.BUTTERFREE], TrainerSlot.TRAINER, true))
|
||||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true))
|
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true))
|
||||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true));
|
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true));
|
||||||
} else if (waveIndex < WAVE_LEVEL_BREAKPOINTS[3]) {
|
} else if (waveIndex < WAVE_LEVEL_BREAKPOINTS[3]) {
|
||||||
config
|
config
|
||||||
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
|
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BEEDRILL], TrainerSlot.TRAINER, true))
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.BEEDRILL], TrainerSlot.TRAINER, true))
|
||||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.BUTTERFREE], TrainerSlot.TRAINER, true))
|
.setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.BUTTERFREE], TrainerSlot.TRAINER, true))
|
||||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true))
|
.setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_1_POKEMON, TrainerSlot.TRAINER, true))
|
||||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
.setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true))
|
||||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true));
|
.setPartyMemberFunc(4, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true));
|
||||||
@ -547,7 +552,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
|||||||
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
|
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
|
||||||
.setPartyMemberFunc(
|
.setPartyMemberFunc(
|
||||||
0,
|
0,
|
||||||
getRandomPartyMemberFunc([Species.BEEDRILL], TrainerSlot.TRAINER, true, p => {
|
getRandomPartyMemberFunc([SpeciesId.BEEDRILL], TrainerSlot.TRAINER, true, p => {
|
||||||
p.formIndex = 1;
|
p.formIndex = 1;
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.generateName();
|
p.generateName();
|
||||||
@ -555,7 +560,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
|||||||
)
|
)
|
||||||
.setPartyMemberFunc(
|
.setPartyMemberFunc(
|
||||||
1,
|
1,
|
||||||
getRandomPartyMemberFunc([Species.BUTTERFREE], TrainerSlot.TRAINER, true, p => {
|
getRandomPartyMemberFunc([SpeciesId.BUTTERFREE], TrainerSlot.TRAINER, true, p => {
|
||||||
p.formIndex = 1;
|
p.formIndex = 1;
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.generateName();
|
p.generateName();
|
||||||
@ -580,7 +585,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
|||||||
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
|
.setPartyTemplates(new TrainerPartyTemplate(5, PartyMemberStrength.AVERAGE))
|
||||||
.setPartyMemberFunc(
|
.setPartyMemberFunc(
|
||||||
0,
|
0,
|
||||||
getRandomPartyMemberFunc([Species.BEEDRILL], TrainerSlot.TRAINER, true, p => {
|
getRandomPartyMemberFunc([SpeciesId.BEEDRILL], TrainerSlot.TRAINER, true, p => {
|
||||||
p.formIndex = 1;
|
p.formIndex = 1;
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.generateName();
|
p.generateName();
|
||||||
@ -588,7 +593,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
|||||||
)
|
)
|
||||||
.setPartyMemberFunc(
|
.setPartyMemberFunc(
|
||||||
1,
|
1,
|
||||||
getRandomPartyMemberFunc([Species.BUTTERFREE], TrainerSlot.TRAINER, true, p => {
|
getRandomPartyMemberFunc([SpeciesId.BUTTERFREE], TrainerSlot.TRAINER, true, p => {
|
||||||
p.formIndex = 1;
|
p.formIndex = 1;
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.generateName();
|
p.generateName();
|
||||||
@ -625,7 +630,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
|||||||
)
|
)
|
||||||
.setPartyMemberFunc(
|
.setPartyMemberFunc(
|
||||||
0,
|
0,
|
||||||
getRandomPartyMemberFunc([Species.BEEDRILL], TrainerSlot.TRAINER, true, p => {
|
getRandomPartyMemberFunc([SpeciesId.BEEDRILL], TrainerSlot.TRAINER, true, p => {
|
||||||
p.formIndex = 1;
|
p.formIndex = 1;
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.generateName();
|
p.generateName();
|
||||||
@ -633,7 +638,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
|||||||
)
|
)
|
||||||
.setPartyMemberFunc(
|
.setPartyMemberFunc(
|
||||||
1,
|
1,
|
||||||
getRandomPartyMemberFunc([Species.BUTTERFREE], TrainerSlot.TRAINER, true, p => {
|
getRandomPartyMemberFunc([SpeciesId.BUTTERFREE], TrainerSlot.TRAINER, true, p => {
|
||||||
p.formIndex = 1;
|
p.formIndex = 1;
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.generateName();
|
p.generateName();
|
||||||
@ -663,7 +668,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
|||||||
)
|
)
|
||||||
.setPartyMemberFunc(
|
.setPartyMemberFunc(
|
||||||
0,
|
0,
|
||||||
getRandomPartyMemberFunc([Species.BEEDRILL], TrainerSlot.TRAINER, true, p => {
|
getRandomPartyMemberFunc([SpeciesId.BEEDRILL], TrainerSlot.TRAINER, true, p => {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
p.formIndex = 1;
|
p.formIndex = 1;
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
@ -672,7 +677,7 @@ function getTrainerConfigForWave(waveIndex: number) {
|
|||||||
)
|
)
|
||||||
.setPartyMemberFunc(
|
.setPartyMemberFunc(
|
||||||
1,
|
1,
|
||||||
getRandomPartyMemberFunc([Species.BUTTERFREE], TrainerSlot.TRAINER, true, p => {
|
getRandomPartyMemberFunc([SpeciesId.BUTTERFREE], TrainerSlot.TRAINER, true, p => {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
p.formIndex = 1;
|
p.formIndex = 1;
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
@ -760,8 +765,10 @@ function doBugTypeMoveTutor(): Promise<void> {
|
|||||||
|
|
||||||
// Option select complete, handle if they are learning a move
|
// Option select complete, handle if they are learning a move
|
||||||
if (result && result.selectedOptionIndex < moveOptions.length) {
|
if (result && result.selectedOptionIndex < moveOptions.length) {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new LearnMovePhase(result.selectedPokemonIndex, moveOptions[result.selectedOptionIndex].moveId),
|
"LearnMovePhase",
|
||||||
|
result.selectedPokemonIndex,
|
||||||
|
moveOptions[result.selectedOptionIndex].moveId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,10 +20,10 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import {
|
import {
|
||||||
applyAbilityOverrideToPokemon,
|
applyAbilityOverrideToPokemon,
|
||||||
applyModifierTypeToPlayerPokemon,
|
applyModifierTypeToPlayerPokemon,
|
||||||
@ -37,12 +37,12 @@ import { UiMode } from "#enums/ui-mode";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type { OptionSelectConfig } from "#app/ui/abstact-option-select-ui-handler";
|
import type { OptionSelectConfig } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import { Ability } from "#app/data/abilities/ability-class";
|
import { Ability } from "#app/data/abilities/ability-class";
|
||||||
import { BerryModifier } from "#app/modifier/modifier";
|
import { BerryModifier } from "#app/modifier/modifier";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { EncounterBattleAnim } from "#app/data/battle-anims";
|
import { EncounterBattleAnim } from "#app/data/battle-anims";
|
||||||
import { MoveCategory } from "#enums/MoveCategory";
|
import { MoveCategory } from "#enums/MoveCategory";
|
||||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
@ -54,21 +54,21 @@ import { Challenges } from "#enums/challenges";
|
|||||||
const namespace = "mysteryEncounters/clowningAround";
|
const namespace = "mysteryEncounters/clowningAround";
|
||||||
|
|
||||||
const RANDOM_ABILITY_POOL = [
|
const RANDOM_ABILITY_POOL = [
|
||||||
Abilities.STURDY,
|
AbilityId.STURDY,
|
||||||
Abilities.PICKUP,
|
AbilityId.PICKUP,
|
||||||
Abilities.INTIMIDATE,
|
AbilityId.INTIMIDATE,
|
||||||
Abilities.GUTS,
|
AbilityId.GUTS,
|
||||||
Abilities.DROUGHT,
|
AbilityId.DROUGHT,
|
||||||
Abilities.DRIZZLE,
|
AbilityId.DRIZZLE,
|
||||||
Abilities.SNOW_WARNING,
|
AbilityId.SNOW_WARNING,
|
||||||
Abilities.SAND_STREAM,
|
AbilityId.SAND_STREAM,
|
||||||
Abilities.ELECTRIC_SURGE,
|
AbilityId.ELECTRIC_SURGE,
|
||||||
Abilities.PSYCHIC_SURGE,
|
AbilityId.PSYCHIC_SURGE,
|
||||||
Abilities.GRASSY_SURGE,
|
AbilityId.GRASSY_SURGE,
|
||||||
Abilities.MISTY_SURGE,
|
AbilityId.MISTY_SURGE,
|
||||||
Abilities.MAGICIAN,
|
AbilityId.MAGICIAN,
|
||||||
Abilities.SHEER_FORCE,
|
AbilityId.SHEER_FORCE,
|
||||||
Abilities.PRANKSTER,
|
AbilityId.PRANKSTER,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,7 +86,7 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
.withAutoHideIntroVisuals(false)
|
.withAutoHideIntroVisuals(false)
|
||||||
.withIntroSpriteConfigs([
|
.withIntroSpriteConfigs([
|
||||||
{
|
{
|
||||||
spriteKey: Species.MR_MIME.toString(),
|
spriteKey: SpeciesId.MR_MIME.toString(),
|
||||||
fileRoot: "pokemon",
|
fileRoot: "pokemon",
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
@ -96,7 +96,7 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
yShadow: -3,
|
yShadow: -3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
spriteKey: Species.BLACEPHALON.toString(),
|
spriteKey: SpeciesId.BLACEPHALON.toString(),
|
||||||
fileRoot: "pokemon/exp",
|
fileRoot: "pokemon/exp",
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
@ -154,28 +154,28 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
// Overrides first 2 pokemon to be Mr. Mime and Blacephalon
|
// Overrides first 2 pokemon to be Mr. Mime and Blacephalon
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.MR_MIME),
|
species: getPokemonSpecies(SpeciesId.MR_MIME),
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
moveSet: [Moves.TEETER_DANCE, Moves.ALLY_SWITCH, Moves.DAZZLING_GLEAM, Moves.PSYCHIC],
|
moveSet: [MoveId.TEETER_DANCE, MoveId.ALLY_SWITCH, MoveId.DAZZLING_GLEAM, MoveId.PSYCHIC],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter
|
// Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter
|
||||||
species: getPokemonSpecies(Species.BLACEPHALON),
|
species: getPokemonSpecies(SpeciesId.BLACEPHALON),
|
||||||
customPokemonData: new CustomPokemonData({
|
customPokemonData: new CustomPokemonData({
|
||||||
ability: ability,
|
ability: ability,
|
||||||
types: [firstType, secondType],
|
types: [firstType, secondType],
|
||||||
}),
|
}),
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN],
|
moveSet: [MoveId.TRICK, MoveId.HYPNOSIS, MoveId.SHADOW_BALL, MoveId.MIND_BLOWN],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
doubleBattle: true,
|
doubleBattle: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load animations/sfx for start of fight moves
|
// Load animations/sfx for start of fight moves
|
||||||
loadCustomMovesForEncounter([Moves.ROLE_PLAY, Moves.TAUNT]);
|
loadCustomMovesForEncounter([MoveId.ROLE_PLAY, MoveId.TAUNT]);
|
||||||
|
|
||||||
encounter.setDialogueToken("blacephalonName", getPokemonSpecies(Species.BLACEPHALON).getName());
|
encounter.setDialogueToken("blacephalonName", getPokemonSpecies(SpeciesId.BLACEPHALON).getName());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
@ -208,19 +208,19 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
// Mr. Mime copies the Blacephalon's random ability
|
// Mr. Mime copies the Blacephalon's random ability
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||||
targets: [BattlerIndex.ENEMY_2],
|
targets: [BattlerIndex.ENEMY_2],
|
||||||
move: new PokemonMove(Moves.ROLE_PLAY),
|
move: new PokemonMove(MoveId.ROLE_PLAY),
|
||||||
ignorePp: true,
|
ignorePp: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||||
targets: [BattlerIndex.PLAYER],
|
targets: [BattlerIndex.PLAYER],
|
||||||
move: new PokemonMove(Moves.TAUNT),
|
move: new PokemonMove(MoveId.TAUNT),
|
||||||
ignorePp: true,
|
ignorePp: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||||
targets: [BattlerIndex.PLAYER_2],
|
targets: [BattlerIndex.PLAYER_2],
|
||||||
move: new PokemonMove(Moves.TAUNT),
|
move: new PokemonMove(MoveId.TAUNT),
|
||||||
ignorePp: true,
|
ignorePp: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { EncounterBattleAnim } from "#app/data/battle-anims";
|
import { EncounterBattleAnim } from "#app/data/battle-anims";
|
||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
@ -23,22 +23,21 @@ import { getPokemonSpecies } from "#app/data/pokemon-species";
|
|||||||
import { TrainerSlot } from "#enums/trainer-slot";
|
import { TrainerSlot } from "#enums/trainer-slot";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
|
import { EnemyPokemon } from "#app/field/pokemon";
|
||||||
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { Biome } from "#enums/biome";
|
import { BiomeId } from "#enums/biome-id";
|
||||||
import { EncounterAnim } from "#enums/encounter-anims";
|
import { EncounterAnim } from "#enums/encounter-anims";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { PokeballType } from "#enums/pokeball";
|
import { PokeballType } from "#enums/pokeball";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
@ -47,46 +46,46 @@ const namespace = "mysteryEncounters/dancingLessons";
|
|||||||
|
|
||||||
// Fire form
|
// Fire form
|
||||||
const BAILE_STYLE_BIOMES = [
|
const BAILE_STYLE_BIOMES = [
|
||||||
Biome.VOLCANO,
|
BiomeId.VOLCANO,
|
||||||
Biome.BEACH,
|
BiomeId.BEACH,
|
||||||
Biome.ISLAND,
|
BiomeId.ISLAND,
|
||||||
Biome.WASTELAND,
|
BiomeId.WASTELAND,
|
||||||
Biome.MOUNTAIN,
|
BiomeId.MOUNTAIN,
|
||||||
Biome.BADLANDS,
|
BiomeId.BADLANDS,
|
||||||
Biome.DESERT,
|
BiomeId.DESERT,
|
||||||
];
|
];
|
||||||
|
|
||||||
// Electric form
|
// Electric form
|
||||||
const POM_POM_STYLE_BIOMES = [
|
const POM_POM_STYLE_BIOMES = [
|
||||||
Biome.CONSTRUCTION_SITE,
|
BiomeId.CONSTRUCTION_SITE,
|
||||||
Biome.POWER_PLANT,
|
BiomeId.POWER_PLANT,
|
||||||
Biome.FACTORY,
|
BiomeId.FACTORY,
|
||||||
Biome.LABORATORY,
|
BiomeId.LABORATORY,
|
||||||
Biome.SLUM,
|
BiomeId.SLUM,
|
||||||
Biome.METROPOLIS,
|
BiomeId.METROPOLIS,
|
||||||
Biome.DOJO,
|
BiomeId.DOJO,
|
||||||
];
|
];
|
||||||
|
|
||||||
// Psychic form
|
// Psychic form
|
||||||
const PAU_STYLE_BIOMES = [
|
const PAU_STYLE_BIOMES = [
|
||||||
Biome.JUNGLE,
|
BiomeId.JUNGLE,
|
||||||
Biome.FAIRY_CAVE,
|
BiomeId.FAIRY_CAVE,
|
||||||
Biome.MEADOW,
|
BiomeId.MEADOW,
|
||||||
Biome.PLAINS,
|
BiomeId.PLAINS,
|
||||||
Biome.GRASS,
|
BiomeId.GRASS,
|
||||||
Biome.TALL_GRASS,
|
BiomeId.TALL_GRASS,
|
||||||
Biome.FOREST,
|
BiomeId.FOREST,
|
||||||
];
|
];
|
||||||
|
|
||||||
// Ghost form
|
// Ghost form
|
||||||
const SENSU_STYLE_BIOMES = [
|
const SENSU_STYLE_BIOMES = [
|
||||||
Biome.RUINS,
|
BiomeId.RUINS,
|
||||||
Biome.SWAMP,
|
BiomeId.SWAMP,
|
||||||
Biome.CAVE,
|
BiomeId.CAVE,
|
||||||
Biome.ABYSS,
|
BiomeId.ABYSS,
|
||||||
Biome.GRAVEYARD,
|
BiomeId.GRAVEYARD,
|
||||||
Biome.LAKE,
|
BiomeId.LAKE,
|
||||||
Biome.TEMPLE,
|
BiomeId.TEMPLE,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -127,14 +126,14 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
.withOnInit(() => {
|
.withOnInit(() => {
|
||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
|
|
||||||
const species = getPokemonSpecies(Species.ORICORIO);
|
const species = getPokemonSpecies(SpeciesId.ORICORIO);
|
||||||
const level = getEncounterPokemonLevelForWave(STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER);
|
const level = getEncounterPokemonLevelForWave(STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER);
|
||||||
const enemyPokemon = new EnemyPokemon(species, level, TrainerSlot.NONE, false);
|
const enemyPokemon = new EnemyPokemon(species, level, TrainerSlot.NONE, false);
|
||||||
if (!enemyPokemon.moveset.some(m => m && m.getMove().id === Moves.REVELATION_DANCE)) {
|
if (!enemyPokemon.moveset.some(m => m && m.getMove().id === MoveId.REVELATION_DANCE)) {
|
||||||
if (enemyPokemon.moveset.length < 4) {
|
if (enemyPokemon.moveset.length < 4) {
|
||||||
enemyPokemon.moveset.push(new PokemonMove(Moves.REVELATION_DANCE));
|
enemyPokemon.moveset.push(new PokemonMove(MoveId.REVELATION_DANCE));
|
||||||
} else {
|
} else {
|
||||||
enemyPokemon.moveset[0] = new PokemonMove(Moves.REVELATION_DANCE);
|
enemyPokemon.moveset[0] = new PokemonMove(MoveId.REVELATION_DANCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,13 +175,12 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:option.1.boss_enraged`);
|
queueEncounterMessage(`${namespace}:option.1.boss_enraged`);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(
|
"StatStageChangePhase",
|
||||||
pokemon.getBattlerIndex(),
|
pokemon.getBattlerIndex(),
|
||||||
true,
|
true,
|
||||||
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF],
|
[Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF],
|
||||||
1,
|
1,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -193,7 +191,7 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
oricorioData,
|
oricorioData,
|
||||||
};
|
};
|
||||||
|
|
||||||
encounter.setDialogueToken("oricorioName", getPokemonSpecies(Species.ORICORIO).getName());
|
encounter.setDialogueToken("oricorioName", getPokemonSpecies(SpeciesId.ORICORIO).getName());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
@ -215,7 +213,7 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
encounter.startOfBattleEffects.push({
|
encounter.startOfBattleEffects.push({
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||||
targets: [BattlerIndex.PLAYER],
|
targets: [BattlerIndex.PLAYER],
|
||||||
move: new PokemonMove(Moves.REVELATION_DANCE),
|
move: new PokemonMove(MoveId.REVELATION_DANCE),
|
||||||
ignorePp: true,
|
ignorePp: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -245,8 +243,10 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
|
|
||||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
encounter.setDialogueToken("selectedPokemon", pokemon.getNameToRender());
|
encounter.setDialogueToken("selectedPokemon", pokemon.getNameToRender());
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new LearnMovePhase(globalScene.getPlayerParty().indexOf(pokemon), Moves.REVELATION_DANCE),
|
"LearnMovePhase",
|
||||||
|
globalScene.getPlayerParty().indexOf(pokemon),
|
||||||
|
MoveId.REVELATION_DANCE,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Play animation again to "learn" the dance
|
// Play animation again to "learn" the dance
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { PokemonType } from "#enums/pokemon-type";
|
import type { PokemonType } from "#enums/pokemon-type";
|
||||||
import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
|
import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
@ -16,7 +16,6 @@ import {
|
|||||||
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
|
||||||
import type { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
import type { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
import { PokemonFormChangeItemModifier } from "#app/modifier/modifier";
|
import { PokemonFormChangeItemModifier } from "#app/modifier/modifier";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
@ -27,68 +26,68 @@ const namespace = "mysteryEncounters/darkDeal";
|
|||||||
|
|
||||||
/** Exclude Ultra Beasts (inludes Cosmog/Solgaleo/Lunala/Necrozma), Paradox (includes Miraidon/Koraidon), Eternatus, and Mythicals */
|
/** Exclude Ultra Beasts (inludes Cosmog/Solgaleo/Lunala/Necrozma), Paradox (includes Miraidon/Koraidon), Eternatus, and Mythicals */
|
||||||
const excludedBosses = [
|
const excludedBosses = [
|
||||||
Species.NECROZMA,
|
SpeciesId.NECROZMA,
|
||||||
Species.COSMOG,
|
SpeciesId.COSMOG,
|
||||||
Species.COSMOEM,
|
SpeciesId.COSMOEM,
|
||||||
Species.SOLGALEO,
|
SpeciesId.SOLGALEO,
|
||||||
Species.LUNALA,
|
SpeciesId.LUNALA,
|
||||||
Species.ETERNATUS,
|
SpeciesId.ETERNATUS,
|
||||||
Species.NIHILEGO,
|
SpeciesId.NIHILEGO,
|
||||||
Species.BUZZWOLE,
|
SpeciesId.BUZZWOLE,
|
||||||
Species.PHEROMOSA,
|
SpeciesId.PHEROMOSA,
|
||||||
Species.XURKITREE,
|
SpeciesId.XURKITREE,
|
||||||
Species.CELESTEELA,
|
SpeciesId.CELESTEELA,
|
||||||
Species.KARTANA,
|
SpeciesId.KARTANA,
|
||||||
Species.GUZZLORD,
|
SpeciesId.GUZZLORD,
|
||||||
Species.POIPOLE,
|
SpeciesId.POIPOLE,
|
||||||
Species.NAGANADEL,
|
SpeciesId.NAGANADEL,
|
||||||
Species.STAKATAKA,
|
SpeciesId.STAKATAKA,
|
||||||
Species.BLACEPHALON,
|
SpeciesId.BLACEPHALON,
|
||||||
Species.GREAT_TUSK,
|
SpeciesId.GREAT_TUSK,
|
||||||
Species.SCREAM_TAIL,
|
SpeciesId.SCREAM_TAIL,
|
||||||
Species.BRUTE_BONNET,
|
SpeciesId.BRUTE_BONNET,
|
||||||
Species.FLUTTER_MANE,
|
SpeciesId.FLUTTER_MANE,
|
||||||
Species.SLITHER_WING,
|
SpeciesId.SLITHER_WING,
|
||||||
Species.SANDY_SHOCKS,
|
SpeciesId.SANDY_SHOCKS,
|
||||||
Species.ROARING_MOON,
|
SpeciesId.ROARING_MOON,
|
||||||
Species.KORAIDON,
|
SpeciesId.KORAIDON,
|
||||||
Species.WALKING_WAKE,
|
SpeciesId.WALKING_WAKE,
|
||||||
Species.GOUGING_FIRE,
|
SpeciesId.GOUGING_FIRE,
|
||||||
Species.RAGING_BOLT,
|
SpeciesId.RAGING_BOLT,
|
||||||
Species.IRON_TREADS,
|
SpeciesId.IRON_TREADS,
|
||||||
Species.IRON_BUNDLE,
|
SpeciesId.IRON_BUNDLE,
|
||||||
Species.IRON_HANDS,
|
SpeciesId.IRON_HANDS,
|
||||||
Species.IRON_JUGULIS,
|
SpeciesId.IRON_JUGULIS,
|
||||||
Species.IRON_MOTH,
|
SpeciesId.IRON_MOTH,
|
||||||
Species.IRON_THORNS,
|
SpeciesId.IRON_THORNS,
|
||||||
Species.IRON_VALIANT,
|
SpeciesId.IRON_VALIANT,
|
||||||
Species.MIRAIDON,
|
SpeciesId.MIRAIDON,
|
||||||
Species.IRON_LEAVES,
|
SpeciesId.IRON_LEAVES,
|
||||||
Species.IRON_BOULDER,
|
SpeciesId.IRON_BOULDER,
|
||||||
Species.IRON_CROWN,
|
SpeciesId.IRON_CROWN,
|
||||||
Species.MEW,
|
SpeciesId.MEW,
|
||||||
Species.CELEBI,
|
SpeciesId.CELEBI,
|
||||||
Species.DEOXYS,
|
SpeciesId.DEOXYS,
|
||||||
Species.JIRACHI,
|
SpeciesId.JIRACHI,
|
||||||
Species.DARKRAI,
|
SpeciesId.DARKRAI,
|
||||||
Species.PHIONE,
|
SpeciesId.PHIONE,
|
||||||
Species.MANAPHY,
|
SpeciesId.MANAPHY,
|
||||||
Species.ARCEUS,
|
SpeciesId.ARCEUS,
|
||||||
Species.SHAYMIN,
|
SpeciesId.SHAYMIN,
|
||||||
Species.VICTINI,
|
SpeciesId.VICTINI,
|
||||||
Species.MELOETTA,
|
SpeciesId.MELOETTA,
|
||||||
Species.KELDEO,
|
SpeciesId.KELDEO,
|
||||||
Species.GENESECT,
|
SpeciesId.GENESECT,
|
||||||
Species.DIANCIE,
|
SpeciesId.DIANCIE,
|
||||||
Species.HOOPA,
|
SpeciesId.HOOPA,
|
||||||
Species.VOLCANION,
|
SpeciesId.VOLCANION,
|
||||||
Species.MAGEARNA,
|
SpeciesId.MAGEARNA,
|
||||||
Species.MARSHADOW,
|
SpeciesId.MARSHADOW,
|
||||||
Species.ZERAORA,
|
SpeciesId.ZERAORA,
|
||||||
Species.ZARUDE,
|
SpeciesId.ZARUDE,
|
||||||
Species.MELTAN,
|
SpeciesId.MELTAN,
|
||||||
Species.MELMETAL,
|
SpeciesId.MELMETAL,
|
||||||
Species.PECHARUNT,
|
SpeciesId.PECHARUNT,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,7 +164,7 @@ export const DarkDealEncounter: MysteryEncounter = MysteryEncounterBuilder.withE
|
|||||||
.withOptionPhase(async () => {
|
.withOptionPhase(async () => {
|
||||||
// Give the player 5 Rogue Balls
|
// Give the player 5 Rogue Balls
|
||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.ROGUE_BALL));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.ROGUE_BALL);
|
||||||
|
|
||||||
// Start encounter with random legendary (7-10 starter strength) that has level additive
|
// Start encounter with random legendary (7-10 starter strength) that has level additive
|
||||||
// If this is a mono-type challenge, always ensure the required type is filtered for
|
// If this is a mono-type challenge, always ensure the required type is filtered for
|
||||||
|
@ -29,14 +29,13 @@ import {
|
|||||||
} from "#app/modifier/modifier";
|
} from "#app/modifier/modifier";
|
||||||
import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
|
||||||
import i18next from "#app/plugins/i18n";
|
import i18next from "#app/plugins/i18n";
|
||||||
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import { randSeedItem } from "#app/utils/common";
|
import { randSeedItem } from "#app/utils/common";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { timedEventManager } from "#app/global-event-manager";
|
import { timedEventManager } from "#app/global-event-manager";
|
||||||
|
|
||||||
/** the i18n namespace for this encounter */
|
/** the i18n namespace for this encounter */
|
||||||
@ -65,10 +64,10 @@ const doEventReward = () => {
|
|||||||
return !(existingCharm && existingCharm.getStackCount() >= existingCharm.getMaxStackCount());
|
return !(existingCharm && existingCharm.getStackCount() >= existingCharm.getMaxStackCount());
|
||||||
});
|
});
|
||||||
if (candidates.length > 0) {
|
if (candidates.length > 0) {
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes[randSeedItem(candidates)]));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes[randSeedItem(candidates)]);
|
||||||
} else {
|
} else {
|
||||||
// At max stacks, give a Voucher instead
|
// At max stacks, give a Voucher instead
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.VOUCHER));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.VOUCHER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -95,7 +94,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
{
|
{
|
||||||
spriteKey: "",
|
spriteKey: "",
|
||||||
fileRoot: "",
|
fileRoot: "",
|
||||||
species: Species.DELIBIRD,
|
species: SpeciesId.DELIBIRD,
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
startFrame: 38,
|
startFrame: 38,
|
||||||
@ -104,7 +103,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
{
|
{
|
||||||
spriteKey: "",
|
spriteKey: "",
|
||||||
fileRoot: "",
|
fileRoot: "",
|
||||||
species: Species.DELIBIRD,
|
species: SpeciesId.DELIBIRD,
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
scale: 1.06,
|
scale: 1.06,
|
||||||
@ -112,7 +111,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
{
|
{
|
||||||
spriteKey: "",
|
spriteKey: "",
|
||||||
fileRoot: "",
|
fileRoot: "",
|
||||||
species: Species.DELIBIRD,
|
species: SpeciesId.DELIBIRD,
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
startFrame: 65,
|
startFrame: 65,
|
||||||
@ -137,7 +136,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
])
|
])
|
||||||
.withOnInit(() => {
|
.withOnInit(() => {
|
||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
encounter.setDialogueToken("delibirdName", getPokemonSpecies(Species.DELIBIRD).getName());
|
encounter.setDialogueToken("delibirdName", getPokemonSpecies(SpeciesId.DELIBIRD).getName());
|
||||||
|
|
||||||
globalScene.loadBgm("mystery_encounter_delibirdy", "mystery_encounter_delibirdy.mp3");
|
globalScene.loadBgm("mystery_encounter_delibirdy", "mystery_encounter_delibirdy.mp3");
|
||||||
return true;
|
return true;
|
||||||
@ -181,7 +180,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
);
|
);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.AMULET_COIN));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.AMULET_COIN);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +265,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
);
|
);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.CANDY_JAR));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.CANDY_JAR);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -288,7 +287,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
);
|
);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.BERRY_POUCH));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.BERRY_POUCH);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,7 +371,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
);
|
);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
} else {
|
} else {
|
||||||
globalScene.unshiftPhase(new ModifierRewardPhase(modifierTypes.HEALING_CHARM));
|
globalScene.phaseManager.unshiftNew("ModifierRewardPhase", modifierTypes.HEALING_CHARM);
|
||||||
doEventReward();
|
doEventReward();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import type { ModifierTypeFunc } from "#app/modifier/modifier-type";
|
|||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { randSeedInt } from "#app/utils/common";
|
import { randSeedInt } from "#app/utils/common";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
@ -35,7 +35,7 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter = MysteryEncounterBu
|
|||||||
{
|
{
|
||||||
spriteKey: "",
|
spriteKey: "",
|
||||||
fileRoot: "",
|
fileRoot: "",
|
||||||
species: Species.FURFROU,
|
species: SpeciesId.FURFROU,
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
x: 30,
|
x: 30,
|
||||||
|
@ -7,7 +7,8 @@ import {
|
|||||||
setEncounterExp,
|
setEncounterExp,
|
||||||
setEncounterRewards,
|
setEncounterRewards,
|
||||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import type { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
|
import type { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
|
@ -20,14 +20,14 @@ import {
|
|||||||
CombinationPokemonRequirement,
|
CombinationPokemonRequirement,
|
||||||
TypeRequirement,
|
TypeRequirement,
|
||||||
} from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
} from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { Gender } from "#app/data/gender";
|
import { Gender } from "#app/data/gender";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { EncounterBattleAnim } from "#app/data/battle-anims";
|
import { EncounterBattleAnim } from "#app/data/battle-anims";
|
||||||
import { WeatherType } from "#enums/weather-type";
|
import { WeatherType } from "#enums/weather-type";
|
||||||
import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
|
import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
|
||||||
@ -42,9 +42,8 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
|||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { EncounterAnim } from "#enums/encounter-anims";
|
import { EncounterAnim } from "#enums/encounter-anims";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { Ability } from "#app/data/abilities/ability-class";
|
import { Ability } from "#app/data/abilities/ability-class";
|
||||||
import { FIRE_RESISTANT_ABILITIES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
import { FIRE_RESISTANT_ABILITIES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||||
@ -83,7 +82,7 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
|||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
|
|
||||||
// Calculate boss mons
|
// Calculate boss mons
|
||||||
const volcaronaSpecies = getPokemonSpecies(Species.VOLCARONA);
|
const volcaronaSpecies = getPokemonSpecies(SpeciesId.VOLCARONA);
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
@ -92,8 +91,12 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
|||||||
gender: Gender.MALE,
|
gender: Gender.MALE,
|
||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, [Stat.SPDEF, Stat.SPD], 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[Stat.SPDEF, Stat.SPD],
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -103,8 +106,12 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
|||||||
gender: Gender.FEMALE,
|
gender: Gender.FEMALE,
|
||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, [Stat.SPDEF, Stat.SPD], 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[Stat.SPDEF, Stat.SPD],
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -119,7 +126,7 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
|||||||
{
|
{
|
||||||
spriteKey: "",
|
spriteKey: "",
|
||||||
fileRoot: "",
|
fileRoot: "",
|
||||||
species: Species.VOLCARONA,
|
species: SpeciesId.VOLCARONA,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
hidden: true,
|
hidden: true,
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
@ -129,7 +136,7 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
|||||||
{
|
{
|
||||||
spriteKey: "",
|
spriteKey: "",
|
||||||
fileRoot: "",
|
fileRoot: "",
|
||||||
species: Species.VOLCARONA,
|
species: SpeciesId.VOLCARONA,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
hidden: true,
|
hidden: true,
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
@ -138,12 +145,12 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Load animations/sfx for Volcarona moves
|
// Load animations/sfx for Volcarona moves
|
||||||
loadCustomMovesForEncounter([Moves.FIRE_SPIN, Moves.QUIVER_DANCE]);
|
loadCustomMovesForEncounter([MoveId.FIRE_SPIN, MoveId.QUIVER_DANCE]);
|
||||||
|
|
||||||
const pokemon = globalScene.getEnemyPokemon();
|
const pokemon = globalScene.getEnemyPokemon();
|
||||||
globalScene.arena.trySetWeather(WeatherType.SUNNY, pokemon);
|
globalScene.arena.trySetWeather(WeatherType.SUNNY, pokemon);
|
||||||
|
|
||||||
encounter.setDialogueToken("volcaronaName", getPokemonSpecies(Species.VOLCARONA).getName());
|
encounter.setDialogueToken("volcaronaName", getPokemonSpecies(SpeciesId.VOLCARONA).getName());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
@ -193,13 +200,13 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
|||||||
{
|
{
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||||
targets: [BattlerIndex.PLAYER],
|
targets: [BattlerIndex.PLAYER],
|
||||||
move: new PokemonMove(Moves.FIRE_SPIN),
|
move: new PokemonMove(MoveId.FIRE_SPIN),
|
||||||
ignorePp: true,
|
ignorePp: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
sourceBattlerIndex: BattlerIndex.ENEMY_2,
|
||||||
targets: [BattlerIndex.PLAYER_2],
|
targets: [BattlerIndex.PLAYER_2],
|
||||||
move: new PokemonMove(Moves.FIRE_SPIN),
|
move: new PokemonMove(MoveId.FIRE_SPIN),
|
||||||
ignorePp: true,
|
ignorePp: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -239,11 +246,11 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
|||||||
if (chosenPokemon.trySetStatus(StatusEffect.BURN)) {
|
if (chosenPokemon.trySetStatus(StatusEffect.BURN)) {
|
||||||
// Burn applied
|
// Burn applied
|
||||||
encounter.setDialogueToken("burnedPokemon", chosenPokemon.getNameToRender());
|
encounter.setDialogueToken("burnedPokemon", chosenPokemon.getNameToRender());
|
||||||
encounter.setDialogueToken("abilityName", new Ability(Abilities.HEATPROOF, 3).name);
|
encounter.setDialogueToken("abilityName", new Ability(AbilityId.HEATPROOF, 3).name);
|
||||||
queueEncounterMessage(`${namespace}:option.2.target_burned`);
|
queueEncounterMessage(`${namespace}:option.2.target_burned`);
|
||||||
|
|
||||||
// Also permanently change the burned Pokemon's ability to Heatproof
|
// Also permanently change the burned Pokemon's ability to Heatproof
|
||||||
applyAbilityOverrideToPokemon(chosenPokemon, Abilities.HEATPROOF);
|
applyAbilityOverrideToPokemon(chosenPokemon, AbilityId.HEATPROOF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +290,7 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
|||||||
|
|
||||||
const primary = encounter.options[2].primaryPokemon!;
|
const primary = encounter.options[2].primaryPokemon!;
|
||||||
|
|
||||||
setEncounterExp([primary.id], getPokemonSpecies(Species.VOLCARONA).baseExp * 2);
|
setEncounterExp([primary.id], getPokemonSpecies(SpeciesId.VOLCARONA).baseExp * 2);
|
||||||
leaveEncounterWithoutBattle();
|
leaveEncounterWithoutBattle();
|
||||||
})
|
})
|
||||||
.build(),
|
.build(),
|
||||||
|
@ -32,7 +32,6 @@ import PokemonData from "#app/system/pokemon-data";
|
|||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { randSeedInt } from "#app/utils/common";
|
import { randSeedInt } from "#app/utils/common";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
@ -76,7 +75,13 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
queueEncounterMessage(`${namespace}:option.1.stat_boost`);
|
queueEncounterMessage(`${namespace}:option.1.stat_boost`);
|
||||||
// Randomly boost 1 stat 2 stages
|
// Randomly boost 1 stat 2 stages
|
||||||
// Cannot boost Spd, Acc, or Evasion
|
// Cannot boost Spd, Acc, or Evasion
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [randSeedInt(4, 1)], 2));
|
globalScene.phaseManager.unshiftNew(
|
||||||
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[randSeedInt(4, 1)],
|
||||||
|
2,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -13,21 +13,19 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/myst
|
|||||||
import { TrainerSlot } from "#enums/trainer-slot";
|
import { TrainerSlot } from "#enums/trainer-slot";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { FieldPosition } from "#app/field/pokemon";
|
import { FieldPosition } from "#enums/field-position";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { PlayerGender } from "#enums/player-gender";
|
import { PlayerGender } from "#enums/player-gender";
|
||||||
import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball";
|
import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball";
|
||||||
import { addPokeballOpenParticles } from "#app/field/anims";
|
import { addPokeballOpenParticles } from "#app/field/anims";
|
||||||
import { ShinySparklePhase } from "#app/phases/shiny-sparkle-phase";
|
import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms/form-change-triggers";
|
||||||
import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms";
|
|
||||||
import { PostSummonPhase } from "#app/phases/post-summon-phase";
|
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
@ -91,7 +89,7 @@ export const FunAndGamesEncounter: MysteryEncounter = MysteryEncounterBuilder.wi
|
|||||||
.withOnInit(() => {
|
.withOnInit(() => {
|
||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
globalScene.loadBgm("mystery_encounter_fun_and_games", "mystery_encounter_fun_and_games.mp3");
|
globalScene.loadBgm("mystery_encounter_fun_and_games", "mystery_encounter_fun_and_games.mp3");
|
||||||
encounter.setDialogueToken("wobbuffetName", getPokemonSpecies(Species.WOBBUFFET).getName());
|
encounter.setDialogueToken("wobbuffetName", getPokemonSpecies(SpeciesId.WOBBUFFET).getName());
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.withOnVisualsStart(() => {
|
.withOnVisualsStart(() => {
|
||||||
@ -214,7 +212,7 @@ async function summonPlayerPokemon() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Also loads Wobbuffet data (cannot be shiny)
|
// Also loads Wobbuffet data (cannot be shiny)
|
||||||
const enemySpecies = getPokemonSpecies(Species.WOBBUFFET);
|
const enemySpecies = getPokemonSpecies(SpeciesId.WOBBUFFET);
|
||||||
globalScene.currentBattle.enemyParty = [];
|
globalScene.currentBattle.enemyParty = [];
|
||||||
const wobbuffet = globalScene.addEnemyPokemon(
|
const wobbuffet = globalScene.addEnemyPokemon(
|
||||||
enemySpecies,
|
enemySpecies,
|
||||||
@ -411,13 +409,13 @@ function summonPlayerPokemonAnimation(pokemon: PlayerPokemon): Promise<void> {
|
|||||||
pokemon.resetSummonData();
|
pokemon.resetSummonData();
|
||||||
globalScene.time.delayedCall(1000, () => {
|
globalScene.time.delayedCall(1000, () => {
|
||||||
if (pokemon.isShiny()) {
|
if (pokemon.isShiny()) {
|
||||||
globalScene.unshiftPhase(new ShinySparklePhase(pokemon.getBattlerIndex()));
|
globalScene.phaseManager.unshiftNew("ShinySparklePhase", pokemon.getBattlerIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
pokemon.resetTurnData();
|
pokemon.resetTurnData();
|
||||||
|
|
||||||
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true);
|
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true);
|
||||||
globalScene.pushPhase(new PostSummonPhase(pokemon.getBattlerIndex()));
|
globalScene.phaseManager.pushNew("PostSummonPhase", pokemon.getBattlerIndex());
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -17,7 +17,7 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import type PokemonSpecies from "#app/data/pokemon-species";
|
import type PokemonSpecies from "#app/data/pokemon-species";
|
||||||
import { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
import { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { getTypeRgb } from "#app/data/type";
|
import { getTypeRgb } from "#app/data/type";
|
||||||
@ -33,7 +33,8 @@ import {
|
|||||||
} from "#app/utils/common";
|
} from "#app/utils/common";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
|
import { EnemyPokemon } from "#app/field/pokemon";
|
||||||
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import type { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
import type { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
import {
|
import {
|
||||||
HiddenAbilityRateBoosterModifier,
|
HiddenAbilityRateBoosterModifier,
|
||||||
@ -64,39 +65,39 @@ const WONDER_TRADE_SHINY_CHANCE = 512;
|
|||||||
const MAX_WONDER_TRADE_SHINY_CHANCE = 4096;
|
const MAX_WONDER_TRADE_SHINY_CHANCE = 4096;
|
||||||
|
|
||||||
const LEGENDARY_TRADE_POOLS = {
|
const LEGENDARY_TRADE_POOLS = {
|
||||||
1: [Species.RATTATA, Species.PIDGEY, Species.WEEDLE],
|
1: [SpeciesId.RATTATA, SpeciesId.PIDGEY, SpeciesId.WEEDLE],
|
||||||
2: [Species.SENTRET, Species.HOOTHOOT, Species.LEDYBA],
|
2: [SpeciesId.SENTRET, SpeciesId.HOOTHOOT, SpeciesId.LEDYBA],
|
||||||
3: [Species.POOCHYENA, Species.ZIGZAGOON, Species.TAILLOW],
|
3: [SpeciesId.POOCHYENA, SpeciesId.ZIGZAGOON, SpeciesId.TAILLOW],
|
||||||
4: [Species.BIDOOF, Species.STARLY, Species.KRICKETOT],
|
4: [SpeciesId.BIDOOF, SpeciesId.STARLY, SpeciesId.KRICKETOT],
|
||||||
5: [Species.PATRAT, Species.PURRLOIN, Species.PIDOVE],
|
5: [SpeciesId.PATRAT, SpeciesId.PURRLOIN, SpeciesId.PIDOVE],
|
||||||
6: [Species.BUNNELBY, Species.LITLEO, Species.SCATTERBUG],
|
6: [SpeciesId.BUNNELBY, SpeciesId.LITLEO, SpeciesId.SCATTERBUG],
|
||||||
7: [Species.PIKIPEK, Species.YUNGOOS, Species.ROCKRUFF],
|
7: [SpeciesId.PIKIPEK, SpeciesId.YUNGOOS, SpeciesId.ROCKRUFF],
|
||||||
8: [Species.SKWOVET, Species.WOOLOO, Species.ROOKIDEE],
|
8: [SpeciesId.SKWOVET, SpeciesId.WOOLOO, SpeciesId.ROOKIDEE],
|
||||||
9: [Species.LECHONK, Species.FIDOUGH, Species.TAROUNTULA],
|
9: [SpeciesId.LECHONK, SpeciesId.FIDOUGH, SpeciesId.TAROUNTULA],
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Exclude Paradox mons as they aren't considered legendary/mythical */
|
/** Exclude Paradox mons as they aren't considered legendary/mythical */
|
||||||
const EXCLUDED_TRADE_SPECIES = [
|
const EXCLUDED_TRADE_SPECIES = [
|
||||||
Species.GREAT_TUSK,
|
SpeciesId.GREAT_TUSK,
|
||||||
Species.SCREAM_TAIL,
|
SpeciesId.SCREAM_TAIL,
|
||||||
Species.BRUTE_BONNET,
|
SpeciesId.BRUTE_BONNET,
|
||||||
Species.FLUTTER_MANE,
|
SpeciesId.FLUTTER_MANE,
|
||||||
Species.SLITHER_WING,
|
SpeciesId.SLITHER_WING,
|
||||||
Species.SANDY_SHOCKS,
|
SpeciesId.SANDY_SHOCKS,
|
||||||
Species.ROARING_MOON,
|
SpeciesId.ROARING_MOON,
|
||||||
Species.WALKING_WAKE,
|
SpeciesId.WALKING_WAKE,
|
||||||
Species.GOUGING_FIRE,
|
SpeciesId.GOUGING_FIRE,
|
||||||
Species.RAGING_BOLT,
|
SpeciesId.RAGING_BOLT,
|
||||||
Species.IRON_TREADS,
|
SpeciesId.IRON_TREADS,
|
||||||
Species.IRON_BUNDLE,
|
SpeciesId.IRON_BUNDLE,
|
||||||
Species.IRON_HANDS,
|
SpeciesId.IRON_HANDS,
|
||||||
Species.IRON_JUGULIS,
|
SpeciesId.IRON_JUGULIS,
|
||||||
Species.IRON_MOTH,
|
SpeciesId.IRON_MOTH,
|
||||||
Species.IRON_THORNS,
|
SpeciesId.IRON_THORNS,
|
||||||
Species.IRON_VALIANT,
|
SpeciesId.IRON_VALIANT,
|
||||||
Species.IRON_LEAVES,
|
SpeciesId.IRON_LEAVES,
|
||||||
Species.IRON_BOULDER,
|
SpeciesId.IRON_BOULDER,
|
||||||
Species.IRON_CROWN,
|
SpeciesId.IRON_CROWN,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { Moves } from "#app/enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { Species } from "#app/enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
@ -11,10 +11,10 @@ import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encount
|
|||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
|
|
||||||
const OPTION_1_REQUIRED_MOVE = Moves.SURF;
|
const OPTION_1_REQUIRED_MOVE = MoveId.SURF;
|
||||||
const OPTION_2_REQUIRED_MOVE = Moves.FLY;
|
const OPTION_2_REQUIRED_MOVE = MoveId.FLY;
|
||||||
/**
|
/**
|
||||||
* Damage percentage taken when wandering aimlessly.
|
* Damage percentage taken when wandering aimlessly.
|
||||||
* Can be a number between `0` - `100`.
|
* Can be a number between `0` - `100`.
|
||||||
@ -129,7 +129,7 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
|||||||
* Generic handler for using a guiding pokemon to guide you back.
|
* Generic handler for using a guiding pokemon to guide you back.
|
||||||
*/
|
*/
|
||||||
function handlePokemonGuidingYouPhase() {
|
function handlePokemonGuidingYouPhase() {
|
||||||
const laprasSpecies = getPokemonSpecies(Species.LAPRAS);
|
const laprasSpecies = getPokemonSpecies(SpeciesId.LAPRAS);
|
||||||
const { mysteryEncounter } = globalScene.currentBattle;
|
const { mysteryEncounter } = globalScene.currentBattle;
|
||||||
|
|
||||||
if (mysteryEncounter?.selectedOption?.primaryPokemon?.id) {
|
if (mysteryEncounter?.selectedOption?.primaryPokemon?.id) {
|
||||||
|
@ -17,13 +17,12 @@ import {
|
|||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
import { GameOverPhase } from "#app/phases/game-over-phase";
|
|
||||||
import { randSeedInt } from "#app/utils/common";
|
import { randSeedInt } from "#app/utils/common";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
|
||||||
/** i18n namespace for encounter */
|
/** i18n namespace for encounter */
|
||||||
const namespace = "mysteryEncounters/mysteriousChest";
|
const namespace = "mysteryEncounters/mysteriousChest";
|
||||||
@ -86,17 +85,17 @@ export const MysteriousChestEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
disableSwitch: true,
|
disableSwitch: true,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.GIMMIGHOUL),
|
species: getPokemonSpecies(SpeciesId.GIMMIGHOUL),
|
||||||
formIndex: 0,
|
formIndex: 0,
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
moveSet: [Moves.NASTY_PLOT, Moves.SHADOW_BALL, Moves.POWER_GEM, Moves.THIEF],
|
moveSet: [MoveId.NASTY_PLOT, MoveId.SHADOW_BALL, MoveId.POWER_GEM, MoveId.THIEF],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
encounter.enemyPartyConfigs = [config];
|
encounter.enemyPartyConfigs = [config];
|
||||||
|
|
||||||
encounter.setDialogueToken("gimmighoulName", getPokemonSpecies(Species.GIMMIGHOUL).getName());
|
encounter.setDialogueToken("gimmighoulName", getPokemonSpecies(SpeciesId.GIMMIGHOUL).getName());
|
||||||
encounter.setDialogueToken("trapPercent", TRAP_PERCENT.toString());
|
encounter.setDialogueToken("trapPercent", TRAP_PERCENT.toString());
|
||||||
encounter.setDialogueToken("commonPercent", COMMON_REWARDS_PERCENT.toString());
|
encounter.setDialogueToken("commonPercent", COMMON_REWARDS_PERCENT.toString());
|
||||||
encounter.setDialogueToken("ultraPercent", ULTRA_REWARDS_PERCENT.toString());
|
encounter.setDialogueToken("ultraPercent", ULTRA_REWARDS_PERCENT.toString());
|
||||||
@ -189,8 +188,8 @@ export const MysteriousChestEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
const allowedPokemon = globalScene.getPokemonAllowedInBattle();
|
const allowedPokemon = globalScene.getPokemonAllowedInBattle();
|
||||||
if (allowedPokemon.length === 0) {
|
if (allowedPokemon.length === 0) {
|
||||||
// If there are no longer any legal pokemon in the party, game over.
|
// If there are no longer any legal pokemon in the party, game over.
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.unshiftPhase(new GameOverPhase());
|
globalScene.phaseManager.unshiftNew("GameOverPhase");
|
||||||
} else {
|
} else {
|
||||||
// Show which Pokemon was KOed, then start battle against Gimmighoul
|
// Show which Pokemon was KOed, then start battle against Gimmighoul
|
||||||
await transitionMysteryEncounterIntroVisuals(true, true, 500);
|
await transitionMysteryEncounterIntroVisuals(true, true, 500);
|
||||||
|
@ -29,8 +29,6 @@ import { getEncounterText, showEncounterText } from "#app/data/mystery-encounter
|
|||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { ScanIvsPhase } from "#app/phases/scan-ivs-phase";
|
|
||||||
import { SummonPhase } from "#app/phases/summon-phase";
|
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { NON_LEGEND_PARADOX_POKEMON } from "#app/data/balance/special-species-groups";
|
import { NON_LEGEND_PARADOX_POKEMON } from "#app/data/balance/special-species-groups";
|
||||||
|
|
||||||
@ -276,7 +274,7 @@ async function summonSafariPokemon() {
|
|||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
// Message pokemon remaining
|
// Message pokemon remaining
|
||||||
encounter.setDialogueToken("remainingCount", encounter.misc.safariPokemonRemaining);
|
encounter.setDialogueToken("remainingCount", encounter.misc.safariPokemonRemaining);
|
||||||
globalScene.queueMessage(getEncounterText(`${namespace}:safari.remaining_count`) ?? "", null, true);
|
globalScene.phaseManager.queueMessage(getEncounterText(`${namespace}:safari.remaining_count`) ?? "", null, true);
|
||||||
|
|
||||||
// Generate pokemon using safariPokemonRemaining so they are always the same pokemon no matter how many turns are taken
|
// 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
|
// Safari pokemon roll twice on shiny and HA chances, but are otherwise normal
|
||||||
@ -325,7 +323,7 @@ async function summonSafariPokemon() {
|
|||||||
encounter.misc.pokemon = pokemon;
|
encounter.misc.pokemon = pokemon;
|
||||||
encounter.misc.safariPokemonRemaining -= 1;
|
encounter.misc.safariPokemonRemaining -= 1;
|
||||||
|
|
||||||
globalScene.unshiftPhase(new SummonPhase(0, false));
|
globalScene.phaseManager.unshiftNew("SummonPhase", 0, false);
|
||||||
|
|
||||||
encounter.setDialogueToken("pokemonName", getPokemonNameWithAffix(pokemon));
|
encounter.setDialogueToken("pokemonName", getPokemonNameWithAffix(pokemon));
|
||||||
|
|
||||||
@ -336,7 +334,7 @@ async function summonSafariPokemon() {
|
|||||||
|
|
||||||
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
|
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
|
||||||
if (ivScannerModifier) {
|
if (ivScannerModifier) {
|
||||||
globalScene.pushPhase(new ScanIvsPhase(pokemon.getBattlerIndex()));
|
globalScene.phaseManager.pushNew("ScanIvsPhase", pokemon.getBattlerIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +557,7 @@ async function doEndTurn(cursorIndex: number) {
|
|||||||
leaveEncounterWithoutBattle(true);
|
leaveEncounterWithoutBattle(true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
globalScene.queueMessage(getEncounterText(`${namespace}:safari.watching`) ?? "", 0, null, 1000);
|
globalScene.phaseManager.queueMessage(getEncounterText(`${namespace}:safari.watching`) ?? "", 0, null, 1000);
|
||||||
initSubsequentOptionSelect({
|
initSubsequentOptionSelect({
|
||||||
overrideOptions: safariZoneGameOptions,
|
overrideOptions: safariZoneGameOptions,
|
||||||
startingCursorIndex: cursorIndex,
|
startingCursorIndex: cursorIndex,
|
||||||
|
@ -10,7 +10,7 @@ import type Pokemon from "#app/field/pokemon";
|
|||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { randSeedInt } from "#app/utils/common";
|
import { randSeedInt } from "#app/utils/common";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
@ -49,7 +49,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui
|
|||||||
.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([
|
.withIntroSpriteConfigs([
|
||||||
{
|
{
|
||||||
spriteKey: Species.KROOKODILE.toString(),
|
spriteKey: SpeciesId.KROOKODILE.toString(),
|
||||||
fileRoot: "pokemon",
|
fileRoot: "pokemon",
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
|
@ -2,7 +2,7 @@ import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requir
|
|||||||
import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
@ -20,13 +20,13 @@ import {
|
|||||||
} from "../utils/encounter-phase-utils";
|
} from "../utils/encounter-phase-utils";
|
||||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import { AiType, PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
|
import { AiType } from "#enums/ai-type";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
@ -50,7 +50,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil
|
|||||||
.withFleeAllowed(false)
|
.withFleeAllowed(false)
|
||||||
.withIntroSpriteConfigs([
|
.withIntroSpriteConfigs([
|
||||||
{
|
{
|
||||||
spriteKey: Species.SNORLAX.toString(),
|
spriteKey: SpeciesId.SNORLAX.toString(),
|
||||||
fileRoot: "pokemon",
|
fileRoot: "pokemon",
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
tint: 0.25,
|
tint: 0.25,
|
||||||
@ -69,14 +69,14 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil
|
|||||||
console.log(encounter);
|
console.log(encounter);
|
||||||
|
|
||||||
// Calculate boss mon
|
// Calculate boss mon
|
||||||
const bossSpecies = getPokemonSpecies(Species.SNORLAX);
|
const bossSpecies = getPokemonSpecies(SpeciesId.SNORLAX);
|
||||||
const pokemonConfig: EnemyPokemonConfig = {
|
const pokemonConfig: EnemyPokemonConfig = {
|
||||||
species: bossSpecies,
|
species: bossSpecies,
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
shiny: false, // Shiny lock because shiny is rolled only if the battle option is picked
|
shiny: false, // Shiny lock because shiny is rolled only if the battle option is picked
|
||||||
status: [StatusEffect.SLEEP, 6], // Extra turns on timer for Snorlax's start of fight moves
|
status: [StatusEffect.SLEEP, 6], // Extra turns on timer for Snorlax's start of fight moves
|
||||||
nature: Nature.DOCILE,
|
nature: Nature.DOCILE,
|
||||||
moveSet: [Moves.BODY_SLAM, Moves.CRUNCH, Moves.SLEEP_TALK, Moves.REST],
|
moveSet: [MoveId.BODY_SLAM, MoveId.CRUNCH, MoveId.SLEEP_TALK, MoveId.REST],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType,
|
||||||
@ -106,9 +106,9 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil
|
|||||||
encounter.enemyPartyConfigs = [config];
|
encounter.enemyPartyConfigs = [config];
|
||||||
|
|
||||||
// Load animations/sfx for Snorlax fight start moves
|
// Load animations/sfx for Snorlax fight start moves
|
||||||
loadCustomMovesForEncounter([Moves.SNORE]);
|
loadCustomMovesForEncounter([MoveId.SNORE]);
|
||||||
|
|
||||||
encounter.setDialogueToken("snorlaxName", getPokemonSpecies(Species.SNORLAX).getName());
|
encounter.setDialogueToken("snorlaxName", getPokemonSpecies(SpeciesId.SNORLAX).getName());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
@ -133,14 +133,12 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil
|
|||||||
guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS],
|
guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS],
|
||||||
fillRemaining: true,
|
fillRemaining: true,
|
||||||
});
|
});
|
||||||
encounter.startOfBattleEffects.push(
|
encounter.startOfBattleEffects.push({
|
||||||
{
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
targets: [BattlerIndex.PLAYER],
|
||||||
targets: [BattlerIndex.PLAYER],
|
move: new PokemonMove(MoveId.SNORE),
|
||||||
move: new PokemonMove(Moves.SNORE),
|
ignorePp: true,
|
||||||
ignorePp: true,
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
await initBattleWithEnemyConfig(encounter.enemyPartyConfigs[0]);
|
await initBattleWithEnemyConfig(encounter.enemyPartyConfigs[0]);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -157,7 +155,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil
|
|||||||
async () => {
|
async () => {
|
||||||
// Fall asleep waiting for Snorlax
|
// Fall asleep waiting for Snorlax
|
||||||
// Full heal party
|
// Full heal party
|
||||||
globalScene.unshiftPhase(new PartyHealPhase(true));
|
globalScene.phaseManager.unshiftNew("PartyHealPhase", true);
|
||||||
queueEncounterMessage(`${namespace}:option.2.rest_result`);
|
queueEncounterMessage(`${namespace}:option.2.rest_result`);
|
||||||
leaveEncounterWithoutBattle();
|
leaveEncounterWithoutBattle();
|
||||||
},
|
},
|
||||||
@ -183,7 +181,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil
|
|||||||
fillRemaining: false,
|
fillRemaining: false,
|
||||||
});
|
});
|
||||||
// Snorlax exp to Pokemon that did the stealing
|
// Snorlax exp to Pokemon that did the stealing
|
||||||
setEncounterExp(instance.primaryPokemon!.id, getPokemonSpecies(Species.SNORLAX).baseExp);
|
setEncounterExp(instance.primaryPokemon!.id, getPokemonSpecies(SpeciesId.SNORLAX).baseExp);
|
||||||
leaveEncounterWithoutBattle();
|
leaveEncounterWithoutBattle();
|
||||||
})
|
})
|
||||||
.build(),
|
.build(),
|
||||||
|
@ -20,14 +20,13 @@ import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-enco
|
|||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { Biome } from "#enums/biome";
|
import { BiomeId } from "#enums/biome-id";
|
||||||
import { getBiomeKey } from "#app/field/arena";
|
import { getBiomeKey } from "#app/field/arena";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { getPartyLuckValue, modifierTypes } from "#app/modifier/modifier-type";
|
import { getPartyLuckValue, modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { TrainerSlot } from "#enums/trainer-slot";
|
import { TrainerSlot } from "#enums/trainer-slot";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import {
|
import {
|
||||||
@ -39,7 +38,14 @@ import {
|
|||||||
const namespace = "mysteryEncounters/teleportingHijinks";
|
const namespace = "mysteryEncounters/teleportingHijinks";
|
||||||
|
|
||||||
const MONEY_COST_MULTIPLIER = 1.75;
|
const MONEY_COST_MULTIPLIER = 1.75;
|
||||||
const BIOME_CANDIDATES = [Biome.SPACE, Biome.FAIRY_CAVE, Biome.LABORATORY, Biome.ISLAND, Biome.WASTELAND, Biome.DOJO];
|
const BIOME_CANDIDATES = [
|
||||||
|
BiomeId.SPACE,
|
||||||
|
BiomeId.FAIRY_CAVE,
|
||||||
|
BiomeId.LABORATORY,
|
||||||
|
BiomeId.ISLAND,
|
||||||
|
BiomeId.WASTELAND,
|
||||||
|
BiomeId.DOJO,
|
||||||
|
];
|
||||||
const MACHINE_INTERFACING_TYPES = [PokemonType.ELECTRIC, PokemonType.STEEL];
|
const MACHINE_INTERFACING_TYPES = [PokemonType.ELECTRIC, PokemonType.STEEL];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,7 +226,13 @@ async function doBiomeTransitionDialogueAndBattleInit() {
|
|||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:boss_enraged`);
|
queueEncounterMessage(`${namespace}:boss_enraged`);
|
||||||
globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, statChangesForBattle, 1));
|
globalScene.phaseManager.unshiftNew(
|
||||||
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
statChangesForBattle,
|
||||||
|
1,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -229,7 +241,7 @@ async function doBiomeTransitionDialogueAndBattleInit() {
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function animateBiomeChange(nextBiome: Biome) {
|
async function animateBiomeChange(nextBiome: BiomeId) {
|
||||||
return new Promise<void>(resolve => {
|
return new Promise<void>(resolve => {
|
||||||
globalScene.tweens.add({
|
globalScene.tweens.add({
|
||||||
targets: [globalScene.arenaEnemy, globalScene.lastEnemyTrainer],
|
targets: [globalScene.arenaEnemy, globalScene.lastEnemyTrainer],
|
||||||
|
@ -11,14 +11,14 @@ import { randSeedShuffle } from "#app/utils/common";
|
|||||||
import type MysteryEncounter from "../mystery-encounter";
|
import type MysteryEncounter from "../mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "../mystery-encounter";
|
import { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { Biome } from "#enums/biome";
|
import { BiomeId } from "#enums/biome-id";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import type { IEggOptions } from "#app/data/egg";
|
import type { IEggOptions } from "#app/data/egg";
|
||||||
@ -42,75 +42,75 @@ const FINAL_STAGE_EVOLUTION_WAVE = 75;
|
|||||||
const FRIENDSHIP_ADDED = 20;
|
const FRIENDSHIP_ADDED = 20;
|
||||||
|
|
||||||
class BreederSpeciesEvolution {
|
class BreederSpeciesEvolution {
|
||||||
species: Species;
|
species: SpeciesId;
|
||||||
evolution: number;
|
evolution: number;
|
||||||
|
|
||||||
constructor(species: Species, evolution: number) {
|
constructor(species: SpeciesId, evolution: number) {
|
||||||
this.species = species;
|
this.species = species;
|
||||||
this.evolution = evolution;
|
this.evolution = evolution;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const POOL_1_POKEMON: (Species | BreederSpeciesEvolution)[][] = [
|
const POOL_1_POKEMON: (SpeciesId | BreederSpeciesEvolution)[][] = [
|
||||||
[Species.MUNCHLAX, new BreederSpeciesEvolution(Species.SNORLAX, SECOND_STAGE_EVOLUTION_WAVE)],
|
[SpeciesId.MUNCHLAX, new BreederSpeciesEvolution(SpeciesId.SNORLAX, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
[
|
[
|
||||||
Species.HAPPINY,
|
SpeciesId.HAPPINY,
|
||||||
new BreederSpeciesEvolution(Species.CHANSEY, FIRST_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.CHANSEY, FIRST_STAGE_EVOLUTION_WAVE),
|
||||||
new BreederSpeciesEvolution(Species.BLISSEY, FINAL_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.BLISSEY, FINAL_STAGE_EVOLUTION_WAVE),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Species.MAGBY,
|
SpeciesId.MAGBY,
|
||||||
new BreederSpeciesEvolution(Species.MAGMAR, FIRST_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.MAGMAR, FIRST_STAGE_EVOLUTION_WAVE),
|
||||||
new BreederSpeciesEvolution(Species.MAGMORTAR, FINAL_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.MAGMORTAR, FINAL_STAGE_EVOLUTION_WAVE),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Species.ELEKID,
|
SpeciesId.ELEKID,
|
||||||
new BreederSpeciesEvolution(Species.ELECTABUZZ, FIRST_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.ELECTABUZZ, FIRST_STAGE_EVOLUTION_WAVE),
|
||||||
new BreederSpeciesEvolution(Species.ELECTIVIRE, FINAL_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.ELECTIVIRE, FINAL_STAGE_EVOLUTION_WAVE),
|
||||||
],
|
],
|
||||||
[Species.RIOLU, new BreederSpeciesEvolution(Species.LUCARIO, SECOND_STAGE_EVOLUTION_WAVE)],
|
[SpeciesId.RIOLU, new BreederSpeciesEvolution(SpeciesId.LUCARIO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
[
|
[
|
||||||
Species.BUDEW,
|
SpeciesId.BUDEW,
|
||||||
new BreederSpeciesEvolution(Species.ROSELIA, FIRST_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.ROSELIA, FIRST_STAGE_EVOLUTION_WAVE),
|
||||||
new BreederSpeciesEvolution(Species.ROSERADE, FINAL_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.ROSERADE, FINAL_STAGE_EVOLUTION_WAVE),
|
||||||
],
|
],
|
||||||
[Species.TOXEL, new BreederSpeciesEvolution(Species.TOXTRICITY, SECOND_STAGE_EVOLUTION_WAVE)],
|
[SpeciesId.TOXEL, new BreederSpeciesEvolution(SpeciesId.TOXTRICITY, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
[
|
[
|
||||||
Species.MIME_JR,
|
SpeciesId.MIME_JR,
|
||||||
new BreederSpeciesEvolution(Species.GALAR_MR_MIME, FIRST_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.GALAR_MR_MIME, FIRST_STAGE_EVOLUTION_WAVE),
|
||||||
new BreederSpeciesEvolution(Species.MR_RIME, FINAL_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.MR_RIME, FINAL_STAGE_EVOLUTION_WAVE),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
const POOL_2_POKEMON: (Species | BreederSpeciesEvolution)[][] = [
|
const POOL_2_POKEMON: (SpeciesId | BreederSpeciesEvolution)[][] = [
|
||||||
[
|
[
|
||||||
Species.PICHU,
|
SpeciesId.PICHU,
|
||||||
new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE),
|
||||||
new BreederSpeciesEvolution(Species.RAICHU, FINAL_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.RAICHU, FINAL_STAGE_EVOLUTION_WAVE),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Species.PICHU,
|
SpeciesId.PICHU,
|
||||||
new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE),
|
||||||
new BreederSpeciesEvolution(Species.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE),
|
||||||
],
|
],
|
||||||
[Species.SMOOCHUM, new BreederSpeciesEvolution(Species.JYNX, SECOND_STAGE_EVOLUTION_WAVE)],
|
[SpeciesId.SMOOCHUM, new BreederSpeciesEvolution(SpeciesId.JYNX, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE)],
|
[SpeciesId.TYROGUE, new BreederSpeciesEvolution(SpeciesId.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE)],
|
[SpeciesId.TYROGUE, new BreederSpeciesEvolution(SpeciesId.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE)],
|
[SpeciesId.TYROGUE, new BreederSpeciesEvolution(SpeciesId.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
[
|
[
|
||||||
Species.IGGLYBUFF,
|
SpeciesId.IGGLYBUFF,
|
||||||
new BreederSpeciesEvolution(Species.JIGGLYPUFF, FIRST_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.JIGGLYPUFF, FIRST_STAGE_EVOLUTION_WAVE),
|
||||||
new BreederSpeciesEvolution(Species.WIGGLYTUFF, FINAL_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.WIGGLYTUFF, FINAL_STAGE_EVOLUTION_WAVE),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
Species.AZURILL,
|
SpeciesId.AZURILL,
|
||||||
new BreederSpeciesEvolution(Species.MARILL, FIRST_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.MARILL, FIRST_STAGE_EVOLUTION_WAVE),
|
||||||
new BreederSpeciesEvolution(Species.AZUMARILL, FINAL_STAGE_EVOLUTION_WAVE),
|
new BreederSpeciesEvolution(SpeciesId.AZUMARILL, FINAL_STAGE_EVOLUTION_WAVE),
|
||||||
],
|
],
|
||||||
[Species.WYNAUT, new BreederSpeciesEvolution(Species.WOBBUFFET, SECOND_STAGE_EVOLUTION_WAVE)],
|
[SpeciesId.WYNAUT, new BreederSpeciesEvolution(SpeciesId.WOBBUFFET, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
[Species.CHINGLING, new BreederSpeciesEvolution(Species.CHIMECHO, SECOND_STAGE_EVOLUTION_WAVE)],
|
[SpeciesId.CHINGLING, new BreederSpeciesEvolution(SpeciesId.CHIMECHO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
[Species.BONSLY, new BreederSpeciesEvolution(Species.SUDOWOODO, SECOND_STAGE_EVOLUTION_WAVE)],
|
[SpeciesId.BONSLY, new BreederSpeciesEvolution(SpeciesId.SUDOWOODO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
[Species.MANTYKE, new BreederSpeciesEvolution(Species.MANTINE, SECOND_STAGE_EVOLUTION_WAVE)],
|
[SpeciesId.MANTYKE, new BreederSpeciesEvolution(SpeciesId.MANTINE, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -144,10 +144,10 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount
|
|||||||
|
|
||||||
const cleffaSpecies =
|
const cleffaSpecies =
|
||||||
waveIndex < FIRST_STAGE_EVOLUTION_WAVE
|
waveIndex < FIRST_STAGE_EVOLUTION_WAVE
|
||||||
? Species.CLEFFA
|
? SpeciesId.CLEFFA
|
||||||
: waveIndex < FINAL_STAGE_EVOLUTION_WAVE
|
: waveIndex < FINAL_STAGE_EVOLUTION_WAVE
|
||||||
? Species.CLEFAIRY
|
? SpeciesId.CLEFAIRY
|
||||||
: Species.CLEFABLE;
|
: SpeciesId.CLEFABLE;
|
||||||
encounter.spriteConfigs = [
|
encounter.spriteConfigs = [
|
||||||
{
|
{
|
||||||
spriteKey: cleffaSpecies.toString(),
|
spriteKey: cleffaSpecies.toString(),
|
||||||
@ -466,10 +466,10 @@ function getPartyConfig(): EnemyPartyConfig {
|
|||||||
// First mon is *always* this special cleffa
|
// First mon is *always* this special cleffa
|
||||||
const cleffaSpecies =
|
const cleffaSpecies =
|
||||||
waveIndex < FIRST_STAGE_EVOLUTION_WAVE
|
waveIndex < FIRST_STAGE_EVOLUTION_WAVE
|
||||||
? Species.CLEFFA
|
? SpeciesId.CLEFFA
|
||||||
: waveIndex < FINAL_STAGE_EVOLUTION_WAVE
|
: waveIndex < FINAL_STAGE_EVOLUTION_WAVE
|
||||||
? Species.CLEFAIRY
|
? SpeciesId.CLEFAIRY
|
||||||
: Species.CLEFABLE;
|
: SpeciesId.CLEFABLE;
|
||||||
const baseConfig: EnemyPartyConfig = {
|
const baseConfig: EnemyPartyConfig = {
|
||||||
trainerType: TrainerType.EXPERT_POKEMON_BREEDER,
|
trainerType: TrainerType.EXPERT_POKEMON_BREEDER,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
@ -482,14 +482,14 @@ function getPartyConfig(): EnemyPartyConfig {
|
|||||||
abilityIndex: 1, // Magic Guard
|
abilityIndex: 1, // Magic Guard
|
||||||
shiny: false,
|
shiny: false,
|
||||||
nature: Nature.ADAMANT,
|
nature: Nature.ADAMANT,
|
||||||
moveSet: [Moves.FIRE_PUNCH, Moves.ICE_PUNCH, Moves.THUNDER_PUNCH, Moves.METEOR_MASH],
|
moveSet: [MoveId.FIRE_PUNCH, MoveId.ICE_PUNCH, MoveId.THUNDER_PUNCH, MoveId.METEOR_MASH],
|
||||||
ivs: [31, 31, 31, 31, 31, 31],
|
ivs: [31, 31, 31, 31, 31, 31],
|
||||||
tera: PokemonType.FAIRY,
|
tera: PokemonType.FAIRY,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (globalScene.arena.biomeType === Biome.SPACE) {
|
if (globalScene.arena.biomeType === BiomeId.SPACE) {
|
||||||
// All 3 members always Cleffa line, but different configs
|
// All 3 members always Cleffa line, but different configs
|
||||||
baseConfig.pokemonConfigs!.push(
|
baseConfig.pokemonConfigs!.push(
|
||||||
{
|
{
|
||||||
@ -502,7 +502,7 @@ function getPartyConfig(): EnemyPartyConfig {
|
|||||||
shiny: true,
|
shiny: true,
|
||||||
variant: 1,
|
variant: 1,
|
||||||
nature: Nature.MODEST,
|
nature: Nature.MODEST,
|
||||||
moveSet: [Moves.MOONBLAST, Moves.MYSTICAL_FIRE, Moves.ICE_BEAM, Moves.THUNDERBOLT],
|
moveSet: [MoveId.MOONBLAST, MoveId.MYSTICAL_FIRE, MoveId.ICE_BEAM, MoveId.THUNDERBOLT],
|
||||||
ivs: [31, 31, 31, 31, 31, 31],
|
ivs: [31, 31, 31, 31, 31, 31],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -515,7 +515,7 @@ function getPartyConfig(): EnemyPartyConfig {
|
|||||||
shiny: true,
|
shiny: true,
|
||||||
variant: 2,
|
variant: 2,
|
||||||
nature: Nature.BOLD,
|
nature: Nature.BOLD,
|
||||||
moveSet: [Moves.TRI_ATTACK, Moves.STORED_POWER, Moves.TAKE_HEART, Moves.MOONLIGHT],
|
moveSet: [MoveId.TRI_ATTACK, MoveId.STORED_POWER, MoveId.TAKE_HEART, MoveId.MOONLIGHT],
|
||||||
ivs: [31, 31, 31, 31, 31, 31],
|
ivs: [31, 31, 31, 31, 31, 31],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -542,7 +542,7 @@ function getPartyConfig(): EnemyPartyConfig {
|
|||||||
return baseConfig;
|
return baseConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSpeciesFromPool(speciesPool: (Species | BreederSpeciesEvolution)[][], waveIndex: number): Species {
|
function getSpeciesFromPool(speciesPool: (SpeciesId | BreederSpeciesEvolution)[][], waveIndex: number): SpeciesId {
|
||||||
const poolCopy = randSeedShuffle(speciesPool.slice(0));
|
const poolCopy = randSeedShuffle(speciesPool.slice(0));
|
||||||
const speciesEvolutions = poolCopy.pop()!.slice(0);
|
const speciesEvolutions = poolCopy.pop()!.slice(0);
|
||||||
let speciesObject = speciesEvolutions.pop()!;
|
let speciesObject = speciesEvolutions.pop()!;
|
||||||
@ -658,8 +658,8 @@ function onGameOver() {
|
|||||||
globalScene.playBgm(globalScene.arena.bgm);
|
globalScene.playBgm(globalScene.arena.bgm);
|
||||||
|
|
||||||
// Clear any leftover battle phases
|
// Clear any leftover battle phases
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.clearPhaseQueueSplice();
|
globalScene.phaseManager.clearPhaseQueueSplice();
|
||||||
|
|
||||||
// Return enemy Pokemon
|
// Return enemy Pokemon
|
||||||
const pokemon = globalScene.getEnemyPokemon();
|
const pokemon = globalScene.getEnemyPokemon();
|
||||||
|
@ -17,7 +17,7 @@ import {
|
|||||||
import type PokemonSpecies from "#app/data/pokemon-species";
|
import type PokemonSpecies from "#app/data/pokemon-species";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { PokeballType } from "#enums/pokeball";
|
import { PokeballType } from "#enums/pokeball";
|
||||||
import type { EnemyPokemon } from "#app/field/pokemon";
|
import type { EnemyPokemon } from "#app/field/pokemon";
|
||||||
import { PlayerPokemon } from "#app/field/pokemon";
|
import { PlayerPokemon } from "#app/field/pokemon";
|
||||||
@ -27,7 +27,7 @@ import PokemonData from "#app/system/pokemon-data";
|
|||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { NON_LEGEND_PARADOX_POKEMON, NON_LEGEND_ULTRA_BEASTS } from "#app/data/balance/special-species-groups";
|
import { NON_LEGEND_PARADOX_POKEMON, NON_LEGEND_ULTRA_BEASTS } from "#app/data/balance/special-species-groups";
|
||||||
import { timedEventManager } from "#app/global-event-manager";
|
import { timedEventManager } from "#app/global-event-manager";
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui
|
|||||||
let tries = 0;
|
let tries = 0;
|
||||||
|
|
||||||
// Reroll any species that don't have HAs
|
// Reroll any species that don't have HAs
|
||||||
while ((isNullOrUndefined(species.abilityHidden) || species.abilityHidden === Abilities.NONE) && tries < 5) {
|
while ((isNullOrUndefined(species.abilityHidden) || species.abilityHidden === AbilityId.NONE) && tries < 5) {
|
||||||
species = getSalesmanSpeciesOffer();
|
species = getSalesmanSpeciesOffer();
|
||||||
tries++;
|
tries++;
|
||||||
}
|
}
|
||||||
@ -110,15 +110,15 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui
|
|||||||
*/
|
*/
|
||||||
if (
|
if (
|
||||||
r === 0 ||
|
r === 0 ||
|
||||||
((isNullOrUndefined(species.abilityHidden) || species.abilityHidden === Abilities.NONE) &&
|
((isNullOrUndefined(species.abilityHidden) || species.abilityHidden === AbilityId.NONE) &&
|
||||||
validEventEncounters.length === 0)
|
validEventEncounters.length === 0)
|
||||||
) {
|
) {
|
||||||
// If you roll 1%, give shiny Magikarp with random variant
|
// If you roll 1%, give shiny Magikarp with random variant
|
||||||
species = getPokemonSpecies(Species.MAGIKARP);
|
species = getPokemonSpecies(SpeciesId.MAGIKARP);
|
||||||
pokemon = new PlayerPokemon(species, 5, 2, undefined, undefined, true);
|
pokemon = new PlayerPokemon(species, 5, 2, undefined, undefined, true);
|
||||||
} else if (
|
} else if (
|
||||||
validEventEncounters.length > 0 &&
|
validEventEncounters.length > 0 &&
|
||||||
(r <= EVENT_THRESHOLD || isNullOrUndefined(species.abilityHidden) || species.abilityHidden === Abilities.NONE)
|
(r <= EVENT_THRESHOLD || isNullOrUndefined(species.abilityHidden) || species.abilityHidden === AbilityId.NONE)
|
||||||
) {
|
) {
|
||||||
tries = 0;
|
tries = 0;
|
||||||
do {
|
do {
|
||||||
@ -128,7 +128,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui
|
|||||||
pokemon = new PlayerPokemon(
|
pokemon = new PlayerPokemon(
|
||||||
species,
|
species,
|
||||||
5,
|
5,
|
||||||
species.abilityHidden === Abilities.NONE ? undefined : 2,
|
species.abilityHidden === AbilityId.NONE ? undefined : 2,
|
||||||
enc.formIndex,
|
enc.formIndex,
|
||||||
);
|
);
|
||||||
pokemon.trySetShinySeed();
|
pokemon.trySetShinySeed();
|
||||||
@ -151,7 +151,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui
|
|||||||
pokemon.trySetShinySeed();
|
pokemon.trySetShinySeed();
|
||||||
} else {
|
} else {
|
||||||
// If there's, and this would never happen, no eligible event encounters with a hidden ability, just do Magikarp
|
// If there's, and this would never happen, no eligible event encounters with a hidden ability, just do Magikarp
|
||||||
species = getPokemonSpecies(Species.MAGIKARP);
|
species = getPokemonSpecies(SpeciesId.MAGIKARP);
|
||||||
pokemon = new PlayerPokemon(species, 5, 2, undefined, undefined, true);
|
pokemon = new PlayerPokemon(species, 5, 2, undefined, undefined, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,20 +14,19 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { modifyPlayerPokemonBST } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { modifyPlayerPokemonBST } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
@ -64,7 +63,7 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
disableAnimation: true,
|
disableAnimation: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
spriteKey: Species.SHUCKLE.toString(),
|
spriteKey: SpeciesId.SHUCKLE.toString(),
|
||||||
fileRoot: "pokemon",
|
fileRoot: "pokemon",
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
@ -88,13 +87,13 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
disableSwitch: true,
|
disableSwitch: true,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.SHUCKLE),
|
species: getPokemonSpecies(SpeciesId.SHUCKLE),
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
bossSegments: 5,
|
bossSegments: 5,
|
||||||
shiny: false, // Shiny lock because shiny is rolled only if the battle option is picked
|
shiny: false, // Shiny lock because shiny is rolled only if the battle option is picked
|
||||||
customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }),
|
customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }),
|
||||||
nature: Nature.HARDY,
|
nature: Nature.HARDY,
|
||||||
moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER],
|
moveSet: [MoveId.INFESTATION, MoveId.SALT_CURE, MoveId.GASTRO_ACID, MoveId.HEAL_ORDER],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType,
|
||||||
@ -116,8 +115,12 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:option.2.stat_boost`);
|
queueEncounterMessage(`${namespace}:option.2.stat_boost`);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, [Stat.DEF, Stat.SPDEF], 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
[Stat.DEF, Stat.SPDEF],
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -126,9 +129,9 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
|
|
||||||
encounter.enemyPartyConfigs = [config];
|
encounter.enemyPartyConfigs = [config];
|
||||||
|
|
||||||
loadCustomMovesForEncounter([Moves.GASTRO_ACID, Moves.STEALTH_ROCK]);
|
loadCustomMovesForEncounter([MoveId.GASTRO_ACID, MoveId.STEALTH_ROCK]);
|
||||||
|
|
||||||
encounter.setDialogueToken("shuckleName", getPokemonSpecies(Species.SHUCKLE).getName());
|
encounter.setDialogueToken("shuckleName", getPokemonSpecies(SpeciesId.SHUCKLE).getName());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
@ -210,13 +213,13 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
{
|
{
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||||
targets: [BattlerIndex.PLAYER],
|
targets: [BattlerIndex.PLAYER],
|
||||||
move: new PokemonMove(Moves.GASTRO_ACID),
|
move: new PokemonMove(MoveId.GASTRO_ACID),
|
||||||
ignorePp: true,
|
ignorePp: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||||
targets: [BattlerIndex.PLAYER],
|
targets: [BattlerIndex.PLAYER],
|
||||||
move: new PokemonMove(Moves.STEALTH_ROCK),
|
move: new PokemonMove(MoveId.STEALTH_ROCK),
|
||||||
ignorePp: true,
|
ignorePp: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -15,21 +15,18 @@ import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounte
|
|||||||
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { SpeciesFormChangeAbilityTrigger } from "#app/data/pokemon-forms";
|
import { SpeciesFormChangeAbilityTrigger } from "#app/data/pokemon-forms/form-change-triggers";
|
||||||
import { applyPostBattleInitAbAttrs, PostBattleInitAbAttr } from "#app/data/abilities/ability";
|
import { applyPostBattleInitAbAttrs, PostBattleInitAbAttr } from "#app/data/abilities/ability";
|
||||||
import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
|
||||||
import { ShowTrainerPhase } from "#app/phases/show-trainer-phase";
|
|
||||||
import { ReturnPhase } from "#app/phases/return-phase";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
@ -143,7 +140,7 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter = MysteryEncounter
|
|||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
// Refuse the challenge, they full heal the party and give the player a Rarer Candy
|
// Refuse the challenge, they full heal the party and give the player a Rarer Candy
|
||||||
globalScene.unshiftPhase(new PartyHealPhase(true));
|
globalScene.phaseManager.unshiftNew("PartyHealPhase", true);
|
||||||
setEncounterRewards({
|
setEncounterRewards({
|
||||||
guaranteedModifierTypeFuncs: [modifierTypes.RARER_CANDY],
|
guaranteedModifierTypeFuncs: [modifierTypes.RARER_CANDY],
|
||||||
fillRemaining: false,
|
fillRemaining: false,
|
||||||
@ -209,14 +206,14 @@ function endTrainerBattleAndShowDialogue(): Promise<void> {
|
|||||||
for (const pokemon of playerField) {
|
for (const pokemon of playerField) {
|
||||||
pokemon.lapseTag(BattlerTagType.COMMANDED);
|
pokemon.lapseTag(BattlerTagType.COMMANDED);
|
||||||
}
|
}
|
||||||
playerField.forEach((_, p) => globalScene.unshiftPhase(new ReturnPhase(p)));
|
playerField.forEach((_, p) => globalScene.phaseManager.unshiftNew("ReturnPhase", p));
|
||||||
|
|
||||||
for (const pokemon of globalScene.getPlayerParty()) {
|
for (const pokemon of globalScene.getPlayerParty()) {
|
||||||
// Only trigger form change when Eiscue is in Noice form
|
// Only trigger form change when Eiscue is in Noice form
|
||||||
// Hardcoded Eiscue for now in case it is fused with another pokemon
|
// Hardcoded Eiscue for now in case it is fused with another pokemon
|
||||||
if (
|
if (
|
||||||
pokemon.species.speciesId === Species.EISCUE &&
|
pokemon.species.speciesId === SpeciesId.EISCUE &&
|
||||||
pokemon.hasAbility(Abilities.ICE_FACE) &&
|
pokemon.hasAbility(AbilityId.ICE_FACE) &&
|
||||||
pokemon.formIndex === 1
|
pokemon.formIndex === 1
|
||||||
) {
|
) {
|
||||||
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger);
|
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger);
|
||||||
@ -227,7 +224,7 @@ function endTrainerBattleAndShowDialogue(): Promise<void> {
|
|||||||
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon);
|
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon);
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.unshiftPhase(new ShowTrainerPhase());
|
globalScene.phaseManager.unshiftNew("ShowTrainerPhase");
|
||||||
// Hide the trainer and init next battle
|
// Hide the trainer and init next battle
|
||||||
const trainer = globalScene.currentBattle.trainer;
|
const trainer = globalScene.currentBattle.trainer;
|
||||||
// Unassign previous trainer from battle so it isn't destroyed before animation completes
|
// Unassign previous trainer from battle so it isn't destroyed before animation completes
|
||||||
@ -256,11 +253,11 @@ function getVictorTrainerConfig(): EnemyPartyConfig {
|
|||||||
trainerType: TrainerType.VICTOR,
|
trainerType: TrainerType.VICTOR,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.SWELLOW),
|
species: getPokemonSpecies(SpeciesId.SWELLOW),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
abilityIndex: 0, // Guts
|
abilityIndex: 0, // Guts
|
||||||
nature: Nature.ADAMANT,
|
nature: Nature.ADAMANT,
|
||||||
moveSet: [Moves.FACADE, Moves.BRAVE_BIRD, Moves.PROTECT, Moves.QUICK_ATTACK],
|
moveSet: [MoveId.FACADE, MoveId.BRAVE_BIRD, MoveId.PROTECT, MoveId.QUICK_ATTACK],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.FLAME_ORB) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.FLAME_ORB) as PokemonHeldItemModifierType,
|
||||||
@ -274,11 +271,11 @@ function getVictorTrainerConfig(): EnemyPartyConfig {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.OBSTAGOON),
|
species: getPokemonSpecies(SpeciesId.OBSTAGOON),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
abilityIndex: 1, // Guts
|
abilityIndex: 1, // Guts
|
||||||
nature: Nature.ADAMANT,
|
nature: Nature.ADAMANT,
|
||||||
moveSet: [Moves.FACADE, Moves.OBSTRUCT, Moves.NIGHT_SLASH, Moves.FIRE_PUNCH],
|
moveSet: [MoveId.FACADE, MoveId.OBSTRUCT, MoveId.NIGHT_SLASH, MoveId.FIRE_PUNCH],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.FLAME_ORB) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.FLAME_ORB) as PokemonHeldItemModifierType,
|
||||||
@ -300,11 +297,11 @@ function getVictoriaTrainerConfig(): EnemyPartyConfig {
|
|||||||
trainerType: TrainerType.VICTORIA,
|
trainerType: TrainerType.VICTORIA,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.ROSERADE),
|
species: getPokemonSpecies(SpeciesId.ROSERADE),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
abilityIndex: 0, // Natural Cure
|
abilityIndex: 0, // Natural Cure
|
||||||
nature: Nature.CALM,
|
nature: Nature.CALM,
|
||||||
moveSet: [Moves.SYNTHESIS, Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.SLEEP_POWDER],
|
moveSet: [MoveId.SYNTHESIS, MoveId.SLUDGE_BOMB, MoveId.GIGA_DRAIN, MoveId.SLEEP_POWDER],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.SOUL_DEW) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.SOUL_DEW) as PokemonHeldItemModifierType,
|
||||||
@ -318,11 +315,11 @@ function getVictoriaTrainerConfig(): EnemyPartyConfig {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.GARDEVOIR),
|
species: getPokemonSpecies(SpeciesId.GARDEVOIR),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
formIndex: 1,
|
formIndex: 1,
|
||||||
nature: Nature.TIMID,
|
nature: Nature.TIMID,
|
||||||
moveSet: [Moves.PSYSHOCK, Moves.MOONBLAST, Moves.SHADOW_BALL, Moves.WILL_O_WISP],
|
moveSet: [MoveId.PSYSHOCK, MoveId.MOONBLAST, MoveId.SHADOW_BALL, MoveId.WILL_O_WISP],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, [
|
modifier: generateModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, [
|
||||||
@ -349,11 +346,11 @@ function getViviTrainerConfig(): EnemyPartyConfig {
|
|||||||
trainerType: TrainerType.VIVI,
|
trainerType: TrainerType.VIVI,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.SEAKING),
|
species: getPokemonSpecies(SpeciesId.SEAKING),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
abilityIndex: 3, // Lightning Rod
|
abilityIndex: 3, // Lightning Rod
|
||||||
nature: Nature.ADAMANT,
|
nature: Nature.ADAMANT,
|
||||||
moveSet: [Moves.WATERFALL, Moves.MEGAHORN, Moves.KNOCK_OFF, Moves.REST],
|
moveSet: [MoveId.WATERFALL, MoveId.MEGAHORN, MoveId.KNOCK_OFF, MoveId.REST],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.LUM]) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.LUM]) as PokemonHeldItemModifierType,
|
||||||
@ -368,11 +365,11 @@ function getViviTrainerConfig(): EnemyPartyConfig {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.BRELOOM),
|
species: getPokemonSpecies(SpeciesId.BRELOOM),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
abilityIndex: 1, // Poison Heal
|
abilityIndex: 1, // Poison Heal
|
||||||
nature: Nature.JOLLY,
|
nature: Nature.JOLLY,
|
||||||
moveSet: [Moves.SPORE, Moves.SWORDS_DANCE, Moves.SEED_BOMB, Moves.DRAIN_PUNCH],
|
moveSet: [MoveId.SPORE, MoveId.SWORDS_DANCE, MoveId.SEED_BOMB, MoveId.DRAIN_PUNCH],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.BASE_STAT_BOOSTER, [Stat.HP]) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.BASE_STAT_BOOSTER, [Stat.HP]) as PokemonHeldItemModifierType,
|
||||||
@ -386,11 +383,11 @@ function getViviTrainerConfig(): EnemyPartyConfig {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.CAMERUPT),
|
species: getPokemonSpecies(SpeciesId.CAMERUPT),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
formIndex: 1,
|
formIndex: 1,
|
||||||
nature: Nature.CALM,
|
nature: Nature.CALM,
|
||||||
moveSet: [Moves.EARTH_POWER, Moves.FIRE_BLAST, Moves.YAWN, Moves.PROTECT],
|
moveSet: [MoveId.EARTH_POWER, MoveId.FIRE_BLAST, MoveId.YAWN, MoveId.PROTECT],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.QUICK_CLAW) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.QUICK_CLAW) as PokemonHeldItemModifierType,
|
||||||
@ -408,11 +405,11 @@ function getVickyTrainerConfig(): EnemyPartyConfig {
|
|||||||
trainerType: TrainerType.VICKY,
|
trainerType: TrainerType.VICKY,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.MEDICHAM),
|
species: getPokemonSpecies(SpeciesId.MEDICHAM),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
formIndex: 1,
|
formIndex: 1,
|
||||||
nature: Nature.IMPISH,
|
nature: Nature.IMPISH,
|
||||||
moveSet: [Moves.AXE_KICK, Moves.ICE_PUNCH, Moves.ZEN_HEADBUTT, Moves.BULLET_PUNCH],
|
moveSet: [MoveId.AXE_KICK, MoveId.ICE_PUNCH, MoveId.ZEN_HEADBUTT, MoveId.BULLET_PUNCH],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType,
|
||||||
@ -429,11 +426,11 @@ function getVitoTrainerConfig(): EnemyPartyConfig {
|
|||||||
trainerType: TrainerType.VITO,
|
trainerType: TrainerType.VITO,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.HISUI_ELECTRODE),
|
species: getPokemonSpecies(SpeciesId.HISUI_ELECTRODE),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
abilityIndex: 0, // Soundproof
|
abilityIndex: 0, // Soundproof
|
||||||
nature: Nature.MODEST,
|
nature: Nature.MODEST,
|
||||||
moveSet: [Moves.THUNDERBOLT, Moves.GIGA_DRAIN, Moves.FOUL_PLAY, Moves.THUNDER_WAVE],
|
moveSet: [MoveId.THUNDERBOLT, MoveId.GIGA_DRAIN, MoveId.FOUL_PLAY, MoveId.THUNDER_WAVE],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.BASE_STAT_BOOSTER, [Stat.SPD]) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.BASE_STAT_BOOSTER, [Stat.SPD]) as PokemonHeldItemModifierType,
|
||||||
@ -443,11 +440,11 @@ function getVitoTrainerConfig(): EnemyPartyConfig {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.SWALOT),
|
species: getPokemonSpecies(SpeciesId.SWALOT),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
abilityIndex: 2, // Gluttony
|
abilityIndex: 2, // Gluttony
|
||||||
nature: Nature.QUIET,
|
nature: Nature.QUIET,
|
||||||
moveSet: [Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.ICE_BEAM, Moves.EARTHQUAKE],
|
moveSet: [MoveId.SLUDGE_BOMB, MoveId.GIGA_DRAIN, MoveId.ICE_BEAM, MoveId.EARTHQUAKE],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType,
|
||||||
@ -496,11 +493,11 @@ function getVitoTrainerConfig(): EnemyPartyConfig {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.DODRIO),
|
species: getPokemonSpecies(SpeciesId.DODRIO),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
abilityIndex: 2, // Tangled Feet
|
abilityIndex: 2, // Tangled Feet
|
||||||
nature: Nature.JOLLY,
|
nature: Nature.JOLLY,
|
||||||
moveSet: [Moves.DRILL_PECK, Moves.QUICK_ATTACK, Moves.THRASH, Moves.KNOCK_OFF],
|
moveSet: [MoveId.DRILL_PECK, MoveId.QUICK_ATTACK, MoveId.THRASH, MoveId.KNOCK_OFF],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.KINGS_ROCK) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.KINGS_ROCK) as PokemonHeldItemModifierType,
|
||||||
@ -510,11 +507,11 @@ function getVitoTrainerConfig(): EnemyPartyConfig {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.ALAKAZAM),
|
species: getPokemonSpecies(SpeciesId.ALAKAZAM),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
formIndex: 1,
|
formIndex: 1,
|
||||||
nature: Nature.BOLD,
|
nature: Nature.BOLD,
|
||||||
moveSet: [Moves.PSYCHIC, Moves.SHADOW_BALL, Moves.FOCUS_BLAST, Moves.THUNDERBOLT],
|
moveSet: [MoveId.PSYCHIC, MoveId.SHADOW_BALL, MoveId.FOCUS_BLAST, MoveId.THUNDERBOLT],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.WIDE_LENS) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.WIDE_LENS) as PokemonHeldItemModifierType,
|
||||||
@ -524,11 +521,11 @@ function getVitoTrainerConfig(): EnemyPartyConfig {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.DARMANITAN),
|
species: getPokemonSpecies(SpeciesId.DARMANITAN),
|
||||||
isBoss: false,
|
isBoss: false,
|
||||||
abilityIndex: 0, // Sheer Force
|
abilityIndex: 0, // Sheer Force
|
||||||
nature: Nature.IMPISH,
|
nature: Nature.IMPISH,
|
||||||
moveSet: [Moves.EARTHQUAKE, Moves.U_TURN, Moves.FLARE_BLITZ, Moves.ROCK_SLIDE],
|
moveSet: [MoveId.EARTHQUAKE, MoveId.U_TURN, MoveId.FLARE_BLITZ, MoveId.ROCK_SLIDE],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.QUICK_CLAW) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.QUICK_CLAW) as PokemonHeldItemModifierType,
|
||||||
|
@ -12,7 +12,7 @@ import { speciesStarterCosts } from "#app/data/balance/starters";
|
|||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import type { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
import type { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
import { AbilityAttr } from "#app/system/game-data";
|
import { AbilityAttr } from "#enums/ability-attr";
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import { isNullOrUndefined, randSeedShuffle } from "#app/utils/common";
|
import { isNullOrUndefined, randSeedShuffle } from "#app/utils/common";
|
||||||
@ -25,7 +25,7 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/myst
|
|||||||
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { getStatKey } from "#enums/stat";
|
import { getStatKey } from "#enums/stat";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
|
@ -16,16 +16,16 @@ import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-en
|
|||||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { HitHealModifier, PokemonHeldItemModifier, TurnHealModifier } from "#app/modifier/modifier";
|
import { HitHealModifier, PokemonHeldItemModifier, TurnHealModifier } from "#app/modifier/modifier";
|
||||||
import { applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import i18next from "#app/plugins/i18n";
|
import i18next from "#app/plugins/i18n";
|
||||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { randSeedInt } from "#app/utils/common";
|
import { randSeedInt } from "#app/utils/common";
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
.withFleeAllowed(false)
|
.withFleeAllowed(false)
|
||||||
.withIntroSpriteConfigs([
|
.withIntroSpriteConfigs([
|
||||||
{
|
{
|
||||||
spriteKey: Species.GARBODOR.toString() + "-gigantamax",
|
spriteKey: SpeciesId.GARBODOR.toString() + "-gigantamax",
|
||||||
fileRoot: "pokemon",
|
fileRoot: "pokemon",
|
||||||
hasShadow: false,
|
hasShadow: false,
|
||||||
disableAnimation: true,
|
disableAnimation: true,
|
||||||
@ -74,14 +74,14 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||||
|
|
||||||
// Calculate boss mon (shiny locked)
|
// Calculate boss mon (shiny locked)
|
||||||
const bossSpecies = getPokemonSpecies(Species.GARBODOR);
|
const bossSpecies = getPokemonSpecies(SpeciesId.GARBODOR);
|
||||||
const pokemonConfig: EnemyPokemonConfig = {
|
const pokemonConfig: EnemyPokemonConfig = {
|
||||||
species: bossSpecies,
|
species: bossSpecies,
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
shiny: false, // Shiny lock because of custom intro sprite
|
shiny: false, // Shiny lock because of custom intro sprite
|
||||||
formIndex: 1, // Gmax
|
formIndex: 1, // Gmax
|
||||||
bossSegmentModifier: 1, // +1 Segment from normal
|
bossSegmentModifier: 1, // +1 Segment from normal
|
||||||
moveSet: [Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.HAMMER_ARM, Moves.PAYBACK],
|
moveSet: [MoveId.GUNK_SHOT, MoveId.STOMPING_TANTRUM, MoveId.HAMMER_ARM, MoveId.PAYBACK],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
{
|
{
|
||||||
modifier: generateModifierType(modifierTypes.BERRY) as PokemonHeldItemModifierType,
|
modifier: generateModifierType(modifierTypes.BERRY) as PokemonHeldItemModifierType,
|
||||||
@ -127,7 +127,7 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
encounter.enemyPartyConfigs = [config];
|
encounter.enemyPartyConfigs = [config];
|
||||||
|
|
||||||
// Load animations/sfx for Garbodor fight start moves
|
// Load animations/sfx for Garbodor fight start moves
|
||||||
loadCustomMovesForEncounter([Moves.TOXIC, Moves.STOCKPILE]);
|
loadCustomMovesForEncounter([MoveId.TOXIC, MoveId.STOCKPILE]);
|
||||||
|
|
||||||
globalScene.loadSe("PRSFX- Dig2", "battle_anims", "PRSFX- Dig2.wav");
|
globalScene.loadSe("PRSFX- Dig2", "battle_anims", "PRSFX- Dig2.wav");
|
||||||
globalScene.loadSe("PRSFX- Venom Drench", "battle_anims", "PRSFX- Venom Drench.wav");
|
globalScene.loadSe("PRSFX- Venom Drench", "battle_anims", "PRSFX- Venom Drench.wav");
|
||||||
@ -206,13 +206,13 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
{
|
{
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||||
targets: [BattlerIndex.PLAYER],
|
targets: [BattlerIndex.PLAYER],
|
||||||
move: new PokemonMove(Moves.TOXIC),
|
move: new PokemonMove(MoveId.TOXIC),
|
||||||
ignorePp: true,
|
ignorePp: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||||
targets: [BattlerIndex.ENEMY],
|
targets: [BattlerIndex.ENEMY],
|
||||||
move: new PokemonMove(Moves.STOCKPILE),
|
move: new PokemonMove(MoveId.STOCKPILE),
|
||||||
ignorePp: true,
|
ignorePp: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
import { CHARMING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
import { CHARMING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import type { EnemyPokemon } from "#app/field/pokemon";
|
import type { EnemyPokemon } from "#app/field/pokemon";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
@ -28,14 +28,12 @@ import {
|
|||||||
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
|
import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
|
||||||
import type { Moves } from "#enums/moves";
|
import type { MoveId } from "#enums/move-id";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import { SelfStatusMove } from "#app/data/moves/move";
|
|
||||||
import { PokeballType } from "#enums/pokeball";
|
import { PokeballType } from "#enums/pokeball";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { BerryModifier } from "#app/modifier/modifier";
|
import { BerryModifier } from "#app/modifier/modifier";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
|
|
||||||
@ -73,7 +71,7 @@ export const UncommonBreedEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
const eggMoves = pokemon.getEggMoves();
|
const eggMoves = pokemon.getEggMoves();
|
||||||
if (eggMoves) {
|
if (eggMoves) {
|
||||||
const eggMoveIndex = randSeedInt(4);
|
const eggMoveIndex = randSeedInt(4);
|
||||||
const randomEggMove: Moves = eggMoves[eggMoveIndex];
|
const randomEggMove: MoveId = eggMoves[eggMoveIndex];
|
||||||
encounter.misc = {
|
encounter.misc = {
|
||||||
eggMove: randomEggMove,
|
eggMove: randomEggMove,
|
||||||
pokemon: pokemon,
|
pokemon: pokemon,
|
||||||
@ -103,8 +101,12 @@ export const UncommonBreedEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(`${namespace}:option.1.stat_boost`);
|
queueEncounterMessage(`${namespace}:option.1.stat_boost`);
|
||||||
globalScene.unshiftPhase(
|
globalScene.phaseManager.unshiftNew(
|
||||||
new StatStageChangePhase(pokemon.getBattlerIndex(), true, statChangesForBattle, 1),
|
"StatStageChangePhase",
|
||||||
|
pokemon.getBattlerIndex(),
|
||||||
|
true,
|
||||||
|
statChangesForBattle,
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -172,7 +174,7 @@ export const UncommonBreedEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
// Check what type of move the egg move is to determine target
|
// Check what type of move the egg move is to determine target
|
||||||
const pokemonMove = new PokemonMove(eggMove);
|
const pokemonMove = new PokemonMove(eggMove);
|
||||||
const move = pokemonMove.getMove();
|
const move = pokemonMove.getMove();
|
||||||
const target = move instanceof SelfStatusMove ? BattlerIndex.ENEMY : BattlerIndex.PLAYER;
|
const target = move.is("SelfStatusMove") ? BattlerIndex.ENEMY : BattlerIndex.PLAYER;
|
||||||
|
|
||||||
encounter.startOfBattleEffects.push({
|
encounter.startOfBattleEffects.push({
|
||||||
sourceBattlerIndex: BattlerIndex.ENEMY,
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
||||||
@ -270,10 +272,10 @@ export const UncommonBreedEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
|||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
function givePokemonExtraEggMove(pokemon: EnemyPokemon, previousEggMove: Moves) {
|
function givePokemonExtraEggMove(pokemon: EnemyPokemon, previousEggMove: MoveId) {
|
||||||
const eggMoves = pokemon.getEggMoves();
|
const eggMoves = pokemon.getEggMoves();
|
||||||
if (eggMoves) {
|
if (eggMoves) {
|
||||||
let randomEggMove: Moves = eggMoves[randSeedInt(4)];
|
let randomEggMove: MoveId = eggMoves[randSeedInt(4)];
|
||||||
while (randomEggMove === previousEggMove) {
|
while (randomEggMove === previousEggMove) {
|
||||||
randomEggMove = eggMoves[randSeedInt(4)];
|
randomEggMove = eggMoves[randSeedInt(4)];
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
@ -16,7 +16,7 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
|||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import { NumberHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils/common";
|
import { NumberHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils/common";
|
||||||
import type PokemonSpecies from "#app/data/pokemon-species";
|
import type PokemonSpecies from "#app/data/pokemon-species";
|
||||||
import { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
import { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
@ -39,7 +39,7 @@ import { PlayerGender } from "#enums/player-gender";
|
|||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||||
import { trainerConfigs } from "#app/data/trainers/trainer-config";
|
import { trainerConfigs } from "#app/data/trainers/trainer-config";
|
||||||
import { TrainerPartyTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
import { TrainerPartyTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
@ -49,55 +49,55 @@ const namespace = "mysteryEncounters/weirdDream";
|
|||||||
|
|
||||||
/** Exclude Ultra Beasts, Paradox, Eternatus, and all legendary/mythical/trio pokemon that are below 570 BST */
|
/** Exclude Ultra Beasts, Paradox, Eternatus, and all legendary/mythical/trio pokemon that are below 570 BST */
|
||||||
const EXCLUDED_TRANSFORMATION_SPECIES = [
|
const EXCLUDED_TRANSFORMATION_SPECIES = [
|
||||||
Species.ETERNATUS,
|
SpeciesId.ETERNATUS,
|
||||||
/** UBs */
|
/** UBs */
|
||||||
Species.NIHILEGO,
|
SpeciesId.NIHILEGO,
|
||||||
Species.BUZZWOLE,
|
SpeciesId.BUZZWOLE,
|
||||||
Species.PHEROMOSA,
|
SpeciesId.PHEROMOSA,
|
||||||
Species.XURKITREE,
|
SpeciesId.XURKITREE,
|
||||||
Species.CELESTEELA,
|
SpeciesId.CELESTEELA,
|
||||||
Species.KARTANA,
|
SpeciesId.KARTANA,
|
||||||
Species.GUZZLORD,
|
SpeciesId.GUZZLORD,
|
||||||
Species.POIPOLE,
|
SpeciesId.POIPOLE,
|
||||||
Species.NAGANADEL,
|
SpeciesId.NAGANADEL,
|
||||||
Species.STAKATAKA,
|
SpeciesId.STAKATAKA,
|
||||||
Species.BLACEPHALON,
|
SpeciesId.BLACEPHALON,
|
||||||
/** Paradox */
|
/** Paradox */
|
||||||
Species.GREAT_TUSK,
|
SpeciesId.GREAT_TUSK,
|
||||||
Species.SCREAM_TAIL,
|
SpeciesId.SCREAM_TAIL,
|
||||||
Species.BRUTE_BONNET,
|
SpeciesId.BRUTE_BONNET,
|
||||||
Species.FLUTTER_MANE,
|
SpeciesId.FLUTTER_MANE,
|
||||||
Species.SLITHER_WING,
|
SpeciesId.SLITHER_WING,
|
||||||
Species.SANDY_SHOCKS,
|
SpeciesId.SANDY_SHOCKS,
|
||||||
Species.ROARING_MOON,
|
SpeciesId.ROARING_MOON,
|
||||||
Species.WALKING_WAKE,
|
SpeciesId.WALKING_WAKE,
|
||||||
Species.GOUGING_FIRE,
|
SpeciesId.GOUGING_FIRE,
|
||||||
Species.RAGING_BOLT,
|
SpeciesId.RAGING_BOLT,
|
||||||
Species.IRON_TREADS,
|
SpeciesId.IRON_TREADS,
|
||||||
Species.IRON_BUNDLE,
|
SpeciesId.IRON_BUNDLE,
|
||||||
Species.IRON_HANDS,
|
SpeciesId.IRON_HANDS,
|
||||||
Species.IRON_JUGULIS,
|
SpeciesId.IRON_JUGULIS,
|
||||||
Species.IRON_MOTH,
|
SpeciesId.IRON_MOTH,
|
||||||
Species.IRON_THORNS,
|
SpeciesId.IRON_THORNS,
|
||||||
Species.IRON_VALIANT,
|
SpeciesId.IRON_VALIANT,
|
||||||
Species.IRON_LEAVES,
|
SpeciesId.IRON_LEAVES,
|
||||||
Species.IRON_BOULDER,
|
SpeciesId.IRON_BOULDER,
|
||||||
Species.IRON_CROWN,
|
SpeciesId.IRON_CROWN,
|
||||||
/** These are banned so they don't appear in the < 570 BST pool */
|
/** These are banned so they don't appear in the < 570 BST pool */
|
||||||
Species.COSMOG,
|
SpeciesId.COSMOG,
|
||||||
Species.MELTAN,
|
SpeciesId.MELTAN,
|
||||||
Species.KUBFU,
|
SpeciesId.KUBFU,
|
||||||
Species.COSMOEM,
|
SpeciesId.COSMOEM,
|
||||||
Species.POIPOLE,
|
SpeciesId.POIPOLE,
|
||||||
Species.TERAPAGOS,
|
SpeciesId.TERAPAGOS,
|
||||||
Species.TYPE_NULL,
|
SpeciesId.TYPE_NULL,
|
||||||
Species.CALYREX,
|
SpeciesId.CALYREX,
|
||||||
Species.NAGANADEL,
|
SpeciesId.NAGANADEL,
|
||||||
Species.URSHIFU,
|
SpeciesId.URSHIFU,
|
||||||
Species.OGERPON,
|
SpeciesId.OGERPON,
|
||||||
Species.OKIDOGI,
|
SpeciesId.OKIDOGI,
|
||||||
Species.MUNKIDORI,
|
SpeciesId.MUNKIDORI,
|
||||||
Species.FEZANDIPITI,
|
SpeciesId.FEZANDIPITI,
|
||||||
];
|
];
|
||||||
|
|
||||||
const SUPER_LEGENDARY_BST_THRESHOLD = 600;
|
const SUPER_LEGENDARY_BST_THRESHOLD = 600;
|
||||||
@ -500,7 +500,7 @@ async function doNewTeamPostProcess(transformations: PokemonTransformation[]) {
|
|||||||
async function postProcessTransformedPokemon(
|
async function postProcessTransformedPokemon(
|
||||||
previousPokemon: PlayerPokemon,
|
previousPokemon: PlayerPokemon,
|
||||||
newPokemon: PlayerPokemon,
|
newPokemon: PlayerPokemon,
|
||||||
speciesRootForm: Species,
|
speciesRootForm: SpeciesId,
|
||||||
forBattle = false,
|
forBattle = false,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
let isNewStarter = false;
|
let isNewStarter = false;
|
||||||
@ -768,7 +768,7 @@ function doSideBySideTransformations(transformations: PokemonTransformation[]) {
|
|||||||
*/
|
*/
|
||||||
async function addEggMoveToNewPokemonMoveset(
|
async function addEggMoveToNewPokemonMoveset(
|
||||||
newPokemon: PlayerPokemon,
|
newPokemon: PlayerPokemon,
|
||||||
speciesRootForm: Species,
|
speciesRootForm: SpeciesId,
|
||||||
forBattle = false,
|
forBattle = false,
|
||||||
): Promise<number | null> {
|
): Promise<number | null> {
|
||||||
let eggMoveIndex: null | number = null;
|
let eggMoveIndex: null | number = null;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { OptionTextDisplay } from "#app/data/mystery-encounters/mystery-encounter-dialogue";
|
import type { OptionTextDisplay } from "#app/data/mystery-encounters/mystery-encounter-dialogue";
|
||||||
import type { Moves } from "#app/enums/moves";
|
import type { MoveId } from "#enums/move-id";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
@ -300,7 +300,7 @@ export class MysteryEncounterOptionBuilder implements Partial<IMysteryEncounterO
|
|||||||
* @param options see {@linkcode CanLearnMoveRequirementOptions}
|
* @param options see {@linkcode CanLearnMoveRequirementOptions}
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withPokemonCanLearnMoveRequirement(move: Moves | Moves[], options?: CanLearnMoveRequirementOptions) {
|
withPokemonCanLearnMoveRequirement(move: MoveId | MoveId[], options?: CanLearnMoveRequirementOptions) {
|
||||||
return this.withPrimaryPokemonRequirement(new CanLearnMoveRequirement(move, options));
|
return this.withPrimaryPokemonRequirement(new CanLearnMoveRequirement(move, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,9 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { allAbilities } from "../data-lists";
|
import { allAbilities } from "../data-lists";
|
||||||
import { EvolutionItem, pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
import { EvolutionItem, pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import { FormChangeItem, pokemonFormChanges, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms";
|
import { pokemonFormChanges } from "#app/data/pokemon-forms";
|
||||||
|
import { SpeciesFormChangeItemTrigger } from "../pokemon-forms/form-change-triggers";
|
||||||
|
import { FormChangeItem } from "#enums/form-change-item";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { WeatherType } from "#enums/weather-type";
|
import { WeatherType } from "#enums/weather-type";
|
||||||
@ -10,10 +12,10 @@ import type { PlayerPokemon } from "#app/field/pokemon";
|
|||||||
import { AttackTypeBoosterModifier } from "#app/modifier/modifier";
|
import { AttackTypeBoosterModifier } from "#app/modifier/modifier";
|
||||||
import type { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type";
|
import type { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type";
|
||||||
import { isNullOrUndefined } from "#app/utils/common";
|
import { isNullOrUndefined } from "#app/utils/common";
|
||||||
import type { Abilities } from "#enums/abilities";
|
import type { AbilityId } from "#enums/ability-id";
|
||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||||
import { TimeOfDay } from "#enums/time-of-day";
|
import { TimeOfDay } from "#enums/time-of-day";
|
||||||
|
|
||||||
@ -275,15 +277,11 @@ export class TimeOfDayRequirement extends EncounterSceneRequirement {
|
|||||||
|
|
||||||
override meetsRequirement(): boolean {
|
override meetsRequirement(): boolean {
|
||||||
const timeOfDay = globalScene.arena?.getTimeOfDay();
|
const timeOfDay = globalScene.arena?.getTimeOfDay();
|
||||||
if (
|
return !(
|
||||||
!isNullOrUndefined(timeOfDay) &&
|
!isNullOrUndefined(timeOfDay) &&
|
||||||
this.requiredTimeOfDay?.length > 0 &&
|
this.requiredTimeOfDay?.length > 0 &&
|
||||||
!this.requiredTimeOfDay.includes(timeOfDay)
|
!this.requiredTimeOfDay.includes(timeOfDay)
|
||||||
) {
|
);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override getDialogueToken(_pokemon?: PlayerPokemon): [string, string] {
|
override getDialogueToken(_pokemon?: PlayerPokemon): [string, string] {
|
||||||
@ -301,15 +299,11 @@ export class WeatherRequirement extends EncounterSceneRequirement {
|
|||||||
|
|
||||||
override meetsRequirement(): boolean {
|
override meetsRequirement(): boolean {
|
||||||
const currentWeather = globalScene.arena.weather?.weatherType;
|
const currentWeather = globalScene.arena.weather?.weatherType;
|
||||||
if (
|
return !(
|
||||||
!isNullOrUndefined(currentWeather) &&
|
!isNullOrUndefined(currentWeather) &&
|
||||||
this.requiredWeather?.length > 0 &&
|
this.requiredWeather?.length > 0 &&
|
||||||
!this.requiredWeather.includes(currentWeather!)
|
!this.requiredWeather.includes(currentWeather!)
|
||||||
) {
|
);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override getDialogueToken(_pokemon?: PlayerPokemon): [string, string] {
|
override getDialogueToken(_pokemon?: PlayerPokemon): [string, string] {
|
||||||
@ -424,11 +418,11 @@ export class MoneyRequirement extends EncounterSceneRequirement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class SpeciesRequirement extends EncounterPokemonRequirement {
|
export class SpeciesRequirement extends EncounterPokemonRequirement {
|
||||||
requiredSpecies: Species[];
|
requiredSpecies: SpeciesId[];
|
||||||
minNumberOfPokemon: number;
|
minNumberOfPokemon: number;
|
||||||
invertQuery: boolean;
|
invertQuery: boolean;
|
||||||
|
|
||||||
constructor(species: Species | Species[], minNumberOfPokemon = 1, invertQuery = false) {
|
constructor(species: SpeciesId | SpeciesId[], minNumberOfPokemon = 1, invertQuery = false) {
|
||||||
super();
|
super();
|
||||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||||
this.invertQuery = invertQuery;
|
this.invertQuery = invertQuery;
|
||||||
@ -457,7 +451,7 @@ export class SpeciesRequirement extends EncounterPokemonRequirement {
|
|||||||
|
|
||||||
override getDialogueToken(pokemon?: PlayerPokemon): [string, string] {
|
override getDialogueToken(pokemon?: PlayerPokemon): [string, string] {
|
||||||
if (pokemon?.species.speciesId && this.requiredSpecies.includes(pokemon.species.speciesId)) {
|
if (pokemon?.species.speciesId && this.requiredSpecies.includes(pokemon.species.speciesId)) {
|
||||||
return ["species", Species[pokemon.species.speciesId]];
|
return ["species", SpeciesId[pokemon.species.speciesId]];
|
||||||
}
|
}
|
||||||
return ["species", ""];
|
return ["species", ""];
|
||||||
}
|
}
|
||||||
@ -549,12 +543,17 @@ export class TypeRequirement extends EncounterPokemonRequirement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MoveRequirement extends EncounterPokemonRequirement {
|
export class MoveRequirement extends EncounterPokemonRequirement {
|
||||||
requiredMoves: Moves[] = [];
|
requiredMoves: MoveId[] = [];
|
||||||
minNumberOfPokemon: number;
|
minNumberOfPokemon: number;
|
||||||
invertQuery: boolean;
|
invertQuery: boolean;
|
||||||
excludeDisallowedPokemon: boolean;
|
excludeDisallowedPokemon: boolean;
|
||||||
|
|
||||||
constructor(moves: Moves | Moves[], excludeDisallowedPokemon: boolean, minNumberOfPokemon = 1, invertQuery = false) {
|
constructor(
|
||||||
|
moves: MoveId | MoveId[],
|
||||||
|
excludeDisallowedPokemon: boolean,
|
||||||
|
minNumberOfPokemon = 1,
|
||||||
|
invertQuery = false,
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.excludeDisallowedPokemon = excludeDisallowedPokemon;
|
this.excludeDisallowedPokemon = excludeDisallowedPokemon;
|
||||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||||
@ -602,11 +601,11 @@ export class MoveRequirement extends EncounterPokemonRequirement {
|
|||||||
* NOTE: If the Pokemon already knows the move, this requirement will fail, since it's not technically learnable.
|
* NOTE: If the Pokemon already knows the move, this requirement will fail, since it's not technically learnable.
|
||||||
*/
|
*/
|
||||||
export class CompatibleMoveRequirement extends EncounterPokemonRequirement {
|
export class CompatibleMoveRequirement extends EncounterPokemonRequirement {
|
||||||
requiredMoves: Moves[];
|
requiredMoves: MoveId[];
|
||||||
minNumberOfPokemon: number;
|
minNumberOfPokemon: number;
|
||||||
invertQuery: boolean;
|
invertQuery: boolean;
|
||||||
|
|
||||||
constructor(learnableMove: Moves | Moves[], minNumberOfPokemon = 1, invertQuery = false) {
|
constructor(learnableMove: MoveId | MoveId[], minNumberOfPokemon = 1, invertQuery = false) {
|
||||||
super();
|
super();
|
||||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||||
this.invertQuery = invertQuery;
|
this.invertQuery = invertQuery;
|
||||||
@ -644,20 +643,20 @@ export class CompatibleMoveRequirement extends EncounterPokemonRequirement {
|
|||||||
pokemon?.compatibleTms.filter(tm => !pokemon.moveset.find(m => m.moveId === tm)).includes(reqMove),
|
pokemon?.compatibleTms.filter(tm => !pokemon.moveset.find(m => m.moveId === tm)).includes(reqMove),
|
||||||
);
|
);
|
||||||
if (includedCompatMoves.length > 0) {
|
if (includedCompatMoves.length > 0) {
|
||||||
return ["compatibleMove", Moves[includedCompatMoves[0]]];
|
return ["compatibleMove", MoveId[includedCompatMoves[0]]];
|
||||||
}
|
}
|
||||||
return ["compatibleMove", ""];
|
return ["compatibleMove", ""];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AbilityRequirement extends EncounterPokemonRequirement {
|
export class AbilityRequirement extends EncounterPokemonRequirement {
|
||||||
requiredAbilities: Abilities[];
|
requiredAbilities: AbilityId[];
|
||||||
minNumberOfPokemon: number;
|
minNumberOfPokemon: number;
|
||||||
invertQuery: boolean;
|
invertQuery: boolean;
|
||||||
excludeDisallowedPokemon: boolean;
|
excludeDisallowedPokemon: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
abilities: Abilities | Abilities[],
|
abilities: AbilityId | AbilityId[],
|
||||||
excludeDisallowedPokemon: boolean,
|
excludeDisallowedPokemon: boolean,
|
||||||
minNumberOfPokemon = 1,
|
minNumberOfPokemon = 1,
|
||||||
invertQuery = false,
|
invertQuery = false,
|
||||||
@ -798,7 +797,7 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen
|
|||||||
}
|
}
|
||||||
|
|
||||||
filterByForm(pokemon, formChangeItem) {
|
filterByForm(pokemon, formChangeItem) {
|
||||||
if (
|
return (
|
||||||
pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId) &&
|
pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId) &&
|
||||||
// Get all form changes for this species with an item trigger, including any compound triggers
|
// Get all form changes for this species with an item trigger, including any compound triggers
|
||||||
pokemonFormChanges[pokemon.species.speciesId]
|
pokemonFormChanges[pokemon.species.speciesId]
|
||||||
@ -807,10 +806,7 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen
|
|||||||
.flatMap(fc => fc.findTrigger(SpeciesFormChangeItemTrigger) as SpeciesFormChangeItemTrigger)
|
.flatMap(fc => fc.findTrigger(SpeciesFormChangeItemTrigger) as SpeciesFormChangeItemTrigger)
|
||||||
.flatMap(fc => fc.item)
|
.flatMap(fc => fc.item)
|
||||||
.includes(formChangeItem)
|
.includes(formChangeItem)
|
||||||
) {
|
);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||||
@ -868,17 +864,15 @@ export class CanEvolveWithItemRequirement extends EncounterPokemonRequirement {
|
|||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
|
return (
|
||||||
pokemon.isFusion() &&
|
pokemon.isFusion() &&
|
||||||
pokemonEvolutions.hasOwnProperty(pokemon.fusionSpecies.speciesId) &&
|
pokemonEvolutions.hasOwnProperty(pokemon.fusionSpecies.speciesId) &&
|
||||||
pokemonEvolutions[pokemon.fusionSpecies.speciesId].filter(
|
pokemonEvolutions[pokemon.fusionSpecies.speciesId].filter(
|
||||||
e => e.item === evolutionItem && (!e.condition || e.condition.predicate(pokemon)),
|
e => e.item === evolutionItem && (!e.condition || e.condition.predicate(pokemon)),
|
||||||
).length &&
|
).length &&
|
||||||
pokemon.getFusionFormKey() !== SpeciesFormKey.GIGANTAMAX
|
pokemon.getFusionFormKey() !== SpeciesFormKey.GIGANTAMAX
|
||||||
) {
|
);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import type { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import type { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
|
import type { PokemonMove } from "../moves/pokemon-move";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { capitalizeFirstLetter, isNullOrUndefined } from "#app/utils/common";
|
import { capitalizeFirstLetter, isNullOrUndefined } from "#app/utils/common";
|
||||||
import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
@ -20,11 +21,11 @@ import {
|
|||||||
StatusEffectRequirement,
|
StatusEffectRequirement,
|
||||||
WaveRangeRequirement,
|
WaveRangeRequirement,
|
||||||
} from "./mystery-encounter-requirements";
|
} from "./mystery-encounter-requirements";
|
||||||
import type { BattlerIndex } from "#app/battle";
|
import type { BattlerIndex } from "#enums/battler-index";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import type { GameModes } from "#app/game-mode";
|
import type { GameModes } from "#enums/game-modes";
|
||||||
import type { EncounterAnim } from "#enums/encounter-anims";
|
import type { EncounterAnim } from "#enums/encounter-anims";
|
||||||
import type { Challenges } from "#enums/challenges";
|
import type { Challenges } from "#enums/challenges";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Biome } from "#enums/biome";
|
import { BiomeId } from "#enums/biome-id";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { DarkDealEncounter } from "./encounters/dark-deal-encounter";
|
import { DarkDealEncounter } from "./encounters/dark-deal-encounter";
|
||||||
import { DepartmentStoreSaleEncounter } from "./encounters/department-store-sale-encounter";
|
import { DepartmentStoreSaleEncounter } from "./encounters/department-store-sale-encounter";
|
||||||
@ -71,44 +71,44 @@ export const AVERAGE_ENCOUNTERS_PER_RUN_TARGET = 12;
|
|||||||
export const ANTI_VARIANCE_WEIGHT_MODIFIER = 15;
|
export const ANTI_VARIANCE_WEIGHT_MODIFIER = 15;
|
||||||
|
|
||||||
export const EXTREME_ENCOUNTER_BIOMES = [
|
export const EXTREME_ENCOUNTER_BIOMES = [
|
||||||
Biome.SEA,
|
BiomeId.SEA,
|
||||||
Biome.SEABED,
|
BiomeId.SEABED,
|
||||||
Biome.BADLANDS,
|
BiomeId.BADLANDS,
|
||||||
Biome.DESERT,
|
BiomeId.DESERT,
|
||||||
Biome.ICE_CAVE,
|
BiomeId.ICE_CAVE,
|
||||||
Biome.VOLCANO,
|
BiomeId.VOLCANO,
|
||||||
Biome.WASTELAND,
|
BiomeId.WASTELAND,
|
||||||
Biome.ABYSS,
|
BiomeId.ABYSS,
|
||||||
Biome.SPACE,
|
BiomeId.SPACE,
|
||||||
Biome.END,
|
BiomeId.END,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const NON_EXTREME_ENCOUNTER_BIOMES = [
|
export const NON_EXTREME_ENCOUNTER_BIOMES = [
|
||||||
Biome.TOWN,
|
BiomeId.TOWN,
|
||||||
Biome.PLAINS,
|
BiomeId.PLAINS,
|
||||||
Biome.GRASS,
|
BiomeId.GRASS,
|
||||||
Biome.TALL_GRASS,
|
BiomeId.TALL_GRASS,
|
||||||
Biome.METROPOLIS,
|
BiomeId.METROPOLIS,
|
||||||
Biome.FOREST,
|
BiomeId.FOREST,
|
||||||
Biome.SWAMP,
|
BiomeId.SWAMP,
|
||||||
Biome.BEACH,
|
BiomeId.BEACH,
|
||||||
Biome.LAKE,
|
BiomeId.LAKE,
|
||||||
Biome.MOUNTAIN,
|
BiomeId.MOUNTAIN,
|
||||||
Biome.CAVE,
|
BiomeId.CAVE,
|
||||||
Biome.MEADOW,
|
BiomeId.MEADOW,
|
||||||
Biome.POWER_PLANT,
|
BiomeId.POWER_PLANT,
|
||||||
Biome.GRAVEYARD,
|
BiomeId.GRAVEYARD,
|
||||||
Biome.DOJO,
|
BiomeId.DOJO,
|
||||||
Biome.FACTORY,
|
BiomeId.FACTORY,
|
||||||
Biome.RUINS,
|
BiomeId.RUINS,
|
||||||
Biome.CONSTRUCTION_SITE,
|
BiomeId.CONSTRUCTION_SITE,
|
||||||
Biome.JUNGLE,
|
BiomeId.JUNGLE,
|
||||||
Biome.FAIRY_CAVE,
|
BiomeId.FAIRY_CAVE,
|
||||||
Biome.TEMPLE,
|
BiomeId.TEMPLE,
|
||||||
Biome.SLUM,
|
BiomeId.SLUM,
|
||||||
Biome.SNOWY_FOREST,
|
BiomeId.SNOWY_FOREST,
|
||||||
Biome.ISLAND,
|
BiomeId.ISLAND,
|
||||||
Biome.LABORATORY,
|
BiomeId.LABORATORY,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,55 +120,55 @@ export const NON_EXTREME_ENCOUNTER_BIOMES = [
|
|||||||
* + ICE_CAVE
|
* + ICE_CAVE
|
||||||
*/
|
*/
|
||||||
export const HUMAN_TRANSITABLE_BIOMES = [
|
export const HUMAN_TRANSITABLE_BIOMES = [
|
||||||
Biome.TOWN,
|
BiomeId.TOWN,
|
||||||
Biome.PLAINS,
|
BiomeId.PLAINS,
|
||||||
Biome.GRASS,
|
BiomeId.GRASS,
|
||||||
Biome.TALL_GRASS,
|
BiomeId.TALL_GRASS,
|
||||||
Biome.METROPOLIS,
|
BiomeId.METROPOLIS,
|
||||||
Biome.FOREST,
|
BiomeId.FOREST,
|
||||||
Biome.SWAMP,
|
BiomeId.SWAMP,
|
||||||
Biome.BEACH,
|
BiomeId.BEACH,
|
||||||
Biome.LAKE,
|
BiomeId.LAKE,
|
||||||
Biome.MOUNTAIN,
|
BiomeId.MOUNTAIN,
|
||||||
Biome.BADLANDS,
|
BiomeId.BADLANDS,
|
||||||
Biome.CAVE,
|
BiomeId.CAVE,
|
||||||
Biome.DESERT,
|
BiomeId.DESERT,
|
||||||
Biome.ICE_CAVE,
|
BiomeId.ICE_CAVE,
|
||||||
Biome.MEADOW,
|
BiomeId.MEADOW,
|
||||||
Biome.POWER_PLANT,
|
BiomeId.POWER_PLANT,
|
||||||
Biome.GRAVEYARD,
|
BiomeId.GRAVEYARD,
|
||||||
Biome.DOJO,
|
BiomeId.DOJO,
|
||||||
Biome.FACTORY,
|
BiomeId.FACTORY,
|
||||||
Biome.RUINS,
|
BiomeId.RUINS,
|
||||||
Biome.CONSTRUCTION_SITE,
|
BiomeId.CONSTRUCTION_SITE,
|
||||||
Biome.JUNGLE,
|
BiomeId.JUNGLE,
|
||||||
Biome.FAIRY_CAVE,
|
BiomeId.FAIRY_CAVE,
|
||||||
Biome.TEMPLE,
|
BiomeId.TEMPLE,
|
||||||
Biome.SLUM,
|
BiomeId.SLUM,
|
||||||
Biome.SNOWY_FOREST,
|
BiomeId.SNOWY_FOREST,
|
||||||
Biome.ISLAND,
|
BiomeId.ISLAND,
|
||||||
Biome.LABORATORY,
|
BiomeId.LABORATORY,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Places where you could expect a town or city, some form of large civilization
|
* Places where you could expect a town or city, some form of large civilization
|
||||||
*/
|
*/
|
||||||
export const CIVILIZATION_ENCOUNTER_BIOMES = [
|
export const CIVILIZATION_ENCOUNTER_BIOMES = [
|
||||||
Biome.TOWN,
|
BiomeId.TOWN,
|
||||||
Biome.PLAINS,
|
BiomeId.PLAINS,
|
||||||
Biome.GRASS,
|
BiomeId.GRASS,
|
||||||
Biome.TALL_GRASS,
|
BiomeId.TALL_GRASS,
|
||||||
Biome.METROPOLIS,
|
BiomeId.METROPOLIS,
|
||||||
Biome.BEACH,
|
BiomeId.BEACH,
|
||||||
Biome.LAKE,
|
BiomeId.LAKE,
|
||||||
Biome.MEADOW,
|
BiomeId.MEADOW,
|
||||||
Biome.POWER_PLANT,
|
BiomeId.POWER_PLANT,
|
||||||
Biome.GRAVEYARD,
|
BiomeId.GRAVEYARD,
|
||||||
Biome.DOJO,
|
BiomeId.DOJO,
|
||||||
Biome.FACTORY,
|
BiomeId.FACTORY,
|
||||||
Biome.CONSTRUCTION_SITE,
|
BiomeId.CONSTRUCTION_SITE,
|
||||||
Biome.SLUM,
|
BiomeId.SLUM,
|
||||||
Biome.ISLAND,
|
BiomeId.ISLAND,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const allMysteryEncounters: {
|
export const allMysteryEncounters: {
|
||||||
@ -224,41 +224,41 @@ const anyBiomeEncounters: MysteryEncounterType[] = [
|
|||||||
* Adding specific Encounters to the mysteryEncountersByBiome map is for specific cases and special circumstances
|
* Adding specific Encounters to the mysteryEncountersByBiome map is for specific cases and special circumstances
|
||||||
* that biome groups do not cover
|
* that biome groups do not cover
|
||||||
*/
|
*/
|
||||||
export const mysteryEncountersByBiome = new Map<Biome, MysteryEncounterType[]>([
|
export const mysteryEncountersByBiome = new Map<BiomeId, MysteryEncounterType[]>([
|
||||||
[Biome.TOWN, []],
|
[BiomeId.TOWN, []],
|
||||||
[Biome.PLAINS, [MysteryEncounterType.SLUMBERING_SNORLAX]],
|
[BiomeId.PLAINS, [MysteryEncounterType.SLUMBERING_SNORLAX]],
|
||||||
[Biome.GRASS, [MysteryEncounterType.SLUMBERING_SNORLAX, MysteryEncounterType.ABSOLUTE_AVARICE]],
|
[BiomeId.GRASS, [MysteryEncounterType.SLUMBERING_SNORLAX, MysteryEncounterType.ABSOLUTE_AVARICE]],
|
||||||
[Biome.TALL_GRASS, [MysteryEncounterType.SLUMBERING_SNORLAX, MysteryEncounterType.ABSOLUTE_AVARICE]],
|
[BiomeId.TALL_GRASS, [MysteryEncounterType.SLUMBERING_SNORLAX, MysteryEncounterType.ABSOLUTE_AVARICE]],
|
||||||
[Biome.METROPOLIS, []],
|
[BiomeId.METROPOLIS, []],
|
||||||
[Biome.FOREST, [MysteryEncounterType.SAFARI_ZONE, MysteryEncounterType.ABSOLUTE_AVARICE]],
|
[BiomeId.FOREST, [MysteryEncounterType.SAFARI_ZONE, MysteryEncounterType.ABSOLUTE_AVARICE]],
|
||||||
[Biome.SEA, [MysteryEncounterType.LOST_AT_SEA]],
|
[BiomeId.SEA, [MysteryEncounterType.LOST_AT_SEA]],
|
||||||
[Biome.SWAMP, [MysteryEncounterType.SAFARI_ZONE]],
|
[BiomeId.SWAMP, [MysteryEncounterType.SAFARI_ZONE]],
|
||||||
[Biome.BEACH, []],
|
[BiomeId.BEACH, []],
|
||||||
[Biome.LAKE, []],
|
[BiomeId.LAKE, []],
|
||||||
[Biome.SEABED, []],
|
[BiomeId.SEABED, []],
|
||||||
[Biome.MOUNTAIN, []],
|
[BiomeId.MOUNTAIN, []],
|
||||||
[Biome.BADLANDS, [MysteryEncounterType.DANCING_LESSONS]],
|
[BiomeId.BADLANDS, [MysteryEncounterType.DANCING_LESSONS]],
|
||||||
[Biome.CAVE, [MysteryEncounterType.THE_STRONG_STUFF]],
|
[BiomeId.CAVE, [MysteryEncounterType.THE_STRONG_STUFF]],
|
||||||
[Biome.DESERT, [MysteryEncounterType.DANCING_LESSONS]],
|
[BiomeId.DESERT, [MysteryEncounterType.DANCING_LESSONS]],
|
||||||
[Biome.ICE_CAVE, []],
|
[BiomeId.ICE_CAVE, []],
|
||||||
[Biome.MEADOW, []],
|
[BiomeId.MEADOW, []],
|
||||||
[Biome.POWER_PLANT, []],
|
[BiomeId.POWER_PLANT, []],
|
||||||
[Biome.VOLCANO, [MysteryEncounterType.FIERY_FALLOUT, MysteryEncounterType.DANCING_LESSONS]],
|
[BiomeId.VOLCANO, [MysteryEncounterType.FIERY_FALLOUT, MysteryEncounterType.DANCING_LESSONS]],
|
||||||
[Biome.GRAVEYARD, []],
|
[BiomeId.GRAVEYARD, []],
|
||||||
[Biome.DOJO, []],
|
[BiomeId.DOJO, []],
|
||||||
[Biome.FACTORY, []],
|
[BiomeId.FACTORY, []],
|
||||||
[Biome.RUINS, []],
|
[BiomeId.RUINS, []],
|
||||||
[Biome.WASTELAND, [MysteryEncounterType.DANCING_LESSONS]],
|
[BiomeId.WASTELAND, [MysteryEncounterType.DANCING_LESSONS]],
|
||||||
[Biome.ABYSS, [MysteryEncounterType.DANCING_LESSONS]],
|
[BiomeId.ABYSS, [MysteryEncounterType.DANCING_LESSONS]],
|
||||||
[Biome.SPACE, [MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER]],
|
[BiomeId.SPACE, [MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER]],
|
||||||
[Biome.CONSTRUCTION_SITE, []],
|
[BiomeId.CONSTRUCTION_SITE, []],
|
||||||
[Biome.JUNGLE, [MysteryEncounterType.SAFARI_ZONE]],
|
[BiomeId.JUNGLE, [MysteryEncounterType.SAFARI_ZONE]],
|
||||||
[Biome.FAIRY_CAVE, []],
|
[BiomeId.FAIRY_CAVE, []],
|
||||||
[Biome.TEMPLE, []],
|
[BiomeId.TEMPLE, []],
|
||||||
[Biome.SLUM, []],
|
[BiomeId.SLUM, []],
|
||||||
[Biome.SNOWY_FOREST, []],
|
[BiomeId.SNOWY_FOREST, []],
|
||||||
[Biome.ISLAND, []],
|
[BiomeId.ISLAND, []],
|
||||||
[Biome.LABORATORY, []],
|
[BiomeId.LABORATORY, []],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export function initMysteryEncounters() {
|
export function initMysteryEncounters() {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { Moves } from "#app/enums/moves";
|
import type { MoveId } from "#enums/move-id";
|
||||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
import { isNullOrUndefined } from "#app/utils/common";
|
import { isNullOrUndefined } from "#app/utils/common";
|
||||||
import { EncounterPokemonRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
import { EncounterPokemonRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
@ -21,13 +21,13 @@ export interface CanLearnMoveRequirementOptions {
|
|||||||
* Requires that a pokemon can learn a specific move/moveset.
|
* Requires that a pokemon can learn a specific move/moveset.
|
||||||
*/
|
*/
|
||||||
export class CanLearnMoveRequirement extends EncounterPokemonRequirement {
|
export class CanLearnMoveRequirement extends EncounterPokemonRequirement {
|
||||||
private readonly requiredMoves: Moves[];
|
private readonly requiredMoves: MoveId[];
|
||||||
private readonly excludeLevelMoves?: boolean;
|
private readonly excludeLevelMoves?: boolean;
|
||||||
private readonly excludeTmMoves?: boolean;
|
private readonly excludeTmMoves?: boolean;
|
||||||
private readonly excludeEggMoves?: boolean;
|
private readonly excludeEggMoves?: boolean;
|
||||||
private readonly includeFainted?: boolean;
|
private readonly includeFainted?: boolean;
|
||||||
|
|
||||||
constructor(requiredMoves: Moves | Moves[], options: CanLearnMoveRequirementOptions = {}) {
|
constructor(requiredMoves: MoveId | MoveId[], options: CanLearnMoveRequirementOptions = {}) {
|
||||||
super();
|
super();
|
||||||
this.requiredMoves = Array.isArray(requiredMoves) ? requiredMoves : [requiredMoves];
|
this.requiredMoves = Array.isArray(requiredMoves) ? requiredMoves : [requiredMoves];
|
||||||
|
|
||||||
@ -69,12 +69,12 @@ export class CanLearnMoveRequirement extends EncounterPokemonRequirement {
|
|||||||
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[] {
|
private getPokemonLevelMoves(pkm: PlayerPokemon): MoveId[] {
|
||||||
return pkm.getLevelMoves().map(([_level, move]) => move);
|
return pkm.getLevelMoves().map(([_level, move]) => move);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getAllPokemonMoves(pkm: PlayerPokemon): Moves[] {
|
private getAllPokemonMoves(pkm: PlayerPokemon): MoveId[] {
|
||||||
const allPokemonMoves: Moves[] = [];
|
const allPokemonMoves: MoveId[] = [];
|
||||||
|
|
||||||
if (!this.excludeLevelMoves) {
|
if (!this.excludeLevelMoves) {
|
||||||
allPokemonMoves.push(...(this.getPokemonLevelMoves(pkm) ?? []));
|
allPokemonMoves.push(...(this.getPokemonLevelMoves(pkm) ?? []));
|
||||||
|
@ -1,130 +1,137 @@
|
|||||||
import { Moves } from "#enums/moves";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves that "steal" things
|
* Moves that "steal" things
|
||||||
*/
|
*/
|
||||||
export const STEALING_MOVES = [Moves.PLUCK, Moves.COVET, Moves.KNOCK_OFF, Moves.THIEF, Moves.TRICK, Moves.SWITCHEROO];
|
export const STEALING_MOVES = [
|
||||||
|
MoveId.PLUCK,
|
||||||
|
MoveId.COVET,
|
||||||
|
MoveId.KNOCK_OFF,
|
||||||
|
MoveId.THIEF,
|
||||||
|
MoveId.TRICK,
|
||||||
|
MoveId.SWITCHEROO,
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves that "charm" someone
|
* Moves that "charm" someone
|
||||||
*/
|
*/
|
||||||
export const CHARMING_MOVES = [
|
export const CHARMING_MOVES = [
|
||||||
Moves.CHARM,
|
MoveId.CHARM,
|
||||||
Moves.FLATTER,
|
MoveId.FLATTER,
|
||||||
Moves.DRAGON_CHEER,
|
MoveId.DRAGON_CHEER,
|
||||||
Moves.ALLURING_VOICE,
|
MoveId.ALLURING_VOICE,
|
||||||
Moves.ATTRACT,
|
MoveId.ATTRACT,
|
||||||
Moves.SWEET_SCENT,
|
MoveId.SWEET_SCENT,
|
||||||
Moves.CAPTIVATE,
|
MoveId.CAPTIVATE,
|
||||||
Moves.AROMATIC_MIST,
|
MoveId.AROMATIC_MIST,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves for the Dancer ability
|
* Moves for the Dancer ability
|
||||||
*/
|
*/
|
||||||
export const DANCING_MOVES = [
|
export const DANCING_MOVES = [
|
||||||
Moves.AQUA_STEP,
|
MoveId.AQUA_STEP,
|
||||||
Moves.CLANGOROUS_SOUL,
|
MoveId.CLANGOROUS_SOUL,
|
||||||
Moves.DRAGON_DANCE,
|
MoveId.DRAGON_DANCE,
|
||||||
Moves.FEATHER_DANCE,
|
MoveId.FEATHER_DANCE,
|
||||||
Moves.FIERY_DANCE,
|
MoveId.FIERY_DANCE,
|
||||||
Moves.LUNAR_DANCE,
|
MoveId.LUNAR_DANCE,
|
||||||
Moves.PETAL_DANCE,
|
MoveId.PETAL_DANCE,
|
||||||
Moves.REVELATION_DANCE,
|
MoveId.REVELATION_DANCE,
|
||||||
Moves.QUIVER_DANCE,
|
MoveId.QUIVER_DANCE,
|
||||||
Moves.SWORDS_DANCE,
|
MoveId.SWORDS_DANCE,
|
||||||
Moves.TEETER_DANCE,
|
MoveId.TEETER_DANCE,
|
||||||
Moves.VICTORY_DANCE,
|
MoveId.VICTORY_DANCE,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves that can distract someone/something
|
* Moves that can distract someone/something
|
||||||
*/
|
*/
|
||||||
export const DISTRACTION_MOVES = [
|
export const DISTRACTION_MOVES = [
|
||||||
Moves.FAKE_OUT,
|
MoveId.FAKE_OUT,
|
||||||
Moves.FOLLOW_ME,
|
MoveId.FOLLOW_ME,
|
||||||
Moves.TAUNT,
|
MoveId.TAUNT,
|
||||||
Moves.ROAR,
|
MoveId.ROAR,
|
||||||
Moves.TELEPORT,
|
MoveId.TELEPORT,
|
||||||
Moves.CHARM,
|
MoveId.CHARM,
|
||||||
Moves.FAKE_TEARS,
|
MoveId.FAKE_TEARS,
|
||||||
Moves.TICKLE,
|
MoveId.TICKLE,
|
||||||
Moves.CAPTIVATE,
|
MoveId.CAPTIVATE,
|
||||||
Moves.RAGE_POWDER,
|
MoveId.RAGE_POWDER,
|
||||||
Moves.SUBSTITUTE,
|
MoveId.SUBSTITUTE,
|
||||||
Moves.SHED_TAIL,
|
MoveId.SHED_TAIL,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves that protect in some way
|
* Moves that protect in some way
|
||||||
*/
|
*/
|
||||||
export const PROTECTING_MOVES = [
|
export const PROTECTING_MOVES = [
|
||||||
Moves.PROTECT,
|
MoveId.PROTECT,
|
||||||
Moves.WIDE_GUARD,
|
MoveId.WIDE_GUARD,
|
||||||
Moves.MAX_GUARD,
|
MoveId.MAX_GUARD,
|
||||||
Moves.SAFEGUARD,
|
MoveId.SAFEGUARD,
|
||||||
Moves.REFLECT,
|
MoveId.REFLECT,
|
||||||
Moves.BARRIER,
|
MoveId.BARRIER,
|
||||||
Moves.QUICK_GUARD,
|
MoveId.QUICK_GUARD,
|
||||||
Moves.FLOWER_SHIELD,
|
MoveId.FLOWER_SHIELD,
|
||||||
Moves.KINGS_SHIELD,
|
MoveId.KINGS_SHIELD,
|
||||||
Moves.CRAFTY_SHIELD,
|
MoveId.CRAFTY_SHIELD,
|
||||||
Moves.SPIKY_SHIELD,
|
MoveId.SPIKY_SHIELD,
|
||||||
Moves.OBSTRUCT,
|
MoveId.OBSTRUCT,
|
||||||
Moves.DETECT,
|
MoveId.DETECT,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves that (loosely) can be used to trap/rob someone
|
* Moves that (loosely) can be used to trap/rob someone
|
||||||
*/
|
*/
|
||||||
export const EXTORTION_MOVES = [
|
export const EXTORTION_MOVES = [
|
||||||
Moves.BIND,
|
MoveId.BIND,
|
||||||
Moves.CLAMP,
|
MoveId.CLAMP,
|
||||||
Moves.INFESTATION,
|
MoveId.INFESTATION,
|
||||||
Moves.SAND_TOMB,
|
MoveId.SAND_TOMB,
|
||||||
Moves.SNAP_TRAP,
|
MoveId.SNAP_TRAP,
|
||||||
Moves.THUNDER_CAGE,
|
MoveId.THUNDER_CAGE,
|
||||||
Moves.WRAP,
|
MoveId.WRAP,
|
||||||
Moves.SPIRIT_SHACKLE,
|
MoveId.SPIRIT_SHACKLE,
|
||||||
Moves.MEAN_LOOK,
|
MoveId.MEAN_LOOK,
|
||||||
Moves.JAW_LOCK,
|
MoveId.JAW_LOCK,
|
||||||
Moves.BLOCK,
|
MoveId.BLOCK,
|
||||||
Moves.SPIDER_WEB,
|
MoveId.SPIDER_WEB,
|
||||||
Moves.ANCHOR_SHOT,
|
MoveId.ANCHOR_SHOT,
|
||||||
Moves.OCTOLOCK,
|
MoveId.OCTOLOCK,
|
||||||
Moves.PURSUIT,
|
MoveId.PURSUIT,
|
||||||
Moves.CONSTRICT,
|
MoveId.CONSTRICT,
|
||||||
Moves.BEAT_UP,
|
MoveId.BEAT_UP,
|
||||||
Moves.COIL,
|
MoveId.COIL,
|
||||||
Moves.WRING_OUT,
|
MoveId.WRING_OUT,
|
||||||
Moves.STRING_SHOT,
|
MoveId.STRING_SHOT,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abilities that (loosely) can be used to trap/rob someone
|
* Abilities that (loosely) can be used to trap/rob someone
|
||||||
*/
|
*/
|
||||||
export const EXTORTION_ABILITIES = [
|
export const EXTORTION_ABILITIES = [
|
||||||
Abilities.INTIMIDATE,
|
AbilityId.INTIMIDATE,
|
||||||
Abilities.ARENA_TRAP,
|
AbilityId.ARENA_TRAP,
|
||||||
Abilities.SHADOW_TAG,
|
AbilityId.SHADOW_TAG,
|
||||||
Abilities.SUCTION_CUPS,
|
AbilityId.SUCTION_CUPS,
|
||||||
Abilities.STICKY_HOLD,
|
AbilityId.STICKY_HOLD,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abilities that signify resistance to fire
|
* Abilities that signify resistance to fire
|
||||||
*/
|
*/
|
||||||
export const FIRE_RESISTANT_ABILITIES = [
|
export const FIRE_RESISTANT_ABILITIES = [
|
||||||
Abilities.FLAME_BODY,
|
AbilityId.FLAME_BODY,
|
||||||
Abilities.FLASH_FIRE,
|
AbilityId.FLASH_FIRE,
|
||||||
Abilities.WELL_BAKED_BODY,
|
AbilityId.WELL_BAKED_BODY,
|
||||||
Abilities.HEATPROOF,
|
AbilityId.HEATPROOF,
|
||||||
Abilities.THERMAL_EXCHANGE,
|
AbilityId.THERMAL_EXCHANGE,
|
||||||
Abilities.THICK_FAT,
|
AbilityId.THICK_FAT,
|
||||||
Abilities.WATER_BUBBLE,
|
AbilityId.WATER_BUBBLE,
|
||||||
Abilities.MAGMA_ARMOR,
|
AbilityId.MAGMA_ARMOR,
|
||||||
Abilities.WATER_VEIL,
|
AbilityId.WATER_VEIL,
|
||||||
Abilities.STEAM_ENGINE,
|
AbilityId.STEAM_ENGINE,
|
||||||
Abilities.PRIMORDIAL_SEA,
|
AbilityId.PRIMORDIAL_SEA,
|
||||||
];
|
];
|
||||||
|
@ -51,7 +51,7 @@ function getTextWithDialogueTokens(keyOrString: string): string | null {
|
|||||||
*/
|
*/
|
||||||
export function queueEncounterMessage(contentKey: string): void {
|
export function queueEncounterMessage(contentKey: string): void {
|
||||||
const text: string | null = getEncounterText(contentKey);
|
const text: string | null = getEncounterText(contentKey);
|
||||||
globalScene.queueMessage(text ?? "", null, true);
|
globalScene.phaseManager.queueMessage(text ?? "", null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type Battle from "#app/battle";
|
import type Battle from "#app/battle";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import { BattleType } from "#enums/battle-type";
|
import { BattleType } from "#enums/battle-type";
|
||||||
import { biomeLinks, BiomePoolTier } from "#app/data/balance/biomes";
|
import { biomeLinks, BiomePoolTier } from "#app/data/balance/biomes";
|
||||||
import type MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
|
import type MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
@ -8,9 +8,12 @@ import {
|
|||||||
WEIGHT_INCREMENT_ON_SPAWN_MISS,
|
WEIGHT_INCREMENT_ON_SPAWN_MISS,
|
||||||
} from "#app/data/mystery-encounters/mystery-encounters";
|
} from "#app/data/mystery-encounters/mystery-encounters";
|
||||||
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import type { AiType, PlayerPokemon } from "#app/field/pokemon";
|
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||||
|
import type { AiType } from "#enums/ai-type";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { EnemyPokemon, FieldPosition, PokemonMove } from "#app/field/pokemon";
|
import { EnemyPokemon } from "#app/field/pokemon";
|
||||||
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
|
import { FieldPosition } from "#enums/field-position";
|
||||||
import type { CustomModifierSettings, ModifierType } from "#app/modifier/modifier-type";
|
import type { CustomModifierSettings, ModifierType } from "#app/modifier/modifier-type";
|
||||||
import {
|
import {
|
||||||
getPartyLuckValue,
|
getPartyLuckValue,
|
||||||
@ -20,12 +23,6 @@ import {
|
|||||||
modifierTypes,
|
modifierTypes,
|
||||||
regenerateModifierPoolThresholds,
|
regenerateModifierPoolThresholds,
|
||||||
} from "#app/modifier/modifier-type";
|
} from "#app/modifier/modifier-type";
|
||||||
import {
|
|
||||||
MysteryEncounterBattlePhase,
|
|
||||||
MysteryEncounterBattleStartCleanupPhase,
|
|
||||||
MysteryEncounterPhase,
|
|
||||||
MysteryEncounterRewardsPhase,
|
|
||||||
} from "#app/phases/mystery-encounter-phases";
|
|
||||||
import type PokemonData from "#app/system/pokemon-data";
|
import type PokemonData from "#app/system/pokemon-data";
|
||||||
import type { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import type { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import type { PartyOption, PokemonSelectFilter } from "#app/ui/party-ui-handler";
|
import type { PartyOption, PokemonSelectFilter } from "#app/ui/party-ui-handler";
|
||||||
@ -33,13 +30,14 @@ import { PartyUiMode } from "#app/ui/party-ui-handler";
|
|||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { isNullOrUndefined, randSeedInt, randomString, randSeedItem } from "#app/utils/common";
|
import { isNullOrUndefined, randSeedInt, randomString, randSeedItem } from "#app/utils/common";
|
||||||
import type { BattlerTagType } from "#enums/battler-tag-type";
|
import type { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { Biome } from "#enums/biome";
|
import { BiomeId } from "#enums/biome-id";
|
||||||
import type { TrainerType } from "#enums/trainer-type";
|
import type { TrainerType } from "#enums/trainer-type";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import Trainer, { TrainerVariant } from "#app/field/trainer";
|
import Trainer from "#app/field/trainer";
|
||||||
|
import { TrainerVariant } from "#enums/trainer-variant";
|
||||||
import type { Gender } from "#app/data/gender";
|
import type { Gender } from "#app/data/gender";
|
||||||
import type { Nature } from "#enums/nature";
|
import type { Nature } from "#enums/nature";
|
||||||
import type { Moves } from "#enums/moves";
|
import type { MoveId } from "#enums/move-id";
|
||||||
import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims";
|
import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims";
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
import { Status } from "#app/data/status-effect";
|
import { Status } from "#app/data/status-effect";
|
||||||
@ -50,14 +48,7 @@ import type PokemonSpecies from "#app/data/pokemon-species";
|
|||||||
import type { IEggOptions } from "#app/data/egg";
|
import type { IEggOptions } from "#app/data/egg";
|
||||||
import { Egg } from "#app/data/egg";
|
import { Egg } from "#app/data/egg";
|
||||||
import type { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
import type { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||||
import { MovePhase } from "#app/phases/move-phase";
|
|
||||||
import { EggLapsePhase } from "#app/phases/egg-lapse-phase";
|
|
||||||
import { TrainerVictoryPhase } from "#app/phases/trainer-victory-phase";
|
|
||||||
import { BattleEndPhase } from "#app/phases/battle-end-phase";
|
|
||||||
import { GameOverPhase } from "#app/phases/game-over-phase";
|
|
||||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
|
||||||
import { PartyExpPhase } from "#app/phases/party-exp-phase";
|
|
||||||
import type { Variant } from "#app/sprites/variant";
|
import type { Variant } from "#app/sprites/variant";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
@ -106,7 +97,7 @@ export interface EnemyPokemonConfig {
|
|||||||
level?: number;
|
level?: number;
|
||||||
gender?: Gender;
|
gender?: Gender;
|
||||||
passive?: boolean;
|
passive?: boolean;
|
||||||
moveSet?: Moves[];
|
moveSet?: MoveId[];
|
||||||
nature?: Nature;
|
nature?: Nature;
|
||||||
ivs?: [number, number, number, number, number, number];
|
ivs?: [number, number, number, number, number, number];
|
||||||
shiny?: boolean;
|
shiny?: boolean;
|
||||||
@ -428,7 +419,7 @@ export async function initBattleWithEnemyConfig(partyConfig: EnemyPartyConfig):
|
|||||||
console.log("Moveset:", moveset);
|
console.log("Moveset:", moveset);
|
||||||
});
|
});
|
||||||
|
|
||||||
globalScene.pushPhase(new MysteryEncounterBattlePhase(partyConfig.disableSwitch));
|
globalScene.phaseManager.pushNew("MysteryEncounterBattlePhase", partyConfig.disableSwitch);
|
||||||
|
|
||||||
await Promise.all(loadEnemyAssets);
|
await Promise.all(loadEnemyAssets);
|
||||||
battle.enemyParty.forEach((enemyPokemon_2, e_1) => {
|
battle.enemyParty.forEach((enemyPokemon_2, e_1) => {
|
||||||
@ -460,7 +451,7 @@ export async function initBattleWithEnemyConfig(partyConfig: EnemyPartyConfig):
|
|||||||
* This promise does not need to be awaited on if called in an encounter onInit (will just load lazily)
|
* This promise does not need to be awaited on if called in an encounter onInit (will just load lazily)
|
||||||
* @param moves
|
* @param moves
|
||||||
*/
|
*/
|
||||||
export function loadCustomMovesForEncounter(moves: Moves | Moves[]) {
|
export function loadCustomMovesForEncounter(moves: MoveId | MoveId[]) {
|
||||||
moves = Array.isArray(moves) ? moves : [moves];
|
moves = Array.isArray(moves) ? moves : [moves];
|
||||||
return Promise.all(moves.map(move => initMoveAnim(move))).then(() => loadMoveAnimAssets(moves));
|
return Promise.all(moves.map(move => initMoveAnim(move))).then(() => loadMoveAnimAssets(moves));
|
||||||
}
|
}
|
||||||
@ -480,7 +471,7 @@ export function updatePlayerMoney(changeValue: number, playSound = true, showMes
|
|||||||
}
|
}
|
||||||
if (showMessage) {
|
if (showMessage) {
|
||||||
if (changeValue < 0) {
|
if (changeValue < 0) {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("mysteryEncounterMessages:paid_money", {
|
i18next.t("mysteryEncounterMessages:paid_money", {
|
||||||
amount: -changeValue,
|
amount: -changeValue,
|
||||||
}),
|
}),
|
||||||
@ -488,7 +479,7 @@ export function updatePlayerMoney(changeValue: number, playSound = true, showMes
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
globalScene.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("mysteryEncounterMessages:receive_money", {
|
i18next.t("mysteryEncounterMessages:receive_money", {
|
||||||
amount: changeValue,
|
amount: changeValue,
|
||||||
}),
|
}),
|
||||||
@ -767,9 +758,9 @@ export function setEncounterRewards(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (customShopRewards) {
|
if (customShopRewards) {
|
||||||
globalScene.unshiftPhase(new SelectModifierPhase(0, undefined, customShopRewards));
|
globalScene.phaseManager.unshiftNew("SelectModifierPhase", 0, undefined, customShopRewards);
|
||||||
} else {
|
} else {
|
||||||
globalScene.tryRemovePhase(p => p instanceof SelectModifierPhase);
|
globalScene.phaseManager.tryRemovePhase(p => p.is("MysteryEncounterRewardsPhase"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eggRewards) {
|
if (eggRewards) {
|
||||||
@ -807,7 +798,7 @@ export function setEncounterExp(participantId: number | number[], baseExpValue:
|
|||||||
const participantIds = Array.isArray(participantId) ? participantId : [participantId];
|
const participantIds = Array.isArray(participantId) ? participantId : [participantId];
|
||||||
|
|
||||||
globalScene.currentBattle.mysteryEncounter!.doEncounterExp = () => {
|
globalScene.currentBattle.mysteryEncounter!.doEncounterExp = () => {
|
||||||
globalScene.unshiftPhase(new PartyExpPhase(baseExpValue, useWaveIndex, new Set(participantIds)));
|
globalScene.phaseManager.unshiftNew("PartyExpPhase", baseExpValue, useWaveIndex, new Set(participantIds));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@ -829,7 +820,7 @@ export class OptionSelectSettings {
|
|||||||
* @param optionSelectSettings
|
* @param optionSelectSettings
|
||||||
*/
|
*/
|
||||||
export function initSubsequentOptionSelect(optionSelectSettings: OptionSelectSettings) {
|
export function initSubsequentOptionSelect(optionSelectSettings: OptionSelectSettings) {
|
||||||
globalScene.pushPhase(new MysteryEncounterPhase(optionSelectSettings));
|
globalScene.phaseManager.pushNew("MysteryEncounterPhase", optionSelectSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -843,8 +834,8 @@ export function leaveEncounterWithoutBattle(
|
|||||||
encounterMode: MysteryEncounterMode = MysteryEncounterMode.NO_BATTLE,
|
encounterMode: MysteryEncounterMode = MysteryEncounterMode.NO_BATTLE,
|
||||||
) {
|
) {
|
||||||
globalScene.currentBattle.mysteryEncounter!.encounterMode = encounterMode;
|
globalScene.currentBattle.mysteryEncounter!.encounterMode = encounterMode;
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.clearPhaseQueueSplice();
|
globalScene.phaseManager.clearPhaseQueueSplice();
|
||||||
handleMysteryEncounterVictory(addHealPhase);
|
handleMysteryEncounterVictory(addHealPhase);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -857,8 +848,8 @@ export function handleMysteryEncounterVictory(addHealPhase = false, doNotContinu
|
|||||||
const allowedPkm = globalScene.getPlayerParty().filter(pkm => pkm.isAllowedInBattle());
|
const allowedPkm = globalScene.getPlayerParty().filter(pkm => pkm.isAllowedInBattle());
|
||||||
|
|
||||||
if (allowedPkm.length === 0) {
|
if (allowedPkm.length === 0) {
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.unshiftPhase(new GameOverPhase());
|
globalScene.phaseManager.unshiftNew("GameOverPhase");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -869,8 +860,8 @@ export function handleMysteryEncounterVictory(addHealPhase = false, doNotContinu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (encounter.encounterMode === MysteryEncounterMode.NO_BATTLE) {
|
if (encounter.encounterMode === MysteryEncounterMode.NO_BATTLE) {
|
||||||
globalScene.pushPhase(new MysteryEncounterRewardsPhase(addHealPhase));
|
globalScene.phaseManager.pushNew("MysteryEncounterRewardsPhase", addHealPhase);
|
||||||
globalScene.pushPhase(new EggLapsePhase());
|
globalScene.phaseManager.pushNew("EggLapsePhase");
|
||||||
} else if (
|
} else if (
|
||||||
!globalScene
|
!globalScene
|
||||||
.getEnemyParty()
|
.getEnemyParty()
|
||||||
@ -878,15 +869,15 @@ export function handleMysteryEncounterVictory(addHealPhase = false, doNotContinu
|
|||||||
encounter.encounterMode !== MysteryEncounterMode.TRAINER_BATTLE ? p.isOnField() : !p?.isFainted(true),
|
encounter.encounterMode !== MysteryEncounterMode.TRAINER_BATTLE ? p.isOnField() : !p?.isFainted(true),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
globalScene.pushPhase(new BattleEndPhase(true));
|
globalScene.phaseManager.pushNew("BattleEndPhase", true);
|
||||||
if (encounter.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
if (encounter.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
globalScene.pushPhase(new TrainerVictoryPhase());
|
globalScene.phaseManager.pushNew("TrainerVictoryPhase");
|
||||||
}
|
}
|
||||||
if (globalScene.gameMode.isEndless || !globalScene.gameMode.isWaveFinal(globalScene.currentBattle.waveIndex)) {
|
if (globalScene.gameMode.isEndless || !globalScene.gameMode.isWaveFinal(globalScene.currentBattle.waveIndex)) {
|
||||||
globalScene.pushPhase(new MysteryEncounterRewardsPhase(addHealPhase));
|
globalScene.phaseManager.pushNew("MysteryEncounterRewardsPhase", addHealPhase);
|
||||||
if (!encounter.doContinueEncounter) {
|
if (!encounter.doContinueEncounter) {
|
||||||
// Only lapse eggs once for multi-battle encounters
|
// Only lapse eggs once for multi-battle encounters
|
||||||
globalScene.pushPhase(new EggLapsePhase());
|
globalScene.phaseManager.pushNew("EggLapsePhase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -900,8 +891,8 @@ export function handleMysteryEncounterBattleFailed(addHealPhase = false, doNotCo
|
|||||||
const allowedPkm = globalScene.getPlayerParty().filter(pkm => pkm.isAllowedInBattle());
|
const allowedPkm = globalScene.getPlayerParty().filter(pkm => pkm.isAllowedInBattle());
|
||||||
|
|
||||||
if (allowedPkm.length === 0) {
|
if (allowedPkm.length === 0) {
|
||||||
globalScene.clearPhaseQueue();
|
globalScene.phaseManager.clearPhaseQueue();
|
||||||
globalScene.unshiftPhase(new GameOverPhase());
|
globalScene.phaseManager.unshiftNew("GameOverPhase");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -912,14 +903,14 @@ export function handleMysteryEncounterBattleFailed(addHealPhase = false, doNotCo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (encounter.encounterMode !== MysteryEncounterMode.NO_BATTLE) {
|
if (encounter.encounterMode !== MysteryEncounterMode.NO_BATTLE) {
|
||||||
globalScene.pushPhase(new BattleEndPhase(false));
|
globalScene.phaseManager.pushNew("BattleEndPhase", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.pushPhase(new MysteryEncounterRewardsPhase(addHealPhase));
|
globalScene.phaseManager.pushNew("MysteryEncounterRewardsPhase", addHealPhase);
|
||||||
|
|
||||||
if (!encounter.doContinueEncounter) {
|
if (!encounter.doContinueEncounter) {
|
||||||
// Only lapse eggs once for multi-battle encounters
|
// Only lapse eggs once for multi-battle encounters
|
||||||
globalScene.pushPhase(new EggLapsePhase());
|
globalScene.phaseManager.pushNew("EggLapsePhase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1004,12 +995,19 @@ export function handleMysteryEncounterBattleStartEffects() {
|
|||||||
} else {
|
} else {
|
||||||
source = globalScene.getEnemyField()[0];
|
source = globalScene.getEnemyField()[0];
|
||||||
}
|
}
|
||||||
// @ts-ignore: source cannot be undefined
|
globalScene.phaseManager.pushNew(
|
||||||
globalScene.pushPhase(new MovePhase(source, effect.targets, effect.move, effect.followUp, effect.ignorePp));
|
"MovePhase",
|
||||||
|
// @ts-expect-error: source is guaranteed to be defined
|
||||||
|
source,
|
||||||
|
effect.targets,
|
||||||
|
effect.move,
|
||||||
|
effect.followUp,
|
||||||
|
effect.ignorePp,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pseudo turn end phase to reset flinch states, Endure, etc.
|
// Pseudo turn end phase to reset flinch states, Endure, etc.
|
||||||
globalScene.pushPhase(new MysteryEncounterBattleStartCleanupPhase());
|
globalScene.phaseManager.pushNew("MysteryEncounterBattleStartCleanupPhase");
|
||||||
|
|
||||||
encounter.startOfBattleEffectsComplete = true;
|
encounter.startOfBattleEffectsComplete = true;
|
||||||
}
|
}
|
||||||
@ -1088,16 +1086,16 @@ export function getRandomEncounterSpecies(level: number, isBoss = false, rerollH
|
|||||||
export function calculateMEAggregateStats(baseSpawnWeight: number) {
|
export function calculateMEAggregateStats(baseSpawnWeight: number) {
|
||||||
const numRuns = 1000;
|
const numRuns = 1000;
|
||||||
let run = 0;
|
let run = 0;
|
||||||
const biomes = Object.keys(Biome).filter(key => Number.isNaN(Number(key)));
|
const biomes = Object.keys(BiomeId).filter(key => Number.isNaN(Number(key)));
|
||||||
const alwaysPickTheseBiomes = [
|
const alwaysPickTheseBiomes = [
|
||||||
Biome.ISLAND,
|
BiomeId.ISLAND,
|
||||||
Biome.ABYSS,
|
BiomeId.ABYSS,
|
||||||
Biome.WASTELAND,
|
BiomeId.WASTELAND,
|
||||||
Biome.FAIRY_CAVE,
|
BiomeId.FAIRY_CAVE,
|
||||||
Biome.TEMPLE,
|
BiomeId.TEMPLE,
|
||||||
Biome.LABORATORY,
|
BiomeId.LABORATORY,
|
||||||
Biome.SPACE,
|
BiomeId.SPACE,
|
||||||
Biome.WASTELAND,
|
BiomeId.WASTELAND,
|
||||||
];
|
];
|
||||||
|
|
||||||
const calculateNumEncounters = (): any[] => {
|
const calculateNumEncounters = (): any[] => {
|
||||||
@ -1106,7 +1104,7 @@ export function calculateMEAggregateStats(baseSpawnWeight: number) {
|
|||||||
let mostRecentEncounterWave = 0;
|
let mostRecentEncounterWave = 0;
|
||||||
const encountersByBiome = 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]));
|
const validMEfloorsByBiome = new Map<string, number>(biomes.map(b => [b, 0]));
|
||||||
let currentBiome = Biome.TOWN;
|
let currentBiome = BiomeId.TOWN;
|
||||||
let currentArena = globalScene.newArena(currentBiome);
|
let currentArena = globalScene.newArena(currentBiome);
|
||||||
globalScene.setSeed(randomString(24));
|
globalScene.setSeed(randomString(24));
|
||||||
globalScene.resetSeed();
|
globalScene.resetSeed();
|
||||||
@ -1119,9 +1117,9 @@ export function calculateMEAggregateStats(baseSpawnWeight: number) {
|
|||||||
// New biome
|
// New biome
|
||||||
if (i % 10 === 1) {
|
if (i % 10 === 1) {
|
||||||
if (Array.isArray(biomeLinks[currentBiome])) {
|
if (Array.isArray(biomeLinks[currentBiome])) {
|
||||||
let biomes: Biome[];
|
let biomes: BiomeId[];
|
||||||
globalScene.executeWithSeedOffset(() => {
|
globalScene.executeWithSeedOffset(() => {
|
||||||
biomes = (biomeLinks[currentBiome] as (Biome | [Biome, number])[])
|
biomes = (biomeLinks[currentBiome] as (BiomeId | [BiomeId, number])[])
|
||||||
.filter(b => {
|
.filter(b => {
|
||||||
return !Array.isArray(b) || !randSeedInt(b[1]);
|
return !Array.isArray(b) || !randSeedInt(b[1]);
|
||||||
})
|
})
|
||||||
@ -1136,10 +1134,10 @@ export function calculateMEAggregateStats(baseSpawnWeight: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (biomeLinks.hasOwnProperty(currentBiome)) {
|
} else if (biomeLinks.hasOwnProperty(currentBiome)) {
|
||||||
currentBiome = biomeLinks[currentBiome] as Biome;
|
currentBiome = biomeLinks[currentBiome] as BiomeId;
|
||||||
} else {
|
} else {
|
||||||
if (!(i % 50)) {
|
if (!(i % 50)) {
|
||||||
currentBiome = Biome.END;
|
currentBiome = BiomeId.END;
|
||||||
} else {
|
} else {
|
||||||
currentBiome = globalScene.generateRandomBiome(i);
|
currentBiome = globalScene.generateRandomBiome(i);
|
||||||
}
|
}
|
||||||
@ -1161,7 +1159,7 @@ export function calculateMEAggregateStats(baseSpawnWeight: number) {
|
|||||||
// Otherwise, roll encounter
|
// Otherwise, roll encounter
|
||||||
|
|
||||||
const roll = randSeedInt(256);
|
const roll = randSeedInt(256);
|
||||||
validMEfloorsByBiome.set(Biome[currentBiome], (validMEfloorsByBiome.get(Biome[currentBiome]) ?? 0) + 1);
|
validMEfloorsByBiome.set(BiomeId[currentBiome], (validMEfloorsByBiome.get(BiomeId[currentBiome]) ?? 0) + 1);
|
||||||
|
|
||||||
// If total number of encounters is lower than expected for the run, slightly favor a new encounter
|
// If total number of encounters is lower than expected for the run, slightly favor a new encounter
|
||||||
// Do the reverse as well
|
// Do the reverse as well
|
||||||
@ -1197,7 +1195,7 @@ export function calculateMEAggregateStats(baseSpawnWeight: number) {
|
|||||||
: tierValue > rareThreshold
|
: tierValue > rareThreshold
|
||||||
? ++numEncounters[2]
|
? ++numEncounters[2]
|
||||||
: ++numEncounters[3];
|
: ++numEncounters[3];
|
||||||
encountersByBiome.set(Biome[currentBiome], (encountersByBiome.get(Biome[currentBiome]) ?? 0) + 1);
|
encountersByBiome.set(BiomeId[currentBiome], (encountersByBiome.get(BiomeId[currentBiome]) ?? 0) + 1);
|
||||||
} else {
|
} else {
|
||||||
encounterRate += WEIGHT_INCREMENT_ON_SPAWN_MISS;
|
encounterRate += WEIGHT_INCREMENT_ON_SPAWN_MISS;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import { achvs } from "#app/system/achv";
|
|||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { PartyOption } from "#app/ui/party-ui-handler";
|
import type { PartyOption } from "#app/ui/party-ui-handler";
|
||||||
import { PartyUiMode } from "#app/ui/party-ui-handler";
|
import { PartyUiMode } from "#app/ui/party-ui-handler";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import type { PokemonType } from "#enums/pokemon-type";
|
import type { PokemonType } from "#enums/pokemon-type";
|
||||||
import type PokemonSpecies from "#app/data/pokemon-species";
|
import type PokemonSpecies from "#app/data/pokemon-species";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
@ -32,10 +32,9 @@ import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
|||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { Gender } from "#app/data/gender";
|
import { Gender } from "#app/data/gender";
|
||||||
import type { PermanentStat } from "#enums/stat";
|
import type { PermanentStat } from "#enums/stat";
|
||||||
import { VictoryPhase } from "#app/phases/victory-phase";
|
|
||||||
import { SummaryUiMode } from "#app/ui/summary-ui-handler";
|
import { SummaryUiMode } from "#app/ui/summary-ui-handler";
|
||||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import type { Abilities } from "#enums/abilities";
|
import type { AbilityId } from "#enums/ability-id";
|
||||||
import type { PokeballType } from "#enums/pokeball";
|
import type { PokeballType } from "#enums/pokeball";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
|
|
||||||
@ -51,7 +50,7 @@ export const STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER = 1;
|
|||||||
* @param variant
|
* @param variant
|
||||||
*/
|
*/
|
||||||
export function getSpriteKeysFromSpecies(
|
export function getSpriteKeysFromSpecies(
|
||||||
species: Species,
|
species: SpeciesId,
|
||||||
female?: boolean,
|
female?: boolean,
|
||||||
formIndex?: number,
|
formIndex?: number,
|
||||||
shiny?: boolean,
|
shiny?: boolean,
|
||||||
@ -247,17 +246,17 @@ export function getHighestStatTotalPlayerPokemon(isAllowed = false, isFainted =
|
|||||||
*/
|
*/
|
||||||
export function getRandomSpeciesByStarterCost(
|
export function getRandomSpeciesByStarterCost(
|
||||||
starterTiers: number | [number, number],
|
starterTiers: number | [number, number],
|
||||||
excludedSpecies?: Species[],
|
excludedSpecies?: SpeciesId[],
|
||||||
types?: PokemonType[],
|
types?: PokemonType[],
|
||||||
allowSubLegendary = true,
|
allowSubLegendary = true,
|
||||||
allowLegendary = true,
|
allowLegendary = true,
|
||||||
allowMythical = true,
|
allowMythical = true,
|
||||||
): Species {
|
): SpeciesId {
|
||||||
let min = Array.isArray(starterTiers) ? starterTiers[0] : starterTiers;
|
let min = Array.isArray(starterTiers) ? starterTiers[0] : starterTiers;
|
||||||
let max = Array.isArray(starterTiers) ? starterTiers[1] : starterTiers;
|
let max = Array.isArray(starterTiers) ? starterTiers[1] : starterTiers;
|
||||||
|
|
||||||
let filteredSpecies: [PokemonSpecies, number][] = Object.keys(speciesStarterCosts)
|
let filteredSpecies: [PokemonSpecies, number][] = Object.keys(speciesStarterCosts)
|
||||||
.map(s => [Number.parseInt(s) as Species, speciesStarterCosts[s] as number])
|
.map(s => [Number.parseInt(s) as SpeciesId, speciesStarterCosts[s] as number])
|
||||||
.filter(s => {
|
.filter(s => {
|
||||||
const pokemonSpecies = getPokemonSpecies(s[0]);
|
const pokemonSpecies = getPokemonSpecies(s[0]);
|
||||||
return (
|
return (
|
||||||
@ -294,7 +293,7 @@ export function getRandomSpeciesByStarterCost(
|
|||||||
return Phaser.Math.RND.shuffle(tryFilterStarterTiers)[index][0].speciesId;
|
return Phaser.Math.RND.shuffle(tryFilterStarterTiers)[index][0].speciesId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Species.BULBASAUR;
|
return SpeciesId.BULBASAUR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -675,7 +674,7 @@ export async function catchPokemon(
|
|||||||
if (!globalScene.getEnemyParty().some(p => p.id === pokemon.id)) {
|
if (!globalScene.getEnemyParty().some(p => p.id === pokemon.id)) {
|
||||||
globalScene.getEnemyParty().push(pokemon);
|
globalScene.getEnemyParty().push(pokemon);
|
||||||
}
|
}
|
||||||
globalScene.unshiftPhase(new VictoryPhase(pokemon.id, true));
|
globalScene.phaseManager.unshiftNew("VictoryPhase", pokemon.id, true);
|
||||||
globalScene.pokemonInfoContainer.hide();
|
globalScene.pokemonInfoContainer.hide();
|
||||||
if (pokeball) {
|
if (pokeball) {
|
||||||
removePb(pokeball);
|
removePb(pokeball);
|
||||||
@ -903,34 +902,34 @@ export function doPlayerFlee(pokemon: EnemyPokemon): Promise<void> {
|
|||||||
/**
|
/**
|
||||||
* Bug Species and their corresponding weights
|
* Bug Species and their corresponding weights
|
||||||
*/
|
*/
|
||||||
const GOLDEN_BUG_NET_SPECIES_POOL: [Species, number][] = [
|
const GOLDEN_BUG_NET_SPECIES_POOL: [SpeciesId, number][] = [
|
||||||
[Species.SCYTHER, 40],
|
[SpeciesId.SCYTHER, 40],
|
||||||
[Species.SCIZOR, 40],
|
[SpeciesId.SCIZOR, 40],
|
||||||
[Species.KLEAVOR, 40],
|
[SpeciesId.KLEAVOR, 40],
|
||||||
[Species.PINSIR, 40],
|
[SpeciesId.PINSIR, 40],
|
||||||
[Species.HERACROSS, 40],
|
[SpeciesId.HERACROSS, 40],
|
||||||
[Species.YANMA, 40],
|
[SpeciesId.YANMA, 40],
|
||||||
[Species.YANMEGA, 40],
|
[SpeciesId.YANMEGA, 40],
|
||||||
[Species.SHUCKLE, 40],
|
[SpeciesId.SHUCKLE, 40],
|
||||||
[Species.ANORITH, 40],
|
[SpeciesId.ANORITH, 40],
|
||||||
[Species.ARMALDO, 40],
|
[SpeciesId.ARMALDO, 40],
|
||||||
[Species.ESCAVALIER, 40],
|
[SpeciesId.ESCAVALIER, 40],
|
||||||
[Species.ACCELGOR, 40],
|
[SpeciesId.ACCELGOR, 40],
|
||||||
[Species.JOLTIK, 40],
|
[SpeciesId.JOLTIK, 40],
|
||||||
[Species.GALVANTULA, 40],
|
[SpeciesId.GALVANTULA, 40],
|
||||||
[Species.DURANT, 40],
|
[SpeciesId.DURANT, 40],
|
||||||
[Species.LARVESTA, 40],
|
[SpeciesId.LARVESTA, 40],
|
||||||
[Species.VOLCARONA, 40],
|
[SpeciesId.VOLCARONA, 40],
|
||||||
[Species.DEWPIDER, 40],
|
[SpeciesId.DEWPIDER, 40],
|
||||||
[Species.ARAQUANID, 40],
|
[SpeciesId.ARAQUANID, 40],
|
||||||
[Species.WIMPOD, 40],
|
[SpeciesId.WIMPOD, 40],
|
||||||
[Species.GOLISOPOD, 40],
|
[SpeciesId.GOLISOPOD, 40],
|
||||||
[Species.SIZZLIPEDE, 40],
|
[SpeciesId.SIZZLIPEDE, 40],
|
||||||
[Species.CENTISKORCH, 40],
|
[SpeciesId.CENTISKORCH, 40],
|
||||||
[Species.NYMBLE, 40],
|
[SpeciesId.NYMBLE, 40],
|
||||||
[Species.LOKIX, 40],
|
[SpeciesId.LOKIX, 40],
|
||||||
[Species.BUZZWOLE, 1],
|
[SpeciesId.BUZZWOLE, 1],
|
||||||
[Species.PHEROMOSA, 1],
|
[SpeciesId.PHEROMOSA, 1],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -951,7 +950,7 @@ export function getGoldenBugNetSpecies(level: number): PokemonSpecies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Defaults to Scyther
|
// Defaults to Scyther
|
||||||
return getPokemonSpecies(Species.SCYTHER);
|
return getPokemonSpecies(SpeciesId.SCYTHER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1024,7 +1023,7 @@ export function isPokemonValidForEncounterOptionSelection(
|
|||||||
* Permanently overrides the ability (not passive) of a pokemon.
|
* Permanently overrides the ability (not passive) of a pokemon.
|
||||||
* If the pokemon is a fusion, instead overrides the fused pokemon's ability.
|
* If the pokemon is a fusion, instead overrides the fused pokemon's ability.
|
||||||
*/
|
*/
|
||||||
export function applyAbilityOverrideToPokemon(pokemon: Pokemon, ability: Abilities) {
|
export function applyAbilityOverrideToPokemon(pokemon: Pokemon, ability: AbilityId) {
|
||||||
if (pokemon.isFusion()) {
|
if (pokemon.isFusion()) {
|
||||||
if (!pokemon.fusionCustomPokemonData) {
|
if (!pokemon.fusionCustomPokemonData) {
|
||||||
pokemon.fusionCustomPokemonData = new CustomPokemonData();
|
pokemon.fusionCustomPokemonData = new CustomPokemonData();
|
||||||
|
File diff suppressed because it is too large
Load Diff
348
src/data/pokemon-forms/form-change-triggers.ts
Normal file
348
src/data/pokemon-forms/form-change-triggers.ts
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
import i18next from "i18next";
|
||||||
|
import type { Constructor } from "#app/utils/common";
|
||||||
|
import type { TimeOfDay } from "#enums/time-of-day";
|
||||||
|
import type Pokemon from "#app/field/pokemon";
|
||||||
|
import type { SpeciesFormChange } from "#app/data/pokemon-forms";
|
||||||
|
import type { PokemonFormChangeItemModifier } from "#app/modifier/modifier";
|
||||||
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { FormChangeItem } from "#enums/form-change-item";
|
||||||
|
import { AbilityId } from "#enums/ability-id";
|
||||||
|
import { Challenges } from "#enums/challenges";
|
||||||
|
import { MoveId } from "#enums/move-id";
|
||||||
|
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||||
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
|
import { WeatherType } from "#enums/weather-type";
|
||||||
|
|
||||||
|
export abstract class SpeciesFormChangeTrigger {
|
||||||
|
public description = "";
|
||||||
|
|
||||||
|
canChange(_pokemon: Pokemon): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasTriggerType(triggerType: Constructor<SpeciesFormChangeTrigger>): boolean {
|
||||||
|
return this instanceof triggerType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SpeciesFormChangeManualTrigger extends SpeciesFormChangeTrigger {}
|
||||||
|
|
||||||
|
export class SpeciesFormChangeAbilityTrigger extends SpeciesFormChangeTrigger {
|
||||||
|
public description: string = i18next.t("pokemonEvolutions:Forms.ability");
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SpeciesFormChangeCompoundTrigger {
|
||||||
|
public description = "";
|
||||||
|
public triggers: SpeciesFormChangeTrigger[];
|
||||||
|
|
||||||
|
constructor(...triggers: SpeciesFormChangeTrigger[]) {
|
||||||
|
this.triggers = triggers;
|
||||||
|
this.description = this.triggers
|
||||||
|
.filter(trigger => trigger?.description?.length > 0)
|
||||||
|
.map(trigger => trigger.description)
|
||||||
|
.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
canChange(pokemon: Pokemon): boolean {
|
||||||
|
for (const trigger of this.triggers) {
|
||||||
|
if (!trigger.canChange(pokemon)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasTriggerType(triggerType: Constructor<SpeciesFormChangeTrigger>): boolean {
|
||||||
|
return !!this.triggers.find(t => t.hasTriggerType(triggerType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SpeciesFormChangeItemTrigger extends SpeciesFormChangeTrigger {
|
||||||
|
public item: FormChangeItem;
|
||||||
|
public active: boolean;
|
||||||
|
|
||||||
|
constructor(item: FormChangeItem, active = true) {
|
||||||
|
super();
|
||||||
|
this.item = item;
|
||||||
|
this.active = active;
|
||||||
|
this.description = this.active
|
||||||
|
? i18next.t("pokemonEvolutions:Forms.item", {
|
||||||
|
item: i18next.t(`modifierType:FormChangeItem.${FormChangeItem[this.item]}`),
|
||||||
|
})
|
||||||
|
: i18next.t("pokemonEvolutions:Forms.deactivateItem", {
|
||||||
|
item: i18next.t(`modifierType:FormChangeItem.${FormChangeItem[this.item]}`),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
canChange(pokemon: Pokemon): boolean {
|
||||||
|
return !!globalScene.findModifier(r => {
|
||||||
|
// Assume that if m has the `formChangeItem` property, then it is a PokemonFormChangeItemModifier
|
||||||
|
const m = r as PokemonFormChangeItemModifier;
|
||||||
|
return (
|
||||||
|
"formChangeItem" in m &&
|
||||||
|
m.pokemonId === pokemon.id &&
|
||||||
|
m.formChangeItem === this.item &&
|
||||||
|
m.active === this.active
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SpeciesFormChangeTimeOfDayTrigger extends SpeciesFormChangeTrigger {
|
||||||
|
public timesOfDay: TimeOfDay[];
|
||||||
|
|
||||||
|
constructor(...timesOfDay: TimeOfDay[]) {
|
||||||
|
super();
|
||||||
|
this.timesOfDay = timesOfDay;
|
||||||
|
this.description = i18next.t("pokemonEvolutions:Forms.timeOfDay");
|
||||||
|
}
|
||||||
|
|
||||||
|
canChange(_pokemon: Pokemon): boolean {
|
||||||
|
return this.timesOfDay.indexOf(globalScene.arena.getTimeOfDay()) > -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class SpeciesFormChangeActiveTrigger extends SpeciesFormChangeTrigger {
|
||||||
|
public active: boolean;
|
||||||
|
|
||||||
|
constructor(active = false) {
|
||||||
|
super();
|
||||||
|
this.active = active;
|
||||||
|
this.description = this.active
|
||||||
|
? i18next.t("pokemonEvolutions:Forms.enter")
|
||||||
|
: i18next.t("pokemonEvolutions:Forms.leave");
|
||||||
|
}
|
||||||
|
|
||||||
|
canChange(pokemon: Pokemon): boolean {
|
||||||
|
return pokemon.isActive(true) === this.active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SpeciesFormChangeStatusEffectTrigger extends SpeciesFormChangeTrigger {
|
||||||
|
public statusEffects: StatusEffect[];
|
||||||
|
public invert: boolean;
|
||||||
|
|
||||||
|
constructor(statusEffects: StatusEffect | StatusEffect[], invert = false) {
|
||||||
|
super();
|
||||||
|
if (!Array.isArray(statusEffects)) {
|
||||||
|
statusEffects = [statusEffects];
|
||||||
|
}
|
||||||
|
this.statusEffects = statusEffects;
|
||||||
|
this.invert = invert;
|
||||||
|
// this.description = i18next.t("pokemonEvolutions:Forms.statusEffect");
|
||||||
|
}
|
||||||
|
|
||||||
|
canChange(pokemon: Pokemon): boolean {
|
||||||
|
return this.statusEffects.indexOf(pokemon.status?.effect || StatusEffect.NONE) > -1 !== this.invert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SpeciesFormChangeMoveLearnedTrigger extends SpeciesFormChangeTrigger {
|
||||||
|
public move: MoveId;
|
||||||
|
public known: boolean;
|
||||||
|
|
||||||
|
constructor(move: MoveId, known = true) {
|
||||||
|
super();
|
||||||
|
this.move = move;
|
||||||
|
this.known = known;
|
||||||
|
const moveKey = MoveId[this.move]
|
||||||
|
.split("_")
|
||||||
|
.filter(f => f)
|
||||||
|
.map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()))
|
||||||
|
.join("") as unknown as string;
|
||||||
|
this.description = known
|
||||||
|
? i18next.t("pokemonEvolutions:Forms.moveLearned", {
|
||||||
|
move: i18next.t(`move:${moveKey}.name`),
|
||||||
|
})
|
||||||
|
: i18next.t("pokemonEvolutions:Forms.moveForgotten", {
|
||||||
|
move: i18next.t(`move:${moveKey}.name`),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
canChange(pokemon: Pokemon): boolean {
|
||||||
|
return !!pokemon.moveset.filter(m => m.moveId === this.move).length === this.known;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class SpeciesFormChangeMoveTrigger extends SpeciesFormChangeTrigger {
|
||||||
|
public movePredicate: (m: MoveId) => boolean;
|
||||||
|
public used: boolean;
|
||||||
|
|
||||||
|
constructor(move: MoveId | ((m: MoveId) => boolean), used = true) {
|
||||||
|
super();
|
||||||
|
this.movePredicate = typeof move === "function" ? move : (m: MoveId) => m === move;
|
||||||
|
this.used = used;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SpeciesFormChangePreMoveTrigger extends SpeciesFormChangeMoveTrigger {
|
||||||
|
description = i18next.t("pokemonEvolutions:Forms.preMove");
|
||||||
|
canChange(pokemon: Pokemon): boolean {
|
||||||
|
const command = globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()];
|
||||||
|
return !!command?.move && this.movePredicate(command.move.move) === this.used;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SpeciesFormChangePostMoveTrigger extends SpeciesFormChangeMoveTrigger {
|
||||||
|
description = i18next.t("pokemonEvolutions:Forms.postMove");
|
||||||
|
canChange(pokemon: Pokemon): boolean {
|
||||||
|
return (
|
||||||
|
pokemon.summonData && !!pokemon.getLastXMoves(1).filter(m => this.movePredicate(m.move)).length === this.used
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MeloettaFormChangePostMoveTrigger extends SpeciesFormChangePostMoveTrigger {
|
||||||
|
override canChange(pokemon: Pokemon): boolean {
|
||||||
|
if (globalScene.gameMode.hasChallenge(Challenges.SINGLE_TYPE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Meloetta will not transform if it has the ability Sheer Force when using Relic Song
|
||||||
|
if (pokemon.hasAbility(AbilityId.SHEER_FORCE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return super.canChange(pokemon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SpeciesDefaultFormMatchTrigger extends SpeciesFormChangeTrigger {
|
||||||
|
private formKey: string;
|
||||||
|
|
||||||
|
constructor(formKey: string) {
|
||||||
|
super();
|
||||||
|
this.formKey = formKey;
|
||||||
|
this.description = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
canChange(pokemon: Pokemon): boolean {
|
||||||
|
return (
|
||||||
|
this.formKey ===
|
||||||
|
pokemon.species.forms[globalScene.getSpeciesFormIndex(pokemon.species, pokemon.gender, pokemon.getNature(), true)]
|
||||||
|
.formKey
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used for triggering form changes based on the user's Tera type.
|
||||||
|
* Used by Ogerpon and Terapagos.
|
||||||
|
*/
|
||||||
|
export class SpeciesFormChangeTeraTrigger extends SpeciesFormChangeTrigger {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used for triggering form changes based on the user's lapsed Tera type.
|
||||||
|
* Used by Ogerpon and Terapagos.
|
||||||
|
*/
|
||||||
|
export class SpeciesFormChangeLapseTeraTrigger extends SpeciesFormChangeTrigger {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used for triggering form changes based on weather.
|
||||||
|
* Used by Castform and Cherrim.
|
||||||
|
*/
|
||||||
|
export class SpeciesFormChangeWeatherTrigger extends SpeciesFormChangeTrigger {
|
||||||
|
/** The ability that triggers the form change */
|
||||||
|
public ability: AbilityId;
|
||||||
|
/** The list of weathers that trigger the form change */
|
||||||
|
public weathers: WeatherType[];
|
||||||
|
|
||||||
|
constructor(ability: AbilityId, weathers: WeatherType[]) {
|
||||||
|
super();
|
||||||
|
this.ability = ability;
|
||||||
|
this.weathers = weathers;
|
||||||
|
this.description = i18next.t("pokemonEvolutions:Forms.weather");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the Pokemon has the required ability and is in the correct weather while
|
||||||
|
* the weather or ability is also not suppressed.
|
||||||
|
* @param pokemon - The pokemon that is trying to do the form change
|
||||||
|
* @returns `true` if the Pokemon can change forms, `false` otherwise
|
||||||
|
*/
|
||||||
|
canChange(pokemon: Pokemon): boolean {
|
||||||
|
const currentWeather = globalScene.arena.weather?.weatherType ?? WeatherType.NONE;
|
||||||
|
const isWeatherSuppressed = globalScene.arena.weather?.isEffectSuppressed();
|
||||||
|
const isAbilitySuppressed = pokemon.summonData.abilitySuppressed;
|
||||||
|
|
||||||
|
return (
|
||||||
|
!isAbilitySuppressed &&
|
||||||
|
!isWeatherSuppressed &&
|
||||||
|
pokemon.hasAbility(this.ability) &&
|
||||||
|
this.weathers.includes(currentWeather)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used for reverting to the original form when the weather runs out
|
||||||
|
* or when the user loses the ability/is suppressed.
|
||||||
|
* Used by Castform and Cherrim.
|
||||||
|
*/
|
||||||
|
export class SpeciesFormChangeRevertWeatherFormTrigger extends SpeciesFormChangeTrigger {
|
||||||
|
/** The ability that triggers the form change*/
|
||||||
|
public ability: AbilityId;
|
||||||
|
/** The list of weathers that will also trigger a form change to original form */
|
||||||
|
public weathers: WeatherType[];
|
||||||
|
|
||||||
|
constructor(ability: AbilityId, weathers: WeatherType[]) {
|
||||||
|
super();
|
||||||
|
this.ability = ability;
|
||||||
|
this.weathers = weathers;
|
||||||
|
this.description = i18next.t("pokemonEvolutions:Forms.weatherRevert");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the Pokemon has the required ability and the weather is one that will revert
|
||||||
|
* the Pokemon to its original form or the weather or ability is suppressed
|
||||||
|
* @param {Pokemon} pokemon the pokemon that is trying to do the form change
|
||||||
|
* @returns `true` if the Pokemon will revert to its original form, `false` otherwise
|
||||||
|
*/
|
||||||
|
canChange(pokemon: Pokemon): boolean {
|
||||||
|
if (pokemon.hasAbility(this.ability, false, true)) {
|
||||||
|
const currentWeather = globalScene.arena.weather?.weatherType ?? WeatherType.NONE;
|
||||||
|
const isWeatherSuppressed = globalScene.arena.weather?.isEffectSuppressed();
|
||||||
|
const isAbilitySuppressed = pokemon.summonData.abilitySuppressed;
|
||||||
|
const summonDataAbility = pokemon.summonData.ability;
|
||||||
|
const isAbilityChanged = summonDataAbility !== this.ability && summonDataAbility !== AbilityId.NONE;
|
||||||
|
|
||||||
|
if (this.weathers.includes(currentWeather) || isWeatherSuppressed || isAbilitySuppressed || isAbilityChanged) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSpeciesFormChangeMessage(pokemon: Pokemon, formChange: SpeciesFormChange, preName: string): string {
|
||||||
|
const isMega = formChange.formKey.indexOf(SpeciesFormKey.MEGA) > -1;
|
||||||
|
const isGmax = formChange.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1;
|
||||||
|
const isEmax = formChange.formKey.indexOf(SpeciesFormKey.ETERNAMAX) > -1;
|
||||||
|
const isRevert = !isMega && formChange.formKey === pokemon.species.forms[0].formKey;
|
||||||
|
if (isMega) {
|
||||||
|
return i18next.t("battlePokemonForm:megaChange", {
|
||||||
|
preName,
|
||||||
|
pokemonName: pokemon.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (isGmax) {
|
||||||
|
return i18next.t("battlePokemonForm:gigantamaxChange", {
|
||||||
|
preName,
|
||||||
|
pokemonName: pokemon.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (isEmax) {
|
||||||
|
return i18next.t("battlePokemonForm:eternamaxChange", {
|
||||||
|
preName,
|
||||||
|
pokemonName: pokemon.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (isRevert) {
|
||||||
|
return i18next.t("battlePokemonForm:revertChange", {
|
||||||
|
pokemonName: getPokemonNameWithAffix(pokemon),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (pokemon.getAbility().id === AbilityId.DISGUISE) {
|
||||||
|
return i18next.t("battlePokemonForm:disguiseChange");
|
||||||
|
}
|
||||||
|
return i18next.t("battlePokemonForm:formChange", { preName });
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,7 @@
|
|||||||
import type Pokemon from "../field/pokemon";
|
import type Pokemon from "../field/pokemon";
|
||||||
import type Move from "./moves/move";
|
import type Move from "./moves/move";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { ProtectAttr } from "./moves/move";
|
import type { BattlerIndex } from "#enums/battler-index";
|
||||||
import type { BattlerIndex } from "#app/battle";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export enum TerrainType {
|
export enum TerrainType {
|
||||||
@ -55,7 +54,7 @@ export class Terrain {
|
|||||||
isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move): boolean {
|
isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move): boolean {
|
||||||
switch (this.terrainType) {
|
switch (this.terrainType) {
|
||||||
case TerrainType.PSYCHIC:
|
case TerrainType.PSYCHIC:
|
||||||
if (!move.hasAttr(ProtectAttr)) {
|
if (!move.hasAttr("ProtectAttr")) {
|
||||||
// Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain
|
// Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain
|
||||||
return (
|
return (
|
||||||
move.getPriority(user) > 0 &&
|
move.getPriority(user) > 0 &&
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { startingWave } from "#app/starting-wave";
|
import { startingWave } from "#app/starting-wave";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import { GameModes } from "#app/game-mode";
|
import { GameModes } from "#enums/game-modes";
|
||||||
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
||||||
|
|
||||||
export class TrainerPartyTemplate {
|
export class TrainerPartyTemplate {
|
||||||
|
@ -1,438 +1,443 @@
|
|||||||
import type { TrainerTierPools } from "#app/data/trainers/typedefs";
|
import type { TrainerTierPools } from "#app/@types/trainer-funcs";
|
||||||
import { TrainerPoolTier } from "#enums/trainer-pool-tier";
|
import { TrainerPoolTier } from "#enums/trainer-pool-tier";
|
||||||
import { Species } from "#enums/species";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
|
||||||
/** Team Rocket's admin trainer pool. */
|
/** Team Rocket's admin trainer pool. */
|
||||||
const ROCKET: TrainerTierPools = {
|
const ROCKET: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.RATTATA,
|
SpeciesId.RATTATA,
|
||||||
Species.SPEAROW,
|
SpeciesId.SPEAROW,
|
||||||
Species.EKANS,
|
SpeciesId.EKANS,
|
||||||
Species.VILEPLUME,
|
SpeciesId.VILEPLUME,
|
||||||
Species.DIGLETT,
|
SpeciesId.DIGLETT,
|
||||||
Species.GROWLITHE,
|
SpeciesId.GROWLITHE,
|
||||||
Species.GRIMER,
|
SpeciesId.GRIMER,
|
||||||
Species.DROWZEE,
|
SpeciesId.DROWZEE,
|
||||||
Species.VOLTORB,
|
SpeciesId.VOLTORB,
|
||||||
Species.EXEGGCUTE,
|
SpeciesId.EXEGGCUTE,
|
||||||
Species.CUBONE,
|
SpeciesId.CUBONE,
|
||||||
Species.KOFFING,
|
SpeciesId.KOFFING,
|
||||||
Species.MAGIKARP,
|
SpeciesId.MAGIKARP,
|
||||||
Species.ZUBAT,
|
SpeciesId.ZUBAT,
|
||||||
Species.ONIX,
|
SpeciesId.ONIX,
|
||||||
Species.HOUNDOUR,
|
SpeciesId.HOUNDOUR,
|
||||||
Species.MURKROW,
|
SpeciesId.MURKROW,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.ABRA,
|
SpeciesId.ABRA,
|
||||||
Species.GASTLY,
|
SpeciesId.GASTLY,
|
||||||
Species.OMANYTE,
|
SpeciesId.OMANYTE,
|
||||||
Species.KABUTO,
|
SpeciesId.KABUTO,
|
||||||
Species.PORYGON,
|
SpeciesId.PORYGON,
|
||||||
Species.MANKEY,
|
SpeciesId.MANKEY,
|
||||||
Species.SCYTHER,
|
SpeciesId.SCYTHER,
|
||||||
Species.ELEKID,
|
SpeciesId.ELEKID,
|
||||||
Species.MAGBY,
|
SpeciesId.MAGBY,
|
||||||
Species.ALOLA_SANDSHREW,
|
SpeciesId.ALOLA_SANDSHREW,
|
||||||
Species.ALOLA_MEOWTH,
|
SpeciesId.ALOLA_MEOWTH,
|
||||||
Species.ALOLA_GEODUDE,
|
SpeciesId.ALOLA_GEODUDE,
|
||||||
Species.ALOLA_GRIMER,
|
SpeciesId.ALOLA_GRIMER,
|
||||||
Species.PALDEA_TAUROS,
|
SpeciesId.PALDEA_TAUROS,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.DRATINI, Species.LARVITAR],
|
[TrainerPoolTier.RARE]: [SpeciesId.DRATINI, SpeciesId.LARVITAR],
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Team Magma's admin trainer pool */
|
/** Team Magma's admin trainer pool */
|
||||||
const MAGMA: TrainerTierPools = {
|
const MAGMA: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.DIGLETT,
|
SpeciesId.DIGLETT,
|
||||||
Species.GROWLITHE,
|
SpeciesId.GROWLITHE,
|
||||||
Species.VULPIX,
|
SpeciesId.VULPIX,
|
||||||
Species.KOFFING,
|
SpeciesId.KOFFING,
|
||||||
Species.RHYHORN,
|
SpeciesId.RHYHORN,
|
||||||
Species.SLUGMA,
|
SpeciesId.SLUGMA,
|
||||||
Species.HOUNDOUR,
|
SpeciesId.HOUNDOUR,
|
||||||
Species.POOCHYENA,
|
SpeciesId.POOCHYENA,
|
||||||
Species.TORKOAL,
|
SpeciesId.TORKOAL,
|
||||||
Species.ZANGOOSE,
|
SpeciesId.ZANGOOSE,
|
||||||
Species.SOLROCK,
|
SpeciesId.SOLROCK,
|
||||||
Species.BALTOY,
|
SpeciesId.BALTOY,
|
||||||
Species.ROLYCOLY,
|
SpeciesId.ROLYCOLY,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.MAGBY,
|
SpeciesId.MAGBY,
|
||||||
Species.TRAPINCH,
|
SpeciesId.TRAPINCH,
|
||||||
Species.LILEEP,
|
SpeciesId.LILEEP,
|
||||||
Species.ANORITH,
|
SpeciesId.ANORITH,
|
||||||
Species.GOLETT,
|
SpeciesId.GOLETT,
|
||||||
Species.FLETCHLING,
|
SpeciesId.FLETCHLING,
|
||||||
Species.SALANDIT,
|
SpeciesId.SALANDIT,
|
||||||
Species.TURTONATOR,
|
SpeciesId.TURTONATOR,
|
||||||
Species.TOEDSCOOL,
|
SpeciesId.TOEDSCOOL,
|
||||||
Species.CAPSAKID,
|
SpeciesId.CAPSAKID,
|
||||||
Species.HISUI_GROWLITHE,
|
SpeciesId.HISUI_GROWLITHE,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.CHARCADET, Species.ARON],
|
[TrainerPoolTier.RARE]: [SpeciesId.CHARCADET, SpeciesId.ARON],
|
||||||
};
|
};
|
||||||
|
|
||||||
const AQUA: TrainerTierPools = {
|
const AQUA: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.TENTACOOL,
|
SpeciesId.TENTACOOL,
|
||||||
Species.GRIMER,
|
SpeciesId.GRIMER,
|
||||||
Species.AZURILL,
|
SpeciesId.AZURILL,
|
||||||
Species.CHINCHOU,
|
SpeciesId.CHINCHOU,
|
||||||
Species.REMORAID,
|
SpeciesId.REMORAID,
|
||||||
Species.POOCHYENA,
|
SpeciesId.POOCHYENA,
|
||||||
Species.LOTAD,
|
SpeciesId.LOTAD,
|
||||||
Species.WINGULL,
|
SpeciesId.WINGULL,
|
||||||
Species.WAILMER,
|
SpeciesId.WAILMER,
|
||||||
Species.SEVIPER,
|
SpeciesId.SEVIPER,
|
||||||
Species.BARBOACH,
|
SpeciesId.BARBOACH,
|
||||||
Species.CORPHISH,
|
SpeciesId.CORPHISH,
|
||||||
Species.SPHEAL,
|
SpeciesId.SPHEAL,
|
||||||
Species.CLAMPERL,
|
SpeciesId.CLAMPERL,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.MANTYKE,
|
SpeciesId.MANTYKE,
|
||||||
Species.HORSEA,
|
SpeciesId.HORSEA,
|
||||||
Species.FEEBAS,
|
SpeciesId.FEEBAS,
|
||||||
Species.TYMPOLE,
|
SpeciesId.TYMPOLE,
|
||||||
Species.SKRELP,
|
SpeciesId.SKRELP,
|
||||||
Species.WIMPOD,
|
SpeciesId.WIMPOD,
|
||||||
Species.DHELMISE,
|
SpeciesId.DHELMISE,
|
||||||
Species.ARROKUDA,
|
SpeciesId.ARROKUDA,
|
||||||
Species.CLOBBOPUS,
|
SpeciesId.CLOBBOPUS,
|
||||||
Species.HISUI_QWILFISH,
|
SpeciesId.HISUI_QWILFISH,
|
||||||
Species.WIGLETT,
|
SpeciesId.WIGLETT,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.BASCULEGION, Species.DONDOZO],
|
[TrainerPoolTier.RARE]: [SpeciesId.BASCULEGION, SpeciesId.DONDOZO],
|
||||||
};
|
};
|
||||||
|
|
||||||
const GALACTIC: TrainerTierPools = {
|
const GALACTIC: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.ZUBAT,
|
SpeciesId.ZUBAT,
|
||||||
Species.MAGNEMITE,
|
SpeciesId.MAGNEMITE,
|
||||||
Species.RHYHORN,
|
SpeciesId.RHYHORN,
|
||||||
Species.TANGELA,
|
SpeciesId.TANGELA,
|
||||||
Species.LICKITUNG,
|
SpeciesId.LICKITUNG,
|
||||||
Species.MAGIKARP,
|
SpeciesId.MAGIKARP,
|
||||||
Species.YANMA,
|
SpeciesId.YANMA,
|
||||||
Species.MURKROW,
|
SpeciesId.MURKROW,
|
||||||
Species.SWINUB,
|
SpeciesId.SWINUB,
|
||||||
Species.ELEKID,
|
SpeciesId.ELEKID,
|
||||||
Species.MAGBY,
|
SpeciesId.MAGBY,
|
||||||
Species.BRONZOR,
|
SpeciesId.BRONZOR,
|
||||||
Species.SKORUPI,
|
SpeciesId.SKORUPI,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.ABRA,
|
SpeciesId.ABRA,
|
||||||
Species.GLIGAR,
|
SpeciesId.GLIGAR,
|
||||||
Species.SNEASEL,
|
SpeciesId.SNEASEL,
|
||||||
Species.DUSKULL,
|
SpeciesId.DUSKULL,
|
||||||
Species.DRIFLOON,
|
SpeciesId.DRIFLOON,
|
||||||
Species.CRANIDOS,
|
SpeciesId.CRANIDOS,
|
||||||
Species.SHIELDON,
|
SpeciesId.SHIELDON,
|
||||||
Species.ROTOM,
|
SpeciesId.ROTOM,
|
||||||
Species.HISUI_QWILFISH,
|
SpeciesId.HISUI_QWILFISH,
|
||||||
|
],
|
||||||
|
[TrainerPoolTier.RARE]: [
|
||||||
|
SpeciesId.SPIRITOMB,
|
||||||
|
SpeciesId.TEDDIURSA,
|
||||||
|
SpeciesId.HISUI_SNEASEL,
|
||||||
|
SpeciesId.HISUI_LILLIGANT,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.SPIRITOMB, Species.TEDDIURSA, Species.HISUI_SNEASEL, Species.HISUI_LILLIGANT],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const PLASMA_ZINZOLIN: TrainerTierPools = {
|
const PLASMA_ZINZOLIN: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.SNEASEL,
|
SpeciesId.SNEASEL,
|
||||||
Species.SWINUB,
|
SpeciesId.SWINUB,
|
||||||
Species.SNORUNT,
|
SpeciesId.SNORUNT,
|
||||||
Species.SNOVER,
|
SpeciesId.SNOVER,
|
||||||
Species.TIMBURR,
|
SpeciesId.TIMBURR,
|
||||||
Species.TYMPOLE,
|
SpeciesId.TYMPOLE,
|
||||||
Species.SANDILE,
|
SpeciesId.SANDILE,
|
||||||
Species.DARUMAKA,
|
SpeciesId.DARUMAKA,
|
||||||
Species.VANILLITE,
|
SpeciesId.VANILLITE,
|
||||||
Species.FOONGUS,
|
SpeciesId.FOONGUS,
|
||||||
Species.FRILLISH,
|
SpeciesId.FRILLISH,
|
||||||
Species.JOLTIK,
|
SpeciesId.JOLTIK,
|
||||||
Species.FERROSEED,
|
SpeciesId.FERROSEED,
|
||||||
Species.CUBCHOO,
|
SpeciesId.CUBCHOO,
|
||||||
Species.GALAR_DARUMAKA,
|
SpeciesId.GALAR_DARUMAKA,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.SPHEAL,
|
SpeciesId.SPHEAL,
|
||||||
Species.DRILBUR,
|
SpeciesId.DRILBUR,
|
||||||
Species.SIGILYPH,
|
SpeciesId.SIGILYPH,
|
||||||
Species.YAMASK,
|
SpeciesId.YAMASK,
|
||||||
Species.ZORUA,
|
SpeciesId.ZORUA,
|
||||||
Species.TYNAMO,
|
SpeciesId.TYNAMO,
|
||||||
Species.MIENFOO,
|
SpeciesId.MIENFOO,
|
||||||
Species.GOLETT,
|
SpeciesId.GOLETT,
|
||||||
Species.PAWNIARD,
|
SpeciesId.PAWNIARD,
|
||||||
Species.VULLABY,
|
SpeciesId.VULLABY,
|
||||||
Species.DURANT,
|
SpeciesId.DURANT,
|
||||||
Species.BERGMITE,
|
SpeciesId.BERGMITE,
|
||||||
Species.EISCUE,
|
SpeciesId.EISCUE,
|
||||||
Species.ALOLA_SANDSHREW,
|
SpeciesId.ALOLA_SANDSHREW,
|
||||||
Species.HISUI_ZORUA,
|
SpeciesId.HISUI_ZORUA,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.DEINO, Species.FRIGIBAX, Species.HISUI_BRAVIARY],
|
[TrainerPoolTier.RARE]: [SpeciesId.DEINO, SpeciesId.FRIGIBAX, SpeciesId.HISUI_BRAVIARY],
|
||||||
};
|
};
|
||||||
|
|
||||||
const PLASMA_COLRESS: TrainerTierPools = {
|
const PLASMA_COLRESS: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.MAGNEMITE,
|
SpeciesId.MAGNEMITE,
|
||||||
Species.GRIMER,
|
SpeciesId.GRIMER,
|
||||||
Species.VOLTORB,
|
SpeciesId.VOLTORB,
|
||||||
Species.PORYGON,
|
SpeciesId.PORYGON,
|
||||||
Species.BRONZOR,
|
SpeciesId.BRONZOR,
|
||||||
Species.ROTOM,
|
SpeciesId.ROTOM,
|
||||||
Species.MUNNA,
|
SpeciesId.MUNNA,
|
||||||
Species.DWEBBLE,
|
SpeciesId.DWEBBLE,
|
||||||
Species.FERROSEED,
|
SpeciesId.FERROSEED,
|
||||||
Species.ELGYEM,
|
SpeciesId.ELGYEM,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.BELDUM,
|
SpeciesId.BELDUM,
|
||||||
Species.SIGILYPH,
|
SpeciesId.SIGILYPH,
|
||||||
Species.TIRTOUGA,
|
SpeciesId.TIRTOUGA,
|
||||||
Species.ARCHEN,
|
SpeciesId.ARCHEN,
|
||||||
Species.TYNAMO,
|
SpeciesId.TYNAMO,
|
||||||
Species.GOLETT,
|
SpeciesId.GOLETT,
|
||||||
Species.BLIPBUG,
|
SpeciesId.BLIPBUG,
|
||||||
Species.VAROOM,
|
SpeciesId.VAROOM,
|
||||||
Species.ALOLA_GRIMER,
|
SpeciesId.ALOLA_GRIMER,
|
||||||
Species.HISUI_VOLTORB,
|
SpeciesId.HISUI_VOLTORB,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.ELEKID, Species.MAGBY, Species.PAWNIARD, Species.DURALUDON],
|
[TrainerPoolTier.RARE]: [SpeciesId.ELEKID, SpeciesId.MAGBY, SpeciesId.PAWNIARD, SpeciesId.DURALUDON],
|
||||||
};
|
};
|
||||||
|
|
||||||
const FLARE: TrainerTierPools = {
|
const FLARE: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.ELECTRIKE,
|
SpeciesId.ELECTRIKE,
|
||||||
Species.SKORUPI,
|
SpeciesId.SKORUPI,
|
||||||
Species.PURRLOIN,
|
SpeciesId.PURRLOIN,
|
||||||
Species.FOONGUS,
|
SpeciesId.FOONGUS,
|
||||||
Species.BUNNELBY,
|
SpeciesId.BUNNELBY,
|
||||||
Species.FLETCHLING,
|
SpeciesId.FLETCHLING,
|
||||||
Species.LITLEO,
|
SpeciesId.LITLEO,
|
||||||
Species.PANGORO,
|
SpeciesId.PANGORO,
|
||||||
Species.ESPURR,
|
SpeciesId.ESPURR,
|
||||||
Species.INKAY,
|
SpeciesId.INKAY,
|
||||||
Species.CLAUNCHER,
|
SpeciesId.CLAUNCHER,
|
||||||
Species.HELIOPTILE,
|
SpeciesId.HELIOPTILE,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.HOUNDOUR,
|
SpeciesId.HOUNDOUR,
|
||||||
Species.SNEASEL,
|
SpeciesId.SNEASEL,
|
||||||
Species.LITWICK,
|
SpeciesId.LITWICK,
|
||||||
Species.HONEDGE,
|
SpeciesId.HONEDGE,
|
||||||
Species.BINACLE,
|
SpeciesId.BINACLE,
|
||||||
Species.SKRELP,
|
SpeciesId.SKRELP,
|
||||||
Species.NOIBAT,
|
SpeciesId.NOIBAT,
|
||||||
Species.PHANTUMP,
|
SpeciesId.PHANTUMP,
|
||||||
Species.PUMPKABOO,
|
SpeciesId.PUMPKABOO,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.GOOMY, Species.HISUI_AVALUGG],
|
[TrainerPoolTier.RARE]: [SpeciesId.GOOMY, SpeciesId.HISUI_AVALUGG],
|
||||||
};
|
};
|
||||||
|
|
||||||
const AETHER: TrainerTierPools = {
|
const AETHER: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.ABRA,
|
SpeciesId.ABRA,
|
||||||
Species.SLOWPOKE,
|
SpeciesId.SLOWPOKE,
|
||||||
Species.MAGNEMITE,
|
SpeciesId.MAGNEMITE,
|
||||||
Species.EXEGGUTOR,
|
SpeciesId.EXEGGUTOR,
|
||||||
Species.NATU,
|
SpeciesId.NATU,
|
||||||
Species.BALTOY,
|
SpeciesId.BALTOY,
|
||||||
Species.MIME_JR,
|
SpeciesId.MIME_JR,
|
||||||
Species.ELGYEM,
|
SpeciesId.ELGYEM,
|
||||||
Species.INKAY,
|
SpeciesId.INKAY,
|
||||||
Species.BRUXISH,
|
SpeciesId.BRUXISH,
|
||||||
Species.BLIPBUG,
|
SpeciesId.BLIPBUG,
|
||||||
Species.ALOLA_RAICHU,
|
SpeciesId.ALOLA_RAICHU,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.RALTS,
|
SpeciesId.RALTS,
|
||||||
Species.MEDITITE,
|
SpeciesId.MEDITITE,
|
||||||
Species.BELDUM,
|
SpeciesId.BELDUM,
|
||||||
Species.SOLOSIS,
|
SpeciesId.SOLOSIS,
|
||||||
Species.HATENNA,
|
SpeciesId.HATENNA,
|
||||||
Species.STANTLER,
|
SpeciesId.STANTLER,
|
||||||
Species.GIRAFARIG,
|
SpeciesId.GIRAFARIG,
|
||||||
Species.ALOLA_GRIMER,
|
SpeciesId.ALOLA_GRIMER,
|
||||||
Species.GALAR_SLOWPOKE,
|
SpeciesId.GALAR_SLOWPOKE,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.PORYGON, Species.ARMAROUGE],
|
[TrainerPoolTier.RARE]: [SpeciesId.PORYGON, SpeciesId.ARMAROUGE],
|
||||||
};
|
};
|
||||||
|
|
||||||
const SKULL: TrainerTierPools = {
|
const SKULL: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.GASTLY,
|
SpeciesId.GASTLY,
|
||||||
Species.KOFFING,
|
SpeciesId.KOFFING,
|
||||||
Species.ZUBAT,
|
SpeciesId.ZUBAT,
|
||||||
Species.VENONAT,
|
SpeciesId.VENONAT,
|
||||||
Species.STUNKY,
|
SpeciesId.STUNKY,
|
||||||
Species.CROAGUNK,
|
SpeciesId.CROAGUNK,
|
||||||
Species.VENIPEDE,
|
SpeciesId.VENIPEDE,
|
||||||
Species.SCRAGGY,
|
SpeciesId.SCRAGGY,
|
||||||
Species.MAREANIE,
|
SpeciesId.MAREANIE,
|
||||||
Species.FOMANTIS,
|
SpeciesId.FOMANTIS,
|
||||||
Species.ALOLA_GRIMER,
|
SpeciesId.ALOLA_GRIMER,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.NIDORAN_F,
|
SpeciesId.NIDORAN_F,
|
||||||
Species.SKORUPI,
|
SpeciesId.SKORUPI,
|
||||||
Species.PAWNIARD,
|
SpeciesId.PAWNIARD,
|
||||||
Species.VULLABY,
|
SpeciesId.VULLABY,
|
||||||
Species.TOXEL,
|
SpeciesId.TOXEL,
|
||||||
Species.GLIMMET,
|
SpeciesId.GLIMMET,
|
||||||
Species.PALDEA_WOOPER,
|
SpeciesId.PALDEA_WOOPER,
|
||||||
Species.GALAR_SLOWPOKE,
|
SpeciesId.GALAR_SLOWPOKE,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.SKRELP, Species.HISUI_SNEASEL],
|
[TrainerPoolTier.RARE]: [SpeciesId.SKRELP, SpeciesId.HISUI_SNEASEL],
|
||||||
};
|
};
|
||||||
|
|
||||||
const MACRO_COSMOS: TrainerTierPools = {
|
const MACRO_COSMOS: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.VULPIX,
|
SpeciesId.VULPIX,
|
||||||
Species.FEEBAS,
|
SpeciesId.FEEBAS,
|
||||||
Species.MAWILE,
|
SpeciesId.MAWILE,
|
||||||
Species.FROSLASS,
|
SpeciesId.FROSLASS,
|
||||||
Species.GOTHITA,
|
SpeciesId.GOTHITA,
|
||||||
Species.FLABEBE,
|
SpeciesId.FLABEBE,
|
||||||
Species.SALANDIT,
|
SpeciesId.SALANDIT,
|
||||||
Species.TSAREENA,
|
SpeciesId.TSAREENA,
|
||||||
Species.SINISTEA,
|
SpeciesId.SINISTEA,
|
||||||
Species.HATENNA,
|
SpeciesId.HATENNA,
|
||||||
Species.INDEEDEE,
|
SpeciesId.INDEEDEE,
|
||||||
Species.GALAR_PONYTA,
|
SpeciesId.GALAR_PONYTA,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.TOGEPI,
|
SpeciesId.TOGEPI,
|
||||||
Species.VULLABY,
|
SpeciesId.VULLABY,
|
||||||
Species.MAREANIE,
|
SpeciesId.MAREANIE,
|
||||||
Species.CUFANT,
|
SpeciesId.CUFANT,
|
||||||
Species.TINKATINK,
|
SpeciesId.TINKATINK,
|
||||||
Species.ALOLA_VULPIX,
|
SpeciesId.ALOLA_VULPIX,
|
||||||
Species.GALAR_CORSOLA,
|
SpeciesId.GALAR_CORSOLA,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.APPLIN, Species.HISUI_LILLIGANT],
|
[TrainerPoolTier.RARE]: [SpeciesId.APPLIN, SpeciesId.HISUI_LILLIGANT],
|
||||||
};
|
};
|
||||||
|
|
||||||
const STAR_DARK: TrainerTierPools = {
|
const STAR_DARK: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.MURKROW,
|
SpeciesId.MURKROW,
|
||||||
Species.SEEDOT,
|
SpeciesId.SEEDOT,
|
||||||
Species.SABLEYE,
|
SpeciesId.SABLEYE,
|
||||||
Species.CACNEA,
|
SpeciesId.CACNEA,
|
||||||
Species.STUNKY,
|
SpeciesId.STUNKY,
|
||||||
Species.SANDILE,
|
SpeciesId.SANDILE,
|
||||||
Species.INKAY,
|
SpeciesId.INKAY,
|
||||||
Species.NYMBLE,
|
SpeciesId.NYMBLE,
|
||||||
Species.MASCHIFF,
|
SpeciesId.MASCHIFF,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.UMBREON,
|
SpeciesId.UMBREON,
|
||||||
Species.CORPHISH,
|
SpeciesId.CORPHISH,
|
||||||
Species.SNEASEL,
|
SpeciesId.SNEASEL,
|
||||||
Species.ZORUA,
|
SpeciesId.ZORUA,
|
||||||
Species.IMPIDIMP,
|
SpeciesId.IMPIDIMP,
|
||||||
Species.BOMBIRDIER,
|
SpeciesId.BOMBIRDIER,
|
||||||
Species.GALAR_ZIGZAGOON,
|
SpeciesId.GALAR_ZIGZAGOON,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.DEINO, Species.SPRIGATITO],
|
[TrainerPoolTier.RARE]: [SpeciesId.DEINO, SpeciesId.SPRIGATITO],
|
||||||
};
|
};
|
||||||
|
|
||||||
const STAR_FIRE: TrainerTierPools = {
|
const STAR_FIRE: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.GROWLITHE,
|
SpeciesId.GROWLITHE,
|
||||||
Species.HOUNDOUR,
|
SpeciesId.HOUNDOUR,
|
||||||
Species.NUMEL,
|
SpeciesId.NUMEL,
|
||||||
Species.TORKOAL,
|
SpeciesId.TORKOAL,
|
||||||
Species.FLETCHLING,
|
SpeciesId.FLETCHLING,
|
||||||
Species.LITLEO,
|
SpeciesId.LITLEO,
|
||||||
Species.SIZZLIPEDE,
|
SpeciesId.SIZZLIPEDE,
|
||||||
Species.ROLYCOLY,
|
SpeciesId.ROLYCOLY,
|
||||||
Species.CAPSAKID,
|
SpeciesId.CAPSAKID,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.PONYTA,
|
SpeciesId.PONYTA,
|
||||||
Species.FLAREON,
|
SpeciesId.FLAREON,
|
||||||
Species.MAGBY,
|
SpeciesId.MAGBY,
|
||||||
Species.DARUMAKA,
|
SpeciesId.DARUMAKA,
|
||||||
Species.LITWICK,
|
SpeciesId.LITWICK,
|
||||||
Species.SALANDIT,
|
SpeciesId.SALANDIT,
|
||||||
Species.TURTONATOR,
|
SpeciesId.TURTONATOR,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.LARVESTA, Species.FUECOCO],
|
[TrainerPoolTier.RARE]: [SpeciesId.LARVESTA, SpeciesId.FUECOCO],
|
||||||
};
|
};
|
||||||
|
|
||||||
const STAR_POISON: TrainerTierPools = {
|
const STAR_POISON: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.GRIMER,
|
SpeciesId.GRIMER,
|
||||||
Species.VENONAT,
|
SpeciesId.VENONAT,
|
||||||
Species.SEVIPER,
|
SpeciesId.SEVIPER,
|
||||||
Species.STUNKY,
|
SpeciesId.STUNKY,
|
||||||
Species.FOONGUS,
|
SpeciesId.FOONGUS,
|
||||||
Species.MAREANIE,
|
SpeciesId.MAREANIE,
|
||||||
Species.TOXEL,
|
SpeciesId.TOXEL,
|
||||||
Species.GRAFAIAI,
|
SpeciesId.GRAFAIAI,
|
||||||
Species.PALDEA_WOOPER,
|
SpeciesId.PALDEA_WOOPER,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.ZUBAT,
|
SpeciesId.ZUBAT,
|
||||||
Species.GASTLY,
|
SpeciesId.GASTLY,
|
||||||
Species.SKRELP,
|
SpeciesId.SKRELP,
|
||||||
Species.OVERQWIL,
|
SpeciesId.OVERQWIL,
|
||||||
Species.ALOLA_GRIMER,
|
SpeciesId.ALOLA_GRIMER,
|
||||||
Species.GALAR_SLOWPOKE,
|
SpeciesId.GALAR_SLOWPOKE,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.GLIMMET, Species.BULBASAUR],
|
[TrainerPoolTier.RARE]: [SpeciesId.GLIMMET, SpeciesId.BULBASAUR],
|
||||||
};
|
};
|
||||||
|
|
||||||
const STAR_FAIRY: TrainerTierPools = {
|
const STAR_FAIRY: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.IGGLYBUFF,
|
SpeciesId.IGGLYBUFF,
|
||||||
Species.AZURILL,
|
SpeciesId.AZURILL,
|
||||||
Species.COTTONEE,
|
SpeciesId.COTTONEE,
|
||||||
Species.FLABEBE,
|
SpeciesId.FLABEBE,
|
||||||
Species.KLEFKI,
|
SpeciesId.KLEFKI,
|
||||||
Species.CUTIEFLY,
|
SpeciesId.CUTIEFLY,
|
||||||
Species.HATENNA,
|
SpeciesId.HATENNA,
|
||||||
Species.TINKATINK,
|
SpeciesId.TINKATINK,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.CLEFFA,
|
SpeciesId.CLEFFA,
|
||||||
Species.TOGEPI,
|
SpeciesId.TOGEPI,
|
||||||
Species.GARDEVOIR,
|
SpeciesId.GARDEVOIR,
|
||||||
Species.SYLVEON,
|
SpeciesId.SYLVEON,
|
||||||
Species.MIMIKYU,
|
SpeciesId.MIMIKYU,
|
||||||
Species.IMPIDIMP,
|
SpeciesId.IMPIDIMP,
|
||||||
Species.ALOLA_VULPIX,
|
SpeciesId.ALOLA_VULPIX,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.GALAR_PONYTA, Species.POPPLIO],
|
[TrainerPoolTier.RARE]: [SpeciesId.GALAR_PONYTA, SpeciesId.POPPLIO],
|
||||||
};
|
};
|
||||||
|
|
||||||
const STAR_FIGHTING: TrainerTierPools = {
|
const STAR_FIGHTING: TrainerTierPools = {
|
||||||
[TrainerPoolTier.COMMON]: [
|
[TrainerPoolTier.COMMON]: [
|
||||||
Species.TYROGUE,
|
SpeciesId.TYROGUE,
|
||||||
Species.SHROOMISH,
|
SpeciesId.SHROOMISH,
|
||||||
Species.MAKUHITA,
|
SpeciesId.MAKUHITA,
|
||||||
Species.RIOLU,
|
SpeciesId.RIOLU,
|
||||||
Species.CROAGUNK,
|
SpeciesId.CROAGUNK,
|
||||||
Species.SCRAGGY,
|
SpeciesId.SCRAGGY,
|
||||||
Species.MIENFOO,
|
SpeciesId.MIENFOO,
|
||||||
Species.PASSIMIAN,
|
SpeciesId.PASSIMIAN,
|
||||||
Species.PAWMI,
|
SpeciesId.PAWMI,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.UNCOMMON]: [
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
Species.MEDITITE,
|
SpeciesId.MEDITITE,
|
||||||
Species.GALLADE,
|
SpeciesId.GALLADE,
|
||||||
Species.TIMBURR,
|
SpeciesId.TIMBURR,
|
||||||
Species.HAWLUCHA,
|
SpeciesId.HAWLUCHA,
|
||||||
Species.STUFFUL,
|
SpeciesId.STUFFUL,
|
||||||
Species.FALINKS,
|
SpeciesId.FALINKS,
|
||||||
Species.FLAMIGO,
|
SpeciesId.FLAMIGO,
|
||||||
Species.PALDEA_TAUROS,
|
SpeciesId.PALDEA_TAUROS,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [Species.JANGMO_O, Species.QUAXLY],
|
[TrainerPoolTier.RARE]: [SpeciesId.JANGMO_O, SpeciesId.QUAXLY],
|
||||||
};
|
};
|
||||||
|
|
||||||
export type EvilTeam =
|
export type EvilTeam =
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,9 @@
|
|||||||
import { Biome } from "#enums/biome";
|
import { BiomeId } from "#enums/biome-id";
|
||||||
import { WeatherType } from "#enums/weather-type";
|
import { WeatherType } from "#enums/weather-type";
|
||||||
import { getPokemonNameWithAffix } from "../messages";
|
import { getPokemonNameWithAffix } from "../messages";
|
||||||
import type Pokemon from "../field/pokemon";
|
import type Pokemon from "../field/pokemon";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import type Move from "./moves/move";
|
import type Move from "./moves/move";
|
||||||
import { AttackMove } from "./moves/move";
|
|
||||||
import { randSeedInt } from "#app/utils/common";
|
import { randSeedInt } from "#app/utils/common";
|
||||||
import { SuppressWeatherEffectAbAttr } from "./abilities/ability";
|
import { SuppressWeatherEffectAbAttr } from "./abilities/ability";
|
||||||
import { TerrainType, getTerrainName } from "./terrain";
|
import { TerrainType, getTerrainName } from "./terrain";
|
||||||
@ -95,9 +94,9 @@ export class Weather {
|
|||||||
|
|
||||||
switch (this.weatherType) {
|
switch (this.weatherType) {
|
||||||
case WeatherType.HARSH_SUN:
|
case WeatherType.HARSH_SUN:
|
||||||
return move instanceof AttackMove && moveType === PokemonType.WATER;
|
return move.is("AttackMove") && moveType === PokemonType.WATER;
|
||||||
case WeatherType.HEAVY_RAIN:
|
case WeatherType.HEAVY_RAIN:
|
||||||
return move instanceof AttackMove && moveType === PokemonType.FIRE;
|
return move.is("AttackMove") && moveType === PokemonType.FIRE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -289,13 +288,13 @@ export function getRandomWeatherType(arena: Arena): WeatherType {
|
|||||||
let weatherPool: WeatherPoolEntry[] = [];
|
let weatherPool: WeatherPoolEntry[] = [];
|
||||||
const hasSun = arena.getTimeOfDay() < 2;
|
const hasSun = arena.getTimeOfDay() < 2;
|
||||||
switch (arena.biomeType) {
|
switch (arena.biomeType) {
|
||||||
case Biome.GRASS:
|
case BiomeId.GRASS:
|
||||||
weatherPool = [{ weatherType: WeatherType.NONE, weight: 7 }];
|
weatherPool = [{ weatherType: WeatherType.NONE, weight: 7 }];
|
||||||
if (hasSun) {
|
if (hasSun) {
|
||||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 3 });
|
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 3 });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Biome.TALL_GRASS:
|
case BiomeId.TALL_GRASS:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||||
{ weatherType: WeatherType.RAIN, weight: 5 },
|
{ weatherType: WeatherType.RAIN, weight: 5 },
|
||||||
@ -304,26 +303,26 @@ export function getRandomWeatherType(arena: Arena): WeatherType {
|
|||||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 8 });
|
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 8 });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Biome.FOREST:
|
case BiomeId.FOREST:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||||
{ weatherType: WeatherType.RAIN, weight: 5 },
|
{ weatherType: WeatherType.RAIN, weight: 5 },
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.SEA:
|
case BiomeId.SEA:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||||
{ weatherType: WeatherType.RAIN, weight: 12 },
|
{ weatherType: WeatherType.RAIN, weight: 12 },
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.SWAMP:
|
case BiomeId.SWAMP:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||||
{ weatherType: WeatherType.RAIN, weight: 4 },
|
{ weatherType: WeatherType.RAIN, weight: 4 },
|
||||||
{ weatherType: WeatherType.FOG, weight: 1 },
|
{ weatherType: WeatherType.FOG, weight: 1 },
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.BEACH:
|
case BiomeId.BEACH:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||||
{ weatherType: WeatherType.RAIN, weight: 3 },
|
{ weatherType: WeatherType.RAIN, weight: 3 },
|
||||||
@ -332,17 +331,17 @@ export function getRandomWeatherType(arena: Arena): WeatherType {
|
|||||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 });
|
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Biome.LAKE:
|
case BiomeId.LAKE:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 10 },
|
{ weatherType: WeatherType.NONE, weight: 10 },
|
||||||
{ weatherType: WeatherType.RAIN, weight: 5 },
|
{ weatherType: WeatherType.RAIN, weight: 5 },
|
||||||
{ weatherType: WeatherType.FOG, weight: 1 },
|
{ weatherType: WeatherType.FOG, weight: 1 },
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.SEABED:
|
case BiomeId.SEABED:
|
||||||
weatherPool = [{ weatherType: WeatherType.RAIN, weight: 1 }];
|
weatherPool = [{ weatherType: WeatherType.RAIN, weight: 1 }];
|
||||||
break;
|
break;
|
||||||
case Biome.BADLANDS:
|
case BiomeId.BADLANDS:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||||
{ weatherType: WeatherType.SANDSTORM, weight: 2 },
|
{ weatherType: WeatherType.SANDSTORM, weight: 2 },
|
||||||
@ -351,26 +350,26 @@ export function getRandomWeatherType(arena: Arena): WeatherType {
|
|||||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 });
|
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Biome.DESERT:
|
case BiomeId.DESERT:
|
||||||
weatherPool = [{ weatherType: WeatherType.SANDSTORM, weight: 2 }];
|
weatherPool = [{ weatherType: WeatherType.SANDSTORM, weight: 2 }];
|
||||||
if (hasSun) {
|
if (hasSun) {
|
||||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
|
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Biome.ICE_CAVE:
|
case BiomeId.ICE_CAVE:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||||
{ weatherType: WeatherType.SNOW, weight: 4 },
|
{ weatherType: WeatherType.SNOW, weight: 4 },
|
||||||
{ weatherType: WeatherType.HAIL, weight: 1 },
|
{ weatherType: WeatherType.HAIL, weight: 1 },
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.MEADOW:
|
case BiomeId.MEADOW:
|
||||||
weatherPool = [{ weatherType: WeatherType.NONE, weight: 2 }];
|
weatherPool = [{ weatherType: WeatherType.NONE, weight: 2 }];
|
||||||
if (hasSun) {
|
if (hasSun) {
|
||||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
|
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Biome.VOLCANO:
|
case BiomeId.VOLCANO:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{
|
{
|
||||||
weatherType: hasSun ? WeatherType.SUNNY : WeatherType.NONE,
|
weatherType: hasSun ? WeatherType.SUNNY : WeatherType.NONE,
|
||||||
@ -378,25 +377,25 @@ export function getRandomWeatherType(arena: Arena): WeatherType {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.GRAVEYARD:
|
case BiomeId.GRAVEYARD:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||||
{ weatherType: WeatherType.FOG, weight: 1 },
|
{ weatherType: WeatherType.FOG, weight: 1 },
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.JUNGLE:
|
case BiomeId.JUNGLE:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||||
{ weatherType: WeatherType.RAIN, weight: 2 },
|
{ weatherType: WeatherType.RAIN, weight: 2 },
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.SNOWY_FOREST:
|
case BiomeId.SNOWY_FOREST:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.SNOW, weight: 7 },
|
{ weatherType: WeatherType.SNOW, weight: 7 },
|
||||||
{ weatherType: WeatherType.HAIL, weight: 1 },
|
{ weatherType: WeatherType.HAIL, weight: 1 },
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.ISLAND:
|
case BiomeId.ISLAND:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 5 },
|
{ weatherType: WeatherType.NONE, weight: 5 },
|
||||||
{ weatherType: WeatherType.RAIN, weight: 1 },
|
{ weatherType: WeatherType.RAIN, weight: 1 },
|
||||||
@ -407,7 +406,7 @@ export function getRandomWeatherType(arena: Arena): WeatherType {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arena.biomeType === Biome.TOWN && timedEventManager.isEventActive()) {
|
if (arena.biomeType === BiomeId.TOWN && timedEventManager.isEventActive()) {
|
||||||
timedEventManager.getWeather()?.map(w => weatherPool.push(w));
|
timedEventManager.getWeather()?.map(w => weatherPool.push(w));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
src/debug.js
17
src/debug.js
@ -1,17 +0,0 @@
|
|||||||
export function getData() {
|
|
||||||
const dataStr = localStorage.getItem("data");
|
|
||||||
if (!dataStr) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return JSON.parse(atob(dataStr), (k, v) =>
|
|
||||||
k.endsWith("Attr") && !["natureAttr", "abilityAttr", "passiveAttr"].includes(k) ? BigInt(v) : v,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getSession() {
|
|
||||||
const sessionStr = localStorage.getItem("sessionData");
|
|
||||||
if (!sessionStr) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return JSON.parse(atob(sessionStr));
|
|
||||||
}
|
|
@ -4,11 +4,11 @@ export enum MoveFlags {
|
|||||||
IGNORE_PROTECT = 1 << 1,
|
IGNORE_PROTECT = 1 << 1,
|
||||||
/**
|
/**
|
||||||
* Sound-based moves have the following effects:
|
* Sound-based moves have the following effects:
|
||||||
* - Pokemon with the {@linkcode Abilities.SOUNDPROOF Soundproof Ability} are unaffected by other Pokemon's sound-based moves.
|
* - Pokemon with the {@linkcode AbilityId.SOUNDPROOF Soundproof Ability} are unaffected by other Pokemon's sound-based moves.
|
||||||
* - Pokemon affected by {@linkcode Moves.THROAT_CHOP Throat Chop} cannot use sound-based moves for two turns.
|
* - Pokemon affected by {@linkcode MoveId.THROAT_CHOP Throat Chop} cannot use sound-based moves for two turns.
|
||||||
* - Sound-based moves used by a Pokemon with {@linkcode Abilities.LIQUID_VOICE Liquid Voice} become Water-type moves.
|
* - Sound-based moves used by a Pokemon with {@linkcode AbilityId.LIQUID_VOICE Liquid Voice} become Water-type moves.
|
||||||
* - Sound-based moves used by a Pokemon with {@linkcode Abilities.PUNK_ROCK Punk Rock} are boosted by 30%. Pokemon with Punk Rock also take half damage from sound-based moves.
|
* - Sound-based moves used by a Pokemon with {@linkcode AbilityId.PUNK_ROCK Punk Rock} are boosted by 30%. Pokemon with Punk Rock also take half damage from sound-based moves.
|
||||||
* - All sound-based moves (except Howl) can hit Pokemon behind an active {@linkcode Moves.SUBSTITUTE Substitute}.
|
* - All sound-based moves (except Howl) can hit Pokemon behind an active {@linkcode MoveId.SUBSTITUTE Substitute}.
|
||||||
*
|
*
|
||||||
* cf https://bulbapedia.bulbagarden.net/wiki/Sound-based_move
|
* cf https://bulbapedia.bulbagarden.net/wiki/Sound-based_move
|
||||||
*/
|
*/
|
||||||
@ -20,19 +20,19 @@ export enum MoveFlags {
|
|||||||
PUNCHING_MOVE = 1 << 7,
|
PUNCHING_MOVE = 1 << 7,
|
||||||
SLICING_MOVE = 1 << 8,
|
SLICING_MOVE = 1 << 8,
|
||||||
/**
|
/**
|
||||||
* Indicates a move should be affected by {@linkcode Abilities.RECKLESS}
|
* Indicates a move should be affected by {@linkcode AbilityId.RECKLESS}
|
||||||
* @see {@linkcode Move.recklessMove()}
|
* @see {@linkcode Move.recklessMove()}
|
||||||
*/
|
*/
|
||||||
RECKLESS_MOVE = 1 << 9,
|
RECKLESS_MOVE = 1 << 9,
|
||||||
/** Indicates a move should be affected by {@linkcode Abilities.BULLETPROOF} */
|
/** Indicates a move should be affected by {@linkcode AbilityId.BULLETPROOF} */
|
||||||
BALLBOMB_MOVE = 1 << 10,
|
BALLBOMB_MOVE = 1 << 10,
|
||||||
/** Grass types and pokemon with {@linkcode Abilities.OVERCOAT} are immune to powder moves */
|
/** Grass types and pokemon with {@linkcode AbilityId.OVERCOAT} are immune to powder moves */
|
||||||
POWDER_MOVE = 1 << 11,
|
POWDER_MOVE = 1 << 11,
|
||||||
/** Indicates a move should trigger {@linkcode Abilities.DANCER} */
|
/** Indicates a move should trigger {@linkcode AbilityId.DANCER} */
|
||||||
DANCE_MOVE = 1 << 12,
|
DANCE_MOVE = 1 << 12,
|
||||||
/** Indicates a move should trigger {@linkcode Abilities.WIND_RIDER} */
|
/** Indicates a move should trigger {@linkcode AbilityId.WIND_RIDER} */
|
||||||
WIND_MOVE = 1 << 13,
|
WIND_MOVE = 1 << 13,
|
||||||
/** Indicates a move should trigger {@linkcode Abilities.TRIAGE} */
|
/** Indicates a move should trigger {@linkcode AbilityId.TRIAGE} */
|
||||||
TRIAGE_MOVE = 1 << 14,
|
TRIAGE_MOVE = 1 << 14,
|
||||||
IGNORE_ABILITIES = 1 << 15,
|
IGNORE_ABILITIES = 1 << 15,
|
||||||
/** Enables all hits of a multi-hit move to be accuracy checked individually */
|
/** Enables all hits of a multi-hit move to be accuracy checked individually */
|
||||||
@ -41,6 +41,6 @@ export enum MoveFlags {
|
|||||||
IGNORE_SUBSTITUTE = 1 << 17,
|
IGNORE_SUBSTITUTE = 1 << 17,
|
||||||
/** Indicates a move is able to be redirected to allies in a double battle if the attacker faints */
|
/** Indicates a move is able to be redirected to allies in a double battle if the attacker faints */
|
||||||
REDIRECT_COUNTER = 1 << 18,
|
REDIRECT_COUNTER = 1 << 18,
|
||||||
/** Indicates a move is able to be reflected by {@linkcode Abilities.MAGIC_BOUNCE} and {@linkcode Moves.MAGIC_COAT} */
|
/** Indicates a move is able to be reflected by {@linkcode AbilityId.MAGIC_BOUNCE} and {@linkcode MoveId.MAGIC_COAT} */
|
||||||
REFLECTABLE = 1 << 19
|
REFLECTABLE = 1 << 19
|
||||||
}
|
}
|
||||||
|
11
src/enums/ability-attr.ts
Normal file
11
src/enums/ability-attr.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Not to be confused with an Ability Attribute.
|
||||||
|
* This is an object literal storing the slot that an ability can occupy.
|
||||||
|
*/
|
||||||
|
export const AbilityAttr = Object.freeze({
|
||||||
|
ABILITY_1: 1,
|
||||||
|
ABILITY_2: 2,
|
||||||
|
ABILITY_HIDDEN: 4,
|
||||||
|
});
|
||||||
|
|
||||||
|
export type AbilityAttr = typeof AbilityAttr[keyof typeof AbilityAttr];
|
@ -1,4 +1,4 @@
|
|||||||
export enum Abilities {
|
export enum AbilityId {
|
||||||
/**{@link https://bulbapedia.bulbagarden.net/wiki/None_(ability) | Source} */
|
/**{@link https://bulbapedia.bulbagarden.net/wiki/None_(ability) | Source} */
|
||||||
NONE,
|
NONE,
|
||||||
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stench_(ability) | Source} */
|
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stench_(ability) | Source} */
|
5
src/enums/ai-type.ts
Normal file
5
src/enums/ai-type.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export enum AiType {
|
||||||
|
RANDOM,
|
||||||
|
SMART_RANDOM,
|
||||||
|
SMART
|
||||||
|
}
|
5
src/enums/arena-tag-side.ts
Normal file
5
src/enums/arena-tag-side.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export enum ArenaTagSide {
|
||||||
|
BOTH,
|
||||||
|
PLAYER,
|
||||||
|
ENEMY
|
||||||
|
}
|
7
src/enums/battler-index.ts
Normal file
7
src/enums/battler-index.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export enum BattlerIndex {
|
||||||
|
ATTACKER = -1,
|
||||||
|
PLAYER,
|
||||||
|
PLAYER_2,
|
||||||
|
ENEMY,
|
||||||
|
ENEMY_2
|
||||||
|
}
|
12
src/enums/battler-tag-lapse-type.ts
Normal file
12
src/enums/battler-tag-lapse-type.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export enum BattlerTagLapseType {
|
||||||
|
FAINT,
|
||||||
|
MOVE,
|
||||||
|
PRE_MOVE,
|
||||||
|
AFTER_MOVE,
|
||||||
|
MOVE_EFFECT,
|
||||||
|
TURN_END,
|
||||||
|
HIT,
|
||||||
|
/** Tag lapses AFTER_HIT, applying its effects even if the user faints */
|
||||||
|
AFTER_HIT,
|
||||||
|
CUSTOM
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
export enum Biome {
|
export enum BiomeId {
|
||||||
// TODO: Should -1 be part of the enum signature (for "unknown place")
|
// TODO: Should -1 be part of the enum signature (for "unknown place")
|
||||||
TOWN,
|
TOWN,
|
||||||
PLAINS,
|
PLAINS,
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user