Merge branch 'beta' into refactor/api-requests
|
@ -1,5 +1,5 @@
|
||||||
import tseslint from '@typescript-eslint/eslint-plugin';
|
import tseslint from '@typescript-eslint/eslint-plugin';
|
||||||
import stylisticTs from '@stylistic/eslint-plugin-ts'
|
import stylisticTs from '@stylistic/eslint-plugin-ts';
|
||||||
import parser from '@typescript-eslint/parser';
|
import parser from '@typescript-eslint/parser';
|
||||||
import importX from 'eslint-plugin-import-x';
|
import importX from 'eslint-plugin-import-x';
|
||||||
|
|
||||||
|
@ -16,15 +16,15 @@ export default [
|
||||||
'@typescript-eslint': tseslint
|
'@typescript-eslint': tseslint
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
"eqeqeq": ["error", "always"], // Enforces the use of === and !== instead of == and !=
|
"eqeqeq": ["error", "always"], // Enforces the use of `===` and `!==` instead of `==` and `!=`
|
||||||
"indent": ["error", 2], // Enforces a 2-space indentation
|
"indent": ["error", 2, { "SwitchCase": 1 }], // Enforces a 2-space indentation, enforces indentation of `case ...:` statements
|
||||||
"quotes": ["error", "double"], // Enforces the use of double quotes for strings
|
"quotes": ["error", "double"], // Enforces the use of double quotes for strings
|
||||||
"no-var": "error", // Disallows the use of var, enforcing let or const instead
|
"no-var": "error", // Disallows the use of `var`, enforcing `let` or `const` instead
|
||||||
"prefer-const": "error", // Prefers the use of const for variables that are never reassigned
|
"prefer-const": "error", // Enforces the use of `const` for variables that are never reassigned
|
||||||
"no-undef": "off", // Disables the rule that disallows the use of undeclared variables (TypeScript handles this)
|
"no-undef": "off", // Disables the rule that disallows the use of undeclared variables (TypeScript handles this)
|
||||||
"@typescript-eslint/no-unused-vars": [ "error", {
|
"@typescript-eslint/no-unused-vars": [ "error", {
|
||||||
"args": "none", // Allows unused function parameters. Useful for functions with specific signatures where not all parameters are always used.
|
"args": "none", // Allows unused function parameters. Useful for functions with specific signatures where not all parameters are always used.
|
||||||
"ignoreRestSiblings": true // Allows unused variables that are part of a rest property in object destructuring. Useful for excluding certain properties from an object while using the rest.
|
"ignoreRestSiblings": true // Allows unused variables that are part of a rest property in object destructuring. Useful for excluding certain properties from an object while using the others.
|
||||||
}],
|
}],
|
||||||
"eol-last": ["error", "always"], // Enforces at least one newline at the end of files
|
"eol-last": ["error", "always"], // Enforces at least one newline at the end of files
|
||||||
"@stylistic/ts/semi": ["error", "always"], // Requires semicolons for TypeScript-specific syntax
|
"@stylistic/ts/semi": ["error", "always"], // Requires semicolons for TypeScript-specific syntax
|
||||||
|
@ -32,14 +32,14 @@ export default [
|
||||||
"no-extra-semi": ["error"], // Disallows unnecessary semicolons for TypeScript-specific syntax
|
"no-extra-semi": ["error"], // Disallows unnecessary semicolons for TypeScript-specific syntax
|
||||||
"brace-style": "off", // Note: you must disable the base rule as it can report incorrect errors
|
"brace-style": "off", // Note: you must disable the base rule as it can report incorrect errors
|
||||||
"curly": ["error", "all"], // Enforces the use of curly braces for all control statements
|
"curly": ["error", "all"], // Enforces the use of curly braces for all control statements
|
||||||
"@stylistic/ts/brace-style": ["error", "1tbs"],
|
"@stylistic/ts/brace-style": ["error", "1tbs"], // Enforces the following brace style: https://eslint.style/rules/js/brace-style#_1tbs
|
||||||
"no-trailing-spaces": ["error", { // Disallows trailing whitespace at the end of lines
|
"no-trailing-spaces": ["error", { // Disallows trailing whitespace at the end of lines
|
||||||
"skipBlankLines": false, // Enforces the rule even on blank lines
|
"skipBlankLines": false, // Enforces the rule even on blank lines
|
||||||
"ignoreComments": false // Enforces the rule on lines containing comments
|
"ignoreComments": false // Enforces the rule on lines containing comments
|
||||||
}],
|
}],
|
||||||
"space-before-blocks": ["error", "always"], // Enforces a space before blocks
|
"space-before-blocks": ["error", "always"], // Enforces a space before blocks
|
||||||
"keyword-spacing": ["error", { "before": true, "after": true }], // Enforces spacing before and after keywords
|
"keyword-spacing": ["error", { "before": true, "after": true }], // Enforces spacing before and after keywords
|
||||||
"comma-spacing": ["error", { "before": false, "after": true }], // Enforces spacing after comma
|
"comma-spacing": ["error", { "before": false, "after": true }], // Enforces spacing after commas
|
||||||
"import-x/extensions": ["error", "never", { "json": "always" }], // Enforces no extension for imports unless json
|
"import-x/extensions": ["error", "never", { "json": "always" }], // Enforces no extension for imports unless json
|
||||||
"array-bracket-spacing": ["error", "always", { "objectsInArrays": false, "arraysInArrays": false }], // Enforces consistent spacing inside array brackets
|
"array-bracket-spacing": ["error", "always", { "objectsInArrays": false, "arraysInArrays": false }], // Enforces consistent spacing inside array brackets
|
||||||
"object-curly-spacing": ["error", "always", { "arraysInObjects": false, "objectsInObjects": false }], // Enforces consistent spacing inside braces of object literals, destructuring assignments, and import/export specifiers
|
"object-curly-spacing": ["error", "always", { "arraysInObjects": false, "objectsInObjects": false }], // Enforces consistent spacing inside braces of object literals, destructuring assignments, and import/export specifiers
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "pokemon-rogue-battle",
|
"name": "pokemon-rogue-battle",
|
||||||
"version": "1.0.4",
|
"version": "1.1.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pokemon-rogue-battle",
|
"name": "pokemon-rogue-battle",
|
||||||
"version": "1.0.4",
|
"version": "1.1.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material/material-color-utilities": "^0.2.7",
|
"@material/material-color-utilities": "^0.2.7",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "pokemon-rogue-battle",
|
"name": "pokemon-rogue-battle",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.4",
|
"version": "1.1.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "vite",
|
"start": "vite",
|
||||||
|
|
|
@ -3416,12 +3416,12 @@
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": true,
|
"trimmed": true,
|
||||||
"sourceSize": {
|
"sourceSize": {
|
||||||
"w": 24,
|
"w": 32,
|
||||||
"h": 24
|
"h": 32
|
||||||
},
|
},
|
||||||
"spriteSourceSize": {
|
"spriteSourceSize": {
|
||||||
"x": 1,
|
"x": 5,
|
||||||
"y": 2,
|
"y": 7,
|
||||||
"w": 22,
|
"w": 22,
|
||||||
"h": 19
|
"h": 19
|
||||||
},
|
},
|
||||||
|
@ -8415,6 +8415,6 @@
|
||||||
"meta": {
|
"meta": {
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
"version": "3.0",
|
"version": "3.0",
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:934ea4080bad980d4fea720cc771f133:ed564bc47b79b15a763de57045178e88:110e074689c9edd2c54833ce2e4d9270$"
|
"smartupdate": "$TexturePacker:SmartUpdate:9ef21166268f7487fc9ff8d0f9b996e4:82658ac7bdd4c2b417e1f59168179262:110e074689c9edd2c54833ce2e4d9270$"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 285 B |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 879 B After Width: | Height: | Size: 942 B |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"566678": "0e6296",
|
||||||
|
"e0e4f4": "513981",
|
||||||
|
"625287": "4e4094",
|
||||||
|
"536273": "1f1233",
|
||||||
|
"988b98": "b24c86",
|
||||||
|
"9170b9": "8b69c3",
|
||||||
|
"c4cce1": "3b235c",
|
||||||
|
"e6d3e9": "f1a4c5",
|
||||||
|
"bfacc1": "da75a5",
|
||||||
|
"515f70": "197497",
|
||||||
|
"c5cee3": "63cee1",
|
||||||
|
"8e96aa": "301848",
|
||||||
|
"8b93a6": "3aa8c4",
|
||||||
|
"80737f": "8a2166",
|
||||||
|
"4b454f": "6f1357",
|
||||||
|
"36404c": "0c5474",
|
||||||
|
"b791f2": "c7a1e5"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"566678": "8e480b",
|
||||||
|
"e0e4f4": "176463",
|
||||||
|
"625287": "274159",
|
||||||
|
"536273": "02262c",
|
||||||
|
"988b98": "2a6563",
|
||||||
|
"9170b9": "2f667c",
|
||||||
|
"c4cce1": "0d484a",
|
||||||
|
"e6d3e9": "9cead8",
|
||||||
|
"bfacc1": "5db6a9",
|
||||||
|
"515f70": "a34205",
|
||||||
|
"c5cee3": "f7af58",
|
||||||
|
"8e96aa": "073338",
|
||||||
|
"8b93a6": "d27e26",
|
||||||
|
"80737f": "2b736f",
|
||||||
|
"4b454f": "194f51",
|
||||||
|
"36404c": "842401",
|
||||||
|
"b791f2": "4a9699"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,41 +0,0 @@
|
||||||
{
|
|
||||||
"textures": [
|
|
||||||
{
|
|
||||||
"image": "6706_2.png",
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"size": {
|
|
||||||
"w": 82,
|
|
||||||
"h": 82
|
|
||||||
},
|
|
||||||
"scale": 1,
|
|
||||||
"frames": [
|
|
||||||
{
|
|
||||||
"filename": "0001.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
|
||||||
"version": "3.0",
|
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:02eb46aa66ac70df612e129b7801a85c:a77cca14b23f4f3aece64d1a82449a0f:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 5.0 KiB |
|
@ -1,41 +0,0 @@
|
||||||
{
|
|
||||||
"textures": [
|
|
||||||
{
|
|
||||||
"image": "6706_3.png",
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"size": {
|
|
||||||
"w": 82,
|
|
||||||
"h": 82
|
|
||||||
},
|
|
||||||
"scale": 1,
|
|
||||||
"frames": [
|
|
||||||
{
|
|
||||||
"filename": "0001.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
|
||||||
"version": "3.0",
|
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:02eb46aa66ac70df612e129b7801a85c:a77cca14b23f4f3aece64d1a82449a0f:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 5.1 KiB |
|
@ -3721,8 +3721,8 @@
|
||||||
],
|
],
|
||||||
"6706": [
|
"6706": [
|
||||||
0,
|
0,
|
||||||
2,
|
1,
|
||||||
2
|
1
|
||||||
],
|
],
|
||||||
"6713": [
|
"6713": [
|
||||||
0,
|
0,
|
||||||
|
@ -7754,8 +7754,8 @@
|
||||||
],
|
],
|
||||||
"6706": [
|
"6706": [
|
||||||
0,
|
0,
|
||||||
2,
|
1,
|
||||||
2
|
1
|
||||||
],
|
],
|
||||||
"6713": [
|
"6713": [
|
||||||
0,
|
0,
|
||||||
|
@ -8493,8 +8493,8 @@
|
||||||
],
|
],
|
||||||
"705": [
|
"705": [
|
||||||
0,
|
0,
|
||||||
2,
|
1,
|
||||||
2
|
1
|
||||||
],
|
],
|
||||||
"706": [
|
"706": [
|
||||||
0,
|
0,
|
||||||
|
@ -9568,8 +9568,8 @@
|
||||||
],
|
],
|
||||||
"6706": [
|
"6706": [
|
||||||
0,
|
0,
|
||||||
2,
|
1,
|
||||||
2
|
1
|
||||||
],
|
],
|
||||||
"female": {},
|
"female": {},
|
||||||
"back": {
|
"back": {
|
||||||
|
@ -11095,8 +11095,8 @@
|
||||||
],
|
],
|
||||||
"6706": [
|
"6706": [
|
||||||
0,
|
0,
|
||||||
2,
|
1,
|
||||||
2
|
1
|
||||||
],
|
],
|
||||||
"6713": [
|
"6713": [
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"566678": "197497",
|
||||||
|
"8e96aa": "3b235c",
|
||||||
|
"929aad": "3aa8c4",
|
||||||
|
"625287": "4e4094",
|
||||||
|
"536273": "301848",
|
||||||
|
"988b98": "b24c86",
|
||||||
|
"36404c": "0c5474",
|
||||||
|
"c4cce1": "513981",
|
||||||
|
"e6d3e9": "f1a4c5",
|
||||||
|
"bfacc1": "d074a0",
|
||||||
|
"546475": "0e6296",
|
||||||
|
"c5cee3": "63cee1",
|
||||||
|
"80737f": "8a2166",
|
||||||
|
"4b454f": "6f1357",
|
||||||
|
"9170b9": "8b69c3",
|
||||||
|
"b791f2": "c7a1e5"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"566678": "a34205",
|
||||||
|
"8e96aa": "073338",
|
||||||
|
"929aad": "d27e26",
|
||||||
|
"625287": "0e3f47",
|
||||||
|
"536273": "042329",
|
||||||
|
"988b98": "2b736f",
|
||||||
|
"36404c": "842401",
|
||||||
|
"c4cce1": "0d484a",
|
||||||
|
"e6d3e9": "9cead8",
|
||||||
|
"bfacc1": "5db6a9",
|
||||||
|
"546475": "8e480b",
|
||||||
|
"c5cee3": "f7af58",
|
||||||
|
"80737f": "194f51",
|
||||||
|
"4b454f": "274159",
|
||||||
|
"9170b9": "2f667c",
|
||||||
|
"b791f2": "4a9699"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,41 +0,0 @@
|
||||||
{
|
|
||||||
"textures": [
|
|
||||||
{
|
|
||||||
"image": "6706_2.png",
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"size": {
|
|
||||||
"w": 79,
|
|
||||||
"h": 79
|
|
||||||
},
|
|
||||||
"scale": 1,
|
|
||||||
"frames": [
|
|
||||||
{
|
|
||||||
"filename": "0001.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 79,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 79,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 79,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
|
||||||
"version": "3.0",
|
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:64f7e6dfa489012922487e45ba53d557:4d24652b372939abe499497c4b6647b0:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 4.7 KiB |
|
@ -1,41 +0,0 @@
|
||||||
{
|
|
||||||
"textures": [
|
|
||||||
{
|
|
||||||
"image": "6706_3.png",
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"size": {
|
|
||||||
"w": 79,
|
|
||||||
"h": 79
|
|
||||||
},
|
|
||||||
"scale": 1,
|
|
||||||
"frames": [
|
|
||||||
{
|
|
||||||
"filename": "0001.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 79,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 79,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 79,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
|
||||||
"version": "3.0",
|
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:64f7e6dfa489012922487e45ba53d557:4d24652b372939abe499497c4b6647b0:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 4.7 KiB |
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"566678": "0e6296",
|
||||||
|
"e0e4f4": "513981",
|
||||||
|
"625287": "4e4094",
|
||||||
|
"536273": "1f1233",
|
||||||
|
"988b98": "b24c86",
|
||||||
|
"36404c": "0c5474",
|
||||||
|
"c4cce1": "3b235c",
|
||||||
|
"e6d3e9": "f1a4c5",
|
||||||
|
"bfacc1": "da75a5",
|
||||||
|
"515f70": "197497",
|
||||||
|
"c5cee3": "63cee1",
|
||||||
|
"b791f2": "c7a1e5",
|
||||||
|
"8b93a6": "3aa8c4",
|
||||||
|
"80737f": "8a2166",
|
||||||
|
"4b454f": "6f1357",
|
||||||
|
"9170b9": "8b69c3",
|
||||||
|
"8e96aa": "301848"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"566678": "8e480b",
|
||||||
|
"e0e4f4": "176463",
|
||||||
|
"625287": "274159",
|
||||||
|
"536273": "02262c",
|
||||||
|
"988b98": "2a6563",
|
||||||
|
"36404c": "842401",
|
||||||
|
"c4cce1": "0d484a",
|
||||||
|
"e6d3e9": "9cead8",
|
||||||
|
"bfacc1": "5db6a9",
|
||||||
|
"515f70": "a34205",
|
||||||
|
"c5cee3": "f7af58",
|
||||||
|
"b791f2": "4a9699",
|
||||||
|
"8b93a6": "d27e26",
|
||||||
|
"80737f": "2b736f",
|
||||||
|
"4b454f": "194f51",
|
||||||
|
"9170b9": "2f667c",
|
||||||
|
"8e96aa": "073338"
|
||||||
|
}
|
||||||
|
}
|
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 55 KiB |
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"101010":"101010",
|
||||||
|
"4d454d":"8a2166",
|
||||||
|
"807380":"b93f84",
|
||||||
|
"bfacbf":"e56ca6",
|
||||||
|
"f2daf2":"fbb3d2",
|
||||||
|
"665980":"4e4094",
|
||||||
|
"8f7db3":"8b69c3",
|
||||||
|
"b8a1e5":"c7a1e5",
|
||||||
|
"4d993d":"aa6a00",
|
||||||
|
"66cc52":"ffd047",
|
||||||
|
"4e9c3e":"0c5474",
|
||||||
|
"67cf53":"3aa8c4",
|
||||||
|
"b6f2aa":"63cee1"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"101010":"101010",
|
||||||
|
"4d454d":"194f51",
|
||||||
|
"807380":"2b736f",
|
||||||
|
"bfacbf":"5db6a9",
|
||||||
|
"f2daf2":"9cead8",
|
||||||
|
"665980":"274159",
|
||||||
|
"8f7db3":"2f667c",
|
||||||
|
"b8a1e5":"4a9699",
|
||||||
|
"4d993d":"007d61",
|
||||||
|
"66cc52":"49ffbf",
|
||||||
|
"4e9c3e":"842401",
|
||||||
|
"67cf53":"a34205",
|
||||||
|
"b6f2aa":"d27e26"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,272 +0,0 @@
|
||||||
{
|
|
||||||
"textures": [
|
|
||||||
{
|
|
||||||
"image": "705_2.png",
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"size": {
|
|
||||||
"w": 154,
|
|
||||||
"h": 154
|
|
||||||
},
|
|
||||||
"scale": 1,
|
|
||||||
"frames": [
|
|
||||||
{
|
|
||||||
"filename": "0006.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 46,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 46,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0008.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 46,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 46,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0005.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 46,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0009.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 46,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0007.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 91,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0004.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 0,
|
|
||||||
"w": 42,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 58,
|
|
||||||
"w": 42,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0010.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 0,
|
|
||||||
"w": 42,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 58,
|
|
||||||
"w": 42,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0003.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 41,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 42,
|
|
||||||
"y": 58,
|
|
||||||
"w": 41,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0011.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 41,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 42,
|
|
||||||
"y": 58,
|
|
||||||
"w": 41,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0002.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 36,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 83,
|
|
||||||
"y": 58,
|
|
||||||
"w": 36,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0012.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 36,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 83,
|
|
||||||
"y": 58,
|
|
||||||
"w": 36,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0001.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 35,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 119,
|
|
||||||
"y": 58,
|
|
||||||
"w": 35,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
|
||||||
"version": "3.0",
|
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:4bf155254b23c88780e7eee282256589:82bb727988054c3064e203b6908ff464:6b57e983626c7fc9144ab67f30c66814$"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 4.0 KiB |
|
@ -1,272 +0,0 @@
|
||||||
{
|
|
||||||
"textures": [
|
|
||||||
{
|
|
||||||
"image": "705_3.png",
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"size": {
|
|
||||||
"w": 154,
|
|
||||||
"h": 154
|
|
||||||
},
|
|
||||||
"scale": 1,
|
|
||||||
"frames": [
|
|
||||||
{
|
|
||||||
"filename": "0006.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 46,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 46,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0008.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 46,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 46,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0005.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 46,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0009.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 46,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0007.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 91,
|
|
||||||
"y": 0,
|
|
||||||
"w": 45,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0004.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 0,
|
|
||||||
"w": 42,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 58,
|
|
||||||
"w": 42,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0010.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 0,
|
|
||||||
"w": 42,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 58,
|
|
||||||
"w": 42,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0003.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 41,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 42,
|
|
||||||
"y": 58,
|
|
||||||
"w": 41,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0011.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 41,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 42,
|
|
||||||
"y": 58,
|
|
||||||
"w": 41,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0002.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 36,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 83,
|
|
||||||
"y": 58,
|
|
||||||
"w": 36,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0012.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 36,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 83,
|
|
||||||
"y": 58,
|
|
||||||
"w": 36,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0001.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 49,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 35,
|
|
||||||
"h": 58
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 119,
|
|
||||||
"y": 58,
|
|
||||||
"w": 35,
|
|
||||||
"h": 58
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
|
||||||
"version": "3.0",
|
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:4bf155254b23c88780e7eee282256589:82bb727988054c3064e203b6908ff464:6b57e983626c7fc9144ab67f30c66814$"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 4.0 KiB |
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"566678": "197497",
|
||||||
|
"8e96aa": "3b235c",
|
||||||
|
"929aad": "3aa8c4",
|
||||||
|
"625287": "4e4094",
|
||||||
|
"536273": "301848",
|
||||||
|
"988b98": "b24c86",
|
||||||
|
"36404c": "0c5474",
|
||||||
|
"c4cce1": "513981",
|
||||||
|
"e6d3e9": "f1a4c5",
|
||||||
|
"bfacc1": "d074a0",
|
||||||
|
"546475": "0e6296",
|
||||||
|
"c5cee3": "63cee1",
|
||||||
|
"80737f": "8a2166",
|
||||||
|
"4b454f": "6f1357",
|
||||||
|
"9170b9": "8b69c3",
|
||||||
|
"b791f2": "c7a1e5"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"566678": "a34205",
|
||||||
|
"8e96aa": "073338",
|
||||||
|
"929aad": "d27e26",
|
||||||
|
"625287": "0e3f47",
|
||||||
|
"536273": "042329",
|
||||||
|
"988b98": "2b736f",
|
||||||
|
"36404c": "842401",
|
||||||
|
"c4cce1": "0d484a",
|
||||||
|
"e6d3e9": "9cead8",
|
||||||
|
"bfacc1": "5db6a9",
|
||||||
|
"546475": "8e480b",
|
||||||
|
"c5cee3": "f7af58",
|
||||||
|
"80737f": "194f51",
|
||||||
|
"4b454f": "274159",
|
||||||
|
"9170b9": "2f667c",
|
||||||
|
"b791f2": "4a9699"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,776 +0,0 @@
|
||||||
{
|
|
||||||
"textures": [
|
|
||||||
{
|
|
||||||
"image": "6706_2.png",
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"size": {
|
|
||||||
"w": 358,
|
|
||||||
"h": 358
|
|
||||||
},
|
|
||||||
"scale": 1,
|
|
||||||
"frames": [
|
|
||||||
{
|
|
||||||
"filename": "0001.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 4,
|
|
||||||
"w": 84,
|
|
||||||
"h": 69
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 84,
|
|
||||||
"h": 69
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0002.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 4,
|
|
||||||
"w": 84,
|
|
||||||
"h": 69
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 84,
|
|
||||||
"h": 69
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0005.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 1,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 84,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0006.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 1,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 84,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0034.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 1,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 69,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0003.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 3,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 167,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0004.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 3,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 167,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0035.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 3,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 250,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0036.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 3,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 250,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0007.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 167,
|
|
||||||
"y": 70,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0008.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 167,
|
|
||||||
"y": 70,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0013.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 83,
|
|
||||||
"y": 72,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0014.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 83,
|
|
||||||
"y": 72,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0025.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 141,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0026.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 141,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0027.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 141,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0032.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 249,
|
|
||||||
"y": 70,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0033.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 249,
|
|
||||||
"y": 70,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0011.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 0,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 214,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0012.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 0,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 214,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0017.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 2,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 287,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0018.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 2,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 287,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0028.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 0,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 81,
|
|
||||||
"y": 214,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0029.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 0,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 81,
|
|
||||||
"y": 214,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0021.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 2,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 81,
|
|
||||||
"y": 287,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0022.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 2,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 81,
|
|
||||||
"y": 287,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0015.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 1,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 165,
|
|
||||||
"y": 143,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0016.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 1,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 165,
|
|
||||||
"y": 143,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0023.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 1,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 247,
|
|
||||||
"y": 143,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0024.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 1,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 247,
|
|
||||||
"y": 143,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0009.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 0,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 162,
|
|
||||||
"y": 215,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0010.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 0,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 162,
|
|
||||||
"y": 215,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0019.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 3,
|
|
||||||
"w": 81,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 162,
|
|
||||||
"y": 288,
|
|
||||||
"w": 81,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0020.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 3,
|
|
||||||
"w": 81,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 162,
|
|
||||||
"y": 288,
|
|
||||||
"w": 81,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0030.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 0,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 242,
|
|
||||||
"y": 215,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0031.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 0,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 242,
|
|
||||||
"y": 215,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
|
||||||
"version": "3.0",
|
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:5d65e2c5a6a97b7c7014a175ce3592af:3255e87f637a475d82734fc7d93baf71:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 22 KiB |
|
@ -1,776 +0,0 @@
|
||||||
{
|
|
||||||
"textures": [
|
|
||||||
{
|
|
||||||
"image": "6706_3.png",
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"size": {
|
|
||||||
"w": 358,
|
|
||||||
"h": 358
|
|
||||||
},
|
|
||||||
"scale": 1,
|
|
||||||
"frames": [
|
|
||||||
{
|
|
||||||
"filename": "0001.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 4,
|
|
||||||
"w": 84,
|
|
||||||
"h": 69
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 84,
|
|
||||||
"h": 69
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0002.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 4,
|
|
||||||
"w": 84,
|
|
||||||
"h": 69
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 84,
|
|
||||||
"h": 69
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0005.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 1,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 84,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0006.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 1,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 84,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0034.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 1,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 69,
|
|
||||||
"w": 83,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0003.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 3,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 167,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0004.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 3,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 167,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0035.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 3,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 250,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0036.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 3,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 250,
|
|
||||||
"y": 0,
|
|
||||||
"w": 83,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0007.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 167,
|
|
||||||
"y": 70,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0008.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 167,
|
|
||||||
"y": 70,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0013.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 83,
|
|
||||||
"y": 72,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0014.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 83,
|
|
||||||
"y": 72,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0025.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 141,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0026.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 141,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0027.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 141,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0032.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 249,
|
|
||||||
"y": 70,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0033.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 249,
|
|
||||||
"y": 70,
|
|
||||||
"w": 82,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0011.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 0,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 214,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0012.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 0,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 214,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0017.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 2,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 287,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0018.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 2,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 287,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0028.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 0,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 81,
|
|
||||||
"y": 214,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0029.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 0,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 81,
|
|
||||||
"y": 214,
|
|
||||||
"w": 81,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0021.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 2,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 81,
|
|
||||||
"y": 287,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0022.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 2,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 81,
|
|
||||||
"y": 287,
|
|
||||||
"w": 81,
|
|
||||||
"h": 71
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0015.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 1,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 165,
|
|
||||||
"y": 143,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0016.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 1,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 165,
|
|
||||||
"y": 143,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0023.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 1,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 247,
|
|
||||||
"y": 143,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0024.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 1,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 247,
|
|
||||||
"y": 143,
|
|
||||||
"w": 82,
|
|
||||||
"h": 72
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0009.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 0,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 162,
|
|
||||||
"y": 215,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0010.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 0,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 162,
|
|
||||||
"y": 215,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0019.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 3,
|
|
||||||
"w": 81,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 162,
|
|
||||||
"y": 288,
|
|
||||||
"w": 81,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0020.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 3,
|
|
||||||
"w": 81,
|
|
||||||
"h": 70
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 162,
|
|
||||||
"y": 288,
|
|
||||||
"w": 81,
|
|
||||||
"h": 70
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0030.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 0,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 242,
|
|
||||||
"y": 215,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "0031.png",
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": true,
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 86,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 0,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
},
|
|
||||||
"frame": {
|
|
||||||
"x": 242,
|
|
||||||
"y": 215,
|
|
||||||
"w": 80,
|
|
||||||
"h": 73
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
|
||||||
"version": "3.0",
|
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:5d65e2c5a6a97b7c7014a175ce3592af:3255e87f637a475d82734fc7d93baf71:d60cc2e5ae2bd18de8ee3ab0649593ee$"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 441 B After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 6.2 KiB |
|
@ -4,7 +4,7 @@ import Pokemon, { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
|
||||||
import PokemonSpecies, { allSpecies, getPokemonSpecies, PokemonSpeciesFilter } from "#app/data/pokemon-species";
|
import PokemonSpecies, { allSpecies, getPokemonSpecies, PokemonSpeciesFilter } from "#app/data/pokemon-species";
|
||||||
import { Constructor, isNullOrUndefined, randSeedInt } from "#app/utils";
|
import { Constructor, isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||||
import * as Utils from "#app/utils";
|
import * as Utils from "#app/utils";
|
||||||
import { ConsumableModifier, ConsumablePokemonModifier, DoubleBattleChanceBoosterModifier, ExpBalanceModifier, ExpShareModifier, FusePokemonModifier, HealingBoosterModifier, Modifier, ModifierBar, ModifierPredicate, MultipleParticipantExpBonusModifier, overrideHeldItems, overrideModifiers, PersistentModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, TerastallizeModifier, TurnHeldItemTransferModifier } from "./modifier/modifier";
|
import { ConsumableModifier, ConsumablePokemonModifier, DoubleBattleChanceBoosterModifier, ExpBalanceModifier, ExpShareModifier, FusePokemonModifier, HealingBoosterModifier, Modifier, ModifierBar, ModifierPredicate, MultipleParticipantExpBonusModifier, overrideHeldItems, overrideModifiers, PersistentModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, RememberMoveModifier, TerastallizeModifier, TurnHeldItemTransferModifier } from "./modifier/modifier";
|
||||||
import { PokeballType } from "#app/data/pokeball";
|
import { PokeballType } from "#app/data/pokeball";
|
||||||
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "#app/data/battle-anims";
|
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "#app/data/battle-anims";
|
||||||
import { Phase } from "#app/phase";
|
import { Phase } from "#app/phase";
|
||||||
|
@ -86,7 +86,7 @@ import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-ph
|
||||||
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
||||||
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
||||||
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||||
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome } from "#app/data/mystery-encounters/mystery-encounters";
|
||||||
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
@ -95,6 +95,7 @@ import { ExpPhase } from "#app/phases/exp-phase";
|
||||||
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
|
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
|
||||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||||
import { ExpGainsSpeed } from "#enums/exp-gains-speed";
|
import { ExpGainsSpeed } from "#enums/exp-gains-speed";
|
||||||
|
import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters";
|
||||||
|
|
||||||
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
||||||
|
|
||||||
|
@ -789,7 +790,7 @@ export default class BattleScene extends SceneBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
getEnemyParty(): EnemyPokemon[] {
|
getEnemyParty(): EnemyPokemon[] {
|
||||||
return this.currentBattle?.enemyParty || [];
|
return this.currentBattle?.enemyParty ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
getEnemyPokemon(): EnemyPokemon | undefined {
|
getEnemyPokemon(): EnemyPokemon | undefined {
|
||||||
|
@ -1190,10 +1191,7 @@ export default class BattleScene extends SceneBase {
|
||||||
if (trainerConfigs[trainerType].doubleOnly) {
|
if (trainerConfigs[trainerType].doubleOnly) {
|
||||||
doubleTrainer = true;
|
doubleTrainer = true;
|
||||||
} else if (trainerConfigs[trainerType].hasDouble) {
|
} else if (trainerConfigs[trainerType].hasDouble) {
|
||||||
const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8);
|
doubleTrainer = !Utils.randSeedInt(this.getDoubleBattleChance(newWaveIndex, playerField));
|
||||||
this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance);
|
|
||||||
playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance));
|
|
||||||
doubleTrainer = !Utils.randSeedInt(doubleChance.value);
|
|
||||||
// Add a check that special trainers can't be double except for tate and liza - they should use the normal double chance
|
// Add a check that special trainers can't be double except for tate and liza - they should use the normal double chance
|
||||||
if (trainerConfigs[trainerType].trainerTypeDouble && ![ TrainerType.TATE, TrainerType.LIZA ].includes(trainerType)) {
|
if (trainerConfigs[trainerType].trainerTypeDouble && ![ TrainerType.TATE, TrainerType.LIZA ].includes(trainerType)) {
|
||||||
doubleTrainer = false;
|
doubleTrainer = false;
|
||||||
|
@ -1206,12 +1204,10 @@ export default class BattleScene extends SceneBase {
|
||||||
|
|
||||||
// Check for mystery encounter
|
// Check for mystery encounter
|
||||||
// Can only occur in place of a standard (non-boss) wild battle, waves 10-180
|
// Can only occur in place of a standard (non-boss) wild battle, waves 10-180
|
||||||
if (this.isWaveMysteryEncounter(newBattleType, newWaveIndex, mysteryEncounterType) || newBattleType === BattleType.MYSTERY_ENCOUNTER) {
|
if (this.isWaveMysteryEncounter(newBattleType, newWaveIndex) || newBattleType === BattleType.MYSTERY_ENCOUNTER) {
|
||||||
newBattleType = BattleType.MYSTERY_ENCOUNTER;
|
newBattleType = BattleType.MYSTERY_ENCOUNTER;
|
||||||
// Reset base spawn weight
|
// Reset to base spawn weight
|
||||||
this.mysteryEncounterSaveData.encounterSpawnChance = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT;
|
this.mysteryEncounterSaveData.encounterSpawnChance = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT;
|
||||||
} else if (newBattleType === BattleType.WILD) {
|
|
||||||
this.mysteryEncounterSaveData.encounterSpawnChance += WEIGHT_INCREMENT_ON_SPAWN_MISS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1389,7 +1385,7 @@ export default class BattleScene extends SceneBase {
|
||||||
case Species.GRENINJA:
|
case Species.GRENINJA:
|
||||||
return Utils.randSeedInt(2);
|
return Utils.randSeedInt(2);
|
||||||
case Species.ZYGARDE:
|
case Species.ZYGARDE:
|
||||||
return Utils.randSeedInt(3);
|
return Utils.randSeedInt(4);
|
||||||
case Species.MINIOR:
|
case Species.MINIOR:
|
||||||
return Utils.randSeedInt(6);
|
return Utils.randSeedInt(6);
|
||||||
case Species.ALCREMIE:
|
case Species.ALCREMIE:
|
||||||
|
@ -2316,7 +2312,10 @@ export default class BattleScene extends SceneBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentPhase?.start();
|
if (this.currentPhase) {
|
||||||
|
console.log(`%cStart Phase ${this.currentPhase.constructor.name}`, "color:green;");
|
||||||
|
this.currentPhase.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
overridePhase(phase: Phase): boolean {
|
overridePhase(phase: Phase): boolean {
|
||||||
|
@ -2326,6 +2325,7 @@ export default class BattleScene extends SceneBase {
|
||||||
|
|
||||||
this.standbyPhase = this.currentPhase;
|
this.standbyPhase = this.currentPhase;
|
||||||
this.currentPhase = phase;
|
this.currentPhase = phase;
|
||||||
|
console.log(`%cStart Phase ${phase.constructor.name}`, "color:green;");
|
||||||
phase.start();
|
phase.start();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2359,6 +2359,19 @@ export default class BattleScene extends SceneBase {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will search for a specific phase in {@linkcode phaseQueuePrepend} via filter, and remove the first result if a match is found.
|
||||||
|
* @param phaseFilter filter function
|
||||||
|
*/
|
||||||
|
tryRemoveUnshiftedPhase(phaseFilter: (phase: Phase) => boolean): boolean {
|
||||||
|
const phaseIndex = this.phaseQueuePrepend.findIndex(phaseFilter);
|
||||||
|
if (phaseIndex > -1) {
|
||||||
|
this.phaseQueuePrepend.splice(phaseIndex, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to add the input phase to index before target phase in the phaseQueue, else simply calls unshiftPhase()
|
* Tries to add the input phase to index before target phase in the phaseQueue, else simply calls unshiftPhase()
|
||||||
* @param phase {@linkcode Phase} the phase to be added
|
* @param phase {@linkcode Phase} the phase to be added
|
||||||
|
@ -2421,7 +2434,7 @@ export default class BattleScene extends SceneBase {
|
||||||
return Math.floor(moneyValue / 10) * 10;
|
return Math.floor(moneyValue / 10) * 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
addModifier(modifier: Modifier | null, ignoreUpdate?: boolean, playSound?: boolean, virtual?: boolean, instant?: boolean): Promise<boolean> {
|
addModifier(modifier: Modifier | null, ignoreUpdate?: boolean, playSound?: boolean, virtual?: boolean, instant?: boolean, cost?: number): Promise<boolean> {
|
||||||
if (!modifier) {
|
if (!modifier) {
|
||||||
return Promise.resolve(false);
|
return Promise.resolve(false);
|
||||||
}
|
}
|
||||||
|
@ -2478,6 +2491,8 @@ export default class BattleScene extends SceneBase {
|
||||||
}
|
}
|
||||||
} else if (modifier instanceof FusePokemonModifier) {
|
} else if (modifier instanceof FusePokemonModifier) {
|
||||||
args.push(this.getPokemonById(modifier.fusePokemonId) as PlayerPokemon);
|
args.push(this.getPokemonById(modifier.fusePokemonId) as PlayerPokemon);
|
||||||
|
} else if (modifier instanceof RememberMoveModifier && !Utils.isNullOrUndefined(cost)) {
|
||||||
|
args.push(cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modifier.shouldApply(pokemon, ...args)) {
|
if (modifier.shouldApply(pokemon, ...args)) {
|
||||||
|
@ -2676,7 +2691,7 @@ export default class BattleScene extends SceneBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all modifiers from enemy of PersistentModifier type
|
* Removes all modifiers from enemy pokemon of {@linkcode PersistentModifier} type
|
||||||
*/
|
*/
|
||||||
clearEnemyModifiers(): void {
|
clearEnemyModifiers(): void {
|
||||||
const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PersistentModifier);
|
const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PersistentModifier);
|
||||||
|
@ -2687,10 +2702,11 @@ export default class BattleScene extends SceneBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all modifiers from enemy of PokemonHeldItemModifier type
|
* Removes all modifiers from enemy pokemon of {@linkcode PokemonHeldItemModifier} type
|
||||||
|
* @param pokemon - If specified, only removes held items from that {@linkcode Pokemon}
|
||||||
*/
|
*/
|
||||||
clearEnemyHeldItemModifiers(): void {
|
clearEnemyHeldItemModifiers(pokemon?: Pokemon): void {
|
||||||
const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PokemonHeldItemModifier);
|
const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PokemonHeldItemModifier && (!pokemon || m.getPokemon(this) === pokemon));
|
||||||
for (const m of modifiersToRemove) {
|
for (const m of modifiersToRemove) {
|
||||||
this.enemyModifiers.splice(this.enemyModifiers.indexOf(m), 1);
|
this.enemyModifiers.splice(this.enemyModifiers.indexOf(m), 1);
|
||||||
}
|
}
|
||||||
|
@ -3047,7 +3063,7 @@ export default class BattleScene extends SceneBase {
|
||||||
const pId = partyMember.id;
|
const pId = partyMember.id;
|
||||||
const participated = participantIds.has(pId);
|
const participated = participantIds.has(pId);
|
||||||
if (participated && pokemonDefeated) {
|
if (participated && pokemonDefeated) {
|
||||||
partyMember.addFriendship(2);
|
partyMember.addFriendship(FRIENDSHIP_GAIN_FROM_BATTLE);
|
||||||
const machoBraceModifier = partyMember.getHeldItems().find(m => m instanceof PokemonIncrementingStatModifier);
|
const machoBraceModifier = partyMember.getHeldItems().find(m => m instanceof PokemonIncrementingStatModifier);
|
||||||
if (machoBraceModifier && machoBraceModifier.stackCount < machoBraceModifier.getMaxStackCount(this)) {
|
if (machoBraceModifier && machoBraceModifier.stackCount < machoBraceModifier.getMaxStackCount(this)) {
|
||||||
machoBraceModifier.stackCount++;
|
machoBraceModifier.stackCount++;
|
||||||
|
@ -3117,18 +3133,26 @@ export default class BattleScene extends SceneBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if a wave COULD spawn a {@linkcode MysteryEncounter}.
|
||||||
|
* Even if returns `true`, does not guarantee that a wave will actually be a ME.
|
||||||
|
* That check is made in {@linkcode BattleScene.isWaveMysteryEncounter} instead.
|
||||||
|
*/
|
||||||
|
isMysteryEncounterValidForWave(battleType: BattleType, waveIndex: number): boolean {
|
||||||
|
const [ lowestMysteryEncounterWave, highestMysteryEncounterWave ] = this.gameMode.getMysteryEncounterLegalWaves();
|
||||||
|
return this.gameMode.hasMysteryEncounters && battleType === BattleType.WILD && !this.gameMode.isBoss(waveIndex) && waveIndex < highestMysteryEncounterWave && waveIndex > lowestMysteryEncounterWave;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether a wave should randomly generate a {@linkcode MysteryEncounter}.
|
* Determines whether a wave should randomly generate a {@linkcode MysteryEncounter}.
|
||||||
* Currently, the only modes that MEs are allowed in are Classic and Challenge.
|
* Currently, the only modes that MEs are allowed in are Classic and Challenge.
|
||||||
* Additionally, MEs cannot spawn outside of waves 10-180 in those modes
|
* Additionally, MEs cannot spawn outside of waves 10-180 in those modes
|
||||||
*
|
|
||||||
* @param newBattleType
|
* @param newBattleType
|
||||||
* @param waveIndex
|
* @param waveIndex
|
||||||
* @param sessionDataEncounterType
|
|
||||||
*/
|
*/
|
||||||
private isWaveMysteryEncounter(newBattleType: BattleType, waveIndex: number, sessionDataEncounterType?: MysteryEncounterType): boolean {
|
private isWaveMysteryEncounter(newBattleType: BattleType, waveIndex: number): boolean {
|
||||||
const [ lowestMysteryEncounterWave, highestMysteryEncounterWave ] = this.gameMode.getMysteryEncounterLegalWaves();
|
const [ lowestMysteryEncounterWave, highestMysteryEncounterWave ] = this.gameMode.getMysteryEncounterLegalWaves();
|
||||||
if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(waveIndex) && waveIndex < highestMysteryEncounterWave && waveIndex > lowestMysteryEncounterWave) {
|
if (this.isMysteryEncounterValidForWave(newBattleType, waveIndex)) {
|
||||||
// Base spawn weight is BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT/256, and increases by WEIGHT_INCREMENT_ON_SPAWN_MISS/256 for each missed attempt at spawning an encounter on a valid floor
|
// Base spawn weight is BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT/256, and increases by WEIGHT_INCREMENT_ON_SPAWN_MISS/256 for each missed attempt at spawning an encounter on a valid floor
|
||||||
const sessionEncounterRate = this.mysteryEncounterSaveData.encounterSpawnChance;
|
const sessionEncounterRate = this.mysteryEncounterSaveData.encounterSpawnChance;
|
||||||
const encounteredEvents = this.mysteryEncounterSaveData.encounteredEvents;
|
const encounteredEvents = this.mysteryEncounterSaveData.encounteredEvents;
|
||||||
|
@ -3169,6 +3193,9 @@ export default class BattleScene extends SceneBase {
|
||||||
let encounter: MysteryEncounter | null;
|
let encounter: MysteryEncounter | null;
|
||||||
if (!isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_OVERRIDE) && allMysteryEncounters.hasOwnProperty(Overrides.MYSTERY_ENCOUNTER_OVERRIDE)) {
|
if (!isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_OVERRIDE) && allMysteryEncounters.hasOwnProperty(Overrides.MYSTERY_ENCOUNTER_OVERRIDE)) {
|
||||||
encounter = allMysteryEncounters[Overrides.MYSTERY_ENCOUNTER_OVERRIDE];
|
encounter = allMysteryEncounters[Overrides.MYSTERY_ENCOUNTER_OVERRIDE];
|
||||||
|
if (canBypass) {
|
||||||
|
return encounter;
|
||||||
|
}
|
||||||
} else if (canBypass) {
|
} else if (canBypass) {
|
||||||
encounter = allMysteryEncounters[encounterType ?? -1];
|
encounter = allMysteryEncounters[encounterType ?? -1];
|
||||||
return encounter;
|
return encounter;
|
||||||
|
|
|
@ -118,6 +118,14 @@ export class Ability implements Localizable {
|
||||||
this.nameAppend += " (N)";
|
this.nameAppend += " (N)";
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal flag used for developers to document edge cases. When using this, please be sure to document the edge case.
|
||||||
|
* @returns the ability
|
||||||
|
*/
|
||||||
|
edgeCase(): this {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type AbAttrApplyFunc<TAttr extends AbAttr> = (attr: TAttr, passive: boolean) => boolean | Promise<boolean>;
|
type AbAttrApplyFunc<TAttr extends AbAttr> = (attr: TAttr, passive: boolean) => boolean | Promise<boolean>;
|
||||||
|
@ -4905,8 +4913,7 @@ export function initAbilities() {
|
||||||
.attr(TypeImmunityAddBattlerTagAbAttr, Type.FIRE, BattlerTagType.FIRE_BOOST, 1)
|
.attr(TypeImmunityAddBattlerTagAbAttr, Type.FIRE, BattlerTagType.FIRE_BOOST, 1)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.SHIELD_DUST, 3)
|
new Ability(Abilities.SHIELD_DUST, 3)
|
||||||
.attr(IgnoreMoveEffectsAbAttr)
|
.attr(IgnoreMoveEffectsAbAttr),
|
||||||
.partial(),
|
|
||||||
new Ability(Abilities.OWN_TEMPO, 3)
|
new Ability(Abilities.OWN_TEMPO, 3)
|
||||||
.attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED)
|
.attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED)
|
||||||
.attr(IntimidateImmunityAbAttr)
|
.attr(IntimidateImmunityAbAttr)
|
||||||
|
@ -4950,8 +4957,7 @@ export function initAbilities() {
|
||||||
.attr(TypeImmunityStatStageChangeAbAttr, Type.ELECTRIC, Stat.SPATK, 1)
|
.attr(TypeImmunityStatStageChangeAbAttr, Type.ELECTRIC, Stat.SPATK, 1)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.SERENE_GRACE, 3)
|
new Ability(Abilities.SERENE_GRACE, 3)
|
||||||
.attr(MoveEffectChanceMultiplierAbAttr, 2)
|
.attr(MoveEffectChanceMultiplierAbAttr, 2),
|
||||||
.partial(),
|
|
||||||
new Ability(Abilities.SWIFT_SWIM, 3)
|
new Ability(Abilities.SWIFT_SWIM, 3)
|
||||||
.attr(StatMultiplierAbAttr, Stat.SPD, 2)
|
.attr(StatMultiplierAbAttr, Stat.SPD, 2)
|
||||||
.condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)),
|
.condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)),
|
||||||
|
@ -5235,7 +5241,8 @@ export function initAbilities() {
|
||||||
new Ability(Abilities.SHEER_FORCE, 5)
|
new Ability(Abilities.SHEER_FORCE, 5)
|
||||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 5461 / 4096)
|
.attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 5461 / 4096)
|
||||||
.attr(MoveEffectChanceMultiplierAbAttr, 0)
|
.attr(MoveEffectChanceMultiplierAbAttr, 0)
|
||||||
.partial(),
|
.edgeCase() // Should disable shell bell and Meloetta's relic song transformation
|
||||||
|
.edgeCase(), // Should disable life orb, eject button, red card, kee/maranga berry if they get implemented
|
||||||
new Ability(Abilities.CONTRARY, 5)
|
new Ability(Abilities.CONTRARY, 5)
|
||||||
.attr(StatStageChangeMultiplierAbAttr, -1)
|
.attr(StatStageChangeMultiplierAbAttr, -1)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
|
@ -5278,7 +5285,7 @@ export function initAbilities() {
|
||||||
/** Rate is doubled when under sun {@link https://dex.pokemonshowdown.com/abilities/harvest} */
|
/** Rate is doubled when under sun {@link https://dex.pokemonshowdown.com/abilities/harvest} */
|
||||||
(pokemon) => 0.5 * (getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)(pokemon) ? 2 : 1)
|
(pokemon) => 0.5 * (getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)(pokemon) ? 2 : 1)
|
||||||
)
|
)
|
||||||
.partial(),
|
.edgeCase(), // Cannot recover berries used up by fling or natural gift (unimplemented)
|
||||||
new Ability(Abilities.TELEPATHY, 5)
|
new Ability(Abilities.TELEPATHY, 5)
|
||||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon.getAlly() === attacker && move instanceof AttackMove)
|
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon.getAlly() === attacker && move instanceof AttackMove)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
|
@ -5357,7 +5364,7 @@ export function initAbilities() {
|
||||||
.bypassFaint(),
|
.bypassFaint(),
|
||||||
new Ability(Abilities.VICTORY_STAR, 5)
|
new Ability(Abilities.VICTORY_STAR, 5)
|
||||||
.attr(StatMultiplierAbAttr, Stat.ACC, 1.1)
|
.attr(StatMultiplierAbAttr, Stat.ACC, 1.1)
|
||||||
.partial(),
|
.partial(), // Does not boost ally's accuracy
|
||||||
new Ability(Abilities.TURBOBLAZE, 5)
|
new Ability(Abilities.TURBOBLAZE, 5)
|
||||||
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonTurboblaze", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonTurboblaze", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
||||||
.attr(MoveAbilityBypassAbAttr),
|
.attr(MoveAbilityBypassAbAttr),
|
||||||
|
@ -5468,7 +5475,7 @@ export function initAbilities() {
|
||||||
.attr(UnsuppressableAbilityAbAttr)
|
.attr(UnsuppressableAbilityAbAttr)
|
||||||
.attr(NoFusionAbilityAbAttr)
|
.attr(NoFusionAbilityAbAttr)
|
||||||
.bypassFaint()
|
.bypassFaint()
|
||||||
.partial(),
|
.partial(), // Meteor form should protect against status effects and yawn
|
||||||
new Ability(Abilities.STAKEOUT, 7)
|
new Ability(Abilities.STAKEOUT, 7)
|
||||||
.attr(MovePowerBoostAbAttr, (user, target, move) => user?.scene.currentBattle.turnCommands[target?.getBattlerIndex() ?? BattlerIndex.ATTACKER]?.command === Command.POKEMON, 2),
|
.attr(MovePowerBoostAbAttr, (user, target, move) => user?.scene.currentBattle.turnCommands[target?.getBattlerIndex() ?? BattlerIndex.ATTACKER]?.command === Command.POKEMON, 2),
|
||||||
new Ability(Abilities.WATER_BUBBLE, 7)
|
new Ability(Abilities.WATER_BUBBLE, 7)
|
||||||
|
@ -5526,19 +5533,21 @@ export function initAbilities() {
|
||||||
.attr(UnsuppressableAbilityAbAttr)
|
.attr(UnsuppressableAbilityAbAttr)
|
||||||
.attr(NoFusionAbilityAbAttr)
|
.attr(NoFusionAbilityAbAttr)
|
||||||
.bypassFaint(),
|
.bypassFaint(),
|
||||||
new Ability(Abilities.POWER_CONSTRUCT, 7) // TODO: 10% Power Construct Zygarde isn't accounted for yet. If changed, update Zygarde's getSpeciesFormIndex entry accordingly
|
new Ability(Abilities.POWER_CONSTRUCT, 7)
|
||||||
.attr(PostBattleInitFormChangeAbAttr, () => 2)
|
.conditionalAttr(pokemon => pokemon.formIndex === 2 || pokemon.formIndex === 4, PostBattleInitFormChangeAbAttr, () => 2)
|
||||||
.attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2)
|
.conditionalAttr(pokemon => pokemon.formIndex === 3 || pokemon.formIndex === 5, PostBattleInitFormChangeAbAttr, () => 3)
|
||||||
.attr(PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2)
|
.conditionalAttr(pokemon => pokemon.formIndex === 2 || pokemon.formIndex === 4, PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2)
|
||||||
|
.conditionalAttr(pokemon => pokemon.formIndex === 2 || pokemon.formIndex === 4, PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2)
|
||||||
|
.conditionalAttr(pokemon => pokemon.formIndex === 3 || pokemon.formIndex === 5, PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "10-complete" ? 5 : 3)
|
||||||
|
.conditionalAttr(pokemon => pokemon.formIndex === 3 || pokemon.formIndex === 5, PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "10-complete" ? 5 : 3)
|
||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
.attr(UnsuppressableAbilityAbAttr)
|
.attr(UnsuppressableAbilityAbAttr)
|
||||||
.attr(NoFusionAbilityAbAttr)
|
.attr(NoFusionAbilityAbAttr)
|
||||||
.bypassFaint()
|
.bypassFaint(),
|
||||||
.partial(),
|
new Ability(Abilities.CORROSION, 7)
|
||||||
new Ability(Abilities.CORROSION, 7) // TODO: Test Corrosion against Magic Bounce once it is implemented
|
|
||||||
.attr(IgnoreTypeStatusEffectImmunityAbAttr, [ StatusEffect.POISON, StatusEffect.TOXIC ], [ Type.STEEL, Type.POISON ])
|
.attr(IgnoreTypeStatusEffectImmunityAbAttr, [ StatusEffect.POISON, StatusEffect.TOXIC ], [ Type.STEEL, Type.POISON ])
|
||||||
.partial(),
|
.edgeCase(), // Should interact correctly with magic coat/bounce (not yet implemented), fling with toxic orb (not implemented yet), and synchronize (not fully implemented yet)
|
||||||
new Ability(Abilities.COMATOSE, 7)
|
new Ability(Abilities.COMATOSE, 7)
|
||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
|
@ -5693,7 +5702,7 @@ export function initAbilities() {
|
||||||
new Ability(Abilities.WANDERING_SPIRIT, 8)
|
new Ability(Abilities.WANDERING_SPIRIT, 8)
|
||||||
.attr(PostDefendAbilitySwapAbAttr)
|
.attr(PostDefendAbilitySwapAbAttr)
|
||||||
.bypassFaint()
|
.bypassFaint()
|
||||||
.partial(),
|
.edgeCase(), // interacts incorrectly with rock head. It's meant to switch abilities before recoil would apply so that a pokemon with rock head would lose rock head first and still take the recoil
|
||||||
new Ability(Abilities.GORILLA_TACTICS, 8)
|
new Ability(Abilities.GORILLA_TACTICS, 8)
|
||||||
.attr(GorillaTacticsAbAttr),
|
.attr(GorillaTacticsAbAttr),
|
||||||
new Ability(Abilities.NEUTRALIZING_GAS, 8)
|
new Ability(Abilities.NEUTRALIZING_GAS, 8)
|
||||||
|
@ -5702,7 +5711,7 @@ export function initAbilities() {
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
.attr(NoTransformAbilityAbAttr)
|
.attr(NoTransformAbilityAbAttr)
|
||||||
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonNeutralizingGas", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonNeutralizingGas", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
||||||
.partial(),
|
.partial(), // A bunch of weird interactions with other abilities being suppressed then unsuppressed
|
||||||
new Ability(Abilities.PASTEL_VEIL, 8)
|
new Ability(Abilities.PASTEL_VEIL, 8)
|
||||||
.attr(PostSummonUserFieldRemoveStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
.attr(PostSummonUserFieldRemoveStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
||||||
.attr(UserFieldStatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
.attr(UserFieldStatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
||||||
|
@ -5807,7 +5816,7 @@ export function initAbilities() {
|
||||||
new Ability(Abilities.GOOD_AS_GOLD, 9)
|
new Ability(Abilities.GOOD_AS_GOLD, 9)
|
||||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.category === MoveCategory.STATUS)
|
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.category === MoveCategory.STATUS)
|
||||||
.ignorable()
|
.ignorable()
|
||||||
.partial(),
|
.partial(), // Lots of weird interactions with moves and abilities such as negating status moves that target the field
|
||||||
new Ability(Abilities.VESSEL_OF_RUIN, 9)
|
new Ability(Abilities.VESSEL_OF_RUIN, 9)
|
||||||
.attr(FieldMultiplyStatAbAttr, Stat.SPATK, 0.75)
|
.attr(FieldMultiplyStatAbAttr, Stat.SPATK, 0.75)
|
||||||
.attr(PostSummonMessageAbAttr, (user) => i18next.t("abilityTriggers:postSummonVesselOfRuin", { pokemonNameWithAffix: getPokemonNameWithAffix(user), statName: i18next.t(getStatKey(Stat.SPATK)) }))
|
.attr(PostSummonMessageAbAttr, (user) => i18next.t("abilityTriggers:postSummonVesselOfRuin", { pokemonNameWithAffix: getPokemonNameWithAffix(user), statName: i18next.t(getStatKey(Stat.SPATK)) }))
|
||||||
|
@ -5840,7 +5849,7 @@ export function initAbilities() {
|
||||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.SLICING_MOVE), 1.5),
|
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.SLICING_MOVE), 1.5),
|
||||||
new Ability(Abilities.SUPREME_OVERLORD, 9)
|
new Ability(Abilities.SUPREME_OVERLORD, 9)
|
||||||
.attr(VariableMovePowerBoostAbAttr, (user, target, move) => 1 + 0.1 * Math.min(user.isPlayer() ? user.scene.currentBattle.playerFaints : user.scene.currentBattle.enemyFaints, 5))
|
.attr(VariableMovePowerBoostAbAttr, (user, target, move) => 1 + 0.1 * Math.min(user.isPlayer() ? user.scene.currentBattle.playerFaints : user.scene.currentBattle.enemyFaints, 5))
|
||||||
.partial(),
|
.partial(), // Counter resets every wave
|
||||||
new Ability(Abilities.COSTAR, 9)
|
new Ability(Abilities.COSTAR, 9)
|
||||||
.attr(PostSummonCopyAllyStatsAbAttr),
|
.attr(PostSummonCopyAllyStatsAbAttr),
|
||||||
new Ability(Abilities.TOXIC_DEBRIS, 9)
|
new Ability(Abilities.TOXIC_DEBRIS, 9)
|
||||||
|
@ -5873,25 +5882,25 @@ export function initAbilities() {
|
||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
.attr(NoTransformAbilityAbAttr)
|
.attr(NoTransformAbilityAbAttr)
|
||||||
.partial(),
|
.partial(), // Ogerpon tera interactions
|
||||||
new Ability(Abilities.EMBODY_ASPECT_WELLSPRING, 9)
|
new Ability(Abilities.EMBODY_ASPECT_WELLSPRING, 9)
|
||||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.SPDEF ], 1, true)
|
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.SPDEF ], 1, true)
|
||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
.attr(NoTransformAbilityAbAttr)
|
.attr(NoTransformAbilityAbAttr)
|
||||||
.partial(),
|
.partial(), // Ogerpon tera interactions
|
||||||
new Ability(Abilities.EMBODY_ASPECT_HEARTHFLAME, 9)
|
new Ability(Abilities.EMBODY_ASPECT_HEARTHFLAME, 9)
|
||||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.ATK ], 1, true)
|
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.ATK ], 1, true)
|
||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
.attr(NoTransformAbilityAbAttr)
|
.attr(NoTransformAbilityAbAttr)
|
||||||
.partial(),
|
.partial(), // Ogerpon tera interactions
|
||||||
new Ability(Abilities.EMBODY_ASPECT_CORNERSTONE, 9)
|
new Ability(Abilities.EMBODY_ASPECT_CORNERSTONE, 9)
|
||||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.DEF ], 1, true)
|
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.DEF ], 1, true)
|
||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
.attr(NoTransformAbilityAbAttr)
|
.attr(NoTransformAbilityAbAttr)
|
||||||
.partial(),
|
.partial(), // Ogerpon tera interactions
|
||||||
new Ability(Abilities.TERA_SHIFT, 9)
|
new Ability(Abilities.TERA_SHIFT, 9)
|
||||||
.attr(PostSummonFormChangeAbAttr, p => p.getFormKey() ? 0 : 1)
|
.attr(PostSummonFormChangeAbAttr, p => p.getFormKey() ? 0 : 1)
|
||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Arena } from "#app/field/arena";
|
import { Arena } from "#app/field/arena";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import { Type } from "#app/data/type";
|
import { Type } from "#app/data/type";
|
||||||
import * as Utils from "#app/utils";
|
import { BooleanHolder, NumberHolder, toDmgValue } from "#app/utils";
|
||||||
import { MoveCategory, allMoves, MoveTarget, IncrementMovePriorityAttr, applyMoveAttrs } from "#app/data/move";
|
import { MoveCategory, allMoves, MoveTarget, IncrementMovePriorityAttr, applyMoveAttrs } from "#app/data/move";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import Pokemon, { HitResult, PlayerPokemon, PokemonMove, EnemyPokemon } from "#app/field/pokemon";
|
import Pokemon, { HitResult, PokemonMove } from "#app/field/pokemon";
|
||||||
import { StatusEffect } from "#app/data/status-effect";
|
import { StatusEffect } from "#app/data/status-effect";
|
||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#app/battle";
|
||||||
import { BlockNonDirectDamageAbAttr, ChangeMovePriorityAbAttr, ProtectStatAbAttr, applyAbAttrs } from "#app/data/ability";
|
import { BlockNonDirectDamageAbAttr, ChangeMovePriorityAbAttr, ProtectStatAbAttr, applyAbAttrs } from "#app/data/ability";
|
||||||
|
@ -28,22 +28,15 @@ export enum ArenaTagSide {
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class ArenaTag {
|
export abstract class ArenaTag {
|
||||||
public tagType: ArenaTagType;
|
constructor(
|
||||||
public turnCount: integer;
|
public tagType: ArenaTagType,
|
||||||
public sourceMove?: Moves;
|
public turnCount: number,
|
||||||
public sourceId?: integer;
|
public sourceMove?: Moves,
|
||||||
public side: ArenaTagSide;
|
public sourceId?: number,
|
||||||
|
public side: ArenaTagSide = ArenaTagSide.BOTH
|
||||||
|
) {}
|
||||||
|
|
||||||
|
apply(arena: Arena, simulated: boolean, ...args: unknown[]): boolean {
|
||||||
constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves | undefined, sourceId?: integer, side: ArenaTagSide = ArenaTagSide.BOTH) {
|
|
||||||
this.tagType = tagType;
|
|
||||||
this.turnCount = turnCount;
|
|
||||||
this.sourceMove = sourceMove;
|
|
||||||
this.sourceId = sourceId;
|
|
||||||
this.side = side;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply(arena: Arena, args: any[]): boolean {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +59,44 @@ export abstract class ArenaTag {
|
||||||
? allMoves[this.sourceMove].name
|
? allMoves[this.sourceMove].name
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When given a arena tag or json representing one, load the data for it.
|
||||||
|
* This is meant to be inherited from by any arena tag with custom attributes
|
||||||
|
* @param {ArenaTag | any} source An arena tag
|
||||||
|
*/
|
||||||
|
loadTag(source : ArenaTag | any) : void {
|
||||||
|
this.turnCount = source.turnCount;
|
||||||
|
this.sourceMove = source.sourceMove;
|
||||||
|
this.sourceId = source.sourceId;
|
||||||
|
this.side = source.side;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function that retrieves the source Pokemon
|
||||||
|
* @param scene medium to retrieve the source Pokemon
|
||||||
|
* @returns The source {@linkcode Pokemon} or `null` if none is found
|
||||||
|
*/
|
||||||
|
public getSourcePokemon(scene: BattleScene): Pokemon | null {
|
||||||
|
return this.sourceId ? scene.getPokemonById(this.sourceId) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function that retrieves the Pokemon affected
|
||||||
|
* @param scene - medium to retrieve the involved Pokemon
|
||||||
|
* @returns list of PlayerPokemon or EnemyPokemon on the field
|
||||||
|
*/
|
||||||
|
public getAffectedPokemon(scene: BattleScene): Pokemon[] {
|
||||||
|
switch (this.side) {
|
||||||
|
case ArenaTagSide.PLAYER:
|
||||||
|
return scene.getPlayerField() ?? [];
|
||||||
|
case ArenaTagSide.ENEMY:
|
||||||
|
return scene.getEnemyField() ?? [];
|
||||||
|
case ArenaTagSide.BOTH:
|
||||||
|
default:
|
||||||
|
return scene.getField(true) ?? [];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,7 +104,7 @@ export abstract class ArenaTag {
|
||||||
* Prevents Pokémon on the opposing side from lowering the stats of the Pokémon in the Mist.
|
* Prevents Pokémon on the opposing side from lowering the stats of the Pokémon in the Mist.
|
||||||
*/
|
*/
|
||||||
export class MistTag extends ArenaTag {
|
export class MistTag extends ArenaTag {
|
||||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.MIST, turnCount, Moves.MIST, sourceId, side);
|
super(ArenaTagType.MIST, turnCount, Moves.MIST, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,10 +122,20 @@ export class MistTag extends ArenaTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(arena: Arena, args: any[]): boolean {
|
/**
|
||||||
(args[0] as Utils.BooleanHolder).value = true;
|
* Cancels the lowering of stats
|
||||||
|
* @param arena the {@linkcode Arena} containing this effect
|
||||||
|
* @param simulated `true` if the effect should be applied quietly
|
||||||
|
* @param cancelled a {@linkcode BooleanHolder} whose value is set to `true`
|
||||||
|
* to flag the stat reduction as cancelled
|
||||||
|
* @returns `true` if a stat reduction was cancelled; `false` otherwise
|
||||||
|
*/
|
||||||
|
override apply(arena: Arena, simulated: boolean, cancelled: BooleanHolder): boolean {
|
||||||
|
cancelled.value = true;
|
||||||
|
|
||||||
|
if (!simulated) {
|
||||||
arena.scene.queueMessage(i18next.t("arenaTag:mistApply"));
|
arena.scene.queueMessage(i18next.t("arenaTag:mistApply"));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -117,7 +158,7 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
||||||
* @param side - The side (player or enemy) the tag affects.
|
* @param side - The side (player or enemy) the tag affects.
|
||||||
* @param weakenedCategories - The categories of moves that are weakened by this tag.
|
* @param weakenedCategories - The categories of moves that are weakened by this tag.
|
||||||
*/
|
*/
|
||||||
constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, weakenedCategories: MoveCategory[]) {
|
constructor(tagType: ArenaTagType, turnCount: number, sourceMove: Moves, sourceId: number, side: ArenaTagSide, weakenedCategories: MoveCategory[]) {
|
||||||
super(tagType, turnCount, sourceMove, sourceId, side);
|
super(tagType, turnCount, sourceMove, sourceId, side);
|
||||||
|
|
||||||
this.weakenedCategories = weakenedCategories;
|
this.weakenedCategories = weakenedCategories;
|
||||||
|
@ -126,17 +167,15 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
||||||
/**
|
/**
|
||||||
* Applies the weakening effect to the move.
|
* Applies the weakening effect to the move.
|
||||||
*
|
*
|
||||||
* @param arena - The arena where the move is applied.
|
* @param arena the {@linkcode Arena} where the move is applied.
|
||||||
* @param args - The arguments for the move application.
|
* @param simulated n/a
|
||||||
* @param args[0] - The category of the move.
|
* @param moveCategory the attacking move's {@linkcode MoveCategory}.
|
||||||
* @param args[1] - A boolean indicating whether it is a double battle.
|
* @param damageMultiplier A {@linkcode NumberHolder} containing the damage multiplier
|
||||||
* @param args[2] - An object of type `Utils.NumberHolder` that holds the damage multiplier
|
* @returns `true` if the attacking move was weakened; `false` otherwise.
|
||||||
*
|
|
||||||
* @returns True if the move was weakened, otherwise false.
|
|
||||||
*/
|
*/
|
||||||
apply(arena: Arena, args: any[]): boolean {
|
override apply(arena: Arena, simulated: boolean, moveCategory: MoveCategory, damageMultiplier: NumberHolder): boolean {
|
||||||
if (this.weakenedCategories.includes((args[0] as MoveCategory))) {
|
if (this.weakenedCategories.includes(moveCategory)) {
|
||||||
(args[2] as Utils.NumberHolder).value = (args[1] as boolean) ? 2732 / 4096 : 0.5;
|
damageMultiplier.value = arena.scene.currentBattle.double ? 2732 / 4096 : 0.5;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -148,7 +187,7 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
||||||
* Used by {@linkcode Moves.REFLECT}
|
* Used by {@linkcode Moves.REFLECT}
|
||||||
*/
|
*/
|
||||||
class ReflectTag extends WeakenMoveScreenTag {
|
class ReflectTag extends WeakenMoveScreenTag {
|
||||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side, [ MoveCategory.PHYSICAL ]);
|
super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side, [ MoveCategory.PHYSICAL ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +203,7 @@ class ReflectTag extends WeakenMoveScreenTag {
|
||||||
* Used by {@linkcode Moves.LIGHT_SCREEN}
|
* Used by {@linkcode Moves.LIGHT_SCREEN}
|
||||||
*/
|
*/
|
||||||
class LightScreenTag extends WeakenMoveScreenTag {
|
class LightScreenTag extends WeakenMoveScreenTag {
|
||||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side, [ MoveCategory.SPECIAL ]);
|
super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side, [ MoveCategory.SPECIAL ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +219,7 @@ class LightScreenTag extends WeakenMoveScreenTag {
|
||||||
* Used by {@linkcode Moves.AURORA_VEIL}
|
* Used by {@linkcode Moves.AURORA_VEIL}
|
||||||
*/
|
*/
|
||||||
class AuroraVeilTag extends WeakenMoveScreenTag {
|
class AuroraVeilTag extends WeakenMoveScreenTag {
|
||||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side, [ MoveCategory.SPECIAL, MoveCategory.PHYSICAL ]);
|
super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side, [ MoveCategory.SPECIAL, MoveCategory.PHYSICAL ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +242,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
||||||
/** Does this apply to all moves, including those that ignore other forms of protection? */
|
/** Does this apply to all moves, including those that ignore other forms of protection? */
|
||||||
protected ignoresBypass: boolean;
|
protected ignoresBypass: boolean;
|
||||||
|
|
||||||
constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, condition: ProtectConditionFunc, ignoresBypass: boolean = false) {
|
constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: number, side: ArenaTagSide, condition: ProtectConditionFunc, ignoresBypass: boolean = false) {
|
||||||
super(tagType, 1, sourceMove, sourceId, side);
|
super(tagType, 1, sourceMove, sourceId, side);
|
||||||
|
|
||||||
this.protectConditionFunc = condition;
|
this.protectConditionFunc = condition;
|
||||||
|
@ -218,39 +257,35 @@ export class ConditionalProtectTag extends ArenaTag {
|
||||||
onRemove(arena: Arena): void { }
|
onRemove(arena: Arena): void { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* apply(): Checks incoming moves against the condition function
|
* Checks incoming moves against the condition function
|
||||||
* and protects the target if conditions are met
|
* and protects the target if conditions are met
|
||||||
* @param arena The arena containing this tag
|
* @param arena the {@linkcode Arena} containing this tag
|
||||||
* @param args\[0\] (Utils.BooleanHolder) Signals if the move is cancelled
|
* @param simulated `true` if the tag is applied quietly; `false` otherwise.
|
||||||
* @param args\[1\] (Pokemon) The Pokemon using the move
|
* @param isProtected a {@linkcode BooleanHolder} used to flag if the move is protected against
|
||||||
* @param args\[2\] (Pokemon) The intended target of the move
|
* @param attacker the attacking {@linkcode Pokemon}
|
||||||
* @param args\[3\] (Moves) The parameters to the condition function
|
* @param defender the defending {@linkcode Pokemon}
|
||||||
* @param args\[4\] (Utils.BooleanHolder) Signals if the applied protection supercedes protection-ignoring effects
|
* @param moveId the {@linkcode Moves | identifier} for the move being used
|
||||||
* @returns
|
* @param ignoresProtectBypass a {@linkcode BooleanHolder} used to flag if a protection effect supercedes effects that ignore protection
|
||||||
|
* @returns `true` if this tag protected against the attack; `false` otherwise
|
||||||
*/
|
*/
|
||||||
apply(arena: Arena, args: any[]): boolean {
|
override apply(arena: Arena, simulated: boolean, isProtected: BooleanHolder, attacker: Pokemon, defender: Pokemon,
|
||||||
const [ cancelled, user, target, moveId, ignoresBypass ] = args;
|
moveId: Moves, ignoresProtectBypass: BooleanHolder): boolean {
|
||||||
|
|
||||||
if (cancelled instanceof Utils.BooleanHolder
|
if ((this.side === ArenaTagSide.PLAYER) === defender.isPlayer()
|
||||||
&& user instanceof Pokemon
|
|
||||||
&& target instanceof Pokemon
|
|
||||||
&& typeof moveId === "number"
|
|
||||||
&& ignoresBypass instanceof Utils.BooleanHolder) {
|
|
||||||
|
|
||||||
if ((this.side === ArenaTagSide.PLAYER) === target.isPlayer()
|
|
||||||
&& this.protectConditionFunc(arena, moveId)) {
|
&& this.protectConditionFunc(arena, moveId)) {
|
||||||
if (!cancelled.value) {
|
if (!isProtected.value) {
|
||||||
cancelled.value = true;
|
isProtected.value = true;
|
||||||
user.stopMultiHit(target);
|
if (!simulated) {
|
||||||
|
attacker.stopMultiHit(defender);
|
||||||
|
|
||||||
new CommonBattleAnim(CommonAnim.PROTECT, target).play(arena.scene);
|
new CommonBattleAnim(CommonAnim.PROTECT, defender).play(arena.scene);
|
||||||
arena.scene.queueMessage(i18next.t("arenaTag:conditionalProtectApply", { moveName: super.getMoveName(), pokemonNameWithAffix: getPokemonNameWithAffix(target) }));
|
arena.scene.queueMessage(i18next.t("arenaTag:conditionalProtectApply", { moveName: super.getMoveName(), pokemonNameWithAffix: getPokemonNameWithAffix(defender) }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ignoresBypass.value = ignoresBypass.value || this.ignoresBypass;
|
ignoresProtectBypass.value = ignoresProtectBypass.value || this.ignoresBypass;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,7 +300,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
||||||
*/
|
*/
|
||||||
const QuickGuardConditionFunc: ProtectConditionFunc = (arena, moveId) => {
|
const QuickGuardConditionFunc: ProtectConditionFunc = (arena, moveId) => {
|
||||||
const move = allMoves[moveId];
|
const move = allMoves[moveId];
|
||||||
const priority = new Utils.IntegerHolder(move.priority);
|
const priority = new NumberHolder(move.priority);
|
||||||
const effectPhase = arena.scene.getCurrentPhase();
|
const effectPhase = arena.scene.getCurrentPhase();
|
||||||
|
|
||||||
if (effectPhase instanceof MoveEffectPhase) {
|
if (effectPhase instanceof MoveEffectPhase) {
|
||||||
|
@ -281,7 +316,7 @@ const QuickGuardConditionFunc: ProtectConditionFunc = (arena, moveId) => {
|
||||||
* Condition: The incoming move has increased priority.
|
* Condition: The incoming move has increased priority.
|
||||||
*/
|
*/
|
||||||
class QuickGuardTag extends ConditionalProtectTag {
|
class QuickGuardTag extends ConditionalProtectTag {
|
||||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.QUICK_GUARD, Moves.QUICK_GUARD, sourceId, side, QuickGuardConditionFunc);
|
super(ArenaTagType.QUICK_GUARD, Moves.QUICK_GUARD, sourceId, side, QuickGuardConditionFunc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,7 +347,7 @@ const WideGuardConditionFunc: ProtectConditionFunc = (arena, moveId) : boolean =
|
||||||
* can be an ally or enemy.
|
* can be an ally or enemy.
|
||||||
*/
|
*/
|
||||||
class WideGuardTag extends ConditionalProtectTag {
|
class WideGuardTag extends ConditionalProtectTag {
|
||||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.WIDE_GUARD, Moves.WIDE_GUARD, sourceId, side, WideGuardConditionFunc);
|
super(ArenaTagType.WIDE_GUARD, Moves.WIDE_GUARD, sourceId, side, WideGuardConditionFunc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,7 +369,7 @@ const MatBlockConditionFunc: ProtectConditionFunc = (arena, moveId) : boolean =>
|
||||||
* Condition: The incoming move is a Physical or Special attack move.
|
* Condition: The incoming move is a Physical or Special attack move.
|
||||||
*/
|
*/
|
||||||
class MatBlockTag extends ConditionalProtectTag {
|
class MatBlockTag extends ConditionalProtectTag {
|
||||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.MAT_BLOCK, Moves.MAT_BLOCK, sourceId, side, MatBlockConditionFunc);
|
super(ArenaTagType.MAT_BLOCK, Moves.MAT_BLOCK, sourceId, side, MatBlockConditionFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +407,7 @@ const CraftyShieldConditionFunc: ProtectConditionFunc = (arena, moveId) => {
|
||||||
* not target all Pokemon or sides of the field.
|
* not target all Pokemon or sides of the field.
|
||||||
*/
|
*/
|
||||||
class CraftyShieldTag extends ConditionalProtectTag {
|
class CraftyShieldTag extends ConditionalProtectTag {
|
||||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.CRAFTY_SHIELD, Moves.CRAFTY_SHIELD, sourceId, side, CraftyShieldConditionFunc, true);
|
super(ArenaTagType.CRAFTY_SHIELD, Moves.CRAFTY_SHIELD, sourceId, side, CraftyShieldConditionFunc, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,12 +419,12 @@ class CraftyShieldTag extends ConditionalProtectTag {
|
||||||
export class NoCritTag extends ArenaTag {
|
export class NoCritTag extends ArenaTag {
|
||||||
/**
|
/**
|
||||||
* Constructor method for the NoCritTag class
|
* Constructor method for the NoCritTag class
|
||||||
* @param turnCount `integer` the number of turns this effect lasts
|
* @param turnCount `number` the number of turns this effect lasts
|
||||||
* @param sourceMove {@linkcode Moves} the move that created this effect
|
* @param sourceMove {@linkcode Moves} the move that created this effect
|
||||||
* @param sourceId `integer` the ID of the {@linkcode Pokemon} that created this effect
|
* @param sourceId `number` the ID of the {@linkcode Pokemon} that created this effect
|
||||||
* @param side {@linkcode ArenaTagSide} the side to which this effect belongs
|
* @param side {@linkcode ArenaTagSide} the side to which this effect belongs
|
||||||
*/
|
*/
|
||||||
constructor(turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceMove: Moves, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.NO_CRIT, turnCount, sourceMove, sourceId, side);
|
super(ArenaTagType.NO_CRIT, turnCount, sourceMove, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +454,7 @@ class WishTag extends ArenaTag {
|
||||||
private triggerMessage: string;
|
private triggerMessage: string;
|
||||||
private healHp: number;
|
private healHp: number;
|
||||||
|
|
||||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.WISH, turnCount, Moves.WISH, sourceId, side);
|
super(ArenaTagType.WISH, turnCount, Moves.WISH, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +464,7 @@ class WishTag extends ArenaTag {
|
||||||
if (user) {
|
if (user) {
|
||||||
this.battlerIndex = user.getBattlerIndex();
|
this.battlerIndex = user.getBattlerIndex();
|
||||||
this.triggerMessage = i18next.t("arenaTag:wishTagOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(user) });
|
this.triggerMessage = i18next.t("arenaTag:wishTagOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(user) });
|
||||||
this.healHp = Utils.toDmgValue(user.getMaxHp() / 2);
|
this.healHp = toDmgValue(user.getMaxHp() / 2);
|
||||||
} else {
|
} else {
|
||||||
console.warn("Failed to get source for WishTag onAdd");
|
console.warn("Failed to get source for WishTag onAdd");
|
||||||
}
|
}
|
||||||
|
@ -460,18 +495,25 @@ export class WeakenMoveTypeTag extends ArenaTag {
|
||||||
* @param sourceMove - The move that created the tag.
|
* @param sourceMove - The move that created the tag.
|
||||||
* @param sourceId - The ID of the source of the tag.
|
* @param sourceId - The ID of the source of the tag.
|
||||||
*/
|
*/
|
||||||
constructor(tagType: ArenaTagType, turnCount: integer, type: Type, sourceMove: Moves, sourceId: integer) {
|
constructor(tagType: ArenaTagType, turnCount: number, type: Type, sourceMove: Moves, sourceId: number) {
|
||||||
super(tagType, turnCount, sourceMove, sourceId);
|
super(tagType, turnCount, sourceMove, sourceId);
|
||||||
|
|
||||||
this.weakenedType = type;
|
this.weakenedType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(arena: Arena, args: any[]): boolean {
|
/**
|
||||||
if ((args[0] as Type) === this.weakenedType) {
|
* Reduces an attack's power by 0.33x if it matches this tag's weakened type.
|
||||||
(args[1] as Utils.NumberHolder).value *= 0.33;
|
* @param arena n/a
|
||||||
|
* @param simulated n/a
|
||||||
|
* @param type the attack's {@linkcode Type}
|
||||||
|
* @param power a {@linkcode NumberHolder} containing the attack's power
|
||||||
|
* @returns `true` if the attack's power was reduced; `false` otherwise.
|
||||||
|
*/
|
||||||
|
override apply(arena: Arena, simulated: boolean, type: Type, power: NumberHolder): boolean {
|
||||||
|
if (type === this.weakenedType) {
|
||||||
|
power.value *= 0.33;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -481,7 +523,7 @@ export class WeakenMoveTypeTag extends ArenaTag {
|
||||||
* Weakens Electric type moves for a set amount of turns, usually 5.
|
* Weakens Electric type moves for a set amount of turns, usually 5.
|
||||||
*/
|
*/
|
||||||
class MudSportTag extends WeakenMoveTypeTag {
|
class MudSportTag extends WeakenMoveTypeTag {
|
||||||
constructor(turnCount: integer, sourceId: integer) {
|
constructor(turnCount: number, sourceId: number) {
|
||||||
super(ArenaTagType.MUD_SPORT, turnCount, Type.ELECTRIC, Moves.MUD_SPORT, sourceId);
|
super(ArenaTagType.MUD_SPORT, turnCount, Type.ELECTRIC, Moves.MUD_SPORT, sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,7 +541,7 @@ class MudSportTag extends WeakenMoveTypeTag {
|
||||||
* Weakens Fire type moves for a set amount of turns, usually 5.
|
* Weakens Fire type moves for a set amount of turns, usually 5.
|
||||||
*/
|
*/
|
||||||
class WaterSportTag extends WeakenMoveTypeTag {
|
class WaterSportTag extends WeakenMoveTypeTag {
|
||||||
constructor(turnCount: integer, sourceId: integer) {
|
constructor(turnCount: number, sourceId: number) {
|
||||||
super(ArenaTagType.WATER_SPORT, turnCount, Type.FIRE, Moves.WATER_SPORT, sourceId);
|
super(ArenaTagType.WATER_SPORT, turnCount, Type.FIRE, Moves.WATER_SPORT, sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,13 +574,12 @@ export class IonDelugeTag extends ArenaTag {
|
||||||
/**
|
/**
|
||||||
* Converts Normal-type moves to Electric type
|
* Converts Normal-type moves to Electric type
|
||||||
* @param arena n/a
|
* @param arena n/a
|
||||||
* @param args
|
* @param simulated n/a
|
||||||
* - `[0]` {@linkcode Utils.NumberHolder} A container with a move's {@linkcode Type}
|
* @param moveType a {@linkcode NumberHolder} containing a move's {@linkcode Type}
|
||||||
* @returns `true` if the given move type changed; `false` otherwise.
|
* @returns `true` if the given move type changed; `false` otherwise.
|
||||||
*/
|
*/
|
||||||
apply(arena: Arena, args: any[]): boolean {
|
override apply(arena: Arena, simulated: boolean, moveType: NumberHolder): boolean {
|
||||||
const moveType = args[0];
|
if (moveType.value === Type.NORMAL) {
|
||||||
if (moveType instanceof Utils.NumberHolder && moveType.value === Type.NORMAL) {
|
|
||||||
moveType.value = Type.ELECTRIC;
|
moveType.value = Type.ELECTRIC;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -550,8 +591,8 @@ export class IonDelugeTag extends ArenaTag {
|
||||||
* Abstract class to implement arena traps.
|
* Abstract class to implement arena traps.
|
||||||
*/
|
*/
|
||||||
export class ArenaTrapTag extends ArenaTag {
|
export class ArenaTrapTag extends ArenaTag {
|
||||||
public layers: integer;
|
public layers: number;
|
||||||
public maxLayers: integer;
|
public maxLayers: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of the ArenaTrapTag class.
|
* Creates a new instance of the ArenaTrapTag class.
|
||||||
|
@ -562,7 +603,7 @@ export class ArenaTrapTag extends ArenaTag {
|
||||||
* @param side - The side (player or enemy) the tag affects.
|
* @param side - The side (player or enemy) the tag affects.
|
||||||
* @param maxLayers - The maximum amount of layers this tag can have.
|
* @param maxLayers - The maximum amount of layers this tag can have.
|
||||||
*/
|
*/
|
||||||
constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, maxLayers: integer) {
|
constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: number, side: ArenaTagSide, maxLayers: number) {
|
||||||
super(tagType, 0, sourceMove, sourceId, side);
|
super(tagType, 0, sourceMove, sourceId, side);
|
||||||
|
|
||||||
this.layers = 1;
|
this.layers = 1;
|
||||||
|
@ -577,22 +618,34 @@ export class ArenaTrapTag extends ArenaTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(arena: Arena, args: any[]): boolean {
|
/**
|
||||||
const pokemon = args[0] as Pokemon;
|
* Activates the hazard effect onto a Pokemon when it enters the field
|
||||||
|
* @param arena the {@linkcode Arena} containing this tag
|
||||||
|
* @param simulated if `true`, only checks if the hazard would activate.
|
||||||
|
* @param pokemon the {@linkcode Pokemon} triggering this hazard
|
||||||
|
* @returns `true` if this hazard affects the given Pokemon; `false` otherwise.
|
||||||
|
*/
|
||||||
|
override apply(arena: Arena, simulated: boolean, pokemon: Pokemon): boolean {
|
||||||
if (this.sourceId === pokemon.id || (this.side === ArenaTagSide.PLAYER) !== pokemon.isPlayer()) {
|
if (this.sourceId === pokemon.id || (this.side === ArenaTagSide.PLAYER) !== pokemon.isPlayer()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.activateTrap(pokemon);
|
return this.activateTrap(pokemon, simulated);
|
||||||
}
|
}
|
||||||
|
|
||||||
activateTrap(pokemon: Pokemon): boolean {
|
activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMatchupScoreMultiplier(pokemon: Pokemon): number {
|
getMatchupScoreMultiplier(pokemon: Pokemon): number {
|
||||||
return pokemon.isGrounded() ? 1 : Phaser.Math.Linear(0, 1 / Math.pow(2, this.layers), Math.min(pokemon.getHpRatio(), 0.5) * 2);
|
return pokemon.isGrounded() ? 1 : Phaser.Math.Linear(0, 1 / Math.pow(2, this.layers), Math.min(pokemon.getHpRatio(), 0.5) * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadTag(source: any): void {
|
||||||
|
super.loadTag(source);
|
||||||
|
this.layers = source.layers;
|
||||||
|
this.maxLayers = source.maxLayers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -601,7 +654,7 @@ export class ArenaTrapTag extends ArenaTag {
|
||||||
* in damage for 1, 2, or 3 layers of Spikes respectively if they are summoned into this trap.
|
* in damage for 1, 2, or 3 layers of Spikes respectively if they are summoned into this trap.
|
||||||
*/
|
*/
|
||||||
class SpikesTag extends ArenaTrapTag {
|
class SpikesTag extends ArenaTrapTag {
|
||||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.SPIKES, Moves.SPIKES, sourceId, side, 3);
|
super(ArenaTagType.SPIKES, Moves.SPIKES, sourceId, side, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,14 +667,18 @@ class SpikesTag extends ArenaTrapTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activateTrap(pokemon: Pokemon): boolean {
|
override activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
|
||||||
if (pokemon.isGrounded()) {
|
if (pokemon.isGrounded()) {
|
||||||
const cancelled = new Utils.BooleanHolder(false);
|
const cancelled = new BooleanHolder(false);
|
||||||
applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled);
|
applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled);
|
||||||
|
|
||||||
|
if (simulated) {
|
||||||
|
return !cancelled.value;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cancelled.value) {
|
if (!cancelled.value) {
|
||||||
const damageHpRatio = 1 / (10 - 2 * this.layers);
|
const damageHpRatio = 1 / (10 - 2 * this.layers);
|
||||||
const damage = Utils.toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
||||||
|
|
||||||
pokemon.scene.queueMessage(i18next.t("arenaTag:spikesActivateTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
pokemon.scene.queueMessage(i18next.t("arenaTag:spikesActivateTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||||
pokemon.damageAndUpdate(damage, HitResult.OTHER);
|
pokemon.damageAndUpdate(damage, HitResult.OTHER);
|
||||||
|
@ -645,7 +702,7 @@ class SpikesTag extends ArenaTrapTag {
|
||||||
class ToxicSpikesTag extends ArenaTrapTag {
|
class ToxicSpikesTag extends ArenaTrapTag {
|
||||||
private neutralized: boolean;
|
private neutralized: boolean;
|
||||||
|
|
||||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.TOXIC_SPIKES, Moves.TOXIC_SPIKES, sourceId, side, 2);
|
super(ArenaTagType.TOXIC_SPIKES, Moves.TOXIC_SPIKES, sourceId, side, 2);
|
||||||
this.neutralized = false;
|
this.neutralized = false;
|
||||||
}
|
}
|
||||||
|
@ -665,8 +722,11 @@ class ToxicSpikesTag extends ArenaTrapTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activateTrap(pokemon: Pokemon): boolean {
|
override activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
|
||||||
if (pokemon.isGrounded()) {
|
if (pokemon.isGrounded()) {
|
||||||
|
if (simulated) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (pokemon.isOfType(Type.POISON)) {
|
if (pokemon.isOfType(Type.POISON)) {
|
||||||
this.neutralized = true;
|
this.neutralized = true;
|
||||||
if (pokemon.scene.arena.removeTag(this.tagType)) {
|
if (pokemon.scene.arena.removeTag(this.tagType)) {
|
||||||
|
@ -703,7 +763,7 @@ class ToxicSpikesTag extends ArenaTrapTag {
|
||||||
class DelayedAttackTag extends ArenaTag {
|
class DelayedAttackTag extends ArenaTag {
|
||||||
public targetIndex: BattlerIndex;
|
public targetIndex: BattlerIndex;
|
||||||
|
|
||||||
constructor(tagType: ArenaTagType, sourceMove: Moves | undefined, sourceId: integer, targetIndex: BattlerIndex) {
|
constructor(tagType: ArenaTagType, sourceMove: Moves | undefined, sourceId: number, targetIndex: BattlerIndex) {
|
||||||
super(tagType, 3, sourceMove, sourceId);
|
super(tagType, 3, sourceMove, sourceId);
|
||||||
|
|
||||||
this.targetIndex = targetIndex;
|
this.targetIndex = targetIndex;
|
||||||
|
@ -728,7 +788,7 @@ class DelayedAttackTag extends ArenaTag {
|
||||||
* who is summoned into the trap, based on the Rock type's type effectiveness.
|
* who is summoned into the trap, based on the Rock type's type effectiveness.
|
||||||
*/
|
*/
|
||||||
class StealthRockTag extends ArenaTrapTag {
|
class StealthRockTag extends ArenaTrapTag {
|
||||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.STEALTH_ROCK, Moves.STEALTH_ROCK, sourceId, side, 1);
|
super(ArenaTagType.STEALTH_ROCK, Moves.STEALTH_ROCK, sourceId, side, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,8 +830,8 @@ class StealthRockTag extends ArenaTrapTag {
|
||||||
return damageHpRatio;
|
return damageHpRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
activateTrap(pokemon: Pokemon): boolean {
|
override activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
|
||||||
const cancelled = new Utils.BooleanHolder(false);
|
const cancelled = new BooleanHolder(false);
|
||||||
applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled);
|
applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled);
|
||||||
|
|
||||||
if (cancelled.value) {
|
if (cancelled.value) {
|
||||||
|
@ -781,12 +841,16 @@ class StealthRockTag extends ArenaTrapTag {
|
||||||
const damageHpRatio = this.getDamageHpRatio(pokemon);
|
const damageHpRatio = this.getDamageHpRatio(pokemon);
|
||||||
|
|
||||||
if (damageHpRatio) {
|
if (damageHpRatio) {
|
||||||
const damage = Utils.toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
if (simulated) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio);
|
||||||
pokemon.scene.queueMessage(i18next.t("arenaTag:stealthRockActivateTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
pokemon.scene.queueMessage(i18next.t("arenaTag:stealthRockActivateTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||||
pokemon.damageAndUpdate(damage, HitResult.OTHER);
|
pokemon.damageAndUpdate(damage, HitResult.OTHER);
|
||||||
if (pokemon.turnData) {
|
if (pokemon.turnData) {
|
||||||
pokemon.turnData.damageTaken += damage;
|
pokemon.turnData.damageTaken += damage;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -804,7 +868,7 @@ class StealthRockTag extends ArenaTrapTag {
|
||||||
* to any Pokémon who is summoned into this trap.
|
* to any Pokémon who is summoned into this trap.
|
||||||
*/
|
*/
|
||||||
class StickyWebTag extends ArenaTrapTag {
|
class StickyWebTag extends ArenaTrapTag {
|
||||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.STICKY_WEB, Moves.STICKY_WEB, sourceId, side, 1);
|
super(ArenaTagType.STICKY_WEB, Moves.STICKY_WEB, sourceId, side, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,14 +880,20 @@ class StickyWebTag extends ArenaTrapTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activateTrap(pokemon: Pokemon): boolean {
|
override activateTrap(pokemon: Pokemon, simulated: boolean): boolean {
|
||||||
if (pokemon.isGrounded()) {
|
if (pokemon.isGrounded()) {
|
||||||
const cancelled = new Utils.BooleanHolder(false);
|
const cancelled = new BooleanHolder(false);
|
||||||
applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled);
|
applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled);
|
||||||
|
|
||||||
|
if (simulated) {
|
||||||
|
return !cancelled.value;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cancelled.value) {
|
if (!cancelled.value) {
|
||||||
pokemon.scene.queueMessage(i18next.t("arenaTag:stickyWebActivateTrap", { pokemonName: pokemon.getNameToRender() }));
|
pokemon.scene.queueMessage(i18next.t("arenaTag:stickyWebActivateTrap", { pokemonName: pokemon.getNameToRender() }));
|
||||||
const stages = new Utils.NumberHolder(-1);
|
const stages = new NumberHolder(-1);
|
||||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [ Stat.SPD ], stages.value));
|
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [ Stat.SPD ], stages.value));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,12 +908,19 @@ class StickyWebTag extends ArenaTrapTag {
|
||||||
* also reversing the turn order for all Pokémon on the field as well.
|
* also reversing the turn order for all Pokémon on the field as well.
|
||||||
*/
|
*/
|
||||||
export class TrickRoomTag extends ArenaTag {
|
export class TrickRoomTag extends ArenaTag {
|
||||||
constructor(turnCount: integer, sourceId: integer) {
|
constructor(turnCount: number, sourceId: number) {
|
||||||
super(ArenaTagType.TRICK_ROOM, turnCount, Moves.TRICK_ROOM, sourceId);
|
super(ArenaTagType.TRICK_ROOM, turnCount, Moves.TRICK_ROOM, sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(arena: Arena, args: any[]): boolean {
|
/**
|
||||||
const speedReversed = args[0] as Utils.BooleanHolder;
|
* Reverses Speed-based turn order for all Pokemon on the field
|
||||||
|
* @param arena n/a
|
||||||
|
* @param simulated n/a
|
||||||
|
* @param speedReversed a {@linkcode BooleanHolder} used to flag if Speed-based
|
||||||
|
* turn order should be reversed.
|
||||||
|
* @returns `true` if turn order is successfully reversed; `false` otherwise
|
||||||
|
*/
|
||||||
|
override apply(arena: Arena, simulated: boolean, speedReversed: BooleanHolder): boolean {
|
||||||
speedReversed.value = !speedReversed.value;
|
speedReversed.value = !speedReversed.value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -866,7 +943,7 @@ export class TrickRoomTag extends ArenaTag {
|
||||||
* {@linkcode Abilities.LEVITATE} for the duration of the arena tag, usually 5 turns.
|
* {@linkcode Abilities.LEVITATE} for the duration of the arena tag, usually 5 turns.
|
||||||
*/
|
*/
|
||||||
export class GravityTag extends ArenaTag {
|
export class GravityTag extends ArenaTag {
|
||||||
constructor(turnCount: integer) {
|
constructor(turnCount: number) {
|
||||||
super(ArenaTagType.GRAVITY, turnCount, Moves.GRAVITY);
|
super(ArenaTagType.GRAVITY, turnCount, Moves.GRAVITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -874,7 +951,8 @@ export class GravityTag extends ArenaTag {
|
||||||
arena.scene.queueMessage(i18next.t("arenaTag:gravityOnAdd"));
|
arena.scene.queueMessage(i18next.t("arenaTag:gravityOnAdd"));
|
||||||
arena.scene.getField(true).forEach((pokemon) => {
|
arena.scene.getField(true).forEach((pokemon) => {
|
||||||
if (pokemon !== null) {
|
if (pokemon !== null) {
|
||||||
pokemon.removeTag(BattlerTagType.MAGNET_RISEN);
|
pokemon.removeTag(BattlerTagType.FLOATING);
|
||||||
|
pokemon.removeTag(BattlerTagType.TELEKINESIS);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -890,7 +968,7 @@ export class GravityTag extends ArenaTag {
|
||||||
* Applies this arena tag for 4 turns (including the turn the move was used).
|
* Applies this arena tag for 4 turns (including the turn the move was used).
|
||||||
*/
|
*/
|
||||||
class TailwindTag extends ArenaTag {
|
class TailwindTag extends ArenaTag {
|
||||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side);
|
super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,7 +1006,7 @@ class TailwindTag extends ArenaTag {
|
||||||
* Doubles the prize money from trainers and money moves like {@linkcode Moves.PAY_DAY} and {@linkcode Moves.MAKE_IT_RAIN}.
|
* Doubles the prize money from trainers and money moves like {@linkcode Moves.PAY_DAY} and {@linkcode Moves.MAKE_IT_RAIN}.
|
||||||
*/
|
*/
|
||||||
class HappyHourTag extends ArenaTag {
|
class HappyHourTag extends ArenaTag {
|
||||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.HAPPY_HOUR, turnCount, Moves.HAPPY_HOUR, sourceId, side);
|
super(ArenaTagType.HAPPY_HOUR, turnCount, Moves.HAPPY_HOUR, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,7 +1020,7 @@ class HappyHourTag extends ArenaTag {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SafeguardTag extends ArenaTag {
|
class SafeguardTag extends ArenaTag {
|
||||||
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
|
constructor(turnCount: number, sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.SAFEGUARD, turnCount, Moves.SAFEGUARD, sourceId, side);
|
super(ArenaTagType.SAFEGUARD, turnCount, Moves.SAFEGUARD, sourceId, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -955,42 +1033,35 @@ class SafeguardTag extends ArenaTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NoneTag extends ArenaTag {
|
||||||
|
constructor() {
|
||||||
|
super(ArenaTagType.NONE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This arena tag facilitates the application of the move Imprison
|
* This arena tag facilitates the application of the move Imprison
|
||||||
* Imprison remains in effect as long as the source Pokemon is active and present on the field.
|
* Imprison remains in effect as long as the source Pokemon is active and present on the field.
|
||||||
* Imprison will apply to any opposing Pokemon that switch onto the field as well.
|
* Imprison will apply to any opposing Pokemon that switch onto the field as well.
|
||||||
*/
|
*/
|
||||||
class ImprisonTag extends ArenaTrapTag {
|
class ImprisonTag extends ArenaTrapTag {
|
||||||
private source: Pokemon;
|
|
||||||
|
|
||||||
constructor(sourceId: number, side: ArenaTagSide) {
|
constructor(sourceId: number, side: ArenaTagSide) {
|
||||||
super(ArenaTagType.IMPRISON, Moves.IMPRISON, sourceId, side, 1);
|
super(ArenaTagType.IMPRISON, Moves.IMPRISON, sourceId, side, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function that retrieves the Pokemon affected
|
|
||||||
* @param {BattleScene} scene medium to retrieve the involved Pokemon
|
|
||||||
* @returns list of PlayerPokemon or EnemyPokemon on the field
|
|
||||||
*/
|
|
||||||
private retrieveField(scene: BattleScene): PlayerPokemon[] | EnemyPokemon[] {
|
|
||||||
if (!this.source.isPlayer()) {
|
|
||||||
return scene.getPlayerField() ?? [];
|
|
||||||
}
|
|
||||||
return scene.getEnemyField() ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function applies the effects of Imprison to the opposing Pokemon already present on the field.
|
* This function applies the effects of Imprison to the opposing Pokemon already present on the field.
|
||||||
* @param arena
|
* @param arena
|
||||||
*/
|
*/
|
||||||
override onAdd({ scene }: Arena) {
|
override onAdd({ scene }: Arena) {
|
||||||
this.source = scene.getPokemonById(this.sourceId!)!;
|
const source = this.getSourcePokemon(scene);
|
||||||
if (this.source) {
|
if (source) {
|
||||||
const party = this.retrieveField(scene);
|
const party = this.getAffectedPokemon(scene);
|
||||||
party?.forEach((p: PlayerPokemon | EnemyPokemon ) => {
|
party?.forEach((p: Pokemon ) => {
|
||||||
|
if (p.isAllowedInBattle()) {
|
||||||
p.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId);
|
p.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
scene.queueMessage(i18next.t("battlerTags:imprisonOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(this.source) }));
|
scene.queueMessage(i18next.t("battlerTags:imprisonOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(source) }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -999,8 +1070,9 @@ class ImprisonTag extends ArenaTrapTag {
|
||||||
* @param _arena
|
* @param _arena
|
||||||
* @returns `true` if the source of the tag is still active on the field | `false` if not
|
* @returns `true` if the source of the tag is still active on the field | `false` if not
|
||||||
*/
|
*/
|
||||||
override lapse(_arena: Arena): boolean {
|
override lapse({ scene }: Arena): boolean {
|
||||||
return this.source.isActive(true);
|
const source = this.getSourcePokemon(scene);
|
||||||
|
return source ? source.isActive(true) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1009,7 +1081,8 @@ class ImprisonTag extends ArenaTrapTag {
|
||||||
* @returns `true`
|
* @returns `true`
|
||||||
*/
|
*/
|
||||||
override activateTrap(pokemon: Pokemon): boolean {
|
override activateTrap(pokemon: Pokemon): boolean {
|
||||||
if (this.source.isActive(true)) {
|
const source = this.getSourcePokemon(pokemon.scene);
|
||||||
|
if (source && source.isActive(true) && pokemon.isAllowedInBattle()) {
|
||||||
pokemon.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId);
|
pokemon.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1020,8 +1093,8 @@ class ImprisonTag extends ArenaTrapTag {
|
||||||
* @param arena
|
* @param arena
|
||||||
*/
|
*/
|
||||||
override onRemove({ scene }: Arena): void {
|
override onRemove({ scene }: Arena): void {
|
||||||
const party = this.retrieveField(scene);
|
const party = this.getAffectedPokemon(scene);
|
||||||
party?.forEach((p: PlayerPokemon | EnemyPokemon) => {
|
party?.forEach((p: Pokemon) => {
|
||||||
p.removeTag(BattlerTagType.IMPRISON);
|
p.removeTag(BattlerTagType.IMPRISON);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1054,7 +1127,7 @@ class FireGrassPledgeTag extends ArenaTag {
|
||||||
pokemon.scene.queueMessage(i18next.t("arenaTag:fireGrassPledgeLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
pokemon.scene.queueMessage(i18next.t("arenaTag:fireGrassPledgeLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||||
// TODO: Replace this with a proper animation
|
// TODO: Replace this with a proper animation
|
||||||
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.MAGMA_STORM));
|
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.MAGMA_STORM));
|
||||||
pokemon.damageAndUpdate(Utils.toDmgValue(pokemon.getMaxHp() / 8));
|
pokemon.damageAndUpdate(toDmgValue(pokemon.getMaxHp() / 8));
|
||||||
});
|
});
|
||||||
|
|
||||||
return super.lapse(arena);
|
return super.lapse(arena);
|
||||||
|
@ -1078,8 +1151,15 @@ class WaterFirePledgeTag extends ArenaTag {
|
||||||
arena.scene.queueMessage(i18next.t(`arenaTag:waterFirePledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`));
|
arena.scene.queueMessage(i18next.t(`arenaTag:waterFirePledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
override apply(arena: Arena, args: any[]): boolean {
|
/**
|
||||||
const moveChance = args[0] as Utils.NumberHolder;
|
* Doubles the chance for the given move's secondary effect(s) to trigger
|
||||||
|
* @param arena the {@linkcode Arena} containing this tag
|
||||||
|
* @param simulated n/a
|
||||||
|
* @param moveChance a {@linkcode NumberHolder} containing
|
||||||
|
* the move's current effect chance
|
||||||
|
* @returns `true` if the move's effect chance was doubled (currently always `true`)
|
||||||
|
*/
|
||||||
|
override apply(arena: Arena, simulated: boolean, moveChance: NumberHolder): boolean {
|
||||||
moveChance.value *= 2;
|
moveChance.value *= 2;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1102,7 +1182,8 @@ class GrassWaterPledgeTag extends ArenaTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves | undefined, sourceId: integer, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag | null {
|
// TODO: swap `sourceMove` and `sourceId` and make `sourceMove` an optional parameter
|
||||||
|
export function getArenaTag(tagType: ArenaTagType, turnCount: number, sourceMove: Moves | undefined, sourceId: number, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag | null {
|
||||||
switch (tagType) {
|
switch (tagType) {
|
||||||
case ArenaTagType.MIST:
|
case ArenaTagType.MIST:
|
||||||
return new MistTag(turnCount, sourceId, side);
|
return new MistTag(turnCount, sourceId, side);
|
||||||
|
@ -1163,3 +1244,16 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When given a battler tag or json representing one, creates an actual ArenaTag object with the same data.
|
||||||
|
* @param {ArenaTag | any} source An arena tag
|
||||||
|
* @return {ArenaTag} The valid arena tag
|
||||||
|
*/
|
||||||
|
export function loadArenaTag(source: ArenaTag | any): ArenaTag {
|
||||||
|
const tag = getArenaTag(source.tagType, source.turnCount, source.sourceMove, source.sourceId, source.targetIndex, source.side)
|
||||||
|
?? new NoneTag();
|
||||||
|
tag.loadTag(source);
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,12 @@ import { Species } from "#enums/species";
|
||||||
|
|
||||||
export const POKERUS_STARTER_COUNT = 5;
|
export const POKERUS_STARTER_COUNT = 5;
|
||||||
|
|
||||||
|
// #region Friendship constants
|
||||||
|
export const CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER = 2;
|
||||||
|
export const FRIENDSHIP_GAIN_FROM_BATTLE = 2;
|
||||||
|
export const FRIENDSHIP_GAIN_FROM_RARE_CANDY = 5;
|
||||||
|
export const FRIENDSHIP_LOSS_FROM_FAINT = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to get the cumulative friendship threshold at which a candy is earned
|
* Function to get the cumulative friendship threshold at which a candy is earned
|
||||||
* @param starterCost The cost of the starter, found in {@linkcode speciesStarterCosts}
|
* @param starterCost The cost of the starter, found in {@linkcode speciesStarterCosts}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
||||||
import { StatStageChangePhase, StatStageChangeCallback } from "#app/phases/stat-stage-change-phase";
|
import { StatStageChangePhase, StatStageChangeCallback } from "#app/phases/stat-stage-change-phase";
|
||||||
import { PokemonAnimType } from "#app/enums/pokemon-anim-type";
|
import { PokemonAnimType } from "#app/enums/pokemon-anim-type";
|
||||||
|
import BattleScene from "#app/battle-scene";
|
||||||
|
|
||||||
export enum BattlerTagLapseType {
|
export enum BattlerTagLapseType {
|
||||||
FAINT,
|
FAINT,
|
||||||
|
@ -90,6 +91,15 @@ export class BattlerTag {
|
||||||
this.sourceMove = source.sourceMove;
|
this.sourceMove = source.sourceMove;
|
||||||
this.sourceId = source.sourceId;
|
this.sourceId = source.sourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function that retrieves the source Pokemon object
|
||||||
|
* @param scene medium to retrieve the source Pokemon
|
||||||
|
* @returns The source {@linkcode Pokemon} or `null` if none is found
|
||||||
|
*/
|
||||||
|
public getSourcePokemon(scene: BattleScene): Pokemon | null {
|
||||||
|
return this.sourceId ? scene.getPokemonById(this.sourceId) : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WeatherBattlerTag {
|
export interface WeatherBattlerTag {
|
||||||
|
@ -120,7 +130,7 @@ export abstract class MoveRestrictionBattlerTag extends BattlerTag {
|
||||||
const phase = pokemon.scene.getCurrentPhase() as MovePhase;
|
const phase = pokemon.scene.getCurrentPhase() as MovePhase;
|
||||||
const move = phase.move;
|
const move = phase.move;
|
||||||
|
|
||||||
if (this.isMoveRestricted(move.moveId)) {
|
if (this.isMoveRestricted(move.moveId, pokemon)) {
|
||||||
if (this.interruptedText(pokemon, move.moveId)) {
|
if (this.interruptedText(pokemon, move.moveId)) {
|
||||||
pokemon.scene.queueMessage(this.interruptedText(pokemon, move.moveId));
|
pokemon.scene.queueMessage(this.interruptedText(pokemon, move.moveId));
|
||||||
}
|
}
|
||||||
|
@ -136,10 +146,11 @@ export abstract class MoveRestrictionBattlerTag extends BattlerTag {
|
||||||
/**
|
/**
|
||||||
* Gets whether this tag is restricting a move.
|
* Gets whether this tag is restricting a move.
|
||||||
*
|
*
|
||||||
* @param {Moves} move {@linkcode Moves} ID to check restriction for.
|
* @param move - {@linkcode Moves} ID to check restriction for.
|
||||||
* @returns {boolean} `true` if the move is restricted by this tag, otherwise `false`.
|
* @param user - The {@linkcode Pokemon} involved
|
||||||
|
* @returns `true` if the move is restricted by this tag, otherwise `false`.
|
||||||
*/
|
*/
|
||||||
abstract isMoveRestricted(move: Moves): boolean;
|
public abstract isMoveRestricted(move: Moves, user?: Pokemon): boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this tag is restricting a move based on a user's decisions during the target selection phase
|
* Checks if this tag is restricting a move based on a user's decisions during the target selection phase
|
||||||
|
@ -327,6 +338,16 @@ export class GorillaTacticsTag extends MoveRestrictionBattlerTag {
|
||||||
pokemon.setStat(Stat.ATK, pokemon.getStat(Stat.ATK, false) * 1.5, false);
|
pokemon.setStat(Stat.ATK, pokemon.getStat(Stat.ATK, false) * 1.5, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the Gorilla Tactics Battler Tag along with its unique class variable moveId
|
||||||
|
* @override
|
||||||
|
* @param source Gorilla Tactics' {@linkcode BattlerTag} information
|
||||||
|
*/
|
||||||
|
public override loadTag(source: BattlerTag | any): void {
|
||||||
|
super.loadTag(source);
|
||||||
|
this.moveId = source.moveId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
|
@ -1713,7 +1734,12 @@ export class TypeImmuneTag extends BattlerTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MagnetRisenTag extends TypeImmuneTag {
|
/**
|
||||||
|
* Battler Tag that lifts the affected Pokemon into the air and provides immunity to Ground type moves.
|
||||||
|
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Magnet_Rise_(move) | Moves.MAGNET_RISE}
|
||||||
|
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Telekinesis_(move) | Moves.TELEKINESIS}
|
||||||
|
*/
|
||||||
|
export class FloatingTag extends TypeImmuneTag {
|
||||||
constructor(tagType: BattlerTagType, sourceMove: Moves) {
|
constructor(tagType: BattlerTagType, sourceMove: Moves) {
|
||||||
super(tagType, sourceMove, Type.GROUND, 5);
|
super(tagType, sourceMove, Type.GROUND, 5);
|
||||||
}
|
}
|
||||||
|
@ -1721,15 +1747,19 @@ export class MagnetRisenTag extends TypeImmuneTag {
|
||||||
onAdd(pokemon: Pokemon): void {
|
onAdd(pokemon: Pokemon): void {
|
||||||
super.onAdd(pokemon);
|
super.onAdd(pokemon);
|
||||||
|
|
||||||
|
if (this.sourceMove === Moves.MAGNET_RISE) {
|
||||||
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
onRemove(pokemon: Pokemon): void {
|
onRemove(pokemon: Pokemon): void {
|
||||||
super.onRemove(pokemon);
|
super.onRemove(pokemon);
|
||||||
|
if (this.sourceMove === Moves.MAGNET_RISE) {
|
||||||
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnRemove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnRemove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class TypeBoostTag extends BattlerTag {
|
export class TypeBoostTag extends BattlerTag {
|
||||||
public boostedType: Type;
|
public boostedType: Type;
|
||||||
|
@ -2501,8 +2531,6 @@ export class MysteryEncounterPostSummonTag extends BattlerTag {
|
||||||
* Torment does not interrupt the move if the move is performed consecutively in the same turn and right after Torment is applied
|
* Torment does not interrupt the move if the move is performed consecutively in the same turn and right after Torment is applied
|
||||||
*/
|
*/
|
||||||
export class TormentTag extends MoveRestrictionBattlerTag {
|
export class TormentTag extends MoveRestrictionBattlerTag {
|
||||||
private target: Pokemon;
|
|
||||||
|
|
||||||
constructor(sourceId: number) {
|
constructor(sourceId: number) {
|
||||||
super(BattlerTagType.TORMENT, BattlerTagLapseType.AFTER_MOVE, 1, Moves.TORMENT, sourceId);
|
super(BattlerTagType.TORMENT, BattlerTagLapseType.AFTER_MOVE, 1, Moves.TORMENT, sourceId);
|
||||||
}
|
}
|
||||||
|
@ -2514,7 +2542,6 @@ export class TormentTag extends MoveRestrictionBattlerTag {
|
||||||
*/
|
*/
|
||||||
override onAdd(pokemon: Pokemon) {
|
override onAdd(pokemon: Pokemon) {
|
||||||
super.onAdd(pokemon);
|
super.onAdd(pokemon);
|
||||||
this.target = pokemon;
|
|
||||||
pokemon.scene.queueMessage(i18next.t("battlerTags:tormentOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), 1500);
|
pokemon.scene.queueMessage(i18next.t("battlerTags:tormentOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), 1500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2533,15 +2560,18 @@ export class TormentTag extends MoveRestrictionBattlerTag {
|
||||||
* @param {Moves} move the move under investigation
|
* @param {Moves} move the move under investigation
|
||||||
* @returns `true` if there is valid consecutive usage | `false` if the moves are different from each other
|
* @returns `true` if there is valid consecutive usage | `false` if the moves are different from each other
|
||||||
*/
|
*/
|
||||||
override isMoveRestricted(move: Moves): boolean {
|
public override isMoveRestricted(move: Moves, user: Pokemon): boolean {
|
||||||
const lastMove = this.target.getLastXMoves(1)[0];
|
if (!user) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const lastMove = user.getLastXMoves(1)[0];
|
||||||
if ( !lastMove ) {
|
if ( !lastMove ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// This checks for locking / momentum moves like Rollout and Hydro Cannon + if the user is under the influence of BattlerTagType.FRENZY
|
// This checks for locking / momentum moves like Rollout and Hydro Cannon + if the user is under the influence of BattlerTagType.FRENZY
|
||||||
// Because Uproar's unique behavior is not implemented, it does not check for Uproar. Torment has been marked as partial in moves.ts
|
// Because Uproar's unique behavior is not implemented, it does not check for Uproar. Torment has been marked as partial in moves.ts
|
||||||
const moveObj = allMoves[lastMove.move];
|
const moveObj = allMoves[lastMove.move];
|
||||||
const isUnaffected = moveObj.hasAttr(ConsecutiveUseDoublePowerAttr) || this.target.getTag(BattlerTagType.FRENZY) || moveObj.hasAttr(ChargeAttr);
|
const isUnaffected = moveObj.hasAttr(ConsecutiveUseDoublePowerAttr) || user.getTag(BattlerTagType.FRENZY) || moveObj.hasAttr(ChargeAttr);
|
||||||
const validLastMoveResult = (lastMove.result === MoveResult.SUCCESS) || (lastMove.result === MoveResult.MISS);
|
const validLastMoveResult = (lastMove.result === MoveResult.SUCCESS) || (lastMove.result === MoveResult.MISS);
|
||||||
if (lastMove.move === move && validLastMoveResult && lastMove.move !== Moves.STRUGGLE && !isUnaffected) {
|
if (lastMove.move === move && validLastMoveResult && lastMove.move !== Moves.STRUGGLE && !isUnaffected) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -2593,37 +2623,39 @@ export class TauntTag extends MoveRestrictionBattlerTag {
|
||||||
* The tag is only removed when the source-user is removed from the field.
|
* The tag is only removed when the source-user is removed from the field.
|
||||||
*/
|
*/
|
||||||
export class ImprisonTag extends MoveRestrictionBattlerTag {
|
export class ImprisonTag extends MoveRestrictionBattlerTag {
|
||||||
private source: Pokemon | null;
|
|
||||||
|
|
||||||
constructor(sourceId: number) {
|
constructor(sourceId: number) {
|
||||||
super(BattlerTagType.IMPRISON, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE ], 1, Moves.IMPRISON, sourceId);
|
super(BattlerTagType.IMPRISON, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE ], 1, Moves.IMPRISON, sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
override onAdd(pokemon: Pokemon) {
|
|
||||||
if (this.sourceId) {
|
|
||||||
this.source = pokemon.scene.getPokemonById(this.sourceId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the source of Imprison is still active
|
* Checks if the source of Imprison is still active
|
||||||
* @param _pokemon
|
* @override
|
||||||
* @param _lapseType
|
* @param pokemon The pokemon this tag is attached to
|
||||||
* @returns `true` if the source is still active
|
* @returns `true` if the source is still active
|
||||||
*/
|
*/
|
||||||
override lapse(_pokemon: Pokemon, _lapseType: BattlerTagLapseType): boolean {
|
public override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||||
return this.source?.isActive(true) ?? false;
|
const source = this.getSourcePokemon(pokemon.scene);
|
||||||
|
if (source) {
|
||||||
|
if (lapseType === BattlerTagLapseType.PRE_MOVE) {
|
||||||
|
return super.lapse(pokemon, lapseType) && source.isActive(true);
|
||||||
|
} else {
|
||||||
|
return source.isActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the source of the tag has the parameter move in its moveset and that the source is still active
|
* Checks if the source of the tag has the parameter move in its moveset and that the source is still active
|
||||||
|
* @override
|
||||||
* @param {Moves} move the move under investigation
|
* @param {Moves} move the move under investigation
|
||||||
* @returns `false` if either condition is not met
|
* @returns `false` if either condition is not met
|
||||||
*/
|
*/
|
||||||
override isMoveRestricted(move: Moves): boolean {
|
public override isMoveRestricted(move: Moves, user: Pokemon): boolean {
|
||||||
if (this.source) {
|
const source = this.getSourcePokemon(user.scene);
|
||||||
const sourceMoveset = this.source.getMoveset().map(m => m!.moveId);
|
if (source) {
|
||||||
return sourceMoveset?.includes(move) && this.source.isActive(true);
|
const sourceMoveset = source.getMoveset().map(m => m!.moveId);
|
||||||
|
return sourceMoveset?.includes(move) && source.isActive(true);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2676,6 +2708,60 @@ export class SyrupBombTag extends BattlerTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Telekinesis raises the target into the air for three turns and causes all moves used against the target (aside from OHKO moves) to hit the target unless the target is in a semi-invulnerable state from Fly/Dig.
|
||||||
|
* The first effect is provided by {@linkcode FloatingTag}, the accuracy-bypass effect is provided by TelekinesisTag
|
||||||
|
* The effects of Telekinesis can be baton passed to a teammate. Unlike the mainline games, Telekinesis can be baton-passed to Mega Gengar.
|
||||||
|
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Telekinesis_(move) | Moves.TELEKINESIS}
|
||||||
|
*/
|
||||||
|
export class TelekinesisTag extends BattlerTag {
|
||||||
|
constructor(sourceMove: Moves) {
|
||||||
|
super(BattlerTagType.TELEKINESIS, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE ], 3, sourceMove, undefined, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
override onAdd(pokemon: Pokemon) {
|
||||||
|
pokemon.scene.queueMessage(i18next.t("battlerTags:telekinesisOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tag that swaps the user's base ATK stat with its base DEF stat.
|
||||||
|
* @extends BattlerTag
|
||||||
|
*/
|
||||||
|
export class PowerTrickTag extends BattlerTag {
|
||||||
|
constructor(sourceMove: Moves, sourceId: number) {
|
||||||
|
super(BattlerTagType.POWER_TRICK, BattlerTagLapseType.CUSTOM, 0, sourceMove, sourceId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
onAdd(pokemon: Pokemon): void {
|
||||||
|
this.swapStat(pokemon);
|
||||||
|
pokemon.scene.queueMessage(i18next.t("battlerTags:powerTrickActive", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemove(pokemon: Pokemon): void {
|
||||||
|
this.swapStat(pokemon);
|
||||||
|
pokemon.scene.queueMessage(i18next.t("battlerTags:powerTrickActive", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the Power Trick tag and reverts any stat changes if the tag is already applied.
|
||||||
|
* @param {Pokemon} pokemon The {@linkcode Pokemon} that already has the Power Trick tag.
|
||||||
|
*/
|
||||||
|
onOverlap(pokemon: Pokemon): void {
|
||||||
|
pokemon.removeTag(this.tagType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swaps the user's base ATK stat with its base DEF stat.
|
||||||
|
* @param {Pokemon} pokemon The {@linkcode Pokemon} whose stats will be swapped.
|
||||||
|
*/
|
||||||
|
swapStat(pokemon: Pokemon): void {
|
||||||
|
const temp = pokemon.getStat(Stat.ATK, false);
|
||||||
|
pokemon.setStat(Stat.ATK, pokemon.getStat(Stat.DEF, false), false);
|
||||||
|
pokemon.setStat(Stat.DEF, temp, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a {@linkcode BattlerTag} based on the provided tag type, turn count, source move, and source ID.
|
* Retrieves a {@linkcode BattlerTag} based on the provided tag type, turn count, source move, and source ID.
|
||||||
* @param sourceId - The ID of the pokemon adding the tag
|
* @param sourceId - The ID of the pokemon adding the tag
|
||||||
|
@ -2802,8 +2888,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||||
return new CursedTag(sourceId);
|
return new CursedTag(sourceId);
|
||||||
case BattlerTagType.CHARGED:
|
case BattlerTagType.CHARGED:
|
||||||
return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true);
|
return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true);
|
||||||
case BattlerTagType.MAGNET_RISEN:
|
case BattlerTagType.FLOATING:
|
||||||
return new MagnetRisenTag(tagType, sourceMove);
|
return new FloatingTag(tagType, sourceMove);
|
||||||
case BattlerTagType.MINIMIZED:
|
case BattlerTagType.MINIMIZED:
|
||||||
return new MinimizeTag();
|
return new MinimizeTag();
|
||||||
case BattlerTagType.DESTINY_BOND:
|
case BattlerTagType.DESTINY_BOND:
|
||||||
|
@ -2849,6 +2935,10 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||||
return new ImprisonTag(sourceId);
|
return new ImprisonTag(sourceId);
|
||||||
case BattlerTagType.SYRUP_BOMB:
|
case BattlerTagType.SYRUP_BOMB:
|
||||||
return new SyrupBombTag(sourceId);
|
return new SyrupBombTag(sourceId);
|
||||||
|
case BattlerTagType.TELEKINESIS:
|
||||||
|
return new TelekinesisTag(sourceMove);
|
||||||
|
case BattlerTagType.POWER_TRICK:
|
||||||
|
return new PowerTrickTag(sourceMove, sourceId);
|
||||||
case BattlerTagType.NONE:
|
case BattlerTagType.NONE:
|
||||||
default:
|
default:
|
||||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
import { Abilities } from "#enums/abilities";
|
import { Abilities } from "#enums/abilities";
|
||||||
import { Type } from "#app/data/type";
|
import { Type } from "#app/data/type";
|
||||||
import { isNullOrUndefined } from "#app/utils";
|
import { isNullOrUndefined } from "#app/utils";
|
||||||
|
import { Nature } from "#enums/nature";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data that can customize a Pokemon in non-standard ways from its Species
|
* Data that can customize a Pokemon in non-standard ways from its Species
|
||||||
* Currently only used by Mystery Encounters, may need to be renamed if it becomes more widely used
|
* Currently only used by Mystery Encounters and Mints.
|
||||||
*/
|
*/
|
||||||
export class MysteryEncounterPokemonData {
|
export class CustomPokemonData {
|
||||||
public spriteScale: number;
|
public spriteScale: number;
|
||||||
public ability: Abilities | -1;
|
public ability: Abilities | -1;
|
||||||
public passive: Abilities | -1;
|
public passive: Abilities | -1;
|
||||||
|
public nature: Nature | -1;
|
||||||
public types: Type[];
|
public types: Type[];
|
||||||
|
|
||||||
constructor(data?: MysteryEncounterPokemonData | Partial<MysteryEncounterPokemonData>) {
|
constructor(data?: CustomPokemonData | Partial<CustomPokemonData>) {
|
||||||
if (!isNullOrUndefined(data)) {
|
if (!isNullOrUndefined(data)) {
|
||||||
Object.assign(this, data);
|
Object.assign(this, data);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +22,7 @@ export class MysteryEncounterPokemonData {
|
||||||
this.spriteScale = this.spriteScale ?? -1;
|
this.spriteScale = this.spriteScale ?? -1;
|
||||||
this.ability = this.ability ?? -1;
|
this.ability = this.ability ?? -1;
|
||||||
this.passive = this.passive ?? -1;
|
this.passive = this.passive ?? -1;
|
||||||
|
this.nature = this.nature ?? -1;
|
||||||
this.types = this.types ?? [];
|
this.types = this.types ?? [];
|
||||||
}
|
}
|
||||||
}
|
}
|
313
src/data/move.ts
|
@ -365,6 +365,14 @@ export default class Move implements Localizable {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dev flag for documenting edge cases. When using this, please document the known edge case.
|
||||||
|
* @returns the called object {@linkcode Move}
|
||||||
|
*/
|
||||||
|
edgeCase(): this {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the move as "partial": appends texts to the move name
|
* Marks the move as "partial": appends texts to the move name
|
||||||
* @returns the called object {@linkcode Move}
|
* @returns the called object {@linkcode Move}
|
||||||
|
@ -800,7 +808,7 @@ export default class Move implements Localizable {
|
||||||
source.scene.applyModifiers(PokemonMultiHitModifier, source.isPlayer(), source, new Utils.IntegerHolder(0), power);
|
source.scene.applyModifiers(PokemonMultiHitModifier, source.isPlayer(), source, new Utils.IntegerHolder(0), power);
|
||||||
|
|
||||||
if (!this.hasAttr(TypelessAttr)) {
|
if (!this.hasAttr(TypelessAttr)) {
|
||||||
source.scene.arena.applyTags(WeakenMoveTypeTag, this.type, power);
|
source.scene.arena.applyTags(WeakenMoveTypeTag, simulated, this.type, power);
|
||||||
source.scene.applyModifiers(AttackTypeBoosterModifier, source.isPlayer(), source, this.type, power);
|
source.scene.applyModifiers(AttackTypeBoosterModifier, source.isPlayer(), source, this.type, power);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1016,9 +1024,9 @@ export class MoveEffectAttr extends MoveAttr {
|
||||||
|
|
||||||
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, false, moveChance, move, target, selfEffect, showAbility);
|
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, false, moveChance, move, target, selfEffect, showAbility);
|
||||||
|
|
||||||
if (!move.hasAttr(FlinchAttr) || moveChance.value <= move.chance) {
|
if ((!move.hasAttr(FlinchAttr) || moveChance.value <= move.chance) && !move.hasAttr(SecretPowerAttr)) {
|
||||||
const userSide = user.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
|
const userSide = user.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
|
||||||
user.scene.arena.applyTagsForSide(ArenaTagType.WATER_FIRE_PLEDGE, userSide, moveChance);
|
user.scene.arena.applyTagsForSide(ArenaTagType.WATER_FIRE_PLEDGE, userSide, false, moveChance);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selfEffect) {
|
if (!selfEffect) {
|
||||||
|
@ -2867,6 +2875,162 @@ export class StatStageChangeAttr extends MoveEffectAttr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute used to determine the Biome/Terrain-based secondary effect of Secret Power
|
||||||
|
*/
|
||||||
|
export class SecretPowerAttr extends MoveEffectAttr {
|
||||||
|
constructor() {
|
||||||
|
super(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to determine if the move should apply a secondary effect based on Secret Power's 30% chance
|
||||||
|
* @returns `true` if the move's secondary effect should apply
|
||||||
|
*/
|
||||||
|
override canApply(user: Pokemon, target: Pokemon, move: Move, args?: any[]): boolean {
|
||||||
|
this.effectChanceOverride = move.chance;
|
||||||
|
const moveChance = this.getMoveChance(user, target, move, this.selfTarget);
|
||||||
|
if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to apply the secondary effect to the target Pokemon
|
||||||
|
* @returns `true` if a secondary effect is successfully applied
|
||||||
|
*/
|
||||||
|
override apply(user: Pokemon, target: Pokemon, move: Move, args?: any[]): boolean | Promise<boolean> {
|
||||||
|
if (!super.apply(user, target, move, args)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let secondaryEffect: MoveEffectAttr;
|
||||||
|
const terrain = user.scene.arena.getTerrainType();
|
||||||
|
if (terrain !== TerrainType.NONE) {
|
||||||
|
secondaryEffect = this.determineTerrainEffect(terrain);
|
||||||
|
} else {
|
||||||
|
const biome = user.scene.arena.biomeType;
|
||||||
|
secondaryEffect = this.determineBiomeEffect(biome);
|
||||||
|
}
|
||||||
|
// effectChanceOverride used in the application of the actual secondary effect
|
||||||
|
secondaryEffect.effectChanceOverride = 100;
|
||||||
|
return secondaryEffect.apply(user, target, move, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the secondary effect based on terrain.
|
||||||
|
* Takes precedence over biome-based effects.
|
||||||
|
* ```
|
||||||
|
* Electric Terrain | Paralysis
|
||||||
|
* Misty Terrain | SpAtk -1
|
||||||
|
* Grassy Terrain | Sleep
|
||||||
|
* Psychic Terrain | Speed -1
|
||||||
|
* ```
|
||||||
|
* @param terrain - {@linkcode TerrainType} The current terrain
|
||||||
|
* @returns the chosen secondary effect {@linkcode MoveEffectAttr}
|
||||||
|
*/
|
||||||
|
private determineTerrainEffect(terrain: TerrainType): MoveEffectAttr {
|
||||||
|
let secondaryEffect: MoveEffectAttr;
|
||||||
|
switch (terrain) {
|
||||||
|
case TerrainType.ELECTRIC:
|
||||||
|
default:
|
||||||
|
secondaryEffect = new StatusEffectAttr(StatusEffect.PARALYSIS, false);
|
||||||
|
break;
|
||||||
|
case TerrainType.MISTY:
|
||||||
|
secondaryEffect = new StatStageChangeAttr([ Stat.SPATK ], -1, false);
|
||||||
|
break;
|
||||||
|
case TerrainType.GRASSY:
|
||||||
|
secondaryEffect = new StatusEffectAttr(StatusEffect.SLEEP, false);
|
||||||
|
break;
|
||||||
|
case TerrainType.PSYCHIC:
|
||||||
|
secondaryEffect = new StatStageChangeAttr([ Stat.SPD ], -1, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return secondaryEffect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the secondary effect based on biome
|
||||||
|
* ```
|
||||||
|
* Town, Metropolis, Slum, Dojo, Laboratory, Power Plant + Default | Paralysis
|
||||||
|
* Plains, Grass, Tall Grass, Forest, Jungle, Meadow | Sleep
|
||||||
|
* Swamp, Mountain, Temple, Ruins | Speed -1
|
||||||
|
* Ice Cave, Snowy Forest | Freeze
|
||||||
|
* Volcano | Burn
|
||||||
|
* Fairy Cave | SpAtk -1
|
||||||
|
* Desert, Construction Site, Beach, Island, Badlands | Accuracy -1
|
||||||
|
* Sea, Lake, Seabed | Atk -1
|
||||||
|
* Cave, Wasteland, Graveyard, Abyss, Space | Flinch
|
||||||
|
* End | Def -1
|
||||||
|
* ```
|
||||||
|
* @param biome - The current {@linkcode Biome} the battle is set in
|
||||||
|
* @returns the chosen secondary effect {@linkcode MoveEffectAttr}
|
||||||
|
*/
|
||||||
|
private determineBiomeEffect(biome: Biome): MoveEffectAttr {
|
||||||
|
let secondaryEffect: MoveEffectAttr;
|
||||||
|
switch (biome) {
|
||||||
|
case Biome.PLAINS:
|
||||||
|
case Biome.GRASS:
|
||||||
|
case Biome.TALL_GRASS:
|
||||||
|
case Biome.FOREST:
|
||||||
|
case Biome.JUNGLE:
|
||||||
|
case Biome.MEADOW:
|
||||||
|
secondaryEffect = new StatusEffectAttr(StatusEffect.SLEEP, false);
|
||||||
|
break;
|
||||||
|
case Biome.SWAMP:
|
||||||
|
case Biome.MOUNTAIN:
|
||||||
|
case Biome.TEMPLE:
|
||||||
|
case Biome.RUINS:
|
||||||
|
secondaryEffect = new StatStageChangeAttr([ Stat.SPD ], -1, false);
|
||||||
|
break;
|
||||||
|
case Biome.ICE_CAVE:
|
||||||
|
case Biome.SNOWY_FOREST:
|
||||||
|
secondaryEffect = new StatusEffectAttr(StatusEffect.FREEZE, false);
|
||||||
|
break;
|
||||||
|
case Biome.VOLCANO:
|
||||||
|
secondaryEffect = new StatusEffectAttr(StatusEffect.BURN, false);
|
||||||
|
break;
|
||||||
|
case Biome.FAIRY_CAVE:
|
||||||
|
secondaryEffect = new StatStageChangeAttr([ Stat.SPATK ], -1, false);
|
||||||
|
break;
|
||||||
|
case Biome.DESERT:
|
||||||
|
case Biome.CONSTRUCTION_SITE:
|
||||||
|
case Biome.BEACH:
|
||||||
|
case Biome.ISLAND:
|
||||||
|
case Biome.BADLANDS:
|
||||||
|
secondaryEffect = new StatStageChangeAttr([ Stat.ACC ], -1, false);
|
||||||
|
break;
|
||||||
|
case Biome.SEA:
|
||||||
|
case Biome.LAKE:
|
||||||
|
case Biome.SEABED:
|
||||||
|
secondaryEffect = new StatStageChangeAttr([ Stat.ATK ], -1, false);
|
||||||
|
break;
|
||||||
|
case Biome.CAVE:
|
||||||
|
case Biome.WASTELAND:
|
||||||
|
case Biome.GRAVEYARD:
|
||||||
|
case Biome.ABYSS:
|
||||||
|
case Biome.SPACE:
|
||||||
|
secondaryEffect = new AddBattlerTagAttr(BattlerTagType.FLINCHED, false, true);
|
||||||
|
break;
|
||||||
|
case Biome.END:
|
||||||
|
secondaryEffect = new StatStageChangeAttr([ Stat.DEF ], -1, false);
|
||||||
|
break;
|
||||||
|
case Biome.TOWN:
|
||||||
|
case Biome.METROPOLIS:
|
||||||
|
case Biome.SLUM:
|
||||||
|
case Biome.DOJO:
|
||||||
|
case Biome.FACTORY:
|
||||||
|
case Biome.LABORATORY:
|
||||||
|
case Biome.POWER_PLANT:
|
||||||
|
default:
|
||||||
|
secondaryEffect = new StatusEffectAttr(StatusEffect.PARALYSIS, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return secondaryEffect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class PostVictoryStatStageChangeAttr extends MoveAttr {
|
export class PostVictoryStatStageChangeAttr extends MoveAttr {
|
||||||
private stats: BattleStat[];
|
private stats: BattleStat[];
|
||||||
private stages: number;
|
private stages: number;
|
||||||
|
@ -3826,8 +3990,8 @@ export class LastMoveDoublePowerAttr extends VariablePowerAttr {
|
||||||
|
|
||||||
for (const p of pokemonActed) {
|
for (const p of pokemonActed) {
|
||||||
const [ lastMove ] = p.getLastXMoves(1);
|
const [ lastMove ] = p.getLastXMoves(1);
|
||||||
if (lastMove.result !== MoveResult.FAIL) {
|
if (lastMove?.result !== MoveResult.FAIL) {
|
||||||
if ((lastMove.result === MoveResult.SUCCESS) && (lastMove.move === this.move)) {
|
if ((lastMove?.result === MoveResult.SUCCESS) && (lastMove?.move === this.move)) {
|
||||||
power.value *= 2;
|
power.value *= 2;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -4556,19 +4720,20 @@ export class WaterSuperEffectTypeMultiplierAttr extends VariableMoveTypeMultipli
|
||||||
export class IceNoEffectTypeAttr extends VariableMoveTypeMultiplierAttr {
|
export class IceNoEffectTypeAttr extends VariableMoveTypeMultiplierAttr {
|
||||||
/**
|
/**
|
||||||
* Checks to see if the Target is Ice-Type or not. If so, the move will have no effect.
|
* Checks to see if the Target is Ice-Type or not. If so, the move will have no effect.
|
||||||
* @param {Pokemon} user N/A
|
* @param user n/a
|
||||||
* @param {Pokemon} target Pokemon that is being checked whether Ice-Type or not.
|
* @param target The {@linkcode Pokemon} targeted by the move
|
||||||
* @param {Move} move N/A
|
* @param move n/a
|
||||||
* @param {any[]} args Sets to false if the target is Ice-Type, so it should do no damage/no effect.
|
* @param args `[0]` a {@linkcode Utils.NumberHolder | NumberHolder} containing a type effectiveness multiplier
|
||||||
* @returns {boolean} Returns true if move is successful, false if Ice-Type.
|
* @returns `true` if this Ice-type immunity applies; `false` otherwise
|
||||||
*/
|
*/
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
const multiplier = args[0] as Utils.NumberHolder;
|
||||||
if (target.isOfType(Type.ICE)) {
|
if (target.isOfType(Type.ICE)) {
|
||||||
(args[0] as Utils.BooleanHolder).value = false;
|
multiplier.value = 0;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FlyingTypeMultiplierAttr extends VariableMoveTypeMultiplierAttr {
|
export class FlyingTypeMultiplierAttr extends VariableMoveTypeMultiplierAttr {
|
||||||
|
@ -4727,7 +4892,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
|
||||||
}
|
}
|
||||||
|
|
||||||
canApply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
canApply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
if (!super.canApply(user, target, move, args) || (this.cancelOnFail === true && user.getLastXMoves(1)[0].result === MoveResult.FAIL)) {
|
if (!super.canApply(user, target, move, args) || (this.cancelOnFail === true && user.getLastXMoves(1)[0]?.result === MoveResult.FAIL)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
@ -5165,7 +5330,7 @@ export class AddArenaTagAttr extends MoveEffectAttr {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) && user.getLastXMoves(1)[0].result === MoveResult.SUCCESS) {
|
if ((move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) {
|
||||||
user.scene.arena.addTag(this.tagType, this.turnCount, move.id, user.id, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY);
|
user.scene.arena.addTag(this.tagType, this.turnCount, move.id, user.id, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -5240,7 +5405,7 @@ export class AddArenaTrapTagHitAttr extends AddArenaTagAttr {
|
||||||
const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true);
|
const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true);
|
||||||
const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
|
const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
|
||||||
const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag;
|
const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag;
|
||||||
if ((moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) && user.getLastXMoves(1)[0].result === MoveResult.SUCCESS) {
|
if ((moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) {
|
||||||
user.scene.arena.addTag(this.tagType, 0, move.id, user.id, side);
|
user.scene.arena.addTag(this.tagType, 0, move.id, user.id, side);
|
||||||
if (!tag) {
|
if (!tag) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -5377,7 +5542,7 @@ export class AddPledgeEffectAttr extends AddArenaTagAttr {
|
||||||
|
|
||||||
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
// TODO: add support for `HIT` effect triggering in AddArenaTagAttr to remove the need for this check
|
// TODO: add support for `HIT` effect triggering in AddArenaTagAttr to remove the need for this check
|
||||||
if (user.getLastXMoves(1)[0].result !== MoveResult.SUCCESS) {
|
if (user.getLastXMoves(1)[0]?.result !== MoveResult.SUCCESS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5475,37 +5640,38 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
||||||
*/
|
*/
|
||||||
const switchOutTarget = this.selfSwitch ? user : target;
|
const switchOutTarget = this.selfSwitch ? user : target;
|
||||||
if (switchOutTarget instanceof PlayerPokemon) {
|
if (switchOutTarget instanceof PlayerPokemon) {
|
||||||
|
// Switch out logic for the player's Pokemon
|
||||||
if (switchOutTarget.scene.getParty().filter((p) => p.isAllowedInBattle() && !p.isOnField()).length < 1) {
|
if (switchOutTarget.scene.getParty().filter((p) => p.isAllowedInBattle() && !p.isOnField()).length < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH);
|
|
||||||
|
|
||||||
if (switchOutTarget.hp > 0) {
|
if (switchOutTarget.hp > 0) {
|
||||||
|
switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH);
|
||||||
user.scene.prependToPhase(new SwitchPhase(user.scene, this.switchType, switchOutTarget.getFieldIndex(), true, true), MoveEndPhase);
|
user.scene.prependToPhase(new SwitchPhase(user.scene, this.switchType, switchOutTarget.getFieldIndex(), true, true), MoveEndPhase);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else if (user.scene.currentBattle.battleType !== BattleType.WILD) {
|
} else if (user.scene.currentBattle.battleType !== BattleType.WILD) {
|
||||||
|
// Switch out logic for trainer battles
|
||||||
if (switchOutTarget.scene.getEnemyParty().filter((p) => p.isAllowedInBattle() && !p.isOnField()).length < 1) {
|
if (switchOutTarget.scene.getEnemyParty().filter((p) => p.isAllowedInBattle() && !p.isOnField()).length < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Switch out logic for trainer battles
|
|
||||||
switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH);
|
|
||||||
|
|
||||||
if (switchOutTarget.hp > 0) {
|
if (switchOutTarget.hp > 0) {
|
||||||
// for opponent switching out
|
// for opponent switching out
|
||||||
|
switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH);
|
||||||
user.scene.prependToPhase(new SwitchSummonPhase(user.scene, this.switchType, switchOutTarget.getFieldIndex(),
|
user.scene.prependToPhase(new SwitchSummonPhase(user.scene, this.switchType, switchOutTarget.getFieldIndex(),
|
||||||
(user.scene.currentBattle.trainer ? user.scene.currentBattle.trainer.getNextSummonIndex((switchOutTarget as EnemyPokemon).trainerSlot) : 0),
|
(user.scene.currentBattle.trainer ? user.scene.currentBattle.trainer.getNextSummonIndex((switchOutTarget as EnemyPokemon).trainerSlot) : 0),
|
||||||
false, false), MoveEndPhase);
|
false, false), MoveEndPhase);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Switch out logic for everything else (eg: WILD battles)
|
||||||
if (user.scene.currentBattle.waveIndex % 10 === 0) {
|
if (user.scene.currentBattle.waveIndex % 10 === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Switch out logic for everything else (eg: WILD battles)
|
|
||||||
switchOutTarget.leaveField(false);
|
|
||||||
|
|
||||||
if (switchOutTarget.hp) {
|
if (switchOutTarget.hp > 0) {
|
||||||
|
switchOutTarget.leaveField(false);
|
||||||
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
|
||||||
|
@ -6420,6 +6586,9 @@ export class TransformAttr extends MoveEffectAttr {
|
||||||
user.summonData.gender = target.getGender();
|
user.summonData.gender = target.getGender();
|
||||||
user.summonData.fusionGender = target.getFusionGender();
|
user.summonData.fusionGender = target.getFusionGender();
|
||||||
|
|
||||||
|
// Power Trick's effect will not preserved after using Transform
|
||||||
|
user.removeTag(BattlerTagType.POWER_TRICK);
|
||||||
|
|
||||||
// Copy all stats (except HP)
|
// Copy all stats (except HP)
|
||||||
for (const s of EFFECTIVE_STATS) {
|
for (const s of EFFECTIVE_STATS) {
|
||||||
user.setStat(s, target.getStat(s, false), false);
|
user.setStat(s, target.getStat(s, false), false);
|
||||||
|
@ -7083,7 +7252,8 @@ export function initMoves() {
|
||||||
.attr(ForceSwitchOutAttr)
|
.attr(ForceSwitchOutAttr)
|
||||||
.ignoresSubstitute()
|
.ignoresSubstitute()
|
||||||
.hidesTarget()
|
.hidesTarget()
|
||||||
.windMove(),
|
.windMove()
|
||||||
|
.partial(), // Should force random switches
|
||||||
new AttackMove(Moves.FLY, Type.FLYING, MoveCategory.PHYSICAL, 90, 95, 15, -1, 0, 1)
|
new AttackMove(Moves.FLY, Type.FLYING, MoveCategory.PHYSICAL, 90, 95, 15, -1, 0, 1)
|
||||||
.attr(ChargeAttr, ChargeAnim.FLY_CHARGING, i18next.t("moveTriggers:flewUpHigh", { pokemonName: "{USER}" }), BattlerTagType.FLYING)
|
.attr(ChargeAttr, ChargeAnim.FLY_CHARGING, i18next.t("moveTriggers:flewUpHigh", { pokemonName: "{USER}" }), BattlerTagType.FLYING)
|
||||||
.condition(failOnGravityCondition)
|
.condition(failOnGravityCondition)
|
||||||
|
@ -7160,7 +7330,8 @@ export function initMoves() {
|
||||||
new StatusMove(Moves.ROAR, Type.NORMAL, -1, 20, -1, -6, 1)
|
new StatusMove(Moves.ROAR, Type.NORMAL, -1, 20, -1, -6, 1)
|
||||||
.attr(ForceSwitchOutAttr)
|
.attr(ForceSwitchOutAttr)
|
||||||
.soundBased()
|
.soundBased()
|
||||||
.hidesTarget(),
|
.hidesTarget()
|
||||||
|
.partial(), // Should force random switching
|
||||||
new StatusMove(Moves.SING, Type.NORMAL, 55, 15, -1, 0, 1)
|
new StatusMove(Moves.SING, Type.NORMAL, 55, 15, -1, 0, 1)
|
||||||
.attr(StatusEffectAttr, StatusEffect.SLEEP)
|
.attr(StatusEffectAttr, StatusEffect.SLEEP)
|
||||||
.soundBased(),
|
.soundBased(),
|
||||||
|
@ -7301,7 +7472,7 @@ export function initMoves() {
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPD ], 2, true),
|
.attr(StatStageChangeAttr, [ Stat.SPD ], 2, true),
|
||||||
new AttackMove(Moves.QUICK_ATTACK, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 30, -1, 1, 1),
|
new AttackMove(Moves.QUICK_ATTACK, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 30, -1, 1, 1),
|
||||||
new AttackMove(Moves.RAGE, Type.NORMAL, MoveCategory.PHYSICAL, 20, 100, 20, -1, 0, 1)
|
new AttackMove(Moves.RAGE, Type.NORMAL, MoveCategory.PHYSICAL, 20, 100, 20, -1, 0, 1)
|
||||||
.partial(),
|
.partial(), // No effect implemented
|
||||||
new SelfStatusMove(Moves.TELEPORT, Type.PSYCHIC, -1, 20, -1, -6, 1)
|
new SelfStatusMove(Moves.TELEPORT, Type.PSYCHIC, -1, 20, -1, -6, 1)
|
||||||
.attr(ForceSwitchOutAttr, true)
|
.attr(ForceSwitchOutAttr, true)
|
||||||
.hidesUser(),
|
.hidesUser(),
|
||||||
|
@ -7616,7 +7787,7 @@ export function initMoves() {
|
||||||
new StatusMove(Moves.CHARM, Type.FAIRY, 100, 20, -1, 0, 2)
|
new StatusMove(Moves.CHARM, Type.FAIRY, 100, 20, -1, 0, 2)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK ], -2),
|
.attr(StatStageChangeAttr, [ Stat.ATK ], -2),
|
||||||
new AttackMove(Moves.ROLLOUT, Type.ROCK, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 2)
|
new AttackMove(Moves.ROLLOUT, Type.ROCK, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 2)
|
||||||
.partial()
|
.partial() // Does not lock the user, also does not increase damage properly
|
||||||
.attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL),
|
.attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL),
|
||||||
new AttackMove(Moves.FALSE_SWIPE, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 2)
|
new AttackMove(Moves.FALSE_SWIPE, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 2)
|
||||||
.attr(SurviveDamageAttr),
|
.attr(SurviveDamageAttr),
|
||||||
|
@ -7687,7 +7858,7 @@ export function initMoves() {
|
||||||
.ignoresSubstitute()
|
.ignoresSubstitute()
|
||||||
.condition((user, target, move) => new EncoreTag(user.id).canAdd(target)),
|
.condition((user, target, move) => new EncoreTag(user.id).canAdd(target)),
|
||||||
new AttackMove(Moves.PURSUIT, Type.DARK, MoveCategory.PHYSICAL, 40, 100, 20, -1, 0, 2)
|
new AttackMove(Moves.PURSUIT, Type.DARK, MoveCategory.PHYSICAL, 40, 100, 20, -1, 0, 2)
|
||||||
.partial(),
|
.partial(), // No effect implemented
|
||||||
new AttackMove(Moves.RAPID_SPIN, Type.NORMAL, MoveCategory.PHYSICAL, 50, 100, 40, 100, 0, 2)
|
new AttackMove(Moves.RAPID_SPIN, Type.NORMAL, MoveCategory.PHYSICAL, 50, 100, 40, 100, 0, 2)
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPD ], 1, true)
|
.attr(StatStageChangeAttr, [ Stat.SPD ], 1, true)
|
||||||
.attr(RemoveBattlerTagAttr, [
|
.attr(RemoveBattlerTagAttr, [
|
||||||
|
@ -7752,7 +7923,7 @@ export function initMoves() {
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPDEF ], -1)
|
.attr(StatStageChangeAttr, [ Stat.SPDEF ], -1)
|
||||||
.ballBombMove(),
|
.ballBombMove(),
|
||||||
new AttackMove(Moves.FUTURE_SIGHT, Type.PSYCHIC, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 2)
|
new AttackMove(Moves.FUTURE_SIGHT, Type.PSYCHIC, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 2)
|
||||||
.partial()
|
.partial() // Complete buggy mess
|
||||||
.attr(DelayedAttackAttr, ArenaTagType.FUTURE_SIGHT, ChargeAnim.FUTURE_SIGHT_CHARGING, i18next.t("moveTriggers:foresawAnAttack", { pokemonName: "{USER}" })),
|
.attr(DelayedAttackAttr, ArenaTagType.FUTURE_SIGHT, ChargeAnim.FUTURE_SIGHT_CHARGING, i18next.t("moveTriggers:foresawAnAttack", { pokemonName: "{USER}" })),
|
||||||
new AttackMove(Moves.ROCK_SMASH, Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 15, 50, 0, 2)
|
new AttackMove(Moves.ROCK_SMASH, Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 15, 50, 0, 2)
|
||||||
.attr(StatStageChangeAttr, [ Stat.DEF ], -1),
|
.attr(StatStageChangeAttr, [ Stat.DEF ], -1),
|
||||||
|
@ -7770,7 +7941,7 @@ export function initMoves() {
|
||||||
.ignoresVirtual()
|
.ignoresVirtual()
|
||||||
.soundBased()
|
.soundBased()
|
||||||
.target(MoveTarget.RANDOM_NEAR_ENEMY)
|
.target(MoveTarget.RANDOM_NEAR_ENEMY)
|
||||||
.partial(),
|
.partial(), // Does not lock the user, does not stop Pokemon from sleeping
|
||||||
new SelfStatusMove(Moves.STOCKPILE, Type.NORMAL, -1, 20, -1, 0, 3)
|
new SelfStatusMove(Moves.STOCKPILE, Type.NORMAL, -1, 20, -1, 0, 3)
|
||||||
.condition(user => (user.getTag(StockpilingTag)?.stockpiledCount ?? 0) < 3)
|
.condition(user => (user.getTag(StockpilingTag)?.stockpiledCount ?? 0) < 3)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.STOCKPILING, true),
|
.attr(AddBattlerTagAttr, BattlerTagType.STOCKPILING, true),
|
||||||
|
@ -7793,7 +7964,7 @@ export function initMoves() {
|
||||||
.target(MoveTarget.BOTH_SIDES),
|
.target(MoveTarget.BOTH_SIDES),
|
||||||
new StatusMove(Moves.TORMENT, Type.DARK, 100, 15, -1, 0, 3)
|
new StatusMove(Moves.TORMENT, Type.DARK, 100, 15, -1, 0, 3)
|
||||||
.ignoresSubstitute()
|
.ignoresSubstitute()
|
||||||
.partial() // Incomplete implementation because of Uproar's partial implementation
|
.edgeCase() // Incomplete implementation because of Uproar's partial implementation
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.TORMENT, false, true, 1),
|
.attr(AddBattlerTagAttr, BattlerTagType.TORMENT, false, true, 1),
|
||||||
new StatusMove(Moves.FLATTER, Type.DARK, 100, 15, -1, 0, 3)
|
new StatusMove(Moves.FLATTER, Type.DARK, 100, 15, -1, 0, 3)
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPATK ], 1)
|
.attr(StatStageChangeAttr, [ Stat.SPATK ], 1)
|
||||||
|
@ -7842,7 +8013,9 @@ export function initMoves() {
|
||||||
.attr(RandomMovesetMoveAttr, true)
|
.attr(RandomMovesetMoveAttr, true)
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new SelfStatusMove(Moves.INGRAIN, Type.GRASS, -1, 20, -1, 0, 3)
|
new SelfStatusMove(Moves.INGRAIN, Type.GRASS, -1, 20, -1, 0, 3)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.INGRAIN, true, true),
|
.attr(AddBattlerTagAttr, BattlerTagType.INGRAIN, true, true)
|
||||||
|
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, true, true)
|
||||||
|
.attr(RemoveBattlerTagAttr, [ BattlerTagType.FLOATING ], true),
|
||||||
new AttackMove(Moves.SUPERPOWER, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 3)
|
new AttackMove(Moves.SUPERPOWER, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 3)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF ], -1, true),
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF ], -1, true),
|
||||||
new SelfStatusMove(Moves.MAGIC_COAT, Type.PSYCHIC, -1, 15, -1, 4, 3)
|
new SelfStatusMove(Moves.MAGIC_COAT, Type.PSYCHIC, -1, 15, -1, 4, 3)
|
||||||
|
@ -7870,7 +8043,8 @@ export function initMoves() {
|
||||||
.attr(SwitchAbilitiesAttr),
|
.attr(SwitchAbilitiesAttr),
|
||||||
new StatusMove(Moves.IMPRISON, Type.PSYCHIC, 100, 10, -1, 0, 3)
|
new StatusMove(Moves.IMPRISON, Type.PSYCHIC, 100, 10, -1, 0, 3)
|
||||||
.ignoresSubstitute()
|
.ignoresSubstitute()
|
||||||
.attr(AddArenaTagAttr, ArenaTagType.IMPRISON, 1, true, false),
|
.attr(AddArenaTagAttr, ArenaTagType.IMPRISON, 1, true, false)
|
||||||
|
.target(MoveTarget.ENEMY_SIDE),
|
||||||
new SelfStatusMove(Moves.REFRESH, Type.NORMAL, -1, 20, -1, 0, 3)
|
new SelfStatusMove(Moves.REFRESH, Type.NORMAL, -1, 20, -1, 0, 3)
|
||||||
.attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN)
|
.attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN)
|
||||||
.condition((user, target, move) => !!user.status && (user.status.effect === StatusEffect.PARALYSIS || user.status.effect === StatusEffect.POISON || user.status.effect === StatusEffect.TOXIC || user.status.effect === StatusEffect.BURN)),
|
.condition((user, target, move) => !!user.status && (user.status.effect === StatusEffect.PARALYSIS || user.status.effect === StatusEffect.POISON || user.status.effect === StatusEffect.TOXIC || user.status.effect === StatusEffect.BURN)),
|
||||||
|
@ -7880,7 +8054,7 @@ export function initMoves() {
|
||||||
.unimplemented(),
|
.unimplemented(),
|
||||||
new AttackMove(Moves.SECRET_POWER, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, 30, 0, 3)
|
new AttackMove(Moves.SECRET_POWER, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, 30, 0, 3)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.partial(),
|
.attr(SecretPowerAttr),
|
||||||
new AttackMove(Moves.DIVE, Type.WATER, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 3)
|
new AttackMove(Moves.DIVE, Type.WATER, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 3)
|
||||||
.attr(ChargeAttr, ChargeAnim.DIVE_CHARGING, i18next.t("moveTriggers:hidUnderwater", { pokemonName: "{USER}" }), BattlerTagType.UNDERWATER, true)
|
.attr(ChargeAttr, ChargeAnim.DIVE_CHARGING, i18next.t("moveTriggers:hidUnderwater", { pokemonName: "{USER}" }), BattlerTagType.UNDERWATER, true)
|
||||||
.attr(GulpMissileTagAttr)
|
.attr(GulpMissileTagAttr)
|
||||||
|
@ -7911,7 +8085,7 @@ export function initMoves() {
|
||||||
.attr(AddArenaTagAttr, ArenaTagType.MUD_SPORT, 5)
|
.attr(AddArenaTagAttr, ArenaTagType.MUD_SPORT, 5)
|
||||||
.target(MoveTarget.BOTH_SIDES),
|
.target(MoveTarget.BOTH_SIDES),
|
||||||
new AttackMove(Moves.ICE_BALL, Type.ICE, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 3)
|
new AttackMove(Moves.ICE_BALL, Type.ICE, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 3)
|
||||||
.partial()
|
.partial() // Does not lock the user properly, does not increase damage correctly
|
||||||
.attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL)
|
.attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL)
|
||||||
.ballBombMove(),
|
.ballBombMove(),
|
||||||
new AttackMove(Moves.NEEDLE_ARM, Type.GRASS, MoveCategory.PHYSICAL, 60, 100, 15, 30, 0, 3)
|
new AttackMove(Moves.NEEDLE_ARM, Type.GRASS, MoveCategory.PHYSICAL, 60, 100, 15, 30, 0, 3)
|
||||||
|
@ -8054,7 +8228,7 @@ export function initMoves() {
|
||||||
.attr(ConfuseAttr)
|
.attr(ConfuseAttr)
|
||||||
.pulseMove(),
|
.pulseMove(),
|
||||||
new AttackMove(Moves.DOOM_DESIRE, Type.STEEL, MoveCategory.SPECIAL, 140, 100, 5, -1, 0, 3)
|
new AttackMove(Moves.DOOM_DESIRE, Type.STEEL, MoveCategory.SPECIAL, 140, 100, 5, -1, 0, 3)
|
||||||
.partial()
|
.partial() // Complete buggy mess
|
||||||
.attr(DelayedAttackAttr, ArenaTagType.DOOM_DESIRE, ChargeAnim.DOOM_DESIRE_CHARGING, i18next.t("moveTriggers:choseDoomDesireAsDestiny", { pokemonName: "{USER}" })),
|
.attr(DelayedAttackAttr, ArenaTagType.DOOM_DESIRE, ChargeAnim.DOOM_DESIRE_CHARGING, i18next.t("moveTriggers:choseDoomDesireAsDestiny", { pokemonName: "{USER}" })),
|
||||||
new AttackMove(Moves.PSYCHO_BOOST, Type.PSYCHIC, MoveCategory.SPECIAL, 140, 90, 5, -1, 0, 3)
|
new AttackMove(Moves.PSYCHO_BOOST, Type.PSYCHIC, MoveCategory.SPECIAL, 140, 90, 5, -1, 0, 3)
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPATK ], -2, true),
|
.attr(StatStageChangeAttr, [ Stat.SPATK ], -2, true),
|
||||||
|
@ -8138,7 +8312,7 @@ export function initMoves() {
|
||||||
.attr(OpponentHighHpPowerAttr, 120)
|
.attr(OpponentHighHpPowerAttr, 120)
|
||||||
.makesContact(),
|
.makesContact(),
|
||||||
new SelfStatusMove(Moves.POWER_TRICK, Type.PSYCHIC, -1, 10, -1, 0, 4)
|
new SelfStatusMove(Moves.POWER_TRICK, Type.PSYCHIC, -1, 10, -1, 0, 4)
|
||||||
.unimplemented(),
|
.attr(AddBattlerTagAttr, BattlerTagType.POWER_TRICK, true),
|
||||||
new StatusMove(Moves.GASTRO_ACID, Type.POISON, 100, 10, -1, 0, 4)
|
new StatusMove(Moves.GASTRO_ACID, Type.POISON, 100, 10, -1, 0, 4)
|
||||||
.attr(SuppressAbilitiesAttr),
|
.attr(SuppressAbilitiesAttr),
|
||||||
new StatusMove(Moves.LUCKY_CHANT, Type.NORMAL, -1, 30, -1, 0, 4)
|
new StatusMove(Moves.LUCKY_CHANT, Type.NORMAL, -1, 30, -1, 0, 4)
|
||||||
|
@ -8176,8 +8350,8 @@ export function initMoves() {
|
||||||
new SelfStatusMove(Moves.AQUA_RING, Type.WATER, -1, 20, -1, 0, 4)
|
new SelfStatusMove(Moves.AQUA_RING, Type.WATER, -1, 20, -1, 0, 4)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.AQUA_RING, true, true),
|
.attr(AddBattlerTagAttr, BattlerTagType.AQUA_RING, true, true),
|
||||||
new SelfStatusMove(Moves.MAGNET_RISE, Type.ELECTRIC, -1, 10, -1, 0, 4)
|
new SelfStatusMove(Moves.MAGNET_RISE, Type.ELECTRIC, -1, 10, -1, 0, 4)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.MAGNET_RISEN, true, true)
|
.attr(AddBattlerTagAttr, BattlerTagType.FLOATING, true, true)
|
||||||
.condition((user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY) && [ BattlerTagType.MAGNET_RISEN, BattlerTagType.IGNORE_FLYING, BattlerTagType.INGRAIN ].every((tag) => !user.getTag(tag))),
|
.condition((user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY) && [ BattlerTagType.FLOATING, BattlerTagType.IGNORE_FLYING, BattlerTagType.INGRAIN ].every((tag) => !user.getTag(tag))),
|
||||||
new AttackMove(Moves.FLARE_BLITZ, Type.FIRE, MoveCategory.PHYSICAL, 120, 100, 15, 10, 0, 4)
|
new AttackMove(Moves.FLARE_BLITZ, Type.FIRE, MoveCategory.PHYSICAL, 120, 100, 15, 10, 0, 4)
|
||||||
.attr(RecoilAttr, false, 0.33)
|
.attr(RecoilAttr, false, 0.33)
|
||||||
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
|
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
|
||||||
|
@ -8402,7 +8576,11 @@ export function initMoves() {
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.CENTER_OF_ATTENTION, true),
|
.attr(AddBattlerTagAttr, BattlerTagType.CENTER_OF_ATTENTION, true),
|
||||||
new StatusMove(Moves.TELEKINESIS, Type.PSYCHIC, -1, 15, -1, 0, 5)
|
new StatusMove(Moves.TELEKINESIS, Type.PSYCHIC, -1, 15, -1, 0, 5)
|
||||||
.condition(failOnGravityCondition)
|
.condition(failOnGravityCondition)
|
||||||
.unimplemented(),
|
.condition((_user, target, _move) => ![ Species.DIGLETT, Species.DUGTRIO, Species.ALOLA_DIGLETT, Species.ALOLA_DUGTRIO, Species.SANDYGAST, Species.PALOSSAND, Species.WIGLETT, Species.WUGTRIO ].includes(target.species.speciesId))
|
||||||
|
.condition((_user, target, _move) => !(target.species.speciesId === Species.GENGAR && target.getFormKey() === "mega"))
|
||||||
|
.condition((_user, target, _move) => Utils.isNullOrUndefined(target.getTag(BattlerTagType.INGRAIN)) && Utils.isNullOrUndefined(target.getTag(BattlerTagType.IGNORE_FLYING)))
|
||||||
|
.attr(AddBattlerTagAttr, BattlerTagType.TELEKINESIS, false, true, 3)
|
||||||
|
.attr(AddBattlerTagAttr, BattlerTagType.FLOATING, false, true, 3),
|
||||||
new StatusMove(Moves.MAGIC_ROOM, Type.PSYCHIC, -1, 10, -1, 0, 5)
|
new StatusMove(Moves.MAGIC_ROOM, Type.PSYCHIC, -1, 10, -1, 0, 5)
|
||||||
.ignoresProtect()
|
.ignoresProtect()
|
||||||
.target(MoveTarget.BOTH_SIDES)
|
.target(MoveTarget.BOTH_SIDES)
|
||||||
|
@ -8410,7 +8588,7 @@ export function initMoves() {
|
||||||
new AttackMove(Moves.SMACK_DOWN, Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5)
|
new AttackMove(Moves.SMACK_DOWN, Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5)
|
||||||
.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.FLOATING, BattlerTagType.TELEKINESIS ])
|
||||||
.attr(HitsTagAttr, BattlerTagType.FLYING)
|
.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)
|
||||||
|
@ -8460,7 +8638,7 @@ export function initMoves() {
|
||||||
.attr(AfterYouAttr),
|
.attr(AfterYouAttr),
|
||||||
new AttackMove(Moves.ROUND, Type.NORMAL, MoveCategory.SPECIAL, 60, 100, 15, -1, 0, 5)
|
new AttackMove(Moves.ROUND, Type.NORMAL, MoveCategory.SPECIAL, 60, 100, 15, -1, 0, 5)
|
||||||
.soundBased()
|
.soundBased()
|
||||||
.partial(),
|
.partial(), // No effect implemented
|
||||||
new AttackMove(Moves.ECHOED_VOICE, Type.NORMAL, MoveCategory.SPECIAL, 40, 100, 15, -1, 0, 5)
|
new AttackMove(Moves.ECHOED_VOICE, Type.NORMAL, MoveCategory.SPECIAL, 40, 100, 15, -1, 0, 5)
|
||||||
.attr(ConsecutiveUseMultiBasePowerAttr, 5, false)
|
.attr(ConsecutiveUseMultiBasePowerAttr, 5, false)
|
||||||
.soundBased(),
|
.soundBased(),
|
||||||
|
@ -8502,7 +8680,8 @@ export function initMoves() {
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK ], 1, true)
|
.attr(StatStageChangeAttr, [ Stat.ATK ], 1, true)
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPD ], 2, true),
|
.attr(StatStageChangeAttr, [ Stat.SPD ], 2, true),
|
||||||
new AttackMove(Moves.CIRCLE_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 90, 10, -1, -6, 5)
|
new AttackMove(Moves.CIRCLE_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 90, 10, -1, -6, 5)
|
||||||
.attr(ForceSwitchOutAttr),
|
.attr(ForceSwitchOutAttr)
|
||||||
|
.partial(), // Should force random switches
|
||||||
new AttackMove(Moves.INCINERATE, Type.FIRE, MoveCategory.SPECIAL, 60, 100, 15, -1, 0, 5)
|
new AttackMove(Moves.INCINERATE, Type.FIRE, MoveCategory.SPECIAL, 60, 100, 15, -1, 0, 5)
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES)
|
.target(MoveTarget.ALL_NEAR_ENEMIES)
|
||||||
.attr(RemoveHeldItemAttr, true),
|
.attr(RemoveHeldItemAttr, true),
|
||||||
|
@ -8570,7 +8749,8 @@ export function initMoves() {
|
||||||
.attr(CritOnlyAttr),
|
.attr(CritOnlyAttr),
|
||||||
new AttackMove(Moves.DRAGON_TAIL, Type.DRAGON, MoveCategory.PHYSICAL, 60, 90, 10, -1, -6, 5)
|
new AttackMove(Moves.DRAGON_TAIL, Type.DRAGON, MoveCategory.PHYSICAL, 60, 90, 10, -1, -6, 5)
|
||||||
.attr(ForceSwitchOutAttr)
|
.attr(ForceSwitchOutAttr)
|
||||||
.hidesTarget(),
|
.hidesTarget()
|
||||||
|
.partial(), // Should force random switches
|
||||||
new SelfStatusMove(Moves.WORK_UP, Type.NORMAL, -1, 30, -1, 0, 5)
|
new SelfStatusMove(Moves.WORK_UP, Type.NORMAL, -1, 30, -1, 0, 5)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, true),
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, true),
|
||||||
new AttackMove(Moves.ELECTROWEB, Type.ELECTRIC, MoveCategory.SPECIAL, 55, 95, 15, 100, 0, 5)
|
new AttackMove(Moves.ELECTROWEB, Type.ELECTRIC, MoveCategory.SPECIAL, 55, 95, 15, 100, 0, 5)
|
||||||
|
@ -8698,7 +8878,7 @@ export function initMoves() {
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new StatusMove(Moves.TRICK_OR_TREAT, Type.GHOST, 100, 20, -1, 0, 6)
|
new StatusMove(Moves.TRICK_OR_TREAT, Type.GHOST, 100, 20, -1, 0, 6)
|
||||||
.attr(AddTypeAttr, Type.GHOST)
|
.attr(AddTypeAttr, Type.GHOST)
|
||||||
.partial(),
|
.edgeCase(), // Weird interaction with Forest's Curse, reflect type, burn up
|
||||||
new StatusMove(Moves.NOBLE_ROAR, Type.NORMAL, 100, 30, -1, 0, 6)
|
new StatusMove(Moves.NOBLE_ROAR, Type.NORMAL, 100, 30, -1, 0, 6)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1)
|
||||||
.soundBased(),
|
.soundBased(),
|
||||||
|
@ -8711,7 +8891,7 @@ export function initMoves() {
|
||||||
.triageMove(),
|
.triageMove(),
|
||||||
new StatusMove(Moves.FORESTS_CURSE, Type.GRASS, 100, 20, -1, 0, 6)
|
new StatusMove(Moves.FORESTS_CURSE, Type.GRASS, 100, 20, -1, 0, 6)
|
||||||
.attr(AddTypeAttr, Type.GRASS)
|
.attr(AddTypeAttr, Type.GRASS)
|
||||||
.partial(),
|
.edgeCase(), // Weird interaction with Trick or Treat, reflect type, burn up
|
||||||
new AttackMove(Moves.PETAL_BLIZZARD, Type.GRASS, MoveCategory.PHYSICAL, 90, 100, 15, -1, 0, 6)
|
new AttackMove(Moves.PETAL_BLIZZARD, Type.GRASS, MoveCategory.PHYSICAL, 90, 100, 15, -1, 0, 6)
|
||||||
.windMove()
|
.windMove()
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
|
@ -8719,7 +8899,7 @@ export function initMoves() {
|
||||||
new AttackMove(Moves.FREEZE_DRY, Type.ICE, MoveCategory.SPECIAL, 70, 100, 20, 10, 0, 6)
|
new AttackMove(Moves.FREEZE_DRY, Type.ICE, MoveCategory.SPECIAL, 70, 100, 20, 10, 0, 6)
|
||||||
.attr(StatusEffectAttr, StatusEffect.FREEZE)
|
.attr(StatusEffectAttr, StatusEffect.FREEZE)
|
||||||
.attr(WaterSuperEffectTypeMultiplierAttr)
|
.attr(WaterSuperEffectTypeMultiplierAttr)
|
||||||
.partial(), // This currently just multiplies the move's power instead of changing its effectiveness. It also doesn't account for abilities that modify type effectiveness such as tera shell.
|
.edgeCase(), // This currently just multiplies the move's power instead of changing its effectiveness. It also doesn't account for abilities that modify type effectiveness such as tera shell.
|
||||||
new AttackMove(Moves.DISARMING_VOICE, Type.FAIRY, MoveCategory.SPECIAL, 40, -1, 15, -1, 0, 6)
|
new AttackMove(Moves.DISARMING_VOICE, Type.FAIRY, MoveCategory.SPECIAL, 40, -1, 15, -1, 0, 6)
|
||||||
.soundBased()
|
.soundBased()
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||||
|
@ -8843,9 +9023,9 @@ export function initMoves() {
|
||||||
.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)
|
.attr(HitsTagAttr, BattlerTagType.FLYING)
|
||||||
.attr(HitsTagAttr, BattlerTagType.MAGNET_RISEN)
|
.attr(HitsTagAttr, BattlerTagType.FLOATING)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
|
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
|
||||||
.attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN ])
|
.attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.FLOATING, BattlerTagType.TELEKINESIS ])
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||||
new AttackMove(Moves.THOUSAND_WAVES, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6)
|
new AttackMove(Moves.THOUSAND_WAVES, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6)
|
||||||
|
@ -9097,15 +9277,15 @@ export function initMoves() {
|
||||||
/* Unused */
|
/* Unused */
|
||||||
new AttackMove(Moves.SINISTER_ARROW_RAID, Type.GHOST, MoveCategory.PHYSICAL, 180, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.SINISTER_ARROW_RAID, Type.GHOST, MoveCategory.PHYSICAL, 180, -1, 1, -1, 0, 7)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.partial()
|
.edgeCase() // I assume it's because the user needs spirit shackle and decidueye
|
||||||
.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(AlwaysHitMinimizeAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.MINIMIZED, true)
|
.attr(HitsTagAttr, BattlerTagType.MINIMIZED, true)
|
||||||
.partial()
|
.edgeCase() // I assume it's because it needs darkest lariat and incineroar
|
||||||
.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)
|
||||||
.partial()
|
.edgeCase() // I assume it's because it needs sparkling aria and primarina
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new AttackMove(Moves.GUARDIAN_OF_ALOLA, Type.FAIRY, MoveCategory.SPECIAL, -1, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.GUARDIAN_OF_ALOLA, Type.FAIRY, MoveCategory.SPECIAL, -1, -1, 1, -1, 0, 7)
|
||||||
.unimplemented()
|
.unimplemented()
|
||||||
|
@ -9114,10 +9294,10 @@ export function initMoves() {
|
||||||
.unimplemented()
|
.unimplemented()
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new AttackMove(Moves.STOKED_SPARKSURFER, Type.ELECTRIC, MoveCategory.SPECIAL, 175, -1, 1, 100, 0, 7)
|
new AttackMove(Moves.STOKED_SPARKSURFER, Type.ELECTRIC, MoveCategory.SPECIAL, 175, -1, 1, 100, 0, 7)
|
||||||
.partial()
|
.edgeCase() // I assume it's because it needs thunderbolt and Alola Raichu
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new AttackMove(Moves.PULVERIZING_PANCAKE, Type.NORMAL, MoveCategory.PHYSICAL, 210, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.PULVERIZING_PANCAKE, Type.NORMAL, MoveCategory.PHYSICAL, 210, -1, 1, -1, 0, 7)
|
||||||
.partial()
|
.edgeCase() // I assume it's because it needs giga impact and snorlax
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new SelfStatusMove(Moves.EXTREME_EVOBOOST, Type.NORMAL, -1, 1, -1, 0, 7)
|
new SelfStatusMove(Moves.EXTREME_EVOBOOST, Type.NORMAL, -1, 1, -1, 0, 7)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 2, true)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 2, true)
|
||||||
|
@ -9148,13 +9328,13 @@ export function initMoves() {
|
||||||
.attr(RechargeAttr),
|
.attr(RechargeAttr),
|
||||||
new AttackMove(Moves.SPECTRAL_THIEF, Type.GHOST, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 7)
|
new AttackMove(Moves.SPECTRAL_THIEF, Type.GHOST, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 7)
|
||||||
.ignoresSubstitute()
|
.ignoresSubstitute()
|
||||||
.partial(),
|
.partial(), // Does not steal stats
|
||||||
new AttackMove(Moves.SUNSTEEL_STRIKE, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 7)
|
new AttackMove(Moves.SUNSTEEL_STRIKE, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 7)
|
||||||
.ignoresAbilities()
|
.ignoresAbilities()
|
||||||
.partial(),
|
.edgeCase(), // Should not ignore abilities when called virtually (metronome)
|
||||||
new AttackMove(Moves.MOONGEIST_BEAM, Type.GHOST, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7)
|
new AttackMove(Moves.MOONGEIST_BEAM, Type.GHOST, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7)
|
||||||
.ignoresAbilities()
|
.ignoresAbilities()
|
||||||
.partial(),
|
.edgeCase(), // Should not ignore abilities when called virtually (metronome)
|
||||||
new StatusMove(Moves.TEARFUL_LOOK, Type.NORMAL, -1, 20, -1, 0, 7)
|
new StatusMove(Moves.TEARFUL_LOOK, Type.NORMAL, -1, 20, -1, 0, 7)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1),
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1),
|
||||||
new AttackMove(Moves.ZING_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 80, 100, 10, 30, 0, 7)
|
new AttackMove(Moves.ZING_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 80, 100, 10, 30, 0, 7)
|
||||||
|
@ -9165,7 +9345,7 @@ export function initMoves() {
|
||||||
.attr(FormChangeItemTypeAttr),
|
.attr(FormChangeItemTypeAttr),
|
||||||
/* Unused */
|
/* Unused */
|
||||||
new AttackMove(Moves.TEN_MILLION_VOLT_THUNDERBOLT, Type.ELECTRIC, MoveCategory.SPECIAL, 195, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.TEN_MILLION_VOLT_THUNDERBOLT, Type.ELECTRIC, MoveCategory.SPECIAL, 195, -1, 1, -1, 0, 7)
|
||||||
.partial()
|
.edgeCase() // I assume it's because it needs thunderbolt and pikachu in a cap
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
/* End Unused */
|
/* End Unused */
|
||||||
new AttackMove(Moves.MIND_BLOWN, Type.FIRE, MoveCategory.SPECIAL, 150, 100, 5, -1, 0, 7)
|
new AttackMove(Moves.MIND_BLOWN, Type.FIRE, MoveCategory.SPECIAL, 150, 100, 5, -1, 0, 7)
|
||||||
|
@ -9178,7 +9358,7 @@ export function initMoves() {
|
||||||
new AttackMove(Moves.PHOTON_GEYSER, Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7)
|
new AttackMove(Moves.PHOTON_GEYSER, Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7)
|
||||||
.attr(PhotonGeyserCategoryAttr)
|
.attr(PhotonGeyserCategoryAttr)
|
||||||
.ignoresAbilities()
|
.ignoresAbilities()
|
||||||
.partial(),
|
.edgeCase(), // Should not ignore abilities when called virtually (metronome)
|
||||||
/* Unused */
|
/* Unused */
|
||||||
new AttackMove(Moves.LIGHT_THAT_BURNS_THE_SKY, Type.PSYCHIC, MoveCategory.SPECIAL, 200, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.LIGHT_THAT_BURNS_THE_SKY, Type.PSYCHIC, MoveCategory.SPECIAL, 200, -1, 1, -1, 0, 7)
|
||||||
.attr(PhotonGeyserCategoryAttr)
|
.attr(PhotonGeyserCategoryAttr)
|
||||||
|
@ -9191,7 +9371,7 @@ export function initMoves() {
|
||||||
.ignoresAbilities()
|
.ignoresAbilities()
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new AttackMove(Moves.LETS_SNUGGLE_FOREVER, Type.FAIRY, MoveCategory.PHYSICAL, 190, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.LETS_SNUGGLE_FOREVER, Type.FAIRY, MoveCategory.PHYSICAL, 190, -1, 1, -1, 0, 7)
|
||||||
.partial()
|
.edgeCase() // I assume it needs play rough and mimikyu
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new AttackMove(Moves.SPLINTERED_STORMSHARDS, Type.ROCK, MoveCategory.PHYSICAL, 190, -1, 1, -1, 0, 7)
|
new AttackMove(Moves.SPLINTERED_STORMSHARDS, Type.ROCK, MoveCategory.PHYSICAL, 190, -1, 1, -1, 0, 7)
|
||||||
.attr(ClearTerrainAttr)
|
.attr(ClearTerrainAttr)
|
||||||
|
@ -9201,7 +9381,7 @@ export function initMoves() {
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true, undefined, undefined, undefined, undefined, true)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true, undefined, undefined, undefined, undefined, true)
|
||||||
.soundBased()
|
.soundBased()
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES)
|
.target(MoveTarget.ALL_NEAR_ENEMIES)
|
||||||
.partial()
|
.edgeCase() // I assume it needs clanging scales and Kommo-O
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
/* End Unused */
|
/* End Unused */
|
||||||
new AttackMove(Moves.ZIPPY_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 50, 100, 15, -1, 2, 7) //LGPE Implementation
|
new AttackMove(Moves.ZIPPY_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 50, 100, 15, -1, 2, 7) //LGPE Implementation
|
||||||
|
@ -9264,14 +9444,14 @@ export function initMoves() {
|
||||||
new AttackMove(Moves.JAW_LOCK, Type.DARK, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 8)
|
new AttackMove(Moves.JAW_LOCK, Type.DARK, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 8)
|
||||||
.attr(JawLockAttr)
|
.attr(JawLockAttr)
|
||||||
.bitingMove(),
|
.bitingMove(),
|
||||||
new SelfStatusMove(Moves.STUFF_CHEEKS, Type.NORMAL, -1, 10, -1, 0, 8) // TODO: Stuff Cheeks should not be selectable when the user does not have a berry, see wiki
|
new SelfStatusMove(Moves.STUFF_CHEEKS, Type.NORMAL, -1, 10, -1, 0, 8)
|
||||||
.attr(EatBerryAttr)
|
.attr(EatBerryAttr)
|
||||||
.attr(StatStageChangeAttr, [ Stat.DEF ], 2, true)
|
.attr(StatStageChangeAttr, [ Stat.DEF ], 2, true)
|
||||||
.condition((user) => {
|
.condition((user) => {
|
||||||
const userBerries = user.scene.findModifiers(m => m instanceof BerryModifier, user.isPlayer());
|
const userBerries = user.scene.findModifiers(m => m instanceof BerryModifier, user.isPlayer());
|
||||||
return userBerries.length > 0;
|
return userBerries.length > 0;
|
||||||
})
|
})
|
||||||
.partial(),
|
.edgeCase(), // Stuff Cheeks should not be selectable when the user does not have a berry, see wiki
|
||||||
new SelfStatusMove(Moves.NO_RETREAT, Type.FIGHTING, -1, 5, -1, 0, 8)
|
new SelfStatusMove(Moves.NO_RETREAT, Type.FIGHTING, -1, 5, -1, 0, 8)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.NO_RETREAT, true, false)
|
.attr(AddBattlerTagAttr, BattlerTagType.NO_RETREAT, true, false)
|
||||||
|
@ -9285,7 +9465,7 @@ export function initMoves() {
|
||||||
new AttackMove(Moves.DRAGON_DARTS, Type.DRAGON, MoveCategory.PHYSICAL, 50, 100, 10, -1, 0, 8)
|
new AttackMove(Moves.DRAGON_DARTS, Type.DRAGON, MoveCategory.PHYSICAL, 50, 100, 10, -1, 0, 8)
|
||||||
.attr(MultiHitAttr, MultiHitType._2)
|
.attr(MultiHitAttr, MultiHitType._2)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.partial(),
|
.partial(), // smart targetting is unimplemented
|
||||||
new StatusMove(Moves.TEATIME, Type.NORMAL, -1, 10, -1, 0, 8)
|
new StatusMove(Moves.TEATIME, Type.NORMAL, -1, 10, -1, 0, 8)
|
||||||
.attr(EatBerryAttr)
|
.attr(EatBerryAttr)
|
||||||
.target(MoveTarget.ALL),
|
.target(MoveTarget.ALL),
|
||||||
|
@ -9724,7 +9904,7 @@ export function initMoves() {
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPDEF ], -2),
|
.attr(StatStageChangeAttr, [ Stat.SPDEF ], -2),
|
||||||
new AttackMove(Moves.ORDER_UP, Type.DRAGON, MoveCategory.PHYSICAL, 80, 100, 10, 100, 0, 9)
|
new AttackMove(Moves.ORDER_UP, Type.DRAGON, MoveCategory.PHYSICAL, 80, 100, 10, 100, 0, 9)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.partial(),
|
.partial(), // No effect implemented (requires Commander)
|
||||||
new AttackMove(Moves.JET_PUNCH, Type.WATER, MoveCategory.PHYSICAL, 60, 100, 15, -1, 1, 9)
|
new AttackMove(Moves.JET_PUNCH, Type.WATER, MoveCategory.PHYSICAL, 60, 100, 15, -1, 1, 9)
|
||||||
.punchingMove(),
|
.punchingMove(),
|
||||||
new StatusMove(Moves.SPICY_EXTRACT, Type.GRASS, -1, 15, -1, 0, 9)
|
new StatusMove(Moves.SPICY_EXTRACT, Type.GRASS, -1, 15, -1, 0, 9)
|
||||||
|
@ -9936,8 +10116,7 @@ export function initMoves() {
|
||||||
new AttackMove(Moves.UPPER_HAND, Type.FIGHTING, MoveCategory.PHYSICAL, 65, 100, 15, 100, 3, 9)
|
new AttackMove(Moves.UPPER_HAND, Type.FIGHTING, MoveCategory.PHYSICAL, 65, 100, 15, 100, 3, 9)
|
||||||
.attr(FlinchAttr)
|
.attr(FlinchAttr)
|
||||||
.condition((user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.command === Command.FIGHT && !target.turnData.acted && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move!].category !== MoveCategory.STATUS && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move!].priority > 0 ) // TODO: is this bang correct?
|
.condition((user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.command === Command.FIGHT && !target.turnData.acted && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move!].category !== MoveCategory.STATUS && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move!].priority > 0 ) // TODO: is this bang correct?
|
||||||
//TODO: Should also apply when target move priority increased by ability ex. gale wings
|
.partial(), // Should also apply when target move priority increased by ability ex. gale wings
|
||||||
.partial(),
|
|
||||||
new AttackMove(Moves.MALIGNANT_CHAIN, Type.POISON, MoveCategory.SPECIAL, 100, 100, 5, 50, 0, 9)
|
new AttackMove(Moves.MALIGNANT_CHAIN, Type.POISON, MoveCategory.SPECIAL, 100, 100, 5, 50, 0, 9)
|
||||||
.attr(StatusEffectAttr, StatusEffect.TOXIC)
|
.attr(StatusEffectAttr, StatusEffect.TOXIC)
|
||||||
);
|
);
|
||||||
|
|
|
@ -154,7 +154,7 @@ 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);
|
await initBattleWithEnemyConfig(scene, config);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.withSimpleOption(
|
.withSimpleOption(
|
||||||
|
|
|
@ -286,7 +286,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||||
ignorePp: true
|
ignorePp: true
|
||||||
});
|
});
|
||||||
|
|
||||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
await transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
|
@ -328,7 +328,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||||
});
|
});
|
||||||
await scene.updateModifiers(true);
|
await scene.updateModifiers(true);
|
||||||
|
|
||||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
await transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||||
leaveEncounterWithoutBattle(scene, true);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
|
@ -359,7 +359,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter =
|
||||||
greedent.moveset = [ new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF) ];
|
greedent.moveset = [ new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF) ];
|
||||||
greedent.passive = true;
|
greedent.passive = true;
|
||||||
|
|
||||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
await transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||||
await catchPokemon(scene, greedent, null, PokeballType.POKEBALL, false);
|
await catchPokemon(scene, greedent, null, PokeballType.POKEBALL, false);
|
||||||
leaveEncounterWithoutBattle(scene, true);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
})
|
})
|
||||||
|
|
|
@ -133,8 +133,8 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
||||||
new MoveRequirement(EXTORTION_MOVES),
|
new MoveRequirement(EXTORTION_MOVES, true),
|
||||||
new AbilityRequirement(EXTORTION_ABILITIES))
|
new AbilityRequirement(EXTORTION_ABILITIES, true))
|
||||||
)
|
)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option.2.label`,
|
buttonLabel: `${namespace}:option.2.label`,
|
||||||
|
|
|
@ -42,6 +42,8 @@ import {
|
||||||
AttackTypeBoosterModifier,
|
AttackTypeBoosterModifier,
|
||||||
BypassSpeedChanceModifier,
|
BypassSpeedChanceModifier,
|
||||||
ContactHeldItemTransferChanceModifier,
|
ContactHeldItemTransferChanceModifier,
|
||||||
|
GigantamaxAccessModifier,
|
||||||
|
MegaEvolutionAccessModifier,
|
||||||
PokemonHeldItemModifier
|
PokemonHeldItemModifier
|
||||||
} from "#app/modifier/modifier";
|
} from "#app/modifier/modifier";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -356,10 +358,17 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
// If player has any evolution/form change items that are valid for their party, will spawn one of those items in addition to a Master Ball
|
// If the player has any evolution/form change items that are valid for their party,
|
||||||
const modifierOptions: ModifierTypeOption[] = [ generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)!, generateModifierTypeOption(scene, modifierTypes.MAX_LURE)! ];
|
// spawn one of those items in addition to Dynamax Band, Mega Band, and Master Ball
|
||||||
|
const modifierOptions: ModifierTypeOption[] = [ generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)! ];
|
||||||
const specialOptions: ModifierTypeOption[] = [];
|
const specialOptions: ModifierTypeOption[] = [];
|
||||||
|
|
||||||
|
if (!scene.findModifier(m => m instanceof MegaEvolutionAccessModifier)) {
|
||||||
|
modifierOptions.push(generateModifierTypeOption(scene, modifierTypes.MEGA_BRACELET)!);
|
||||||
|
}
|
||||||
|
if (!scene.findModifier(m => m instanceof GigantamaxAccessModifier)) {
|
||||||
|
modifierOptions.push(generateModifierTypeOption(scene, modifierTypes.DYNAMAX_BAND)!);
|
||||||
|
}
|
||||||
const nonRareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.EVOLUTION_ITEM);
|
const nonRareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.EVOLUTION_ITEM);
|
||||||
if (nonRareEvolutionModifier) {
|
if (nonRareEvolutionModifier) {
|
||||||
specialOptions.push(nonRareEvolutionModifier);
|
specialOptions.push(nonRareEvolutionModifier);
|
||||||
|
|
|
@ -28,7 +28,7 @@ import { BattlerIndex } from "#app/battle";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import { EncounterBattleAnim } from "#app/data/battle-anims";
|
import { EncounterBattleAnim } from "#app/data/battle-anims";
|
||||||
import { MoveCategory } from "#app/data/move";
|
import { MoveCategory } from "#app/data/move";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
import { EncounterAnim } from "#enums/encounter-anims";
|
import { EncounterAnim } from "#enums/encounter-anims";
|
||||||
import { Challenges } from "#enums/challenges";
|
import { Challenges } from "#enums/challenges";
|
||||||
|
@ -133,7 +133,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||||
},
|
},
|
||||||
{ // Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter
|
{ // Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter
|
||||||
species: getPokemonSpecies(Species.BLACEPHALON),
|
species: getPokemonSpecies(Species.BLACEPHALON),
|
||||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ ability: ability, types: [ randSeedInt(18), randSeedInt(18) ]}),
|
customPokemonData: new CustomPokemonData({ ability: ability, types: [ randSeedInt(18), randSeedInt(18) ]}),
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
moveSet: [ Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN ]
|
moveSet: [ Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN ]
|
||||||
},
|
},
|
||||||
|
@ -353,15 +353,15 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
||||||
newTypes.push(secondType);
|
newTypes.push(secondType);
|
||||||
|
|
||||||
// Apply the type changes (to both base and fusion, if pokemon is fused)
|
// Apply the type changes (to both base and fusion, if pokemon is fused)
|
||||||
if (!pokemon.mysteryEncounterPokemonData) {
|
if (!pokemon.customPokemonData) {
|
||||||
pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
pokemon.customPokemonData = new CustomPokemonData();
|
||||||
}
|
}
|
||||||
pokemon.mysteryEncounterPokemonData.types = newTypes;
|
pokemon.customPokemonData.types = newTypes;
|
||||||
if (pokemon.isFusion()) {
|
if (pokemon.isFusion()) {
|
||||||
if (!pokemon.fusionMysteryEncounterPokemonData) {
|
if (!pokemon.fusionCustomPokemonData) {
|
||||||
pokemon.fusionMysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
pokemon.fusionCustomPokemonData = new CustomPokemonData();
|
||||||
}
|
}
|
||||||
pokemon.fusionMysteryEncounterPokemonData.types = newTypes;
|
pokemon.fusionCustomPokemonData.types = newTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -426,15 +426,15 @@ function onYesAbilitySwap(scene: BattleScene, resolve) {
|
||||||
// Do ability swap
|
// Do ability swap
|
||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
if (pokemon.isFusion()) {
|
if (pokemon.isFusion()) {
|
||||||
if (!pokemon.fusionMysteryEncounterPokemonData) {
|
if (!pokemon.fusionCustomPokemonData) {
|
||||||
pokemon.fusionMysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
pokemon.fusionCustomPokemonData = new CustomPokemonData();
|
||||||
}
|
}
|
||||||
pokemon.fusionMysteryEncounterPokemonData.ability = encounter.misc.ability;
|
pokemon.fusionCustomPokemonData.ability = encounter.misc.ability;
|
||||||
} else {
|
} else {
|
||||||
if (!pokemon.mysteryEncounterPokemonData) {
|
if (!pokemon.customPokemonData) {
|
||||||
pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
pokemon.customPokemonData = new CustomPokemonData();
|
||||||
}
|
}
|
||||||
pokemon.mysteryEncounterPokemonData.ability = encounter.misc.ability;
|
pokemon.customPokemonData.ability = encounter.misc.ability;
|
||||||
}
|
}
|
||||||
encounter.setDialogueToken("chosenPokemon", pokemon.getNameToRender());
|
encounter.setDialogueToken("chosenPokemon", pokemon.getNameToRender());
|
||||||
scene.ui.setMode(Mode.MESSAGE).then(() => resolve(true));
|
scene.ui.setMode(Mode.MESSAGE).then(() => resolve(true));
|
||||||
|
|
|
@ -228,7 +228,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||||
})
|
})
|
||||||
.withOptionPhase(async (scene: BattleScene) => {
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
// Learn its Dance
|
// Learn its Dance
|
||||||
hideOricorioPokemon(scene);
|
await hideOricorioPokemon(scene);
|
||||||
leaveEncounterWithoutBattle(scene, true);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
|
@ -236,7 +236,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new MoveRequirement(DANCING_MOVES)) // Will set option3PrimaryName and option3PrimaryMove dialogue tokens automatically
|
.withPrimaryPokemonRequirement(new MoveRequirement(DANCING_MOVES, true)) // Will set option3PrimaryName and option3PrimaryMove dialogue tokens automatically
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option.3.label`,
|
buttonLabel: `${namespace}:option.3.label`,
|
||||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||||
|
@ -303,7 +303,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hideOricorioPokemon(scene);
|
await hideOricorioPokemon(scene);
|
||||||
await catchPokemon(scene, oricorio, null, PokeballType.POKEBALL, false);
|
await catchPokemon(scene, oricorio, null, PokeballType.POKEBALL, false);
|
||||||
leaveEncounterWithoutBattle(scene, true);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
})
|
})
|
||||||
|
|
|
@ -182,7 +182,7 @@ export const DarkDealEncounter: MysteryEncounter =
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
pokemonConfigs: [ pokemonConfig ],
|
pokemonConfigs: [ pokemonConfig ],
|
||||||
};
|
};
|
||||||
return initBattleWithEnemyConfig(scene, config);
|
await initBattleWithEnemyConfig(scene, config);
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
|
|
@ -222,12 +222,13 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.withPreOptionPhase(async (scene: BattleScene) => {
|
.withPreOptionPhase(async (scene: BattleScene) => {
|
||||||
|
// Do NOT await this, to prevent player from repeatedly pressing options
|
||||||
transitionMysteryEncounterIntroVisuals(scene, false, false, 2000);
|
transitionMysteryEncounterIntroVisuals(scene, false, false, 2000);
|
||||||
})
|
})
|
||||||
.withOptionPhase(async (scene: BattleScene) => {
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
// Fire types help calm the Volcarona
|
// Fire types help calm the Volcarona
|
||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
transitionMysteryEncounterIntroVisuals(scene);
|
await transitionMysteryEncounterIntroVisuals(scene);
|
||||||
setEncounterRewards(scene,
|
setEncounterRewards(scene,
|
||||||
{ fillRemaining: true },
|
{ fillRemaining: true },
|
||||||
undefined,
|
undefined,
|
||||||
|
|
|
@ -145,7 +145,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES, true)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option.2.label`,
|
buttonLabel: `${namespace}:option.2.label`,
|
||||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||||
|
|
|
@ -152,7 +152,7 @@ export const FunAndGamesEncounter: MysteryEncounter =
|
||||||
},
|
},
|
||||||
async (scene: BattleScene) => {
|
async (scene: BattleScene) => {
|
||||||
// Leave encounter with no rewards or exp
|
// Leave encounter with no rewards or exp
|
||||||
transitionMysteryEncounterIntroVisuals(scene, true, true);
|
await transitionMysteryEncounterIntroVisuals(scene, true, true);
|
||||||
leaveEncounterWithoutBattle(scene, true);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -399,7 +399,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
|
||||||
if (modifier.stackCount === 0) {
|
if (modifier.stackCount === 0) {
|
||||||
scene.removeModifier(modifier);
|
scene.removeModifier(modifier);
|
||||||
}
|
}
|
||||||
scene.updateModifiers(true, true);
|
await scene.updateModifiers(true, true);
|
||||||
|
|
||||||
// Generate a trainer name
|
// Generate a trainer name
|
||||||
const traderName = generateRandomTraderName();
|
const traderName = generateRandomTraderName();
|
||||||
|
|
|
@ -129,7 +129,7 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||||
*
|
*
|
||||||
* @param scene Battle scene
|
* @param scene Battle scene
|
||||||
*/
|
*/
|
||||||
async function handlePokemonGuidingYouPhase(scene: BattleScene) {
|
function handlePokemonGuidingYouPhase(scene: BattleScene) {
|
||||||
const laprasSpecies = getPokemonSpecies(Species.LAPRAS);
|
const laprasSpecies = getPokemonSpecies(Species.LAPRAS);
|
||||||
const { mysteryEncounter } = scene.currentBattle;
|
const { mysteryEncounter } = scene.currentBattle;
|
||||||
|
|
||||||
|
|
|
@ -147,11 +147,11 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM ], fillRemaining: true });
|
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM ], fillRemaining: true });
|
||||||
|
|
||||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||||
let ret;
|
let initBattlePromise: Promise<void>;
|
||||||
scene.executeWithSeedOffset(() => {
|
scene.executeWithSeedOffset(() => {
|
||||||
ret = initBattleWithEnemyConfig(scene, config);
|
initBattlePromise = initBattleWithEnemyConfig(scene, config);
|
||||||
}, scene.currentBattle.waveIndex * 10);
|
}, scene.currentBattle.waveIndex * 10);
|
||||||
return ret;
|
await initBattlePromise!;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.withSimpleOption(
|
.withSimpleOption(
|
||||||
|
@ -172,11 +172,11 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], fillRemaining: true });
|
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], fillRemaining: true });
|
||||||
|
|
||||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||||
let ret;
|
let initBattlePromise: Promise<void>;
|
||||||
scene.executeWithSeedOffset(() => {
|
scene.executeWithSeedOffset(() => {
|
||||||
ret = initBattleWithEnemyConfig(scene, config);
|
initBattlePromise = initBattleWithEnemyConfig(scene, config);
|
||||||
}, scene.currentBattle.waveIndex * 100);
|
}, scene.currentBattle.waveIndex * 100);
|
||||||
return ret;
|
await initBattlePromise!;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.withSimpleOption(
|
.withSimpleOption(
|
||||||
|
@ -200,11 +200,11 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
|
||||||
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT ], fillRemaining: true });
|
setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT ], fillRemaining: true });
|
||||||
|
|
||||||
// Seed offsets to remove possibility of different trainers having exact same teams
|
// Seed offsets to remove possibility of different trainers having exact same teams
|
||||||
let ret;
|
let initBattlePromise: Promise<void>;
|
||||||
scene.executeWithSeedOffset(() => {
|
scene.executeWithSeedOffset(() => {
|
||||||
ret = initBattleWithEnemyConfig(scene, config);
|
initBattlePromise = initBattleWithEnemyConfig(scene, config);
|
||||||
}, scene.currentBattle.waveIndex * 1000);
|
}, scene.currentBattle.waveIndex * 1000);
|
||||||
return ret;
|
await initBattlePromise!;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.withOutroDialogue([
|
.withOutroDialogue([
|
||||||
|
|
|
@ -184,7 +184,7 @@ export const MysteriousChestEncounter: MysteryEncounter =
|
||||||
scene.unshiftPhase(new GameOverPhase(scene));
|
scene.unshiftPhase(new GameOverPhase(scene));
|
||||||
} else {
|
} else {
|
||||||
// Show which Pokemon was KOed, then start battle against Gimmighoul
|
// Show which Pokemon was KOed, then start battle against Gimmighoul
|
||||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
await transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||||
setEncounterRewards(scene, { fillRemaining: true });
|
setEncounterRewards(scene, { fillRemaining: true });
|
||||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ export const PartTimerEncounter: MysteryEncounter =
|
||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new MoveRequirement(CHARMING_MOVES)) // Will set option3PrimaryName and option3PrimaryMove dialogue tokens automatically
|
.withPrimaryPokemonRequirement(new MoveRequirement(CHARMING_MOVES, true)) // Will set option3PrimaryName and option3PrimaryMove dialogue tokens automatically
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option.3.label`,
|
buttonLabel: `${namespace}:option.3.label`,
|
||||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||||
|
|
|
@ -303,13 +303,16 @@ async function summonSafariPokemon(scene: BattleScene) {
|
||||||
scene.unshiftPhase(new SummonPhase(scene, 0, false));
|
scene.unshiftPhase(new SummonPhase(scene, 0, false));
|
||||||
|
|
||||||
encounter.setDialogueToken("pokemonName", getPokemonNameWithAffix(pokemon));
|
encounter.setDialogueToken("pokemonName", getPokemonNameWithAffix(pokemon));
|
||||||
showEncounterText(scene, getEncounterText(scene, "battle:singleWildAppeared") ?? "", null, 1500, false)
|
|
||||||
.then(() => {
|
// TODO: If we await showEncounterText here, then the text will display without
|
||||||
|
// the wild Pokemon on screen, but if we don't await it, then the text never
|
||||||
|
// shows up and the IV scanner breaks. For now, we place the IV scanner code
|
||||||
|
// separately so that at least the IV scanner works.
|
||||||
|
|
||||||
const ivScannerModifier = scene.findModifier(m => m instanceof IvScannerModifier);
|
const ivScannerModifier = scene.findModifier(m => m instanceof IvScannerModifier);
|
||||||
if (ivScannerModifier) {
|
if (ivScannerModifier) {
|
||||||
scene.pushPhase(new ScanIvsPhase(scene, pokemon.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6)));
|
scene.pushPhase(new ScanIvsPhase(scene, pokemon.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6)));
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function throwPokeball(scene: BattleScene, pokemon: EnemyPokemon): Promise<boolean> {
|
function throwPokeball(scene: BattleScene, pokemon: EnemyPokemon): Promise<boolean> {
|
||||||
|
|
|
@ -138,11 +138,11 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||||
newNature = randSeedInt(25) as Nature;
|
newNature = randSeedInt(25) as Nature;
|
||||||
}
|
}
|
||||||
|
|
||||||
chosenPokemon.nature = newNature;
|
chosenPokemon.customPokemonData.nature = newNature;
|
||||||
encounter.setDialogueToken("newNature", getNatureName(newNature));
|
encounter.setDialogueToken("newNature", getNatureName(newNature));
|
||||||
queueEncounterMessage(scene, `${namespace}:cheap_side_effects`);
|
queueEncounterMessage(scene, `${namespace}:cheap_side_effects`);
|
||||||
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
||||||
chosenPokemon.updateInfo();
|
await chosenPokemon.updateInfo();
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
@ -204,7 +204,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
||||||
queueEncounterMessage(scene, `${namespace}:no_bad_effects`);
|
queueEncounterMessage(scene, `${namespace}:no_bad_effects`);
|
||||||
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
||||||
|
|
||||||
chosenPokemon.updateInfo();
|
await chosenPokemon.updateInfo();
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,7 +18,7 @@ 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 { BerryType } from "#enums/berry-type";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
|
|
||||||
/** i18n namespace for the encounter */
|
/** i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounters/slumberingSnorlax";
|
const namespace = "mysteryEncounters/slumberingSnorlax";
|
||||||
|
@ -72,7 +72,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||||
stackCount: 2
|
stackCount: 2
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }),
|
customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }),
|
||||||
aiType: AiType.SMART // Required to ensure Snorlax uses Sleep Talk while it is asleep
|
aiType: AiType.SMART // Required to ensure Snorlax uses Sleep Talk while it is asleep
|
||||||
};
|
};
|
||||||
const config: EnemyPartyConfig = {
|
const config: EnemyPartyConfig = {
|
||||||
|
@ -143,7 +143,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES))
|
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES, true))
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option.3.label`,
|
buttonLabel: `${namespace}:option.3.label`,
|
||||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||||
|
|
|
@ -149,7 +149,7 @@ export const TeleportingHijinksEncounter: MysteryEncounter =
|
||||||
const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.STEEL ])!;
|
const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.STEEL ])!;
|
||||||
const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.ELECTRIC ])!;
|
const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.ELECTRIC ])!;
|
||||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ magnet, metalCoat ], fillRemaining: true });
|
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ magnet, metalCoat ], fillRemaining: true });
|
||||||
transitionMysteryEncounterIntroVisuals(scene, true, true);
|
await transitionMysteryEncounterIntroVisuals(scene, true, true);
|
||||||
await initBattleWithEnemyConfig(scene, config);
|
await initBattleWithEnemyConfig(scene, config);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { achvs } from "#app/system/achv";
|
||||||
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||||
import { Type } from "#app/data/type";
|
import { Type } from "#app/data/type";
|
||||||
import { getPokeballTintColor } from "#app/data/pokeball";
|
import { getPokeballTintColor } from "#app/data/pokeball";
|
||||||
|
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
|
|
||||||
/** the i18n namespace for the encounter */
|
/** the i18n namespace for the encounter */
|
||||||
const namespace = "mysteryEncounters/theExpertPokemonBreeder";
|
const namespace = "mysteryEncounters/theExpertPokemonBreeder";
|
||||||
|
@ -61,7 +62,7 @@ const POOL_1_POKEMON: (Species | BreederSpeciesEvolution)[][] = [
|
||||||
const POOL_2_POKEMON: (Species | BreederSpeciesEvolution)[][] = [
|
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.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.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE) ],
|
||||||
[ Species.JYNX ],
|
[ Species.SMOOCHUM, new BreederSpeciesEvolution(Species.JYNX, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||||
[ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE) ],
|
[ 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.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||||
[ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE) ],
|
[ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE) ],
|
||||||
|
@ -163,7 +164,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||||
if (pokemon2CommonEggs > 0) {
|
if (pokemon2CommonEggs > 0) {
|
||||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon2CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon2CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||||
pokemon2Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText });
|
pokemon2Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText });
|
||||||
encounter.setDialogueToken("pokemon1CommonEggs", eggsText);
|
encounter.setDialogueToken("pokemon2CommonEggs", eggsText);
|
||||||
}
|
}
|
||||||
encounter.options[1].dialogue!.buttonTooltip = pokemon2Tooltip;
|
encounter.options[1].dialogue!.buttonTooltip = pokemon2Tooltip;
|
||||||
|
|
||||||
|
@ -221,7 +222,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||||
encounter.misc.chosenPokemon = pokemon1;
|
encounter.misc.chosenPokemon = pokemon1;
|
||||||
encounter.setDialogueToken("chosenPokemon", pokemon1.getNameToRender());
|
encounter.setDialogueToken("chosenPokemon", pokemon1.getNameToRender());
|
||||||
const eggOptions = getEggOptions(scene, pokemon1CommonEggs, pokemon1RareEggs);
|
const eggOptions = getEggOptions(scene, pokemon1CommonEggs, pokemon1RareEggs);
|
||||||
setEncounterRewards(scene, { fillRemaining: true }, eggOptions);
|
setEncounterRewards(scene, { fillRemaining: true }, eggOptions, () => doPostEncounterCleanup(scene));
|
||||||
|
|
||||||
// Remove all Pokemon from the party except the chosen Pokemon
|
// Remove all Pokemon from the party except the chosen Pokemon
|
||||||
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon1);
|
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon1);
|
||||||
|
@ -245,10 +246,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||||
}
|
}
|
||||||
|
|
||||||
encounter.onGameOver = onGameOver;
|
encounter.onGameOver = onGameOver;
|
||||||
initBattleWithEnemyConfig(scene, config);
|
await initBattleWithEnemyConfig(scene, config);
|
||||||
})
|
|
||||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
|
||||||
await doPostEncounterCleanup(scene);
|
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
@ -273,7 +271,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||||
encounter.misc.chosenPokemon = pokemon2;
|
encounter.misc.chosenPokemon = pokemon2;
|
||||||
encounter.setDialogueToken("chosenPokemon", pokemon2.getNameToRender());
|
encounter.setDialogueToken("chosenPokemon", pokemon2.getNameToRender());
|
||||||
const eggOptions = getEggOptions(scene, pokemon2CommonEggs, pokemon2RareEggs);
|
const eggOptions = getEggOptions(scene, pokemon2CommonEggs, pokemon2RareEggs);
|
||||||
setEncounterRewards(scene, { fillRemaining: true }, eggOptions);
|
setEncounterRewards(scene, { fillRemaining: true }, eggOptions, () => doPostEncounterCleanup(scene));
|
||||||
|
|
||||||
// Remove all Pokemon from the party except the chosen Pokemon
|
// Remove all Pokemon from the party except the chosen Pokemon
|
||||||
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon2);
|
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon2);
|
||||||
|
@ -297,10 +295,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||||
}
|
}
|
||||||
|
|
||||||
encounter.onGameOver = onGameOver;
|
encounter.onGameOver = onGameOver;
|
||||||
initBattleWithEnemyConfig(scene, config);
|
await initBattleWithEnemyConfig(scene, config);
|
||||||
})
|
|
||||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
|
||||||
await doPostEncounterCleanup(scene);
|
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
@ -325,7 +320,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||||
encounter.misc.chosenPokemon = pokemon3;
|
encounter.misc.chosenPokemon = pokemon3;
|
||||||
encounter.setDialogueToken("chosenPokemon", pokemon3.getNameToRender());
|
encounter.setDialogueToken("chosenPokemon", pokemon3.getNameToRender());
|
||||||
const eggOptions = getEggOptions(scene, pokemon3CommonEggs, pokemon3RareEggs);
|
const eggOptions = getEggOptions(scene, pokemon3CommonEggs, pokemon3RareEggs);
|
||||||
setEncounterRewards(scene, { fillRemaining: true }, eggOptions);
|
setEncounterRewards(scene, { fillRemaining: true }, eggOptions, () => doPostEncounterCleanup(scene));
|
||||||
|
|
||||||
// Remove all Pokemon from the party except the chosen Pokemon
|
// Remove all Pokemon from the party except the chosen Pokemon
|
||||||
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon3);
|
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon3);
|
||||||
|
@ -349,10 +344,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
||||||
}
|
}
|
||||||
|
|
||||||
encounter.onGameOver = onGameOver;
|
encounter.onGameOver = onGameOver;
|
||||||
initBattleWithEnemyConfig(scene, config);
|
await initBattleWithEnemyConfig(scene, config);
|
||||||
})
|
|
||||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
|
||||||
await doPostEncounterCleanup(scene);
|
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
@ -521,19 +513,19 @@ function checkAchievement(scene: BattleScene) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function restorePartyAndHeldItems(scene: BattleScene) {
|
function restorePartyAndHeldItems(scene: BattleScene) {
|
||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
// Restore original party
|
// Restore original party
|
||||||
scene.getParty().push(...encounter.misc.originalParty);
|
scene.getParty().push(...encounter.misc.originalParty);
|
||||||
|
|
||||||
// Restore held items
|
// Restore held items
|
||||||
const originalHeldItems = encounter.misc.originalPartyHeldItems;
|
const originalHeldItems = encounter.misc.originalPartyHeldItems;
|
||||||
originalHeldItems.forEach(pokemonHeldItemsList => {
|
originalHeldItems.forEach((pokemonHeldItemsList: PokemonHeldItemModifier[]) => {
|
||||||
pokemonHeldItemsList.forEach(heldItem => {
|
pokemonHeldItemsList.forEach(heldItem => {
|
||||||
scene.addModifier(heldItem, true, false, false, true);
|
scene.addModifier(heldItem, true, false, false, true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
await scene.updateModifiers(true);
|
scene.updateModifiers(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGameOver(scene: BattleScene) {
|
function onGameOver(scene: BattleScene) {
|
||||||
|
@ -609,13 +601,13 @@ function onGameOver(scene: BattleScene) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function doPostEncounterCleanup(scene: BattleScene) {
|
function doPostEncounterCleanup(scene: BattleScene) {
|
||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
if (!encounter.misc.encounterFailed) {
|
if (!encounter.misc.encounterFailed) {
|
||||||
// Give achievement if in Space biome
|
// Give achievement if in Space biome
|
||||||
checkAchievement(scene);
|
checkAchievement(scene);
|
||||||
// Give 20 friendship to the chosen pokemon
|
// Give 20 friendship to the chosen pokemon
|
||||||
encounter.misc.chosenPokemon.addFriendship(FRIENDSHIP_ADDED);
|
encounter.misc.chosenPokemon.addFriendship(FRIENDSHIP_ADDED);
|
||||||
await restorePartyAndHeldItems(scene);
|
restorePartyAndHeldItems(scene);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { BattlerIndex } from "#app/battle";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||||
|
@ -79,7 +79,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
||||||
species: getPokemonSpecies(Species.SHUCKLE),
|
species: getPokemonSpecies(Species.SHUCKLE),
|
||||||
isBoss: true,
|
isBoss: true,
|
||||||
bossSegments: 5,
|
bossSegments: 5,
|
||||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }),
|
customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }),
|
||||||
nature: Nature.BOLD,
|
nature: Nature.BOLD,
|
||||||
moveSet: [ Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER ],
|
moveSet: [ Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER ],
|
||||||
modifierConfigs: [
|
modifierConfigs: [
|
||||||
|
@ -201,7 +201,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
||||||
});
|
});
|
||||||
|
|
||||||
encounter.dialogue.outro = [];
|
encounter.dialogue.outro = [];
|
||||||
transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
await transitionMysteryEncounterIntroVisuals(scene, true, true, 500);
|
||||||
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -111,8 +111,8 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter =
|
||||||
},
|
},
|
||||||
async (scene: BattleScene) => {
|
async (scene: BattleScene) => {
|
||||||
// Spawn 5 trainer battles back to back with Macho Brace in rewards
|
// Spawn 5 trainer battles back to back with Macho Brace in rewards
|
||||||
scene.currentBattle.mysteryEncounter!.doContinueEncounter = (scene: BattleScene) => {
|
scene.currentBattle.mysteryEncounter!.doContinueEncounter = async (scene: BattleScene) => {
|
||||||
return endTrainerBattleAndShowDialogue(scene);
|
await endTrainerBattleAndShowDialogue(scene);
|
||||||
};
|
};
|
||||||
await transitionMysteryEncounterIntroVisuals(scene, true, false);
|
await transitionMysteryEncounterIntroVisuals(scene, true, false);
|
||||||
await spawnNextTrainerOrEndEncounter(scene);
|
await spawnNextTrainerOrEndEncounter(scene);
|
||||||
|
|
|
@ -162,7 +162,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||||
|
|
||||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
||||||
|
|
||||||
return initBattleWithEnemyConfig(scene, config);
|
await initBattleWithEnemyConfig(scene, config);
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
@ -238,7 +238,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||||
|
|
||||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
||||||
|
|
||||||
return initBattleWithEnemyConfig(scene, config);
|
await initBattleWithEnemyConfig(scene, config);
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
@ -351,7 +351,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||||
|
|
||||||
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase);
|
||||||
|
|
||||||
return initBattleWithEnemyConfig(scene, config);
|
await initBattleWithEnemyConfig(scene, config);
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
|
|
@ -105,7 +105,7 @@ export const TrashToTreasureEncounter: MysteryEncounter =
|
||||||
})
|
})
|
||||||
.withOptionPhase(async (scene: BattleScene) => {
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
// Gain 2 Leftovers and 2 Shell Bell
|
// Gain 2 Leftovers and 2 Shell Bell
|
||||||
transitionMysteryEncounterIntroVisuals(scene);
|
await transitionMysteryEncounterIntroVisuals(scene);
|
||||||
await tryApplyDigRewardItems(scene);
|
await tryApplyDigRewardItems(scene);
|
||||||
|
|
||||||
const blackSludge = generateModifierType(scene, modifierTypes.MYSTERY_ENCOUNTER_BLACK_SLUDGE, [ SHOP_ITEM_COST_MULTIPLIER ]);
|
const blackSludge = generateModifierType(scene, modifierTypes.MYSTERY_ENCOUNTER_BLACK_SLUDGE, [ SHOP_ITEM_COST_MULTIPLIER ]);
|
||||||
|
@ -136,7 +136,7 @@ export const TrashToTreasureEncounter: MysteryEncounter =
|
||||||
// Investigate garbage, battle Gmax Garbodor
|
// Investigate garbage, battle Gmax Garbodor
|
||||||
scene.setFieldScale(0.75);
|
scene.setFieldScale(0.75);
|
||||||
await showEncounterText(scene, `${namespace}:option.2.selected_2`);
|
await showEncounterText(scene, `${namespace}:option.2.selected_2`);
|
||||||
transitionMysteryEncounterIntroVisuals(scene);
|
await transitionMysteryEncounterIntroVisuals(scene);
|
||||||
|
|
||||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ async function tryApplyDigRewardItems(scene: BattleScene) {
|
||||||
await showEncounterText(scene, i18next.t("battle:rewardGainCount", { modifierName: shellBell.name, count: 2 }), null, undefined, true);
|
await showEncounterText(scene, i18next.t("battle:rewardGainCount", { modifierName: shellBell.name, count: 2 }), null, undefined, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function doGarbageDig(scene: BattleScene) {
|
function doGarbageDig(scene: BattleScene) {
|
||||||
scene.playSound("battle_anims/PRSFX- Dig2");
|
scene.playSound("battle_anims/PRSFX- Dig2");
|
||||||
scene.time.delayedCall(SOUND_EFFECT_WAIT_TIME, () => {
|
scene.time.delayedCall(SOUND_EFFECT_WAIT_TIME, () => {
|
||||||
scene.playSound("battle_anims/PRSFX- Dig2");
|
scene.playSound("battle_anims/PRSFX- Dig2");
|
||||||
|
|
|
@ -210,7 +210,7 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new MoveRequirement(CHARMING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
.withPrimaryPokemonRequirement(new MoveRequirement(CHARMING_MOVES, true)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option.3.label`,
|
buttonLabel: `${namespace}:option.3.label`,
|
||||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { IntegerHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "
|
||||||
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
||||||
import { HiddenAbilityRateBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
|
import { HiddenAbilityRateBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||||
import { achvs } from "#app/system/achv";
|
import { achvs } from "#app/system/achv";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { 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";
|
||||||
|
@ -379,10 +379,10 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
|
||||||
newType = randSeedInt(18) as Type;
|
newType = randSeedInt(18) as Type;
|
||||||
}
|
}
|
||||||
newTypes.push(newType);
|
newTypes.push(newType);
|
||||||
if (!newPokemon.mysteryEncounterPokemonData) {
|
if (!newPokemon.customPokemonData) {
|
||||||
newPokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
newPokemon.customPokemonData = new CustomPokemonData();
|
||||||
}
|
}
|
||||||
newPokemon.mysteryEncounterPokemonData.types = newTypes;
|
newPokemon.customPokemonData.types = newTypes;
|
||||||
|
|
||||||
for (const item of transformation.heldItems) {
|
for (const item of transformation.heldItems) {
|
||||||
item.pokemonId = newPokemon.id;
|
item.pokemonId = newPokemon.id;
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { AttackTypeBoosterModifier } from "#app/modifier/modifier";
|
import { AttackTypeBoosterModifier } from "#app/modifier/modifier";
|
||||||
import { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type";
|
import { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type";
|
||||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||||
|
import { allAbilities } from "#app/data/ability";
|
||||||
|
|
||||||
export interface EncounterRequirement {
|
export interface EncounterRequirement {
|
||||||
meetsRequirement(scene: BattleScene): boolean; // Boolean to see if a requirement is met
|
meetsRequirement(scene: BattleScene): boolean; // Boolean to see if a requirement is met
|
||||||
|
@ -476,9 +477,11 @@ export class MoveRequirement extends EncounterPokemonRequirement {
|
||||||
requiredMoves: Moves[] = [];
|
requiredMoves: Moves[] = [];
|
||||||
minNumberOfPokemon: number;
|
minNumberOfPokemon: number;
|
||||||
invertQuery: boolean;
|
invertQuery: boolean;
|
||||||
|
excludeDisallowedPokemon: boolean;
|
||||||
|
|
||||||
constructor(moves: Moves | Moves[], minNumberOfPokemon: number = 1, invertQuery: boolean = false) {
|
constructor(moves: Moves | Moves[], excludeDisallowedPokemon: boolean, minNumberOfPokemon: number = 1, invertQuery: boolean = false) {
|
||||||
super();
|
super();
|
||||||
|
this.excludeDisallowedPokemon = excludeDisallowedPokemon;
|
||||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||||
this.invertQuery = invertQuery;
|
this.invertQuery = invertQuery;
|
||||||
this.requiredMoves = Array.isArray(moves) ? moves : [ moves ];
|
this.requiredMoves = Array.isArray(moves) ? moves : [ moves ];
|
||||||
|
@ -494,10 +497,15 @@ export class MoveRequirement extends EncounterPokemonRequirement {
|
||||||
|
|
||||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||||
if (!this.invertQuery) {
|
if (!this.invertQuery) {
|
||||||
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((reqMove) => pokemon.moveset.filter((move) => move?.moveId === reqMove).length > 0).length > 0);
|
// get the Pokemon with at least one move in the required moves list
|
||||||
|
return partyPokemon.filter((pokemon) =>
|
||||||
|
(!this.excludeDisallowedPokemon || pokemon.isAllowedInBattle())
|
||||||
|
&& pokemon.moveset.some((move) => move?.moveId && this.requiredMoves.includes(move.moveId)));
|
||||||
} else {
|
} else {
|
||||||
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed moves
|
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed moves
|
||||||
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((reqMove) => pokemon.moveset.filter((move) => move?.moveId === reqMove).length === 0).length === 0);
|
return partyPokemon.filter((pokemon) =>
|
||||||
|
(!this.excludeDisallowedPokemon || pokemon.isAllowedInBattle())
|
||||||
|
&& !pokemon.moveset.some((move) => move?.moveId && this.requiredMoves.includes(move.moveId)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,9 +567,11 @@ export class AbilityRequirement extends EncounterPokemonRequirement {
|
||||||
requiredAbilities: Abilities[];
|
requiredAbilities: Abilities[];
|
||||||
minNumberOfPokemon: number;
|
minNumberOfPokemon: number;
|
||||||
invertQuery: boolean;
|
invertQuery: boolean;
|
||||||
|
excludeDisallowedPokemon: boolean;
|
||||||
|
|
||||||
constructor(abilities: Abilities | Abilities[], minNumberOfPokemon: number = 1, invertQuery: boolean = false) {
|
constructor(abilities: Abilities | Abilities[], excludeDisallowedPokemon: boolean, minNumberOfPokemon: number = 1, invertQuery: boolean = false) {
|
||||||
super();
|
super();
|
||||||
|
this.excludeDisallowedPokemon = excludeDisallowedPokemon;
|
||||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||||
this.invertQuery = invertQuery;
|
this.invertQuery = invertQuery;
|
||||||
this.requiredAbilities = Array.isArray(abilities) ? abilities : [ abilities ];
|
this.requiredAbilities = Array.isArray(abilities) ? abilities : [ abilities ];
|
||||||
|
@ -577,16 +587,21 @@ export class AbilityRequirement extends EncounterPokemonRequirement {
|
||||||
|
|
||||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||||
if (!this.invertQuery) {
|
if (!this.invertQuery) {
|
||||||
return partyPokemon.filter((pokemon) => this.requiredAbilities.some((ability) => pokemon.getAbility().id === ability));
|
return partyPokemon.filter((pokemon) =>
|
||||||
|
(!this.excludeDisallowedPokemon || pokemon.isAllowedInBattle())
|
||||||
|
&& this.requiredAbilities.some((ability) => pokemon.hasAbility(ability, false)));
|
||||||
} else {
|
} else {
|
||||||
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed abilitiess
|
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed abilities
|
||||||
return partyPokemon.filter((pokemon) => this.requiredAbilities.filter((ability) => pokemon.getAbility().id === ability).length === 0);
|
return partyPokemon.filter((pokemon) =>
|
||||||
|
(!this.excludeDisallowedPokemon || pokemon.isAllowedInBattle())
|
||||||
|
&& this.requiredAbilities.filter((ability) => pokemon.hasAbility(ability, false)).length === 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
override getDialogueToken(_scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||||
if (pokemon?.getAbility().id && this.requiredAbilities.some(a => pokemon.getAbility().id === a)) {
|
const matchingAbility = this.requiredAbilities.find(a => pokemon?.hasAbility(a, false));
|
||||||
return [ "ability", pokemon.getAbility().name ];
|
if (!isNullOrUndefined(matchingAbility)) {
|
||||||
|
return [ "ability", allAbilities[matchingAbility].name ];
|
||||||
}
|
}
|
||||||
return [ "ability", "" ];
|
return [ "ability", "" ];
|
||||||
}
|
}
|
||||||
|
|
|
@ -325,7 +325,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
||||||
if (activeMon.length > 0) {
|
if (activeMon.length > 0) {
|
||||||
this.primaryPokemon = activeMon[0];
|
this.primaryPokemon = activeMon[0];
|
||||||
} else {
|
} else {
|
||||||
this.primaryPokemon = scene.getParty().filter(p => !p.isFainted())[0];
|
this.primaryPokemon = scene.getParty().filter(p => p.isAllowedInBattle())[0];
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { Status, StatusEffect } from "#app/data/status-effect";
|
||||||
import { TrainerConfig, trainerConfigs, TrainerSlot } from "#app/data/trainer-config";
|
import { TrainerConfig, trainerConfigs, TrainerSlot } from "#app/data/trainer-config";
|
||||||
import PokemonSpecies from "#app/data/pokemon-species";
|
import PokemonSpecies from "#app/data/pokemon-species";
|
||||||
import { Egg, IEggOptions } from "#app/data/egg";
|
import { Egg, IEggOptions } from "#app/data/egg";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
import HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||||
import { MovePhase } from "#app/phases/move-phase";
|
import { MovePhase } from "#app/phases/move-phase";
|
||||||
import { EggLapsePhase } from "#app/phases/egg-lapse-phase";
|
import { EggLapsePhase } from "#app/phases/egg-lapse-phase";
|
||||||
|
@ -71,7 +71,7 @@ export interface EnemyPokemonConfig {
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
bossSegments?: number;
|
bossSegments?: number;
|
||||||
bossSegmentModifier?: number; // Additive to the determined segment number
|
bossSegmentModifier?: number; // Additive to the determined segment number
|
||||||
mysteryEncounterPokemonData?: MysteryEncounterPokemonData;
|
customPokemonData?: CustomPokemonData;
|
||||||
formIndex?: number;
|
formIndex?: number;
|
||||||
abilityIndex?: number;
|
abilityIndex?: number;
|
||||||
level?: number;
|
level?: number;
|
||||||
|
@ -145,7 +145,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
||||||
newTrainer.setVisible(false);
|
newTrainer.setVisible(false);
|
||||||
scene.field.add(newTrainer);
|
scene.field.add(newTrainer);
|
||||||
scene.currentBattle.trainer = newTrainer;
|
scene.currentBattle.trainer = newTrainer;
|
||||||
loadEnemyAssets.push(newTrainer.loadAssets());
|
loadEnemyAssets.push(newTrainer.loadAssets().then(() => newTrainer.initSprite()));
|
||||||
|
|
||||||
battle.enemyLevels = scene.currentBattle.trainer.getPartyLevels(scene.currentBattle.waveIndex);
|
battle.enemyLevels = scene.currentBattle.trainer.getPartyLevels(scene.currentBattle.waveIndex);
|
||||||
} else {
|
} else {
|
||||||
|
@ -250,8 +250,8 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.customPokemonData)) {
|
||||||
enemyPokemon.mysteryEncounterPokemonData = config.mysteryEncounterPokemonData;
|
enemyPokemon.customPokemonData = config.customPokemonData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Boss
|
// Set Boss
|
||||||
|
|
|
@ -799,8 +799,8 @@ export const pokemonFormChanges: PokemonFormChanges = {
|
||||||
[Species.ZYGARDE]: [
|
[Species.ZYGARDE]: [
|
||||||
new SpeciesFormChange(Species.ZYGARDE, "50-pc", "complete", new SpeciesFormChangeManualTrigger(), true),
|
new SpeciesFormChange(Species.ZYGARDE, "50-pc", "complete", new SpeciesFormChangeManualTrigger(), true),
|
||||||
new SpeciesFormChange(Species.ZYGARDE, "complete", "50-pc", new SpeciesFormChangeManualTrigger(), true),
|
new SpeciesFormChange(Species.ZYGARDE, "complete", "50-pc", new SpeciesFormChangeManualTrigger(), true),
|
||||||
new SpeciesFormChange(Species.ZYGARDE, "10-pc", "complete", new SpeciesFormChangeManualTrigger(), true),
|
new SpeciesFormChange(Species.ZYGARDE, "10-pc", "10-complete", new SpeciesFormChangeManualTrigger(), true),
|
||||||
new SpeciesFormChange(Species.ZYGARDE, "complete", "10-pc", new SpeciesFormChangeManualTrigger(), true)
|
new SpeciesFormChange(Species.ZYGARDE, "10-complete", "10-pc", new SpeciesFormChangeManualTrigger(), true)
|
||||||
],
|
],
|
||||||
[Species.DIANCIE]: [
|
[Species.DIANCIE]: [
|
||||||
new SpeciesFormChange(Species.DIANCIE, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.DIANCITE))
|
new SpeciesFormChange(Species.DIANCIE, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.DIANCITE))
|
||||||
|
|
|
@ -425,6 +425,7 @@ export abstract class PokemonSpeciesForm {
|
||||||
case "hero":
|
case "hero":
|
||||||
case "roaming":
|
case "roaming":
|
||||||
case "complete":
|
case "complete":
|
||||||
|
case "10-complete":
|
||||||
case "10":
|
case "10":
|
||||||
case "10-pc":
|
case "10-pc":
|
||||||
case "super":
|
case "super":
|
||||||
|
@ -975,7 +976,7 @@ export function initSpecies() {
|
||||||
new PokemonSpecies(Species.VENUSAUR, 1, false, false, false, "Seed Pokémon", Type.GRASS, Type.POISON, 2, 100, Abilities.OVERGROW, Abilities.NONE, Abilities.CHLOROPHYLL, 525, 80, 82, 83, 100, 100, 80, 45, 50, 263, GrowthRate.MEDIUM_SLOW, 87.5, true, true,
|
new PokemonSpecies(Species.VENUSAUR, 1, false, false, false, "Seed Pokémon", Type.GRASS, Type.POISON, 2, 100, Abilities.OVERGROW, Abilities.NONE, Abilities.CHLOROPHYLL, 525, 80, 82, 83, 100, 100, 80, 45, 50, 263, GrowthRate.MEDIUM_SLOW, 87.5, true, true,
|
||||||
new PokemonForm("Normal", "", Type.GRASS, Type.POISON, 2, 100, Abilities.OVERGROW, Abilities.NONE, Abilities.CHLOROPHYLL, 525, 80, 82, 83, 100, 100, 80, 45, 50, 263, true, null, true),
|
new PokemonForm("Normal", "", Type.GRASS, Type.POISON, 2, 100, Abilities.OVERGROW, Abilities.NONE, Abilities.CHLOROPHYLL, 525, 80, 82, 83, 100, 100, 80, 45, 50, 263, true, null, true),
|
||||||
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.GRASS, Type.POISON, 2.4, 155.5, Abilities.THICK_FAT, Abilities.THICK_FAT, Abilities.THICK_FAT, 625, 80, 100, 123, 122, 120, 80, 45, 50, 263, true),
|
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.GRASS, Type.POISON, 2.4, 155.5, Abilities.THICK_FAT, Abilities.THICK_FAT, Abilities.THICK_FAT, 625, 80, 100, 123, 122, 120, 80, 45, 50, 263, true),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, Type.POISON, 24, 999.9, Abilities.EFFECT_SPORE, Abilities.EFFECT_SPORE, Abilities.EFFECT_SPORE, 625, 120, 82, 98, 130, 115, 80, 45, 50, 263, true),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, Type.POISON, 24, 999.9, Abilities.EFFECT_SPORE, Abilities.NONE, Abilities.EFFECT_SPORE, 625, 120, 82, 98, 130, 115, 80, 45, 50, 263, true),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.CHARMANDER, 1, false, false, false, "Lizard Pokémon", Type.FIRE, null, 0.6, 8.5, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 309, 39, 52, 43, 60, 50, 65, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
new PokemonSpecies(Species.CHARMANDER, 1, false, false, false, "Lizard Pokémon", Type.FIRE, null, 0.6, 8.5, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 309, 39, 52, 43, 60, 50, 65, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
||||||
new PokemonSpecies(Species.CHARMELEON, 1, false, false, false, "Flame Pokémon", Type.FIRE, null, 1.1, 19, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 405, 58, 64, 58, 80, 65, 80, 45, 50, 142, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
new PokemonSpecies(Species.CHARMELEON, 1, false, false, false, "Flame Pokémon", Type.FIRE, null, 1.1, 19, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 405, 58, 64, 58, 80, 65, 80, 45, 50, 142, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
||||||
|
@ -983,20 +984,20 @@ export function initSpecies() {
|
||||||
new PokemonForm("Normal", "", Type.FIRE, Type.FLYING, 1.7, 90.5, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 534, 78, 84, 78, 109, 85, 100, 45, 50, 267, false, null, true),
|
new PokemonForm("Normal", "", Type.FIRE, Type.FLYING, 1.7, 90.5, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 534, 78, 84, 78, 109, 85, 100, 45, 50, 267, false, null, true),
|
||||||
new PokemonForm("Mega X", SpeciesFormKey.MEGA_X, Type.FIRE, Type.DRAGON, 1.7, 110.5, Abilities.TOUGH_CLAWS, Abilities.NONE, Abilities.TOUGH_CLAWS, 634, 78, 130, 111, 130, 85, 100, 45, 50, 267),
|
new PokemonForm("Mega X", SpeciesFormKey.MEGA_X, Type.FIRE, Type.DRAGON, 1.7, 110.5, Abilities.TOUGH_CLAWS, Abilities.NONE, Abilities.TOUGH_CLAWS, 634, 78, 130, 111, 130, 85, 100, 45, 50, 267),
|
||||||
new PokemonForm("Mega Y", SpeciesFormKey.MEGA_Y, Type.FIRE, Type.FLYING, 1.7, 100.5, Abilities.DROUGHT, Abilities.NONE, Abilities.DROUGHT, 634, 78, 104, 78, 159, 115, 100, 45, 50, 267),
|
new PokemonForm("Mega Y", SpeciesFormKey.MEGA_Y, Type.FIRE, Type.FLYING, 1.7, 100.5, Abilities.DROUGHT, Abilities.NONE, Abilities.DROUGHT, 634, 78, 104, 78, 159, 115, 100, 45, 50, 267),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, Type.FLYING, 28, 999.9, Abilities.BERSERK, Abilities.BERSERK, Abilities.BERSERK, 634, 118, 84, 93, 139, 110, 100, 45, 50, 267),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, Type.FLYING, 28, 999.9, Abilities.BERSERK, Abilities.NONE, Abilities.BERSERK, 634, 118, 84, 93, 139, 100, 100, 45, 50, 267),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.SQUIRTLE, 1, false, false, false, "Tiny Turtle Pokémon", Type.WATER, null, 0.5, 9, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 314, 44, 48, 65, 50, 64, 43, 45, 50, 63, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
new PokemonSpecies(Species.SQUIRTLE, 1, false, false, false, "Tiny Turtle Pokémon", Type.WATER, null, 0.5, 9, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 314, 44, 48, 65, 50, 64, 43, 45, 50, 63, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
||||||
new PokemonSpecies(Species.WARTORTLE, 1, false, false, false, "Turtle Pokémon", Type.WATER, null, 1, 22.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 405, 59, 63, 80, 65, 80, 58, 45, 50, 142, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
new PokemonSpecies(Species.WARTORTLE, 1, false, false, false, "Turtle Pokémon", Type.WATER, null, 1, 22.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 405, 59, 63, 80, 65, 80, 58, 45, 50, 142, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
||||||
new PokemonSpecies(Species.BLASTOISE, 1, false, false, false, "Shellfish Pokémon", Type.WATER, null, 1.6, 85.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 530, 79, 83, 100, 85, 105, 78, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
|
new PokemonSpecies(Species.BLASTOISE, 1, false, false, false, "Shellfish Pokémon", Type.WATER, null, 1.6, 85.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 530, 79, 83, 100, 85, 105, 78, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
|
||||||
new PokemonForm("Normal", "", Type.WATER, null, 1.6, 85.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 530, 79, 83, 100, 85, 105, 78, 45, 50, 265, false, null, true),
|
new PokemonForm("Normal", "", Type.WATER, null, 1.6, 85.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 530, 79, 83, 100, 85, 105, 78, 45, 50, 265, false, null, true),
|
||||||
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.WATER, null, 1.6, 101.1, Abilities.MEGA_LAUNCHER, Abilities.NONE, Abilities.MEGA_LAUNCHER, 630, 79, 103, 120, 135, 115, 78, 45, 50, 265),
|
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.WATER, null, 1.6, 101.1, Abilities.MEGA_LAUNCHER, Abilities.NONE, Abilities.MEGA_LAUNCHER, 630, 79, 103, 120, 135, 115, 78, 45, 50, 265),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, Type.STEEL, 25, 999.9, Abilities.SHELL_ARMOR, Abilities.SHELL_ARMOR, Abilities.SHELL_ARMOR, 630, 119, 83, 135, 115, 110, 68, 45, 50, 265),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, Type.STEEL, 25, 999.9, Abilities.SHELL_ARMOR, Abilities.NONE, Abilities.SHELL_ARMOR, 630, 119, 83, 135, 115, 110, 68, 45, 50, 265),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.CATERPIE, 1, false, false, false, "Worm Pokémon", Type.BUG, null, 0.3, 2.9, Abilities.SHIELD_DUST, Abilities.NONE, Abilities.RUN_AWAY, 195, 45, 30, 35, 20, 20, 45, 255, 50, 39, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.CATERPIE, 1, false, false, false, "Worm Pokémon", Type.BUG, null, 0.3, 2.9, Abilities.SHIELD_DUST, Abilities.NONE, Abilities.RUN_AWAY, 195, 45, 30, 35, 20, 20, 45, 255, 50, 39, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(Species.METAPOD, 1, false, false, false, "Cocoon Pokémon", Type.BUG, null, 0.7, 9.9, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 50, 20, 55, 25, 25, 30, 120, 50, 72, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.METAPOD, 1, false, false, false, "Cocoon Pokémon", Type.BUG, null, 0.7, 9.9, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 50, 20, 55, 25, 25, 30, 120, 50, 72, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(Species.BUTTERFREE, 1, false, false, false, "Butterfly Pokémon", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, GrowthRate.MEDIUM_FAST, 50, true, true,
|
new PokemonSpecies(Species.BUTTERFREE, 1, false, false, false, "Butterfly Pokémon", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, GrowthRate.MEDIUM_FAST, 50, true, true,
|
||||||
new PokemonForm("Normal", "", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, true, null, true),
|
new PokemonForm("Normal", "", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, true, null, true),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.BUG, Type.FLYING, 17, 999.9, Abilities.COMPOUND_EYES, Abilities.COMPOUND_EYES, Abilities.COMPOUND_EYES, 495, 85, 35, 80, 120, 90, 85, 45, 50, 198, true),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.BUG, Type.FLYING, 17, 999.9, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.COMPOUND_EYES, 495, 85, 35, 80, 120, 90, 85, 45, 50, 198, true),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.WEEDLE, 1, false, false, false, "Hairy Bug Pokémon", Type.BUG, Type.POISON, 0.3, 3.2, Abilities.SHIELD_DUST, Abilities.NONE, Abilities.RUN_AWAY, 195, 40, 35, 30, 20, 20, 50, 255, 70, 39, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.WEEDLE, 1, false, false, false, "Hairy Bug Pokémon", Type.BUG, Type.POISON, 0.3, 3.2, Abilities.SHIELD_DUST, Abilities.NONE, Abilities.RUN_AWAY, 195, 40, 35, 30, 20, 20, 50, 255, 70, 39, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(Species.KAKUNA, 1, false, false, false, "Cocoon Pokémon", Type.BUG, Type.POISON, 0.6, 10, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 45, 25, 50, 25, 25, 35, 120, 70, 72, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.KAKUNA, 1, false, false, false, "Cocoon Pokémon", Type.BUG, Type.POISON, 0.6, 10, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 45, 25, 50, 25, 25, 35, 120, 70, 72, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
|
@ -1025,7 +1026,7 @@ export function initSpecies() {
|
||||||
new PokemonForm("Cute Cosplay", "cute-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
|
new PokemonForm("Cute Cosplay", "cute-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
|
||||||
new PokemonForm("Smart Cosplay", "smart-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
|
new PokemonForm("Smart Cosplay", "smart-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
|
||||||
new PokemonForm("Tough Cosplay", "tough-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
|
new PokemonForm("Tough Cosplay", "tough-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.ELECTRIC, null, 21, 999.9, Abilities.LIGHTNING_ROD, Abilities.LIGHTNING_ROD, Abilities.LIGHTNING_ROD, 530, 125, 95, 60, 90, 70, 90, 190, 50, 112), //+100 BST from Partner Form
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.ELECTRIC, null, 21, 999.9, Abilities.LIGHTNING_ROD, Abilities.NONE, Abilities.LIGHTNING_ROD, 530, 125, 95, 60, 90, 70, 90, 190, 50, 112), //+100 BST from Partner Form
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.RAICHU, 1, false, false, false, "Mouse Pokémon", Type.ELECTRIC, null, 0.8, 30, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 485, 60, 90, 55, 90, 80, 110, 75, 50, 243, GrowthRate.MEDIUM_FAST, 50, true),
|
new PokemonSpecies(Species.RAICHU, 1, false, false, false, "Mouse Pokémon", Type.ELECTRIC, null, 0.8, 30, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 485, 60, 90, 55, 90, 80, 110, 75, 50, 243, GrowthRate.MEDIUM_FAST, 50, true),
|
||||||
new PokemonSpecies(Species.SANDSHREW, 1, false, false, false, "Mouse Pokémon", Type.GROUND, null, 0.6, 12, Abilities.SAND_VEIL, Abilities.NONE, Abilities.SAND_RUSH, 300, 50, 75, 85, 20, 30, 40, 255, 50, 60, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.SANDSHREW, 1, false, false, false, "Mouse Pokémon", Type.GROUND, null, 0.6, 12, Abilities.SAND_VEIL, Abilities.NONE, Abilities.SAND_RUSH, 300, 50, 75, 85, 20, 30, 40, 255, 50, 60, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
|
@ -1110,7 +1111,7 @@ export function initSpecies() {
|
||||||
new PokemonSpecies(Species.GENGAR, 1, false, false, false, "Shadow Pokémon", Type.GHOST, Type.POISON, 1.5, 40.5, Abilities.CURSED_BODY, Abilities.NONE, Abilities.NONE, 500, 60, 65, 60, 130, 75, 110, 45, 50, 250, GrowthRate.MEDIUM_SLOW, 50, false, true,
|
new PokemonSpecies(Species.GENGAR, 1, false, false, false, "Shadow Pokémon", Type.GHOST, Type.POISON, 1.5, 40.5, Abilities.CURSED_BODY, Abilities.NONE, Abilities.NONE, 500, 60, 65, 60, 130, 75, 110, 45, 50, 250, GrowthRate.MEDIUM_SLOW, 50, false, true,
|
||||||
new PokemonForm("Normal", "", Type.GHOST, Type.POISON, 1.5, 40.5, Abilities.CURSED_BODY, Abilities.NONE, Abilities.NONE, 500, 60, 65, 60, 130, 75, 110, 45, 50, 250, false, null, true),
|
new PokemonForm("Normal", "", Type.GHOST, Type.POISON, 1.5, 40.5, Abilities.CURSED_BODY, Abilities.NONE, Abilities.NONE, 500, 60, 65, 60, 130, 75, 110, 45, 50, 250, false, null, true),
|
||||||
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.GHOST, Type.POISON, 1.4, 40.5, Abilities.SHADOW_TAG, Abilities.NONE, Abilities.NONE, 600, 60, 65, 80, 170, 95, 130, 45, 50, 250),
|
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.GHOST, Type.POISON, 1.4, 40.5, Abilities.SHADOW_TAG, Abilities.NONE, Abilities.NONE, 600, 60, 65, 80, 170, 95, 130, 45, 50, 250),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GHOST, Type.POISON, 20, 999.9, Abilities.CURSED_BODY, Abilities.CURSED_BODY, Abilities.CURSED_BODY, 600, 140, 65, 70, 140, 85, 100, 45, 50, 250),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GHOST, Type.POISON, 20, 999.9, Abilities.CURSED_BODY, Abilities.NONE, Abilities.NONE, 600, 140, 65, 70, 140, 85, 100, 45, 50, 250),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.ONIX, 1, false, false, false, "Rock Snake Pokémon", Type.ROCK, Type.GROUND, 8.8, 210, Abilities.ROCK_HEAD, Abilities.STURDY, Abilities.WEAK_ARMOR, 385, 35, 45, 160, 30, 45, 70, 45, 50, 77, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.ONIX, 1, false, false, false, "Rock Snake Pokémon", Type.ROCK, Type.GROUND, 8.8, 210, Abilities.ROCK_HEAD, Abilities.STURDY, Abilities.WEAK_ARMOR, 385, 35, 45, 160, 30, 45, 70, 45, 50, 77, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(Species.DROWZEE, 1, false, false, false, "Hypnosis Pokémon", Type.PSYCHIC, null, 1, 32.4, Abilities.INSOMNIA, Abilities.FOREWARN, Abilities.INNER_FOCUS, 328, 60, 48, 45, 43, 90, 42, 190, 70, 66, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.DROWZEE, 1, false, false, false, "Hypnosis Pokémon", Type.PSYCHIC, null, 1, 32.4, Abilities.INSOMNIA, Abilities.FOREWARN, Abilities.INNER_FOCUS, 328, 60, 48, 45, 43, 90, 42, 190, 70, 66, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
|
@ -1118,7 +1119,7 @@ export function initSpecies() {
|
||||||
new PokemonSpecies(Species.KRABBY, 1, false, false, false, "River Crab Pokémon", Type.WATER, null, 0.4, 6.5, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 325, 30, 105, 90, 25, 25, 50, 225, 50, 65, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.KRABBY, 1, false, false, false, "River Crab Pokémon", Type.WATER, null, 0.4, 6.5, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 325, 30, 105, 90, 25, 25, 50, 225, 50, 65, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(Species.KINGLER, 1, false, false, false, "Pincer Pokémon", Type.WATER, null, 1.3, 60, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 475, 55, 130, 115, 50, 50, 75, 60, 50, 166, GrowthRate.MEDIUM_FAST, 50, false, true,
|
new PokemonSpecies(Species.KINGLER, 1, false, false, false, "Pincer Pokémon", Type.WATER, null, 1.3, 60, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 475, 55, 130, 115, 50, 50, 75, 60, 50, 166, GrowthRate.MEDIUM_FAST, 50, false, true,
|
||||||
new PokemonForm("Normal", "", Type.WATER, null, 1.3, 60, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 475, 55, 130, 115, 50, 50, 75, 60, 50, 166, false, null, true),
|
new PokemonForm("Normal", "", Type.WATER, null, 1.3, 60, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 475, 55, 130, 115, 50, 50, 75, 60, 50, 166, false, null, true),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 19, 999.9, Abilities.TOUGH_CLAWS, Abilities.TOUGH_CLAWS, Abilities.TOUGH_CLAWS, 575, 90, 155, 140, 50, 80, 70, 60, 50, 166),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 19, 999.9, Abilities.TOUGH_CLAWS, Abilities.TOUGH_CLAWS, Abilities.TOUGH_CLAWS, 575, 90, 155, 140, 50, 70, 70, 60, 50, 166),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.VOLTORB, 1, false, false, false, "Ball Pokémon", Type.ELECTRIC, null, 0.5, 10.4, Abilities.SOUNDPROOF, Abilities.STATIC, Abilities.AFTERMATH, 330, 40, 30, 50, 55, 55, 100, 190, 70, 66, GrowthRate.MEDIUM_FAST, null, false),
|
new PokemonSpecies(Species.VOLTORB, 1, false, false, false, "Ball Pokémon", Type.ELECTRIC, null, 0.5, 10.4, Abilities.SOUNDPROOF, Abilities.STATIC, Abilities.AFTERMATH, 330, 40, 30, 50, 55, 55, 100, 190, 70, 66, GrowthRate.MEDIUM_FAST, null, false),
|
||||||
new PokemonSpecies(Species.ELECTRODE, 1, false, false, false, "Ball Pokémon", Type.ELECTRIC, null, 1.2, 66.6, Abilities.SOUNDPROOF, Abilities.STATIC, Abilities.AFTERMATH, 490, 60, 50, 70, 80, 80, 150, 60, 70, 172, GrowthRate.MEDIUM_FAST, null, false),
|
new PokemonSpecies(Species.ELECTRODE, 1, false, false, false, "Ball Pokémon", Type.ELECTRIC, null, 1.2, 66.6, Abilities.SOUNDPROOF, Abilities.STATIC, Abilities.AFTERMATH, 490, 60, 50, 70, 80, 80, 150, 60, 70, 172, GrowthRate.MEDIUM_FAST, null, false),
|
||||||
|
@ -2135,7 +2136,8 @@ export function initSpecies() {
|
||||||
new PokemonForm("10% Forme", "10", Type.DRAGON, Type.GROUND, 1.2, 33.5, Abilities.AURA_BREAK, Abilities.NONE, Abilities.NONE, 486, 54, 100, 71, 61, 85, 115, 3, 0, 300, false, null, true),
|
new PokemonForm("10% Forme", "10", Type.DRAGON, Type.GROUND, 1.2, 33.5, Abilities.AURA_BREAK, Abilities.NONE, Abilities.NONE, 486, 54, 100, 71, 61, 85, 115, 3, 0, 300, false, null, true),
|
||||||
new PokemonForm("50% Forme Power Construct", "50-pc", Type.DRAGON, Type.GROUND, 5, 305, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 600, 108, 100, 121, 81, 95, 95, 3, 0, 300, false, "", true),
|
new PokemonForm("50% Forme Power Construct", "50-pc", Type.DRAGON, Type.GROUND, 5, 305, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 600, 108, 100, 121, 81, 95, 95, 3, 0, 300, false, "", true),
|
||||||
new PokemonForm("10% Forme Power Construct", "10-pc", Type.DRAGON, Type.GROUND, 1.2, 33.5, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 486, 54, 100, 71, 61, 85, 115, 3, 0, 300, false, "10", true),
|
new PokemonForm("10% Forme Power Construct", "10-pc", Type.DRAGON, Type.GROUND, 1.2, 33.5, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 486, 54, 100, 71, 61, 85, 115, 3, 0, 300, false, "10", true),
|
||||||
new PokemonForm("Complete Forme", "complete", Type.DRAGON, Type.GROUND, 4.5, 610, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 708, 216, 100, 121, 91, 95, 85, 3, 0, 300),
|
new PokemonForm("Complete Forme (50% PC)", "complete", Type.DRAGON, Type.GROUND, 4.5, 610, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 708, 216, 100, 121, 91, 95, 85, 3, 0, 300),
|
||||||
|
new PokemonForm("Complete Forme (10% PC)", "10-complete", Type.DRAGON, Type.GROUND, 4.5, 610, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 708, 216, 100, 121, 91, 95, 85, 3, 0, 300, false, "complete"),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.DIANCIE, 6, false, false, true, "Jewel Pokémon", Type.ROCK, Type.FAIRY, 0.7, 8.8, Abilities.CLEAR_BODY, Abilities.NONE, Abilities.NONE, 600, 50, 100, 150, 100, 150, 50, 3, 50, 300, GrowthRate.SLOW, null, false, true,
|
new PokemonSpecies(Species.DIANCIE, 6, false, false, true, "Jewel Pokémon", Type.ROCK, Type.FAIRY, 0.7, 8.8, Abilities.CLEAR_BODY, Abilities.NONE, Abilities.NONE, 600, 50, 100, 150, 100, 150, 50, 3, 50, 300, GrowthRate.SLOW, null, false, true,
|
||||||
new PokemonForm("Normal", "", Type.ROCK, Type.FAIRY, 0.7, 8.8, Abilities.CLEAR_BODY, Abilities.NONE, Abilities.NONE, 600, 50, 100, 150, 100, 150, 50, 3, 50, 300, false, null, true),
|
new PokemonForm("Normal", "", Type.ROCK, Type.FAIRY, 0.7, 8.8, Abilities.CLEAR_BODY, Abilities.NONE, Abilities.NONE, 600, 50, 100, 150, 100, 150, 50, 3, 50, 300, false, null, true),
|
||||||
|
@ -2298,25 +2300,25 @@ export function initSpecies() {
|
||||||
new PokemonSpecies(Species.MELTAN, 7, false, false, true, "Hex Nut Pokémon", Type.STEEL, null, 0.2, 8, Abilities.MAGNET_PULL, Abilities.NONE, Abilities.NONE, 300, 46, 65, 65, 55, 35, 34, 3, 0, 150, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(Species.MELTAN, 7, false, false, true, "Hex Nut Pokémon", Type.STEEL, null, 0.2, 8, Abilities.MAGNET_PULL, Abilities.NONE, Abilities.NONE, 300, 46, 65, 65, 55, 35, 34, 3, 0, 150, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(Species.MELMETAL, 7, false, false, true, "Hex Nut Pokémon", Type.STEEL, null, 2.5, 800, Abilities.IRON_FIST, Abilities.NONE, Abilities.NONE, 600, 135, 143, 143, 80, 65, 34, 3, 0, 300, GrowthRate.SLOW, null, false, true,
|
new PokemonSpecies(Species.MELMETAL, 7, false, false, true, "Hex Nut Pokémon", Type.STEEL, null, 2.5, 800, Abilities.IRON_FIST, Abilities.NONE, Abilities.NONE, 600, 135, 143, 143, 80, 65, 34, 3, 0, 300, GrowthRate.SLOW, null, false, true,
|
||||||
new PokemonForm("Normal", "", Type.STEEL, null, 2.5, 800, Abilities.IRON_FIST, Abilities.NONE, Abilities.NONE, 600, 135, 143, 143, 80, 65, 34, 3, 0, 300, false, null, true),
|
new PokemonForm("Normal", "", Type.STEEL, null, 2.5, 800, Abilities.IRON_FIST, Abilities.NONE, Abilities.NONE, 600, 135, 143, 143, 80, 65, 34, 3, 0, 300, false, null, true),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, null, 25, 999.9, Abilities.IRON_FIST, Abilities.IRON_FIST, Abilities.IRON_FIST, 700, 175, 165, 155, 85, 75, 45, 3, 0, 300),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, null, 25, 999.9, Abilities.IRON_FIST, Abilities.NONE, Abilities.NONE, 700, 175, 165, 155, 85, 75, 45, 3, 0, 300),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.GROOKEY, 8, false, false, false, "Chimp Pokémon", Type.GRASS, null, 0.3, 5, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 310, 50, 65, 50, 40, 40, 65, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
new PokemonSpecies(Species.GROOKEY, 8, false, false, false, "Chimp Pokémon", Type.GRASS, null, 0.3, 5, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 310, 50, 65, 50, 40, 40, 65, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
||||||
new PokemonSpecies(Species.THWACKEY, 8, false, false, false, "Beat Pokémon", Type.GRASS, null, 0.7, 14, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 420, 70, 85, 70, 55, 60, 80, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
new PokemonSpecies(Species.THWACKEY, 8, false, false, false, "Beat Pokémon", Type.GRASS, null, 0.7, 14, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 420, 70, 85, 70, 55, 60, 80, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
||||||
new PokemonSpecies(Species.RILLABOOM, 8, false, false, false, "Drummer Pokémon", Type.GRASS, null, 2.1, 90, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 530, 100, 125, 90, 60, 70, 85, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
|
new PokemonSpecies(Species.RILLABOOM, 8, false, false, false, "Drummer Pokémon", Type.GRASS, null, 2.1, 90, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 530, 100, 125, 90, 60, 70, 85, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
|
||||||
new PokemonForm("Normal", "", Type.GRASS, null, 2.1, 90, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 530, 100, 125, 90, 60, 70, 85, 45, 50, 265, false, null, true),
|
new PokemonForm("Normal", "", Type.GRASS, null, 2.1, 90, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 530, 100, 125, 90, 60, 70, 85, 45, 50, 265, false, null, true),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, null, 28, 999.9, Abilities.GRASSY_SURGE, Abilities.GRASSY_SURGE, Abilities.GRASSY_SURGE, 630, 125, 150, 105, 85, 85, 80, 45, 50, 265),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, null, 28, 999.9, Abilities.GRASSY_SURGE, Abilities.NONE, Abilities.GRASSY_SURGE, 630, 125, 150, 105, 85, 85, 80, 45, 50, 265),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.SCORBUNNY, 8, false, false, false, "Rabbit Pokémon", Type.FIRE, null, 0.3, 4.5, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 310, 50, 71, 40, 40, 40, 69, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
new PokemonSpecies(Species.SCORBUNNY, 8, false, false, false, "Rabbit Pokémon", Type.FIRE, null, 0.3, 4.5, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 310, 50, 71, 40, 40, 40, 69, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
||||||
new PokemonSpecies(Species.RABOOT, 8, false, false, false, "Rabbit Pokémon", Type.FIRE, null, 0.6, 9, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 420, 65, 86, 60, 55, 60, 94, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
new PokemonSpecies(Species.RABOOT, 8, false, false, false, "Rabbit Pokémon", Type.FIRE, null, 0.6, 9, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 420, 65, 86, 60, 55, 60, 94, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
||||||
new PokemonSpecies(Species.CINDERACE, 8, false, false, false, "Striker Pokémon", Type.FIRE, null, 1.4, 33, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 530, 80, 116, 75, 65, 75, 119, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
|
new PokemonSpecies(Species.CINDERACE, 8, false, false, false, "Striker Pokémon", Type.FIRE, null, 1.4, 33, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 530, 80, 116, 75, 65, 75, 119, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
|
||||||
new PokemonForm("Normal", "", Type.FIRE, null, 1.4, 33, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 530, 80, 116, 75, 65, 75, 119, 45, 50, 265, false, null, true),
|
new PokemonForm("Normal", "", Type.FIRE, null, 1.4, 33, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 530, 80, 116, 75, 65, 75, 119, 45, 50, 265, false, null, true),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, null, 27, 999.9, Abilities.LIBERO, Abilities.LIBERO, Abilities.LIBERO, 630, 100, 146, 80, 90, 80, 134, 45, 50, 265),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, null, 27, 999.9, Abilities.LIBERO, Abilities.NONE, Abilities.LIBERO, 630, 100, 146, 80, 90, 80, 134, 45, 50, 265),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.SOBBLE, 8, false, false, false, "Water Lizard Pokémon", Type.WATER, null, 0.3, 4, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 310, 50, 40, 40, 70, 40, 70, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
new PokemonSpecies(Species.SOBBLE, 8, false, false, false, "Water Lizard Pokémon", Type.WATER, null, 0.3, 4, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 310, 50, 40, 40, 70, 40, 70, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
||||||
new PokemonSpecies(Species.DRIZZILE, 8, false, false, false, "Water Lizard Pokémon", Type.WATER, null, 0.7, 11.5, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 420, 65, 60, 55, 95, 55, 90, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
new PokemonSpecies(Species.DRIZZILE, 8, false, false, false, "Water Lizard Pokémon", Type.WATER, null, 0.7, 11.5, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 420, 65, 60, 55, 95, 55, 90, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
||||||
new PokemonSpecies(Species.INTELEON, 8, false, false, false, "Secret Agent Pokémon", Type.WATER, null, 1.9, 45.2, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 530, 70, 85, 65, 125, 65, 120, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
|
new PokemonSpecies(Species.INTELEON, 8, false, false, false, "Secret Agent Pokémon", Type.WATER, null, 1.9, 45.2, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 530, 70, 85, 65, 125, 65, 120, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
|
||||||
new PokemonForm("Normal", "", Type.WATER, null, 1.9, 45.2, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 530, 70, 85, 65, 125, 65, 120, 45, 50, 265, false, null, true),
|
new PokemonForm("Normal", "", Type.WATER, null, 1.9, 45.2, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 530, 70, 85, 65, 125, 65, 120, 45, 50, 265, false, null, true),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 40, 999.9, Abilities.SNIPER, Abilities.SNIPER, Abilities.SNIPER, 630, 95, 97, 77, 147, 77, 137, 45, 50, 265),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 40, 999.9, Abilities.SNIPER, Abilities.NONE, Abilities.SNIPER, 630, 95, 97, 77, 147, 77, 137, 45, 50, 265),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.SKWOVET, 8, false, false, false, "Cheeky Pokémon", Type.NORMAL, null, 0.3, 2.5, Abilities.CHEEK_POUCH, Abilities.NONE, Abilities.GLUTTONY, 275, 70, 55, 55, 35, 35, 25, 255, 50, 55, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.SKWOVET, 8, false, false, false, "Cheeky Pokémon", Type.NORMAL, null, 0.3, 2.5, Abilities.CHEEK_POUCH, Abilities.NONE, Abilities.GLUTTONY, 275, 70, 55, 55, 35, 35, 25, 255, 50, 55, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(Species.GREEDENT, 8, false, false, false, "Greedy Pokémon", Type.NORMAL, null, 0.6, 6, Abilities.CHEEK_POUCH, Abilities.NONE, Abilities.GLUTTONY, 460, 120, 95, 95, 55, 75, 20, 90, 50, 161, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.GREEDENT, 8, false, false, false, "Greedy Pokémon", Type.NORMAL, null, 0.6, 6, Abilities.CHEEK_POUCH, Abilities.NONE, Abilities.GLUTTONY, 460, 120, 95, 95, 55, 75, 20, 90, 50, 161, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
|
@ -2422,7 +2424,7 @@ export function initSpecies() {
|
||||||
new PokemonForm("Ruby Swirl", "ruby-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true),
|
new PokemonForm("Ruby Swirl", "ruby-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true),
|
||||||
new PokemonForm("Caramel Swirl", "caramel-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true),
|
new PokemonForm("Caramel Swirl", "caramel-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true),
|
||||||
new PokemonForm("Rainbow Swirl", "rainbow-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true),
|
new PokemonForm("Rainbow Swirl", "rainbow-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FAIRY, null, 30, 999.9, Abilities.MISTY_SURGE, Abilities.MISTY_SURGE, Abilities.MISTY_SURGE, 595, 135, 60, 75, 130, 131, 64, 100, 50, 173),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FAIRY, null, 30, 999.9, Abilities.MISTY_SURGE, Abilities.NONE, Abilities.MISTY_SURGE, 595, 135, 60, 75, 130, 131, 64, 100, 50, 173),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.FALINKS, 8, false, false, false, "Formation Pokémon", Type.FIGHTING, null, 3, 62, Abilities.BATTLE_ARMOR, Abilities.NONE, Abilities.DEFIANT, 470, 65, 100, 100, 70, 60, 75, 45, 50, 165, GrowthRate.MEDIUM_FAST, null, false),
|
new PokemonSpecies(Species.FALINKS, 8, false, false, false, "Formation Pokémon", Type.FIGHTING, null, 3, 62, Abilities.BATTLE_ARMOR, Abilities.NONE, Abilities.DEFIANT, 470, 65, 100, 100, 70, 60, 75, 45, 50, 165, GrowthRate.MEDIUM_FAST, null, false),
|
||||||
new PokemonSpecies(Species.PINCURCHIN, 8, false, false, false, "Sea Urchin Pokémon", Type.ELECTRIC, null, 0.3, 1, Abilities.LIGHTNING_ROD, Abilities.NONE, Abilities.ELECTRIC_SURGE, 435, 48, 101, 95, 91, 85, 15, 75, 50, 152, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.PINCURCHIN, 8, false, false, false, "Sea Urchin Pokémon", Type.ELECTRIC, null, 0.3, 1, Abilities.LIGHTNING_ROD, Abilities.NONE, Abilities.ELECTRIC_SURGE, 435, 48, 101, 95, 91, 85, 15, 75, 50, 152, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
|
@ -2444,7 +2446,7 @@ export function initSpecies() {
|
||||||
new PokemonSpecies(Species.CUFANT, 8, false, false, false, "Copperderm Pokémon", Type.STEEL, null, 1.2, 100, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 330, 72, 80, 49, 40, 49, 40, 190, 50, 66, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.CUFANT, 8, false, false, false, "Copperderm Pokémon", Type.STEEL, null, 1.2, 100, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 330, 72, 80, 49, 40, 49, 40, 190, 50, 66, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(Species.COPPERAJAH, 8, false, false, false, "Copperderm Pokémon", Type.STEEL, null, 3, 650, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 500, 122, 130, 69, 80, 69, 30, 90, 50, 175, GrowthRate.MEDIUM_FAST, 50, false, true,
|
new PokemonSpecies(Species.COPPERAJAH, 8, false, false, false, "Copperderm Pokémon", Type.STEEL, null, 3, 650, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 500, 122, 130, 69, 80, 69, 30, 90, 50, 175, GrowthRate.MEDIUM_FAST, 50, false, true,
|
||||||
new PokemonForm("Normal", "", Type.STEEL, null, 3, 650, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 500, 122, 130, 69, 80, 69, 30, 90, 50, 175, false, null, true),
|
new PokemonForm("Normal", "", Type.STEEL, null, 3, 650, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 500, 122, 130, 69, 80, 69, 30, 90, 50, 175, false, null, true),
|
||||||
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, Type.GROUND, 23, 999.9, Abilities.MOLD_BREAKER, Abilities.MOLD_BREAKER, Abilities.MOLD_BREAKER, 600, 167, 155, 89, 80, 89, 20, 90, 50, 175),
|
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, Type.GROUND, 23, 999.9, Abilities.MOLD_BREAKER, Abilities.NONE, Abilities.MOLD_BREAKER, 600, 167, 155, 89, 80, 89, 20, 90, 50, 175),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.DRACOZOLT, 8, false, false, false, "Fossil Pokémon", Type.ELECTRIC, Type.DRAGON, 1.8, 190, Abilities.VOLT_ABSORB, Abilities.HUSTLE, Abilities.SAND_RUSH, 505, 90, 100, 90, 80, 70, 75, 45, 50, 177, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(Species.DRACOZOLT, 8, false, false, false, "Fossil Pokémon", Type.ELECTRIC, Type.DRAGON, 1.8, 190, Abilities.VOLT_ABSORB, Abilities.HUSTLE, Abilities.SAND_RUSH, 505, 90, 100, 90, 80, 70, 75, 45, 50, 177, GrowthRate.SLOW, null, false),
|
||||||
new PokemonSpecies(Species.ARCTOZOLT, 8, false, false, false, "Fossil Pokémon", Type.ELECTRIC, Type.ICE, 2.3, 150, Abilities.VOLT_ABSORB, Abilities.STATIC, Abilities.SLUSH_RUSH, 505, 90, 100, 90, 90, 80, 55, 45, 50, 177, GrowthRate.SLOW, null, false),
|
new PokemonSpecies(Species.ARCTOZOLT, 8, false, false, false, "Fossil Pokémon", Type.ELECTRIC, Type.ICE, 2.3, 150, Abilities.VOLT_ABSORB, Abilities.STATIC, Abilities.SLUSH_RUSH, 505, 90, 100, 90, 90, 80, 55, 45, 50, 177, GrowthRate.SLOW, null, false),
|
||||||
|
|
|
@ -574,13 +574,13 @@ export class TrainerConfig {
|
||||||
case "magma": {
|
case "magma": {
|
||||||
return {
|
return {
|
||||||
[TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.SLUGMA, Species.SOLROCK, Species.HIPPOPOTAS, Species.BALTOY, Species.ROLYCOLY, Species.GLIGAR, Species.TORKOAL, Species.HOUNDOUR, Species.MAGBY ],
|
[TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.SLUGMA, Species.SOLROCK, Species.HIPPOPOTAS, Species.BALTOY, Species.ROLYCOLY, Species.GLIGAR, Species.TORKOAL, Species.HOUNDOUR, Species.MAGBY ],
|
||||||
[TrainerPoolTier.UNCOMMON]: [ Species.TRAPINCH, Species.SILICOBRA, Species.RHYHORN, Species.ANORITH, Species.LILEEP, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON, Species.BARBOACH ],
|
[TrainerPoolTier.UNCOMMON]: [ Species.TRAPINCH, Species.SILICOBRA, Species.RHYHORN, Species.ANORITH, Species.LILEEP, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON, Species.TOEDSCOOL ],
|
||||||
[TrainerPoolTier.RARE]: [ Species.CAPSAKID, Species.CHARCADET ]
|
[TrainerPoolTier.RARE]: [ Species.CAPSAKID, Species.CHARCADET ]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case "aqua": {
|
case "aqua": {
|
||||||
return {
|
return {
|
||||||
[TrainerPoolTier.COMMON]: [ Species.CORPHISH, Species.SPHEAL, Species.CLAMPERL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL, Species.AZURILL, Species.LOTAD, Species.WAILMER, Species.REMORAID ],
|
[TrainerPoolTier.COMMON]: [ Species.CORPHISH, Species.SPHEAL, Species.CLAMPERL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL, Species.AZURILL, Species.LOTAD, Species.WAILMER, Species.REMORAID, Species.BARBOACH ],
|
||||||
[TrainerPoolTier.UNCOMMON]: [ Species.MANTYKE, Species.HISUI_QWILFISH, Species.ARROKUDA, Species.DHELMISE, Species.CLOBBOPUS, Species.FEEBAS, Species.PALDEA_WOOPER, Species.HORSEA, Species.SKRELP ],
|
[TrainerPoolTier.UNCOMMON]: [ Species.MANTYKE, Species.HISUI_QWILFISH, Species.ARROKUDA, Species.DHELMISE, Species.CLOBBOPUS, Species.FEEBAS, Species.PALDEA_WOOPER, Species.HORSEA, Species.SKRELP ],
|
||||||
[TrainerPoolTier.RARE]: [ Species.DONDOZO, Species.BASCULEGION ]
|
[TrainerPoolTier.RARE]: [ Species.DONDOZO, Species.BASCULEGION ]
|
||||||
};
|
};
|
||||||
|
@ -601,9 +601,9 @@ export class TrainerConfig {
|
||||||
}
|
}
|
||||||
case "flare": {
|
case "flare": {
|
||||||
return {
|
return {
|
||||||
[TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.INKAY, Species.HELIOPTILE, Species.ELECTRIKE, Species.SKORUPI, Species.PURRLOIN, Species.CLAWITZER, Species.PANCHAM, Species.ESPURR, Species.BUNNELBY ],
|
[TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.INKAY, Species.FOONGUS, Species.HELIOPTILE, Species.ELECTRIKE, Species.SKORUPI, Species.PURRLOIN, Species.CLAWITZER, Species.PANCHAM, Species.ESPURR, Species.BUNNELBY ],
|
||||||
[TrainerPoolTier.UNCOMMON]: [ Species.LITWICK, Species.SNEASEL, Species.PUMPKABOO, Species.PHANTUMP, Species.HONEDGE, Species.BINACLE, Species.HOUNDOUR, Species.SKRELP, Species.SLIGGOO ],
|
[TrainerPoolTier.UNCOMMON]: [ Species.LITWICK, Species.SNEASEL, Species.PUMPKABOO, Species.PHANTUMP, Species.HONEDGE, Species.BINACLE, Species.HOUNDOUR, Species.SKRELP, Species.SLIGGOO ],
|
||||||
[TrainerPoolTier.RARE]: [ Species.NOIVERN, Species.HISUI_AVALUGG, Species.HISUI_SLIGGOO ]
|
[TrainerPoolTier.RARE]: [ Species.NOIBAT, Species.HISUI_AVALUGG, Species.HISUI_SLIGGOO ]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case "aether": {
|
case "aether": {
|
||||||
|
@ -1504,7 +1504,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
.setSpeciesPools({
|
.setSpeciesPools({
|
||||||
[TrainerPoolTier.COMMON]: [ Species.SLUGMA, Species.POOCHYENA, Species.NUMEL, Species.ZIGZAGOON, Species.DIGLETT, Species.MAGBY, Species.TORKOAL, Species.GROWLITHE, Species.BALTOY ],
|
[TrainerPoolTier.COMMON]: [ Species.SLUGMA, Species.POOCHYENA, Species.NUMEL, Species.ZIGZAGOON, Species.DIGLETT, Species.MAGBY, Species.TORKOAL, Species.GROWLITHE, Species.BALTOY ],
|
||||||
[TrainerPoolTier.UNCOMMON]: [ Species.SOLROCK, Species.HIPPOPOTAS, Species.SANDACONDA, Species.PHANPY, Species.ROLYCOLY, Species.GLIGAR, Species.RHYHORN, Species.HEATMOR ],
|
[TrainerPoolTier.UNCOMMON]: [ Species.SOLROCK, Species.HIPPOPOTAS, Species.SANDACONDA, Species.PHANPY, Species.ROLYCOLY, Species.GLIGAR, Species.RHYHORN, Species.HEATMOR ],
|
||||||
[TrainerPoolTier.RARE]: [ Species.TRAPINCH, Species.LILEEP, Species.ANORITH, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON ],
|
[TrainerPoolTier.RARE]: [ Species.TRAPINCH, Species.LILEEP, Species.ANORITH, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON, Species.TOEDSCOOL ],
|
||||||
[TrainerPoolTier.SUPER_RARE]: [ Species.CAPSAKID, Species.CHARCADET ]
|
[TrainerPoolTier.SUPER_RARE]: [ Species.CAPSAKID, Species.CHARCADET ]
|
||||||
}),
|
}),
|
||||||
[TrainerType.TABITHA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("magma_admin", "magma", [ Species.CAMERUPT ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)),
|
[TrainerType.TABITHA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("magma_admin", "magma", [ Species.CAMERUPT ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)),
|
||||||
|
@ -1540,9 +1540,9 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
[TrainerType.FLARE_GRUNT]: new TrainerConfig(++t).setHasGenders("Flare Grunt Female").setHasDouble("Flare Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
|
[TrainerType.FLARE_GRUNT]: new TrainerConfig(++t).setHasGenders("Flare Grunt Female").setHasDouble("Flare Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
|
||||||
.setSpeciesPools({
|
.setSpeciesPools({
|
||||||
[TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.PONYTA, Species.INKAY, Species.HOUNDOUR, Species.SKORUPI, Species.SCRAFTY, Species.CROAGUNK, Species.SCATTERBUG, Species.ESPURR ],
|
[TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.PONYTA, Species.INKAY, Species.HOUNDOUR, Species.SKORUPI, Species.SCRAFTY, Species.CROAGUNK, Species.SCATTERBUG, Species.ESPURR ],
|
||||||
[TrainerPoolTier.UNCOMMON]: [ Species.HELIOPTILE, Species.ELECTRIKE, Species.SKRELP, Species.PANCHAM, Species.PURRLOIN, Species.POOCHYENA, Species.BINACLE, Species.CLAUNCHER, Species.PUMPKABOO, Species.PHANTUMP ],
|
[TrainerPoolTier.UNCOMMON]: [ Species.HELIOPTILE, Species.ELECTRIKE, Species.SKRELP, Species.PANCHAM, Species.PURRLOIN, Species.POOCHYENA, Species.BINACLE, Species.CLAUNCHER, Species.PUMPKABOO, Species.PHANTUMP, Species.FOONGUS ],
|
||||||
[TrainerPoolTier.RARE]: [ Species.LITWICK, Species.SNEASEL, Species.PAWNIARD, Species.SLIGGOO ],
|
[TrainerPoolTier.RARE]: [ Species.LITWICK, Species.SNEASEL, Species.PAWNIARD, Species.SLIGGOO ],
|
||||||
[TrainerPoolTier.SUPER_RARE]: [ Species.NOIVERN, Species.HISUI_SLIGGOO, Species.HISUI_AVALUGG ]
|
[TrainerPoolTier.SUPER_RARE]: [ Species.NOIBAT, Species.HISUI_SLIGGOO, Species.HISUI_AVALUGG ]
|
||||||
}),
|
}),
|
||||||
[TrainerType.BRYONY]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("flare_admin_female", "flare", [ Species.LIEPARD ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)),
|
[TrainerType.BRYONY]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("flare_admin_female", "flare", [ Species.LIEPARD ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)),
|
||||||
[TrainerType.XEROSIC]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("flare_admin", "flare", [ Species.MALAMAR ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)),
|
[TrainerType.XEROSIC]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("flare_admin", "flare", [ Species.MALAMAR ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)),
|
||||||
|
@ -1893,7 +1893,10 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
[TrainerType.ROCKET_BOSS_GIOVANNI_1]: new TrainerConfig(t = TrainerType.ROCKET_BOSS_GIOVANNI_1).setName("Giovanni").initForEvilTeamLeader("Rocket Boss", []).setMixedBattleBgm("battle_rocket_boss").setVictoryBgm("victory_team_plasma")
|
[TrainerType.ROCKET_BOSS_GIOVANNI_1]: new TrainerConfig(t = TrainerType.ROCKET_BOSS_GIOVANNI_1).setName("Giovanni").initForEvilTeamLeader("Rocket Boss", []).setMixedBattleBgm("battle_rocket_boss").setVictoryBgm("victory_team_plasma")
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PERSIAN, Species.ALOLA_PERSIAN ]))
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PERSIAN, Species.ALOLA_PERSIAN ], TrainerSlot.TRAINER, true, p => {
|
||||||
|
p.generateAndPopulateMoveset();
|
||||||
|
p.gender = Gender.MALE;
|
||||||
|
}))
|
||||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.DUGTRIO, Species.ALOLA_DUGTRIO ]))
|
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.DUGTRIO, Species.ALOLA_DUGTRIO ]))
|
||||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.HONCHKROW ]))
|
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.HONCHKROW ]))
|
||||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.NIDOKING, Species.NIDOQUEEN ]))
|
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.NIDOKING, Species.NIDOQUEEN ]))
|
||||||
|
@ -1945,6 +1948,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
p.formIndex = 1; // Mega Camerupt
|
p.formIndex = 1; // Mega Camerupt
|
||||||
p.generateName();
|
p.generateName();
|
||||||
|
p.gender = Gender.MALE;
|
||||||
})),
|
})),
|
||||||
[TrainerType.MAXIE_2]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss", [], true).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma")
|
[TrainerType.MAXIE_2]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss", [], true).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma")
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SOLROCK, Species.TYPHLOSION ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SOLROCK, Species.TYPHLOSION ], TrainerSlot.TRAINER, true, p => {
|
||||||
|
@ -1967,6 +1971,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
p.formIndex = 1; // Mega Camerupt
|
p.formIndex = 1; // Mega Camerupt
|
||||||
p.generateName();
|
p.generateName();
|
||||||
|
p.gender = Gender.MALE;
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GROUDON ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GROUDON ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
|
@ -1985,6 +1990,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
p.formIndex = 1; // Mega Sharpedo
|
p.formIndex = 1; // Mega Sharpedo
|
||||||
p.generateName();
|
p.generateName();
|
||||||
|
p.gender = Gender.MALE;
|
||||||
})),
|
})),
|
||||||
[TrainerType.ARCHIE_2]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss", [], true).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma")
|
[TrainerType.ARCHIE_2]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss", [], true).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma")
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.EMPOLEON, Species.LUDICOLO ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.EMPOLEON, Species.LUDICOLO ], TrainerSlot.TRAINER, true, p => {
|
||||||
|
@ -2010,6 +2016,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
p.formIndex = 1; // Mega Sharpedo
|
p.formIndex = 1; // Mega Sharpedo
|
||||||
p.generateName();
|
p.generateName();
|
||||||
|
p.gender = Gender.MALE;
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KYOGRE ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KYOGRE ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
|
@ -2031,6 +2038,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
|
p.gender = Gender.MALE;
|
||||||
})),
|
})),
|
||||||
[TrainerType.CYRUS_2]: new TrainerConfig(++t).setName("Cyrus").initForEvilTeamLeader("Galactic Boss", [], true).setMixedBattleBgm("battle_galactic_boss").setVictoryBgm("victory_team_plasma")
|
[TrainerType.CYRUS_2]: new TrainerConfig(++t).setName("Cyrus").initForEvilTeamLeader("Galactic Boss", [], true).setMixedBattleBgm("battle_galactic_boss").setVictoryBgm("victory_team_plasma")
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.AZELF, Species.UXIE, Species.MESPRIT ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.AZELF, Species.UXIE, Species.MESPRIT ], TrainerSlot.TRAINER, true, p => {
|
||||||
|
@ -2049,6 +2057,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
|
p.gender = Gender.MALE;
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.DARKRAI ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.DARKRAI ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
|
@ -2065,6 +2074,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
|
p.gender = Gender.MALE;
|
||||||
})),
|
})),
|
||||||
[TrainerType.GHETSIS_2]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss", [], true).setMixedBattleBgm("battle_plasma_boss").setVictoryBgm("victory_team_plasma")
|
[TrainerType.GHETSIS_2]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss", [], true).setMixedBattleBgm("battle_plasma_boss").setVictoryBgm("victory_team_plasma")
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GENESECT ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GENESECT ], TrainerSlot.TRAINER, true, p => {
|
||||||
|
@ -2084,6 +2094,11 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
|
if (p.species.speciesId === Species.HYDREIGON) {
|
||||||
|
p.gender = Gender.MALE;
|
||||||
|
} else if (p.species.speciesId === Species.IRON_JUGULIS) {
|
||||||
|
p.gender = Gender.GENDERLESS;
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KYUREM ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KYUREM ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
|
@ -2105,6 +2120,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
p.formIndex = 1; // Mega Gyarados
|
p.formIndex = 1; // Mega Gyarados
|
||||||
p.generateName();
|
p.generateName();
|
||||||
|
p.gender = Gender.MALE;
|
||||||
})),
|
})),
|
||||||
[TrainerType.LYSANDRE_2]: new TrainerConfig(++t).setName("Lysandre").initForEvilTeamLeader("Flare Boss", [], true).setMixedBattleBgm("battle_flare_boss").setVictoryBgm("victory_team_plasma")
|
[TrainerType.LYSANDRE_2]: new TrainerConfig(++t).setName("Lysandre").initForEvilTeamLeader("Flare Boss", [], true).setMixedBattleBgm("battle_flare_boss").setVictoryBgm("victory_team_plasma")
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SCREAM_TAIL, Species.FLUTTER_MANE ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SCREAM_TAIL, Species.FLUTTER_MANE ], TrainerSlot.TRAINER, true, p => {
|
||||||
|
@ -2124,6 +2140,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
p.formIndex = 1; // Mega Gyardos
|
p.formIndex = 1; // Mega Gyardos
|
||||||
p.generateName();
|
p.generateName();
|
||||||
|
p.gender = Gender.MALE;
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.YVELTAL ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.YVELTAL ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
|
@ -2131,7 +2148,10 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.pokeball = PokeballType.MASTER_BALL;
|
p.pokeball = PokeballType.MASTER_BALL;
|
||||||
})),
|
})),
|
||||||
[TrainerType.LUSAMINE]: new TrainerConfig(++t).setName("Lusamine").initForEvilTeamLeader("Aether Boss", []).setMixedBattleBgm("battle_aether_boss").setVictoryBgm("victory_team_plasma")
|
[TrainerType.LUSAMINE]: new TrainerConfig(++t).setName("Lusamine").initForEvilTeamLeader("Aether Boss", []).setMixedBattleBgm("battle_aether_boss").setVictoryBgm("victory_team_plasma")
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CLEFABLE ]))
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CLEFABLE ], TrainerSlot.TRAINER, true, p => {
|
||||||
|
p.generateAndPopulateMoveset();
|
||||||
|
p.gender = Gender.FEMALE;
|
||||||
|
}))
|
||||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.LILLIGANT, Species.HISUI_LILLIGANT ]))
|
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.LILLIGANT, Species.HISUI_LILLIGANT ]))
|
||||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.MILOTIC, Species.PRIMARINA ]))
|
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.MILOTIC, Species.PRIMARINA ]))
|
||||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GALAR_SLOWBRO, Species.GALAR_SLOWKING ]))
|
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GALAR_SLOWBRO, Species.GALAR_SLOWKING ]))
|
||||||
|
@ -2148,7 +2168,10 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.pokeball = PokeballType.ROGUE_BALL;
|
p.pokeball = PokeballType.ROGUE_BALL;
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MILOTIC, Species.PRIMARINA ]))
|
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MILOTIC, Species.PRIMARINA ]))
|
||||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.CLEFABLE ]))
|
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.CLEFABLE ], TrainerSlot.TRAINER, true, p => {
|
||||||
|
p.generateAndPopulateMoveset();
|
||||||
|
p.gender = Gender.FEMALE;
|
||||||
|
}))
|
||||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.STAKATAKA, Species.CELESTEELA, Species.GUZZLORD ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.STAKATAKA, Species.CELESTEELA, Species.GUZZLORD ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.pokeball = PokeballType.ROGUE_BALL;
|
p.pokeball = PokeballType.ROGUE_BALL;
|
||||||
|
@ -2191,6 +2214,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GOLISOPOD ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GOLISOPOD ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
|
p.gender = Gender.MALE;
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
})),
|
})),
|
||||||
[TrainerType.GUZMA_2]: new TrainerConfig(++t).setName("Guzma").initForEvilTeamLeader("Skull Boss", [], true).setMixedBattleBgm("battle_skull_boss").setVictoryBgm("victory_team_plasma")
|
[TrainerType.GUZMA_2]: new TrainerConfig(++t).setName("Guzma").initForEvilTeamLeader("Skull Boss", [], true).setMixedBattleBgm("battle_skull_boss").setVictoryBgm("victory_team_plasma")
|
||||||
|
@ -2198,6 +2222,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.abilityIndex = 2; //Anticipation
|
p.abilityIndex = 2; //Anticipation
|
||||||
|
p.gender = Gender.MALE;
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.SCIZOR, Species.KLEAVOR ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.SCIZOR, Species.KLEAVOR ], TrainerSlot.TRAINER, true, p => {
|
||||||
|
@ -2239,6 +2264,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.formIndex = 1; // G-Max Copperajah
|
p.formIndex = 1; // G-Max Copperajah
|
||||||
p.generateName();
|
p.generateName();
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
|
p.gender = Gender.FEMALE;
|
||||||
})),
|
})),
|
||||||
[TrainerType.ROSE_2]: new TrainerConfig(++t).setName("Rose").initForEvilTeamLeader("Macro Boss", [], true).setMixedBattleBgm("battle_macro_boss").setVictoryBgm("victory_team_plasma")
|
[TrainerType.ROSE_2]: new TrainerConfig(++t).setName("Rose").initForEvilTeamLeader("Macro Boss", [], true).setMixedBattleBgm("battle_macro_boss").setVictoryBgm("victory_team_plasma")
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ARCHALUDON ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ARCHALUDON ], TrainerSlot.TRAINER, true, p => {
|
||||||
|
@ -2262,6 +2288,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.formIndex = 1; // G-Max Copperajah
|
p.formIndex = 1; // G-Max Copperajah
|
||||||
p.generateName();
|
p.generateName();
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
|
p.gender = Gender.FEMALE;
|
||||||
})),
|
})),
|
||||||
[TrainerType.PENNY]: new TrainerConfig(++t).setName("Cassiopeia").initForEvilTeamLeader("Star Boss", []).setMixedBattleBgm("battle_star_boss").setVictoryBgm("victory_team_plasma")
|
[TrainerType.PENNY]: new TrainerConfig(++t).setName("Cassiopeia").initForEvilTeamLeader("Star Boss", []).setMixedBattleBgm("battle_star_boss").setVictoryBgm("victory_team_plasma")
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VAPOREON, Species.JOLTEON, Species.FLAREON ]))
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VAPOREON, Species.JOLTEON, Species.FLAREON ]))
|
||||||
|
@ -2275,8 +2302,9 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.formIndex = Utils.randSeedInt(5, 1); // Heat, Wash, Frost, Fan, or Mow
|
p.formIndex = Utils.randSeedInt(5, 1); // Heat, Wash, Frost, Fan, or Mow
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.generateAndPopulateMoveset();
|
|
||||||
p.abilityIndex = 2; // Pixilate
|
p.abilityIndex = 2; // Pixilate
|
||||||
|
p.generateAndPopulateMoveset();
|
||||||
|
p.gender = Gender.FEMALE;
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.EEVEE ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.EEVEE ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
|
@ -2290,20 +2318,21 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; //TODO: is the bang correct?
|
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; //TODO: is the bang correct?
|
||||||
}),
|
}),
|
||||||
[TrainerType.PENNY_2]: new TrainerConfig(++t).setName("Cassiopeia").initForEvilTeamLeader("Star Boss", [], true).setMixedBattleBgm("battle_star_boss").setVictoryBgm("victory_team_plasma")
|
[TrainerType.PENNY_2]: new TrainerConfig(++t).setName("Cassiopeia").initForEvilTeamLeader("Star Boss", [], true).setMixedBattleBgm("battle_star_boss").setVictoryBgm("victory_team_plasma")
|
||||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
p.formIndex = Utils.randSeedInt(5, 1); //Random Starmobile form
|
p.abilityIndex = 2; // Pixilate
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.gender = Gender.FEMALE;
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ENTEI, Species.RAIKOU, Species.SUICUNE ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ENTEI, Species.RAIKOU, Species.SUICUNE ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.pokeball = PokeballType.ULTRA_BALL;
|
p.pokeball = PokeballType.ULTRA_BALL;
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WALKING_WAKE, Species.GOUGING_FIRE, Species.RAGING_BOLT ]))
|
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WALKING_WAKE, Species.GOUGING_FIRE, Species.RAGING_BOLT ]))
|
||||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => {
|
||||||
|
p.formIndex = Utils.randSeedInt(5, 1); //Random Starmobile form
|
||||||
p.generateAndPopulateMoveset();
|
p.generateAndPopulateMoveset();
|
||||||
p.abilityIndex = 2; // Pixilate
|
p.pokeball = PokeballType.ROGUE_BALL;
|
||||||
}))
|
}))
|
||||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.EEVEE ], TrainerSlot.TRAINER, true, p => {
|
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.EEVEE ], TrainerSlot.TRAINER, true, p => {
|
||||||
p.setBoss(true, 2);
|
p.setBoss(true, 2);
|
||||||
|
@ -2318,7 +2347,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.pokeball = PokeballType.MASTER_BALL;
|
p.pokeball = PokeballType.MASTER_BALL;
|
||||||
}))
|
}))
|
||||||
.setGenModifiersFunc(party => {
|
.setGenModifiersFunc(party => {
|
||||||
const teraPokemon = party[3];
|
const teraPokemon = party[0];
|
||||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; //TODO: is the bang correct?
|
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; //TODO: is the bang correct?
|
||||||
}),
|
}),
|
||||||
[TrainerType.BUCK]: new TrainerConfig(++t).setName("Buck").initForStatTrainer([], true)
|
[TrainerType.BUCK]: new TrainerConfig(++t).setName("Buck").initForStatTrainer([], true)
|
||||||
|
|
|
@ -54,7 +54,7 @@ export enum BattlerTagType {
|
||||||
CURSED = "CURSED",
|
CURSED = "CURSED",
|
||||||
CHARGED = "CHARGED",
|
CHARGED = "CHARGED",
|
||||||
ROOSTED = "ROOSTED",
|
ROOSTED = "ROOSTED",
|
||||||
MAGNET_RISEN = "MAGNET_RISEN",
|
FLOATING = "FLOATING",
|
||||||
MINIMIZED = "MINIMIZED",
|
MINIMIZED = "MINIMIZED",
|
||||||
DESTINY_BOND = "DESTINY_BOND",
|
DESTINY_BOND = "DESTINY_BOND",
|
||||||
CENTER_OF_ATTENTION = "CENTER_OF_ATTENTION",
|
CENTER_OF_ATTENTION = "CENTER_OF_ATTENTION",
|
||||||
|
@ -80,10 +80,12 @@ export enum BattlerTagType {
|
||||||
DOUBLE_SHOCKED = "DOUBLE_SHOCKED",
|
DOUBLE_SHOCKED = "DOUBLE_SHOCKED",
|
||||||
AUTOTOMIZED = "AUTOTOMIZED",
|
AUTOTOMIZED = "AUTOTOMIZED",
|
||||||
MYSTERY_ENCOUNTER_POST_SUMMON = "MYSTERY_ENCOUNTER_POST_SUMMON",
|
MYSTERY_ENCOUNTER_POST_SUMMON = "MYSTERY_ENCOUNTER_POST_SUMMON",
|
||||||
|
POWER_TRICK = "POWER_TRICK",
|
||||||
HEAL_BLOCK = "HEAL_BLOCK",
|
HEAL_BLOCK = "HEAL_BLOCK",
|
||||||
TORMENT = "TORMENT",
|
TORMENT = "TORMENT",
|
||||||
TAUNT = "TAUNT",
|
TAUNT = "TAUNT",
|
||||||
IMPRISON = "IMPRISON",
|
IMPRISON = "IMPRISON",
|
||||||
SYRUP_BOMB = "SYRUP_BOMB",
|
SYRUP_BOMB = "SYRUP_BOMB",
|
||||||
ELECTRIFIED = "ELECTRIFIED",
|
ELECTRIFIED = "ELECTRIFIED",
|
||||||
|
TELEKINESIS = "TELEKINESIS"
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ export function getStatStageChangeDescriptionKey(stages: number, isIncrease: boo
|
||||||
return isIncrease ? "battle:statRose" : "battle:statFell";
|
return isIncrease ? "battle:statRose" : "battle:statFell";
|
||||||
} else if (stages === 2) {
|
} else if (stages === 2) {
|
||||||
return isIncrease ? "battle:statSharplyRose" : "battle:statHarshlyFell";
|
return isIncrease ? "battle:statSharplyRose" : "battle:statHarshlyFell";
|
||||||
} else if (stages <= 6) {
|
} else if (stages > 2 && stages <= 6) {
|
||||||
return isIncrease ? "battle:statRoseDrastically" : "battle:statSeverelyFell";
|
return isIncrease ? "battle:statRoseDrastically" : "battle:statSeverelyFell";
|
||||||
}
|
}
|
||||||
return isIncrease ? "battle:statWontGoAnyHigher" : "battle:statWontGoAnyLower";
|
return isIncrease ? "battle:statWontGoAnyHigher" : "battle:statWontGoAnyLower";
|
||||||
|
|
|
@ -579,26 +579,28 @@ export class Arena {
|
||||||
* Applies each `ArenaTag` in this Arena, based on which side (self, enemy, or both) is passed in as a parameter
|
* Applies each `ArenaTag` in this Arena, based on which side (self, enemy, or both) is passed in as a parameter
|
||||||
* @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply
|
* @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply
|
||||||
* @param side {@linkcode ArenaTagSide} which side's arena tags to apply
|
* @param side {@linkcode ArenaTagSide} which side's arena tags to apply
|
||||||
|
* @param simulated if `true`, this applies arena tags without changing game state
|
||||||
* @param args array of parameters that the called upon tags may need
|
* @param args array of parameters that the called upon tags may need
|
||||||
*/
|
*/
|
||||||
applyTagsForSide(tagType: ArenaTagType | Constructor<ArenaTag>, side: ArenaTagSide, ...args: unknown[]): void {
|
applyTagsForSide(tagType: ArenaTagType | Constructor<ArenaTag>, side: ArenaTagSide, simulated: boolean, ...args: unknown[]): void {
|
||||||
let tags = typeof tagType === "string"
|
let tags = typeof tagType === "string"
|
||||||
? this.tags.filter(t => t.tagType === tagType)
|
? this.tags.filter(t => t.tagType === tagType)
|
||||||
: this.tags.filter(t => t instanceof tagType);
|
: this.tags.filter(t => t instanceof tagType);
|
||||||
if (side !== ArenaTagSide.BOTH) {
|
if (side !== ArenaTagSide.BOTH) {
|
||||||
tags = tags.filter(t => t.side === side);
|
tags = tags.filter(t => t.side === side);
|
||||||
}
|
}
|
||||||
tags.forEach(t => t.apply(this, args));
|
tags.forEach(t => t.apply(this, simulated, ...args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the specified tag to both sides (ie: both user and trainer's tag that match the Tag specified)
|
* Applies the specified tag to both sides (ie: both user and trainer's tag that match the Tag specified)
|
||||||
* by calling {@linkcode applyTagsForSide()}
|
* by calling {@linkcode applyTagsForSide()}
|
||||||
* @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply
|
* @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply
|
||||||
|
* @param simulated if `true`, this applies arena tags without changing game state
|
||||||
* @param args array of parameters that the called upon tags may need
|
* @param args array of parameters that the called upon tags may need
|
||||||
*/
|
*/
|
||||||
applyTags(tagType: ArenaTagType | Constructor<ArenaTag>, ...args: unknown[]): void {
|
applyTags(tagType: ArenaTagType | Constructor<ArenaTag>, simulated: boolean, ...args: unknown[]): void {
|
||||||
this.applyTagsForSide(tagType, ArenaTagSide.BOTH, ...args);
|
this.applyTagsForSide(tagType, ArenaTagSide.BOTH, simulated, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { variantData } from "#app/data/variant";
|
||||||
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "#app/ui/battle-info";
|
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "#app/ui/battle-info";
|
||||||
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget, CombinedPledgeStabBoostAttr } from "#app/data/move";
|
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget, CombinedPledgeStabBoostAttr } from "#app/data/move";
|
||||||
import { default as PokemonSpecies, PokemonSpeciesForm, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
import { default as PokemonSpecies, PokemonSpeciesForm, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||||
import { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters";
|
import { CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER, getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters";
|
||||||
import { starterPassiveAbilities } from "#app/data/balance/passives";
|
import { starterPassiveAbilities } from "#app/data/balance/passives";
|
||||||
import { Constructor, isNullOrUndefined, randSeedInt } from "#app/utils";
|
import { Constructor, isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||||
import * as Utils from "#app/utils";
|
import * as Utils from "#app/utils";
|
||||||
|
@ -19,7 +19,7 @@ import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims";
|
||||||
import { Status, StatusEffect, getRandomStatus } from "#app/data/status-effect";
|
import { Status, StatusEffect, getRandomStatus } from "#app/data/status-effect";
|
||||||
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
|
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
|
||||||
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "#app/data/balance/tms";
|
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "#app/data/balance/tms";
|
||||||
import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, SubstituteTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, MoveRestrictionBattlerTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag, TarShotTag, AutotomizedTag } from "../data/battler-tags";
|
import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, SubstituteTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, MoveRestrictionBattlerTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag, TarShotTag, AutotomizedTag, PowerTrickTag } from "../data/battler-tags";
|
||||||
import { WeatherType } from "#app/data/weather";
|
import { WeatherType } from "#app/data/weather";
|
||||||
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "#app/data/arena-tag";
|
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "#app/data/arena-tag";
|
||||||
import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr, PostSetStatusAbAttr, applyPostSetStatusAbAttrs } from "#app/data/ability";
|
import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr, PostSetStatusAbAttr, applyPostSetStatusAbAttrs } from "#app/data/ability";
|
||||||
|
@ -62,7 +62,7 @@ import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-ph
|
||||||
import { Challenges } from "#enums/challenges";
|
import { Challenges } from "#enums/challenges";
|
||||||
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||||
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
|
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
|
||||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||||
import { SwitchType } from "#enums/switch-type";
|
import { SwitchType } from "#enums/switch-type";
|
||||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||||
import { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE, SHINY_EPIC_CHANCE, SHINY_VARIANT_CHANCE } from "#app/data/balance/rates";
|
import { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE, SHINY_EPIC_CHANCE, SHINY_VARIANT_CHANCE } from "#app/data/balance/rates";
|
||||||
|
@ -114,7 +114,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
public fusionVariant: Variant;
|
public fusionVariant: Variant;
|
||||||
public fusionGender: Gender;
|
public fusionGender: Gender;
|
||||||
public fusionLuck: integer;
|
public fusionLuck: integer;
|
||||||
public fusionMysteryEncounterPokemonData: MysteryEncounterPokemonData | null;
|
public fusionCustomPokemonData: CustomPokemonData | null;
|
||||||
|
|
||||||
private summonDataPrimer: PokemonSummonData | null;
|
private summonDataPrimer: PokemonSummonData | null;
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
public battleData: PokemonBattleData;
|
public battleData: PokemonBattleData;
|
||||||
public battleSummonData: PokemonBattleSummonData;
|
public battleSummonData: PokemonBattleSummonData;
|
||||||
public turnData: PokemonTurnData;
|
public turnData: PokemonTurnData;
|
||||||
public mysteryEncounterPokemonData: MysteryEncounterPokemonData;
|
public customPokemonData: CustomPokemonData;
|
||||||
|
|
||||||
/** Used by Mystery Encounters to execute pokemon-specific logic (such as stat boosts) at start of battle */
|
/** Used by Mystery Encounters to execute pokemon-specific logic (such as stat boosts) at start of battle */
|
||||||
public mysteryEncounterBattleEffects?: (pokemon: Pokemon) => void;
|
public mysteryEncounterBattleEffects?: (pokemon: Pokemon) => void;
|
||||||
|
@ -193,7 +193,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
this.nature = dataSource.nature || 0 as Nature;
|
this.nature = dataSource.nature || 0 as Nature;
|
||||||
this.nickname = dataSource.nickname;
|
this.nickname = dataSource.nickname;
|
||||||
this.natureOverride = dataSource.natureOverride !== undefined ? dataSource.natureOverride : -1;
|
|
||||||
this.moveset = dataSource.moveset;
|
this.moveset = dataSource.moveset;
|
||||||
this.status = dataSource.status!; // TODO: is this bang correct?
|
this.status = dataSource.status!; // TODO: is this bang correct?
|
||||||
this.friendship = dataSource.friendship !== undefined ? dataSource.friendship : this.species.baseFriendship;
|
this.friendship = dataSource.friendship !== undefined ? dataSource.friendship : this.species.baseFriendship;
|
||||||
|
@ -212,9 +211,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
this.fusionVariant = dataSource.fusionVariant || 0;
|
this.fusionVariant = dataSource.fusionVariant || 0;
|
||||||
this.fusionGender = dataSource.fusionGender;
|
this.fusionGender = dataSource.fusionGender;
|
||||||
this.fusionLuck = dataSource.fusionLuck;
|
this.fusionLuck = dataSource.fusionLuck;
|
||||||
this.fusionMysteryEncounterPokemonData = dataSource.fusionMysteryEncounterPokemonData;
|
this.fusionCustomPokemonData = dataSource.fusionCustomPokemonData;
|
||||||
this.usedTMs = dataSource.usedTMs ?? [];
|
this.usedTMs = dataSource.usedTMs ?? [];
|
||||||
this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(dataSource.mysteryEncounterPokemonData);
|
this.customPokemonData = new CustomPokemonData(dataSource.customPokemonData);
|
||||||
} else {
|
} else {
|
||||||
this.id = Utils.randSeedInt(4294967296);
|
this.id = Utils.randSeedInt(4294967296);
|
||||||
this.ivs = ivs || Utils.getIvsFromId(this.id);
|
this.ivs = ivs || Utils.getIvsFromId(this.id);
|
||||||
|
@ -235,7 +234,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
this.variant = this.shiny ? this.generateVariant() : 0;
|
this.variant = this.shiny ? this.generateVariant() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
this.customPokemonData = new CustomPokemonData();
|
||||||
|
|
||||||
if (nature !== undefined) {
|
if (nature !== undefined) {
|
||||||
this.setNature(nature);
|
this.setNature(nature);
|
||||||
|
@ -243,8 +242,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
this.generateNature();
|
this.generateNature();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.natureOverride = -1;
|
|
||||||
|
|
||||||
this.friendship = species.baseFriendship;
|
this.friendship = species.baseFriendship;
|
||||||
this.metLevel = level;
|
this.metLevel = level;
|
||||||
this.metBiome = scene.currentBattle ? scene.arena.biomeType : -1;
|
this.metBiome = scene.currentBattle ? scene.arena.biomeType : -1;
|
||||||
|
@ -593,8 +590,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
const formKey = this.getFormKey();
|
const formKey = this.getFormKey();
|
||||||
if (this.isMax() === true || formKey === "segin-starmobile" || formKey === "schedar-starmobile" || formKey === "navi-starmobile" || formKey === "ruchbah-starmobile" || formKey === "caph-starmobile") {
|
if (this.isMax() === true || formKey === "segin-starmobile" || formKey === "schedar-starmobile" || formKey === "navi-starmobile" || formKey === "ruchbah-starmobile" || formKey === "caph-starmobile") {
|
||||||
return 1.5;
|
return 1.5;
|
||||||
} else if (this.mysteryEncounterPokemonData.spriteScale > 0) {
|
} else if (this.customPokemonData.spriteScale > 0) {
|
||||||
return this.mysteryEncounterPokemonData.spriteScale;
|
return this.customPokemonData.spriteScale;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -749,9 +746,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
const relX = newOffset[0] - initialOffset[0];
|
const relX = newOffset[0] - initialOffset[0];
|
||||||
const relY = newOffset[1] - initialOffset[1];
|
const relY = newOffset[1] - initialOffset[1];
|
||||||
|
|
||||||
|
const subTag = this.getTag(SubstituteTag);
|
||||||
|
|
||||||
if (duration) {
|
if (duration) {
|
||||||
|
// TODO: can this use stricter typing?
|
||||||
|
const targets: any[] = [ this ];
|
||||||
|
if (subTag?.sprite) {
|
||||||
|
targets.push(subTag.sprite);
|
||||||
|
}
|
||||||
this.scene.tweens.add({
|
this.scene.tweens.add({
|
||||||
targets: this,
|
targets: targets,
|
||||||
x: (_target, _key, value: number) => value + relX,
|
x: (_target, _key, value: number) => value + relX,
|
||||||
y: (_target, _key, value: number) => value + relY,
|
y: (_target, _key, value: number) => value + relY,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
|
@ -761,6 +765,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
} else {
|
} else {
|
||||||
this.x += relX;
|
this.x += relX;
|
||||||
this.y += relY;
|
this.y += relY;
|
||||||
|
if (subTag?.sprite) {
|
||||||
|
subTag.sprite.x += relX;
|
||||||
|
subTag.sprite.y += relY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1012,7 +1020,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
|
|
||||||
getNature(): Nature {
|
getNature(): Nature {
|
||||||
return this.natureOverride !== -1 ? this.natureOverride : this.nature;
|
return this.customPokemonData.nature !== -1 ? this.customPokemonData.nature : this.nature;
|
||||||
}
|
}
|
||||||
|
|
||||||
setNature(nature: Nature): void {
|
setNature(nature: Nature): void {
|
||||||
|
@ -1187,15 +1195,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
if (!types.length || !includeTeraType) {
|
if (!types.length || !includeTeraType) {
|
||||||
if (!ignoreOverride && this.summonData?.types && this.summonData.types.length > 0) {
|
if (!ignoreOverride && this.summonData?.types && this.summonData.types.length > 0) {
|
||||||
this.summonData.types.forEach(t => types.push(t));
|
this.summonData.types.forEach(t => types.push(t));
|
||||||
} else if (this.mysteryEncounterPokemonData.types && this.mysteryEncounterPokemonData.types.length > 0) {
|
} else if (this.customPokemonData.types && this.customPokemonData.types.length > 0) {
|
||||||
// "Permanent" override for a Pokemon's normal types, currently only used by Mystery Encounters
|
// "Permanent" override for a Pokemon's normal types, currently only used by Mystery Encounters
|
||||||
types.push(this.mysteryEncounterPokemonData.types[0]);
|
types.push(this.customPokemonData.types[0]);
|
||||||
|
|
||||||
// Fusing a Pokemon onto something with "permanently changed" types will still apply the fusion's types as normal
|
// Fusing a Pokemon onto something with "permanently changed" types will still apply the fusion's types as normal
|
||||||
const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride);
|
const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride);
|
||||||
if (fusionSpeciesForm) {
|
if (fusionSpeciesForm) {
|
||||||
// Check if the fusion Pokemon also had "permanently changed" types
|
// Check if the fusion Pokemon also had "permanently changed" types
|
||||||
const fusionMETypes = this.fusionMysteryEncounterPokemonData?.types;
|
const fusionMETypes = this.fusionCustomPokemonData?.types;
|
||||||
if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) {
|
if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) {
|
||||||
types.push(fusionMETypes[1]);
|
types.push(fusionMETypes[1]);
|
||||||
} else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) {
|
} else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) {
|
||||||
|
@ -1207,8 +1215,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (types.length === 1 && this.mysteryEncounterPokemonData.types.length >= 2) {
|
if (types.length === 1 && this.customPokemonData.types.length >= 2) {
|
||||||
types.push(this.mysteryEncounterPokemonData.types[1]);
|
types.push(this.customPokemonData.types[1]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const speciesForm = this.getSpeciesForm(ignoreOverride);
|
const speciesForm = this.getSpeciesForm(ignoreOverride);
|
||||||
|
@ -1219,7 +1227,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
if (fusionSpeciesForm) {
|
if (fusionSpeciesForm) {
|
||||||
// Check if the fusion Pokemon also had "permanently changed" types
|
// Check if the fusion Pokemon also had "permanently changed" types
|
||||||
// Otherwise, use standard fusion type logic
|
// Otherwise, use standard fusion type logic
|
||||||
const fusionMETypes = this.fusionMysteryEncounterPokemonData?.types;
|
const fusionMETypes = this.fusionCustomPokemonData?.types;
|
||||||
if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) {
|
if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) {
|
||||||
types.push(fusionMETypes[1]);
|
types.push(fusionMETypes[1]);
|
||||||
} else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) {
|
} else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) {
|
||||||
|
@ -1251,6 +1259,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If both types are the same (can happen in weird custom typing scenarios), reduce to single type
|
||||||
|
if (types.length > 1 && types[0] === types[1]) {
|
||||||
|
types.splice(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1277,14 +1290,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
return allAbilities[Overrides.OPP_ABILITY_OVERRIDE];
|
return allAbilities[Overrides.OPP_ABILITY_OVERRIDE];
|
||||||
}
|
}
|
||||||
if (this.isFusion()) {
|
if (this.isFusion()) {
|
||||||
if (!isNullOrUndefined(this.fusionMysteryEncounterPokemonData?.ability) && this.fusionMysteryEncounterPokemonData.ability !== -1) {
|
if (!isNullOrUndefined(this.fusionCustomPokemonData?.ability) && this.fusionCustomPokemonData.ability !== -1) {
|
||||||
return allAbilities[this.fusionMysteryEncounterPokemonData.ability];
|
return allAbilities[this.fusionCustomPokemonData.ability];
|
||||||
} else {
|
} else {
|
||||||
return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)];
|
return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isNullOrUndefined(this.mysteryEncounterPokemonData.ability) && this.mysteryEncounterPokemonData.ability !== -1) {
|
if (!isNullOrUndefined(this.customPokemonData.ability) && this.customPokemonData.ability !== -1) {
|
||||||
return allAbilities[this.mysteryEncounterPokemonData.ability];
|
return allAbilities[this.customPokemonData.ability];
|
||||||
}
|
}
|
||||||
let abilityId = this.getSpeciesForm(ignoreOverride).getAbility(this.abilityIndex);
|
let abilityId = this.getSpeciesForm(ignoreOverride).getAbility(this.abilityIndex);
|
||||||
if (abilityId === Abilities.NONE) {
|
if (abilityId === Abilities.NONE) {
|
||||||
|
@ -1307,8 +1320,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && !this.isPlayer()) {
|
if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && !this.isPlayer()) {
|
||||||
return allAbilities[Overrides.OPP_PASSIVE_ABILITY_OVERRIDE];
|
return allAbilities[Overrides.OPP_PASSIVE_ABILITY_OVERRIDE];
|
||||||
}
|
}
|
||||||
if (!isNullOrUndefined(this.mysteryEncounterPokemonData.passive) && this.mysteryEncounterPokemonData.passive !== -1) {
|
if (!isNullOrUndefined(this.customPokemonData.passive) && this.customPokemonData.passive !== -1) {
|
||||||
return allAbilities[this.mysteryEncounterPokemonData.passive];
|
return allAbilities[this.customPokemonData.passive];
|
||||||
}
|
}
|
||||||
|
|
||||||
let starterSpeciesId = this.species.speciesId;
|
let starterSpeciesId = this.species.speciesId;
|
||||||
|
@ -1488,7 +1501,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
|
|
||||||
isGrounded(): boolean {
|
isGrounded(): boolean {
|
||||||
return !!this.getTag(GroundedTag) || (!this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE) && !this.getTag(BattlerTagType.MAGNET_RISEN) && !this.getTag(SemiInvulnerableTag));
|
return !!this.getTag(GroundedTag) || (!this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE) && !this.getTag(BattlerTagType.FLOATING) && !this.getTag(SemiInvulnerableTag));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1527,7 +1540,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
applyMoveAttrs(VariableMoveTypeAttr, this, null, move, moveTypeHolder);
|
applyMoveAttrs(VariableMoveTypeAttr, this, null, move, moveTypeHolder);
|
||||||
applyPreAttackAbAttrs(MoveTypeChangeAbAttr, this, null, move, simulated, moveTypeHolder);
|
applyPreAttackAbAttrs(MoveTypeChangeAbAttr, this, null, move, simulated, moveTypeHolder);
|
||||||
|
|
||||||
this.scene.arena.applyTags(ArenaTagType.ION_DELUGE, moveTypeHolder);
|
this.scene.arena.applyTags(ArenaTagType.ION_DELUGE, simulated, moveTypeHolder);
|
||||||
if (this.getTag(BattlerTagType.ELECTRIFIED)) {
|
if (this.getTag(BattlerTagType.ELECTRIFIED)) {
|
||||||
moveTypeHolder.value = Type.ELECTRIC;
|
moveTypeHolder.value = Type.ELECTRIC;
|
||||||
}
|
}
|
||||||
|
@ -2007,7 +2020,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
this.fusionVariant = 0;
|
this.fusionVariant = 0;
|
||||||
this.fusionGender = 0;
|
this.fusionGender = 0;
|
||||||
this.fusionLuck = 0;
|
this.fusionLuck = 0;
|
||||||
this.fusionMysteryEncounterPokemonData = null;
|
this.fusionCustomPokemonData = null;
|
||||||
|
|
||||||
this.generateName();
|
this.generateName();
|
||||||
this.calculateStats();
|
this.calculateStats();
|
||||||
|
@ -2176,8 +2189,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
this.moveset.push(new PokemonMove(movePool[index][0], 0, 0));
|
this.moveset.push(new PokemonMove(movePool[index][0], 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trigger FormChange, except for enemy Pokemon during Mystery Encounters, to avoid crashes
|
||||||
|
if (this.isPlayer() || !this.scene.currentBattle?.isBattleMysteryEncounter() || !this.scene.currentBattle?.mysteryEncounter) {
|
||||||
this.scene.triggerPokemonFormChange(this, SpeciesFormChangeMoveLearnedTrigger);
|
this.scene.triggerPokemonFormChange(this, SpeciesFormChangeMoveLearnedTrigger);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trySelectMove(moveIndex: integer, ignorePp?: boolean): boolean {
|
trySelectMove(moveIndex: integer, ignorePp?: boolean): boolean {
|
||||||
const move = this.getMoveset().length > moveIndex
|
const move = this.getMoveset().length > moveIndex
|
||||||
|
@ -2594,7 +2610,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
|
|
||||||
/** Reduces damage if this Pokemon has a relevant screen (e.g. Light Screen for special attacks) */
|
/** Reduces damage if this Pokemon has a relevant screen (e.g. Light Screen for special attacks) */
|
||||||
const screenMultiplier = new Utils.NumberHolder(1);
|
const screenMultiplier = new Utils.NumberHolder(1);
|
||||||
this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, defendingSide, move.category, this.scene.currentBattle.double, screenMultiplier);
|
this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, defendingSide, simulated, moveCategory, screenMultiplier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For each {@linkcode HitsTagAttr} the move has, doubles the damage of the move if:
|
* For each {@linkcode HitsTagAttr} the move has, doubles the damage of the move if:
|
||||||
|
@ -2799,15 +2815,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
if (this.isFainted()) {
|
if (this.isFainted()) {
|
||||||
// set splice index here, so future scene queues happen before FaintedPhase
|
// set splice index here, so future scene queues happen before FaintedPhase
|
||||||
this.scene.setPhaseQueueSplice();
|
this.scene.setPhaseQueueSplice();
|
||||||
|
if (!isNullOrUndefined(destinyTag) && dmg) {
|
||||||
|
// Destiny Bond will activate during FaintPhase
|
||||||
|
this.scene.unshiftPhase(new FaintPhase(this.scene, this.getBattlerIndex(), isOneHitKo, destinyTag, source));
|
||||||
|
} else {
|
||||||
this.scene.unshiftPhase(new FaintPhase(this.scene, this.getBattlerIndex(), isOneHitKo));
|
this.scene.unshiftPhase(new FaintPhase(this.scene, this.getBattlerIndex(), isOneHitKo));
|
||||||
|
}
|
||||||
this.destroySubstitute();
|
this.destroySubstitute();
|
||||||
this.resetSummonData();
|
this.resetSummonData();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dmg) {
|
|
||||||
destinyTag?.lapse(source, BattlerTagLapseType.CUSTOM);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3037,6 +3054,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tag instanceof PowerTrickTag) {
|
||||||
|
tag.swapStat(this);
|
||||||
|
}
|
||||||
|
|
||||||
this.summonData.tags.push(tag);
|
this.summonData.tags.push(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3051,8 +3072,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
*
|
*
|
||||||
* @see {@linkcode MoveRestrictionBattlerTag}
|
* @see {@linkcode MoveRestrictionBattlerTag}
|
||||||
*/
|
*/
|
||||||
isMoveRestricted(moveId: Moves): boolean {
|
public isMoveRestricted(moveId: Moves, pokemon?: Pokemon): boolean {
|
||||||
return this.getRestrictingTag(moveId) !== null;
|
return this.getRestrictingTag(moveId, pokemon) !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3085,7 +3106,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
*/
|
*/
|
||||||
getRestrictingTag(moveId: Moves, user?: Pokemon, target?: Pokemon): MoveRestrictionBattlerTag | null {
|
getRestrictingTag(moveId: Moves, user?: Pokemon, target?: Pokemon): MoveRestrictionBattlerTag | null {
|
||||||
for (const tag of this.findTags(t => t instanceof MoveRestrictionBattlerTag)) {
|
for (const tag of this.findTags(t => t instanceof MoveRestrictionBattlerTag)) {
|
||||||
if ((tag as MoveRestrictionBattlerTag).isMoveRestricted(moveId)) {
|
if ((tag as MoveRestrictionBattlerTag).isMoveRestricted(moveId, user)) {
|
||||||
return tag as MoveRestrictionBattlerTag;
|
return tag as MoveRestrictionBattlerTag;
|
||||||
} else if (user && target && (tag as MoveRestrictionBattlerTag).isMoveTargetRestricted(moveId, user, target)) {
|
} else if (user && target && (tag as MoveRestrictionBattlerTag).isMoveTargetRestricted(moveId, user, target)) {
|
||||||
return tag as MoveRestrictionBattlerTag;
|
return tag as MoveRestrictionBattlerTag;
|
||||||
|
@ -4066,7 +4087,7 @@ export class PlayerPokemon extends Pokemon {
|
||||||
fusionStarterSpeciesId ? this.scene.gameData.starterData[fusionStarterSpeciesId] : null
|
fusionStarterSpeciesId ? this.scene.gameData.starterData[fusionStarterSpeciesId] : null
|
||||||
].filter(d => !!d);
|
].filter(d => !!d);
|
||||||
const amount = new Utils.IntegerHolder(friendship);
|
const amount = new Utils.IntegerHolder(friendship);
|
||||||
const starterAmount = new Utils.IntegerHolder(Math.floor(friendship * (this.scene.gameMode.isClassic && friendship > 0 ? 2 : 1) / (fusionStarterSpeciesId ? 2 : 1)));
|
const starterAmount = new Utils.IntegerHolder(Math.floor(friendship * (this.scene.gameMode.isClassic && friendship > 0 ? CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER : 1) / (fusionStarterSpeciesId ? 2 : 1)));
|
||||||
if (amount.value > 0) {
|
if (amount.value > 0) {
|
||||||
this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount);
|
this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount);
|
||||||
this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount);
|
this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount);
|
||||||
|
@ -4276,12 +4297,33 @@ export class PlayerPokemon extends Pokemon {
|
||||||
|
|
||||||
changeForm(formChange: SpeciesFormChange): Promise<void> {
|
changeForm(formChange: SpeciesFormChange): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
const previousFormIndex = this.formIndex;
|
||||||
this.formIndex = Math.max(this.species.forms.findIndex(f => f.formKey === formChange.formKey), 0);
|
this.formIndex = Math.max(this.species.forms.findIndex(f => f.formKey === formChange.formKey), 0);
|
||||||
this.generateName();
|
this.generateName();
|
||||||
const abilityCount = this.getSpeciesForm().getAbilityCount();
|
const abilityCount = this.getSpeciesForm().getAbilityCount();
|
||||||
if (this.abilityIndex >= abilityCount) { // Shouldn't happen
|
if (this.abilityIndex >= abilityCount) { // Shouldn't happen
|
||||||
this.abilityIndex = abilityCount - 1;
|
this.abilityIndex = abilityCount - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In cases where a form change updates the type of a Pokemon from its previous form (Arceus, Silvally, Castform, etc.),
|
||||||
|
// persist that type change in customPokemonData if necessary
|
||||||
|
const baseForm = this.species.forms[previousFormIndex];
|
||||||
|
const baseFormTypes = [ baseForm.type1, baseForm.type2 ];
|
||||||
|
if (this.customPokemonData.types.length > 0) {
|
||||||
|
if (this.getSpeciesForm().type1 !== baseFormTypes[0]) {
|
||||||
|
this.customPokemonData.types[0] = this.getSpeciesForm().type1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const type2 = this.getSpeciesForm().type2;
|
||||||
|
if (!isNullOrUndefined(type2) && type2 !== baseFormTypes[1]) {
|
||||||
|
if (this.customPokemonData.types.length > 1) {
|
||||||
|
this.customPokemonData.types[1] = type2;
|
||||||
|
} else {
|
||||||
|
this.customPokemonData.types.push(type2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.compatibleTms.splice(0, this.compatibleTms.length);
|
this.compatibleTms.splice(0, this.compatibleTms.length);
|
||||||
this.generateCompatibleTms();
|
this.generateCompatibleTms();
|
||||||
const updateAndResolve = () => {
|
const updateAndResolve = () => {
|
||||||
|
@ -4318,7 +4360,7 @@ export class PlayerPokemon extends Pokemon {
|
||||||
this.fusionVariant = pokemon.variant;
|
this.fusionVariant = pokemon.variant;
|
||||||
this.fusionGender = pokemon.gender;
|
this.fusionGender = pokemon.gender;
|
||||||
this.fusionLuck = pokemon.luck;
|
this.fusionLuck = pokemon.luck;
|
||||||
this.fusionMysteryEncounterPokemonData = pokemon.mysteryEncounterPokemonData;
|
this.fusionCustomPokemonData = pokemon.customPokemonData;
|
||||||
if ((pokemon.pauseEvolutions) || (this.pauseEvolutions)) {
|
if ((pokemon.pauseEvolutions) || (this.pauseEvolutions)) {
|
||||||
this.pauseEvolutions = true;
|
this.pauseEvolutions = true;
|
||||||
}
|
}
|
||||||
|
@ -5128,7 +5170,7 @@ export class PokemonMove {
|
||||||
* @returns `true` if the move can be selected and used by the Pokemon, otherwise `false`.
|
* @returns `true` if the move can be selected and used by the Pokemon, otherwise `false`.
|
||||||
*/
|
*/
|
||||||
isUsable(pokemon: Pokemon, ignorePp: boolean = false, ignoreRestrictionTags: boolean = false): boolean {
|
isUsable(pokemon: Pokemon, ignorePp: boolean = false, ignoreRestrictionTags: boolean = false): boolean {
|
||||||
if (this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId)) {
|
if (this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId, pokemon)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -383,7 +383,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||||
const battle = this.scene.currentBattle;
|
const battle = this.scene.currentBattle;
|
||||||
const template = this.getPartyTemplate();
|
const template = this.getPartyTemplate();
|
||||||
|
|
||||||
let species: PokemonSpecies;
|
let baseSpecies: PokemonSpecies;
|
||||||
if (this.config.speciesPools) {
|
if (this.config.speciesPools) {
|
||||||
const tierValue = Utils.randSeedInt(512);
|
const tierValue = Utils.randSeedInt(512);
|
||||||
let tier = tierValue >= 156 ? TrainerPoolTier.COMMON : tierValue >= 32 ? TrainerPoolTier.UNCOMMON : tierValue >= 6 ? TrainerPoolTier.RARE : tierValue >= 1 ? TrainerPoolTier.SUPER_RARE : TrainerPoolTier.ULTRA_RARE;
|
let tier = tierValue >= 156 ? TrainerPoolTier.COMMON : tierValue >= 32 ? TrainerPoolTier.UNCOMMON : tierValue >= 6 ? TrainerPoolTier.RARE : tierValue >= 1 ? TrainerPoolTier.SUPER_RARE : TrainerPoolTier.ULTRA_RARE;
|
||||||
|
@ -393,17 +393,17 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||||
tier--;
|
tier--;
|
||||||
}
|
}
|
||||||
const tierPool = this.config.speciesPools[tier];
|
const tierPool = this.config.speciesPools[tier];
|
||||||
species = getPokemonSpecies(Utils.randSeedItem(tierPool));
|
baseSpecies = getPokemonSpecies(Utils.randSeedItem(tierPool));
|
||||||
} else {
|
} else {
|
||||||
species = this.scene.randomSpecies(battle.waveIndex, level, false, this.config.speciesFilter);
|
baseSpecies = this.scene.randomSpecies(battle.waveIndex, level, false, this.config.speciesFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ret = getPokemonSpecies(species.getTrainerSpeciesForLevel(level, true, strength, this.scene.currentBattle.waveIndex));
|
let ret = getPokemonSpecies(baseSpecies.getTrainerSpeciesForLevel(level, true, strength, this.scene.currentBattle.waveIndex));
|
||||||
let retry = false;
|
let retry = false;
|
||||||
|
|
||||||
console.log(ret.getName());
|
console.log(ret.getName());
|
||||||
|
|
||||||
if (pokemonPrevolutions.hasOwnProperty(species.speciesId) && ret.speciesId !== species.speciesId) {
|
if (pokemonPrevolutions.hasOwnProperty(baseSpecies.speciesId) && ret.speciesId !== baseSpecies.speciesId) {
|
||||||
retry = true;
|
retry = true;
|
||||||
} else if (template.isBalanced(battle.enemyParty.length)) {
|
} else if (template.isBalanced(battle.enemyParty.length)) {
|
||||||
const partyMemberTypes = battle.enemyParty.map(p => p.getTypes(true)).flat();
|
const partyMemberTypes = battle.enemyParty.map(p => p.getTypes(true)).flat();
|
||||||
|
@ -417,7 +417,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||||
console.log("Attempting reroll of species evolution to fit specialty type...");
|
console.log("Attempting reroll of species evolution to fit specialty type...");
|
||||||
let evoAttempt = 0;
|
let evoAttempt = 0;
|
||||||
while (retry && evoAttempt++ < 10) {
|
while (retry && evoAttempt++ < 10) {
|
||||||
ret = getPokemonSpecies(species.getTrainerSpeciesForLevel(level, true, strength, this.scene.currentBattle.waveIndex));
|
ret = getPokemonSpecies(baseSpecies.getTrainerSpeciesForLevel(level, true, strength, this.scene.currentBattle.waveIndex));
|
||||||
console.log(ret.name);
|
console.log(ret.name);
|
||||||
if (this.config.specialtyTypes.find(t => ret.isOfType(t))) {
|
if (this.config.specialtyTypes.find(t => ret.isOfType(t))) {
|
||||||
retry = false;
|
retry = false;
|
||||||
|
@ -426,7 +426,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prompts reroll of party member species if species already present in the enemy party
|
// Prompts reroll of party member species if species already present in the enemy party
|
||||||
if (this.checkDuplicateSpecies(ret)) {
|
if (this.checkDuplicateSpecies(ret, baseSpecies)) {
|
||||||
console.log("Duplicate species detected, prompting reroll...");
|
console.log("Duplicate species detected, prompting reroll...");
|
||||||
retry = true;
|
retry = true;
|
||||||
}
|
}
|
||||||
|
@ -442,13 +442,16 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||||
/**
|
/**
|
||||||
* Checks if the enemy trainer already has the Pokemon species in their party
|
* Checks if the enemy trainer already has the Pokemon species in their party
|
||||||
* @param {PokemonSpecies} species {@linkcode PokemonSpecies}
|
* @param {PokemonSpecies} species {@linkcode PokemonSpecies}
|
||||||
|
* @param {PokemonSpecies} baseSpecies {@linkcode PokemonSpecies} - baseSpecies of the Pokemon if species is forced to evolve
|
||||||
* @returns `true` if the species is already present in the party
|
* @returns `true` if the species is already present in the party
|
||||||
*/
|
*/
|
||||||
checkDuplicateSpecies(species: PokemonSpecies): boolean {
|
checkDuplicateSpecies(species: PokemonSpecies, baseSpecies: PokemonSpecies): boolean {
|
||||||
|
const staticPartyPokemon = (signatureSpecies[TrainerType[this.config.trainerType]] ?? []).flat(1);
|
||||||
|
|
||||||
const currentPartySpecies = this.scene.getEnemyParty().map(p => {
|
const currentPartySpecies = this.scene.getEnemyParty().map(p => {
|
||||||
return p.species.speciesId;
|
return p.species.speciesId;
|
||||||
});
|
});
|
||||||
return currentPartySpecies.includes(species.speciesId);
|
return currentPartySpecies.includes(species.speciesId) || staticPartyPokemon.includes(baseSpecies.speciesId);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPartyMemberMatchupScores(trainerSlot: TrainerSlot = TrainerSlot.NONE, forSwitch: boolean = false): [integer, integer][] {
|
getPartyMemberMatchupScores(trainerSlot: TrainerSlot = TrainerSlot.NONE, forSwitch: boolean = false): [integer, integer][] {
|
||||||
|
|
|
@ -1126,7 +1126,7 @@ class EvolutionItemModifierTypeGenerator extends ModifierTypeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
||||||
constructor(rare: boolean) {
|
constructor(isRareFormChangeItem: boolean) {
|
||||||
super((party: Pokemon[], pregenArgs?: any[]) => {
|
super((party: Pokemon[], pregenArgs?: any[]) => {
|
||||||
if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in FormChangeItem)) {
|
if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in FormChangeItem)) {
|
||||||
return new FormChangeItemModifierType(pregenArgs[0] as FormChangeItem);
|
return new FormChangeItemModifierType(pregenArgs[0] as FormChangeItem);
|
||||||
|
@ -1167,7 +1167,7 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
||||||
}
|
}
|
||||||
return formChangeItemTriggers;
|
return formChangeItemTriggers;
|
||||||
}).flat())
|
}).flat())
|
||||||
].flat().flatMap(fc => fc.item).filter(i => (i && i < 100) === rare);
|
].flat().flatMap(fc => fc.item).filter(i => (i && i < 100) === isRareFormChangeItem);
|
||||||
// convert it into a set to remove duplicate values, which can appear when the same species with a potential form change is in the party.
|
// convert it into a set to remove duplicate values, which can appear when the same species with a potential form change is in the party.
|
||||||
|
|
||||||
if (!formChangeItemPool.length) {
|
if (!formChangeItemPool.length) {
|
||||||
|
@ -2227,7 +2227,8 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.HYPER_POTION(), 0, baseCost * 0.8),
|
new ModifierTypeOption(modifierTypes.HYPER_POTION(), 0, baseCost * 0.8),
|
||||||
new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0, baseCost * 2.75)
|
new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0, baseCost * 2.75),
|
||||||
|
new ModifierTypeOption(modifierTypes.MEMORY_MUSHROOM(), 0, baseCost * 4)
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.MAX_POTION(), 0, baseCost * 1.5),
|
new ModifierTypeOption(modifierTypes.MAX_POTION(), 0, baseCost * 1.5),
|
||||||
|
|
|
@ -11,7 +11,7 @@ import Pokemon, { type PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
import { EvolutionPhase } from "#app/phases/evolution-phase";
|
import { EvolutionPhase } from "#app/phases/evolution-phase";
|
||||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
import { LearnMovePhase, LearnMoveType } from "#app/phases/learn-move-phase";
|
||||||
import { LevelUpPhase } from "#app/phases/level-up-phase";
|
import { LevelUpPhase } from "#app/phases/level-up-phase";
|
||||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||||
import { achvs } from "#app/system/achv";
|
import { achvs } from "#app/system/achv";
|
||||||
|
@ -30,6 +30,7 @@ import { StatusEffect } from "#enums/status-effect";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { type DoubleBattleChanceBoosterModifierType, type EvolutionItemModifierType, type FormChangeItemModifierType, type ModifierOverride, type ModifierType, type PokemonBaseStatTotalModifierType, type PokemonExpBoosterModifierType, type PokemonFriendshipBoosterModifierType, type PokemonMoveAccuracyBoosterModifierType, type PokemonMultiHitModifierType, type TerastallizeModifierType, type TmModifierType, getModifierType, ModifierPoolType, ModifierTypeGenerator, modifierTypes, PokemonHeldItemModifierType } from "./modifier-type";
|
import { type DoubleBattleChanceBoosterModifierType, type EvolutionItemModifierType, type FormChangeItemModifierType, type ModifierOverride, type ModifierType, type PokemonBaseStatTotalModifierType, type PokemonExpBoosterModifierType, type PokemonFriendshipBoosterModifierType, type PokemonMoveAccuracyBoosterModifierType, type PokemonMultiHitModifierType, type TerastallizeModifierType, type TmModifierType, getModifierType, ModifierPoolType, ModifierTypeGenerator, modifierTypes, PokemonHeldItemModifierType } from "./modifier-type";
|
||||||
import { Color, ShadowColor } from "#enums/color";
|
import { Color, ShadowColor } from "#enums/color";
|
||||||
|
import { FRIENDSHIP_GAIN_FROM_RARE_CANDY } from "#app/data/balance/starters";
|
||||||
|
|
||||||
export type ModifierPredicate = (modifier: Modifier) => boolean;
|
export type ModifierPredicate = (modifier: Modifier) => boolean;
|
||||||
|
|
||||||
|
@ -2180,7 +2181,7 @@ export class PokemonNatureChangeModifier extends ConsumablePokemonModifier {
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
override apply(playerPokemon: PlayerPokemon): boolean {
|
override apply(playerPokemon: PlayerPokemon): boolean {
|
||||||
playerPokemon.natureOverride = this.nature;
|
playerPokemon.customPokemonData.nature = this.nature;
|
||||||
let speciesId = playerPokemon.species.speciesId;
|
let speciesId = playerPokemon.species.speciesId;
|
||||||
playerPokemon.scene.gameData.dexData[speciesId].natureAttr |= 1 << (this.nature + 1);
|
playerPokemon.scene.gameData.dexData[speciesId].natureAttr |= 1 << (this.nature + 1);
|
||||||
|
|
||||||
|
@ -2213,7 +2214,7 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier {
|
||||||
playerPokemon.levelExp = 0;
|
playerPokemon.levelExp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerPokemon.addFriendship(5);
|
playerPokemon.addFriendship(FRIENDSHIP_GAIN_FROM_RARE_CANDY);
|
||||||
|
|
||||||
playerPokemon.scene.unshiftPhase(new LevelUpPhase(playerPokemon.scene, playerPokemon.scene.getParty().indexOf(playerPokemon), playerPokemon.level - levelCount.value, playerPokemon.level));
|
playerPokemon.scene.unshiftPhase(new LevelUpPhase(playerPokemon.scene, playerPokemon.scene.getParty().indexOf(playerPokemon), playerPokemon.level - levelCount.value, playerPokemon.level));
|
||||||
|
|
||||||
|
@ -2235,7 +2236,7 @@ export class TmModifier extends ConsumablePokemonModifier {
|
||||||
*/
|
*/
|
||||||
override apply(playerPokemon: PlayerPokemon): boolean {
|
override apply(playerPokemon: PlayerPokemon): boolean {
|
||||||
|
|
||||||
playerPokemon.scene.unshiftPhase(new LearnMovePhase(playerPokemon.scene, playerPokemon.scene.getParty().indexOf(playerPokemon), this.type.moveId, true));
|
playerPokemon.scene.unshiftPhase(new LearnMovePhase(playerPokemon.scene, playerPokemon.scene.getParty().indexOf(playerPokemon), this.type.moveId, LearnMoveType.TM));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2255,8 +2256,9 @@ export class RememberMoveModifier extends ConsumablePokemonModifier {
|
||||||
* @param playerPokemon The {@linkcode PlayerPokemon} that should remember the move
|
* @param playerPokemon The {@linkcode PlayerPokemon} that should remember the move
|
||||||
* @returns always `true`
|
* @returns always `true`
|
||||||
*/
|
*/
|
||||||
override apply(playerPokemon: PlayerPokemon): boolean {
|
override apply(playerPokemon: PlayerPokemon, cost?: number): boolean {
|
||||||
playerPokemon.scene.unshiftPhase(new LearnMovePhase(playerPokemon.scene, playerPokemon.scene.getParty().indexOf(playerPokemon), playerPokemon.getLearnableLevelMoves()[this.levelMoveIndex]));
|
|
||||||
|
playerPokemon.scene.unshiftPhase(new LearnMovePhase(playerPokemon.scene, playerPokemon.scene.getParty().indexOf(playerPokemon), playerPokemon.getLearnableLevelMoves()[this.levelMoveIndex], LearnMoveType.MEMORY, cost));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3635,7 +3637,7 @@ export function overrideHeldItems(scene: BattleScene, pokemon: Pokemon, isPlayer
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isPlayer) {
|
if (!isPlayer) {
|
||||||
scene.clearEnemyHeldItemModifiers();
|
scene.clearEnemyHeldItemModifiers(pokemon);
|
||||||
}
|
}
|
||||||
|
|
||||||
heldItemsOverride.forEach(item => {
|
heldItemsOverride.forEach(item => {
|
||||||
|
|
|
@ -8,7 +8,6 @@ export class Phase {
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
console.log(`%cStart Phase ${this.constructor.name}`, "color:green;");
|
|
||||||
if (this.scene.abilityBar.shown) {
|
if (this.scene.abilityBar.shown) {
|
||||||
this.scene.abilityBar.resetAutoHideTimer();
|
this.scene.abilityBar.resetAutoHideTimer();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { PostTurnStatusEffectPhase } from "#app/phases/post-turn-status-effect-phase";
|
||||||
|
import { Phase } from "#app/phase";
|
||||||
|
import { BattlerIndex } from "#app/battle";
|
||||||
|
import BattleScene from "#app/battle-scene";
|
||||||
|
|
||||||
|
export class CheckStatusEffectPhase extends Phase {
|
||||||
|
private order : BattlerIndex[];
|
||||||
|
constructor(scene : BattleScene, order : BattlerIndex[]) {
|
||||||
|
super(scene);
|
||||||
|
this.scene = scene;
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
const field = this.scene.getField();
|
||||||
|
for (const o of this.order) {
|
||||||
|
if (field[o].status && field[o].status.isPostTurn()) {
|
||||||
|
this.scene.unshiftPhase(new PostTurnStatusEffectPhase(this.scene, o));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.end();
|
||||||
|
}
|
||||||
|
}
|
|
@ -114,8 +114,8 @@ export class CommandPhase extends FieldPhase {
|
||||||
|
|
||||||
// Decides between a Disabled, Not Implemented, or No PP translation message
|
// Decides between a Disabled, Not Implemented, or No PP translation message
|
||||||
const errorMessage =
|
const errorMessage =
|
||||||
playerPokemon.isMoveRestricted(move.moveId)
|
playerPokemon.isMoveRestricted(move.moveId, playerPokemon)
|
||||||
? playerPokemon.getRestrictingTag(move.moveId)!.selectionDeniedText(playerPokemon, move.moveId)
|
? playerPokemon.getRestrictingTag(move.moveId, playerPokemon)!.selectionDeniedText(playerPokemon, move.moveId)
|
||||||
: move.getName().endsWith(" (N)") ? "battle:moveNotImplemented" : "battle:moveNoPP";
|
: move.getName().endsWith(" (N)") ? "battle:moveNotImplemented" : "battle:moveNoPP";
|
||||||
const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator
|
const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ export class EggLapsePhase extends Phase {
|
||||||
if (eggsToHatchCount > 0) {
|
if (eggsToHatchCount > 0) {
|
||||||
if (eggsToHatchCount >= this.minEggsToSkip && this.scene.eggSkipPreference === 1) {
|
if (eggsToHatchCount >= this.minEggsToSkip && this.scene.eggSkipPreference === 1) {
|
||||||
this.scene.ui.showText(i18next.t("battle:eggHatching"), 0, () => {
|
this.scene.ui.showText(i18next.t("battle:eggHatching"), 0, () => {
|
||||||
// show prompt for skip
|
// show prompt for skip, blocking inputs for 1 second
|
||||||
this.scene.ui.showText(i18next.t("battle:eggSkipPrompt"), 0);
|
this.scene.ui.showText(i18next.t("battle:eggSkipPrompt"), 0);
|
||||||
this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
||||||
this.hatchEggsSkipped(eggsToHatch);
|
this.hatchEggsSkipped(eggsToHatch);
|
||||||
|
@ -41,7 +41,8 @@ export class EggLapsePhase extends Phase {
|
||||||
}, () => {
|
}, () => {
|
||||||
this.hatchEggsRegular(eggsToHatch);
|
this.hatchEggsRegular(eggsToHatch);
|
||||||
this.end();
|
this.end();
|
||||||
}
|
},
|
||||||
|
null, null, null, 1000, true
|
||||||
);
|
);
|
||||||
}, 100, true);
|
}, 100, true);
|
||||||
} else if (eggsToHatchCount >= this.minEggsToSkip && this.scene.eggSkipPreference === 2) {
|
} else if (eggsToHatchCount >= this.minEggsToSkip && this.scene.eggSkipPreference === 2) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
import { Phase } from "#app/phase";
|
import { Phase } from "#app/phase";
|
||||||
import { Mode } from "#app/ui/ui";
|
import { Mode } from "#app/ui/ui";
|
||||||
import EggHatchSceneHandler from "#app/ui/egg-hatch-scene-handler";
|
|
||||||
import { EggHatchData } from "#app/data/egg-hatch-data";
|
import { EggHatchData } from "#app/data/egg-hatch-data";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,7 +10,6 @@ import { EggHatchData } from "#app/data/egg-hatch-data";
|
||||||
*/
|
*/
|
||||||
export class EggSummaryPhase extends Phase {
|
export class EggSummaryPhase extends Phase {
|
||||||
private eggHatchData: EggHatchData[];
|
private eggHatchData: EggHatchData[];
|
||||||
private eggHatchHandler: EggHatchSceneHandler;
|
|
||||||
|
|
||||||
constructor(scene: BattleScene, eggHatchData: EggHatchData[]) {
|
constructor(scene: BattleScene, eggHatchData: EggHatchData[]) {
|
||||||
super(scene);
|
super(scene);
|
||||||
|
@ -26,7 +24,6 @@ export class EggSummaryPhase extends Phase {
|
||||||
if (i >= this.eggHatchData.length) {
|
if (i >= this.eggHatchData.length) {
|
||||||
this.scene.ui.setModeForceTransition(Mode.EGG_HATCH_SUMMARY, this.eggHatchData).then(() => {
|
this.scene.ui.setModeForceTransition(Mode.EGG_HATCH_SUMMARY, this.eggHatchData).then(() => {
|
||||||
this.scene.fadeOutBgm(undefined, false);
|
this.scene.fadeOutBgm(undefined, false);
|
||||||
this.eggHatchHandler = this.scene.ui.getHandler() as EggHatchSceneHandler;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|