Compare commits
971 Commits
2024-09-27
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
965f92ba0f | ||
|
4de7858f00 | ||
|
e3c8e3141e | ||
|
30b2f95a30 | ||
|
1d669719a0 | ||
|
663e047af8 | ||
|
80ae42d3ba | ||
|
59a00e0af3 | ||
|
18ba33e6f0 | ||
|
a9869569fa | ||
|
a26a930980 | ||
|
ddc160b862 | ||
|
a98f897591 | ||
|
999cbf911e | ||
|
b803f6f18a | ||
|
e053ead67c | ||
|
8410aee3a1 | ||
|
7756f35d79 | ||
|
dda94c7b22 | ||
|
10fced4f03 | ||
|
9ae969117b | ||
|
22f5ed1232 | ||
|
4376a22a7c | ||
|
998619e7e5 | ||
|
0c48fff14b | ||
|
84192cd323 | ||
|
a1d736b950 | ||
|
30ba53894e | ||
|
9b1a222935 | ||
|
d790b30a30 | ||
|
6c6821b47d | ||
|
e7f0ea624b | ||
|
09e38bad39 | ||
|
0712f86462 | ||
|
b183f26330 | ||
|
efebb9c9cf | ||
|
5a58abfddf | ||
|
530b2b8a00 | ||
|
cf1367cece | ||
|
fa6c51d1e2 | ||
|
5ba294ffee | ||
|
4aa0eac5aa | ||
|
3ba1ed3fb4 | ||
|
4f541a8dce | ||
|
e677e2725e | ||
|
4203513db2 | ||
|
b42b2f6752 | ||
|
3161461b6c | ||
|
92f1cfdd50 | ||
|
ae25a70b4d | ||
|
a3039ef6a6 | ||
|
bd913a201c | ||
|
7547b37e85 | ||
|
e3028c6219 | ||
|
fa774268ca | ||
|
c31bd9ef61 | ||
|
b353b0de62 | ||
|
9e433c85a9 | ||
|
b5cfa88455 | ||
|
04bfaf901a | ||
|
8dd6ba29a1 | ||
|
1042b528ec | ||
|
a5311779b4 | ||
|
9283be652d | ||
|
cedeaf8668 | ||
|
24939ad2e0 | ||
|
3cb3fd15ec | ||
|
a8382d71fc | ||
|
5fc379c405 | ||
|
cdeb143643 | ||
|
bf0abd3ddc | ||
|
75d01adf9a | ||
|
3a89b7bb75 | ||
|
8f0eee9c4c | ||
|
6d90649b92 | ||
|
fa86ea3214 | ||
|
7a9fc3fc8d | ||
|
3af1bdbcff | ||
|
8eeec9511b | ||
|
da3b2e0edd | ||
|
bee06410dd | ||
|
d3a1b42628 | ||
|
ff7860413a | ||
|
a81cac547b | ||
|
cdcc338afd | ||
|
fd5612e253 | ||
|
9187edcf6c | ||
|
ef9a867e67 | ||
|
84a2ce979f | ||
|
1e8fc076a7 | ||
|
43d73b01b1 | ||
|
9a9759d31c | ||
|
34670fd921 | ||
|
217fbe027a | ||
|
69df76dd88 | ||
|
a7479c8eb6 | ||
|
89a9d55d3c | ||
|
c87598d01d | ||
|
c6e7dd660e | ||
|
6460d46a5d | ||
|
ab7d010a17 | ||
|
423bab1057 | ||
|
a036f865f0 | ||
|
0a48726e70 | ||
|
a288de700d | ||
|
42f291eab3 | ||
|
38d75897bb | ||
|
30e74eaaa8 | ||
|
6dc2a7fddc | ||
|
793d89fa24 | ||
|
6ea5b4fa9d | ||
|
75400a39ed | ||
|
5de567a3db | ||
|
c7265543bd | ||
|
b49c994d2d | ||
|
389ad6ceb6 | ||
|
b848777880 | ||
|
110fd2f0a1 | ||
|
aadb57ab75 | ||
|
be6a117b1e | ||
|
0da56cda9f | ||
|
b89b945b11 | ||
|
d0be6a9274 | ||
|
2cf0b51299 | ||
|
8515cadd77 | ||
|
bda286cebb | ||
|
65294f408e | ||
|
5854b21da0 | ||
|
a6e87c8438 | ||
|
54ce58411b | ||
|
82cd492117 | ||
|
b8b101119c | ||
|
3a46aae687 | ||
|
eef8367caf | ||
|
45a2f42602 | ||
|
b2bab46e1c | ||
|
8d311e65cf | ||
|
ae588ebff9 | ||
|
efad0d1324 | ||
|
18c4dddcf0 | ||
|
ff44cbfa97 | ||
|
4740b593a0 | ||
|
3ec8f236f9 | ||
|
8216a379bf | ||
|
b41eee3c7f | ||
|
c82e01eed3 | ||
|
15e535a1a0 | ||
|
f9ff4abfb0 | ||
|
6f56dce771 | ||
|
81f424dc71 | ||
|
1a7442511c | ||
|
787feceb14 | ||
|
b3a4c75c06 | ||
|
2c2a34cfaf | ||
|
31835e6d53 | ||
|
1171656d12 | ||
|
17a56cc6c1 | ||
|
cb5deb408f | ||
|
1b79d1f832 | ||
|
0479b9dfcc | ||
|
1e6ceb5581 | ||
|
fdf8c1a695 | ||
|
46d234983c | ||
|
5318d717b3 | ||
|
9e4162d429 | ||
|
420c2e37c2 | ||
|
e31bf91223 | ||
|
b364bb1899 | ||
|
7dfd8e72cc | ||
|
68f10dc199 | ||
|
7b38596a12 | ||
|
333975017f | ||
|
d0703e0e0b | ||
|
4c8f81bb09 | ||
|
c6721521ab | ||
|
db7ed43ad7 | ||
|
a7394130a7 | ||
|
cf1616212c | ||
|
7f4b37a36f | ||
|
2773354193 | ||
|
951d8b633d | ||
|
d92bf29030 | ||
|
70ba974348 | ||
|
5416c76ecb | ||
|
4a4e766135 | ||
|
5217703d2b | ||
|
1229bfe004 | ||
|
7d6b375f6f | ||
|
6477be99f5 | ||
|
13b118454c | ||
|
a975192cf4 | ||
|
6538eddf91 | ||
|
318b0c25d8 | ||
|
fd40bb50e9 | ||
|
95194ce8f1 | ||
|
f417c0915e | ||
|
136ea70a6e | ||
|
4afac11814 | ||
|
3d9aea7d71 | ||
|
5685220dda | ||
|
16bce25333 | ||
|
efa3662099 | ||
|
6add614e1c | ||
|
7e4151f1ef | ||
|
51f765d67a | ||
|
111390631d | ||
|
28234e577e | ||
|
d2ffc12d65 | ||
|
05691970e2 | ||
|
b33d95d27d | ||
|
66bc83fce4 | ||
|
ba1fa85045 | ||
|
451b1f6b08 | ||
|
9c13fa5f80 | ||
|
2ad030ec16 | ||
|
27a1638243 | ||
|
4f19e4a126 | ||
|
25b9fa7933 | ||
|
a727375730 | ||
|
5f01caffae | ||
|
fac20ca97a | ||
|
4a560d7185 | ||
|
4149d3600a | ||
|
35e733e87a | ||
|
b838d5f775 | ||
|
f09c77c81b | ||
|
188647d2e5 | ||
|
46d110e705 | ||
|
0ea8edcf75 | ||
|
19c61a041f | ||
|
eb12b8c692 | ||
|
d955051730 | ||
|
5fdc133955 | ||
|
6316218bd3 | ||
|
db850c79cd | ||
|
0b1f324f97 | ||
|
938f1b8756 | ||
|
f911ffc266 | ||
|
ead1bc6cce | ||
|
bba7c1610d | ||
|
f78015d757 | ||
|
443264a3ea | ||
|
f3141280c9 | ||
|
7f72794d23 | ||
|
37e51e9657 | ||
|
dbc8ac26af | ||
|
40e1e7fd4e | ||
|
817095d895 | ||
|
1e876ec595 | ||
|
4b8f1df8cd | ||
|
d0a9672e91 | ||
|
87b78e6b70 | ||
|
c792d5e704 | ||
|
66965bf7e2 | ||
|
17e71a1b8a | ||
|
b3c7300c37 | ||
|
585f040057 | ||
|
3f887988a6 | ||
|
a1a6b0dd5a | ||
|
b2848af899 | ||
|
b1d494eadb | ||
|
3b99d3aea2 | ||
|
d9288a7908 | ||
|
a5ed9c5191 | ||
|
02ae7952ad | ||
|
1d7f916240 | ||
|
7aa5649aa8 | ||
|
e8e0041ed0 | ||
|
4e1ee9e50b | ||
|
dc46cf6d05 | ||
|
85c39754c4 | ||
|
f3f43f4a44 | ||
|
b298138157 | ||
|
929392fe8b | ||
|
572556b7b9 | ||
|
7f226df8d6 | ||
|
408b66f913 | ||
|
7455360824 | ||
|
c977bc86c1 | ||
|
60a4db7059 | ||
|
e73dbe9861 | ||
|
da68cf15c6 | ||
|
fdc5e7daea | ||
|
7a9b1e5033 | ||
|
ba617ad91b | ||
|
6595966478 | ||
|
9544973f1f | ||
|
f185039474 | ||
|
632caff2f3 | ||
|
c890b7ae46 | ||
|
1882e96ec5 | ||
|
6181afc6d2 | ||
|
ff4184e23f | ||
|
cabcfcbd39 | ||
|
5e469620ef | ||
|
6f686a05e3 | ||
|
73afb35c4d | ||
|
659bc82676 | ||
|
882b965da1 | ||
|
b50d2c0783 | ||
|
8f280bec49 | ||
|
04ac5c3762 | ||
|
5c73a1ea46 | ||
|
c7df847e66 | ||
|
89e8085c39 | ||
|
d16197e950 | ||
|
b348626ec2 | ||
|
7cc5f40af8 | ||
|
118bdcc49e | ||
|
9b2f649078 | ||
|
942bcacb56 | ||
|
13429446d3 | ||
|
b33ffb29b3 | ||
|
5941cfb001 | ||
|
9701f27c63 | ||
|
49edc39bda | ||
|
2b535622ac | ||
|
078c3d00ce | ||
|
9ff20af8b7 | ||
|
922a17048c | ||
|
3124aeb810 | ||
|
02edfb673e | ||
|
f902716837 | ||
|
32ae72150f | ||
|
d12aa635af | ||
|
de148277ea | ||
|
13373a6391 | ||
|
905fec92e9 | ||
|
035aed3e85 | ||
|
85f8c59036 | ||
|
71f644c453 | ||
|
883bf45bc0 | ||
|
6e8a4b287c | ||
|
b9a853ed2e | ||
|
92ee9d06ca | ||
|
ca5e578954 | ||
|
aa3f924633 | ||
|
2cc0ac90f8 | ||
|
870bff0e6e | ||
|
7a9bede38d | ||
|
8cc5f650f3 | ||
|
d11f02aa3d | ||
|
c81d9b6a89 | ||
|
88a5c9d416 | ||
|
d14f71d27a | ||
|
b95bedce7a | ||
|
4128d09a1d | ||
|
6857cd459c | ||
|
cc7e1af827 | ||
|
0cb3a28dfa | ||
|
5996f8c6eb | ||
|
9fb654ce73 | ||
|
8f15788b39 | ||
|
1c192d434b | ||
|
9d03004dd3 | ||
|
3ab75b297b | ||
|
095634fe6d | ||
|
cefd92bee8 | ||
|
eeeb4171b1 | ||
|
a51a504155 | ||
|
bd288ad862 | ||
|
b1b71dbd6d | ||
|
7a015e094f | ||
|
180a9cc054 | ||
|
39f2fdf4ff | ||
|
e4ce822ce6 | ||
|
97aeceab58 | ||
|
bec73fd8d3 | ||
|
6a4c6f1c89 | ||
|
13d9140340 | ||
|
5072460f4c | ||
|
ed8d162125 | ||
|
073a36a33e | ||
|
2d067ec7ce | ||
|
3a4c8eb92e | ||
|
c3045b58b6 | ||
|
a346318f9d | ||
|
7ec0dba74b | ||
|
9cc1b17745 | ||
|
7fafccf8de | ||
|
8864347cb0 | ||
|
5fa77b7177 | ||
|
fd066ac9b2 | ||
|
3018a747bd | ||
|
62bacf52a7 | ||
|
c7ee0173f6 | ||
|
a8bf385899 | ||
|
200d52cd99 | ||
|
9e1cc1f188 | ||
|
7463bedbfd | ||
|
af91ea85c3 | ||
|
ed8ef48068 | ||
|
db22354057 | ||
|
e1327c1d2d | ||
|
0913c77140 | ||
|
4361aa089b | ||
|
90d32b886c | ||
|
4bc617bd5f | ||
|
ef11527b9a | ||
|
5b1950a1ae | ||
|
4d5f9cecf1 | ||
|
8f496ee226 | ||
|
8555ef7cb7 | ||
|
7b9d1d6570 | ||
|
77fbcc70ef | ||
|
727bf0d74d | ||
|
d159901ea1 | ||
|
8f498f1197 | ||
|
f68a833fcf | ||
|
7611061378 | ||
|
5ad8f18950 | ||
|
1b16825a50 | ||
|
3fd5414f5c | ||
|
dcd1636338 | ||
|
6acd15970e | ||
|
d629bf12ab | ||
|
f1283ad1c8 | ||
|
be0f3b2ab3 | ||
|
595413edd7 | ||
|
7199aee9ad | ||
|
5743751e5c | ||
|
f087162eeb | ||
|
b483aa0465 | ||
|
ce8b5752c4 | ||
|
03011c4601 | ||
|
195a3936b3 | ||
|
5045b637ff | ||
|
7fea8603f3 | ||
|
b31d5fd23e | ||
|
5296966f70 | ||
|
702a6ba482 | ||
|
60b27f4f62 | ||
|
f5ef4a5da9 | ||
|
42c4ca27e6 | ||
|
abf9c83607 | ||
|
de5aba3d5e | ||
|
20ed4db88b | ||
|
e75ddfa975 | ||
|
8012a1b559 | ||
|
3daa9054f3 | ||
|
f77bfc8367 | ||
|
c5968d52ce | ||
|
612e6a25c1 | ||
|
366c88517c | ||
|
7cd3217114 | ||
|
a941533a13 | ||
|
e29b8937f2 | ||
|
090a60dfba | ||
|
66024c9bcd | ||
|
db50091f12 | ||
|
e6340de046 | ||
|
f38393e64f | ||
|
66c70b07a7 | ||
|
6e0c8dba88 | ||
|
10502b777c | ||
|
280c552d6d | ||
|
a46d59b031 | ||
|
345329a31e | ||
|
986fbf3cf7 | ||
|
e06a9df4cd | ||
|
c80489460c | ||
|
c88c9337dd | ||
|
6c4dedb73e | ||
|
60990deaf2 | ||
|
f89e42fa7b | ||
|
a7aebb0823 | ||
|
e5691f11a4 | ||
|
c363d2b93c | ||
|
8d043a9f55 | ||
|
0d1dacbc7a | ||
|
91a4333e96 | ||
|
45f4bf3f13 | ||
|
3f71f79d7b | ||
|
f5c4a205b4 | ||
|
9db2fb1617 | ||
|
0d4d25b1e2 | ||
|
268dff2e3f | ||
|
0da777ff80 | ||
|
d318c9b9ae | ||
|
82da3c1b6d | ||
|
dcb4299aaf | ||
|
2cac113959 | ||
|
5c5622ed0e | ||
|
4cc62c9d76 | ||
|
4dc81c4e7b | ||
|
38e2abc059 | ||
|
da076d0aa2 | ||
|
7d6036df98 | ||
|
c2a7afc5ba | ||
|
db37dcc204 | ||
|
5539c5f21f | ||
|
6446e1b7ad | ||
|
5280f309f8 | ||
|
e5c0b11c02 | ||
|
a255e06d82 | ||
|
6b36e4ca06 | ||
|
861c2e9274 | ||
|
6c845cc0d3 | ||
|
a9ffe03804 | ||
|
974fe9f7d3 | ||
|
0989128deb | ||
|
4e0b10769b | ||
|
4c17ebd400 | ||
|
ec09186264 | ||
|
1e6c74abb8 | ||
|
e88b8aeb6f | ||
|
8d20b7b5e0 | ||
|
d14a5b8819 | ||
|
7563a6cd0b | ||
|
9fb9bb7e5d | ||
|
7ee573937e | ||
|
8d11313458 | ||
|
ec68ec2066 | ||
|
2593d0206c | ||
|
8a2ae0a683 | ||
|
15f88fcc39 | ||
|
33982c311e | ||
|
f1c06a5476 | ||
|
706a23238c | ||
|
996ce5d986 | ||
|
1a57d3998f | ||
|
8685ec3c3c | ||
|
747656e8df | ||
|
9c29cdc63d | ||
|
134c6e928f | ||
|
d10b7c05f7 | ||
|
271e51be58 | ||
|
93fc779350 | ||
|
39283e373b | ||
|
d85aedbdfc | ||
|
d495c48716 | ||
|
f551c51413 | ||
|
ce30897c0a | ||
|
58b7f67ca8 | ||
|
05485aefdd | ||
|
f3256ec5d4 | ||
|
75e66b4099 | ||
|
46e1268a64 | ||
|
ab17df83c7 | ||
|
24f1fedcd0 | ||
|
ea3fbecfd3 | ||
|
ae2c9071e4 | ||
|
ca0522436a | ||
|
481616c2ad | ||
|
188664f389 | ||
|
c3641a370f | ||
|
ee6115f49d | ||
|
608a92b70c | ||
|
95c6f4cd52 | ||
|
d624733565 | ||
|
39b4d74e95 | ||
|
e2c6bec418 | ||
|
d2a3e4bb2d | ||
|
7ae216f0d6 | ||
|
d5f84cf3df | ||
|
6681a913fe | ||
|
001b61c1c7 | ||
|
f1e500400a | ||
|
3a3ebfb783 | ||
|
0107b1d47e | ||
|
f83ab00ce4 | ||
|
d3fafa2770 | ||
|
29087710b7 | ||
|
b0c347e20d | ||
|
d0db6a35d2 | ||
|
07b69c9485 | ||
|
197b264fb0 | ||
|
1be95e8a1a | ||
|
bfe0d9bb79 | ||
|
355e70328c | ||
|
ec5dadb4f4 | ||
|
206419c9f1 | ||
|
14902cdb60 | ||
|
1b6374f469 | ||
|
6946abadb8 | ||
|
8f884a7ef0 | ||
|
10e0f9f0de | ||
|
8457fb96fe | ||
|
f95a5d41cb | ||
|
6392ee857c | ||
|
e75fa0d16d | ||
|
82dad5568c | ||
|
e9d97db11b | ||
|
bbb6b46801 | ||
|
1953e8dbe9 | ||
|
ba28511046 | ||
|
0022972be9 | ||
|
6ef15eca4a | ||
|
29a079cfd3 | ||
|
806585f1a6 | ||
|
708e58d083 | ||
|
62e4a7ec54 | ||
|
cb719d99a5 | ||
|
f6f29f0f66 | ||
|
90c8c97437 | ||
|
dfde40f1ae | ||
|
5db3074e2c | ||
|
f2ef3620b5 | ||
|
22f4e747ab | ||
|
6d903440b4 | ||
|
757fe1a17c | ||
|
50a4669a26 | ||
|
dd72c5e189 | ||
|
c6e80de1be | ||
|
3ca0fdae6b | ||
|
2f377f26b7 | ||
|
e930536efe | ||
|
1607a694c3 | ||
|
0556e1ad50 | ||
|
282b0c8215 | ||
|
2b59a53285 | ||
|
fad29ffc51 | ||
|
37b8c337e1 | ||
|
7b06314940 | ||
|
9ce4d5eeca | ||
|
cef2f2adf7 | ||
|
d6854c4969 | ||
|
38d7a26053 | ||
|
80555be22c | ||
|
d5146a57b9 | ||
|
5fc41dfd16 | ||
|
5af2bcd5ec | ||
|
d1294caeb6 | ||
|
eef0183761 | ||
|
cd6cee860a | ||
|
b70bf0f4aa | ||
|
4d75d902d8 | ||
|
75a50be3ce | ||
|
5cc8013341 | ||
|
75af359154 | ||
|
5fed690187 | ||
|
3bf2059aaf | ||
|
5992564842 | ||
|
6733d81d11 | ||
|
34cb234159 | ||
|
a91d420eb4 | ||
|
9bc046fd64 | ||
|
4d341bf1fd | ||
|
6725164918 | ||
|
de0d97739e | ||
|
48dc5d0ee7 | ||
|
03b073f21f | ||
|
2b64ef6fc9 | ||
|
c86b6352bc | ||
|
a7fa593f79 | ||
|
8f053ea16f | ||
|
4c8a18690e | ||
|
bba5a87392 | ||
|
6442b8345f | ||
|
2d6dfc45a0 | ||
|
6eed6c24c2 | ||
|
b293797c99 | ||
|
c584dfafb7 | ||
|
a86afa6725 | ||
|
0c920ba195 | ||
|
dd904fe782 | ||
|
89a3edba1c | ||
|
33d8db73ef | ||
|
e825e308f9 | ||
|
6b58d51ea2 | ||
|
1867ac4a9e | ||
|
07f08877c1 | ||
|
ae8efeedf8 | ||
|
7dc4210f71 | ||
|
c2afac8b02 | ||
|
c22b48f903 | ||
|
4aff2ffa1d | ||
|
77b94bf45d | ||
|
360a897ed2 | ||
|
413f2b80c8 | ||
|
5e7d44abfd | ||
|
c535e928d8 | ||
|
eb3c0d731a | ||
|
5ca1fd5cfd | ||
|
ef7d860166 | ||
|
9273b4930d | ||
|
8326e3556b | ||
|
6dec84e39c | ||
|
b1138c1d70 | ||
|
f778bd5877 | ||
|
58912db8f1 | ||
|
640ac23741 | ||
|
d0d9eb78da | ||
|
0c521bbe08 | ||
|
162eea500d | ||
|
e45cb42f7e | ||
|
b6b756a162 | ||
|
6f3fd0f138 | ||
|
8e26db944d | ||
|
4802f512ff | ||
|
cebedd220b | ||
|
e5e3926176 | ||
|
6feb63484c | ||
|
6799594bbb | ||
|
efa9f119a0 | ||
|
f2a2281ff1 | ||
|
63ffab027d | ||
|
2968059814 | ||
|
b3a94e6a6b | ||
|
44a68a91ba | ||
|
265b3cb938 | ||
|
198ac2431d | ||
|
2bf8acea06 | ||
|
a763cd173d | ||
|
329e43ad48 | ||
|
c54d21c313 | ||
|
c6cc187c96 | ||
|
de4ec5e1cb | ||
|
00f7fd47df | ||
|
58d40b905a | ||
|
625b98a6fe | ||
|
4821df68f2 | ||
|
aa2c794910 | ||
|
2b91d9d259 | ||
|
b2fdb9fcd1 | ||
|
5601bb14ec | ||
|
4c5b83612b | ||
|
1f6dab069d | ||
|
9dae28f264 | ||
|
6b7efb444b | ||
|
4f733796c5 | ||
|
eb32545772 | ||
|
b79b643b31 | ||
|
198d3ce2a6 | ||
|
6fd3ba284c | ||
|
88789c685e | ||
|
543a97076b | ||
|
13841765f1 | ||
|
ab6d15ee8a | ||
|
433d4b4fc9 | ||
|
7a0c88e661 | ||
|
a70f0860e1 | ||
|
618dfbd324 | ||
|
3a767ed38a | ||
|
770f388c45 | ||
|
62f9f6dd32 | ||
|
c3d832aaca | ||
|
3f97c9e39f | ||
|
1619d512cf | ||
|
836b37f383 | ||
|
af473ba4ff | ||
|
87b7122b60 | ||
|
5e2dfa975a | ||
|
f0ae36de6c | ||
|
b17b1d6e7e | ||
|
f16309fd06 | ||
|
70ddc29e86 | ||
|
c31657d952 | ||
|
1474f8cf14 | ||
|
1659f57262 | ||
|
80a8c659ee | ||
|
c2d24d6e93 | ||
|
8169760e1e | ||
|
684fb93e39 | ||
|
abc9264b3d | ||
|
5755180279 | ||
|
5b9dfe17ad | ||
|
b3a0ca9475 | ||
|
15dedf06ed | ||
|
afe6d2900d | ||
|
fd1aa41d09 | ||
|
921d4fa18c | ||
|
f9fe59239e | ||
|
1cbe8b1505 | ||
|
65269f935f | ||
|
13ff80fb95 | ||
|
fb2d3e45d6 | ||
|
38a6bf07e3 | ||
|
13377806ff | ||
|
3241332a3c | ||
|
fe7d156d2d | ||
|
b4cc9d7892 | ||
|
5797f265a4 | ||
|
33f5f4c33b | ||
|
41380b39b9 | ||
|
dfb42e44a6 | ||
|
9a56f080db | ||
|
908784b011 | ||
|
a9a73863e8 | ||
|
78adade5c3 | ||
|
22865c010a | ||
|
4fb1f37baa | ||
|
61193562f1 | ||
|
4be0214d5a | ||
|
39362389c7 | ||
|
51b2a4d7fe | ||
|
61cf937cab | ||
|
f87ac116fa | ||
|
6418f46bf7 | ||
|
a50763cd89 | ||
|
414e0a5447 | ||
|
a2419c4fc3 | ||
|
a13550ec44 | ||
|
c7e9eaf435 | ||
|
958d79140c | ||
|
fd38ab4cb4 | ||
|
03025b2674 | ||
|
16b7194366 | ||
|
a0baf89297 | ||
|
1ad4f3b376 | ||
|
0fe57b44b5 | ||
|
96e5f2d763 | ||
|
5e7f2042fc | ||
|
181f59882a | ||
|
7066a15ceb | ||
|
c2eb9de9df | ||
|
467841d167 | ||
|
f7797603a1 | ||
|
966b07f62b | ||
|
f51814467a | ||
|
b76e54fe7f | ||
|
75a114a89f | ||
|
e6c06d57be | ||
|
39abac65be | ||
|
5c70ab238e | ||
|
de64fd7720 | ||
|
c5b3220b86 | ||
|
2f212f52eb | ||
|
85b8ca6467 | ||
|
afebecd43c | ||
|
d92d63e81f | ||
|
d5fee37868 | ||
|
3ea459746a | ||
|
1907824670 | ||
|
72c08e5cfd | ||
|
2caa09f246 | ||
|
c6ec01958c | ||
|
50ff6e703a | ||
|
093f3d90f5 | ||
|
c04d81bd65 | ||
|
1966335627 | ||
|
d01d856898 | ||
|
21b71595e0 | ||
|
d5f87bbea7 | ||
|
bb98bc2f8e | ||
|
e962ac1f18 | ||
|
e7a4d4055f | ||
|
676322e800 | ||
|
8981f0e7a8 | ||
|
e340abe75d | ||
|
8a355d500a | ||
|
470f9e4e19 | ||
|
391f38c3c8 | ||
|
8e7aea0f89 | ||
|
caf29e2ce3 | ||
|
ebb7612999 | ||
|
2ac688de4b | ||
|
b7eb95b761 | ||
|
cfb92b4e08 | ||
|
7645d5042d | ||
|
f0cc1fc88b | ||
|
89d7e7ea65 | ||
|
70b9a43c8b | ||
|
4f456339f4 | ||
|
80a784ac8d | ||
|
407cd65dcb | ||
|
3f63c147a3 | ||
|
5d0b361320 | ||
|
6ad5ba972c | ||
|
0996789ee6 | ||
|
ba7e26152e | ||
|
a778537cca | ||
|
64147e4414 | ||
|
51894d46c2 | ||
|
e9906ea229 | ||
|
52257def2f | ||
|
ca3cc3c9c6 | ||
|
f180b6070e | ||
|
ffe941d235 | ||
|
d2c579cf2a | ||
|
deb2035610 | ||
|
d8c914c768 | ||
|
39cebb76d0 | ||
|
57a967890a | ||
|
0ede7b057d | ||
|
6e10f6600f | ||
|
9bb6398385 | ||
|
a1ca7e632b | ||
|
0a4c12387b | ||
|
8980513a83 | ||
|
f5fa478eb8 | ||
|
a259ccfc34 | ||
|
c01fff49c4 | ||
|
1226ab37e1 | ||
|
a7157bbe9a | ||
|
f9691b872b | ||
|
c2c41d9be8 | ||
|
f629a3e453 | ||
|
e8f40c10c9 | ||
|
42b75e8440 | ||
|
f562a76332 | ||
|
c99df9712a | ||
|
1947472f1c | ||
|
d362456501 | ||
|
27537286b9 | ||
|
0bd4d6c86b | ||
|
75bd730c04 | ||
|
2c97b2bda2 | ||
|
22442d3aa0 | ||
|
2bc5f50154 | ||
|
a5db2e1d6d | ||
|
38c682cca7 | ||
|
db1e50dfd7 | ||
|
644c078a6c | ||
|
74ea358f18 | ||
|
9c56c15a6c | ||
|
af51c1f2f0 | ||
|
46c84155b3 | ||
|
76e25a6d6f | ||
|
c58b5e943b | ||
|
54efd44497 | ||
|
ea9e0c7909 | ||
|
8fc0d9a429 | ||
|
5f700590be | ||
|
831efeb6bf | ||
|
f634b7c044 | ||
|
ea261a039d | ||
|
8a2900ad29 | ||
|
7473c31c77 | ||
|
a6bcd6eeea | ||
|
c46507d49b | ||
|
5e151f5604 | ||
|
95386861bb | ||
|
160b730921 | ||
|
45f6b23309 | ||
|
145b80f491 | ||
|
8a8adad7fe | ||
|
e9ee2c1179 | ||
|
5a20416fd4 | ||
|
de9fdc5b9c | ||
|
d660c217b3 | ||
|
814aceebc9 | ||
|
bab5b31476 | ||
|
7d2df53c51 | ||
|
3d3460888a | ||
|
1bae87fa56 | ||
|
d8ee8ad821 | ||
|
79e172176d | ||
|
d99dbf4955 | ||
|
4c327e9e63 | ||
|
d620b5c7fa | ||
|
82111bc62d | ||
|
7339facae1 | ||
|
6d89ad9569 | ||
|
bcec819fa9 | ||
|
d0600125dd | ||
|
fd67096a6a | ||
|
2488bf805b | ||
|
4160aefd93 | ||
|
b43620b8c5 | ||
|
3976d115d8 | ||
|
6187830de7 | ||
|
3e8b3930a8 | ||
|
7bb49a3199 | ||
|
000b8d9b2b | ||
|
a69da4bc06 | ||
|
771b0edcb0 | ||
|
357056ebeb | ||
|
b1194cdfb6 | ||
|
8ce5de6d45 | ||
|
d87234504c | ||
|
3a5f3c39cd | ||
|
0464d8f666 | ||
|
f460f9a0e8 | ||
|
5d819aacf2 | ||
|
3def9fc15d | ||
|
2b3dbcc72f | ||
|
7eb755ca9c | ||
|
1b6593d242 | ||
|
c9664b66d3 | ||
|
2e7f6a2f4f |
@ -2,92 +2,86 @@
|
||||
module.exports = {
|
||||
forbidden: [
|
||||
{
|
||||
name: 'no-circular-at-runtime',
|
||||
severity: 'warn',
|
||||
name: "no-circular-at-runtime",
|
||||
severity: "warn",
|
||||
comment:
|
||||
'This dependency is part of a circular relationship. You might want to revise ' +
|
||||
'your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ',
|
||||
"This dependency is part of a circular relationship. You might want to revise " +
|
||||
"your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ",
|
||||
from: {},
|
||||
to: {
|
||||
circular: true,
|
||||
viaOnly: {
|
||||
dependencyTypesNot: [
|
||||
'type-only'
|
||||
]
|
||||
}
|
||||
}
|
||||
dependencyTypesNot: ["type-only"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'no-orphans',
|
||||
name: "no-orphans",
|
||||
comment:
|
||||
"This is an orphan module - it's likely not used (anymore?). Either use it or " +
|
||||
"remove it. If it's logical this module is an orphan (i.e. it's a config file), " +
|
||||
"add an exception for it in your dependency-cruiser configuration. By default " +
|
||||
"this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration " +
|
||||
"files (.d.ts), tsconfig.json and some of the babel and webpack configs.",
|
||||
severity: 'warn',
|
||||
severity: "warn",
|
||||
from: {
|
||||
orphan: true,
|
||||
pathNot: [
|
||||
'(^|/)[.][^/]+[.](?:js|cjs|mjs|ts|cts|mts|json)$', // dot files
|
||||
'[.]d[.]ts$', // TypeScript declaration files
|
||||
'(^|/)tsconfig[.]json$', // TypeScript config
|
||||
'(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$' // other configs
|
||||
]
|
||||
"(^|/)[.][^/]+[.](?:js|cjs|mjs|ts|cts|mts|json)$", // dot files
|
||||
"[.]d[.]ts$", // TypeScript declaration files
|
||||
"(^|/)tsconfig[.]json$", // TypeScript config
|
||||
"(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$", // other configs
|
||||
],
|
||||
},
|
||||
to: {},
|
||||
},
|
||||
{
|
||||
name: 'no-deprecated-core',
|
||||
name: "no-deprecated-core",
|
||||
comment:
|
||||
'A module depends on a node core module that has been deprecated. Find an alternative - these are ' +
|
||||
"A module depends on a node core module that has been deprecated. Find an alternative - these are " +
|
||||
"bound to exist - node doesn't deprecate lightly.",
|
||||
severity: 'warn',
|
||||
severity: "warn",
|
||||
from: {},
|
||||
to: {
|
||||
dependencyTypes: [
|
||||
'core'
|
||||
],
|
||||
dependencyTypes: ["core"],
|
||||
path: [
|
||||
'^v8/tools/codemap$',
|
||||
'^v8/tools/consarray$',
|
||||
'^v8/tools/csvparser$',
|
||||
'^v8/tools/logreader$',
|
||||
'^v8/tools/profile_view$',
|
||||
'^v8/tools/profile$',
|
||||
'^v8/tools/SourceMap$',
|
||||
'^v8/tools/splaytree$',
|
||||
'^v8/tools/tickprocessor-driver$',
|
||||
'^v8/tools/tickprocessor$',
|
||||
'^node-inspect/lib/_inspect$',
|
||||
'^node-inspect/lib/internal/inspect_client$',
|
||||
'^node-inspect/lib/internal/inspect_repl$',
|
||||
'^async_hooks$',
|
||||
'^punycode$',
|
||||
'^domain$',
|
||||
'^constants$',
|
||||
'^sys$',
|
||||
'^_linklist$',
|
||||
'^_stream_wrap$'
|
||||
"^v8/tools/codemap$",
|
||||
"^v8/tools/consarray$",
|
||||
"^v8/tools/csvparser$",
|
||||
"^v8/tools/logreader$",
|
||||
"^v8/tools/profile_view$",
|
||||
"^v8/tools/profile$",
|
||||
"^v8/tools/SourceMap$",
|
||||
"^v8/tools/splaytree$",
|
||||
"^v8/tools/tickprocessor-driver$",
|
||||
"^v8/tools/tickprocessor$",
|
||||
"^node-inspect/lib/_inspect$",
|
||||
"^node-inspect/lib/internal/inspect_client$",
|
||||
"^node-inspect/lib/internal/inspect_repl$",
|
||||
"^async_hooks$",
|
||||
"^punycode$",
|
||||
"^domain$",
|
||||
"^constants$",
|
||||
"^sys$",
|
||||
"^_linklist$",
|
||||
"^_stream_wrap$",
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'not-to-deprecated',
|
||||
name: "not-to-deprecated",
|
||||
comment:
|
||||
'This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later ' +
|
||||
'version of that module, or find an alternative. Deprecated modules are a security risk.',
|
||||
severity: 'warn',
|
||||
"This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later " +
|
||||
"version of that module, or find an alternative. Deprecated modules are a security risk.",
|
||||
severity: "warn",
|
||||
from: {},
|
||||
to: {
|
||||
dependencyTypes: [
|
||||
'deprecated'
|
||||
]
|
||||
}
|
||||
dependencyTypes: ["deprecated"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'no-non-package-json',
|
||||
severity: 'error',
|
||||
name: "no-non-package-json",
|
||||
severity: "error",
|
||||
comment:
|
||||
"This module depends on an npm package that isn't in the 'dependencies' section of your package.json. " +
|
||||
"That's problematic as the package either (1) won't be available on live (2 - worse) will be " +
|
||||
@ -95,87 +89,75 @@ module.exports = {
|
||||
"in your package.json.",
|
||||
from: {},
|
||||
to: {
|
||||
dependencyTypes: [
|
||||
'npm-no-pkg',
|
||||
'npm-unknown'
|
||||
]
|
||||
}
|
||||
dependencyTypes: ["npm-no-pkg", "npm-unknown"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'not-to-unresolvable',
|
||||
name: "not-to-unresolvable",
|
||||
comment:
|
||||
"This module depends on a module that cannot be found ('resolved to disk'). If it's an npm " +
|
||||
'module: add it to your package.json. In all other cases you likely already know what to do.',
|
||||
severity: 'error',
|
||||
"module: add it to your package.json. In all other cases you likely already know what to do.",
|
||||
severity: "error",
|
||||
from: {},
|
||||
to: {
|
||||
couldNotResolve: true
|
||||
}
|
||||
couldNotResolve: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'no-duplicate-dep-types',
|
||||
name: "no-duplicate-dep-types",
|
||||
comment:
|
||||
"Likely this module depends on an external ('npm') package that occurs more than once " +
|
||||
"in your package.json i.e. bot as a devDependencies and in dependencies. This will cause " +
|
||||
"maintenance problems later on.",
|
||||
severity: 'warn',
|
||||
severity: "warn",
|
||||
from: {},
|
||||
to: {
|
||||
moreThanOneDependencyType: true,
|
||||
// as it's pretty common to have a type import be a type only import
|
||||
// as it's pretty common to have a type import be a type only import
|
||||
// _and_ (e.g.) a devDependency - don't consider type-only dependency
|
||||
// types for this rule
|
||||
dependencyTypesNot: ["type-only"]
|
||||
}
|
||||
dependencyTypesNot: ["type-only"],
|
||||
},
|
||||
},
|
||||
|
||||
/* rules you might want to tweak for your specific situation: */
|
||||
|
||||
{
|
||||
name: 'not-to-spec',
|
||||
name: "not-to-spec",
|
||||
comment:
|
||||
'This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. ' +
|
||||
"This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. " +
|
||||
"If there's something in a spec that's of use to other modules, it doesn't have that single " +
|
||||
'responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.',
|
||||
severity: 'error',
|
||||
"responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.",
|
||||
severity: "error",
|
||||
from: {},
|
||||
to: {
|
||||
path: '[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$'
|
||||
}
|
||||
path: "[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'not-to-dev-dep',
|
||||
severity: 'error',
|
||||
name: "not-to-dev-dep",
|
||||
severity: "error",
|
||||
comment:
|
||||
"This module depends on an npm package from the 'devDependencies' section of your " +
|
||||
'package.json. It looks like something that ships to production, though. To prevent problems ' +
|
||||
"package.json. It looks like something that ships to production, though. To prevent problems " +
|
||||
"with npm packages that aren't there on production declare it (only!) in the 'dependencies'" +
|
||||
'section of your package.json. If this module is development only - add it to the ' +
|
||||
'from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration',
|
||||
"section of your package.json. If this module is development only - add it to the " +
|
||||
"from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration",
|
||||
from: {
|
||||
path: '^(src)',
|
||||
pathNot: [
|
||||
'[.](?:spec|test|setup|script)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$',
|
||||
'src/test'
|
||||
]
|
||||
path: "^(src)",
|
||||
pathNot: ["[.](?:spec|test|setup|script)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$", "./test"],
|
||||
},
|
||||
to: {
|
||||
dependencyTypes: [
|
||||
'npm-dev',
|
||||
],
|
||||
dependencyTypes: ["npm-dev"],
|
||||
// type only dependencies are not a problem as they don't end up in the
|
||||
// production code or are ignored by the runtime.
|
||||
dependencyTypesNot: [
|
||||
'type-only'
|
||||
],
|
||||
pathNot: [
|
||||
'node_modules/@types/'
|
||||
]
|
||||
}
|
||||
dependencyTypesNot: ["type-only"],
|
||||
pathNot: ["node_modules/@types/"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'optional-deps-used',
|
||||
severity: 'info',
|
||||
name: "optional-deps-used",
|
||||
severity: "info",
|
||||
comment:
|
||||
"This module depends on an npm package that is declared as an optional dependency " +
|
||||
"in your package.json. As this makes sense in limited situations only, it's flagged here. " +
|
||||
@ -183,33 +165,28 @@ module.exports = {
|
||||
"dependency-cruiser configuration.",
|
||||
from: {},
|
||||
to: {
|
||||
dependencyTypes: [
|
||||
'npm-optional'
|
||||
]
|
||||
}
|
||||
dependencyTypes: ["npm-optional"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'peer-deps-used',
|
||||
name: "peer-deps-used",
|
||||
comment:
|
||||
"This module depends on an npm package that is declared as a peer dependency " +
|
||||
"in your package.json. This makes sense if your package is e.g. a plugin, but in " +
|
||||
"other cases - maybe not so much. If the use of a peer dependency is intentional " +
|
||||
"add an exception to your dependency-cruiser configuration.",
|
||||
severity: 'warn',
|
||||
severity: "warn",
|
||||
from: {},
|
||||
to: {
|
||||
dependencyTypes: [
|
||||
'npm-peer'
|
||||
]
|
||||
}
|
||||
}
|
||||
dependencyTypes: ["npm-peer"],
|
||||
},
|
||||
},
|
||||
],
|
||||
options: {
|
||||
|
||||
/* Which modules not to follow further when encountered */
|
||||
doNotFollow: {
|
||||
/* path: an array of regular expressions in strings to match against */
|
||||
path: ['node_modules']
|
||||
path: ["node_modules"],
|
||||
},
|
||||
|
||||
/* Which modules to exclude */
|
||||
@ -271,7 +248,7 @@ module.exports = {
|
||||
defaults to './tsconfig.json'.
|
||||
*/
|
||||
tsConfig: {
|
||||
fileName: 'tsconfig.json'
|
||||
fileName: "tsconfig.json",
|
||||
},
|
||||
|
||||
/* Webpack configuration to use to get resolve options from.
|
||||
@ -345,7 +322,7 @@ module.exports = {
|
||||
collapses everything in node_modules to one folder deep so you see
|
||||
the external modules, but their innards.
|
||||
*/
|
||||
collapsePattern: 'node_modules/(?:@[^/]+/[^/]+|[^/]+)',
|
||||
collapsePattern: "node_modules/(?:@[^/]+/[^/]+|[^/]+)",
|
||||
|
||||
/* Options to tweak the appearance of your graph.See
|
||||
https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#reporteroptions
|
||||
@ -367,7 +344,8 @@ module.exports = {
|
||||
dependency graph reporter (`archi`) you probably want to tweak
|
||||
this collapsePattern to your situation.
|
||||
*/
|
||||
collapsePattern: '^(?:packages|src|lib(s?)|app(s?)|bin|test(s?)|spec(s?))/[^/]+|node_modules/(?:@[^/]+/[^/]+|[^/]+)',
|
||||
collapsePattern:
|
||||
"^(?:packages|src|lib(s?)|app(s?)|bin|test(s?)|spec(s?))/[^/]+|node_modules/(?:@[^/]+/[^/]+|[^/]+)",
|
||||
|
||||
/* Options to tweak the appearance of your graph. If you don't specify a
|
||||
theme for 'archi' dependency-cruiser will use the one specified in the
|
||||
@ -375,10 +353,10 @@ module.exports = {
|
||||
*/
|
||||
// theme: { },
|
||||
},
|
||||
"text": {
|
||||
"highlightFocused": true
|
||||
text: {
|
||||
highlightFocused: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
// generated: dependency-cruiser@16.3.3 on 2024-06-13T23:26:36.169Z
|
||||
|
12
.editorconfig
Normal file
@ -0,0 +1,12 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[src/*.{js,ts}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
@ -1,6 +1,6 @@
|
||||
VITE_BYPASS_LOGIN=0
|
||||
VITE_BYPASS_TUTORIAL=0
|
||||
VITE_SERVER_URL=https://api.beta.pokerogue.net
|
||||
VITE_SERVER_URL=https://apibeta.pokerogue.net
|
||||
VITE_DISCORD_CLIENT_ID=1248062921129459756
|
||||
VITE_GOOGLE_CLIENT_ID=955345393540-2k6lfftf0fdnb0krqmpthjnqavfvvf73.apps.googleusercontent.com
|
||||
VITE_I18N_DEBUG=1
|
||||
VITE_I18N_DEBUG=0
|
||||
|
@ -3,5 +3,5 @@ VITE_BYPASS_TUTORIAL=0
|
||||
VITE_SERVER_URL=http://localhost:8001
|
||||
VITE_DISCORD_CLIENT_ID=1234567890
|
||||
VITE_GOOGLE_CLIENT_ID=1234567890
|
||||
VITE_I18N_DEBUG=1
|
||||
VITE_I18N_DEBUG=0
|
||||
VITE_PORT=8000
|
||||
|
1
.gitattributes
vendored
@ -1,2 +1,3 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
* -crlf
|
||||
|
49
.github/CODEOWNERS
vendored
@ -4,42 +4,19 @@
|
||||
* @pagefaultgames/junior-dev-team
|
||||
|
||||
# github actions/templates etc. - Dev Leads
|
||||
/.github @pagefaultgames/dev-leads
|
||||
/.github @pagefaultgames/senior-dev-team
|
||||
|
||||
# --- Translations ---
|
||||
# Art Team
|
||||
/public/**/*.png @pagefaultgames/art-team
|
||||
/public/**/*.json @pagefaultgames/art-team
|
||||
/public/images @pagefaultgames/art-team
|
||||
/public/battle-anims @pagefaultgames/art-team
|
||||
|
||||
# all translations - Translation Leads
|
||||
/src/locales @pagefaultgames/translation-leads
|
||||
# Audio files
|
||||
*.mp3 @pagefaultgames/composer-team
|
||||
*.wav @pagefaultgames/composer-team
|
||||
*.ogg @pagefaultgames/composer-team
|
||||
/public/audio @pagefaultgames/composer-team
|
||||
|
||||
# Catalan (Spain/Spanish)
|
||||
/src/locales/ca_ES @pagefaultgames/catalan-translation-team
|
||||
|
||||
# German
|
||||
/src/locales/de @pagefaultgames/german-translation-team
|
||||
|
||||
# English
|
||||
/src/locales/en @pagefaultgames/english-translation-team
|
||||
|
||||
# Spanish
|
||||
/src/locales/es @pagefaultgames/spanish-translation-team
|
||||
|
||||
# French
|
||||
/src/locales/fr @pagefaultgames/french-translation-team
|
||||
|
||||
# Italian
|
||||
/src/locales/it @pagefaultgames/italian-translation-team
|
||||
|
||||
# Japenese
|
||||
/src/locales/ja @pagefaultgames/japanese-translation-team
|
||||
|
||||
# Korean
|
||||
/src/locales/ko @pagefaultgames/korean-translation-team
|
||||
|
||||
# Brasilian (Brasil/Portuguese)
|
||||
/src/locales/pt_BR @pagefaultgames/portuguese_br-translation-team
|
||||
|
||||
# Chinese (simplified)
|
||||
/src/locales/zh_CN @pagefaultgames/chinese_simplified-translation-team
|
||||
|
||||
# Chinese (traditional)
|
||||
/src/locales/zh_TW @pagefaultgames/chinese_traditional-translation-team
|
||||
# Balance Files; contain actual code logic and must also be owned by dev team
|
||||
/src/data/balance @pagefaultgames/balance-team @pagefaultgames/junior-dev-team
|
2
.github/FUNDING.yml
vendored
@ -1 +1 @@
|
||||
github: patapancakes
|
||||
github: pagefaultgames
|
||||
|
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,6 +1,7 @@
|
||||
name: Bug Report
|
||||
description: Create a report to help us improve
|
||||
title: "[Bug] "
|
||||
type: bug
|
||||
labels: ["Bug", "Triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
|
1
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@ -1,6 +1,7 @@
|
||||
name: Feature Request
|
||||
description: Suggest an idea for this project
|
||||
title: "[Feature] "
|
||||
type: 'feature'
|
||||
labels: ["Enhancement", "Triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
|
81
.github/pull_request_template.md
vendored
@ -1,37 +1,76 @@
|
||||
<!-- Make sure the title includes categorization (i.e. [Bug], [QoL], [Localization]) -->
|
||||
<!-- Make sure that this PR is not overlapping with someone else's work -->
|
||||
<!-- Please try to keep the PR self-contained (and small) -->
|
||||
<!-- (Once you have read these comments, you are free to remove them) -->
|
||||
<!-- Feel free to look at other PRs for examples -->
|
||||
<!--
|
||||
Make sure the title includes categorization (choose the one that best fits):
|
||||
- [Bug]: If the PR is primarily a bug fix
|
||||
- [Move]: If a move has new or changed functionality
|
||||
- [Ability]: If an ability has new or changed functionality
|
||||
- [Item]: For new or modified items
|
||||
- [Mystery]: For new or modified Mystery Encounters
|
||||
- [Test]: If the PR is primarily adding or modifying tests
|
||||
- [UI/UX]: If the PR is changing UI/UX elements
|
||||
- [Audio]: If the PR is adding or changing music/sfx
|
||||
- [Sprite]: If the PR is adding or changing sprites
|
||||
- [Balance]: If the PR is related to game balance
|
||||
- [Challenge]: If the PR is adding or modifying challenges
|
||||
- [Refactor]: If the PR is primarily rewriting existing code
|
||||
- [Docs]: If the PR is just adding or modifying documentation (such as tsdocs/code comments)
|
||||
- [GitHub]: For changes to GitHub workflows/templates/etc
|
||||
- [Misc]: If no other category fits the PR
|
||||
-->
|
||||
<!--
|
||||
Make sure that this PR is not overlapping with someone else's work
|
||||
Please try to keep the PR self-contained (and small)
|
||||
-->
|
||||
|
||||
## What are the changes the user will see?
|
||||
<!-- Summarize what are the changes from a user perspective on the application -->
|
||||
|
||||
## Why am I making these changes?
|
||||
<!-- Explain why you decided to introduce these changes -->
|
||||
<!-- Does it come from an issue or another PR? Please link it -->
|
||||
<!-- Explain why you believe this can enhance user experience -->
|
||||
<!--
|
||||
Explain why you decided to introduce these changes
|
||||
Does it come from an issue or another PR? Please link it
|
||||
Explain why you believe this can enhance user experience
|
||||
-->
|
||||
<!--
|
||||
If there are existing GitHub issues related to the PR that would be fixed,
|
||||
you can add "Fixes #[issue number]" (ie: "Fixes #1234") to link an issue to your PR
|
||||
so that it will automatically be closed when the PR is merged.
|
||||
-->
|
||||
|
||||
## What are the changes from a developer perspective?
|
||||
<!-- Explicitly state what are the changes introduced by the PR -->
|
||||
<!-- You can make use of a comparison between what was the state before and after your PR changes -->
|
||||
<!--
|
||||
Explicitly state what are the changes introduced by the PR
|
||||
You can make use of a comparison between what was the state before and after your PR changes
|
||||
Ex: What files have been changed? What classes/functions/variables/etc have been added or changed?
|
||||
-->
|
||||
|
||||
### Screenshots/Videos
|
||||
<!-- If your change is changing anything on the user experience, please provide visual proofs of it -->
|
||||
<!-- Please take screenshots/videos before and after your changes, to show what is brought by this PR -->
|
||||
## Screenshots/Videos
|
||||
<!--
|
||||
If your changes are changing anything on the user experience, please provide visual proofs of it
|
||||
Please take screenshots/videos before and after your changes, to show what is brought by this PR
|
||||
-->
|
||||
|
||||
## How to test the changes?
|
||||
<!-- How can a reviewer test your changes once they check out on your branch? -->
|
||||
<!-- Did you just make use of the `src/overrides.ts` file? -->
|
||||
<!-- Did you introduce any automated tests? -->
|
||||
<!-- Do the reviewer need to do something special in order to test your change? -->
|
||||
<!--
|
||||
How can a reviewer test your changes once they check out on your branch?
|
||||
Did you make use of the `src/overrides.ts` file?
|
||||
Did you introduce any automated tests?
|
||||
Do the reviewers need to do something special in order to test your changes?
|
||||
-->
|
||||
|
||||
## Checklist
|
||||
- [ ] **I'm using `beta` as my base branch**
|
||||
- [ ] There is no overlap with another PR?
|
||||
- [ ] The PR is self-contained and cannot be split into smaller PRs?
|
||||
- [ ] Have I provided a clear explanation of the changes?
|
||||
- [ ] Have I considered writing automated tests for the issue?
|
||||
- [ ] If I have text, did I make it translatable and add a key in the English locale file(s)?
|
||||
- [ ] Have I tested the changes (manually)?
|
||||
- [ ] Are all unit tests still passing? (`npm run test`)
|
||||
- [ ] Are the changes visual?
|
||||
- [ ] Have I provided screenshots/videos of the changes?
|
||||
- [ ] Have I tested the changes manually?
|
||||
- [ ] Are all unit tests still passing? (`npm run test:silent`)
|
||||
- [ ] Have I created new automated tests (`npm run create-test`) or updated existing tests related to the PR's changes?
|
||||
- [ ] Have I provided screenshots/videos of the changes (if applicable)?
|
||||
- [ ] Have I made sure that any UI change works for both UI themes (default and legacy)?
|
||||
|
||||
Are there any localization additions or changes? If so:
|
||||
- [ ] Has a locales PR been created on the [locales](https://github.com/pagefaultgames/pokerogue-locales) repo?
|
||||
- [ ] If so, please leave a link to it here:
|
||||
- [ ] Has the translation team been contacted for proofreading/translation?
|
73
.github/workflows/create-release.yml
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
name: Create Release Branch
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
versionName:
|
||||
description: "Name of version (i.e. 1.9.0)"
|
||||
type: string
|
||||
required: true
|
||||
confirmVersion:
|
||||
type: string
|
||||
required: true
|
||||
description: "Confirm version name"
|
||||
|
||||
# explicitly specify the necessary scopes
|
||||
permissions:
|
||||
pull-requests: write
|
||||
actions: write
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
create-release:
|
||||
if: github.repository == 'pagefaultgames/pokerogue' && (vars.BETA_DEPLOY_BRANCH == '' || ! startsWith(vars.BETA_DEPLOY_BRANCH, 'release'))
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed for github cli commands
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Validate provided version
|
||||
# Ensure version matches confirmation and conforms to expected pattern.
|
||||
run: |
|
||||
if [[ "${{ github.event.inputs.versionName }}" != "${{ github.event.inputs.confirmVersion }}" ]]; then
|
||||
echo "Version name does not match confirmation. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "${{ github.event.inputs.versionName }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Version name must follow the format X.Y.Z where X, Y, and Z are all numbers. Exiting..."
|
||||
exit 1
|
||||
fi
|
||||
shell: bash
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
# Always base off of beta branch, regardless of the branch the workflow was triggered from.
|
||||
ref: beta
|
||||
- name: Create release branch
|
||||
run: git checkout -b release
|
||||
# In order to be able to open a PR into beta, we need the branch to have at least one change.
|
||||
- name: Overwrite RELEASE file
|
||||
run: |
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
echo "Release v${{ github.event.inputs.versionName }}" > RELEASE
|
||||
git add RELEASE
|
||||
git commit -m "Stage release v${{ github.event.inputs.versionName }}"
|
||||
- name: Push new branch
|
||||
run: git push origin release
|
||||
# The repository variable is used by the deploy-beta workflow to determine whether to deploy from beta or release.
|
||||
- name: Set repository variable
|
||||
run: GITHUB_TOKEN="${{ secrets.RW_VARS_PAT }}" gh variable set BETA_DEPLOY_BRANCH --body "release"
|
||||
- name: Create pull request to main
|
||||
run: |
|
||||
gh pr create --base main \
|
||||
--head release \
|
||||
--title "Release v${{ github.event.inputs.versionName }} to main" \
|
||||
--body "This PR is for the release of v${{ github.event.inputs.versionName }}, and was created automatically by the GitHub Actions workflow invoked by ${{ github.actor }}" \
|
||||
--draft
|
||||
- name: Create pull request to beta
|
||||
run: |
|
||||
gh pr create --base beta \
|
||||
--head release \
|
||||
--title "Release v${{ github.event.inputs.versionName }} to beta" \
|
||||
--body "This PR is for the release of v${{ github.event.inputs.versionName }}, and was created automatically by the GitHub Actions workflow invoked by ${{ github.actor }}" \
|
||||
--draft
|
15
.github/workflows/deploy-beta.yml
vendored
@ -4,16 +4,23 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- beta
|
||||
- release
|
||||
workflow_run:
|
||||
types: completed
|
||||
workflows: ["Post Release Deleted"]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
if: github.repository == 'pagefaultgames/pokerogue'
|
||||
if: github.repository == 'pagefaultgames/pokerogue' && github.ref_name == ${{ vars.BETA_DEPLOY_BRANCH || 'beta' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
ref: ${{ vars.BETA_DEPLOY_BRANCH || 'beta'}}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
node-version-file: ".nvmrc"
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Build
|
||||
@ -28,5 +35,5 @@ jobs:
|
||||
chmod 600 ~/.ssh/*
|
||||
ssh-keyscan -H ${{ secrets.BETA_SSH_HOST }} >> ~/.ssh/known_hosts
|
||||
- name: Deploy build on server
|
||||
run: |
|
||||
rsync --del --no-times --checksum -vrm dist/* ${{ secrets.BETA_SSH_USER }}@${{ secrets.BETA_SSH_HOST }}:${{ secrets.BETA_DESTINATION_DIR }}
|
||||
run: |
|
||||
rsync --del --no-times --checksum -vrm dist/* ${{ secrets.BETA_SSH_USER }}@${{ secrets.BETA_SSH_HOST }}:${{ secrets.BETA_DESTINATION_DIR }}
|
||||
|
20
.github/workflows/deploy.yml
vendored
@ -1,8 +1,12 @@
|
||||
name: Deploy
|
||||
name: Deploy Main
|
||||
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
@ -10,9 +14,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Build
|
||||
@ -20,7 +26,7 @@ jobs:
|
||||
env:
|
||||
NODE_ENV: production
|
||||
- name: Set up SSH
|
||||
if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
|
||||
if: github.event_name == 'push' && github.ref_name == 'main'
|
||||
run: |
|
||||
mkdir ~/.ssh
|
||||
echo "${{ secrets.SSH_PUBLIC_KEY }}" > ~/.ssh/id_ed25519.pub
|
||||
@ -28,12 +34,12 @@ jobs:
|
||||
chmod 600 ~/.ssh/*
|
||||
ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts
|
||||
- name: Deploy build on server
|
||||
if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
|
||||
if: github.event_name == 'push' && github.ref_name == 'main'
|
||||
run: |
|
||||
rsync --del --no-times --checksum -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }}
|
||||
ssh -t ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/prmanifest --inpath ${{ secrets.DESTINATION_DIR }} --outpath ${{ secrets.DESTINATION_DIR }}/manifest.json"
|
||||
- name: Purge Cloudflare Cache
|
||||
if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
|
||||
if: github.event_name == 'push' && github.ref_name == 'main'
|
||||
id: purge-cache
|
||||
uses: NathanVaughn/actions-cloudflare-purge@v3.1.0
|
||||
with:
|
||||
|
35
.github/workflows/eslint.yml
vendored
@ -1,35 +0,0 @@
|
||||
name: ESLint
|
||||
|
||||
on:
|
||||
# Trigger the workflow on push or pull request,
|
||||
# but only for the main branch
|
||||
push:
|
||||
branches:
|
||||
- main # Trigger on push events to the main branch
|
||||
- beta # Trigger on push events to the beta branch
|
||||
pull_request:
|
||||
branches:
|
||||
- main # Trigger on pull request events targeting the main branch
|
||||
- beta # Trigger on pull request events targeting the beta branch
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
|
||||
jobs:
|
||||
run-linters: # Define a job named "run-linters"
|
||||
name: Run linters # Human-readable name for the job
|
||||
runs-on: ubuntu-latest # Specify the latest Ubuntu runner for the job
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository # Step to check out the repository
|
||||
uses: actions/checkout@v4 # Use the checkout action version 4
|
||||
|
||||
- name: Set up Node.js # Step to set up Node.js environment
|
||||
uses: actions/setup-node@v4 # Use the setup-node action version 4
|
||||
with:
|
||||
node-version: 20 # Specify Node.js version 20
|
||||
|
||||
- name: Install Node.js dependencies # Step to install Node.js dependencies
|
||||
run: npm ci # Use 'npm ci' to install dependencies
|
||||
|
||||
- name: eslint # Step to run linters
|
||||
run: npm run eslint-ci
|
11
.github/workflows/github-pages.yml
vendored
@ -24,8 +24,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository for Typedoc
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
path: pokerogue_docs
|
||||
|
||||
- name: Install OS package
|
||||
@ -33,14 +34,14 @@ jobs:
|
||||
sudo apt update
|
||||
sudo apt install -y git openssh-client
|
||||
|
||||
- name: Setup Node 20.13.1
|
||||
uses: actions/setup-node@v1
|
||||
- name: Setup Node 22.14.1
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version-file: "pokerogue_docs/.nvmrc"
|
||||
|
||||
- name: Checkout repository for Github Pages
|
||||
if: github.event_name == 'push'
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: pokerogue_gh
|
||||
ref: gh-pages
|
||||
|
12
.github/workflows/post-release-deleted.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
name: Post Release Deleted
|
||||
on:
|
||||
delete:
|
||||
|
||||
jobs:
|
||||
# Set the BETA_DEPLOY_BRANCH variable to beta when a release branch is deleted
|
||||
update-release-var:
|
||||
if: github.repository == 'pagefaultgames/pokerogue' && github.event.ref_type == 'branch' && github.event.ref == 'release'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set BETA_DEPLOY_BRANCH to beta
|
||||
run: GITHUB_TOKEN="${{ secrets.RW_VARS_PAT }}" gh variable set BETA_DEPLOY_BRANCH --body "beta" --repo "pagefaultgames/pokerogue"
|
41
.github/workflows/quality.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
name: Biome Code Quality
|
||||
|
||||
on:
|
||||
# Trigger the workflow on push or pull request,
|
||||
# but only for the main branch
|
||||
push:
|
||||
branches:
|
||||
- main # Trigger on push events to the main branch
|
||||
- beta # Trigger on push events to the beta branch
|
||||
pull_request:
|
||||
branches:
|
||||
- main # Trigger on pull request events targeting the main branch
|
||||
- beta # Trigger on pull request events targeting the beta branch
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
|
||||
jobs:
|
||||
run-linters: # Define a job named "run-linters"
|
||||
name: Run linters # Human-readable name for the job
|
||||
runs-on: ubuntu-latest # Specify the latest Ubuntu runner for the job
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository # Step to check out the repository
|
||||
uses: actions/checkout@v4 # Use the checkout action version 4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Set up Node.js # Step to set up Node.js environment
|
||||
uses: actions/setup-node@v4 # Use the setup-node action version 4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install Node.js dependencies # Step to install Node.js dependencies
|
||||
run: npm ci # Use 'npm ci' to install dependencies
|
||||
|
||||
- name: eslint # Step to run linters
|
||||
run: npm run eslint-ci
|
||||
|
||||
- name: Lint with Biome # Step to run linters
|
||||
run: npm run biome-ci
|
9
.github/workflows/test-shard-template.yml
vendored
@ -19,12 +19,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
- name: Install Node.js dependencies
|
||||
run: npm ci
|
||||
- name: Run tests
|
||||
run: npx vitest --project ${{ inputs.project }} --shard=${{ inputs.shard }}/${{ inputs.totalShards }} ${{ !runner.debug && '--silent' || '' }}
|
||||
run: npx vitest --project ${{ inputs.project }} --no-isolate --shard=${{ inputs.shard }}/${{ inputs.totalShards }} ${{ !runner.debug && '--silent' || '' }}
|
||||
|
70
.github/workflows/tests.yml
vendored
@ -5,38 +5,60 @@ on:
|
||||
# but only for the main branch
|
||||
push:
|
||||
branches:
|
||||
- main # Trigger on push events to the main branch
|
||||
- main # Trigger on push events to the main branch
|
||||
- beta # Trigger on push events to the beta branch
|
||||
- release # Trigger on push events to the release branch
|
||||
# go upvote https://github.com/actions/runner/issues/1182 and yell at microsoft until they fix this or ditch yml for workflows
|
||||
paths:
|
||||
# src and test files
|
||||
- "src/**"
|
||||
- "test/**"
|
||||
- "public/**"
|
||||
# Workflows that can impact tests
|
||||
- ".github/workflows/test*.yml"
|
||||
# top-level files
|
||||
- "package*.json"
|
||||
- ".nvrmc" # Updates to node version can break tests
|
||||
- "vite.*.ts" # vite.config.ts, vite.vitest.config.ts, vitest.workspace.ts
|
||||
- "tsconfig*.json" # tsconfig.json tweaking can impact compilation
|
||||
- "global.d.ts"
|
||||
- ".env.*"
|
||||
# Blanket negations for files that cannot impact tests
|
||||
- "!**/*.py" # No .py files
|
||||
- "!**/*.sh" # No .sh files
|
||||
- "!**/*.md" # No .md files
|
||||
- "!**/.git*" # .gitkeep and family
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- main # Trigger on pull request events targeting the main branch
|
||||
- main # Trigger on pull request events targeting the main branch
|
||||
- beta # Trigger on pull request events targeting the beta branch
|
||||
- release # Trigger on pull request events targeting the release branch
|
||||
paths: # go upvote https://github.com/actions/runner/issues/1182 and yell at microsoft because until then we have to duplicate this
|
||||
# src and test files
|
||||
- "src/**"
|
||||
- "test/**"
|
||||
- "public/**"
|
||||
# Workflows that can impact tests
|
||||
- ".github/workflows/test*.yml"
|
||||
# top-level files
|
||||
- "package*.json"
|
||||
- ".nvrmc" # Updates to node version can break tests
|
||||
- "vite*" # vite.config.ts, vite.vitest.config.ts, vitest.workspace.ts
|
||||
- "tsconfig*.json" # tsconfig.json tweaking can impact compilation
|
||||
- "global.d.ts"
|
||||
- ".env.*"
|
||||
# Blanket negations for files that cannot impact tests
|
||||
- "!**/*.py" # No .py files
|
||||
- "!**/*.sh" # No .sh files
|
||||
- "!**/*.md" # No .md files
|
||||
- "!**/.git*" # .gitkeep and family
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
|
||||
jobs:
|
||||
pre-test:
|
||||
name: Run Pre-test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: tests-action
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- name: Install Node.js dependencies
|
||||
working-directory: tests-action
|
||||
run: npm ci
|
||||
- name: Run Pre-test
|
||||
working-directory: tests-action
|
||||
run: npx vitest run --project pre ${{ !runner.debug && '--silent' || '' }}
|
||||
|
||||
run-tests:
|
||||
name: Run Tests
|
||||
needs: [pre-test]
|
||||
name: Run Tests
|
||||
strategy:
|
||||
matrix:
|
||||
shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
@ -44,4 +66,4 @@ jobs:
|
||||
with:
|
||||
project: main
|
||||
shard: ${{ matrix.shard }}
|
||||
totalShards: 10
|
||||
totalShards: 10
|
||||
|
7
.gitignore
vendored
@ -13,7 +13,8 @@ dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
.vscode
|
||||
*.code-workspace
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
@ -41,3 +42,7 @@ coverage
|
||||
|
||||
/dependency-graph.svg
|
||||
/.vs
|
||||
|
||||
|
||||
# Script outputs
|
||||
./*.csv
|
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "public/locales"]
|
||||
path = public/locales
|
||||
url = https://github.com/pagefaultgames/pokerogue-locales
|
624
CREDITS.md
Normal file
@ -0,0 +1,624 @@
|
||||
# 🎵 Music
|
||||
|
||||
## BGM
|
||||
- Pokémon Mystery Dungeon: Explorers of Sky
|
||||
- Arata Iiyoshi
|
||||
- Hideki Sakamoto
|
||||
- Keisuke Ito
|
||||
- Ken-ichi Saito
|
||||
- Yoshihiro Maeda
|
||||
- Pokémon Black/White
|
||||
- Go Ichinose
|
||||
- Hitomi Sato
|
||||
- Shota Kageyama
|
||||
- Pokémon Mystery Dungeon: Rescue Team DX
|
||||
- Keisuke Ito
|
||||
- Arata Iiyoshi
|
||||
- Atsuhiro Ishizuna
|
||||
- Pokémon HeartGold/SoulSilver
|
||||
- Pokémon Black/White 2
|
||||
- Pokémon X/Y
|
||||
- Pokémon Omega Ruby/Alpha Sapphire
|
||||
- Pokémon Sun/Moon
|
||||
- Pokémon Ultra Sun/Ultra Moon
|
||||
- Pokémon Sword/Shield
|
||||
- Pokémon Legends: Arceus
|
||||
- Pokémon Scarlet/Violet
|
||||
- Firel (Custom Graveyard, Ice Cave, Laboratory, Metropolis, Plains, Power Plant, Seabed, Space, and Volcano biome music)
|
||||
- Lmz (Custom Ancient Ruins, Jungle, and Lake biome music)
|
||||
- Andr06 (Custom Forest, Slum and Sea biome music)
|
||||
- _tresnoir
|
||||
- unveiler
|
||||
|
||||
## Sound Effects
|
||||
- Pokémon Emerald
|
||||
- Pokémon Black/White
|
||||
|
||||
|
||||
# 🎨 Art
|
||||
|
||||
## Backgrounds
|
||||
- Squip (Paid Commissions)
|
||||
- Contributions by Someonealive-QN
|
||||
|
||||
## UI
|
||||
- GAMEFREAK
|
||||
- LJ Birdman
|
||||
|
||||
## Pagefault Games Intro
|
||||
- Spectremint
|
||||
|
||||
## Game Logo
|
||||
- Gonstar (Paid Commission)
|
||||
|
||||
## Trainer Sprites
|
||||
- GAMEFREAK (Pokémon Black/White 2, Pokémon Diamond/Pearl)
|
||||
- kyledove
|
||||
- Brumirage
|
||||
- pkmn_realidea (Paid Commissions)
|
||||
- IceJkai
|
||||
- Leparagon
|
||||
- wormhood
|
||||
|
||||
## Mystery Event Sprites
|
||||
- chrysomelinae
|
||||
- koda_want_to_sleep
|
||||
- “🐺Kieran/YJ 🐍” rival_kieran aka thedreadedden
|
||||
- ImperialSympathizer
|
||||
- wormhood
|
||||
- gerolau
|
||||
- otterwatch
|
||||
|
||||
## Trainer Portraits
|
||||
- pkmn_realidea (Paid Commissions)
|
||||
|
||||
## Pokémon Sprites and Animation
|
||||
In addition to the lists below, please check [the PokéRogue wiki](https://wiki.pokerogue.net/credits:credits) for a more detailed list of Pokémon Sprite credits.
|
||||
|
||||
- GAMEFREAK (Pokémon Black/White 2)
|
||||
- Smogon Sprite Project (Various Artists)
|
||||
- Skyflyer
|
||||
- Nolo33
|
||||
- Ebaru
|
||||
- EricLostie
|
||||
- kiriaura
|
||||
- Caruban
|
||||
- Sopita_Yorita
|
||||
- Azrita
|
||||
- AshnixsLaw
|
||||
- Hellfire0raptor
|
||||
- RetroNC
|
||||
- Franark122k
|
||||
- OldSoulja
|
||||
- PKMarioG
|
||||
- ItsYugen
|
||||
- lucasomi
|
||||
- Pkm Sinfonia
|
||||
- Poki Papillon
|
||||
- Fleimer_
|
||||
- bizcoeindoloro
|
||||
- mangalos810
|
||||
- selstar
|
||||
|
||||
### Static Sprites and Base Shiny Replacements Credits
|
||||
- AMVictory
|
||||
- Antiant
|
||||
- Arhops
|
||||
- arinoelle
|
||||
- Arkeis
|
||||
- aXl
|
||||
- BananaToast
|
||||
- Basic Vanillite
|
||||
- BlackWhiteRobin
|
||||
- Blaquaza
|
||||
- Branflakes325
|
||||
- Brylark
|
||||
- Buna
|
||||
- Bynine
|
||||
- Corson
|
||||
- Cynda
|
||||
- “Diashi” diazhi
|
||||
- Dleep
|
||||
- doomchaos
|
||||
- Espeon Scientist
|
||||
- Farriella
|
||||
- fishbowlsoul90
|
||||
- “Follower” rulerofthesea11
|
||||
- Galifia
|
||||
- GeoisEvil
|
||||
- G.E.Z.
|
||||
- Glustora
|
||||
- Harrie
|
||||
- HealnDeal
|
||||
- Hematite
|
||||
- HM100
|
||||
- Ice-cold Claws
|
||||
- Involuntary Twitch
|
||||
- “Jay” itsamejay
|
||||
- KattenK
|
||||
- KingOfThe-X-Roads
|
||||
- KyleDove
|
||||
- Kyleo
|
||||
- Kyuzeth
|
||||
- Larryturbo
|
||||
- Layell
|
||||
- Legitimate Username
|
||||
- leParagon
|
||||
- “LJ” lj_birdman
|
||||
- Luigi Player
|
||||
- Madmadness65
|
||||
- Mega-Pokebattlerz
|
||||
- Mintly
|
||||
- mjco
|
||||
- “Momo” sphinx_sage
|
||||
- MrDollSteak
|
||||
- MyMarshlands
|
||||
- N-Kin
|
||||
- Noscium
|
||||
- “Nova” fabunova
|
||||
- “Omniv” omniv
|
||||
- paintseagull
|
||||
- princessofmusic
|
||||
- PumpkinPastel
|
||||
- Quanyails
|
||||
- RadicalCharizard
|
||||
- RedRooster
|
||||
- “♂ROMEO⚧” gerolau
|
||||
- ruleroftheseas11
|
||||
- SelenaArmorclaw
|
||||
- “serif” serifaizawa
|
||||
- Siiilver
|
||||
- Sleet
|
||||
- Snivy101
|
||||
- Speed-X
|
||||
- Sphex
|
||||
- Spook
|
||||
- Squip
|
||||
- TeraVolt
|
||||
- TheAetherPlayer
|
||||
- TheCynicalPoet
|
||||
- Tooni
|
||||
- TrainerSplash
|
||||
- Travis
|
||||
- Turtleye
|
||||
- Tyrell D. Barnes
|
||||
- “Vari” \_vari\_
|
||||
- Wobblebuns
|
||||
- WolfPP
|
||||
- WPS
|
||||
- Wyverii
|
||||
- “zan” smtif
|
||||
- Zerudez
|
||||
- Z-nogyroP
|
||||
|
||||
### Animated Sprites Credits
|
||||
- Antiant
|
||||
- arinoelle
|
||||
- Blaquaza
|
||||
- Claire Starsword
|
||||
- Coyotango
|
||||
- DanEx
|
||||
- “Diashi” diazhi
|
||||
- GalacticArtistMuffin
|
||||
- G.E.Z.
|
||||
- hexagonereal
|
||||
- HM100
|
||||
- Katten
|
||||
- LeParagon
|
||||
- localghost
|
||||
- MallowOut
|
||||
- mattiwarden
|
||||
- “Momo” sphinx_sage
|
||||
- N-Kin
|
||||
- NoelleMBrooks
|
||||
- Nyx
|
||||
- “Omniv” omniv
|
||||
- princessofmusic
|
||||
- PumpkinPastel
|
||||
- RadicalCharizard
|
||||
- seleccion
|
||||
- SelenaArmorclaw
|
||||
- TheAetherPlayer
|
||||
- Tinkatooni
|
||||
- Typhlito
|
||||
- uppa
|
||||
- “Vari” \_vari\_
|
||||
|
||||
### Rare/Epic Shiny Variants Credits
|
||||
- “Andr06” andr06
|
||||
- “Appo” appo
|
||||
- “Ashhawk” k_redacted
|
||||
- “Auralite” _auralite
|
||||
- “Awesome_Soul” awesome_soul
|
||||
- “Bagon” bagonganda
|
||||
- “Bibble” nuts_.
|
||||
- “BloomOfWoods” bloomofwoods
|
||||
- “Buge” buge
|
||||
- “bun” bunove
|
||||
- “bukie” bukie
|
||||
- cameranian
|
||||
- “Caramel” saltedcarriemel
|
||||
- “Chocolate Niblets” choconibs
|
||||
- “CKC” ckc_
|
||||
- “ClawsHDi” clawshdi
|
||||
- “Clown Princess” clown_princess
|
||||
- “Cmac2173” cmac2173
|
||||
- “Corsola” corsola_bandit
|
||||
- “Criminon” criminon
|
||||
- “Cryptican Gogoat Enthusiast” crypticanexe
|
||||
- “Diashi” diazhi
|
||||
- “deviant.daffodil, bug enthusiast” deviant.daffodil
|
||||
- “DigitalVaporeon” digitalvaporeon
|
||||
- dingosig
|
||||
- “Eku” ekusas00
|
||||
- “Elefante”
|
||||
- “Esca” colossalsquid
|
||||
- “Folf” folf.
|
||||
- “Follower” ruleroftheseas11
|
||||
- “Fontbane” fontbane
|
||||
- “Gallow” gallowhound
|
||||
- “Giojoe” giojoe10
|
||||
- “Gonfold” gonfold
|
||||
- greenninja757
|
||||
- “Grassy_Storm” grassy_storm
|
||||
- “GreenMegaMan” greenmegaman
|
||||
- “GROWL” myflixer.to
|
||||
- “guy claiming to work on a guide” 7thatlas
|
||||
- “h. 🍄” letterh.
|
||||
- “hamez” .hamez
|
||||
- “Hanniel” hanniel.15
|
||||
- “ImaginaryNeon” imaginaryneon
|
||||
- “Jay” itsamejay
|
||||
- “Jelke” jelke
|
||||
- kalikimothy
|
||||
- “🐺Kieran/YJ 🐍” rival_kieran aka thedreadedden
|
||||
- “Koda” Koda_want_to_sleep
|
||||
- “Lana” smogonian
|
||||
- “LJ” lj_birdman
|
||||
- “Long Girl” docamakesart
|
||||
- “Lucky” luckyluckylucky
|
||||
- “MissingNo.” clickonflareblitz
|
||||
- “Momo” sphinx_sage
|
||||
- monkehestman
|
||||
- “Nexxus” nexxus_
|
||||
- “Nik :3” realniktrustme
|
||||
- “Nikolatsu”
|
||||
- “nora” ora.n
|
||||
- “NOVA” fabunova
|
||||
- officerporkchops
|
||||
- “Omniv” omniv
|
||||
- “Otterwatch” otterwatch_
|
||||
- “Pandoraz” pandoraz
|
||||
- “Papa Pepsm An” papapepsman
|
||||
- “Penguin” peng06
|
||||
- “Prodigy” lorekeeperprodigy
|
||||
- “Purpenigma” purpenigma
|
||||
- “Rage” ragerevival
|
||||
- “♂ROMEO⚧” gerolau
|
||||
- “Sagrell D'Arcadia” coffeerequired
|
||||
- “serif” serifaizawa
|
||||
- “SillyTopplingGoose” sillytopplinggoose
|
||||
- “Splash Damage” splashceles
|
||||
- “Sweg1b01” sweg1b01
|
||||
- “SyntheGrim” synthegrim
|
||||
- “TaMenace” tamariontherestless
|
||||
- “TheTRUEgge” thetruegge
|
||||
- “Thorn” crownofthorns
|
||||
- “Togepi” togepimax
|
||||
- “Toopy” .toopy
|
||||
- “Tristan” tristan.w
|
||||
- “Umbreon” umbreon\_.\_
|
||||
- “Vari” \_vari\_
|
||||
- “Waasephi”
|
||||
- wormhood
|
||||
- “Yep, it's Caio” yepitscaio
|
||||
- “Ymri” ymri
|
||||
- “zaccie” zaccie
|
||||
- “zan” smtif
|
||||
|
||||
## Move Animations
|
||||
- Pokémon Reborn
|
||||
|
||||
|
||||
# ⚖️ Balance
|
||||
|
||||
## Balance Team
|
||||
- damocleas
|
||||
- Blitzy aka Kazapple
|
||||
- Cynthia_calliope
|
||||
- Esca
|
||||
- Fontbane
|
||||
- Plasto
|
||||
- Sethcurry
|
||||
- Starkrieg
|
||||
|
||||
## Past Members
|
||||
- Swizzo
|
||||
- Zaccie
|
||||
|
||||
## Past Contributors
|
||||
- chrysomelinae (Mystery Events)
|
||||
- AsdarDevelops (Mystery Events)
|
||||
|
||||
|
||||
# 💻 Development
|
||||
|
||||
## Server Developers
|
||||
- pancakes aka patapancakes
|
||||
|
||||
## Current and former Development Team members
|
||||
- bennybroseph
|
||||
- Brain Frog
|
||||
- CodeTappert
|
||||
- Dakurei
|
||||
- flx-sta
|
||||
- frutescens
|
||||
- Greenlamp
|
||||
- ImperialSympathizer
|
||||
- innerthunder
|
||||
- KimJeongSun
|
||||
- Madmadness65
|
||||
- Moka
|
||||
- Navori
|
||||
- NightKev
|
||||
- Opaquer
|
||||
- OrangeRed
|
||||
- Sam aka Flashfyre (initial developer, started PokéRogue)
|
||||
- SirzBenjie
|
||||
- sirzento
|
||||
- SN34KZ
|
||||
- Swain aka torranx
|
||||
- Temp aka Tempo-anon
|
||||
- Walker
|
||||
- Wlowscha (aka Curbio)
|
||||
- Xavion
|
||||
|
||||
## Bug/Issue Managers
|
||||
- Daleks
|
||||
- Lily
|
||||
- PigeonBar
|
||||
- Snailman
|
||||
|
||||
## Other Code Contributors
|
||||
- Admiral-Billy
|
||||
- allen925
|
||||
- arColm
|
||||
- Arxalc
|
||||
- AsdarDevelops
|
||||
- Corrade
|
||||
- DustinLin
|
||||
- ElizaAlex
|
||||
- EmberCM
|
||||
- EmoUsedHM01
|
||||
- EvasiveAce
|
||||
- Fontbane
|
||||
- francktrouillez
|
||||
- FredeX
|
||||
- geeilhan
|
||||
- happinyz
|
||||
- hayuna
|
||||
- InfernoVulpix
|
||||
- j-diefenbach
|
||||
- jaimefd
|
||||
- JakubHanko
|
||||
- JonStudders
|
||||
- karl-police
|
||||
- lucfd
|
||||
- Lugiadrien
|
||||
- madibye
|
||||
- mattrossdev
|
||||
- mcmontag
|
||||
- meepen
|
||||
- Mewtwo2387
|
||||
- muscode
|
||||
- Neverblade
|
||||
- NxKarim
|
||||
- okimin
|
||||
- PigeonBar
|
||||
- PrabbyDD
|
||||
- prateau
|
||||
- prime-dialga
|
||||
- PyGaVS
|
||||
- rationality6
|
||||
- RedstonewolfX
|
||||
- ReneGV
|
||||
- rnicar245
|
||||
- schmidtc1
|
||||
- shayebeadling
|
||||
- snoozbuster
|
||||
- sodaMelon
|
||||
- td76099
|
||||
- Vassiat
|
||||
- Xiaphear
|
||||
- zaccie
|
||||
- zacharied
|
||||
- Zé Ricardo
|
||||
|
||||
|
||||
# 🌎 Translation
|
||||
|
||||
## In-Game Translators
|
||||
|
||||
### 🇩🇪 German (de)
|
||||
- CodeTappert
|
||||
|
||||
### 🇪🇸 Spanish (es-ES)
|
||||
- Dan Stevenson
|
||||
- Javi
|
||||
- Lily Alterni
|
||||
- Qyxgames
|
||||
|
||||
### 🇫🇷 French (fr)
|
||||
- Lugiadrien
|
||||
|
||||
### 🇮🇹 Italian (it)
|
||||
- Nicus
|
||||
|
||||
### 🇯🇵 Japanese (ja)
|
||||
- 6mozuke9
|
||||
- Chapybara
|
||||
- PeachFresca
|
||||
|
||||
### 🇰🇷 Korean (ko)
|
||||
- Enoch
|
||||
- KimJeongSun
|
||||
- Returntoice
|
||||
- sodamelon
|
||||
|
||||
### 🇧🇷 Portuguese (pt-BR)
|
||||
- Zé Ricardo
|
||||
|
||||
### 🇨🇳 Chinese (zh-CN)
|
||||
- dddsenic
|
||||
- mercurius
|
||||
- VittorioVeneto
|
||||
- Yonmaru
|
||||
|
||||
### 🇹🇼 Chinese (zh-TW)
|
||||
- mercurius
|
||||
- Seagull
|
||||
|
||||
### Past contributors
|
||||
- Asdar (es-ES)
|
||||
- Rafa (es-ES)
|
||||
- GINK-SS (ko)
|
||||
- prostagma (pt-BR)
|
||||
- Ei (zh-TW)
|
||||
|
||||
## Wiki Translators
|
||||
|
||||
### 🇪🇸 Spanish (es-ES)
|
||||
- victorcooler
|
||||
|
||||
### 🇫🇷 French (fr)
|
||||
- Evan
|
||||
- Mitsue
|
||||
- Papier
|
||||
- Sangara
|
||||
- Voltarix
|
||||
|
||||
### 🇮🇹 Italian (it)
|
||||
- Purce
|
||||
- T-reds
|
||||
|
||||
### 🇰🇷 Korean (ko)
|
||||
- LeKaaN
|
||||
- Returntoice
|
||||
- sodamelon
|
||||
|
||||
### 🇵🇱 Polish (pl)
|
||||
- Talo
|
||||
|
||||
### 🇧🇷 Portuguese (pt-BR)
|
||||
- Beast
|
||||
- Sushi
|
||||
- Zé Ricardo
|
||||
|
||||
### 🇨🇳 Chinese (zh-CN)
|
||||
- jw-0-
|
||||
|
||||
### Past contributors
|
||||
- Dietaube (de)
|
||||
- Gnorpelltroll (de)
|
||||
- xRegix (de)
|
||||
- Broly Ikari (fr)
|
||||
- Leo Edgar_Zimmer (fr)
|
||||
- Telor (fr)
|
||||
- dorri (ko)
|
||||
- Little Moder_eldenring (ko)
|
||||
- Andy (zh-CN)
|
||||
- Black Feather (zh-CN)
|
||||
- itschili (zh-CN)
|
||||
- RimKnight (zh-CN)
|
||||
- Yubari (zh-CN)
|
||||
|
||||
## 🇺🇸 English Proofreaders
|
||||
- Cheyu
|
||||
- Faust
|
||||
- HaywiredUp
|
||||
- Irridescence
|
||||
- Ke'ahi
|
||||
- Louie
|
||||
- Nully
|
||||
- PeD
|
||||
- The Programmer
|
||||
|
||||
### Past contributors
|
||||
- I...
|
||||
|
||||
|
||||
# 📰 Wiki
|
||||
|
||||
## Wiki Head
|
||||
- H.A.R.V.
|
||||
|
||||
## Wiki Lead
|
||||
- Sangara
|
||||
- Zac
|
||||
- Smew
|
||||
- Brain Frog
|
||||
- Hannah
|
||||
|
||||
## Editor
|
||||
- Prodigy
|
||||
- Akuma
|
||||
- Dan Gioia
|
||||
- Shimizoki
|
||||
- Stave
|
||||
- NalysArbur
|
||||
- Ceimir
|
||||
- Solanum Tuberosum
|
||||
- Pom
|
||||
|
||||
## Artist
|
||||
- dub
|
||||
- SmashMania
|
||||
- Wren
|
||||
- Lugiadrien
|
||||
|
||||
## Contributor
|
||||
- Daleks <3
|
||||
- Inferno Vulpix
|
||||
- Embri
|
||||
- Nekod
|
||||
- P0kemonY
|
||||
- Scoom
|
||||
- BlueVaron
|
||||
|
||||
|
||||
# ☎️ Discord
|
||||
|
||||
## Head Moderator
|
||||
- leah
|
||||
|
||||
## Senior Moderators
|
||||
- Solanum Tuberosum
|
||||
- Madmadness65
|
||||
- Necrowmancer
|
||||
- lana
|
||||
|
||||
## Moderators
|
||||
- Sethcurry
|
||||
|
||||
## Junior Moderators
|
||||
- chacolah
|
||||
- ChaosGrimmon
|
||||
- Cynthia
|
||||
- Kat
|
||||
- lyn
|
||||
- Pom
|
||||
|
||||
|
||||
# ✨ Special Thanks
|
||||
|
||||
## Reddit Moderators
|
||||
- TheZigglez
|
||||
- Vicksin
|
||||
- Sapphire
|
||||
- Javi
|
||||
- roi
|
||||
|
||||
## External Tools
|
||||
- Ydarissep (creator of the now defunct "Yda's Dex")
|
||||
- Admiral-Billy (Offline App - Desktop)
|
||||
- Red aka StonedModder (iOS App)
|
113
README.md
@ -3,118 +3,51 @@
|
||||
PokéRogue is a browser based Pokémon fangame heavily inspired by the roguelite genre. Battle endlessly while gathering stacking items, exploring many different biomes, fighting trainers, bosses, and more!
|
||||
|
||||
# Contributing
|
||||
|
||||
## 🛠️ Development
|
||||
|
||||
If you have the motivation and experience with Typescript/Javascript (or are willing to learn) please feel free to fork the repository and make pull requests with contributions. If you don't know what to work on but want to help, reference the below **To-Do** section or the **#feature-vote** channel in the discord.
|
||||
|
||||
### 💻 Environment Setup
|
||||
|
||||
#### Prerequisites
|
||||
- node: 20.13.1
|
||||
|
||||
- node: 22.14.0
|
||||
- npm: [how to install](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
|
||||
|
||||
#### Running Locally
|
||||
|
||||
1. Clone the repo and in the root directory run `npm install`
|
||||
- *if you run into any errors, reach out in the **#dev-corner** channel in discord*
|
||||
2. Run `npm run start:dev` to locally run the project in `localhost:8000`
|
||||
|
||||
#### Linting
|
||||
We're using ESLint as our common linter and formatter. It will run automatically during the pre-commit hook but if you would like to manually run it, use the `npm run eslint` script.
|
||||
|
||||
We're using Biome as our common linter and formatter. It will run automatically during the pre-commit hook but if you would like to manually run it, use the `npm run biome` script. To view the complete rules, check out the [biome.jsonc](./biome.jsonc) file.
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
You can find the auto-generated documentation [here](https://pagefaultgames.github.io/pokerogue/main/index.html).
|
||||
For information on enemy AI, check out the [enemy-ai.md](./docs/enemy-ai.md) file.
|
||||
For detailed guidelines on documenting your code, refer to the [comments.md](./docs/comments.md) file.
|
||||
|
||||
### ❔ FAQ
|
||||
|
||||
**How do I test a new _______?**
|
||||
|
||||
- In the `src/overrides.ts` file there are overrides for most values you'll need to change for testing
|
||||
|
||||
**How do I retrieve the translations?**
|
||||
|
||||
- The translations were moved to the [dedicated translation repository](https://github.com/pagefaultgames/pokerogue-locales) and are now applied as a submodule in this project.
|
||||
- The command to retrieve the translations is `git submodule update --init --recursive`. If you still struggle to get it working, please reach out to #dev-corner channel in Discord.
|
||||
|
||||
## 🪧 To Do
|
||||
|
||||
Check out [Github Issues](https://github.com/pagefaultgames/pokerogue/issues) to see how can you help us!
|
||||
|
||||
# 📝 Credits
|
||||
> If this project contains assets you have produced and you do not see your name here, **please** reach out.
|
||||
>
|
||||
> If this project contains assets you have produced and you do not see your name, **please** reach out, either [here on GitHub](https://github.com/pagefaultgames/pokerogue/issues/new) or via [Discord](https://discord.gg/pokerogue).
|
||||
|
||||
### 🎵 BGM
|
||||
- Pokémon Mystery Dungeon: Explorers of Sky
|
||||
- Arata Iiyoshi
|
||||
- Hideki Sakamoto
|
||||
- Keisuke Ito
|
||||
- Ken-ichi Saito
|
||||
- Yoshihiro Maeda
|
||||
- Pokémon Black/White
|
||||
- Go Ichinose
|
||||
- Hitomi Sato
|
||||
- Shota Kageyama
|
||||
- Pokémon Mystery Dungeon: Rescue Team DX
|
||||
- Keisuke Ito
|
||||
- Arata Iiyoshi
|
||||
- Atsuhiro Ishizuna
|
||||
- Pokémon HeartGold/SoulSilver
|
||||
- Pokémon Black/White 2
|
||||
- Pokémon X/Y
|
||||
- Pokémon Omega Ruby/Alpha Sapphire
|
||||
- Pokémon Sun/Moon
|
||||
- Pokémon Ultra Sun/Ultra Moon
|
||||
- Pokémon Sword/Shield
|
||||
- Pokémon Legends: Arceus
|
||||
- Pokémon Scarlet/Violet
|
||||
- Firel (Custom Ice Cave, Laboratory, Metropolis, Plains, Power Plant, Seabed, Space, and Volcano biome music)
|
||||
- Lmz (Custom Ancient Ruins, Jungle, and Lake biome music)
|
||||
- Andr06 (Custom Slum and Sea biome music)
|
||||
|
||||
### 🎵 Sound Effects
|
||||
- Pokémon Emerald
|
||||
- Pokémon Black/White
|
||||
|
||||
### 🎨 Backgrounds
|
||||
- Squip (Paid Commissions)
|
||||
- Contributions by Someonealive-QN
|
||||
|
||||
### 🎨 UI
|
||||
- GAMEFREAK
|
||||
- LJ Birdman
|
||||
|
||||
### 🎨 Pagefault Games Intro
|
||||
- Spectremint
|
||||
|
||||
### 🎨 Game Logo
|
||||
- Gonstar (Paid Commission)
|
||||
|
||||
### 🎨 Trainer Sprites
|
||||
- GAMEFREAK (Pokémon Black/White 2, Pokémon Diamond/Pearl)
|
||||
- kyledove
|
||||
- Brumirage
|
||||
- pkmn_realidea (Paid Commissions)
|
||||
- IceJkai
|
||||
|
||||
### 🎨 Trainer Portraits
|
||||
- pkmn_realidea (Paid Commissions)
|
||||
|
||||
### 🎨 Pokemon Sprites and Animation
|
||||
- GAMEFREAK (Pokémon Black/White 2)
|
||||
- Smogon Sprite Project (Various Artists)
|
||||
- Skyflyer
|
||||
- Nolo33
|
||||
- Ebaru
|
||||
- EricLostie
|
||||
- KingOfThe-X-Roads
|
||||
- kiriaura
|
||||
- Caruban
|
||||
- Sopita_Yorita
|
||||
- Azrita
|
||||
- AshnixsLaw
|
||||
- Hellfire0raptor
|
||||
- RetroNC
|
||||
- Franark122k
|
||||
- OldSoulja
|
||||
- PKMarioG
|
||||
- ItsYugen
|
||||
- lucasomi
|
||||
- Pkm Sinfonia
|
||||
- Poki Papillon
|
||||
- Fleimer_
|
||||
- bizcoeindoloro
|
||||
- mangalos810
|
||||
- Involuntary-Twitch
|
||||
- selstar
|
||||
- koda_want_to_sleep
|
||||
|
||||
### 🎨 Move Animations
|
||||
- Pokémon Reborn
|
||||
Thank you to all the wonderful people that have contributed to the PokéRogue project! You can find the credits [here](./CREDITS.md).
|
||||
|
117
biome.jsonc
Normal file
@ -0,0 +1,117 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
||||
"vcs": {
|
||||
"enabled": false,
|
||||
"clientKind": "git",
|
||||
"useIgnoreFile": true,
|
||||
"defaultBranch": "beta"
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"useEditorconfig": true,
|
||||
"indentStyle": "space",
|
||||
"ignore": ["src/enums/*", "src/data/balance/*"],
|
||||
"lineWidth": 120
|
||||
},
|
||||
"files": {
|
||||
"ignoreUnknown": true,
|
||||
// Adding folders to the ignore list is GREAT for performance because it prevents biome from descending into them
|
||||
// and having to verify whether each individual file is ignored
|
||||
"ignore": [
|
||||
"**/*.d.ts",
|
||||
"dist/*",
|
||||
"build/*",
|
||||
"coverage/*",
|
||||
"public/*",
|
||||
".github/*",
|
||||
"node_modules/*",
|
||||
".vscode/*",
|
||||
"*.css", // TODO?
|
||||
"*.html", // TODO?
|
||||
"src/overrides.ts",
|
||||
// TODO: these files are too big and complex, ignore them until their respective refactors
|
||||
"src/data/moves/move.ts",
|
||||
"src/data/abilities/ability.ts",
|
||||
"src/field/pokemon.ts",
|
||||
|
||||
// this file is just too big:
|
||||
"src/data/balance/tms.ts"
|
||||
]
|
||||
},
|
||||
|
||||
// While it'd be nice to enable consistent sorting, enabling this causes issues due to circular import resolution order
|
||||
// TODO: Remove if we ever get down to 0 circular imports
|
||||
"organizeImports": { "enabled": false },
|
||||
"linter": {
|
||||
"ignore": [
|
||||
"src/phases/move-effect-phase.ts" // TODO: unignore after move-effect-phase refactor
|
||||
],
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true,
|
||||
"correctness": {
|
||||
"noUndeclaredVariables": "off",
|
||||
"noUnusedVariables": "error",
|
||||
"noSwitchDeclarations": "warn", // TODO: refactor and make this an error
|
||||
"noVoidTypeReturn": "warn", // TODO: Refactor and make this an error
|
||||
"noUnusedImports": "error"
|
||||
},
|
||||
"style": {
|
||||
"noVar": "error",
|
||||
"useEnumInitializers": "off", // large enums like Moves/Species would make this cumbersome
|
||||
"useBlockStatements": "error",
|
||||
"useConst": "error",
|
||||
"useImportType": "error",
|
||||
"noNonNullAssertion": "off", // TODO: Turn this on ASAP and fix all non-null assertions in non-test files
|
||||
"noParameterAssign": "off",
|
||||
"useExponentiationOperator": "off", // Too typo-prone and easy to mixup with standard multiplication (* vs **)
|
||||
"useDefaultParameterLast": "off", // TODO: Fix spots in the codebase where this flag would be triggered, and then enable
|
||||
"useSingleVarDeclarator": "off",
|
||||
"useNodejsImportProtocol": "off",
|
||||
"useTemplate": "off", // string concatenation is faster: https://stackoverflow.com/questions/29055518/are-es6-template-literals-faster-than-string-concatenation
|
||||
"noNamespaceImport": "error"
|
||||
},
|
||||
"suspicious": {
|
||||
"noDoubleEquals": "error",
|
||||
// While this would be a nice rule to enable, the current structure of the codebase makes this infeasible
|
||||
// due to being used for move/ability `args` params and save data-related code.
|
||||
// This can likely be enabled for all non-utils files once these are eventually reworked, but until then we leave it off.
|
||||
"noExplicitAny": "off",
|
||||
"noAssignInExpressions": "off",
|
||||
"noPrototypeBuiltins": "off",
|
||||
"noFallthroughSwitchClause": "error", // Prevents accidental automatic fallthroughs in switch cases (use disable comment if needed)
|
||||
"noImplicitAnyLet": "warn", // TODO: Refactor and make this an error
|
||||
"noRedeclare": "info", // TODO: Refactor and make this an error
|
||||
"noGlobalIsNan": "off",
|
||||
"noAsyncPromiseExecutor": "warn" // TODO: Refactor and make this an error
|
||||
},
|
||||
"complexity": {
|
||||
"noExcessiveCognitiveComplexity": "warn", // TODO: Refactor and make this an error
|
||||
"useLiteralKeys": "off",
|
||||
"noForEach": "off", // Foreach vs for of is not that simple.
|
||||
"noUselessSwitchCase": "off", // Explicit > Implicit
|
||||
"noUselessConstructor": "warn", // TODO: Refactor and make this an error
|
||||
"noBannedTypes": "warn" // TODO: Refactor and make this an error
|
||||
}
|
||||
}
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": { "quoteStyle": "double", "arrowParentheses": "asNeeded" }
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"include": ["test/**/*.test.ts"],
|
||||
"javascript": { "globals": [] },
|
||||
"linter": {
|
||||
"rules": {
|
||||
"performance": {
|
||||
"noDelete": "off" // TODO: evaluate if this is necessary for the test(s) to function
|
||||
},
|
||||
"style": {
|
||||
"noNamespaceImport": "off" // this is required for `vi.spyOn` to work in some tests
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
/**
|
||||
* This script creates a test boilerplate file for a move or ability.
|
||||
* @param {string} type - The type of test to create. Either "move", "ability",
|
||||
* or "item".
|
||||
* @param {string} fileName - The name of the file to create.
|
||||
* @example npm run create-test move tackle
|
||||
* This script creates a test boilerplate file in the appropriate
|
||||
* directory based on the type selected.
|
||||
* @example npm run create-test
|
||||
*/
|
||||
|
||||
import fs from "fs";
|
||||
@ -33,8 +31,9 @@ async function promptTestType() {
|
||||
if (typeAnswer.selectedOption === "EXIT") {
|
||||
console.log("Exiting...");
|
||||
return process.exit();
|
||||
} else if (!typeChoices.includes(typeAnswer.selectedOption)) {
|
||||
console.error('Please provide a valid type ("move", "ability", or "item")!');
|
||||
}
|
||||
if (!typeChoices.includes(typeAnswer.selectedOption)) {
|
||||
console.error(`Please provide a valid type (${typeChoices.join(", ")})!`);
|
||||
return await promptTestType();
|
||||
}
|
||||
|
||||
@ -51,7 +50,7 @@ async function promptFileName(selectedType) {
|
||||
{
|
||||
type: "input",
|
||||
name: "userInput",
|
||||
message: `Please provide a file name for the ${selectedType} test:`,
|
||||
message: `Please provide the name of the ${selectedType}:`,
|
||||
},
|
||||
]);
|
||||
|
||||
@ -76,33 +75,33 @@ async function runInteractive() {
|
||||
const fileName = fileNameAnswer.userInput
|
||||
.replace(/-+/g, "_") // Convert kebab-case (dashes) to underscores
|
||||
.replace(/([a-z])([A-Z])/g, "$1_$2") // Convert camelCase to snake_case
|
||||
.replace(/\s+/g, '_') // Replace spaces with underscores
|
||||
.replace(/\s+/g, "_") // Replace spaces with underscores
|
||||
.toLowerCase(); // Ensure all lowercase
|
||||
// Format the description for the test case
|
||||
|
||||
const formattedName = fileName.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
||||
const formattedName = fileName.replace(/_/g, " ").replace(/\b\w/g, char => char.toUpperCase());
|
||||
// Determine the directory based on the type
|
||||
let dir;
|
||||
let description;
|
||||
switch (type) {
|
||||
case "move":
|
||||
dir = path.join(__dirname, "src", "test", "moves");
|
||||
dir = path.join(__dirname, "test", "moves");
|
||||
description = `Moves - ${formattedName}`;
|
||||
break;
|
||||
case "ability":
|
||||
dir = path.join(__dirname, "src", "test", "abilities");
|
||||
dir = path.join(__dirname, "test", "abilities");
|
||||
description = `Abilities - ${formattedName}`;
|
||||
break;
|
||||
case "item":
|
||||
dir = path.join(__dirname, "src", "test", "items");
|
||||
dir = path.join(__dirname, "test", "items");
|
||||
description = `Items - ${formattedName}`;
|
||||
break;
|
||||
case "mystery encounter":
|
||||
dir = path.join(__dirname, "src", "test", "mystery-encounter", "encounters");
|
||||
dir = path.join(__dirname, "test", "mystery-encounter", "encounters");
|
||||
description = `Mystery Encounter - ${formattedName}`;
|
||||
break;
|
||||
default:
|
||||
console.error('Invalid type. Please use "move", "ability", or "item".');
|
||||
console.error(`Invalid type. Please use one of the following: ${typeChoices.join(", ")}.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@ -110,9 +109,9 @@ async function runInteractive() {
|
||||
const content = `import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import GameManager from "#test/testUtils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
describe("${description}", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
@ -131,15 +130,22 @@ describe("${description}", () => {
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.moveset([Moves.SPLASH])
|
||||
.moveset([ Moves.SPLASH ])
|
||||
.ability(Abilities.BALL_FETCH)
|
||||
.battleType("single")
|
||||
.disableCrits()
|
||||
.enemySpecies(Species.MAGIKARP)
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.enemyMoveset(Moves.SPLASH);
|
||||
});
|
||||
|
||||
it("test case", async () => {
|
||||
// await game.classicMode.startBattle([Species.MAGIKARP]);
|
||||
// game.move.select(Moves.SPLASH);
|
||||
it("should do X", async () => {
|
||||
await game.classicMode.startBattle([ Species.FEEBAS ]);
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to("BerryPhase");
|
||||
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
`;
|
||||
|
@ -10,4 +10,4 @@ for await (const chunk of process.stdin) {
|
||||
const file = Buffer.concat(inputFile).toString("utf-8");
|
||||
|
||||
const svg = graphviz.dot(file, "svg");
|
||||
process.stdout.write(svg);
|
||||
process.stdout.write(svg);
|
||||
|
117
docs/comments.md
@ -1,64 +1,107 @@
|
||||
## How do I comment my code?
|
||||
# Commenting code
|
||||
|
||||
### While we're not enforcing a strict standard, there are some things to keep in mind:
|
||||
People spend more time reading code than writing it (sometimes substantially more so). As such, comments and documentation are **vital** for any large codebase like this.
|
||||
|
||||
## General Guidelines
|
||||
While we're not enforcing a strict standard, here are some things to keep in mind:
|
||||
- Make comments meaningful
|
||||
- Comments should be explaining why a line or block of code exists and what the reason behind it is
|
||||
- Comments should not be repeating chunks of code or explaining what 'true' and 'false' means in typescript
|
||||
- Comments should **NOT** repeat _what_ code _does_[^1] or explain concepts obvious to someone with a basic understanding of the language at hand. Instead, focus on explaining _why_ a line or block of code exists.
|
||||
- Anyone with basic reading comprehension and a good IDE can figure out what code does; gaining a _post hoc_ understanding of the _reasons_ behind its existence takes a lot more digging, effort and bloodshed.
|
||||
- Keep comments readable
|
||||
- A comment's verbosity should roughly scale with the complexity of its subject matter. Some people naturally write shorter or longer comments as a personal style, but summarizing a 300 line function with "does a thing" is about as good as writing nothing. Conversely, writing a paragraph-level response where a basic one-liner would suffice is no less undesirable.
|
||||
- Long comments should ideally be broken into multiple lines at around the 100-120 character mark. This isn't _mandatory_, but avoids unnecessary scrolling in terminals and IDEs.
|
||||
- Make sure comments exist on Functions, Classes, Methods, and Properties
|
||||
- This may be the most important things to comment. When someone goes to use a function/class/method/etc., having a comment reduces the need to flip back and forth between files to figure out how something works. Peek Definition is great until you're three nested functions deep.
|
||||
- The best example of this is JSDoc-style comments as seen below:
|
||||
- When formatted this way, the comment gets shown by intellisense in VS Code or similar IDEs just by hovering over the text!
|
||||
- Functions also show each the comment for parameter as you type them, making keeping track of what each one does in lengthy functions much more clear
|
||||
```js
|
||||
/**
|
||||
* Changes the type-based weather modifier if this move's power would be reduced by it
|
||||
* @param user {@linkcode Pokemon} using this move
|
||||
* @param target {@linkcode Pokemon} target of this move
|
||||
* @param move {@linkcode Move} being used
|
||||
* @param args [0] {@linkcode Utils.NumberHolder} for arenaAttackTypeMultiplier
|
||||
* @returns true if the function succeeds
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
}
|
||||
- These may be the most important things to comment. When someone goes to use a function/class/method/etc., having a comment reduces the need to flip back and forth between files to figure out what XYZ does. Peek Definition is great until you're three nested levels deep.
|
||||
|
||||
/** Set to true when experimental animated sprites from Gen6+ are used */
|
||||
public experimentalSprites: boolean = false;
|
||||
[^1]: With exceptions for extremely long, convoluted or unintuitive methods (though an over-dependency on said comments is likely a symptom of poorly structured code).
|
||||
|
||||
# TSDoc
|
||||
The codebase makes extensive use of [TSDoc](https://tsdoc.org), which is a TypeScript-specific version of [JSDoc](https://jsdoc.app/about-getting-started)
|
||||
that uses similar syntax and attaches to functions, classes, etc.
|
||||
|
||||
When formatted correctly, these comments are shown within VS Code or similar IDEs just by hovering over the function or object.
|
||||
- Functions also show the comment for each parameter as you type them, making keeping track of arguments inside lengthy functions much more clear.
|
||||
|
||||
They can also be used to generate a commentated overview of the codebase. There is a GitHub action that automatically updates [this docs site](https://pagefaultgames.github.io/pokerogue/main/index.html)
|
||||
and you can generate it locally as well via `npm run docs` which will generate into the `typedoc/` directory.
|
||||
|
||||
## Syntax
|
||||
For an example of how TSDoc comments work, here are some TSDoc comments taken from `src/data/moves/move.ts`:
|
||||
```ts
|
||||
/**
|
||||
* Cures the user's party of non-volatile status conditions, ie. Heal Bell, Aromatherapy
|
||||
* @extends MoveAttr
|
||||
* @see {@linkcode apply}
|
||||
* Attribute to put in a {@link https://bulbapedia.bulbagarden.net/wiki/Substitute_(doll) | Substitute Doll} for the user.
|
||||
*/
|
||||
export class DontHealThePartyPlsAttr extends MoveAttr {
|
||||
export class AddSubstituteAttr extends MoveEffectAttr {
|
||||
/** The ratio of the user's max HP that is required to apply this effect */
|
||||
private hpCost: number;
|
||||
/** Whether the damage taken should be rounded up (Shed Tail rounds up) */
|
||||
private roundUp: boolean;
|
||||
|
||||
constructor(hpCost: number, roundUp: boolean) {
|
||||
// code removed
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes 1/4 of the user's maximum HP (rounded down) to create a substitute for the user
|
||||
* @param user - The {@linkcode Pokemon} that used the move.
|
||||
* @param target - n/a
|
||||
* @param move - The {@linkcode Move} with this attribute.
|
||||
* @param args - n/a
|
||||
* @returns `true` if the attribute successfully applies, `false` otherwise
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
// code removed
|
||||
}
|
||||
|
||||
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number {
|
||||
// code removed
|
||||
}
|
||||
|
||||
getCondition(): MoveConditionFunc {
|
||||
// code removed
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the substitute-specific failure message if one should be displayed.
|
||||
* @param user - The pokemon using the move.
|
||||
* @returns The substitute-specific failure message if the conditions apply, otherwise `undefined`
|
||||
*/
|
||||
getFailedText(user: Pokemon, _target: Pokemon, _move: Move): string | undefined {
|
||||
// code removed
|
||||
}
|
||||
}
|
||||
```
|
||||
You'll notice this contains an `{@linkcode Object}` tag for each parameter. This provides an easy type denomination and hyperlink to that type using VS Code's Intellisense. `@linkcode` is used instead of `@link` so that the text appears in monospace which is more obviously a `type` rather than a random hyperlink.
|
||||
|
||||
If you're interested in going more in depth, you can find a reference guide for how comments like these work [here](https://jsdoc.app)
|
||||
Looking at the example given, you'll notice this contains an `{@linkcode XYZ}` tag in some of the parameters. This provides a clickable hyperlink to that type or object in most modern IDEs. (`@linkcode` is used here instead of `@link` so that the text appears in monospace which is more obviously a `type` rather than a random hyperlink.) \
|
||||
Also note the dashes (` - `) between the parameter names and descriptions - these are **mandatory** under the TSDoc spec[^2].
|
||||
|
||||
If you're interested in going more in depth, you can find a reference guide for how comments like these work [on the TSDoc website](https://tsdoc.org).
|
||||
The [playground page](https://tsdoc.org/play/) there can also be used for live testing of examples.
|
||||
|
||||
[^2]: Incidentally, this is also the only place dashes are explicitly _required_.
|
||||
|
||||
### What not to do:
|
||||
- Don't leave comments for code you don't understand
|
||||
- Incorrect information is worse than no information. If you aren't sure how something works, don't make something up to explain it. Ask for help instead.
|
||||
- Incorrect information is worse than no information. If you aren't sure how something works, don't make something up to explain it - ask for help and/or mark it as TODO.
|
||||
- Don't over-comment
|
||||
- Not everything needs an explanation. Try to summarize blocks of code instead of singular lines where possible. Single line comments should call out specific oddities.
|
||||
- Not everything needs a comment. Try to summarize blocks of code instead of singular lines where possible, always preferring giving a reason over stating a fact. Single line comments should call out specific oddities or features.
|
||||
|
||||
## How do Abilities and Moves differ from other classes?
|
||||
While other classes should be fully documented, Abilities and Moves heavily incoperate inheritance (i.e. the `extends` keyword). Because of this, much of the functionality in these classes is duplicated or only slightly changed between classes.
|
||||
### With this in mind, there's a few more things to keep in mind for these:
|
||||
- Do not document any parameters if the function mirrors the one they extend.
|
||||
- Keep this in mind for functions that are not the `apply` function as they are usually sparce and mostly reused
|
||||
- The class itself must be documented
|
||||
- This must include the `@extends BaseClass` and `@see {@linkcode apply}` tags
|
||||
- Keep this in mind for functions that are not the `apply` function as they are usually sparse and mostly reused
|
||||
- Class member variables must be documented
|
||||
- You can use a single line documentation comment for these `/** i.e. a comment like this */`
|
||||
- `args` parameters must be documented if used
|
||||
- This should look something like this when there are multiple:
|
||||
- This should look something vaguely like this when there are multiple:
|
||||
```ts
|
||||
/**
|
||||
...
|
||||
* @param args [0] {@linkcode Utils.NumberHolder} of arenaAttackTypeMultiplier
|
||||
* [1] {@linkcode Utils.BooleanHolder} of cancelled
|
||||
* [2] {@linkcode Utils.BooleanHolder} of rWeDoneYet
|
||||
* @param args -
|
||||
* `[0]` The {@linkcode Move} being used
|
||||
* `[1]` A {@linkcode BooleanHolder} used to track XYZ
|
||||
* `[2]` {@linkcode BooleanHolder} `paramC` - paramC description here
|
||||
...
|
||||
*/
|
||||
```
|
||||
```
|
||||
|
129
docs/enemy-ai.md
@ -37,12 +37,12 @@ The `EnemyCommandPhase` follows this process to determine whether or not an enem
|
||||
1. If the Pokémon has a move already queued (e.g. they are recharging after using Hyper Beam), or they are trapped (e.g. by Bind or Arena Trap), skip to resolving a `FIGHT` command (see next section).
|
||||
2. For each Pokémon in the enemy's party, [compute their matchup scores](#calculating-matchup-scores) against the active player Pokémon. If there are two active player Pokémon in the battle, add their matchup scores together.
|
||||
3. Take the party member with the highest matchup score and apply a multiplier to the score that reduces the score based on how frequently the enemy trainer has switched Pokémon in the current battle.
|
||||
- The multiplier scales off of a counter that increments when the enemy trainer chooses to switch a Pokémon and decrements when they choose to use a move.
|
||||
- The multiplier scales off of a counter that increments when the enemy trainer chooses to switch a Pokémon and decrements when they choose to use a move.
|
||||
4. Compare the result of Step 3 with the active enemy Pokémon's matchup score. If the party member's matchup score is at least three times that of the active Pokémon, switch to that party member.
|
||||
- "Boss" trainers only require the party member's matchup score to be at least two times that of the active Pokémon, so they are more likely to switch than other trainers. The full list of boss trainers in the game is as follows:
|
||||
- All gym leaders, Elite 4 members, and Champions
|
||||
- All Evil Team leaders
|
||||
- The last three Rival Fights (on waves 95, 145, and 195)
|
||||
- "Boss" trainers only require the party member's matchup score to be at least two times that of the active Pokémon, so they are more likely to switch than other trainers. The full list of boss trainers in the game is as follows:
|
||||
- All gym leaders, Elite 4 members, and Champions
|
||||
- All Evil Team leaders
|
||||
- The last three Rival Fights (on waves 95, 145, and 195)
|
||||
5. If the enemy decided to switch, send a switch `turnCommand` and end this `EnemyCommandPhase`; otherwise, move on to resolving a `FIGHT` enemy command.
|
||||
|
||||
## Step 2: Selecting a Move
|
||||
@ -54,34 +54,41 @@ At this point, the enemy (a wild or trainer Pokémon) has decided against switch
|
||||
In `getNextMove()`, the enemy Pokémon chooses a move to use in the following steps:
|
||||
1. If the Pokémon has a move in its Move Queue (e.g. the second turn of a charging move), and the queued move is still usable, use that move against the given target.
|
||||
2. Filter out any moves it can't use within its moveset. The remaining moves make up the enemy's **move pool** for the turn.
|
||||
1. A move can be unusable if it has no PP left or it has been disabled by another move or effect
|
||||
2. If the enemy's move pool is empty, use Struggle.
|
||||
1. A move can be unusable if it has no PP left or it has been disabled by another move or effect.
|
||||
2. If the enemy's move pool is empty, use Struggle.
|
||||
3. Calculate the **move score** of each move in the enemy's move pool.
|
||||
1. A move's move score is equivalent to the move's maximum **target score** among all of the move's possible targets on the field ([more on this later](#calculating-move-and-target-scores)).
|
||||
2. A move's move score is set to -20 if at least one of these conditions are met:
|
||||
- The move is unimplemented (or, more precisely, the move's name ends with " (N)").
|
||||
- Conditions for the move to succeed are not met (unless the move is Sucker Punch, Upper Hand, or Thunderclap, as those moves' conditions can't be resolved before the turn starts).
|
||||
- The move's target scores are 0 or `NaN` for each target. In this case, the game assumes the target score calculation for that move is unimplemented.
|
||||
1. A move's move score is equivalent to the move's maximum **target score** among all of the move's possible targets on the field ([more on this later](#calculating-move-and-target-scores)).
|
||||
2. A move's move score is set to -20 if at least one of these conditions are met:
|
||||
- The move is unimplemented (or, more precisely, the move's name ends with "(N)").
|
||||
- Conditions for the move to succeed are not met (unless the move is Sucker Punch, Upper Hand or Thunderclap, as those moves' conditions can't be resolved until after the turn starts).
|
||||
- The move's target scores are 0 or `NaN` for each target. In this case, the game assumes the target score calculation for that move is unimplemented.
|
||||
4. Sort the move pool in descending order of move scores.
|
||||
5. From here, the enemy's move selection varies based on its `aiType`. If the enemy is a Boss Pokémon or has a Trainer, it uses the `SMART` AI type; otherwise, it uses the `SMART_RANDOM` AI type.
|
||||
1. Let $m_i$ be the *i*-th move in the sorted move pool $M$:
|
||||
- If `aiType === SMART_RANDOM`, the enemy has a 5/8 chance of selecting $m_0$ and a 3/8 chance of advancing to the next best move $m_1$, where it then repeats this roll. This process stops when a move is selected or the last move in the move pool is reached.
|
||||
- If `aiType === SMART`, a similar loop is used to decide between selecting the move $m_i$ and advancing to the next iteration with the move $m_{i+1}$. However, instead of using a flat probability, the following conditions need to be met to advance from selecting $m_i$ to $m_{i+1}$:
|
||||
- $\text{sign}(s_i) = \text{sign}(s_{i+1})$, where $s_i$ is the move score of $m_i$.
|
||||
- $\text{randInt}(0, 100) < \text{round}(\frac{s_{i+1}}{s_i}\times 50)$. In other words: if the scores of $m_i$ and $m_{i+1}$ have the same sign, the chance to advance to the next iteration with $m_{i+1}$ is proportional to how close the scores are to each other. The probability to advance to the next iteration is at most 50 percent (when $s_i$ and $s_{i+1}$ are equal).
|
||||
1. Let $m_i$ be the *i*-th move in the sorted move pool $M$:
|
||||
- If `aiType === SMART_RANDOM`, the enemy has a 5/8 chance of selecting $m_0$ and a 3/8 chance of advancing to the next best move $m_1$, where it then repeats this roll. This process stops when a move is selected or the last move in the move pool is reached.
|
||||
- If `aiType === SMART`, a similar loop is used to decide between selecting the move $m_i$ and advancing to the next iteration with the move $m_{i+1}$. However, instead of using a flat probability, the following conditions need to be met to advance from selecting $m_i$ to $m_{i+1}$:
|
||||
- $\text{sign}(s_i) = \text{sign}(s_{i+1})$, where $s_i$ is the move score of $m_i$.
|
||||
- $\text{randInt}(0, 100) < \text{round}(\frac{s_{i+1}}{s_i}\times 50)$. In other words: if the scores of $m_i$ and $m_{i+1}$ have the same sign, the chance to advance to the next iteration with $m_{i+1}$ is proportional to how close the scores are to each other. The probability to advance to the next iteration is at most 50 percent (when $s_i$ and $s_{i+1}$ are equal).
|
||||
6. The enemy will use the move selected in Step 5 against the target(s) with the highest [**target selection score (TSS)**](#choosing-targets-with-getnexttargets)
|
||||
|
||||
### Calculating Move and Target Scores
|
||||
|
||||
As part of the move selection process, the enemy Pokémon must compute a **target score (TS)** for each legal target for each move in its move pool. The base target score for all moves is a combination of the move's **user benefit score (UBS)** and **target benefit score (TBS)**.
|
||||
As part of the move selection process, the enemy Pokémon must compute a **target score (TS)** for each legal target for each move in its move pool. The base target score is a combination of the move's **user benefit score (UBS)** and **target benefit score (TBS)**, representing how much the move helps or hinders the user and/or its target(s).
|
||||
|
||||

|
||||
$$
|
||||
\text{TS} = \text{UBS} + \left( \text{TBS} \times
|
||||
\begin{cases}
|
||||
-1 & \text{if target is an opponent} \\
|
||||
1 & \text{otherwise}
|
||||
\end{cases}
|
||||
\right)
|
||||
$$
|
||||
|
||||
A move's UBS and TBS are computed with the respective functions in the `Move` class:
|
||||
|
||||
```ts
|
||||
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer;
|
||||
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer;
|
||||
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number;
|
||||
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number;
|
||||
```
|
||||
|
||||
Logically, these functions are very similar – they add up their respective benefit scores from each of the move's attributes (as determined by `attr.getUserBenefitScore`, and `attr.getTargetBenefitScore`, respectively) and return the total benefit score. However, there are two key functional differences in how the UBS and TBS of a move are handled:
|
||||
@ -96,19 +103,38 @@ In addition to the base score from `Move.getTargetBenefitScore()`, attack moves
|
||||
- The move's category (Physical/Special), and whether the user has a higher Attack or Special Attack stat.
|
||||
|
||||
More specifically, the following steps are taken to compute the move's `attackScore`:
|
||||
1. Compute a multiplier based on the move's type effectiveness:
|
||||
1. Compute a multiplier based on the move's type effectiveness:
|
||||
|
||||
%7D%5C%5C-2&&%5Ctext%7Botherwise%7D%5C%5C%5Cend%7Bmatrix%7D%5Cright.)
|
||||
$$
|
||||
\text{typeMult} =
|
||||
\begin{cases}
|
||||
2 & \text{if move is super effective (or better)} \\
|
||||
-2 & \text{otherwise}
|
||||
\end{cases}
|
||||
$$
|
||||
2. Compute a multiplier based on the move's category and the user's offensive stats:
|
||||
1. Compute the user's offensive stat ratio:
|
||||
|
||||

|
||||
2. Compute the stat-based multiplier:
|
||||
1. Compute the user's offensive stat ratio:
|
||||
|
||||

|
||||
$$
|
||||
\text{statRatio} =
|
||||
\begin{cases}
|
||||
\frac{\text{userSpAtk}}{\text{userAtk}} & \text{if move is physical} \\
|
||||
\frac{\text{userAtk}}{\text{userSpAtk}} & \text{otherwise}
|
||||
\end{cases}
|
||||
$$
|
||||
2. Compute the stat-based multiplier:
|
||||
|
||||
$$
|
||||
\text{statMult} =
|
||||
\begin{cases}
|
||||
2 & \text{if statRatio} \leq 0.75 \\
|
||||
1.5 & \text{if } 0.75 \leq \text{statRatio} \leq 0.875 \\
|
||||
1 & \text{otherwise}
|
||||
\end{cases}
|
||||
$$
|
||||
3. Calculate the move's `attackScore`:
|
||||
|
||||
$\text{attackScore} = (\text{typeMult}\times \text{statMult})+\lfloor \frac{\text{power}}{5} \rfloor$
|
||||
$\text{attackScore} = (\text{typeMult}\times \text{statMult})+\lfloor \frac{\text{power}}{5} \rfloor$
|
||||
|
||||
The maximum total multiplier in `attackScore` ($\text{typeMult}\times \text{statMult}$) is 4, which occurs for attacks that are super effective against the target and are categorically aligned with the user's offensive stats (e.g. the move is physical, and the user has much higher Attack than Sp. Atk). The minimum total multiplier of -4 occurs (somewhat confusingly) for attacks that are not super effective but are categorically aligned with the user's offensive stats.
|
||||
|
||||
@ -125,18 +151,31 @@ The final step to calculate an attack move's target score (TS) is to multiply th
|
||||
|
||||
The enemy's target selection for single-target moves works in a very similar way to its move selection. Each potential target is given a **target selection score (TSS)** which is based on the move's [target benefit score](#calculating-move-and-target-scores) for that target:
|
||||
|
||||

|
||||
$$
|
||||
\text{TSS} = \text{TBS} \times
|
||||
\begin{cases}
|
||||
-1 & \text{if target is an opponent} \\
|
||||
1 & \text{otherwise}
|
||||
\end{cases}
|
||||
$$
|
||||
|
||||
Once the TSS is calculated for each target, the target is selected as follows:
|
||||
1. Sort the targets (indexes) in decreasing order of their target selection scores (or weights). Let $t_i$ be the index of the *i*-th target in the sorted list, and let $w_i$ be that target's corresponding TSS.
|
||||
2. Normalize the weights. Let $w_n$ be the lowest-weighted target in the sorted list, then:
|
||||
|
||||

|
||||
|
||||
$$
|
||||
W_i =
|
||||
\begin{cases}
|
||||
w_i + |w_n| & \text{if } w_n \text{ is negative} \\
|
||||
w_i & \text{otherwise}
|
||||
\end{cases}
|
||||
$$
|
||||
|
||||
3. Remove all weights from the list such that $W_i < \frac{W_0}{2}$
|
||||
4. Generate a random integer $R=\text{rand}(0, W_{\text{total}})$ where $W_{\text{total}}$ is the sum of all the remaining weights after Step 3.
|
||||
5. For each target $(t_i, W_i)$,
|
||||
1. if $R \le \sum_{j=0}^{i} W_i$, or if $t_i$ is the last target in the list, **return** $t_i$
|
||||
2. otherwise, advance to the next target $t_{i+1}$ and repeat this check.
|
||||
1. if $R \le \sum_{j=0}^{i} W_i$, or if $t_i$ is the last target in the list, **return** $t_i$
|
||||
2. otherwise, advance to the next target $t_{i+1}$ and repeat this check.
|
||||
|
||||
Once the target is selected, the enemy has successfully determined its next action for the turn, and its corresponding `EnemyCommandPhase` ends. From here, the `TurnStartPhase` processes the enemy's commands alongside the player's commands and begins to resolve the turn.
|
||||
|
||||
@ -145,15 +184,15 @@ Once the target is selected, the enemy has successfully determined its next acti
|
||||
Suppose you enter a single battle against an enemy trainer with the following Pokémon in their party:
|
||||
|
||||
1. An [Excadrill](https://bulbapedia.bulbagarden.net/wiki/Excadrill_(Pok%C3%A9mon)) with the Ability Sand Force and the following moveset
|
||||
1. Earthquake
|
||||
2. Iron Head
|
||||
3. Crush Claw
|
||||
4. Swords Dance
|
||||
1. Earthquake
|
||||
2. Iron Head
|
||||
3. Crush Claw
|
||||
4. Swords Dance
|
||||
2. A [Heatmor](https://bulbapedia.bulbagarden.net/wiki/Heatmor_(Pok%C3%A9mon)) with the Ability Flash Fire and the following moveset
|
||||
1. Fire Lash
|
||||
2. Inferno
|
||||
3. Hone Claws
|
||||
4. Shadow Claw
|
||||
1. Fire Lash
|
||||
2. Inferno
|
||||
3. Hone Claws
|
||||
4. Shadow Claw
|
||||
|
||||
The enemy trainer leads with their Heatmor, and you lead with a [Dachsbun](https://bulbapedia.bulbagarden.net/wiki/Dachsbun_(Pok%C3%A9mon)) with the Ability Well-Baked Body. We'll cover the enemy's behavior over the next two turns.
|
||||
|
||||
@ -172,13 +211,13 @@ Based on the enemy party's matchup scores, whether or not the trainer switches o
|
||||
Now that the enemy Pokémon with the best matchup score is on the field (assuming it survives Dachsbun's attack on the last turn), the enemy will now decide to have Excadrill use one of its moves. Assuming all of its moves are usable, we'll go through the target score calculations for each move:
|
||||
|
||||
- **Earthquake**: In a single battle, this move is just a 100-power Ground-type physical attack with no additional effects. With no additional benefit score from attributes, the move's base target score against the player's Dachsbun is just the `attackScore` from `AttackMove.getTargetBenefitScore()`. In this case, Earthquake's `attackScore` is given by
|
||||
|
||||
|
||||
$\text{attackScore}=(\text{typeMult}\times \text{statMult}) + \lfloor \frac{\text{power}}{5} \rfloor = -2\times 2 + 20 = 16$
|
||||
|
||||
Here, `typeMult` is -2 because the move is not super effective, and `statMult` is 2 because Excadrill's Attack is significantly higher than its Sp. Atk. Accounting for STAB thanks to Excadrill's typing, the final target score for this move is **24**
|
||||
|
||||
- **Iron Head**: This move is an 80-power Steel-type physical attack with an additional chance to cause the target to flinch. With these properties, Iron Head has a user benefit score of 0 and a target benefit score given by
|
||||
|
||||
|
||||
$\text{TBS}=\text{getTargetBenefitScore(FlinchAttr)}-\text{attackScore}$
|
||||
|
||||
Under its current implementation, the target benefit score of `FlinchAttr` is -5. Calculating the move's `attackScore`, we get:
|
||||
@ -198,7 +237,7 @@ Now that the enemy Pokémon with the best matchup score is on the field (assumin
|
||||
where `levels` is the number of stat stages added by the attribute (in this case, +2). The final score for this move is **6** (Note: because this move is self-targeted, we don't flip the sign of TBS when computing the target score).
|
||||
|
||||
- **Crush Claw**: This move is a 75-power Normal-type physical attack with a 50 percent chance to lower the target's Defense by one stage. The additional effect is implemented by the same `StatStageChangeAttr` as Swords Dance, so we can use the same formulas from before to compute the total TBS and base target score.
|
||||
|
||||
|
||||
$\text{TBS}=\text{getTargetBenefitScore(StatStageChangeAttr)}-\text{attackScore}$
|
||||
|
||||
$\text{TBS}=(-4 + 2)-(-2\times 2 + \lfloor \frac{75}{5} \rfloor)=-2-11=-13$
|
||||
|
@ -1,40 +1,65 @@
|
||||
# ESLint
|
||||
## Key Features
|
||||
# Linting & Formatting
|
||||
|
||||
1. **Automation**:
|
||||
- A pre-commit hook has been added to automatically run ESLint on the added or modified files, ensuring code quality before commits.
|
||||
> "Any fool can write code that a computer can understand. Good programmers write code that humans can understand."
|
||||
>
|
||||
> — Martin Fowler
|
||||
|
||||
2. **Manual Usage**:
|
||||
- If you prefer not to use the pre-commit hook, you can manually run ESLint to automatically fix issues using the command:
|
||||
```sh
|
||||
npx eslint --fix . or npm run eslint
|
||||
```
|
||||
- Running this command will lint all files in the repository.
|
||||
Writing clean, readable code is important, and linters and formatters are an integral part of ensuring code quality and readability.
|
||||
It is for this reason we are using [Biome](https://biomejs.dev), an opinionated linter/formatter (akin to Prettier) with a heavy focus on speed and performance.
|
||||
|
||||
3. **GitHub Action**:
|
||||
- A GitHub Action has been added to automatically run ESLint on every push and pull request, ensuring code quality in the CI/CD pipeline.
|
||||
### Installation
|
||||
You probably installed Biome already without noticing it - it's included inside `package.json` and should've been downloaded when you ran `npm install` after cloning the repo (assuming you followed proper instructions, that is). If you haven't done that yet, go do it.
|
||||
|
||||
## Summary of ESLint Rules
|
||||
# Using Biome
|
||||
|
||||
1. **General Rules**:
|
||||
- **Equality**: Use `===` and `!==` instead of `==` and `!=` (`eqeqeq`).
|
||||
- **Indentation**: Enforce 2-space indentation (`indent`).
|
||||
- **Quotes**: Use doublequotes for strings (`quotes`).
|
||||
- **Variable Declarations**:
|
||||
- Disallow `var`; use `let` or `const` (`no-var`).
|
||||
- Prefer `const` for variables that are never reassigned (`prefer-const`).
|
||||
- **Unused Variables**: Allow unused function parameters but enforce error for other unused variables (`@typescript-eslint/no-unused-vars`).
|
||||
- **End of Line**: Ensure at least one newline at the end of files (`eol-last`).
|
||||
- **Curly Braces**: Enforce the use of curly braces for all control statements (`curly`).
|
||||
- **Brace Style**: Use one true brace style (`1tbs`) for TypeScript-specific syntax (`@typescript-eslint/brace-style`).
|
||||
For the most part, Biome attempts to stay "out of your hair", letting you write code while enforcing a consistent formatting standard and only notifying for errors it can't automatically fix.\
|
||||
On the other hand, if Biome complains about a piece of code, **there's probably a good reason why**. Disable comments should be used sparingly or when readabilty demands it - your first instinct should be to fix the code in question, not disable the rule.
|
||||
|
||||
2. **TypeScript-Specific Rules**:
|
||||
- **Semicolons**:
|
||||
- Enforce semicolons for TypeScript-specific syntax (`@typescript-eslint/semi`).
|
||||
- Disallow unnecessary semicolons (`@typescript-eslint/no-extra-semi`).
|
||||
## Editor Integration
|
||||
Biome has integration with many popular code editors. See [these](https://biomejs.dev/guides/editors/first-party-extensions/) [pages](https://biomejs.dev/guides/editors/third-party-extensions/) for information about enabling Biome in your editor of choice.
|
||||
|
||||
## Benefits
|
||||
## Automated Runs
|
||||
Generally speaking, most users shouldn't need to run Biome directly; in addition to editor integration, [pre-commit hook](../lefthook.yml) will periodically run Biome before each commit.
|
||||
You will **not** be able to push code with `error`-level linting problems - fix them beforehand.
|
||||
|
||||
- **Consistency**: Ensures consistent coding style across the project.
|
||||
- **Code Quality**: Helps catch potential errors and improve overall code quality.
|
||||
- **Readability**: Makes the codebase easier to read and maintain.
|
||||
We also have a [Github Action](../.github/workflows/quality.yml) to verify code quality each time a PR is updated, preventing bad code from inadvertently making its way upstream.
|
||||
|
||||
### Why am I getting errors for code I didn't write?
|
||||
<!-- TODO: Remove this if/when we perform a project wide linting spree -->
|
||||
To save time and minimize friction with existing code, both the pre-commit hook and workflow run will only check files **directly changed** by a given PR or commit.
|
||||
As a result, changes to files not updated since Biome's introduction can cause any _prior_ linting errors in them to resurface and get flagged.
|
||||
This should occur less and less often as time passes and more files are updated to the new standard.
|
||||
|
||||
## Running Biome via CLI
|
||||
If you want Biome to check your files manually, you can run it from the command line like so:
|
||||
|
||||
```sh
|
||||
npx biome check --[flags]
|
||||
```
|
||||
|
||||
A full list of flags and options can be found on [their website](https://biomejs.dev/reference/cli/), but here's a few useful ones to keep in mind:
|
||||
|
||||
- `--write` will cause Biome to write all "safe" fixes and formatting changes directly to your files (rather than just complaining and doing nothing).
|
||||
- `--changed` and `--staged` will only perform checks on all changed or staged files respectively. Biome sources this info from the relevant version control system (in this case Git).
|
||||
- `diagnostic-level=XXX` will only show diagnostics with at least the given severity level (`info/warn/error`). Useful to only focus on errors causing a failed workflow run or similar.
|
||||
|
||||
## Linting Rules
|
||||
|
||||
We primarily use Biome's [recommended ruleset](https://biomejs.dev/linter/rules/) for linting JS/TS, with some customizations to better suit our project's needs[^1].
|
||||
|
||||
Some things to consider:
|
||||
|
||||
- We have disabled rules that prioritize style over performance, such as `useTemplate`.
|
||||
- Some rules are currently disabled or marked as warnings (`warn`) to allow for gradual refactoring without blocking development. **Do not write new code that triggers these warnings.**
|
||||
- The linter is configured to ignore specific files and folders (such as excessively large files or ones in need of refactoring) to improve performance and focus on actionable areas.
|
||||
|
||||
Any questions about linting rules should be brought up in the `#dev-corner` channel in the discord.
|
||||
|
||||
[^1]: A complete list of rules can be found in the `biome.jsonc` file in the project root.
|
||||
|
||||
## What about ESLint?
|
||||
|
||||
<!-- Remove if/when we finally ditch eslint for good -->
|
||||
Our project migrated away from ESLint around March 2025 due to it simply not scaling well enough with the codebase's ever-growing size. The [existing eslint rules](../eslint.config.js) are considered _deprecated_, only kept due to Biome lacking the corresponding rules in its current ruleset.
|
||||
|
||||
No additional ESLint rules should be added under any circumstances - even the few currently in circulation take longer to run than the entire Biome formatting/linting suite combined.
|
@ -1,46 +1,43 @@
|
||||
import tseslint from '@typescript-eslint/eslint-plugin';
|
||||
import stylisticTs from '@stylistic/eslint-plugin-ts'
|
||||
import parser from '@typescript-eslint/parser';
|
||||
import importX from 'eslint-plugin-import-x';
|
||||
/** @ts-check */
|
||||
import tseslint from "typescript-eslint";
|
||||
import stylisticTs from "@stylistic/eslint-plugin-ts";
|
||||
import parser from "@typescript-eslint/parser";
|
||||
import importX from "eslint-plugin-import-x";
|
||||
|
||||
export default [
|
||||
{
|
||||
files: ["src/**/*.{ts,tsx,js,jsx}"],
|
||||
ignores: ["dist/*", "build/*", "coverage/*", "public/*", ".github/*", "node_modules/*", ".vscode/*"],
|
||||
languageOptions: {
|
||||
parser: parser
|
||||
},
|
||||
plugins: {
|
||||
"import-x": importX,
|
||||
'@stylistic/ts': stylisticTs,
|
||||
'@typescript-eslint': tseslint
|
||||
},
|
||||
rules: {
|
||||
"eqeqeq": ["error", "always"], // Enforces the use of === and !== instead of == and !=
|
||||
"indent": ["error", 2], // Enforces a 2-space indentation
|
||||
"quotes": ["error", "double"], // Enforces the use of double quotes for strings
|
||||
"no-var": "error", // Disallows the use of var, enforcing let or const instead
|
||||
"prefer-const": "error", // Prefers the use of const for variables that are never reassigned
|
||||
"no-undef": "off", // Disables the rule that disallows the use of undeclared variables (TypeScript handles this)
|
||||
"@typescript-eslint/no-unused-vars": [ "error", {
|
||||
"args": "none", // Allows unused function parameters. Useful for functions with specific signatures where not all parameters are always used.
|
||||
"ignoreRestSiblings": true // Allows unused variables that are part of a rest property in object destructuring. Useful for excluding certain properties from an object while using the rest.
|
||||
}],
|
||||
"eol-last": ["error", "always"], // Enforces at least one newline at the end of files
|
||||
"@stylistic/ts/semi": ["error", "always"], // Requires semicolons for TypeScript-specific syntax
|
||||
"semi": "off", // Disables the general semi rule for TypeScript files
|
||||
"no-extra-semi": ["error"], // Disallows unnecessary semicolons for TypeScript-specific syntax
|
||||
"brace-style": "off", // Note: you must disable the base rule as it can report incorrect errors
|
||||
"curly": ["error", "all"], // Enforces the use of curly braces for all control statements
|
||||
"@stylistic/ts/brace-style": ["error", "1tbs"],
|
||||
"no-trailing-spaces": ["error", { // Disallows trailing whitespace at the end of lines
|
||||
"skipBlankLines": false, // Enforces the rule even on blank lines
|
||||
"ignoreComments": false // Enforces the rule on lines containing comments
|
||||
}],
|
||||
"space-before-blocks": ["error", "always"], // Enforces a space before blocks
|
||||
"keyword-spacing": ["error", { "before": true, "after": true }], // Enforces spacing before and after keywords
|
||||
"comma-spacing": ["error", { "before": false, "after": true }], // Enforces spacing after comma
|
||||
"import-x/extensions": ["error", "never", { "json": "always" }], // Enforces no extension for imports unless json
|
||||
}
|
||||
}
|
||||
]
|
||||
export default tseslint.config(
|
||||
{
|
||||
name: "eslint-config",
|
||||
files: ["src/**/*.{ts,tsx,js,jsx}", "test/**/*.{ts,tsx,js,jsx}"],
|
||||
ignores: ["dist/*", "build/*", "coverage/*", "public/*", ".github/*", "node_modules/*", ".vscode/*"],
|
||||
languageOptions: {
|
||||
parser: parser,
|
||||
},
|
||||
plugins: {
|
||||
"import-x": importX,
|
||||
"@stylistic/ts": stylisticTs,
|
||||
"@typescript-eslint": tseslint.plugin,
|
||||
},
|
||||
rules: {
|
||||
"no-undef": "off", // Disables the rule that disallows the use of undeclared variables (TypeScript handles this)
|
||||
"no-extra-semi": "error", // Disallows unnecessary semicolons for TypeScript-specific syntax
|
||||
"import-x/extensions": ["error", "never", { json: "always" }], // Enforces no extension for imports unless json
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "eslint-tests",
|
||||
files: ["test/**/**.test.ts"],
|
||||
languageOptions: {
|
||||
parser: parser,
|
||||
parserOptions: {
|
||||
project: ["./tsconfig.json"],
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
"@typescript-eslint": tseslint.plugin,
|
||||
},
|
||||
rules: {
|
||||
"@typescript-eslint/no-floating-promises": "error", // Require Promise-like statements to be handled appropriately. - https://typescript-eslint.io/rules/no-floating-promises/
|
||||
"@typescript-eslint/no-misused-promises": "error", // Disallow Promises in places not designed to handle them. - https://typescript-eslint.io/rules/no-misused-promises/
|
||||
},
|
||||
},
|
||||
);
|
||||
|
14
global.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import type { SetupServerApi } from "msw/node";
|
||||
|
||||
export {};
|
||||
|
||||
declare global {
|
||||
/**
|
||||
* Only used in testing.
|
||||
* Can technically be undefined/null but for ease of use we are going to assume it is always defined.
|
||||
* Used to load i18n files exclusively.
|
||||
*
|
||||
* To set up your own server in a test see `game_data.test.ts`
|
||||
*/
|
||||
var server: SetupServerApi;
|
||||
}
|
194
index.css
@ -11,7 +11,7 @@ html {
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display:flex;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: #484050;
|
||||
@ -49,16 +49,17 @@ body {
|
||||
|
||||
@media (pointer: coarse) {
|
||||
/* hasTouchscreen() && !isTouchControlsEnabled */
|
||||
body:has(> #touchControls[class=visible]) #app {
|
||||
body:has(> #touchControls[class="visible"]) #app {
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
body:has(> #touchControls[class=visible]) #app > div:first-child {
|
||||
body:has(> #touchControls[class="visible"]) #app > div:first-child {
|
||||
transform-origin: top !important;
|
||||
}
|
||||
}
|
||||
|
||||
#layout:fullscreen #dpad, #layout:fullscreen {
|
||||
#layout:fullscreen #dpad,
|
||||
#layout:fullscreen {
|
||||
bottom: 6rem;
|
||||
}
|
||||
|
||||
@ -67,6 +68,10 @@ input:-internal-autofill-selected {
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
input:-webkit-autofill {
|
||||
-webkit-text-fill-color: #a1a1a1;
|
||||
}
|
||||
|
||||
/* Need adjust input font-size */
|
||||
input {
|
||||
font-size: 3.2rem;
|
||||
@ -76,7 +81,6 @@ input {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
input:-internal-autofill-selected {
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
@ -91,18 +95,33 @@ input:-internal-autofill-selected {
|
||||
|
||||
--controls-padding: 1rem;
|
||||
|
||||
--controls-size-with-padding: calc(var(--controls-size) + var(--controls-padding));
|
||||
--controls-size-with-wide-padding: calc(var(--controls-size) *1.2 + var(--controls-padding));
|
||||
--controls-size-with-padding: calc(
|
||||
var(--controls-size) +
|
||||
var(--controls-padding)
|
||||
);
|
||||
--controls-size-with-wide-padding: calc(
|
||||
var(--controls-size) *
|
||||
1.2 +
|
||||
var(--controls-padding)
|
||||
);
|
||||
--control-group-extra-size: calc(var(--controls-size) * 0.8);
|
||||
--control-group-extra-wide-size: calc(var(--controls-size) * 1.2);
|
||||
|
||||
--control-group-extra-2-offset: calc(var(--controls-size-with-padding) + (var(--controls-size) - var(--control-group-extra-size)) / 2);
|
||||
--control-group-extra-1-offset: calc(var(--controls-padding) + (var(--controls-size) - var(--control-group-extra-size)) / 2);
|
||||
--control-group-extra-2-offset: calc(
|
||||
var(--controls-size-with-padding) +
|
||||
(var(--controls-size) - var(--control-group-extra-size)) /
|
||||
2
|
||||
);
|
||||
--control-group-extra-1-offset: calc(
|
||||
var(--controls-padding) +
|
||||
(var(--controls-size) - var(--control-group-extra-size)) /
|
||||
2
|
||||
);
|
||||
|
||||
--small-control-size: calc(var(--controls-size) / 3);
|
||||
--rect-control-size: calc(var(--controls-size) * 0.74);
|
||||
|
||||
font-family: 'emerald';
|
||||
font-family: "emerald";
|
||||
font-size: var(--controls-size);
|
||||
text-shadow: var(--color-dark) var(--text-shadow-size) var(--text-shadow-size);
|
||||
color: var(--color-light);
|
||||
@ -146,32 +165,69 @@ input:-internal-autofill-selected {
|
||||
/* Hide buttons on specific UIs */
|
||||
|
||||
/* Show #apadPreviousTab and #apadNextTab only in settings, except in touch configuration panel */
|
||||
#touchControls:not([data-ui-mode^='SETTINGS']) #apadPreviousTab,
|
||||
#touchControls:not([data-ui-mode^='SETTINGS']) #apadNextTab,
|
||||
#touchControls:not([data-ui-mode^="SETTINGS"]) #apadPreviousTab,
|
||||
#touchControls:not([data-ui-mode^="SETTINGS"]) #apadNextTab,
|
||||
#touchControls:is(.config-mode) #apadPreviousTab,
|
||||
#touchControls:is(.config-mode) #apadNextTab {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Show #apadInfo only in battle */
|
||||
#touchControls:not([data-ui-mode='COMMAND']):not([data-ui-mode='FIGHT']):not([data-ui-mode='BALL']):not([data-ui-mode='TARGET_SELECT']) #apadInfo {
|
||||
#touchControls:not([data-ui-mode="COMMAND"]):not([data-ui-mode="FIGHT"]):not(
|
||||
[data-ui-mode="BALL"]
|
||||
):not([data-ui-mode="TARGET_SELECT"])
|
||||
#apadInfo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Show #apadStats only in battle and shop */
|
||||
#touchControls:not([data-ui-mode='COMMAND']):not([data-ui-mode='FIGHT']):not([data-ui-mode='BALL']):not([data-ui-mode='TARGET_SELECT']):not([data-ui-mode='MODIFIER_SELECT']) #apadStats {
|
||||
#touchControls:not([data-ui-mode="COMMAND"]):not([data-ui-mode="FIGHT"]):not(
|
||||
[data-ui-mode="BALL"]
|
||||
):not([data-ui-mode="TARGET_SELECT"]):not([data-ui-mode="MODIFIER_SELECT"])
|
||||
#apadStats {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Show cycle buttons only on STARTER_SELECT and on touch configuration panel */
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT']) #apadOpenFilters,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='RUN_INFO']) #apadCycleForm,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='RUN_INFO']) #apadCycleShiny,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT']) #apadCycleNature,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='RUN_INFO']) #apadCycleAbility,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT']) #apadCycleGender,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT']) #apadCycleVariant {
|
||||
display: none;
|
||||
#touchControls:not(.config-mode):not(
|
||||
[data-ui-mode="STARTER_SELECT"],
|
||||
[data-ui-mode="POKEDEX"],
|
||||
[data-ui-mode="POKEDEX_PAGE"]
|
||||
)
|
||||
#apadOpenFilters,
|
||||
#touchControls:not(.config-mode):not(
|
||||
[data-ui-mode="STARTER_SELECT"],
|
||||
[data-ui-mode="POKEDEX"],
|
||||
[data-ui-mode="POKEDEX_PAGE"],
|
||||
[data-ui-mode="RUN_INFO"]
|
||||
)
|
||||
#apadCycleForm,
|
||||
#touchControls:not(.config-mode):not(
|
||||
[data-ui-mode="STARTER_SELECT"],
|
||||
[data-ui-mode="POKEDEX"],
|
||||
[data-ui-mode="POKEDEX_PAGE"],
|
||||
[data-ui-mode="RUN_INFO"]
|
||||
)
|
||||
#apadCycleShiny,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode="STARTER_SELECT"])
|
||||
#apadCycleNature,
|
||||
#touchControls:not(.config-mode):not(
|
||||
[data-ui-mode="STARTER_SELECT"],
|
||||
[data-ui-mode="POKEDEX_PAGE"],
|
||||
[data-ui-mode="RUN_INFO"]
|
||||
)
|
||||
#apadCycleAbility,
|
||||
#touchControls:not(.config-mode):not(
|
||||
[data-ui-mode="STARTER_SELECT"],
|
||||
[data-ui-mode="POKEDEX_PAGE"]
|
||||
)
|
||||
#apadCycleGender,
|
||||
#touchControls:not(.config-mode):not(
|
||||
[data-ui-mode="STARTER_SELECT"],
|
||||
[data-ui-mode="POKEDEX"]
|
||||
)
|
||||
#apadCycleTera {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Configuration toolbar */
|
||||
@ -217,16 +273,18 @@ input:-internal-autofill-selected {
|
||||
font-size: var(--small-control-size);
|
||||
border-radius: 8px;
|
||||
padding: 2px 8px;
|
||||
text-shadow: var(--color-dark) calc(var(--text-shadow-size) / 3) calc(var(--text-shadow-size) / 3);
|
||||
text-shadow: var(--color-dark) calc(var(--text-shadow-size) / 3)
|
||||
calc(var(--text-shadow-size) / 3);
|
||||
}
|
||||
|
||||
#configToolbar .button:active {
|
||||
opacity: var(--touch-control-opacity)
|
||||
opacity: var(--touch-control-opacity);
|
||||
}
|
||||
|
||||
#configToolbar .orientation-label {
|
||||
font-size: var(--small-control-size);
|
||||
text-shadow: var(--color-dark) calc(var(--text-shadow-size) / 3) calc(var(--text-shadow-size) / 3);
|
||||
text-shadow: var(--color-dark) calc(var(--text-shadow-size) / 3)
|
||||
calc(var(--text-shadow-size) / 3);
|
||||
}
|
||||
|
||||
/* dpad */
|
||||
@ -270,7 +328,8 @@ input:-internal-autofill-selected {
|
||||
|
||||
.apad-small > .apad-label {
|
||||
font-size: var(--small-control-size);
|
||||
text-shadow: var(--color-dark) calc(var(--text-shadow-size) / 3) calc(var(--text-shadow-size) / 3);
|
||||
text-shadow: var(--color-dark) calc(var(--text-shadow-size) / 3)
|
||||
calc(var(--text-shadow-size) / 3);
|
||||
}
|
||||
|
||||
.apad-rectangle {
|
||||
@ -320,7 +379,8 @@ input:-internal-autofill-selected {
|
||||
|
||||
/* Layout */
|
||||
|
||||
#layout:fullscreen #dpad, #layout:fullscreen #apad {
|
||||
#layout:fullscreen #dpad,
|
||||
#layout:fullscreen #apad {
|
||||
bottom: 6rem;
|
||||
}
|
||||
|
||||
@ -353,55 +413,55 @@ a {
|
||||
|
||||
/* Firefox old*/
|
||||
@-moz-keyframes blink {
|
||||
0% {
|
||||
opacity:1;
|
||||
}
|
||||
50% {
|
||||
opacity:0;
|
||||
}
|
||||
100% {
|
||||
opacity:1;
|
||||
}
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes blink {
|
||||
0% {
|
||||
opacity:1;
|
||||
}
|
||||
50% {
|
||||
opacity:0;
|
||||
}
|
||||
100% {
|
||||
opacity:1;
|
||||
}
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
/* IE */
|
||||
@-ms-keyframes blink {
|
||||
0% {
|
||||
opacity:1;
|
||||
}
|
||||
50% {
|
||||
opacity:0;
|
||||
}
|
||||
100% {
|
||||
opacity:1;
|
||||
}
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
/* Opera and prob css3 final iteration */
|
||||
@keyframes blink {
|
||||
0% {
|
||||
opacity:1;
|
||||
}
|
||||
50% {
|
||||
opacity:0;
|
||||
}
|
||||
100% {
|
||||
opacity:1;
|
||||
}
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.blink-image {
|
||||
-moz-animation: blink normal 4s infinite ease-in-out; /* Firefox */
|
||||
-webkit-animation: blink normal 4s infinite ease-in-out; /* Webkit */
|
||||
-ms-animation: blink normal 4s infinite ease-in-out; /* IE */
|
||||
animation: blink normal 4s infinite ease-in-out; /* Opera and prob css3 final iteration */
|
||||
-moz-animation: blink normal 4s infinite ease-in-out; /* Firefox */
|
||||
-webkit-animation: blink normal 4s infinite ease-in-out; /* Webkit */
|
||||
-ms-animation: blink normal 4s infinite ease-in-out; /* IE */
|
||||
animation: blink normal 4s infinite ease-in-out; /* Opera and prob css3 final iteration */
|
||||
}
|
||||
|
@ -129,11 +129,11 @@
|
||||
<div id="apadCycleNature" class="apad-button apad-square apad-small" data-key="CYCLE_NATURE">
|
||||
<span class="apad-label">N</span>
|
||||
</div>
|
||||
<div id="apadCycleVariant" class="apad-button apad-square apad-small" data-key="V">
|
||||
<div id="apadCycleTera" class="apad-button apad-square apad-small" data-key="CYCLE_TERA">
|
||||
<span class="apad-label">V</span>
|
||||
</div>
|
||||
<!-- buttons to display battle-specific information -->
|
||||
<div id="apadInfo" class="apad-button apad-rectangle apad-small" data-key="V">
|
||||
<div id="apadInfo" class="apad-button apad-rectangle apad-small" data-key="CYCLE_TERA">
|
||||
<span class="apad-label">V</span>
|
||||
</div>
|
||||
<div id="apadStats" class="apad-button apad-rectangle apad-small" data-key="STATS">
|
||||
|
12
lefthook.yml
@ -1,16 +1,14 @@
|
||||
pre-commit:
|
||||
parallel: true
|
||||
commands:
|
||||
eslint:
|
||||
glob: "*.{js,jsx,ts,tsx}"
|
||||
run: npx eslint --fix {staged_files}
|
||||
biome-lint:
|
||||
run: npx biome check --write --reporter=summary --staged --no-errors-on-unmatched
|
||||
stage_fixed: true
|
||||
skip:
|
||||
- merge
|
||||
- rebase
|
||||
|
||||
pre-push:
|
||||
post-merge:
|
||||
commands:
|
||||
eslint:
|
||||
glob: "*.{js,ts,jsx,tsx}"
|
||||
run: npx eslint --fix {push_files}
|
||||
update-submodules:
|
||||
run: git submodule update --init --recursive
|
15051
package-lock.json
generated
136
package.json
@ -1,68 +1,72 @@
|
||||
{
|
||||
"name": "pokemon-rogue-battle",
|
||||
"private": true,
|
||||
"version": "1.0.4",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
"start:dev": "vite --mode development",
|
||||
"build": "vite build",
|
||||
"build:beta": "vite build --mode beta",
|
||||
"preview": "vite preview",
|
||||
"test": "vitest run --project pre && vitest run --project main",
|
||||
"test:cov": "vitest run --project pre && vitest run --project main --coverage",
|
||||
"test:watch": "vitest run --project pre && vitest watch --project main --coverage",
|
||||
"test:silent": "vitest run --project pre && vitest run --project main --silent",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"eslint": "eslint --fix .",
|
||||
"eslint-ci": "eslint .",
|
||||
"docs": "typedoc",
|
||||
"depcruise": "depcruise src",
|
||||
"depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg",
|
||||
"create-test": "node ./create-test-boilerplate.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.3.0",
|
||||
"@hpcc-js/wasm": "^2.18.0",
|
||||
"@stylistic/eslint-plugin-ts": "^2.6.0-beta.0",
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/node": "^20.12.13",
|
||||
"@typescript-eslint/eslint-plugin": "^8.0.0-alpha.54",
|
||||
"@typescript-eslint/parser": "^8.0.0-alpha.54",
|
||||
"@vitest/coverage-istanbul": "^2.0.4",
|
||||
"dependency-cruiser": "^16.3.10",
|
||||
"eslint": "^9.7.0",
|
||||
"eslint-plugin-import-x": "^4.2.1",
|
||||
"inquirer": "^11.0.2",
|
||||
"jsdom": "^24.0.0",
|
||||
"lefthook": "^1.6.12",
|
||||
"msw": "^2.4.9",
|
||||
"phaser3spectorjs": "^0.0.8",
|
||||
"typedoc": "^0.26.4",
|
||||
"typescript": "^5.5.3",
|
||||
"typescript-eslint": "^8.0.0-alpha.54",
|
||||
"vite": "^5.3.5",
|
||||
"vite-tsconfig-paths": "^4.3.2",
|
||||
"vitest": "^2.0.4",
|
||||
"vitest-canvas-mock": "^0.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@material/material-color-utilities": "^0.2.7",
|
||||
"crypto-js": "^4.2.0",
|
||||
"i18next": "^23.11.1",
|
||||
"i18next-browser-languagedetector": "^7.2.1",
|
||||
"i18next-korean-postposition-processor": "^1.0.0",
|
||||
"json-stable-stringify": "^1.1.0",
|
||||
"phaser": "^3.70.0",
|
||||
"phaser3-rex-plugins": "^1.1.84"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"imports": {
|
||||
"#enums/*": "./enums/*",
|
||||
"#app": "./src/main.js",
|
||||
"#app/*": "./src/*",
|
||||
"#test/*": "./src/test/*"
|
||||
}
|
||||
"name": "pokemon-rogue-battle",
|
||||
"private": true,
|
||||
"version": "1.9.6",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
"start:dev": "vite --mode development",
|
||||
"build": "vite build",
|
||||
"build:beta": "vite build --mode beta",
|
||||
"preview": "vite preview",
|
||||
"test": "vitest run --no-isolate",
|
||||
"test:cov": "vitest run --coverage --no-isolate",
|
||||
"test:watch": "vitest watch --coverage --no-isolate",
|
||||
"test:silent": "vitest run --silent --no-isolate",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"eslint": "eslint --fix .",
|
||||
"eslint-ci": "eslint .",
|
||||
"biome": "biome check --write --changed --no-errors-on-unmatched",
|
||||
"biome-ci": "biome ci --diagnostic-level=error --reporter=github --changed --no-errors-on-unmatched",
|
||||
"docs": "typedoc",
|
||||
"depcruise": "depcruise src",
|
||||
"depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg",
|
||||
"create-test": "node ./create-test-boilerplate.js",
|
||||
"postinstall": "npx lefthook install && npx lefthook run post-merge",
|
||||
"update-version:patch": "npm version patch --force --no-git-tag-version",
|
||||
"update-version:minor": "npm version minor --force --no-git-tag-version",
|
||||
"update-locales:remote": "git submodule update --progress --init --recursive --force --remote"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@eslint/js": "^9.23.0",
|
||||
"@hpcc-js/wasm": "^2.22.4",
|
||||
"@stylistic/eslint-plugin-ts": "^4.1.0",
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/node": "^22.13.14",
|
||||
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
||||
"@typescript-eslint/parser": "^8.28.0",
|
||||
"@vitest/coverage-istanbul": "^3.0.9",
|
||||
"dependency-cruiser": "^16.3.10",
|
||||
"eslint": "^9.23.0",
|
||||
"eslint-plugin-import-x": "^4.9.4",
|
||||
"inquirer": "^12.4.2",
|
||||
"jsdom": "^26.0.0",
|
||||
"lefthook": "^1.11.5",
|
||||
"msw": "^2.7.3",
|
||||
"phaser3spectorjs": "^0.0.8",
|
||||
"typedoc": "^0.28.1",
|
||||
"typescript": "^5.8.2",
|
||||
"typescript-eslint": "^8.28.0",
|
||||
"vite": "^6.3.4",
|
||||
"vite-tsconfig-paths": "^5.1.4",
|
||||
"vitest": "^3.0.9",
|
||||
"vitest-canvas-mock": "^0.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@material/material-color-utilities": "^0.2.7",
|
||||
"compare-versions": "^6.1.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"i18next": "^24.2.2",
|
||||
"i18next-browser-languagedetector": "^8.0.4",
|
||||
"i18next-http-backend": "^3.0.2",
|
||||
"i18next-korean-postposition-processor": "^1.0.0",
|
||||
"json-stable-stringify": "^1.2.0",
|
||||
"jszip": "^3.10.1",
|
||||
"phaser": "^3.88.2",
|
||||
"phaser3-rex-plugins": "^1.80.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.0.0"
|
||||
}
|
||||
}
|
||||
|
BIN
public/audio/bgm/battle_champion_kukui.mp3
Normal file
BIN
public/audio/bgm/battle_colress.mp3
Normal file
BIN
public/audio/bgm/battle_mustard.mp3
Normal file
BIN
public/audio/bgm/battle_rival_3_afd.mp3
Normal file
BIN
public/audio/bgm/title_afd.mp3
Normal file
BIN
public/audio/cry/718-10-complete.m4a
Normal file
BIN
public/audio/se/crit_throw.wav
Normal file
2496
public/battle-anims/common-powder.json
Normal file
774
public/battle-anims/common-terastallize.json
Normal file
@ -0,0 +1,774 @@
|
||||
{
|
||||
"graphic": "terastallize",
|
||||
"frames": [
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 150,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 225,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 70,
|
||||
"zoomY": 70,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 70,
|
||||
"zoomY": 70,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 90,
|
||||
"zoomY": 90,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 90,
|
||||
"zoomY": 90,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 200,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 100,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 100,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 60,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 60,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 60,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
255
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
255
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
}
|
||||
]
|
||||
],
|
||||
"frameTimedEvents": {},
|
||||
"position": 4,
|
||||
"hue": 0
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": 94,
|
||||
"graphic": "PRAS- PsychicBG",
|
||||
"graphic": "PRAS- Psychic BG",
|
||||
"frames": [
|
||||
[
|
||||
{
|
||||
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
BIN
public/images/battle_anims/terastallize.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
public/images/events/aprf25-de.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
public/images/events/aprf25-en.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
public/images/events/aprf25-es-ES.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
public/images/events/aprf25-es-MX.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
public/images/events/aprf25-fr.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
public/images/events/aprf25-it.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
public/images/events/aprf25-ja.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
public/images/events/aprf25-ko.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
public/images/events/aprf25-pt-BR.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
public/images/events/aprf25-zh-CN.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
public/images/events/halloween2024-event-de.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
public/images/events/halloween2024-event-en.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/images/events/halloween2024-event-es-ES.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/images/events/halloween2024-event-fr.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
public/images/events/halloween2024-event-it.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/images/events/halloween2024-event-ja.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
public/images/events/halloween2024-event-ko.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
public/images/events/halloween2024-event-pt-BR.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
public/images/events/halloween2024-event-zh-CN.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
public/images/events/pkmnday2025event-de.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
public/images/events/pkmnday2025event-en.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
public/images/events/pkmnday2025event-es-ES.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
public/images/events/pkmnday2025event-fr.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
public/images/events/pkmnday2025event-it.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
public/images/events/pkmnday2025event-ja.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
public/images/events/pkmnday2025event-ko.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
public/images/events/pkmnday2025event-pt-BR.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
public/images/events/pkmnday2025event-zh-CN.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
public/images/events/pride2025-de.png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
public/images/events/pride2025-en.png
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
public/images/events/pride2025-es-ES.png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
public/images/events/pride2025-es-MX.png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
public/images/events/pride2025-fr.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
public/images/events/pride2025-it.png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
public/images/events/pride2025-ja.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
public/images/events/pride2025-ko.png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
public/images/events/pride2025-pt-BR.png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
public/images/events/pride2025-zh-CN.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
public/images/events/pride2025-zh-TW.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
public/images/events/spr25event-de.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
public/images/events/spr25event-en.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
public/images/events/spr25event-es-ES.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
public/images/events/spr25event-es-MX.png
Normal file
After Width: | Height: | Size: 30 KiB |