Merge branch 'beta' into healBlock
@ -55,8 +55,8 @@ Check out [Github Issues](https://github.com/pagefaultgames/pokerogue/issues) to
|
|||||||
- Pokémon Sword/Shield
|
- Pokémon Sword/Shield
|
||||||
- Pokémon Legends: Arceus
|
- Pokémon Legends: Arceus
|
||||||
- Pokémon Scarlet/Violet
|
- Pokémon Scarlet/Violet
|
||||||
- Firel (Custom Laboratory, Metropolis, Seabed, and Space biome music)
|
- Firel (Custom Ice Cave, Laboratory, Metropolis, Plains, Power Plant, Seabed, Space, and Volcano biome music)
|
||||||
- Lmz (Custom Jungle biome music)
|
- Lmz (Custom Ancient Ruins, Jungle, and Lake biome music)
|
||||||
- Andr06 (Custom Slum and Sea biome music)
|
- Andr06 (Custom Slum and Sea biome music)
|
||||||
|
|
||||||
### 🎵 Sound Effects
|
### 🎵 Sound Effects
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This script creates a test boilerplate file for a move or ability.
|
* This script creates a test boilerplate file for a move or ability.
|
||||||
* @param {string} type - The type of test to create. Either "move", "ability",
|
* @param {string} type - The type of test to create. Either "move", "ability",
|
||||||
@ -10,61 +6,101 @@ import { fileURLToPath } from 'url';
|
|||||||
* @example npm run create-test move tackle
|
* @example npm run create-test move tackle
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
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
|
// Get the directory name of the current module file
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
const typeChoices = ["Move", "Ability", "Item"];
|
||||||
|
|
||||||
// Get the arguments from the command line
|
/**
|
||||||
const args = process.argv.slice(2);
|
* Prompts the user to select a type via list.
|
||||||
const type = args[0]; // "move" or "ability"
|
* @returns {Promise<{selectedOption: string}>} the selected type
|
||||||
let fileName = args[1]; // The file name
|
*/
|
||||||
|
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 (!type || !fileName) {
|
if (typeAnswer.selectedOption === "EXIT") {
|
||||||
console.error('Please provide a type ("move", "ability", or "item") and a file name.');
|
console.log("Exiting...");
|
||||||
process.exit(1);
|
return process.exit();
|
||||||
|
} else if (!typeChoices.includes(typeAnswer.selectedOption)) {
|
||||||
|
console.error('Please provide a valid type ("move", "ability", or "item")!');
|
||||||
|
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 a file name for the ${selectedType} test:`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
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
|
// Convert fileName from kebab-case or camelCase to snake_case
|
||||||
fileName = fileName
|
const fileName = fileNameAnswer.userInput
|
||||||
.replace(/-+/g, '_') // Convert kebab-case (dashes) to underscores
|
.replace(/-+/g, "_") // Convert kebab-case (dashes) to underscores
|
||||||
.replace(/([a-z])([A-Z])/g, '$1_$2') // Convert camelCase to snake_case
|
.replace(/([a-z])([A-Z])/g, "$1_$2") // Convert camelCase to snake_case
|
||||||
.toLowerCase(); // Ensure all lowercase
|
.toLowerCase(); // Ensure all lowercase
|
||||||
|
|
||||||
// Format the description for the test case
|
// Format the description for the test case
|
||||||
const formattedName = fileName
|
|
||||||
.replace(/_/g, ' ')
|
|
||||||
.replace(/\b\w/g, char => char.toUpperCase());
|
|
||||||
|
|
||||||
|
const formattedName = fileName.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
||||||
// Determine the directory based on the type
|
// Determine the directory based on the type
|
||||||
let dir;
|
let dir;
|
||||||
let description;
|
let description;
|
||||||
if (type === 'move') {
|
switch (type) {
|
||||||
dir = path.join(__dirname, 'src', 'test', 'moves');
|
case "move":
|
||||||
|
dir = path.join(__dirname, "src", "test", "moves");
|
||||||
description = `Moves - ${formattedName}`;
|
description = `Moves - ${formattedName}`;
|
||||||
} else if (type === 'ability') {
|
break;
|
||||||
dir = path.join(__dirname, 'src', 'test', 'abilities');
|
case "ability":
|
||||||
|
dir = path.join(__dirname, "src", "test", "abilities");
|
||||||
description = `Abilities - ${formattedName}`;
|
description = `Abilities - ${formattedName}`;
|
||||||
} else if (type === "item") {
|
break;
|
||||||
dir = path.join(__dirname, 'src', 'test', 'items');
|
case "item":
|
||||||
|
dir = path.join(__dirname, "src", "test", "items");
|
||||||
description = `Items - ${formattedName}`;
|
description = `Items - ${formattedName}`;
|
||||||
} else {
|
break;
|
||||||
|
default:
|
||||||
console.error('Invalid type. Please use "move", "ability", or "item".');
|
console.error('Invalid type. Please use "move", "ability", or "item".');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define the content template
|
// Define the content template
|
||||||
const content = `import { Abilities } from "#enums/abilities";
|
const content = `import { Abilities } from "#enums/abilities";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
@ -104,7 +140,23 @@ describe("${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(`File "${fileName}.test.ts" already exists.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
// Write the template content to the file
|
// Write the template content to the file
|
||||||
fs.writeFileSync(filePath, content, 'utf8');
|
fs.writeFileSync(filePath, content, "utf8");
|
||||||
|
|
||||||
console.log(`File created at: ${filePath}`);
|
console.log(`File created at: ${filePath}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
runInteractive();
|
||||||
|
26
index.css
@ -26,11 +26,37 @@ body {
|
|||||||
#app {
|
#app {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app > div:first-child {
|
#app > div:first-child {
|
||||||
|
transform-origin: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Supports automatic vertical centering as suggested in PR#1114, but only via CSS
|
||||||
|
|
||||||
|
Condition factorized to deduce CSS rules:
|
||||||
|
true if (isLandscape && !isMobile() && !hasTouchscreen() || (hasTouchscreen() && !isTouchControlsEnabled))
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* isLandscape && !isMobile() && !hasTouchscreen() */
|
||||||
|
@media (orientation: landscape) and (pointer: fine) {
|
||||||
|
#app {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (pointer: coarse) {
|
||||||
|
/* hasTouchscreen() && !isTouchControlsEnabled */
|
||||||
|
body:has(> #touchControls[class=visible]) #app {
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
body:has(> #touchControls[class=visible]) #app > div:first-child {
|
||||||
transform-origin: top !important;
|
transform-origin: top !important;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#layout:fullscreen #dpad, #layout:fullscreen {
|
#layout:fullscreen #dpad, #layout:fullscreen {
|
||||||
bottom: 6rem;
|
bottom: 6rem;
|
||||||
|
453
package-lock.json
generated
@ -29,6 +29,7 @@
|
|||||||
"dependency-cruiser": "^16.3.10",
|
"dependency-cruiser": "^16.3.10",
|
||||||
"eslint": "^9.7.0",
|
"eslint": "^9.7.0",
|
||||||
"eslint-plugin-import-x": "^4.2.1",
|
"eslint-plugin-import-x": "^4.2.1",
|
||||||
|
"inquirer": "^11.0.2",
|
||||||
"jsdom": "^24.0.0",
|
"jsdom": "^24.0.0",
|
||||||
"lefthook": "^1.6.12",
|
"lefthook": "^1.6.12",
|
||||||
"phaser3spectorjs": "^0.0.8",
|
"phaser3spectorjs": "^0.0.8",
|
||||||
@ -1070,6 +1071,281 @@
|
|||||||
"url": "https://github.com/sponsors/nzakas"
|
"url": "https://github.com/sponsors/nzakas"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@inquirer/checkbox": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/core": "^9.2.1",
|
||||||
|
"@inquirer/figures": "^1.0.6",
|
||||||
|
"@inquirer/type": "^2.0.0",
|
||||||
|
"ansi-escapes": "^4.3.2",
|
||||||
|
"yoctocolors-cjs": "^2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/confirm": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/core": "^9.2.1",
|
||||||
|
"@inquirer/type": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/core": {
|
||||||
|
"version": "9.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.2.1.tgz",
|
||||||
|
"integrity": "sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/figures": "^1.0.6",
|
||||||
|
"@inquirer/type": "^2.0.0",
|
||||||
|
"@types/mute-stream": "^0.0.4",
|
||||||
|
"@types/node": "^22.5.5",
|
||||||
|
"@types/wrap-ansi": "^3.0.0",
|
||||||
|
"ansi-escapes": "^4.3.2",
|
||||||
|
"cli-width": "^4.1.0",
|
||||||
|
"mute-stream": "^1.0.0",
|
||||||
|
"signal-exit": "^4.1.0",
|
||||||
|
"strip-ansi": "^6.0.1",
|
||||||
|
"wrap-ansi": "^6.2.0",
|
||||||
|
"yoctocolors-cjs": "^2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/core/node_modules/@types/node": {
|
||||||
|
"version": "22.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz",
|
||||||
|
"integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~6.19.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/core/node_modules/emoji-regex": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/core/node_modules/string-width": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"emoji-regex": "^8.0.0",
|
||||||
|
"is-fullwidth-code-point": "^3.0.0",
|
||||||
|
"strip-ansi": "^6.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/core/node_modules/undici-types": {
|
||||||
|
"version": "6.19.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||||
|
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/core/node_modules/wrap-ansi": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^4.0.0",
|
||||||
|
"string-width": "^4.1.0",
|
||||||
|
"strip-ansi": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/editor": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/core": "^9.2.1",
|
||||||
|
"@inquirer/type": "^2.0.0",
|
||||||
|
"external-editor": "^3.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/expand": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/core": "^9.2.1",
|
||||||
|
"@inquirer/type": "^2.0.0",
|
||||||
|
"yoctocolors-cjs": "^2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/figures": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-yfZzps3Cso2UbM7WlxKwZQh2Hs6plrbjs1QnzQDZhK2DgyCo6D8AaHps9olkNcUFlcYERMqU3uJSp1gmy3s/qQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/input": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/input/-/input-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/core": "^9.2.1",
|
||||||
|
"@inquirer/type": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/number": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/number/-/number-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/core": "^9.2.1",
|
||||||
|
"@inquirer/type": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/password": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/password/-/password-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/core": "^9.2.1",
|
||||||
|
"@inquirer/type": "^2.0.0",
|
||||||
|
"ansi-escapes": "^4.3.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/prompts": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/checkbox": "^3.0.1",
|
||||||
|
"@inquirer/confirm": "^4.0.1",
|
||||||
|
"@inquirer/editor": "^3.0.1",
|
||||||
|
"@inquirer/expand": "^3.0.1",
|
||||||
|
"@inquirer/input": "^3.0.1",
|
||||||
|
"@inquirer/number": "^2.0.1",
|
||||||
|
"@inquirer/password": "^3.0.1",
|
||||||
|
"@inquirer/rawlist": "^3.0.1",
|
||||||
|
"@inquirer/search": "^2.0.1",
|
||||||
|
"@inquirer/select": "^3.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/rawlist": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/core": "^9.2.1",
|
||||||
|
"@inquirer/type": "^2.0.0",
|
||||||
|
"yoctocolors-cjs": "^2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/search": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/search/-/search-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/core": "^9.2.1",
|
||||||
|
"@inquirer/figures": "^1.0.6",
|
||||||
|
"@inquirer/type": "^2.0.0",
|
||||||
|
"yoctocolors-cjs": "^2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/select": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/select/-/select-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/core": "^9.2.1",
|
||||||
|
"@inquirer/figures": "^1.0.6",
|
||||||
|
"@inquirer/type": "^2.0.0",
|
||||||
|
"ansi-escapes": "^4.3.2",
|
||||||
|
"yoctocolors-cjs": "^2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/type": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/type/-/type-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mute-stream": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@isaacs/cliui": {
|
"node_modules/@isaacs/cliui": {
|
||||||
"version": "8.0.2",
|
"version": "8.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||||
@ -1563,6 +1839,16 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/mute-stream": {
|
||||||
|
"version": "0.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz",
|
||||||
|
"integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "20.14.11",
|
"version": "20.14.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz",
|
||||||
@ -1585,6 +1871,13 @@
|
|||||||
"integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==",
|
"integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/wrap-ansi": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.0.0-alpha.58",
|
"version": "8.0.0-alpha.58",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.0-alpha.58.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.0-alpha.58.tgz",
|
||||||
@ -1970,6 +2263,22 @@
|
|||||||
"url": "https://github.com/sponsors/epoberezkin"
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ansi-escapes": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"type-fest": "^0.21.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ansi-regex": {
|
"node_modules/ansi-regex": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||||
@ -2192,6 +2501,13 @@
|
|||||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chardet": {
|
||||||
|
"version": "0.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
||||||
|
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/check-error": {
|
"node_modules/check-error": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
|
||||||
@ -2202,6 +2518,16 @@
|
|||||||
"node": ">= 16"
|
"node": ">= 16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cli-width": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cliui": {
|
"node_modules/cliui": {
|
||||||
"version": "8.0.1",
|
"version": "8.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||||
@ -3057,6 +3383,21 @@
|
|||||||
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/external-editor": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chardet": "^0.7.0",
|
||||||
|
"iconv-lite": "^0.4.24",
|
||||||
|
"tmp": "^0.0.33"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
@ -3579,6 +3920,19 @@
|
|||||||
"i18next": ">=8.4.0"
|
"i18next": ">=8.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/iconv-lite": {
|
||||||
|
"version": "0.4.24",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
|
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.3.1",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
|
||||||
@ -3626,6 +3980,26 @@
|
|||||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/inquirer": {
|
||||||
|
"version": "11.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-11.0.2.tgz",
|
||||||
|
"integrity": "sha512-pnbn3nL+JFrTw/pLhzyE/IQ3+gA3n5JxTAZQDjB6qu4gbjOaiTnpZbxT6HY2DDCT7bzDjTTsd3snRP+B6N//Pg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/core": "^9.2.1",
|
||||||
|
"@inquirer/prompts": "^6.0.1",
|
||||||
|
"@inquirer/type": "^2.0.0",
|
||||||
|
"@types/mute-stream": "^0.0.4",
|
||||||
|
"ansi-escapes": "^4.3.2",
|
||||||
|
"mute-stream": "^1.0.0",
|
||||||
|
"run-async": "^3.0.0",
|
||||||
|
"rxjs": "^7.8.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/interpret": {
|
"node_modules/interpret": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz",
|
||||||
@ -4456,6 +4830,16 @@
|
|||||||
"mustache": "bin/mustache"
|
"mustache": "bin/mustache"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mute-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.7",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||||
@ -4605,6 +4989,16 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/os-tmpdir": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/p-limit": {
|
"node_modules/p-limit": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||||
@ -5092,6 +5486,16 @@
|
|||||||
"integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==",
|
"integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/run-async": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/run-parallel": {
|
"node_modules/run-parallel": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||||
@ -5116,6 +5520,16 @@
|
|||||||
"queue-microtask": "^1.2.2"
|
"queue-microtask": "^1.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rxjs": {
|
||||||
|
"version": "7.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||||
|
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/safe-regex": {
|
"node_modules/safe-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz",
|
||||||
@ -5538,6 +5952,19 @@
|
|||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tmp": {
|
||||||
|
"version": "0.0.33",
|
||||||
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||||
|
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"os-tmpdir": "~1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/to-fast-properties": {
|
"node_modules/to-fast-properties": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||||
@ -5673,6 +6100,19 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/type-fest": {
|
||||||
|
"version": "0.21.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
|
||||||
|
"integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "(MIT OR CC0-1.0)",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/typedoc": {
|
"node_modules/typedoc": {
|
||||||
"version": "0.26.5",
|
"version": "0.26.5",
|
||||||
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.5.tgz",
|
||||||
@ -6346,6 +6786,19 @@
|
|||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yoctocolors-cjs": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
"dependency-cruiser": "^16.3.10",
|
"dependency-cruiser": "^16.3.10",
|
||||||
"eslint": "^9.7.0",
|
"eslint": "^9.7.0",
|
||||||
"eslint-plugin-import-x": "^4.2.1",
|
"eslint-plugin-import-x": "^4.2.1",
|
||||||
|
"inquirer": "^11.0.2",
|
||||||
"jsdom": "^24.0.0",
|
"jsdom": "^24.0.0",
|
||||||
"lefthook": "^1.6.12",
|
"lefthook": "^1.6.12",
|
||||||
"phaser3spectorjs": "^0.0.8",
|
"phaser3spectorjs": "^0.0.8",
|
||||||
|
BIN
public/audio/bgm/mystery_encounter_delibirdy.mp3
Normal file
@ -27,7 +27,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@ -115,7 +115,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@ -215,7 +215,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@ -315,7 +315,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@ -414,7 +414,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@ -538,7 +538,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 23,
|
"x": 23,
|
||||||
@ -685,7 +685,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": -19,
|
"x": -19,
|
||||||
@ -784,7 +784,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 26,
|
"x": 26,
|
||||||
@ -883,7 +883,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 23.5,
|
"x": 23.5,
|
||||||
@ -994,7 +994,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 9,
|
"x": 9,
|
||||||
@ -1069,7 +1069,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": -18.5,
|
"x": -18.5,
|
||||||
@ -1157,7 +1157,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 37.5,
|
"x": 37.5,
|
||||||
@ -1221,7 +1221,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@ -1284,7 +1284,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@ -1348,7 +1348,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@ -1448,7 +1448,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@ -1548,7 +1548,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@ -1647,7 +1647,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@ -1759,7 +1759,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": -25.5,
|
"x": -25.5,
|
||||||
@ -1870,7 +1870,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 12,
|
"x": 12,
|
||||||
@ -1957,7 +1957,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": -27,
|
"x": -27,
|
||||||
@ -2044,7 +2044,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": -16,
|
"x": -16,
|
||||||
@ -2143,7 +2143,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": -26.5,
|
"x": -26.5,
|
||||||
@ -2230,7 +2230,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 23,
|
"x": 23,
|
||||||
@ -2306,7 +2306,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 24,
|
"x": 24,
|
||||||
@ -2346,7 +2346,7 @@
|
|||||||
"opacity": 255,
|
"opacity": 255,
|
||||||
"locked": true,
|
"locked": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"focus": 2
|
"focus": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": -27,
|
"x": -27,
|
||||||
|
@ -5,29 +5,29 @@
|
|||||||
"format": "RGBA8888",
|
"format": "RGBA8888",
|
||||||
"size": {
|
"size": {
|
||||||
"w": 78,
|
"w": 78,
|
||||||
"h": 87
|
"h": 86
|
||||||
},
|
},
|
||||||
"scale": 1,
|
"scale": 1,
|
||||||
"frames": [
|
"frames": [
|
||||||
{
|
{
|
||||||
"filename": "0001.png",
|
"filename": "0001.png",
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": true,
|
"trimmed": false,
|
||||||
"sourceSize": {
|
"sourceSize": {
|
||||||
"w": 80,
|
"w": 78,
|
||||||
"h": 87
|
"h": 86
|
||||||
},
|
},
|
||||||
"spriteSourceSize": {
|
"spriteSourceSize": {
|
||||||
"x": 1,
|
"x": 0,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 78,
|
"w": 78,
|
||||||
"h": 87
|
"h": 86
|
||||||
},
|
},
|
||||||
"frame": {
|
"frame": {
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 78,
|
"w": 78,
|
||||||
"h": 87
|
"h": 86
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -36,6 +36,6 @@
|
|||||||
"meta": {
|
"meta": {
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
"version": "3.0",
|
"version": "3.0",
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:d3cce87ee0e3a880d840bffe9373d5d4:7c776d33b75abad1fe36b14a5e5734af:56468b7a2883e66dadcd2af13ebd8010$"
|
"smartupdate": "$TexturePacker:SmartUpdate:65266da62e9d2953511c0d68ae431345:c1ca63690bed8dd5af71bb443910c830:56468b7a2883e66dadcd2af13ebd8010$"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
188
public/images/statuses_ca_ES.json
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "statuses_ca_ES.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 64
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "pokerus",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "burn",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 8,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "faint",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 16,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "freeze",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 24,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "paralysis",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 32,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "poison",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 40,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "sleep",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 48,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "toxic",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 56,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/statuses_ca_ES.png
Normal file
After Width: | Height: | Size: 441 B |
188
public/images/statuses_de.json
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "statuses_de.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 64
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "pokerus",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "burn",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 8,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "faint",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 16,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "freeze",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 24,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "paralysis",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 32,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "poison",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 40,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "sleep",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 48,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "toxic",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 56,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/statuses_de.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
188
public/images/statuses_es.json
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "statuses_es.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 64
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "pokerus",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "burn",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 8,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "faint",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 16,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "freeze",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 24,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "paralysis",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 32,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "poison",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 40,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "sleep",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 48,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "toxic",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 56,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/statuses_es.png
Normal file
After Width: | Height: | Size: 441 B |
188
public/images/statuses_fr.json
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "statuses_fr.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 64
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "pokerus",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "burn",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 8,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "faint",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 16,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "freeze",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 24,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "paralysis",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 32,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "poison",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 40,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "sleep",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 48,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "toxic",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 56,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/statuses_fr.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
188
public/images/statuses_it.json
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "statuses_it.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 64
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "pokerus",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "burn",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 8,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "faint",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 16,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "freeze",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 24,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "paralysis",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 32,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "poison",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 40,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "sleep",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 48,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "toxic",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 56,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/statuses_it.png
Normal file
After Width: | Height: | Size: 441 B |
188
public/images/statuses_ja.json
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "statuses_ja.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 64
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "pokerus",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "burn",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 8,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "faint",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 16,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "freeze",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 24,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "paralysis",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 32,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "poison",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 40,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "sleep",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 48,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "toxic",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 56,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/statuses_ja.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
188
public/images/statuses_ko.json
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "statuses_ko.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 64
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "pokerus",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "burn",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 8,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "faint",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 16,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "freeze",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 24,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "paralysis",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 32,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "poison",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 40,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "sleep",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 48,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "toxic",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 56,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/statuses_ko.png
Normal file
After Width: | Height: | Size: 441 B |
188
public/images/statuses_pt_BR.json
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "statuses_pt_BR.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 64
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "pokerus",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "burn",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 8,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "faint",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 16,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "freeze",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 24,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "paralysis",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 32,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "poison",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 40,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "sleep",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 48,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "toxic",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 56,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/statuses_pt_BR.png
Normal file
After Width: | Height: | Size: 519 B |
188
public/images/statuses_zh_CN.json
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "statuses_zh_CN.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 64
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "pokerus",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "burn",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 8,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "faint",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 16,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "freeze",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 24,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "paralysis",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 32,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "poison",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 40,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "sleep",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 48,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "toxic",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 56,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/statuses_zh_CN.png
Normal file
After Width: | Height: | Size: 441 B |
188
public/images/statuses_zh_TW.json
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "statuses.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 64
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "pokerus",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 22,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "burn",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 8,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "faint",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 16,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "freeze",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 24,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "paralysis",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 32,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "poison",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 40,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "sleep",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 48,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "toxic",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 56,
|
||||||
|
"w": 20,
|
||||||
|
"h": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:37686e85605d17b806f22d43081c1139:70535ffee63ba61b3397d8470c2c8982:e6649238c018d3630e55681417c698ca$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/statuses_zh_TW.png
Normal file
After Width: | Height: | Size: 441 B |
41
public/images/trainer/expert_pokemon_breeder.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "expert_pokemon_breeder.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 39,
|
||||||
|
"h": 75
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "0001.png",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": true,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 80,
|
||||||
|
"h": 80
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 21,
|
||||||
|
"y": 3,
|
||||||
|
"w": 39,
|
||||||
|
"h": 75
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 39,
|
||||||
|
"h": 75
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:cb681265d8dca038a518ab14076fd140:18ff41b1ef6967682643a11695926e58:c59ea3971195f5a395b75223a77d9068$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/trainer/expert_pokemon_breeder.png
Normal file
After Width: | Height: | Size: 1006 B |
@ -782,6 +782,14 @@ export default class BattleScene extends SceneBase {
|
|||||||
return this.getPlayerField().find(p => p.isActive());
|
return this.getPlayerField().find(p => p.isActive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the first {@linkcode Pokemon.isActive() | active PlayerPokemon} that isn't also currently switching out
|
||||||
|
* @returns Either the first {@linkcode PlayerPokemon} satisfying, or undefined if no player pokemon on the field satisfy
|
||||||
|
*/
|
||||||
|
getNonSwitchedPlayerPokemon(): PlayerPokemon | undefined {
|
||||||
|
return this.getPlayerField().find(p => p.isActive() && p.switchOutStatus === false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of PlayerPokemon of length 1 or 2 depending on if double battles or not
|
* Returns an array of PlayerPokemon of length 1 or 2 depending on if double battles or not
|
||||||
* @returns array of {@linkcode PlayerPokemon}
|
* @returns array of {@linkcode PlayerPokemon}
|
||||||
@ -799,6 +807,14 @@ export default class BattleScene extends SceneBase {
|
|||||||
return this.getEnemyField().find(p => p.isActive());
|
return this.getEnemyField().find(p => p.isActive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the first {@linkcode Pokemon.isActive() | active EnemyPokemon} pokemon from the enemy that isn't also currently switching out
|
||||||
|
* @returns Either the first {@linkcode EnemyPokemon} satisfying, or undefined if no player pokemon on the field satisfy
|
||||||
|
*/
|
||||||
|
getNonSwitchedEnemyPokemon(): EnemyPokemon | undefined {
|
||||||
|
return this.getEnemyField().find(p => p.isActive() && p.switchOutStatus === false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of EnemyPokemon of length 1 or 2 depending on if double battles or not
|
* Returns an array of EnemyPokemon of length 1 or 2 depending on if double battles or not
|
||||||
* @returns array of {@linkcode EnemyPokemon}
|
* @returns array of {@linkcode EnemyPokemon}
|
||||||
@ -1911,6 +1927,19 @@ export default class BattleScene extends SceneBase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fades out current track for `delay` ms, then fades in new track.
|
||||||
|
* @param newBgmKey
|
||||||
|
* @param destroy
|
||||||
|
* @param delay
|
||||||
|
*/
|
||||||
|
fadeAndSwitchBgm(newBgmKey: string, destroy: boolean = false, delay: number = 2000) {
|
||||||
|
this.fadeOutBgm(delay, destroy);
|
||||||
|
this.time.delayedCall(delay, () => {
|
||||||
|
this.playBgm(newBgmKey);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
playSound(sound: string | AnySound, config?: object): AnySound {
|
playSound(sound: string | AnySound, config?: object): AnySound {
|
||||||
const key = typeof sound === "string" ? sound : sound.key;
|
const key = typeof sound === "string" ? sound : sound.key;
|
||||||
config = config ?? {};
|
config = config ?? {};
|
||||||
@ -2157,6 +2186,16 @@ export default class BattleScene extends SceneBase {
|
|||||||
return 13.13;
|
return 13.13;
|
||||||
case "battle_macro_boss": //SWSH Rose Battle
|
case "battle_macro_boss": //SWSH Rose Battle
|
||||||
return 11.42;
|
return 11.42;
|
||||||
|
case "mystery_encounter_gen_5_gts": // BW GTS
|
||||||
|
return 8.52;
|
||||||
|
case "mystery_encounter_gen_6_gts": // XY GTS
|
||||||
|
return 9.24;
|
||||||
|
case "mystery_encounter_fun_and_games": // EoS Guildmaster Wigglytuff
|
||||||
|
return 4.78;
|
||||||
|
case "mystery_encounter_weird_dream": // EoS Temporal Spire
|
||||||
|
return 41.42;
|
||||||
|
case "mystery_encounter_delibirdy": // Firel Delibirdy
|
||||||
|
return 82.28;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2603,7 +2642,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
party.forEach((enemyPokemon: EnemyPokemon, i: integer) => {
|
party.forEach((enemyPokemon: EnemyPokemon, i: integer) => {
|
||||||
if (heldModifiersConfigs && i < heldModifiersConfigs.length && heldModifiersConfigs[i] && heldModifiersConfigs[i].length > 0) {
|
if (heldModifiersConfigs && i < heldModifiersConfigs.length && heldModifiersConfigs[i]) {
|
||||||
heldModifiersConfigs[i].forEach(mt => {
|
heldModifiersConfigs[i].forEach(mt => {
|
||||||
let modifier: PokemonHeldItemModifier;
|
let modifier: PokemonHeldItemModifier;
|
||||||
if (mt.modifier instanceof PokemonHeldItemModifierType) {
|
if (mt.modifier instanceof PokemonHeldItemModifierType) {
|
||||||
@ -2614,8 +2653,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
const stackCount = mt.stackCount ?? 1;
|
const stackCount = mt.stackCount ?? 1;
|
||||||
modifier.stackCount = stackCount;
|
modifier.stackCount = stackCount;
|
||||||
// TODO: set isTransferable
|
modifier.isTransferable = mt.isTransferable ?? modifier.isTransferable;
|
||||||
// modifier.isTransferrable = mt.isTransferable ?? true;
|
|
||||||
this.addEnemyModifier(modifier, true);
|
this.addEnemyModifier(modifier, true);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -14,8 +14,16 @@ import { PlayerGender } from "#enums/player-gender";
|
|||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
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 MysteryEncounter from "./data/mystery-encounters/mystery-encounter";
|
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
|
import { CustomModifierSettings } from "#app/modifier/modifier-type";
|
||||||
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
|
|
||||||
|
export enum ClassicFixedBossWaves {
|
||||||
|
// TODO: other fixed wave battles should be added here
|
||||||
|
EVIL_BOSS_1 = 115,
|
||||||
|
EVIL_BOSS_2 = 165,
|
||||||
|
}
|
||||||
|
|
||||||
export enum BattleType {
|
export enum BattleType {
|
||||||
WILD,
|
WILD,
|
||||||
@ -157,7 +165,7 @@ export default class Battle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addPostBattleLoot(enemyPokemon: EnemyPokemon): void {
|
addPostBattleLoot(enemyPokemon: EnemyPokemon): void {
|
||||||
this.postBattleLoot.push(...enemyPokemon.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && m.pokemonId === enemyPokemon.id && m.isTransferrable, false).map(i => {
|
this.postBattleLoot.push(...enemyPokemon.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && m.pokemonId === enemyPokemon.id && m.isTransferable, false).map(i => {
|
||||||
const ret = i as PokemonHeldItemModifier;
|
const ret = i as PokemonHeldItemModifier;
|
||||||
//@ts-ignore - this is awful to fix/change
|
//@ts-ignore - this is awful to fix/change
|
||||||
ret.pokemonId = null;
|
ret.pokemonId = null;
|
||||||
@ -419,6 +427,7 @@ export class FixedBattleConfig {
|
|||||||
public getTrainer: GetTrainerFunc;
|
public getTrainer: GetTrainerFunc;
|
||||||
public getEnemyParty: GetEnemyPartyFunc;
|
public getEnemyParty: GetEnemyPartyFunc;
|
||||||
public seedOffsetWaveIndex: number;
|
public seedOffsetWaveIndex: number;
|
||||||
|
public customModifierRewardSettings?: CustomModifierSettings;
|
||||||
|
|
||||||
setBattleType(battleType: BattleType): FixedBattleConfig {
|
setBattleType(battleType: BattleType): FixedBattleConfig {
|
||||||
this.battleType = battleType;
|
this.battleType = battleType;
|
||||||
@ -444,6 +453,11 @@ export class FixedBattleConfig {
|
|||||||
this.seedOffsetWaveIndex = seedOffsetWaveIndex;
|
this.seedOffsetWaveIndex = seedOffsetWaveIndex;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setCustomModifierRewards(customModifierRewardSettings: CustomModifierSettings) {
|
||||||
|
this.customModifierRewardSettings = customModifierRewardSettings;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -503,11 +517,13 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
|||||||
[8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
[8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||||
[25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
[25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||||
|
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }),
|
||||||
[35]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
[35]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)),
|
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)),
|
||||||
[55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
[55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||||
|
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }),
|
||||||
[62]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
[62]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)),
|
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)),
|
||||||
[64]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
[64]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||||
@ -515,17 +531,21 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
|||||||
[66]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
[66]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||||
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA ], true)),
|
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA ], true)),
|
||||||
[95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
[95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||||
|
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||||
[112]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
[112]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)),
|
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)),
|
||||||
[114]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
[114]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||||
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA ], true, 1)),
|
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA ], true, 1)),
|
||||||
[115]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
[ClassicFixedBossWaves.EVIL_BOSS_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE ])),
|
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE ]))
|
||||||
|
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||||
[145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
[145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||||
[165]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2, TrainerType.LUSAMINE_2, TrainerType.GUZMA_2, TrainerType.ROSE_2 ])),
|
[ClassicFixedBossWaves.EVIL_BOSS_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||||
|
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2, TrainerType.LUSAMINE_2, TrainerType.GUZMA_2, TrainerType.ROSE_2 ]))
|
||||||
|
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
|
||||||
[182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
[182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])),
|
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])),
|
||||||
[184]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182)
|
[184]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182)
|
||||||
@ -538,4 +558,5 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
|||||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN ])),
|
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN ])),
|
||||||
[195]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
[195]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_6, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_6, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
||||||
|
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false })
|
||||||
};
|
};
|
||||||
|
@ -1 +1,5 @@
|
|||||||
export const PLAYER_PARTY_MAX_SIZE = 6;
|
/** The maximum size of the player's party */
|
||||||
|
export const PLAYER_PARTY_MAX_SIZE: number = 6;
|
||||||
|
|
||||||
|
/** Whether to use seasonal splash messages in general */
|
||||||
|
export const USE_SEASONAL_SPLASH_MESSAGES: boolean = false;
|
||||||
|
@ -1670,7 +1670,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
|||||||
applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise<boolean> {
|
applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise<boolean> {
|
||||||
return new Promise<boolean>(resolve => {
|
return new Promise<boolean>(resolve => {
|
||||||
if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.stealCondition || this.stealCondition(pokemon, defender, move))) {
|
if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.stealCondition || this.stealCondition(pokemon, defender, move))) {
|
||||||
const heldItems = this.getTargetHeldItems(defender).filter(i => i.isTransferrable);
|
const heldItems = this.getTargetHeldItems(defender).filter(i => i.isTransferable);
|
||||||
if (heldItems.length) {
|
if (heldItems.length) {
|
||||||
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
||||||
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
|
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
|
||||||
@ -1763,7 +1763,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
|
|||||||
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise<boolean> {
|
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise<boolean> {
|
||||||
return new Promise<boolean>(resolve => {
|
return new Promise<boolean>(resolve => {
|
||||||
if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move))) {
|
if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move))) {
|
||||||
const heldItems = this.getTargetHeldItems(attacker).filter(i => i.isTransferrable);
|
const heldItems = this.getTargetHeldItems(attacker).filter(i => i.isTransferable);
|
||||||
if (heldItems.length) {
|
if (heldItems.length) {
|
||||||
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
||||||
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
|
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
|
||||||
@ -2625,7 +2625,11 @@ export class PreStatStageChangeAbAttr extends AbAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protect one or all {@linkcode BattleStat} from reductions caused by other Pokémon's moves and Abilities
|
||||||
|
*/
|
||||||
export class ProtectStatAbAttr extends PreStatStageChangeAbAttr {
|
export class ProtectStatAbAttr extends PreStatStageChangeAbAttr {
|
||||||
|
/** {@linkcode BattleStat} to protect or `undefined` if **all** {@linkcode BattleStat} are protected */
|
||||||
private protectedStat?: BattleStat;
|
private protectedStat?: BattleStat;
|
||||||
|
|
||||||
constructor(protectedStat?: BattleStat) {
|
constructor(protectedStat?: BattleStat) {
|
||||||
@ -2634,7 +2638,17 @@ export class ProtectStatAbAttr extends PreStatStageChangeAbAttr {
|
|||||||
this.protectedStat = protectedStat;
|
this.protectedStat = protectedStat;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyPreStatStageChange(_pokemon: Pokemon, _passive: boolean, simulated: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, _args: any[]): boolean {
|
/**
|
||||||
|
* Apply the {@linkcode ProtectedStatAbAttr} to an interaction
|
||||||
|
* @param _pokemon
|
||||||
|
* @param _passive
|
||||||
|
* @param simulated
|
||||||
|
* @param stat the {@linkcode BattleStat} being affected
|
||||||
|
* @param cancelled The {@linkcode Utils.BooleanHolder} that will be set to true if the stat is protected
|
||||||
|
* @param _args
|
||||||
|
* @returns true if the stat is protected, false otherwise
|
||||||
|
*/
|
||||||
|
applyPreStatStageChange(_pokemon: Pokemon, _passive: boolean, _simulated: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, _args: any[]): boolean {
|
||||||
if (Utils.isNullOrUndefined(this.protectedStat) || stat === this.protectedStat) {
|
if (Utils.isNullOrUndefined(this.protectedStat) || stat === this.protectedStat) {
|
||||||
cancelled.value = true;
|
cancelled.value = true;
|
||||||
return true;
|
return true;
|
||||||
@ -3757,7 +3771,7 @@ export class StatStageChangeMultiplierAbAttr extends AbAttr {
|
|||||||
this.multiplier = multiplier;
|
this.multiplier = multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||||
(args[0] as Utils.IntegerHolder).value *= this.multiplier;
|
(args[0] as Utils.IntegerHolder).value *= this.multiplier;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -428,7 +428,7 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent {
|
|||||||
moveAnim.bgSprite.setScale(1.25);
|
moveAnim.bgSprite.setScale(1.25);
|
||||||
moveAnim.bgSprite.setAlpha(this.opacity / 255);
|
moveAnim.bgSprite.setAlpha(this.opacity / 255);
|
||||||
scene.field.add(moveAnim.bgSprite);
|
scene.field.add(moveAnim.bgSprite);
|
||||||
const fieldPokemon = scene.getEnemyPokemon() || scene.getPlayerPokemon();
|
const fieldPokemon = scene.getNonSwitchedEnemyPokemon() || scene.getNonSwitchedPlayerPokemon();
|
||||||
if (!isNullOrUndefined(priority)) {
|
if (!isNullOrUndefined(priority)) {
|
||||||
scene.field.moveTo(moveAnim.bgSprite as Phaser.GameObjects.GameObject, priority!);
|
scene.field.moveTo(moveAnim.bgSprite as Phaser.GameObjects.GameObject, priority!);
|
||||||
} else if (fieldPokemon?.isOnField()) {
|
} else if (fieldPokemon?.isOnField()) {
|
||||||
@ -488,14 +488,14 @@ export function initMoveAnim(scene: BattleScene, move: Moves): Promise<void> {
|
|||||||
} else {
|
} else {
|
||||||
moveAnims.set(move, null);
|
moveAnims.set(move, null);
|
||||||
const defaultMoveAnim = allMoves[move] instanceof AttackMove ? Moves.TACKLE : allMoves[move] instanceof SelfStatusMove ? Moves.FOCUS_ENERGY : Moves.TAIL_WHIP;
|
const defaultMoveAnim = allMoves[move] instanceof AttackMove ? Moves.TACKLE : allMoves[move] instanceof SelfStatusMove ? Moves.FOCUS_ENERGY : Moves.TAIL_WHIP;
|
||||||
const moveName = Moves[move].toLowerCase().replace(/\_/g, "-");
|
|
||||||
const fetchAnimAndResolve = (move: Moves) => {
|
const fetchAnimAndResolve = (move: Moves) => {
|
||||||
scene.cachedFetch(`./battle-anims/${moveName}.json`)
|
scene.cachedFetch(`./battle-anims/${Utils.animationFileName(move)}.json`)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const contentType = response.headers.get("content-type");
|
const contentType = response.headers.get("content-type");
|
||||||
if (!response.ok || contentType?.indexOf("application/json") === -1) {
|
if (!response.ok || contentType?.indexOf("application/json") === -1) {
|
||||||
console.error(`Could not load animation file for move '${moveName}'`, response.status, response.statusText);
|
useDefaultAnim(move, defaultMoveAnim);
|
||||||
populateMoveAnim(move, moveAnims.get(defaultMoveAnim));
|
logMissingMoveAnim(move, response.status, response.statusText);
|
||||||
return resolve();
|
return resolve();
|
||||||
}
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
@ -515,6 +515,11 @@ export function initMoveAnim(scene: BattleScene, move: Moves): Promise<void> {
|
|||||||
} else {
|
} else {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
useDefaultAnim(move, defaultMoveAnim);
|
||||||
|
logMissingMoveAnim(move, error);
|
||||||
|
return resolve();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
fetchAnimAndResolve(move);
|
fetchAnimAndResolve(move);
|
||||||
@ -522,6 +527,29 @@ export function initMoveAnim(scene: BattleScene, move: Moves): Promise<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the default animation for the given move.
|
||||||
|
*
|
||||||
|
* @param move the move to populate an animation for
|
||||||
|
* @param defaultMoveAnim the move to use as the default animation
|
||||||
|
*/
|
||||||
|
function useDefaultAnim(move: Moves, defaultMoveAnim: Moves) {
|
||||||
|
populateMoveAnim(move, moveAnims.get(defaultMoveAnim));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for printing a warning to the console when a move animation is missing.
|
||||||
|
*
|
||||||
|
* @param move the move to populate an animation for
|
||||||
|
* @param optionalParams parameters to add to the error logging
|
||||||
|
*
|
||||||
|
* @remarks use {@linkcode useDefaultAnim} to use a default animation
|
||||||
|
*/
|
||||||
|
function logMissingMoveAnim(move: Moves, ...optionalParams: any[]) {
|
||||||
|
const moveName = Utils.animationFileName(move);
|
||||||
|
console.warn(`Could not load animation file for move '${moveName}'`, ...optionalParams);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches animation configs to be used in a Mystery Encounter
|
* Fetches animation configs to be used in a Mystery Encounter
|
||||||
* @param scene
|
* @param scene
|
||||||
@ -961,7 +989,7 @@ export abstract class BattleAnim {
|
|||||||
const setSpritePriority = (priority: integer) => {
|
const setSpritePriority = (priority: integer) => {
|
||||||
switch (priority) {
|
switch (priority) {
|
||||||
case 0:
|
case 0:
|
||||||
scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, scene.getEnemyPokemon() || scene.getPlayerPokemon()!); // TODO: is this bang correct?
|
scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, scene.getNonSwitchedEnemyPokemon() || scene.getNonSwitchedPlayerPokemon()!); // This bang assumes that if (the EnemyPokemon is undefined, then the PlayerPokemon function must return an object), correct assumption?
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
scene.field.moveTo(moveSprite, scene.field.getAll().length - 1);
|
scene.field.moveTo(moveSprite, scene.field.getAll().length - 1);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import BattleScene from "../battle-scene";
|
import BattleScene from "../battle-scene";
|
||||||
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species";
|
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species";
|
||||||
import { VariantTier } from "../enums/variant-tiers";
|
import { VariantTier } from "../enums/variant-tier";
|
||||||
import * as Utils from "../utils";
|
import * as Utils from "../utils";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
import { pokemonPrevolutions } from "./pokemon-evolutions";
|
import { pokemonPrevolutions } from "./pokemon-evolutions";
|
||||||
@ -178,7 +178,7 @@ export class Egg {
|
|||||||
// be done because species with no variants get filtered at rollSpecies but if the
|
// be done because species with no variants get filtered at rollSpecies but if the
|
||||||
// species is set via options or the legendary gacha pokemon gets choosen the check never happens
|
// species is set via options or the legendary gacha pokemon gets choosen the check never happens
|
||||||
if (this._species && !getPokemonSpecies(this._species).hasVariants()) {
|
if (this._species && !getPokemonSpecies(this._species).hasVariants()) {
|
||||||
this._variantTier = VariantTier.COMMON;
|
this._variantTier = VariantTier.STANDARD;
|
||||||
}
|
}
|
||||||
// Needs this._tier so it needs to be generated afer the tier override if bought from same species
|
// Needs this._tier so it needs to be generated afer the tier override if bought from same species
|
||||||
this._eggMoveIndex = eggOptions?.eggMoveIndex ?? this.rollEggMoveIndex();
|
this._eggMoveIndex = eggOptions?.eggMoveIndex ?? this.rollEggMoveIndex();
|
||||||
@ -494,12 +494,12 @@ export class Egg {
|
|||||||
// place but I don't want to touch the pokemon class.
|
// place but I don't want to touch the pokemon class.
|
||||||
private rollVariant(): VariantTier {
|
private rollVariant(): VariantTier {
|
||||||
if (!this.isShiny) {
|
if (!this.isShiny) {
|
||||||
return VariantTier.COMMON;
|
return VariantTier.STANDARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rand = Utils.randSeedInt(10);
|
const rand = Utils.randSeedInt(10);
|
||||||
if (rand >= 4) {
|
if (rand >= 4) {
|
||||||
return VariantTier.COMMON; // 6/10
|
return VariantTier.STANDARD; // 6/10
|
||||||
} else if (rand >= 1) {
|
} else if (rand >= 1) {
|
||||||
return VariantTier.RARE; // 3/10
|
return VariantTier.RARE; // 3/10
|
||||||
} else {
|
} else {
|
||||||
|
128
src/data/move.ts
@ -1,16 +1,15 @@
|
|||||||
import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims";
|
import { ChargeAnim, initMoveAnim, loadMoveAnimAssets, MoveChargeAnim } from "./battle-anims";
|
||||||
import { EncoreTag, GulpMissileTag, HelpingHandTag, SemiInvulnerableTag, ShellTrapTag, StockpilingTag, TrappedTag, SubstituteTag, TypeBoostTag } from "./battler-tags";
|
import { EncoreTag, GulpMissileTag, HelpingHandTag, SemiInvulnerableTag, ShellTrapTag, StockpilingTag, SubstituteTag, TrappedTag, TypeBoostTag } from "./battler-tags";
|
||||||
import { getPokemonNameWithAffix } from "../messages";
|
import { getPokemonNameWithAffix } from "../messages";
|
||||||
import Pokemon, { AttackMoveResult, EnemyPokemon, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../field/pokemon";
|
import Pokemon, { AttackMoveResult, EnemyPokemon, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../field/pokemon";
|
||||||
import { StatusEffect, getStatusEffectHealText, isNonVolatileStatusEffect, getNonVolatileStatusEffects } from "./status-effect";
|
import { getNonVolatileStatusEffects, getStatusEffectHealText, isNonVolatileStatusEffect, StatusEffect } from "./status-effect";
|
||||||
import { getTypeDamageMultiplier, Type } from "./type";
|
import { getTypeDamageMultiplier, Type } from "./type";
|
||||||
import { Constructor } from "#app/utils";
|
import { Constructor, NumberHolder } from "#app/utils";
|
||||||
import * as Utils from "../utils";
|
import * as Utils from "../utils";
|
||||||
import { WeatherType } from "./weather";
|
import { WeatherType } from "./weather";
|
||||||
import { ArenaTagSide, ArenaTrapTag, WeakenMoveTypeTag } from "./arena-tag";
|
import { ArenaTagSide, ArenaTrapTag, WeakenMoveTypeTag } from "./arena-tag";
|
||||||
import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr, HealFromBerryUseAbAttr, IgnoreProtectOnContactAbAttr, IgnoreMoveEffectsAbAttr, applyPreDefendAbAttrs, MoveEffectChanceMultiplierAbAttr, WonderSkinAbAttr, applyPreAttackAbAttrs, MoveTypeChangeAbAttr, UserFieldMoveTypePowerBoostAbAttr, FieldMoveTypePowerBoostAbAttr, AllyMoveCategoryPowerBoostAbAttr, VariableMovePowerAbAttr } from "./ability";
|
import { allAbilities, AllyMoveCategoryPowerBoostAbAttr, applyAbAttrs, applyPostAttackAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, BlockItemTheftAbAttr, BlockNonDirectDamageAbAttr, BlockOneHitKOAbAttr, BlockRecoilDamageAttr, ConfusionOnStatusEffectAbAttr, FieldMoveTypePowerBoostAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, HealFromBerryUseAbAttr, IgnoreContactAbAttr, IgnoreMoveEffectsAbAttr, IgnoreProtectOnContactAbAttr, MaxMultiHitAbAttr, MoveAbilityBypassAbAttr, MoveEffectChanceMultiplierAbAttr, MoveTypeChangeAbAttr, ReverseDrainAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, UnswappableAbilityAbAttr, UserFieldMoveTypePowerBoostAbAttr, VariableMovePowerAbAttr, WonderSkinAbAttr } from "./ability";
|
||||||
import { allAbilities } from "./ability";
|
import { AttackTypeBoosterModifier, BerryModifier, PokemonHeldItemModifier, PokemonMoveAccuracyBoosterModifier, PokemonMultiHitModifier, PreserveBerryModifier } from "../modifier/modifier";
|
||||||
import { PokemonHeldItemModifier, BerryModifier, PreserveBerryModifier, PokemonMoveAccuracyBoosterModifier, AttackTypeBoosterModifier, PokemonMultiHitModifier } from "../modifier/modifier";
|
|
||||||
import { BattlerIndex, BattleType } from "../battle";
|
import { BattlerIndex, BattleType } from "../battle";
|
||||||
import { TerrainType } from "./terrain";
|
import { TerrainType } from "./terrain";
|
||||||
import { ModifierPoolType } from "#app/modifier/modifier-type";
|
import { ModifierPoolType } from "#app/modifier/modifier-type";
|
||||||
@ -25,7 +24,7 @@ import { Biome } from "#enums/biome";
|
|||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { MoveUsedEvent } from "#app/events/battle-scene";
|
import { MoveUsedEvent } from "#app/events/battle-scene";
|
||||||
import { Stat, type BattleStat, type EffectiveStat, BATTLE_STATS, EFFECTIVE_STATS, getStatKey } from "#app/enums/stat";
|
import { BATTLE_STATS, type BattleStat, EFFECTIVE_STATS, type EffectiveStat, getStatKey, Stat } from "#app/enums/stat";
|
||||||
import { PartyStatusCurePhase } from "#app/phases/party-status-cure-phase";
|
import { PartyStatusCurePhase } from "#app/phases/party-status-cure-phase";
|
||||||
import { BattleEndPhase } from "#app/phases/battle-end-phase";
|
import { BattleEndPhase } from "#app/phases/battle-end-phase";
|
||||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
||||||
@ -36,7 +35,6 @@ import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|||||||
import { SwitchPhase } from "#app/phases/switch-phase";
|
import { SwitchPhase } from "#app/phases/switch-phase";
|
||||||
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
||||||
import { SpeciesFormChangeRevertWeatherFormTrigger } from "./pokemon-forms";
|
import { SpeciesFormChangeRevertWeatherFormTrigger } from "./pokemon-forms";
|
||||||
import { NumberHolder } from "#app/utils";
|
|
||||||
import { GameMode } from "#app/game-mode";
|
import { GameMode } from "#app/game-mode";
|
||||||
import { applyChallenges, ChallengeType } from "./challenge";
|
import { applyChallenges, ChallengeType } from "./challenge";
|
||||||
|
|
||||||
@ -2136,7 +2134,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr {
|
|||||||
if (rand >= this.chance) {
|
if (rand >= this.chance) {
|
||||||
return resolve(false);
|
return resolve(false);
|
||||||
}
|
}
|
||||||
const heldItems = this.getTargetHeldItems(target).filter(i => i.isTransferrable);
|
const heldItems = this.getTargetHeldItems(target).filter(i => i.isTransferable);
|
||||||
if (heldItems.length) {
|
if (heldItems.length) {
|
||||||
const poolType = target.isPlayer() ? ModifierPoolType.PLAYER : target.hasTrainer() ? ModifierPoolType.TRAINER : ModifierPoolType.WILD;
|
const poolType = target.isPlayer() ? ModifierPoolType.PLAYER : target.hasTrainer() ? ModifierPoolType.TRAINER : ModifierPoolType.WILD;
|
||||||
const highestItemTier = heldItems.map(m => m.type.getOrInferTier(poolType)).reduce((highestTier, tier) => Math.max(tier!, highestTier), 0); // TODO: is the bang after tier correct?
|
const highestItemTier = heldItems.map(m => m.type.getOrInferTier(poolType)).reduce((highestTier, tier) => Math.max(tier!, highestTier), 0); // TODO: is the bang after tier correct?
|
||||||
@ -2213,7 +2211,7 @@ export class RemoveHeldItemAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Considers entire transferrable item pool by default (Knock Off). Otherwise berries only if specified (Incinerate).
|
// Considers entire transferrable item pool by default (Knock Off). Otherwise berries only if specified (Incinerate).
|
||||||
let heldItems = this.getTargetHeldItems(target).filter(i => i.isTransferrable);
|
let heldItems = this.getTargetHeldItems(target).filter(i => i.isTransferable);
|
||||||
|
|
||||||
if (this.berriesOnly) {
|
if (this.berriesOnly) {
|
||||||
heldItems = heldItems.filter(m => m instanceof BerryModifier && m.pokemonId === target.id, target.isPlayer());
|
heldItems = heldItems.filter(m => m instanceof BerryModifier && m.pokemonId === target.id, target.isPlayer());
|
||||||
@ -2417,6 +2415,16 @@ export class BypassSleepAttr extends MoveAttr {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns arbitrarily high score when Pokemon is asleep, otherwise shouldn't be used
|
||||||
|
* @param user
|
||||||
|
* @param target
|
||||||
|
* @param move
|
||||||
|
*/
|
||||||
|
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
|
||||||
|
return user.status && user.status.effect === StatusEffect.SLEEP ? 200 : -10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3839,7 +3847,7 @@ export class StormAccuracyAttr extends VariableAccuracyAttr {
|
|||||||
* @extends VariableAccuracyAttr
|
* @extends VariableAccuracyAttr
|
||||||
* @see {@linkcode apply}
|
* @see {@linkcode apply}
|
||||||
*/
|
*/
|
||||||
export class MinimizeAccuracyAttr extends VariableAccuracyAttr {
|
export class AlwaysHitMinimizeAttr extends VariableAccuracyAttr {
|
||||||
/**
|
/**
|
||||||
* @see {@linkcode apply}
|
* @see {@linkcode apply}
|
||||||
* @param user N/A
|
* @param user N/A
|
||||||
@ -3974,18 +3982,17 @@ export class StatusCategoryOnAllyAttr extends VariableMoveCategoryAttr {
|
|||||||
export class ShellSideArmCategoryAttr extends VariableMoveCategoryAttr {
|
export class ShellSideArmCategoryAttr extends VariableMoveCategoryAttr {
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
const category = (args[0] as Utils.NumberHolder);
|
const category = (args[0] as Utils.NumberHolder);
|
||||||
const atkRatio = user.getEffectiveStat(Stat.ATK, target, move) / target.getEffectiveStat(Stat.DEF, user, move);
|
|
||||||
const specialRatio = user.getEffectiveStat(Stat.SPATK, target, move) / target.getEffectiveStat(Stat.SPDEF, user, move);
|
|
||||||
|
|
||||||
// Shell Side Arm is much more complicated than it looks, this is a partial implementation to try to achieve something similar to the games
|
const predictedPhysDmg = target.getBaseDamage(user, move, MoveCategory.PHYSICAL, true, true);
|
||||||
if (atkRatio > specialRatio) {
|
const predictedSpecDmg = target.getBaseDamage(user, move, MoveCategory.SPECIAL, true, true);
|
||||||
|
|
||||||
|
if (predictedPhysDmg > predictedSpecDmg) {
|
||||||
category.value = MoveCategory.PHYSICAL;
|
category.value = MoveCategory.PHYSICAL;
|
||||||
return true;
|
return true;
|
||||||
} else if (atkRatio === specialRatio && user.randSeedInt(2) === 0) {
|
} else if (predictedPhysDmg === predictedSpecDmg && user.randSeedInt(2) === 0) {
|
||||||
category.value = MoveCategory.PHYSICAL;
|
category.value = MoveCategory.PHYSICAL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4852,7 +4859,9 @@ export class RemoveAllSubstitutesAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attribute used when a move hits a {@linkcode BattlerTagType} for double damage
|
* Attribute used when a move can deal damage to {@linkcode BattlerTagType}
|
||||||
|
* Moves that always hit but do not deal double damage: Thunder, Fissure, Sky Uppercut,
|
||||||
|
* Smack Down, Hurricane, Thousand Arrows
|
||||||
* @extends MoveAttr
|
* @extends MoveAttr
|
||||||
*/
|
*/
|
||||||
export class HitsTagAttr extends MoveAttr {
|
export class HitsTagAttr extends MoveAttr {
|
||||||
@ -4861,7 +4870,7 @@ export class HitsTagAttr extends MoveAttr {
|
|||||||
/** Should this move deal double damage against {@linkcode HitsTagAttr.tagType}? */
|
/** Should this move deal double damage against {@linkcode HitsTagAttr.tagType}? */
|
||||||
public doubleDamage: boolean;
|
public doubleDamage: boolean;
|
||||||
|
|
||||||
constructor(tagType: BattlerTagType, doubleDamage?: boolean) {
|
constructor(tagType: BattlerTagType, doubleDamage: boolean = false) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.tagType = tagType;
|
this.tagType = tagType;
|
||||||
@ -4873,6 +4882,17 @@ export class HitsTagAttr extends MoveAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for moves that will always hit for a given tag but also doubles damage.
|
||||||
|
* Moves include: Gust, Stomp, Body Slam, Surf, Earthquake, Magnitude, Twister,
|
||||||
|
* Whirlpool, Dragon Rush, Heat Crash, Steam Roller, Flying Press
|
||||||
|
*/
|
||||||
|
export class HitsTagForDoubleDamageAttr extends HitsTagAttr {
|
||||||
|
constructor(tagType: BattlerTagType) {
|
||||||
|
super(tagType, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class AddArenaTagAttr extends MoveEffectAttr {
|
export class AddArenaTagAttr extends MoveEffectAttr {
|
||||||
public tagType: ArenaTagType;
|
public tagType: ArenaTagType;
|
||||||
public turnCount: integer;
|
public turnCount: integer;
|
||||||
@ -5201,7 +5221,6 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||||||
switchOutTarget.leaveField(false);
|
switchOutTarget.leaveField(false);
|
||||||
|
|
||||||
if (switchOutTarget.hp) {
|
if (switchOutTarget.hp) {
|
||||||
switchOutTarget.setWildFlee(true);
|
|
||||||
user.scene.queueMessage(i18next.t("moveTriggers:fled", {pokemonName: getPokemonNameWithAffix(switchOutTarget)}), null, true, 500);
|
user.scene.queueMessage(i18next.t("moveTriggers:fled", {pokemonName: getPokemonNameWithAffix(switchOutTarget)}), null, true, 500);
|
||||||
|
|
||||||
// in double battles redirect potential moves off fled pokemon
|
// in double battles redirect potential moves off fled pokemon
|
||||||
@ -6393,7 +6412,7 @@ export class AttackedByItemAttr extends MoveAttr {
|
|||||||
*/
|
*/
|
||||||
getCondition(): MoveConditionFunc {
|
getCondition(): MoveConditionFunc {
|
||||||
return (user: Pokemon, target: Pokemon, move: Move) => {
|
return (user: Pokemon, target: Pokemon, move: Move) => {
|
||||||
const heldItems = target.getHeldItems().filter(i => i.isTransferrable);
|
const heldItems = target.getHeldItems().filter(i => i.isTransferable);
|
||||||
if (heldItems.length === 0) {
|
if (heldItems.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -6752,12 +6771,11 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.CUT, Type.NORMAL, MoveCategory.PHYSICAL, 50, 95, 30, -1, 0, 1)
|
new AttackMove(Moves.CUT, Type.NORMAL, MoveCategory.PHYSICAL, 50, 95, 30, -1, 0, 1)
|
||||||
.slicingMove(),
|
.slicingMove(),
|
||||||
new AttackMove(Moves.GUST, Type.FLYING, MoveCategory.SPECIAL, 40, 100, 35, -1, 0, 1)
|
new AttackMove(Moves.GUST, Type.FLYING, MoveCategory.SPECIAL, 40, 100, 35, -1, 0, 1)
|
||||||
.attr(HitsTagAttr, BattlerTagType.FLYING, true)
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.FLYING)
|
||||||
.windMove(),
|
.windMove(),
|
||||||
new AttackMove(Moves.WING_ATTACK, Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 35, -1, 0, 1),
|
new AttackMove(Moves.WING_ATTACK, Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 35, -1, 0, 1),
|
||||||
new StatusMove(Moves.WHIRLWIND, Type.NORMAL, -1, 20, -1, -6, 1)
|
new StatusMove(Moves.WHIRLWIND, Type.NORMAL, -1, 20, -1, -6, 1)
|
||||||
.attr(ForceSwitchOutAttr)
|
.attr(ForceSwitchOutAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.FLYING, false)
|
|
||||||
.ignoresSubstitute()
|
.ignoresSubstitute()
|
||||||
.hidesTarget()
|
.hidesTarget()
|
||||||
.windMove(),
|
.windMove(),
|
||||||
@ -6770,8 +6788,8 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.SLAM, Type.NORMAL, MoveCategory.PHYSICAL, 80, 75, 20, -1, 0, 1),
|
new AttackMove(Moves.SLAM, Type.NORMAL, MoveCategory.PHYSICAL, 80, 75, 20, -1, 0, 1),
|
||||||
new AttackMove(Moves.VINE_WHIP, Type.GRASS, MoveCategory.PHYSICAL, 45, 100, 25, -1, 0, 1),
|
new AttackMove(Moves.VINE_WHIP, Type.GRASS, MoveCategory.PHYSICAL, 45, 100, 25, -1, 0, 1),
|
||||||
new AttackMove(Moves.STOMP, Type.NORMAL, MoveCategory.PHYSICAL, 65, 100, 20, 30, 0, 1)
|
new AttackMove(Moves.STOMP, Type.NORMAL, MoveCategory.PHYSICAL, 65, 100, 20, 30, 0, 1)
|
||||||
.attr(MinimizeAccuracyAttr)
|
.attr(AlwaysHitMinimizeAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.MINIMIZED, true)
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.MINIMIZED)
|
||||||
.attr(FlinchAttr),
|
.attr(FlinchAttr),
|
||||||
new AttackMove(Moves.DOUBLE_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 30, 100, 30, -1, 0, 1)
|
new AttackMove(Moves.DOUBLE_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 30, 100, 30, -1, 0, 1)
|
||||||
.attr(MultiHitAttr, MultiHitType._2),
|
.attr(MultiHitAttr, MultiHitType._2),
|
||||||
@ -6795,8 +6813,8 @@ export function initMoves() {
|
|||||||
.attr(OneHitKOAccuracyAttr),
|
.attr(OneHitKOAccuracyAttr),
|
||||||
new AttackMove(Moves.TACKLE, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, 0, 1),
|
new AttackMove(Moves.TACKLE, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, 0, 1),
|
||||||
new AttackMove(Moves.BODY_SLAM, Type.NORMAL, MoveCategory.PHYSICAL, 85, 100, 15, 30, 0, 1)
|
new AttackMove(Moves.BODY_SLAM, Type.NORMAL, MoveCategory.PHYSICAL, 85, 100, 15, 30, 0, 1)
|
||||||
.attr(MinimizeAccuracyAttr)
|
.attr(AlwaysHitMinimizeAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.MINIMIZED, true)
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.MINIMIZED)
|
||||||
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
|
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
|
||||||
new AttackMove(Moves.WRAP, Type.NORMAL, MoveCategory.PHYSICAL, 15, 90, 20, -1, 0, 1)
|
new AttackMove(Moves.WRAP, Type.NORMAL, MoveCategory.PHYSICAL, 15, 90, 20, -1, 0, 1)
|
||||||
.attr(TrapAttr, BattlerTagType.WRAP),
|
.attr(TrapAttr, BattlerTagType.WRAP),
|
||||||
@ -6864,7 +6882,7 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.HYDRO_PUMP, Type.WATER, MoveCategory.SPECIAL, 110, 80, 5, -1, 0, 1),
|
new AttackMove(Moves.HYDRO_PUMP, Type.WATER, MoveCategory.SPECIAL, 110, 80, 5, -1, 0, 1),
|
||||||
new AttackMove(Moves.SURF, Type.WATER, MoveCategory.SPECIAL, 90, 100, 15, -1, 0, 1)
|
new AttackMove(Moves.SURF, Type.WATER, MoveCategory.SPECIAL, 90, 100, 15, -1, 0, 1)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS)
|
.target(MoveTarget.ALL_NEAR_OTHERS)
|
||||||
.attr(HitsTagAttr, BattlerTagType.UNDERWATER, true)
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.UNDERWATER)
|
||||||
.attr(GulpMissileTagAttr),
|
.attr(GulpMissileTagAttr),
|
||||||
new AttackMove(Moves.ICE_BEAM, Type.ICE, MoveCategory.SPECIAL, 90, 100, 10, 10, 0, 1)
|
new AttackMove(Moves.ICE_BEAM, Type.ICE, MoveCategory.SPECIAL, 90, 100, 10, 10, 0, 1)
|
||||||
.attr(StatusEffectAttr, StatusEffect.FREEZE),
|
.attr(StatusEffectAttr, StatusEffect.FREEZE),
|
||||||
@ -6947,18 +6965,18 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.THUNDER, Type.ELECTRIC, MoveCategory.SPECIAL, 110, 70, 10, 30, 0, 1)
|
new AttackMove(Moves.THUNDER, Type.ELECTRIC, MoveCategory.SPECIAL, 110, 70, 10, 30, 0, 1)
|
||||||
.attr(StatusEffectAttr, StatusEffect.PARALYSIS)
|
.attr(StatusEffectAttr, StatusEffect.PARALYSIS)
|
||||||
.attr(ThunderAccuracyAttr)
|
.attr(ThunderAccuracyAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.FLYING, false),
|
.attr(HitsTagAttr, BattlerTagType.FLYING),
|
||||||
new AttackMove(Moves.ROCK_THROW, Type.ROCK, MoveCategory.PHYSICAL, 50, 90, 15, -1, 0, 1)
|
new AttackMove(Moves.ROCK_THROW, Type.ROCK, MoveCategory.PHYSICAL, 50, 90, 15, -1, 0, 1)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.EARTHQUAKE, Type.GROUND, MoveCategory.PHYSICAL, 100, 100, 10, -1, 0, 1)
|
new AttackMove(Moves.EARTHQUAKE, Type.GROUND, MoveCategory.PHYSICAL, 100, 100, 10, -1, 0, 1)
|
||||||
.attr(HitsTagAttr, BattlerTagType.UNDERGROUND, true)
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.UNDERGROUND)
|
||||||
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.GRASSY ? 0.5 : 1)
|
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.GRASSY && target.isGrounded() ? 0.5 : 1)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS),
|
.target(MoveTarget.ALL_NEAR_OTHERS),
|
||||||
new AttackMove(Moves.FISSURE, Type.GROUND, MoveCategory.PHYSICAL, 200, 30, 5, -1, 0, 1)
|
new AttackMove(Moves.FISSURE, Type.GROUND, MoveCategory.PHYSICAL, 200, 30, 5, -1, 0, 1)
|
||||||
.attr(OneHitKOAttr)
|
.attr(OneHitKOAttr)
|
||||||
.attr(OneHitKOAccuracyAttr)
|
.attr(OneHitKOAccuracyAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.UNDERGROUND, false)
|
.attr(HitsTagAttr, BattlerTagType.UNDERGROUND)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.DIG, Type.GROUND, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 1)
|
new AttackMove(Moves.DIG, Type.GROUND, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 1)
|
||||||
.attr(ChargeAttr, ChargeAnim.DIG_CHARGING, i18next.t("moveTriggers:dugAHole", {pokemonName: "{USER}"}), BattlerTagType.UNDERGROUND)
|
.attr(ChargeAttr, ChargeAnim.DIG_CHARGING, i18next.t("moveTriggers:dugAHole", {pokemonName: "{USER}"}), BattlerTagType.UNDERGROUND)
|
||||||
@ -7346,8 +7364,8 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.MAGNITUDE, Type.GROUND, MoveCategory.PHYSICAL, -1, 100, 30, -1, 0, 2)
|
new AttackMove(Moves.MAGNITUDE, Type.GROUND, MoveCategory.PHYSICAL, -1, 100, 30, -1, 0, 2)
|
||||||
.attr(PreMoveMessageAttr, magnitudeMessageFunc)
|
.attr(PreMoveMessageAttr, magnitudeMessageFunc)
|
||||||
.attr(MagnitudePowerAttr)
|
.attr(MagnitudePowerAttr)
|
||||||
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.GRASSY ? 0.5 : 1)
|
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.GRASSY && target.isGrounded() ? 0.5 : 1)
|
||||||
.attr(HitsTagAttr, BattlerTagType.UNDERGROUND, true)
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.UNDERGROUND)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS),
|
.target(MoveTarget.ALL_NEAR_OTHERS),
|
||||||
new AttackMove(Moves.DYNAMIC_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 50, 5, 100, 0, 2)
|
new AttackMove(Moves.DYNAMIC_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 50, 5, 100, 0, 2)
|
||||||
@ -7403,7 +7421,7 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.CROSS_CHOP, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 80, 5, -1, 0, 2)
|
new AttackMove(Moves.CROSS_CHOP, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 80, 5, -1, 0, 2)
|
||||||
.attr(HighCritAttr),
|
.attr(HighCritAttr),
|
||||||
new AttackMove(Moves.TWISTER, Type.DRAGON, MoveCategory.SPECIAL, 40, 100, 20, 20, 0, 2)
|
new AttackMove(Moves.TWISTER, Type.DRAGON, MoveCategory.SPECIAL, 40, 100, 20, 20, 0, 2)
|
||||||
.attr(HitsTagAttr, BattlerTagType.FLYING, true)
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.FLYING)
|
||||||
.attr(FlinchAttr)
|
.attr(FlinchAttr)
|
||||||
.windMove()
|
.windMove()
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||||
@ -7435,7 +7453,7 @@ export function initMoves() {
|
|||||||
.attr(StatStageChangeAttr, [ Stat.DEF ], -1),
|
.attr(StatStageChangeAttr, [ Stat.DEF ], -1),
|
||||||
new AttackMove(Moves.WHIRLPOOL, Type.WATER, MoveCategory.SPECIAL, 35, 85, 15, -1, 0, 2)
|
new AttackMove(Moves.WHIRLPOOL, Type.WATER, MoveCategory.SPECIAL, 35, 85, 15, -1, 0, 2)
|
||||||
.attr(TrapAttr, BattlerTagType.WHIRLPOOL)
|
.attr(TrapAttr, BattlerTagType.WHIRLPOOL)
|
||||||
.attr(HitsTagAttr, BattlerTagType.UNDERWATER, true),
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.UNDERWATER),
|
||||||
new AttackMove(Moves.BEAT_UP, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 2)
|
new AttackMove(Moves.BEAT_UP, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 2)
|
||||||
.attr(MultiHitAttr, MultiHitType.BEAT_UP)
|
.attr(MultiHitAttr, MultiHitType.BEAT_UP)
|
||||||
.attr(BeatUpAttr)
|
.attr(BeatUpAttr)
|
||||||
@ -7533,7 +7551,7 @@ export function initMoves() {
|
|||||||
.attr(AddBattlerTagAttr, BattlerTagType.DROWSY, false, true)
|
.attr(AddBattlerTagAttr, BattlerTagType.DROWSY, false, true)
|
||||||
.condition((user, target, move) => !target.status && !target.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, target.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)),
|
.condition((user, target, move) => !target.status && !target.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, target.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)),
|
||||||
new AttackMove(Moves.KNOCK_OFF, Type.DARK, MoveCategory.PHYSICAL, 65, 100, 20, -1, 0, 3)
|
new AttackMove(Moves.KNOCK_OFF, Type.DARK, MoveCategory.PHYSICAL, 65, 100, 20, -1, 0, 3)
|
||||||
.attr(MovePowerMultiplierAttr, (user, target, move) => target.getHeldItems().filter(i => i.isTransferrable).length > 0 ? 1.5 : 1)
|
.attr(MovePowerMultiplierAttr, (user, target, move) => target.getHeldItems().filter(i => i.isTransferable).length > 0 ? 1.5 : 1)
|
||||||
.attr(RemoveHeldItemAttr, false),
|
.attr(RemoveHeldItemAttr, false),
|
||||||
new AttackMove(Moves.ENDEAVOR, Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 3)
|
new AttackMove(Moves.ENDEAVOR, Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 3)
|
||||||
.attr(MatchHpAttr)
|
.attr(MatchHpAttr)
|
||||||
@ -7889,8 +7907,8 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.DRAGON_PULSE, Type.DRAGON, MoveCategory.SPECIAL, 85, 100, 10, -1, 0, 4)
|
new AttackMove(Moves.DRAGON_PULSE, Type.DRAGON, MoveCategory.SPECIAL, 85, 100, 10, -1, 0, 4)
|
||||||
.pulseMove(),
|
.pulseMove(),
|
||||||
new AttackMove(Moves.DRAGON_RUSH, Type.DRAGON, MoveCategory.PHYSICAL, 100, 75, 10, 20, 0, 4)
|
new AttackMove(Moves.DRAGON_RUSH, Type.DRAGON, MoveCategory.PHYSICAL, 100, 75, 10, 20, 0, 4)
|
||||||
.attr(MinimizeAccuracyAttr)
|
.attr(AlwaysHitMinimizeAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.MINIMIZED, true)
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.MINIMIZED)
|
||||||
.attr(FlinchAttr),
|
.attr(FlinchAttr),
|
||||||
new AttackMove(Moves.POWER_GEM, Type.ROCK, MoveCategory.SPECIAL, 80, 100, 20, -1, 0, 4),
|
new AttackMove(Moves.POWER_GEM, Type.ROCK, MoveCategory.SPECIAL, 80, 100, 20, -1, 0, 4),
|
||||||
new AttackMove(Moves.DRAIN_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 75, 100, 10, -1, 0, 4)
|
new AttackMove(Moves.DRAIN_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 75, 100, 10, -1, 0, 4)
|
||||||
@ -8087,7 +8105,7 @@ export function initMoves() {
|
|||||||
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 1, 1, true)
|
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 1, 1, true)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
|
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
|
||||||
.attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN])
|
.attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN])
|
||||||
.attr(HitsTagAttr, BattlerTagType.FLYING, false)
|
.attr(HitsTagAttr, BattlerTagType.FLYING)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.STORM_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 5)
|
new AttackMove(Moves.STORM_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 5)
|
||||||
.attr(CritOnlyAttr),
|
.attr(CritOnlyAttr),
|
||||||
@ -8100,9 +8118,9 @@ export function initMoves() {
|
|||||||
.attr(StatStageChangeAttr, [ Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true)
|
.attr(StatStageChangeAttr, [ Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true)
|
||||||
.danceMove(),
|
.danceMove(),
|
||||||
new AttackMove(Moves.HEAVY_SLAM, Type.STEEL, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 5)
|
new AttackMove(Moves.HEAVY_SLAM, Type.STEEL, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 5)
|
||||||
.attr(MinimizeAccuracyAttr)
|
.attr(AlwaysHitMinimizeAttr)
|
||||||
.attr(CompareWeightPowerAttr)
|
.attr(CompareWeightPowerAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.MINIMIZED, true),
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.MINIMIZED),
|
||||||
new AttackMove(Moves.SYNCHRONOISE, Type.PSYCHIC, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 5)
|
new AttackMove(Moves.SYNCHRONOISE, Type.PSYCHIC, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 5)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS)
|
.target(MoveTarget.ALL_NEAR_OTHERS)
|
||||||
.condition(unknownTypeCondition)
|
.condition(unknownTypeCondition)
|
||||||
@ -8185,7 +8203,7 @@ export function initMoves() {
|
|||||||
new StatusMove(Moves.QUASH, Type.DARK, 100, 15, -1, 0, 5)
|
new StatusMove(Moves.QUASH, Type.DARK, 100, 15, -1, 0, 5)
|
||||||
.unimplemented(),
|
.unimplemented(),
|
||||||
new AttackMove(Moves.ACROBATICS, Type.FLYING, MoveCategory.PHYSICAL, 55, 100, 15, -1, 0, 5)
|
new AttackMove(Moves.ACROBATICS, Type.FLYING, MoveCategory.PHYSICAL, 55, 100, 15, -1, 0, 5)
|
||||||
.attr(MovePowerMultiplierAttr, (user, target, move) => Math.max(1, 2 - 0.2 * user.getHeldItems().filter(i => i.isTransferrable).reduce((v, m) => v + m.stackCount, 0))),
|
.attr(MovePowerMultiplierAttr, (user, target, move) => Math.max(1, 2 - 0.2 * user.getHeldItems().filter(i => i.isTransferable).reduce((v, m) => v + m.stackCount, 0))),
|
||||||
new StatusMove(Moves.REFLECT_TYPE, Type.NORMAL, -1, 15, -1, 0, 5)
|
new StatusMove(Moves.REFLECT_TYPE, Type.NORMAL, -1, 15, -1, 0, 5)
|
||||||
.ignoresSubstitute()
|
.ignoresSubstitute()
|
||||||
.attr(CopyTypeAttr),
|
.attr(CopyTypeAttr),
|
||||||
@ -8221,7 +8239,7 @@ export function initMoves() {
|
|||||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||||
new AttackMove(Moves.BULLDOZE, Type.GROUND, MoveCategory.PHYSICAL, 60, 100, 20, 100, 0, 5)
|
new AttackMove(Moves.BULLDOZE, Type.GROUND, MoveCategory.PHYSICAL, 60, 100, 20, 100, 0, 5)
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPD ], -1)
|
.attr(StatStageChangeAttr, [ Stat.SPD ], -1)
|
||||||
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.GRASSY ? 0.5 : 1)
|
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.GRASSY && target.isGrounded() ? 0.5 : 1)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS),
|
.target(MoveTarget.ALL_NEAR_OTHERS),
|
||||||
new AttackMove(Moves.FROST_BREATH, Type.ICE, MoveCategory.SPECIAL, 60, 90, 10, 100, 0, 5)
|
new AttackMove(Moves.FROST_BREATH, Type.ICE, MoveCategory.SPECIAL, 60, 90, 10, 100, 0, 5)
|
||||||
@ -8253,12 +8271,14 @@ export function initMoves() {
|
|||||||
.attr(StatStageChangeAttr, [ Stat.DEF ], -1)
|
.attr(StatStageChangeAttr, [ Stat.DEF ], -1)
|
||||||
.slicingMove(),
|
.slicingMove(),
|
||||||
new AttackMove(Moves.HEAT_CRASH, Type.FIRE, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 5)
|
new AttackMove(Moves.HEAT_CRASH, Type.FIRE, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 5)
|
||||||
.attr(MinimizeAccuracyAttr)
|
.attr(AlwaysHitMinimizeAttr)
|
||||||
.attr(CompareWeightPowerAttr)
|
.attr(CompareWeightPowerAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.MINIMIZED, true),
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.MINIMIZED),
|
||||||
new AttackMove(Moves.LEAF_TORNADO, Type.GRASS, MoveCategory.SPECIAL, 65, 90, 10, 50, 0, 5)
|
new AttackMove(Moves.LEAF_TORNADO, Type.GRASS, MoveCategory.SPECIAL, 65, 90, 10, 50, 0, 5)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ACC ], -1),
|
.attr(StatStageChangeAttr, [ Stat.ACC ], -1),
|
||||||
new AttackMove(Moves.STEAMROLLER, Type.BUG, MoveCategory.PHYSICAL, 65, 100, 20, 30, 0, 5)
|
new AttackMove(Moves.STEAMROLLER, Type.BUG, MoveCategory.PHYSICAL, 65, 100, 20, 30, 0, 5)
|
||||||
|
.attr(AlwaysHitMinimizeAttr)
|
||||||
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.MINIMIZED)
|
||||||
.attr(FlinchAttr),
|
.attr(FlinchAttr),
|
||||||
new SelfStatusMove(Moves.COTTON_GUARD, Type.GRASS, -1, 10, -1, 0, 5)
|
new SelfStatusMove(Moves.COTTON_GUARD, Type.GRASS, -1, 10, -1, 0, 5)
|
||||||
.attr(StatStageChangeAttr, [ Stat.DEF ], 3, true),
|
.attr(StatStageChangeAttr, [ Stat.DEF ], 3, true),
|
||||||
@ -8271,7 +8291,7 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.HURRICANE, Type.FLYING, MoveCategory.SPECIAL, 110, 70, 10, 30, 0, 5)
|
new AttackMove(Moves.HURRICANE, Type.FLYING, MoveCategory.SPECIAL, 110, 70, 10, 30, 0, 5)
|
||||||
.attr(ThunderAccuracyAttr)
|
.attr(ThunderAccuracyAttr)
|
||||||
.attr(ConfuseAttr)
|
.attr(ConfuseAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.FLYING, false)
|
.attr(HitsTagAttr, BattlerTagType.FLYING)
|
||||||
.windMove(),
|
.windMove(),
|
||||||
new AttackMove(Moves.HEAD_CHARGE, Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, -1, 0, 5)
|
new AttackMove(Moves.HEAD_CHARGE, Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, -1, 0, 5)
|
||||||
.attr(RecoilAttr)
|
.attr(RecoilAttr)
|
||||||
@ -8325,9 +8345,9 @@ export function initMoves() {
|
|||||||
.attr(LastMoveDoublePowerAttr, Moves.FUSION_FLARE)
|
.attr(LastMoveDoublePowerAttr, Moves.FUSION_FLARE)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.FLYING_PRESS, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 95, 10, -1, 0, 6)
|
new AttackMove(Moves.FLYING_PRESS, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 95, 10, -1, 0, 6)
|
||||||
.attr(MinimizeAccuracyAttr)
|
.attr(AlwaysHitMinimizeAttr)
|
||||||
.attr(FlyingTypeMultiplierAttr)
|
.attr(FlyingTypeMultiplierAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.MINIMIZED, true)
|
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.MINIMIZED)
|
||||||
.condition(failOnGravityCondition),
|
.condition(failOnGravityCondition),
|
||||||
new StatusMove(Moves.MAT_BLOCK, Type.FIGHTING, -1, 10, -1, 0, 6)
|
new StatusMove(Moves.MAT_BLOCK, Type.FIGHTING, -1, 10, -1, 0, 6)
|
||||||
.target(MoveTarget.USER_SIDE)
|
.target(MoveTarget.USER_SIDE)
|
||||||
@ -8498,8 +8518,8 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.THOUSAND_ARROWS, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6)
|
new AttackMove(Moves.THOUSAND_ARROWS, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6)
|
||||||
.attr(NeutralDamageAgainstFlyingTypeMultiplierAttr)
|
.attr(NeutralDamageAgainstFlyingTypeMultiplierAttr)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 1, 1, true)
|
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 1, 1, true)
|
||||||
.attr(HitsTagAttr, BattlerTagType.FLYING, false)
|
.attr(HitsTagAttr, BattlerTagType.FLYING)
|
||||||
.attr(HitsTagAttr, BattlerTagType.MAGNET_RISEN, false)
|
.attr(HitsTagAttr, BattlerTagType.MAGNET_RISEN)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
|
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
|
||||||
.attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN])
|
.attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN])
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
@ -8756,6 +8776,8 @@ export function initMoves() {
|
|||||||
.partial()
|
.partial()
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new AttackMove(Moves.MALICIOUS_MOONSAULT, Type.DARK, MoveCategory.PHYSICAL, 180, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.MALICIOUS_MOONSAULT, Type.DARK, MoveCategory.PHYSICAL, 180, -1, 1, -1, 0, 7)
|
||||||
|
.attr(AlwaysHitMinimizeAttr)
|
||||||
|
.attr(HitsTagAttr, BattlerTagType.MINIMIZED, true)
|
||||||
.partial()
|
.partial()
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new AttackMove(Moves.OCEANIC_OPERETTA, Type.WATER, MoveCategory.SPECIAL, 195, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.OCEANIC_OPERETTA, Type.WATER, MoveCategory.SPECIAL, 195, -1, 1, -1, 0, 7)
|
||||||
@ -9103,7 +9125,7 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.SHELL_SIDE_ARM, Type.POISON, MoveCategory.SPECIAL, 90, 100, 10, 20, 0, 8)
|
new AttackMove(Moves.SHELL_SIDE_ARM, Type.POISON, MoveCategory.SPECIAL, 90, 100, 10, 20, 0, 8)
|
||||||
.attr(ShellSideArmCategoryAttr)
|
.attr(ShellSideArmCategoryAttr)
|
||||||
.attr(StatusEffectAttr, StatusEffect.POISON)
|
.attr(StatusEffectAttr, StatusEffect.POISON)
|
||||||
.partial(),
|
.partial(), // Physical version of the move does not make contact
|
||||||
new AttackMove(Moves.MISTY_EXPLOSION, Type.FAIRY, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 8)
|
new AttackMove(Moves.MISTY_EXPLOSION, Type.FAIRY, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 8)
|
||||||
.attr(SacrificialAttr)
|
.attr(SacrificialAttr)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS)
|
.target(MoveTarget.ALL_NEAR_OTHERS)
|
||||||
|
@ -2,7 +2,7 @@ import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattl
|
|||||||
import { trainerConfigs, } from "#app/data/trainer-config";
|
import { trainerConfigs, } from "#app/data/trainer-config";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { 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 { Species } from "#enums/species";
|
||||||
@ -99,7 +99,7 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
|||||||
const trainerConfig = trainerConfigs[trainerType].clone();
|
const trainerConfig = trainerConfigs[trainerType].clone();
|
||||||
const trainerSpriteKey = trainerConfig.getSpriteKey();
|
const trainerSpriteKey = trainerConfig.getSpriteKey();
|
||||||
encounter.enemyPartyConfigs.push({
|
encounter.enemyPartyConfigs.push({
|
||||||
levelAdditiveMultiplier: 1,
|
levelAdditiveModifier: 1,
|
||||||
trainerConfig: trainerConfig
|
trainerConfig: trainerConfig
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -152,7 +152,6 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
|||||||
};
|
};
|
||||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}.eggTypes.epic`));
|
encounter.setDialogueToken("eggType", i18next.t(`${namespace}.eggTypes.epic`));
|
||||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH], guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA], fillRemaining: true }, [eggOptions]);
|
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH], guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA], fillRemaining: true }, [eggOptions]);
|
||||||
|
|
||||||
return initBattleWithEnemyConfig(scene, config);
|
return initBattleWithEnemyConfig(scene, config);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -180,7 +179,7 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
|||||||
)
|
)
|
||||||
.withOutroDialogue([
|
.withOutroDialogue([
|
||||||
{
|
{
|
||||||
text: `${namespace}.outro`,
|
text: `${namespace}.outro`
|
||||||
},
|
}
|
||||||
])
|
])
|
||||||
.build();
|
.build();
|
||||||
|
@ -4,9 +4,9 @@ import { BerryModifierType, modifierTypes, PokemonHeldItemModifierType } from "#
|
|||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { PersistentModifierRequirement } from "../mystery-encounter-requirements";
|
import { PersistentModifierRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage } 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";
|
||||||
@ -208,7 +208,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
|||||||
|
|
||||||
// Calculate boss mon
|
// Calculate boss mon
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
levelAdditiveMultiplier: 1,
|
levelAdditiveModifier: 1,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
species: getPokemonSpecies(Species.GREEDENT),
|
species: getPokemonSpecies(Species.GREEDENT),
|
||||||
@ -291,7 +291,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
|||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
const berryMap = encounter.misc.berryItemsMap;
|
const berryMap = encounter.misc.berryItemsMap;
|
||||||
|
|
||||||
// Returns 2/5 of the berries stolen from each Pokemon
|
// Returns 2/5 of the berries stolen to each Pokemon
|
||||||
const party = scene.getParty();
|
const party = scene.getParty();
|
||||||
party.forEach(pokemon => {
|
party.forEach(pokemon => {
|
||||||
const stolenBerries: BerryModifier[] = berryMap.get(pokemon.id);
|
const stolenBerries: BerryModifier[] = berryMap.get(pokemon.id);
|
||||||
@ -310,6 +310,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
await scene.updateModifiers(true);
|
||||||
|
|
||||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||||
leaveEncounterWithoutBattle(scene, true);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
|
@ -3,9 +3,9 @@ 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 { Species } from "#enums/species";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { AbilityRequirement, CombinationPokemonRequirement, MoveRequirement } from "../mystery-encounter-requirements";
|
import { AbilityRequirement, CombinationPokemonRequirement, MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import { getHighestStatTotalPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { getHighestStatTotalPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { EXTORTION_ABILITIES, EXTORTION_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
import { EXTORTION_ABILITIES, EXTORTION_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
|
@ -17,13 +17,13 @@ import { randSeedInt } from "#app/utils";
|
|||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
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 { 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 { TrainerSlot } from "#app/data/trainer-config";
|
import { TrainerSlot } from "#app/data/trainer-config";
|
||||||
import { applyModifierTypeToPlayerPokemon, getHighestStatPlayerPokemon, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { applyModifierTypeToPlayerPokemon, getEncounterPokemonLevelForWave, getHighestStatPlayerPokemon, getSpriteKeysFromPokemon, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
import { BerryModifier } from "#app/modifier/modifier";
|
import { BerryModifier } from "#app/modifier/modifier";
|
||||||
import i18next from "#app/plugins/i18n";
|
import i18next from "#app/plugins/i18n";
|
||||||
@ -56,12 +56,11 @@ export const BerriesAboundEncounter: MysteryEncounter =
|
|||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
|
|
||||||
// Calculate boss mon
|
// Calculate boss mon
|
||||||
const level = (scene.currentBattle.enemyLevels?.[0] ?? scene.currentBattle.waveIndex) + Math.max(Math.round((scene.currentBattle.waveIndex / 10)), 0);
|
const level = getEncounterPokemonLevelForWave(scene, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER);
|
||||||
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true);
|
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true);
|
||||||
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
||||||
encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon));
|
encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon));
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
levelAdditiveMultiplier: 1,
|
|
||||||
pokemonConfigs: [{
|
pokemonConfigs: [{
|
||||||
level: level,
|
level: level,
|
||||||
species: bossSpecies,
|
species: bossSpecies,
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
transitionMysteryEncounterIntroVisuals,
|
transitionMysteryEncounterIntroVisuals,
|
||||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import {
|
import {
|
||||||
|
getRandomPartyMemberFunc,
|
||||||
trainerConfigs,
|
trainerConfigs,
|
||||||
TrainerPartyCompoundTemplate,
|
TrainerPartyCompoundTemplate,
|
||||||
TrainerPartyTemplate,
|
TrainerPartyTemplate,
|
||||||
@ -17,14 +18,12 @@ import {
|
|||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import * as Utils from "#app/utils";
|
|
||||||
import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils";
|
import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { 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 { Species } from "#enums/species";
|
||||||
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
import Pokemon, { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
|
||||||
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 { LearnMovePhase } from "#app/phases/learn-move-phase";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
@ -192,6 +191,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
|||||||
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1),
|
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1),
|
||||||
new TypeRequirement(Type.BUG, false, 1)
|
new TypeRequirement(Type.BUG, false, 1)
|
||||||
))
|
))
|
||||||
|
.withMaxAllowedEncounters(1)
|
||||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||||
.withIntroSpriteConfigs([]) // These are set in onInit()
|
.withIntroSpriteConfigs([]) // These are set in onInit()
|
||||||
.withAutoHideIntroVisuals(false)
|
.withAutoHideIntroVisuals(false)
|
||||||
@ -286,7 +286,8 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
|||||||
|
|
||||||
// Player gets different rewards depending on the number of bug types they have
|
// Player gets different rewards depending on the number of bug types they have
|
||||||
const numBugTypes = scene.getParty().filter(p => p.isOfType(Type.BUG, true)).length;
|
const numBugTypes = scene.getParty().filter(p => p.isOfType(Type.BUG, true)).length;
|
||||||
encounter.setDialogueToken("numBugTypes", numBugTypes.toString());
|
const numBugTypesText = i18next.t(`${namespace}.numBugTypes`, { count: numBugTypes });
|
||||||
|
encounter.setDialogueToken("numBugTypes", numBugTypesText);
|
||||||
|
|
||||||
if (numBugTypes < 2) {
|
if (numBugTypes < 2) {
|
||||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SUPER_LURE, modifierTypes.GREAT_BALL], fillRemaining: false });
|
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SUPER_LURE, modifierTypes.GREAT_BALL], fillRemaining: false });
|
||||||
@ -582,16 +583,6 @@ function getTrainerConfigForWave(waveIndex: number) {
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandomPartyMemberFunc(speciesPool: Species[], trainerSlot: TrainerSlot = TrainerSlot.TRAINER, ignoreEvolution: boolean = false, postProcess?: (enemyPokemon: EnemyPokemon) => void) {
|
|
||||||
return (scene: BattleScene, level: number, strength: PartyMemberStrength) => {
|
|
||||||
let species = Utils.randSeedItem(speciesPool);
|
|
||||||
if (!ignoreEvolution) {
|
|
||||||
species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength);
|
|
||||||
}
|
|
||||||
return scene.addEnemyPokemon(getPokemonSpecies(species), level, trainerSlot, undefined, undefined, postProcess);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function doBugTypeMoveTutor(scene: BattleScene): Promise<void> {
|
function doBugTypeMoveTutor(scene: BattleScene): Promise<void> {
|
||||||
return new Promise<void>(async resolve => {
|
return new Promise<void>(async resolve => {
|
||||||
const moveOptions = scene.currentBattle.mysteryEncounter!.misc.moveTutorOptions;
|
const moveOptions = scene.currentBattle.mysteryEncounter!.misc.moveTutorOptions;
|
||||||
|
@ -5,7 +5,7 @@ import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifi
|
|||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { 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 { Species } from "#enums/species";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
@ -246,12 +246,12 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||||||
const party = scene.getParty();
|
const party = scene.getParty();
|
||||||
let mostHeldItemsPokemon = party[0];
|
let mostHeldItemsPokemon = party[0];
|
||||||
let count = mostHeldItemsPokemon.getHeldItems()
|
let count = mostHeldItemsPokemon.getHeldItems()
|
||||||
.filter(m => m.isTransferrable && !(m instanceof BerryModifier))
|
.filter(m => m.isTransferable && !(m instanceof BerryModifier))
|
||||||
.reduce((v, m) => v + m.stackCount, 0);
|
.reduce((v, m) => v + m.stackCount, 0);
|
||||||
|
|
||||||
party.forEach(pokemon => {
|
party.forEach(pokemon => {
|
||||||
const nextCount = pokemon.getHeldItems()
|
const nextCount = pokemon.getHeldItems()
|
||||||
.filter(m => m.isTransferrable && !(m instanceof BerryModifier))
|
.filter(m => m.isTransferable && !(m instanceof BerryModifier))
|
||||||
.reduce((v, m) => v + m.stackCount, 0);
|
.reduce((v, m) => v + m.stackCount, 0);
|
||||||
if (nextCount > count) {
|
if (nextCount > count) {
|
||||||
mostHeldItemsPokemon = pokemon;
|
mostHeldItemsPokemon = pokemon;
|
||||||
@ -276,7 +276,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||||||
// Shuffle Transferable held items in the same tier (only shuffles Ultra and Rogue atm)
|
// Shuffle Transferable held items in the same tier (only shuffles Ultra and Rogue atm)
|
||||||
let numUltra = 0;
|
let numUltra = 0;
|
||||||
let numRogue = 0;
|
let numRogue = 0;
|
||||||
items.filter(m => m.isTransferrable && !(m instanceof BerryModifier))
|
items.filter(m => m.isTransferable && !(m instanceof BerryModifier))
|
||||||
.forEach(m => {
|
.forEach(m => {
|
||||||
const type = m.type.withTierFromPool();
|
const type = m.type.withTierFromPool();
|
||||||
const tier = type.tier ?? ModifierTier.ULTRA;
|
const tier = type.tier ?? ModifierTier.ULTRA;
|
||||||
|
@ -3,8 +3,8 @@ import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/po
|
|||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../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 { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
@ -19,7 +19,7 @@ import { MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-
|
|||||||
import { DANCING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
import { DANCING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#app/battle";
|
||||||
import { catchPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { catchPokemon, getEncounterPokemonLevelForWave, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { PokeballType } from "#enums/pokeball";
|
import { PokeballType } from "#enums/pokeball";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
||||||
@ -107,7 +107,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
|
|
||||||
const species = getPokemonSpecies(Species.ORICORIO);
|
const species = getPokemonSpecies(Species.ORICORIO);
|
||||||
const level = (scene.currentBattle.enemyLevels?.[0] ?? scene.currentBattle.waveIndex) + Math.max(Math.round((scene.currentBattle.waveIndex / 10)), 0);
|
const level = getEncounterPokemonLevelForWave(scene, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER);
|
||||||
const enemyPokemon = new EnemyPokemon(scene, species, level, TrainerSlot.NONE, false);
|
const enemyPokemon = new EnemyPokemon(scene, 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 === Moves.REVELATION_DANCE)) {
|
||||||
if (enemyPokemon.moveset.length < 4) {
|
if (enemyPokemon.moveset.length < 4) {
|
||||||
@ -133,7 +133,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||||||
}
|
}
|
||||||
|
|
||||||
const oricorioData = new PokemonData(enemyPokemon);
|
const oricorioData = new PokemonData(enemyPokemon);
|
||||||
const oricorio = scene.addEnemyPokemon(species, scene.currentBattle.enemyLevels![0], TrainerSlot.NONE, false, oricorioData);
|
const oricorio = scene.addEnemyPokemon(species, level, TrainerSlot.NONE, false, oricorioData);
|
||||||
|
|
||||||
// Adds a real Pokemon sprite to the field (required for the animation)
|
// Adds a real Pokemon sprite to the field (required for the animation)
|
||||||
scene.getEnemyParty().forEach(enemyPokemon => {
|
scene.getEnemyParty().forEach(enemyPokemon => {
|
||||||
@ -146,7 +146,6 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||||||
encounter.loadAssets.push(oricorio.loadAssets());
|
encounter.loadAssets.push(oricorio.loadAssets());
|
||||||
|
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
levelAdditiveMultiplier: 1,
|
|
||||||
pokemonConfigs: [{
|
pokemonConfigs: [{
|
||||||
species: species,
|
species: species,
|
||||||
dataSource: oricorioData,
|
dataSource: oricorioData,
|
||||||
|
@ -5,8 +5,8 @@ import { Species } from "#enums/species";
|
|||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-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";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, } from "../utils/encounter-phase-utils";
|
import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, } from "../utils/encounter-phase-utils";
|
||||||
import { getRandomPlayerPokemon, getRandomSpeciesByStarterTier } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { getRandomPlayerPokemon, getRandomSpeciesByStarterTier } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
@ -18,7 +18,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
|||||||
/** i18n namespace for encounter */
|
/** i18n namespace for encounter */
|
||||||
const namespace = "mysteryEncounter:darkDeal";
|
const namespace = "mysteryEncounter:darkDeal";
|
||||||
|
|
||||||
/** Exclude Ultra Beasts (inludes Cosmog/Solgaleo/Lunala/Necrozma), Paradox (includes Miraidon/Koraidon), Eternatus, and egg-locked mythicals */
|
/** Exclude Ultra Beasts (inludes Cosmog/Solgaleo/Lunala/Necrozma), Paradox (includes Miraidon/Koraidon), Eternatus, and Mythicals */
|
||||||
const excludedBosses = [
|
const excludedBosses = [
|
||||||
Species.NECROZMA,
|
Species.NECROZMA,
|
||||||
Species.COSMOG,
|
Species.COSMOG,
|
||||||
@ -63,11 +63,24 @@ const excludedBosses = [
|
|||||||
Species.CELEBI,
|
Species.CELEBI,
|
||||||
Species.DEOXYS,
|
Species.DEOXYS,
|
||||||
Species.JIRACHI,
|
Species.JIRACHI,
|
||||||
|
Species.DARKRAI,
|
||||||
Species.PHIONE,
|
Species.PHIONE,
|
||||||
Species.MANAPHY,
|
Species.MANAPHY,
|
||||||
Species.ARCEUS,
|
Species.ARCEUS,
|
||||||
|
Species.SHAYMIN,
|
||||||
Species.VICTINI,
|
Species.VICTINI,
|
||||||
|
Species.MELOETTA,
|
||||||
|
Species.KELDEO,
|
||||||
|
Species.GENESECT,
|
||||||
|
Species.DIANCIE,
|
||||||
|
Species.HOOPA,
|
||||||
|
Species.VOLCANION,
|
||||||
|
Species.MAGEARNA,
|
||||||
|
Species.MARSHADOW,
|
||||||
|
Species.ZERAORA,
|
||||||
|
Species.ZARUDE,
|
||||||
Species.MELTAN,
|
Species.MELTAN,
|
||||||
|
Species.MELMETAL,
|
||||||
Species.PECHARUNT,
|
Species.PECHARUNT,
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -151,7 +164,7 @@ export const DarkDealEncounter: MysteryEncounter =
|
|||||||
// Starter egg tier, 35/50/10/5 %odds for tiers 6/7/8/9+
|
// Starter egg tier, 35/50/10/5 %odds for tiers 6/7/8/9+
|
||||||
const roll = randSeedInt(100);
|
const roll = randSeedInt(100);
|
||||||
const starterTier: number | [number, number] =
|
const starterTier: number | [number, number] =
|
||||||
roll > 65 ? 6 : roll > 15 ? 7 : roll > 5 ? 8 : [9, 10];
|
roll >= 65 ? 6 : roll >= 15 ? 7 : roll >= 5 ? 8 : [9, 10];
|
||||||
const bossSpecies = getPokemonSpecies(getRandomSpeciesByStarterTier(starterTier, excludedBosses, bossTypes));
|
const bossSpecies = getPokemonSpecies(getRandomSpeciesByStarterTier(starterTier, excludedBosses, bossTypes));
|
||||||
const pokemonConfig: EnemyPokemonConfig = {
|
const pokemonConfig: EnemyPokemonConfig = {
|
||||||
species: bossSpecies,
|
species: bossSpecies,
|
||||||
|
@ -4,9 +4,9 @@ import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifi
|
|||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { CombinationPokemonRequirement, HeldItemRequirement, MoneyRequirement } from "../mystery-encounter-requirements";
|
import { CombinationPokemonRequirement, HeldItemRequirement, MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText, 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";
|
||||||
@ -33,6 +33,8 @@ const OPTION_3_DISALLOWED_MODIFIERS = [
|
|||||||
"PokemonBaseStatTotalModifier"
|
"PokemonBaseStatTotalModifier"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const DELIBIRDY_MONEY_PRICE_MULTIPLIER = 1.5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delibird-y encounter.
|
* Delibird-y encounter.
|
||||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3804 | GitHub Issue #3804}
|
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3804 | GitHub Issue #3804}
|
||||||
@ -42,7 +44,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DELIBIRDY)
|
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DELIBIRDY)
|
||||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||||
.withSceneRequirement(new MoneyRequirement(0, 2)) // Must have enough money for it to spawn at the very least
|
.withSceneRequirement(new MoneyRequirement(0, DELIBIRDY_MONEY_PRICE_MULTIPLIER)) // Must have enough money for it to spawn at the very least
|
||||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement( // Must also have either option 2 or 3 available to spawn
|
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement( // Must also have either option 2 or 3 available to spawn
|
||||||
new HeldItemRequirement(OPTION_2_ALLOWED_MODIFIERS),
|
new HeldItemRequirement(OPTION_2_ALLOWED_MODIFIERS),
|
||||||
new HeldItemRequirement(OPTION_3_DISALLOWED_MODIFIERS, 1, true)
|
new HeldItemRequirement(OPTION_3_DISALLOWED_MODIFIERS, 1, true)
|
||||||
@ -93,12 +95,18 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||||||
.withOnInit((scene: BattleScene) => {
|
.withOnInit((scene: BattleScene) => {
|
||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
encounter.setDialogueToken("delibirdName", getPokemonSpecies(Species.DELIBIRD).getName());
|
encounter.setDialogueToken("delibirdName", getPokemonSpecies(Species.DELIBIRD).getName());
|
||||||
|
|
||||||
|
scene.loadBgm("mystery_encounter_delibirdy", "mystery_encounter_delibirdy.mp3");
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.withOnVisualsStart((scene: BattleScene) => {
|
||||||
|
scene.fadeAndSwitchBgm("mystery_encounter_delibirdy");
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||||
.withSceneMoneyRequirement(0, 2) // Must have money to spawn
|
.withSceneMoneyRequirement(0, DELIBIRDY_MONEY_PRICE_MULTIPLIER) // Must have money to spawn
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}.option.1.label`,
|
buttonLabel: `${namespace}.option.1.label`,
|
||||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||||
|
@ -9,7 +9,7 @@ import { Species } from "#enums/species";
|
|||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, {
|
import MysteryEncounter, {
|
||||||
MysteryEncounterBuilder,
|
MysteryEncounterBuilder,
|
||||||
} from "../mystery-encounter";
|
} from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import { modifierTypes } from "#app/modifier/modifier-type";
|
|||||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
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 { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
|
@ -3,8 +3,8 @@ import { EnemyPartyConfig, initBattleWithEnemyConfig, loadCustomMovesForEncounte
|
|||||||
import { AttackTypeBoosterModifierType, modifierTypes, } from "#app/modifier/modifier-type";
|
import { AttackTypeBoosterModifierType, modifierTypes, } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { TypeRequirement } from "../mystery-encounter-requirements";
|
import { TypeRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
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";
|
||||||
|
@ -17,12 +17,12 @@ import {
|
|||||||
} from "#app/modifier/modifier-type";
|
} from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MoveRequirement } from "../mystery-encounter-requirements";
|
import { MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
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 { TrainerSlot } from "#app/data/trainer-config";
|
import { TrainerSlot } from "#app/data/trainer-config";
|
||||||
import { getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { getEncounterPokemonLevelForWave, getSpriteKeysFromPokemon, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
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";
|
||||||
@ -54,12 +54,11 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
|||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
|
|
||||||
// Calculate boss mon
|
// Calculate boss mon
|
||||||
const level = (scene.currentBattle.enemyLevels?.[0] ?? scene.currentBattle.waveIndex) + Math.max(Math.round((scene.currentBattle.waveIndex / 10)), 0);
|
const level = getEncounterPokemonLevelForWave(scene, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER);
|
||||||
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true);
|
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true);
|
||||||
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
||||||
encounter.setDialogueToken("enemyPokemon", bossPokemon.getNameToRender());
|
encounter.setDialogueToken("enemyPokemon", bossPokemon.getNameToRender());
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
levelAdditiveMultiplier: 1,
|
|
||||||
pokemonConfigs: [{
|
pokemonConfigs: [{
|
||||||
level: level,
|
level: level,
|
||||||
species: bossSpecies,
|
species: bossSpecies,
|
||||||
@ -69,7 +68,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
|||||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.stat_boost`);
|
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.stat_boost`);
|
||||||
// Randomly boost 1 stat 2 stages
|
// Randomly boost 1 stat 2 stages
|
||||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [randSeedInt(5)], 2));
|
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [randSeedInt(4, 1)], 2));
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import { leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { TrainerSlot } from "#app/data/trainer-config";
|
import { TrainerSlot } from "#app/data/trainer-config";
|
||||||
import Pokemon, { FieldPosition, PlayerPokemon } from "#app/field/pokemon";
|
import Pokemon, { FieldPosition, PlayerPokemon } from "#app/field/pokemon";
|
||||||
@ -84,12 +84,7 @@ export const FunAndGamesEncounter: MysteryEncounter =
|
|||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.withOnVisualsStart((scene: BattleScene) => {
|
.withOnVisualsStart((scene: BattleScene) => {
|
||||||
// Change the bgm
|
scene.fadeAndSwitchBgm("mystery_encounter_fun_and_games");
|
||||||
scene.fadeOutBgm(2000, false);
|
|
||||||
scene.time.delayedCall(2000, () => {
|
|
||||||
scene.playBgm("mystery_encounter_fun_and_games");
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.withOption(MysteryEncounterOptionBuilder
|
.withOption(MysteryEncounterOptionBuilder
|
||||||
@ -175,7 +170,9 @@ async function summonPlayerPokemon(scene: BattleScene) {
|
|||||||
const party = scene.getParty();
|
const party = scene.getParty();
|
||||||
const chosenIndex = party.indexOf(playerPokemon);
|
const chosenIndex = party.indexOf(playerPokemon);
|
||||||
if (chosenIndex !== 0) {
|
if (chosenIndex !== 0) {
|
||||||
[party[chosenIndex], party[0]] = [party[chosenIndex], party[chosenIndex]];
|
const leadPokemon = party[0];
|
||||||
|
party[0] = playerPokemon;
|
||||||
|
party[chosenIndex] = leadPokemon;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do trainer summon animation
|
// Do trainer summon animation
|
||||||
|
@ -4,7 +4,7 @@ import { ModifierTier } from "#app/modifier/modifier-tier";
|
|||||||
import { getPlayerModifierTypeOptions, ModifierPoolType, ModifierTypeOption, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
import { getPlayerModifierTypeOptions, ModifierPoolType, ModifierTypeOption, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { 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 { Species } from "#enums/species";
|
||||||
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
@ -23,6 +23,7 @@ import { getPokeballAtlasKey, getPokeballTintColor, PokeballType } from "#app/da
|
|||||||
import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { trainerNamePools } from "#app/data/trainer-names";
|
import { trainerNamePools } from "#app/data/trainer-names";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
|
import { addPokemonDataToDexAndValidateAchievements } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounter:globalTradeSystem";
|
const namespace = "mysteryEncounter:globalTradeSystem";
|
||||||
@ -118,17 +119,13 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
|||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.withOnVisualsStart((scene: BattleScene) => {
|
.withOnVisualsStart((scene: BattleScene) => {
|
||||||
// Change the bgm
|
scene.fadeAndSwitchBgm(scene.currentBattle.mysteryEncounter!.misc.bgmKey);
|
||||||
scene.fadeOutBgm(1500, false);
|
|
||||||
scene.time.delayedCall(1500, () => {
|
|
||||||
scene.playBgm(scene.currentBattle.mysteryEncounter!.misc.bgmKey);
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
|
.withHasDexProgress(true)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}.option.1.label`,
|
buttonLabel: `${namespace}.option.1.label`,
|
||||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||||
@ -200,6 +197,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
|||||||
await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon);
|
await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon);
|
||||||
await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000);
|
await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000);
|
||||||
scene.playBgm(encounter.misc.bgmKey);
|
scene.playBgm(encounter.misc.bgmKey);
|
||||||
|
await addPokemonDataToDexAndValidateAchievements(scene, newPlayerPokemon);
|
||||||
await hideTradeBackground(scene);
|
await hideTradeBackground(scene);
|
||||||
tradedPokemon.destroy();
|
tradedPokemon.destroy();
|
||||||
|
|
||||||
@ -210,6 +208,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
|||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
|
.withHasDexProgress(true)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}.option.2.label`,
|
buttonLabel: `${namespace}.option.2.label`,
|
||||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||||
@ -218,8 +217,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
|||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
// Randomly generate a Wonder Trade pokemon
|
// Randomly generate a Wonder Trade pokemon
|
||||||
// const randomTradeOption = generateTradeOption(scene.getParty().map(p => p.species));
|
const randomTradeOption = generateTradeOption(scene.getParty().map(p => p.species));
|
||||||
const randomTradeOption = getPokemonSpecies(Species.BURMY);
|
|
||||||
const tradePokemon = new EnemyPokemon(scene, randomTradeOption, pokemon.level, TrainerSlot.NONE, false);
|
const tradePokemon = new EnemyPokemon(scene, randomTradeOption, pokemon.level, TrainerSlot.NONE, false);
|
||||||
// Extra shiny roll at 1/128 odds (boosted by events and charms)
|
// Extra shiny roll at 1/128 odds (boosted by events and charms)
|
||||||
if (!tradePokemon.shiny) {
|
if (!tradePokemon.shiny) {
|
||||||
@ -280,7 +278,8 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
|||||||
await showTradeBackground(scene);
|
await showTradeBackground(scene);
|
||||||
await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon);
|
await doPokemonTradeSequence(scene, tradedPokemon, newPlayerPokemon);
|
||||||
await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000);
|
await showEncounterText(scene, `${namespace}.trade_received`, null, 0, true, 4000);
|
||||||
scene.playBgm(scene.currentBattle.mysteryEncounter!.misc.bgmKey);
|
scene.playBgm(encounter.misc.bgmKey);
|
||||||
|
await addPokemonDataToDexAndValidateAchievements(scene, newPlayerPokemon);
|
||||||
await hideTradeBackground(scene);
|
await hideTradeBackground(scene);
|
||||||
tradedPokemon.destroy();
|
tradedPokemon.destroy();
|
||||||
|
|
||||||
@ -301,7 +300,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
|||||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
// Get Pokemon held items and filter for valid ones
|
// Get Pokemon held items and filter for valid ones
|
||||||
const validItems = pokemon.getHeldItems().filter((it) => {
|
const validItems = pokemon.getHeldItems().filter((it) => {
|
||||||
return it.isTransferrable;
|
return it.isTransferable;
|
||||||
});
|
});
|
||||||
|
|
||||||
return validItems.map((modifier: PokemonHeldItemModifier) => {
|
return validItems.map((modifier: PokemonHeldItemModifier) => {
|
||||||
@ -322,7 +321,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
|||||||
const selectableFilter = (pokemon: Pokemon) => {
|
const selectableFilter = (pokemon: Pokemon) => {
|
||||||
// If pokemon has items to trade
|
// If pokemon has items to trade
|
||||||
const meetsReqs = pokemon.getHeldItems().filter((it) => {
|
const meetsReqs = pokemon.getHeldItems().filter((it) => {
|
||||||
return it.isTransferrable;
|
return it.isTransferable;
|
||||||
}).length > 0;
|
}).length > 0;
|
||||||
if (!meetsReqs) {
|
if (!meetsReqs) {
|
||||||
return getEncounterText(scene, `${namespace}.option.3.invalid_selection`) ?? null;
|
return getEncounterText(scene, `${namespace}.option.3.invalid_selection`) ?? null;
|
||||||
|
@ -3,8 +3,8 @@ import { Moves } from "#app/enums/moves";
|
|||||||
import { Species } from "#app/enums/species";
|
import { Species } from "#app/enums/species";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { leaveEncounterWithoutBattle, setEncounterExp } from "../utils/encounter-phase-utils";
|
import { leaveEncounterWithoutBattle, setEncounterExp } from "../utils/encounter-phase-utils";
|
||||||
import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
@ -15,7 +15,7 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
|||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import * as Utils from "#app/utils";
|
import * as Utils from "#app/utils";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
|||||||
const hardSpriteKey = hardConfig.getSpriteKey(female, hardConfig.doubleOnly);
|
const hardSpriteKey = hardConfig.getSpriteKey(female, hardConfig.doubleOnly);
|
||||||
encounter.enemyPartyConfigs.push({
|
encounter.enemyPartyConfigs.push({
|
||||||
trainerConfig: hardConfig,
|
trainerConfig: hardConfig,
|
||||||
levelAdditiveMultiplier: 1,
|
levelAdditiveModifier: 1,
|
||||||
female: female,
|
female: female,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
|||||||
const brutalSpriteKey = brutalConfig.getSpriteKey(female, brutalConfig.doubleOnly);
|
const brutalSpriteKey = brutalConfig.getSpriteKey(female, brutalConfig.doubleOnly);
|
||||||
encounter.enemyPartyConfigs.push({
|
encounter.enemyPartyConfigs.push({
|
||||||
trainerConfig: brutalConfig,
|
trainerConfig: brutalConfig,
|
||||||
levelAdditiveMultiplier: 1.5,
|
levelAdditiveModifier: 1.5,
|
||||||
female: female,
|
female: female,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ import { ModifierTier } from "#app/modifier/modifier-tier";
|
|||||||
import { randSeedInt } from "#app/utils";
|
import { randSeedInt } from "#app/utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../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 { getPokemonSpecies } from "#app/data/pokemon-species";
|
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
@ -68,7 +68,7 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
|||||||
|
|
||||||
// Calculate boss mon
|
// Calculate boss mon
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
levelAdditiveMultiplier: 0.5,
|
levelAdditiveModifier: 0.5,
|
||||||
disableSwitch: true,
|
disableSwitch: true,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
@ -179,6 +179,7 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
|||||||
encounter.setDialogueToken("pokeName", highestLevelPokemon.getNameToRender());
|
encounter.setDialogueToken("pokeName", highestLevelPokemon.getNameToRender());
|
||||||
await showEncounterText(scene, `${namespace}.option.1.bad`);
|
await showEncounterText(scene, `${namespace}.option.1.bad`);
|
||||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||||
|
setEncounterRewards(scene, { fillRemaining: true });
|
||||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/myst
|
|||||||
import { leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals, updatePlayerMoney } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import { leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals, updatePlayerMoney } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MoveRequirement } from "../mystery-encounter-requirements";
|
import { MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
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 { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { initSubsequentOptionSelect, leaveEncounterWithoutBattle, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import { initSubsequentOptionSelect, leaveEncounterWithoutBattle, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import MysteryEncounterOption, { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import MysteryEncounterOption, { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { TrainerSlot } from "#app/data/trainer-config";
|
import { TrainerSlot } from "#app/data/trainer-config";
|
||||||
import { HiddenAbilityRateBoosterModifier, IvScannerModifier } from "#app/modifier/modifier";
|
import { HiddenAbilityRateBoosterModifier, IvScannerModifier } from "#app/modifier/modifier";
|
||||||
@ -25,7 +25,7 @@ const namespace = "mysteryEncounter:safariZone";
|
|||||||
|
|
||||||
const TRAINER_THROW_ANIMATION_TIMES = [512, 184, 768];
|
const TRAINER_THROW_ANIMATION_TIMES = [512, 184, 768];
|
||||||
|
|
||||||
const SAFARI_MONEY_MULTIPLIER = 2.75;
|
const SAFARI_MONEY_MULTIPLIER = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Safari Zone encounter.
|
* Safari Zone encounter.
|
||||||
|
@ -5,9 +5,9 @@ import { randSeedInt } from "#app/utils";
|
|||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { MoneyRequirement } from "../mystery-encounter-requirements";
|
import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import { getEncounterText, queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText, queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { applyDamageToPokemon, applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { applyDamageToPokemon, applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
@ -19,6 +19,9 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
|||||||
/** the i18n namespace for this encounter */
|
/** the i18n namespace for this encounter */
|
||||||
const namespace = "mysteryEncounter:shadyVitaminDealer";
|
const namespace = "mysteryEncounter:shadyVitaminDealer";
|
||||||
|
|
||||||
|
const VITAMIN_DEALER_CHEAP_PRICE_MULTIPLIER = 1.5;
|
||||||
|
const VITAMIN_DEALER_EXPENSIVE_PRICE_MULTIPLIER = 3.5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shady Vitamin Dealer encounter.
|
* Shady Vitamin Dealer encounter.
|
||||||
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3798 | GitHub Issue #3798}
|
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3798 | GitHub Issue #3798}
|
||||||
@ -28,7 +31,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
|||||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.SHADY_VITAMIN_DEALER)
|
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.SHADY_VITAMIN_DEALER)
|
||||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||||
.withSceneRequirement(new MoneyRequirement(0, 1.5)) // Must have the money for at least the cheap deal
|
.withSceneRequirement(new MoneyRequirement(0, VITAMIN_DEALER_CHEAP_PRICE_MULTIPLIER)) // Must have the money for at least the cheap deal
|
||||||
.withPrimaryPokemonHealthRatioRequirement([0.5, 1]) // At least 1 Pokemon must have above half HP
|
.withPrimaryPokemonHealthRatioRequirement([0.5, 1]) // At least 1 Pokemon must have above half HP
|
||||||
.withIntroSpriteConfigs([
|
.withIntroSpriteConfigs([
|
||||||
{
|
{
|
||||||
@ -64,7 +67,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
|||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||||
.withSceneMoneyRequirement(0, 1.5)
|
.withSceneMoneyRequirement(0, VITAMIN_DEALER_CHEAP_PRICE_MULTIPLIER)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}.option.1.label`,
|
buttonLabel: `${namespace}.option.1.label`,
|
||||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||||
@ -115,7 +118,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
|||||||
await applyModifierTypeToPlayerPokemon(scene, chosenPokemon, modType);
|
await applyModifierTypeToPlayerPokemon(scene, chosenPokemon, modType);
|
||||||
}
|
}
|
||||||
|
|
||||||
leaveEncounterWithoutBattle(scene);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
})
|
})
|
||||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||||
// Damage and status applied after dealer leaves (to make thematic sense)
|
// Damage and status applied after dealer leaves (to make thematic sense)
|
||||||
@ -142,7 +145,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
|||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||||
.withSceneMoneyRequirement(0, 3.5)
|
.withSceneMoneyRequirement(0, VITAMIN_DEALER_EXPENSIVE_PRICE_MULTIPLIER)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}.option.2.label`,
|
buttonLabel: `${namespace}.option.2.label`,
|
||||||
buttonTooltip: `${namespace}.option.2.tooltip`,
|
buttonTooltip: `${namespace}.option.2.tooltip`,
|
||||||
@ -193,7 +196,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
|||||||
await applyModifierTypeToPlayerPokemon(scene, chosenPokemon, modType);
|
await applyModifierTypeToPlayerPokemon(scene, chosenPokemon, modType);
|
||||||
}
|
}
|
||||||
|
|
||||||
leaveEncounterWithoutBattle(scene);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
})
|
})
|
||||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||||
// Status applied after dealer leaves (to make thematic sense)
|
// Status applied after dealer leaves (to make thematic sense)
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes, PokemonHeldItemModifierType } 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 { Species } from "#enums/species";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import { StatusEffect } from "#app/data/status-effect";
|
import { StatusEffect } from "#app/data/status-effect";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { MoveRequirement } from "../mystery-encounter-requirements";
|
import { MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, loadCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, } from "../utils/encounter-phase-utils";
|
import { EnemyPartyConfig, EnemyPokemonConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, setEncounterExp, setEncounterRewards, } 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 { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#app/battle";
|
||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { AiType, PokemonMove } from "#app/field/pokemon";
|
||||||
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 { PartyHealPhase } from "#app/phases/party-heal-phase";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
|
import { BerryType } from "#enums/berry-type";
|
||||||
|
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||||
|
|
||||||
/** i18n namespace for the encounter */
|
/** i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounter:slumberingSnorlax";
|
const namespace = "mysteryEncounter:slumberingSnorlax";
|
||||||
@ -38,7 +40,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
|||||||
fileRoot: "pokemon",
|
fileRoot: "pokemon",
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
tint: 0.25,
|
tint: 0.25,
|
||||||
scale: 1.5,
|
scale: 1.25,
|
||||||
repeat: true,
|
repeat: true,
|
||||||
y: 5,
|
y: 5,
|
||||||
},
|
},
|
||||||
@ -58,10 +60,22 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
|||||||
species: bossSpecies,
|
species: bossSpecies,
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
status: [StatusEffect.SLEEP, 5], // Extra turns on timer for Snorlax's start of fight moves
|
status: [StatusEffect.SLEEP, 5], // Extra turns on timer for Snorlax's start of fight moves
|
||||||
moveSet: [Moves.REST, Moves.SLEEP_TALK, Moves.CRUNCH, Moves.GIGA_IMPACT]
|
moveSet: [Moves.REST, Moves.SLEEP_TALK, Moves.CRUNCH, Moves.GIGA_IMPACT],
|
||||||
|
modifierConfigs: [
|
||||||
|
{
|
||||||
|
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType,
|
||||||
|
stackCount: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.ENIGMA]) as PokemonHeldItemModifierType,
|
||||||
|
stackCount: 2
|
||||||
|
},
|
||||||
|
],
|
||||||
|
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }),
|
||||||
|
aiType: AiType.SMART // Required to ensure Snorlax uses Sleep Talk while it is asleep
|
||||||
};
|
};
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
levelAdditiveMultiplier: 0.5,
|
levelAdditiveModifier: 0.5,
|
||||||
pokemonConfigs: [pokemonConfig],
|
pokemonConfigs: [pokemonConfig],
|
||||||
};
|
};
|
||||||
encounter.enemyPartyConfigs = [config];
|
encounter.enemyPartyConfigs = [config];
|
||||||
|
@ -2,8 +2,8 @@ import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig
|
|||||||
import { randSeedInt } from "#app/utils";
|
import { randSeedInt } from "#app/utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MoneyRequirement, WaveModulusRequirement } from "../mystery-encounter-requirements";
|
import { MoneyRequirement, WaveModulusRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import Pokemon, { EnemyPokemon } from "#app/field/pokemon";
|
import Pokemon, { EnemyPokemon } from "#app/field/pokemon";
|
||||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
@ -20,12 +20,13 @@ import { getPokemonNameWithAffix } from "#app/messages";
|
|||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
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/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
|
import { getEncounterPokemonLevelForWave, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
|
|
||||||
/** the i18n namespace for this encounter */
|
/** the i18n namespace for this encounter */
|
||||||
const namespace = "mysteryEncounter:teleportingHijinks";
|
const namespace = "mysteryEncounter:teleportingHijinks";
|
||||||
|
|
||||||
const MONEY_COST_MULTIPLIER = 2.5;
|
const MONEY_COST_MULTIPLIER = 1.75;
|
||||||
const BIOME_CANDIDATES = [Biome.SPACE, Biome.FAIRY_CAVE, Biome.LABORATORY, Biome.ISLAND];
|
const BIOME_CANDIDATES = [Biome.SPACE, Biome.FAIRY_CAVE, Biome.LABORATORY, Biome.ISLAND, Biome.WASTELAND, Biome.DOJO];
|
||||||
const MACHINE_INTERFACING_TYPES = [Type.ELECTRIC, Type.STEEL];
|
const MACHINE_INTERFACING_TYPES = [Type.ELECTRIC, Type.STEEL];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,7 +131,7 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
|||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
|
|
||||||
// Init enemy
|
// Init enemy
|
||||||
const level = (scene.currentBattle.enemyLevels?.[0] ?? scene.currentBattle.waveIndex) + Math.max(Math.round((scene.currentBattle.waveIndex / 10)), 0);
|
const level = getEncounterPokemonLevelForWave(scene, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER);
|
||||||
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true);
|
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true);
|
||||||
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
||||||
encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon));
|
encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon));
|
||||||
@ -166,7 +167,7 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) {
|
|||||||
await showEncounterText(scene, `${namespace}.attacked`);
|
await showEncounterText(scene, `${namespace}.attacked`);
|
||||||
|
|
||||||
// Init enemy
|
// Init enemy
|
||||||
const level = (scene.currentBattle.enemyLevels?.[0] ?? scene.currentBattle.waveIndex) + Math.max(Math.round((scene.currentBattle.waveIndex / 10)), 0);
|
const level = getEncounterPokemonLevelForWave(scene, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER);
|
||||||
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true);
|
const bossSpecies = scene.arena.randomSpecies(scene.currentBattle.waveIndex, level, 0, getPartyLuckValue(scene.getParty()), true);
|
||||||
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
const bossPokemon = new EnemyPokemon(scene, bossSpecies, level, TrainerSlot.NONE, true);
|
||||||
encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon));
|
encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon));
|
||||||
|
@ -0,0 +1,549 @@
|
|||||||
|
import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, setEncounterRewards, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
|
import { trainerConfigs } from "#app/data/trainer-config";
|
||||||
|
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||||
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
|
import BattleScene from "#app/battle-scene";
|
||||||
|
import { randSeedShuffle } from "#app/utils";
|
||||||
|
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
||||||
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
|
import { Biome } from "#enums/biome";
|
||||||
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
|
import i18next from "i18next";
|
||||||
|
import { Species } from "#enums/species";
|
||||||
|
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||||
|
import { Nature } from "#enums/nature";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import { Type } from "#app/data/type";
|
||||||
|
import { Stat } from "#enums/stat";
|
||||||
|
import { PlayerPokemon } from "#app/field/pokemon";
|
||||||
|
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
|
import { IEggOptions } from "#app/data/egg";
|
||||||
|
import { EggSourceType } from "#enums/egg-source-types";
|
||||||
|
import { EggTier } from "#enums/egg-type";
|
||||||
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
import { achvs } from "#app/system/achv";
|
||||||
|
|
||||||
|
/** the i18n namespace for the encounter */
|
||||||
|
const namespace = "mysteryEncounter:expertPokemonBreeder";
|
||||||
|
|
||||||
|
const trainerNameKey = "trainerNames:expert_pokemon_breeder";
|
||||||
|
|
||||||
|
const FIRST_STAGE_EVOLUTION_WAVE = 30;
|
||||||
|
const SECOND_STAGE_EVOLUTION_WAVE = 45;
|
||||||
|
const FINAL_STAGE_EVOLUTION_WAVE = 60;
|
||||||
|
|
||||||
|
const FRIENDSHIP_ADDED = 20;
|
||||||
|
|
||||||
|
class BreederSpeciesEvolution {
|
||||||
|
species: Species;
|
||||||
|
evolution: number;
|
||||||
|
|
||||||
|
constructor(species: Species, evolution: number) {
|
||||||
|
this.species = species;
|
||||||
|
this.evolution = evolution;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const POOL_1_POKEMON: (Species | BreederSpeciesEvolution)[][] = [
|
||||||
|
[Species.MUNCHLAX, new BreederSpeciesEvolution(Species.SNORLAX, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.HAPPINY, new BreederSpeciesEvolution(Species.CHANSEY, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.BLISSEY, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.MAGBY, new BreederSpeciesEvolution(Species.MAGMAR, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MAGMORTAR, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.ELEKID, new BreederSpeciesEvolution(Species.ELECTABUZZ, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ELECTIVIRE, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.RIOLU, new BreederSpeciesEvolution(Species.LUCARIO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.BUDEW, new BreederSpeciesEvolution(Species.ROSELIA, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ROSERADE, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.TOXEL, new BreederSpeciesEvolution(Species.TOXTRICITY, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.MIME_JR, new BreederSpeciesEvolution(Species.GALAR_MR_MIME, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MR_RIME, FINAL_STAGE_EVOLUTION_WAVE)]
|
||||||
|
];
|
||||||
|
|
||||||
|
const POOL_2_POKEMON: (Species | BreederSpeciesEvolution)[][] = [
|
||||||
|
[Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.RAICHU, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.JYNX],
|
||||||
|
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.IGGLYBUFF, new BreederSpeciesEvolution(Species.JIGGLYPUFF, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.WIGGLYTUFF, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.AZURILL, new BreederSpeciesEvolution(Species.MARILL, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.AZUMARILL, FINAL_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.WYNAUT, new BreederSpeciesEvolution(Species.WOBBUFFET, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.CHINGLING, new BreederSpeciesEvolution(Species.CHIMECHO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.BONSLY, new BreederSpeciesEvolution(Species.SUDOWOODO, SECOND_STAGE_EVOLUTION_WAVE)],
|
||||||
|
[Species.MANTYKE, new BreederSpeciesEvolution(Species.MANTINE, SECOND_STAGE_EVOLUTION_WAVE)]
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Expert Pokémon Breeder encounter.
|
||||||
|
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3818 | GitHub Issue #3818}
|
||||||
|
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||||
|
*/
|
||||||
|
export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||||
|
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER)
|
||||||
|
.withEncounterTier(MysteryEncounterTier.ULTRA)
|
||||||
|
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||||
|
.withScenePartySizeRequirement(4, 6, true) // Must have at least 4 legal pokemon in party
|
||||||
|
.withIntroSpriteConfigs([]) // These are set in onInit()
|
||||||
|
.withIntroDialogue([
|
||||||
|
{
|
||||||
|
text: `${namespace}.intro`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: trainerNameKey,
|
||||||
|
text: `${namespace}.intro_dialogue`,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.withOnInit((scene: BattleScene) => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
|
const waveIndex = scene.currentBattle.waveIndex;
|
||||||
|
// Calculates what trainers are available for battle in the encounter
|
||||||
|
|
||||||
|
// If player is in space biome, uses special "Space" version of the trainer
|
||||||
|
encounter.enemyPartyConfigs = [
|
||||||
|
getPartyConfig(scene)
|
||||||
|
];
|
||||||
|
|
||||||
|
const cleffaSpecies = waveIndex < FIRST_STAGE_EVOLUTION_WAVE ? Species.CLEFFA : waveIndex < FINAL_STAGE_EVOLUTION_WAVE ? Species.CLEFAIRY : Species.CLEFABLE;
|
||||||
|
encounter.spriteConfigs = [
|
||||||
|
{
|
||||||
|
spriteKey: cleffaSpecies.toString(),
|
||||||
|
fileRoot: "pokemon",
|
||||||
|
hasShadow: true,
|
||||||
|
repeat: true,
|
||||||
|
x: 14,
|
||||||
|
y: -2,
|
||||||
|
yShadow: -2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
spriteKey: "expert_pokemon_breeder",
|
||||||
|
fileRoot: "trainer",
|
||||||
|
hasShadow: true,
|
||||||
|
x: -14,
|
||||||
|
y: 4,
|
||||||
|
yShadow: 2
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// Determine the 3 pokemon the player can battle with
|
||||||
|
let partyCopy = scene.getParty().slice(0);
|
||||||
|
partyCopy = partyCopy
|
||||||
|
.filter(p => p.isAllowedInBattle())
|
||||||
|
.sort((a, b) => a.friendship - b.friendship);
|
||||||
|
|
||||||
|
const pokemon1 = partyCopy[0];
|
||||||
|
const pokemon2 = partyCopy[1];
|
||||||
|
const pokemon3 = partyCopy[2];
|
||||||
|
encounter.setDialogueToken("pokemon1Name", pokemon1.getNameToRender());
|
||||||
|
encounter.setDialogueToken("pokemon2Name", pokemon2.getNameToRender());
|
||||||
|
encounter.setDialogueToken("pokemon3Name", pokemon3.getNameToRender());
|
||||||
|
|
||||||
|
// Dialogue and egg calcs for Pokemon 1
|
||||||
|
const [pokemon1CommonEggs, pokemon1RareEggs] = calculateEggRewardsForPokemon(pokemon1);
|
||||||
|
let pokemon1Tooltip = getEncounterText(scene, `${namespace}.option.1.tooltip_base`)!;
|
||||||
|
if (pokemon1RareEggs > 0) {
|
||||||
|
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon1RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||||
|
pokemon1Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||||
|
encounter.setDialogueToken("pokemon1RareEggs", eggsText);
|
||||||
|
}
|
||||||
|
if (pokemon1CommonEggs > 0) {
|
||||||
|
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon1CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||||
|
pokemon1Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||||
|
encounter.setDialogueToken("pokemon1CommonEggs", eggsText);
|
||||||
|
}
|
||||||
|
encounter.options[0].dialogue!.buttonTooltip = pokemon1Tooltip;
|
||||||
|
|
||||||
|
// Dialogue and egg calcs for Pokemon 2
|
||||||
|
const [pokemon2CommonEggs, pokemon2RareEggs] = calculateEggRewardsForPokemon(pokemon2);
|
||||||
|
let pokemon2Tooltip = getEncounterText(scene, `${namespace}.option.2.tooltip_base`)!;
|
||||||
|
if (pokemon2RareEggs > 0) {
|
||||||
|
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon2RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||||
|
pokemon2Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||||
|
encounter.setDialogueToken("pokemon2RareEggs", eggsText);
|
||||||
|
}
|
||||||
|
if (pokemon2CommonEggs > 0) {
|
||||||
|
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon2CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||||
|
pokemon2Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||||
|
encounter.setDialogueToken("pokemon1CommonEggs", eggsText);
|
||||||
|
}
|
||||||
|
encounter.options[1].dialogue!.buttonTooltip = pokemon2Tooltip;
|
||||||
|
|
||||||
|
// Dialogue and egg calcs for Pokemon 3
|
||||||
|
const [pokemon3CommonEggs, pokemon3RareEggs] = calculateEggRewardsForPokemon(pokemon3);
|
||||||
|
let pokemon3Tooltip = getEncounterText(scene, `${namespace}.option.3.tooltip_base`)!;
|
||||||
|
if (pokemon3RareEggs > 0) {
|
||||||
|
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon3RareEggs, rarity: i18next.t("egg:greatTier") });
|
||||||
|
pokemon3Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||||
|
encounter.setDialogueToken("pokemon3RareEggs", eggsText);
|
||||||
|
}
|
||||||
|
if (pokemon3CommonEggs > 0) {
|
||||||
|
const eggsText = i18next.t(`${namespace}.numEggs`, { count: pokemon3CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||||
|
pokemon3Tooltip += i18next.t(`${namespace}.eggs_tooltip`, { eggs: eggsText });
|
||||||
|
encounter.setDialogueToken("pokemon3CommonEggs", eggsText);
|
||||||
|
}
|
||||||
|
encounter.options[2].dialogue!.buttonTooltip = pokemon3Tooltip;
|
||||||
|
|
||||||
|
encounter.misc = {
|
||||||
|
pokemon1,
|
||||||
|
pokemon1CommonEggs,
|
||||||
|
pokemon1RareEggs,
|
||||||
|
pokemon2,
|
||||||
|
pokemon2CommonEggs,
|
||||||
|
pokemon2RareEggs,
|
||||||
|
pokemon3,
|
||||||
|
pokemon3CommonEggs,
|
||||||
|
pokemon3RareEggs
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.withTitle(`${namespace}.title`)
|
||||||
|
.withDescription(`${namespace}.description`)
|
||||||
|
.withQuery(`${namespace}.query`)
|
||||||
|
.withOption(
|
||||||
|
MysteryEncounterOptionBuilder
|
||||||
|
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
|
.withDialogue({
|
||||||
|
buttonLabel: `${namespace}.option.1.label`,
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
speaker: trainerNameKey,
|
||||||
|
text: `${namespace}.option.selected`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
|
// Spawn battle with first pokemon
|
||||||
|
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
||||||
|
|
||||||
|
const { pokemon1, pokemon1CommonEggs, pokemon1RareEggs } = encounter.misc;
|
||||||
|
encounter.setDialogueToken("chosenPokemon", pokemon1.getNameToRender());
|
||||||
|
const eggOptions = getEggOptions(scene, pokemon1CommonEggs, pokemon1RareEggs);
|
||||||
|
setEncounterRewards(scene, { fillRemaining: true }, eggOptions);
|
||||||
|
|
||||||
|
// Remove all Pokemon from the party except the chosen Pokemon
|
||||||
|
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon1);
|
||||||
|
|
||||||
|
// Configure outro dialogue for egg rewards
|
||||||
|
encounter.dialogue.outro = [
|
||||||
|
{
|
||||||
|
speaker: trainerNameKey,
|
||||||
|
text: `${namespace}.outro`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
if (encounter.dialogueTokens.hasOwnProperty("pokemon1CommonEggs")) {
|
||||||
|
encounter.dialogue.outro.push({
|
||||||
|
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon1CommonEggs"] }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (encounter.dialogueTokens.hasOwnProperty("pokemon1RareEggs")) {
|
||||||
|
encounter.dialogue.outro.push({
|
||||||
|
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon1RareEggs"] }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initBattleWithEnemyConfig(scene, config);
|
||||||
|
})
|
||||||
|
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||||
|
// Give achievement if in Space biome
|
||||||
|
checkAchievement(scene);
|
||||||
|
// Give 20 friendship to the chosen pokemon
|
||||||
|
scene.currentBattle.mysteryEncounter!.misc.pokemon1.addFriendship(FRIENDSHIP_ADDED);
|
||||||
|
await restorePartyAndHeldItems(scene);
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.withOption(
|
||||||
|
MysteryEncounterOptionBuilder
|
||||||
|
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
|
.withDialogue({
|
||||||
|
buttonLabel: `${namespace}.option.2.label`,
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
speaker: trainerNameKey,
|
||||||
|
text: `${namespace}.option.selected`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
|
// Spawn battle with second pokemon
|
||||||
|
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
||||||
|
|
||||||
|
const { pokemon2, pokemon2CommonEggs, pokemon2RareEggs } = encounter.misc;
|
||||||
|
encounter.setDialogueToken("chosenPokemon", pokemon2.getNameToRender());
|
||||||
|
const eggOptions = getEggOptions(scene, pokemon2CommonEggs, pokemon2RareEggs);
|
||||||
|
setEncounterRewards(scene, { fillRemaining: true }, eggOptions);
|
||||||
|
|
||||||
|
// Remove all Pokemon from the party except the chosen Pokemon
|
||||||
|
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon2);
|
||||||
|
|
||||||
|
// Configure outro dialogue for egg rewards
|
||||||
|
encounter.dialogue.outro = [
|
||||||
|
{
|
||||||
|
speaker: trainerNameKey,
|
||||||
|
text: `${namespace}.outro`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
if (encounter.dialogueTokens.hasOwnProperty("pokemon2CommonEggs")) {
|
||||||
|
encounter.dialogue.outro.push({
|
||||||
|
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon2CommonEggs"] }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (encounter.dialogueTokens.hasOwnProperty("pokemon2RareEggs")) {
|
||||||
|
encounter.dialogue.outro.push({
|
||||||
|
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon2RareEggs"] }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initBattleWithEnemyConfig(scene, config);
|
||||||
|
})
|
||||||
|
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||||
|
// Give achievement if in Space biome
|
||||||
|
checkAchievement(scene);
|
||||||
|
// Give 20 friendship to the chosen pokemon
|
||||||
|
scene.currentBattle.mysteryEncounter!.misc.pokemon2.addFriendship(FRIENDSHIP_ADDED);
|
||||||
|
await restorePartyAndHeldItems(scene);
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.withOption(
|
||||||
|
MysteryEncounterOptionBuilder
|
||||||
|
.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
||||||
|
.withDialogue({
|
||||||
|
buttonLabel: `${namespace}.option.3.label`,
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
speaker: trainerNameKey,
|
||||||
|
text: `${namespace}.option.selected`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
|
// Spawn battle with third pokemon
|
||||||
|
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
||||||
|
|
||||||
|
const { pokemon3, pokemon3CommonEggs, pokemon3RareEggs } = encounter.misc;
|
||||||
|
encounter.setDialogueToken("chosenPokemon", pokemon3.getNameToRender());
|
||||||
|
const eggOptions = getEggOptions(scene, pokemon3CommonEggs, pokemon3RareEggs);
|
||||||
|
setEncounterRewards(scene, { fillRemaining: true }, eggOptions);
|
||||||
|
|
||||||
|
// Remove all Pokemon from the party except the chosen Pokemon
|
||||||
|
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon3);
|
||||||
|
|
||||||
|
// Configure outro dialogue for egg rewards
|
||||||
|
encounter.dialogue.outro = [
|
||||||
|
{
|
||||||
|
speaker: trainerNameKey,
|
||||||
|
text: `${namespace}.outro`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
if (encounter.dialogueTokens.hasOwnProperty("pokemon3CommonEggs")) {
|
||||||
|
encounter.dialogue.outro.push({
|
||||||
|
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon3CommonEggs"] }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (encounter.dialogueTokens.hasOwnProperty("pokemon3RareEggs")) {
|
||||||
|
encounter.dialogue.outro.push({
|
||||||
|
text: i18next.t(`${namespace}.gained_eggs`, { numEggs: encounter.dialogueTokens["pokemon3RareEggs"] }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initBattleWithEnemyConfig(scene, config);
|
||||||
|
})
|
||||||
|
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||||
|
// Give achievement if in Space biome
|
||||||
|
checkAchievement(scene);
|
||||||
|
// Give 20 friendship to the chosen pokemon
|
||||||
|
scene.currentBattle.mysteryEncounter!.misc.pokemon3.addFriendship(FRIENDSHIP_ADDED);
|
||||||
|
await restorePartyAndHeldItems(scene);
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.withOutroDialogue([
|
||||||
|
{
|
||||||
|
text: `${namespace}.outro`,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
function getPartyConfig(scene: BattleScene): EnemyPartyConfig {
|
||||||
|
// Bug type superfan trainer config
|
||||||
|
const waveIndex = scene.currentBattle.waveIndex;
|
||||||
|
const breederConfig = trainerConfigs[TrainerType.EXPERT_POKEMON_BREEDER].clone();
|
||||||
|
breederConfig.name = i18next.t(trainerNameKey);
|
||||||
|
|
||||||
|
// First mon is *always* this special cleffa
|
||||||
|
const cleffaSpecies = waveIndex < FIRST_STAGE_EVOLUTION_WAVE ? Species.CLEFFA : waveIndex < FINAL_STAGE_EVOLUTION_WAVE ? Species.CLEFAIRY : Species.CLEFABLE;
|
||||||
|
const baseConfig: EnemyPartyConfig = {
|
||||||
|
trainerType: TrainerType.EXPERT_POKEMON_BREEDER,
|
||||||
|
pokemonConfigs: [
|
||||||
|
{
|
||||||
|
nickname: i18next.t(`${namespace}.cleffa_1_nickname`),
|
||||||
|
species: getPokemonSpecies(cleffaSpecies),
|
||||||
|
isBoss: false,
|
||||||
|
abilityIndex: 1, // Magic Guard
|
||||||
|
shiny: false,
|
||||||
|
nature: Nature.ADAMANT,
|
||||||
|
moveSet: [Moves.METEOR_MASH, Moves.FIRE_PUNCH, Moves.ICE_PUNCH, Moves.THUNDER_PUNCH],
|
||||||
|
ivs: [31, 31, 31, 31, 31, 31],
|
||||||
|
modifierConfigs: [
|
||||||
|
{
|
||||||
|
modifier: generateModifierType(scene, modifierTypes.TERA_SHARD, [Type.STEEL]) as PokemonHeldItemModifierType,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [Stat.ATK]) as PokemonHeldItemModifierType,
|
||||||
|
stackCount: 1 + Math.floor(waveIndex / 20), // +1 Protein every 20 waves
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [Stat.SPD]) as PokemonHeldItemModifierType,
|
||||||
|
stackCount: 1 + Math.floor(waveIndex / 40), // +1 Carbos every 40 waves
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
if (scene.arena.biomeType === Biome.SPACE) {
|
||||||
|
// All 3 members always Cleffa line, but different configs
|
||||||
|
baseConfig.pokemonConfigs!.push({
|
||||||
|
nickname: i18next.t(`${namespace}.cleffa_2_nickname`),
|
||||||
|
species: getPokemonSpecies(cleffaSpecies),
|
||||||
|
isBoss: false,
|
||||||
|
abilityIndex: 1, // Magic Guard
|
||||||
|
shiny: true,
|
||||||
|
variant: 1,
|
||||||
|
nature: Nature.MODEST,
|
||||||
|
moveSet: [Moves.MOONBLAST, Moves.MYSTICAL_FIRE, Moves.ICE_BEAM, Moves.THUNDERBOLT],
|
||||||
|
ivs: [31, 31, 31, 31, 31, 31]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nickname: i18next.t(`${namespace}.cleffa_3_nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName() }),
|
||||||
|
species: getPokemonSpecies(cleffaSpecies),
|
||||||
|
isBoss: false,
|
||||||
|
abilityIndex: 2, // Friend Guard / Unaware
|
||||||
|
shiny: true,
|
||||||
|
variant: 2,
|
||||||
|
nature: Nature.BOLD,
|
||||||
|
moveSet: [Moves.TRI_ATTACK, Moves.STORED_POWER, Moves.TAKE_HEART, Moves.MOONLIGHT],
|
||||||
|
ivs: [31, 31, 31, 31, 31, 31]
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Second member from pool 1
|
||||||
|
const pool1Species = getSpeciesFromPool(POOL_1_POKEMON, waveIndex);
|
||||||
|
// Third member from pool 2
|
||||||
|
const pool2Species = getSpeciesFromPool(POOL_2_POKEMON, waveIndex);
|
||||||
|
|
||||||
|
baseConfig.pokemonConfigs!.push({
|
||||||
|
species: getPokemonSpecies(pool1Species),
|
||||||
|
isBoss: false,
|
||||||
|
ivs: [31, 31, 31, 31, 31, 31]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
species: getPokemonSpecies(pool2Species),
|
||||||
|
isBoss: false,
|
||||||
|
ivs: [31, 31, 31, 31, 31, 31]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSpeciesFromPool(speciesPool: (Species | BreederSpeciesEvolution)[][], waveIndex: number): Species {
|
||||||
|
const poolCopy = speciesPool.slice(0);
|
||||||
|
randSeedShuffle(poolCopy);
|
||||||
|
const speciesEvolutions = poolCopy.pop()!.slice(0);
|
||||||
|
let speciesObject = speciesEvolutions.pop()!;
|
||||||
|
while (speciesObject instanceof BreederSpeciesEvolution && speciesObject.evolution > waveIndex) {
|
||||||
|
speciesObject = speciesEvolutions.pop()!;
|
||||||
|
}
|
||||||
|
return speciesObject instanceof BreederSpeciesEvolution ? speciesObject.species : speciesObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateEggRewardsForPokemon(pokemon: PlayerPokemon): [number, number] {
|
||||||
|
const bst = pokemon.calculateBaseStats().reduce((a, b) => a + b, 0);
|
||||||
|
// 1 point for every 20 points below 680 BST the pokemon is, (max 18, min 1)
|
||||||
|
const pointsFromBst = Math.min(Math.max(Math.floor((680 - bst) / 20), 1), 18);
|
||||||
|
|
||||||
|
const rootSpecies = pokemon.species.getRootSpeciesId(true);
|
||||||
|
let pointsFromStarterTier = 0;
|
||||||
|
// 2 points for every 1 below 7 that the pokemon's starter tier is (max 12, min 0)
|
||||||
|
if (speciesStarters.hasOwnProperty(rootSpecies)) {
|
||||||
|
const starterTier = speciesStarters[rootSpecies];
|
||||||
|
pointsFromStarterTier = Math.min(Math.max(Math.floor(7 - starterTier) * 2, 0), 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maximum of 30 points
|
||||||
|
const totalPoints = Math.min(pointsFromStarterTier + pointsFromBst, 30);
|
||||||
|
|
||||||
|
// 1 Rare egg for every 6 points
|
||||||
|
const numRares = Math.floor(totalPoints / 6);
|
||||||
|
// 1 Common egg for every point leftover
|
||||||
|
const numCommons = totalPoints % 6;
|
||||||
|
|
||||||
|
return [numCommons, numRares];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEggOptions(scene: BattleScene, commonEggs: number, rareEggs: number) {
|
||||||
|
const eggDescription = i18next.t(`${namespace}.title`) + ":\n" + i18next.t(trainerNameKey);
|
||||||
|
const eggOptions: IEggOptions[] = [];
|
||||||
|
|
||||||
|
if (commonEggs > 0) {
|
||||||
|
for (let i = 0; i < commonEggs; i++) {
|
||||||
|
eggOptions.push({
|
||||||
|
scene,
|
||||||
|
pulled: false,
|
||||||
|
sourceType: EggSourceType.EVENT,
|
||||||
|
eggDescriptor: eggDescription,
|
||||||
|
tier: EggTier.COMMON
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rareEggs > 0) {
|
||||||
|
for (let i = 0; i < rareEggs; i++) {
|
||||||
|
eggOptions.push({
|
||||||
|
scene,
|
||||||
|
pulled: false,
|
||||||
|
sourceType: EggSourceType.EVENT,
|
||||||
|
eggDescriptor: eggDescription,
|
||||||
|
tier: EggTier.GREAT
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eggOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removePokemonFromPartyAndStoreHeldItems(scene: BattleScene, encounter: MysteryEncounter, chosenPokemon: PlayerPokemon) {
|
||||||
|
const party = scene.getParty();
|
||||||
|
const chosenIndex = party.indexOf(chosenPokemon);
|
||||||
|
party[chosenIndex] = party[0];
|
||||||
|
party[0] = chosenPokemon;
|
||||||
|
encounter.misc.originalParty = scene.getParty().slice(1);
|
||||||
|
encounter.misc.originalPartyHeldItems = encounter.misc.originalParty
|
||||||
|
.map(p => p.getHeldItems());
|
||||||
|
scene["party"] = [
|
||||||
|
chosenPokemon
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAchievement(scene: BattleScene) {
|
||||||
|
if (scene.arena.biomeType === Biome.SPACE) {
|
||||||
|
scene.validateAchv(achvs.BREEDERS_IN_SPACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function restorePartyAndHeldItems(scene: BattleScene) {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
|
// Restore original party
|
||||||
|
scene.getParty().push(...encounter.misc.originalParty);
|
||||||
|
|
||||||
|
// Restore held items
|
||||||
|
const originalHeldItems = encounter.misc.originalPartyHeldItems;
|
||||||
|
originalHeldItems.forEach(pokemonHeldItemsList => {
|
||||||
|
pokemonHeldItemsList.forEach(heldItem => {
|
||||||
|
scene.addModifier(heldItem, true, false, false, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await scene.updateModifiers(true);
|
||||||
|
}
|
@ -2,8 +2,8 @@ import { leaveEncounterWithoutBattle, transitionMysteryEncounterIntroVisuals, up
|
|||||||
import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MoneyRequirement } from "../mystery-encounter-requirements";
|
import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import { catchPokemon, getRandomSpeciesByStarterTier, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
import { catchPokemon, getRandomSpeciesByStarterTier, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||||
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
@ -15,11 +15,15 @@ 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/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
|
||||||
/** the i18n namespace for this encounter */
|
/** the i18n namespace for this encounter */
|
||||||
const namespace = "mysteryEncounter:pokemonSalesman";
|
const namespace = "mysteryEncounter:pokemonSalesman";
|
||||||
|
|
||||||
const MAX_POKEMON_PRICE_MULTIPLIER = 6;
|
const MAX_POKEMON_PRICE_MULTIPLIER = 4;
|
||||||
|
|
||||||
|
/** Odds of shiny magikarp will be 1/value */
|
||||||
|
const SHINY_MAGIKARP_WEIGHT = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pokemon Salesman encounter.
|
* Pokemon Salesman encounter.
|
||||||
@ -58,12 +62,12 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
|||||||
const tries = 0;
|
const tries = 0;
|
||||||
|
|
||||||
// Reroll any species that don't have HAs
|
// Reroll any species that don't have HAs
|
||||||
while (isNullOrUndefined(species.abilityHidden) && tries < 5) {
|
while ((isNullOrUndefined(species.abilityHidden) || species.abilityHidden === Abilities.NONE) && tries < 5) {
|
||||||
species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5]));
|
species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5]));
|
||||||
}
|
}
|
||||||
|
|
||||||
let pokemon: PlayerPokemon;
|
let pokemon: PlayerPokemon;
|
||||||
if (isNullOrUndefined(species.abilityHidden) || randSeedInt(100) === 0) {
|
if (randSeedInt(SHINY_MAGIKARP_WEIGHT) === 0 || isNullOrUndefined(species.abilityHidden) || species.abilityHidden === Abilities.NONE) {
|
||||||
// If no HA mon found or you roll 1%, give shiny Magikarp
|
// If no HA mon found or you roll 1%, give shiny Magikarp
|
||||||
species = getPokemonSpecies(Species.MAGIKARP);
|
species = getPokemonSpecies(Species.MAGIKARP);
|
||||||
const hiddenIndex = species.ability2 ? 2 : 1;
|
const hiddenIndex = species.ability2 ? 2 : 1;
|
||||||
|
@ -2,7 +2,7 @@ import { EnemyPartyConfig, initBattleWithEnemyConfig, loadCustomMovesForEncounte
|
|||||||
import { modifierTypes, PokemonHeldItemModifierType, } from "#app/modifier/modifier-type";
|
import { modifierTypes, PokemonHeldItemModifierType, } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { 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 { Species } from "#enums/species";
|
||||||
import { Nature } from "#app/data/nature";
|
import { Nature } from "#app/data/nature";
|
||||||
@ -36,6 +36,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
|||||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||||
.withScenePartySizeRequirement(3, 6) // Must have at least 3 pokemon in party
|
.withScenePartySizeRequirement(3, 6) // Must have at least 3 pokemon in party
|
||||||
|
.withMaxAllowedEncounters(1)
|
||||||
.withHideWildIntroMessage(true)
|
.withHideWildIntroMessage(true)
|
||||||
.withAutoHideIntroVisuals(false)
|
.withAutoHideIntroVisuals(false)
|
||||||
.withIntroSpriteConfigs([
|
.withIntroSpriteConfigs([
|
||||||
@ -70,7 +71,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
|||||||
|
|
||||||
// Calculate boss mon
|
// Calculate boss mon
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
levelAdditiveMultiplier: 1,
|
levelAdditiveModifier: 1,
|
||||||
disableSwitch: true,
|
disableSwitch: true,
|
||||||
pokemonConfigs: [
|
pokemonConfigs: [
|
||||||
{
|
{
|
||||||
@ -159,6 +160,11 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
|||||||
encounter.setDialogueToken("increaseValue", BST_INCREASE_VALUE.toString());
|
encounter.setDialogueToken("increaseValue", BST_INCREASE_VALUE.toString());
|
||||||
await showEncounterText(scene, `${namespace}.option.1.selected_2`, null, undefined, true);
|
await showEncounterText(scene, `${namespace}.option.1.selected_2`, null, undefined, true);
|
||||||
|
|
||||||
|
encounter.dialogue.outro = [
|
||||||
|
{
|
||||||
|
text: `${namespace}.outro`,
|
||||||
|
}
|
||||||
|
];
|
||||||
setEncounterRewards(scene, { fillRemaining: true });
|
setEncounterRewards(scene, { fillRemaining: true });
|
||||||
leaveEncounterWithoutBattle(scene, true);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
return true;
|
return true;
|
||||||
@ -192,6 +198,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
|||||||
ignorePp: true
|
ignorePp: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
encounter.dialogue.outro = [];
|
||||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { EnemyPartyConfig, generateModifierType, generateModifierTypeOption, ini
|
|||||||
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { 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 { Species } from "#enums/species";
|
||||||
@ -146,7 +146,7 @@ async function spawnNextTrainerOrEndEncounter(scene: BattleScene) {
|
|||||||
|
|
||||||
// Give 10x Voucher
|
// Give 10x Voucher
|
||||||
const newModifier = modifierTypes.VOUCHER_PREMIUM().newModifier();
|
const newModifier = modifierTypes.VOUCHER_PREMIUM().newModifier();
|
||||||
scene.addModifier(newModifier);
|
await scene.addModifier(newModifier);
|
||||||
scene.playSound("item_fanfare");
|
scene.playSound("item_fanfare");
|
||||||
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: newModifier?.type.name }));
|
await showEncounterText(scene, i18next.t("battle:rewardGain", { modifierName: newModifier?.type.name }));
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattl
|
|||||||
import { getNatureName, Nature } from "#app/data/nature";
|
import { getNatureName, Nature } from "#app/data/nature";
|
||||||
import { speciesStarters } from "#app/data/pokemon-species";
|
import { speciesStarters } from "#app/data/pokemon-species";
|
||||||
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
|
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
|
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
import { AbilityAttr } from "#app/system/game-data";
|
import { AbilityAttr } from "#app/system/game-data";
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
@ -11,8 +11,8 @@ import { isNullOrUndefined, randSeedShuffle } from "#app/utils";
|
|||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { getEncounterText, queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { getEncounterText, 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";
|
||||||
@ -34,6 +34,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||||||
.withEncounterTier(MysteryEncounterTier.ULTRA)
|
.withEncounterTier(MysteryEncounterTier.ULTRA)
|
||||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||||
.withScenePartySizeRequirement(2, 6, true) // Must have at least 2 unfainted pokemon in party
|
.withScenePartySizeRequirement(2, 6, true) // Must have at least 2 unfainted pokemon in party
|
||||||
|
.withFleeAllowed(false)
|
||||||
.withHideWildIntroMessage(true)
|
.withHideWildIntroMessage(true)
|
||||||
.withIntroSpriteConfigs([
|
.withIntroSpriteConfigs([
|
||||||
{
|
{
|
||||||
@ -97,12 +98,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||||||
5
|
5
|
||||||
);
|
);
|
||||||
const modifiers = new ModifiersHolder();
|
const modifiers = new ModifiersHolder();
|
||||||
const config = getEnemyConfig(
|
const config = getEnemyConfig(scene, playerPokemon, segments, modifiers);
|
||||||
scene,
|
|
||||||
playerPokemon,
|
|
||||||
segments,
|
|
||||||
modifiers
|
|
||||||
);
|
|
||||||
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
||||||
|
|
||||||
const onBeforeRewardsPhase = () => {
|
const onBeforeRewardsPhase = () => {
|
||||||
@ -163,6 +159,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||||||
// Add pokemon and mods back
|
// Add pokemon and mods back
|
||||||
scene.getParty().push(playerPokemon);
|
scene.getParty().push(playerPokemon);
|
||||||
for (const mod of modifiers.value) {
|
for (const mod of modifiers.value) {
|
||||||
|
mod.pokemonId = playerPokemon.id;
|
||||||
scene.addModifier(mod, true, false, false, true);
|
scene.addModifier(mod, true, false, false, true);
|
||||||
}
|
}
|
||||||
scene.updateModifiers(true);
|
scene.updateModifiers(true);
|
||||||
@ -230,17 +227,9 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||||||
|
|
||||||
// Spawn medium training session with chosen pokemon
|
// Spawn medium training session with chosen pokemon
|
||||||
// Every 40 waves, add +1 boss segment, capping at 6
|
// Every 40 waves, add +1 boss segment, capping at 6
|
||||||
const segments = Math.min(
|
const segments = Math.min(2 + Math.floor(scene.currentBattle.waveIndex / 40), 6);
|
||||||
2 + Math.floor(scene.currentBattle.waveIndex / 40),
|
|
||||||
6
|
|
||||||
);
|
|
||||||
const modifiers = new ModifiersHolder();
|
const modifiers = new ModifiersHolder();
|
||||||
const config = getEnemyConfig(
|
const config = getEnemyConfig(scene, playerPokemon, segments, modifiers);
|
||||||
scene,
|
|
||||||
playerPokemon,
|
|
||||||
segments,
|
|
||||||
modifiers
|
|
||||||
);
|
|
||||||
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
scene.removePokemonFromPlayerParty(playerPokemon, false);
|
||||||
|
|
||||||
const onBeforeRewardsPhase = () => {
|
const onBeforeRewardsPhase = () => {
|
||||||
@ -377,6 +366,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||||||
// Add pokemon and mods back
|
// Add pokemon and mods back
|
||||||
scene.getParty().push(playerPokemon);
|
scene.getParty().push(playerPokemon);
|
||||||
for (const mod of modifiers.value) {
|
for (const mod of modifiers.value) {
|
||||||
|
mod.pokemonId = playerPokemon.id;
|
||||||
scene.addModifier(mod, true, false, false, true);
|
scene.addModifier(mod, true, false, false, true);
|
||||||
}
|
}
|
||||||
scene.updateModifiers(true);
|
scene.updateModifiers(true);
|
||||||
@ -410,10 +400,12 @@ function getEnemyConfig(scene: BattleScene, playerPokemon: PlayerPokemon, segmen
|
|||||||
playerPokemon.resetSummonData();
|
playerPokemon.resetSummonData();
|
||||||
|
|
||||||
// Passes modifiers by reference
|
// Passes modifiers by reference
|
||||||
modifiers.value = playerPokemon.getHeldItems().filter(m => !(m instanceof PokemonFormChangeItemModifier));
|
modifiers.value = playerPokemon.getHeldItems();
|
||||||
const modifierConfigs = modifiers.value.map((mod) => {
|
const modifierConfigs = modifiers.value.map((mod) => {
|
||||||
return {
|
return {
|
||||||
modifier: mod
|
modifier: mod.clone(),
|
||||||
|
isTransferable: false,
|
||||||
|
stackCount: mod.stackCount
|
||||||
};
|
};
|
||||||
}) as HeldModifierConfig[];
|
}) as HeldModifierConfig[];
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@ import { EnemyPartyConfig, EnemyPokemonConfig, generateModifierType, initBattleW
|
|||||||
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../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 { Species } from "#enums/species";
|
||||||
@ -67,7 +67,7 @@ export const TrashToTreasureEncounter: MysteryEncounter =
|
|||||||
moveSet: [Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH]
|
moveSet: [Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH]
|
||||||
};
|
};
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
levelAdditiveMultiplier: 1,
|
levelAdditiveModifier: 1,
|
||||||
pokemonConfigs: [pokemonConfig],
|
pokemonConfigs: [pokemonConfig],
|
||||||
disableSwitch: true
|
disableSwitch: true
|
||||||
};
|
};
|
||||||
|
@ -5,8 +5,8 @@ import Pokemon, { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
|
|||||||
import { getPartyLuckValue } from "#app/modifier/modifier-type";
|
import { getPartyLuckValue } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MoveRequirement, PersistentModifierRequirement } from "../mystery-encounter-requirements";
|
import { MoveRequirement, PersistentModifierRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
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 { TrainerSlot } from "#app/data/trainer-config";
|
import { TrainerSlot } from "#app/data/trainer-config";
|
||||||
|
@ -2,8 +2,8 @@ import { Type } from "#app/data/type";
|
|||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { leaveEncounterWithoutBattle, setEncounterRewards, } from "../utils/encounter-phase-utils";
|
import { leaveEncounterWithoutBattle, setEncounterRewards, } from "../utils/encounter-phase-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";
|
||||||
@ -14,7 +14,7 @@ import { HiddenAbilityRateBoosterModifier, PokemonFormChangeItemModifier, Pokemo
|
|||||||
import { achvs } from "#app/system/achv";
|
import { achvs } from "#app/system/achv";
|
||||||
import { speciesEggMoves } from "#app/data/egg-moves";
|
import { speciesEggMoves } from "#app/data/egg-moves";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||||
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
import i18next from "#app/plugins/i18n";
|
import i18next from "#app/plugins/i18n";
|
||||||
import { doPokemonTransformationSequence, TransformationScreenPosition } from "#app/data/mystery-encounters/utils/encounter-transformation-sequence";
|
import { doPokemonTransformationSequence, TransformationScreenPosition } from "#app/data/mystery-encounters/utils/encounter-transformation-sequence";
|
||||||
@ -130,12 +130,7 @@ export const WeirdDreamEncounter: MysteryEncounter =
|
|||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.withOnVisualsStart((scene: BattleScene) => {
|
.withOnVisualsStart((scene: BattleScene) => {
|
||||||
// Change the bgm
|
scene.fadeAndSwitchBgm("mystery_encounter_weird_dream");
|
||||||
scene.fadeOutBgm(3000, false);
|
|
||||||
scene.time.delayedCall(3000, () => {
|
|
||||||
scene.playBgm("mystery_encounter_weird_dream");
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.withOption(
|
.withOption(
|
||||||
@ -340,7 +335,7 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
|
|||||||
const newStarterUnlocked = await scene.gameData.setPokemonCaught(newPokemon, true, false, false);
|
const newStarterUnlocked = await scene.gameData.setPokemonCaught(newPokemon, true, false, false);
|
||||||
if (newStarterUnlocked) {
|
if (newStarterUnlocked) {
|
||||||
atLeastOneNewStarter = true;
|
atLeastOneNewStarter = true;
|
||||||
queueEncounterMessage(scene, i18next.t("battle:addedAsAStarter", { pokemonName: getPokemonSpecies(speciesRootForm).getName() }));
|
await showEncounterText(scene, i18next.t("battle:addedAsAStarter", { pokemonName: getPokemonSpecies(speciesRootForm).getName() }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { Moves } from "#app/enums/moves";
|
|||||||
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
|
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import { Type } from "../type";
|
import { Type } from "../type";
|
||||||
import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequirement, TypeRequirement } from "./mystery-encounter-requirements";
|
import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequirement, TypeRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
import { CanLearnMoveRequirement, CanLearnMoveRequirementOptions } from "./requirements/can-learn-move-requirement";
|
import { CanLearnMoveRequirement, CanLearnMoveRequirementOptions } from "./requirements/can-learn-move-requirement";
|
||||||
import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
|
@ -25,6 +25,9 @@ export interface EncounterStartOfBattleEffect {
|
|||||||
followUp?: boolean;
|
followUp?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_MAX_ALLOWED_ENCOUNTERS = 2;
|
||||||
|
const DEFAULT_MAX_ALLOWED_ROGUE_ENCOUNTERS = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by {@linkcode MysteryEncounterBuilder} class to define required/optional properties on the {@linkcode MysteryEncounter} class when building.
|
* Used by {@linkcode MysteryEncounterBuilder} class to define required/optional properties on the {@linkcode MysteryEncounter} class when building.
|
||||||
*
|
*
|
||||||
@ -42,6 +45,7 @@ export interface IMysteryEncounter {
|
|||||||
autoHideIntroVisuals: boolean;
|
autoHideIntroVisuals: boolean;
|
||||||
enterIntroVisualsFromRight: boolean;
|
enterIntroVisualsFromRight: boolean;
|
||||||
catchAllowed: boolean;
|
catchAllowed: boolean;
|
||||||
|
fleeAllowed: boolean;
|
||||||
continuousEncounter: boolean;
|
continuousEncounter: boolean;
|
||||||
maxAllowedEncounters: number;
|
maxAllowedEncounters: number;
|
||||||
hasBattleAnimationsWithoutTargets: boolean;
|
hasBattleAnimationsWithoutTargets: boolean;
|
||||||
@ -110,6 +114,11 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||||||
* Default false
|
* Default false
|
||||||
*/
|
*/
|
||||||
catchAllowed: boolean;
|
catchAllowed: boolean;
|
||||||
|
/**
|
||||||
|
* If true, allows fleeing from a wild encounter (trainer battle MEs auto-disable fleeing)
|
||||||
|
* Default true
|
||||||
|
*/
|
||||||
|
fleeAllowed: boolean;
|
||||||
/**
|
/**
|
||||||
* If true, encounter will continuously run through multiple battles/puzzles/etc. instead of going to next wave
|
* If true, encounter will continuously run through multiple battles/puzzles/etc. instead of going to next wave
|
||||||
* MUST EVENTUALLY BE DISABLED TO CONTINUE TO NEXT WAVE
|
* MUST EVENTUALLY BE DISABLED TO CONTINUE TO NEXT WAVE
|
||||||
@ -246,8 +255,8 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||||||
this.encounterTier = this.encounterTier ?? MysteryEncounterTier.COMMON;
|
this.encounterTier = this.encounterTier ?? MysteryEncounterTier.COMMON;
|
||||||
this.dialogue = this.dialogue ?? {};
|
this.dialogue = this.dialogue ?? {};
|
||||||
this.spriteConfigs = this.spriteConfigs ? [...this.spriteConfigs] : [];
|
this.spriteConfigs = this.spriteConfigs ? [...this.spriteConfigs] : [];
|
||||||
// Default max is 1 for ROGUE encounters, 3 for others
|
// Default max is 1 for ROGUE encounters, 2 for others
|
||||||
this.maxAllowedEncounters = this.maxAllowedEncounters ?? this.encounterTier === MysteryEncounterTier.ROGUE ? 1 : 3;
|
this.maxAllowedEncounters = this.maxAllowedEncounters ?? this.encounterTier === MysteryEncounterTier.ROGUE ? DEFAULT_MAX_ALLOWED_ROGUE_ENCOUNTERS : DEFAULT_MAX_ALLOWED_ENCOUNTERS;
|
||||||
this.encounterMode = MysteryEncounterMode.DEFAULT;
|
this.encounterMode = MysteryEncounterMode.DEFAULT;
|
||||||
this.requirements = this.requirements ? this.requirements : [];
|
this.requirements = this.requirements ? this.requirements : [];
|
||||||
this.hideBattleIntroMessage = this.hideBattleIntroMessage ?? false;
|
this.hideBattleIntroMessage = this.hideBattleIntroMessage ?? false;
|
||||||
@ -520,6 +529,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
enterIntroVisualsFromRight: boolean = false;
|
enterIntroVisualsFromRight: boolean = false;
|
||||||
continuousEncounter: boolean = false;
|
continuousEncounter: boolean = false;
|
||||||
catchAllowed: boolean = false;
|
catchAllowed: boolean = false;
|
||||||
|
fleeAllowed: boolean = true;
|
||||||
lockEncounterRewardTiers: boolean = false;
|
lockEncounterRewardTiers: boolean = false;
|
||||||
startOfBattleEffectsComplete: boolean = false;
|
startOfBattleEffectsComplete: boolean = false;
|
||||||
hasBattleAnimationsWithoutTargets: boolean = false;
|
hasBattleAnimationsWithoutTargets: boolean = false;
|
||||||
@ -580,8 +590,8 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
* There should be at least 2 options defined and no more than 4.
|
* There should be at least 2 options defined and no more than 4.
|
||||||
* If complex use {@linkcode MysteryEncounterBuilder.withOption}
|
* If complex use {@linkcode MysteryEncounterBuilder.withOption}
|
||||||
*
|
*
|
||||||
* @param dialogue - {@linkcode OptionTextDisplay}
|
* @param dialogue {@linkcode OptionTextDisplay}
|
||||||
* @param callback - {@linkcode OptionPhaseCallback}
|
* @param callback {@linkcode OptionPhaseCallback}
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withSimpleDexProgressOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback): this & Pick<IMysteryEncounter, "options"> {
|
withSimpleDexProgressOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback): this & Pick<IMysteryEncounter, "options"> {
|
||||||
@ -732,7 +742,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
*
|
*
|
||||||
* @param min min wave (or exact size if only min is given)
|
* @param min min wave (or exact size if only min is given)
|
||||||
* @param max optional max size. If not given, defaults to min => exact wave
|
* @param max optional max size. If not given, defaults to min => exact wave
|
||||||
* @param excludeFainted - if true, only counts unfainted mons
|
* @param excludeFainted if true, only counts unfainted mons
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withScenePartySizeRequirement(min: number, max?: number, excludeFainted: boolean = false): this & Required<Pick<IMysteryEncounter, "requirements">> {
|
withScenePartySizeRequirement(min: number, max?: number, excludeFainted: boolean = false): this & Required<Pick<IMysteryEncounter, "requirements">> {
|
||||||
@ -798,7 +808,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
* NOTE: If rewards are dependent on options selected, runtime data, etc.,
|
* NOTE: If rewards are dependent on options selected, runtime data, etc.,
|
||||||
* It may be better to programmatically set doEncounterRewards elsewhere.
|
* It may be better to programmatically set doEncounterRewards elsewhere.
|
||||||
* There is a helper function in mystery-encounter utils, setEncounterRewards(), which can be called programmatically to set rewards
|
* There is a helper function in mystery-encounter utils, setEncounterRewards(), which can be called programmatically to set rewards
|
||||||
* @param doEncounterRewards - synchronous callback function to perform during rewards phase of the encounter
|
* @param doEncounterRewards Synchronous callback function to perform during rewards phase of the encounter
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withRewards(doEncounterRewards: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "doEncounterRewards">> {
|
withRewards(doEncounterRewards: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "doEncounterRewards">> {
|
||||||
@ -812,7 +822,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
* NOTE: If rewards are dependent on options selected, runtime data, etc.,
|
* NOTE: If rewards are dependent on options selected, runtime data, etc.,
|
||||||
* It may be better to programmatically set doEncounterExp elsewhere.
|
* It may be better to programmatically set doEncounterExp elsewhere.
|
||||||
* There is a helper function in mystery-encounter utils, setEncounterExp(), which can be called programmatically to set rewards
|
* There is a helper function in mystery-encounter utils, setEncounterExp(), which can be called programmatically to set rewards
|
||||||
* @param doEncounterExp - synchronous callback function to perform during rewards phase of the encounter
|
* @param doEncounterExp Synchronous callback function to perform during rewards phase of the encounter
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withExp(doEncounterExp: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "doEncounterExp">> {
|
withExp(doEncounterExp: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "doEncounterExp">> {
|
||||||
@ -823,7 +833,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
* Can be used to perform init logic before intro visuals are shown and before the MysteryEncounterPhase begins
|
* Can be used to perform init logic before intro visuals are shown and before the MysteryEncounterPhase begins
|
||||||
* Useful for performing things like procedural generation of intro sprites, etc.
|
* Useful for performing things like procedural generation of intro sprites, etc.
|
||||||
*
|
*
|
||||||
* @param onInit - synchronous callback function to perform as soon as the encounter is selected for the next phase
|
* @param onInit Synchronous callback function to perform as soon as the encounter is selected for the next phase
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withOnInit(onInit: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "onInit">> {
|
withOnInit(onInit: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "onInit">> {
|
||||||
@ -833,7 +843,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
/**
|
/**
|
||||||
* Can be used to perform some extra logic (usually animations) when the enemy field is finished sliding in
|
* Can be used to perform some extra logic (usually animations) when the enemy field is finished sliding in
|
||||||
*
|
*
|
||||||
* @param onVisualsStart - synchronous callback function to perform as soon as the enemy field finishes sliding in
|
* @param onVisualsStart Synchronous callback function to perform as soon as the enemy field finishes sliding in
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withOnVisualsStart(onVisualsStart: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "onVisualsStart">> {
|
withOnVisualsStart(onVisualsStart: (scene: BattleScene) => boolean): this & Required<Pick<IMysteryEncounter, "onVisualsStart">> {
|
||||||
@ -843,7 +853,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
/**
|
/**
|
||||||
* Can set whether catching is allowed or not on the encounter
|
* Can set whether catching is allowed or not on the encounter
|
||||||
* This flag can also be programmatically set inside option event functions or elsewhere
|
* This flag can also be programmatically set inside option event functions or elsewhere
|
||||||
* @param catchAllowed - if true, allows enemy pokemon to be caught during the encounter
|
* @param catchAllowed If `true`, allows enemy pokemon to be caught during the encounter
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withCatchAllowed(catchAllowed: boolean): this & Required<Pick<IMysteryEncounter, "catchAllowed">> {
|
withCatchAllowed(catchAllowed: boolean): this & Required<Pick<IMysteryEncounter, "catchAllowed">> {
|
||||||
@ -851,7 +861,16 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param hideBattleIntroMessage - if true, will not show the trainerAppeared/wildAppeared/bossAppeared message for an encounter
|
* Can set whether fleeing is allowed or not on the encounter
|
||||||
|
* @param fleeAllowed If `false`, prevents fleeing from a wild battle (trainer battle MEs already have flee disabled)
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
withFleeAllowed(fleeAllowed: boolean): this & Required<Pick<IMysteryEncounter, "fleeAllowed">> {
|
||||||
|
return Object.assign(this, { fleeAllowed });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param hideBattleIntroMessage If `true`, will not show the trainerAppeared/wildAppeared/bossAppeared message for an encounter
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withHideWildIntroMessage(hideBattleIntroMessage: boolean): this & Required<Pick<IMysteryEncounter, "hideBattleIntroMessage">> {
|
withHideWildIntroMessage(hideBattleIntroMessage: boolean): this & Required<Pick<IMysteryEncounter, "hideBattleIntroMessage">> {
|
||||||
@ -859,7 +878,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param autoHideIntroVisuals - if false, will not hide the intro visuals that are displayed at the beginning of encounter
|
* @param autoHideIntroVisuals If `false`, will not hide the intro visuals that are displayed at the beginning of encounter
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withAutoHideIntroVisuals(autoHideIntroVisuals: boolean): this & Required<Pick<IMysteryEncounter, "autoHideIntroVisuals">> {
|
withAutoHideIntroVisuals(autoHideIntroVisuals: boolean): this & Required<Pick<IMysteryEncounter, "autoHideIntroVisuals">> {
|
||||||
@ -867,7 +886,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param enterIntroVisualsFromRight - If true, will slide in intro visuals from the right side of the screen. If false, slides in from left, as normal
|
* @param enterIntroVisualsFromRight If `true`, will slide in intro visuals from the right side of the screen. If false, slides in from left, as normal
|
||||||
* Default false
|
* Default false
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
@ -878,7 +897,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
/**
|
/**
|
||||||
* Add a title for the encounter
|
* Add a title for the encounter
|
||||||
*
|
*
|
||||||
* @param title - title of the encounter
|
* @param title Title of the encounter
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withTitle(title: string): this {
|
withTitle(title: string): this {
|
||||||
@ -898,7 +917,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
/**
|
/**
|
||||||
* Add a description of the encounter
|
* Add a description of the encounter
|
||||||
*
|
*
|
||||||
* @param description - description of the encounter
|
* @param description Description of the encounter
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withDescription(description: string): this {
|
withDescription(description: string): this {
|
||||||
@ -918,7 +937,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
/**
|
/**
|
||||||
* Add a query for the encounter
|
* Add a query for the encounter
|
||||||
*
|
*
|
||||||
* @param query - query to use for the encounter
|
* @param query Query to use for the encounter
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withQuery(query: string): this {
|
withQuery(query: string): this {
|
||||||
@ -938,7 +957,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||||||
/**
|
/**
|
||||||
* Add outro dialogue/s for the encounter
|
* Add outro dialogue/s for the encounter
|
||||||
*
|
*
|
||||||
* @param dialogue - outro dialogue/s
|
* @param dialogue Outro dialogue(s)
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
withOutroDialogue(dialogue: MysteryEncounterDialogue["outro"] = []): this {
|
withOutroDialogue(dialogue: MysteryEncounterDialogue["outro"] = []): this {
|
||||||
|
@ -31,6 +31,7 @@ import { BugTypeSuperfanEncounter } from "#app/data/mystery-encounters/encounter
|
|||||||
import { FunAndGamesEncounter } from "#app/data/mystery-encounters/encounters/fun-and-games-encounter";
|
import { FunAndGamesEncounter } from "#app/data/mystery-encounters/encounters/fun-and-games-encounter";
|
||||||
import { UncommonBreedEncounter } from "#app/data/mystery-encounters/encounters/uncommon-breed-encounter";
|
import { UncommonBreedEncounter } from "#app/data/mystery-encounters/encounters/uncommon-breed-encounter";
|
||||||
import { GlobalTradeSystemEncounter } from "#app/data/mystery-encounters/encounters/global-trade-system-encounter";
|
import { GlobalTradeSystemEncounter } from "#app/data/mystery-encounters/encounters/global-trade-system-encounter";
|
||||||
|
import { TheExpertPokemonBreederEncounter } from "#app/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT
|
* Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT
|
||||||
@ -184,7 +185,8 @@ const humanTransitableBiomeEncounters: MysteryEncounterType[] = [
|
|||||||
MysteryEncounterType.SHADY_VITAMIN_DEALER,
|
MysteryEncounterType.SHADY_VITAMIN_DEALER,
|
||||||
MysteryEncounterType.THE_POKEMON_SALESMAN,
|
MysteryEncounterType.THE_POKEMON_SALESMAN,
|
||||||
MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE,
|
MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE,
|
||||||
MysteryEncounterType.THE_WINSTRATE_CHALLENGE
|
MysteryEncounterType.THE_WINSTRATE_CHALLENGE,
|
||||||
|
MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER
|
||||||
];
|
];
|
||||||
|
|
||||||
const civilizationBiomeEncounters: MysteryEncounterType[] = [
|
const civilizationBiomeEncounters: MysteryEncounterType[] = [
|
||||||
@ -238,7 +240,6 @@ export const mysteryEncountersByBiome = new Map<Biome, MysteryEncounterType[]>([
|
|||||||
MysteryEncounterType.SAFARI_ZONE,
|
MysteryEncounterType.SAFARI_ZONE,
|
||||||
MysteryEncounterType.ABSOLUTE_AVARICE
|
MysteryEncounterType.ABSOLUTE_AVARICE
|
||||||
]],
|
]],
|
||||||
|
|
||||||
[Biome.SEA, [
|
[Biome.SEA, [
|
||||||
MysteryEncounterType.LOST_AT_SEA
|
MysteryEncounterType.LOST_AT_SEA
|
||||||
]],
|
]],
|
||||||
@ -275,7 +276,9 @@ export const mysteryEncountersByBiome = new Map<Biome, MysteryEncounterType[]>([
|
|||||||
[Biome.ABYSS, [
|
[Biome.ABYSS, [
|
||||||
MysteryEncounterType.DANCING_LESSONS
|
MysteryEncounterType.DANCING_LESSONS
|
||||||
]],
|
]],
|
||||||
[Biome.SPACE, []],
|
[Biome.SPACE, [
|
||||||
|
MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER
|
||||||
|
]],
|
||||||
[Biome.CONSTRUCTION_SITE, []],
|
[Biome.CONSTRUCTION_SITE, []],
|
||||||
[Biome.JUNGLE, [
|
[Biome.JUNGLE, [
|
||||||
MysteryEncounterType.SAFARI_ZONE
|
MysteryEncounterType.SAFARI_ZONE
|
||||||
@ -319,6 +322,7 @@ export function initMysteryEncounters() {
|
|||||||
allMysteryEncounters[MysteryEncounterType.FUN_AND_GAMES] = FunAndGamesEncounter;
|
allMysteryEncounters[MysteryEncounterType.FUN_AND_GAMES] = FunAndGamesEncounter;
|
||||||
allMysteryEncounters[MysteryEncounterType.UNCOMMON_BREED] = UncommonBreedEncounter;
|
allMysteryEncounters[MysteryEncounterType.UNCOMMON_BREED] = UncommonBreedEncounter;
|
||||||
allMysteryEncounters[MysteryEncounterType.GLOBAL_TRADE_SYSTEM] = GlobalTradeSystemEncounter;
|
allMysteryEncounters[MysteryEncounterType.GLOBAL_TRADE_SYSTEM] = GlobalTradeSystemEncounter;
|
||||||
|
allMysteryEncounters[MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER] = TheExpertPokemonBreederEncounter;
|
||||||
|
|
||||||
// Add extreme encounters to biome map
|
// Add extreme encounters to biome map
|
||||||
extremeBiomeEncounters.forEach(encounter => {
|
extremeBiomeEncounters.forEach(encounter => {
|
||||||
|
@ -2,7 +2,7 @@ import BattleScene from "#app/battle-scene";
|
|||||||
import { Moves } from "#app/enums/moves";
|
import { Moves } from "#app/enums/moves";
|
||||||
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||||
import { isNullOrUndefined } from "#app/utils";
|
import { isNullOrUndefined } from "#app/utils";
|
||||||
import { EncounterPokemonRequirement } from "../mystery-encounter-requirements";
|
import { EncounterPokemonRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@linkcode CanLearnMoveRequirement} options
|
* {@linkcode CanLearnMoveRequirement} options
|
||||||
|
@ -3,7 +3,7 @@ import { biomeLinks, BiomePoolTier } from "#app/data/biomes";
|
|||||||
import MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
|
import MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
import { AVERAGE_ENCOUNTERS_PER_RUN_TARGET, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
import { AVERAGE_ENCOUNTERS_PER_RUN_TARGET, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
||||||
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||||
import Pokemon, { FieldPosition, PlayerPokemon, PokemonMove, PokemonSummonData } from "#app/field/pokemon";
|
import Pokemon, { AiType, FieldPosition, PlayerPokemon, PokemonMove, PokemonSummonData } from "#app/field/pokemon";
|
||||||
import { CustomModifierSettings, ModifierPoolType, ModifierType, ModifierTypeGenerator, ModifierTypeOption, modifierTypes, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
import { CustomModifierSettings, ModifierPoolType, ModifierType, ModifierTypeGenerator, ModifierTypeOption, modifierTypes, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterBattlePhase, MysteryEncounterBattleStartCleanupPhase, MysteryEncounterPhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phases";
|
import { MysteryEncounterBattlePhase, MysteryEncounterBattleStartCleanupPhase, MysteryEncounterPhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phases";
|
||||||
import PokemonData from "#app/system/pokemon-data";
|
import PokemonData from "#app/system/pokemon-data";
|
||||||
@ -36,6 +36,7 @@ import { BattleEndPhase } from "#app/phases/battle-end-phase";
|
|||||||
import { GameOverPhase } from "#app/phases/game-over-phase";
|
import { GameOverPhase } from "#app/phases/game-over-phase";
|
||||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||||
import { PartyExpPhase } from "#app/phases/party-exp-phase";
|
import { PartyExpPhase } from "#app/phases/party-exp-phase";
|
||||||
|
import { Variant } from "#app/data/variant";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Animates exclamation sprite over trainer's head at start of encounter
|
* Animates exclamation sprite over trainer's head at start of encounter
|
||||||
@ -67,6 +68,7 @@ export function doTrainerExclamation(scene: BattleScene) {
|
|||||||
export interface EnemyPokemonConfig {
|
export interface EnemyPokemonConfig {
|
||||||
species: PokemonSpecies;
|
species: PokemonSpecies;
|
||||||
isBoss: boolean;
|
isBoss: boolean;
|
||||||
|
nickname?: string;
|
||||||
bossSegments?: number;
|
bossSegments?: number;
|
||||||
bossSegmentModifier?: number; // Additive to the determined segment number
|
bossSegmentModifier?: number; // Additive to the determined segment number
|
||||||
mysteryEncounterPokemonData?: MysteryEncounterPokemonData;
|
mysteryEncounterPokemonData?: MysteryEncounterPokemonData;
|
||||||
@ -79,27 +81,32 @@ export interface EnemyPokemonConfig {
|
|||||||
nature?: Nature;
|
nature?: Nature;
|
||||||
ivs?: [number, number, number, number, number, number];
|
ivs?: [number, number, number, number, number, number];
|
||||||
shiny?: boolean;
|
shiny?: boolean;
|
||||||
|
/** Is only checked if Pokemon is shiny */
|
||||||
|
variant?: Variant;
|
||||||
/** Can set just the status, or pass a timer on the status turns */
|
/** Can set just the status, or pass a timer on the status turns */
|
||||||
status?: StatusEffect | [StatusEffect, number];
|
status?: StatusEffect | [StatusEffect, number];
|
||||||
mysteryEncounterBattleEffects?: (pokemon: Pokemon) => void;
|
mysteryEncounterBattleEffects?: (pokemon: Pokemon) => void;
|
||||||
modifierConfigs?: HeldModifierConfig[];
|
modifierConfigs?: HeldModifierConfig[];
|
||||||
tags?: BattlerTagType[];
|
tags?: BattlerTagType[];
|
||||||
dataSource?: PokemonData;
|
dataSource?: PokemonData;
|
||||||
|
aiType?: AiType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EnemyPartyConfig {
|
export interface EnemyPartyConfig {
|
||||||
/** Formula for enemy: level += waveIndex / 10 * levelAdditive */
|
/** Formula for enemy level: level += waveIndex / 10 * levelAdditiveModifier */
|
||||||
levelAdditiveMultiplier?: number;
|
levelAdditiveModifier?: number;
|
||||||
doubleBattle?: boolean;
|
doubleBattle?: boolean;
|
||||||
/** Generates trainer battle solely off trainer type */
|
/** Generates trainer battle solely off trainer type */
|
||||||
trainerType?: TrainerType;
|
trainerType?: TrainerType;
|
||||||
/** More customizable option for configuring trainer battle */
|
/** More customizable option for configuring trainer battle */
|
||||||
trainerConfig?: TrainerConfig;
|
trainerConfig?: TrainerConfig;
|
||||||
pokemonConfigs?: EnemyPokemonConfig[];
|
pokemonConfigs?: EnemyPokemonConfig[];
|
||||||
/** True for female trainer, false for male */
|
/** `true` for female trainer, false for male */
|
||||||
female?: boolean;
|
female?: boolean;
|
||||||
/** True will prevent player from switching */
|
/** `true` will prevent player from switching */
|
||||||
disableSwitch?: boolean;
|
disableSwitch?: boolean;
|
||||||
|
/** `true` or leaving undefined will increment dex seen count for the encounter battle, `false` will not */
|
||||||
|
countAsSeen?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,10 +163,10 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||||||
|
|
||||||
// ME levels are modified by an additive value that scales with wave index
|
// ME levels are modified by an additive value that scales with wave index
|
||||||
// Base scaling: Every 10 waves, modifier gets +1 level
|
// Base scaling: Every 10 waves, modifier gets +1 level
|
||||||
// This can be amplified or counteracted by setting levelAdditiveMultiplier in config
|
// This can be amplified or counteracted by setting levelAdditiveModifier in config
|
||||||
// levelAdditiveMultiplier value of 0.5 will halve the modifier scaling, 2 will double it, etc.
|
// levelAdditiveModifier value of 0.5 will halve the modifier scaling, 2 will double it, etc.
|
||||||
// Leaving null/undefined will disable level scaling
|
// Leaving null/undefined will disable level scaling
|
||||||
const mult: number = !isNullOrUndefined(partyConfig.levelAdditiveMultiplier) ? partyConfig.levelAdditiveMultiplier! : 0;
|
const mult: number = !isNullOrUndefined(partyConfig.levelAdditiveModifier) ? partyConfig.levelAdditiveModifier! : 0;
|
||||||
const additive = Math.max(Math.round((scene.currentBattle.waveIndex / 10) * mult), 0);
|
const additive = Math.max(Math.round((scene.currentBattle.waveIndex / 10) * mult), 0);
|
||||||
battle.enemyLevels = battle.enemyLevels.map(level => level + additive);
|
battle.enemyLevels = battle.enemyLevels.map(level => level + additive);
|
||||||
|
|
||||||
@ -210,13 +217,18 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||||||
enemyPokemon.resetSummonData();
|
enemyPokemon.resetSummonData();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loaded) {
|
if (!loaded && isNullOrUndefined(partyConfig.countAsSeen) || partyConfig.countAsSeen) {
|
||||||
scene.gameData.setPokemonSeen(enemyPokemon, true, !!(trainerType || trainerConfig));
|
scene.gameData.setPokemonSeen(enemyPokemon, true, !!(trainerType || trainerConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (partyConfig?.pokemonConfigs && e < partyConfig.pokemonConfigs.length) {
|
if (partyConfig?.pokemonConfigs && e < partyConfig.pokemonConfigs.length) {
|
||||||
const config = partyConfig.pokemonConfigs[e];
|
const config = partyConfig.pokemonConfigs[e];
|
||||||
|
|
||||||
|
// Set form
|
||||||
|
if (!isNullOrUndefined(config.nickname)) {
|
||||||
|
enemyPokemon.nickname = btoa(unescape(encodeURIComponent(config.nickname!)));
|
||||||
|
}
|
||||||
|
|
||||||
// Generate new id, reset status and HP in case using data source
|
// Generate new id, reset status and HP in case using data source
|
||||||
if (config.dataSource) {
|
if (config.dataSource) {
|
||||||
enemyPokemon.id = Utils.randSeedInt(4294967296);
|
enemyPokemon.id = Utils.randSeedInt(4294967296);
|
||||||
@ -232,6 +244,11 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||||||
enemyPokemon.shiny = config.shiny!;
|
enemyPokemon.shiny = config.shiny!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set Variant
|
||||||
|
if (enemyPokemon.shiny && !isNullOrUndefined(config.variant)) {
|
||||||
|
enemyPokemon.variant = config.variant!;
|
||||||
|
}
|
||||||
|
|
||||||
// Set custom mystery encounter data fields (such as sprite scale, custom abilities, types, etc.)
|
// Set custom mystery encounter data fields (such as sprite scale, custom abilities, types, etc.)
|
||||||
if (!isNullOrUndefined(config.mysteryEncounterPokemonData)) {
|
if (!isNullOrUndefined(config.mysteryEncounterPokemonData)) {
|
||||||
enemyPokemon.mysteryEncounterPokemonData = config.mysteryEncounterPokemonData!;
|
enemyPokemon.mysteryEncounterPokemonData = config.mysteryEncounterPokemonData!;
|
||||||
@ -286,6 +303,11 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||||||
enemyPokemon.summonData.gender = config.gender!;
|
enemyPokemon.summonData.gender = config.gender!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set AI type
|
||||||
|
if (!isNullOrUndefined(config.aiType)) {
|
||||||
|
enemyPokemon.aiType = config.aiType!;
|
||||||
|
}
|
||||||
|
|
||||||
// Set moves
|
// Set moves
|
||||||
if (config?.moveSet && config.moveSet.length > 0) {
|
if (config?.moveSet && config.moveSet.length > 0) {
|
||||||
const moves = config.moveSet.map(m => new PokemonMove(m));
|
const moves = config.moveSet.map(m => new PokemonMove(m));
|
||||||
@ -307,6 +329,9 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||||||
// Requires re-priming summon data to update everything properly
|
// Requires re-priming summon data to update everything properly
|
||||||
enemyPokemon.primeSummonData(enemyPokemon.summonData);
|
enemyPokemon.primeSummonData(enemyPokemon.summonData);
|
||||||
|
|
||||||
|
if (enemyPokemon.isShiny() && !enemyPokemon["shinySparkle"]) {
|
||||||
|
enemyPokemon.initShinySparkle();
|
||||||
|
}
|
||||||
enemyPokemon.initBattleInfo();
|
enemyPokemon.initBattleInfo();
|
||||||
enemyPokemon.getBattleInfo().initInfo(enemyPokemon);
|
enemyPokemon.getBattleInfo().initInfo(enemyPokemon);
|
||||||
enemyPokemon.generateName();
|
enemyPokemon.generateName();
|
||||||
@ -702,19 +727,19 @@ export function handleMysteryEncounterVictory(scene: BattleScene, addHealPhase:
|
|||||||
if (encounter.continuousEncounter || doNotContinue) {
|
if (encounter.continuousEncounter || doNotContinue) {
|
||||||
return;
|
return;
|
||||||
} else if (encounter.encounterMode === MysteryEncounterMode.NO_BATTLE) {
|
} else if (encounter.encounterMode === MysteryEncounterMode.NO_BATTLE) {
|
||||||
scene.pushPhase(new EggLapsePhase(scene));
|
|
||||||
scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase));
|
scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase));
|
||||||
|
scene.pushPhase(new EggLapsePhase(scene));
|
||||||
} else if (!scene.getEnemyParty().find(p => encounter.encounterMode !== MysteryEncounterMode.TRAINER_BATTLE ? p.isOnField() : !p?.isFainted(true))) {
|
} else if (!scene.getEnemyParty().find(p => encounter.encounterMode !== MysteryEncounterMode.TRAINER_BATTLE ? p.isOnField() : !p?.isFainted(true))) {
|
||||||
scene.pushPhase(new BattleEndPhase(scene));
|
scene.pushPhase(new BattleEndPhase(scene));
|
||||||
if (encounter.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
if (encounter.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
scene.pushPhase(new TrainerVictoryPhase(scene));
|
scene.pushPhase(new TrainerVictoryPhase(scene));
|
||||||
}
|
}
|
||||||
if (scene.gameMode.isEndless || !scene.gameMode.isWaveFinal(scene.currentBattle.waveIndex)) {
|
if (scene.gameMode.isEndless || !scene.gameMode.isWaveFinal(scene.currentBattle.waveIndex)) {
|
||||||
|
scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase));
|
||||||
if (!encounter.doContinueEncounter) {
|
if (!encounter.doContinueEncounter) {
|
||||||
// Only lapse eggs once for multi-battle encounters
|
// Only lapse eggs once for multi-battle encounters
|
||||||
scene.pushPhase(new EggLapsePhase(scene));
|
scene.pushPhase(new EggLapsePhase(scene));
|
||||||
}
|
}
|
||||||
scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,10 @@ import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifi
|
|||||||
import { Gender } from "#app/data/gender";
|
import { Gender } from "#app/data/gender";
|
||||||
import { PermanentStat } from "#enums/stat";
|
import { PermanentStat } from "#enums/stat";
|
||||||
import { VictoryPhase } from "#app/phases/victory-phase";
|
import { VictoryPhase } from "#app/phases/victory-phase";
|
||||||
|
import { SummaryUiMode } from "#app/ui/summary-ui-handler";
|
||||||
|
|
||||||
|
/** Will give +1 level every 10 waves */
|
||||||
|
export const STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the sprite key and file root for a given PokemonSpecies (accounts for gender, shiny, variants, forms, and experimental)
|
* Gets the sprite key and file root for a given PokemonSpecies (accounts for gender, shiny, variants, forms, and experimental)
|
||||||
@ -289,10 +293,12 @@ export async function modifyPlayerPokemonBST(pokemon: PlayerPokemon, value: numb
|
|||||||
*/
|
*/
|
||||||
export async function applyModifierTypeToPlayerPokemon(scene: BattleScene, pokemon: PlayerPokemon, modType: PokemonHeldItemModifierType, fallbackModifierType?: PokemonHeldItemModifierType) {
|
export async function applyModifierTypeToPlayerPokemon(scene: BattleScene, pokemon: PlayerPokemon, modType: PokemonHeldItemModifierType, fallbackModifierType?: PokemonHeldItemModifierType) {
|
||||||
// Check if the Pokemon has max stacks of that item already
|
// Check if the Pokemon has max stacks of that item already
|
||||||
|
const modifier = modType.newModifier(pokemon);
|
||||||
const existing = scene.findModifier(m => (
|
const existing = scene.findModifier(m => (
|
||||||
m instanceof PokemonHeldItemModifier &&
|
m instanceof PokemonHeldItemModifier &&
|
||||||
m.type.id === modType.id &&
|
m.type.id === modType.id &&
|
||||||
m.pokemonId === pokemon.id
|
m.pokemonId === pokemon.id &&
|
||||||
|
m.matchType(modifier)
|
||||||
)) as PokemonHeldItemModifier;
|
)) as PokemonHeldItemModifier;
|
||||||
|
|
||||||
// At max stacks
|
// At max stacks
|
||||||
@ -305,7 +311,6 @@ export async function applyModifierTypeToPlayerPokemon(scene: BattleScene, pokem
|
|||||||
return applyModifierTypeToPlayerPokemon(scene, pokemon, fallbackModifierType);
|
return applyModifierTypeToPlayerPokemon(scene, pokemon, fallbackModifierType);
|
||||||
}
|
}
|
||||||
|
|
||||||
const modifier = modType.newModifier(pokemon);
|
|
||||||
await scene.addModifier(modifier, false, false, false, true);
|
await scene.addModifier(modifier, false, false, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,7 +332,7 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon,
|
|||||||
const _3m = 3 * pokemon.getMaxHp();
|
const _3m = 3 * pokemon.getMaxHp();
|
||||||
const _2h = 2 * pokemon.hp;
|
const _2h = 2 * pokemon.hp;
|
||||||
const catchRate = pokemon.species.catchRate;
|
const catchRate = pokemon.species.catchRate;
|
||||||
const pokeballMultiplier = getPokeballCatchMultiplier(this.pokeballType);
|
const pokeballMultiplier = getPokeballCatchMultiplier(pokeballType);
|
||||||
const statusMultiplier = pokemon.status ? getStatusEffectCatchRateMultiplier(pokemon.status.effect) : 1;
|
const statusMultiplier = pokemon.status ? getStatusEffectCatchRateMultiplier(pokemon.status.effect) : 1;
|
||||||
const x = Math.round((((_3m - _2h) * catchRate * pokeballMultiplier) / _3m) * statusMultiplier);
|
const x = Math.round((((_3m - _2h) * catchRate * pokeballMultiplier) / _3m) * statusMultiplier);
|
||||||
ballTwitchRate = Math.round(65536 / Math.sqrt(Math.sqrt(255 / x)));
|
ballTwitchRate = Math.round(65536 / Math.sqrt(Math.sqrt(255 / x)));
|
||||||
@ -501,8 +506,6 @@ function failCatch(scene: BattleScene, pokemon: EnemyPokemon, originalY: number,
|
|||||||
* @param isObtain
|
* @param isObtain
|
||||||
*/
|
*/
|
||||||
export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, pokeball: Phaser.GameObjects.Sprite | null, pokeballType: PokeballType, showCatchObtainMessage: boolean = true, isObtain: boolean = false): Promise<void> {
|
export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, pokeball: Phaser.GameObjects.Sprite | null, pokeballType: PokeballType, showCatchObtainMessage: boolean = true, isObtain: boolean = false): Promise<void> {
|
||||||
scene.unshiftPhase(new VictoryPhase(scene, pokemon.id, true));
|
|
||||||
|
|
||||||
const speciesForm = !pokemon.fusionSpecies ? pokemon.getSpeciesForm() : pokemon.getFusionSpeciesForm();
|
const speciesForm = !pokemon.fusionSpecies ? pokemon.getSpeciesForm() : pokemon.getFusionSpeciesForm();
|
||||||
|
|
||||||
if (speciesForm.abilityHidden && (pokemon.fusionSpecies ? pokemon.fusionAbilityIndex : pokemon.abilityIndex) === speciesForm.getAbilityCount() - 1) {
|
if (speciesForm.abilityHidden && (pokemon.fusionSpecies ? pokemon.fusionAbilityIndex : pokemon.abilityIndex) === speciesForm.getAbilityCount() - 1) {
|
||||||
@ -528,6 +531,11 @@ export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, po
|
|||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const doPokemonCatchMenu = () => {
|
const doPokemonCatchMenu = () => {
|
||||||
const end = () => {
|
const end = () => {
|
||||||
|
// Ensure the pokemon is in the enemy party in all situations
|
||||||
|
if (!scene.getEnemyParty().some(p => p.id === pokemon.id)) {
|
||||||
|
scene.getEnemyParty().push(pokemon);
|
||||||
|
}
|
||||||
|
scene.unshiftPhase(new VictoryPhase(scene, pokemon.id, true));
|
||||||
scene.pokemonInfoContainer.hide();
|
scene.pokemonInfoContainer.hide();
|
||||||
if (pokeball) {
|
if (pokeball) {
|
||||||
removePb(scene, pokeball);
|
removePb(scene, pokeball);
|
||||||
@ -539,8 +547,8 @@ export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, po
|
|||||||
scene.field.remove(pokemon, true);
|
scene.field.remove(pokemon, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const addToParty = () => {
|
const addToParty = (slotIndex?: number) => {
|
||||||
const newPokemon = pokemon.addToParty(pokeballType);
|
const newPokemon = pokemon.addToParty(pokeballType, slotIndex);
|
||||||
const modifiers = scene.findModifiers(m => m instanceof PokemonHeldItemModifier, false);
|
const modifiers = scene.findModifiers(m => m instanceof PokemonHeldItemModifier, false);
|
||||||
if (scene.getParty().filter(p => p.isShiny()).length === 6) {
|
if (scene.getParty().filter(p => p.isShiny()).length === 6) {
|
||||||
scene.validateAchv(achvs.SHINY_PARTY);
|
scene.validateAchv(achvs.SHINY_PARTY);
|
||||||
@ -559,12 +567,19 @@ export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, po
|
|||||||
if (scene.getParty().length === 6) {
|
if (scene.getParty().length === 6) {
|
||||||
const promptRelease = () => {
|
const promptRelease = () => {
|
||||||
scene.ui.showText(i18next.t("battle:partyFull", { pokemonName: pokemon.getNameToRender() }), null, () => {
|
scene.ui.showText(i18next.t("battle:partyFull", { pokemonName: pokemon.getNameToRender() }), null, () => {
|
||||||
scene.pokemonInfoContainer.makeRoomForConfirmUi();
|
scene.pokemonInfoContainer.makeRoomForConfirmUi(1, true);
|
||||||
scene.ui.setMode(Mode.CONFIRM, () => {
|
scene.ui.setMode(Mode.CONFIRM, () => {
|
||||||
scene.ui.setMode(Mode.PARTY, PartyUiMode.RELEASE, 0, (slotIndex: number, _option: PartyOption) => {
|
const newPokemon = scene.addPlayerPokemon(pokemon.species, pokemon.level, pokemon.abilityIndex, pokemon.formIndex, pokemon.gender, pokemon.shiny, pokemon.variant, pokemon.ivs, pokemon.nature, pokemon);
|
||||||
|
scene.ui.setMode(Mode.SUMMARY, newPokemon, 0, SummaryUiMode.DEFAULT, () => {
|
||||||
|
scene.ui.setMode(Mode.MESSAGE).then(() => {
|
||||||
|
promptRelease();
|
||||||
|
});
|
||||||
|
}, false);
|
||||||
|
}, () => {
|
||||||
|
scene.ui.setMode(Mode.PARTY, PartyUiMode.RELEASE, 0, (slotIndex: integer, _option: PartyOption) => {
|
||||||
scene.ui.setMode(Mode.MESSAGE).then(() => {
|
scene.ui.setMode(Mode.MESSAGE).then(() => {
|
||||||
if (slotIndex < 6) {
|
if (slotIndex < 6) {
|
||||||
addToParty();
|
addToParty(slotIndex);
|
||||||
} else {
|
} else {
|
||||||
promptRelease();
|
promptRelease();
|
||||||
}
|
}
|
||||||
@ -575,7 +590,7 @@ export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, po
|
|||||||
removePokemon();
|
removePokemon();
|
||||||
end();
|
end();
|
||||||
});
|
});
|
||||||
});
|
}, "fullParty");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
promptRelease();
|
promptRelease();
|
||||||
@ -711,13 +726,50 @@ export function getGoldenBugNetSpecies(): PokemonSpecies {
|
|||||||
const roll = randSeedInt(totalWeight);
|
const roll = randSeedInt(totalWeight);
|
||||||
|
|
||||||
let w = 0;
|
let w = 0;
|
||||||
for (const species of GOLDEN_BUG_NET_SPECIES_POOL) {
|
for (const speciesWeightPair of GOLDEN_BUG_NET_SPECIES_POOL) {
|
||||||
w += species[1];
|
w += speciesWeightPair[1];
|
||||||
if (roll < w) {
|
if (roll < w) {
|
||||||
return getPokemonSpecies(species);
|
return getPokemonSpecies(speciesWeightPair[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defaults to Scyther
|
// Defaults to Scyther
|
||||||
return getPokemonSpecies(Species.SCYTHER);
|
return getPokemonSpecies(Species.SCYTHER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a Pokemon level for a given wave, with an option to increase/decrease by a scaling modifier
|
||||||
|
* @param scene
|
||||||
|
* @param levelAdditiveModifier Default 0. will add +(1 level / 10 waves * levelAdditiveModifier) to the level calculation
|
||||||
|
*/
|
||||||
|
export function getEncounterPokemonLevelForWave(scene: BattleScene, levelAdditiveModifier: number = 0) {
|
||||||
|
const currentBattle = scene.currentBattle;
|
||||||
|
// Default to use the first generated level from enemyLevels, or generate a new one if it DNE
|
||||||
|
const baseLevel = currentBattle.enemyLevels && currentBattle.enemyLevels?.length > 0 ? currentBattle.enemyLevels[0] : currentBattle.getLevelForWave();
|
||||||
|
|
||||||
|
// Add a level scaling modifier that is (+1 level per 10 waves) * levelAdditiveModifier
|
||||||
|
return baseLevel + Math.max(Math.round((currentBattle.waveIndex / 10) * levelAdditiveModifier), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function addPokemonDataToDexAndValidateAchievements(scene: BattleScene, pokemon: PlayerPokemon) {
|
||||||
|
const speciesForm = !pokemon.fusionSpecies ? pokemon.getSpeciesForm() : pokemon.getFusionSpeciesForm();
|
||||||
|
|
||||||
|
if (speciesForm.abilityHidden && (pokemon.fusionSpecies ? pokemon.fusionAbilityIndex : pokemon.abilityIndex) === speciesForm.getAbilityCount() - 1) {
|
||||||
|
scene.validateAchv(achvs.HIDDEN_ABILITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pokemon.species.subLegendary) {
|
||||||
|
scene.validateAchv(achvs.CATCH_SUB_LEGENDARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pokemon.species.legendary) {
|
||||||
|
scene.validateAchv(achvs.CATCH_LEGENDARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pokemon.species.mythical) {
|
||||||
|
scene.validateAchv(achvs.CATCH_MYTHICAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
scene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs);
|
||||||
|
return scene.gameData.setPokemonCaught(pokemon, true, false, false);
|
||||||
|
}
|
||||||
|
@ -103,7 +103,7 @@ export function doPokemonTransformationSequence(scene: BattleScene, previousPoke
|
|||||||
scene.time.delayedCall(1000, () => {
|
scene.time.delayedCall(1000, () => {
|
||||||
pokemonEvoTintSprite.setScale(0.25);
|
pokemonEvoTintSprite.setScale(0.25);
|
||||||
pokemonEvoTintSprite.setVisible(true);
|
pokemonEvoTintSprite.setVisible(true);
|
||||||
doCycle(scene, 2, 6, pokemonTintSprite, pokemonEvoTintSprite).then(() => {
|
doCycle(scene, 1.5, 6, pokemonTintSprite, pokemonEvoTintSprite).then(() => {
|
||||||
pokemonEvoSprite.setVisible(true);
|
pokemonEvoSprite.setVisible(true);
|
||||||
doCircleInward(scene, transformationBaseBg, transformationContainer, xOffset, yOffset);
|
doCircleInward(scene, transformationBaseBg, transformationContainer, xOffset, yOffset);
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ export function doPokemonTransformationSequence(scene: BattleScene, previousPoke
|
|||||||
delay: 150,
|
delay: 150,
|
||||||
easing: "Sine.easeIn",
|
easing: "Sine.easeIn",
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
scene.time.delayedCall(2500, () => {
|
scene.time.delayedCall(3000, () => {
|
||||||
resolve();
|
resolve();
|
||||||
scene.tweens.add({
|
scene.tweens.add({
|
||||||
targets: pokemonEvoSprite,
|
targets: pokemonEvoSprite,
|
||||||
|
@ -684,7 +684,7 @@ export const pokemonFormChanges: PokemonFormChanges = {
|
|||||||
new SpeciesFormChange(Species.GROUDON, "", SpeciesFormKey.PRIMAL, new SpeciesFormChangeItemTrigger(FormChangeItem.RED_ORB))
|
new SpeciesFormChange(Species.GROUDON, "", SpeciesFormKey.PRIMAL, new SpeciesFormChangeItemTrigger(FormChangeItem.RED_ORB))
|
||||||
],
|
],
|
||||||
[Species.RAYQUAZA]: [
|
[Species.RAYQUAZA]: [
|
||||||
new SpeciesFormChange(Species.RAYQUAZA, "", SpeciesFormKey.MEGA, new SpeciesFormChangeCompoundTrigger(new SpeciesFormChangeItemTrigger(FormChangeItem.RAYQUAZITE), new SpeciesFormChangeMoveLearnedTrigger(Moves.DRAGON_ASCENT)))
|
new SpeciesFormChange(Species.RAYQUAZA, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.RAYQUAZITE))
|
||||||
],
|
],
|
||||||
[Species.DEOXYS]: [
|
[Species.DEOXYS]: [
|
||||||
new SpeciesFormChange(Species.DEOXYS, "normal", "attack", new SpeciesFormChangeItemTrigger(FormChangeItem.SHARP_METEORITE)),
|
new SpeciesFormChange(Species.DEOXYS, "normal", "attack", new SpeciesFormChangeItemTrigger(FormChangeItem.SHARP_METEORITE)),
|
||||||
|
@ -1,46 +1,136 @@
|
|||||||
import i18next from "i18next";
|
import { USE_SEASONAL_SPLASH_MESSAGES } from "#app/constants";
|
||||||
|
|
||||||
export function getBattleCountSplashMessage(): string {
|
//#region Interfaces/Types
|
||||||
return `{COUNT} ${i18next.t("splashMessages:battlesWon")}`;
|
|
||||||
|
type Month = "01" | "02" | "03" | "04" | "05" | "06" | "07" | "08" | "09" | "10" | "11" | "12";
|
||||||
|
type Day =
|
||||||
|
| Month
|
||||||
|
| "13"
|
||||||
|
| "14"
|
||||||
|
| "15"
|
||||||
|
| "16"
|
||||||
|
| "17"
|
||||||
|
| "18"
|
||||||
|
| "19"
|
||||||
|
| "20"
|
||||||
|
| "21"
|
||||||
|
| "22"
|
||||||
|
| "23"
|
||||||
|
| "24"
|
||||||
|
| "25"
|
||||||
|
| "26"
|
||||||
|
| "27"
|
||||||
|
| "28"
|
||||||
|
| "29"
|
||||||
|
| "30"
|
||||||
|
| "31";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a season with its {@linkcode name},
|
||||||
|
* {@linkcode start} day+month, {@linkcode end} day+month
|
||||||
|
* and {@linkcode messages}.
|
||||||
|
*/
|
||||||
|
interface Season {
|
||||||
|
/** The name of the season (internal use only) */
|
||||||
|
name: string;
|
||||||
|
/** The start day and month of the season. Format `MM-DD` */
|
||||||
|
start: `${Month}-${Day}`;
|
||||||
|
/** The end day and month of the season. Format `MM-DD` */
|
||||||
|
end: `${Month}-${Day}`;
|
||||||
|
/** Collection of the messages to display (without the `i18next.t()` call!) */
|
||||||
|
messages: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#region Constants
|
||||||
|
|
||||||
|
/** The weight multiplier for the battles-won splash message */
|
||||||
|
const BATTLES_WON_WEIGHT_MULTIPLIER = 10;
|
||||||
|
/** The weight multiplier for the seasonal splash messages */
|
||||||
|
const SEASONAL_WEIGHT_MULTIPLIER = 10;
|
||||||
|
|
||||||
|
//#region Common Messages
|
||||||
|
|
||||||
|
const commonSplashMessages = [
|
||||||
|
...Array(BATTLES_WON_WEIGHT_MULTIPLIER).fill("battlesWon"),
|
||||||
|
"joinTheDiscord",
|
||||||
|
"infiniteLevels",
|
||||||
|
"everythingStacks",
|
||||||
|
"optionalSaveScumming",
|
||||||
|
"biomes",
|
||||||
|
"openSource",
|
||||||
|
"playWithSpeed",
|
||||||
|
"liveBugTesting",
|
||||||
|
"heavyInfluence",
|
||||||
|
"pokemonRiskAndPokemonRain",
|
||||||
|
"nowWithMoreSalt",
|
||||||
|
"infiniteFusionAtHome",
|
||||||
|
"brokenEggMoves",
|
||||||
|
"magnificent",
|
||||||
|
"mubstitute",
|
||||||
|
"thatsCrazy",
|
||||||
|
"oranceJuice",
|
||||||
|
"questionableBalancing",
|
||||||
|
"coolShaders",
|
||||||
|
"aiFree",
|
||||||
|
"suddenDifficultySpikes",
|
||||||
|
"basedOnAnUnfinishedFlashGame",
|
||||||
|
"moreAddictiveThanIntended",
|
||||||
|
"mostlyConsistentSeeds",
|
||||||
|
"achievementPointsDontDoAnything",
|
||||||
|
"youDoNotStartAtLevel",
|
||||||
|
"dontTalkAboutTheManaphyEggIncident",
|
||||||
|
"alsoTryPokengine",
|
||||||
|
"alsoTryEmeraldRogue",
|
||||||
|
"alsoTryRadicalRed",
|
||||||
|
"eeveeExpo",
|
||||||
|
"ynoproject",
|
||||||
|
"breedersInSpace",
|
||||||
|
];
|
||||||
|
|
||||||
|
//#region Seasonal Messages
|
||||||
|
|
||||||
|
const seasonalSplashMessages: Season[] = [
|
||||||
|
{
|
||||||
|
name: "Halloween",
|
||||||
|
start: "09-15",
|
||||||
|
end: "10-31",
|
||||||
|
messages: ["halloween.pumpkaboosAbout", "halloween.mayContainSpiders", "halloween.spookyScaryDuskulls"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "XMAS",
|
||||||
|
start: "12-01",
|
||||||
|
end: "12-26",
|
||||||
|
messages: ["xmas.happyHolidays", "xmas.delibirdSeason"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "New Year's",
|
||||||
|
start: "01-01",
|
||||||
|
end: "01-31",
|
||||||
|
messages: ["newYears.happyNewYear"],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
export function getSplashMessages(): string[] {
|
export function getSplashMessages(): string[] {
|
||||||
const splashMessages = Array(10).fill(getBattleCountSplashMessage());
|
const splashMessages: string[] = [...commonSplashMessages];
|
||||||
splashMessages.push(
|
console.log("use seasonal splash messages", USE_SEASONAL_SPLASH_MESSAGES);
|
||||||
i18next.t("splashMessages:joinTheDiscord"),
|
if (USE_SEASONAL_SPLASH_MESSAGES) {
|
||||||
i18next.t("splashMessages:infiniteLevels"),
|
// add seasonal splash messages if the season is active
|
||||||
i18next.t("splashMessages:everythingStacks"),
|
for (const { name, start, end, messages } of seasonalSplashMessages) {
|
||||||
i18next.t("splashMessages:optionalSaveScumming"),
|
const now = new Date();
|
||||||
i18next.t("splashMessages:biomes"),
|
const startDate = new Date(`${start}-${now.getFullYear()}`);
|
||||||
i18next.t("splashMessages:openSource"),
|
const endDate = new Date(`${end}-${now.getFullYear()}`);
|
||||||
i18next.t("splashMessages:playWithSpeed"),
|
|
||||||
i18next.t("splashMessages:liveBugTesting"),
|
|
||||||
i18next.t("splashMessages:heavyInfluence"),
|
|
||||||
i18next.t("splashMessages:pokemonRiskAndPokemonRain"),
|
|
||||||
i18next.t("splashMessages:nowWithMoreSalt"),
|
|
||||||
i18next.t("splashMessages:infiniteFusionAtHome"),
|
|
||||||
i18next.t("splashMessages:brokenEggMoves"),
|
|
||||||
i18next.t("splashMessages:magnificent"),
|
|
||||||
i18next.t("splashMessages:mubstitute"),
|
|
||||||
i18next.t("splashMessages:thatsCrazy"),
|
|
||||||
i18next.t("splashMessages:oranceJuice"),
|
|
||||||
i18next.t("splashMessages:questionableBalancing"),
|
|
||||||
i18next.t("splashMessages:coolShaders"),
|
|
||||||
i18next.t("splashMessages:aiFree"),
|
|
||||||
i18next.t("splashMessages:suddenDifficultySpikes"),
|
|
||||||
i18next.t("splashMessages:basedOnAnUnfinishedFlashGame"),
|
|
||||||
i18next.t("splashMessages:moreAddictiveThanIntended"),
|
|
||||||
i18next.t("splashMessages:mostlyConsistentSeeds"),
|
|
||||||
i18next.t("splashMessages:achievementPointsDontDoAnything"),
|
|
||||||
i18next.t("splashMessages:youDoNotStartAtLevel"),
|
|
||||||
i18next.t("splashMessages:dontTalkAboutTheManaphyEggIncident"),
|
|
||||||
i18next.t("splashMessages:alsoTryPokengine"),
|
|
||||||
i18next.t("splashMessages:alsoTryEmeraldRogue"),
|
|
||||||
i18next.t("splashMessages:alsoTryRadicalRed"),
|
|
||||||
i18next.t("splashMessages:eeveeExpo"),
|
|
||||||
i18next.t("splashMessages:ynoproject"),
|
|
||||||
i18next.t("splashMessages:breedersInSpace"),
|
|
||||||
);
|
|
||||||
|
|
||||||
return splashMessages;
|
if (now >= startDate && now <= endDate) {
|
||||||
|
console.log(`Adding ${messages.length} ${name} splash messages (weight: x${SEASONAL_WEIGHT_MULTIPLIER})`);
|
||||||
|
messages.forEach((message) => {
|
||||||
|
const weightedMessage = Array(SEASONAL_WEIGHT_MULTIPLIER).fill(message);
|
||||||
|
splashMessages.push(...weightedMessage);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return splashMessages.map((message) => `splashMessages:${message}`);
|
||||||
}
|
}
|
||||||
|
@ -1105,8 +1105,16 @@ function getGymLeaderPartyTemplate(scene: BattleScene) {
|
|||||||
return getWavePartyTemplate(scene, trainerPartyTemplates.GYM_LEADER_1, trainerPartyTemplates.GYM_LEADER_2, trainerPartyTemplates.GYM_LEADER_3, trainerPartyTemplates.GYM_LEADER_4, trainerPartyTemplates.GYM_LEADER_5);
|
return getWavePartyTemplate(scene, trainerPartyTemplates.GYM_LEADER_1, trainerPartyTemplates.GYM_LEADER_2, trainerPartyTemplates.GYM_LEADER_3, trainerPartyTemplates.GYM_LEADER_4, trainerPartyTemplates.GYM_LEADER_5);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandomPartyMemberFunc(speciesPool: Species[], trainerSlot: TrainerSlot = TrainerSlot.TRAINER, ignoreEvolution: boolean = false, postProcess?: (enemyPokemon: EnemyPokemon) => void): PartyMemberFunc {
|
/**
|
||||||
return (scene: BattleScene, level: integer, strength: PartyMemberStrength) => {
|
* Randomly selects one of the `Species` from `speciesPool`, determines its evolution, level, and strength.
|
||||||
|
* Then adds Pokemon to scene.
|
||||||
|
* @param speciesPool
|
||||||
|
* @param trainerSlot
|
||||||
|
* @param ignoreEvolution
|
||||||
|
* @param postProcess
|
||||||
|
*/
|
||||||
|
export function getRandomPartyMemberFunc(speciesPool: Species[], trainerSlot: TrainerSlot = TrainerSlot.TRAINER, ignoreEvolution: boolean = false, postProcess?: (enemyPokemon: EnemyPokemon) => void) {
|
||||||
|
return (scene: BattleScene, level: number, strength: PartyMemberStrength) => {
|
||||||
let species = Utils.randSeedItem(speciesPool);
|
let species = Utils.randSeedItem(speciesPool);
|
||||||
if (!ignoreEvolution) {
|
if (!ignoreEvolution) {
|
||||||
species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength, scene.currentBattle.waveIndex);
|
species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength, scene.currentBattle.waveIndex);
|
||||||
@ -2302,6 +2310,8 @@ export const trainerConfigs: TrainerConfigs = {
|
|||||||
.setMoneyMultiplier(2)
|
.setMoneyMultiplier(2)
|
||||||
.setPartyTemplates(new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, PartyMemberStrength.STRONG))),
|
.setPartyTemplates(new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, PartyMemberStrength.STRONG))),
|
||||||
[TrainerType.BUG_TYPE_SUPERFAN]: new TrainerConfig(++t).setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.ACE_TRAINER)
|
[TrainerType.BUG_TYPE_SUPERFAN]: new TrainerConfig(++t).setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.ACE_TRAINER)
|
||||||
.setPartyTemplates(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE))
|
.setPartyTemplates(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE)),
|
||||||
|
[TrainerType.EXPERT_POKEMON_BREEDER]: new TrainerConfig(++t).setMoneyMultiplier(3).setEncounterBgm(TrainerType.ACE_TRAINER)
|
||||||
|
.setPartyTemplates(new TrainerPartyTemplate(3, PartyMemberStrength.STRONG))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,5 +28,6 @@ export enum MysteryEncounterType {
|
|||||||
BUG_TYPE_SUPERFAN,
|
BUG_TYPE_SUPERFAN,
|
||||||
FUN_AND_GAMES,
|
FUN_AND_GAMES,
|
||||||
UNCOMMON_BREED,
|
UNCOMMON_BREED,
|
||||||
GLOBAL_TRADE_SYSTEM
|
GLOBAL_TRADE_SYSTEM,
|
||||||
|
THE_EXPERT_POKEMON_BREEDER
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,7 @@ export enum TrainerType {
|
|||||||
VICKY,
|
VICKY,
|
||||||
VITO,
|
VITO,
|
||||||
BUG_TYPE_SUPERFAN,
|
BUG_TYPE_SUPERFAN,
|
||||||
|
EXPERT_POKEMON_BREEDER,
|
||||||
|
|
||||||
BROCK = 200,
|
BROCK = 200,
|
||||||
MISTY,
|
MISTY,
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
export enum VariantTier {
|
|
||||||
COMMON,
|
|
||||||
RARE,
|
|
||||||
EPIC
|
|
||||||
}
|
|
@ -1,19 +1,19 @@
|
|||||||
import BattleScene from "../battle-scene";
|
import BattleScene from "../battle-scene";
|
||||||
import { BiomePoolTier, PokemonPools, BiomeTierTrainerPools, biomePokemonPools, biomeTrainerPools } from "../data/biomes";
|
import { biomePokemonPools, BiomePoolTier, BiomeTierTrainerPools, biomeTrainerPools, PokemonPools } from "../data/biomes";
|
||||||
import { Constructor } from "#app/utils";
|
import { Constructor } from "#app/utils";
|
||||||
import * as Utils from "../utils";
|
import * as Utils from "../utils";
|
||||||
import PokemonSpecies, { getPokemonSpecies } from "../data/pokemon-species";
|
import PokemonSpecies, { getPokemonSpecies } from "../data/pokemon-species";
|
||||||
import { Weather, WeatherType, getTerrainClearMessage, getTerrainStartMessage, getWeatherClearMessage, getWeatherStartMessage } from "../data/weather";
|
import { getTerrainClearMessage, getTerrainStartMessage, getWeatherClearMessage, getWeatherStartMessage, Weather, WeatherType } from "../data/weather";
|
||||||
import { CommonAnim } from "../data/battle-anims";
|
import { CommonAnim } from "../data/battle-anims";
|
||||||
import { Type } from "../data/type";
|
import { Type } from "../data/type";
|
||||||
import Move from "../data/move";
|
import Move from "../data/move";
|
||||||
import { ArenaTag, ArenaTagSide, ArenaTrapTag, getArenaTag } from "../data/arena-tag";
|
import { ArenaTag, ArenaTagSide, ArenaTrapTag, getArenaTag } from "../data/arena-tag";
|
||||||
import { BattlerIndex } from "../battle";
|
import { BattlerIndex } from "../battle";
|
||||||
import { Terrain, TerrainType } from "../data/terrain";
|
import { Terrain, TerrainType } from "../data/terrain";
|
||||||
import { PostTerrainChangeAbAttr, PostWeatherChangeAbAttr, applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs } from "../data/ability";
|
import { applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs, PostTerrainChangeAbAttr, PostWeatherChangeAbAttr } from "../data/ability";
|
||||||
import Pokemon from "./pokemon";
|
import Pokemon from "./pokemon";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
import { WeatherChangedEvent, TerrainChangedEvent, TagAddedEvent, TagRemovedEvent } from "../events/arena";
|
import { TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "../events/arena";
|
||||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||||
import { Biome } from "#enums/biome";
|
import { Biome } from "#enums/biome";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
@ -746,7 +746,7 @@ export class Arena {
|
|||||||
case Biome.TOWN:
|
case Biome.TOWN:
|
||||||
return 7.288;
|
return 7.288;
|
||||||
case Biome.PLAINS:
|
case Biome.PLAINS:
|
||||||
return 7.693;
|
return 17.485;
|
||||||
case Biome.GRASS:
|
case Biome.GRASS:
|
||||||
return 1.995;
|
return 1.995;
|
||||||
case Biome.TALL_GRASS:
|
case Biome.TALL_GRASS:
|
||||||
@ -762,7 +762,7 @@ export class Arena {
|
|||||||
case Biome.BEACH:
|
case Biome.BEACH:
|
||||||
return 3.462;
|
return 3.462;
|
||||||
case Biome.LAKE:
|
case Biome.LAKE:
|
||||||
return 5.350;
|
return 7.215;
|
||||||
case Biome.SEABED:
|
case Biome.SEABED:
|
||||||
return 2.600;
|
return 2.600;
|
||||||
case Biome.MOUNTAIN:
|
case Biome.MOUNTAIN:
|
||||||
@ -774,13 +774,13 @@ export class Arena {
|
|||||||
case Biome.DESERT:
|
case Biome.DESERT:
|
||||||
return 1.143;
|
return 1.143;
|
||||||
case Biome.ICE_CAVE:
|
case Biome.ICE_CAVE:
|
||||||
return 15.010;
|
return 0.000;
|
||||||
case Biome.MEADOW:
|
case Biome.MEADOW:
|
||||||
return 3.891;
|
return 3.891;
|
||||||
case Biome.POWER_PLANT:
|
case Biome.POWER_PLANT:
|
||||||
return 2.810;
|
return 9.447;
|
||||||
case Biome.VOLCANO:
|
case Biome.VOLCANO:
|
||||||
return 5.116;
|
return 17.637;
|
||||||
case Biome.GRAVEYARD:
|
case Biome.GRAVEYARD:
|
||||||
return 3.232;
|
return 3.232;
|
||||||
case Biome.DOJO:
|
case Biome.DOJO:
|
||||||
@ -788,7 +788,7 @@ export class Arena {
|
|||||||
case Biome.FACTORY:
|
case Biome.FACTORY:
|
||||||
return 4.985;
|
return 4.985;
|
||||||
case Biome.RUINS:
|
case Biome.RUINS:
|
||||||
return 2.270;
|
return 0.000;
|
||||||
case Biome.WASTELAND:
|
case Biome.WASTELAND:
|
||||||
return 6.336;
|
return 6.336;
|
||||||
case Biome.ABYSS:
|
case Biome.ABYSS:
|
||||||
|
@ -95,10 +95,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
public metLevel: integer;
|
public metLevel: integer;
|
||||||
public metBiome: Biome | -1;
|
public metBiome: Biome | -1;
|
||||||
public metSpecies: Species;
|
public metSpecies: Species;
|
||||||
|
public metWave: number;
|
||||||
public luck: integer;
|
public luck: integer;
|
||||||
public pauseEvolutions: boolean;
|
public pauseEvolutions: boolean;
|
||||||
public pokerus: boolean;
|
public pokerus: boolean;
|
||||||
public wildFlee: boolean;
|
public switchOutStatus: boolean;
|
||||||
public evoCounter: integer;
|
public evoCounter: integer;
|
||||||
|
|
||||||
public fusionSpecies: PokemonSpecies | null;
|
public fusionSpecies: PokemonSpecies | null;
|
||||||
@ -144,7 +145,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
this.species = species;
|
this.species = species;
|
||||||
this.pokeball = dataSource?.pokeball || PokeballType.POKEBALL;
|
this.pokeball = dataSource?.pokeball || PokeballType.POKEBALL;
|
||||||
this.level = level;
|
this.level = level;
|
||||||
this.wildFlee = false;
|
this.switchOutStatus = false;
|
||||||
|
|
||||||
// Determine the ability index
|
// Determine the ability index
|
||||||
if (abilityIndex !== undefined) {
|
if (abilityIndex !== undefined) {
|
||||||
@ -194,6 +195,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
this.luck = dataSource.luck;
|
this.luck = dataSource.luck;
|
||||||
this.metBiome = dataSource.metBiome;
|
this.metBiome = dataSource.metBiome;
|
||||||
this.metSpecies = dataSource.metSpecies ?? (this.metBiome !== -1 ? this.species.speciesId : this.species.getRootSpeciesId(true));
|
this.metSpecies = dataSource.metSpecies ?? (this.metBiome !== -1 ? this.species.speciesId : this.species.getRootSpeciesId(true));
|
||||||
|
this.metWave = dataSource.metWave ?? (this.metBiome === -1 ? -1 : 0);
|
||||||
this.pauseEvolutions = dataSource.pauseEvolutions;
|
this.pauseEvolutions = dataSource.pauseEvolutions;
|
||||||
this.pokerus = !!dataSource.pokerus;
|
this.pokerus = !!dataSource.pokerus;
|
||||||
this.evoCounter = dataSource.evoCounter ?? 0;
|
this.evoCounter = dataSource.evoCounter ?? 0;
|
||||||
@ -240,6 +242,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
this.metLevel = level;
|
this.metLevel = level;
|
||||||
this.metBiome = scene.currentBattle ? scene.arena.biomeType : -1;
|
this.metBiome = scene.currentBattle ? scene.arena.biomeType : -1;
|
||||||
this.metSpecies = species.speciesId;
|
this.metSpecies = species.speciesId;
|
||||||
|
this.metWave = scene.currentBattle ? scene.currentBattle.waveIndex : -1;
|
||||||
this.pokerus = false;
|
this.pokerus = false;
|
||||||
|
|
||||||
if (level > 1) {
|
if (level > 1) {
|
||||||
@ -340,7 +343,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
isAllowed(): boolean {
|
isAllowed(): boolean {
|
||||||
const challengeAllowed = new Utils.BooleanHolder(true);
|
const challengeAllowed = new Utils.BooleanHolder(true);
|
||||||
applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, this, challengeAllowed);
|
applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, this, challengeAllowed);
|
||||||
return !this.wildFlee && challengeAllowed.value;
|
return !this.isFainted() && challengeAllowed.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
isActive(onField?: boolean): boolean {
|
isActive(onField?: boolean): boolean {
|
||||||
@ -1270,13 +1273,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* @param attrType {@linkcode AbAttr} The ability attribute to check for.
|
* @param attrType {@linkcode AbAttr} The ability attribute to check for.
|
||||||
* @param canApply {@linkcode Boolean} If false, it doesn't check whether the ability is currently active
|
* @param canApply {@linkcode Boolean} If false, it doesn't check whether the ability is currently active
|
||||||
* @param ignoreOverride {@linkcode Boolean} If true, it ignores ability changing effects
|
* @param ignoreOverride {@linkcode Boolean} If true, it ignores ability changing effects
|
||||||
* @returns {AbAttr[]} A list of all the ability attributes on this ability.
|
* @returns A list of all the ability attributes on this ability.
|
||||||
*/
|
*/
|
||||||
getAbilityAttrs(attrType: { new(...args: any[]): AbAttr }, canApply: boolean = true, ignoreOverride?: boolean): AbAttr[] {
|
getAbilityAttrs<T extends AbAttr = AbAttr>(attrType: { new(...args: any[]): T }, canApply: boolean = true, ignoreOverride?: boolean): T[] {
|
||||||
const abilityAttrs: AbAttr[] = [];
|
const abilityAttrs: T[] = [];
|
||||||
|
|
||||||
if (!canApply || this.canApplyAbility()) {
|
if (!canApply || this.canApplyAbility()) {
|
||||||
abilityAttrs.push(...this.getAbility(ignoreOverride).getAttrs(attrType));
|
abilityAttrs.push(...this.getAbility(ignoreOverride).getAttrs<T>(attrType));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!canApply || this.canApplyAbility(true)) {
|
if (!canApply || this.canApplyAbility(true)) {
|
||||||
@ -2149,11 +2152,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets if the pokemon has fled (implies it's a wild pokemon)
|
* sets if the pokemon is switching out (if it's a enemy wild implies it's going to flee)
|
||||||
* @param status - boolean
|
* @param status - boolean
|
||||||
*/
|
*/
|
||||||
setWildFlee(status: boolean): void {
|
setSwitchOutStatus(status: boolean): void {
|
||||||
this.wildFlee = status;
|
this.switchOutStatus = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateInfo(instant?: boolean): Promise<void> {
|
updateInfo(instant?: boolean): Promise<void> {
|
||||||
@ -2319,11 +2322,61 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
return accuracyMultiplier.value / evasionMultiplier.value;
|
return accuracyMultiplier.value / evasionMultiplier.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the base damage of the given move against this Pokemon when attacked by the given source.
|
||||||
|
* Used during damage calculation and for Shell Side Arm's forecasting effect.
|
||||||
|
* @param source the attacking {@linkcode Pokemon}.
|
||||||
|
* @param move the {@linkcode Move} used in the attack.
|
||||||
|
* @param moveCategory the move's {@linkcode MoveCategory} after variable-category effects are applied.
|
||||||
|
* @param ignoreAbility if `true`, ignores this Pokemon's defensive ability effects (defaults to `false`).
|
||||||
|
* @param ignoreSourceAbility if `true`, ignore's the attacking Pokemon's ability effects (defaults to `false`).
|
||||||
|
* @param isCritical if `true`, calculates effective stats as if the hit were critical (defaults to `false`).
|
||||||
|
* @param simulated if `true`, suppresses changes to game state during calculation (defaults to `true`).
|
||||||
|
* @returns The move's base damage against this Pokemon when used by the source Pokemon.
|
||||||
|
*/
|
||||||
|
getBaseDamage(source: Pokemon, move: Move, moveCategory: MoveCategory, ignoreAbility: boolean = false, ignoreSourceAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true): number {
|
||||||
|
const isPhysical = moveCategory === MoveCategory.PHYSICAL;
|
||||||
|
|
||||||
|
/** A base damage multiplier based on the source's level */
|
||||||
|
const levelMultiplier = (2 * source.level / 5 + 2);
|
||||||
|
|
||||||
|
/** The power of the move after power boosts from abilities, etc. have applied */
|
||||||
|
const power = move.calculateBattlePower(source, this, simulated);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attacker's offensive stat for the given move's category.
|
||||||
|
* Critical hits cause negative stat stages to be ignored.
|
||||||
|
*/
|
||||||
|
const sourceAtk = new Utils.NumberHolder(source.getEffectiveStat(isPhysical ? Stat.ATK : Stat.SPATK, this, undefined, ignoreSourceAbility, ignoreAbility, isCritical, simulated));
|
||||||
|
applyMoveAttrs(VariableAtkAttr, source, this, move, sourceAtk);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Pokemon's defensive stat for the given move's category.
|
||||||
|
* Critical hits cause positive stat stages to be ignored.
|
||||||
|
*/
|
||||||
|
const targetDef = new Utils.NumberHolder(this.getEffectiveStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, ignoreAbility, ignoreSourceAbility, isCritical, simulated));
|
||||||
|
applyMoveAttrs(VariableDefAttr, source, this, move, targetDef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attack's base damage, as determined by the source's level, move power
|
||||||
|
* and Attack stat as well as this Pokemon's Defense stat
|
||||||
|
*/
|
||||||
|
const baseDamage = ((levelMultiplier * power * sourceAtk.value / targetDef.value) / 50) + 2;
|
||||||
|
|
||||||
|
/** Debug message for non-simulated calls (i.e. when damage is actually dealt) */
|
||||||
|
if (!simulated) {
|
||||||
|
console.log("base damage", baseDamage, move.name, power, sourceAtk.value, targetDef.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseDamage;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the damage of an attack made by another Pokemon against this Pokemon
|
* Calculates the damage of an attack made by another Pokemon against this Pokemon
|
||||||
* @param source {@linkcode Pokemon} the attacking Pokemon
|
* @param source {@linkcode Pokemon} the attacking Pokemon
|
||||||
* @param move {@linkcode Pokemon} the move used in the attack
|
* @param move {@linkcode Pokemon} the move used in the attack
|
||||||
* @param ignoreAbility If `true`, ignores this Pokemon's defensive ability effects
|
* @param ignoreAbility If `true`, ignores this Pokemon's defensive ability effects
|
||||||
|
* @param ignoreSourceAbility If `true`, ignores the attacking Pokemon's ability effects
|
||||||
* @param isCritical If `true`, calculates damage for a critical hit.
|
* @param isCritical If `true`, calculates damage for a critical hit.
|
||||||
* @param simulated If `true`, suppresses changes to game state during the calculation.
|
* @param simulated If `true`, suppresses changes to game state during the calculation.
|
||||||
* @returns a {@linkcode DamageCalculationResult} object with three fields:
|
* @returns a {@linkcode DamageCalculationResult} object with three fields:
|
||||||
@ -2392,35 +2445,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----- BEGIN BASE DAMAGE MULTIPLIERS -----
|
|
||||||
|
|
||||||
/** A base damage multiplier based on the source's level */
|
|
||||||
const levelMultiplier = (2 * source.level / 5 + 2);
|
|
||||||
|
|
||||||
/** The power of the move after power boosts from abilities, etc. have applied */
|
|
||||||
const power = move.calculateBattlePower(source, this, simulated);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The attacker's offensive stat for the given move's category.
|
|
||||||
* Critical hits ignore negative stat stages.
|
|
||||||
*/
|
|
||||||
const sourceAtk = new Utils.NumberHolder(source.getEffectiveStat(isPhysical ? Stat.ATK : Stat.SPATK, this, undefined, ignoreSourceAbility, ignoreAbility, isCritical, simulated));
|
|
||||||
applyMoveAttrs(VariableAtkAttr, source, this, move, sourceAtk);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This Pokemon's defensive stat for the given move's category.
|
|
||||||
* Critical hits ignore positive stat stages.
|
|
||||||
*/
|
|
||||||
const targetDef = new Utils.NumberHolder(this.getEffectiveStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, ignoreAbility, ignoreSourceAbility, isCritical, simulated));
|
|
||||||
applyMoveAttrs(VariableDefAttr, source, this, move, targetDef);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attack's base damage, as determined by the source's level, move power
|
* The attack's base damage, as determined by the source's level, move power
|
||||||
* and Attack stat as well as this Pokemon's Defense stat
|
* and Attack stat as well as this Pokemon's Defense stat
|
||||||
*/
|
*/
|
||||||
const baseDamage = ((levelMultiplier * power * sourceAtk.value / targetDef.value) / 50) + 2;
|
const baseDamage = this.getBaseDamage(source, move, moveCategory, ignoreAbility, ignoreSourceAbility, isCritical, simulated);
|
||||||
|
|
||||||
// ------ END BASE DAMAGE MULTIPLIERS ------
|
|
||||||
|
|
||||||
/** 25% damage debuff on moves hitting more than one non-fainted target (regardless of immunities) */
|
/** 25% damage debuff on moves hitting more than one non-fainted target (regardless of immunities) */
|
||||||
const { targets, multiple } = getMoveTargets(source, move.id);
|
const { targets, multiple } = getMoveTargets(source, move.id);
|
||||||
@ -2546,7 +2575,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
// debug message for when damage is applied (i.e. not simulated)
|
// debug message for when damage is applied (i.e. not simulated)
|
||||||
if (!simulated) {
|
if (!simulated) {
|
||||||
console.log("damage", damage.value, move.name, power, sourceAtk, targetDef);
|
console.log("damage", damage.value, move.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
let hitResult: HitResult;
|
let hitResult: HitResult;
|
||||||
@ -3355,6 +3384,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
this.updateFusionPalette();
|
this.updateFusionPalette();
|
||||||
}
|
}
|
||||||
this.summonData = new PokemonSummonData();
|
this.summonData = new PokemonSummonData();
|
||||||
|
this.setSwitchOutStatus(false);
|
||||||
if (!this.battleData) {
|
if (!this.battleData) {
|
||||||
this.resetBattleData();
|
this.resetBattleData();
|
||||||
}
|
}
|
||||||
@ -3760,6 +3790,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
this.hideInfo();
|
this.hideInfo();
|
||||||
}
|
}
|
||||||
this.scene.field.remove(this);
|
this.scene.field.remove(this);
|
||||||
|
this.setSwitchOutStatus(true);
|
||||||
this.scene.triggerPokemonFormChange(this, SpeciesFormChangeActiveTrigger, true);
|
this.scene.triggerPokemonFormChange(this, SpeciesFormChangeActiveTrigger, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3783,6 +3814,25 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
const rootForm = getPokemonSpecies(this.species.getRootSpeciesId());
|
const rootForm = getPokemonSpecies(this.species.getRootSpeciesId());
|
||||||
return rootForm.getAbility(abilityIndex) === rootForm.getAbility(currentAbilityIndex);
|
return rootForm.getAbility(abilityIndex) === rootForm.getAbility(currentAbilityIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to check if the player already owns the starter data of the Pokemon's
|
||||||
|
* current ability
|
||||||
|
* @param ownedAbilityAttrs the owned abilityAttr of this Pokemon's root form
|
||||||
|
* @returns true if the player already has it, false otherwise
|
||||||
|
*/
|
||||||
|
checkIfPlayerHasAbilityOfStarter(ownedAbilityAttrs: number): boolean {
|
||||||
|
if ((ownedAbilityAttrs & 1) > 0 && this.hasSameAbilityInRootForm(0)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((ownedAbilityAttrs & 2) > 0 && this.hasSameAbilityInRootForm(1)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((ownedAbilityAttrs & 4) > 0 && this.hasSameAbilityInRootForm(2)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default interface Pokemon {
|
export default interface Pokemon {
|
||||||
@ -4081,6 +4131,7 @@ export class PlayerPokemon extends Pokemon {
|
|||||||
newPokemon.metLevel = this.metLevel;
|
newPokemon.metLevel = this.metLevel;
|
||||||
newPokemon.metBiome = this.metBiome;
|
newPokemon.metBiome = this.metBiome;
|
||||||
newPokemon.metSpecies = this.metSpecies;
|
newPokemon.metSpecies = this.metSpecies;
|
||||||
|
newPokemon.metWave = this.metWave;
|
||||||
newPokemon.fusionSpecies = this.fusionSpecies;
|
newPokemon.fusionSpecies = this.fusionSpecies;
|
||||||
newPokemon.fusionFormIndex = this.fusionFormIndex;
|
newPokemon.fusionFormIndex = this.fusionFormIndex;
|
||||||
newPokemon.fusionAbilityIndex = this.fusionAbilityIndex;
|
newPokemon.fusionAbilityIndex = this.fusionAbilityIndex;
|
||||||
@ -4088,6 +4139,7 @@ export class PlayerPokemon extends Pokemon {
|
|||||||
newPokemon.fusionVariant = this.fusionVariant;
|
newPokemon.fusionVariant = this.fusionVariant;
|
||||||
newPokemon.fusionGender = this.fusionGender;
|
newPokemon.fusionGender = this.fusionGender;
|
||||||
newPokemon.fusionLuck = this.fusionLuck;
|
newPokemon.fusionLuck = this.fusionLuck;
|
||||||
|
newPokemon.usedTMs = this.usedTMs;
|
||||||
|
|
||||||
this.scene.getParty().push(newPokemon);
|
this.scene.getParty().push(newPokemon);
|
||||||
newPokemon.evolve((!isFusion ? newEvolution : new FusionSpeciesFormEvolution(this.id, newEvolution)), evoSpecies);
|
newPokemon.evolve((!isFusion ? newEvolution : new FusionSpeciesFormEvolution(this.id, newEvolution)), evoSpecies);
|
||||||
@ -4779,6 +4831,7 @@ export class EnemyPokemon extends Pokemon {
|
|||||||
this.pokeball = pokeballType;
|
this.pokeball = pokeballType;
|
||||||
this.metLevel = this.level;
|
this.metLevel = this.level;
|
||||||
this.metBiome = this.scene.arena.biomeType;
|
this.metBiome = this.scene.arena.biomeType;
|
||||||
|
this.metWave = this.scene.currentBattle.waveIndex;
|
||||||
this.metSpecies = this.species.speciesId;
|
this.metSpecies = this.species.speciesId;
|
||||||
const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this);
|
const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this);
|
||||||
|
|
||||||
|
@ -268,7 +268,6 @@ export class GameMode implements GameModeConfig {
|
|||||||
isFixedBattle(waveIndex: integer): boolean {
|
isFixedBattle(waveIndex: integer): boolean {
|
||||||
const dummyConfig = new FixedBattleConfig();
|
const dummyConfig = new FixedBattleConfig();
|
||||||
return this.battleConfig.hasOwnProperty(waveIndex) || applyChallenges(this, ChallengeType.FIXED_BATTLES, waveIndex, dummyConfig);
|
return this.battleConfig.hasOwnProperty(waveIndex) || applyChallenges(this, ChallengeType.FIXED_BATTLES, waveIndex, dummyConfig);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -241,12 +241,15 @@ export class LoadingScene extends SceneBase {
|
|||||||
const lang = i18next.resolvedLanguage;
|
const lang = i18next.resolvedLanguage;
|
||||||
if (lang !== "en") {
|
if (lang !== "en") {
|
||||||
if (Utils.verifyLang(lang)) {
|
if (Utils.verifyLang(lang)) {
|
||||||
|
this.loadAtlas(`statuses_${lang}`, "");
|
||||||
this.loadAtlas(`types_${lang}`, "");
|
this.loadAtlas(`types_${lang}`, "");
|
||||||
} else {
|
} else {
|
||||||
// Fallback to English
|
// Fallback to English
|
||||||
|
this.loadAtlas("statuses", "");
|
||||||
this.loadAtlas("types", "");
|
this.loadAtlas("types", "");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
this.loadAtlas("statuses", "");
|
||||||
this.loadAtlas("types", "");
|
this.loadAtlas("types", "");
|
||||||
}
|
}
|
||||||
const availableLangs = ["en", "de", "it", "fr", "ja", "ko", "es", "pt-BR", "zh-CN"];
|
const availableLangs = ["en", "de", "it", "fr", "ja", "ko", "es", "pt-BR", "zh-CN"];
|
||||||
|