Merge branch 'beta' into charge-move-overhaul
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 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: 10 KiB After Width: | Height: | Size: 11 KiB |
40
public/images/pokemon/variant/6706.json
Normal file
@ -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": [
|
||||
0,
|
||||
2,
|
||||
2
|
||||
1,
|
||||
1
|
||||
],
|
||||
"6713": [
|
||||
0,
|
||||
@ -7754,8 +7754,8 @@
|
||||
],
|
||||
"6706": [
|
||||
0,
|
||||
2,
|
||||
2
|
||||
1,
|
||||
1
|
||||
],
|
||||
"6713": [
|
||||
0,
|
||||
@ -8493,8 +8493,8 @@
|
||||
],
|
||||
"705": [
|
||||
0,
|
||||
2,
|
||||
2
|
||||
1,
|
||||
1
|
||||
],
|
||||
"706": [
|
||||
0,
|
||||
@ -9568,8 +9568,8 @@
|
||||
],
|
||||
"6706": [
|
||||
0,
|
||||
2,
|
||||
2
|
||||
1,
|
||||
1
|
||||
],
|
||||
"female": {},
|
||||
"back": {
|
||||
@ -11095,8 +11095,8 @@
|
||||
],
|
||||
"6706": [
|
||||
0,
|
||||
2,
|
||||
2
|
||||
1,
|
||||
1
|
||||
],
|
||||
"6713": [
|
||||
0,
|
||||
|
38
public/images/pokemon/variant/back/6706.json
Normal file
@ -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 |
40
public/images/pokemon/variant/exp/6706.json
Normal file
@ -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 |
33
public/images/pokemon/variant/exp/705.json
Normal file
@ -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 |
38
public/images/pokemon/variant/exp/back/6706.json
Normal file
@ -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 |
@ -2316,7 +2316,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 {
|
||||
@ -2326,6 +2329,7 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
this.standbyPhase = this.currentPhase;
|
||||
this.currentPhase = phase;
|
||||
console.log(`%cStart Phase ${phase.constructor.name}`, "color:green;");
|
||||
phase.start();
|
||||
|
||||
return true;
|
||||
@ -2676,7 +2680,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 {
|
||||
const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PersistentModifier);
|
||||
@ -2687,10 +2691,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 {
|
||||
const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PokemonHeldItemModifier);
|
||||
clearEnemyHeldItemModifiers(pokemon?: Pokemon): void {
|
||||
const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PokemonHeldItemModifier && (!pokemon || m.getPokemon(this) === pokemon));
|
||||
for (const m of modifiersToRemove) {
|
||||
this.enemyModifiers.splice(this.enemyModifiers.indexOf(m), 1);
|
||||
}
|
||||
|
@ -118,6 +118,14 @@ export class Ability implements Localizable {
|
||||
this.nameAppend += " (N)";
|
||||
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>;
|
||||
@ -4906,7 +4914,7 @@ export function initAbilities() {
|
||||
.ignorable(),
|
||||
new Ability(Abilities.SHIELD_DUST, 3)
|
||||
.attr(IgnoreMoveEffectsAbAttr)
|
||||
.partial(),
|
||||
.edgeCase(), // Does not work with secret power (unimplemented)
|
||||
new Ability(Abilities.OWN_TEMPO, 3)
|
||||
.attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED)
|
||||
.attr(IntimidateImmunityAbAttr)
|
||||
@ -4951,7 +4959,7 @@ export function initAbilities() {
|
||||
.ignorable(),
|
||||
new Ability(Abilities.SERENE_GRACE, 3)
|
||||
.attr(MoveEffectChanceMultiplierAbAttr, 2)
|
||||
.partial(),
|
||||
.edgeCase(), // does not work with secret power (unimplemented)
|
||||
new Ability(Abilities.SWIFT_SWIM, 3)
|
||||
.attr(StatMultiplierAbAttr, Stat.SPD, 2)
|
||||
.condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)),
|
||||
@ -5235,7 +5243,8 @@ export function initAbilities() {
|
||||
new Ability(Abilities.SHEER_FORCE, 5)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 5461 / 4096)
|
||||
.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)
|
||||
.attr(StatStageChangeMultiplierAbAttr, -1)
|
||||
.ignorable(),
|
||||
@ -5278,7 +5287,7 @@ export function initAbilities() {
|
||||
/** 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)
|
||||
)
|
||||
.partial(),
|
||||
.edgeCase(), // Cannot recover berries used up by fling or natural gift (unimplemented)
|
||||
new Ability(Abilities.TELEPATHY, 5)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon.getAlly() === attacker && move instanceof AttackMove)
|
||||
.ignorable(),
|
||||
@ -5357,7 +5366,7 @@ export function initAbilities() {
|
||||
.bypassFaint(),
|
||||
new Ability(Abilities.VICTORY_STAR, 5)
|
||||
.attr(StatMultiplierAbAttr, Stat.ACC, 1.1)
|
||||
.partial(),
|
||||
.partial(), // Does not boost ally's accuracy
|
||||
new Ability(Abilities.TURBOBLAZE, 5)
|
||||
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonTurboblaze", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
|
||||
.attr(MoveAbilityBypassAbAttr),
|
||||
@ -5468,7 +5477,7 @@ export function initAbilities() {
|
||||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.bypassFaint()
|
||||
.partial(),
|
||||
.partial(), // Meteor form should protect against status effects and yawn
|
||||
new Ability(Abilities.STAKEOUT, 7)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => user?.scene.currentBattle.turnCommands[target?.getBattlerIndex() ?? BattlerIndex.ATTACKER]?.command === Command.POKEMON, 2),
|
||||
new Ability(Abilities.WATER_BUBBLE, 7)
|
||||
@ -5536,9 +5545,9 @@ export function initAbilities() {
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.bypassFaint()
|
||||
.partial(),
|
||||
new Ability(Abilities.CORROSION, 7) // TODO: Test Corrosion against Magic Bounce once it is implemented
|
||||
new Ability(Abilities.CORROSION, 7)
|
||||
.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)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
@ -5693,7 +5702,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.WANDERING_SPIRIT, 8)
|
||||
.attr(PostDefendAbilitySwapAbAttr)
|
||||
.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)
|
||||
.attr(GorillaTacticsAbAttr),
|
||||
new Ability(Abilities.NEUTRALIZING_GAS, 8)
|
||||
@ -5702,7 +5711,7 @@ export function initAbilities() {
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.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)
|
||||
.attr(PostSummonUserFieldRemoveStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
||||
.attr(UserFieldStatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
|
||||
@ -5807,7 +5816,7 @@ export function initAbilities() {
|
||||
new Ability(Abilities.GOOD_AS_GOLD, 9)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.category === MoveCategory.STATUS)
|
||||
.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)
|
||||
.attr(FieldMultiplyStatAbAttr, Stat.SPATK, 0.75)
|
||||
.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),
|
||||
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))
|
||||
.partial(),
|
||||
.partial(), // Counter resets every wave
|
||||
new Ability(Abilities.COSTAR, 9)
|
||||
.attr(PostSummonCopyAllyStatsAbAttr),
|
||||
new Ability(Abilities.TOXIC_DEBRIS, 9)
|
||||
@ -5873,25 +5882,25 @@ export function initAbilities() {
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(),
|
||||
.partial(), // Ogerpon tera interactions
|
||||
new Ability(Abilities.EMBODY_ASPECT_WELLSPRING, 9)
|
||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.SPDEF ], 1, true)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(),
|
||||
.partial(), // Ogerpon tera interactions
|
||||
new Ability(Abilities.EMBODY_ASPECT_HEARTHFLAME, 9)
|
||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.ATK ], 1, true)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(),
|
||||
.partial(), // Ogerpon tera interactions
|
||||
new Ability(Abilities.EMBODY_ASPECT_CORNERSTONE, 9)
|
||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.DEF ], 1, true)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(),
|
||||
.partial(), // Ogerpon tera interactions
|
||||
new Ability(Abilities.TERA_SHIFT, 9)
|
||||
.attr(PostSummonFormChangeAbAttr, p => p.getFormKey() ? 0 : 1)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
|
@ -28,20 +28,13 @@ export enum ArenaTagSide {
|
||||
}
|
||||
|
||||
export abstract class ArenaTag {
|
||||
public tagType: ArenaTagType;
|
||||
public turnCount: integer;
|
||||
public sourceMove?: Moves;
|
||||
public sourceId?: integer;
|
||||
public side: ArenaTagSide;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
constructor(
|
||||
public tagType: ArenaTagType,
|
||||
public turnCount: number,
|
||||
public sourceMove?: Moves,
|
||||
public sourceId?: number,
|
||||
public side: ArenaTagSide = ArenaTagSide.BOTH
|
||||
) {}
|
||||
|
||||
apply(arena: Arena, args: any[]): boolean {
|
||||
return true;
|
||||
@ -66,6 +59,18 @@ export abstract class ArenaTag {
|
||||
? allMoves[this.sourceMove].name
|
||||
: 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,7 +78,7 @@ export abstract class ArenaTag {
|
||||
* Prevents Pokémon on the opposing side from lowering the stats of the Pokémon in the Mist.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -117,7 +122,7 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
||||
* @param side - The side (player or enemy) the tag affects.
|
||||
* @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);
|
||||
|
||||
this.weakenedCategories = weakenedCategories;
|
||||
@ -148,7 +153,7 @@ export class WeakenMoveScreenTag extends ArenaTag {
|
||||
* Used by {@linkcode Moves.REFLECT}
|
||||
*/
|
||||
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 ]);
|
||||
}
|
||||
|
||||
@ -164,7 +169,7 @@ class ReflectTag extends WeakenMoveScreenTag {
|
||||
* Used by {@linkcode Moves.LIGHT_SCREEN}
|
||||
*/
|
||||
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 ]);
|
||||
}
|
||||
|
||||
@ -180,7 +185,7 @@ class LightScreenTag extends WeakenMoveScreenTag {
|
||||
* Used by {@linkcode Moves.AURORA_VEIL}
|
||||
*/
|
||||
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 ]);
|
||||
}
|
||||
|
||||
@ -203,7 +208,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
||||
/** Does this apply to all moves, including those that ignore other forms of protection? */
|
||||
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);
|
||||
|
||||
this.protectConditionFunc = condition;
|
||||
@ -265,7 +270,7 @@ export class ConditionalProtectTag extends ArenaTag {
|
||||
*/
|
||||
const QuickGuardConditionFunc: ProtectConditionFunc = (arena, moveId) => {
|
||||
const move = allMoves[moveId];
|
||||
const priority = new Utils.IntegerHolder(move.priority);
|
||||
const priority = new Utils.NumberHolder(move.priority);
|
||||
const effectPhase = arena.scene.getCurrentPhase();
|
||||
|
||||
if (effectPhase instanceof MoveEffectPhase) {
|
||||
@ -281,7 +286,7 @@ const QuickGuardConditionFunc: ProtectConditionFunc = (arena, moveId) => {
|
||||
* Condition: The incoming move has increased priority.
|
||||
*/
|
||||
class QuickGuardTag extends ConditionalProtectTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.QUICK_GUARD, Moves.QUICK_GUARD, sourceId, side, QuickGuardConditionFunc);
|
||||
}
|
||||
}
|
||||
@ -312,7 +317,7 @@ const WideGuardConditionFunc: ProtectConditionFunc = (arena, moveId) : boolean =
|
||||
* can be an ally or enemy.
|
||||
*/
|
||||
class WideGuardTag extends ConditionalProtectTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.WIDE_GUARD, Moves.WIDE_GUARD, sourceId, side, WideGuardConditionFunc);
|
||||
}
|
||||
}
|
||||
@ -334,7 +339,7 @@ const MatBlockConditionFunc: ProtectConditionFunc = (arena, moveId) : boolean =>
|
||||
* Condition: The incoming move is a Physical or Special attack move.
|
||||
*/
|
||||
class MatBlockTag extends ConditionalProtectTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.MAT_BLOCK, Moves.MAT_BLOCK, sourceId, side, MatBlockConditionFunc);
|
||||
}
|
||||
|
||||
@ -372,7 +377,7 @@ const CraftyShieldConditionFunc: ProtectConditionFunc = (arena, moveId) => {
|
||||
* not target all Pokemon or sides of the field.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -384,12 +389,12 @@ class CraftyShieldTag extends ConditionalProtectTag {
|
||||
export class NoCritTag extends ArenaTag {
|
||||
/**
|
||||
* 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 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
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -419,7 +424,7 @@ class WishTag extends ArenaTag {
|
||||
private triggerMessage: string;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -460,7 +465,7 @@ export class WeakenMoveTypeTag extends ArenaTag {
|
||||
* @param sourceMove - The move that created 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);
|
||||
|
||||
this.weakenedType = type;
|
||||
@ -481,7 +486,7 @@ export class WeakenMoveTypeTag extends ArenaTag {
|
||||
* Weakens Electric type moves for a set amount of turns, usually 5.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -499,7 +504,7 @@ class MudSportTag extends WeakenMoveTypeTag {
|
||||
* Weakens Fire type moves for a set amount of turns, usually 5.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -550,8 +555,8 @@ export class IonDelugeTag extends ArenaTag {
|
||||
* Abstract class to implement arena traps.
|
||||
*/
|
||||
export class ArenaTrapTag extends ArenaTag {
|
||||
public layers: integer;
|
||||
public maxLayers: integer;
|
||||
public layers: number;
|
||||
public maxLayers: number;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the ArenaTrapTag class.
|
||||
@ -562,7 +567,7 @@ export class ArenaTrapTag extends ArenaTag {
|
||||
* @param side - The side (player or enemy) the tag affects.
|
||||
* @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);
|
||||
|
||||
this.layers = 1;
|
||||
@ -593,6 +598,12 @@ export class ArenaTrapTag extends ArenaTag {
|
||||
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);
|
||||
}
|
||||
|
||||
loadTag(source: any): void {
|
||||
super.loadTag(source);
|
||||
this.layers = source.layers;
|
||||
this.maxLayers = source.maxLayers;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -601,7 +612,7 @@ export class ArenaTrapTag extends ArenaTag {
|
||||
* in damage for 1, 2, or 3 layers of Spikes respectively if they are summoned into this trap.
|
||||
*/
|
||||
class SpikesTag extends ArenaTrapTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.SPIKES, Moves.SPIKES, sourceId, side, 3);
|
||||
}
|
||||
|
||||
@ -645,7 +656,7 @@ class SpikesTag extends ArenaTrapTag {
|
||||
class ToxicSpikesTag extends ArenaTrapTag {
|
||||
private neutralized: boolean;
|
||||
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.TOXIC_SPIKES, Moves.TOXIC_SPIKES, sourceId, side, 2);
|
||||
this.neutralized = false;
|
||||
}
|
||||
@ -703,7 +714,7 @@ class ToxicSpikesTag extends ArenaTrapTag {
|
||||
class DelayedAttackTag extends ArenaTag {
|
||||
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);
|
||||
|
||||
this.targetIndex = targetIndex;
|
||||
@ -728,7 +739,7 @@ class DelayedAttackTag extends ArenaTag {
|
||||
* who is summoned into the trap, based on the Rock type's type effectiveness.
|
||||
*/
|
||||
class StealthRockTag extends ArenaTrapTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.STEALTH_ROCK, Moves.STEALTH_ROCK, sourceId, side, 1);
|
||||
}
|
||||
|
||||
@ -804,7 +815,7 @@ class StealthRockTag extends ArenaTrapTag {
|
||||
* to any Pokémon who is summoned into this trap.
|
||||
*/
|
||||
class StickyWebTag extends ArenaTrapTag {
|
||||
constructor(sourceId: integer, side: ArenaTagSide) {
|
||||
constructor(sourceId: number, side: ArenaTagSide) {
|
||||
super(ArenaTagType.STICKY_WEB, Moves.STICKY_WEB, sourceId, side, 1);
|
||||
}
|
||||
|
||||
@ -838,7 +849,7 @@ class StickyWebTag extends ArenaTrapTag {
|
||||
* also reversing the turn order for all Pokémon on the field as well.
|
||||
*/
|
||||
export class TrickRoomTag extends ArenaTag {
|
||||
constructor(turnCount: integer, sourceId: integer) {
|
||||
constructor(turnCount: number, sourceId: number) {
|
||||
super(ArenaTagType.TRICK_ROOM, turnCount, Moves.TRICK_ROOM, sourceId);
|
||||
}
|
||||
|
||||
@ -866,7 +877,7 @@ export class TrickRoomTag extends ArenaTag {
|
||||
* {@linkcode Abilities.LEVITATE} for the duration of the arena tag, usually 5 turns.
|
||||
*/
|
||||
export class GravityTag extends ArenaTag {
|
||||
constructor(turnCount: integer) {
|
||||
constructor(turnCount: number) {
|
||||
super(ArenaTagType.GRAVITY, turnCount, Moves.GRAVITY);
|
||||
}
|
||||
|
||||
@ -874,7 +885,8 @@ export class GravityTag extends ArenaTag {
|
||||
arena.scene.queueMessage(i18next.t("arenaTag:gravityOnAdd"));
|
||||
arena.scene.getField(true).forEach((pokemon) => {
|
||||
if (pokemon !== null) {
|
||||
pokemon.removeTag(BattlerTagType.MAGNET_RISEN);
|
||||
pokemon.removeTag(BattlerTagType.FLOATING);
|
||||
pokemon.removeTag(BattlerTagType.TELEKINESIS);
|
||||
if (pokemon.getTag(BattlerTagType.FLYING)) {
|
||||
pokemon.addTag(BattlerTagType.INTERRUPTED);
|
||||
}
|
||||
@ -893,7 +905,7 @@ export class GravityTag extends ArenaTag {
|
||||
* Applies this arena tag for 4 turns (including the turn the move was used).
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -931,7 +943,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}.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -945,7 +957,7 @@ class HappyHourTag 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);
|
||||
}
|
||||
|
||||
@ -958,6 +970,11 @@ class SafeguardTag extends ArenaTag {
|
||||
}
|
||||
}
|
||||
|
||||
class NoneTag extends ArenaTag {
|
||||
constructor() {
|
||||
super(ArenaTagType.NONE, 0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
@ -1105,7 +1122,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) {
|
||||
case ArenaTagType.MIST:
|
||||
return new MistTag(turnCount, sourceId, side);
|
||||
@ -1166,3 +1184,16 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1709,7 +1709,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) {
|
||||
super(tagType, sourceMove, Type.GROUND, 5);
|
||||
}
|
||||
@ -1717,13 +1722,17 @@ export class MagnetRisenTag extends TypeImmuneTag {
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
if (this.sourceMove === Moves.MAGNET_RISE) {
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onRemove(pokemon: Pokemon): void {
|
||||
super.onRemove(pokemon);
|
||||
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnRemove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
if (this.sourceMove === Moves.MAGNET_RISE) {
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnRemove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2672,6 +2681,22 @@ 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) }));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -2798,8 +2823,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||
return new CursedTag(sourceId);
|
||||
case BattlerTagType.CHARGED:
|
||||
return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true);
|
||||
case BattlerTagType.MAGNET_RISEN:
|
||||
return new MagnetRisenTag(tagType, sourceMove);
|
||||
case BattlerTagType.FLOATING:
|
||||
return new FloatingTag(tagType, sourceMove);
|
||||
case BattlerTagType.MINIMIZED:
|
||||
return new MinimizeTag();
|
||||
case BattlerTagType.DESTINY_BOND:
|
||||
@ -2845,6 +2870,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||
return new ImprisonTag(sourceId);
|
||||
case BattlerTagType.SYRUP_BOMB:
|
||||
return new SyrupBombTag(sourceId);
|
||||
case BattlerTagType.TELEKINESIS:
|
||||
return new TelekinesisTag(sourceMove);
|
||||
case BattlerTagType.NONE:
|
||||
default:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||
|
118
src/data/move.ts
@ -368,6 +368,14 @@ export default class Move implements Localizable {
|
||||
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
|
||||
* @returns the called object {@linkcode Move}
|
||||
@ -4590,18 +4598,19 @@ export class WaterSuperEffectTypeMultiplierAttr extends VariableMoveTypeMultipli
|
||||
export class IceNoEffectTypeAttr extends VariableMoveTypeMultiplierAttr {
|
||||
/**
|
||||
* 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 {Pokemon} target Pokemon that is being checked whether Ice-Type or not.
|
||||
* @param {Move} move N/A
|
||||
* @param {any[]} args Sets to false if the target is Ice-Type, so it should do no damage/no effect.
|
||||
* @returns {boolean} Returns true if move is successful, false if Ice-Type.
|
||||
* @param user n/a
|
||||
* @param target The {@linkcode Pokemon} targeted by the move
|
||||
* @param move n/a
|
||||
* @param args `[0]` a {@linkcode Utils.NumberHolder | NumberHolder} containing a type effectiveness multiplier
|
||||
* @returns `true` if this Ice-type immunity applies; `false` otherwise
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const multiplier = args[0] as Utils.NumberHolder;
|
||||
if (target.isOfType(Type.ICE)) {
|
||||
(args[0] as Utils.BooleanHolder).value = false;
|
||||
return false;
|
||||
multiplier.value = 0;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7166,7 +7175,8 @@ export function initMoves() {
|
||||
.attr(ForceSwitchOutAttr)
|
||||
.ignoresSubstitute()
|
||||
.hidesTarget()
|
||||
.windMove(),
|
||||
.windMove()
|
||||
.partial(), // Should force random switches
|
||||
new ChargingAttackMove(Moves.FLY, Type.FLYING, MoveCategory.PHYSICAL, 90, 95, 15, -1, 0, 1)
|
||||
.chargeText(i18next.t("moveTriggers:flewUpHigh", { pokemonName: "{USER}" }))
|
||||
.chargeAttr(SemiInvulnerableAttr, BattlerTagType.FLYING)
|
||||
@ -7244,7 +7254,8 @@ export function initMoves() {
|
||||
new StatusMove(Moves.ROAR, Type.NORMAL, -1, 20, -1, -6, 1)
|
||||
.attr(ForceSwitchOutAttr)
|
||||
.soundBased()
|
||||
.hidesTarget(),
|
||||
.hidesTarget()
|
||||
.partial(), // Should force random switching
|
||||
new StatusMove(Moves.SING, Type.NORMAL, 55, 15, -1, 0, 1)
|
||||
.attr(StatusEffectAttr, StatusEffect.SLEEP)
|
||||
.soundBased(),
|
||||
@ -7387,7 +7398,7 @@ export function initMoves() {
|
||||
.attr(StatStageChangeAttr, [ Stat.SPD ], 2, true),
|
||||
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)
|
||||
.partial(),
|
||||
.partial(), // No effect implemented
|
||||
new SelfStatusMove(Moves.TELEPORT, Type.PSYCHIC, -1, 20, -1, -6, 1)
|
||||
.attr(ForceSwitchOutAttr, true)
|
||||
.hidesUser(),
|
||||
@ -7702,7 +7713,7 @@ export function initMoves() {
|
||||
new StatusMove(Moves.CHARM, Type.FAIRY, 100, 20, -1, 0, 2)
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK ], -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),
|
||||
new AttackMove(Moves.FALSE_SWIPE, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 2)
|
||||
.attr(SurviveDamageAttr),
|
||||
@ -7773,7 +7784,7 @@ export function initMoves() {
|
||||
.ignoresSubstitute()
|
||||
.condition((user, target, move) => new EncoreTag(user.id).canAdd(target)),
|
||||
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)
|
||||
.attr(StatStageChangeAttr, [ Stat.SPD ], 1, true)
|
||||
.attr(RemoveBattlerTagAttr, [
|
||||
@ -7838,7 +7849,7 @@ export function initMoves() {
|
||||
.attr(StatStageChangeAttr, [ Stat.SPDEF ], -1)
|
||||
.ballBombMove(),
|
||||
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}" })),
|
||||
new AttackMove(Moves.ROCK_SMASH, Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 15, 50, 0, 2)
|
||||
.attr(StatStageChangeAttr, [ Stat.DEF ], -1),
|
||||
@ -7856,7 +7867,7 @@ export function initMoves() {
|
||||
.ignoresVirtual()
|
||||
.soundBased()
|
||||
.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)
|
||||
.condition(user => (user.getTag(StockpilingTag)?.stockpiledCount ?? 0) < 3)
|
||||
.attr(AddBattlerTagAttr, BattlerTagType.STOCKPILING, true),
|
||||
@ -7879,7 +7890,7 @@ export function initMoves() {
|
||||
.target(MoveTarget.BOTH_SIDES),
|
||||
new StatusMove(Moves.TORMENT, Type.DARK, 100, 15, -1, 0, 3)
|
||||
.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),
|
||||
new StatusMove(Moves.FLATTER, Type.DARK, 100, 15, -1, 0, 3)
|
||||
.attr(StatStageChangeAttr, [ Stat.SPATK ], 1)
|
||||
@ -7928,7 +7939,9 @@ export function initMoves() {
|
||||
.attr(RandomMovesetMoveAttr, true)
|
||||
.ignoresVirtual(),
|
||||
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)
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF ], -1, true),
|
||||
new SelfStatusMove(Moves.MAGIC_COAT, Type.PSYCHIC, -1, 15, -1, 4, 3)
|
||||
@ -7966,7 +7979,7 @@ export function initMoves() {
|
||||
.unimplemented(),
|
||||
new AttackMove(Moves.SECRET_POWER, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, 30, 0, 3)
|
||||
.makesContact(false)
|
||||
.partial(),
|
||||
.partial(), // No effect implemented
|
||||
new ChargingAttackMove(Moves.DIVE, Type.WATER, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 3)
|
||||
.chargeText(i18next.t("moveTriggers:hidUnderwater", { pokemonName: "{USER}" }))
|
||||
.chargeAttr(SemiInvulnerableAttr, BattlerTagType.UNDERWATER)
|
||||
@ -7998,7 +8011,7 @@ export function initMoves() {
|
||||
.attr(AddArenaTagAttr, ArenaTagType.MUD_SPORT, 5)
|
||||
.target(MoveTarget.BOTH_SIDES),
|
||||
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)
|
||||
.ballBombMove(),
|
||||
new AttackMove(Moves.NEEDLE_ARM, Type.GRASS, MoveCategory.PHYSICAL, 60, 100, 15, 30, 0, 3)
|
||||
@ -8142,7 +8155,7 @@ export function initMoves() {
|
||||
.attr(ConfuseAttr)
|
||||
.pulseMove(),
|
||||
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}" })),
|
||||
new AttackMove(Moves.PSYCHO_BOOST, Type.PSYCHIC, MoveCategory.SPECIAL, 140, 90, 5, -1, 0, 3)
|
||||
.attr(StatStageChangeAttr, [ Stat.SPATK ], -2, true),
|
||||
@ -8264,8 +8277,8 @@ export function initMoves() {
|
||||
new SelfStatusMove(Moves.AQUA_RING, Type.WATER, -1, 20, -1, 0, 4)
|
||||
.attr(AddBattlerTagAttr, BattlerTagType.AQUA_RING, true, true),
|
||||
new SelfStatusMove(Moves.MAGNET_RISE, Type.ELECTRIC, -1, 10, -1, 0, 4)
|
||||
.attr(AddBattlerTagAttr, BattlerTagType.MAGNET_RISEN, 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))),
|
||||
.attr(AddBattlerTagAttr, BattlerTagType.FLOATING, true, true)
|
||||
.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)
|
||||
.attr(RecoilAttr, false, 0.33)
|
||||
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
|
||||
@ -8491,7 +8504,11 @@ export function initMoves() {
|
||||
.attr(AddBattlerTagAttr, BattlerTagType.CENTER_OF_ATTENTION, true),
|
||||
new StatusMove(Moves.TELEKINESIS, Type.PSYCHIC, -1, 15, -1, 0, 5)
|
||||
.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)
|
||||
.ignoresProtect()
|
||||
.target(MoveTarget.BOTH_SIDES)
|
||||
@ -8499,7 +8516,7 @@ export function initMoves() {
|
||||
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.INTERRUPTED)
|
||||
.attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN ])
|
||||
.attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.FLOATING, BattlerTagType.TELEKINESIS ])
|
||||
.attr(HitsTagAttr, BattlerTagType.FLYING)
|
||||
.makesContact(false),
|
||||
new AttackMove(Moves.STORM_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 5)
|
||||
@ -8549,7 +8566,7 @@ export function initMoves() {
|
||||
.attr(AfterYouAttr),
|
||||
new AttackMove(Moves.ROUND, Type.NORMAL, MoveCategory.SPECIAL, 60, 100, 15, -1, 0, 5)
|
||||
.soundBased()
|
||||
.partial(),
|
||||
.partial(), // No effect implemented
|
||||
new AttackMove(Moves.ECHOED_VOICE, Type.NORMAL, MoveCategory.SPECIAL, 40, 100, 15, -1, 0, 5)
|
||||
.attr(ConsecutiveUseMultiBasePowerAttr, 5, false)
|
||||
.soundBased(),
|
||||
@ -8592,7 +8609,8 @@ export function initMoves() {
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK ], 1, true)
|
||||
.attr(StatStageChangeAttr, [ Stat.SPD ], 2, true),
|
||||
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)
|
||||
.target(MoveTarget.ALL_NEAR_ENEMIES)
|
||||
.attr(RemoveHeldItemAttr, true),
|
||||
@ -8660,7 +8678,8 @@ export function initMoves() {
|
||||
.attr(CritOnlyAttr),
|
||||
new AttackMove(Moves.DRAGON_TAIL, Type.DRAGON, MoveCategory.PHYSICAL, 60, 90, 10, -1, -6, 5)
|
||||
.attr(ForceSwitchOutAttr)
|
||||
.hidesTarget(),
|
||||
.hidesTarget()
|
||||
.partial(), // Should force random switches
|
||||
new SelfStatusMove(Moves.WORK_UP, Type.NORMAL, -1, 30, -1, 0, 5)
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, true),
|
||||
new AttackMove(Moves.ELECTROWEB, Type.ELECTRIC, MoveCategory.SPECIAL, 55, 95, 15, 100, 0, 5)
|
||||
@ -8789,7 +8808,7 @@ export function initMoves() {
|
||||
.ignoresVirtual(),
|
||||
new StatusMove(Moves.TRICK_OR_TREAT, Type.GHOST, 100, 20, -1, 0, 6)
|
||||
.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)
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1)
|
||||
.soundBased(),
|
||||
@ -8802,7 +8821,7 @@ export function initMoves() {
|
||||
.triageMove(),
|
||||
new StatusMove(Moves.FORESTS_CURSE, Type.GRASS, 100, 20, -1, 0, 6)
|
||||
.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)
|
||||
.windMove()
|
||||
.makesContact(false)
|
||||
@ -8810,7 +8829,7 @@ export function initMoves() {
|
||||
new AttackMove(Moves.FREEZE_DRY, Type.ICE, MoveCategory.SPECIAL, 70, 100, 20, 10, 0, 6)
|
||||
.attr(StatusEffectAttr, StatusEffect.FREEZE)
|
||||
.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)
|
||||
.soundBased()
|
||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||
@ -8934,9 +8953,9 @@ export function initMoves() {
|
||||
.attr(NeutralDamageAgainstFlyingTypeMultiplierAttr)
|
||||
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 1, 1, true)
|
||||
.attr(HitsTagAttr, BattlerTagType.FLYING)
|
||||
.attr(HitsTagAttr, BattlerTagType.MAGNET_RISEN)
|
||||
.attr(HitsTagAttr, BattlerTagType.FLOATING)
|
||||
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
|
||||
.attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN ])
|
||||
.attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.FLOATING, BattlerTagType.TELEKINESIS ])
|
||||
.makesContact(false)
|
||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||
new AttackMove(Moves.THOUSAND_WAVES, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6)
|
||||
@ -9189,15 +9208,15 @@ export function initMoves() {
|
||||
/* Unused */
|
||||
new AttackMove(Moves.SINISTER_ARROW_RAID, Type.GHOST, MoveCategory.PHYSICAL, 180, -1, 1, -1, 0, 7)
|
||||
.makesContact(false)
|
||||
.partial()
|
||||
.edgeCase() // I assume it's because the user needs spirit shackle and decidueye
|
||||
.ignoresVirtual(),
|
||||
new AttackMove(Moves.MALICIOUS_MOONSAULT, Type.DARK, MoveCategory.PHYSICAL, 180, -1, 1, -1, 0, 7)
|
||||
.attr(AlwaysHitMinimizeAttr)
|
||||
.attr(HitsTagAttr, BattlerTagType.MINIMIZED, true)
|
||||
.partial()
|
||||
.edgeCase() // I assume it's because it needs darkest lariat and incineroar
|
||||
.ignoresVirtual(),
|
||||
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(),
|
||||
new AttackMove(Moves.GUARDIAN_OF_ALOLA, Type.FAIRY, MoveCategory.SPECIAL, -1, -1, 1, -1, 0, 7)
|
||||
.unimplemented()
|
||||
@ -9206,10 +9225,10 @@ export function initMoves() {
|
||||
.unimplemented()
|
||||
.ignoresVirtual(),
|
||||
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(),
|
||||
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(),
|
||||
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)
|
||||
@ -9240,13 +9259,13 @@ export function initMoves() {
|
||||
.attr(RechargeAttr),
|
||||
new AttackMove(Moves.SPECTRAL_THIEF, Type.GHOST, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 7)
|
||||
.ignoresSubstitute()
|
||||
.partial(),
|
||||
.partial(), // Does not steal stats
|
||||
new AttackMove(Moves.SUNSTEEL_STRIKE, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 7)
|
||||
.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)
|
||||
.ignoresAbilities()
|
||||
.partial(),
|
||||
.edgeCase(), // Should not ignore abilities when called virtually (metronome)
|
||||
new StatusMove(Moves.TEARFUL_LOOK, Type.NORMAL, -1, 20, -1, 0, 7)
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1),
|
||||
new AttackMove(Moves.ZING_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 80, 100, 10, 30, 0, 7)
|
||||
@ -9257,7 +9276,7 @@ export function initMoves() {
|
||||
.attr(FormChangeItemTypeAttr),
|
||||
/* Unused */
|
||||
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(),
|
||||
/* End Unused */
|
||||
new AttackMove(Moves.MIND_BLOWN, Type.FIRE, MoveCategory.SPECIAL, 150, 100, 5, -1, 0, 7)
|
||||
@ -9270,7 +9289,7 @@ export function initMoves() {
|
||||
new AttackMove(Moves.PHOTON_GEYSER, Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7)
|
||||
.attr(PhotonGeyserCategoryAttr)
|
||||
.ignoresAbilities()
|
||||
.partial(),
|
||||
.edgeCase(), // Should not ignore abilities when called virtually (metronome)
|
||||
/* Unused */
|
||||
new AttackMove(Moves.LIGHT_THAT_BURNS_THE_SKY, Type.PSYCHIC, MoveCategory.SPECIAL, 200, -1, 1, -1, 0, 7)
|
||||
.attr(PhotonGeyserCategoryAttr)
|
||||
@ -9283,7 +9302,7 @@ export function initMoves() {
|
||||
.ignoresAbilities()
|
||||
.ignoresVirtual(),
|
||||
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(),
|
||||
new AttackMove(Moves.SPLINTERED_STORMSHARDS, Type.ROCK, MoveCategory.PHYSICAL, 190, -1, 1, -1, 0, 7)
|
||||
.attr(ClearTerrainAttr)
|
||||
@ -9293,7 +9312,7 @@ export function initMoves() {
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true, undefined, undefined, undefined, undefined, true)
|
||||
.soundBased()
|
||||
.target(MoveTarget.ALL_NEAR_ENEMIES)
|
||||
.partial()
|
||||
.edgeCase() // I assume it needs clanging scales and Kommo-O
|
||||
.ignoresVirtual(),
|
||||
/* End Unused */
|
||||
new AttackMove(Moves.ZIPPY_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 50, 100, 15, -1, 2, 7) //LGPE Implementation
|
||||
@ -9356,14 +9375,14 @@ export function initMoves() {
|
||||
new AttackMove(Moves.JAW_LOCK, Type.DARK, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 8)
|
||||
.attr(JawLockAttr)
|
||||
.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(StatStageChangeAttr, [ Stat.DEF ], 2, true)
|
||||
.condition((user) => {
|
||||
const userBerries = user.scene.findModifiers(m => m instanceof BerryModifier, user.isPlayer());
|
||||
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)
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true)
|
||||
.attr(AddBattlerTagAttr, BattlerTagType.NO_RETREAT, true, false)
|
||||
@ -9377,7 +9396,7 @@ export function initMoves() {
|
||||
new AttackMove(Moves.DRAGON_DARTS, Type.DRAGON, MoveCategory.PHYSICAL, 50, 100, 10, -1, 0, 8)
|
||||
.attr(MultiHitAttr, MultiHitType._2)
|
||||
.makesContact(false)
|
||||
.partial(),
|
||||
.partial(), // smart targetting is unimplemented
|
||||
new StatusMove(Moves.TEATIME, Type.NORMAL, -1, 10, -1, 0, 8)
|
||||
.attr(EatBerryAttr)
|
||||
.target(MoveTarget.ALL),
|
||||
@ -9816,7 +9835,7 @@ export function initMoves() {
|
||||
.attr(StatStageChangeAttr, [ Stat.SPDEF ], -2),
|
||||
new AttackMove(Moves.ORDER_UP, Type.DRAGON, MoveCategory.PHYSICAL, 80, 100, 10, 100, 0, 9)
|
||||
.makesContact(false)
|
||||
.partial(),
|
||||
.partial(), // No effect implemented (requires Commander)
|
||||
new AttackMove(Moves.JET_PUNCH, Type.WATER, MoveCategory.PHYSICAL, 60, 100, 15, -1, 1, 9)
|
||||
.punchingMove(),
|
||||
new StatusMove(Moves.SPICY_EXTRACT, Type.GRASS, -1, 15, -1, 0, 9)
|
||||
@ -10030,8 +10049,7 @@ export function initMoves() {
|
||||
new AttackMove(Moves.UPPER_HAND, Type.FIGHTING, MoveCategory.PHYSICAL, 65, 100, 15, 100, 3, 9)
|
||||
.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?
|
||||
//TODO: Should also apply when target move priority increased by ability ex. gale wings
|
||||
.partial(),
|
||||
.partial(), // Should also apply when target move priority increased by ability ex. gale wings
|
||||
new AttackMove(Moves.MALIGNANT_CHAIN, Type.POISON, MoveCategory.SPECIAL, 100, 100, 5, 50, 0, 9)
|
||||
.attr(StatusEffectAttr, StatusEffect.TOXIC)
|
||||
);
|
||||
|
@ -975,7 +975,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 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("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.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 +983,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("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("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.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 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("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.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 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.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 +1025,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("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("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.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 +1110,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 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("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.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 +1118,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.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("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.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),
|
||||
@ -2298,25 +2298,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.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("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.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 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.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 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.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 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.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 +2422,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("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("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.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 +2444,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.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("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.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),
|
||||
|
@ -54,7 +54,7 @@ export enum BattlerTagType {
|
||||
CURSED = "CURSED",
|
||||
CHARGED = "CHARGED",
|
||||
ROOSTED = "ROOSTED",
|
||||
MAGNET_RISEN = "MAGNET_RISEN",
|
||||
FLOATING = "FLOATING",
|
||||
MINIMIZED = "MINIMIZED",
|
||||
DESTINY_BOND = "DESTINY_BOND",
|
||||
CENTER_OF_ATTENTION = "CENTER_OF_ATTENTION",
|
||||
@ -86,4 +86,5 @@ export enum BattlerTagType {
|
||||
IMPRISON = "IMPRISON",
|
||||
SYRUP_BOMB = "SYRUP_BOMB",
|
||||
ELECTRIFIED = "ELECTRIFIED",
|
||||
TELEKINESIS = "TELEKINESIS"
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ export function getStatStageChangeDescriptionKey(stages: number, isIncrease: boo
|
||||
return isIncrease ? "battle:statRose" : "battle:statFell";
|
||||
} else if (stages === 2) {
|
||||
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:statWontGoAnyHigher" : "battle:statWontGoAnyLower";
|
||||
|
@ -749,9 +749,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
const relX = newOffset[0] - initialOffset[0];
|
||||
const relY = newOffset[1] - initialOffset[1];
|
||||
|
||||
const subTag = this.getTag(SubstituteTag);
|
||||
|
||||
if (duration) {
|
||||
// TODO: can this use stricter typing?
|
||||
const targets: any[] = [ this ];
|
||||
if (subTag?.sprite) {
|
||||
targets.push(subTag.sprite);
|
||||
}
|
||||
this.scene.tweens.add({
|
||||
targets: this,
|
||||
targets: targets,
|
||||
x: (_target, _key, value: number) => value + relX,
|
||||
y: (_target, _key, value: number) => value + relY,
|
||||
duration: duration,
|
||||
@ -761,6 +768,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
} else {
|
||||
this.x += relX;
|
||||
this.y += relY;
|
||||
if (subTag?.sprite) {
|
||||
subTag.sprite.x += relX;
|
||||
subTag.sprite.y += relY;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1488,7 +1499,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3635,7 +3635,7 @@ export function overrideHeldItems(scene: BattleScene, pokemon: Pokemon, isPlayer
|
||||
}
|
||||
|
||||
if (!isPlayer) {
|
||||
scene.clearEnemyHeldItemModifiers();
|
||||
scene.clearEnemyHeldItemModifiers(pokemon);
|
||||
}
|
||||
|
||||
heldItemsOverride.forEach(item => {
|
||||
|
@ -8,7 +8,6 @@ export class Phase {
|
||||
}
|
||||
|
||||
start() {
|
||||
console.log(`%cStart Phase ${this.constructor.name}`, "color:green;");
|
||||
if (this.scene.abilityBar.shown) {
|
||||
this.scene.abilityBar.resetAutoHideTimer();
|
||||
}
|
||||
|
23
src/phases/check-status-effect-phase.ts
Normal file
@ -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();
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import { applyPreAttackAbAttrs, AddSecondStrikeAbAttr, IgnoreMoveEffectsAbAttr,
|
||||
import { ArenaTagSide, ConditionalProtectTag } from "#app/data/arena-tag";
|
||||
import { MoveAnim } from "#app/data/battle-anims";
|
||||
import { BattlerTagLapseType, DamageProtectedTag, ProtectedTag, SemiInvulnerableTag, SubstituteTag } from "#app/data/battler-tags";
|
||||
import { MoveTarget, applyMoveAttrs, OverrideMoveEffectAttr, MultiHitAttr, AttackMove, FixedDamageAttr, VariableTargetAttr, MissEffectAttr, MoveFlags, applyFilteredMoveAttrs, MoveAttr, MoveEffectAttr, MoveEffectTrigger, MoveCategory, NoEffectAttr, HitsTagAttr, ToxicAccuracyAttr } from "#app/data/move";
|
||||
import { MoveTarget, applyMoveAttrs, OverrideMoveEffectAttr, MultiHitAttr, AttackMove, FixedDamageAttr, VariableTargetAttr, MissEffectAttr, MoveFlags, applyFilteredMoveAttrs, MoveAttr, MoveEffectAttr, OneHitKOAttr, MoveEffectTrigger, MoveCategory, NoEffectAttr, HitsTagAttr, ToxicAccuracyAttr } from "#app/data/move";
|
||||
import { SpeciesFormChangePostMoveTrigger } from "#app/data/pokemon-forms";
|
||||
import { BattlerTagType } from "#app/enums/battler-tag-type";
|
||||
import { Moves } from "#app/enums/moves";
|
||||
@ -401,6 +401,10 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target.getTag(BattlerTagType.TELEKINESIS) && !target.getTag(SemiInvulnerableTag) && !this.move.getMove().hasAttr(OneHitKOAttr)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const semiInvulnerableTag = target.getTag(SemiInvulnerableTag);
|
||||
if (semiInvulnerableTag
|
||||
&& !this.move.getMove().getAttrs(HitsTagAttr).some(hta => hta.tagType === semiInvulnerableTag.tagType)
|
||||
|
@ -6,7 +6,6 @@ import { StatusEffect } from "#app/enums/status-effect";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { PokemonPhase } from "./pokemon-phase";
|
||||
import { PostTurnStatusEffectPhase } from "./post-turn-status-effect-phase";
|
||||
|
||||
export class ObtainStatusEffectPhase extends PokemonPhase {
|
||||
private statusEffect?: StatusEffect | undefined;
|
||||
@ -33,9 +32,6 @@ export class ObtainStatusEffectPhase extends PokemonPhase {
|
||||
pokemon.updateInfo(true);
|
||||
new CommonBattleAnim(CommonAnim.POISON + (this.statusEffect! - 1), pokemon).play(this.scene, false, () => {
|
||||
this.scene.queueMessage(getStatusEffectObtainText(this.statusEffect, getPokemonNameWithAffix(pokemon), this.sourceText ?? undefined));
|
||||
if (pokemon.status?.isPostTurn()) {
|
||||
this.scene.pushPhase(new PostTurnStatusEffectPhase(this.scene, this.battlerIndex));
|
||||
}
|
||||
this.end();
|
||||
});
|
||||
return;
|
||||
|
@ -36,6 +36,16 @@ export class StatStageChangePhase extends PokemonPhase {
|
||||
}
|
||||
|
||||
start() {
|
||||
|
||||
// Check if multiple stats are being changed at the same time, then run SSCPhase for each of them
|
||||
if (this.stats.length > 1) {
|
||||
for (let i = 0; i < this.stats.length; i++) {
|
||||
const stat = [ this.stats[i] ];
|
||||
this.scene.unshiftPhase(new StatStageChangePhase(this.scene, this.battlerIndex, this.selfTarget, stat, this.stages, this.showMessage, this.ignoreAbilities, this.canBeCopied, this.onChange));
|
||||
}
|
||||
return this.end();
|
||||
}
|
||||
|
||||
const pokemon = this.getPokemon();
|
||||
|
||||
if (!pokemon.isActive(true)) {
|
||||
|
@ -13,10 +13,10 @@ import { BerryPhase } from "./berry-phase";
|
||||
import { FieldPhase } from "./field-phase";
|
||||
import { MoveHeaderPhase } from "./move-header-phase";
|
||||
import { MovePhase } from "./move-phase";
|
||||
import { PostTurnStatusEffectPhase } from "./post-turn-status-effect-phase";
|
||||
import { SwitchSummonPhase } from "./switch-summon-phase";
|
||||
import { TurnEndPhase } from "./turn-end-phase";
|
||||
import { WeatherEffectPhase } from "./weather-effect-phase";
|
||||
import { CheckStatusEffectPhase } from "#app/phases/check-status-effect-phase";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { TrickRoomTag } from "#app/data/arena-tag";
|
||||
import { SwitchType } from "#enums/switch-type";
|
||||
@ -206,11 +206,8 @@ export class TurnStartPhase extends FieldPhase {
|
||||
|
||||
this.scene.pushPhase(new WeatherEffectPhase(this.scene));
|
||||
|
||||
for (const o of moveOrder) {
|
||||
if (field[o].status && field[o].status.isPostTurn()) {
|
||||
this.scene.pushPhase(new PostTurnStatusEffectPhase(this.scene, o));
|
||||
}
|
||||
}
|
||||
/** Add a new phase to check who should be taking status damage */
|
||||
this.scene.pushPhase(new CheckStatusEffectPhase(this.scene, moveOrder));
|
||||
|
||||
this.scene.pushPhase(new BerryPhase(this.scene));
|
||||
this.scene.pushPhase(new TurnEndPhase(this.scene));
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Arena } from "../field/arena";
|
||||
import { ArenaTag } from "../data/arena-tag";
|
||||
import { ArenaTag, loadArenaTag } from "../data/arena-tag";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { Weather } from "../data/weather";
|
||||
import { Terrain } from "#app/data/terrain";
|
||||
@ -15,6 +15,10 @@ export default class ArenaData {
|
||||
this.biome = sourceArena ? sourceArena.biomeType : source.biome;
|
||||
this.weather = sourceArena ? sourceArena.weather : source.weather ? new Weather(source.weather.weatherType, source.weather.turnsLeft) : null;
|
||||
this.terrain = sourceArena ? sourceArena.terrain : source.terrain ? new Terrain(source.terrain.terrainType, source.terrain.turnsLeft) : null;
|
||||
this.tags = sourceArena ? sourceArena.tags : [];
|
||||
this.tags = [];
|
||||
|
||||
if (source.tags) {
|
||||
this.tags = source.tags.map(t => loadArenaTag(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import { TrainerVariant } from "#app/field/trainer";
|
||||
import { Variant } from "#app/data/variant";
|
||||
import { setSettingGamepad, SettingGamepad, settingGamepadDefaults } from "#app/system/settings/settings-gamepad";
|
||||
import { setSettingKeyboard, SettingKeyboard } from "#app/system/settings/settings-keyboard";
|
||||
import { TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena";
|
||||
import { TagAddedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena";
|
||||
import * as Modifier from "#app/modifier/modifier";
|
||||
import { StatusEffect } from "#app/data/status-effect";
|
||||
import ChallengeData from "#app/system/challenge-data";
|
||||
@ -50,6 +50,7 @@ import { applySessionDataPatches, applySettingsDataPatches, applySystemDataPatch
|
||||
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { PokerogueApiClearSessionData } from "#app/@types/pokerogue-api";
|
||||
import { ArenaTrapTag } from "#app/data/arena-tag";
|
||||
|
||||
export const defaultStarterSpecies: Species[] = [
|
||||
Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE,
|
||||
@ -1085,8 +1086,18 @@ export class GameData {
|
||||
|
||||
scene.arena.terrain = sessionData.arena.terrain;
|
||||
scene.arena.eventTarget.dispatchEvent(new TerrainChangedEvent(TerrainType.NONE, scene.arena.terrain?.terrainType!, scene.arena.terrain?.turnsLeft!)); // TODO: is this bang correct?
|
||||
// TODO
|
||||
//scene.arena.tags = sessionData.arena.tags;
|
||||
|
||||
scene.arena.tags = sessionData.arena.tags;
|
||||
if (scene.arena.tags) {
|
||||
for (const tag of scene.arena.tags) {
|
||||
if (tag instanceof ArenaTrapTag) {
|
||||
const { tagType, side, turnCount, layers, maxLayers } = tag as ArenaTrapTag;
|
||||
scene.arena.eventTarget.dispatchEvent(new TagAddedEvent(tagType, side, turnCount, layers, maxLayers));
|
||||
} else {
|
||||
scene.arena.eventTarget.dispatchEvent(new TagAddedEvent(tag.tagType, tag.side, tag.turnCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const modifierData of sessionData.modifiers) {
|
||||
const modifier = modifierData.toModifier(scene, Modifier[modifierData.className]);
|
||||
|
72
src/test/abilities/competitive.test.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { Stat } from "#enums/stat";
|
||||
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
describe("Abilities - Competitive", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
|
||||
game.override.battleType("single")
|
||||
.enemySpecies(Species.BEEDRILL)
|
||||
.enemyMoveset(Moves.TICKLE)
|
||||
.startingLevel(1)
|
||||
.moveset([ Moves.SPLASH, Moves.CLOSE_COMBAT ])
|
||||
.ability(Abilities.COMPETITIVE);
|
||||
});
|
||||
|
||||
it("lower atk and def by 1 via tickle, then increase spatk by 4 via competitive", async () => {
|
||||
await game.classicMode.startBattle([ Species.FLYGON ]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(-1);
|
||||
expect(playerPokemon.getStatStage(Stat.DEF)).toBe(-1);
|
||||
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(4);
|
||||
});
|
||||
|
||||
it("lowering your own stats should not trigger competitive", async () => {
|
||||
game.override.enemyMoveset(Moves.SPLASH);
|
||||
await game.classicMode.startBattle([ Species.FLYGON ]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
game.move.select(Moves.CLOSE_COMBAT);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.SPDEF)).toBe(-1);
|
||||
expect(playerPokemon.getStatStage(Stat.DEF)).toBe(-1);
|
||||
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(0);
|
||||
});
|
||||
|
||||
it("white herb should remove only the negative effects", async () => {
|
||||
game.override.startingHeldItems([{ name: "WHITE_HERB" }]);
|
||||
await game.classicMode.startBattle([ Species.FLYGON ]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||
expect(playerPokemon.getStatStage(Stat.DEF)).toBe(0);
|
||||
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(4);
|
||||
});
|
||||
});
|
70
src/test/abilities/defiant.test.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { Stat } from "#enums/stat";
|
||||
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
describe("Abilities - Defiant", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
|
||||
game.override.battleType("single")
|
||||
.enemySpecies(Species.BEEDRILL)
|
||||
.enemyMoveset(Moves.TICKLE)
|
||||
.startingLevel(1)
|
||||
.moveset([ Moves.SPLASH, Moves.CLOSE_COMBAT ])
|
||||
.ability(Abilities.DEFIANT);
|
||||
});
|
||||
|
||||
it("lower atk and def by 1 via tickle, then increase atk by 4 via defiant", async () => {
|
||||
await game.classicMode.startBattle([ Species.FLYGON ]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(3);
|
||||
expect(playerPokemon.getStatStage(Stat.DEF)).toBe(-1);
|
||||
});
|
||||
|
||||
it("lowering your own stats should not trigger defiant", async () => {
|
||||
game.override.enemyMoveset(Moves.SPLASH);
|
||||
await game.classicMode.startBattle([ Species.FLYGON ]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
game.move.select(Moves.CLOSE_COMBAT);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.SPDEF)).toBe(-1);
|
||||
expect(playerPokemon.getStatStage(Stat.DEF)).toBe(-1);
|
||||
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||
});
|
||||
|
||||
it("white herb should remove only the negative effects", async () => {
|
||||
game.override.startingHeldItems([{ name: "WHITE_HERB" }]);
|
||||
await game.classicMode.startBattle([ Species.FLYGON ]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnInitPhase);
|
||||
|
||||
expect(playerPokemon.getStatStage(Stat.DEF)).toBe(0);
|
||||
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(3);
|
||||
});
|
||||
});
|
@ -1,7 +1,4 @@
|
||||
import { StatusEffect } from "#app/data/status-effect";
|
||||
import { EnemyCommandPhase } from "#app/phases/enemy-command-phase";
|
||||
import { MessagePhase } from "#app/phases/message-phase";
|
||||
import { TurnEndPhase } from "#app/phases/turn-end-phase";
|
||||
import i18next from "#app/plugins/i18n";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
@ -10,6 +7,7 @@ import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
describe("Items - Toxic orb", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
@ -27,40 +25,36 @@ describe("Items - Toxic orb", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
const moveToUse = Moves.GROWTH;
|
||||
const oppMoveToUse = Moves.TACKLE;
|
||||
game.override.battleType("single");
|
||||
game.override.enemySpecies(Species.RATTATA);
|
||||
game.override.ability(Abilities.INSOMNIA);
|
||||
game.override.enemyAbility(Abilities.INSOMNIA);
|
||||
game.override.startingLevel(2000);
|
||||
game.override.moveset([ moveToUse ]);
|
||||
game.override.enemyMoveset([ oppMoveToUse, oppMoveToUse, oppMoveToUse, oppMoveToUse ]);
|
||||
game.override.startingHeldItems([{
|
||||
name: "TOXIC_ORB",
|
||||
}]);
|
||||
game.override
|
||||
.battleType("single")
|
||||
.enemySpecies(Species.RATTATA)
|
||||
.ability(Abilities.BALL_FETCH)
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.moveset([ Moves.SPLASH ])
|
||||
.enemyMoveset(Moves.SPLASH)
|
||||
.startingHeldItems([{
|
||||
name: "TOXIC_ORB",
|
||||
}]);
|
||||
|
||||
vi.spyOn(i18next, "t");
|
||||
});
|
||||
|
||||
it("TOXIC ORB", async () => {
|
||||
const moveToUse = Moves.GROWTH;
|
||||
await game.startBattle([
|
||||
Species.MIGHTYENA,
|
||||
Species.MIGHTYENA,
|
||||
]);
|
||||
expect(game.scene.modifiers[0].type.id).toBe("TOXIC_ORB");
|
||||
it("badly poisons the holder", async () => {
|
||||
await game.classicMode.startBattle([ Species.MIGHTYENA ]);
|
||||
|
||||
game.move.select(moveToUse);
|
||||
const player = game.scene.getPlayerField()[0];
|
||||
|
||||
// will run the 13 phase from enemyCommandPhase to TurnEndPhase
|
||||
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnEndPhase);
|
||||
game.move.select(Moves.SPLASH);
|
||||
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
// Toxic orb should trigger here
|
||||
await game.phaseInterceptor.run(MessagePhase);
|
||||
await game.phaseInterceptor.run("MessagePhase");
|
||||
expect(i18next.t).toHaveBeenCalledWith("statusEffect:toxic.obtainSource", expect.anything());
|
||||
|
||||
await game.phaseInterceptor.run(MessagePhase);
|
||||
expect(i18next.t).toHaveBeenCalledWith("statusEffect:toxic.activation", expect.anything());
|
||||
expect(game.scene.getParty()[0].status!.effect).toBe(StatusEffect.TOXIC);
|
||||
}, 20000);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(player.status?.effect).toBe(StatusEffect.TOXIC);
|
||||
// Damage should not have ticked yet.
|
||||
expect(player.status?.turnCount).toBe(0);
|
||||
}, TIMEOUT);
|
||||
});
|
||||
|
@ -33,7 +33,7 @@ describe("Moves - Safeguard", () => {
|
||||
.enemyLevel(5)
|
||||
.starterSpecies(Species.DRATINI)
|
||||
.moveset([ Moves.NUZZLE, Moves.SPORE, Moves.YAWN, Moves.SPLASH ])
|
||||
.ability(Abilities.BALL_FETCH);
|
||||
.ability(Abilities.UNNERVE); // Stop wild Pokemon from potentially eating Lum Berry
|
||||
});
|
||||
|
||||
it("protects from damaging moves with additional effects", async () => {
|
||||
|
124
src/test/moves/telekinesis.test.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { allMoves } from "#app/data/move";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { MoveResult } from "#app/field/pokemon";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest";
|
||||
|
||||
describe("Moves - Telekinesis", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.moveset([ Moves.TELEKINESIS, Moves.TACKLE, Moves.MUD_SHOT, Moves.SMACK_DOWN ])
|
||||
.battleType("single")
|
||||
.enemySpecies(Species.SNORLAX)
|
||||
.enemyLevel(60)
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.enemyMoveset([ Moves.SPLASH ]);
|
||||
});
|
||||
|
||||
it("Telekinesis makes the affected vulnerable to most attacking moves regardless of accuracy", async () => {
|
||||
await game.classicMode.startBattle([ Species.MAGIKARP ]);
|
||||
|
||||
const enemyOpponent = game.scene.getEnemyPokemon()!;
|
||||
|
||||
game.move.select(Moves.TELEKINESIS);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined();
|
||||
expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeDefined();
|
||||
|
||||
await game.toNextTurn();
|
||||
vi.spyOn(allMoves[Moves.TACKLE], "accuracy", "get").mockReturnValue(0);
|
||||
game.move.select(Moves.TACKLE);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
expect(enemyOpponent.isFullHp()).toBe(false);
|
||||
});
|
||||
|
||||
it("Telekinesis makes the affected airborne and immune to most Ground-moves", async () => {
|
||||
await game.classicMode.startBattle([ Species.MAGIKARP ]);
|
||||
|
||||
const enemyOpponent = game.scene.getEnemyPokemon()!;
|
||||
|
||||
game.move.select(Moves.TELEKINESIS);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined();
|
||||
expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeDefined();
|
||||
|
||||
await game.toNextTurn();
|
||||
vi.spyOn(allMoves[Moves.MUD_SHOT], "accuracy", "get").mockReturnValue(100);
|
||||
game.move.select(Moves.MUD_SHOT);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
expect(enemyOpponent.isFullHp()).toBe(true);
|
||||
});
|
||||
|
||||
it("Telekinesis can still affect Pokemon that have been transformed into invalid Pokemon", async () => {
|
||||
game.override.enemyMoveset(Moves.TRANSFORM);
|
||||
await game.classicMode.startBattle([ Species.DIGLETT ]);
|
||||
|
||||
const enemyOpponent = game.scene.getEnemyPokemon()!;
|
||||
|
||||
game.move.select(Moves.TELEKINESIS);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined();
|
||||
expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeDefined();
|
||||
expect(enemyOpponent.summonData.speciesForm?.speciesId).toBe(Species.DIGLETT);
|
||||
});
|
||||
|
||||
it("Moves like Smack Down and 1000 Arrows remove all effects of Telekinesis from the target Pokemon", async () => {
|
||||
await game.classicMode.startBattle([ Species.MAGIKARP ]);
|
||||
|
||||
const enemyOpponent = game.scene.getEnemyPokemon()!;
|
||||
|
||||
game.move.select(Moves.TELEKINESIS);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined();
|
||||
expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeDefined();
|
||||
|
||||
await game.toNextTurn();
|
||||
game.move.select(Moves.SMACK_DOWN);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeUndefined();
|
||||
expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("Ingrain will remove the floating effect of Telekinesis, but not the 100% hit", async () => {
|
||||
game.override.enemyMoveset([ Moves.SPLASH, Moves.INGRAIN ]);
|
||||
await game.classicMode.startBattle([ Species.MAGIKARP ]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyOpponent = game.scene.getEnemyPokemon()!;
|
||||
|
||||
game.move.select(Moves.TELEKINESIS);
|
||||
await game.forceEnemyMove(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined();
|
||||
expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeDefined();
|
||||
|
||||
await game.toNextTurn();
|
||||
vi.spyOn(allMoves[Moves.MUD_SHOT], "accuracy", "get").mockReturnValue(0);
|
||||
game.move.select(Moves.MUD_SHOT);
|
||||
await game.forceEnemyMove(Moves.INGRAIN);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined();
|
||||
expect(enemyOpponent.getTag(BattlerTagType.INGRAIN)).toBeDefined();
|
||||
expect(enemyOpponent.getTag(BattlerTagType.IGNORE_FLYING)).toBeDefined();
|
||||
expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeUndefined();
|
||||
expect(playerPokemon.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS);
|
||||
});
|
||||
});
|
@ -85,13 +85,13 @@ describe("Moves - Thousand Arrows", () => {
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
|
||||
enemyPokemon.addTag(BattlerTagType.MAGNET_RISEN, undefined, Moves.MAGNET_RISE);
|
||||
enemyPokemon.addTag(BattlerTagType.FLOATING, undefined, Moves.MAGNET_RISE);
|
||||
|
||||
game.move.select(Moves.THOUSAND_ARROWS);
|
||||
|
||||
await game.phaseInterceptor.to(BerryPhase, false);
|
||||
|
||||
expect(enemyPokemon.getTag(BattlerTagType.MAGNET_RISEN)).toBeUndefined();
|
||||
expect(enemyPokemon.getTag(BattlerTagType.FLOATING)).toBeUndefined();
|
||||
expect(enemyPokemon.getTag(BattlerTagType.IGNORE_FLYING)).toBeDefined();
|
||||
expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp());
|
||||
}
|
||||
|
136
src/test/moves/toxic_spikes.test.ts
Normal file
@ -0,0 +1,136 @@
|
||||
import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag";
|
||||
import { StatusEffect } from "#app/data/status-effect";
|
||||
import { decrypt, encrypt, GameData, SessionSaveData } from "#app/system/game-data";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
describe("Moves - Toxic Spikes", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.battleType("single")
|
||||
.startingWave(5)
|
||||
.enemySpecies(Species.RATTATA)
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.ability(Abilities.BALL_FETCH)
|
||||
.enemyMoveset(Moves.SPLASH)
|
||||
.moveset([ Moves.TOXIC_SPIKES, Moves.SPLASH, Moves.ROAR ]);
|
||||
});
|
||||
|
||||
it("should not affect the opponent if they do not switch", async() => {
|
||||
await game.classicMode.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA ]);
|
||||
|
||||
const enemy = game.scene.getEnemyField()[0];
|
||||
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
game.doSwitchPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(enemy.hp).toBe(enemy.getMaxHp());
|
||||
expect(enemy.status?.effect).toBeUndefined();
|
||||
}, TIMEOUT);
|
||||
|
||||
it("should poison the opponent if they switch into 1 layer", async() => {
|
||||
await game.classicMode.runToSummon([ Species.MIGHTYENA ]);
|
||||
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
game.move.select(Moves.ROAR);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
const enemy = game.scene.getEnemyField()[0];
|
||||
|
||||
expect(enemy.hp).toBeLessThan(enemy.getMaxHp());
|
||||
expect(enemy.status?.effect).toBe(StatusEffect.POISON);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("should badly poison the opponent if they switch into 2 layers", async() => {
|
||||
await game.classicMode.runToSummon([ Species.MIGHTYENA ]);
|
||||
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
game.move.select(Moves.ROAR);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
const enemy = game.scene.getEnemyField()[0];
|
||||
expect(enemy.hp).toBeLessThan(enemy.getMaxHp());
|
||||
expect(enemy.status?.effect).toBe(StatusEffect.TOXIC);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("should be removed if a grounded poison pokemon switches in", async() => {
|
||||
game.override.enemySpecies(Species.GRIMER);
|
||||
await game.classicMode.runToSummon([ Species.MIGHTYENA ]);
|
||||
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
game.move.select(Moves.ROAR);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
const enemy = game.scene.getEnemyField()[0];
|
||||
expect(enemy.hp).toBe(enemy.getMaxHp());
|
||||
expect(enemy.status?.effect).toBeUndefined();
|
||||
|
||||
expect(game.scene.arena.tags.length).toBe(0);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("shouldn't create multiple layers per use in doubles", async() => {
|
||||
await game.classicMode.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA ]);
|
||||
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
const arenaTags = (game.scene.arena.getTagOnSide(ArenaTagType.TOXIC_SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag);
|
||||
expect(arenaTags.tagType).toBe(ArenaTagType.TOXIC_SPIKES);
|
||||
expect(arenaTags.layers).toBe(1);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("should persist through reload", async() => {
|
||||
game.override.startingWave(1);
|
||||
const scene = game.scene;
|
||||
const gameData = new GameData(scene);
|
||||
|
||||
await game.classicMode.runToSummon([ Species.MIGHTYENA ]);
|
||||
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.doKillOpponents();
|
||||
await game.phaseInterceptor.to("BattleEndPhase");
|
||||
await game.toNextWave();
|
||||
|
||||
const sessionData : SessionSaveData = gameData["getSessionSaveData"](game.scene);
|
||||
localStorage.setItem("sessionTestData", encrypt(JSON.stringify(sessionData), true));
|
||||
const recoveredData : SessionSaveData = gameData.parseSessionData(decrypt(localStorage.getItem("sessionTestData")!, true));
|
||||
gameData.loadSession(game.scene, 0, recoveredData);
|
||||
|
||||
expect(sessionData.arena.tags).toEqual(recoveredData.arena.tags);
|
||||
localStorage.removeItem("sessionTestData");
|
||||
}, TIMEOUT);
|
||||
});
|
@ -18,6 +18,7 @@ import { Moves } from "#enums/moves";
|
||||
import { ShinyRateBoosterModifier } from "#app/modifier/modifier";
|
||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||
import i18next from "i18next";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
|
||||
const namespace = "mysteryEncounters/anOfferYouCantRefuse";
|
||||
/** Gyarados for Indimidate */
|
||||
@ -37,10 +38,11 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => {
|
||||
beforeEach(async () => {
|
||||
game = new GameManager(phaserGame);
|
||||
scene = game.scene;
|
||||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.disableTrainerWaves();
|
||||
game.override.mysteryEncounterChance(100)
|
||||
.startingWave(defaultWave)
|
||||
.startingBiome(defaultBiome)
|
||||
.disableTrainerWaves()
|
||||
.ability(Abilities.INTIMIDATE); // Extortion ability
|
||||
|
||||
const biomeMap = new Map<Biome, MysteryEncounterType[]>([
|
||||
[ Biome.VOLCANO, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]],
|
||||
@ -195,6 +197,7 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => {
|
||||
});
|
||||
|
||||
it("should award EXP to a pokemon with a move in EXTORTION_MOVES", async () => {
|
||||
game.override.ability(Abilities.SYNCHRONIZE); // Not an extortion ability, so we can test extortion move
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, [ Species.ABRA ]);
|
||||
const party = scene.getParty();
|
||||
const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA)!;
|
||||
|
@ -176,10 +176,12 @@ describe("Berries Abound - Mystery Encounter", () => {
|
||||
const encounterTextSpy = vi.spyOn(EncounterDialogueUtils, "showEncounterText");
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty);
|
||||
|
||||
scene.getParty().forEach(pkm => {
|
||||
vi.spyOn(pkm, "getStat").mockReturnValue(1); // for ease return for every stat
|
||||
});
|
||||
|
||||
const config = game.scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0];
|
||||
const speciesToSpawn = config.pokemonConfigs?.[0].species.speciesId;
|
||||
// Setting enemy's level arbitrarily high to outspeed
|
||||
config.pokemonConfigs![0].dataSource!.level = 1000;
|
||||
|
||||
await runMysteryEncounterToEnd(game, 2, undefined, true);
|
||||
|
||||
@ -198,10 +200,12 @@ describe("Berries Abound - Mystery Encounter", () => {
|
||||
const encounterTextSpy = vi.spyOn(EncounterDialogueUtils, "showEncounterText");
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty);
|
||||
|
||||
scene.getParty().forEach(pkm => {
|
||||
vi.spyOn(pkm, "getStat").mockReturnValue(1); // for ease return for every stat
|
||||
});
|
||||
|
||||
const config = game.scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0];
|
||||
const speciesToSpawn = config.pokemonConfigs?.[0].species.speciesId;
|
||||
// Setting enemy's level arbitrarily high to outspeed
|
||||
config.pokemonConfigs![0].dataSource!.level = 1000;
|
||||
|
||||
await runMysteryEncounterToEnd(game, 2, undefined, true);
|
||||
|
||||
|
@ -147,8 +147,8 @@ describe("The Pokemon Salesman - Mystery Encounter", () => {
|
||||
|
||||
expect(scene.getParty().length).toBe(initialPartySize + 1);
|
||||
|
||||
const newlyPurchasedPokemon = scene.getParty().find(p => p.name === pokemonName);
|
||||
expect(newlyPurchasedPokemon).toBeDefined();
|
||||
const newlyPurchasedPokemon = scene.getParty()[scene.getParty().length - 1];
|
||||
expect(newlyPurchasedPokemon.name).toBe(pokemonName);
|
||||
expect(newlyPurchasedPokemon!.moveset.length > 0).toBeTruthy();
|
||||
});
|
||||
|
||||
|
@ -40,7 +40,9 @@ export default class AchvsUiHandler extends MessageUiHandler {
|
||||
private iconsBg: Phaser.GameObjects.NineSlice;
|
||||
private icons: Phaser.GameObjects.Sprite[];
|
||||
|
||||
private titleBg: Phaser.GameObjects.NineSlice;
|
||||
private titleText: Phaser.GameObjects.Text;
|
||||
private scoreContainer: Phaser.GameObjects.Container;
|
||||
private scoreText: Phaser.GameObjects.Text;
|
||||
private unlockText: Phaser.GameObjects.Text;
|
||||
|
||||
@ -114,29 +116,31 @@ export default class AchvsUiHandler extends MessageUiHandler {
|
||||
|
||||
const titleBg = addWindow(this.scene, 0, this.headerBg.height + this.iconsBg.height, 174, 24);
|
||||
titleBg.setOrigin(0, 0);
|
||||
this.titleBg = titleBg;
|
||||
|
||||
this.titleText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW);
|
||||
const textSize = languageSettings[i18next.language]?.TextSize ?? this.titleText.style.fontSize;
|
||||
this.titleText.setFontSize(textSize);
|
||||
this.titleText.setOrigin(0, 0);
|
||||
const titleBgCenterX = titleBg.x + titleBg.width / 2;
|
||||
const titleBgCenterY = titleBg.y + titleBg.height / 2;
|
||||
this.titleText.setOrigin(0.5, 0.5);
|
||||
this.titleText.setPosition(titleBgCenterX, titleBgCenterY);
|
||||
|
||||
const scoreBg = addWindow(this.scene, titleBg.x + titleBg.width, titleBg.y, 46, 24);
|
||||
this.scoreContainer = this.scene.add.container(titleBg.x + titleBg.width, titleBg.y);
|
||||
const scoreBg = addWindow(this.scene, 0, 0, 46, 24);
|
||||
scoreBg.setOrigin(0, 0);
|
||||
this.scoreContainer.add(scoreBg);
|
||||
|
||||
this.scoreText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW);
|
||||
this.scoreText.setOrigin(0, 0);
|
||||
this.scoreText.setPositionRelative(scoreBg, 8, 4);
|
||||
this.scoreText = addTextObject(this.scene, scoreBg.width / 2, scoreBg.height / 2, "", TextStyle.WINDOW);
|
||||
this.scoreText.setOrigin(0.5, 0.5);
|
||||
this.scoreContainer.add(this.scoreText);
|
||||
|
||||
const unlockBg = addWindow(this.scene, scoreBg.x + scoreBg.width, scoreBg.y, 98, 24);
|
||||
const unlockBg = addWindow(this.scene, this.scoreContainer.x + scoreBg.width, titleBg.y, 98, 24);
|
||||
unlockBg.setOrigin(0, 0);
|
||||
|
||||
this.unlockText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW);
|
||||
this.unlockText.setOrigin(0, 0);
|
||||
this.unlockText.setPositionRelative(unlockBg, 8, 4);
|
||||
this.unlockText.setOrigin(0.5, 0.5);
|
||||
this.unlockText.setPositionRelative(unlockBg, unlockBg.width / 2, unlockBg.height / 2);
|
||||
|
||||
const descriptionBg = addWindow(this.scene, 0, titleBg.y + titleBg.height, (this.scene.game.canvas.width / 6) - 2, 42);
|
||||
descriptionBg.setOrigin(0, 0);
|
||||
@ -157,8 +161,7 @@ export default class AchvsUiHandler extends MessageUiHandler {
|
||||
this.mainContainer.add(this.iconsContainer);
|
||||
this.mainContainer.add(titleBg);
|
||||
this.mainContainer.add(this.titleText);
|
||||
this.mainContainer.add(scoreBg);
|
||||
this.mainContainer.add(this.scoreText);
|
||||
this.mainContainer.add(this.scoreContainer);
|
||||
this.mainContainer.add(unlockBg);
|
||||
this.mainContainer.add(this.unlockText);
|
||||
this.mainContainer.add(descriptionBg);
|
||||
@ -167,8 +170,6 @@ export default class AchvsUiHandler extends MessageUiHandler {
|
||||
ui.add(this.mainContainer);
|
||||
|
||||
this.currentPage = Page.ACHIEVEMENTS;
|
||||
this.setCursor(0);
|
||||
this.setScrollCursor(0);
|
||||
|
||||
this.mainContainer.setVisible(false);
|
||||
}
|
||||
@ -316,9 +317,19 @@ export default class AchvsUiHandler extends MessageUiHandler {
|
||||
if (update || pageChange) {
|
||||
switch (this.currentPage) {
|
||||
case Page.ACHIEVEMENTS:
|
||||
if (pageChange) {
|
||||
this.titleBg.width = 174;
|
||||
this.titleText.x = this.titleBg.width / 2;
|
||||
this.scoreContainer.setVisible(true);
|
||||
}
|
||||
this.showAchv(achvs[Object.keys(achvs)[cursor + this.scrollCursor * this.COLS]]);
|
||||
break;
|
||||
case Page.VOUCHERS:
|
||||
if (pageChange) {
|
||||
this.titleBg.width = 220;
|
||||
this.titleText.x = this.titleBg.width / 2;
|
||||
this.scoreContainer.setVisible(false);
|
||||
}
|
||||
this.showVoucher(vouchers[Object.keys(vouchers)[cursor + this.scrollCursor * this.COLS]]);
|
||||
break;
|
||||
}
|
||||
@ -442,6 +453,7 @@ export default class AchvsUiHandler extends MessageUiHandler {
|
||||
this.currentPage = Page.ACHIEVEMENTS;
|
||||
this.mainContainer.setVisible(false);
|
||||
this.setScrollCursor(0);
|
||||
this.setCursor(0, true);
|
||||
this.eraseCursor();
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,8 @@ import { Mode } from "./ui";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import { RunDisplayMode } from "#app/ui/run-info-ui-handler";
|
||||
|
||||
const sessionSlotCount = 5;
|
||||
const SESSION_SLOTS_COUNT = 5;
|
||||
const SLOTS_ON_SCREEN = 3;
|
||||
|
||||
export enum SaveSlotUiMode {
|
||||
LOAD,
|
||||
@ -84,12 +85,10 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
|
||||
this.saveSlotSelectCallback = args[1] as SaveSlotSelectCallback;
|
||||
|
||||
this.saveSlotSelectContainer.setVisible(true);
|
||||
this.populateSessionSlots()
|
||||
.then(() => {
|
||||
this.setScrollCursor(0);
|
||||
this.setCursor(0);
|
||||
});
|
||||
this.populateSessionSlots();
|
||||
|
||||
this.setScrollCursor(0);
|
||||
this.setCursor(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -161,9 +160,9 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
|
||||
}
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (this.cursor < 2) {
|
||||
success = this.setCursor(this.cursor + 1, this.cursor);
|
||||
} else if (this.scrollCursor < sessionSlotCount - 3) {
|
||||
if (this.cursor < (SLOTS_ON_SCREEN - 1)) {
|
||||
success = this.setCursor(this.cursor + 1, cursorPosition);
|
||||
} else if (this.scrollCursor < SESSION_SLOTS_COUNT - SLOTS_ON_SCREEN) {
|
||||
success = this.setScrollCursor(this.scrollCursor + 1, cursorPosition);
|
||||
}
|
||||
break;
|
||||
@ -184,13 +183,19 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
|
||||
return success || error;
|
||||
}
|
||||
|
||||
async populateSessionSlots() {
|
||||
for (let s = 0; s < sessionSlotCount; s++) {
|
||||
populateSessionSlots() {
|
||||
for (let s = 0; s < SESSION_SLOTS_COUNT; s++) {
|
||||
const sessionSlot = new SessionSlot(this.scene, s);
|
||||
await sessionSlot.load();
|
||||
this.scene.add.existing(sessionSlot);
|
||||
this.sessionSlotsContainer.add(sessionSlot);
|
||||
this.sessionSlots.push(sessionSlot);
|
||||
sessionSlot.load().then((success) => {
|
||||
// If the cursor was moved to this slot while the session was loading
|
||||
// call setCursor again to shift the slot position and show the arrow for save preview
|
||||
if (success && (this.cursor + this.scrollCursor) === s) {
|
||||
this.setCursor(s);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,12 +214,12 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* setCursor takes user navigation as an input and positions the cursor accordingly
|
||||
* @param cursor the index provided to the cursor
|
||||
* @param prevCursor the previous index occupied by the cursor - optional
|
||||
* Move the cursor to a new position and update the view accordingly
|
||||
* @param cursor the new cursor position, between `0` and `SLOTS_ON_SCREEN - 1`
|
||||
* @param prevSlotIndex index of the previous session occupied by the cursor, between `0` and `SESSION_SLOTS_COUNT - 1` - optional
|
||||
* @returns `true` if the cursor position has changed | `false` if it has not
|
||||
*/
|
||||
override setCursor(cursor: integer, prevCursor?: integer): boolean {
|
||||
override setCursor(cursor: integer, prevSlotIndex?: integer): boolean {
|
||||
const changed = super.setCursor(cursor);
|
||||
|
||||
if (!this.cursorObj) {
|
||||
@ -241,21 +246,20 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
|
||||
}
|
||||
this.setArrowVisibility(hasData);
|
||||
}
|
||||
if (!Utils.isNullOrUndefined(prevCursor)) {
|
||||
this.revertSessionSlot(prevCursor);
|
||||
if (!Utils.isNullOrUndefined(prevSlotIndex)) {
|
||||
this.revertSessionSlot(prevSlotIndex);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that resets the session slot position to its default central position
|
||||
* @param prevCursor the previous location of the cursor
|
||||
* Helper function that resets the given session slot to its default central position
|
||||
*/
|
||||
revertSessionSlot(prevCursor: integer): void {
|
||||
const sessionSlot = this.sessionSlots[prevCursor];
|
||||
revertSessionSlot(slotIndex: integer): void {
|
||||
const sessionSlot = this.sessionSlots[slotIndex];
|
||||
if (sessionSlot) {
|
||||
sessionSlot.setPosition(0, prevCursor * 56);
|
||||
sessionSlot.setPosition(0, slotIndex * 56);
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,12 +274,18 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
setScrollCursor(scrollCursor: integer, priorCursor?: integer): boolean {
|
||||
/**
|
||||
* Move the scrolling cursor to a new position and update the view accordingly
|
||||
* @param scrollCursor the new cursor position, between `0` and `SESSION_SLOTS_COUNT - SLOTS_ON_SCREEN`
|
||||
* @param prevSlotIndex index of the previous slot occupied by the cursor, between `0` and `SESSION_SLOTS_COUNT-1` - optional
|
||||
* @returns `true` if the cursor position has changed | `false` if it has not
|
||||
*/
|
||||
setScrollCursor(scrollCursor: integer, prevSlotIndex?: integer): boolean {
|
||||
const changed = scrollCursor !== this.scrollCursor;
|
||||
|
||||
if (changed) {
|
||||
this.scrollCursor = scrollCursor;
|
||||
this.setCursor(this.cursor, priorCursor);
|
||||
this.setCursor(this.cursor, prevSlotIndex);
|
||||
this.scene.tweens.add({
|
||||
targets: this.sessionSlotsContainer,
|
||||
y: this.sessionSlotsContainerInitialY - 56 * scrollCursor,
|
||||
@ -290,6 +300,7 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
|
||||
clear() {
|
||||
super.clear();
|
||||
this.saveSlotSelectContainer.setVisible(false);
|
||||
this.setScrollCursor(0);
|
||||
this.eraseCursor();
|
||||
this.saveSlotSelectCallback = null;
|
||||
this.clearSessionSlots();
|
||||
@ -391,6 +402,10 @@ class SessionSlot extends Phaser.GameObjects.Container {
|
||||
load(): Promise<boolean> {
|
||||
return new Promise<boolean>(resolve => {
|
||||
this.scene.gameData.getSession(this.slotId).then(async sessionData => {
|
||||
// Ignore the results if the view was exited
|
||||
if (!this.active) {
|
||||
return;
|
||||
}
|
||||
if (!sessionData) {
|
||||
this.hasData = false;
|
||||
this.loadingLabel.setText(i18next.t("saveSlotSelectUiHandler:empty"));
|
||||
|
@ -2963,8 +2963,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
this.natureCursor = -1;
|
||||
|
||||
if (this.activeTooltip === "CANDY") {
|
||||
const { currentFriendship, friendshipCap } = this.getFriendship(this.lastSpecies.speciesId);
|
||||
this.scene.ui.editTooltip("", `${currentFriendship}/${friendshipCap}`);
|
||||
if (this.lastSpecies) {
|
||||
const { currentFriendship, friendshipCap } = this.getFriendship(this.lastSpecies.speciesId);
|
||||
this.scene.ui.editTooltip("", `${currentFriendship}/${friendshipCap}`);
|
||||
} else {
|
||||
this.scene.ui.hideTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
if (species?.forms?.find(f => f.formKey === "female")) {
|
||||
@ -3655,6 +3659,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
StarterPrefs.save(this.starterPreferences);
|
||||
this.cursor = -1;
|
||||
this.hideInstructions();
|
||||
this.activeTooltip = undefined;
|
||||
this.scene.ui.hideTooltip();
|
||||
|
||||
this.starterSelectContainer.setVisible(false);
|
||||
this.blockInput = false;
|
||||
|
||||
|