Compare commits
7 Commits
7ce209dd02
...
5de0185c0a
Author | SHA1 | Date | |
---|---|---|---|
|
5de0185c0a | ||
|
91abddb693 | ||
|
54aabceb29 | ||
|
5cb8bb7fda | ||
|
033c966f1b | ||
|
d03c75c2f9 | ||
|
f6ad30b58f |
1
.gitignore
vendored
@ -34,6 +34,7 @@ src/data/battle-anim-data.ts
|
||||
src/overrides.ts
|
||||
|
||||
coverage
|
||||
/.vs
|
||||
|
||||
# Local Documentation
|
||||
/typedoc
|
||||
|
BIN
public/audio/bgm/battle_plasma_grunt.mp3
Normal file
BIN
public/audio/bgm/encounter_plasma_grunt.mp3
Normal file
41
public/images/trainer/aqua_grunt_f.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "aqua_grunt_f.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 71,
|
||||
"h": 71
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 22,
|
||||
"y": 8,
|
||||
"w": 36,
|
||||
"h": 71
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 36,
|
||||
"h": 71
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:6db25cb5753163d19bca8e2db45849ae:7d8f51509862bfdf8a78bf42dd0005cd:af0aa9494be37941522487032b556989$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/aqua_grunt_f.png
Normal file
After Width: | Height: | Size: 767 B |
41
public/images/trainer/aqua_grunt_m.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "aqua_grunt_m.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 73,
|
||||
"h": 73
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 17,
|
||||
"y": 6,
|
||||
"w": 46,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 46,
|
||||
"h": 73
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:efd07ff3ed1e610150a4b8ca18974343:d9b85b9eb11182e9e4669e2bd8b08694:72b7b50231708a9486d5f315824e4df1$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/aqua_grunt_m.png
Normal file
After Width: | Height: | Size: 787 B |
41
public/images/trainer/archie.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "archie.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 21,
|
||||
"y": 0,
|
||||
"w": 42,
|
||||
"h": 80
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 42,
|
||||
"h": 80
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:bfa7fdd7b6ac9be68dc9dc562fb8339f:06f87a279450b21b19294ba956b69c26:4b7980be4e3ac1d20c9eaf970913ec63$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/archie.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
41
public/images/trainer/cyrus.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "cyrus.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 15,
|
||||
"y": 0,
|
||||
"w": 48,
|
||||
"h": 80
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 48,
|
||||
"h": 80
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:5fc65535a23867fca7511cc9d7fc15b3:f328e97821f4faffcbca155cc2c5dc2c:55da82f1e1919212896c9c96b682cbd1$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/cyrus.png
Normal file
After Width: | Height: | Size: 857 B |
41
public/images/trainer/flare_grunt_f.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "flare_grunt_f.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 31,
|
||||
"y": 0,
|
||||
"w": 23,
|
||||
"h": 80
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 23,
|
||||
"h": 80
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:c30bf82452209a923f4becf13d275a9a:a6355b09f92c9c0388d0b919010f587f:0638dbf213f8a974eb5af76eb1e5ddeb$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/flare_grunt_f.png
Normal file
After Width: | Height: | Size: 613 B |
41
public/images/trainer/flare_grunt_m.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "flare_grunt_m.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 77,
|
||||
"h": 77
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 24,
|
||||
"y": 2,
|
||||
"w": 31,
|
||||
"h": 77
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 31,
|
||||
"h": 77
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:a26606e70778f88a1a7053b2f2420dde:84abf0d0f6bc90c6a60f660567b2d641:adc35a4070bac9fe828c2605a3b15744$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/flare_grunt_m.png
Normal file
After Width: | Height: | Size: 662 B |
41
public/images/trainer/galactic_grunt_f.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "galactic_grunt_f.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 68,
|
||||
"h": 68
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 10,
|
||||
"y": 11,
|
||||
"w": 57,
|
||||
"h": 68
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 57,
|
||||
"h": 68
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:3012867f03f02c4ee67a8ab3ad5a000e:77a5f60f1adc158664b3b2ee17bf30fe:7e8259b5177c0a76e5d02d6bdc66affe$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/galactic_grunt_f.png
Normal file
After Width: | Height: | Size: 805 B |
41
public/images/trainer/galactic_grunt_m.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "galactic_grunt_m.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 73,
|
||||
"h": 73
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 20,
|
||||
"y": 6,
|
||||
"w": 37,
|
||||
"h": 73
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 37,
|
||||
"h": 73
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:856b85bb5d7a1ea2e7a76708ebf82d21:1687dff972369c6248e4aa5b0795fe62:259dd316440c335df5dc6008166d69ca$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/galactic_grunt_m.png
Normal file
After Width: | Height: | Size: 762 B |
41
public/images/trainer/lysandre.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "lysandre.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 14,
|
||||
"y": 0,
|
||||
"w": 52,
|
||||
"h": 80
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 52,
|
||||
"h": 80
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:6b887c8bab74885a1b05f2b382759db6:ba102d9d25ddd794a3a17f029b971daf:e6066149f6ec4ccb9fc28faea3d64a7f$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/lysandre.png
Normal file
After Width: | Height: | Size: 797 B |
41
public/images/trainer/magma_grunt_f.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "magma_grunt_f.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 10,
|
||||
"y": 0,
|
||||
"w": 60,
|
||||
"h": 80
|
||||
},
|
||||
"frame": {
|
||||
"x": 10,
|
||||
"y": 0,
|
||||
"w": 60,
|
||||
"h": 80
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:f63ad48affc076f60fae78992c96a2bf:80928b32710abcb28c07c6fc5a425d99:3b961d8852b62aaf24ceb2030c036515$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/magma_grunt_f.png
Normal file
After Width: | Height: | Size: 727 B |
41
public/images/trainer/magma_grunt_m.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "magma_grunt_m.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 10,
|
||||
"y": 0,
|
||||
"w": 60,
|
||||
"h": 80
|
||||
},
|
||||
"frame": {
|
||||
"x": 10,
|
||||
"y": 0,
|
||||
"w": 60,
|
||||
"h": 80
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:96aa833d987a01bcdcb6f0e7809f5daf:791cce8d026f92b2e52f0b66df8b8e11:35532fd5d9aea30957d50d06f2d2f9a6$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/magma_grunt_m.png
Normal file
After Width: | Height: | Size: 756 B |
41
public/images/trainer/maxie.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "maxie.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 79,
|
||||
"h": 79
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 20,
|
||||
"y": 0,
|
||||
"w": 35,
|
||||
"h": 79
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 35,
|
||||
"h": 79
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:a943a18803f18065ae5f19e5089c83bb:33a1c168d314f5fb32f9b34244201178:54a227d24523907b8adf8e907821dcd9$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/maxie.png
Normal file
After Width: | Height: | Size: 794 B |
41
public/images/trainer/plasma_grunt_f.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "plasma_grunt_f.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 75,
|
||||
"h": 75
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 21,
|
||||
"y": 4,
|
||||
"w": 37,
|
||||
"h": 75
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 37,
|
||||
"h": 75
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:c3001e18f1878c01a4825697200e823e:2003e0d4db249f7020c3471872198ac8:b01645b9e941158814978f2126e7e995$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/plasma_grunt_f.png
Normal file
After Width: | Height: | Size: 764 B |
41
public/images/trainer/plasma_grunt_m.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "plasma_grunt_m.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 72,
|
||||
"h": 72
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 16,
|
||||
"y": 7,
|
||||
"w": 47,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 47,
|
||||
"h": 72
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:61f195ebbcde93ab7442408edad7fe7a:28ae203b3cb42a94c4ba4420fdebdccc:9ae0ee174d431d48052a2f6b74e9d40c$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/plasma_grunt_m.png
Normal file
After Width: | Height: | Size: 914 B |
41
public/images/trainer/rocket_grunt_f.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "rocket_grunt_f.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 67,
|
||||
"h": 67
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 18,
|
||||
"y": 9,
|
||||
"w": 50,
|
||||
"h": 67
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 50,
|
||||
"h": 67
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:f2e4df704ed3262efeba03b98c4f34b6:856ea7816491331f96e020076871263b:fadb24d665ba1be4d210fe9064954d5b$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/rocket_grunt_f.png
Normal file
After Width: | Height: | Size: 718 B |
41
public/images/trainer/rocket_grunt_m.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "rocket_grunt_m.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 65,
|
||||
"h": 65
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 17,
|
||||
"y": 9,
|
||||
"w": 42,
|
||||
"h": 65
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 42,
|
||||
"h": 65
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:831f5748dad92911b10a1cb358ee2dae:a3bf81bbaa3b49cad5e0e549cf94563b:bb6befc9383c9c08837183ae2a7a80c1$"
|
||||
}
|
||||
}
|
BIN
public/images/trainer/rocket_grunt_m.png
Normal file
After Width: | Height: | Size: 677 B |
@ -314,7 +314,6 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
update() {
|
||||
this.inputController.update();
|
||||
this.ui?.update();
|
||||
}
|
||||
|
||||
@ -1820,6 +1819,8 @@ export default class BattleScene extends SceneBase {
|
||||
return 13.940;
|
||||
case "end_summit": //PMD RTDX Sky Tower Summit
|
||||
return 30.025;
|
||||
case "battle_plasma_grunt": //BW Team Plasma Battle
|
||||
return 12.974;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -423,7 +423,14 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[]): Get
|
||||
export interface FixedBattleConfigs {
|
||||
[key: integer]: FixedBattleConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* Youngster/Lass on 5
|
||||
* Rival on 8, 55, 95, 145, 195
|
||||
* Evil team grunts on 35, 62, 64, 65, 112, 114 (Not currently spawning)
|
||||
* Evil leader on 115, 165 (Not currently spawning)
|
||||
* E4 on 182, 184, 186, 188
|
||||
* Champion on 190
|
||||
*/
|
||||
export const classicFixedBattles: FixedBattleConfigs = {
|
||||
[5]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.YOUNGSTER, Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||
@ -431,12 +438,28 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||
[25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||
// [35]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
|
||||
[55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||
// [62]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
|
||||
// [64]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
|
||||
// [65]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
|
||||
[95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||
// [112]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
|
||||
// [114]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT ])),
|
||||
// [115]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE ])),
|
||||
[145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||
// [165]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
|
||||
// .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2 ])),
|
||||
[182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])),
|
||||
[184]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182)
|
||||
|
@ -449,6 +449,222 @@ export const trainerTypeDialogue: TrainerTypeDialogue = {
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.ROCKET_GRUNT]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:rocket_grunt.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:rocket_grunt.victory.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.MAGMA_GRUNT]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:magma_grunt.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:magma_grunt.victory.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.AQUA_GRUNT]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:aqua_grunt.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:aqua_grunt.victory.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.GALACTIC_GRUNT]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:galactic_grunt.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:galactic_grunt.victory.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.PLASMA_GRUNT]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:plasma_grunt.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:plasma_grunt.victory.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.FLARE_GRUNT]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:flare_grunt.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:flare_grunt.victory.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.ROCKET_BOSS_GIOVANNI_1]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:rocket_boss_giovanni_1.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:rocket_boss_giovanni_1.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:rocket_boss_giovanni_1.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.ROCKET_BOSS_GIOVANNI_2]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:rocket_boss_giovanni_2.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:rocket_boss_giovanni_2.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:rocket_boss_giovanni_2.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.MAXIE]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:magma_boss_maxie_1.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:magma_boss_maxie_1.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:magma_boss_maxie_1.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.MAXIE_2]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:magma_boss_maxie_2.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:magma_boss_maxie_2.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:magma_boss_maxie_2.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.ARCHIE]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:aqua_boss_archie_1.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:aqua_boss_archie_1.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:aqua_boss_archie_1.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.ARCHIE_2]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:aqua_boss_archie_2.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:aqua_boss_archie_2.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:aqua_boss_archie_2.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.CYRUS]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:galactic_boss_cyrus_1.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:galactic_boss_cyrus_1.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:galactic_boss_cyrus_1.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.CYRUS_2]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:galactic_boss_cyrus_2.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:galactic_boss_cyrus_2.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:galactic_boss_cyrus_2.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.GHETSIS]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:plasma_boss_ghetsis_1.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:plasma_boss_ghetsis_1.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:plasma_boss_ghetsis_1.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.GHETSIS_2]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:plasma_boss_ghetsis_2.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:plasma_boss_ghetsis_2.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:plasma_boss_ghetsis_2.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.LYSANDRE]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:flare_boss_lysandre_1.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:flare_boss_lysandre_1.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:flare_boss_lysandre_1.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.LYSANDRE_2]: [
|
||||
{
|
||||
encounter: [
|
||||
"dialogue:flare_boss_lysandre_2.encounter.1"
|
||||
],
|
||||
victory: [
|
||||
"dialogue:flare_boss_lysandre_2.victory.1"
|
||||
],
|
||||
defeat: [
|
||||
"dialogue:flare_boss_lysandre_2.defeat.1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[TrainerType.BROCK]: {
|
||||
encounter: [
|
||||
"dialogue:brock.encounter.1",
|
||||
|
@ -52,6 +52,24 @@ export enum TrainerType {
|
||||
WAITER,
|
||||
WORKER,
|
||||
YOUNGSTER,
|
||||
ROCKET_GRUNT,
|
||||
MAGMA_GRUNT,
|
||||
AQUA_GRUNT,
|
||||
GALACTIC_GRUNT,
|
||||
PLASMA_GRUNT,
|
||||
FLARE_GRUNT,
|
||||
ROCKET_BOSS_GIOVANNI_1,
|
||||
ROCKET_BOSS_GIOVANNI_2,
|
||||
MAXIE,
|
||||
MAXIE_2,
|
||||
ARCHIE,
|
||||
ARCHIE_2,
|
||||
CYRUS,
|
||||
CYRUS_2,
|
||||
GHETSIS,
|
||||
GHETSIS_2,
|
||||
LYSANDRE,
|
||||
LYSANDRE_2,
|
||||
|
||||
BROCK = 200,
|
||||
MISTY,
|
||||
|
@ -295,6 +295,25 @@ export class TrainerConfig {
|
||||
case TrainerType.LARRY_ELITE:
|
||||
trainerType = TrainerType.LARRY;
|
||||
break;
|
||||
case TrainerType.ROCKET_BOSS_GIOVANNI_1:
|
||||
case TrainerType.ROCKET_BOSS_GIOVANNI_2:
|
||||
trainerType = TrainerType.GIOVANNI;
|
||||
break;
|
||||
case TrainerType.MAXIE_2:
|
||||
trainerType = TrainerType.MAXIE;
|
||||
break;
|
||||
case TrainerType.ARCHIE_2:
|
||||
trainerType = TrainerType.ARCHIE;
|
||||
break;
|
||||
case TrainerType.CYRUS_2:
|
||||
trainerType = TrainerType.CYRUS;
|
||||
break;
|
||||
case TrainerType.GHETSIS_2:
|
||||
trainerType = TrainerType.GHETSIS;
|
||||
break;
|
||||
case TrainerType.LYSANDRE_2:
|
||||
trainerType = TrainerType.LYSANDRE;
|
||||
break;
|
||||
case TrainerType.MARNIE_ELITE:
|
||||
trainerType = TrainerType.MARNIE;
|
||||
break;
|
||||
@ -508,6 +527,40 @@ export class TrainerConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the trainer configuration for an evil team leader. Temporarily hardcoding evil leader teams though.
|
||||
* @param {Species | Species[]} signatureSpecies - The signature species for the evil team leader.
|
||||
* @param {Type[]} specialtyTypes - The specialty types for the evil team Leader.
|
||||
* @returns {TrainerConfig} - The updated TrainerConfig instance.
|
||||
* **/
|
||||
initForEvilTeamLeader(title: string, signatureSpecies: (Species | Species[])[], ...specialtyTypes: Type[]): TrainerConfig {
|
||||
if (!getIsInitialized()) {
|
||||
initI18n();
|
||||
}
|
||||
this.setPartyTemplates(trainerPartyTemplates.RIVAL_5);
|
||||
console.log(signatureSpecies);
|
||||
signatureSpecies.forEach((speciesPool, s) => {
|
||||
if (!Array.isArray(speciesPool)) {
|
||||
speciesPool = [speciesPool];
|
||||
}
|
||||
this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool));
|
||||
});
|
||||
if (specialtyTypes.length) {
|
||||
this.setSpeciesFilter(p => specialtyTypes.find(t => p.isOfType(t)) !== undefined);
|
||||
this.setSpecialtyTypes(...specialtyTypes);
|
||||
}
|
||||
const nameForCall = this.name.toLowerCase().replace(/\s/g, "_");
|
||||
this.name = i18next.t(`trainerNames:${nameForCall}`);
|
||||
this.setTitle(title);
|
||||
this.setMoneyMultiplier(2.5);
|
||||
this.setBoss();
|
||||
this.setStaticParty();
|
||||
this.setBattleBgm("battle_unova_gym"); // TODO: change
|
||||
this.setVictoryBgm("victory_gym"); // TODO: change
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the trainer configuration for a Gym Leader.
|
||||
* @param {Species | Species[]} signatureSpecies - The signature species for the Gym Leader.
|
||||
@ -761,6 +814,34 @@ interface TrainerConfigs {
|
||||
[key: integer]: TrainerConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* The function to get variable strength grutns
|
||||
* @param scene the singleton scene being passed in
|
||||
* @returns the correct TrainerPartyTemplate
|
||||
*/
|
||||
function getEvilGruntPartyTemplate(scene: BattleScene): TrainerPartyTemplate {
|
||||
const waveIndex = scene.currentBattle?.waveIndex;
|
||||
if (waveIndex < 40) {
|
||||
return trainerPartyTemplates.TWO_AVG;
|
||||
} else if (waveIndex < 80) {
|
||||
switch (waveIndex) {
|
||||
case 62:
|
||||
return trainerPartyTemplates.THREE_AVG;
|
||||
case 64:
|
||||
return trainerPartyTemplates.TWO_AVG_ONE_STRONG;
|
||||
case 65:
|
||||
return trainerPartyTemplates.GYM_LEADER_4; // 3avg 1 strong 1 stronger
|
||||
}
|
||||
} else {
|
||||
switch (waveIndex) {
|
||||
case 112:
|
||||
return trainerPartyTemplates.GYM_LEADER_4; // 3avg 1 strong 1 stronger
|
||||
case 114:
|
||||
return trainerPartyTemplates.GYM_LEADER_5; // 3 avg 2 strong 1 stronger
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getWavePartyTemplate(scene: BattleScene, ...templates: TrainerPartyTemplate[]) {
|
||||
return templates[Math.min(Math.max(Math.ceil((scene.gameMode.getWaveForDifficulty(scene.currentBattle?.waveIndex || startingWave, true) - 20) / 30), 0), templates.length - 1)];
|
||||
}
|
||||
@ -1103,6 +1184,54 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setSpeciesPools(
|
||||
[Species.CATERPIE, Species.WEEDLE, Species.RATTATA, Species.SENTRET, Species.POOCHYENA, Species.ZIGZAGOON, Species.WURMPLE, Species.BIDOOF, Species.PATRAT, Species.LILLIPUP]
|
||||
),
|
||||
[TrainerType.ROCKET_GRUNT]: new TrainerConfig(++t).setHasGenders("Rocket Grunt Female").setHasDouble("Rocket Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.WEEDLE, Species.RATTATA, Species.EKANS, Species.SANDSHREW, Species.ZUBAT, Species.GEODUDE, Species.KOFFING],
|
||||
[TrainerPoolTier.UNCOMMON]: [Species.GRIMER, Species.CUBONE, Species.ODDISH, Species.GROWLITHE, Species.MURKROW, Species.GASTLY, Species.EXEGGCUTE, Species.VOLTORB],
|
||||
[TrainerPoolTier.RARE]: [Species.GYARADOS, Species.TAUROS, Species.SCYTHER],
|
||||
[TrainerPoolTier.SUPER_RARE]: [Species.PORYGON, Species.ALOLA_RATTATA, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER, Species.ALOLA_GEODUDE],
|
||||
[TrainerPoolTier.ULTRA_RARE]: [Species.DRATINI, Species.LARVITAR]
|
||||
}),
|
||||
[TrainerType.MAGMA_GRUNT]: new TrainerConfig(++t).setHasGenders("Magma Grunt Female").setHasDouble("Magma Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [Species.SLUGMA, Species.POOCHYENA, Species.NUMEL, Species.ZIGZAGOON, Species.DIGLETT, Species.MAGBY],
|
||||
[TrainerPoolTier.UNCOMMON]: [Species.PHANPY, Species.SWINUB, Species.GLIGAR, Species.TORKOAL, Species.BALTOY, Species.BARBOACH],
|
||||
[TrainerPoolTier.RARE]: [Species.SOLROCK, Species.HIPPOPOTAS, Species.SANDACONDA],
|
||||
[TrainerPoolTier.SUPER_RARE]: [Species.TRAPINCH, Species.HEATMOR],
|
||||
[TrainerPoolTier.ULTRA_RARE]: [Species.TURTONATOR, Species.CHARCADET]
|
||||
}),
|
||||
[TrainerType.AQUA_GRUNT]: new TrainerConfig(++t).setHasGenders("Aqua Grunt Female").setHasDouble("Aqua Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.CARVANHA, Species.WAILMER, Species.ZIGZAGOON, Species.LOTAD, Species.CORPHISH],
|
||||
[TrainerPoolTier.UNCOMMON]: [Species.SPHEAL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL ],
|
||||
[TrainerPoolTier.RARE]: [Species.CLAMPERL, Species.REMORAID, Species.ARROKUDA],
|
||||
[TrainerPoolTier.SUPER_RARE]: [Species.MANTINE, Species.BASCULEGION],
|
||||
[TrainerPoolTier.ULTRA_RARE]: [Species.DONDOZO]
|
||||
}),
|
||||
[TrainerType.GALACTIC_GRUNT]: new TrainerConfig(++t).setHasGenders("Galactic Grunt Female").setHasDouble("Galactic Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.GLAMEOW, Species.STUNKY, Species.CROAGUNK, Species.SHINX, Species.WURMPLE],
|
||||
[TrainerPoolTier.UNCOMMON]: [Species.BRONZOR, Species.DRIFLOON, Species.BURMY],
|
||||
[TrainerPoolTier.RARE]: [Species.CARNIVINE],
|
||||
[TrainerPoolTier.SUPER_RARE]: [Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH, Species.HISUI_SNEASEL],
|
||||
[TrainerPoolTier.ULTRA_RARE]: [Species.HISUI_ZORUA, Species.HISUI_SLIGGOO]
|
||||
}),
|
||||
[TrainerType.PLASMA_GRUNT]: new TrainerConfig(++t).setHasGenders("Plasma Grunt Female").setHasDouble("Plasma Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.PATRAT, Species.LILLIPUP, Species.PURRLOIN, Species.SCRAFTY, Species.WOOBAT, Species.VANILLITE],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.FRILLISH, Species.VENIPEDE, Species.SANDILE, Species.TRUBBISH, Species.GOLETT],
|
||||
[TrainerPoolTier.RARE]: [Species.TIMBURR, Species.DARUMAKA, Species.AMOONGUSS, Species.DRILBUR, Species.KLINK, Species.VULLABY],
|
||||
[TrainerPoolTier.SUPER_RARE]: [Species.PAWNIARD, Species.VULLABY, Species.DRUDDIGON, Species.BOUFFALANT, Species.ZORUA],
|
||||
[TrainerPoolTier.ULTRA_RARE]: [Species.AXEW, Species.DEINO, Species.DURANT]
|
||||
}),
|
||||
[TrainerType.FLARE_GRUNT]: new TrainerConfig(++t).setHasGenders("Flare Grunt Female").setHasDouble("Flare Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene))
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.PONYTA, Species.INKAY, Species.HOUNDOUR, Species.SKORUPI],
|
||||
[TrainerPoolTier.UNCOMMON]: [Species.HELIOPTILE, Species.ELECTRIKE, Species.SKRELP, Species.GULPIN],
|
||||
[TrainerPoolTier.RARE]: [Species.LITWICK, Species.SNEASEL],
|
||||
[TrainerPoolTier.SUPER_RARE]: [Species.NOIVERN],
|
||||
[TrainerPoolTier.ULTRA_RARE]: []
|
||||
}),
|
||||
[TrainerType.BROCK]: new TrainerConfig((t = TrainerType.BROCK)).initForGymLeader(signatureSpecies["BROCK"],true, Type.ROCK).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.MISTY]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["MISTY"],false, Type.WATER).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
[TrainerType.LT_SURGE]: new TrainerConfig(++t).initForGymLeader(signatureSpecies["LT_SURGE"],true, Type.ELECTRIC).setBattleBgm("battle_kanto_gym").setMixedBattleBgm("battle_kanto_gym"),
|
||||
@ -1316,7 +1445,6 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
})),
|
||||
|
||||
|
||||
[TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL)
|
||||
.setModifierRewardFuncs(() => modifierTypes.SUPER_EXP_CHARM, () => modifierTypes.EXP_SHARE)
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.CHIKORITA, Species.CYNDAQUIL, Species.TOTODILE, Species.TREECKO, Species.TORCHIC, Species.MUDKIP, Species.TURTWIG, Species.CHIMCHAR, Species.PIPLUP, Species.SNIVY, Species.TEPIG, Species.OSHAWOTT, Species.CHESPIN, Species.FENNEKIN, Species.FROAKIE, Species.ROWLET, Species.LITTEN, Species.POPPLIO, Species.GROOKEY, Species.SCORBUNNY, Species.SOBBLE, Species.SPRIGATITO, Species.FUECOCO, Species.QUAXLY], TrainerSlot.TRAINER, true))
|
||||
@ -1381,4 +1509,211 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
const starter = party[0];
|
||||
return [modifierTypes.TERA_SHARD().generateType(null, [starter.species.type1]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier];
|
||||
}),
|
||||
|
||||
[TrainerType.ROCKET_BOSS_GIOVANNI_1]: new TrainerConfig(t = TrainerType.ROCKET_BOSS_GIOVANNI_1).setName("Giovanni").initForEvilTeamLeader("Rocket Boss",[])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PERSIAN , Species.ALOLA_PERSIAN]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.NIDOKING , Species.NIDOQUEEN ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.RHYPERIOR ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.DUGTRIO, Species.ALOLA_DUGTRIO ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.MAROWAK , Species.ALOLA_MAROWAK]))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KANGASKHAN ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.formIndex = 1;
|
||||
})),
|
||||
[TrainerType.ROCKET_BOSS_GIOVANNI_2]: new TrainerConfig(++t).setName("Giovanni").initForEvilTeamLeader("Rocket Boss", [])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.TYRANITAR , Species.IRON_THORNS], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.EXCADRILL ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.HIPPOWDON ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.KANGASKHAN ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.formIndex = 1;
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GASTRODON]))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.MEWTWO ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
})),
|
||||
[TrainerType.MAXIE]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss",[])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.MIGHTYENA ]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CROBAT, Species.GLISCOR ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WEEZING, Species.GALAR_WEEZING ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.MAGMORTAR, Species.TORKOAL ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.FLYGON]))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.CAMERUPT ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.formIndex = 1;
|
||||
})),
|
||||
[TrainerType.MAXIE_2]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss",[])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SOLROCK, Species.HOUNDOOM ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.GREAT_TUSK ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SHIFTRY, Species.SCOVILLAIN ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.abilityIndex = 0; // Chlorophyll
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TORKOAL, Species.NINETALES ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.abilityIndex = 2; // DROUGHT
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GROUDON ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.CAMERUPT ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.formIndex = 1;
|
||||
})),
|
||||
[TrainerType.ARCHIE]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss",[])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LINOONE ]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CROBAT, Species.PELIPPER ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.MUK, Species.ALOLA_MUK ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TENTACRUEL ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.RELICANTH, Species.WAILORD ]))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.SHARPEDO ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.formIndex = 1;
|
||||
})),
|
||||
[TrainerType.ARCHIE_2]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss",[])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.KINGDRA, Species.LUDICOLO ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BEARTIC, Species.ARMALDO ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.abilityIndex = 2; // Swift Swim
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.HUNTAIL, Species.GOREBYSS ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.abilityIndex = 0; // Swift Swim
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.POLITOED, Species.PELIPPER ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.abilityIndex = 2; // Drizzle
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.KYOGRE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.SHARPEDO ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.formIndex = 1;
|
||||
})),
|
||||
[TrainerType.CYRUS]: new TrainerConfig(++t).setName("Cyrus").initForEvilTeamLeader("Galactic Boss",[])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GYARADOS, Species.BASCULEGION ]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HONCHKROW, Species.HISUI_BRAVIARY ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.CROBAT, Species.OVERQWIL ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.AZELF, Species.UXIE, Species.MESPRIT ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.HOUNDOOM ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.formIndex = 1;
|
||||
}))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.WEAVILE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
})),
|
||||
[TrainerType.CYRUS_2]: new TrainerConfig(++t).setName("Cyrus").initForEvilTeamLeader("Galactic Boss",[])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.AZELF, Species.UXIE, Species.MESPRIT ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ELECTRODE, Species.HISUI_ELECTRODE ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SALAMENCE, Species.ROARING_MOON ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.HISUI_ZOROARK ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.DARKRAI ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.WEAVILE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
})),
|
||||
[TrainerType.GHETSIS]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss",[])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.COFAGRIGUS, Species.RUNERIGUS ]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BOUFFALANT ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SEISMITOAD, Species.CARRACOSTA ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.EELEKTROSS, Species.GALVANTULA ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.VOLCARONA ]))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.HYDREIGON ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
})),
|
||||
[TrainerType.GHETSIS_2]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss",[])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SLITHER_WING, Species.IRON_MOTH ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.DURANT ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.DARMANITAN, Species.GALAR_DARMANITAN ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.KINGAMBIT ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.KYUREM ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.HYDREIGON, Species.IRON_JUGULIS ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
})),
|
||||
[TrainerType.LYSANDRE]: new TrainerConfig(++t).setName("Lysandre").initForEvilTeamLeader("Flare Boss",[])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.MIENSHAO ]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HONCHKROW, Species.TALONFLAME ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.PYROAR ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.MILOTIC ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.HELIOLISK ]))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GYARADOS ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.formIndex = 1;
|
||||
})),
|
||||
[TrainerType.LYSANDRE_2]: new TrainerConfig(++t).setName("Lysandre").initForEvilTeamLeader("Flare Boss",[])
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SCREAM_TAIL, Species.FLUTTER_MANE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.GHOLDENGO, Species.AEGISLASH ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.PYROAR ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GOODRA, Species.HISUI_GOODRA ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.YVELTAL ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GYARADOS ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.formIndex = 1;
|
||||
})),
|
||||
};
|
||||
|
@ -122,6 +122,14 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||
// Determine the title to include based on the configuration and includeTitle flag.
|
||||
let title = includeTitle && this.config.title ? this.config.title : null;
|
||||
|
||||
if (this.name === "" && name.toLowerCase().includes("grunt")) {
|
||||
// This is a evil team grunt so we localize it by only using the "name" as the title
|
||||
title = i18next.t(`trainerClasses:${name.toLowerCase().replace(/\s/g, "_")}`);
|
||||
console.log("Localized grunt name: " + title);
|
||||
// Since grunts are not named we can just return the title
|
||||
return title;
|
||||
}
|
||||
|
||||
// If the trainer has a name (not null or undefined).
|
||||
if (this.name) {
|
||||
// If the title should be included.
|
||||
|
@ -1,7 +1,6 @@
|
||||
import Phaser from "phaser";
|
||||
import * as Utils from "./utils";
|
||||
import {deepCopy} from "./utils";
|
||||
import {initTouchControls} from "./touch-controls";
|
||||
import pad_generic from "./configs/inputs/pad_generic";
|
||||
import pad_unlicensedSNES from "./configs/inputs/pad_unlicensedSNES";
|
||||
import pad_xbox360 from "./configs/inputs/pad_xbox360";
|
||||
@ -21,6 +20,7 @@ import {
|
||||
import BattleScene from "./battle-scene";
|
||||
import {SettingGamepad} from "#app/system/settings/settings-gamepad.js";
|
||||
import {SettingKeyboard} from "#app/system/settings/settings-keyboard";
|
||||
import TouchControl from "#app/touch-controls";
|
||||
|
||||
export interface DeviceMapping {
|
||||
[key: string]: number;
|
||||
@ -48,7 +48,7 @@ export interface InterfaceConfig {
|
||||
custom?: MappingLayout;
|
||||
}
|
||||
|
||||
const repeatInputDelayMillis = 500;
|
||||
const repeatInputDelayMillis = 250;
|
||||
|
||||
// Phaser.Input.Gamepad.GamepadPlugin#refreshPads
|
||||
declare module "phaser" {
|
||||
@ -92,7 +92,7 @@ export class InputsController {
|
||||
private scene: BattleScene;
|
||||
public events: Phaser.Events.EventEmitter;
|
||||
|
||||
private buttonLock: Button;
|
||||
private buttonLock: Button[] = new Array();
|
||||
private interactions: Map<Button, Map<string, boolean>> = new Map();
|
||||
private configs: Map<string, InterfaceConfig> = new Map();
|
||||
|
||||
@ -101,10 +101,10 @@ export class InputsController {
|
||||
|
||||
private disconnectedGamepads: Array<String> = new Array();
|
||||
|
||||
private pauseUpdate: boolean = false;
|
||||
|
||||
public lastSource: string = "keyboard";
|
||||
private keys: Array<number> = [];
|
||||
private inputInterval: NodeJS.Timeout[] = new Array();
|
||||
private touchControls: TouchControl;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the game control system, setting up initial state and configurations.
|
||||
@ -181,7 +181,7 @@ export class InputsController {
|
||||
this.scene.input.keyboard.on("keydown", this.keyboardKeyDown, this);
|
||||
this.scene.input.keyboard.on("keyup", this.keyboardKeyUp, this);
|
||||
}
|
||||
initTouchControls(this.events);
|
||||
this.touchControls = new TouchControl(this.scene);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -192,6 +192,7 @@ export class InputsController {
|
||||
*/
|
||||
loseFocus(): void {
|
||||
this.deactivatePressedKey();
|
||||
this.touchControls.deactivatePressedKey();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -232,47 +233,6 @@ export class InputsController {
|
||||
this.initChosenLayoutKeyboard(layoutKeyboard);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the interaction handling by processing input states.
|
||||
* This method gives priority to certain buttons by reversing the order in which they are checked.
|
||||
* This method loops through all button values, checks for valid and timely interactions, and conditionally processes
|
||||
* or ignores them based on the current state of gamepad support and other criteria.
|
||||
*
|
||||
* It handles special conditions such as the absence of gamepad support or mismatches between the source of the input and
|
||||
* the currently chosen gamepad. It also respects the paused state of updates to prevent unwanted input processing.
|
||||
*
|
||||
* If an interaction is valid and should be processed, it emits an 'input_down' event with details of the interaction.
|
||||
*/
|
||||
update(): void {
|
||||
if (this.pauseUpdate) {
|
||||
return;
|
||||
}
|
||||
for (const b of Utils.getEnumValues(Button).reverse()) {
|
||||
if (
|
||||
this.interactions.hasOwnProperty(b) &&
|
||||
this.repeatInputDurationJustPassed(b as Button) &&
|
||||
this.interactions[b].isPressed
|
||||
) {
|
||||
// Prevents repeating button interactions when gamepad support is disabled.
|
||||
if (
|
||||
(!this.gamepadSupport && this.interactions[b].source === "gamepad") ||
|
||||
(this.interactions[b].source === "gamepad" && this.interactions[b].sourceName && this.interactions[b].sourceName !== this.selectedDevice[Device.GAMEPAD]) ||
|
||||
(this.interactions[b].source === "keyboard" && this.interactions[b].sourceName && this.interactions[b].sourceName !== this.selectedDevice[Device.KEYBOARD])
|
||||
) {
|
||||
// Deletes the last interaction for a button if gamepad is disabled.
|
||||
this.delLastProcessedMovementTime(b as Button);
|
||||
return;
|
||||
}
|
||||
// Emits an event for the button press.
|
||||
this.events.emit("input_down", {
|
||||
controller_type: this.interactions[b].source,
|
||||
button: b,
|
||||
});
|
||||
this.setLastProcessedMovementTime(b as Button, this.interactions[b].source, this.interactions[b].sourceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the identifiers of all connected gamepads, excluding any that are currently marked as disconnected.
|
||||
* @returns Array<String> An array of strings representing the IDs of the connected gamepads.
|
||||
@ -404,19 +364,24 @@ export class InputsController {
|
||||
*/
|
||||
keyboardKeyDown(event): void {
|
||||
this.lastSource = "keyboard";
|
||||
const keyDown = event.keyCode;
|
||||
this.ensureKeyboardIsInit();
|
||||
if (this.keys.includes(keyDown)) {
|
||||
return;
|
||||
}
|
||||
this.keys.push(keyDown);
|
||||
const buttonDown = getButtonWithKeycode(this.getActiveConfig(Device.KEYBOARD), keyDown);
|
||||
const buttonDown = getButtonWithKeycode(this.getActiveConfig(Device.KEYBOARD), event.keyCode);
|
||||
if (buttonDown !== undefined) {
|
||||
if (this.buttonLock.includes(buttonDown)) {
|
||||
return;
|
||||
}
|
||||
this.events.emit("input_down", {
|
||||
controller_type: "keyboard",
|
||||
button: buttonDown,
|
||||
});
|
||||
this.setLastProcessedMovementTime(buttonDown, "keyboard", this.selectedDevice[Device.KEYBOARD]);
|
||||
clearInterval(this.inputInterval[buttonDown]);
|
||||
this.inputInterval[buttonDown] = setInterval(() => {
|
||||
this.events.emit("input_down", {
|
||||
controller_type: "keyboard",
|
||||
button: buttonDown,
|
||||
});
|
||||
}, repeatInputDelayMillis);
|
||||
this.buttonLock.push(buttonDown);
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,16 +392,15 @@ export class InputsController {
|
||||
*/
|
||||
keyboardKeyUp(event): void {
|
||||
this.lastSource = "keyboard";
|
||||
const keyDown = event.keyCode;
|
||||
this.keys = this.keys.filter(k => k !== keyDown);
|
||||
this.ensureKeyboardIsInit();
|
||||
const buttonUp = getButtonWithKeycode(this.getActiveConfig(Device.KEYBOARD), keyDown);
|
||||
const buttonUp = getButtonWithKeycode(this.getActiveConfig(Device.KEYBOARD), event.keyCode);
|
||||
if (buttonUp !== undefined) {
|
||||
this.events.emit("input_up", {
|
||||
controller_type: "keyboard",
|
||||
button: buttonUp,
|
||||
});
|
||||
this.delLastProcessedMovementTime(buttonUp);
|
||||
const index = this.buttonLock.indexOf(buttonUp);
|
||||
this.buttonLock.splice(index, 1);
|
||||
clearInterval(this.inputInterval[buttonUp]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -466,11 +430,25 @@ export class InputsController {
|
||||
const activeConfig = this.getActiveConfig(Device.GAMEPAD);
|
||||
const buttonDown = activeConfig && getButtonWithKeycode(activeConfig, button.index);
|
||||
if (buttonDown !== undefined) {
|
||||
if (this.buttonLock.includes(buttonDown)) {
|
||||
return;
|
||||
}
|
||||
this.events.emit("input_down", {
|
||||
controller_type: "gamepad",
|
||||
button: buttonDown,
|
||||
});
|
||||
this.setLastProcessedMovementTime(buttonDown, "gamepad", pad.id);
|
||||
clearInterval(this.inputInterval[buttonDown]);
|
||||
this.inputInterval[buttonDown] = setInterval(() => {
|
||||
if (!this.buttonLock.includes(buttonDown)) {
|
||||
clearInterval(this.inputInterval[buttonDown]);
|
||||
return;
|
||||
}
|
||||
this.events.emit("input_down", {
|
||||
controller_type: "gamepad",
|
||||
button: buttonDown,
|
||||
});
|
||||
}, repeatInputDelayMillis);
|
||||
this.buttonLock.push(buttonDown);
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,7 +475,9 @@ export class InputsController {
|
||||
controller_type: "gamepad",
|
||||
button: buttonUp,
|
||||
});
|
||||
this.delLastProcessedMovementTime(buttonUp);
|
||||
const index = this.buttonLock.indexOf(buttonUp);
|
||||
this.buttonLock.splice(index, 1);
|
||||
clearInterval(this.inputInterval[buttonUp]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -540,144 +520,13 @@ export class InputsController {
|
||||
}
|
||||
|
||||
/**
|
||||
* repeatInputDurationJustPassed returns true if @param button has been held down long
|
||||
* enough to fire a repeated input. A button must claim the buttonLock before
|
||||
* firing a repeated input - this is to prevent multiple buttons from firing repeatedly.
|
||||
*/
|
||||
repeatInputDurationJustPassed(button: Button): boolean {
|
||||
if (!this.isButtonLocked(button)) {
|
||||
return false;
|
||||
}
|
||||
const duration = Date.now() - this.interactions[button].pressTime;
|
||||
if (duration >= repeatInputDelayMillis) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method updates the interaction state to reflect that the button is pressed.
|
||||
*
|
||||
* @param button - The button for which to set the interaction.
|
||||
* @param source - The source of the input (defaults to 'keyboard'). This helps identify the origin of the input, especially useful in environments with multiple input devices.
|
||||
*
|
||||
* @remarks
|
||||
* This method is responsible for updating the interaction state of a button within the `interactions` dictionary. If the button is not already registered, this method returns immediately.
|
||||
* When invoked, it performs the following updates:
|
||||
* - `pressTime`: Sets this to the current time, representing when the button was initially pressed.
|
||||
* - `isPressed`: Marks the button as currently being pressed.
|
||||
* - `source`: Identifies the source device of the input, which can vary across different hardware (e.g., keyboard, gamepad).
|
||||
*
|
||||
* Additionally, this method locks the button (by calling `setButtonLock`) to prevent it from being re-processed until it is released, ensuring that each press is handled distinctly.
|
||||
*/
|
||||
setLastProcessedMovementTime(button: Button, source: String = "keyboard", sourceName?: String): void {
|
||||
if (!this.interactions.hasOwnProperty(button)) {
|
||||
return;
|
||||
}
|
||||
this.setButtonLock(button);
|
||||
this.interactions[button].pressTime = Date.now();
|
||||
this.interactions[button].isPressed = true;
|
||||
this.interactions[button].source = source;
|
||||
this.interactions[button].sourceName = sourceName.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the last interaction for a specified button.
|
||||
*
|
||||
* @param button - The button for which to clear the interaction.
|
||||
*
|
||||
* @remarks
|
||||
* This method resets the interaction details of the button, allowing it to be processed as a new input when pressed again.
|
||||
* If the button is not registered in the `interactions` dictionary, this method returns immediately, otherwise:
|
||||
* - `pressTime` is cleared. This was previously storing the timestamp of when the button was initially pressed.
|
||||
* - `isPressed` is set to false, indicating that the button is no longer being pressed.
|
||||
* - `source` is set to null, which had been indicating the device from which the button input was originating.
|
||||
*
|
||||
* It releases the button lock, which prevents the button from being processed repeatedly until it's explicitly released.
|
||||
*/
|
||||
delLastProcessedMovementTime(button: Button): void {
|
||||
if (!this.interactions.hasOwnProperty(button)) {
|
||||
return;
|
||||
}
|
||||
this.releaseButtonLock(button);
|
||||
this.interactions[button].pressTime = null;
|
||||
this.interactions[button].isPressed = false;
|
||||
this.interactions[button].source = null;
|
||||
this.interactions[button].sourceName = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates all currently pressed keys and resets their interaction states.
|
||||
*
|
||||
* @remarks
|
||||
* This method is used to reset the state of all buttons within the `interactions` dictionary,
|
||||
* effectively deactivating any currently pressed keys. It performs the following actions:
|
||||
*
|
||||
* - Releases button lock for predefined buttons, allowing them
|
||||
* to be pressed again or properly re-initialized in future interactions.
|
||||
* - Iterates over all possible button values obtained via `Utils.getEnumValues(Button)`, and for
|
||||
* each button:
|
||||
* - Checks if the button is currently registered in the `interactions` dictionary.
|
||||
* - Resets `pressTime` to null, indicating that there is no ongoing interaction.
|
||||
* - Sets `isPressed` to false, marking the button as not currently active.
|
||||
* - Clears the `source` field, removing the record of which device the button press came from.
|
||||
*
|
||||
* This method is typically called when needing to ensure that all inputs are neutralized.
|
||||
* Deactivates all currently pressed keys.
|
||||
*/
|
||||
deactivatePressedKey(): void {
|
||||
this.pauseUpdate = true;
|
||||
this.releaseButtonLock(this.buttonLock);
|
||||
for (const b of Utils.getEnumValues(Button)) {
|
||||
if (this.interactions.hasOwnProperty(b)) {
|
||||
this.interactions[b].pressTime = null;
|
||||
this.interactions[b].isPressed = false;
|
||||
this.interactions[b].source = null;
|
||||
this.interactions[b].sourceName = null;
|
||||
}
|
||||
}
|
||||
this.pauseUpdate = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specific button is currently locked.
|
||||
*
|
||||
* @param button - The button to check for a lock status.
|
||||
* @returns `true` if the button is locked, otherwise `false`.
|
||||
*
|
||||
* @remarks
|
||||
* This method is used to determine if a given button is currently prevented from being processed due to a lock.
|
||||
* It checks against two separate lock variables, allowing for up to two buttons to be locked simultaneously.
|
||||
*/
|
||||
isButtonLocked(button: Button): boolean {
|
||||
return this.buttonLock === button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a lock on a given button.
|
||||
*
|
||||
* @param button - The button to lock.
|
||||
*
|
||||
* @remarks
|
||||
* This method ensures that a button is not processed multiple times inadvertently.
|
||||
* It checks if the button is already locked.
|
||||
*/
|
||||
setButtonLock(button: Button): void {
|
||||
this.buttonLock = button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a lock on a specific button, allowing it to be processed again.
|
||||
*
|
||||
* @param button - The button whose lock is to be released.
|
||||
*
|
||||
* @remarks
|
||||
* This method checks lock variable.
|
||||
* If either lock matches the specified button, that lock is cleared.
|
||||
* This action frees the button to be processed again, ensuring it can respond to new inputs.
|
||||
*/
|
||||
releaseButtonLock(button: Button): void {
|
||||
if (this.buttonLock === button) {
|
||||
this.buttonLock = null;
|
||||
for (const key of Object.keys(this.inputInterval)) {
|
||||
clearInterval(this.inputInterval[key]);
|
||||
}
|
||||
this.buttonLock = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -751,8 +600,7 @@ export class InputsController {
|
||||
* @param pressedButton The button that was pressed.
|
||||
*/
|
||||
assignBinding(config, settingName, pressedButton): boolean {
|
||||
this.pauseUpdate = true;
|
||||
setTimeout(() => this.pauseUpdate = false, 500);
|
||||
this.deactivatePressedKey();
|
||||
if (config.padType === "keyboard") {
|
||||
return assign(config, settingName, pressedButton);
|
||||
} else {
|
||||
|
@ -367,6 +367,17 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
1: "Ich werde für das nächste Rennen tunen."
|
||||
},
|
||||
},
|
||||
"rocket_grunt": {
|
||||
"encounter": {
|
||||
1: `Jetzt gibt es Ärger!…
|
||||
$und es kommt noch härter!
|
||||
$Wir wollen über die Erde regieren…
|
||||
$und naja du kennst den Rest…!`
|
||||
},
|
||||
"victory": {
|
||||
1: "Das war mal wieder ein Schuss in den Ofen!"
|
||||
},
|
||||
},
|
||||
"firebreather": {
|
||||
"encounter": {
|
||||
1: "Meine Flammen werden dich verschlingen!",
|
||||
@ -391,6 +402,190 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
3: "Ich glaube, ich bin der der seekrank ist..."
|
||||
},
|
||||
},
|
||||
"magma_grunt": {
|
||||
"encounter": {
|
||||
1: "Keiner, der sich Team Magma in den Weg stellt, bekommt Gnade, nicht einmal Kinder!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Wie kann das sein? Ich bin Teil vom mächtigen Team Magma! Wir wollen doch nur die Welt verbessern…"
|
||||
},
|
||||
},
|
||||
"aqua_grunt": {
|
||||
"encounter": {
|
||||
1: "Du willst dich also mit Team Aqua anlegen? Du traust dich ja was… Dich werfe ich über Bord!",
|
||||
},
|
||||
"victory": {
|
||||
1: "Vielleicht sollte ich wohl lieber selber über die Planke gehen…",
|
||||
},
|
||||
},
|
||||
"galactic_grunt": {
|
||||
"encounter": {
|
||||
1: "Team Galaktik wird die Welt in eine bessere Welt verwandeln! Und du wirst uns nicht aufhalten!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Zyrus wird uns für diese Niederlage bestrafen…"
|
||||
},
|
||||
},
|
||||
"plasma_grunt": {
|
||||
"encounter": {
|
||||
1: "Pokémon sollten frei sein! Team Plasma wird sie befreien!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Wie konnte ich verlieren? Ich dachte, ich würde die Welt retten…"
|
||||
},
|
||||
},
|
||||
"flare_grunt": {
|
||||
"encounter": {
|
||||
1: `Ich bin ein Mitglied von Team Flare! Das sieht man mir doch an. Mein Stil ist unverkennbar!
|
||||
$Du kannst definitiv ein Umstyling gebrauchen!`
|
||||
},
|
||||
"victory": {
|
||||
1: "Stil ist wohl doch nicht alles…"
|
||||
},
|
||||
},
|
||||
"rocket_boss_giovanni_1": {
|
||||
"encounter": {
|
||||
1: `Ich bin beeindruckt, du hast es bis hierher geschafft!
|
||||
$Ich bin Giovanni, der Anführer von Team Rocket!
|
||||
$Wir regieren den Untergrund von Kanto!
|
||||
$Und wir lassen sicherlich nicht zu, dass ein Kind uns aufhält!`
|
||||
|
||||
},
|
||||
"victory": {
|
||||
1: "Ich ziehe mich zurück, aber ich werde zurückkehren! Team Rocket wird niemals besiegt werden!"
|
||||
},
|
||||
"defeat": {
|
||||
1: `Merke dir meine Worte. Nicht in der Lage zu sein,
|
||||
$deine eigene Stärke zu messen, zeigt, dass du immer noch ein Kind bist.`
|
||||
}
|
||||
},
|
||||
"rocket_boss_giovanni_2": {
|
||||
"encounter": {
|
||||
1: "Du schon wieder… Wie hast du mich gefunden? Team Rocket wird dich endlich aus der Welt schaffen!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Wie ist das möglich...? Der kostbare Traum von Team Rocket ist nicht mehr als eine Illusion geworden..."
|
||||
},
|
||||
"defeat": {
|
||||
1: "Team Rocket wird niemals besiegt werden! Ich werde zurückkehren!"
|
||||
}
|
||||
},
|
||||
"magma_boss_maxie_1": {
|
||||
"encounter": {
|
||||
1: `Die Welt ist nicht perfekt. Ich werde sie verbessern, indem ich sie neu erschaffe!
|
||||
$Wir brauchen mehr Landmassen um zu leben! Team Magma wird dieses Ziel mit aller Macht erreichen!`
|
||||
},
|
||||
"victory": {
|
||||
1:"Ugh! Das entspricht nicht meinen Berechnungen! Wie konnte ich verlieren? Wir sehen uns wieder!"
|
||||
},
|
||||
"defeat": {
|
||||
1: "Team Magma wird weiterhin die Welt verbessern!"
|
||||
}
|
||||
},
|
||||
"magma_boss_maxie_2": {
|
||||
"encounter": {
|
||||
1: `Du bist das letzte Hindernis, das zwischen mir und meinen Zielen steht.
|
||||
$Mach dich bereit durch die Macht von Team Magma besiegt zu werden!`
|
||||
},
|
||||
"victory": {
|
||||
1: "Das... Das kann nicht sein...",
|
||||
},
|
||||
"defeat": {
|
||||
1: "Und jetzt werde ich diesen Planeten terraformen, um ihn ideal für die Menschheit zu machen."
|
||||
}
|
||||
},
|
||||
"aqua_boss_archie_1": {
|
||||
"encounter": {
|
||||
1: "Ich bin Adrian, der Anführer von Team Aqua! Wir werden die Welt mit Wasser überfluten!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Lass uns mal wieder treffen. Ich werde mir sicher sein, dass ich dieses Gesicht wiedererkenne."
|
||||
},
|
||||
"defeat": {
|
||||
1: "Brilliant! Mein Team wird jetzt nicht zurückhalten!"
|
||||
}
|
||||
},
|
||||
"aqua_boss_archie_2": {
|
||||
"encounter": {
|
||||
1: "Ich habe lange auf diesen Tag gewartet. Das ist die wahre Macht von Team Aqua!"
|
||||
},
|
||||
"victory": {
|
||||
1: "So habe ich mir das nicht vorgestellt..."
|
||||
},
|
||||
"defeat": {
|
||||
1: "Ich werde alles in dieser Welt in seinen ursprünglichen, reinen Zustand zurückversetzen!!"
|
||||
}
|
||||
},
|
||||
"galactic_boss_cyrus_1": {
|
||||
"encounter": {
|
||||
1: `Du wurdest von leerer Gefühlsduselei hierher getrieben.
|
||||
$Ich werde dich bereuen lassen, auf dein Herz gehört zu haben!`
|
||||
},
|
||||
"victory": {
|
||||
1: "Interessant. Und ziemlich eigenartig."
|
||||
},
|
||||
"defeat": {
|
||||
1: "Ich werde meine neue Welt erschaffen..."
|
||||
}
|
||||
},
|
||||
"galactic_boss_cyrus_2": {
|
||||
"encounter": {
|
||||
1: `So sehen wir uns wieder. Es scheint, als wären unsere Schicksale miteinander verflochten.
|
||||
$Aber hier und jetzt werde ich diese Verbindung brechen!`
|
||||
},
|
||||
"victory": {
|
||||
1: "Wie? Wie? WIE?!"
|
||||
},
|
||||
"defeat": {
|
||||
1: "Bis bald."
|
||||
}
|
||||
},
|
||||
"plasma_boss_ghetsis_1": {
|
||||
"encounter": {
|
||||
1:"Ich werde nicht zulassen, dass mich jemand aufhält! Egal wer es auch sein mag!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Wie kann das sein? Ich bin der Schöpfer von Team Plasma! Ich bin perfekt!"
|
||||
},
|
||||
"defeat": {
|
||||
1: "Ich bin der perfekte Herrscher einer perfekten neuen Welt! Mwa ha ha!"
|
||||
}
|
||||
},
|
||||
"plasma_boss_ghetsis_2": {
|
||||
"encounter": {
|
||||
1: "Komm schon! Ich will dein Gesicht sehen, in dem Moment, in dem du alle Hoffnung verlierst!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Meine Berechnungen... Nein! Meine sorgfältigen Pläne! Die Welt sollte mir gehören!"
|
||||
},
|
||||
"defeat": {
|
||||
1: "Kyurem! Verwende Absorptionsfusion!"
|
||||
}
|
||||
},
|
||||
"flare_boss_lysandre_1": {
|
||||
"encounter": {
|
||||
1: "DU willst mich aufhalten? Dann zeig mir deine Stärke in einem Kampf!"
|
||||
},
|
||||
"victory": {
|
||||
1: `Du bist hier, um mich aufzuhalten. Aber ich bitte dich zu warten.
|
||||
$Ich bin so kurz davor, meine Vision zu verwirklichen.`
|
||||
},
|
||||
"defeat": {
|
||||
1: "Pokémon... Sollten nicht mehr existieren."
|
||||
}
|
||||
},
|
||||
"flare_boss_lysandre_2": {
|
||||
"encounter": {
|
||||
1: `Die Zukunft, die du willst, oder die Zukunft, die ich will...
|
||||
$Lass uns sehen, welche mehr zu existieren verdient, sollen wir?`
|
||||
},
|
||||
"victory": {
|
||||
1: "Die Zukunft, die ich erschaffen wollte... Es ist vorbei..."
|
||||
},
|
||||
"defeat": {
|
||||
1: "Narren ohne Vision werden weiterhin diese wunderschöne Welt verunreinigen."
|
||||
}
|
||||
},
|
||||
"brock": {
|
||||
"encounter": {
|
||||
1: "Meine Expertise in Bezug auf Gesteins-Pokémon wird dich besiegen! Komm schon!",
|
||||
|
@ -13,6 +13,12 @@ export const titles: SimpleTranslationEntries = {
|
||||
"rival": "Rivale",
|
||||
"professor": "Professor",
|
||||
"frontier_brain": "Kampfkoryphäen",
|
||||
"rocket_boss": "Rocket-Boss",
|
||||
"magma_boss": "Magma-Boss",
|
||||
"aqua_boss": "Aqua-Boss",
|
||||
"galactic_boss": "Galaktik-Boss",
|
||||
"plasma_boss": "Weiser von Team Plasma", // This is on purpose, since "Ghetsis" is never mentioned as the boss of team plasma in the game but as "Weiser"
|
||||
"flare_boss": "Flare-Boss",
|
||||
// Maybe if we add the evil teams we can add "Team Rocket" and "Team Aqua" etc. here as well as "Team Rocket Boss" and "Team Aqua Admin" etc.
|
||||
} as const;
|
||||
|
||||
@ -118,7 +124,25 @@ export const trainerClasses: SimpleTranslationEntries = {
|
||||
"worker": "Arbeiter",
|
||||
"worker_female": "Arbeiterin",
|
||||
"workers": "Arbeiter",
|
||||
"youngster": "Knirps"
|
||||
"youngster": "Knirps",
|
||||
"rocket_grunt": "Rüpel von Team Rocket",
|
||||
"rocket_grunt_female": "Rüpel von Team Rocket",
|
||||
"rocket_grunts": "Rüpel von Team Rocket",
|
||||
"magma_grunt": "Rüpel von Team Magma",
|
||||
"magma_grunt_female": "Rüpel von Team Magma",
|
||||
"magma_grunts": "Rüpel von Team Magma",
|
||||
"aqua_grunt": "Rüpel von Team Aqua",
|
||||
"aqua_grunt_female": "Rüpel von Team Aqua",
|
||||
"aqua_grunts": "Rüpel von Team Aqua",
|
||||
"galactic_grunt": "Rüpel von Team Galaktik",
|
||||
"galactic_grunt_female": "Rüpel von Team Galaktik",
|
||||
"galactic_grunts": "Rüpel von Team Galaktik",
|
||||
"plasma_grunt": "Rüpel von Team Plasma",
|
||||
"plasma_grunt_female": "Rüpel von Team Plasma",
|
||||
"plasma_grunts": "Rüpel von Team Plasma",
|
||||
"flare_grunt": "Rüpel von Team Flare",
|
||||
"flare_grunt_female": "Rüpel von Team Flare",
|
||||
"flare_grunts": "Rüpel von Team Flare",
|
||||
} as const;
|
||||
|
||||
// Names of special trainers like gym leaders, elite four, and the champion
|
||||
@ -247,6 +271,11 @@ export const trainerNames: SimpleTranslationEntries = {
|
||||
"leon": "Delion",
|
||||
"rival": "Finn",
|
||||
"rival_female": "Ivy",
|
||||
"maxie": "Marc",
|
||||
"archie": "Adrian",
|
||||
"cyrus": "Zyrus",
|
||||
"ghetsis": "G-Cis",
|
||||
"lysandre": "Flordelis",
|
||||
|
||||
// Double Names
|
||||
"blue_red_double": "Blau & Rot",
|
||||
|
@ -383,6 +383,186 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
3: "I think it's me that's seasick..."
|
||||
},
|
||||
},
|
||||
"rocket_grunt": {
|
||||
"encounter": {
|
||||
1: "Prepare for trouble!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Team Rocket blasting off again!"
|
||||
},
|
||||
},
|
||||
"magma_grunt": {
|
||||
"encounter": {
|
||||
1: " If you get in the way of Team Magma, don’t expect any mercy!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Huh? I lost?!"
|
||||
},
|
||||
},
|
||||
"aqua_grunt": {
|
||||
"encounter": {
|
||||
1: "No one who crosses Team Aqua gets any mercy, not even kids!"
|
||||
},
|
||||
"victory": {
|
||||
1: "You're kidding me!"
|
||||
},
|
||||
},
|
||||
"galactic_grunt": {
|
||||
"encounter": {
|
||||
1: "Don't mess with Team Galactic!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Shut down..."
|
||||
},
|
||||
},
|
||||
"plasma_grunt": {
|
||||
"encounter": {
|
||||
1: "We won't tolerate people who have different ideas!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Plasmaaaaaaaaa!"
|
||||
},
|
||||
},
|
||||
"flare_grunt": {
|
||||
"encounter": {
|
||||
1: "Fashion is most important to us!"
|
||||
},
|
||||
"victory": {
|
||||
1: "The future doesn't look bright for me."
|
||||
},
|
||||
},
|
||||
"rocket_boss_giovanni_1": {
|
||||
"encounter": {
|
||||
1: "So! I must say, I am impressed you got here!"
|
||||
},
|
||||
"victory": {
|
||||
1: "WHAT! This cannot be!"
|
||||
},
|
||||
"defeat": {
|
||||
1: "Mark my words. Not being able to measure your own strength shows that you are still a child."
|
||||
}
|
||||
},
|
||||
"rocket_boss_giovanni_2": {
|
||||
"encounter": {
|
||||
1: "My old associates need me... Are you going to get in my way?"
|
||||
},
|
||||
"victory": {
|
||||
1: "How is this possible...?\nThe precious dream of Team Rocket has become little more than an illusion..."
|
||||
},
|
||||
"defeat": {
|
||||
1: "Team Rocket will be reborn again, and I will rule the world!"
|
||||
}
|
||||
},
|
||||
"magma_boss_maxie_1": {
|
||||
"encounter": {
|
||||
1: "I will bury you by my own hand. I hope you appreciate this honor!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Ugh! You are... quite capable...\nI fell behind, but only by an inch..."
|
||||
},
|
||||
"defeat": {
|
||||
1: "Team Magma will prevail!"
|
||||
}
|
||||
},
|
||||
"magma_boss_maxie_2": {
|
||||
"encounter": {
|
||||
1: "You are the final obstacle remaining between me and my goals.\nBrace yourself for my ultimate attack! Fuhahaha!"
|
||||
},
|
||||
"victory": {
|
||||
1: "This... This is not.. Ngh..."
|
||||
},
|
||||
"defeat": {
|
||||
1: "And now... I will transform this planet to a land ideal for humanity."
|
||||
}
|
||||
},
|
||||
"aqua_boss_archie_1": {
|
||||
"encounter": {
|
||||
1: "I'm leader of Team Aqua, so I'm afraid it's the rope's end for you."
|
||||
},
|
||||
"victory": {
|
||||
1: "Let's meet again somewhere. I'll be sure to remember that face."
|
||||
},
|
||||
"defeat": {
|
||||
1: "Brilliant! My team won't hold back now!"
|
||||
}
|
||||
},
|
||||
"aqua_boss_archie_2": {
|
||||
"encounter": {
|
||||
1: "I've been waiting so long for this day to come.\nThis is the true power of my team!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Like I figured..."
|
||||
},
|
||||
"defeat": {
|
||||
1: "I'll return everything in this world to its original, pure state!!"
|
||||
}
|
||||
},
|
||||
"galactic_boss_cyrus_1": {
|
||||
"encounter": {
|
||||
1: "You were compelled to come here by such vacuous sentimentality\nI will make you regret paying heed to your heart!"
|
||||
},
|
||||
"victory": {
|
||||
1: "Interesting. And quite curious."
|
||||
},
|
||||
"defeat": {
|
||||
1: "I will create my new world..."
|
||||
}
|
||||
},
|
||||
"galactic_boss_cyrus_2": {
|
||||
"encounter": {
|
||||
1: "So we meet again. It seems our fates have become intertwined.\nBut here and now, I will finally break that bond!"
|
||||
},
|
||||
"victory": {
|
||||
1: "How? How? HOW?!"
|
||||
},
|
||||
"defeat": {
|
||||
1: "Farewell."
|
||||
}
|
||||
},
|
||||
"plasma_boss_ghetsis_1": {
|
||||
"encounter": {
|
||||
1: "I won't allow anyone to stop me! No matter who does what!"
|
||||
},
|
||||
"victory": {
|
||||
1: "How can this be? I'm the creator of Team Plasma! I'm perfect!"
|
||||
},
|
||||
"defeat": {
|
||||
1: "I am the perfect ruler of a perfect new world! Mwa ha ha!"
|
||||
}
|
||||
},
|
||||
"plasma_boss_ghetsis_2": {
|
||||
"encounter": {
|
||||
1: "Come now! I want to see your face at the moment you lose all hope!"
|
||||
},
|
||||
"victory": {
|
||||
1: "My calculations... No! My careful schemes! The world should be mine!"
|
||||
},
|
||||
"defeat": {
|
||||
1: "Kyurem! Use Absofusion!"
|
||||
}
|
||||
},
|
||||
"flare_boss_lysandre_1": {
|
||||
"encounter": {
|
||||
1: "Do you want to stop me? Show me in battle."
|
||||
},
|
||||
"victory": {
|
||||
1: "You are here to stop me. But I ask you to wait. "
|
||||
},
|
||||
"defeat": {
|
||||
1: "Pokemon...Shall no longer exist."
|
||||
}
|
||||
},
|
||||
"flare_boss_lysandre_2": {
|
||||
"encounter": {
|
||||
1: "The future you want, or the future I want... Let us see which one is more deserving, shall we?"
|
||||
},
|
||||
"victory": {
|
||||
1: "Whaugh!"
|
||||
},
|
||||
"defeat": {
|
||||
1: "Fools with no vision will continue to befoul this beautiful world."
|
||||
}
|
||||
},
|
||||
"brock": {
|
||||
"encounter": {
|
||||
1: "My expertise on Rock-type Pokémon will take you down! Come on!",
|
||||
|
@ -7,5 +7,6 @@ export const pokemonInfoContainer: SimpleTranslationEntries = {
|
||||
"nature": "Nature:",
|
||||
"epic": "Epic",
|
||||
"rare": "Rare",
|
||||
"common": "Common"
|
||||
"common": "Common",
|
||||
"form": "Form:"
|
||||
} as const;
|
||||
|
@ -13,6 +13,12 @@ export const titles: SimpleTranslationEntries = {
|
||||
"rival": "Rival",
|
||||
"professor": "Professor",
|
||||
"frontier_brain": "Frontier Brain",
|
||||
"rocket_boss": "Team Rocket Boss",
|
||||
"magma_boss": "Team Magma Boss",
|
||||
"aqua_boss": "Team Aqua Boss",
|
||||
"galactic_boss": "Team Galactic Boss",
|
||||
"plasma_boss": "Team Plasma Boss",
|
||||
"flare_boss": "Team Flare Boss",
|
||||
// Maybe if we add the evil teams we can add "Team Rocket" and "Team Aqua" etc. here as well as "Team Rocket Boss" and "Team Aqua Admin" etc.
|
||||
} as const;
|
||||
|
||||
@ -118,7 +124,19 @@ export const trainerClasses: SimpleTranslationEntries = {
|
||||
"worker": "Worker",
|
||||
"worker_female": "Worker",
|
||||
"workers": "Workers",
|
||||
"youngster": "Youngster"
|
||||
"youngster": "Youngster",
|
||||
"rocket_grunt": "Rocket Grunt",
|
||||
"rocket_grunt_female": "Rocket Grunt",
|
||||
"magma_grunt": "Magma Grunt",
|
||||
"magma_grunt_female": "Magma Grunt",
|
||||
"aqua_grunt": "Aqua Grunt",
|
||||
"aqua_grunt_female": "Aqua Grunt",
|
||||
"galactic_grunt": "Galactic Grunt",
|
||||
"galactic_grunt_female": "Galactic Grunt",
|
||||
"plasma_grunt": "Plasma Grunt",
|
||||
"plasma_grunt_female": "Plasma Grunt",
|
||||
"flare_grunt": "Flare Grunt",
|
||||
"flare_grunt_female": "Flare Grunt",
|
||||
} as const;
|
||||
|
||||
// Names of special trainers like gym leaders, elite four, and the champion
|
||||
@ -247,6 +265,11 @@ export const trainerNames: SimpleTranslationEntries = {
|
||||
"leon": "Leon",
|
||||
"rival": "Finn",
|
||||
"rival_female": "Ivy",
|
||||
"maxie": "Maxie",
|
||||
"archie": "Archie",
|
||||
"cyrus": "Cyrus",
|
||||
"ghetsis": "Ghetsis",
|
||||
"lysandre": "Lysandre",
|
||||
|
||||
// Double Names
|
||||
"blue_red_double": "Blue & Red",
|
||||
|
@ -4,5 +4,5 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "¡{{abilityName}} de {{pokemonName}}\nlo protegió del daño de retroceso!",
|
||||
"badDreams": "¡{{pokemonName}} está atormentado!",
|
||||
"windPowerCharged": "¡{{pokemonName}} se ha cargado de electricidad gracias a {{moveName}}!",
|
||||
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!"
|
||||
"iceFaceAvoidedDamage": "¡{{pokemonNameWithAffix}} evitó\ndaño con {{abilityName}}!"
|
||||
} as const;
|
||||
|
@ -14,7 +14,7 @@ export const challenges: SimpleTranslationEntries = {
|
||||
"singleGeneration.value.3": "3세대",
|
||||
"singleGeneration.desc.3": "3세대의 포켓몬만 사용할 수 있습니다.",
|
||||
"singleGeneration.value.4": "4세대",
|
||||
"singleGeneration.desc.4": "4세대의 포켓몬만 사용할 수 있습니다r",
|
||||
"singleGeneration.desc.4": "4세대의 포켓몬만 사용할 수 있습니다.",
|
||||
"singleGeneration.value.5": "5세대",
|
||||
"singleGeneration.desc.5": "5세대의 포켓몬만 사용할 수 있습니다.",
|
||||
"singleGeneration.value.6": "6세대",
|
||||
|
@ -223,7 +223,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
|
||||
2: "살아있는 산같은… 큰 체격을 부모님이 물려주셨죠…",
|
||||
},
|
||||
"victory": {
|
||||
1: "적어도 BMI에 대하서는 질 수 없습니다!",
|
||||
1: "적어도 BMI에 대해서는 질 수 없습니다!",
|
||||
2: "부족해… 절대로 충분하지 않아. 저의 콜레스테롤이 부족합니다…"
|
||||
},
|
||||
},
|
||||
|
@ -52,11 +52,6 @@ describe("Inputs", () => {
|
||||
expect(game.inputsHandler.log.length).toBe(4);
|
||||
});
|
||||
|
||||
it("keyboard - test input holding for 1ms - 1 input", async() => {
|
||||
await game.inputsHandler.pressKeyboardKey(cfg_keyboard_qwerty.deviceMapping.KEY_ARROW_UP, 1);
|
||||
expect(game.inputsHandler.log.length).toBe(1);
|
||||
});
|
||||
|
||||
it("keyboard - test input holding for 200ms - 1 input", async() => {
|
||||
await game.inputsHandler.pressKeyboardKey(cfg_keyboard_qwerty.deviceMapping.KEY_ARROW_UP, 200);
|
||||
expect(game.inputsHandler.log.length).toBe(1);
|
||||
@ -87,6 +82,11 @@ describe("Inputs", () => {
|
||||
expect(game.inputsHandler.log.length).toBe(1);
|
||||
});
|
||||
|
||||
it("gamepad - test input holding for 249ms - 1 input", async() => {
|
||||
await game.inputsHandler.pressGamepadButton(pad_xbox360.deviceMapping.RC_S, 249);
|
||||
expect(game.inputsHandler.log.length).toBe(1);
|
||||
});
|
||||
|
||||
it("gamepad - test input holding for 300ms - 2 input", async() => {
|
||||
await game.inputsHandler.pressGamepadButton(pad_xbox360.deviceMapping.RC_S, 300);
|
||||
expect(game.inputsHandler.log.length).toBe(2);
|
||||
|
@ -3,7 +3,7 @@ import Phaser from "phaser";
|
||||
import {InputsController} from "#app/inputs-controller";
|
||||
import pad_xbox360 from "#app/configs/inputs/pad_xbox360";
|
||||
import {holdOn} from "#app/test/utils/gameManagerUtils";
|
||||
import {initTouchControls} from "#app/touch-controls";
|
||||
import TouchControl from "#app/touch-controls";
|
||||
import { JSDOM } from "jsdom";
|
||||
import fs from "fs";
|
||||
|
||||
@ -54,10 +54,8 @@ export default class InputsHandler {
|
||||
}
|
||||
|
||||
init(): void {
|
||||
setInterval(() => {
|
||||
this.inputController.update();
|
||||
});
|
||||
initTouchControls(this.inputController.events);
|
||||
const touchControl = new TouchControl(this.scene);
|
||||
touchControl.deactivatePressedKey(); //test purpose
|
||||
this.events = this.inputController.events;
|
||||
this.scene.input.gamepad.emit("connected", this.fakePad);
|
||||
this.listenInputs();
|
||||
|
@ -1,25 +1,164 @@
|
||||
import {Button} from "./enums/buttons";
|
||||
import EventEmitter = Phaser.Events.EventEmitter;
|
||||
import BattleScene from "./battle-scene";
|
||||
|
||||
// Create a map to store key bindings
|
||||
export const keys = new Map<string, string>();
|
||||
// Create a map to store keys that are currently pressed
|
||||
export const keysDown = new Map<string, string>();
|
||||
// Variable to store the ID of the last touched element
|
||||
let lastTouchedId: string;
|
||||
const repeatInputDelayMillis = 250;
|
||||
|
||||
/**
|
||||
* Initialize touch controls by binding keys to buttons.
|
||||
*
|
||||
* @param events - The event emitter for handling input events.
|
||||
*/
|
||||
export function initTouchControls(events: EventEmitter): void {
|
||||
preventElementZoom(document.querySelector("#dpad"));
|
||||
preventElementZoom(document.querySelector("#apad"));
|
||||
// Select all elements with the 'data-key' attribute and bind keys to them
|
||||
for (const button of document.querySelectorAll("[data-key]")) {
|
||||
// @ts-ignore - Bind the key to the button using the dataset key
|
||||
bindKey(button, button.dataset.key, events);
|
||||
export default class TouchControl {
|
||||
events: EventEmitter;
|
||||
private buttonLock: string[] = new Array();
|
||||
private inputInterval: NodeJS.Timeout[] = new Array();
|
||||
|
||||
constructor(scene: BattleScene) {
|
||||
this.events = scene.game.events;
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize touch controls by binding keys to buttons.
|
||||
*/
|
||||
init() {
|
||||
this.preventElementZoom(document.querySelector("#dpad"));
|
||||
this.preventElementZoom(document.querySelector("#apad"));
|
||||
// Select all elements with the 'data-key' attribute and bind keys to them
|
||||
for (const button of document.querySelectorAll("[data-key]")) {
|
||||
// @ts-ignore - Bind the key to the button using the dataset key
|
||||
this.bindKey(button, button.dataset.key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a node to a specific key to simulate keyboard events on touch.
|
||||
*
|
||||
* @param node - The DOM element to bind the key to.
|
||||
* @param key - The key to simulate.
|
||||
* @param events - The event emitter for handling input events.
|
||||
*
|
||||
* @remarks
|
||||
* This function binds touch events to a node to simulate 'keydown' and 'keyup' keyboard events.
|
||||
* It adds the key to the keys map and tracks the keydown state. When a touch starts, it simulates
|
||||
* a 'keydown' event and adds an 'active' class to the node. When the touch ends, it simulates a 'keyup'
|
||||
* event, removes the keydown state, and removes the 'active' class from the node and the last touched element.
|
||||
*/
|
||||
bindKey(node: HTMLElement, key: string) {
|
||||
node.addEventListener("touchstart", event => {
|
||||
event.preventDefault();
|
||||
this.touchButtonDown(node, key);
|
||||
});
|
||||
|
||||
node.addEventListener("touchend", event => {
|
||||
event.preventDefault();
|
||||
this.touchButtonUp(node, key, event.target["id"]);
|
||||
});
|
||||
}
|
||||
|
||||
touchButtonDown(node: HTMLElement, key: string) {
|
||||
if (this.buttonLock.includes(key)) {
|
||||
return;
|
||||
}
|
||||
this.simulateKeyboardEvent("keydown", key);
|
||||
clearInterval(this.inputInterval[key]);
|
||||
this.inputInterval[key] = setInterval(() => {
|
||||
this.simulateKeyboardEvent("keydown", key);
|
||||
}, repeatInputDelayMillis);
|
||||
this.buttonLock.push(key);
|
||||
node.classList.add("active");
|
||||
|
||||
}
|
||||
|
||||
touchButtonUp(node: HTMLElement, key: string, id: string) {
|
||||
if (!this.buttonLock.includes(key)) {
|
||||
return;
|
||||
}
|
||||
this.simulateKeyboardEvent("keyup", key);
|
||||
|
||||
node.classList.remove("active");
|
||||
|
||||
document.getElementById(id)?.classList.remove("active");
|
||||
const index = this.buttonLock.indexOf(key);
|
||||
this.buttonLock.splice(index, 1);
|
||||
clearInterval(this.inputInterval[key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates a keyboard event on the canvas.
|
||||
*
|
||||
* @param eventType - The type of the keyboard event ('keydown' or 'keyup').
|
||||
* @param key - The key to simulate.
|
||||
*
|
||||
* @remarks
|
||||
* This function checks if the key exists in the Button enum. If it does, it retrieves the corresponding button
|
||||
* and emits the appropriate event ('input_down' or 'input_up') based on the event type.
|
||||
*/
|
||||
simulateKeyboardEvent(eventType: string, key: string) {
|
||||
if (!Button.hasOwnProperty(key)) {
|
||||
return;
|
||||
}
|
||||
const button = Button[key];
|
||||
|
||||
switch (eventType) {
|
||||
case "keydown":
|
||||
this.events.emit("input_down", {
|
||||
controller_type: "keyboard",
|
||||
button: button,
|
||||
isTouch: true
|
||||
});
|
||||
break;
|
||||
case "keyup":
|
||||
this.events.emit("input_up", {
|
||||
controller_type: "keyboard",
|
||||
button: button,
|
||||
isTouch: true
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link https://stackoverflow.com/a/39778831/4622620|Source}
|
||||
*
|
||||
* Prevent zoom on specified element
|
||||
* @param {HTMLElement} element
|
||||
*/
|
||||
preventElementZoom(element: HTMLElement): void {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
element.addEventListener("touchstart", (event: TouchEvent) => {
|
||||
|
||||
if (!(event.currentTarget instanceof HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentTouchTimeStamp = event.timeStamp;
|
||||
const previousTouchTimeStamp = Number(event.currentTarget.dataset.lastTouchTimeStamp) || currentTouchTimeStamp;
|
||||
const timeStampDifference = currentTouchTimeStamp - previousTouchTimeStamp;
|
||||
const fingers = event.touches.length;
|
||||
event.currentTarget.dataset.lastTouchTimeStamp = String(currentTouchTimeStamp);
|
||||
|
||||
if (!timeStampDifference || timeStampDifference > 500 || fingers > 1) {
|
||||
return;
|
||||
} // not double-tap
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (event.target instanceof HTMLElement) {
|
||||
event.target.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates all currently pressed keys.
|
||||
*/
|
||||
deactivatePressedKey(): void {
|
||||
for (const key of Object.keys(this.inputInterval)) {
|
||||
clearInterval(this.inputInterval[key]);
|
||||
}
|
||||
for (const button of document.querySelectorAll("[data-key]")) {
|
||||
button.classList.remove("active");
|
||||
}
|
||||
this.buttonLock = [];
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,113 +186,3 @@ export function isMobile(): boolean {
|
||||
})(navigator.userAgent || navigator.vendor || window["opera"]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates a keyboard event on the canvas.
|
||||
*
|
||||
* @param eventType - The type of the keyboard event ('keydown' or 'keyup').
|
||||
* @param key - The key to simulate.
|
||||
* @param events - The event emitter for handling input events.
|
||||
*
|
||||
* @remarks
|
||||
* This function checks if the key exists in the Button enum. If it does, it retrieves the corresponding button
|
||||
* and emits the appropriate event ('input_down' or 'input_up') based on the event type.
|
||||
*/
|
||||
function simulateKeyboardEvent(eventType: string, key: string, events: EventEmitter) {
|
||||
if (!Button.hasOwnProperty(key)) {
|
||||
return;
|
||||
}
|
||||
const button = Button[key];
|
||||
|
||||
switch (eventType) {
|
||||
case "keydown":
|
||||
events.emit("input_down", {
|
||||
controller_type: "keyboard",
|
||||
button: button,
|
||||
isTouch: true
|
||||
});
|
||||
break;
|
||||
case "keyup":
|
||||
events.emit("input_up", {
|
||||
controller_type: "keyboard",
|
||||
button: button,
|
||||
isTouch: true
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a node to a specific key to simulate keyboard events on touch.
|
||||
*
|
||||
* @param node - The DOM element to bind the key to.
|
||||
* @param key - The key to simulate.
|
||||
* @param events - The event emitter for handling input events.
|
||||
*
|
||||
* @remarks
|
||||
* This function binds touch events to a node to simulate 'keydown' and 'keyup' keyboard events.
|
||||
* It adds the key to the keys map and tracks the keydown state. When a touch starts, it simulates
|
||||
* a 'keydown' event and adds an 'active' class to the node. When the touch ends, it simulates a 'keyup'
|
||||
* event, removes the keydown state, and removes the 'active' class from the node and the last touched element.
|
||||
*/
|
||||
function bindKey(node: HTMLElement, key: string, events) {
|
||||
keys.set(node.id, key);
|
||||
|
||||
node.addEventListener("touchstart", event => {
|
||||
event.preventDefault();
|
||||
simulateKeyboardEvent("keydown", key, events);
|
||||
keysDown.set(event.target["id"], node.id);
|
||||
node.classList.add("active");
|
||||
});
|
||||
|
||||
node.addEventListener("touchend", event => {
|
||||
event.preventDefault();
|
||||
|
||||
const pressedKey = keysDown.get(event.target["id"]);
|
||||
if (pressedKey && keys.has(pressedKey)) {
|
||||
const key = keys.get(pressedKey);
|
||||
simulateKeyboardEvent("keyup", key, events);
|
||||
}
|
||||
|
||||
keysDown.delete(event.target["id"]);
|
||||
node.classList.remove("active");
|
||||
|
||||
if (lastTouchedId) {
|
||||
document.getElementById(lastTouchedId).classList.remove("active");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link https://stackoverflow.com/a/39778831/4622620|Source}
|
||||
*
|
||||
* Prevent zoom on specified element
|
||||
* @param {HTMLElement} element
|
||||
*/
|
||||
function preventElementZoom(element: HTMLElement): void {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
element.addEventListener("touchstart", (event: TouchEvent) => {
|
||||
|
||||
if (!(event.currentTarget instanceof HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentTouchTimeStamp = event.timeStamp;
|
||||
const previousTouchTimeStamp = Number(event.currentTarget.dataset.lastTouchTimeStamp) || currentTouchTimeStamp;
|
||||
const timeStampDifference = currentTouchTimeStamp - previousTouchTimeStamp;
|
||||
const fingers = event.touches.length;
|
||||
event.currentTarget.dataset.lastTouchTimeStamp = String(currentTouchTimeStamp);
|
||||
|
||||
if (!timeStampDifference || timeStampDifference > 500 || fingers > 1) {
|
||||
return;
|
||||
} // not double-tap
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (event.target instanceof HTMLElement) {
|
||||
event.target.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import ConfirmUiHandler from "./confirm-ui-handler";
|
||||
import { StatsContainer } from "./stats-container";
|
||||
import { TextStyle, addBBCodeTextObject, addTextObject, getTextColor } from "./text";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import { DexAttr } from "../system/game-data";
|
||||
|
||||
interface LanguageSetting {
|
||||
infoContainerTextSize: string;
|
||||
@ -47,19 +48,24 @@ const languageSettings: { [key: string]: LanguageSetting } = {
|
||||
export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
|
||||
private readonly infoWindowWidth = 104;
|
||||
|
||||
private pokemonGenderLabelText: Phaser.GameObjects.Text;
|
||||
private pokemonFormLabelText: Phaser.GameObjects.Text;
|
||||
private pokemonFormText: Phaser.GameObjects.Text;
|
||||
private pokemonGenderText: Phaser.GameObjects.Text;
|
||||
private pokemonGenderNewText: Phaser.GameObjects.Text;
|
||||
private pokemonAbilityLabelText: Phaser.GameObjects.Text;
|
||||
private pokemonAbilityText: Phaser.GameObjects.Text;
|
||||
private pokemonNatureLabelText: Phaser.GameObjects.Text;
|
||||
private pokemonNatureText: BBCodeText;
|
||||
private pokemonShinyIcon: Phaser.GameObjects.Image;
|
||||
private pokemonShinyNewIcon: Phaser.GameObjects.Text;
|
||||
private pokemonFusionShinyIcon: Phaser.GameObjects.Image;
|
||||
private pokemonMovesContainer: Phaser.GameObjects.Container;
|
||||
private pokemonMovesContainers: Phaser.GameObjects.Container[];
|
||||
private pokemonMoveBgs: Phaser.GameObjects.NineSlice[];
|
||||
private pokemonMoveLabels: Phaser.GameObjects.Text[];
|
||||
|
||||
private numCharsBeforeCutoff = 16;
|
||||
|
||||
private initialX: number;
|
||||
private movesContainerInitialX: number;
|
||||
|
||||
@ -137,34 +143,44 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
|
||||
// The font size should be set by language
|
||||
const infoContainerTextSize = textSettings?.infoContainerTextSize || "64px";
|
||||
|
||||
this.pokemonGenderLabelText = addTextObject(this.scene, infoContainerLabelXPos, 18, i18next.t("pokemonInfoContainer:gender"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonGenderLabelText.setOrigin(1, 0);
|
||||
this.pokemonGenderLabelText.setVisible(false);
|
||||
this.pokemonGenderLabelText.setName("text-pkmn-gender-label");
|
||||
this.add(this.pokemonGenderLabelText);
|
||||
this.pokemonFormLabelText = addTextObject(this.scene, infoContainerLabelXPos, 19, i18next.t("pokemonInfoContainer:form"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonFormLabelText.setOrigin(1, 0);
|
||||
this.pokemonFormLabelText.setVisible(false);
|
||||
this.add(this.pokemonFormLabelText);
|
||||
|
||||
this.pokemonGenderText = addTextObject(this.scene, infoContainerTextXPos, 18, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonFormText = addTextObject(this.scene, infoContainerTextXPos, 19, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonFormText.setOrigin(0, 0);
|
||||
this.pokemonFormText.setVisible(false);
|
||||
this.add(this.pokemonFormText);
|
||||
|
||||
this.pokemonGenderText = addTextObject(this.scene, -42, -61, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonGenderText.setOrigin(0, 0);
|
||||
this.pokemonGenderText.setVisible(false);
|
||||
this.pokemonGenderText.setName("text-pkmn-gender");
|
||||
this.add(this.pokemonGenderText);
|
||||
|
||||
this.pokemonAbilityLabelText = addTextObject(this.scene, infoContainerLabelXPos, 28, i18next.t("pokemonInfoContainer:ability"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonGenderNewText = addTextObject(this.scene, -36, -61, "", TextStyle.WINDOW, { fontSize: "64px" });
|
||||
this.pokemonGenderNewText.setOrigin(0, 0);
|
||||
this.pokemonGenderNewText.setVisible(false);
|
||||
this.pokemonGenderNewText.setName("text-pkmn-new-gender");
|
||||
this.add(this.pokemonGenderNewText);
|
||||
|
||||
this.pokemonAbilityLabelText = addTextObject(this.scene, infoContainerLabelXPos, 29, i18next.t("pokemonInfoContainer:ability"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonAbilityLabelText.setOrigin(1, 0);
|
||||
this.pokemonAbilityLabelText.setName("text-pkmn-ability-label");
|
||||
this.add(this.pokemonAbilityLabelText);
|
||||
|
||||
this.pokemonAbilityText = addTextObject(this.scene, infoContainerTextXPos, 28, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonAbilityText = addTextObject(this.scene, infoContainerTextXPos, 29, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonAbilityText.setOrigin(0, 0);
|
||||
this.pokemonAbilityText.setName("text-pkmn-ability");
|
||||
this.add(this.pokemonAbilityText);
|
||||
|
||||
this.pokemonNatureLabelText = addTextObject(this.scene, infoContainerLabelXPos, 38, i18next.t("pokemonInfoContainer:nature"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonNatureLabelText = addTextObject(this.scene, infoContainerLabelXPos, 39, i18next.t("pokemonInfoContainer:nature"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonNatureLabelText.setOrigin(1, 0);
|
||||
this.pokemonNatureLabelText.setName("text-pkmn-nature-label");
|
||||
this.add(this.pokemonNatureLabelText);
|
||||
|
||||
this.pokemonNatureText = addBBCodeTextObject(this.scene, infoContainerTextXPos, 38, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize, lineSpacing: 3, maxLines: 2 });
|
||||
this.pokemonNatureText = addBBCodeTextObject(this.scene, infoContainerTextXPos, 39, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize, lineSpacing: 3, maxLines: 2 });
|
||||
this.pokemonNatureText.setOrigin(0, 0);
|
||||
this.pokemonNatureText.setName("text-pkmn-nature");
|
||||
this.add(this.pokemonNatureText);
|
||||
@ -176,6 +192,12 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
|
||||
this.pokemonShinyIcon.setName("img-pkmn-shiny-icon");
|
||||
this.add(this.pokemonShinyIcon);
|
||||
|
||||
this.pokemonShinyNewIcon = addTextObject(this.scene, this.pokemonShinyIcon.x + 12, this.pokemonShinyIcon.y, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize });
|
||||
this.pokemonShinyNewIcon.setOrigin(0, 0);
|
||||
this.pokemonShinyNewIcon.setName("text-pkmn-shiny-new-icon");
|
||||
this.add(this.pokemonShinyNewIcon);
|
||||
this.pokemonShinyNewIcon.setVisible(false);
|
||||
|
||||
this.pokemonFusionShinyIcon = this.scene.add.image(this.pokemonShinyIcon.x, this.pokemonShinyIcon.y, "shiny_star_2");
|
||||
this.pokemonFusionShinyIcon.setOrigin(0, 0);
|
||||
this.pokemonFusionShinyIcon.setScale(0.75);
|
||||
@ -187,23 +209,87 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
|
||||
|
||||
show(pokemon: Pokemon, showMoves: boolean = false, speedMultiplier: number = 1): Promise<void> {
|
||||
return new Promise<void>(resolve => {
|
||||
const caughtAttr = BigInt(pokemon.scene.gameData.dexData[pokemon.species.speciesId].caughtAttr);
|
||||
if (pokemon.gender > Gender.GENDERLESS) {
|
||||
this.pokemonGenderText.setText(getGenderSymbol(pokemon.gender));
|
||||
this.pokemonGenderText.setColor(getGenderColor(pokemon.gender));
|
||||
this.pokemonGenderText.setShadowColor(getGenderColor(pokemon.gender, true));
|
||||
this.pokemonGenderLabelText.setVisible(true);
|
||||
this.pokemonGenderText.setVisible(true);
|
||||
|
||||
const newGender = BigInt(Math.pow(2, pokemon.gender)) * DexAttr.MALE;
|
||||
this.pokemonGenderNewText.setText("(+)");
|
||||
this.pokemonGenderNewText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme));
|
||||
this.pokemonGenderNewText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, this.scene.uiTheme));
|
||||
this.pokemonGenderNewText.setVisible((newGender & caughtAttr) === BigInt(0));
|
||||
} else {
|
||||
this.pokemonGenderText.setVisible(false);
|
||||
}
|
||||
|
||||
if (pokemon.species.forms?.[pokemon.formIndex]?.formName) {
|
||||
this.pokemonFormLabelText.setVisible(true);
|
||||
this.pokemonFormText.setVisible(true);
|
||||
const newForm = BigInt(Math.pow(2, pokemon.formIndex)) * DexAttr.DEFAULT_FORM;
|
||||
|
||||
if ((newForm & caughtAttr) === BigInt(0)) {
|
||||
this.pokemonFormLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme));
|
||||
this.pokemonFormLabelText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, this.scene.uiTheme));
|
||||
} else {
|
||||
this.pokemonFormLabelText.setColor(getTextColor(TextStyle.WINDOW, false, this.scene.uiTheme));
|
||||
this.pokemonFormLabelText.setShadowColor(getTextColor(TextStyle.WINDOW, true, this.scene.uiTheme));
|
||||
}
|
||||
|
||||
const formName = pokemon.species.forms?.[pokemon.formIndex]?.formName;
|
||||
this.pokemonFormText.setText(formName.length > this.numCharsBeforeCutoff ? formName.substring(0, this.numCharsBeforeCutoff - 3) + "..." : formName);
|
||||
if (formName.length > this.numCharsBeforeCutoff) {
|
||||
this.pokemonFormText.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.pokemonFormText.width, this.pokemonFormText.height), Phaser.Geom.Rectangle.Contains);
|
||||
this.pokemonFormText.on("pointerover", () => (this.scene as BattleScene).ui.showTooltip(null, pokemon.species.forms?.[pokemon.formIndex]?.formName, true));
|
||||
this.pokemonFormText.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip());
|
||||
} else {
|
||||
this.pokemonFormText.disableInteractive();
|
||||
}
|
||||
} else {
|
||||
this.pokemonFormLabelText.setVisible(false);
|
||||
this.pokemonFormText.setVisible(false);
|
||||
this.pokemonFormText.disableInteractive();
|
||||
}
|
||||
|
||||
const abilityTextStyle = pokemon.abilityIndex === (pokemon.species.ability2 ? 2 : 1) ? TextStyle.MONEY : TextStyle.WINDOW;
|
||||
this.pokemonAbilityText.setText(pokemon.getAbility(true).name);
|
||||
this.pokemonAbilityText.setColor(getTextColor(abilityTextStyle, false, this.scene.uiTheme));
|
||||
this.pokemonAbilityText.setShadowColor(getTextColor(abilityTextStyle, true, this.scene.uiTheme));
|
||||
|
||||
/**
|
||||
* If the opposing Pokemon only has 1 normal ability and is using the hidden ability it should have the same behavior
|
||||
* if it had 2 normal abilities. This code checks if that is the case and uses the correct opponent Pokemon abilityIndex (2)
|
||||
* for calculations so it aligns with where the hidden ability is stored in the starter data's abilityAttr (4)
|
||||
*/
|
||||
const opponentPokemonOneNormalAbility = (pokemon.species.getAbilityCount() === 2);
|
||||
const opponentPokemonAbilityIndex = (opponentPokemonOneNormalAbility && pokemon.abilityIndex === 1) ? 2 : pokemon.abilityIndex;
|
||||
const opponentPokemonAbilityAttr = Math.pow(2, opponentPokemonAbilityIndex);
|
||||
|
||||
const rootFormHasHiddenAbility = pokemon.scene.gameData.starterData[pokemon.species.getRootSpeciesId()].abilityAttr & opponentPokemonAbilityAttr;
|
||||
|
||||
if (!rootFormHasHiddenAbility) {
|
||||
this.pokemonAbilityLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme));
|
||||
this.pokemonAbilityLabelText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, this.scene.uiTheme));
|
||||
} else {
|
||||
this.pokemonAbilityLabelText.setColor(getTextColor(TextStyle.WINDOW, false, this.scene.uiTheme));
|
||||
this.pokemonAbilityLabelText.setShadowColor(getTextColor(TextStyle.WINDOW, true, this.scene.uiTheme));
|
||||
}
|
||||
|
||||
this.pokemonNatureText.setText(getNatureName(pokemon.getNature(), true, false, false, this.scene.uiTheme));
|
||||
|
||||
const dexNatures = pokemon.scene.gameData.dexData[pokemon.species.speciesId].natureAttr;
|
||||
const newNature = Math.pow(2, pokemon.nature + 1);
|
||||
|
||||
if (!(dexNatures & newNature)) {
|
||||
this.pokemonNatureLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme));
|
||||
this.pokemonNatureLabelText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, this.scene.uiTheme));
|
||||
} else {
|
||||
this.pokemonNatureLabelText.setColor(getTextColor(TextStyle.WINDOW, false, this.scene.uiTheme));
|
||||
this.pokemonNatureLabelText.setShadowColor(getTextColor(TextStyle.WINDOW, true, this.scene.uiTheme));
|
||||
}
|
||||
|
||||
const isFusion = pokemon.isFusion();
|
||||
const doubleShiny = isFusion && pokemon.shiny && pokemon.fusionShiny;
|
||||
const baseVariant = !doubleShiny ? pokemon.getVariant() : pokemon.variant;
|
||||
@ -217,6 +303,15 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
|
||||
: "";
|
||||
this.pokemonShinyIcon.on("pointerover", () => (this.scene as BattleScene).ui.showTooltip(null, `Shiny${shinyDescriptor ? ` (${shinyDescriptor})` : ""}`, true));
|
||||
this.pokemonShinyIcon.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip());
|
||||
|
||||
const newShiny = BigInt(Math.pow(2, (pokemon.shiny ? 1 : 0)));
|
||||
const newVariant = BigInt(Math.pow(2, pokemon.variant + 4));
|
||||
|
||||
this.pokemonShinyNewIcon.setText("(+)");
|
||||
this.pokemonShinyNewIcon.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme));
|
||||
this.pokemonShinyNewIcon.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, this.scene.uiTheme));
|
||||
const newShinyOrVariant = ((newShiny & caughtAttr) === BigInt(0)) || ((newVariant & caughtAttr) === BigInt(0));
|
||||
this.pokemonShinyNewIcon.setVisible(!!newShinyOrVariant);
|
||||
}
|
||||
|
||||
this.pokemonFusionShinyIcon.setPosition(this.pokemonShinyIcon.x, this.pokemonShinyIcon.y);
|
||||
|
@ -4,7 +4,10 @@ import { Stat, getStatName } from "../data/pokemon-stat";
|
||||
import { TextStyle, addBBCodeTextObject, addTextObject, getTextColor } from "./text";
|
||||
|
||||
const ivChartSize = 24;
|
||||
const ivChartStatCoordMultipliers = [ [ 0, -1 ], [ 0.825, -0.5 ], [ 0.825, 0.5 ], [ -0.825, -0.5 ], [ -0.825, 0.5 ], [ 0, 1 ] ];
|
||||
const ivChartStatCoordMultipliers = [[0, -1], [0.825, -0.5], [0.825, 0.5], [-0.825, -0.5], [-0.825, 0.5], [0, 1]];
|
||||
const speedLabelOffset = -3;
|
||||
const sideLabelOffset = 1;
|
||||
const ivLabelOffset = [0, sideLabelOffset, -sideLabelOffset, sideLabelOffset, -sideLabelOffset, speedLabelOffset];
|
||||
const ivChartStatIndexes = [0,1,2,5,4,3]; // swap special attack and speed
|
||||
const defaultIvChartData = new Array(12).fill(null).map(() => 0);
|
||||
|
||||
@ -51,7 +54,7 @@ export class StatsContainer extends Phaser.GameObjects.Container {
|
||||
this.ivStatValueTexts = [];
|
||||
|
||||
new Array(6).fill(null).map((_, i: integer) => {
|
||||
const statLabel = addTextObject(this.scene, ivChartBg.x + (ivChartSize) * ivChartStatCoordMultipliers[i][0] * 1.325, ivChartBg.y + (ivChartSize) * ivChartStatCoordMultipliers[i][1] * 1.325 - 4, getStatName(i as Stat), TextStyle.TOOLTIP_CONTENT);
|
||||
const statLabel = addTextObject(this.scene, ivChartBg.x + (ivChartSize) * ivChartStatCoordMultipliers[i][0] * 1.325, ivChartBg.y + (ivChartSize) * ivChartStatCoordMultipliers[i][1] * 1.325 - 4 + ivLabelOffset[i], getStatName(i as Stat), TextStyle.TOOLTIP_CONTENT);
|
||||
statLabel.setOrigin(0.5);
|
||||
|
||||
this.ivStatValueTexts[i] = addBBCodeTextObject(this.scene, statLabel.x, statLabel.y + 8, "0", TextStyle.TOOLTIP_CONTENT);
|
||||
|