diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..be478a2b5fa --- /dev/null +++ b/.editorconfig @@ -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 diff --git a/docs/enemy-ai.md b/docs/enemy-ai.md index 46482f56a90..8edf5a3f10e 100644 --- a/docs/enemy-ai.md +++ b/docs/enemy-ai.md @@ -80,8 +80,8 @@ As part of the move selection process, the enemy Pokémon must compute a **targe 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: diff --git a/package.json b/package.json index 81f01e1d482..da5bc393c52 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,10 @@ "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" + "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": { "@eslint/js": "^9.3.0", diff --git a/public/audio/bgm/battle_champion_kukui.mp3 b/public/audio/bgm/battle_champion_kukui.mp3 new file mode 100644 index 00000000000..9e0739fc4d0 Binary files /dev/null and b/public/audio/bgm/battle_champion_kukui.mp3 differ diff --git a/public/audio/bgm/battle_colress.mp3 b/public/audio/bgm/battle_colress.mp3 new file mode 100644 index 00000000000..49a5557860b Binary files /dev/null and b/public/audio/bgm/battle_colress.mp3 differ diff --git a/public/audio/bgm/battle_mustard.mp3 b/public/audio/bgm/battle_mustard.mp3 new file mode 100644 index 00000000000..dccb8f7dcc5 Binary files /dev/null and b/public/audio/bgm/battle_mustard.mp3 differ diff --git a/public/audio/bgm/battle_plasma_grunt.mp3 b/public/audio/bgm/battle_plasma_grunt.mp3 index 7d1bf710bc5..c3d004514d0 100644 Binary files a/public/audio/bgm/battle_plasma_grunt.mp3 and b/public/audio/bgm/battle_plasma_grunt.mp3 differ diff --git a/public/images/trainer/aether_grunt_f.json b/public/images/trainer/aether_grunt_f.json index c43bdae9b2e..26ae177bd21 100644 --- a/public/images/trainer/aether_grunt_f.json +++ b/public/images/trainer/aether_grunt_f.json @@ -4,8 +4,8 @@ "image": "aether_grunt_f.png", "format": "RGBA8888", "size": { - "w": 69, - "h": 69 + "w": 70, + "h": 70 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 39, + "h": 70 }, "spriteSourceSize": { - "x": 23, - "y": 10, - "w": 35, - "h": 69 + "x": 0, + "y": 0, + "w": 39, + "h": 70 }, "frame": { "x": 0, "y": 0, - "w": 35, - "h": 69 + "w": 39, + "h": 70 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:0c9e77856d3b434e719021572bcb93de:f9c45dc5d67009b134dd1bbc5593f6ec:a694f8828aff21c718e5161e2fd63ade$" + "smartupdate": "$TexturePacker:SmartUpdate:0a678d2035c82d3741f2de29e01d42d3:374042fde99a4ff05c5e90cedbc5bd1f:a694f8828aff21c718e5161e2fd63ade$" } } diff --git a/public/images/trainer/aether_grunt_f.png b/public/images/trainer/aether_grunt_f.png index b43c5e71a51..a5088c9e1de 100644 Binary files a/public/images/trainer/aether_grunt_f.png and b/public/images/trainer/aether_grunt_f.png differ diff --git a/public/images/trainer/aether_grunt_m.json b/public/images/trainer/aether_grunt_m.json index eba00096f8d..74195b97dde 100644 --- a/public/images/trainer/aether_grunt_m.json +++ b/public/images/trainer/aether_grunt_m.json @@ -4,8 +4,8 @@ "image": "aether_grunt_m.png", "format": "RGBA8888", "size": { - "w": 65, - "h": 65 + "w": 69, + "h": 69 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 45, + "h": 69 }, "spriteSourceSize": { - "x": 16, - "y": 14, - "w": 47, - "h": 65 + "x": 0, + "y": 0, + "w": 45, + "h": 69 }, "frame": { "x": 0, "y": 0, - "w": 47, - "h": 65 + "w": 45, + "h": 69 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:963887cf29549ad3c123b8055cb4d701:68004c4a6e04c93bd21c26a6f8921f0c:d2241fc11d0fc31b26ecbedae6da74f4$" + "smartupdate": "$TexturePacker:SmartUpdate:f7ad29bea8c4a179c08958890cadb04b:741fc1b2e43d2da720c249c6f81910bc:d2241fc11d0fc31b26ecbedae6da74f4$" } } diff --git a/public/images/trainer/aether_grunt_m.png b/public/images/trainer/aether_grunt_m.png index f4df26ef007..1b1e092a340 100644 Binary files a/public/images/trainer/aether_grunt_m.png and b/public/images/trainer/aether_grunt_m.png differ diff --git a/public/images/trainer/aqua_grunt_f.json b/public/images/trainer/aqua_grunt_f.json index 20515f30e5e..23f118927f1 100644 --- a/public/images/trainer/aqua_grunt_f.json +++ b/public/images/trainer/aqua_grunt_f.json @@ -4,8 +4,8 @@ "image": "aqua_grunt_f.png", "format": "RGBA8888", "size": { - "w": 71, - "h": 71 + "w": 73, + "h": 73 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 34, + "h": 73 }, "spriteSourceSize": { - "x": 22, - "y": 8, - "w": 36, - "h": 71 + "x": 0, + "y": 0, + "w": 34, + "h": 73 }, "frame": { "x": 0, "y": 0, - "w": 36, - "h": 71 + "w": 34, + "h": 73 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:6db25cb5753163d19bca8e2db45849ae:7d8f51509862bfdf8a78bf42dd0005cd:af0aa9494be37941522487032b556989$" + "smartupdate": "$TexturePacker:SmartUpdate:99d76e35df4b09fc9d312218d8fa8cc7:8ad846929ea03b5fb70fd16144e5e2fa:af0aa9494be37941522487032b556989$" } } diff --git a/public/images/trainer/aqua_grunt_f.png b/public/images/trainer/aqua_grunt_f.png index 132d239c0b8..4db237bf9e7 100644 Binary files a/public/images/trainer/aqua_grunt_f.png and b/public/images/trainer/aqua_grunt_f.png differ diff --git a/public/images/trainer/aqua_grunt_m.json b/public/images/trainer/aqua_grunt_m.json index 93408cc40c8..3a120f7d20c 100644 --- a/public/images/trainer/aqua_grunt_m.json +++ b/public/images/trainer/aqua_grunt_m.json @@ -4,8 +4,8 @@ "image": "aqua_grunt_m.png", "format": "RGBA8888", "size": { - "w": 73, - "h": 73 + "w": 74, + "h": 74 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 38, + "h": 74 }, "spriteSourceSize": { - "x": 17, - "y": 6, - "w": 46, - "h": 73 + "x": 0, + "y": 0, + "w": 38, + "h": 74 }, "frame": { "x": 0, "y": 0, - "w": 46, - "h": 73 + "w": 38, + "h": 74 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:efd07ff3ed1e610150a4b8ca18974343:d9b85b9eb11182e9e4669e2bd8b08694:72b7b50231708a9486d5f315824e4df1$" + "smartupdate": "$TexturePacker:SmartUpdate:ea2cdca90584089079af92307948ecdc:331e1f5314abbfcf58331ab0b9fd1c40:72b7b50231708a9486d5f315824e4df1$" } } diff --git a/public/images/trainer/aqua_grunt_m.png b/public/images/trainer/aqua_grunt_m.png index 87dbfd566a1..4fe230ca119 100644 Binary files a/public/images/trainer/aqua_grunt_m.png and b/public/images/trainer/aqua_grunt_m.png differ diff --git a/public/images/trainer/archie.json b/public/images/trainer/archie.json index 63837d40847..3718bcffd0c 100644 --- a/public/images/trainer/archie.json +++ b/public/images/trainer/archie.json @@ -4,8 +4,8 @@ "image": "archie.png", "format": "RGBA8888", "size": { - "w": 80, - "h": 80 + "w": 79, + "h": 79 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 58, + "h": 79 }, "spriteSourceSize": { - "x": 21, + "x": 0, "y": 0, - "w": 42, - "h": 80 + "w": 58, + "h": 79 }, "frame": { "x": 0, "y": 0, - "w": 42, - "h": 80 + "w": 58, + "h": 79 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:bfa7fdd7b6ac9be68dc9dc562fb8339f:06f87a279450b21b19294ba956b69c26:4b7980be4e3ac1d20c9eaf970913ec63$" + "smartupdate": "$TexturePacker:SmartUpdate:1edc051db037c1742819ac8674ebe4be:bfaa715c0faf707c1b20ab8259d42a35:4b7980be4e3ac1d20c9eaf970913ec63$" } } diff --git a/public/images/trainer/archie.png b/public/images/trainer/archie.png index c83975c0690..d4c003fd348 100644 Binary files a/public/images/trainer/archie.png and b/public/images/trainer/archie.png differ diff --git a/public/images/trainer/atticus.json b/public/images/trainer/atticus.json index 95621998bf2..8b1ebdd63f2 100644 --- a/public/images/trainer/atticus.json +++ b/public/images/trainer/atticus.json @@ -4,8 +4,8 @@ "image": "atticus.png", "format": "RGBA8888", "size": { - "w": 46, - "h": 46 + "w": 55, + "h": 55 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 55, + "h": 49 }, "spriteSourceSize": { - "x": 21, - "y": 33, - "w": 43, - "h": 46 + "x": 0, + "y": 0, + "w": 55, + "h": 49 }, "frame": { "x": 0, "y": 0, - "w": 43, - "h": 46 + "w": 55, + "h": 49 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:6dcd7c3d3982793cbca0d6fcd1f9260e:19c44634629fadd9d039d23dc71ec987:d26ede35f15aa571d5a7a2dd2fb868e1$" + "smartupdate": "$TexturePacker:SmartUpdate:2c1a2ecebeac4770c51422bede6add57:5c82bf231c27d62e440081f186eb1da9:d26ede35f15aa571d5a7a2dd2fb868e1$" } } diff --git a/public/images/trainer/atticus.png b/public/images/trainer/atticus.png index e3e7e870f2b..75cd70b72d8 100644 Binary files a/public/images/trainer/atticus.png and b/public/images/trainer/atticus.png differ diff --git a/public/images/trainer/courtney.json b/public/images/trainer/courtney.json index de55e91eb85..1da3e08b107 100644 --- a/public/images/trainer/courtney.json +++ b/public/images/trainer/courtney.json @@ -4,8 +4,8 @@ "image": "courtney.png", "format": "RGBA8888", "size": { - "w": 52, - "h": 80 + "w": 72, + "h": 72 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 52, - "h": 80 + "w": 44, + "h": 72 }, "spriteSourceSize": { "x": 0, "y": 0, - "w": 52, - "h": 80 + "w": 44, + "h": 72 }, "frame": { "x": 0, "y": 0, - "w": 52, - "h": 80 + "w": 44, + "h": 72 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:831f5748dad92911b10a1cb358ee2dae:a3bf81bbaa3b49cad5e0e549cf94563b:bb6befc9383c9c08837183ae2a7a80c1$" + "smartupdate": "$TexturePacker:SmartUpdate:c39b0f300dc09114fba490e6ab68b2b5:a24a6dbdd0e3f4d4b7a567673b73316a:b0c7d3a5747d1c7edafa00c8e6d1257e$" } } diff --git a/public/images/trainer/courtney.png b/public/images/trainer/courtney.png index 0efdb615fcd..3db5151e61c 100644 Binary files a/public/images/trainer/courtney.png and b/public/images/trainer/courtney.png differ diff --git a/public/images/trainer/eri.json b/public/images/trainer/eri.json index fd4daf60437..08312d7a310 100644 --- a/public/images/trainer/eri.json +++ b/public/images/trainer/eri.json @@ -4,8 +4,8 @@ "image": "eri.png", "format": "RGBA8888", "size": { - "w": 74, - "h": 74 + "w": 78, + "h": 78 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 52, + "h": 78 }, "spriteSourceSize": { - "x": 15, - "y": 5, - "w": 45, - "h": 74 + "x": 0, + "y": 0, + "w": 52, + "h": 78 }, "frame": { "x": 0, "y": 0, - "w": 45, - "h": 74 + "w": 52, + "h": 78 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:59594ac27e74ec85e2949d12ff680dc2:d65b6b00858ac47b26ef8393a8fa6795:d7f4cd3ff755f8074c14d3006b0c8301$" + "smartupdate": "$TexturePacker:SmartUpdate:d413fdffea2ec50087a67019a6ce4063:66a18e7a21ca3a1953778dbc09074ab6:d7f4cd3ff755f8074c14d3006b0c8301$" } } diff --git a/public/images/trainer/eri.png b/public/images/trainer/eri.png index 0c9bdf7b47b..cb38f96b030 100644 Binary files a/public/images/trainer/eri.png and b/public/images/trainer/eri.png differ diff --git a/public/images/trainer/faba.json b/public/images/trainer/faba.json index 0e9544e2529..a419c782d87 100644 --- a/public/images/trainer/faba.json +++ b/public/images/trainer/faba.json @@ -4,8 +4,8 @@ "image": "faba.png", "format": "RGBA8888", "size": { - "w": 74, - "h": 74 + "w": 76, + "h": 76 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 29, + "h": 76 }, "spriteSourceSize": { - "x": 25, - "y": 5, - "w": 31, - "h": 74 + "x": 0, + "y": 0, + "w": 29, + "h": 76 }, "frame": { "x": 0, "y": 0, - "w": 31, - "h": 74 + "w": 29, + "h": 76 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:47622708d99a504998950bd9c389a504:fe1c51be191dd9fafb5b6f309c08ae1a:8d64db18930325b8b513740c1d83ce4c$" + "smartupdate": "$TexturePacker:SmartUpdate:bbfce6e1ed69401694ce8c2537dd1fea:a2c9351e4ba08d44cafa66ecdf509866:8d64db18930325b8b513740c1d83ce4c$" } } diff --git a/public/images/trainer/faba.png b/public/images/trainer/faba.png index a7fa0fb4879..1c509da8a78 100644 Binary files a/public/images/trainer/faba.png and b/public/images/trainer/faba.png differ diff --git a/public/images/trainer/flare_grunt_f.json b/public/images/trainer/flare_grunt_f.json index e536d28a1aa..a8ebf9a8a4a 100644 --- a/public/images/trainer/flare_grunt_f.json +++ b/public/images/trainer/flare_grunt_f.json @@ -4,8 +4,8 @@ "image": "flare_grunt_f.png", "format": "RGBA8888", "size": { - "w": 80, - "h": 80 + "w": 85, + "h": 85 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 23, + "h": 85 }, "spriteSourceSize": { - "x": 31, + "x": 0, "y": 0, "w": 23, - "h": 80 + "h": 85 }, "frame": { "x": 0, "y": 0, "w": 23, - "h": 80 + "h": 85 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:c30bf82452209a923f4becf13d275a9a:a6355b09f92c9c0388d0b919010f587f:0638dbf213f8a974eb5af76eb1e5ddeb$" + "smartupdate": "$TexturePacker:SmartUpdate:88d242a8c3b9859307ecdd290c30ce7d:acd04d60ab09f18e86e4e5727132dac2:0638dbf213f8a974eb5af76eb1e5ddeb$" } } diff --git a/public/images/trainer/flare_grunt_f.png b/public/images/trainer/flare_grunt_f.png index 4446675dc44..e2a4dd7fe92 100644 Binary files a/public/images/trainer/flare_grunt_f.png and b/public/images/trainer/flare_grunt_f.png differ diff --git a/public/images/trainer/flare_grunt_m.json b/public/images/trainer/flare_grunt_m.json index 4d54acbf810..226257ef84a 100644 --- a/public/images/trainer/flare_grunt_m.json +++ b/public/images/trainer/flare_grunt_m.json @@ -14,12 +14,12 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 31, + "h": 77 }, "spriteSourceSize": { - "x": 24, - "y": 2, + "x": 0, + "y": 0, "w": 31, "h": 77 }, @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:a26606e70778f88a1a7053b2f2420dde:84abf0d0f6bc90c6a60f660567b2d641:adc35a4070bac9fe828c2605a3b15744$" + "smartupdate": "$TexturePacker:SmartUpdate:8683e52bbd1a42992f4d7ab8aa65a2a1:e8279cd322279bc5f8e2bb5797e6f818:adc35a4070bac9fe828c2605a3b15744$" } } diff --git a/public/images/trainer/flare_grunt_m.png b/public/images/trainer/flare_grunt_m.png index 79eb98449ca..eb14dbed0e2 100644 Binary files a/public/images/trainer/flare_grunt_m.png and b/public/images/trainer/flare_grunt_m.png differ diff --git a/public/images/trainer/giacomo.json b/public/images/trainer/giacomo.json index 5eeb2cd685b..f61d5b64901 100644 --- a/public/images/trainer/giacomo.json +++ b/public/images/trainer/giacomo.json @@ -4,8 +4,8 @@ "image": "giacomo.png", "format": "RGBA8888", "size": { - "w": 75, - "h": 75 + "w": 71, + "h": 71 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 37, + "h": 71 }, "spriteSourceSize": { - "x": 23, - "y": 4, + "x": 0, + "y": 0, "w": 37, - "h": 75 + "h": 71 }, "frame": { "x": 0, "y": 0, "w": 37, - "h": 75 + "h": 71 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:8c4e7da48e5667abc6d364330268c092:0fa43e58d8a746d3b86cb2dd763719f4:8603cc19e888c8c8de62177f4011577c$" + "smartupdate": "$TexturePacker:SmartUpdate:8d4b9bca01f3729556cd02a8795c3e89:cb2840cbbd1e5a614bfa6bcb23db5b62:8603cc19e888c8c8de62177f4011577c$" } } diff --git a/public/images/trainer/giacomo.png b/public/images/trainer/giacomo.png index 275f47fad3c..352acaddf95 100644 Binary files a/public/images/trainer/giacomo.png and b/public/images/trainer/giacomo.png differ diff --git a/public/images/trainer/guzma.json b/public/images/trainer/guzma.json index c278d68be24..1b75915c088 100644 --- a/public/images/trainer/guzma.json +++ b/public/images/trainer/guzma.json @@ -4,8 +4,8 @@ "image": "guzma.png", "format": "RGBA8888", "size": { - "w": 58, - "h": 58 + "w": 64, + "h": 64 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 34, + "h": 64 }, "spriteSourceSize": { - "x": 21, - "y": 20, - "w": 37, - "h": 58 + "x": 0, + "y": 0, + "w": 34, + "h": 64 }, "frame": { "x": 0, "y": 0, - "w": 37, - "h": 58 + "w": 34, + "h": 64 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:c3b08a562a2882d1ca8b5e031e245da9:72a8305e547f091d15abccd2b142e401:3b302c7f9eb6ea81b65bcaeead4a95a9$" + "smartupdate": "$TexturePacker:SmartUpdate:90cfe8ae514c30ddf48840678b251141:87a93d268c61327ad913bba3b052686b:3b302c7f9eb6ea81b65bcaeead4a95a9$" } } diff --git a/public/images/trainer/guzma.png b/public/images/trainer/guzma.png index 6afd6f3b34a..1ae6d8eb8d1 100644 Binary files a/public/images/trainer/guzma.png and b/public/images/trainer/guzma.png differ diff --git a/public/images/trainer/hala.json b/public/images/trainer/hala.json index f909ebe7684..5fcea739488 100644 --- a/public/images/trainer/hala.json +++ b/public/images/trainer/hala.json @@ -4,8 +4,8 @@ "image": "hala.png", "format": "RGBA8888", "size": { - "w": 78, - "h": 78 + "w": 82, + "h": 82 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 59, - "h": 78 + "w": 58, + "h": 82 }, "spriteSourceSize": { "x": 0, "y": 0, - "w": 59, - "h": 78 + "w": 58, + "h": 82 }, "frame": { "x": 0, "y": 0, - "w": 59, - "h": 78 + "w": 58, + "h": 82 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:b6547cc9975d92a02b99fd63122d740b:0a72e0ac4fcbfe4329a7dcdad284ab36:7c2af56b9a9851f2e2eaeaf0cdca9370$" + "smartupdate": "$TexturePacker:SmartUpdate:57dc13db648785ad4694bf67c40fa21d:ee2bc7184f4f48ab8ba3c10c89bfc8f0:7c2af56b9a9851f2e2eaeaf0cdca9370$" } } diff --git a/public/images/trainer/hala.png b/public/images/trainer/hala.png index 0a72be4113b..4f26cbb8ff3 100644 Binary files a/public/images/trainer/hala.png and b/public/images/trainer/hala.png differ diff --git a/public/images/trainer/hau.json b/public/images/trainer/hau.json index 5f2ef8bcec8..351283ff0ad 100644 --- a/public/images/trainer/hau.json +++ b/public/images/trainer/hau.json @@ -4,8 +4,8 @@ "image": "hau.png", "format": "RGBA8888", "size": { - "w": 70, - "h": 70 + "w": 71, + "h": 71 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 24, + "h": 71 }, "spriteSourceSize": { - "x": 27, - "y": 9, - "w": 29, - "h": 70 + "x": 0, + "y": 0, + "w": 24, + "h": 71 }, "frame": { "x": 0, "y": 0, - "w": 29, - "h": 70 + "w": 24, + "h": 71 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:688d6d27e686efec45b144ba4544f248:676457a4e9dfbcad0510f6e7bfa73514:d4c7e8b349477c2295b49b0e99b91bb3$" + "smartupdate": "$TexturePacker:SmartUpdate:0d500afd9a36f32a23b5a316dcf397d9:aa5d3e58d6df67b90e484ec7f345a4cf:d4c7e8b349477c2295b49b0e99b91bb3$" } } diff --git a/public/images/trainer/hau.png b/public/images/trainer/hau.png index 1ce2c98f6af..7aa673a6fe9 100644 Binary files a/public/images/trainer/hau.png and b/public/images/trainer/hau.png differ diff --git a/public/images/trainer/korrina.json b/public/images/trainer/korrina.json index cc1ba59bd55..7c258fa4927 100644 --- a/public/images/trainer/korrina.json +++ b/public/images/trainer/korrina.json @@ -4,8 +4,8 @@ "image": "korrina.png", "format": "RGBA8888", "size": { - "w": 75, - "h": 75 + "w": 83, + "h": 83 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 57, + "h": 83 }, "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 56, - "h": 75 + "x": 0, + "y": 0, + "w": 57, + "h": 83 }, "frame": { "x": 0, "y": 0, - "w": 56, - "h": 75 + "w": 57, + "h": 83 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:43a6564beec2569a58110232e9752b64:0decef066ae75dc7f3bd0c811f9a92d1:ed5be09cd8b82ed6439ff8617ffa74c0$" + "smartupdate": "$TexturePacker:SmartUpdate:1dc28e18e99698fbfd8a110a1dc737f2:79d24176afd3059dc69ce785ce672bbb:ed5be09cd8b82ed6439ff8617ffa74c0$" } } diff --git a/public/images/trainer/korrina.png b/public/images/trainer/korrina.png index 6d6817faf94..8994afdddb1 100644 Binary files a/public/images/trainer/korrina.png and b/public/images/trainer/korrina.png differ diff --git a/public/images/trainer/kukui.json b/public/images/trainer/kukui.json new file mode 100644 index 00000000000..139a1456cc5 --- /dev/null +++ b/public/images/trainer/kukui.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "kukui.png", + "format": "RGBA8888", + "size": { + "w": 74, + "h": 74 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 37, + "h": 74 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 37, + "h": 74 + }, + "frame": { + "x": 0, + "y": 0, + "w": 37, + "h": 74 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:bccd7af37a8608585716e34d0acb49af:8e1ebc6f022707fbb1e6b4f7d1dbb00c:70bdbf4bca082082ae121aa8ef03c2be$" + } +} diff --git a/public/images/trainer/kukui.png b/public/images/trainer/kukui.png new file mode 100644 index 00000000000..aacf1c197ee Binary files /dev/null and b/public/images/trainer/kukui.png differ diff --git a/public/images/trainer/lusamine.json b/public/images/trainer/lusamine.json index 55a711a21fb..c2e9b2f2356 100644 --- a/public/images/trainer/lusamine.json +++ b/public/images/trainer/lusamine.json @@ -4,8 +4,8 @@ "image": "lusamine.png", "format": "RGBA8888", "size": { - "w": 74, - "h": 74 + "w": 80, + "h": 80 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, + "w": 52, "h": 80 }, "spriteSourceSize": { - "x": 22, - "y": 5, - "w": 36, - "h": 74 + "x": 0, + "y": 0, + "w": 52, + "h": 80 }, "frame": { "x": 0, "y": 0, - "w": 36, - "h": 74 + "w": 52, + "h": 80 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:41da3a1299e3831be70016dc91e49313:2413ba06767fb10fdc6fde8cc736c51c:4012333084c529872232c8d052561dc1$" + "smartupdate": "$TexturePacker:SmartUpdate:52c5f9beccbfe68b9861b8fc393ba674:35d25e8bad6c7212e330a0e3d0c88315:4012333084c529872232c8d052561dc1$" } } diff --git a/public/images/trainer/lusamine.png b/public/images/trainer/lusamine.png index 8b835a2d0be..1619dc11e2d 100644 Binary files a/public/images/trainer/lusamine.png and b/public/images/trainer/lusamine.png differ diff --git a/public/images/trainer/lysandre.json b/public/images/trainer/lysandre.json index 931b1633a32..1dcb9c8c710 100644 --- a/public/images/trainer/lysandre.json +++ b/public/images/trainer/lysandre.json @@ -4,8 +4,8 @@ "image": "lysandre.png", "format": "RGBA8888", "size": { - "w": 80, - "h": 80 + "w": 82, + "h": 82 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 50, + "h": 82 }, "spriteSourceSize": { - "x": 14, + "x": 0, "y": 0, - "w": 52, - "h": 80 + "w": 50, + "h": 82 }, "frame": { "x": 0, "y": 0, - "w": 52, - "h": 80 + "w": 50, + "h": 82 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:6b887c8bab74885a1b05f2b382759db6:ba102d9d25ddd794a3a17f029b971daf:e6066149f6ec4ccb9fc28faea3d64a7f$" + "smartupdate": "$TexturePacker:SmartUpdate:b09528fe2d3137bba8ce5c667d2a962f:7c522eefcc85ee87df485d34b58e814b:e6066149f6ec4ccb9fc28faea3d64a7f$" } } diff --git a/public/images/trainer/lysandre.png b/public/images/trainer/lysandre.png index b83b649d142..fe6dafb00f8 100644 Binary files a/public/images/trainer/lysandre.png and b/public/images/trainer/lysandre.png differ diff --git a/public/images/trainer/macro_grunt_f.json b/public/images/trainer/macro_grunt_f.json index 04b30ec4ca5..8a9a3943a27 100644 --- a/public/images/trainer/macro_grunt_f.json +++ b/public/images/trainer/macro_grunt_f.json @@ -14,19 +14,19 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 33, + "h": 74 }, "spriteSourceSize": { - "x": 24, - "y": 5, - "w": 31, + "x": 0, + "y": 0, + "w": 33, "h": 74 }, "frame": { "x": 0, "y": 0, - "w": 31, + "w": 33, "h": 74 } } @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:a015c43d80f8fd1932758e0e2cfcec61:59fc8205ea5ca04295831b4a2eb623ec:30df2ea8e9dac9e95f70534ec43d5ecd$" + "smartupdate": "$TexturePacker:SmartUpdate:7449212fcdbfb4a600364bd3761e4fb6:37c81a387501a047cff84cabdeedb496:d1412ef32f1904a102cf70569806f3b7$" } } diff --git a/public/images/trainer/macro_grunt_f.png b/public/images/trainer/macro_grunt_f.png index 892299d701e..85586126da1 100644 Binary files a/public/images/trainer/macro_grunt_f.png and b/public/images/trainer/macro_grunt_f.png differ diff --git a/public/images/trainer/macro_grunt_m.json b/public/images/trainer/macro_grunt_m.json index 5357fdb0767..f9a8736c4d1 100644 --- a/public/images/trainer/macro_grunt_m.json +++ b/public/images/trainer/macro_grunt_m.json @@ -4,8 +4,8 @@ "image": "macro_grunt_m.png", "format": "RGBA8888", "size": { - "w": 75, - "h": 75 + "w": 76, + "h": 76 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 35, + "h": 76 }, "spriteSourceSize": { - "x": 15, - "y": 4, - "w": 48, - "h": 75 + "x": 0, + "y": 0, + "w": 35, + "h": 76 }, "frame": { "x": 0, "y": 0, - "w": 48, - "h": 75 + "w": 35, + "h": 76 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:52fccff2a0675b4e10139ddb7067d4cf:10d254175d2d8a9111cce096ffb55fa3:d57016467aa07cafdfaf13e0ff643c1b$" + "smartupdate": "$TexturePacker:SmartUpdate:5800bf6888eb6dd61ea39e1c9a1f93e3:25a930b7c50e2d7832bd3c30402d7544:1f76f2e682f472208a45e187250a6a3d$" } } diff --git a/public/images/trainer/macro_grunt_m.png b/public/images/trainer/macro_grunt_m.png index aa6b3607a87..464c735c75d 100644 Binary files a/public/images/trainer/macro_grunt_m.png and b/public/images/trainer/macro_grunt_m.png differ diff --git a/public/images/trainer/magma_grunt_f.json b/public/images/trainer/magma_grunt_f.json index 05c0512bbf0..d7a3d214317 100644 --- a/public/images/trainer/magma_grunt_f.json +++ b/public/images/trainer/magma_grunt_f.json @@ -4,30 +4,30 @@ "image": "magma_grunt_f.png", "format": "RGBA8888", "size": { - "w": 80, - "h": 80 + "w": 72, + "h": 72 }, "scale": 1, "frames": [ { "filename": "0001.png", "rotated": false, - "trimmed": true, + "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 43, + "h": 72 }, "spriteSourceSize": { - "x": 10, + "x": 0, "y": 0, - "w": 60, - "h": 80 + "w": 43, + "h": 72 }, "frame": { - "x": 10, + "x": 0, "y": 0, - "w": 60, - "h": 80 + "w": 43, + "h": 72 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:f63ad48affc076f60fae78992c96a2bf:80928b32710abcb28c07c6fc5a425d99:3b961d8852b62aaf24ceb2030c036515$" + "smartupdate": "$TexturePacker:SmartUpdate:219462e400564a65012cda9dbc31ab22:4e0070239d24311df52a263271698c59:3b961d8852b62aaf24ceb2030c036515$" } } diff --git a/public/images/trainer/magma_grunt_f.png b/public/images/trainer/magma_grunt_f.png index 215ad83eea1..5ea582ad067 100644 Binary files a/public/images/trainer/magma_grunt_f.png and b/public/images/trainer/magma_grunt_f.png differ diff --git a/public/images/trainer/magma_grunt_m.json b/public/images/trainer/magma_grunt_m.json index ac8cd838c5a..57ac7c40da9 100644 --- a/public/images/trainer/magma_grunt_m.json +++ b/public/images/trainer/magma_grunt_m.json @@ -4,30 +4,30 @@ "image": "magma_grunt_m.png", "format": "RGBA8888", "size": { - "w": 80, - "h": 80 + "w": 72, + "h": 72 }, "scale": 1, "frames": [ { "filename": "0001.png", "rotated": false, - "trimmed": true, + "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 44, + "h": 72 }, "spriteSourceSize": { - "x": 10, + "x": 0, "y": 0, - "w": 60, - "h": 80 + "w": 44, + "h": 72 }, "frame": { - "x": 10, + "x": 0, "y": 0, - "w": 60, - "h": 80 + "w": 44, + "h": 72 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:96aa833d987a01bcdcb6f0e7809f5daf:791cce8d026f92b2e52f0b66df8b8e11:35532fd5d9aea30957d50d06f2d2f9a6$" + "smartupdate": "$TexturePacker:SmartUpdate:46f6e6e1aef8e2e7640c67116e548c5d:34cb6b7f64b0d3c294fcdde45097575d:35532fd5d9aea30957d50d06f2d2f9a6$" } } diff --git a/public/images/trainer/magma_grunt_m.png b/public/images/trainer/magma_grunt_m.png index a37b9acbb52..b2432a79d28 100644 Binary files a/public/images/trainer/magma_grunt_m.png and b/public/images/trainer/magma_grunt_m.png differ diff --git a/public/images/trainer/mela.json b/public/images/trainer/mela.json index c9db18acc5a..1d242d50074 100644 --- a/public/images/trainer/mela.json +++ b/public/images/trainer/mela.json @@ -4,8 +4,8 @@ "image": "mela.png", "format": "RGBA8888", "size": { - "w": 78, - "h": 78 + "w": 75, + "h": 75 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 41, + "h": 75 }, "spriteSourceSize": { - "x": 18, - "y": 1, - "w": 46, - "h": 78 + "x": 0, + "y": 0, + "w": 41, + "h": 75 }, "frame": { "x": 0, "y": 0, - "w": 46, - "h": 78 + "w": 41, + "h": 75 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:e26d8c926c54c848cef673b3f59f35e7:ff040c2cebb1a92d2ef61dc91c018390:68668cf06383ff459cccaafb6bf56215$" + "smartupdate": "$TexturePacker:SmartUpdate:96e97b165e8ca706b7838616d32ab81f:89c577db41f4b610520823e876066e35:68668cf06383ff459cccaafb6bf56215$" } } diff --git a/public/images/trainer/mela.png b/public/images/trainer/mela.png index fbb08ed69cf..a98547d6380 100644 Binary files a/public/images/trainer/mela.png and b/public/images/trainer/mela.png differ diff --git a/public/images/trainer/molayne.json b/public/images/trainer/molayne.json index ae80a12f012..8a0b1b3534e 100644 --- a/public/images/trainer/molayne.json +++ b/public/images/trainer/molayne.json @@ -4,8 +4,8 @@ "image": "molayne.png", "format": "RGBA8888", "size": { - "w": 79, - "h": 79 + "w": 78, + "h": 78 }, "scale": 1, "frames": [ @@ -15,19 +15,19 @@ "trimmed": false, "sourceSize": { "w": 31, - "h": 79 + "h": 78 }, "spriteSourceSize": { "x": 0, "y": 0, "w": 31, - "h": 79 + "h": 78 }, "frame": { "x": 0, "y": 0, "w": 31, - "h": 79 + "h": 78 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:056720ae56077b81375b258850332053:774e1c8463f26fac3be55ed88c8b48b9:11092260a376b1a46e696927361b6498$" + "smartupdate": "$TexturePacker:SmartUpdate:190386db101d4bd1ef5ed1f4f7b5bb1c:c8bc1b069ceb2707738b9178fb6aea0f:11092260a376b1a46e696927361b6498$" } } diff --git a/public/images/trainer/molayne.png b/public/images/trainer/molayne.png index 75f9569370e..c400e5be33d 100644 Binary files a/public/images/trainer/molayne.png and b/public/images/trainer/molayne.png differ diff --git a/public/images/trainer/mustard.json b/public/images/trainer/mustard.json new file mode 100644 index 00000000000..5c3a73f0a0b --- /dev/null +++ b/public/images/trainer/mustard.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "mustard.png", + "format": "RGBA8888", + "size": { + "w": 71, + "h": 71 + }, + "scale": 1, + "frames": [ + { + "filename": "0001.png", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 57, + "h": 71 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 57, + "h": 71 + }, + "frame": { + "x": 0, + "y": 0, + "w": 57, + "h": 71 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:8e2d109ee2cb1b2a6dda840c5bba1d4e:8116b1de2fd7bc0ca08e2d3e618b3dae:ac5d03e7cabff8ff660969c2bc2f3b36$" + } +} diff --git a/public/images/trainer/mustard.png b/public/images/trainer/mustard.png new file mode 100644 index 00000000000..0acba02db45 Binary files /dev/null and b/public/images/trainer/mustard.png differ diff --git a/public/images/trainer/oleana.json b/public/images/trainer/oleana.json index 7219b640c38..d9344226819 100644 --- a/public/images/trainer/oleana.json +++ b/public/images/trainer/oleana.json @@ -4,8 +4,8 @@ "image": "oleana.png", "format": "RGBA8888", "size": { - "w": 79, - "h": 79 + "w": 78, + "h": 78 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 56, + "h": 78 }, "spriteSourceSize": { - "x": 10, - "y": 1, - "w": 53, - "h": 79 + "x": 0, + "y": 0, + "w": 56, + "h": 78 }, "frame": { "x": 0, "y": 0, - "w": 53, - "h": 79 + "w": 56, + "h": 78 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:30987a671771127a38491a588c465964:38b28effcfd5c6cbc0f358912a775af3:82e2a1f8afed29be57f6c2473f4c5be2$" + "smartupdate": "$TexturePacker:SmartUpdate:3f088913cab1db14067e247bd92e82ce:b32e1ef6ef289564b39fd326346002c6:82e2a1f8afed29be57f6c2473f4c5be2$" } } diff --git a/public/images/trainer/oleana.png b/public/images/trainer/oleana.png index 3252c67ab8e..e74fb6ab2eb 100644 Binary files a/public/images/trainer/oleana.png and b/public/images/trainer/oleana.png differ diff --git a/public/images/trainer/ortega.json b/public/images/trainer/ortega.json index 53bab5dba40..082817344e0 100644 --- a/public/images/trainer/ortega.json +++ b/public/images/trainer/ortega.json @@ -4,8 +4,8 @@ "image": "ortega.png", "format": "RGBA8888", "size": { - "w": 69, - "h": 69 + "w": 70, + "h": 70 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 47, + "h": 70 }, "spriteSourceSize": { - "x": 8, - "y": 10, - "w": 53, - "h": 69 + "x": 0, + "y": 0, + "w": 47, + "h": 70 }, "frame": { "x": 0, "y": 0, - "w": 53, - "h": 69 + "w": 47, + "h": 70 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:c6ff92d90ed884222095de81d1db9166:a91cf3c83a063f549c52afb42f7ba3b0:c3f9fcec121c8bc93f2b230b20b79c57$" + "smartupdate": "$TexturePacker:SmartUpdate:f69a1067315885ed736a07362122f371:717e3f134eb10424f0f0fa724500ba63:c3f9fcec121c8bc93f2b230b20b79c57$" } } diff --git a/public/images/trainer/ortega.png b/public/images/trainer/ortega.png index 7f694c6ded6..cede7b6c311 100644 Binary files a/public/images/trainer/ortega.png and b/public/images/trainer/ortega.png differ diff --git a/public/images/trainer/penny.json b/public/images/trainer/penny.json index da64efffa3b..bb74e43da89 100644 --- a/public/images/trainer/penny.json +++ b/public/images/trainer/penny.json @@ -4,8 +4,8 @@ "image": "penny.png", "format": "RGBA8888", "size": { - "w": 75, - "h": 75 + "w": 67, + "h": 67 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 30, + "h": 67 }, "spriteSourceSize": { - "x": 24, - "y": 4, - "w": 34, - "h": 75 + "x": 0, + "y": 0, + "w": 30, + "h": 67 }, "frame": { "x": 0, "y": 0, - "w": 34, - "h": 75 + "w": 30, + "h": 67 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:54f184bf1995a94a78aff33c9a851e6b:a6c9b3fe428b0cd0344b5cf14b999f36:cf221da9747cb8cb356053d3042d8d22$" + "smartupdate": "$TexturePacker:SmartUpdate:cb4d76912d528afe986ac5cad775f455:cc70d9738c9c7347b2ac9afec4ec9290:cf221da9747cb8cb356053d3042d8d22$" } } diff --git a/public/images/trainer/penny.png b/public/images/trainer/penny.png index 0e36760e21b..67c90a41462 100644 Binary files a/public/images/trainer/penny.png and b/public/images/trainer/penny.png differ diff --git a/public/images/trainer/plasma_grunt_f.json b/public/images/trainer/plasma_grunt_f.json index 4d23eeeb483..4a73a55e24b 100644 --- a/public/images/trainer/plasma_grunt_f.json +++ b/public/images/trainer/plasma_grunt_f.json @@ -4,30 +4,408 @@ "image": "plasma_grunt_f.png", "format": "RGBA8888", "size": { - "w": 75, - "h": 75 + "w": 186, + "h": 186 }, "scale": 1, "frames": [ { - "filename": "0001.png", + "filename": "0002.png", "rotated": false, - "trimmed": false, + "trimmed": true, "sourceSize": { "w": 80, "h": 80 }, "spriteSourceSize": { - "x": 21, - "y": 4, - "w": 37, - "h": 75 + "x": 16, + "y": 31, + "w": 49, + "h": 49 }, "frame": { "x": 0, "y": 0, - "w": 37, - "h": 75 + "w": 49, + "h": 49 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 16, + "y": 31, + "w": 49, + "h": 49 + }, + "frame": { + "x": 0, + "y": 0, + "w": 49, + "h": 49 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 27, + "w": 46, + "h": 53 + }, + "frame": { + "x": 49, + "y": 0, + "w": 46, + "h": 53 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 27, + "w": 45, + "h": 53 + }, + "frame": { + "x": 0, + "y": 49, + "w": 45, + "h": 53 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 27, + "w": 45, + "h": 53 + }, + "frame": { + "x": 0, + "y": 49, + "w": 45, + "h": 53 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 27, + "w": 45, + "h": 53 + }, + "frame": { + "x": 0, + "y": 49, + "w": 45, + "h": 53 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 27, + "w": 45, + "h": 53 + }, + "frame": { + "x": 0, + "y": 49, + "w": 45, + "h": 53 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 15, + "y": 33, + "w": 50, + "h": 47 + }, + "frame": { + "x": 45, + "y": 53, + "w": 50, + "h": 47 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 15, + "y": 33, + "w": 50, + "h": 47 + }, + "frame": { + "x": 45, + "y": 53, + "w": 50, + "h": 47 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 15, + "y": 36, + "w": 50, + "h": 44 + }, + "frame": { + "x": 45, + "y": 100, + "w": 50, + "h": 44 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 15, + "y": 36, + "w": 50, + "h": 44 + }, + "frame": { + "x": 45, + "y": 100, + "w": 50, + "h": 44 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 27, + "w": 45, + "h": 53 + }, + "frame": { + "x": 0, + "y": 102, + "w": 45, + "h": 53 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 15, + "y": 38, + "w": 50, + "h": 42 + }, + "frame": { + "x": 45, + "y": 144, + "w": 50, + "h": 42 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 15, + "y": 38, + "w": 50, + "h": 42 + }, + "frame": { + "x": 45, + "y": 144, + "w": 50, + "h": 42 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 27, + "w": 43, + "h": 53 + }, + "frame": { + "x": 95, + "y": 0, + "w": 43, + "h": 53 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 27, + "w": 43, + "h": 53 + }, + "frame": { + "x": 95, + "y": 53, + "w": 43, + "h": 53 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 16, + "y": 31, + "w": 49, + "h": 49 + }, + "frame": { + "x": 95, + "y": 106, + "w": 49, + "h": 49 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 16, + "y": 31, + "w": 49, + "h": 49 + }, + "frame": { + "x": 95, + "y": 106, + "w": 49, + "h": 49 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 16, + "y": 29, + "w": 46, + "h": 51 + }, + "frame": { + "x": 138, + "y": 0, + "w": 46, + "h": 51 } } ] @@ -36,6 +414,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:c3001e18f1878c01a4825697200e823e:2003e0d4db249f7020c3471872198ac8:b01645b9e941158814978f2126e7e995$" + "smartupdate": "$TexturePacker:SmartUpdate:e8e867ad78b993918fba435e10511740:758a95ecd97e2607ff6ab81f85e665e6:b01645b9e941158814978f2126e7e995$" } } diff --git a/public/images/trainer/plasma_grunt_f.png b/public/images/trainer/plasma_grunt_f.png index 95b065f4360..7fa804cc39d 100644 Binary files a/public/images/trainer/plasma_grunt_f.png and b/public/images/trainer/plasma_grunt_f.png differ diff --git a/public/images/trainer/plasma_grunt_m.json b/public/images/trainer/plasma_grunt_m.json index 7c34b16790f..8fda1bd947b 100644 --- a/public/images/trainer/plasma_grunt_m.json +++ b/public/images/trainer/plasma_grunt_m.json @@ -4,30 +4,555 @@ "image": "plasma_grunt_m.png", "format": "RGBA8888", "size": { - "w": 72, - "h": 72 + "w": 262, + "h": 262 }, "scale": 1, "frames": [ { - "filename": "0001.png", + "filename": "0021.png", "rotated": false, - "trimmed": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 13, + "y": 11, + "w": 54, + "h": 69 + }, + "frame": { + "x": 0, + "y": 0, + "w": 54, + "h": 69 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 13, + "y": 11, + "w": 54, + "h": 69 + }, + "frame": { + "x": 0, + "y": 0, + "w": 54, + "h": 69 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, "sourceSize": { "w": 80, "h": 80 }, "spriteSourceSize": { "x": 16, - "y": 7, - "w": 47, - "h": 72 + "y": 11, + "w": 51, + "h": 69 }, "frame": { "x": 0, + "y": 69, + "w": 51, + "h": 69 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 11, + "w": 50, + "h": 69 + }, + "frame": { + "x": 0, + "y": 138, + "w": 50, + "h": 69 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 11, + "w": 50, + "h": 69 + }, + "frame": { + "x": 0, + "y": 138, + "w": 50, + "h": 69 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 11, + "w": 50, + "h": 69 + }, + "frame": { + "x": 0, + "y": 138, + "w": 50, + "h": 69 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 11, + "w": 50, + "h": 69 + }, + "frame": { + "x": 0, + "y": 138, + "w": 50, + "h": 69 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 11, + "w": 50, + "h": 69 + }, + "frame": { + "x": 50, + "y": 138, + "w": 50, + "h": 69 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 11, + "w": 50, + "h": 69 + }, + "frame": { + "x": 50, + "y": 138, + "w": 50, + "h": 69 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 11, + "w": 50, + "h": 69 + }, + "frame": { + "x": 51, + "y": 69, + "w": 50, + "h": 69 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 11, + "w": 50, + "h": 69 + }, + "frame": { + "x": 54, "y": 0, - "w": 47, - "h": 72 + "w": 50, + "h": 69 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 17, + "y": 11, + "w": 50, + "h": 69 + }, + "frame": { + "x": 54, + "y": 0, + "w": 50, + "h": 69 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 18, + "y": 11, + "w": 49, + "h": 69 + }, + "frame": { + "x": 100, + "y": 138, + "w": 49, + "h": 69 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 18, + "y": 11, + "w": 49, + "h": 69 + }, + "frame": { + "x": 100, + "y": 138, + "w": 49, + "h": 69 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 14, + "y": 13, + "w": 52, + "h": 67 + }, + "frame": { + "x": 101, + "y": 69, + "w": 52, + "h": 67 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 14, + "y": 13, + "w": 52, + "h": 67 + }, + "frame": { + "x": 101, + "y": 69, + "w": 52, + "h": 67 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 14, + "y": 13, + "w": 52, + "h": 67 + }, + "frame": { + "x": 104, + "y": 0, + "w": 52, + "h": 67 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 53, + "h": 65 + }, + "frame": { + "x": 156, + "y": 0, + "w": 53, + "h": 65 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 53, + "h": 65 + }, + "frame": { + "x": 156, + "y": 0, + "w": 53, + "h": 65 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 53, + "h": 65 + }, + "frame": { + "x": 209, + "y": 0, + "w": 53, + "h": 65 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 53, + "h": 65 + }, + "frame": { + "x": 156, + "y": 65, + "w": 53, + "h": 65 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 53, + "h": 65 + }, + "frame": { + "x": 209, + "y": 65, + "w": 53, + "h": 65 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 53, + "h": 65 + }, + "frame": { + "x": 153, + "y": 130, + "w": 53, + "h": 65 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 53, + "h": 65 + }, + "frame": { + "x": 149, + "y": 195, + "w": 53, + "h": 65 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 53, + "h": 65 + }, + "frame": { + "x": 202, + "y": 195, + "w": 53, + "h": 65 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 80, + "h": 80 + }, + "spriteSourceSize": { + "x": 12, + "y": 15, + "w": 53, + "h": 65 + }, + "frame": { + "x": 206, + "y": 130, + "w": 53, + "h": 65 } } ] @@ -36,6 +561,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:61f195ebbcde93ab7442408edad7fe7a:28ae203b3cb42a94c4ba4420fdebdccc:9ae0ee174d431d48052a2f6b74e9d40c$" + "smartupdate": "$TexturePacker:SmartUpdate:8e214218a81b826b2cecce3e41f6eee8:2b88638dcf4559e6aad7c14cd730b7c3:9ae0ee174d431d48052a2f6b74e9d40c$" } } diff --git a/public/images/trainer/plasma_grunt_m.png b/public/images/trainer/plasma_grunt_m.png index e3ec6dd8c35..801e91b1d6d 100644 Binary files a/public/images/trainer/plasma_grunt_m.png and b/public/images/trainer/plasma_grunt_m.png differ diff --git a/public/images/trainer/plumeria.json b/public/images/trainer/plumeria.json index 936a8766750..4175fe5d716 100644 --- a/public/images/trainer/plumeria.json +++ b/public/images/trainer/plumeria.json @@ -4,8 +4,8 @@ "image": "plumeria.png", "format": "RGBA8888", "size": { - "w": 72, - "h": 72 + "w": 76, + "h": 76 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 40, + "h": 76 }, "spriteSourceSize": { - "x": 23, - "y": 7, - "w": 36, - "h": 72 + "x": 0, + "y": 0, + "w": 40, + "h": 76 }, "frame": { "x": 0, "y": 0, - "w": 36, - "h": 72 + "w": 40, + "h": 76 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:5527e7b646932d429928b53f055e9d27:c0640510780d2974f9b74a7f8e6b29aa:7bfec029bae78c9d483f59c35b73afad$" + "smartupdate": "$TexturePacker:SmartUpdate:d0e080a4dcc30b39616c49dfd96c98f7:47c6a714be68fabdf11801166e154db6:7bfec029bae78c9d483f59c35b73afad$" } } diff --git a/public/images/trainer/plumeria.png b/public/images/trainer/plumeria.png index b7382f6afde..4528c3e2053 100644 Binary files a/public/images/trainer/plumeria.png and b/public/images/trainer/plumeria.png differ diff --git a/public/images/trainer/rose.json b/public/images/trainer/rose.json index 86869257b63..883aa128e50 100644 --- a/public/images/trainer/rose.json +++ b/public/images/trainer/rose.json @@ -4,8 +4,8 @@ "image": "rose.png", "format": "RGBA8888", "size": { - "w": 79, - "h": 79 + "w": 77, + "h": 77 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 31, + "h": 77 }, "spriteSourceSize": { - "x": 16, - "y": 1, - "w": 52, - "h": 79 + "x": 0, + "y": 0, + "w": 31, + "h": 77 }, "frame": { "x": 0, "y": 0, - "w": 52, - "h": 79 + "w": 31, + "h": 77 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:2b4ccaff7255c7d72661eac13de83ff8:72ee3660cdf470bd67375d355307e19d:8d35b104fc841baa4443581e6cea979e$" + "smartupdate": "$TexturePacker:SmartUpdate:be2215e7232e2260242613e54c91c3c4:852fb3fda379db104106f8888649d9d5:8d35b104fc841baa4443581e6cea979e$" } } diff --git a/public/images/trainer/rose.png b/public/images/trainer/rose.png index f90da7568d4..4c448e3302b 100644 Binary files a/public/images/trainer/rose.png and b/public/images/trainer/rose.png differ diff --git a/public/images/trainer/shelly.json b/public/images/trainer/shelly.json index 7761779864a..bac17e2885e 100644 --- a/public/images/trainer/shelly.json +++ b/public/images/trainer/shelly.json @@ -4,8 +4,8 @@ "image": "shelly.png", "format": "RGBA8888", "size": { - "w": 80, - "h": 80 + "w": 78, + "h": 78 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 45, + "h": 78 }, "spriteSourceSize": { "x": 0, "y": 0, - "w": 80, - "h": 80 + "w": 45, + "h": 78 }, "frame": { "x": 0, "y": 0, - "w": 80, - "h": 80 + "w": 45, + "h": 78 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:831f5748dad92911b10a1cb358ee2dae:a3bf81bbaa3b49cad5e0e549cf94563b:bb6befc9383c9c08837183ae2a7a80c1$" + "smartupdate": "$TexturePacker:SmartUpdate:601dbcee82b14bde5072df26ddd7d684:a0d576e65d8e3ff549dde75f0a82bc94:a277ff67eb669e1dac57ad29940004ac$" } } diff --git a/public/images/trainer/shelly.png b/public/images/trainer/shelly.png index 2885fbde48e..95e6a07310d 100644 Binary files a/public/images/trainer/shelly.png and b/public/images/trainer/shelly.png differ diff --git a/public/images/trainer/skull_grunt_f.json b/public/images/trainer/skull_grunt_f.json index 182f9300ad5..b8c42ffafdd 100644 --- a/public/images/trainer/skull_grunt_f.json +++ b/public/images/trainer/skull_grunt_f.json @@ -4,8 +4,8 @@ "image": "skull_grunt_f.png", "format": "RGBA8888", "size": { - "w": 74, - "h": 74 + "w": 69, + "h": 69 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 31, - "h": 74 + "w": 44, + "h": 69 }, "spriteSourceSize": { "x": 0, "y": 0, - "w": 31, - "h": 74 + "w": 44, + "h": 69 }, "frame": { "x": 0, "y": 0, - "w": 31, - "h": 74 + "w": 44, + "h": 69 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:71a1f5b1981674c6e81163ac8ea576c3:a5e612d58e5f0a1489e111212baea09d:dd369353af16e4c5eb6547e129dfac18$" + "smartupdate": "$TexturePacker:SmartUpdate:b9685517b9674887653c84a03f3781c0:894dcd88bf117d48750df82b7bfac644:9035f560a0ab0d45bcc084aba7172990$" } } diff --git a/public/images/trainer/skull_grunt_f.png b/public/images/trainer/skull_grunt_f.png index fe7834ba4a8..c26e8d7f882 100644 Binary files a/public/images/trainer/skull_grunt_f.png and b/public/images/trainer/skull_grunt_f.png differ diff --git a/public/images/trainer/skull_grunt_m.json b/public/images/trainer/skull_grunt_m.json index 7c728e9d3fc..6a2d13ed8a3 100644 --- a/public/images/trainer/skull_grunt_m.json +++ b/public/images/trainer/skull_grunt_m.json @@ -4,8 +4,8 @@ "image": "skull_grunt_m.png", "format": "RGBA8888", "size": { - "w": 72, - "h": 72 + "w": 64, + "h": 64 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 51, - "h": 72 + "w": 39, + "h": 64 }, "spriteSourceSize": { "x": 0, "y": 0, - "w": 51, - "h": 72 + "w": 39, + "h": 64 }, "frame": { "x": 0, "y": 0, - "w": 51, - "h": 72 + "w": 39, + "h": 64 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:4deb2a68e4d168bb1a40cb5d190a7d1f:be3d7b29f4b544ba51cf907691fef51d:df57ca2c9bf5f80d930306e15a851d4d$" + "smartupdate": "$TexturePacker:SmartUpdate:c39ac1d47c8cbe300cffe98bda48c590:b400e0c6286f0e20dfbc383f7453e35b:1ff10b395daf6ebfa377680a6404f816$" } } diff --git a/public/images/trainer/skull_grunt_m.png b/public/images/trainer/skull_grunt_m.png index f2b8acba984..8babb09ec74 100644 Binary files a/public/images/trainer/skull_grunt_m.png and b/public/images/trainer/skull_grunt_m.png differ diff --git a/public/images/trainer/star_grunt_f.json b/public/images/trainer/star_grunt_f.json index e26477e3512..a6b613f44cf 100644 --- a/public/images/trainer/star_grunt_f.json +++ b/public/images/trainer/star_grunt_f.json @@ -14,12 +14,12 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 30, + "h": 68 }, "spriteSourceSize": { - "x": 24, - "y": 11, + "x": 0, + "y": 0, "w": 30, "h": 68 }, @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:b542a1bdd6995584fc776f75d578b434:f03fddece4494ab59698002fe6671972:c6f0e54e24ec5ffaa711700431b1955e$" + "smartupdate": "$TexturePacker:SmartUpdate:a5493363086a57d0f145cf61c42475de:2e4d3b330bb89e05e93f34d605eee203:c6f0e54e24ec5ffaa711700431b1955e$" } } diff --git a/public/images/trainer/star_grunt_f.png b/public/images/trainer/star_grunt_f.png index 6eb63ae1e03..ee0c25147cc 100644 Binary files a/public/images/trainer/star_grunt_f.png and b/public/images/trainer/star_grunt_f.png differ diff --git a/public/images/trainer/star_grunt_m.json b/public/images/trainer/star_grunt_m.json index bf49e3027e6..ba245e2eeb3 100644 --- a/public/images/trainer/star_grunt_m.json +++ b/public/images/trainer/star_grunt_m.json @@ -4,8 +4,8 @@ "image": "star_grunt_m.png", "format": "RGBA8888", "size": { - "w": 70, - "h": 70 + "w": 64, + "h": 64 }, "scale": 1, "frames": [ @@ -14,20 +14,20 @@ "rotated": false, "trimmed": false, "sourceSize": { - "w": 80, - "h": 80 + "w": 36, + "h": 64 }, "spriteSourceSize": { - "x": 24, - "y": 9, - "w": 31, - "h": 70 + "x": 0, + "y": 0, + "w": 36, + "h": 64 }, "frame": { "x": 0, "y": 0, - "w": 31, - "h": 70 + "w": 36, + "h": 64 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:abc4b0424c37fd55a2bf2e9f5142adce:41a140aa68a1eda61d9a00cab4e07721:a0796711f9e0333796b6629cd43ff8e8$" + "smartupdate": "$TexturePacker:SmartUpdate:11da63c3829d44356a3c26d094212d64:45ebf021548ac0e12b6f25093c5bf0db:a0796711f9e0333796b6629cd43ff8e8$" } } diff --git a/public/images/trainer/star_grunt_m.png b/public/images/trainer/star_grunt_m.png index a69359eda8e..13fd4e88510 100644 Binary files a/public/images/trainer/star_grunt_m.png and b/public/images/trainer/star_grunt_m.png differ diff --git a/public/locales b/public/locales index 5ef993b95fa..2d3765a4f03 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit 5ef993b95fa8248adc0fb7d9489baccf546bf8e3 +Subproject commit 2d3765a4f035b4916523bf75b754e153e9d65134 diff --git a/src/account.ts b/src/account.ts index 316645b38ff..4c86595a5e6 100644 --- a/src/account.ts +++ b/src/account.ts @@ -11,8 +11,8 @@ export function initLoggedInUser(): void { loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: "", hasAdminRole: false }; } -export function updateUserInfo(): Promise<[boolean, integer]> { - return new Promise<[boolean, integer]>(resolve => { +export function updateUserInfo(): Promise<[boolean, number]> { + return new Promise<[boolean, number]>(resolve => { if (bypassLogin) { loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: "", hasAdminRole: false }; let lastSessionSlot = -1; diff --git a/src/battle-scene.ts b/src/battle-scene.ts index d042d2c0b12..82ee785896c 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -118,7 +118,7 @@ export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; const DEBUG_RNG = false; -const OPP_IVS_OVERRIDE_VALIDATED : integer[] = ( +const OPP_IVS_OVERRIDE_VALIDATED : number[] = ( Array.isArray(Overrides.OPP_IVS_OVERRIDE) ? Overrides.OPP_IVS_OVERRIDE : new Array(6).fill(Overrides.OPP_IVS_OVERRIDE) @@ -134,7 +134,7 @@ interface StarterColors { } export interface PokeballCounts { - [pb: string]: integer; + [pb: string]: number; } export type AnySound = Phaser.Sound.WebAudioSound | Phaser.Sound.HTML5AudioSound | Phaser.Sound.NoAudioSound; @@ -149,15 +149,15 @@ export default class BattleScene extends SceneBase { public inputController: InputsController; public uiInputs: UiInputs; - public sessionPlayTime: integer | null = null; - public lastSavePlayTime: integer | null = null; + public sessionPlayTime: number | null = null; + public lastSavePlayTime: number | null = null; public masterVolume: number = 0.5; public bgmVolume: number = 1; public fieldVolume: number = 1; public seVolume: number = 1; public uiVolume: number = 1; - public gameSpeed: integer = 1; - public damageNumbersMode: integer = 0; + public gameSpeed: number = 1; + public damageNumbersMode: number = 0; public reroll: boolean = false; public shopCursorTarget: number = ShopCursorTarget.REWARDS; public commandCursorMemory: boolean = false; @@ -176,16 +176,16 @@ export default class BattleScene extends SceneBase { * - 1 = 'Passives Only' * - 2 = 'On' */ - public candyUpgradeNotification: integer = 0; + public candyUpgradeNotification: number = 0; /** * Determines what type of notification is used for Candy Upgrades * - 0 = 'Icon' * - 1 = 'Animation' */ - public candyUpgradeDisplay: integer = 0; + public candyUpgradeDisplay: number = 0; public moneyFormat: MoneyFormat = MoneyFormat.NORMAL; public uiTheme: UiTheme = UiTheme.DEFAULT; - public windowType: integer = 0; + public windowType: number = 0; public experimentalSprites: boolean = false; public musicPreference: number = MusicPreference.ALLGENS; public moveAnimations: boolean = true; @@ -212,7 +212,7 @@ export default class BattleScene extends SceneBase { * @default 0 - Uses the default normal experience gain display. */ public expParty: ExpNotification = 0; - public hpBarSpeed: integer = 0; + public hpBarSpeed: number = 0; public fusionPaletteSwaps: boolean = true; public enableTouchControls: boolean = false; public enableVibration: boolean = false; @@ -223,7 +223,7 @@ export default class BattleScene extends SceneBase { * - 0 = 'Switch' * - 1 = 'Set' - The option to switch the active pokemon at the start of a battle will not display. */ - public battleStyle: integer = BattleStyle.SWITCH; + public battleStyle: number = BattleStyle.SWITCH; /** * Defines whether or not to show type effectiveness hints @@ -235,7 +235,7 @@ export default class BattleScene extends SceneBase { public disableMenu: boolean = false; public gameData: GameData; - public sessionSlotId: integer; + public sessionSlotId: number; /** PhaseQueue: dequeue/remove the first element to get the next phase */ public phaseQueue: Phase[]; @@ -244,7 +244,7 @@ export default class BattleScene extends SceneBase { private phaseQueuePrepend: Phase[]; /** overrides default of inserting phases to end of phaseQueuePrepend array, useful or inserting Phases "out of order" */ - private phaseQueuePrependSpliceIndex: integer; + private phaseQueuePrependSpliceIndex: number; private nextCommandPhaseQueue: Phase[]; private currentPhase: Phase | null; @@ -265,13 +265,13 @@ export default class BattleScene extends SceneBase { public arenaNextEnemy: ArenaBase; public arena: Arena; public gameMode: GameMode; - public score: integer; + public score: number; public lockModifierTiers: boolean; public trainer: Phaser.GameObjects.Sprite; public lastEnemyTrainer: Trainer | null; public currentBattle: Battle; public pokeballCounts: PokeballCounts; - public money: integer; + public money: number; public pokemonInfoContainer: PokemonInfoContainer; private party: PlayerPokemon[]; /** Session save data that pertains to Mystery Encounters */ @@ -300,7 +300,7 @@ export default class BattleScene extends SceneBase { public seed: string; public waveSeed: string; - public waveCycleOffset: integer; + public waveCycleOffset: number; public offsetGym: boolean; public damageNumberHandler: DamageNumberHandler; @@ -314,9 +314,9 @@ export default class BattleScene extends SceneBase { private bgmCache: Set = new Set(); private playTimeTimer: Phaser.Time.TimerEvent; - public rngCounter: integer = 0; + public rngCounter: number = 0; public rngSeedOverride: string = ""; - public rngOffset: integer = 0; + public rngOffset: number = 0; public inputMethod: string; private infoToggles: InfoToggle[] = []; @@ -717,7 +717,7 @@ export default class BattleScene extends SceneBase { const traverseVariantData = (keys: string[]) => { let variantTree = variantData; let expTree = expVariantData; - keys.map((k: string, i: integer) => { + keys.map((k: string, i: number) => { if (i < keys.length - 1) { variantTree = variantTree[k]; expTree = expTree[k]; @@ -926,12 +926,12 @@ export default class BattleScene extends SceneBase { return activeOnly ? this.infoToggles.filter(t => t?.isActive()) : this.infoToggles; } - getPokemonById(pokemonId: integer): Pokemon | null { + getPokemonById(pokemonId: number): Pokemon | null { const findInParty = (party: Pokemon[]) => party.find(p => p.id === pokemonId); return (findInParty(this.getPlayerParty()) || findInParty(this.getEnemyParty())) ?? null; } - addPlayerPokemon(species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData, postProcess?: (playerPokemon: PlayerPokemon) => void): PlayerPokemon { + addPlayerPokemon(species: PokemonSpecies, level: number, abilityIndex?: number, formIndex?: number, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: number[], nature?: Nature, dataSource?: Pokemon | PokemonData, postProcess?: (playerPokemon: PlayerPokemon) => void): PlayerPokemon { const pokemon = new PlayerPokemon(species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource); if (postProcess) { postProcess(pokemon); @@ -940,7 +940,7 @@ export default class BattleScene extends SceneBase { return pokemon; } - addEnemyPokemon(species: PokemonSpecies, level: integer, trainerSlot: TrainerSlot, boss: boolean = false, shinyLock: boolean = false, dataSource?: PokemonData, postProcess?: (enemyPokemon: EnemyPokemon) => void): EnemyPokemon { + addEnemyPokemon(species: PokemonSpecies, level: number, trainerSlot: TrainerSlot, boss: boolean = false, shinyLock: boolean = false, dataSource?: PokemonData, postProcess?: (enemyPokemon: EnemyPokemon) => void): EnemyPokemon { if (Overrides.OPP_LEVEL_OVERRIDE > 0) { level = Overrides.OPP_LEVEL_OVERRIDE; } @@ -1092,7 +1092,7 @@ export default class BattleScene extends SceneBase { * @param min The minimum integer to pick, default `0` * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) */ - randBattleSeedInt(range: integer, min: integer = 0): integer { + randBattleSeedInt(range: number, min: number = 0): number { return this.currentBattle?.randSeedInt(range, min); } @@ -1217,7 +1217,7 @@ export default class BattleScene extends SceneBase { return Math.max(doubleChance.value, 1); } - newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean, mysteryEncounterType?: MysteryEncounterType): Battle | null { + newBattle(waveIndex?: number, battleType?: BattleType, trainerData?: TrainerData, double?: boolean, mysteryEncounterType?: MysteryEncounterType): Battle | null { const _startingWave = Overrides.STARTING_WAVE_OVERRIDE || startingWave; const newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (_startingWave - 1)) + 1); let newDouble: boolean | undefined; @@ -1443,7 +1443,7 @@ export default class BattleScene extends SceneBase { }); } - getSpeciesFormIndex(species: PokemonSpecies, gender?: Gender, nature?: Nature, ignoreArena?: boolean): integer { + getSpeciesFormIndex(species: PokemonSpecies, gender?: Gender, nature?: Nature, ignoreArena?: boolean): number { if (!species.forms?.length) { return 0; } @@ -1490,6 +1490,8 @@ export default class BattleScene extends SceneBase { return 0; // Don't give trainers Battle Bond Greninja } return Utils.randSeedInt(2); + case Species.URSHIFU: + return Utils.randSeedInt(2); case Species.ZYGARDE: return Utils.randSeedInt(4); case Species.MINIOR: @@ -1538,7 +1540,7 @@ export default class BattleScene extends SceneBase { return ret; } - private getGeneratedWaveCycleOffset(): integer { + private getGeneratedWaveCycleOffset(): number { let ret = 0; this.executeWithSeedOffset(() => { ret = Utils.randSeedInt(8) * 5; @@ -1546,7 +1548,7 @@ export default class BattleScene extends SceneBase { return ret; } - getEncounterBossSegments(waveIndex: integer, level: integer, species?: PokemonSpecies, forceBoss: boolean = false): integer { + getEncounterBossSegments(waveIndex: number, level: number, species?: PokemonSpecies, forceBoss: boolean = false): number { if (Overrides.OPP_HEALTH_SEGMENTS_OVERRIDE > 1) { return Overrides.OPP_HEALTH_SEGMENTS_OVERRIDE; } else if (Overrides.OPP_HEALTH_SEGMENTS_OVERRIDE === 1) { @@ -1570,7 +1572,7 @@ export default class BattleScene extends SceneBase { return 0; } - let ret: integer = 2; + let ret: number = 2; if (level >= 100) { ret++; @@ -1587,7 +1589,7 @@ export default class BattleScene extends SceneBase { trySpreadPokerus(): void { const party = this.getPlayerParty(); - const infectedIndexes: integer[] = []; + const infectedIndexes: number[] = []; const spread = (index: number, spreadTo: number) => { const partyMember = party[index + spreadTo]; if (!partyMember.pokerus && !Utils.randSeedInt(10)) { @@ -1611,7 +1613,7 @@ export default class BattleScene extends SceneBase { }); } - resetSeed(waveIndex?: integer): void { + resetSeed(waveIndex?: number): void { const wave = waveIndex || this.currentBattle?.waveIndex || 0; this.waveSeed = Utils.shiftCharCodes(this.seed, wave); Phaser.Math.RND.sow([ this.waveSeed ]); @@ -1619,7 +1621,7 @@ export default class BattleScene extends SceneBase { this.rngCounter = 0; } - executeWithSeedOffset(func: Function, offset: integer, seedOverride?: string): void { + executeWithSeedOffset(func: Function, offset: number, seedOverride?: string): void { if (!func) { return; } @@ -1667,7 +1669,7 @@ export default class BattleScene extends SceneBase { this.arenaFlyout.toggleFlyout(pressed); } - showFieldOverlay(duration: integer): Promise { + showFieldOverlay(duration: number): Promise { return new Promise(resolve => { this.tweens.add({ targets: this.fieldOverlay, @@ -1679,7 +1681,7 @@ export default class BattleScene extends SceneBase { }); } - hideFieldOverlay(duration: integer): Promise { + hideFieldOverlay(duration: number): Promise { return new Promise(resolve => { this.tweens.add({ targets: this.fieldOverlay, @@ -1699,7 +1701,7 @@ export default class BattleScene extends SceneBase { } } - showShopOverlay(duration: integer): Promise { + showShopOverlay(duration: number): Promise { this.shopOverlayShown = true; return new Promise(resolve => { this.tweens.add({ @@ -1712,7 +1714,7 @@ export default class BattleScene extends SceneBase { }); } - hideShopOverlay(duration: integer): Promise { + hideShopOverlay(duration: number): Promise { this.shopOverlayShown = false; return new Promise(resolve => { this.tweens.add({ @@ -1801,7 +1803,7 @@ export default class BattleScene extends SceneBase { }); } - hideLuckText(duration: integer): void { + hideLuckText(duration: number): void { if (this.reroll) { return; } @@ -1841,7 +1843,7 @@ export default class BattleScene extends SceneBase { } addFaintedEnemyScore(enemy: EnemyPokemon): void { - let scoreIncrease = enemy.getSpeciesForm().getBaseExp() * (enemy.level / this.getMaxExpLevel()) * ((enemy.ivs.reduce((iv: integer, total: integer) => total += iv, 0) / 93) * 0.2 + 0.8); + let scoreIncrease = enemy.getSpeciesForm().getBaseExp() * (enemy.level / this.getMaxExpLevel()) * ((enemy.ivs.reduce((iv: number, total: number) => total += iv, 0) / 93) * 0.2 + 0.8); this.findModifiers(m => m instanceof PokemonHeldItemModifier && m.pokemonId === enemy.id, false).map(m => scoreIncrease *= (m as PokemonHeldItemModifier).getScoreMultiplier()); if (enemy.isBoss()) { scoreIncrease *= Math.sqrt(enemy.bossSegments); @@ -1849,7 +1851,7 @@ export default class BattleScene extends SceneBase { this.currentBattle.battleScore += Math.ceil(scoreIncrease); } - getMaxExpLevel(ignoreLevelCap: boolean = false): integer { + getMaxExpLevel(ignoreLevelCap: boolean = false): number { if (Overrides.LEVEL_CAP_OVERRIDE > 0) { return Overrides.LEVEL_CAP_OVERRIDE; } else if (ignoreLevelCap || Overrides.LEVEL_CAP_OVERRIDE < 0) { @@ -1861,7 +1863,7 @@ export default class BattleScene extends SceneBase { return Math.ceil(baseLevel / 2) * 2 + 2; } - randomSpecies(waveIndex: integer, level: integer, fromArenaPool?: boolean, speciesFilter?: PokemonSpeciesFilter, filterAllEvolutions?: boolean): PokemonSpecies { + randomSpecies(waveIndex: number, level: number, fromArenaPool?: boolean, speciesFilter?: PokemonSpeciesFilter, filterAllEvolutions?: boolean): PokemonSpecies { if (fromArenaPool) { return this.arena.randomSpecies(waveIndex, level, undefined, getPartyLuckValue(this.party)); } @@ -1876,13 +1878,13 @@ export default class BattleScene extends SceneBase { return filteredSpecies[Utils.randSeedInt(filteredSpecies.length)]; } - generateRandomBiome(waveIndex: integer): Biome { + generateRandomBiome(waveIndex: number): Biome { const relWave = waveIndex % 250; const biomes = Utils.getEnumValues(Biome).filter(b => b !== Biome.TOWN && b !== Biome.END); const maxDepth = biomeDepths[Biome.END][0] - 2; const depthWeights = new Array(maxDepth + 1).fill(null) - .map((_, i: integer) => ((1 - Math.min(Math.abs((i / (maxDepth - 1)) - (relWave / 250)) + 0.25, 1)) / 0.75) * 250); - const biomeThresholds: integer[] = []; + .map((_, i: number) => ((1 - Math.min(Math.abs((i / (maxDepth - 1)) - (relWave / 250)) + 0.25, 1)) / 0.75) * 250); + const biomeThresholds: number[] = []; let totalWeight = 0; for (const biome of biomes) { totalWeight += Math.ceil(depthWeights[biomeDepths[biome][0] - 1] / biomeDepths[biome][1]); @@ -2006,7 +2008,7 @@ export default class BattleScene extends SceneBase { } } - fadeOutBgm(duration: integer = 500, destroy: boolean = true): boolean { + fadeOutBgm(duration: number = 500, destroy: boolean = true): boolean { if (!this.bgm) { return false; } @@ -2073,7 +2075,7 @@ export default class BattleScene extends SceneBase { } } - playSoundWithoutBgm(soundName: string, pauseDuration?: integer): AnySound { + playSoundWithoutBgm(soundName: string, pauseDuration?: number): AnySound { this.bgmCache.add(soundName); const resumeBgm = this.pauseBgm(); this.playSound(soundName); @@ -2111,10 +2113,14 @@ export default class BattleScene extends SceneBase { return 10.145; case "battle_kalos_champion": //XY Kalos Champion Battle return 10.380; + case "battle_champion_kukui": //SM Kukui Battle + return 15.784; case "battle_alola_champion": //USUM Alola Champion Battle return 13.025; case "battle_galar_champion": //SWSH Galar Champion Battle return 61.635; + case "battle_mustard": //SWSH Mustard Battle + return 22.442; case "battle_champion_geeta": //SV Champion Geeta Battle return 37.447; case "battle_champion_nemona": //SV Champion Nemona Battle @@ -2249,8 +2255,8 @@ export default class BattleScene extends SceneBase { return 12.062; case "battle_galactic_grunt": //BDSP Team Galactic Battle return 13.043; - case "battle_plasma_grunt": //BW Team Plasma Battle - return 12.974; + case "battle_plasma_grunt": //B2W2 Team Plasma Battle + return 14.758; case "battle_flare_grunt": //XY Team Flare Battle return 4.228; case "battle_aether_grunt": // SM Aether Foundation Battle @@ -2263,6 +2269,8 @@ export default class BattleScene extends SceneBase { return 133.362; case "battle_galactic_admin": //BDSP Team Galactic Admin Battle return 11.997; + case "battle_colress": //B2W2 Colress Battle + return 12.234; case "battle_skull_admin": //SM Team Skull Admin Battle return 15.463; case "battle_oleana": //SWSH Oleana Battle @@ -2527,7 +2535,7 @@ export default class BattleScene extends SceneBase { * @param promptDelay optional param for MessagePhase constructor * @param defer boolean for which queue to add it to, false -> add to PhaseQueuePrepend, true -> nextCommandPhaseQueue */ - queueMessage(message: string, callbackDelay?: integer | null, prompt?: boolean | null, promptDelay?: integer | null, defer?: boolean | null) { + queueMessage(message: string, callbackDelay?: number | null, prompt?: boolean | null, promptDelay?: number | null, defer?: boolean | null) { const phase = new MessagePhase(message, callbackDelay, prompt, promptDelay); if (!defer) { // adds to the end of PhaseQueuePrepend @@ -2549,14 +2557,14 @@ export default class BattleScene extends SceneBase { this.phaseQueue.push(new TurnInitPhase()); } - addMoney(amount: integer): void { + addMoney(amount: number): void { this.money = Math.min(this.money + amount, Number.MAX_SAFE_INTEGER); this.updateMoneyText(); this.animateMoneyChanged(true); this.validateAchvs(MoneyAchv); } - getWaveMoneyAmount(moneyMultiplier: number): integer { + getWaveMoneyAmount(moneyMultiplier: number): number { const waveIndex = this.currentBattle.waveIndex; const waveSetIndex = Math.ceil(waveIndex / 10) - 1; const moneyValue = Math.pow((waveSetIndex + 1 + (0.75 + (((waveIndex - 1) % 10) + 1) / 10)) * 100, 1 + 0.005 * waveSetIndex) * moneyMultiplier; @@ -2753,7 +2761,7 @@ export default class BattleScene extends SceneBase { }); } - removePartyMemberModifiers(partyMemberIndex: integer): Promise { + removePartyMemberModifiers(partyMemberIndex: number): Promise { return new Promise(resolve => { const pokemonId = this.getPlayerParty()[partyMemberIndex].id; const modifiersToRemove = this.modifiers.filter(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === pokemonId); @@ -2785,7 +2793,7 @@ export default class BattleScene extends SceneBase { } } - party.forEach((enemyPokemon: EnemyPokemon, i: integer) => { + party.forEach((enemyPokemon: EnemyPokemon, i: number) => { if (heldModifiersConfigs && i < heldModifiersConfigs.length && heldModifiersConfigs[i]) { heldModifiersConfigs[i].forEach(mt => { let modifier: PokemonHeldItemModifier; diff --git a/src/battle.ts b/src/battle.ts index 287a981f83d..fa333040c22 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -578,14 +578,14 @@ export const classicFixedBattles: FixedBattleConfigs = { [ClassicFixedBossWaves.EVIL_GRUNT_3]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), [ClassicFixedBossWaves.EVIL_ADMIN_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) - .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true)), + .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.COLRESS ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true)), [ClassicFixedBossWaves.RIVAL_4]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(() => new Trainer(TrainerType.RIVAL_4, globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }), [ClassicFixedBossWaves.EVIL_GRUNT_4]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), [ClassicFixedBossWaves.EVIL_ADMIN_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) - .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true, 1)), + .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.COLRESS ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true, 1)), [ClassicFixedBossWaves.EVIL_BOSS_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE, TrainerType.PENNY ])) .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }), @@ -604,7 +604,7 @@ export const classicFixedBattles: FixedBattleConfigs = { [ClassicFixedBossWaves.ELITE_FOUR_4]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL, TrainerType.DRAYTON ])), [ClassicFixedBossWaves.CHAMPION]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(ClassicFixedBossWaves.ELITE_FOUR_1) - .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN ])), + .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, [ TrainerType.KUKUI, TrainerType.HAU ], [ TrainerType.LEON, TrainerType.MUSTARD ], [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN ])), [ClassicFixedBossWaves.RIVAL_6]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(() => new Trainer(TrainerType.RIVAL_6, globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }) diff --git a/src/data/ability.ts b/src/data/ability.ts index 5e5231176b5..4c9c44c6f35 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -51,13 +51,13 @@ export class Ability implements Localizable { private nameAppend: string; public name: string; public description: string; - public generation: integer; + public generation: number; public isBypassFaint: boolean; public isIgnorable: boolean; public attrs: AbAttr[]; public conditions: AbAttrCondition[]; - constructor(id: Abilities, generation: integer) { + constructor(id: Abilities, generation: number) { this.id = id; this.nameAppend = ""; @@ -221,9 +221,9 @@ export class PostBattleInitAbAttr extends AbAttr { } export class PostBattleInitFormChangeAbAttr extends PostBattleInitAbAttr { - private formFunc: (p: Pokemon) => integer; + private formFunc: (p: Pokemon) => number; - constructor(formFunc: ((p: Pokemon) => integer)) { + constructor(formFunc: ((p: Pokemon) => number)) { super(true); this.formFunc = formFunc; @@ -491,9 +491,9 @@ class TypeImmunityStatStageChangeAbAttr extends TypeImmunityAbAttr { class TypeImmunityAddBattlerTagAbAttr extends TypeImmunityAbAttr { private tagType: BattlerTagType; - private turnCount: integer; + private turnCount: number; - constructor(immuneType: Type, tagType: BattlerTagType, turnCount: integer, condition?: AbAttrCondition) { + constructor(immuneType: Type, tagType: BattlerTagType, turnCount: number, condition?: AbAttrCondition) { super(immuneType, condition); this.tagType = tagType; @@ -605,7 +605,7 @@ export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr { } export class PostStatStageChangeAbAttr extends AbAttr { - applyPostStatStageChange(pokemon: Pokemon, simulated: boolean, statsChanged: BattleStat[], stagesChanged: integer, selfTarget: boolean, args: any[]): boolean | Promise { + applyPostStatStageChange(pokemon: Pokemon, simulated: boolean, statsChanged: BattleStat[], stagesChanged: number, selfTarget: boolean, args: any[]): boolean | Promise { return false; } } @@ -866,10 +866,10 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr { } export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { - public chance: integer; + public chance: number; private effects: StatusEffect[]; - constructor(chance: integer, ...effects: StatusEffect[]) { + constructor(chance: number, ...effects: StatusEffect[]) { super(); this.chance = chance; @@ -905,11 +905,11 @@ export class EffectSporeAbAttr extends PostDefendContactApplyStatusEffectAbAttr } export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { - private chance: integer; + private chance: number; private tagType: BattlerTagType; - private turnCount: integer | undefined; + private turnCount: number | undefined; - constructor(chance: integer, tagType: BattlerTagType, turnCount?: integer) { + constructor(chance: number, tagType: BattlerTagType, turnCount?: number) { super(); this.tagType = tagType; @@ -959,9 +959,9 @@ export class PostDefendCritStatStageChangeAbAttr extends PostDefendAbAttr { } export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { - private damageRatio: integer; + private damageRatio: number; - constructor(damageRatio: integer) { + constructor(damageRatio: number) { super(); this.damageRatio = damageRatio; @@ -993,9 +993,9 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { * @extends {PostDefendAbAttr} */ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr { - private turns: integer; + private turns: number; - constructor(turns: integer) { + constructor(turns: number) { super(); this.turns = turns; @@ -1101,11 +1101,11 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr { } export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr { - private chance: integer; + private chance: number; private attacker: Pokemon; private move: Move; - constructor(chance: integer) { + constructor(chance: number) { super(); this.chance = chance; @@ -1688,10 +1688,10 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { private contactRequired: boolean; - private chance: integer; + private chance: number; private effects: StatusEffect[]; - constructor(contactRequired: boolean, chance: integer, ...effects: StatusEffect[]) { + constructor(contactRequired: boolean, chance: number, ...effects: StatusEffect[]) { super(); this.contactRequired = contactRequired; @@ -1715,18 +1715,18 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { } export class PostAttackContactApplyStatusEffectAbAttr extends PostAttackApplyStatusEffectAbAttr { - constructor(chance: integer, ...effects: StatusEffect[]) { + constructor(chance: number, ...effects: StatusEffect[]) { super(true, chance, ...effects); } } export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr { private contactRequired: boolean; - private chance: (user: Pokemon, target: Pokemon, move: Move) => integer; + private chance: (user: Pokemon, target: Pokemon, move: Move) => number; private effects: BattlerTagType[]; - constructor(contactRequired: boolean, chance: (user: Pokemon, target: Pokemon, move: Move) => integer, ...effects: BattlerTagType[]) { + constructor(contactRequired: boolean, chance: (user: Pokemon, target: Pokemon, move: Move) => number, ...effects: BattlerTagType[]) { super(); this.contactRequired = contactRequired; @@ -1863,9 +1863,9 @@ class PostVictoryStatStageChangeAbAttr extends PostVictoryAbAttr { } export class PostVictoryFormChangeAbAttr extends PostVictoryAbAttr { - private formFunc: (p: Pokemon) => integer; + private formFunc: (p: Pokemon) => number; - constructor(formFunc: ((p: Pokemon) => integer)) { + constructor(formFunc: ((p: Pokemon) => number)) { super(true); this.formFunc = formFunc; @@ -2081,9 +2081,9 @@ export class PostSummonUnnamedMessageAbAttr extends PostSummonAbAttr { export class PostSummonAddBattlerTagAbAttr extends PostSummonAbAttr { private tagType: BattlerTagType; - private turnCount: integer; + private turnCount: number; - constructor(tagType: BattlerTagType, turnCount: integer, showAbility?: boolean) { + constructor(tagType: BattlerTagType, turnCount: number, showAbility?: boolean) { super(showAbility); this.tagType = tagType; @@ -2209,9 +2209,9 @@ export class PostSummonClearAllyStatStagesAbAttr extends PostSummonAbAttr { * @see {applyPostSummon} */ export class DownloadAbAttr extends PostSummonAbAttr { - private enemyDef: integer; - private enemySpDef: integer; - private enemyCountTally: integer; + private enemyDef: number; + private enemySpDef: number; + private enemyCountTally: number; private stats: BattleStat[]; /** @@ -2295,9 +2295,9 @@ export class PostSummonTerrainChangeAbAttr extends PostSummonAbAttr { } export class PostSummonFormChangeAbAttr extends PostSummonAbAttr { - private formFunc: (p: Pokemon) => integer; + private formFunc: (p: Pokemon) => number; - constructor(formFunc: ((p: Pokemon) => integer)) { + constructor(formFunc: ((p: Pokemon) => number)) { super(true); this.formFunc = formFunc; @@ -2715,9 +2715,9 @@ export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr { * @see {@linkcode applyPreSwitchOut} */ export class PreSwitchOutFormChangeAbAttr extends PreSwitchOutAbAttr { - private formFunc: (p: Pokemon) => integer; + private formFunc: (p: Pokemon) => number; - constructor(formFunc: ((p: Pokemon) => integer)) { + constructor(formFunc: ((p: Pokemon) => number)) { super(); this.formFunc = formFunc; @@ -2861,7 +2861,7 @@ export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { * @returns A boolean indicating the result of the status application. */ applyPreSetStatus(pokemon: Pokemon, passive: boolean, simulated: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.immuneEffects.length < 1 || this.immuneEffects.includes(effect)) { + if (effect !== StatusEffect.FAINT && this.immuneEffects.length < 1 || this.immuneEffects.includes(effect)) { cancelled.value = true; return true; } @@ -3338,10 +3338,10 @@ export class PostWeatherChangeFormChangeAbAttr extends PostWeatherChangeAbAttr { export class PostWeatherChangeAddBattlerTagAttr extends PostWeatherChangeAbAttr { private tagType: BattlerTagType; - private turnCount: integer; + private turnCount: number; private weatherTypes: WeatherType[]; - constructor(tagType: BattlerTagType, turnCount: integer, ...weatherTypes: WeatherType[]) { + constructor(tagType: BattlerTagType, turnCount: number, ...weatherTypes: WeatherType[]) { super(); this.tagType = tagType; @@ -3382,9 +3382,9 @@ export class PostWeatherLapseAbAttr extends AbAttr { } export class PostWeatherLapseHealAbAttr extends PostWeatherLapseAbAttr { - private healFactor: integer; + private healFactor: number; - constructor(healFactor: integer, ...weatherTypes: WeatherType[]) { + constructor(healFactor: number, ...weatherTypes: WeatherType[]) { super(...weatherTypes); this.healFactor = healFactor; @@ -3405,9 +3405,9 @@ export class PostWeatherLapseHealAbAttr extends PostWeatherLapseAbAttr { } export class PostWeatherLapseDamageAbAttr extends PostWeatherLapseAbAttr { - private damageFactor: integer; + private damageFactor: number; - constructor(damageFactor: integer, ...weatherTypes: WeatherType[]) { + constructor(damageFactor: number, ...weatherTypes: WeatherType[]) { super(...weatherTypes); this.damageFactor = damageFactor; @@ -3436,10 +3436,10 @@ export class PostTerrainChangeAbAttr extends AbAttr { export class PostTerrainChangeAddBattlerTagAttr extends PostTerrainChangeAbAttr { private tagType: BattlerTagType; - private turnCount: integer; + private turnCount: number; private terrainTypes: TerrainType[]; - constructor(tagType: BattlerTagType, turnCount: integer, ...terrainTypes: TerrainType[]) { + constructor(tagType: BattlerTagType, turnCount: number, ...terrainTypes: TerrainType[]) { super(); this.tagType = tagType; @@ -3692,9 +3692,9 @@ export class PostTurnHealAbAttr extends PostTurnAbAttr { } export class PostTurnFormChangeAbAttr extends PostTurnAbAttr { - private formFunc: (p: Pokemon) => integer; + private formFunc: (p: Pokemon) => number; - constructor(formFunc: ((p: Pokemon) => integer)) { + constructor(formFunc: ((p: Pokemon) => number)) { super(true); this.formFunc = formFunc; @@ -3916,9 +3916,9 @@ export class PostItemLostApplyBattlerTagAbAttr extends PostItemLostAbAttr { } export class StatStageChangeMultiplierAbAttr extends AbAttr { - private multiplier: integer; + private multiplier: number; - constructor(multiplier: integer) { + constructor(multiplier: number) { super(true); this.multiplier = multiplier; @@ -4225,9 +4225,9 @@ export class PostFaintClearWeatherAbAttr extends PostFaintAbAttr { } export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { - private damageRatio: integer; + private damageRatio: number; - constructor(damageRatio: integer) { + constructor(damageRatio: number) { super(); this.damageRatio = damageRatio; @@ -4404,9 +4404,9 @@ export class ReduceBerryUseThresholdAbAttr extends AbAttr { * Used for Heavy Metal (doubling weight) and Light Metal (halving weight) */ export class WeightMultiplierAbAttr extends AbAttr { - private multiplier: integer; + private multiplier: number; - constructor(multiplier: integer) { + constructor(multiplier: number) { super(); this.multiplier = multiplier; @@ -4700,12 +4700,12 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr { * @extends AbAttr */ export class BypassSpeedChanceAbAttr extends AbAttr { - public chance: integer; + public chance: number; /** - * @param {integer} chance probability of ability being active. + * @param {number} chance probability of ability being active. */ - constructor(chance: integer) { + constructor(chance: number) { super(true); this.chance = chance; } @@ -5235,7 +5235,7 @@ export function applyPreStatStageChangeAbAttrs(attrType: Constructor, - pokemon: Pokemon, stats: BattleStat[], stages: integer, selfTarget: boolean, simulated: boolean = false, ...args: any[]): Promise { + pokemon: Pokemon, stats: BattleStat[], stages: number, selfTarget: boolean, simulated: boolean = false, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, _passive) => attr.applyPostStatStageChange(pokemon, simulated, stats, stages, selfTarget, args), args, false, simulated); } @@ -5943,12 +5943,14 @@ export function initAbilities() { .attr(PostBattleInitFormChangeAbAttr, () => 0) .attr(PostSummonFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) .attr(PostTurnFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) + .conditionalAttr(p => p.formIndex !== 7, StatusEffectImmunityAbAttr) + .conditionalAttr(p => p.formIndex !== 7, BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) .attr(NoFusionAbilityAbAttr) - .bypassFaint() - .partial(), // Meteor form should protect against status effects and yawn + .attr(NoTransformAbilityAbAttr) + .bypassFaint(), new Ability(Abilities.STAKEOUT, 7) .attr(MovePowerBoostAbAttr, (user, target, move) => !!target?.turnData.switchedInThisTurn, 2), new Ability(Abilities.WATER_BUBBLE, 7) @@ -6287,9 +6289,8 @@ export function initAbilities() { .attr(NoTransformAbilityAbAttr) .partial(), // While setting the tag, the getbattlestat should ignore all modifiers to stats except stat stages new Ability(Abilities.GOOD_AS_GOLD, 9) - .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.category === MoveCategory.STATUS) - .ignorable() - .partial(), // Lots of weird interactions with moves and abilities such as negating status moves that target the field + .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.category === MoveCategory.STATUS && ![ MoveTarget.ENEMY_SIDE, MoveTarget.BOTH_SIDES, MoveTarget.USER_SIDE ].includes(move.moveTarget)) + .ignorable(), new Ability(Abilities.VESSEL_OF_RUIN, 9) .attr(FieldMultiplyStatAbAttr, Stat.SPATK, 0.75) .attr(PostSummonMessageAbAttr, (user) => i18next.t("abilityTriggers:postSummonVesselOfRuin", { pokemonNameWithAffix: getPokemonNameWithAffix(user), statName: i18next.t(getStatKey(Stat.SPATK)) })) diff --git a/src/data/balance/biomes.ts b/src/data/balance/biomes.ts index 240881ad580..5b5e69b4042 100644 --- a/src/data/balance/biomes.ts +++ b/src/data/balance/biomes.ts @@ -26,11 +26,11 @@ export function getBiomeName(biome: Biome | -1) { } interface BiomeLinks { - [key: integer]: Biome | (Biome | [Biome, integer])[] + [key: number]: Biome | (Biome | [Biome, number])[] } interface BiomeDepths { - [key: integer]: [integer, integer] + [key: number]: [number, number] } export const biomeLinks: BiomeLinks = { @@ -87,27 +87,39 @@ export enum BiomePoolTier { export const uncatchableSpecies: Species[] = []; export interface SpeciesTree { - [key: integer]: Species[] + [key: number]: Species[] } export interface PokemonPools { - [key: integer]: (Species | SpeciesTree)[] + [key: number]: (Species | SpeciesTree)[] } export interface BiomeTierPokemonPools { - [key: integer]: PokemonPools + [key: number]: PokemonPools } export interface BiomePokemonPools { - [key: integer]: BiomeTierPokemonPools + [key: number]: BiomeTierPokemonPools } +export interface BiomeTierTod { + biome: Biome, + tier: BiomePoolTier, + tod: TimeOfDay[] +} + +export interface CatchableSpecies{ + [key: number]: BiomeTierTod[] +} + +export const catchableSpecies: CatchableSpecies = {}; + export interface BiomeTierTrainerPools { - [key: integer]: TrainerType[] + [key: number]: TrainerType[] } export interface BiomeTrainerPools { - [key: integer]: BiomeTierTrainerPools + [key: number]: BiomeTierTrainerPools } export const biomePokemonPools: BiomePokemonPools = { @@ -7663,15 +7675,15 @@ export function initBiomes() { biomeDepths[Biome.TOWN] = [ 0, 1 ]; - const traverseBiome = (biome: Biome, depth: integer) => { + const traverseBiome = (biome: Biome, depth: number) => { if (biome === Biome.END) { const biomeList = Object.keys(Biome).filter(key => !isNaN(Number(key))); biomeList.pop(); // Removes Biome.END from the list const randIndex = Utils.randSeedInt(biomeList.length, 1); // Will never be Biome.TOWN biome = Biome[biomeList[randIndex]]; } - const linkedBiomes: (Biome | [ Biome, integer ])[] = Array.isArray(biomeLinks[biome]) - ? biomeLinks[biome] as (Biome | [ Biome, integer ])[] + const linkedBiomes: (Biome | [ Biome, number ])[] = Array.isArray(biomeLinks[biome]) + ? biomeLinks[biome] as (Biome | [ Biome, number ])[] : [ biomeLinks[biome] as Biome ]; for (const linkedBiomeEntry of linkedBiomes) { const linkedBiome = !Array.isArray(linkedBiomeEntry) @@ -7688,7 +7700,7 @@ export function initBiomes() { }; traverseBiome(Biome.TOWN, 0); - biomeDepths[Biome.END] = [ Object.values(biomeDepths).map(d => d[0]).reduce((max: integer, value: integer) => Math.max(max, value), 0) + 1, 1 ]; + biomeDepths[Biome.END] = [ Object.values(biomeDepths).map(d => d[0]).reduce((max: number, value: number) => Math.max(max, value), 0) + 1, 1 ]; for (const biome of Utils.getEnumValues(Biome)) { biomePokemonPools[biome] = {}; @@ -7716,6 +7728,9 @@ export function initBiomes() { uncatchableSpecies.push(speciesId); } + // array of biome options for the current species + catchableSpecies[speciesId] = []; + for (const b of biomeEntries) { const biome = b[0]; const tier = b[1]; @@ -7725,6 +7740,12 @@ export function initBiomes() { : [ b[2] ] : [ TimeOfDay.ALL ]; + catchableSpecies[speciesId].push({ + biome: biome as Biome, + tier: tier as BiomePoolTier, + tod: timesOfDay as TimeOfDay[] + }); + for (const tod of timesOfDay) { if (!biomePokemonPools.hasOwnProperty(biome) || !biomePokemonPools[biome].hasOwnProperty(tier) || !biomePokemonPools[biome][tier].hasOwnProperty(tod)) { continue; diff --git a/src/data/balance/passives.ts b/src/data/balance/passives.ts index 60b50c7909c..3b30a629a4b 100644 --- a/src/data/balance/passives.ts +++ b/src/data/balance/passives.ts @@ -1,7 +1,15 @@ import { Abilities } from "#app/enums/abilities"; import { Species } from "#app/enums/species"; -export const starterPassiveAbilities = { +export interface PassiveAbilities { + [key: number]: Abilities +} + +interface StarterPassiveAbilities { + [key: number]: PassiveAbilities +} + +export const starterPassiveAbilities: StarterPassiveAbilities = { [Species.BULBASAUR]: { 0: Abilities.GRASSY_SURGE }, [Species.CHARMANDER]: { 0: Abilities.BEAST_BOOST }, [Species.SQUIRTLE]: { 0: Abilities.STURDY }, diff --git a/src/data/balance/pokemon-evolutions.ts b/src/data/balance/pokemon-evolutions.ts index a8fe3b5f4ab..9cc693dc33c 100644 --- a/src/data/balance/pokemon-evolutions.ts +++ b/src/data/balance/pokemon-evolutions.ts @@ -77,9 +77,9 @@ export enum EvolutionItem { /** * Pokemon Evolution tuple type consisting of: * @property 0 {@linkcode Species} The species of the Pokemon. - * @property 1 {@linkcode integer} The level at which the Pokemon evolves. + * @property 1 {@linkcode number} The level at which the Pokemon evolves. */ -export type EvolutionLevel = [species: Species, level: integer]; +export type EvolutionLevel = [species: Species, level: number]; export type EvolutionConditionPredicate = (p: Pokemon) => boolean; export type EvolutionConditionEnforceFunc = (p: Pokemon) => void; @@ -88,12 +88,12 @@ export class SpeciesFormEvolution { public speciesId: Species; public preFormKey: string | null; public evoFormKey: string | null; - public level: integer; + public level: number; public item: EvolutionItem | null; public condition: SpeciesEvolutionCondition | null; public wildDelay: SpeciesWildEvolutionDelay; - constructor(speciesId: Species, preFormKey: string | null, evoFormKey: string | null, level: integer, item: EvolutionItem | null, condition: SpeciesEvolutionCondition | null, wildDelay?: SpeciesWildEvolutionDelay) { + constructor(speciesId: Species, preFormKey: string | null, evoFormKey: string | null, level: number, item: EvolutionItem | null, condition: SpeciesEvolutionCondition | null, wildDelay?: SpeciesWildEvolutionDelay) { this.speciesId = speciesId; this.preFormKey = preFormKey; this.evoFormKey = evoFormKey; @@ -105,7 +105,7 @@ export class SpeciesFormEvolution { } export class SpeciesEvolution extends SpeciesFormEvolution { - constructor(speciesId: Species, level: integer, item: EvolutionItem | null, condition: SpeciesEvolutionCondition | null, wildDelay?: SpeciesWildEvolutionDelay) { + constructor(speciesId: Species, level: number, item: EvolutionItem | null, condition: SpeciesEvolutionCondition | null, wildDelay?: SpeciesWildEvolutionDelay) { super(speciesId, null, null, level, item, condition, wildDelay); } } @@ -169,7 +169,7 @@ class MoveEvolutionCondition extends SpeciesEvolutionCondition { } class FriendshipEvolutionCondition extends SpeciesEvolutionCondition { - public amount: integer; + public amount: number; constructor(amount: number) { super(p => p.friendship >= amount); this.amount = amount; @@ -178,7 +178,7 @@ class FriendshipEvolutionCondition extends SpeciesEvolutionCondition { } class FriendshipTimeOfDayEvolutionCondition extends SpeciesEvolutionCondition { - public amount: integer; + public amount: number; public timesOfDay: TimeOfDay[]; constructor(amount: number, tod: "day" | "night") { if (tod === "day") { @@ -197,7 +197,7 @@ class FriendshipTimeOfDayEvolutionCondition extends SpeciesEvolutionCondition { } class FriendshipMoveTypeEvolutionCondition extends SpeciesEvolutionCondition { - public amount: integer; + public amount: number; public type: Type; constructor(amount: number, type: Type) { super(p => p.friendship >= amount && !!p.getMoveset().find(m => m?.getMove().type === type)); diff --git a/src/data/balance/pokemon-level-moves.ts b/src/data/balance/pokemon-level-moves.ts index 8fe61da35c0..dcbc2fb0c0d 100644 --- a/src/data/balance/pokemon-level-moves.ts +++ b/src/data/balance/pokemon-level-moves.ts @@ -1,18 +1,18 @@ import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -export type LevelMoves = ([integer, Moves])[]; +export type LevelMoves = ([number, Moves])[]; interface PokemonSpeciesLevelMoves { - [key: integer]: LevelMoves + [key: number]: LevelMoves } interface PokemonFormLevelMoves { - [key: integer]: LevelMoves + [key: number]: LevelMoves } interface PokemonSpeciesFormLevelMoves { - [key: integer]: PokemonFormLevelMoves + [key: number]: PokemonFormLevelMoves } /** Moves that can only be learned with a memory-mushroom */ diff --git a/src/data/balance/tms.ts b/src/data/balance/tms.ts index da900768987..788ffd4f273 100644 --- a/src/data/balance/tms.ts +++ b/src/data/balance/tms.ts @@ -3,7 +3,7 @@ import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; interface TmSpecies { - [key: integer]: Array> + [key: number]: Array> } export const reverseCompatibleTms: Moves[] = [];/*[ @@ -68433,8 +68433,48 @@ export const tmSpecies: TmSpecies = { ], }; +interface SpeciesTmMoves { + [key: number]: (Moves | [string | Species, Moves])[]; +} + +function transposeTmSpecies(): SpeciesTmMoves { + const flipped: SpeciesTmMoves = {}; + + for (const move in tmSpecies) { + const moveKey = Number(move); + const speciesList = tmSpecies[move]; + + for (const species of speciesList) { + + if (Array.isArray(species)) { + // Extract base species and all associated forms + const [ baseSpecies, ...forms ] = species; + const speciesKey = Number(baseSpecies); + + if (!flipped[speciesKey]) { + flipped[speciesKey] = []; + } + + for (const form of forms) { + flipped[speciesKey].push([ form, moveKey ]); + } + + } else { + const speciesKey = Number(species); + if (!flipped[speciesKey]) { + flipped[speciesKey] = []; + } + flipped[speciesKey].push(moveKey); + } + } + } + return flipped; +} + +export const speciesTmMoves: SpeciesTmMoves = transposeTmSpecies(); + interface TmPoolTiers { - [key: integer]: ModifierTier + [key: number]: ModifierTier } export const tmPoolTiers: TmPoolTiers = { diff --git a/src/data/battle-anims.ts b/src/data/battle-anims.ts index c3da8db57c4..99e9e82d4a6 100644 --- a/src/data/battle-anims.ts +++ b/src/data/battle-anims.ts @@ -106,15 +106,15 @@ export enum CommonAnim { } export class AnimConfig { - public id: integer; + public id: number; public graphic: string; public frames: AnimFrame[][]; - public frameTimedEvents: Map; - public position: integer; - public hue: integer; + public frameTimedEvents: Map; + public position: number; + public hue: number; constructor(source?: any) { - this.frameTimedEvents = new Map; + this.frameTimedEvents = new Map; if (source) { this.id = source.id; @@ -195,18 +195,18 @@ class AnimFrame { public visible: boolean; public blendType: AnimBlendType; public target: AnimFrameTarget; - public graphicFrame: integer; - public opacity: integer; - public color: integer[]; - public tone: integer[]; - public flash: integer[]; + public graphicFrame: number; + public opacity: number; + public color: number[]; + public tone: number[]; + public flash: number[]; public locked: boolean; - public priority: integer; + public priority: number; public focus: AnimFocus; - constructor(x: number, y: number, zoomX: number, zoomY: number, angle: number, mirror: boolean, visible: boolean, blendType: AnimBlendType, pattern: integer, - opacity: integer, colorR: integer, colorG: integer, colorB: integer, colorA: integer, toneR: integer, toneG: integer, toneB: integer, toneA: integer, - flashR: integer, flashG: integer, flashB: integer, flashA: integer, locked: boolean, priority: integer, focus: AnimFocus, init?: boolean) { + constructor(x: number, y: number, zoomX: number, zoomY: number, angle: number, mirror: boolean, visible: boolean, blendType: AnimBlendType, pattern: number, + opacity: number, colorR: number, colorG: number, colorB: number, colorA: number, toneR: number, toneG: number, toneB: number, toneA: number, + flashR: number, flashG: number, flashB: number, flashA: number, locked: boolean, priority: number, focus: AnimFocus, init?: boolean) { this.x = !init ? ((x || 0) - 128) * 0.5 : x; this.y = !init ? ((y || 0) - 224) * 0.5 : y; if (zoomX) { @@ -288,9 +288,9 @@ class AnimFrame { class ImportedAnimFrame extends AnimFrame { constructor(source: any) { - const color: integer[] = source.color || [ 0, 0, 0, 0 ]; - const tone: integer[] = source.tone || [ 0, 0, 0, 0 ]; - const flash: integer[] = source.flash || [ 0, 0, 0, 0 ]; + const color: number[] = source.color || [ 0, 0, 0, 0 ]; + const tone: number[] = source.tone || [ 0, 0, 0, 0 ]; + const flash: number[] = source.flash || [ 0, 0, 0, 0 ]; super(source.x, source.y, source.zoomX, source.zoomY, source.angle, source.mirror, source.visible, source.blendType, source.graphicFrame, source.opacity, color[0], color[1], color[2], color[3], tone[0], tone[1], tone[2], tone[3], flash[0], flash[1], flash[2], flash[3], source.locked, source.priority, source.focus, true); this.target = source.target; this.graphicFrame = source.graphicFrame; @@ -298,15 +298,15 @@ class ImportedAnimFrame extends AnimFrame { } abstract class AnimTimedEvent { - public frameIndex: integer; + public frameIndex: number; public resourceName: string; - constructor(frameIndex: integer, resourceName: string) { + constructor(frameIndex: number, resourceName: string) { this.frameIndex = frameIndex; this.resourceName = resourceName; } - abstract execute(battleAnim: BattleAnim, priority?: number): integer; + abstract execute(battleAnim: BattleAnim, priority?: number): number; abstract getEventType(): string; } @@ -315,7 +315,7 @@ class AnimTimedSoundEvent extends AnimTimedEvent { public volume: number = 100; public pitch: number = 100; - constructor(frameIndex: integer, resourceName: string, source?: any) { + constructor(frameIndex: number, resourceName: string, source?: any) { super(frameIndex, resourceName); if (source) { @@ -324,7 +324,7 @@ class AnimTimedSoundEvent extends AnimTimedEvent { } } - execute(battleAnim: BattleAnim, priority?: number): integer { + execute(battleAnim: BattleAnim, priority?: number): number { const soundConfig = { rate: (this.pitch * 0.01), volume: (this.volume * 0.01) }; if (this.resourceName) { try { @@ -346,20 +346,20 @@ class AnimTimedSoundEvent extends AnimTimedEvent { abstract class AnimTimedBgEvent extends AnimTimedEvent { public bgX: number = 0; public bgY: number = 0; - public opacity: integer = 0; - /*public colorRed: integer = 0; - public colorGreen: integer = 0; - public colorBlue: integer = 0; - public colorAlpha: integer = 0;*/ - public duration: integer = 0; - /*public flashScope: integer = 0; - public flashRed: integer = 0; - public flashGreen: integer = 0; - public flashBlue: integer = 0; - public flashAlpha: integer = 0; - public flashDuration: integer = 0;*/ + public opacity: number = 0; + /*public colorRed: number = 0; + public colorGreen: number = 0; + public colorBlue: number = 0; + public colorAlpha: number = 0;*/ + public duration: number = 0; + /*public flashScope: number = 0; + public flashRed: number = 0; + public flashGreen: number = 0; + public flashBlue: number = 0; + public flashAlpha: number = 0; + public flashDuration: number = 0;*/ - constructor(frameIndex: integer, resourceName: string, source: any) { + constructor(frameIndex: number, resourceName: string, source: any) { super(frameIndex, resourceName); if (source) { @@ -382,11 +382,11 @@ abstract class AnimTimedBgEvent extends AnimTimedEvent { } class AnimTimedUpdateBgEvent extends AnimTimedBgEvent { - constructor(frameIndex: integer, resourceName: string, source?: any) { + constructor(frameIndex: number, resourceName: string, source?: any) { super(frameIndex, resourceName, source); } - execute(moveAnim: MoveAnim, priority?: number): integer { + execute(moveAnim: MoveAnim, priority?: number): number { const tweenProps = {}; if (this.bgX !== undefined) { tweenProps["x"] = (this.bgX * 0.5) - 320; @@ -412,11 +412,11 @@ class AnimTimedUpdateBgEvent extends AnimTimedBgEvent { } class AnimTimedAddBgEvent extends AnimTimedBgEvent { - constructor(frameIndex: integer, resourceName: string, source?: any) { + constructor(frameIndex: number, resourceName: string, source?: any) { super(frameIndex, resourceName, source); } - execute(moveAnim: MoveAnim, priority?: number): integer { + execute(moveAnim: MoveAnim, priority?: number): number { if (moveAnim.bgSprite) { moveAnim.bgSprite.destroy(); } @@ -737,7 +737,7 @@ function isReversed(src1: number, src2: number, dst1: number, dst2: number) { } interface SpriteCache { - [key: integer]: Phaser.GameObjects.Sprite[] + [key: number]: Phaser.GameObjects.Sprite[] } export abstract class BattleAnim { @@ -774,8 +774,8 @@ export abstract class BattleAnim { return false; } - private getGraphicFrameData(frames: AnimFrame[], onSubstitute?: boolean): Map> { - const ret: Map> = new Map([ + private getGraphicFrameData(frames: AnimFrame[], onSubstitute?: boolean): Map> { + const ret: Map> = new Map([ [ AnimFrameTarget.GRAPHIC, new Map() ], [ AnimFrameTarget.USER, new Map() ], [ AnimFrameTarget.TARGET, new Map() ] @@ -853,7 +853,7 @@ export abstract class BattleAnim { [AnimFrameTarget.USER]: [], [AnimFrameTarget.TARGET]: [] }; - const spritePriorities: integer[] = []; + const spritePriorities: number[] = []; const cleanUpAndComplete = () => { userSprite.setPosition(0, 0); @@ -993,7 +993,7 @@ export abstract class BattleAnim { const moveSprite = sprites[graphicIndex]; if (spritePriorities[graphicIndex] !== frame.priority) { spritePriorities[graphicIndex] = frame.priority; - const setSpritePriority = (priority: integer) => { + const setSpritePriority = (priority: number) => { switch (priority) { case 0: globalScene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, globalScene.getEnemyPokemon(false) ?? globalScene.getPlayerPokemon(false)!); // TODO: is this bang correct? @@ -1093,8 +1093,8 @@ export abstract class BattleAnim { }); } - private getGraphicFrameDataWithoutTarget(frames: AnimFrame[], targetInitialX: number, targetInitialY: number): Map> { - const ret: Map> = new Map([ + private getGraphicFrameDataWithoutTarget(frames: AnimFrame[], targetInitialX: number, targetInitialY: number): Map> { + const ret: Map> = new Map([ [ AnimFrameTarget.GRAPHIC, new Map() ], [ AnimFrameTarget.USER, new Map() ], [ AnimFrameTarget.TARGET, new Map() ] @@ -1188,7 +1188,7 @@ export abstract class BattleAnim { const graphicIndex = graphicFrameCount++; const moveSprite = sprites[graphicIndex]; if (!isNullOrUndefined(frame.priority)) { - const setSpritePriority = (priority: integer) => { + const setSpritePriority = (priority: number) => { if (existingFieldSprites.length > priority) { // Move to specified priority index const index = globalScene.field.getIndex(existingFieldSprites[priority]); diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 4c68de5abc5..17dc34aa514 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -137,7 +137,7 @@ export interface TerrainBattlerTag { * to select restricted moves. */ export abstract class MoveRestrictionBattlerTag extends BattlerTag { - constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType | BattlerTagLapseType[], turnCount: integer, sourceMove?: Moves, sourceId?: integer) { + constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType | BattlerTagLapseType[], turnCount: number, sourceMove?: Moves, sourceId?: number) { super(tagType, lapseType, turnCount, sourceMove, sourceId); } @@ -2559,7 +2559,7 @@ export class SubstituteTag extends BattlerTag { /** Is the source Pokemon "in focus," i.e. is it fully visible on the field? */ public sourceInFocus: boolean; - constructor(sourceMove: Moves, sourceId: integer) { + constructor(sourceMove: Moves, sourceId: number) { super(BattlerTagType.SUBSTITUTE, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE, BattlerTagLapseType.HIT ], 0, sourceMove, sourceId, true); } diff --git a/src/data/challenge.ts b/src/data/challenge.ts index fab5196601c..10fb9c55d3d 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -115,17 +115,17 @@ export enum MoveSourceType { export abstract class Challenge { public id: Challenges; // The id of the challenge - public value: integer; // The "strength" of the challenge, all challenges have a numerical value. - public maxValue: integer; // The maximum strength of the challenge. - public severity: integer; // The current severity of the challenge. Some challenges have multiple severities in addition to strength. - public maxSeverity: integer; // The maximum severity of the challenge. + public value: number; // The "strength" of the challenge, all challenges have a numerical value. + public maxValue: number; // The maximum strength of the challenge. + public severity: number; // The current severity of the challenge. Some challenges have multiple severities in addition to strength. + public maxSeverity: number; // The maximum severity of the challenge. public conditions: ChallengeCondition[]; /** * @param id {@link Challenges} The enum value for the challenge */ - constructor(id: Challenges, maxValue: integer = Number.MAX_SAFE_INTEGER) { + constructor(id: Challenges, maxValue: number = Number.MAX_SAFE_INTEGER) { this.id = id; this.value = 0; @@ -180,7 +180,7 @@ export abstract class Challenge { /** * Returns the textual representation of a challenge's current value. - * @param overrideValue {@link integer} The value to check for. If undefined, gets the current value. + * @param overrideValue {@link number} The value to check for. If undefined, gets the current value. * @returns {@link string} The localised name for the current value. */ getValue(overrideValue?: number): string { @@ -190,7 +190,7 @@ export abstract class Challenge { /** * Returns the description of a challenge's current value. - * @param overrideValue {@link integer} The value to check for. If undefined, gets the current value. + * @param overrideValue {@link number} The value to check for. If undefined, gets the current value. * @returns {@link string} The localised description for the current value. */ getDescription(overrideValue?: number): string { @@ -257,7 +257,7 @@ export abstract class Challenge { * Gets the "difficulty" value of this challenge. * @returns {@link integer} The difficulty value. */ - getDifficulty(): integer { + getDifficulty(): number { return this.value; } @@ -265,7 +265,7 @@ export abstract class Challenge { * Gets the minimum difficulty added by this challenge. * @returns {@link integer} The difficulty value. */ - getMinDifficulty(): integer { + getMinDifficulty(): number { return 0; } @@ -469,7 +469,7 @@ export class SingleGenerationChallenge extends Challenge { let trainerTypes: (TrainerType | TrainerType[])[] = []; const evilTeamWaves: number[] = [ ClassicFixedBossWaves.EVIL_GRUNT_1, ClassicFixedBossWaves.EVIL_GRUNT_2, ClassicFixedBossWaves.EVIL_GRUNT_3, ClassicFixedBossWaves.EVIL_ADMIN_1, ClassicFixedBossWaves.EVIL_GRUNT_4, ClassicFixedBossWaves.EVIL_ADMIN_2, ClassicFixedBossWaves.EVIL_BOSS_1, ClassicFixedBossWaves.EVIL_BOSS_2 ]; const evilTeamGrunts = [[ TrainerType.ROCKET_GRUNT ], [ TrainerType.ROCKET_GRUNT ], [ TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT ], [ TrainerType.GALACTIC_GRUNT ], [ TrainerType.PLASMA_GRUNT ], [ TrainerType.FLARE_GRUNT ], [ TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT ], [ TrainerType.MACRO_GRUNT ], [ TrainerType.STAR_GRUNT ]]; - const evilTeamAdmins = [[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [[ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ]], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], [ TrainerType.FABA, TrainerType.PLUMERIA ], [ TrainerType.OLEANA ], [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]]; + const evilTeamAdmins = [[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [[ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ]], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.COLRESS ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], [ TrainerType.FABA, TrainerType.PLUMERIA ], [ TrainerType.OLEANA ], [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]]; const evilTeamBosses = [[ TrainerType.ROCKET_BOSS_GIOVANNI_1 ], [ TrainerType.ROCKET_BOSS_GIOVANNI_1 ], [ TrainerType.MAXIE, TrainerType.ARCHIE ], [ TrainerType.CYRUS ], [ TrainerType.GHETSIS ], [ TrainerType.LYSANDRE ], [ TrainerType.LUSAMINE, TrainerType.GUZMA ], [ TrainerType.ROSE ], [ TrainerType.PENNY ]]; const evilTeamBossRematches = [[ TrainerType.ROCKET_BOSS_GIOVANNI_2 ], [ TrainerType.ROCKET_BOSS_GIOVANNI_2 ], [ TrainerType.MAXIE_2, TrainerType.ARCHIE_2 ], [ TrainerType.CYRUS_2 ], [ TrainerType.GHETSIS_2 ], [ TrainerType.LYSANDRE_2 ], [ TrainerType.LUSAMINE_2, TrainerType.GUZMA_2 ], [ TrainerType.ROSE_2 ], [ TrainerType.PENNY_2 ]]; switch (waveIndex) { @@ -509,7 +509,7 @@ export class SingleGenerationChallenge extends Challenge { trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ]; break; case ClassicFixedBossWaves.CHAMPION: - trainerTypes = [ TrainerType.BLUE, Utils.randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), Utils.randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, Utils.randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, Utils.randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ]; + trainerTypes = [ TrainerType.BLUE, Utils.randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), Utils.randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, Utils.randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, Utils.randSeedItem([ TrainerType.KUKUI, TrainerType.HAU ]), Utils.randSeedItem([ TrainerType.LEON, TrainerType.MUSTARD ]), Utils.randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ]; break; } if (trainerTypes.length === 0) { @@ -643,7 +643,7 @@ export class SingleTypeChallenge extends Challenge { * @param {value} overrideValue The value to check for. If undefined, gets the current value. * @returns {string} The localised name for the current value. */ - getValue(overrideValue?: integer): string { + getValue(overrideValue?: number): string { if (overrideValue === undefined) { overrideValue = this.value; } @@ -655,7 +655,7 @@ export class SingleTypeChallenge extends Challenge { * @param {value} overrideValue The value to check for. If undefined, gets the current value. * @returns {string} The localised description for the current value. */ - getDescription(overrideValue?: integer): string { + getDescription(overrideValue?: number): string { if (overrideValue === undefined) { overrideValue = this.value; } @@ -793,7 +793,7 @@ export class LowerStarterMaxCostChallenge extends Challenge { /** * @override */ - getValue(overrideValue?: integer): string { + getValue(overrideValue?: number): string { if (overrideValue === undefined) { overrideValue = this.value; } @@ -827,7 +827,7 @@ export class LowerStarterPointsChallenge extends Challenge { /** * @override */ - getValue(overrideValue?: integer): string { + getValue(overrideValue?: number): string { if (overrideValue === undefined) { overrideValue = this.value; } diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index 2a4a78a9caf..df6c08fc0f0 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -11,7 +11,7 @@ import { pokerogueApi } from "#app/plugins/api/pokerogue-api"; import { Biome } from "#app/enums/biome"; export interface DailyRunConfig { - seed: integer; + seed: number; starters: Starter; } @@ -38,7 +38,7 @@ export function getDailyRunStarters(seed: string): Starter[] { return; } - const starterCosts: integer[] = []; + const starterCosts: number[] = []; starterCosts.push(Math.min(Math.round(3.5 + Math.abs(Utils.randSeedGauss(1))), 8)); starterCosts.push(Utils.randSeedInt(9 - starterCosts[0], 1)); starterCosts.push(10 - (starterCosts[0] + starterCosts[1])); @@ -57,7 +57,7 @@ export function getDailyRunStarters(seed: string): Starter[] { return starters; } -function getDailyRunStarter(starterSpeciesForm: PokemonSpeciesForm, startingLevel: integer): Starter { +function getDailyRunStarter(starterSpeciesForm: PokemonSpeciesForm, startingLevel: number): Starter { const starterSpecies = starterSpeciesForm instanceof PokemonSpecies ? starterSpeciesForm : getPokemonSpecies(starterSpeciesForm.speciesId); const formIndex = starterSpeciesForm instanceof PokemonSpecies ? undefined : starterSpeciesForm.formIndex; const pokemon = new PlayerPokemon(starterSpecies, startingLevel, undefined, formIndex, undefined, undefined, undefined, undefined, undefined, undefined); @@ -74,7 +74,7 @@ function getDailyRunStarter(starterSpeciesForm: PokemonSpeciesForm, startingLeve } interface BiomeWeights { - [key: integer]: integer + [key: number]: number } // Initially weighted by amount of exits each biome has @@ -125,7 +125,7 @@ export function getDailyStartingBiome(): Biome { const biomes = Utils.getEnumValues(Biome).filter(b => b !== Biome.TOWN && b !== Biome.END); let totalWeight = 0; - const biomeThresholds: integer[] = []; + const biomeThresholds: number[] = []; for (const biome of biomes) { // Keep track of the total weight totalWeight += dailyBiomeWeights[biome]; diff --git a/src/data/dialogue.ts b/src/data/dialogue.ts index 3219ce4d058..f4933a070fd 100644 --- a/src/data/dialogue.ts +++ b/src/data/dialogue.ts @@ -9,7 +9,7 @@ export interface TrainerTypeMessages { } export interface TrainerTypeDialogue { - [key: integer]: TrainerTypeMessages | Array + [key: number]: TrainerTypeMessages | Array } export function getTrainerTypeDialogue(): TrainerTypeDialogue { @@ -726,17 +726,17 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { ] } ], - [TrainerType.ROOD]: [ + [TrainerType.COLRESS]: [ { encounter: [ - "dialogue:rood.encounter.1", - "dialogue:rood.encounter.2", - "dialogue:rood.encounter.3", + "dialogue:colress.encounter.1", + "dialogue:colress.encounter.2", + "dialogue:colress.encounter.3", ], victory: [ - "dialogue:rood.victory.1", - "dialogue:rood.victory.2", - "dialogue:rood.victory.3", + "dialogue:colress.victory.1", + "dialogue:colress.victory.2", + "dialogue:colress.victory.3", ] } ], @@ -2505,6 +2505,17 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { "dialogue:iris.defeat.1" ] }, + [TrainerType.KUKUI]: { + encounter: [ + "dialogue:kukui.encounter.1" + ], + victory: [ + "dialogue:kukui.victory.1" + ], + defeat: [ + "dialogue:kukui.defeat.1" + ] + }, [TrainerType.HAU]: { encounter: [ "dialogue:hau.encounter.1" @@ -2549,6 +2560,17 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { "dialogue:leon.defeat.1" ] }, + [TrainerType.MUSTARD]: { + encounter: [ + "dialogue:mustard.encounter.1" + ], + victory: [ + "dialogue:mustard.victory.1" + ], + defeat: [ + "dialogue:mustard.defeat.1" + ] + }, [TrainerType.WHITNEY]: { encounter: [ "dialogue:whitney.encounter.1" diff --git a/src/data/egg.ts b/src/data/egg.ts index 2599994ecf6..380b5ddabfe 100644 --- a/src/data/egg.ts +++ b/src/data/egg.ts @@ -373,8 +373,8 @@ export class Egg { } } - let minStarterValue: integer; - let maxStarterValue: integer; + let minStarterValue: number; + let maxStarterValue: number; switch (this.tier) { case EggTier.RARE: diff --git a/src/data/exp.ts b/src/data/exp.ts index c03abddadfc..0f5d3e62cef 100644 --- a/src/data/exp.ts +++ b/src/data/exp.ts @@ -16,7 +16,7 @@ const expLevels = [ [ 0, 4, 13, 32, 65, 112, 178, 276, 393, 540, 745, 967, 1230, 1591, 1957, 2457, 3046, 3732, 4526, 5440, 6482, 7666, 9003, 10506, 12187, 14060, 16140, 18439, 20974, 23760, 26811, 30146, 33780, 37731, 42017, 46656, 50653, 55969, 60505, 66560, 71677, 78533, 84277, 91998, 98415, 107069, 114205, 123863, 131766, 142500, 151222, 163105, 172697, 185807, 196322, 210739, 222231, 238036, 250562, 267840, 281456, 300293, 315059, 335544, 351520, 373744, 390991, 415050, 433631, 459620, 479600, 507617, 529063, 559209, 582187, 614566, 639146, 673863, 700115, 737280, 765275, 804997, 834809, 877201, 908905, 954084, 987754, 1035837, 1071552, 1122660, 1160499, 1214753, 1254796, 1312322, 1354652, 1415577, 1460276, 1524731, 1571884, 1640000 ] ]; -export function getLevelTotalExp(level: integer, growthRate: GrowthRate): integer { +export function getLevelTotalExp(level: number, growthRate: GrowthRate): number { if (level < 100) { const levelExp = expLevels[growthRate][level - 1]; if (growthRate !== GrowthRate.MEDIUM_FAST) { @@ -25,7 +25,7 @@ export function getLevelTotalExp(level: integer, growthRate: GrowthRate): intege return levelExp; } - let ret: integer; + let ret: number; switch (growthRate) { case GrowthRate.ERRATIC: @@ -55,7 +55,7 @@ export function getLevelTotalExp(level: integer, growthRate: GrowthRate): intege return Math.floor(ret); } -export function getLevelRelExp(level: integer, growthRate: GrowthRate): number { +export function getLevelRelExp(level: number, growthRate: GrowthRate): number { return getLevelTotalExp(level, growthRate) - getLevelTotalExp(level - 1, growthRate); } diff --git a/src/data/move.ts b/src/data/move.ts index 2d2da38cce7..6d327ec5dc1 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -687,7 +687,7 @@ export default class Move implements Localizable { * @param move {@linkcode Move} using the move * @returns integer representing the total benefitScore */ - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { let score = 0; for (const attr of this.attrs) { @@ -708,7 +708,7 @@ export default class Move implements Localizable { * @param move {@linkcode Move} using the move * @returns integer representing the total benefitScore */ - getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { let score = 0; if (target.getAlly()?.getTag(BattlerTagType.COMMANDED)?.getSourcePokemon() === target) { @@ -875,7 +875,7 @@ export default class Move implements Localizable { } export class AttackMove extends Move { - constructor(id: Moves, type: Type, category: MoveCategory, power: integer, accuracy: integer, pp: integer, chance: integer, priority: integer, generation: integer) { + constructor(id: Moves, type: Type, category: MoveCategory, power: number, accuracy: number, pp: number, chance: number, priority: number, generation: number) { super(id, type, category, MoveTarget.NEAR_OTHER, power, accuracy, pp, chance, priority, generation); /** @@ -887,7 +887,7 @@ export class AttackMove extends Move { } } - getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { let ret = super.getTargetBenefitScore(user, target, move); let attackScore = 0; @@ -932,13 +932,13 @@ export class AttackMove extends Move { } export class StatusMove extends Move { - constructor(id: Moves, type: Type, accuracy: integer, pp: integer, chance: integer, priority: integer, generation: integer) { + constructor(id: Moves, type: Type, accuracy: number, pp: number, chance: number, priority: number, generation: number) { super(id, type, MoveCategory.STATUS, MoveTarget.NEAR_OTHER, -1, accuracy, pp, chance, priority, generation); } } export class SelfStatusMove extends Move { - constructor(id: Moves, type: Type, accuracy: integer, pp: integer, chance: integer, priority: integer, generation: integer) { + constructor(id: Moves, type: Type, accuracy: number, pp: number, chance: number, priority: number, generation: number) { super(id, type, MoveCategory.STATUS, MoveTarget.USER, -1, accuracy, pp, chance, priority, generation); } } @@ -1074,7 +1074,7 @@ export abstract class MoveAttr { * @see {@linkcode EnemyPokemon.getNextMove} * @virtual */ - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return 0; } @@ -1083,7 +1083,7 @@ export abstract class MoveAttr { * @see {@linkcode EnemyPokemon.getNextMove} * @virtual */ - getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return 0; } } @@ -1201,7 +1201,7 @@ export class MoveEffectAttr extends MoveAttr { * @param selfEffect `true` if move targets user. * @returns Move effect chance value. */ - getMoveChance(user: Pokemon, target: Pokemon, move: Move, selfEffect?: Boolean, showAbility?: Boolean): integer { + getMoveChance(user: Pokemon, target: Pokemon, move: Move, selfEffect?: Boolean, showAbility?: Boolean): number { const moveChance = new Utils.NumberHolder(this.effectChanceOverride ?? move.chance); applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, false, moveChance, move, target, selfEffect, showAbility); @@ -1330,7 +1330,7 @@ export class HighCritAttr extends MoveAttr { return true; } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return 3; } } @@ -1342,15 +1342,15 @@ export class CritOnlyAttr extends MoveAttr { return true; } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return 5; } } export class FixedDamageAttr extends MoveAttr { - private damage: integer; + private damage: number; - constructor(damage: integer) { + constructor(damage: number) { super(); this.damage = damage; @@ -1362,7 +1362,7 @@ export class FixedDamageAttr extends MoveAttr { return true; } - getDamage(user: Pokemon, target: Pokemon, move: Move): integer { + getDamage(user: Pokemon, target: Pokemon, move: Move): number { return this.damage; } } @@ -1435,7 +1435,7 @@ export class MatchHpAttr extends FixedDamageAttr { } // TODO - /*getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + /*getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return 0; }*/ } @@ -1446,7 +1446,7 @@ export class CounterDamageAttr extends FixedDamageAttr { private moveFilter: MoveFilter; private multiplier: number; - constructor(moveFilter: MoveFilter, multiplier: integer) { + constructor(moveFilter: MoveFilter, multiplier: number) { super(0); this.moveFilter = moveFilter; @@ -1454,7 +1454,7 @@ export class CounterDamageAttr extends FixedDamageAttr { } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - const damage = user.turnData.attacksReceived.filter(ar => this.moveFilter(allMoves[ar.move])).reduce((total: integer, ar: AttackMoveResult) => total + ar.damage, 0); + const damage = user.turnData.attacksReceived.filter(ar => this.moveFilter(allMoves[ar.move])).reduce((total: number, ar: AttackMoveResult) => total + ar.damage, 0); (args[0] as Utils.IntegerHolder).value = Utils.toDmgValue(damage * this.multiplier); return true; @@ -1493,7 +1493,7 @@ export class ModifiedDamageAttr extends MoveAttr { return true; } - getModifiedDamage(user: Pokemon, target: Pokemon, move: Move, damage: integer): integer { + getModifiedDamage(user: Pokemon, target: Pokemon, move: Move, damage: number): number { return damage; } } @@ -1507,7 +1507,7 @@ export class SurviveDamageAttr extends ModifiedDamageAttr { return (user, target, move) => target.hp > 1; } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return target.hp > 1 ? 0 : -20; } } @@ -1563,7 +1563,7 @@ export class RecoilAttr extends MoveEffectAttr { return true; } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return Math.floor((move.power / 5) / -4); } } @@ -1594,7 +1594,7 @@ export class SacrificialAttr extends MoveEffectAttr { return true; } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { if (user.isBoss()) { return -20; } @@ -1632,7 +1632,7 @@ export class SacrificialAttrOnHit extends MoveEffectAttr { return true; } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { if (user.isBoss()) { return -20; } @@ -1674,7 +1674,7 @@ export class HalfSacrificialAttr extends MoveEffectAttr { return true; } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { if (user.isBoss()) { return -10; } @@ -1778,7 +1778,7 @@ export class HealAttr extends MoveEffectAttr { Utils.toDmgValue(target.getMaxHp() * healRatio), i18next.t("moveTriggers:healHp", { pokemonName: getPokemonNameWithAffix(target) }), true, !this.showAnim)); } - getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { const score = ((1 - (this.selfTarget ? user : target).getHpRatio()) * 20) - this.healRatio * 10; return Math.round(score / (1 - this.healRatio / 2)); } @@ -1870,7 +1870,7 @@ export class FlameBurstAttr extends MoveEffectAttr { return true; } - getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return target.getAlly() ? -5 : 0; } } @@ -1892,7 +1892,8 @@ export class SacrificialFullRestoreAttr extends SacrificialAttr { } // We don't know which party member will be chosen, so pick the highest max HP in the party - const maxPartyMemberHp = globalScene.getPlayerParty().map(p => p.getMaxHp()).reduce((maxHp: integer, hp: integer) => Math.max(hp, maxHp), 0); + const party = user.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty(); + const maxPartyMemberHp = party.map(p => p.getMaxHp()).reduce((maxHp: number, hp: number) => Math.max(hp, maxHp), 0); globalScene.pushPhase( new PokemonHealPhase( @@ -1910,7 +1911,7 @@ export class SacrificialFullRestoreAttr extends SacrificialAttr { return true; } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return -20; } @@ -2117,7 +2118,7 @@ export class HitHealAttr extends MoveEffectAttr { * @param move {@linkcode Move} being used * @returns an integer. Higher means enemy is more likely to use that move. */ - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { if (this.healStat) { const healAmount = target.getEffectiveStat(this.healStat); return Math.floor(Math.max(0, (Math.min(1, (healAmount + user.hp) / user.getMaxHp() - 0.33))) / user.getHpRatio()); @@ -2137,7 +2138,7 @@ export class IncrementMovePriorityAttr extends MoveAttr { /** The condition for a move's priority being incremented */ private moveIncrementFunc: (pokemon: Pokemon, target:Pokemon, move: Move) => boolean; /** The amount to increment priority by, if condition passes. */ - private increaseAmount: integer; + private increaseAmount: number; constructor(moveIncrementFunc: (pokemon: Pokemon, target:Pokemon, move: Move) => boolean, increaseAmount = 1) { super(); @@ -2221,7 +2222,7 @@ export class MultiHitAttr extends MoveAttr { * @param target {@linkcode Pokemon} targeted by the attack * @returns The number of hits this attack should deal */ - getHitCount(user: Pokemon, target: Pokemon): integer { + getHitCount(user: Pokemon, target: Pokemon): number { switch (this.multiHitType) { case MultiHitType._2_TO_5: { @@ -2668,7 +2669,7 @@ export class HealStatusEffectAttr extends MoveEffectAttr { return this.effects.includes(effect); } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return user.status ? 10 : 0; } } @@ -2689,7 +2690,7 @@ export class BypassSleepAttr extends MoveAttr { * @param target * @param move */ - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return user.status && user.status.effect === StatusEffect.SLEEP ? 200 : -10; } } @@ -3059,11 +3060,11 @@ export class StatStageChangeAttr extends MoveEffectAttr { return false; } - getLevels(_user: Pokemon): integer { + getLevels(_user: Pokemon): number { return this.stages; } - getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { let ret = 0; const moveLevels = this.getLevels(user); for (const stat of this.stats) { @@ -3301,10 +3302,10 @@ export class GrowthStatStageChangeAttr extends StatStageChangeAttr { } export class CutHpStatStageBoostAttr extends StatStageChangeAttr { - private cutRatio: integer; + private cutRatio: number; private messageCallback: ((user: Pokemon) => void) | undefined; - constructor(stat: BattleStat[], levels: integer, cutRatio: integer, messageCallback?: ((user: Pokemon) => void) | undefined) { + constructor(stat: BattleStat[], levels: number, cutRatio: number, messageCallback?: ((user: Pokemon) => void) | undefined) { super(stat, levels, true); this.cutRatio = cutRatio; @@ -3654,7 +3655,7 @@ const doublePowerChanceMessageFunc = (user: Pokemon, target: Pokemon, move: Move export class DoublePowerChanceAttr extends VariablePowerAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - let rand: integer; + let rand: number; globalScene.executeWithSeedOffset(() => rand = Utils.randSeedInt(100), globalScene.currentBattle.turn << 6, globalScene.waveSeed); if (rand! < move.chance) { const power = args[0] as Utils.NumberHolder; @@ -3667,7 +3668,7 @@ export class DoublePowerChanceAttr extends VariablePowerAttr { } export abstract class ConsecutiveUsePowerMultiplierAttr extends MovePowerMultiplierAttr { - constructor(limit: integer, resetOnFail: boolean, resetOnLimit?: boolean, ...comboMoves: Moves[]) { + constructor(limit: number, resetOnFail: boolean, resetOnLimit?: boolean, ...comboMoves: Moves[]) { super((user: Pokemon, target: Pokemon, move: Move): number => { const moveHistory = user.getLastXMoves(limit + 1).slice(1); @@ -3688,7 +3689,7 @@ export abstract class ConsecutiveUsePowerMultiplierAttr extends MovePowerMultipl }); } - abstract getMultiplier(count: integer): number; + abstract getMultiplier(count: number): number; } export class ConsecutiveUseDoublePowerAttr extends ConsecutiveUsePowerMultiplierAttr { @@ -3937,7 +3938,7 @@ export class MagnitudePowerAttr extends VariablePowerAttr { const magnitudeThresholds = [ 5, 15, 35, 65, 75, 95 ]; const magnitudePowers = [ 10, 30, 50, 70, 90, 100, 110, 150 ]; - let rand: integer; + let rand: number; globalScene.executeWithSeedOffset(() => rand = Utils.randSeedInt(100), globalScene.currentBattle.turn << 6, globalScene.waveSeed); @@ -4179,9 +4180,9 @@ const hasStockpileStacksCondition: MoveConditionFunc = (user) => { */ export class MultiHitPowerIncrementAttr extends VariablePowerAttr { /** The max number of base power increments allowed for this move */ - private maxHits: integer; + private maxHits: number; - constructor(maxHits: integer) { + constructor(maxHits: number) { super(); this.maxHits = maxHits; @@ -5250,12 +5251,12 @@ export class SemiInvulnerableAttr extends MoveEffectAttr { export class AddBattlerTagAttr extends MoveEffectAttr { public tagType: BattlerTagType; - public turnCountMin: integer; - public turnCountMax: integer; + public turnCountMin: number; + public turnCountMax: number; protected cancelOnFail: boolean; private failOnOverlap: boolean; - constructor(tagType: BattlerTagType, selfTarget: boolean = false, failOnOverlap: boolean = false, turnCountMin: integer = 0, turnCountMax?: integer, lastHitOnly: boolean = false, cancelOnFail: boolean = false) { + constructor(tagType: BattlerTagType, selfTarget: boolean = false, failOnOverlap: boolean = false, turnCountMin: number = 0, turnCountMax?: number, lastHitOnly: boolean = false, cancelOnFail: boolean = false) { super(selfTarget, { lastHitOnly: lastHitOnly }); this.tagType = tagType; @@ -5292,7 +5293,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr { : null; } - getTagTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer | void { + getTagTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number | void { switch (this.tagType) { case BattlerTagType.RECHARGING: case BattlerTagType.PERISH_SONG: @@ -5339,7 +5340,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr { } } - getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { let moveChance = this.getMoveChance(user, target, move, this.selfTarget, false); if (moveChance < 0) { moveChance = 100; @@ -5406,7 +5407,7 @@ export class GulpMissileTagAttr extends MoveEffectAttr { return false; } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { const isCramorant = user.hasAbility(Abilities.GULP_MISSILE) && user.species.speciesId === Species.CRAMORANT; return isCramorant && !user.getTag(GulpMissileTag) ? 10 : 0; } @@ -5668,7 +5669,7 @@ export class HitsTagAttr extends MoveAttr { this.doubleDamage = !!doubleDamage; } - getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return target.getTag(this.tagType) ? this.doubleDamage ? 10 : 5 : 0; } } @@ -5686,11 +5687,11 @@ export class HitsTagForDoubleDamageAttr extends HitsTagAttr { export class AddArenaTagAttr extends MoveEffectAttr { public tagType: ArenaTagType; - public turnCount: integer; + public turnCount: number; private failOnOverlap: boolean; public selfSideTarget: boolean; - constructor(tagType: ArenaTagType, turnCount?: integer | null, failOnOverlap: boolean = false, selfSideTarget: boolean = false) { + constructor(tagType: ArenaTagType, turnCount?: number | null, failOnOverlap: boolean = false, selfSideTarget: boolean = false) { super(true); this.tagType = tagType; @@ -5982,7 +5983,7 @@ export class RevivalBlessingAttr extends MoveEffectAttr { }); } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { if (user.hasTrainer() && globalScene.getEnemyParty().findIndex(p => p.isFainted() && !p.isBoss()) > -1) { return 20; } @@ -6211,13 +6212,13 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { }; } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { if (!globalScene.getEnemyParty().find(p => p.isActive() && !p.isOnField())) { return -20; } let ret = this.selfSwitch ? Math.floor((1 - user.getHpRatio()) * 20) : super.getUserBenefitScore(user, target, move); if (this.selfSwitch && this.isBatonPass()) { - const statStageTotal = user.getStatStages().reduce((s: integer, total: integer) => total += s, 0); + const statStageTotal = user.getStatStages().reduce((s: number, total: number) => total += s, 0); ret = ret / 2 + (Phaser.Tweens.Builders.GetEaseFunction("Sine.easeOut")(Math.min(Math.abs(statStageTotal), 10) / 10) * (statStageTotal >= 0 ? 10 : -10)); } return ret; @@ -7184,7 +7185,7 @@ export class RepeatMoveAttr extends MoveEffectAttr { }; } - getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { // TODO: Make the AI actually use instruct /* Ideally, the AI would score instruct based on the scorings of the on-field pokemons' * last used moves at the time of using Instruct (by the time the instructor gets to act) @@ -7745,7 +7746,7 @@ export class ShiftStatAttr extends MoveEffectAttr { * @param move n/a * @returns number of points to add to the user's benefit score */ - override getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + override getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return user.getStat(this.statToSwitchWith, false) > user.getStat(this.statToSwitch, false) ? 10 : 0; } } @@ -7797,7 +7798,7 @@ export class AverageStatsAttr extends MoveEffectAttr { } export class DiscourageFrequentUseAttr extends MoveAttr { - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { const lastMoves = user.getLastXMoves(4); console.log(lastMoves); for (let m = 0; m < lastMoves.length; m++) { @@ -8051,7 +8052,7 @@ export class MoveCondition { return this.func(user, target, move); } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return 0; } } @@ -8061,7 +8062,7 @@ export class FirstMoveCondition extends MoveCondition { super((user, target, move) => user.battleSummonData?.waveTurnCount === 1); } - getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { return this.apply(user, target, move) ? 10 : -20; } } diff --git a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts index f6700bb3716..e660b0b873c 100644 --- a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts +++ b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts @@ -15,7 +15,7 @@ import { TrainerType } from "#enums/trainer-type"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { Abilities } from "#enums/abilities"; import { applyAbilityOverrideToPokemon, applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; -import type { Type } from "#enums/type"; +import { Type } from "#enums/type"; import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { randSeedInt, randSeedShuffle } from "#app/utils"; @@ -127,6 +127,13 @@ export const ClowningAroundEncounter: MysteryEncounter = encounter.setDialogueToken("ability", new Ability(ability, 3).name); encounter.misc = { ability }; + // Decide the random types for Blacephalon. They should not be the same. + const firstType: number = randSeedInt(18); + let secondType: number = randSeedInt(17); + if ( secondType >= firstType ) { + secondType++; + } + encounter.enemyPartyConfigs.push({ trainerConfig: clownConfig, pokemonConfigs: [ // Overrides first 2 pokemon to be Mr. Mime and Blacephalon @@ -137,7 +144,7 @@ export const ClowningAroundEncounter: MysteryEncounter = }, { // Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter species: getPokemonSpecies(Species.BLACEPHALON), - customPokemonData: new CustomPokemonData({ ability: ability, types: [ randSeedInt(18), randSeedInt(18) ]}), + customPokemonData: new CustomPokemonData({ ability: ability, types: [ firstType, secondType ]}), isBoss: true, moveSet: [ Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN ] }, @@ -347,7 +354,7 @@ export const ClowningAroundEncounter: MysteryEncounter = priorityTypes = randSeedShuffle(priorityTypes); } - const newTypes = [ originalTypes[0] ]; + const newTypes = [ Type.UNKNOWN ]; let secondType: Type | null = null; while (secondType === null || secondType === newTypes[0] || originalTypes.includes(secondType)) { if (priorityTypes.length > 0) { diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index e8a4c405d5f..e047a7a4f01 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -1,4 +1,4 @@ -import type { Type } from "#enums/type"; +import { Type } from "#enums/type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { Species } from "#enums/species"; import { globalScene } from "#app/global-scene"; @@ -528,7 +528,7 @@ async function postProcessTransformedPokemon(previousPokemon: PlayerPokemon, new // Randomize the second type of the pokemon // If the pokemon does not normally have a second type, it will gain 1 - const newTypes = [ newPokemon.getTypes()[0] ]; + const newTypes = [ Type.UNKNOWN ]; let newType = randSeedInt(18) as Type; while (newType === newTypes[0]) { newType = randSeedInt(18) as Type; diff --git a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts index bcce2ad1349..2d0081f19cd 100644 --- a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts @@ -624,7 +624,7 @@ export async function catchPokemon(pokemon: EnemyPokemon, pokeball: Phaser.GameO }); }, false); }, () => { - globalScene.ui.setMode(Mode.PARTY, PartyUiMode.RELEASE, 0, (slotIndex: integer, _option: PartyOption) => { + globalScene.ui.setMode(Mode.PARTY, PartyUiMode.RELEASE, 0, (slotIndex: number, _option: PartyOption) => { globalScene.ui.setMode(Mode.MESSAGE).then(() => { if (slotIndex < 6) { addToParty(slotIndex); diff --git a/src/data/pokeball.ts b/src/data/pokeball.ts index 049baf11f3d..7cd9f061cdd 100644 --- a/src/data/pokeball.ts +++ b/src/data/pokeball.ts @@ -4,7 +4,7 @@ import { NumberHolder } from "#app/utils"; import { PokeballType } from "#enums/pokeball"; import i18next from "i18next"; -export const MAX_PER_TYPE_POKEBALLS: integer = 99; +export const MAX_PER_TYPE_POKEBALLS: number = 99; export function getPokeballAtlasKey(type: PokeballType): string { switch (type) { diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index f2ab2f6520f..edc9cbccfd2 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -718,7 +718,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali * The calculation with evolution delay is a weighted average of the easeIn and easeOut functions where preferredMinLevel is the denominator. * This also means a lower value of x will lead to a higher evolution chance. * @param strength {@linkcode PartyMemberStrength} The strength of the party member in question - * @returns {@linkcode integer} The level difference from expected evolution level tolerated for a mon to be unevolved. Lower value = higher evolution chance. + * @returns {@linkcode number} The level difference from expected evolution level tolerated for a mon to be unevolved. Lower value = higher evolution chance. */ private getStrengthLevelDiff(strength: PartyMemberStrength): number { switch (Math.min(strength, PartyMemberStrength.STRONGER)) { @@ -2664,17 +2664,9 @@ export function initSpecies() { new PokemonSpecies(Species.IRON_VALIANT, 9, false, false, false, "Paradox Pokémon", Type.FAIRY, Type.FIGHTING, 1.4, 35, Abilities.QUARK_DRIVE, Abilities.NONE, Abilities.NONE, 590, 74, 130, 90, 120, 60, 116, 10, 0, 295, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.KORAIDON, 9, false, true, false, "Paradox Pokémon", Type.FIGHTING, Type.DRAGON, 2.5, 303, Abilities.ORICHALCUM_PULSE, Abilities.NONE, Abilities.NONE, 670, 100, 135, 115, 85, 100, 135, 3, 0, 335, GrowthRate.SLOW, null, false, false, new PokemonForm("Apex Build", "apex-build", Type.FIGHTING, Type.DRAGON, 2.5, 303, Abilities.ORICHALCUM_PULSE, Abilities.NONE, Abilities.NONE, 670, 100, 135, 115, 85, 100, 135, 3, 0, 335, false, null, true), - new PokemonForm("Limited Build", "limited-build", Type.FIGHTING, Type.DRAGON, 3.5, 303, Abilities.ORICHALCUM_PULSE, Abilities.NONE, Abilities.NONE, 670, 100, 135, 115, 85, 100, 135, 3, 0, 335, false, null, true), - new PokemonForm("Sprinting Build", "sprinting-build", Type.FIGHTING, Type.DRAGON, 3.5, 303, Abilities.ORICHALCUM_PULSE, Abilities.NONE, Abilities.NONE, 670, 100, 135, 115, 85, 100, 135, 3, 0, 335, false, null, true), - new PokemonForm("Swimming Build", "swimming-build", Type.FIGHTING, Type.DRAGON, 3.5, 303, Abilities.ORICHALCUM_PULSE, Abilities.NONE, Abilities.NONE, 670, 100, 135, 115, 85, 100, 135, 3, 0, 335, false, null, true), - new PokemonForm("Gliding Build", "gliding-build", Type.FIGHTING, Type.DRAGON, 3.5, 303, Abilities.ORICHALCUM_PULSE, Abilities.NONE, Abilities.NONE, 670, 100, 135, 115, 85, 100, 135, 3, 0, 335, false, null, true), ), new PokemonSpecies(Species.MIRAIDON, 9, false, true, false, "Paradox Pokémon", Type.ELECTRIC, Type.DRAGON, 3.5, 240, Abilities.HADRON_ENGINE, Abilities.NONE, Abilities.NONE, 670, 100, 85, 100, 135, 115, 135, 3, 0, 335, GrowthRate.SLOW, null, false, false, new PokemonForm("Ultimate Mode", "ultimate-mode", Type.ELECTRIC, Type.DRAGON, 3.5, 240, Abilities.HADRON_ENGINE, Abilities.NONE, Abilities.NONE, 670, 100, 85, 100, 135, 115, 135, 3, 0, 335, false, null, true), - new PokemonForm("Low-Power Mode", "low-power-mode", Type.ELECTRIC, Type.DRAGON, 2.8, 240, Abilities.HADRON_ENGINE, Abilities.NONE, Abilities.NONE, 670, 100, 85, 100, 135, 115, 135, 3, 0, 335, false, null, true), - new PokemonForm("Drive Mode", "drive-mode", Type.ELECTRIC, Type.DRAGON, 2.8, 240, Abilities.HADRON_ENGINE, Abilities.NONE, Abilities.NONE, 670, 100, 85, 100, 135, 115, 135, 3, 0, 335, false, null, true), - new PokemonForm("Aquatic Mode", "aquatic-mode", Type.ELECTRIC, Type.DRAGON, 2.8, 240, Abilities.HADRON_ENGINE, Abilities.NONE, Abilities.NONE, 670, 100, 85, 100, 135, 115, 135, 3, 0, 335, false, null, true), - new PokemonForm("Glide Mode", "glide-mode", Type.ELECTRIC, Type.DRAGON, 2.8, 240, Abilities.HADRON_ENGINE, Abilities.NONE, Abilities.NONE, 670, 100, 85, 100, 135, 115, 135, 3, 0, 335, false, null, true), ), new PokemonSpecies(Species.WALKING_WAKE, 9, false, false, false, "Paradox Pokémon", Type.WATER, Type.DRAGON, 3.5, 280, Abilities.PROTOSYNTHESIS, Abilities.NONE, Abilities.NONE, 590, 99, 83, 91, 125, 83, 109, 10, 0, 295, GrowthRate.SLOW, null, false), //Custom Catchrate, matching Gouging Fire and Raging Bolt new PokemonSpecies(Species.IRON_LEAVES, 9, false, false, false, "Paradox Pokémon", Type.GRASS, Type.PSYCHIC, 1.5, 125, Abilities.QUARK_DRIVE, Abilities.NONE, Abilities.NONE, 590, 90, 130, 88, 70, 108, 104, 10, 0, 295, GrowthRate.SLOW, null, false), //Custom Catchrate, matching Iron Boulder and Iron Crown diff --git a/src/data/terrain.ts b/src/data/terrain.ts index da315a14a86..1ffe0adc8bf 100644 --- a/src/data/terrain.ts +++ b/src/data/terrain.ts @@ -15,9 +15,9 @@ export enum TerrainType { export class Terrain { public terrainType: TerrainType; - public turnsLeft: integer; + public turnsLeft: number; - constructor(terrainType: TerrainType, turnsLeft?: integer) { + constructor(terrainType: TerrainType, turnsLeft?: number) { this.terrainType = terrainType; this.turnsLeft = turnsLeft || 0; } @@ -81,7 +81,7 @@ export function getTerrainName(terrainType: TerrainType): string { } -export function getTerrainColor(terrainType: TerrainType): [ integer, integer, integer ] { +export function getTerrainColor(terrainType: TerrainType): [ number, number, number ] { switch (terrainType) { case TerrainType.MISTY: return [ 232, 136, 200 ]; diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 266dc342402..016a2c9bca6 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -25,8 +25,6 @@ import { Gender } from "#app/data/gender"; /** Minimum BST for Pokemon generated onto the Elite Four's teams */ const ELITE_FOUR_MINIMUM_BST = 460; -/** Minimum BST for Pokemon generated onto the E4 Champion's team */ -const CHAMPION_MINIMUM_BST = 508; export enum TrainerPoolTier { COMMON, @@ -37,7 +35,7 @@ export enum TrainerPoolTier { } export interface TrainerTierPools { - [key: integer]: Species[] + [key: number]: Species[] } export enum TrainerSlot { @@ -47,27 +45,27 @@ export enum TrainerSlot { } export class TrainerPartyTemplate { - public size: integer; + public size: number; public strength: PartyMemberStrength; public sameSpecies: boolean; public balanced: boolean; - constructor(size: integer, strength: PartyMemberStrength, sameSpecies?: boolean, balanced?: boolean) { + constructor(size: number, strength: PartyMemberStrength, sameSpecies?: boolean, balanced?: boolean) { this.size = size; this.strength = strength; this.sameSpecies = !!sameSpecies; this.balanced = !!balanced; } - getStrength(index: integer): PartyMemberStrength { + getStrength(index: number): PartyMemberStrength { return this.strength; } - isSameSpecies(index: integer): boolean { + isSameSpecies(index: number): boolean { return this.sameSpecies; } - isBalanced(index: integer): boolean { + isBalanced(index: number): boolean { return this.balanced; } } @@ -76,14 +74,14 @@ export class TrainerPartyCompoundTemplate extends TrainerPartyTemplate { public templates: TrainerPartyTemplate[]; constructor(...templates: TrainerPartyTemplate[]) { - super(templates.reduce((total: integer, template: TrainerPartyTemplate) => { + super(templates.reduce((total: number, template: TrainerPartyTemplate) => { total += template.size; return total; }, 0), PartyMemberStrength.AVERAGE); this.templates = templates; } - getStrength(index: integer): PartyMemberStrength { + getStrength(index: number): PartyMemberStrength { let t = 0; for (const template of this.templates) { if (t + template.size > index) { @@ -95,7 +93,7 @@ export class TrainerPartyCompoundTemplate extends TrainerPartyTemplate { return super.getStrength(index); } - isSameSpecies(index: integer): boolean { + isSameSpecies(index: number): boolean { let t = 0; for (const template of this.templates) { if (t + template.size > index) { @@ -107,7 +105,7 @@ export class TrainerPartyCompoundTemplate extends TrainerPartyTemplate { return super.isSameSpecies(index); } - isBalanced(index: integer): boolean { + isBalanced(index: number): boolean { let t = 0; for (const template of this.templates) { if (t + template.size > index) { @@ -164,7 +162,7 @@ export const trainerPartyTemplates = { ELITE_FOUR: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)), - CHAMPION: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER), new TrainerPartyTemplate(5, PartyMemberStrength.STRONG, false, true)), + CHAMPION: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(4, PartyMemberStrength.STRONG), new TrainerPartyTemplate(2, PartyMemberStrength.STRONGER, false, true)), RIVAL: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE)), RIVAL_2: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.WEAK, false, true)), @@ -175,11 +173,11 @@ export const trainerPartyTemplates = { }; type PartyTemplateFunc = () => TrainerPartyTemplate; -type PartyMemberFunc = (level: integer, strength: PartyMemberStrength) => EnemyPokemon; +type PartyMemberFunc = (level: number, strength: PartyMemberStrength) => EnemyPokemon; type GenModifiersFunc = (party: EnemyPokemon[]) => PersistentModifier[]; export interface PartyMemberFuncs { - [key: integer]: PartyMemberFunc + [key: number]: PartyMemberFunc } export class TrainerConfig { @@ -526,7 +524,7 @@ export class TrainerConfig { return this; } - setPartyMemberFunc(slotIndex: integer, partyMemberFunc: PartyMemberFunc): TrainerConfig { + setPartyMemberFunc(slotIndex: number, partyMemberFunc: PartyMemberFunc): TrainerConfig { this.partyMemberFuncs[slotIndex] = partyMemberFunc; return this; } @@ -616,6 +614,13 @@ export class TrainerConfig { [TrainerPoolTier.RARE]: [ Species.HISUI_ZORUA, Species.AXEW, Species.DEINO, Species.HISUI_BRAVIARY ] }; } + case "plasma_2": { + return { + [TrainerPoolTier.COMMON]: [ Species.MAGNEMITE, Species.GRIMER, Species.VOLTORB, Species.PORYGON, Species.BRONZOR, Species.MUNNA, Species.SOLOSIS, Species.JOLTIK, Species.FERROSEED, Species.TYNAMO, Species.ELGYEM ], + [TrainerPoolTier.UNCOMMON]: [ Species.BELDUM, Species.ROTOM, Species.TIRTOUGA, Species.ARCHEN, Species.GOLETT, Species.DURANT, Species.GRUBBIN, Species.BLIPBUG, Species.VAROOM, Species.ALOLA_GRIMER, Species.HISUI_VOLTORB ], + [TrainerPoolTier.RARE]: [ Species.ELEKID, Species.MAGBY, Species.PAWNIARD, Species.DURALUDON ] + }; + } case "flare": { return { [TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.INKAY, Species.FOONGUS, Species.HELIOPTILE, Species.ELECTRIKE, Species.SKORUPI, Species.PURRLOIN, Species.CLAWITZER, Species.PANCHAM, Species.ESPURR, Species.BUNNELBY ], @@ -905,7 +910,7 @@ export class TrainerConfig { this.setHasVoucher(true); this.setBattleBgm("battle_unova_elite"); this.setVictoryBgm("victory_gym"); - this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 2, specialtyTypes.length ? specialtyTypes : undefined)); + this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 1, specialtyTypes.length ? specialtyTypes : undefined)); return this; } @@ -916,7 +921,7 @@ export class TrainerConfig { * @param isMale Whether the Champion is Male or Female (for localization of the title). * @returns {TrainerConfig} The updated TrainerConfig instance. **/ - initForChampion(signatureSpecies: (Species | Species[])[], isMale: boolean): TrainerConfig { + initForChampion(isMale: boolean): TrainerConfig { // Check if the internationalization (i18n) system is initialized. if (!getIsInitialized()) { initI18n(); @@ -925,18 +930,6 @@ export class TrainerConfig { // Set the party templates for the Champion. this.setPartyTemplates(trainerPartyTemplates.CHAMPION); - // Set up party members with their corresponding species. - signatureSpecies.forEach((speciesPool, s) => { - // Ensure speciesPool is an array. - if (!Array.isArray(speciesPool)) { - speciesPool = [ speciesPool ]; - } - // Set a function to get a random party member from the species pool. - this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); - }); - - this.setSpeciesFilter(p => p.baseTotal >= CHAMPION_MINIMUM_BST); - // Localize the trainer's name by converting it to lowercase and replacing spaces with underscores. const nameForCall = this.name.toLowerCase().replace(/\s/g, "_"); this.name = i18next.t(`trainerNames:${nameForCall}`); @@ -955,7 +948,6 @@ export class TrainerConfig { this.setHasVoucher(true); this.setBattleBgm("battle_champion_alder"); this.setVictoryBgm("victory_champion"); - this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 3)); return this; } @@ -1133,7 +1125,7 @@ export class TrainerConfig { let t = 0; interface TrainerConfigs { - [key: integer]: TrainerConfig + [key: number]: TrainerConfig } /** @@ -1205,7 +1197,7 @@ function getSpeciesFilterRandomPartyMemberFunc( }; } -function getRandomTeraModifiers(party: EnemyPokemon[], count: integer, types?: Type[]): PersistentModifier[] { +function getRandomTeraModifiers(party: EnemyPokemon[], count: number, types?: Type[]): PersistentModifier[] { const ret: PersistentModifier[] = []; const partyMemberIndexes = new Array(party.length).fill(null).map((_, i) => i); for (let t = 0; t < Math.min(count, party.length); t++) { @@ -1341,20 +1333,6 @@ export const signatureSpecies: SignatureSpecies = { AMARYS: [ Species.SKARMORY, Species.EMPOLEON, Species.SCIZOR, Species.METAGROSS ], LACEY: [ Species.EXCADRILL, Species.PRIMARINA, [ Species.ALCREMIE, Species.GRANBULL ], Species.WHIMSICOTT ], DRAYTON: [ Species.DRAGONITE, Species.ARCHALUDON, Species.HAXORUS, Species.SCEPTILE ], - BLUE: [[ Species.GYARADOS, Species.EXEGGUTOR, Species.ARCANINE ], Species.HO_OH, [ Species.RHYPERIOR, Species.MAGNEZONE ]], // Alakazam lead, Mega Pidgeot - RED: [ Species.LUGIA, Species.SNORLAX, [ Species.ESPEON, Species.UMBREON, Species.SYLVEON ]], // GMax Pikachu lead, Mega gen 1 starter - LANCE_CHAMPION: [ Species.DRAGONITE, Species.KINGDRA, Species.ALOLA_EXEGGUTOR ], // Aerodactyl lead, Mega Latias/Latios - STEVEN: [ Species.AGGRON, [ Species.ARMALDO, Species.CRADILY ], Species.DIALGA ], // Skarmory lead, Mega Metagross - WALLACE: [ Species.MILOTIC, Species.PALKIA, Species.LUDICOLO ], // Pelipper lead, Mega Swampert - CYNTHIA: [ Species.GIRATINA, Species.LUCARIO, Species.TOGEKISS ], // Spiritomb lead, Mega Garchomp - ALDER: [ Species.VOLCARONA, Species.ZEKROM, [ Species.ACCELGOR, Species.ESCAVALIER ], Species.KELDEO ], // Bouffalant/Braviary lead - IRIS: [ Species.HAXORUS, Species.RESHIRAM, Species.ARCHEOPS ], // Druddigon lead, Gmax Lapras - DIANTHA: [ Species.HAWLUCHA, Species.XERNEAS, Species.GOODRA ], // Gourgeist lead, Mega Gardevoir - HAU: [[ Species.SOLGALEO, Species.LUNALA ], Species.NOIVERN, [ Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA ], [ Species.TAPU_BULU, Species.TAPU_FINI, Species.TAPU_KOKO, Species.TAPU_LELE ]], // Alola Raichu lead - LEON: [ Species.DRAGAPULT, Species.ZACIAN, Species.AEGISLASH ], // Rillaboom/Cinderace/Inteleon lead, GMax Charizard - GEETA: [ Species.MIRAIDON, [ Species.ESPATHRA, Species.VELUZA ], [ Species.AVALUGG, Species.HISUI_AVALUGG ], Species.KINGAMBIT ], // Glimmora lead - NEMONA: [ Species.KORAIDON, Species.PAWMOT, [ Species.DUDUNSPARCE, Species.ORTHWORM ], [ Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ]], // Lycanroc lead - KIERAN: [[ Species.GRIMMSNARL, Species.INCINEROAR, Species.PORYGON_Z ], Species.OGERPON, Species.TERAPAGOS, Species.HYDRAPPLE ], // Poliwrath/Politoed lead }; export const trainerConfigs: TrainerConfigs = { @@ -1567,7 +1545,7 @@ export const trainerConfigs: TrainerConfigs = { [TrainerPoolTier.SUPER_RARE]: [ Species.DRUDDIGON, Species.HISUI_ZORUA, Species.AXEW, Species.DEINO ] }), [TrainerType.ZINZOLIN]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("plasma_sage", "plasma", [ Species.CRYOGONAL ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_plasma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()), - [TrainerType.ROOD]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("plasma_sage", "plasma", [ Species.SWOOBAT ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_plasma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()), + [TrainerType.COLRESS]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("plasma_boss", "plasma_2", [ Species.KLINKLANG ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_colress").setMixedBattleBgm("battle_colress").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()), [TrainerType.FLARE_GRUNT]: new TrainerConfig(++t).setHasGenders("Flare Grunt Female").setHasDouble("Flare Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.PONYTA, Species.INKAY, Species.HOUNDOUR, Species.SKORUPI, Species.SCRAFTY, Species.CROAGUNK, Species.SCATTERBUG, Species.ESPURR ], @@ -1751,111 +1729,417 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.LACEY]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["LACEY"], false, Type.FAIRY).setMixedBattleBgm("battle_bb_elite"), [TrainerType.DRAYTON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAYTON"], true, Type.DRAGON).setMixedBattleBgm("battle_bb_elite"), - [TrainerType.BLUE]: new TrainerConfig((t = TrainerType.BLUE)).initForChampion(signatureSpecies["BLUE"], true).setBattleBgm("battle_kanto_champion").setMixedBattleBgm("battle_kanto_champion").setHasDouble("blue_red_double").setDoubleTrainerType(TrainerType.RED).setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ALAKAZAM ], TrainerSlot.TRAINER, true, p => { + [TrainerType.BLUE]: new TrainerConfig((t = TrainerType.BLUE)).initForChampion(true).setBattleBgm("battle_kanto_champion").setMixedBattleBgm("battle_kanto_champion").setHasDouble("blue_red_double").setDoubleTrainerType(TrainerType.RED).setDoubleTitle("champion_double") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ALAKAZAM ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MACHAMP ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.HO_OH ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.RHYPERIOR, Species.ELECTIVIRE, Species.MAGMORTAR ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.ARCANINE, Species.EXEGGUTOR, Species.GYARADOS ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.setBoss(true, 2); + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.PIDGEOT ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Pidgeot p.generateAndPopulateMoveset(); p.generateName(); - })), - [TrainerType.RED]: new TrainerConfig(++t).initForChampion(signatureSpecies["RED"], true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion").setHasDouble("red_blue_double").setDoubleTrainerType(TrainerType.BLUE).setDoubleTitle("champion_double") + p.gender = Gender.MALE; + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[3]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.RED]: new TrainerConfig(++t).initForChampion(true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion").setHasDouble("red_blue_double").setDoubleTrainerType(TrainerType.BLUE).setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PIKACHU ], TrainerSlot.TRAINER, true, p => { p.formIndex = 8; // G-Max Pikachu p.generateAndPopulateMoveset(); p.generateName(); + p.gender = Gender.MALE; })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ESPEON, Species.UMBREON, Species.SYLVEON ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.LUGIA ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.SNORLAX ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.setBoss(true, 2); + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Venusaur, Mega Charizard X, or Mega Blastoise p.generateAndPopulateMoveset(); p.generateName(); - })), - [TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t).setName("Lance").initForChampion(signatureSpecies["LANCE_CHAMPION"], true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.AERODACTYL ], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); + p.gender = Gender.MALE; })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.LATIAS, Species.LATIOS ], TrainerSlot.TRAINER, true, p => { - p.formIndex = 1; // Mega Latias or Mega Latios + .setGenModifiersFunc(party => { + const teraPokemon = party[3]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t).setName("Lance").initForChampion(true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GYARADOS, Species.KINGDRA ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.AERODACTYL ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SALAMENCE ], TrainerSlot.TRAINER, true, p => { + p.formIndex = 1; // Mega Salamence p.generateAndPopulateMoveset(); p.generateName(); - })), - [TrainerType.STEVEN]: new TrainerConfig(++t).initForChampion(signatureSpecies["STEVEN"], true).setBattleBgm("battle_hoenn_champion_g5").setMixedBattleBgm("battle_hoenn_champion_g6").setHasDouble("steven_wallace_double").setDoubleTrainerType(TrainerType.WALLACE).setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SKARMORY ], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.METAGROSS ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.CHARIZARD ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.TYRANITAR, Species.GARCHOMP, Species.KOMMO_O ])) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.DRAGONITE ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.gender = Gender.MALE; + p.setBoss(true, 2); + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[4]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.STEVEN]: new TrainerConfig(++t).initForChampion(true).setBattleBgm("battle_hoenn_champion_g5").setMixedBattleBgm("battle_hoenn_champion_g6").setHasDouble("steven_wallace_double").setDoubleTrainerType(TrainerType.WALLACE).setDoubleTitle("champion_double") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SKARMORY ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CRADILY, Species.ARMALDO ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.AGGRON ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.setBoss(true, 2); + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GOLURK, Species.RUNERIGUS ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.REGIROCK, Species.REGICE, Species.REGISTEEL ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.METAGROSS ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Metagross p.generateAndPopulateMoveset(); p.generateName(); - })), - [TrainerType.WALLACE]: new TrainerConfig(++t).initForChampion(signatureSpecies["WALLACE"], true).setBattleBgm("battle_hoenn_champion_g5").setMixedBattleBgm("battle_hoenn_champion_g6").setHasDouble("wallace_steven_double").setDoubleTrainerType(TrainerType.STEVEN).setDoubleTitle("champion_double") + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[4]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.WALLACE]: new TrainerConfig(++t).initForChampion(true).setBattleBgm("battle_hoenn_champion_g5").setMixedBattleBgm("battle_hoenn_champion_g6").setHasDouble("wallace_steven_double").setDoubleTrainerType(TrainerType.STEVEN).setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PELIPPER ], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Drizzle p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.SWAMPERT ], TrainerSlot.TRAINER, true, p => { - p.formIndex = 1; // Mega Swampert + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.LUDICOLO ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.LATIAS, Species.LATIOS ], TrainerSlot.TRAINER, true, p => { + p.formIndex = 1; // Mega Latios or Mega Latias p.generateAndPopulateMoveset(); p.generateName(); - })), - [TrainerType.CYNTHIA]: new TrainerConfig(++t).initForChampion(signatureSpecies["CYNTHIA"], false).setBattleBgm("battle_sinnoh_champion").setMixedBattleBgm("battle_sinnoh_champion") + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.SWAMPERT, Species.GASTRODON, Species.SEISMITOAD ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.REGIELEKI, Species.REGIDRAGO ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.MILOTIC ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.gender = Gender.FEMALE; + p.setBoss(true, 2); + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[4]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.CYNTHIA]: new TrainerConfig(++t).initForChampion(false).setBattleBgm("battle_sinnoh_champion").setMixedBattleBgm("battle_sinnoh_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SPIRITOMB ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.GARCHOMP ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.LUCARIO ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.GIRATINA ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.MILOTIC, Species.ROSERADE, Species.HISUI_ARCANINE ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.TOGEKISS ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.setBoss(true, 2); + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GARCHOMP ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Garchomp p.generateAndPopulateMoveset(); p.generateName(); - })), - [TrainerType.ALDER]: new TrainerConfig(++t).initForChampion(signatureSpecies["ALDER"], true).setHasDouble("alder_iris_double").setDoubleTrainerType(TrainerType.IRIS).setDoubleTitle("champion_double").setBattleBgm("battle_champion_alder").setMixedBattleBgm("battle_champion_alder") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BOUFFALANT, Species.BRAVIARY ], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - })), - [TrainerType.IRIS]: new TrainerConfig(++t).initForChampion(signatureSpecies["IRIS"], false).setBattleBgm("battle_champion_iris").setMixedBattleBgm("battle_champion_iris").setHasDouble("iris_alder_double").setDoubleTrainerType(TrainerType.ALDER).setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.DRUDDIGON ], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); + p.gender = Gender.FEMALE; })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.LAPRAS ], TrainerSlot.TRAINER, true, p => { + .setGenModifiersFunc(party => { + const teraPokemon = party[3]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.ALDER]: new TrainerConfig(++t).initForChampion(true).setHasDouble("alder_iris_double").setDoubleTrainerType(TrainerType.IRIS).setDoubleTitle("champion_double").setBattleBgm("battle_champion_alder").setMixedBattleBgm("battle_champion_alder") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BOUFFALANT, Species.BRAVIARY ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HISUI_LILLIGANT, Species.HISUI_ZOROARK, Species.BASCULEGION ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ROGUE_BALL; + })) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.ZEKROM ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.KELDEO ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.CHANDELURE, Species.KROOKODILE, Species.REUNICLUS, Species.CONKELDURR ])) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.VOLCARONA ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.gender = Gender.MALE; + p.setBoss(true, 2); + })) + .setGenModifiersFunc(party => { + const pokemon = party[4]; + return [ modifierTypes.TERA_SHARD().generateType([], [ pokemon.species.speciesId === Species.KROOKODILE ? pokemon.species.type2 : pokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(pokemon) as PersistentModifier ]; + }), + [TrainerType.IRIS]: new TrainerConfig(++t).initForChampion(false).setBattleBgm("battle_champion_iris").setMixedBattleBgm("battle_champion_iris").setHasDouble("iris_alder_double").setDoubleTrainerType(TrainerType.ALDER).setDoubleTitle("champion_double") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.DRUDDIGON ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ARCHEOPS ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.RESHIRAM ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.SALAMENCE, Species.HYDREIGON, Species.ARCHALUDON ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.LAPRAS ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // G-Max Lapras p.generateAndPopulateMoveset(); p.generateName(); - })), - [TrainerType.DIANTHA]: new TrainerConfig(++t).initForChampion(signatureSpecies["DIANTHA"], false).setMixedBattleBgm("battle_kalos_champion") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GOURGEIST ], TrainerSlot.TRAINER, true, p => { + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.HAXORUS ], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = 1; // Mold Breaker + p.generateAndPopulateMoveset(); + p.gender = Gender.FEMALE; + p.setBoss(true, 2); + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[3]; + return [ modifierTypes.TERA_SHARD().generateType([], [ Type.DRAGON ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.DIANTHA]: new TrainerConfig(++t).initForChampion(false).setMixedBattleBgm("battle_kalos_champion") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.HAWLUCHA ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.GARDEVOIR ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.TREVENANT, Species.GOURGEIST ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.XERNEAS ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TYRANTRUM, Species.AURORUS ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.abilityIndex = 2; // Rock Head Tyrantrum, Snow Warning Aurorus + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GOODRA ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.setBoss(true, 2); + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GARDEVOIR ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Gardevoir p.generateAndPopulateMoveset(); p.generateName(); - })), - [TrainerType.HAU]: new TrainerConfig(++t).initForChampion(signatureSpecies["HAU"], true).setMixedBattleBgm("battle_alola_champion") + p.gender = Gender.FEMALE; + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[3]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type2 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.KUKUI]: new TrainerConfig(++t).initForChampion(true).setMixedBattleBgm("battle_champion_kukui") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LYCANROC ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.formIndex = 2; // Dusk Lycanroc + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MAGNEZONE, Species.ALOLA_NINETALES ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.TORNADUS, Species.THUNDURUS, Species.LANDORUS ], TrainerSlot.TRAINER, true, p => { + p.formIndex = 1; // Therian Forms + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TAPU_KOKO, Species.TAPU_FINI ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.setBoss(true, 2); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.SNORLAX ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.formIndex = 1; // G-Max Snorlax + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.INCINEROAR, Species.HISUI_DECIDUEYE ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.gender = Gender.MALE; + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[5]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type2 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.HAU]: new TrainerConfig(++t).initForChampion(true).setMixedBattleBgm("battle_alola_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ALOLA_RAICHU ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - })), - [TrainerType.LEON]: new TrainerConfig(++t).initForChampion(signatureSpecies["LEON"], true).setMixedBattleBgm("battle_galar_champion") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.RILLABOOM, Species.CINDERACE, Species.INTELEON ], TrainerSlot.TRAINER, true, p => { + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.NOIVERN ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SOLGALEO ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TAPU_LELE, Species.TAPU_BULU ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.ZYGARDE ], TrainerSlot.TRAINER, true, p => { + p.formIndex = 1; // Zygarde 10% forme, Aura Break + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ROGUE_BALL; + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.DECIDUEYE, Species.PRIMARINA ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.setBoss(true, 2); + p.gender = p.species.speciesId === Species.PRIMARINA ? Gender.FEMALE : Gender.MALE; + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[3]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.LEON]: new TrainerConfig(++t).initForChampion(true).setMixedBattleBgm("battle_galar_champion") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.AEGISLASH ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CHARIZARD ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.RHYPERIOR, Species.SEISMITOAD, Species.MR_RIME ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.ZACIAN ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.DRAGAPULT ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.RILLABOOM, Species.CINDERACE, Species.INTELEON ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.setBoss(true, 2); + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.CHARIZARD ], TrainerSlot.TRAINER, true, p => { p.formIndex = 3; // G-Max Charizard p.generateAndPopulateMoveset(); p.generateName(); - })), - [TrainerType.GEETA]: new TrainerConfig(++t).initForChampion(signatureSpecies["GEETA"], false).setMixedBattleBgm("battle_champion_geeta") + p.gender = Gender.MALE; + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[3]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.MUSTARD]: new TrainerConfig(++t).initForChampion(true).setMixedBattleBgm("battle_mustard") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CORVIKNIGHT ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.KOMMO_O ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.GALAR_SLOWBRO, Species.GALAR_SLOWKING ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GALAR_DARMANITAN ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.BLASTOISE, Species.VENUSAUR ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.setBoss(true, 2); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.URSHIFU ], TrainerSlot.TRAINER, true, p => { + p.formIndex = Utils.randSeedInt(2, 2); // Random G-Max Urshifu + p.generateAndPopulateMoveset(); + p.generateName(); + p.gender = Gender.MALE; + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[2]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type2 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.GEETA]: new TrainerConfig(++t).initForChampion(false).setMixedBattleBgm("battle_champion_geeta") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GLIMMORA ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - })), - [TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion(signatureSpecies["NEMONA"], false).setMixedBattleBgm("battle_champion_nemona") + p.gender = Gender.MALE; + p.setBoss(true, 2); + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ESPATHRA, Species.VELUZA ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.MIRAIDON ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.BAXCALIBUR ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA ])) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KINGAMBIT ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.abilityIndex = 1; // Supreme Overlord + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[5]; + return [ modifierTypes.TERA_SHARD().generateType([], [ Type.FLYING ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion(false).setMixedBattleBgm("battle_champion_nemona") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LYCANROC ], TrainerSlot.TRAINER, true, p => { p.formIndex = 0; // Midday form p.generateAndPopulateMoveset(); - })), - [TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion(signatureSpecies["KIERAN"], true).setMixedBattleBgm("battle_champion_kieran") + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PAWMOT ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.KORAIDON ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GHOLDENGO ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.ARMAROUGE, Species.CERULEDGE ])) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.gender = Gender.MALE; + p.setBoss(true, 2); + })) + .setGenModifiersFunc(party => { + const teraPokemon = party[4]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type2 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; + }), + [TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion(true).setMixedBattleBgm("battle_champion_kieran") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.POLIWRATH, Species.POLITOED ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - })), + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.INCINEROAR, Species.GRIMMSNARL ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + if (p.species.speciesId === Species.INCINEROAR) { + p.abilityIndex = 2; // Intimidate + } else if (p.species.speciesId === Species.GRIMMSNARL) { + p.abilityIndex = 0; // Prankster + } + })) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.TERAPAGOS ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.URSALUNA, Species.BLOODMOON_URSALUNA ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.OGERPON ], TrainerSlot.TRAINER, true, p => { + p.formIndex = Utils.randSeedInt(4, 4); // Random Ogerpon Tera Mask + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ULTRA_BALL; + if (!p.moveset.some(move => !Utils.isNullOrUndefined(move) && move.moveId === Moves.IVY_CUDGEL)) { // Check if Ivy Cudgel is in the moveset, if not, replace the first move with Ivy Cudgel. + p.moveset[0] = new PokemonMove(Moves.IVY_CUDGEL); + } + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.HYDRAPPLE ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.gender = Gender.MALE; + p.setBoss(true, 2); + })) + .setGenModifiersFunc(party => { + const starter = party[4]; + let teraShardType: Type; + const pokemonType2 = starter.species.forms[starter.formIndex].type2; + if (starter.formIndex === 4 || Utils.isNullOrUndefined(pokemonType2)) { + teraShardType = starter.species.type1; + } else { + teraShardType = pokemonType2; + } + return [ modifierTypes.TERA_SHARD().generateType([], [ teraShardType ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ]; + }), [TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setMixedBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL) .setModifierRewardFuncs(() => modifierTypes.SUPER_EXP_CHARM, () => modifierTypes.EXP_SHARE) @@ -1934,13 +2218,13 @@ export const trainerConfigs: TrainerConfigs = { }), [TrainerType.ROCKET_BOSS_GIOVANNI_1]: new TrainerConfig(t = TrainerType.ROCKET_BOSS_GIOVANNI_1).setName("Giovanni").initForEvilTeamLeader("Rocket Boss", []).setMixedBattleBgm("battle_rocket_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PERSIAN, Species.ALOLA_PERSIAN ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PERSIAN ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; })) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.DUGTRIO, Species.ALOLA_DUGTRIO ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.HONCHKROW ])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.NIDOKING, Species.NIDOQUEEN ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.NIDOQUEEN, Species.NIDOKING ])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.RHYPERIOR ])) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KANGASKHAN ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); @@ -1956,33 +2240,35 @@ export const trainerConfigs: TrainerConfigs = { p.pokeball = PokeballType.ULTRA_BALL; })) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HIPPOWDON ])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.EXCADRILL, Species.GARCHOMP ])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.KANGASKHAN ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.GARCHOMP, Species.EXCADRILL ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GASTRODON, Species.SEISMITOAD ], TrainerSlot.TRAINER, true, p => { + if (p.species.speciesId === Species.GASTRODON) { + p.abilityIndex = 0; // Storm Drain + } else if (p.species.speciesId === Species.SEISMITOAD) { + p.abilityIndex = 2; // Water Absorb + } + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.KANGASKHAN ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.formIndex = 1; // Mega Kangaskhan p.generateName(); })) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GASTRODON, Species.SEISMITOAD ], TrainerSlot.TRAINER, true, p => { - //Storm Drain Gastrodon, Water Absorb Seismitoad - if (p.species.speciesId === Species.GASTRODON) { - p.abilityIndex = 0; - } else if (p.species.speciesId === Species.SEISMITOAD) { - p.abilityIndex = 2; - } - })) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.MEWTWO ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; })), [TrainerType.MAXIE]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss", []).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.MIGHTYENA ])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CROBAT, Species.GLISCOR ])) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SOLROCK ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.TALONFLAME ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WEEZING, Species.GALAR_WEEZING ])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.MAGMORTAR, Species.TORKOAL ])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.FLYGON ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TORKOAL ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.abilityIndex = 1; // Drought + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.DONPHAN ])) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.CAMERUPT ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); @@ -1992,16 +2278,20 @@ export const trainerConfigs: TrainerConfigs = { p.gender = Gender.MALE; })), [TrainerType.MAXIE_2]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss", [], true).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SOLROCK, Species.TYPHLOSION ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.TYPHLOSION, Species.SOLROCK ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.TORKOAL, Species.NINETALES ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.NINETALES, Species.TORKOAL ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - p.abilityIndex = 2; // Drought + if (p.species.speciesId === Species.NINETALES) { + p.abilityIndex = 2; // Drought + } else if (p.species.speciesId === Species.TORKOAL) { + p.abilityIndex = 1; // Drought + } })) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SHIFTRY, Species.SCOVILLAIN ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SCOVILLAIN ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = 0; // Chlorophyll })) @@ -2020,11 +2310,17 @@ export const trainerConfigs: TrainerConfigs = { p.pokeball = PokeballType.MASTER_BALL; })), [TrainerType.ARCHIE]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss", []).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LINOONE ])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CROBAT, Species.PELIPPER ])) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LUDICOLO ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PELIPPER ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.abilityIndex = 1; // Drizzle + })) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.MUK, Species.ALOLA_MUK ])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TENTACRUEL ])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.RELICANTH, Species.WAILORD ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.WAILORD ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.QWILFISH ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.abilityIndex = 1; // Swift Swim + })) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.SHARPEDO ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); @@ -2034,19 +2330,20 @@ export const trainerConfigs: TrainerConfigs = { p.gender = Gender.MALE; })), [TrainerType.ARCHIE_2]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss", [], true).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.EMPOLEON, Species.LUDICOLO ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LUDICOLO, Species.EMPOLEON ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; })) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.POLITOED, Species.PELIPPER ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - p.abilityIndex = 2; // Drizzle - })) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.BEARTIC, Species.ARMALDO ], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.abilityIndex = 2; // Swift Swim + if (p.species.speciesId === Species.POLITOED) { + p.abilityIndex = 2; // Drizzle + } else if (p.species.speciesId === Species.PELIPPER) { + p.abilityIndex = 1; // Drizzle + } })) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.DHELMISE ])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.OVERQWIL ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = 1; // Swift Swim @@ -2067,8 +2364,8 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.CYRUS]: new TrainerConfig(++t).setName("Cyrus").initForEvilTeamLeader("Galactic Boss", []).setMixedBattleBgm("battle_galactic_boss").setVictoryBgm("victory_team_plasma") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GYARADOS ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HONCHKROW, Species.HISUI_BRAVIARY ])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.CROBAT, Species.GLISCOR ])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.AZELF, Species.UXIE, Species.MESPRIT ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.MAGNEZONE ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.UXIE, Species.MESPRIT, Species.AZELF ])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.HOUNDOOM ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; @@ -2082,35 +2379,35 @@ export const trainerConfigs: TrainerConfigs = { p.gender = Gender.MALE; })), [TrainerType.CYRUS_2]: new TrainerConfig(++t).setName("Cyrus").initForEvilTeamLeader("Galactic Boss", [], true).setMixedBattleBgm("battle_galactic_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.AZELF, Species.UXIE, Species.MESPRIT ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CROBAT ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ELECTRODE, Species.HISUI_ELECTRODE ])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SALAMENCE, Species.ROARING_MOON ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MAGNEZONE ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.UXIE, Species.MESPRIT, Species.AZELF ])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.HOUNDOOM ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.formIndex = 1; // Mega Houndoom p.generateName(); })) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.WEAVILE, Species.SNEASLER ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.WEAVILE ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.gender = Gender.MALE; })) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.DARKRAI ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.DIALGA, Species.PALKIA ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; })), [TrainerType.GHETSIS]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss", []).setMixedBattleBgm("battle_plasma_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.COFAGRIGUS, Species.RUNERIGUS ])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BOUFFALANT ])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SEISMITOAD, Species.CARRACOSTA ])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.EELEKTROSS, Species.GALVANTULA ])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.VOLCARONA ])) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.COFAGRIGUS ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.SEISMITOAD ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.GALVANTULA, Species.EELEKTROSS ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.DRAPION, Species.TOXICROAK ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.KINGAMBIT ])) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.HYDREIGON ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); @@ -2118,19 +2415,17 @@ export const trainerConfigs: TrainerConfigs = { p.gender = Gender.MALE; })), [TrainerType.GHETSIS_2]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss", [], true).setMixedBattleBgm("battle_plasma_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GENESECT ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.RUNERIGUS ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.ULTRA_BALL; - p.formIndex = Utils.randSeedInt(4, 1); // Shock, Burn, Chill, or Douse Drive })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BASCULEGION, Species.JELLICENT ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.JELLICENT, Species.BASCULEGION ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.formIndex = 0; })) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.KINGAMBIT ])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.VOLCARONA, Species.SLITHER_WING ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.VOLCARONA, Species.IRON_MOTH ])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.HYDREIGON, Species.IRON_JUGULIS ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); @@ -2153,8 +2448,11 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; })) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.CLAWITZER, Species.DRAGALGE ])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.HELIOLISK, Species.MALAMAR ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.DRAGALGE, Species.CLAWITZER ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GALLADE ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.abilityIndex = 1; // Sharpness + })) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GYARADOS ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); @@ -2164,17 +2462,17 @@ export const trainerConfigs: TrainerConfigs = { p.gender = Gender.MALE; })), [TrainerType.LYSANDRE_2]: new TrainerConfig(++t).setName("Lysandre").initForEvilTeamLeader("Flare Boss", [], true).setMixedBattleBgm("battle_flare_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SCREAM_TAIL, Species.FLUTTER_MANE ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PYROAR ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); - p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.ULTRA_BALL; - })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PYROAR ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; })) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.IRON_MOTH ])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GOODRA, Species.HISUI_GOODRA ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.DRAGALGE, Species.CLAWITZER ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.AEGISLASH, Species.HISUI_GOODRA ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.IRON_VALIANT ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ROGUE_BALL; + })) .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GYARADOS ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); @@ -2183,10 +2481,11 @@ export const trainerConfigs: TrainerConfigs = { p.generateName(); p.gender = Gender.MALE; })) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.YVELTAL ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.ZYGARDE ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; + p.formIndex = 0; // 50% Forme, Aura Break })), [TrainerType.LUSAMINE]: new TrainerConfig(++t).setName("Lusamine").initForEvilTeamLeader("Aether Boss", []).setMixedBattleBgm("battle_aether_boss").setVictoryBgm("victory_team_plasma") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CLEFABLE ], TrainerSlot.TRAINER, true, p => { @@ -2203,46 +2502,51 @@ export const trainerConfigs: TrainerConfigs = { p.pokeball = PokeballType.ROGUE_BALL; })), [TrainerType.LUSAMINE_2]: new TrainerConfig(++t).setName("Lusamine").initForEvilTeamLeader("Aether Boss", [], true).setMixedBattleBgm("battle_aether_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.NIHILEGO ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CLEFABLE ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); - p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.ROGUE_BALL; - })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MILOTIC, Species.PRIMARINA ])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.CLEFABLE ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.gender = Gender.FEMALE; })) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.STAKATAKA, Species.CELESTEELA, Species.GUZZLORD ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MILOTIC, Species.PRIMARINA ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SILVALLY ], TrainerSlot.TRAINER, true, p => { + p.formIndex = Utils.randSeedInt(18); // Random Silvally Form + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ROGUE_BALL; + if (!p.moveset.some(move => !Utils.isNullOrUndefined(move) && move.moveId === Moves.MULTI_ATTACK)) { // Check if Multi Attack is in the moveset, if not, replace the first move with Multi Attack. + p.moveset[0] = new PokemonMove(Moves.MULTI_ATTACK); + } + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.PHEROMOSA ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ROGUE_BALL; })) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.PHEROMOSA ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.NIHILEGO ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ROGUE_BALL; })) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.NECROZMA ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); + p.formIndex = 2; // Dawn Wings p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; })), [TrainerType.GUZMA]: new TrainerConfig(++t).setName("Guzma").initForEvilTeamLeader("Skull Boss", []).setMixedBattleBgm("battle_skull_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LOKIX, Species.YANMEGA ], TrainerSlot.TRAINER, true, p => { - //Tinted Lens Lokix, Tinted Lens Yanmega - if (p.species.speciesId === Species.LOKIX) { - p.abilityIndex = 2; - } else if (p.species.speciesId === Species.YANMEGA) { - p.abilityIndex = 1; + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.YANMEGA, Species.LOKIX ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + if (p.species.speciesId === Species.YANMEGA) { + p.abilityIndex = 1; // Tinted Lens + } else if (p.species.speciesId === Species.LOKIX) { + p.abilityIndex = 2; // Tinted Lens } })) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HERACROSS ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SCIZOR, Species.KLEAVOR ], TrainerSlot.TRAINER, true, p => { - //Technician Scizor, Sharpness Kleavor + p.generateAndPopulateMoveset(); if (p.species.speciesId === Species.SCIZOR) { - p.abilityIndex = 1; + p.abilityIndex = 1; // Technician } else if (p.species.speciesId === Species.KLEAVOR) { - p.abilityIndex = 2; + p.abilityIndex = 2; // Sharpness } })) .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GALVANTULA, Species.VIKAVOLT ])) @@ -2256,49 +2560,48 @@ export const trainerConfigs: TrainerConfigs = { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.gender = Gender.MALE; - p.pokeball = PokeballType.ULTRA_BALL; })), [TrainerType.GUZMA_2]: new TrainerConfig(++t).setName("Guzma").initForEvilTeamLeader("Skull Boss", [], true).setMixedBattleBgm("battle_skull_boss").setVictoryBgm("victory_team_plasma") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GOLISOPOD ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); - p.abilityIndex = 2; //Anticipation + p.abilityIndex = 2; // Anticipation p.gender = Gender.MALE; - p.pokeball = PokeballType.ULTRA_BALL; })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.SCIZOR, Species.KLEAVOR ], TrainerSlot.TRAINER, true, p => { - //Technician Scizor, Sharpness Kleavor - if (p.species.speciesId === Species.SCIZOR) { - p.abilityIndex = 1; - } else if (p.species.speciesId === Species.KLEAVOR) { - p.abilityIndex = 2; - } - })) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.HISUI_SAMUROTT, Species.CRAWDAUNT ], TrainerSlot.TRAINER, true, p => { - p.abilityIndex = 2; //Sharpness Hisui Samurott, Adaptability Crawdaunt - })) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.BUZZWOLE ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BUZZWOLE ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ROGUE_BALL; })) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.XURKITREE ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.CRAWDAUNT, Species.HISUI_SAMUROTT ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.abilityIndex = 2; // Sharpness Hisui Samurott, Adaptability Crawdaunt + })) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.XURKITREE ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.ROGUE_BALL; + })) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GENESECT ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.ROGUE_BALL; + p.pokeball = PokeballType.ULTRA_BALL; + p.formIndex = Utils.randSeedInt(4, 1); // Shock, Burn, Chill, or Douse Drive + if (!p.moveset.some(move => !Utils.isNullOrUndefined(move) && move.moveId === Moves.TECHNO_BLAST)) { // Check if Techno Blast is in the moveset, if not, replace the first move with Techno Blast. + p.moveset[0] = new PokemonMove(Moves.TECHNO_BLAST); + } })) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.PINSIR ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); - p.formIndex = 1; + p.formIndex = 1; // Mega Pinsir p.generateAndPopulateMoveset(); p.generateName(); p.pokeball = PokeballType.ULTRA_BALL; })), [TrainerType.ROSE]: new TrainerConfig(++t).setName("Rose").initForEvilTeamLeader("Macro Boss", []).setMixedBattleBgm("battle_macro_boss").setVictoryBgm("victory_team_plasma") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ARCHALUDON ])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.FERROTHORN, Species.ESCAVALIER ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ESCAVALIER, Species.FERROTHORN ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SIRFETCHD, Species.MR_RIME ])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.CORVIKNIGHT ])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.PERRSERKER, Species.KLINKLANG ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.KLINKLANG, Species.PERRSERKER ])) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.COPPERAJAH ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); @@ -2313,7 +2616,7 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); })) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.AEGISLASH, Species.GHOLDENGO ])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.DRACOVISH, Species.DRACOZOLT ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.DRACOZOLT, Species.DRACOVISH ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = 1; //Strong Jaw Dracovish, Hustle Dracozolt })) @@ -2332,16 +2635,10 @@ export const trainerConfigs: TrainerConfigs = { p.gender = Gender.FEMALE; })), [TrainerType.PENNY]: new TrainerConfig(++t).setName("Cassiopeia").initForEvilTeamLeader("Star Boss", []).setMixedBattleBgm("battle_star_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VAPOREON, Species.JOLTEON, Species.FLAREON ])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ESPEON, Species.UMBREON ], TrainerSlot.TRAINER, true, p => { - p.abilityIndex = 2; // Magic Bounce Espeon, Inner Focus Umbreon - p.generateAndPopulateMoveset(); - })) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.LEAFEON, Species.GLACEON ])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.ROTOM ], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.formIndex = Utils.randSeedInt(5, 1); // Heat, Wash, Frost, Fan, or Mow - })) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.JOLTEON, Species.LEAFEON ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.VAPOREON, Species.UMBREON ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.ESPEON, Species.GLACEON ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.FLAREON ])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 2; // Pixilate p.generateAndPopulateMoveset(); @@ -2365,28 +2662,28 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.gender = Gender.FEMALE; })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ENTEI, Species.RAIKOU, Species.SUICUNE ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ROTOM ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.ULTRA_BALL; + p.formIndex = Utils.randSeedInt(5, 1); // Heat, Wash, Frost, Fan, or Mow })) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WALKING_WAKE, Species.GOUGING_FIRE, Species.RAGING_BOLT ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.RAIKOU, Species.ENTEI, Species.SUICUNE ])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => { - p.formIndex = Utils.randSeedInt(5, 1); //Random Starmobile form + p.formIndex = Utils.randSeedInt(5, 1); // Random Starmobile form p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ROGUE_BALL; })) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.EEVEE ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.ZAMAZENTA ], TrainerSlot.TRAINER, true, p => { + p.setBoss(true, 2); + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + })) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.EEVEE ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.formIndex = 2; p.generateName(); p.pokeball = PokeballType.ULTRA_BALL; })) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.ZAMAZENTA ], TrainerSlot.TRAINER, true, p => { - p.setBoss(true, 2); - p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.MASTER_BALL; - })) .setGenModifiersFunc(party => { const teraPokemon = party[0]; return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; //TODO: is the bang correct? diff --git a/src/data/trainer-names.ts b/src/data/trainer-names.ts index d075b7121f2..8b0091d4398 100644 --- a/src/data/trainer-names.ts +++ b/src/data/trainer-names.ts @@ -16,7 +16,7 @@ class TrainerNameConfig { } interface TrainerNameConfigs { - [key: integer]: TrainerNameConfig + [key: number]: TrainerNameConfig } // used in a commented code diff --git a/src/data/type.ts b/src/data/type.ts index 6170eadc91e..498394bf90e 100644 --- a/src/data/type.ts +++ b/src/data/type.ts @@ -313,7 +313,7 @@ export function getTypeDamageMultiplierColor(multiplier: TypeDamageMultiplier, s } } -export function getTypeRgb(type: Type): [ integer, integer, integer ] { +export function getTypeRgb(type: Type): [ number, number, number ] { switch (type) { case Type.NORMAL: return [ 168, 168, 120 ]; diff --git a/src/data/variant.ts b/src/data/variant.ts index 13869635f1e..13c11b0bb40 100644 --- a/src/data/variant.ts +++ b/src/data/variant.ts @@ -8,7 +8,7 @@ export const variantData: any = {}; export const variantColorCache = {}; -export function getVariantTint(variant: Variant): integer { +export function getVariantTint(variant: Variant): number { switch (variant) { case 0: return 0xf8c020; @@ -19,7 +19,7 @@ export function getVariantTint(variant: Variant): integer { } } -export function getVariantIcon(variant: Variant): integer { +export function getVariantIcon(variant: Variant): number { switch (variant) { case 0: return VariantTier.STANDARD; diff --git a/src/data/weather.ts b/src/data/weather.ts index 7bba698f9b4..0c90f381130 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -14,9 +14,9 @@ import type { Arena } from "#app/field/arena"; export class Weather { public weatherType: WeatherType; - public turnsLeft: integer; + public turnsLeft: number; - constructor(weatherType: WeatherType, turnsLeft?: integer) { + constructor(weatherType: WeatherType, turnsLeft?: number) { this.weatherType = weatherType; this.turnsLeft = !this.isImmutable() ? turnsLeft || 0 : 0; } @@ -246,7 +246,7 @@ export function getTerrainBlockMessage(pokemon: Pokemon, terrainType: TerrainTyp export interface WeatherPoolEntry { weatherType: WeatherType; - weight: integer; + weight: number; } export function getRandomWeatherType(arena: Arena): WeatherType { diff --git a/src/enums/trainer-type.ts b/src/enums/trainer-type.ts index 708faf69196..e22dc5d81c7 100644 --- a/src/enums/trainer-type.ts +++ b/src/enums/trainer-type.ts @@ -68,7 +68,7 @@ export enum TrainerType { SATURN, PLASMA_GRUNT, ZINZOLIN, - ROOD, + COLRESS, FLARE_GRUNT, BRYONY, XEROSIC, @@ -243,8 +243,10 @@ export enum TrainerType { ALDER, IRIS, DIANTHA, + KUKUI, HAU, LEON, + MUSTARD, GEETA, NEMONA, KIERAN, diff --git a/src/events/egg.ts b/src/events/egg.ts index b30c37a25e8..dc3d2b55ffe 100644 --- a/src/events/egg.ts +++ b/src/events/egg.ts @@ -12,7 +12,7 @@ export enum EggEventType { */ export class EggCountChangedEvent extends Event { /** The updated egg count. */ - public eggCount: integer; + public eggCount: number; constructor(eggCount: number) { super(EggEventType.EGG_COUNT_CHANGED); diff --git a/src/field/anims.ts b/src/field/anims.ts index f96427326b5..9ffaae59bbc 100644 --- a/src/field/anims.ts +++ b/src/field/anims.ts @@ -34,7 +34,7 @@ function doDefaultPbOpenParticles(x: number, y: number, radius: number) { }); } - const addParticle = (index: integer) => { + const addParticle = (index: number) => { const particle = globalScene.add.sprite(x, y, "pb_open_particle"); globalScene.field.add(particle); const angle = index * 45; @@ -68,7 +68,7 @@ function doDefaultPbOpenParticles(x: number, y: number, radius: number) { }); } -function doUbOpenParticles(x: number, y: number, frameIndex: integer) { +function doUbOpenParticles(x: number, y: number, frameIndex: number) { const particles: Phaser.GameObjects.Image[] = []; for (let i = 0; i < 10; i++) { particles.push(doFanOutParticle(i * 25, x, y, 1, 1, 5, frameIndex)); @@ -110,7 +110,7 @@ function doMbOpenParticles(x: number, y: number) { } } -function doFanOutParticle(trigIndex: integer, x: integer, y: integer, xSpeed: integer, ySpeed: integer, angle: integer, frameIndex: integer): Phaser.GameObjects.Image { +function doFanOutParticle(trigIndex: number, x: number, y: number, xSpeed: number, ySpeed: number, angle: number, frameIndex: number): Phaser.GameObjects.Image { let f = 0; const particle = globalScene.add.image(x, y, "pb_particles", `${frameIndex}.png`); @@ -179,11 +179,11 @@ export function addPokeballCaptureStars(pokeball: Phaser.GameObjects.Sprite): vo new Array(3).fill(null).map(() => addParticle()); } -export function sin(index: integer, amplitude: integer): number { +export function sin(index: number, amplitude: number): number { return amplitude * Math.sin(index * (Math.PI / 128)); } -export function cos(index: integer, amplitude: integer): number { +export function cos(index: number, amplitude: number): number { return amplitude * Math.cos(index * (Math.PI / 128)); } diff --git a/src/field/arena.ts b/src/field/arena.ts index deeb261a491..acdf6171474 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -86,7 +86,7 @@ export class Arena { } } - randomSpecies(waveIndex: integer, level: integer, attempt?: integer, luckValue?: integer, isBoss?: boolean): PokemonSpecies { + randomSpecies(waveIndex: number, level: number, attempt?: number, luckValue?: number, isBoss?: boolean): PokemonSpecies { const overrideSpecies = globalScene.gameMode.getOverrideSpecies(waveIndex); if (overrideSpecies) { return overrideSpecies; @@ -167,7 +167,7 @@ export class Arena { return ret; } - randomTrainerType(waveIndex: integer, isBoss: boolean = false): TrainerType { + randomTrainerType(waveIndex: number, isBoss: boolean = false): TrainerType { const isTrainerBoss = !!this.trainerPool[BiomePoolTier.BOSS].length && (globalScene.gameMode.isTrainerBoss(waveIndex, this.biomeType, globalScene.offsetGym) || isBoss); console.log(isBoss, this.trainerPool); @@ -184,7 +184,7 @@ export class Arena { return !tierPool.length ? TrainerType.BREEDER : tierPool[Utils.randSeedInt(tierPool.length)]; } - getSpeciesFormIndex(species: PokemonSpecies): integer { + getSpeciesFormIndex(species: PokemonSpecies): number { switch (species.speciesId) { case Species.BURMY: case Species.WORMADAM: @@ -372,7 +372,7 @@ export class Arena { * Gets the denominator for the chance for a trainer spawn * @returns n where 1/n is the chance of a trainer battle */ - getTrainerChance(): integer { + getTrainerChance(): number { switch (this.biomeType) { case Biome.METROPOLIS: return 2; @@ -457,10 +457,10 @@ export class Arena { } } - overrideTint(): [integer, integer, integer] { + overrideTint(): [number, number, number] { switch (Overrides.ARENA_TINT_OVERRIDE) { case TimeOfDay.DUSK: - return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer]; + return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [number, number, number]; break; case (TimeOfDay.NIGHT): return [ 64, 64, 64 ]; @@ -473,7 +473,7 @@ export class Arena { } } - getDayTint(): [integer, integer, integer] { + getDayTint(): [number, number, number] { if (Overrides.ARENA_TINT_OVERRIDE !== null) { return this.overrideTint(); } @@ -485,7 +485,7 @@ export class Arena { } } - getDuskTint(): [integer, integer, integer] { + getDuskTint(): [number, number, number] { if (Overrides.ARENA_TINT_OVERRIDE) { return this.overrideTint(); } @@ -495,11 +495,11 @@ export class Arena { switch (this.biomeType) { default: - return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer]; + return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [number, number, number]; } } - getNightTint(): [integer, integer, integer] { + getNightTint(): [number, number, number] { if (Overrides.ARENA_TINT_OVERRIDE) { return this.overrideTint(); } @@ -813,7 +813,7 @@ export function getBiomeHasProps(biomeType: Biome): boolean { export class ArenaBase extends Phaser.GameObjects.Container { public player: boolean; public biome: Biome; - public propValue: integer; + public propValue: number; public base: Phaser.GameObjects.Sprite; public props: Phaser.GameObjects.Sprite[]; @@ -834,7 +834,7 @@ export class ArenaBase extends Phaser.GameObjects.Container { }) : []; } - setBiome(biome: Biome, propValue?: integer): void { + setBiome(biome: Biome, propValue?: number): void { const hasProps = getBiomeHasProps(biome); const biomeKey = getBiomeKey(biome); const baseKey = `${biomeKey}_${this.player ? "a" : "b"}`; diff --git a/src/field/damage-number-handler.ts b/src/field/damage-number-handler.ts index 57b9d6990ca..1551edc9697 100644 --- a/src/field/damage-number-handler.ts +++ b/src/field/damage-number-handler.ts @@ -15,7 +15,7 @@ export default class DamageNumberHandler { this.damageNumbers = new Map(); } - add(target: Pokemon, amount: integer, result: DamageResult | HitResult.HEAL = HitResult.EFFECTIVE, critical: boolean = false): void { + add(target: Pokemon, amount: number, result: DamageResult | HitResult.HEAL = HitResult.EFFECTIVE, critical: boolean = false): void { if (!globalScene?.damageNumbersMode) { return; } diff --git a/src/field/mystery-encounter-intro.ts b/src/field/mystery-encounter-intro.ts index 0110dabc7a9..1ea8f16e8f7 100644 --- a/src/field/mystery-encounter-intro.ts +++ b/src/field/mystery-encounter-intro.ts @@ -422,7 +422,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con * @param duration * @param ease */ - private tint(sprite, color: number, alpha?: number, duration?: integer, ease?: string): void { + private tint(sprite, color: number, alpha?: number, duration?: number, ease?: string): void { // const tintSprites = this.getTintSprites(); sprite.setTintFill(color); sprite.setVisible(true); @@ -448,7 +448,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con * @param duration * @param ease */ - tintAll(color: number, alpha?: number, duration?: integer, ease?: string): void { + tintAll(color: number, alpha?: number, duration?: number, ease?: string): void { const tintSprites = this.getTintSprites(); tintSprites.map(tintSprite => { this.tint(tintSprite, color, alpha, duration, ease); @@ -461,7 +461,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con * @param duration * @param ease */ - private untint(sprite, duration: integer, ease?: string): void { + private untint(sprite, duration: number, ease?: string): void { if (duration) { globalScene.tweens.add({ targets: sprite, @@ -485,7 +485,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con * @param duration * @param ease */ - untintAll(duration: integer, ease?: string): void { + untintAll(duration: number, ease?: string): void { const tintSprites = this.getTintSprites(); tintSprites.map(tintSprite => { this.untint(tintSprite, duration, ease); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 5b7cafeefb8..ebf665ce5e6 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -7,7 +7,7 @@ import { variantColorCache } from "#app/data/variant"; import { variantData } from "#app/data/variant"; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "#app/ui/battle-info"; import type Move from "#app/data/move"; -import { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget, CombinedPledgeStabBoostAttr, VariableMoveTypeChartAttr } from "#app/data/move"; +import { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget, CombinedPledgeStabBoostAttr, VariableMoveTypeChartAttr, HpSplitAttr } from "#app/data/move"; import type { PokemonSpeciesForm } from "#app/data/pokemon-species"; import { default as PokemonSpecies, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; import { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters"; @@ -99,45 +99,45 @@ export enum FieldPosition { } export default abstract class Pokemon extends Phaser.GameObjects.Container { - public id: integer; + public id: number; public name: string; public nickname: string; public species: PokemonSpecies; - public formIndex: integer; - public abilityIndex: integer; + public formIndex: number; + public abilityIndex: number; public passive: boolean; public shiny: boolean; public variant: Variant; public pokeball: PokeballType; protected battleInfo: BattleInfo; - public level: integer; - public exp: integer; - public levelExp: integer; + public level: number; + public exp: number; + public levelExp: number; public gender: Gender; - public hp: integer; - public stats: integer[]; - public ivs: integer[]; + public hp: number; + public stats: number[]; + public ivs: number[]; public nature: Nature; public moveset: (PokemonMove | null)[]; public status: Status | null; - public friendship: integer; - public metLevel: integer; + public friendship: number; + public metLevel: number; public metBiome: Biome | -1; public metSpecies: Species; public metWave: number; - public luck: integer; + public luck: number; public pauseEvolutions: boolean; public pokerus: boolean; public switchOutStatus: boolean; - public evoCounter: integer; + public evoCounter: number; public fusionSpecies: PokemonSpecies | null; - public fusionFormIndex: integer; - public fusionAbilityIndex: integer; + public fusionFormIndex: number; + public fusionAbilityIndex: number; public fusionShiny: boolean; public fusionVariant: Variant; public fusionGender: Gender; - public fusionLuck: integer; + public fusionLuck: number; public fusionCustomPokemonData: CustomPokemonData | null; private summonDataPrimer: PokemonSummonData | null; @@ -160,7 +160,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { private shinySparkle: Phaser.GameObjects.Sprite; - constructor(x: number, y: number, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) { + constructor(x: number, y: number, species: PokemonSpecies, level: number, abilityIndex?: number, formIndex?: number, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: number[], nature?: Nature, dataSource?: Pokemon | PokemonData) { super(globalScene, x, y); if (!species.isObtainable() && this.isPlayer()) { @@ -423,7 +423,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { abstract hasTrainer(): boolean; - abstract getFieldIndex(): integer; + abstract getFieldIndex(): number; abstract getBattlerIndex(): BattlerIndex; @@ -781,7 +781,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - setFieldPosition(fieldPosition: FieldPosition, duration?: integer): Promise { + setFieldPosition(fieldPosition: FieldPosition, duration?: number): Promise { return new Promise(resolve => { if (fieldPosition === this.fieldPosition) { resolve(); @@ -949,7 +949,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param simulated if `true`, nullifies any effects that produce any changes to game state from triggering * @returns the final in-battle value of a stat */ - getEffectiveStat(stat: EffectiveStat, opponent?: Pokemon, move?: Move, ignoreAbility: boolean = false, ignoreOppAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true): integer { + getEffectiveStat(stat: EffectiveStat, opponent?: Pokemon, move?: Move, ignoreAbility: boolean = false, ignoreOppAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true): number { const statValue = new Utils.NumberHolder(this.getStat(stat, false)); globalScene.applyModifiers(StatBoosterModifier, this.isPlayer(), this, stat, statValue); @@ -1103,12 +1103,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.hp >= this.getMaxHp(); } - getMaxHp(): integer { + getMaxHp(): number { return this.getStat(Stat.HP); } /** Returns the amount of hp currently missing from this {@linkcode Pokemon} (max - current) */ - getInverseHp(): integer { + getInverseHp(): number { return this.getMaxHp() - this.hp; } @@ -1153,7 +1153,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return !this.isFusion() ? this.variant : Math.max(this.variant, this.fusionVariant) as Variant; } - getLuck(): integer { + getLuck(): number { return this.luck + (this.isFusion() ? this.fusionLuck : 0); } @@ -1259,52 +1259,39 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!types.length || !includeTeraType) { if (!ignoreOverride && this.summonData?.types && this.summonData.types.length > 0) { this.summonData.types.forEach(t => types.push(t)); - } else if (this.customPokemonData.types && this.customPokemonData.types.length > 0) { - // "Permanent" override for a Pokemon's normal types, currently only used by Mystery Encounters - types.push(this.customPokemonData.types[0]); - - // Fusing a Pokemon onto something with "permanently changed" types will still apply the fusion's types as normal - const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride); - if (fusionSpeciesForm) { - // Check if the fusion Pokemon also had "permanently changed" types - const fusionMETypes = this.fusionCustomPokemonData?.types; - if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) { - types.push(fusionMETypes[1]); - } else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) { - types.push(fusionMETypes[0]); - } else if (fusionSpeciesForm.type2 !== null && fusionSpeciesForm.type2 !== types[0]) { - types.push(fusionSpeciesForm.type2); - } else if (fusionSpeciesForm.type1 !== types[0]) { - types.push(fusionSpeciesForm.type1); - } - } - - if (types.length === 1 && this.customPokemonData.types.length >= 2) { - types.push(this.customPokemonData.types[1]); - } } else { const speciesForm = this.getSpeciesForm(ignoreOverride); - - types.push(speciesForm.type1); - const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride); + const customTypes = this.customPokemonData.types?.length > 0; + + // First type, checking for "permanently changed" types from ME + const firstType = (customTypes && this.customPokemonData.types[0] !== Type.UNKNOWN) ? this.customPokemonData.types[0] : speciesForm.type1; + types.push(firstType); + + // Second type + let secondType: Type = Type.UNKNOWN; + if (fusionSpeciesForm) { - // Check if the fusion Pokemon also had "permanently changed" types - // Otherwise, use standard fusion type logic - const fusionMETypes = this.fusionCustomPokemonData?.types; - if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) { - types.push(fusionMETypes[1]); - } else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) { - types.push(fusionMETypes[0]); - } else if (fusionSpeciesForm.type2 !== null && fusionSpeciesForm.type2 !== speciesForm.type1) { - types.push(fusionSpeciesForm.type2); - } else if (fusionSpeciesForm.type1 !== speciesForm.type1) { - types.push(fusionSpeciesForm.type1); + // Check if the fusion Pokemon also has permanent changes from ME when determining the fusion types + const fusionType1 = (this.fusionCustomPokemonData?.types && this.fusionCustomPokemonData.types.length > 0 && this.fusionCustomPokemonData.types[0] !== Type.UNKNOWN) + ? this.fusionCustomPokemonData.types[0] : fusionSpeciesForm.type1; + const fusionType2 = (this.fusionCustomPokemonData?.types && this.fusionCustomPokemonData.types.length > 1 && this.fusionCustomPokemonData.types[1] !== Type.UNKNOWN) + ? this.fusionCustomPokemonData.types[1] : fusionSpeciesForm.type2; + + // Assign second type if the fusion can provide one + if (fusionType2 !== null && fusionType2 !== types[0]) { + secondType = fusionType2; + } else if (fusionType1 !== types[0]) { + secondType = fusionType1; } + } else { + // If not a fusion, just get the second type from the species, checking for permanent changes from ME + secondType = (customTypes && this.customPokemonData.types.length > 1 && this.customPokemonData.types[1] !== Type.UNKNOWN) + ? this.customPokemonData.types[1] : (speciesForm.type2 ?? Type.UNKNOWN); } - if (types.length === 1 && speciesForm.type2 !== null) { - types.push(speciesForm.type2); + if (secondType !== Type.UNKNOWN) { + types.push(secondType); } } } @@ -1829,13 +1816,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { /** * Gets all level up moves in a given range for a particular pokemon. - * @param {integer} startingLevel Don't include moves below this level + * @param {number} startingLevel Don't include moves below this level * @param {boolean} includeEvolutionMoves Whether to include evolution moves * @param {boolean} simulateEvolutionChain Whether to include moves from prior evolutions * @param {boolean} includeRelearnerMoves Whether to include moves that would require a relearner. Note the move relearner inherently allows evolution moves * @returns {LevelMoves} A list of moves and the levels they can be learned at */ - getLevelMoves(startingLevel?: integer, includeEvolutionMoves: boolean = false, simulateEvolutionChain: boolean = false, includeRelearnerMoves: boolean = false, learnSituation: LearnMoveSituation = LearnMoveSituation.MISC): LevelMoves { + getLevelMoves(startingLevel?: number, includeEvolutionMoves: boolean = false, simulateEvolutionChain: boolean = false, includeRelearnerMoves: boolean = false, learnSituation: LearnMoveSituation = LearnMoveSituation.MISC): LevelMoves { const ret: LevelMoves = []; let levelMoves: LevelMoves = []; if (!startingLevel) { @@ -1875,7 +1862,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } } - levelMoves.sort((lma: [integer, integer], lmb: [integer, integer]) => lma[0] > lmb[0] ? 1 : lma[0] < lmb[0] ? -1 : 0); + levelMoves.sort((lma: [number, number], lmb: [number, number]) => lma[0] > lmb[0] ? 1 : lma[0] < lmb[0] ? -1 : 0); /** @@ -1932,7 +1919,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return speciesEggMoves[this.getSpeciesForm().getRootSpeciesId()]; } - setMove(moveIndex: integer, moveId: Moves): void { + setMove(moveIndex: number, moveId: Moves): void { const move = moveId ? new PokemonMove(moveId) : null; this.moveset[moveIndex] = move; if (this.summonData?.moveset) { @@ -2237,9 +2224,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - // Bosses never get self ko moves + // Bosses never get self ko moves or Pain Split if (this.isBoss()) { movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttr)); + movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(HpSplitAttr)); } movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttrOnHit)); if (this.hasTrainer()) { @@ -2338,7 +2326,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - public trySelectMove(moveIndex: integer, ignorePp?: boolean): boolean { + public trySelectMove(moveIndex: number, ignorePp?: boolean): boolean { const move = this.getMoveset().length > moveIndex ? this.getMoveset()[moveIndex] : null; @@ -2424,7 +2412,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param exp The amount of experience to add * @param ignoreLevelCap Whether to ignore level caps when adding experience (defaults to false) */ - addExp(exp: integer, ignoreLevelCap: boolean = false) { + addExp(exp: number, ignoreLevelCap: boolean = false) { const maxExpLevel = globalScene.getMaxExpLevel(ignoreLevelCap); const initialExp = this.exp; this.exp += exp; @@ -2447,7 +2435,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.isPlayer() !== target.isPlayer(); } - getOpponent(targetIndex: integer): Pokemon | null { + getOpponent(targetIndex: number): Pokemon | null { const ret = this.getOpponents()[targetIndex]; if (ret.summonData) { return ret; @@ -3004,7 +2992,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param ignoreFaintPhase flag on wheter to add FaintPhase if pokemon after applying damage faints * @returns integer representing damage */ - damage(damage: integer, ignoreSegments: boolean = false, preventEndure: boolean = false, ignoreFaintPhase: boolean = false): integer { + damage(damage: number, ignoreSegments: boolean = false, preventEndure: boolean = false, ignoreFaintPhase: boolean = false): number { if (this.isFainted()) { return 0; } @@ -3074,7 +3062,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return damage; } - heal(amount: integer): integer { + heal(amount: number): number { const healAmount = Math.min(amount, this.getMaxHp() - this.hp); this.hp += healAmount; return healAmount; @@ -3105,7 +3093,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return !cancelled.value; } - addTag(tagType: BattlerTagType, turnCount: integer = 0, sourceMove?: Moves, sourceId?: integer): boolean { + addTag(tagType: BattlerTagType, turnCount: number = 0, sourceMove?: Moves, sourceId?: number): boolean { const existingTag = this.getTag(tagType); if (existingTag) { existingTag.onOverlap(this); @@ -3211,11 +3199,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return true; } - removeTagsBySourceId(sourceId: integer): void { + removeTagsBySourceId(sourceId: number): void { this.findAndRemoveTags(t => t.isSourceLinked() && t.sourceId === sourceId); } - transferTagsBySourceId(sourceId: integer, newSourceId: integer): void { + transferTagsBySourceId(sourceId: number, newSourceId: number): void { if (!this.summonData) { return; } @@ -3792,12 +3780,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.turnData = new PokemonTurnData(); } - getExpValue(): integer { + getExpValue(): number { // Logic to factor in victor level has been removed for balancing purposes, so the player doesn't have to focus on EXP maxxing return ((this.getSpeciesForm().getBaseExp() * this.level) / 5 + 1); } - setFrameRate(frameRate: integer) { + setFrameRate(frameRate: number) { globalScene.anims.get(this.getBattleSpriteKey()).frameRate = frameRate; try { this.getSprite().play(this.getBattleSpriteKey()); @@ -3811,7 +3799,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - tint(color: number, alpha?: number, duration?: integer, ease?: string) { + tint(color: number, alpha?: number, duration?: number, ease?: string) { const tintSprite = this.getTintSprite(); tintSprite?.setTintFill(color); tintSprite?.setVisible(true); @@ -3830,7 +3818,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - untint(duration: integer, ease?: string) { + untint(duration: number, ease?: string) { const tintSprite = this.getTintSprite(); if (duration) { @@ -3907,10 +3895,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const fusionCanvas = document.createElement("canvas"); const fusionBackCanvas = document.createElement("canvas"); - const spriteColors: integer[][] = []; + const spriteColors: number[][] = []; const pixelData: Uint8ClampedArray[] = []; - [ canvas, backCanvas, fusionCanvas, fusionBackCanvas ].forEach((canv: HTMLCanvasElement, c: integer) => { + [ canvas, backCanvas, fusionCanvas, fusionBackCanvas ].forEach((canv: HTMLCanvasElement, c: number) => { const context = canv.getContext("2d"); const frame = [ sourceFrame, sourceBackFrame, fusionFrame, fusionBackFrame ][c]; canv.width = frame.width; @@ -3925,7 +3913,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { for (let f = 0; f < 2; f++) { const variantColors = variantColorCache[!f ? spriteKey : backSpriteKey]; - const variantColorSet = new Map(); + const variantColorSet = new Map(); if (this.shiny && variantColors && variantColors[this.variant]) { Object.keys(variantColors[this.variant]).forEach(k => { variantColorSet.set(Utils.rgbaToInt(Array.from(Object.values(Utils.rgbHexToRgba(k)))), Array.from(Object.values(Utils.rgbHexToRgba(variantColors[this.variant][k])))); @@ -3957,7 +3945,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const pixelColors: number[] = []; for (let f = 0; f < 2; f++) { for (let i = 0; i < pixelData[f].length; i += 4) { - const total = pixelData[f].slice(i, i + 3).reduce((total: integer, value: integer) => total + value, 0); + const total = pixelData[f].slice(i, i + 3).reduce((total: number, value: number) => total + value, 0); if (!total) { continue; } @@ -3968,14 +3956,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const fusionPixelColors : number[] = []; for (let f = 0; f < 2; f++) { const variantColors = variantColorCache[!f ? fusionSpriteKey : fusionBackSpriteKey]; - const variantColorSet = new Map(); + const variantColorSet = new Map(); if (this.fusionShiny && variantColors && variantColors[this.fusionVariant]) { Object.keys(variantColors[this.fusionVariant]).forEach(k => { variantColorSet.set(Utils.rgbaToInt(Array.from(Object.values(Utils.rgbHexToRgba(k)))), Array.from(Object.values(Utils.rgbHexToRgba(variantColors[this.fusionVariant][k])))); }); } for (let i = 0; i < pixelData[2 + f].length; i += 4) { - const total = pixelData[2 + f].slice(i, i + 3).reduce((total: integer, value: integer) => total + value, 0); + const total = pixelData[2 + f].slice(i, i + 3).reduce((total: number, value: number) => total + value, 0); if (!total) { continue; } @@ -4010,18 +3998,18 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { fusionPaletteColors = fusionPaletteColors!; // TS compiler that fusionPaletteColors is defined! const [ palette, fusionPalette ] = [ paletteColors, fusionPaletteColors ] .map(paletteColors => { - let keys = Array.from(paletteColors.keys()).sort((a: integer, b: integer) => paletteColors.get(a)! < paletteColors.get(b)! ? 1 : -1); - let rgbaColors: Map; + let keys = Array.from(paletteColors.keys()).sort((a: number, b: number) => paletteColors.get(a)! < paletteColors.get(b)! ? 1 : -1); + let rgbaColors: Map; let hsvColors: Map; - const mappedColors = new Map(); + const mappedColors = new Map(); do { mappedColors.clear(); - rgbaColors = keys.reduce((map: Map, k: number) => { + rgbaColors = keys.reduce((map: Map, k: number) => { map.set(k, Object.values(rgbaFromArgb(k))); return map; - }, new Map()); + }, new Map()); hsvColors = Array.from(rgbaColors.keys()).reduce((map: Map, k: number) => { const rgb = rgbaColors.get(k)!.slice(0, 3); map.set(k, Utils.rgbToHsv(rgb[0], rgb[1], rgb[2])); @@ -4044,7 +4032,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - mappedColors.forEach((values: integer[], key: integer) => { + mappedColors.forEach((values: number[], key: number) => { const keyColor = rgbaColors.get(key)!; const valueColors = values.map(v => rgbaColors.get(v)!); const color = keyColor.slice(0); @@ -4059,7 +4047,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { for (let c = 0; c < 3; c++) { color[c] *= (paletteColors.get(key)! / count); - values.forEach((value: integer, i: integer) => { + values.forEach((value: number, i: number) => { if (paletteColors.has(value)) { const valueCount = paletteColors.get(value)!; color[c] += valueColors[i][c] * (valueCount / count); @@ -4079,7 +4067,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { paletteColors.set(argbFromRgba({ r: color[0], g: color[1], b: color[2], a: color[3] }), count); }); - keys = Array.from(paletteColors.keys()).sort((a: integer, b: integer) => paletteColors.get(a)! < paletteColors.get(b)! ? 1 : -1); + keys = Array.from(paletteColors.keys()).sort((a: number, b: number) => paletteColors.get(a)! < paletteColors.get(b)! ? 1 : -1); } while (mappedColors.size); return keys.map(c => Object.values(rgbaFromArgb(c))); @@ -4088,7 +4076,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const paletteDeltas: number[][] = []; - spriteColors.forEach((sc: integer[], i: integer) => { + spriteColors.forEach((sc: number[], i: number) => { paletteDeltas.push([]); for (let p = 0; p < palette.length; p++) { paletteDeltas[i].push(Utils.deltaRgb(sc, palette[p])); @@ -4131,7 +4119,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param min The minimum integer to pick, default `0` * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) */ - randSeedInt(range: integer, min: integer = 0): integer { + randSeedInt(range: number, min: number = 0): number { return globalScene.currentBattle ? globalScene.randBattleSeedInt(range, min) : Utils.randSeedInt(range, min); @@ -4143,7 +4131,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param max The maximum integer to generate * @returns a random integer between {@linkcode min} and {@linkcode max} inclusive */ - randSeedIntRange(min: integer, max: integer): integer { + randSeedIntRange(min: number, max: number): number { return this.randSeedInt((max - min) + 1, min); } @@ -4235,7 +4223,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { export class PlayerPokemon extends Pokemon { public compatibleTms: Moves[]; - constructor(species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) { + constructor(species: PokemonSpecies, level: number, abilityIndex?: number, formIndex?: number, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: number[], nature?: Nature, dataSource?: Pokemon | PokemonData) { super(106, 148, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource); if (Overrides.STATUS_OVERRIDE) { @@ -4280,7 +4268,7 @@ export class PlayerPokemon extends Pokemon { return false; } - getFieldIndex(): integer { + getFieldIndex(): number { return globalScene.getPlayerField().indexOf(this); } @@ -4337,7 +4325,7 @@ export class PlayerPokemon extends Pokemon { return new Promise(resolve => { this.leaveField(switchType === SwitchType.SWITCH); - globalScene.ui.setMode(Mode.PARTY, PartyUiMode.FAINT_SWITCH, this.getFieldIndex(), (slotIndex: integer, option: PartyOption) => { + globalScene.ui.setMode(Mode.PARTY, PartyUiMode.FAINT_SWITCH, this.getFieldIndex(), (slotIndex: number, option: PartyOption) => { if (slotIndex >= globalScene.currentBattle.getBattlerCount() && slotIndex < 6) { globalScene.prependToPhase(new SwitchSummonPhase(switchType, this.getFieldIndex(), slotIndex, false), MoveEndPhase); } @@ -4385,7 +4373,7 @@ export class PlayerPokemon extends Pokemon { */ revivalBlessing(): Promise { return new Promise(resolve => { - globalScene.ui.setMode(Mode.PARTY, PartyUiMode.REVIVAL_BLESSING, this.getFieldIndex(), (slotIndex:integer, option: PartyOption) => { + globalScene.ui.setMode(Mode.PARTY, PartyUiMode.REVIVAL_BLESSING, this.getFieldIndex(), (slotIndex:number, option: PartyOption) => { if (slotIndex >= 0 && slotIndex < 6) { const pokemon = globalScene.getPlayerParty()[slotIndex]; if (!pokemon || !pokemon.isFainted()) { @@ -4564,7 +4552,6 @@ export class PlayerPokemon extends Pokemon { changeForm(formChange: SpeciesFormChange): Promise { return new Promise(resolve => { - const previousFormIndex = this.formIndex; this.formIndex = Math.max(this.species.forms.findIndex(f => f.formKey === formChange.formKey), 0); this.generateName(); const abilityCount = this.getSpeciesForm().getAbilityCount(); @@ -4572,25 +4559,6 @@ export class PlayerPokemon extends Pokemon { this.abilityIndex = abilityCount - 1; } - // In cases where a form change updates the type of a Pokemon from its previous form (Arceus, Silvally, Castform, etc.), - // persist that type change in customPokemonData if necessary - const baseForm = this.species.forms[previousFormIndex]; - const baseFormTypes = [ baseForm.type1, baseForm.type2 ]; - if (this.customPokemonData.types.length > 0) { - if (this.getSpeciesForm().type1 !== baseFormTypes[0]) { - this.customPokemonData.types[0] = this.getSpeciesForm().type1; - } - - const type2 = this.getSpeciesForm().type2; - if (!isNullOrUndefined(type2) && type2 !== baseFormTypes[1]) { - if (this.customPokemonData.types.length > 1) { - this.customPokemonData.types[1] = type2; - } else { - this.customPokemonData.types.push(type2); - } - } - } - this.compatibleTms.splice(0, this.compatibleTms.length); this.generateCompatibleTms(); const updateAndResolve = () => { @@ -4707,12 +4675,12 @@ export class PlayerPokemon extends Pokemon { export class EnemyPokemon extends Pokemon { public trainerSlot: TrainerSlot; public aiType: AiType; - public bossSegments: integer; - public bossSegmentIndex: integer; + public bossSegments: number; + public bossSegmentIndex: number; /** To indicate if the instance was populated with a dataSource -> e.g. loaded & populated from session data */ public readonly isPopulatedFromDataSource: boolean; - constructor(species: PokemonSpecies, level: integer, trainerSlot: TrainerSlot, boss: boolean, shinyLock: boolean = false, dataSource?: PokemonData) { + constructor(species: PokemonSpecies, level: number, trainerSlot: TrainerSlot, boss: boolean, shinyLock: boolean = false, dataSource?: PokemonData) { super(236, 84, species, level, dataSource?.abilityIndex, dataSource?.formIndex, dataSource?.gender, (!shinyLock && dataSource) ? dataSource.shiny : false, (!shinyLock && dataSource) ? dataSource.variant : undefined, undefined, dataSource ? dataSource.nature : undefined, dataSource); @@ -4727,7 +4695,7 @@ export class EnemyPokemon extends Pokemon { this.status = new Status(Overrides.OPP_STATUS_OVERRIDE, 0, 4); } - if (Overrides.OPP_GENDER_OVERRIDE) { + if (Overrides.OPP_GENDER_OVERRIDE !== null) { this.gender = Overrides.OPP_GENDER_OVERRIDE; } @@ -4795,7 +4763,7 @@ export class EnemyPokemon extends Pokemon { * @param boss if the pokemon is a boss * @param bossSegments amount of boss segments (health-bar segments) */ - setBoss(boss: boolean = true, bossSegments: integer = 0): void { + setBoss(boss: boolean = true, bossSegments: number = 0): void { if (boss) { this.bossSegments = bossSegments || globalScene.getEncounterBossSegments(globalScene.currentBattle.waveIndex, this.level, this.species, true); this.bossSegmentIndex = this.bossSegments - 1; @@ -4805,7 +4773,7 @@ export class EnemyPokemon extends Pokemon { } } - generateAndPopulateMoveset(formIndex?: integer): void { + generateAndPopulateMoveset(formIndex?: number): void { switch (true) { case (this.species.speciesId === Species.SMEARGLE): this.moveset = [ @@ -4927,7 +4895,7 @@ export class EnemyPokemon extends Pokemon { const move = pokemonMove.getMove(); let moveScore = moveScores[m]; - const targetScores: integer[] = []; + const targetScores: number[] = []; for (const mt of moveTargets[move.id]) { // Prevent a target score from being calculated when the target is whoever attacks the user @@ -5067,9 +5035,9 @@ export class EnemyPokemon extends Pokemon { targetWeights = targetWeights.slice(0, benefitCutoffIndex); } - const thresholds: integer[] = []; - let totalWeight: integer = 0; - targetWeights.reduce((total: integer, w: integer) => { + const thresholds: number[] = []; + let totalWeight: number = 0; + targetWeights.reduce((total: number, w: number) => { total += w; thresholds.push(total); totalWeight = total; @@ -5082,7 +5050,7 @@ export class EnemyPokemon extends Pokemon { * is greater than that random number. */ const randValue = globalScene.randBattleSeedInt(totalWeight); - let targetIndex: integer = 0; + let targetIndex: number = 0; thresholds.every((t, i) => { if (randValue >= t) { @@ -5108,7 +5076,7 @@ export class EnemyPokemon extends Pokemon { return !!this.bossSegments; } - getBossSegmentIndex(): integer { + getBossSegmentIndex(): number { const segments = (this as EnemyPokemon).bossSegments; const segmentSize = this.getMaxHp() / segments; for (let s = segments - 1; s > 0; s--) { @@ -5121,7 +5089,7 @@ export class EnemyPokemon extends Pokemon { return 0; } - damage(damage: integer, ignoreSegments: boolean = false, preventEndure: boolean = false, ignoreFaintPhase: boolean = false): integer { + damage(damage: number, ignoreSegments: boolean = false, preventEndure: boolean = false, ignoreFaintPhase: boolean = false): number { if (this.isFainted()) { return 0; } @@ -5175,7 +5143,7 @@ export class EnemyPokemon extends Pokemon { return ret; } - canBypassBossSegments(segmentCount: integer = 1): boolean { + canBypassBossSegments(segmentCount: number = 1): boolean { if (globalScene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) { if (!this.formIndex && (this.bossSegmentIndex - segmentCount) < 1) { return false; @@ -5192,7 +5160,7 @@ export class EnemyPokemon extends Pokemon { * For Pokemon with 5 health segments or more, breaking the last two shields give +2 each * @param segmentIndex index of the segment to get down to (0 = no shield left, 1 = 1 shield left, etc.) */ - handleBossSegmentCleared(segmentIndex: integer): void { + handleBossSegmentCleared(segmentIndex: number): void { while (this.bossSegmentIndex > 0 && segmentIndex - 1 < this.bossSegmentIndex) { // Filter out already maxed out stat stages and weigh the rest based on existing stats const leftoverStats = EFFECTIVE_STATS.filter((s: EffectiveStat) => this.getStatStage(s) < 6); @@ -5232,7 +5200,7 @@ export class EnemyPokemon extends Pokemon { } } - getFieldIndex(): integer { + getFieldIndex(): number { return globalScene.getEnemyField().indexOf(this); } @@ -5469,7 +5437,7 @@ export class PokemonMove { this.ppUsed = Math.min(this.ppUsed + count, this.getMovePp()); } - getMovePp(): integer { + getMovePp(): number { return this.maxPpOverride || (this.getMove().pp + this.ppUp * Utils.toDmgValue(this.getMove().pp / 5)); } diff --git a/src/field/trainer.ts b/src/field/trainer.ts index 2b74c1e5069..65bca641163 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -33,11 +33,11 @@ export enum TrainerVariant { export default class Trainer extends Phaser.GameObjects.Container { public config: TrainerConfig; public variant: TrainerVariant; - public partyTemplateIndex: integer; + public partyTemplateIndex: number; public name: string; public partnerName: string; - constructor(trainerType: TrainerType, variant: TrainerVariant, partyTemplateIndex?: integer, name?: string, partnerName?: string, trainerConfigOverride?: TrainerConfig) { + constructor(trainerType: TrainerType, variant: TrainerVariant, partyTemplateIndex?: number, name?: string, partnerName?: string, trainerConfigOverride?: TrainerConfig) { super(globalScene, -72, 80); this.config = trainerConfigs.hasOwnProperty(trainerType) ? trainerConfigs[trainerType] @@ -214,7 +214,7 @@ export default class Trainer extends Phaser.GameObjects.Container { return this.config.partyTemplates[this.partyTemplateIndex]; } - getPartyLevels(waveIndex: integer): integer[] { + getPartyLevels(waveIndex: number): number[] { const ret: number[] = []; const partyTemplate = this.getPartyTemplate(); @@ -262,7 +262,7 @@ export default class Trainer extends Phaser.GameObjects.Container { return ret; } - genPartyMember(index: integer): EnemyPokemon { + genPartyMember(index: number): EnemyPokemon { const battle = globalScene.currentBattle; const level = battle.enemyLevels?.[index]!; // TODO: is this bang correct? @@ -381,7 +381,7 @@ export default class Trainer extends Phaser.GameObjects.Container { } - genNewPartyMemberSpecies(level: integer, strength: PartyMemberStrength, attempt?: integer): PokemonSpecies { + genNewPartyMemberSpecies(level: number, strength: PartyMemberStrength, attempt?: number): PokemonSpecies { const battle = globalScene.currentBattle; const template = this.getPartyTemplate(); @@ -462,7 +462,7 @@ export default class Trainer extends Phaser.GameObjects.Container { return currentSpecies.includes(baseSpecies) || staticSpecies.includes(baseSpecies); } - getPartyMemberMatchupScores(trainerSlot: TrainerSlot = TrainerSlot.NONE, forSwitch: boolean = false): [integer, integer][] { + getPartyMemberMatchupScores(trainerSlot: TrainerSlot = TrainerSlot.NONE, forSwitch: boolean = false): [number, number][] { if (trainerSlot && !this.isDouble()) { trainerSlot = TrainerSlot.NONE; } @@ -487,12 +487,12 @@ export default class Trainer extends Phaser.GameObjects.Container { } return [ party.indexOf(p), score ]; - }) as [integer, integer][]; + }) as [number, number][]; return partyMemberScores; } - getSortedPartyMemberMatchupScores(partyMemberScores: [integer, integer][] = this.getPartyMemberMatchupScores()) { + getSortedPartyMemberMatchupScores(partyMemberScores: [number, number][] = this.getPartyMemberMatchupScores()) { const sortedPartyMemberScores = partyMemberScores.slice(0); sortedPartyMemberScores.sort((a, b) => { const scoreA = a[1]; @@ -503,7 +503,7 @@ export default class Trainer extends Phaser.GameObjects.Container { return sortedPartyMemberScores; } - getNextSummonIndex(trainerSlot: TrainerSlot = TrainerSlot.NONE, partyMemberScores: [integer, integer][] = this.getPartyMemberMatchupScores(trainerSlot)): integer { + getNextSummonIndex(trainerSlot: TrainerSlot = TrainerSlot.NONE, partyMemberScores: [number, number][] = this.getPartyMemberMatchupScores(trainerSlot)): number { if (trainerSlot && !this.isDouble()) { trainerSlot = TrainerSlot.NONE; } @@ -513,7 +513,7 @@ export default class Trainer extends Phaser.GameObjects.Container { const maxScorePartyMemberIndexes = partyMemberScores.filter(pms => pms[1] === sortedPartyMemberScores[0][1]).map(pms => pms[0]); if (maxScorePartyMemberIndexes.length > 1) { - let rand: integer; + let rand: number; globalScene.executeWithSeedOffset(() => rand = Utils.randSeedInt(maxScorePartyMemberIndexes.length), globalScene.currentBattle.turn << 2); return maxScorePartyMemberIndexes[rand!]; } @@ -521,7 +521,7 @@ export default class Trainer extends Phaser.GameObjects.Container { return maxScorePartyMemberIndexes[0]; } - getPartyMemberModifierChanceMultiplier(index: integer): number { + getPartyMemberModifierChanceMultiplier(index: number): number { switch (this.getPartyTemplate().getStrength(index)) { case PartyMemberStrength.WEAKER: return 0.75; @@ -626,7 +626,7 @@ export default class Trainer extends Phaser.GameObjects.Container { return ret; } - tint(color: number, alpha?: number, duration?: integer, ease?: string): void { + tint(color: number, alpha?: number, duration?: number, ease?: string): void { const tintSprites = this.getTintSprites(); tintSprites.map(tintSprite => { tintSprite.setTintFill(color); @@ -647,7 +647,7 @@ export default class Trainer extends Phaser.GameObjects.Container { }); } - untint(duration: integer, ease?: string): void { + untint(duration: number, ease?: string): void { const tintSprites = this.getTintSprites(); tintSprites.map(tintSprite => { if (duration) { diff --git a/src/game-mode.ts b/src/game-mode.ts index 78a65a54890..1da125ea55a 100644 --- a/src/game-mode.ts +++ b/src/game-mode.ts @@ -91,7 +91,7 @@ export class GameMode implements GameModeConfig { * - 20 for Daily Runs * - 5 for all other modes */ - getStartingLevel(): integer { + getStartingLevel(): number { if (Overrides.STARTING_LEVEL_OVERRIDE) { return Overrides.STARTING_LEVEL_OVERRIDE; } @@ -108,7 +108,7 @@ export class GameMode implements GameModeConfig { * - override from overrides.ts * - 1000 */ - getStartingMoney(): integer { + getStartingMoney(): number { return Overrides.STARTING_MONEY_OVERRIDE || 1000; } @@ -127,7 +127,7 @@ export class GameMode implements GameModeConfig { } } - getWaveForDifficulty(waveIndex: integer, ignoreCurveChanges: boolean = false): integer { + getWaveForDifficulty(waveIndex: number, ignoreCurveChanges: boolean = false): number { switch (this.modeId) { case GameModes.DAILY: return waveIndex + 30 + (!ignoreCurveChanges ? Math.floor(waveIndex / 5) : 0); @@ -142,7 +142,7 @@ export class GameMode implements GameModeConfig { * @param arena the current {@linkcode Arena} * @returns `true` if a trainer should be generated, `false` otherwise */ - isWaveTrainer(waveIndex: integer, arena: Arena): boolean { + isWaveTrainer(waveIndex: number, arena: Arena): boolean { /** * Daily spawns trainers on floors 5, 15, 20, 25, 30, 35, 40, and 45 */ @@ -186,7 +186,7 @@ export class GameMode implements GameModeConfig { return false; } - isTrainerBoss(waveIndex: integer, biomeType: Biome, offsetGym: boolean): boolean { + isTrainerBoss(waveIndex: number, biomeType: Biome, offsetGym: boolean): boolean { switch (this.modeId) { case GameModes.DAILY: return waveIndex > 10 && waveIndex < 50 && !(waveIndex % 10); @@ -195,7 +195,7 @@ export class GameMode implements GameModeConfig { } } - getOverrideSpecies(waveIndex: integer): PokemonSpecies | null { + getOverrideSpecies(waveIndex: number): PokemonSpecies | null { if (this.isDaily && this.isWaveFinal(waveIndex)) { const allFinalBossSpecies = allSpecies.filter(s => (s.subLegendary || s.legendary || s.mythical) && s.baseTotal >= 600 && s.speciesId !== Species.ETERNATUS && s.speciesId !== Species.ARCEUS); @@ -211,7 +211,7 @@ export class GameMode implements GameModeConfig { * @param modeId game mode * @returns if the current wave is final for classic or daily OR a minor boss in endless */ - isWaveFinal(waveIndex: integer, modeId: GameModes = this.modeId): boolean { + isWaveFinal(waveIndex: number, modeId: GameModes = this.modeId): boolean { switch (modeId) { case GameModes.CLASSIC: case GameModes.CHALLENGE: @@ -228,7 +228,7 @@ export class GameMode implements GameModeConfig { * Every 10 waves is a boss battle * @returns true if waveIndex is a multiple of 10 */ - isBoss(waveIndex: integer): boolean { + isBoss(waveIndex: number): boolean { return waveIndex % 10 === 0; } @@ -244,7 +244,7 @@ export class GameMode implements GameModeConfig { * At this time it is paradox pokemon * @returns true if waveIndex is a multiple of 50 in Endless */ - isEndlessBoss(waveIndex: integer): boolean { + isEndlessBoss(waveIndex: number): boolean { return waveIndex % 50 === 0 && (this.modeId === GameModes.ENDLESS || this.modeId === GameModes.SPLICED_ENDLESS); } @@ -254,7 +254,7 @@ export class GameMode implements GameModeConfig { * At this time it is Eternatus * @returns true if waveIndex is a multiple of 250 in Endless */ - isEndlessMinorBoss(waveIndex: integer): boolean { + isEndlessMinorBoss(waveIndex: number): boolean { return waveIndex % 250 === 0 && (this.modeId === GameModes.ENDLESS || this.modeId === GameModes.SPLICED_ENDLESS); } @@ -264,27 +264,27 @@ export class GameMode implements GameModeConfig { * At this time it is Eternamax Eternatus * @returns true if waveIndex is a multiple of 1000 in Endless */ - isEndlessMajorBoss(waveIndex: integer): boolean { + isEndlessMajorBoss(waveIndex: number): boolean { return waveIndex % 1000 === 0 && (this.modeId === GameModes.ENDLESS || this.modeId === GameModes.SPLICED_ENDLESS); } /** * Checks whether there is a fixed battle on this gamemode on a given wave. - * @param {integer} waveIndex The wave to check. + * @param {number} waveIndex The wave to check. * @returns {boolean} If this game mode has a fixed battle on this wave */ - isFixedBattle(waveIndex: integer): boolean { + isFixedBattle(waveIndex: number): boolean { const dummyConfig = new FixedBattleConfig(); return this.battleConfig.hasOwnProperty(waveIndex) || applyChallenges(this, ChallengeType.FIXED_BATTLES, waveIndex, dummyConfig); } /** * Returns the config for the fixed battle for a particular wave. - * @param {integer} waveIndex The wave to check. + * @param {number} waveIndex The wave to check. * @returns {boolean} The fixed battle for this wave. */ - getFixedBattle(waveIndex: integer): FixedBattleConfig { + getFixedBattle(waveIndex: number): FixedBattleConfig { const challengeConfig = new FixedBattleConfig(); if (applyChallenges(this, ChallengeType.FIXED_BATTLES, waveIndex, challengeConfig)) { return challengeConfig; @@ -294,7 +294,7 @@ export class GameMode implements GameModeConfig { } - getClearScoreBonus(): integer { + getClearScoreBonus(): number { switch (this.modeId) { case GameModes.CLASSIC: case GameModes.CHALLENGE: @@ -306,7 +306,7 @@ export class GameMode implements GameModeConfig { } } - getEnemyModifierChance(isBoss: boolean): integer { + getEnemyModifierChance(isBoss: boolean): number { switch (this.modeId) { case GameModes.CLASSIC: case GameModes.CHALLENGE: diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index f531e96d641..b65f1b53441 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -194,9 +194,9 @@ export interface GeneratedPersistentModifierType { class AddPokeballModifierType extends ModifierType { private pokeballType: PokeballType; - private count: integer; + private count: number; - constructor(iconImage: string, pokeballType: PokeballType, count: integer) { + constructor(iconImage: string, pokeballType: PokeballType, count: number) { super("", iconImage, (_type, _args) => new AddPokeballModifier(this, pokeballType, count), "pb", "se/pb_bounce_1"); this.pokeballType = pokeballType; this.count = count; @@ -221,9 +221,9 @@ class AddPokeballModifierType extends ModifierType { class AddVoucherModifierType extends ModifierType { private voucherType: VoucherType; - private count: integer; + private count: number; - constructor(voucherType: VoucherType, count: integer) { + constructor(voucherType: VoucherType, count: number) { super("", getVoucherTypeIcon(voucherType), (_type, _args) => new AddVoucherModifier(this, voucherType, count), "voucher"); this.count = count; this.voucherType = voucherType; @@ -276,11 +276,11 @@ export class PokemonHeldItemModifierType extends PokemonModifierType { } export class PokemonHpRestoreModifierType extends PokemonModifierType { - protected restorePoints: integer; - protected restorePercent: integer; + protected restorePoints: number; + protected restorePercent: number; protected healStatus: boolean; - constructor(localeKey: string, iconImage: string, restorePoints: integer, restorePercent: integer, healStatus: boolean = false, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, group?: string) { + constructor(localeKey: string, iconImage: string, restorePoints: number, restorePercent: number, healStatus: boolean = false, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, group?: string) { super(localeKey, iconImage, newModifierFunc || ((_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.restorePercent, this.healStatus, false)), selectFilter || ((pokemon: PlayerPokemon) => { if (!pokemon.hp || (pokemon.isFullHp() && (!this.healStatus || (!pokemon.status && !pokemon.getTag(BattlerTagType.CONFUSED))))) { @@ -307,7 +307,7 @@ export class PokemonHpRestoreModifierType extends PokemonModifierType { } export class PokemonReviveModifierType extends PokemonHpRestoreModifierType { - constructor(localeKey: string, iconImage: string, restorePercent: integer) { + constructor(localeKey: string, iconImage: string, restorePercent: number) { super(localeKey, iconImage, 0, restorePercent, false, (_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, 0, this.restorePercent, false, true), ((pokemon: PlayerPokemon) => { if (!pokemon.isFainted()) { @@ -356,10 +356,10 @@ export abstract class PokemonMoveModifierType extends PokemonModifierType { } export class PokemonPpRestoreModifierType extends PokemonMoveModifierType { - protected restorePoints: integer; + protected restorePoints: number; - constructor(localeKey: string, iconImage: string, restorePoints: integer) { - super(localeKey, iconImage, (_type, args) => new PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.restorePoints), + constructor(localeKey: string, iconImage: string, restorePoints: number) { + super(localeKey, iconImage, (_type, args) => new PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as number), this.restorePoints), (_pokemon: PlayerPokemon) => { return null; }, (pokemonMove: PokemonMove) => { @@ -381,9 +381,9 @@ export class PokemonPpRestoreModifierType extends PokemonMoveModifierType { } export class PokemonAllMovePpRestoreModifierType extends PokemonModifierType { - protected restorePoints: integer; + protected restorePoints: number; - constructor(localeKey: string, iconImage: string, restorePoints: integer) { + constructor(localeKey: string, iconImage: string, restorePoints: number) { super(localeKey, iconImage, (_type, args) => new PokemonAllMovePpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints), (pokemon: PlayerPokemon) => { if (!pokemon.getMoveset().filter(m => m?.ppUsed).length) { @@ -404,10 +404,10 @@ export class PokemonAllMovePpRestoreModifierType extends PokemonModifierType { } export class PokemonPpUpModifierType extends PokemonMoveModifierType { - protected upPoints: integer; + protected upPoints: number; - constructor(localeKey: string, iconImage: string, upPoints: integer) { - super(localeKey, iconImage, (_type, args) => new PokemonPpUpModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.upPoints), + constructor(localeKey: string, iconImage: string, upPoints: number) { + super(localeKey, iconImage, (_type, args) => new PokemonPpUpModifier(this, (args[0] as PlayerPokemon).id, (args[1] as number), this.upPoints), (_pokemon: PlayerPokemon) => { return null; }, (pokemonMove: PokemonMove) => { @@ -451,7 +451,7 @@ export class PokemonNatureChangeModifierType extends PokemonModifierType { export class RememberMoveModifierType extends PokemonModifierType { constructor(localeKey: string, iconImage: string, group?: string) { - super(localeKey, iconImage, (type, args) => new RememberMoveModifier(type, (args[0] as PlayerPokemon).id, (args[1] as integer)), + super(localeKey, iconImage, (type, args) => new RememberMoveModifier(type, (args[0] as PlayerPokemon).id, (args[1] as number)), (pokemon: PlayerPokemon) => { if (!pokemon.getLearnableLevelMoves().length) { return PartyUiHandler.NoEffectMessage; @@ -552,9 +552,9 @@ enum AttackTypeBoosterItem { export class AttackTypeBoosterModifierType extends PokemonHeldItemModifierType implements GeneratedPersistentModifierType { public moveType: Type; - public boostPercent: integer; + public boostPercent: number; - constructor(moveType: Type, boostPercent: integer) { + constructor(moveType: Type, boostPercent: number) { super("", `${AttackTypeBoosterItem[moveType]?.toLowerCase()}`, (_type, args) => new AttackTypeBoosterModifier(this, (args[0] as Pokemon).id, moveType, boostPercent)); @@ -657,9 +657,9 @@ export class BaseStatBoosterModifierType extends PokemonHeldItemModifierType imp * Shuckle Juice item */ export class PokemonBaseStatTotalModifierType extends PokemonHeldItemModifierType implements GeneratedPersistentModifierType { - private readonly statModifier: integer; + private readonly statModifier: number; - constructor(statModifier: integer) { + constructor(statModifier: number) { super("modifierType:ModifierType.MYSTERY_ENCOUNTER_SHUCKLE_JUICE", "berry_juice", (_type, args) => new PokemonBaseStatTotalModifier(this, (args[0] as Pokemon).id, this.statModifier)); this.statModifier = statModifier; } @@ -681,10 +681,10 @@ export class PokemonBaseStatTotalModifierType extends PokemonHeldItemModifierTyp * Old Gateau item */ export class PokemonBaseStatFlatModifierType extends PokemonHeldItemModifierType implements GeneratedPersistentModifierType { - private readonly statModifier: integer; + private readonly statModifier: number; private readonly stats: Stat[]; - constructor(statModifier: integer, stats: Stat[]) { + constructor(statModifier: number, stats: Stat[]) { super("modifierType:ModifierType.MYSTERY_ENCOUNTER_OLD_GATEAU", "old_gateau", (_type, args) => new PokemonBaseStatFlatModifier(this, (args[0] as Pokemon).id, this.statModifier, this.stats)); this.statModifier = statModifier; this.stats = stats; @@ -746,9 +746,9 @@ export class MoneyRewardModifierType extends ModifierType { } export class ExpBoosterModifierType extends ModifierType { - private boostPercent: integer; + private boostPercent: number; - constructor(localeKey: string, iconImage: string, boostPercent: integer) { + constructor(localeKey: string, iconImage: string, boostPercent: number) { super(localeKey, iconImage, () => new ExpBoosterModifier(this, boostPercent)); this.boostPercent = boostPercent; @@ -760,9 +760,9 @@ export class ExpBoosterModifierType extends ModifierType { } export class PokemonExpBoosterModifierType extends PokemonHeldItemModifierType { - private boostPercent: integer; + private boostPercent: number; - constructor(localeKey: string, iconImage: string, boostPercent: integer) { + constructor(localeKey: string, iconImage: string, boostPercent: number) { super(localeKey, iconImage, (_type, args) => new PokemonExpBoosterModifier(this, (args[0] as Pokemon).id, boostPercent)); this.boostPercent = boostPercent; @@ -784,9 +784,9 @@ export class PokemonFriendshipBoosterModifierType extends PokemonHeldItemModifie } export class PokemonMoveAccuracyBoosterModifierType extends PokemonHeldItemModifierType { - private amount: integer; + private amount: number; - constructor(localeKey: string, iconImage: string, amount: integer, group?: string, soundName?: string) { + constructor(localeKey: string, iconImage: string, amount: number, group?: string, soundName?: string) { super(localeKey, iconImage, (_type, args) => new PokemonMoveAccuracyBoosterModifier(this, (args[0] as Pokemon).id, amount), group, soundName); this.amount = amount; @@ -934,7 +934,7 @@ class AttackTypeBoosterModifierTypeGenerator extends ModifierTypeGenerator { return null; } - const attackMoveTypeWeights = new Map(); + const attackMoveTypeWeights = new Map(); let totalWeight = 0; for (const t of attackMoveTypes) { if (attackMoveTypeWeights.has(t)) { @@ -1215,9 +1215,9 @@ export class TerastallizeModifierType extends PokemonHeldItemModifierType implem } export class ContactHeldItemTransferChanceModifierType extends PokemonHeldItemModifierType { - private chancePercent: integer; + private chancePercent: number; - constructor(localeKey: string, iconImage: string, chancePercent: integer, group?: string, soundName?: string) { + constructor(localeKey: string, iconImage: string, chancePercent: number, group?: string, soundName?: string) { super(localeKey, iconImage, (type, args) => new ContactHeldItemTransferChanceModifier(type, (args[0] as Pokemon).id, chancePercent), group, soundName); this.chancePercent = chancePercent; @@ -1239,10 +1239,10 @@ export class TurnHeldItemTransferModifierType extends PokemonHeldItemModifierTyp } export class EnemyAttackStatusEffectChanceModifierType extends ModifierType { - private chancePercent: integer; + private chancePercent: number; private effect: StatusEffect; - constructor(localeKey: string, iconImage: string, chancePercent: integer, effect: StatusEffect, stackCount?: integer) { + constructor(localeKey: string, iconImage: string, chancePercent: number, effect: StatusEffect, stackCount?: number) { super(localeKey, iconImage, (type, _args) => new EnemyAttackStatusEffectChanceModifier(type, effect, chancePercent, stackCount), "enemy_status_chance"); this.chancePercent = chancePercent; @@ -1272,7 +1272,7 @@ export class EnemyEndureChanceModifierType extends ModifierType { } export type ModifierTypeFunc = () => ModifierType; -type WeightedModifierTypeWeightFunc = (party: Pokemon[], rerollCount?: integer) => integer; +type WeightedModifierTypeWeightFunc = (party: Pokemon[], rerollCount?: number) => number; /** * High order function that returns a WeightedModifierTypeWeightFunc that will only be applied on @@ -1281,7 +1281,7 @@ type WeightedModifierTypeWeightFunc = (party: Pokemon[], rerollCount?: integer) * @param defaultWeight - ModifierType default weight * @returns A WeightedModifierTypeWeightFunc */ -function skipInClassicAfterWave(wave: integer, defaultWeight: integer): WeightedModifierTypeWeightFunc { +function skipInClassicAfterWave(wave: number, defaultWeight: number): WeightedModifierTypeWeightFunc { return () => { const gameMode = globalScene.gameMode; const currentWave = globalScene.currentBattle.waveIndex; @@ -1295,7 +1295,7 @@ function skipInClassicAfterWave(wave: integer, defaultWeight: integer): Weighted * @param defaultWeight ModifierType default weight * @returns A WeightedModifierTypeWeightFunc */ -function skipInLastClassicWaveOrDefault(defaultWeight: integer) : WeightedModifierTypeWeightFunc { +function skipInLastClassicWaveOrDefault(defaultWeight: number) : WeightedModifierTypeWeightFunc { return skipInClassicAfterWave(199, defaultWeight); } @@ -1314,10 +1314,10 @@ function lureWeightFunc(maxBattles: number, weight: number): WeightedModifierTyp } class WeightedModifierType { public modifierType: ModifierType; - public weight: integer | WeightedModifierTypeWeightFunc; - public maxWeight: integer | WeightedModifierTypeWeightFunc; + public weight: number | WeightedModifierTypeWeightFunc; + public maxWeight: number | WeightedModifierTypeWeightFunc; - constructor(modifierTypeFunc: ModifierTypeFunc, weight: integer | WeightedModifierTypeWeightFunc, maxWeight?: integer | WeightedModifierTypeWeightFunc) { + constructor(modifierTypeFunc: ModifierTypeFunc, weight: number | WeightedModifierTypeWeightFunc, maxWeight?: number | WeightedModifierTypeWeightFunc) { this.modifierType = modifierTypeFunc(); this.modifierType.id = Object.keys(modifierTypes).find(k => modifierTypes[k] === modifierTypeFunc)!; // TODO: is this bang correct? this.weight = weight; @@ -1715,13 +1715,13 @@ const modifierPool: ModifierPool = { if (!party.find(p => p.getLearnableLevelMoves().length)) { return 0; } - const highestPartyLevel = party.map(p => p.level).reduce((highestLevel: integer, level: integer) => Math.max(highestLevel, level), 1); + const highestPartyLevel = party.map(p => p.level).reduce((highestLevel: number, level: number) => Math.max(highestLevel, level), 1); return Math.min(Math.ceil(highestPartyLevel / 20), 4); }, 4), new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3), new WeightedModifierType(modifierTypes.TERA_SHARD, 1), new WeightedModifierType(modifierTypes.DNA_SPLICERS, (party: Pokemon[]) => globalScene.gameMode.isSplicedOnly && party.filter(p => !p.fusionSpecies).length > 1 ? 4 : 0), - new WeightedModifierType(modifierTypes.VOUCHER, (_party: Pokemon[], rerollCount: integer) => !globalScene.gameMode.isDaily ? Math.max(1 - rerollCount, 0) : 0, 1), + new WeightedModifierType(modifierTypes.VOUCHER, (_party: Pokemon[], rerollCount: number) => !globalScene.gameMode.isDaily ? Math.max(1 - rerollCount, 0) : 0, 1), ].map(m => { m.setTier(ModifierTier.GREAT); return m; }), @@ -1868,7 +1868,7 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.RARE_FORM_CHANGE_ITEM, () => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 6, 24), new WeightedModifierType(modifierTypes.MEGA_BRACELET, () => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 9, 36), new WeightedModifierType(modifierTypes.DYNAMAX_BAND, () => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 9, 36), - new WeightedModifierType(modifierTypes.VOUCHER_PLUS, (_party: Pokemon[], rerollCount: integer) => !globalScene.gameMode.isDaily ? Math.max(3 - rerollCount * 1, 0) : 0, 3), + new WeightedModifierType(modifierTypes.VOUCHER_PLUS, (_party: Pokemon[], rerollCount: number) => !globalScene.gameMode.isDaily ? Math.max(3 - rerollCount * 1, 0) : 0, 3), ].map(m => { m.setTier(ModifierTier.ROGUE); return m; }), @@ -1877,7 +1877,7 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.SHINY_CHARM, 14), new WeightedModifierType(modifierTypes.HEALING_CHARM, 18), new WeightedModifierType(modifierTypes.MULTI_LENS, 18), - new WeightedModifierType(modifierTypes.VOUCHER_PREMIUM, (_party: Pokemon[], rerollCount: integer) => + new WeightedModifierType(modifierTypes.VOUCHER_PREMIUM, (_party: Pokemon[], rerollCount: number) => !globalScene.gameMode.isDaily && !globalScene.gameMode.isEndless && !globalScene.gameMode.isSplicedOnly ? Math.max(5 - rerollCount * 2, 0) : 0, 5), new WeightedModifierType(modifierTypes.DNA_SPLICERS, (party: Pokemon[]) => !globalScene.gameMode.isSplicedOnly && party.filter(p => !p.fusionSpecies).length > 1 ? 24 : 0, 24), new WeightedModifierType(modifierTypes.MINI_BLACK_HOLE, () => (globalScene.gameMode.isDaily || (!globalScene.gameMode.isFreshStartChallenge() && globalScene.gameData.isUnlocked(Unlockables.MINI_BLACK_HOLE))) ? 1 : 0, 1), @@ -2077,7 +2077,7 @@ const tierWeights = [ 768 / 1024, 195 / 1024, 48 / 1024, 12 / 1024, 1 / 1024 ]; */ export const itemPoolChecks: Map = new Map(); -export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: ModifierPoolType, rerollCount: integer = 0) { +export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: ModifierPoolType, rerollCount: number = 0) { const pool = getModifierPoolForType(poolType); itemPoolChecks.forEach((_v, k) => { itemPoolChecks.set(k, false); @@ -2091,7 +2091,7 @@ export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: Mod const tierModifierIds: string[] = []; let tierMaxWeight = 0; let i = 0; - pool[t].reduce((total: integer, modifierType: WeightedModifierType) => { + pool[t].reduce((total: number, modifierType: WeightedModifierType) => { const weightedModifierType = modifierType as WeightedModifierType; const existingModifiers = globalScene.findModifiers(m => m.type.id === weightedModifierType.modifierType.id, poolType === ModifierPoolType.PLAYER); const itemModifierType = weightedModifierType.modifierType instanceof ModifierTypeGenerator @@ -2103,7 +2103,7 @@ export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: Mod || existingModifiers.find(m => m.stackCount < m.getMaxStackCount(true)) ? weightedModifierType.weight instanceof Function ? (weightedModifierType.weight as Function)(party, rerollCount) - : weightedModifierType.weight as integer + : weightedModifierType.weight as number : 0; if (weightedModifierType.maxWeight) { const modifierId = weightedModifierType.modifierType.id; @@ -2187,7 +2187,7 @@ export function getModifierTypeFuncById(id: string): ModifierTypeFunc { * - `rerollMultiplier?: number` If specified, can adjust the amount of money required for a shop reroll. If set to a negative value, the shop will not allow rerolls at all. * - `allowLuckUpgrades?: boolean` Default `true`, if `false` will prevent set item tiers from upgrading via luck */ -export function getPlayerModifierTypeOptions(count: integer, party: PlayerPokemon[], modifierTiers?: ModifierTier[], customModifierSettings?: CustomModifierSettings): ModifierTypeOption[] { +export function getPlayerModifierTypeOptions(count: number, party: PlayerPokemon[], modifierTiers?: ModifierTier[], customModifierSettings?: CustomModifierSettings): ModifierTypeOption[] { const options: ModifierTypeOption[] = []; const retryCount = Math.min(count * 5, 50); if (!customModifierSettings) { @@ -2248,7 +2248,7 @@ export function getPlayerModifierTypeOptions(count: integer, party: PlayerPokemo * @param tier If specified will generate item of tier * @param allowLuckUpgrades `true` to allow items to upgrade tiers (the little animation that plays and is affected by luck) */ -function getModifierTypeOptionWithRetry(existingOptions: ModifierTypeOption[], retryCount: integer, party: PlayerPokemon[], tier?: ModifierTier, allowLuckUpgrades?: boolean): ModifierTypeOption { +function getModifierTypeOptionWithRetry(existingOptions: ModifierTypeOption[], retryCount: number, party: PlayerPokemon[], tier?: ModifierTier, allowLuckUpgrades?: boolean): ModifierTypeOption { allowLuckUpgrades = allowLuckUpgrades ?? true; let candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, tier, undefined, 0, allowLuckUpgrades); let r = 0; @@ -2283,7 +2283,7 @@ export function overridePlayerModifierTypeOptions(options: ModifierTypeOption[], } } -export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, baseCost: integer): ModifierTypeOption[] { +export function getPlayerShopModifierTypeOptionsForWave(waveIndex: number, baseCost: number): ModifierTypeOption[] { if (!(waveIndex % 10)) { return []; } @@ -2349,7 +2349,7 @@ export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers: return modifier; } -export function getEnemyModifierTypesForWave(waveIndex: integer, count: integer, party: EnemyPokemon[], poolType: ModifierPoolType.WILD | ModifierPoolType.TRAINER, upgradeChance: integer = 0): PokemonHeldItemModifierType[] { +export function getEnemyModifierTypesForWave(waveIndex: number, count: number, party: EnemyPokemon[], poolType: ModifierPoolType.WILD | ModifierPoolType.TRAINER, upgradeChance: number = 0): PokemonHeldItemModifierType[] { const ret = new Array(count).fill(0).map(() => getNewModifierTypeOption(party, poolType, undefined, upgradeChance && !randSeedInt(upgradeChance) ? 1 : 0)?.type as PokemonHeldItemModifierType); if (!(waveIndex % 1000)) { ret.push(getModifierType(modifierTypes.MINI_BLACK_HOLE) as PokemonHeldItemModifierType); @@ -2393,7 +2393,7 @@ export function getDailyRunStarterModifiers(party: PlayerPokemon[]): PokemonHeld * @param retryCount Max allowed tries before the next tier down is checked for a valid ModifierType * @param allowLuckUpgrades Default true. If false, will not allow ModifierType to randomly upgrade to next tier */ -function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, tier?: ModifierTier, upgradeCount?: integer, retryCount: integer = 0, allowLuckUpgrades: boolean = true): ModifierTypeOption | null { +function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, tier?: ModifierTier, upgradeCount?: number, retryCount: number = 0, allowLuckUpgrades: boolean = true): ModifierTypeOption | null { const player = !poolType; const pool = getModifierPoolForType(poolType); let thresholds: object; @@ -2472,7 +2472,7 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, const tierThresholds = Object.keys(thresholds[tier]); const totalWeight = parseInt(tierThresholds[tierThresholds.length - 1]); const value = randSeedInt(totalWeight); - let index: integer | undefined; + let index: number | undefined; for (const t of tierThresholds) { const threshold = parseInt(t); if (value < threshold) { @@ -2514,10 +2514,10 @@ export function getDefaultModifierTypeForTier(tier: ModifierTier): ModifierType export class ModifierTypeOption { public type: ModifierType; - public upgradeCount: integer; - public cost: integer; + public upgradeCount: number; + public cost: number; - constructor(type: ModifierType, upgradeCount: integer, cost: number = 0) { + constructor(type: ModifierType, upgradeCount: number, cost: number = 0) { this.type = type; this.upgradeCount = upgradeCount; this.cost = Math.min(Math.round(cost), Number.MAX_SAFE_INTEGER); @@ -2529,7 +2529,7 @@ export class ModifierTypeOption { * @param party The player's party. * @returns A number between 0 and 14 based on the party's total luck value, or a random number between 0 and 14 if the player is in Daily Run mode. */ -export function getPartyLuckValue(party: Pokemon[]): integer { +export function getPartyLuckValue(party: Pokemon[]): number { if (globalScene.gameMode.isDaily) { const DailyLuck = new NumberHolder(0); globalScene.executeWithSeedOffset(() => { @@ -2539,15 +2539,15 @@ export function getPartyLuckValue(party: Pokemon[]): integer { } const eventSpecies = globalScene.eventManager.getEventLuckBoostedSpecies(); const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? p.getLuck() + (eventSpecies.includes(p.species.speciesId) ? 1 : 0) : 0) - .reduce((total: integer, value: integer) => total += value, 0), 0, 14); + .reduce((total: number, value: number) => total += value, 0), 0, 14); return Math.min(globalScene.eventManager.getEventLuckBoost() + (luck ?? 0), 14); } -export function getLuckString(luckValue: integer): string { +export function getLuckString(luckValue: number): string { return [ "D", "C", "C+", "B-", "B", "B+", "A-", "A", "A+", "A++", "S", "S+", "SS", "SS+", "SSS" ][luckValue]; } -export function getLuckTextTint(luckValue: integer): integer { +export function getLuckTextTint(luckValue: number): number { let modifierTier: ModifierTier; if (luckValue > 11) { modifierTier = ModifierTier.LUXURY; diff --git a/src/overrides.ts b/src/overrides.ts index 06ad619a074..8f881ca59dd 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -126,7 +126,7 @@ class DefaultOverrides { /** * This will override the species of the fusion */ - readonly STARTER_FUSION_SPECIES_OVERRIDE: Species | integer = 0; + readonly STARTER_FUSION_SPECIES_OVERRIDE: Species | number = 0; readonly ABILITY_OVERRIDE: Abilities = Abilities.NONE; readonly PASSIVE_ABILITY_OVERRIDE: Abilities = Abilities.NONE; readonly STATUS_OVERRIDE: StatusEffect = StatusEffect.NONE; @@ -146,7 +146,7 @@ class DefaultOverrides { /** * This will override the species of the fusion only when the opponent is already a fusion */ - readonly OPP_FUSION_SPECIES_OVERRIDE: Species | integer = 0; + readonly OPP_FUSION_SPECIES_OVERRIDE: Species | number = 0; readonly OPP_LEVEL_OVERRIDE: number = 0; readonly OPP_ABILITY_OVERRIDE: Abilities = Abilities.NONE; readonly OPP_PASSIVE_ABILITY_OVERRIDE: Abilities = Abilities.NONE; diff --git a/src/phases/attempt-capture-phase.ts b/src/phases/attempt-capture-phase.ts index 1f4fc0d6271..6a6a2efa061 100644 --- a/src/phases/attempt-capture-phase.ts +++ b/src/phases/attempt-capture-phase.ts @@ -24,7 +24,7 @@ export class AttemptCapturePhase extends PokemonPhase { private pokeball: Phaser.GameObjects.Sprite; private originalY: number; - constructor(targetIndex: integer, pokeballType: PokeballType) { + constructor(targetIndex: number, pokeballType: PokeballType) { super(BattlerIndex.ENEMY + targetIndex); this.pokeballType = pokeballType; @@ -174,7 +174,7 @@ export class AttemptCapturePhase extends PokemonPhase { }); } - failCatch(shakeCount: integer) { + failCatch(shakeCount: number) { const pokemon = this.getPokemon(); globalScene.playSound("se/pb_rel"); @@ -276,7 +276,7 @@ export class AttemptCapturePhase extends PokemonPhase { }); }, false); }, () => { - globalScene.ui.setMode(Mode.PARTY, PartyUiMode.RELEASE, this.fieldIndex, (slotIndex: integer, _option: PartyOption) => { + globalScene.ui.setMode(Mode.PARTY, PartyUiMode.RELEASE, this.fieldIndex, (slotIndex: number, _option: PartyOption) => { globalScene.ui.setMode(Mode.MESSAGE).then(() => { if (slotIndex < 6) { addToParty(slotIndex); diff --git a/src/phases/check-switch-phase.ts b/src/phases/check-switch-phase.ts index 06e08f7f30d..ea16e91b990 100644 --- a/src/phases/check-switch-phase.ts +++ b/src/phases/check-switch-phase.ts @@ -10,10 +10,10 @@ import { SwitchPhase } from "./switch-phase"; import { SwitchType } from "#enums/switch-type"; export class CheckSwitchPhase extends BattlePhase { - protected fieldIndex: integer; + protected fieldIndex: number; protected useName: boolean; - constructor(fieldIndex: integer, useName: boolean) { + constructor(fieldIndex: number, useName: boolean) { super(); this.fieldIndex = fieldIndex; diff --git a/src/phases/command-phase.ts b/src/phases/command-phase.ts index e2bad953fc5..632344be335 100644 --- a/src/phases/command-phase.ts +++ b/src/phases/command-phase.ts @@ -25,9 +25,9 @@ import { ArenaTagSide } from "#app/data/arena-tag"; import { ArenaTagType } from "#app/enums/arena-tag-type"; export class CommandPhase extends FieldPhase { - protected fieldIndex: integer; + protected fieldIndex: number; - constructor(fieldIndex: integer) { + constructor(fieldIndex: number) { super(); this.fieldIndex = fieldIndex; @@ -113,7 +113,7 @@ export class CommandPhase extends FieldPhase { } } - handleCommand(command: Command, cursor: integer, ...args: any[]): boolean { + handleCommand(command: Command, cursor: number, ...args: any[]): boolean { const playerPokemon = globalScene.getPlayerField()[this.fieldIndex]; let success: boolean = false; @@ -319,7 +319,7 @@ export class CommandPhase extends FieldPhase { } } - getFieldIndex(): integer { + getFieldIndex(): number { return this.fieldIndex; } diff --git a/src/phases/common-anim-phase.ts b/src/phases/common-anim-phase.ts index 53cbdfaeb38..9ca74ed5a77 100644 --- a/src/phases/common-anim-phase.ts +++ b/src/phases/common-anim-phase.ts @@ -6,7 +6,7 @@ import { PokemonPhase } from "./pokemon-phase"; export class CommonAnimPhase extends PokemonPhase { private anim: CommonAnim | null; - private targetIndex: integer | undefined; + private targetIndex: number | undefined; private playOnEmptyField: boolean; constructor(battlerIndex?: BattlerIndex, targetIndex?: BattlerIndex, anim?: CommonAnim, playOnEmptyField: boolean = false) { diff --git a/src/phases/damage-anim-phase.ts b/src/phases/damage-anim-phase.ts index 2983d6b2de0..a21d9d4622a 100644 --- a/src/phases/damage-anim-phase.ts +++ b/src/phases/damage-anim-phase.ts @@ -6,11 +6,11 @@ import { fixedInt } from "#app/utils"; import { PokemonPhase } from "#app/phases/pokemon-phase"; export class DamageAnimPhase extends PokemonPhase { - private amount: integer; + private amount: number; private damageResult: DamageResult; private critical: boolean; - constructor(battlerIndex: BattlerIndex, amount: integer, damageResult?: DamageResult, critical: boolean = false) { + constructor(battlerIndex: BattlerIndex, amount: number, damageResult?: DamageResult, critical: boolean = false) { super(battlerIndex); this.amount = amount; @@ -35,7 +35,7 @@ export class DamageAnimPhase extends PokemonPhase { this.applyDamage(); } - updateAmount(amount: integer): void { + updateAmount(amount: number): void { this.amount = amount; } diff --git a/src/phases/egg-hatch-phase.ts b/src/phases/egg-hatch-phase.ts index 11bf9584ee7..2d0aa24dd1f 100644 --- a/src/phases/egg-hatch-phase.ts +++ b/src/phases/egg-hatch-phase.ts @@ -28,7 +28,7 @@ export class EggHatchPhase extends Phase { private eggHatchData: EggHatchData; /** The number of eggs that are hatching */ - private eggsToHatchCount: integer; + private eggsToHatchCount: number; /** The container that lists how many eggs are hatching */ private eggCounterContainer: EggCounterContainer; @@ -59,7 +59,7 @@ export class EggHatchPhase extends Phase { /** The newly hatched {@link PlayerPokemon} */ private pokemon: PlayerPokemon; /** The index of which egg move is unlocked. 0-2 is common, 3 is rare */ - private eggMoveIndex: integer; + private eggMoveIndex: number; /** Internal booleans representing if the egg is hatched, able to be skipped, or skipped */ private hatched: boolean; private canSkip: boolean; @@ -68,7 +68,7 @@ export class EggHatchPhase extends Phase { private evolutionBgm: AnySound; private eggLapsePhase: EggLapsePhase; - constructor(hatchScene: EggLapsePhase, egg: Egg, eggsToHatchCount: integer) { + constructor(hatchScene: EggLapsePhase, egg: Egg, eggsToHatchCount: number) { super(); this.eggLapsePhase = hatchScene; this.egg = egg; @@ -221,7 +221,7 @@ export class EggHatchPhase extends Phase { * @param count the current number of times this function has been called. * @returns nothing since it's a Promise */ - doEggShake(intensity: number, repeatCount?: integer, count?: integer): Promise { + doEggShake(intensity: number, repeatCount?: number, count?: number): Promise { return new Promise(resolve => { if (repeatCount === undefined) { repeatCount = 0; @@ -382,7 +382,7 @@ export class EggHatchPhase extends Phase { * @param amplitude Scaling * @returns a number */ - sin(index: integer, amplitude: integer): number { + sin(index: number, amplitude: number): number { return amplitude * Math.sin(index * (Math.PI / 128)); } @@ -391,7 +391,7 @@ export class EggHatchPhase extends Phase { * @param intensity number of times this is repeated (this is a badly named variable) * @param offsetY how much to offset the Y coordinates */ - doSpray(intensity: integer, offsetY?: number) { + doSpray(intensity: number, offsetY?: number) { globalScene.tweens.addCounter({ repeat: intensity, duration: Utils.getFrameMs(1), @@ -406,7 +406,7 @@ export class EggHatchPhase extends Phase { * @param trigIndex Used to modify the particle's vertical speed, is a random number from 0-7 * @param offsetY how much to offset the Y coordinate */ - doSprayParticle(trigIndex: integer, offsetY: number) { + doSprayParticle(trigIndex: number, offsetY: number) { const initialX = this.eggHatchBg.displayWidth / 2; const initialY = this.eggHatchBg.displayHeight / 2 + offsetY; const shardKey = !this.egg.isManaphyEgg() ? this.egg.tier.toString() : "1"; diff --git a/src/phases/encounter-phase.ts b/src/phases/encounter-phase.ts index 353dd6681cb..7e62ca17f7c 100644 --- a/src/phases/encounter-phase.ts +++ b/src/phases/encounter-phase.ts @@ -272,7 +272,7 @@ export class EncounterPhase extends BattlePhase { const enemyField = globalScene.getEnemyField(); globalScene.tweens.add({ targets: [ globalScene.arenaEnemy, globalScene.currentBattle.trainer, enemyField, globalScene.arenaPlayer, globalScene.trainer ].flat(), - x: (_target, _key, value, fieldIndex: integer) => fieldIndex < 2 + (enemyField.length) ? value + 300 : value - 300, + x: (_target, _key, value, fieldIndex: number) => fieldIndex < 2 + (enemyField.length) ? value + 300 : value - 300, duration: 2000, onComplete: () => { if (!this.tryOverrideForBattleSpec()) { diff --git a/src/phases/enemy-command-phase.ts b/src/phases/enemy-command-phase.ts index 715303863be..e76518bb71e 100644 --- a/src/phases/enemy-command-phase.ts +++ b/src/phases/enemy-command-phase.ts @@ -15,10 +15,10 @@ import { BattlerTagType } from "#enums/battler-tag-type"; * @see {@linkcode EnemyPokemon.getNextMove} */ export class EnemyCommandPhase extends FieldPhase { - protected fieldIndex: integer; + protected fieldIndex: number; protected skipTurn: boolean = false; - constructor(fieldIndex: integer) { + constructor(fieldIndex: number) { super(); this.fieldIndex = fieldIndex; diff --git a/src/phases/enemy-party-member-pokemon-phase.ts b/src/phases/enemy-party-member-pokemon-phase.ts index 7c02cf97880..5c701f7d73a 100644 --- a/src/phases/enemy-party-member-pokemon-phase.ts +++ b/src/phases/enemy-party-member-pokemon-phase.ts @@ -2,7 +2,7 @@ import type { EnemyPokemon } from "#app/field/pokemon"; import { PartyMemberPokemonPhase } from "./party-member-pokemon-phase"; export abstract class EnemyPartyMemberPokemonPhase extends PartyMemberPokemonPhase { - constructor(partyMemberIndex: integer) { + constructor(partyMemberIndex: number) { super(partyMemberIndex, false); } diff --git a/src/phases/evolution-phase.ts b/src/phases/evolution-phase.ts index bf046e682e4..533edd320e3 100644 --- a/src/phases/evolution-phase.ts +++ b/src/phases/evolution-phase.ts @@ -20,7 +20,7 @@ import { EVOLVE_MOVE } from "#app/data/balance/pokemon-level-moves"; export class EvolutionPhase extends Phase { protected pokemon: PlayerPokemon; - protected lastLevel: integer; + protected lastLevel: number; private preEvolvedPokemonName: string; @@ -39,7 +39,7 @@ export class EvolutionPhase extends Phase { protected pokemonEvoSprite: Phaser.GameObjects.Sprite; protected pokemonEvoTintSprite: Phaser.GameObjects.Sprite; - constructor(pokemon: PlayerPokemon, evolution: SpeciesFormEvolution | null, lastLevel: integer) { + constructor(pokemon: PlayerPokemon, evolution: SpeciesFormEvolution | null, lastLevel: number) { super(); this.pokemon = pokemon; @@ -356,7 +356,7 @@ export class EvolutionPhase extends Phase { }); } - doCycle(l: number, lastCycle: integer = 15): Promise { + doCycle(l: number, lastCycle: number = 15): Promise { return new Promise(resolve => { const isLastCycle = l === lastCycle; globalScene.tweens.add({ @@ -427,7 +427,7 @@ export class EvolutionPhase extends Phase { }); } - doSpiralUpwardParticle(trigIndex: integer) { + doSpiralUpwardParticle(trigIndex: number) { const initialX = this.evolutionBaseBg.displayWidth / 2; const particle = globalScene.add.image(initialX, 0, "evo_sparkle"); this.evolutionContainer.add(particle); @@ -463,7 +463,7 @@ export class EvolutionPhase extends Phase { updateParticle(); } - doArcDownParticle(trigIndex: integer) { + doArcDownParticle(trigIndex: number) { const initialX = this.evolutionBaseBg.displayWidth / 2; const particle = globalScene.add.image(initialX, 0, "evo_sparkle"); particle.setScale(0.5); @@ -496,7 +496,7 @@ export class EvolutionPhase extends Phase { updateParticle(); } - doCircleInwardParticle(trigIndex: integer, speed: integer) { + doCircleInwardParticle(trigIndex: number, speed: number) { const initialX = this.evolutionBaseBg.displayWidth / 2; const initialY = this.evolutionBaseBg.displayHeight / 2; const particle = globalScene.add.image(initialX, initialY, "evo_sparkle"); @@ -528,7 +528,7 @@ export class EvolutionPhase extends Phase { updateParticle(); } - doSprayParticle(trigIndex: integer) { + doSprayParticle(trigIndex: number) { const initialX = this.evolutionBaseBg.displayWidth / 2; const initialY = this.evolutionBaseBg.displayHeight / 2; const particle = globalScene.add.image(initialX, initialY, "evo_sparkle"); diff --git a/src/phases/exp-phase.ts b/src/phases/exp-phase.ts index f0fe9fde719..7cf953851a1 100644 --- a/src/phases/exp-phase.ts +++ b/src/phases/exp-phase.ts @@ -9,7 +9,7 @@ import { LevelUpPhase } from "./level-up-phase"; export class ExpPhase extends PlayerPartyMemberPokemonPhase { private expValue: number; - constructor(partyMemberIndex: integer, expValue: number) { + constructor(partyMemberIndex: number, expValue: number) { super(partyMemberIndex); this.expValue = expValue; diff --git a/src/phases/learn-move-phase.ts b/src/phases/learn-move-phase.ts index a11b797c574..c1f3042dbbe 100644 --- a/src/phases/learn-move-phase.ts +++ b/src/phases/learn-move-phase.ts @@ -29,7 +29,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { private learnMoveType: LearnMoveType; private cost: number; - constructor(partyMemberIndex: integer, moveId: Moves, learnMoveType: LearnMoveType = LearnMoveType.LEARN_MOVE, cost: number = -1) { + constructor(partyMemberIndex: number, moveId: Moves, learnMoveType: LearnMoveType = LearnMoveType.LEARN_MOVE, cost: number = -1) { super(partyMemberIndex); this.moveId = moveId; this.learnMoveType = learnMoveType; @@ -99,7 +99,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { async forgetMoveProcess(move: Move, pokemon: Pokemon) { globalScene.ui.setMode(this.messageMode); await globalScene.ui.showTextPromise(i18next.t("battle:learnMoveForgetQuestion"), undefined, true); - await globalScene.ui.setModeWithoutClear(Mode.SUMMARY, pokemon, SummaryUiMode.LEARN_MOVE, move, (moveIndex: integer) => { + await globalScene.ui.setModeWithoutClear(Mode.SUMMARY, pokemon, SummaryUiMode.LEARN_MOVE, move, (moveIndex: number) => { if (moveIndex === 4) { globalScene.ui.setMode(this.messageMode).then(() => this.rejectMoveAndEnd(move, pokemon)); return; diff --git a/src/phases/message-phase.ts b/src/phases/message-phase.ts index 9439d8286c3..366fd324376 100644 --- a/src/phases/message-phase.ts +++ b/src/phases/message-phase.ts @@ -3,12 +3,12 @@ import { Phase } from "#app/phase"; export class MessagePhase extends Phase { private text: string; - private callbackDelay: integer | null; + private callbackDelay: number | null; private prompt: boolean | null; - private promptDelay: integer | null; + private promptDelay: number | null; private speaker?: string; - constructor(text: string, callbackDelay?: integer | null, prompt?: boolean | null, promptDelay?: integer | null, speaker?: string) { + constructor(text: string, callbackDelay?: number | null, prompt?: boolean | null, promptDelay?: number | null, speaker?: string) { super(); this.text = text; diff --git a/src/phases/party-member-pokemon-phase.ts b/src/phases/party-member-pokemon-phase.ts index bc702c832b1..592f35834aa 100644 --- a/src/phases/party-member-pokemon-phase.ts +++ b/src/phases/party-member-pokemon-phase.ts @@ -3,11 +3,11 @@ import type Pokemon from "#app/field/pokemon"; import { FieldPhase } from "./field-phase"; export abstract class PartyMemberPokemonPhase extends FieldPhase { - protected partyMemberIndex: integer; - protected fieldIndex: integer; + protected partyMemberIndex: number; + protected fieldIndex: number; protected player: boolean; - constructor(partyMemberIndex: integer, player: boolean) { + constructor(partyMemberIndex: number, player: boolean) { super(); this.partyMemberIndex = partyMemberIndex; diff --git a/src/phases/player-party-member-pokemon-phase.ts b/src/phases/player-party-member-pokemon-phase.ts index bdedc0743e9..d97376a8614 100644 --- a/src/phases/player-party-member-pokemon-phase.ts +++ b/src/phases/player-party-member-pokemon-phase.ts @@ -2,7 +2,7 @@ import type { PlayerPokemon } from "#app/field/pokemon"; import { PartyMemberPokemonPhase } from "./party-member-pokemon-phase"; export abstract class PlayerPartyMemberPokemonPhase extends PartyMemberPokemonPhase { - constructor(partyMemberIndex: integer) { + constructor(partyMemberIndex: number) { super(partyMemberIndex, true); } diff --git a/src/phases/pokemon-heal-phase.ts b/src/phases/pokemon-heal-phase.ts index 268794ce97c..a544d47df70 100644 --- a/src/phases/pokemon-heal-phase.ts +++ b/src/phases/pokemon-heal-phase.ts @@ -15,7 +15,7 @@ import { BattlerTagType } from "#app/enums/battler-tag-type"; import type { HealBlockTag } from "#app/data/battler-tags"; export class PokemonHealPhase extends CommonAnimPhase { - private hpHealed: integer; + private hpHealed: number; private message: string | null; private showFullHpMessage: boolean; private skipAnim: boolean; @@ -24,7 +24,7 @@ export class PokemonHealPhase extends CommonAnimPhase { private preventFullHeal: boolean; private fullRestorePP: boolean; - constructor(battlerIndex: BattlerIndex, hpHealed: integer, message: string | null, showFullHpMessage: boolean, skipAnim: boolean = false, revive: boolean = false, healStatus: boolean = false, preventFullHeal: boolean = false, fullRestorePP: boolean = false) { + constructor(battlerIndex: BattlerIndex, hpHealed: number, message: string | null, showFullHpMessage: boolean, skipAnim: boolean = false, revive: boolean = false, healStatus: boolean = false, preventFullHeal: boolean = false, fullRestorePP: boolean = false) { super(battlerIndex, undefined, CommonAnim.HEALTH_UP); this.hpHealed = hpHealed; diff --git a/src/phases/pokemon-phase.ts b/src/phases/pokemon-phase.ts index 29153ee726a..bf4193adb6d 100644 --- a/src/phases/pokemon-phase.ts +++ b/src/phases/pokemon-phase.ts @@ -4,11 +4,11 @@ import type Pokemon from "#app/field/pokemon"; import { FieldPhase } from "./field-phase"; export abstract class PokemonPhase extends FieldPhase { - protected battlerIndex: BattlerIndex | integer; + protected battlerIndex: BattlerIndex | number; public player: boolean; - public fieldIndex: integer; + public fieldIndex: number; - constructor(battlerIndex?: BattlerIndex | integer) { + constructor(battlerIndex?: BattlerIndex | number) { super(); if (battlerIndex === undefined) { diff --git a/src/phases/return-phase.ts b/src/phases/return-phase.ts index 9dd13f6d5be..8a876268c8e 100644 --- a/src/phases/return-phase.ts +++ b/src/phases/return-phase.ts @@ -4,7 +4,7 @@ import { SwitchType } from "#enums/switch-type"; import { SwitchSummonPhase } from "./switch-summon-phase"; export class ReturnPhase extends SwitchSummonPhase { - constructor(fieldIndex: integer) { + constructor(fieldIndex: number) { super(SwitchType.SWITCH, fieldIndex, -1, true); } diff --git a/src/phases/scan-ivs-phase.ts b/src/phases/scan-ivs-phase.ts index b3385a5de94..519d7913b79 100644 --- a/src/phases/scan-ivs-phase.ts +++ b/src/phases/scan-ivs-phase.ts @@ -9,9 +9,9 @@ import i18next from "i18next"; import { PokemonPhase } from "./pokemon-phase"; export class ScanIvsPhase extends PokemonPhase { - private shownIvs: integer; + private shownIvs: number; - constructor(battlerIndex: BattlerIndex, shownIvs: integer) { + constructor(battlerIndex: BattlerIndex, shownIvs: number) { super(battlerIndex); this.shownIvs = shownIvs; diff --git a/src/phases/select-biome-phase.ts b/src/phases/select-biome-phase.ts index 41077dfffc1..ea4dcc4274b 100644 --- a/src/phases/select-biome-phase.ts +++ b/src/phases/select-biome-phase.ts @@ -37,7 +37,7 @@ export class SelectBiomePhase extends BattlePhase { } else if (Array.isArray(biomeLinks[currentBiome])) { let biomes: Biome[] = []; globalScene.executeWithSeedOffset(() => { - biomes = (biomeLinks[currentBiome] as (Biome | [Biome, integer])[]) + biomes = (biomeLinks[currentBiome] as (Biome | [Biome, number])[]) .filter(b => !Array.isArray(b) || !Utils.randSeedInt(b[1])) .map(b => !Array.isArray(b) ? b : b[0]); }, globalScene.currentBattle.waveIndex); @@ -46,7 +46,7 @@ export class SelectBiomePhase extends BattlePhase { globalScene.executeWithSeedOffset(() => { biomeChoices = (!Array.isArray(biomeLinks[currentBiome]) ? [ biomeLinks[currentBiome] as Biome ] - : biomeLinks[currentBiome] as (Biome | [Biome, integer])[]) + : biomeLinks[currentBiome] as (Biome | [Biome, number])[]) .filter((b, i) => !Array.isArray(b) || !Utils.randSeedInt(b[1])) .map(b => Array.isArray(b) ? b[0] : b); }, globalScene.currentBattle.waveIndex); diff --git a/src/phases/select-modifier-phase.ts b/src/phases/select-modifier-phase.ts index 6c8788c6a51..3b9a0a0405c 100644 --- a/src/phases/select-modifier-phase.ts +++ b/src/phases/select-modifier-phase.ts @@ -16,14 +16,14 @@ import type { CustomModifierSettings } from "#app/modifier/modifier-type"; import { isNullOrUndefined, NumberHolder } from "#app/utils"; export class SelectModifierPhase extends BattlePhase { - private rerollCount: integer; + private rerollCount: number; private modifierTiers?: ModifierTier[]; private customModifierSettings?: CustomModifierSettings; private isCopy: boolean; private typeOptions: ModifierTypeOption[]; - constructor(rerollCount: integer = 0, modifierTiers?: ModifierTier[], customModifierSettings?: CustomModifierSettings, isCopy: boolean = false) { + constructor(rerollCount: number = 0, modifierTiers?: ModifierTier[], customModifierSettings?: CustomModifierSettings, isCopy: boolean = false) { super(); this.rerollCount = rerollCount; @@ -66,7 +66,7 @@ export class SelectModifierPhase extends BattlePhase { this.typeOptions = this.getModifierTypeOptions(modifierCount.value); - const modifierSelectCallback = (rowCursor: integer, cursor: integer) => { + const modifierSelectCallback = (rowCursor: number, cursor: number) => { if (rowCursor < 0 || cursor < 0) { globalScene.ui.showText(i18next.t("battle:skipItemQuestion"), null, () => { globalScene.ui.setOverlayMode(Mode.CONFIRM, () => { @@ -78,7 +78,7 @@ export class SelectModifierPhase extends BattlePhase { return false; } let modifierType: ModifierType; - let cost: integer; + let cost: number; const rerollCost = this.getRerollCost(globalScene.lockModifierTiers); switch (rowCursor) { case 0: @@ -101,7 +101,7 @@ export class SelectModifierPhase extends BattlePhase { } break; case 1: - globalScene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer) => { + globalScene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: number, itemIndex: number, itemQuantity: number, toSlotIndex: number) => { if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) { const itemModifiers = globalScene.findModifiers(m => m instanceof PokemonHeldItemModifier && m.isTransferable && m.pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[]; @@ -200,7 +200,7 @@ export class SelectModifierPhase extends BattlePhase { if (modifierType! instanceof PokemonModifierType) { //TODO: is the bang correct? if (modifierType instanceof FusePokemonModifierType) { - globalScene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.SPLICE, -1, (fromSlotIndex: integer, spliceSlotIndex: integer) => { + globalScene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.SPLICE, -1, (fromSlotIndex: number, spliceSlotIndex: number) => { if (spliceSlotIndex !== undefined && fromSlotIndex < 6 && spliceSlotIndex < 6 && fromSlotIndex !== spliceSlotIndex) { globalScene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer()).then(() => { const modifier = modifierType.newModifier(party[fromSlotIndex], party[spliceSlotIndex])!; //TODO: is the bang correct? @@ -223,13 +223,13 @@ export class SelectModifierPhase extends BattlePhase { const tmMoveId = isTmModifier ? (modifierType as TmModifierType).moveId : undefined; - globalScene.ui.setModeWithoutClear(Mode.PARTY, partyUiMode, -1, (slotIndex: integer, option: PartyOption) => { + globalScene.ui.setModeWithoutClear(Mode.PARTY, partyUiMode, -1, (slotIndex: number, option: PartyOption) => { if (slotIndex < 6) { globalScene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer()).then(() => { const modifier = !isMoveModifier ? !isRememberMoveModifier ? modifierType.newModifier(party[slotIndex]) - : modifierType.newModifier(party[slotIndex], option as integer) + : modifierType.newModifier(party[slotIndex], option as number) : modifierType.newModifier(party[slotIndex], option - PartyOption.MOVE_1); applyModifier(modifier!, true); // TODO: is the bang correct? }); @@ -291,7 +291,7 @@ export class SelectModifierPhase extends BattlePhase { return ModifierPoolType.PLAYER; } - getModifierTypeOptions(modifierCount: integer): ModifierTypeOption[] { + getModifierTypeOptions(modifierCount: number): ModifierTypeOption[] { return getPlayerModifierTypeOptions(modifierCount, globalScene.getPlayerParty(), globalScene.lockModifierTiers ? this.modifierTiers : undefined, this.customModifierSettings); } diff --git a/src/phases/select-starter-phase.ts b/src/phases/select-starter-phase.ts index 20ba414147a..79012901a3a 100644 --- a/src/phases/select-starter-phase.ts +++ b/src/phases/select-starter-phase.ts @@ -26,7 +26,7 @@ export class SelectStarterPhase extends Phase { globalScene.ui.setMode(Mode.STARTER_SELECT, (starters: Starter[]) => { globalScene.ui.clearText(); - globalScene.ui.setMode(Mode.SAVE_SLOT, SaveSlotUiMode.SAVE, (slotId: integer) => { + globalScene.ui.setMode(Mode.SAVE_SLOT, SaveSlotUiMode.SAVE, (slotId: number) => { if (slotId === -1) { globalScene.clearPhaseQueue(); globalScene.pushPhase(new TitlePhase()); @@ -45,7 +45,7 @@ export class SelectStarterPhase extends Phase { initBattle(starters: Starter[]) { const party = globalScene.getPlayerParty(); const loadPokemonAssets: Promise[] = []; - starters.forEach((starter: Starter, i: integer) => { + starters.forEach((starter: Starter, i: number) => { if (!i && Overrides.STARTER_SPECIES_OVERRIDE) { starter.species = getPokemonSpecies(Overrides.STARTER_SPECIES_OVERRIDE as Species); } diff --git a/src/phases/select-target-phase.ts b/src/phases/select-target-phase.ts index b21415746fb..a30ef9000a5 100644 --- a/src/phases/select-target-phase.ts +++ b/src/phases/select-target-phase.ts @@ -8,7 +8,7 @@ import i18next from "#app/plugins/i18n"; import { allMoves } from "#app/data/move"; export class SelectTargetPhase extends PokemonPhase { - constructor(fieldIndex: integer) { + constructor(fieldIndex: number) { super(fieldIndex); } diff --git a/src/phases/show-party-exp-bar-phase.ts b/src/phases/show-party-exp-bar-phase.ts index 71bd39e3898..004592bc335 100644 --- a/src/phases/show-party-exp-bar-phase.ts +++ b/src/phases/show-party-exp-bar-phase.ts @@ -10,7 +10,7 @@ import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-pha export class ShowPartyExpBarPhase extends PlayerPartyMemberPokemonPhase { private expValue: number; - constructor(partyMemberIndex: integer, expValue: number) { + constructor(partyMemberIndex: number, expValue: number) { super(partyMemberIndex); this.expValue = expValue; diff --git a/src/phases/stat-stage-change-phase.ts b/src/phases/stat-stage-change-phase.ts index f2e95446139..359610b320c 100644 --- a/src/phases/stat-stage-change-phase.ts +++ b/src/phases/stat-stage-change-phase.ts @@ -16,14 +16,14 @@ export type StatStageChangeCallback = (target: Pokemon | null, changed: BattleSt export class StatStageChangePhase extends PokemonPhase { private stats: BattleStat[]; private selfTarget: boolean; - private stages: integer; + private stages: number; private showMessage: boolean; private ignoreAbilities: boolean; private canBeCopied: boolean; private onChange: StatStageChangeCallback | null; - constructor(battlerIndex: BattlerIndex, selfTarget: boolean, stats: BattleStat[], stages: integer, showMessage: boolean = true, ignoreAbilities: boolean = false, canBeCopied: boolean = true, onChange: StatStageChangeCallback | null = null) { + constructor(battlerIndex: BattlerIndex, selfTarget: boolean, stats: BattleStat[], stages: number, showMessage: boolean = true, ignoreAbilities: boolean = false, canBeCopied: boolean = true, onChange: StatStageChangeCallback | null = null) { super(battlerIndex); this.selfTarget = selfTarget; @@ -211,7 +211,7 @@ export class StatStageChangePhase extends PokemonPhase { } } - getStatStageChangeMessages(stats: BattleStat[], stages: integer, relStages: integer[]): string[] { + getStatStageChangeMessages(stats: BattleStat[], stages: number, relStages: number[]): string[] { const messages: string[] = []; const relStageStatIndexes = {}; diff --git a/src/phases/summon-missing-phase.ts b/src/phases/summon-missing-phase.ts index f32f6a377f5..459a0399964 100644 --- a/src/phases/summon-missing-phase.ts +++ b/src/phases/summon-missing-phase.ts @@ -4,7 +4,7 @@ import { SummonPhase } from "./summon-phase"; import { globalScene } from "#app/global-scene"; export class SummonMissingPhase extends SummonPhase { - constructor(fieldIndex: integer) { + constructor(fieldIndex: number) { super(fieldIndex); } diff --git a/src/phases/summon-phase.ts b/src/phases/summon-phase.ts index 72f5ec8640f..09eded9e52f 100644 --- a/src/phases/summon-phase.ts +++ b/src/phases/summon-phase.ts @@ -18,7 +18,7 @@ import { globalScene } from "#app/global-scene"; export class SummonPhase extends PartyMemberPokemonPhase { private loaded: boolean; - constructor(fieldIndex: integer, player: boolean = true, loaded: boolean = false) { + constructor(fieldIndex: number, player: boolean = true, loaded: boolean = false) { super(fieldIndex, player); this.loaded = loaded; diff --git a/src/phases/switch-phase.ts b/src/phases/switch-phase.ts index e763aee1521..34b70aeaf63 100644 --- a/src/phases/switch-phase.ts +++ b/src/phases/switch-phase.ts @@ -11,7 +11,7 @@ import { SwitchSummonPhase } from "./switch-summon-phase"; * for the player (if a switch would be valid for the current battle state). */ export class SwitchPhase extends BattlePhase { - protected readonly fieldIndex: integer; + protected readonly fieldIndex: number; private readonly switchType: SwitchType; private readonly isModal: boolean; private readonly doReturn: boolean; @@ -25,7 +25,7 @@ export class SwitchPhase extends BattlePhase { * @param doReturn Indicates if the party member on the field should be * recalled to ball or has already left the field. Passed to {@linkcode SwitchSummonPhase}. */ - constructor(switchType: SwitchType, fieldIndex: integer, isModal: boolean, doReturn: boolean) { + constructor(switchType: SwitchType, fieldIndex: number, isModal: boolean, doReturn: boolean) { super(); this.switchType = switchType; @@ -61,7 +61,7 @@ export class SwitchPhase extends BattlePhase { // Override field index to 0 in case of double battle where 2/3 remaining legal party members fainted at once const fieldIndex = globalScene.currentBattle.getBattlerCount() === 1 || globalScene.getPokemonAllowedInBattle().length > 1 ? this.fieldIndex : 0; - globalScene.ui.setMode(Mode.PARTY, this.isModal ? PartyUiMode.FAINT_SWITCH : PartyUiMode.POST_BATTLE_SWITCH, fieldIndex, (slotIndex: integer, option: PartyOption) => { + globalScene.ui.setMode(Mode.PARTY, this.isModal ? PartyUiMode.FAINT_SWITCH : PartyUiMode.POST_BATTLE_SWITCH, fieldIndex, (slotIndex: number, option: PartyOption) => { if (slotIndex >= globalScene.currentBattle.getBattlerCount() && slotIndex < 6) { // Remove any pre-existing PostSummonPhase under the same field index. // Pre-existing PostSummonPhases may occur when this phase is invoked during a prompt to switch at the start of a wave. diff --git a/src/phases/switch-summon-phase.ts b/src/phases/switch-summon-phase.ts index 94e57435922..d24ef68ebb2 100644 --- a/src/phases/switch-summon-phase.ts +++ b/src/phases/switch-summon-phase.ts @@ -16,7 +16,7 @@ import { SwitchType } from "#enums/switch-type"; export class SwitchSummonPhase extends SummonPhase { private readonly switchType: SwitchType; - private readonly slotIndex: integer; + private readonly slotIndex: number; private readonly doReturn: boolean; private lastPokemon: Pokemon; @@ -29,7 +29,7 @@ export class SwitchSummonPhase extends SummonPhase { * @param doReturn boolean whether to render "comeback" dialogue * @param player boolean if the switch is from the player */ - constructor(switchType: SwitchType, fieldIndex: integer, slotIndex: integer, doReturn: boolean, player?: boolean) { + constructor(switchType: SwitchType, fieldIndex: number, slotIndex: number, doReturn: boolean, player?: boolean) { super(fieldIndex, player !== undefined ? player : true); this.switchType = switchType; diff --git a/src/phases/title-phase.ts b/src/phases/title-phase.ts index 219ff441c52..4e96214d600 100644 --- a/src/phases/title-phase.ts +++ b/src/phases/title-phase.ts @@ -133,7 +133,7 @@ export class TitlePhase extends Phase { label: i18next.t("menu:loadGame"), handler: () => { globalScene.ui.setOverlayMode(Mode.SAVE_SLOT, SaveSlotUiMode.LOAD, - (slotId: integer) => { + (slotId: number) => { if (slotId === -1) { return this.showOptions(); } @@ -150,6 +150,14 @@ export class TitlePhase extends Phase { }, keepOpen: true }, + { + label: i18next.t("menu:runHistory"), + handler: () => { + globalScene.ui.setOverlayMode(Mode.RUN_HISTORY); + return true; + }, + keepOpen: true + }, { label: i18next.t("menu:settings"), handler: () => { @@ -166,7 +174,7 @@ export class TitlePhase extends Phase { globalScene.ui.setMode(Mode.TITLE, config); } - loadSaveSlot(slotId: integer): void { + loadSaveSlot(slotId: number): void { globalScene.sessionSlotId = slotId > -1 || !loggedInUser ? slotId : loggedInUser.lastSessionSlot; globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.resetModeChain(); @@ -184,7 +192,7 @@ export class TitlePhase extends Phase { } initDailyRun(): void { - globalScene.ui.setMode(Mode.SAVE_SLOT, SaveSlotUiMode.SAVE, (slotId: integer) => { + globalScene.ui.setMode(Mode.SAVE_SLOT, SaveSlotUiMode.SAVE, (slotId: number) => { globalScene.clearPhaseQueue(); if (slotId === -1) { globalScene.pushPhase(new TitlePhase()); diff --git a/src/phases/victory-phase.ts b/src/phases/victory-phase.ts index 8918b664a36..13e04569ef3 100644 --- a/src/phases/victory-phase.ts +++ b/src/phases/victory-phase.ts @@ -18,7 +18,7 @@ export class VictoryPhase extends PokemonPhase { /** If true, indicates that the phase is intended for EXP purposes only, and not to continue a battle to next phase */ isExpOnly: boolean; - constructor(battlerIndex: BattlerIndex | integer, isExpOnly: boolean = false) { + constructor(battlerIndex: BattlerIndex | number, isExpOnly: boolean = false) { super(battlerIndex); this.isExpOnly = isExpOnly; diff --git a/src/pipelines/sprite.ts b/src/pipelines/sprite.ts index 1fc3b771897..67639d6450a 100644 --- a/src/pipelines/sprite.ts +++ b/src/pipelines/sprite.ts @@ -351,7 +351,7 @@ export default class SpritePipeline extends FieldSpritePipeline { const data = sprite.pipelineData; const tone = data["tone"] as number[]; - const teraColor = data["teraColor"] as integer[] ?? [ 0, 0, 0 ]; + const teraColor = data["teraColor"] as number[] ?? [ 0, 0, 0 ]; const hasShadow = data["hasShadow"] as boolean; const yShadowOffset = data["yShadowOffset"] as number; const ignoreFieldPos = data["ignoreFieldPos"] as boolean; @@ -389,8 +389,8 @@ export default class SpritePipeline extends FieldSpritePipeline { const fusionSpriteColors = ((ignoreOverride && data["fusionSpriteColorsBase"]) || data["fusionSpriteColors"] || []) as number[][]; const emptyColors = [ 0, 0, 0, 0 ]; - const flatSpriteColors: integer[] = []; - const flatFusionSpriteColors: integer[] = []; + const flatSpriteColors: number[] = []; + const flatFusionSpriteColors: number[] = []; for (let c = 0; c < 32; c++) { flatSpriteColors.splice(flatSpriteColors.length, 0, ...(c < spriteColors.length ? spriteColors[c] : emptyColors)); flatFusionSpriteColors.splice(flatFusionSpriteColors.length, 0, ...(c < fusionSpriteColors.length ? fusionSpriteColors[c] : emptyColors)); @@ -406,14 +406,14 @@ export default class SpritePipeline extends FieldSpritePipeline { const sprite = (gameObject as Phaser.GameObjects.Sprite); const data = sprite.pipelineData; - const variant: integer = data.hasOwnProperty("variant") + const variant: number = data.hasOwnProperty("variant") ? data["variant"] : sprite.parentContainer instanceof Pokemon ? sprite.parentContainer.variant : 0; let variantColors; const emptyColors = [ 0, 0, 0, 0 ]; - const flatBaseColors: integer[] = []; + const flatBaseColors: number[] = []; const flatVariantColors: number[] = []; if ((sprite.parentContainer instanceof Pokemon ? sprite.parentContainer.shiny : !!data["shiny"]) diff --git a/src/scene-base.ts b/src/scene-base.ts index 9af97b8e6d4..c6ca9bb8ba2 100644 --- a/src/scene-base.ts +++ b/src/scene-base.ts @@ -41,7 +41,7 @@ export class SceneBase extends Phaser.Scene { } } - loadSpritesheet(key: string, folder: string, size: integer, filename?: string) { + loadSpritesheet(key: string, folder: string, size: number, filename?: string) { if (!filename) { filename = `${key}.png`; } diff --git a/src/system/achv.ts b/src/system/achv.ts index e0c9f0cf052..bd9348a52bf 100644 --- a/src/system/achv.ts +++ b/src/system/achv.ts @@ -25,7 +25,7 @@ export class Achv { public name: string; public description: string; public iconImage: string; - public score: integer; + public score: number; public secret: boolean; public hasParent: boolean; @@ -33,7 +33,7 @@ export class Achv { private conditionFunc: ConditionFn | undefined; - constructor(localizationKey:string, name: string, description: string, iconImage: string, score: integer, conditionFunc?: ConditionFn) { + constructor(localizationKey:string, name: string, description: string, iconImage: string, score: number, conditionFunc?: ConditionFn) { this.name = name; this.description = description; this.iconImage = iconImage; @@ -89,58 +89,58 @@ export class Achv { } export class MoneyAchv extends Achv { - moneyAmount: integer; + moneyAmount: number; - constructor(localizationKey: string, name: string, moneyAmount: integer, iconImage: string, score: integer) { + constructor(localizationKey: string, name: string, moneyAmount: number, iconImage: string, score: number) { super(localizationKey, name, "", iconImage, score, (_args: any[]) => globalScene.money >= this.moneyAmount); this.moneyAmount = moneyAmount; } } export class RibbonAchv extends Achv { - ribbonAmount: integer; + ribbonAmount: number; - constructor(localizationKey: string, name: string, ribbonAmount: integer, iconImage: string, score: integer) { + constructor(localizationKey: string, name: string, ribbonAmount: number, iconImage: string, score: number) { super(localizationKey, name, "", iconImage, score, (_args: any[]) => globalScene.gameData.gameStats.ribbonsOwned >= this.ribbonAmount); this.ribbonAmount = ribbonAmount; } } export class DamageAchv extends Achv { - damageAmount: integer; + damageAmount: number; - constructor(localizationKey: string, name: string, damageAmount: integer, iconImage: string, score: integer) { + constructor(localizationKey: string, name: string, damageAmount: number, iconImage: string, score: number) { super(localizationKey, name, "", iconImage, score, (args: any[]) => (args[0] instanceof Utils.NumberHolder ? args[0].value : args[0]) >= this.damageAmount); this.damageAmount = damageAmount; } } export class HealAchv extends Achv { - healAmount: integer; + healAmount: number; - constructor(localizationKey: string, name: string, healAmount: integer, iconImage: string, score: integer) { + constructor(localizationKey: string, name: string, healAmount: number, iconImage: string, score: number) { super(localizationKey, name, "", iconImage, score, (args: any[]) => (args[0] instanceof Utils.NumberHolder ? args[0].value : args[0]) >= this.healAmount); this.healAmount = healAmount; } } export class LevelAchv extends Achv { - level: integer; + level: number; - constructor(localizationKey: string, name: string, level: integer, iconImage: string, score: integer) { + constructor(localizationKey: string, name: string, level: number, iconImage: string, score: number) { super(localizationKey, name, "", iconImage, score, (args: any[]) => (args[0] instanceof Utils.NumberHolder ? args[0].value : args[0]) >= this.level); this.level = level; } } export class ModifierAchv extends Achv { - constructor(localizationKey: string, name: string, description: string, iconImage: string, score: integer, modifierFunc: (modifier: Modifier) => boolean) { + constructor(localizationKey: string, name: string, description: string, iconImage: string, score: number, modifierFunc: (modifier: Modifier) => boolean) { super(localizationKey, name, description, iconImage, score, (args: any[]) => modifierFunc((args[0] as Modifier))); } } export class ChallengeAchv extends Achv { - constructor(localizationKey: string, name: string, description: string, iconImage: string, score: integer, challengeFunc: (challenge: Challenge) => boolean) { + constructor(localizationKey: string, name: string, description: string, iconImage: string, score: number, challengeFunc: (challenge: Challenge) => boolean) { super(localizationKey, name, description, iconImage, score, (args: any[]) => challengeFunc(args[0] as Challenge)); } } @@ -370,7 +370,7 @@ export const achvs = { export function initAchievements() { const achvKeys = Object.keys(achvs); - achvKeys.forEach((a: string, i: integer) => { + achvKeys.forEach((a: string, i: number) => { achvs[a].id = a; if (achvs[a].hasParent) { achvs[a].parentId = achvKeys[i - 1]; diff --git a/src/system/challenge-data.ts b/src/system/challenge-data.ts index 76a3392861d..87299ae653a 100644 --- a/src/system/challenge-data.ts +++ b/src/system/challenge-data.ts @@ -2,9 +2,9 @@ import type { Challenge } from "#app/data/challenge"; import { copyChallenge } from "#app/data/challenge"; export default class ChallengeData { - public id: integer; - public value: integer; - public severity: integer; + public id: number; + public value: number; + public severity: number; constructor(source: Challenge | any) { this.id = source.id; diff --git a/src/system/egg-data.ts b/src/system/egg-data.ts index 7b75f387c63..8296c2da98e 100644 --- a/src/system/egg-data.ts +++ b/src/system/egg-data.ts @@ -5,11 +5,11 @@ import { EGG_SEED, Egg } from "../data/egg"; import type { EggSourceType } from "#app/enums/egg-source-types"; export default class EggData { - public id: integer; + public id: number; public tier: EggTier; public sourceType: EggSourceType; - public hatchWaves: integer; - public timestamp: integer; + public hatchWaves: number; + public timestamp: number; public variantTier: VariantTier; public isShiny: boolean; public species: Species; diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 58d416eb468..7282d2730a4 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -70,7 +70,7 @@ export const defaultStarterSpecies: Species[] = [ const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet necessary -export function getDataTypeKey(dataType: GameDataType, slotId: integer = 0): string { +export function getDataTypeKey(dataType: GameDataType, slotId: number = 0): string { switch (dataType) { case GameDataType.SYSTEM: return "data"; @@ -104,8 +104,8 @@ export function decrypt(data: string, bypassLogin: boolean): string { } export interface SystemSaveData { - trainerId: integer; - secretId: integer; + trainerId: number; + secretId: number; gender: PlayerGender; dexData: DexData; starterData: StarterData; @@ -116,14 +116,14 @@ export interface SystemSaveData { voucherCounts: VoucherCounts; eggs: EggData[]; gameVersion: string; - timestamp: integer; - eggPity: integer[]; - unlockPity: integer[]; + timestamp: number; + eggPity: number[]; + unlockPity: number[]; } export interface SessionSaveData { seed: string; - playTime: integer; + playTime: number; gameMode: GameModes; party: PokemonData[]; enemyParty: PokemonData[]; @@ -131,46 +131,46 @@ export interface SessionSaveData { enemyModifiers: PersistentModifierData[]; arena: ArenaData; pokeballCounts: PokeballCounts; - money: integer; - score: integer; - waveIndex: integer; + money: number; + score: number; + waveIndex: number; battleType: BattleType; trainer: TrainerData; gameVersion: string; - timestamp: integer; + timestamp: number; challenges: ChallengeData[]; mysteryEncounterType: MysteryEncounterType | -1; // Only defined when current wave is ME, mysteryEncounterSaveData: MysteryEncounterSaveData; } interface Unlocks { - [key: integer]: boolean; + [key: number]: boolean; } interface AchvUnlocks { - [key: string]: integer + [key: string]: number } interface VoucherUnlocks { - [key: string]: integer + [key: string]: number } export interface VoucherCounts { - [type: string]: integer; + [type: string]: number; } export interface DexData { - [key: integer]: DexEntry + [key: number]: DexEntry } export interface DexEntry { seenAttr: bigint; caughtAttr: bigint; - natureAttr: integer, - seenCount: integer; - caughtCount: integer; - hatchedCount: integer; - ivs: integer[]; + natureAttr: number, + seenCount: number; + caughtCount: number; + hatchedCount: number; + ivs: number[]; } export const DexAttr = { @@ -188,7 +188,7 @@ export interface DexAttrProps { shiny: boolean; female: boolean; variant: Variant; - formIndex: integer; + formIndex: number; } export const AbilityAttr = { @@ -209,18 +209,18 @@ export interface RunEntry { export type StarterMoveset = [ Moves ] | [ Moves, Moves ] | [ Moves, Moves, Moves ] | [ Moves, Moves, Moves, Moves ]; export interface StarterFormMoveData { - [key: integer]: StarterMoveset + [key: number]: StarterMoveset } export interface StarterMoveData { - [key: integer]: StarterMoveset | StarterFormMoveData + [key: number]: StarterMoveset | StarterFormMoveData } export interface StarterAttributes { - nature?: integer; - ability?: integer; - variant?: integer; - form?: integer; + nature?: number; + ability?: number; + variant?: number; + form?: number; female?: boolean; shiny?: boolean; favorite?: boolean; @@ -228,7 +228,7 @@ export interface StarterAttributes { } export interface StarterPreferences { - [key: integer]: StarterAttributes; + [key: number]: StarterAttributes; } // the latest data saved/loaded for the Starter Preferences. Required to reduce read/writes. Initialize as "{}", since this is the default value and no data needs to be stored if present. @@ -263,17 +263,17 @@ export class StarterPrefs { export interface StarterDataEntry { moveset: StarterMoveset | StarterFormMoveData | null; - eggMoves: integer; - candyCount: integer; - friendship: integer; - abilityAttr: integer; - passiveAttr: integer; - valueReduction: integer; - classicWinCount: integer; + eggMoves: number; + candyCount: number; + friendship: number; + abilityAttr: number; + passiveAttr: number; + valueReduction: number; + classicWinCount: number; } export interface StarterData { - [key: integer]: StarterDataEntry + [key: number]: StarterDataEntry } export interface TutorialFlags { @@ -303,8 +303,8 @@ const systemShortKeys = { }; export class GameData { - public trainerId: integer; - public secretId: integer; + public trainerId: number; + public secretId: number; public gender: PlayerGender; @@ -323,8 +323,8 @@ export class GameData { public voucherUnlocks: VoucherUnlocks; public voucherCounts: VoucherCounts; public eggs: Egg[]; - public eggPity: integer[]; - public unlockPity: integer[]; + public eggPity: number[]; + public unlockPity: number[]; constructor() { this.loadSettings(); @@ -733,7 +733,7 @@ export class GameData { * @param valueIndex index of the setting's option * @returns true */ - public saveSetting(setting: string, valueIndex: integer): boolean { + public saveSetting(setting: string, valueIndex: number): boolean { let settings: object = {}; if (localStorage.hasOwnProperty("settings")) { settings = JSON.parse(localStorage.getItem("settings")!); // TODO: is this bang correct? @@ -816,7 +816,7 @@ export class GameData { * to update the specified setting with the new value. Finally, it saves the updated settings back * to localStorage and returns `true` to indicate success. */ - public saveControlSetting(device: Device, localStoragePropertyName: string, setting: SettingGamepad|SettingKeyboard, settingDefaults, valueIndex: integer): boolean { + public saveControlSetting(device: Device, localStoragePropertyName: string, setting: SettingGamepad|SettingKeyboard, settingDefaults, valueIndex: number): boolean { let settingsControls: object = {}; // Initialize an empty object to hold the gamepad settings if (localStorage.hasOwnProperty(localStoragePropertyName)) { // Check if 'settingsControls' exists in localStorage @@ -968,7 +968,7 @@ export class GameData { } as SessionSaveData; } - getSession(slotId: integer): Promise { + getSession(slotId: number): Promise { return new Promise(async (resolve, reject) => { if (slotId < 0) { return resolve(null); @@ -1006,7 +1006,7 @@ export class GameData { }); } - loadSession(slotId: integer, sessionData?: SessionSaveData): Promise { + loadSession(slotId: number, sessionData?: SessionSaveData): Promise { return new Promise(async (resolve, reject) => { try { const initSessionFromData = async (sessionData: SessionSaveData) => { @@ -1137,7 +1137,7 @@ export class GameData { * @param slotId the slot to clear * @returns Promise with result `true` if the session was deleted successfully, `false` otherwise */ - deleteSession(slotId: integer): Promise { + deleteSession(slotId: number): Promise { return new Promise(resolve => { if (bypassLogin) { localStorage.removeItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`); @@ -1206,7 +1206,7 @@ export class GameData { * After session data is removed, attempt to update user info so the menu updates * To delete an unfinished run instead, use {@linkcode deleteSession} */ - async tryClearSession(slotId: integer): Promise<[success: boolean, newClear: boolean]> { + async tryClearSession(slotId: number): Promise<[success: boolean, newClear: boolean]> { let result: [boolean, boolean] = [ false, false ]; if (bypassLogin) { @@ -1361,7 +1361,7 @@ export class GameData { }); } - public tryExportData(dataType: GameDataType, slotId: integer = 0): Promise { + public tryExportData(dataType: GameDataType, slotId: number = 0): Promise { return new Promise(resolve => { const dataKey: string = `${getDataTypeKey(dataType, slotId)}_${loggedInUser?.username}`; const handleData = (dataStr: string) => { @@ -1407,7 +1407,7 @@ export class GameData { }); } - public importData(dataType: GameDataType, slotId: integer = 0): void { + public importData(dataType: GameDataType, slotId: number = 0): void { const dataKey = `${getDataTypeKey(dataType, slotId)}_${loggedInUser?.username}`; let saveFile: any = document.getElementById("saveFile"); @@ -1695,7 +1695,7 @@ export class GameData { }); } - incrementRibbonCount(species: PokemonSpecies, forStarter: boolean = false): integer { + incrementRibbonCount(species: PokemonSpecies, forStarter: boolean = false): number { const speciesIdToIncrement: Species = species.getRootSpeciesId(forStarter); if (!this.starterData[speciesIdToIncrement].classicWinCount) { @@ -1706,7 +1706,7 @@ export class GameData { globalScene.gameData.gameStats.ribbonsOwned++; } - const ribbonsInStats: integer = globalScene.gameData.gameStats.ribbonsOwned; + const ribbonsInStats: number = globalScene.gameData.gameStats.ribbonsOwned; if (ribbonsInStats >= 100) { globalScene.validateAchv(achvs._100_RIBBONS); @@ -1733,7 +1733,7 @@ export class GameData { * @param species * @param count */ - addStarterCandy(species: PokemonSpecies, count: integer): void { + addStarterCandy(species: PokemonSpecies, count: number): void { // Only gain candies if the Pokemon has already been marked as caught in dex (ignore "rental" pokemon) const speciesRootForm = species.getRootSpeciesId(); if (globalScene.gameData.dexData[speciesRootForm].caughtAttr) { @@ -1749,7 +1749,7 @@ export class GameData { * @param showMessage Default true. If true, will display message for unlocked egg move * @param prependSpeciesToMessage Default false. If true, will change message from "X Egg Move Unlocked!" to "Bulbasaur X Egg Move Unlocked!" */ - setEggMoveUnlocked(species: PokemonSpecies, eggMoveIndex: integer, showMessage: boolean = true, prependSpeciesToMessage: boolean = false): Promise { + setEggMoveUnlocked(species: PokemonSpecies, eggMoveIndex: number, showMessage: boolean = true, prependSpeciesToMessage: boolean = false): Promise { return new Promise(resolve => { const speciesId = species.speciesId; if (!speciesEggMoves.hasOwnProperty(speciesId) || !speciesEggMoves[speciesId][eggMoveIndex]) { @@ -1808,7 +1808,7 @@ export class GameData { _unlockSpeciesNature(species.speciesId); } - updateSpeciesDexIvs(speciesId: Species, ivs: integer[]): void { + updateSpeciesDexIvs(speciesId: Species, ivs: number[]): void { let dexEntry: DexEntry; do { dexEntry = globalScene.gameData.dexData[speciesId]; @@ -1824,7 +1824,7 @@ export class GameData { } while (pokemonPrevolutions.hasOwnProperty(speciesId) && (speciesId = pokemonPrevolutions[speciesId])); } - getSpeciesCount(dexEntryPredicate: (entry: DexEntry) => boolean): integer { + getSpeciesCount(dexEntryPredicate: (entry: DexEntry) => boolean): number { const dexKeys = Object.keys(this.dexData); let speciesCount = 0; for (const s of dexKeys) { @@ -1835,7 +1835,7 @@ export class GameData { return speciesCount; } - getStarterCount(dexEntryPredicate: (entry: DexEntry) => boolean): integer { + getStarterCount(dexEntryPredicate: (entry: DexEntry) => boolean): number { const starterKeys = Object.keys(speciesStarterCosts); let starterCount = 0; for (const s of starterKeys) { @@ -1906,7 +1906,7 @@ export class GameData { }; } - getStarterSpeciesDefaultAbilityIndex(species: PokemonSpecies): integer { + getStarterSpeciesDefaultAbilityIndex(species: PokemonSpecies): number { const abilityAttr = this.starterData[species.speciesId].abilityAttr; return abilityAttr & AbilityAttr.ABILITY_1 ? 0 : !species.ability2 || abilityAttr & AbilityAttr.ABILITY_2 ? 1 : 2; } @@ -1921,15 +1921,15 @@ export class GameData { return 0 as Nature; } - getSpeciesDefaultNatureAttr(species: PokemonSpecies): integer { + getSpeciesDefaultNatureAttr(species: PokemonSpecies): number { return 1 << (this.getSpeciesDefaultNature(species)); } - getDexAttrLuck(dexAttr: bigint): integer { + getDexAttrLuck(dexAttr: bigint): number { return dexAttr & DexAttr.SHINY ? dexAttr & DexAttr.VARIANT_3 ? 3 : dexAttr & DexAttr.VARIANT_2 ? 2 : 1 : 0; } - getNaturesForAttr(natureAttr: integer = 0): Nature[] { + getNaturesForAttr(natureAttr: number = 0): Nature[] { const ret: Nature[] = []; for (let n = 0; n < 25; n++) { if (natureAttr & (1 << (n + 1))) { @@ -1962,7 +1962,7 @@ export class GameData { return cost.value; } - getFormIndex(attr: bigint): integer { + getFormIndex(attr: bigint): number { if (!attr || attr < DexAttr.DEFAULT_FORM) { return 0; } @@ -1973,7 +1973,7 @@ export class GameData { return f; } - getFormAttr(formIndex: integer): bigint { + getFormAttr(formIndex: number): bigint { return BigInt(1) << BigInt(7 + formIndex); } diff --git a/src/system/game-stats.ts b/src/system/game-stats.ts index a8b74f29bb7..5553a0332fc 100644 --- a/src/system/game-stats.ts +++ b/src/system/game-stats.ts @@ -1,43 +1,43 @@ -// public (.*?): integer; +// public (.*?): number; // this.$1 = source?.$1 || 0; export class GameStats { - public playTime: integer; - public battles: integer; - public classicSessionsPlayed: integer; - public sessionsWon: integer; - public ribbonsOwned: integer; - public dailyRunSessionsPlayed: integer; - public dailyRunSessionsWon: integer; - public endlessSessionsPlayed: integer; - public highestEndlessWave: integer; - public highestLevel: integer; - public highestMoney: integer; - public highestDamage: integer; - public highestHeal: integer; - public pokemonSeen: integer; - public pokemonDefeated: integer; - public pokemonCaught: integer; - public pokemonHatched: integer; - public subLegendaryPokemonSeen: integer; - public subLegendaryPokemonCaught: integer; - public subLegendaryPokemonHatched: integer; - public legendaryPokemonSeen: integer; - public legendaryPokemonCaught: integer; - public legendaryPokemonHatched: integer; - public mythicalPokemonSeen: integer; - public mythicalPokemonCaught: integer; - public mythicalPokemonHatched: integer; - public shinyPokemonSeen: integer; - public shinyPokemonCaught: integer; - public shinyPokemonHatched: integer; - public pokemonFused: integer; - public trainersDefeated: integer; - public eggsPulled: integer; - public rareEggsPulled: integer; - public epicEggsPulled: integer; - public legendaryEggsPulled: integer; - public manaphyEggsPulled: integer; + public playTime: number; + public battles: number; + public classicSessionsPlayed: number; + public sessionsWon: number; + public ribbonsOwned: number; + public dailyRunSessionsPlayed: number; + public dailyRunSessionsWon: number; + public endlessSessionsPlayed: number; + public highestEndlessWave: number; + public highestLevel: number; + public highestMoney: number; + public highestDamage: number; + public highestHeal: number; + public pokemonSeen: number; + public pokemonDefeated: number; + public pokemonCaught: number; + public pokemonHatched: number; + public subLegendaryPokemonSeen: number; + public subLegendaryPokemonCaught: number; + public subLegendaryPokemonHatched: number; + public legendaryPokemonSeen: number; + public legendaryPokemonCaught: number; + public legendaryPokemonHatched: number; + public mythicalPokemonSeen: number; + public mythicalPokemonCaught: number; + public mythicalPokemonHatched: number; + public shinyPokemonSeen: number; + public shinyPokemonCaught: number; + public shinyPokemonHatched: number; + public pokemonFused: number; + public trainersDefeated: number; + public eggsPulled: number; + public rareEggsPulled: number; + public epicEggsPulled: number; + public legendaryEggsPulled: number; + public manaphyEggsPulled: number; constructor(source?: any) { this.playTime = source?.playTime || 0; diff --git a/src/system/modifier-data.ts b/src/system/modifier-data.ts index d153236c93e..4816115f586 100644 --- a/src/system/modifier-data.ts +++ b/src/system/modifier-data.ts @@ -8,7 +8,7 @@ export default class ModifierData { public typeId: string; public typePregenArgs: any[]; public args: any[]; - public stackCount: integer; + public stackCount: number; public className: string; diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index 92eca5c3e9f..6459bb5033d 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -15,47 +15,47 @@ import type { Species } from "#enums/species"; import { CustomPokemonData } from "#app/data/custom-pokemon-data"; export default class PokemonData { - public id: integer; + public id: number; public player: boolean; public species: Species; public nickname: string; - public formIndex: integer; - public abilityIndex: integer; + public formIndex: number; + public abilityIndex: number; public passive: boolean; public shiny: boolean; public variant: Variant; public pokeball: PokeballType; - public level: integer; - public exp: integer; - public levelExp: integer; + public level: number; + public exp: number; + public levelExp: number; public gender: Gender; - public hp: integer; - public stats: integer[]; - public ivs: integer[]; + public hp: number; + public stats: number[]; + public ivs: number[]; public nature: Nature; public moveset: (PokemonMove | null)[]; public status: Status | null; - public friendship: integer; - public metLevel: integer; + public friendship: number; + public metLevel: number; public metBiome: Biome | -1; // -1 for starters public metSpecies: Species; public metWave: number; // 0 for unknown (previous saves), -1 for starters - public luck: integer; + public luck: number; public pauseEvolutions: boolean; public pokerus: boolean; public usedTMs: Moves[]; - public evoCounter: integer; + public evoCounter: number; public fusionSpecies: Species; - public fusionFormIndex: integer; - public fusionAbilityIndex: integer; + public fusionFormIndex: number; + public fusionAbilityIndex: number; public fusionShiny: boolean; public fusionVariant: Variant; public fusionGender: Gender; - public fusionLuck: integer; + public fusionLuck: number; public boss: boolean; - public bossSegments?: integer; + public bossSegments?: number; public summonData: PokemonSummonData; @@ -163,7 +163,7 @@ export default class PokemonData { } } - toPokemon(battleType?: BattleType, partyMemberIndex: integer = 0, double: boolean = false): Pokemon { + toPokemon(battleType?: BattleType, partyMemberIndex: number = 0, double: boolean = false): Pokemon { const species = getPokemonSpecies(this.species); const ret: Pokemon = this.player ? globalScene.addPlayerPokemon(species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this, (playerPokemon) => { diff --git a/src/system/session-history.ts b/src/system/session-history.ts index e6901b2fa93..d9dd2022d8f 100644 --- a/src/system/session-history.ts +++ b/src/system/session-history.ts @@ -10,13 +10,13 @@ export enum SessionHistoryResult { export interface SessionHistory { seed: string; - playTime: integer; + playTime: number; result: SessionHistoryResult, gameMode: GameModes; party: PokemonData[]; modifiers: PersistentModifierData[]; - money: integer; - waveIndex: integer; + money: number; + waveIndex: number; gameVersion: string; - timestamp: integer; + timestamp: number; } diff --git a/src/system/settings/settings-gamepad.ts b/src/system/settings/settings-gamepad.ts index 18973666766..d26c0c9f019 100644 --- a/src/system/settings/settings-gamepad.ts +++ b/src/system/settings/settings-gamepad.ts @@ -80,7 +80,7 @@ export const settingGamepadBlackList = [ SettingKeyboard.Button_Right, ]; -export function setSettingGamepad(setting: SettingGamepad, value: integer): boolean { +export function setSettingGamepad(setting: SettingGamepad, value: number): boolean { switch (setting) { case SettingGamepad.Gamepad_Support: // if we change the value of the gamepad support, we call a method in the inputController to diff --git a/src/system/settings/settings-keyboard.ts b/src/system/settings/settings-keyboard.ts index f4adc30ee52..95ad4ba41f1 100644 --- a/src/system/settings/settings-keyboard.ts +++ b/src/system/settings/settings-keyboard.ts @@ -133,7 +133,7 @@ export const settingKeyboardBlackList = [ ]; -export function setSettingKeyboard(setting: SettingKeyboard, value: integer): boolean { +export function setSettingKeyboard(setting: SettingKeyboard, value: number): boolean { switch (setting) { case SettingKeyboard.Button_Up: case SettingKeyboard.Button_Down: diff --git a/src/system/settings/settings.ts b/src/system/settings/settings.ts index 5c598a0ea5a..a7a0e83f5ff 100644 --- a/src/system/settings/settings.ts +++ b/src/system/settings/settings.ts @@ -713,7 +713,7 @@ export function resetSettings() { * @param value value to update setting with * @returns true if successful, false if not */ -export function setSetting(setting: string, value: integer): boolean { +export function setSetting(setting: string, value: number): boolean { const index: number = settingIndex(setting); if (index === -1) { return false; diff --git a/src/system/trainer-data.ts b/src/system/trainer-data.ts index 51dfdde9ec1..134d16e25ef 100644 --- a/src/system/trainer-data.ts +++ b/src/system/trainer-data.ts @@ -4,7 +4,7 @@ import Trainer, { TrainerVariant } from "../field/trainer"; export default class TrainerData { public trainerType: TrainerType; public variant: TrainerVariant; - public partyTemplateIndex: integer; + public partyTemplateIndex: number; public name: string; public partnerName: string; diff --git a/src/test/abilities/good_as_gold.test.ts b/src/test/abilities/good_as_gold.test.ts new file mode 100644 index 00000000000..ecda1a0e031 --- /dev/null +++ b/src/test/abilities/good_as_gold.test.ts @@ -0,0 +1,143 @@ +import { BattlerIndex } from "#app/battle"; +import { allAbilities } from "#app/data/ability"; +import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagType } from "#app/enums/arena-tag-type"; +import { BattlerTagType } from "#app/enums/battler-tag-type"; +import { Stat } from "#app/enums/stat"; +import { StatusEffect } from "#app/enums/status-effect"; +import { WeatherType } from "#app/enums/weather-type"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +describe("Abilities - Good As Gold", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([ Moves.SPLASH ]) + .ability(Abilities.GOOD_AS_GOLD) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should block normal status moves", async () => { + game.override.enemyMoveset( [ Moves.GROWL ] ); + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + const player = game.scene.getPlayerPokemon()!; + + game.move.select(Moves.SPLASH, 0); + + await game.phaseInterceptor.to("BerryPhase"); + + expect(player.battleData.abilitiesApplied[0]).toBe(Abilities.GOOD_AS_GOLD); + expect(player.getStatStage(Stat.ATK)).toBe(0); + }); + + it("should block memento and prevent the user from fainting", async () => { + game.override.enemyMoveset( [ Moves.MEMENTO ] ); + await game.classicMode.startBattle([ Species.MAGIKARP ]); + game.move.select(Moves.MEMENTO); + await game.phaseInterceptor.to("BerryPhase"); + expect(game.scene.getPlayerPokemon()!.isFainted()).toBe(false); + expect(game.scene.getEnemyPokemon()?.getStatStage(Stat.ATK)).toBe(0); + }); + + it("should not block any status moves that target the field, one side, or all pokemon", async () => { + game.override.battleType("double"); + game.override.enemyMoveset( [ Moves.STEALTH_ROCK, Moves.HAZE ] ); + game.override.moveset([ Moves.SWORDS_DANCE, Moves.SAFEGUARD ]); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.FEEBAS ]); + const [ good_as_gold, ball_fetch ] = game.scene.getPlayerField(); + + // Force second pokemon to have ball fetch to isolate to a single mon. + vi.spyOn(ball_fetch, "getAbility").mockReturnValue(allAbilities[Abilities.BALL_FETCH]); + + game.move.select(Moves.SWORDS_DANCE, 0); + game.move.select(Moves.SAFEGUARD, 1); + await game.forceEnemyMove(Moves.STEALTH_ROCK); + await game.forceEnemyMove(Moves.HAZE); + await game.setTurnOrder( [ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ] ); + await game.phaseInterceptor.to("BerryPhase"); + expect(good_as_gold.getAbility().id).toBe(Abilities.GOOD_AS_GOLD); + expect(good_as_gold.getStatStage(Stat.ATK)).toBe(0); + expect(game.scene.arena.getTagOnSide(ArenaTagType.STEALTH_ROCK, ArenaTagSide.PLAYER)).toBeDefined(); + expect(game.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, ArenaTagSide.PLAYER)).toBeDefined(); + }); + + it("should not block field targeted effects in singles", async () => { + game.override.battleType("single"); + game.override.enemyMoveset( [ Moves.SPIKES ] ); + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + game.move.select(Moves.SPLASH, 0); + await game.phaseInterceptor.to("BerryPhase"); + + expect(game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.PLAYER)).toBeDefined(); + }); + + it("should block the ally's helping hand", async () => { + game.override.battleType("double"); + game.override.moveset([ Moves.HELPING_HAND, Moves.TACKLE ]); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.FEEBAS ]); + + game.move.select(Moves.HELPING_HAND, 0); + game.move.select(Moves.TACKLE, 1); + await game.phaseInterceptor.to("MoveEndPhase", true); + + expect(game.scene.getPlayerField()[1].getTag(BattlerTagType.HELPING_HAND)).toBeUndefined(); + }); + + it("should block the ally's heal bell, but only if the good as gold user is on the field", async () => { + game.override.battleType("double"); + game.override.moveset([ Moves.HEAL_BELL, Moves.SPLASH ]); + game.override.statusEffect(StatusEffect.BURN); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.FEEBAS, Species.ABRA ]); + const [ good_as_gold, ball_fetch ] = game.scene.getPlayerField(); + + // Force second pokemon to have ball fetch to isolate to a single mon. + vi.spyOn(ball_fetch, "getAbility").mockReturnValue(allAbilities[Abilities.BALL_FETCH]); + + // turn 1 + game.move.select(Moves.SPLASH, 0); + game.move.select(Moves.HEAL_BELL, 1); + await game.toNextTurn(); + expect(good_as_gold.status?.effect).toBe(StatusEffect.BURN); + + game.doSwitchPokemon(2); + game.move.select(Moves.HEAL_BELL, 0); + await game.toNextTurn(); + expect(good_as_gold.status?.effect).toBeUndefined(); + }); + + it("should not block field targeted effects like rain dance", async () => { + game.override.battleType("single"); + game.override.enemyMoveset( [ Moves.RAIN_DANCE ] ); + game.override.weather(WeatherType.NONE); + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + game.move.select(Moves.SPLASH, 0); + await game.phaseInterceptor.to("BerryPhase"); + + expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.RAIN); + }); +}); diff --git a/src/test/abilities/shields_down.test.ts b/src/test/abilities/shields_down.test.ts index 6100d3e04d9..ca6d945824e 100644 --- a/src/test/abilities/shields_down.test.ts +++ b/src/test/abilities/shields_down.test.ts @@ -1,4 +1,5 @@ import { Status } from "#app/data/status-effect"; +import { BattlerTagType } from "#app/enums/battler-tag-type"; import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { Abilities } from "#enums/abilities"; @@ -29,7 +30,7 @@ describe("Abilities - SHIELDS DOWN", () => { game.override.battleType("single"); game.override.ability(Abilities.SHIELDS_DOWN); game.override.moveset([ moveToUse ]); - game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); + game.override.enemyMoveset([ Moves.TACKLE ]); }); test( @@ -42,7 +43,7 @@ describe("Abilities - SHIELDS DOWN", () => { [Species.MINIOR]: coreForm, }); - await game.startBattle([ Species.MAGIKARP, Species.MINIOR ]); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.MINIOR ]); const minior = game.scene.getPlayerParty().find((p) => p.species.speciesId === Species.MINIOR)!; expect(minior).not.toBe(undefined); @@ -61,4 +62,146 @@ describe("Abilities - SHIELDS DOWN", () => { expect(minior.formIndex).toBe(meteorForm); }, ); + + test("should ignore non-volatile status moves", + async () => { + game.override.enemyMoveset([ Moves.SPORE ]); + + await game.classicMode.startBattle([ Species.MINIOR ]); + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.getPlayerPokemon()!.status).toBe(undefined); + } + ); + + test("should still ignore non-volatile status moves used by a pokemon with mold breaker", + async () => { + game.override.enemyAbility(Abilities.MOLD_BREAKER); + game.override.enemyMoveset([ Moves.SPORE ]); + + await game.classicMode.startBattle([ Species.MINIOR ]); + + game.move.select(Moves.SPLASH); + await game.forceEnemyMove(Moves.SPORE); + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.getPlayerPokemon()!.status).toBe(undefined); + } + ); + + test("should ignore non-volatile secondary status effects", + async() => { + game.override.enemyMoveset([ Moves.NUZZLE ]); + + await game.classicMode.startBattle([ Species.MINIOR ]); + + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.getPlayerPokemon()!.status).toBe(undefined); + } + ); + + test("should ignore status moves even through mold breaker", + async () => { + game.override.enemyMoveset([ Moves.SPORE ]); + game.override.enemyAbility(Abilities.MOLD_BREAKER); + + await game.classicMode.startBattle([ Species.MINIOR ]); + + game.move.select(Moves.SPLASH); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.getPlayerPokemon()!.status).toBe(undefined); + } + ); + + + // toxic spikes currently does not poison flying types when gravity is in effect + test.todo("should become poisoned by toxic spikes when grounded", + async () => { + game.override.enemyMoveset([ Moves.GRAVITY, Moves.TOXIC_SPIKES, Moves.SPLASH ]); + game.override.moveset([ Moves.GRAVITY, Moves.SPLASH ]); + + await game.classicMode.startBattle([ Species.MAGIKARP, Species.MINIOR ]); + + // turn 1 + game.move.select(Moves.GRAVITY); + await game.forceEnemyMove(Moves.TOXIC_SPIKES); + await game.toNextTurn(); + + // turn 2 + game.doSwitchPokemon(1); + await game.forceEnemyMove(Moves.SPLASH); + await game.toNextTurn(); + + expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(Species.MINIOR); + expect(game.scene.getPlayerPokemon()!.species.formIndex).toBe(0); + expect(game.scene.getPlayerPokemon()!.status?.effect).toBe(StatusEffect.POISON); + } + ); + + test("should ignore yawn", + async () => { + game.override.enemyMoveset([ Moves.YAWN ]); + + await game.classicMode.startBattle([ Species.MAGIKARP, Species.MINIOR ]); + + game.move.select(Moves.SPLASH); + await game.forceEnemyMove(Moves.YAWN); + + await game.phaseInterceptor.to(TurnEndPhase); + expect(game.scene.getPlayerPokemon()!.findTag( (tag ) => tag.tagType === BattlerTagType.DROWSY)).toBe(undefined); + } + ); + + test("should not ignore volatile status effects", + async () => { + game.override.enemyMoveset([ Moves.CONFUSE_RAY ]); + + await game.classicMode.startBattle([ Species.MINIOR ]); + + game.move.select(Moves.SPLASH); + await game.forceEnemyMove(Moves.CONFUSE_RAY); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.getPlayerPokemon()!.findTag( (tag ) => tag.tagType === BattlerTagType.CONFUSED)).not.toBe(undefined); + } + ); + + // the `NoTransformAbilityAbAttr` attribute is not checked anywhere, so this test cannot pass. + test.todo("ditto should not be immune to status after transforming", + async () => { + game.override.enemySpecies(Species.DITTO); + game.override.enemyAbility(Abilities.IMPOSTER); + game.override.moveset([ Moves.SPLASH, Moves.SPORE ]); + + await game.classicMode.startBattle([ Species.MINIOR ]); + + game.move.select(Moves.SPORE); + await game.forceEnemyMove(Moves.SPLASH); + + await game.phaseInterceptor.to(TurnEndPhase); + expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.SLEEP); + } + ); + + test("should not prevent minior from receiving the fainted status effect in trainer battles", async () => { + game.override.enemyMoveset([ Moves.TACKLE ]); + game.override.moveset([ Moves.THUNDERBOLT ]); + game.override.startingLevel(100); + game.override.startingWave(5); + game.override.enemySpecies(Species.MINIOR); + await game.classicMode.startBattle([ Species.REGIELEKI ]); + const minior = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.THUNDERBOLT); + await game.toNextTurn(); + expect(minior.isFainted()).toBe(true); + expect(minior.status?.effect).toBe(StatusEffect.FAINT); + }); + }); diff --git a/src/test/eggs/egg.test.ts b/src/test/eggs/egg.test.ts index 3394771d84a..d7ed07dd151 100644 --- a/src/test/eggs/egg.test.ts +++ b/src/test/eggs/egg.test.ts @@ -14,7 +14,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite describe("Egg Generation Tests", () => { let phaserGame: Phaser.Game; let game: GameManager; - const EGG_HATCH_COUNT: integer = 1000; + const EGG_HATCH_COUNT: number = 1000; beforeAll(() => { phaserGame = new Phaser.Game({ diff --git a/src/test/eggs/manaphy-egg.test.ts b/src/test/eggs/manaphy-egg.test.ts index 4285476a913..5bb5b790201 100644 --- a/src/test/eggs/manaphy-egg.test.ts +++ b/src/test/eggs/manaphy-egg.test.ts @@ -9,7 +9,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite describe("Manaphy Eggs", () => { let phaserGame: Phaser.Game; let game: GameManager; - const EGG_HATCH_COUNT: integer = 48; + const EGG_HATCH_COUNT: number = 48; let rngSweepProgress: number = 0; beforeAll(() => { diff --git a/src/test/field/pokemon.test.ts b/src/test/field/pokemon.test.ts index 1e3769a35b1..0a1ddac9e90 100644 --- a/src/test/field/pokemon.test.ts +++ b/src/test/field/pokemon.test.ts @@ -4,6 +4,8 @@ import GameManager from "../utils/gameManager"; import { PokeballType } from "#enums/pokeball"; import type BattleScene from "#app/battle-scene"; import { Moves } from "#app/enums/moves"; +import { Type } from "#app/enums/type"; +import { CustomPokemonData } from "#app/data/custom-pokemon-data"; describe("Spec - Pokemon", () => { let phaserGame: Phaser.Game; @@ -75,4 +77,125 @@ describe("Spec - Pokemon", () => { expect(fanRotom.compatibleTms).not.toContain(Moves.BLIZZARD); expect(fanRotom.compatibleTms).toContain(Moves.AIR_SLASH); }); + + describe("Get correct fusion type", () => { + let scene: BattleScene; + + beforeEach(async () => { + game.override.enemySpecies(Species.ZUBAT); + game.override.starterSpecies(Species.ABRA); + game.override.enableStarterFusion(); + scene = game.scene; + }); + + it("Fusing two mons with a single type", async () => { + game.override.starterFusionSpecies(Species.CHARMANDER); + await game.classicMode.startBattle(); + const pokemon = scene.getPlayerParty()[0]; + + let types = pokemon.getTypes(); + expect(types[0]).toBe(Type.PSYCHIC); + expect(types[1]).toBe(Type.FIRE); + + pokemon.customPokemonData.types = [ Type.UNKNOWN, Type.NORMAL ]; + types = pokemon.getTypes(); + expect(types[0]).toBe(Type.PSYCHIC); + expect(types[1]).toBe(Type.FIRE); + + pokemon.customPokemonData.types = [ Type.NORMAL, Type.UNKNOWN ]; + types = pokemon.getTypes(); + expect(types[0]).toBe(Type.NORMAL); + expect(types[1]).toBe(Type.FIRE); + + if (!pokemon.fusionCustomPokemonData) { + pokemon.fusionCustomPokemonData = new CustomPokemonData(); + } + pokemon.customPokemonData.types = []; + + pokemon.fusionCustomPokemonData.types = [ Type.UNKNOWN, Type.NORMAL ]; + types = pokemon.getTypes(); + expect(types[0]).toBe(Type.PSYCHIC); + expect(types[1]).toBe(Type.NORMAL); + + pokemon.fusionCustomPokemonData.types = [ Type.NORMAL, Type.UNKNOWN ]; + types = pokemon.getTypes(); + expect(types[0]).toBe(Type.PSYCHIC); + expect(types[1]).toBe(Type.NORMAL); + + pokemon.customPokemonData.types = [ Type.NORMAL, Type.UNKNOWN ]; + pokemon.fusionCustomPokemonData.types = [ Type.UNKNOWN, Type.NORMAL ]; + types = pokemon.getTypes(); + expect(types[0]).toBe(Type.NORMAL); + expect(types[1]).toBe(Type.FIRE); + }); + + it("Fusing two mons with same single type", async () => { + game.override.starterFusionSpecies(Species.DROWZEE); + await game.classicMode.startBattle(); + const pokemon = scene.getPlayerParty()[0]; + + const types = pokemon.getTypes(); + expect(types[0]).toBe(Type.PSYCHIC); + expect(types.length).toBe(1); + }); + + it("Fusing mons with one and two types", async () => { + game.override.starterSpecies(Species.CHARMANDER); + game.override.starterFusionSpecies(Species.HOUNDOUR); + await game.classicMode.startBattle(); + const pokemon = scene.getPlayerParty()[0]; + + const types = pokemon.getTypes(); + expect(types[0]).toBe(Type.FIRE); + expect(types[1]).toBe(Type.DARK); + }); + + it("Fusing two mons with two types", async () => { + game.override.starterSpecies(Species.NATU); + game.override.starterFusionSpecies(Species.HOUNDOUR); + await game.classicMode.startBattle(); + const pokemon = scene.getPlayerParty()[0]; + + let types = pokemon.getTypes(); + expect(types[0]).toBe(Type.PSYCHIC); + expect(types[1]).toBe(Type.FIRE); + + // Natu Psychic/Grass + pokemon.customPokemonData.types = [ Type.UNKNOWN, Type.GRASS ]; + types = pokemon.getTypes(); + expect(types[0]).toBe(Type.PSYCHIC); + expect(types[1]).toBe(Type.FIRE); + + // Natu Grass/Flying + pokemon.customPokemonData.types = [ Type.GRASS, Type.UNKNOWN ]; + types = pokemon.getTypes(); + expect(types[0]).toBe(Type.GRASS); + expect(types[1]).toBe(Type.FIRE); + + if (!pokemon.fusionCustomPokemonData) { + pokemon.fusionCustomPokemonData = new CustomPokemonData(); + } + pokemon.customPokemonData.types = []; + + // Houndour Dark/Grass + pokemon.fusionCustomPokemonData.types = [ Type.UNKNOWN, Type.GRASS ]; + types = pokemon.getTypes(); + expect(types[0]).toBe(Type.PSYCHIC); + expect(types[1]).toBe(Type.GRASS); + + // Houndour Grass/Fire + pokemon.fusionCustomPokemonData.types = [ Type.GRASS, Type.UNKNOWN ]; + types = pokemon.getTypes(); + expect(types[0]).toBe(Type.PSYCHIC); + expect(types[1]).toBe(Type.FIRE); + + // Natu Grass/Flying + // Houndour Dark/Grass + pokemon.customPokemonData.types = [ Type.GRASS, Type.UNKNOWN ]; + pokemon.fusionCustomPokemonData.types = [ Type.UNKNOWN, Type.GRASS ]; + types = pokemon.getTypes(); + expect(types[0]).toBe(Type.GRASS); + expect(types[1]).toBe(Type.DARK); + }); + }); }); diff --git a/src/test/moves/effectiveness.test.ts b/src/test/moves/effectiveness.test.ts index 7742178f595..c78416b1237 100644 --- a/src/test/moves/effectiveness.test.ts +++ b/src/test/moves/effectiveness.test.ts @@ -73,6 +73,10 @@ describe("Moves - Type Effectiveness", () => { () => testMoveEffectiveness(game, Moves.THUNDERBOLT, Species.BLASTOISE, 2) ); + it("Ghost-type attacks have no effect on Normal-type Pokemon", + () => testMoveEffectiveness(game, Moves.SHADOW_BALL, Species.URSALUNA, 0) + ); + it("Electric-type attacks are doubly super-effective against Water/Flying-type Pokemon", () => testMoveEffectiveness(game, Moves.THUNDERBOLT, Species.GYARADOS, 4) ); diff --git a/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts b/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts index 562b8322baa..f105678e71f 100644 --- a/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts @@ -345,9 +345,9 @@ describe("Clowning Around - Mystery Encounter", () => { scene.getPlayerParty()[2].moveset = []; await runMysteryEncounterToEnd(game, 3); - const leadTypesAfter = scene.getPlayerParty()[0].customPokemonData?.types; - const secondaryTypesAfter = scene.getPlayerParty()[1].customPokemonData?.types; - const thirdTypesAfter = scene.getPlayerParty()[2].customPokemonData?.types; + const leadTypesAfter = scene.getPlayerParty()[0].getTypes(); + const secondaryTypesAfter = scene.getPlayerParty()[1].getTypes(); + const thirdTypesAfter = scene.getPlayerParty()[2].getTypes(); expect(leadTypesAfter.length).toBe(2); expect(leadTypesAfter[0]).toBe(Type.WATER); @@ -372,7 +372,7 @@ describe("Clowning Around - Mystery Encounter", () => { }); }); -async function addItemToPokemon(scene: BattleScene, pokemon: Pokemon, stackCount: integer, itemType: PokemonHeldItemModifierType) { +async function addItemToPokemon(scene: BattleScene, pokemon: Pokemon, stackCount: number, itemType: PokemonHeldItemModifierType) { const itemMod = itemType.newModifier(pokemon) as PokemonHeldItemModifier; itemMod.stackCount = stackCount; await scene.addModifier(itemMod, true, false, false, true); diff --git a/src/test/utils/TextInterceptor.ts b/src/test/utils/TextInterceptor.ts index 466bcbf8052..089d8967c61 100644 --- a/src/test/utils/TextInterceptor.ts +++ b/src/test/utils/TextInterceptor.ts @@ -9,12 +9,12 @@ export default class TextInterceptor { scene.messageWrapper = this; } - showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer): void { + showText(text: string, delay?: number, callback?: Function, callbackDelay?: number, prompt?: boolean, promptDelay?: number): void { console.log(text); this.logs.push(text); } - showDialogue(text: string, name: string, delay?: integer, callback?: Function, callbackDelay?: integer, promptDelay?: integer): void { + showDialogue(text: string, name: string, delay?: number, callback?: Function, callbackDelay?: number, promptDelay?: number): void { console.log(name, text); this.logs.push(name, text); } diff --git a/src/test/utils/gameManager.ts b/src/test/utils/gameManager.ts index 8e595212898..fa7624c976e 100644 --- a/src/test/utils/gameManager.ts +++ b/src/test/utils/gameManager.ts @@ -255,7 +255,7 @@ export default class GameManager { * @param {BattlerIndex} targetIndex The index of the attack target, or `undefined` for multi-target attacks * @param movePosition The index of the move in the pokemon's moveset array */ - selectTarget(movePosition: integer, targetIndex?: BattlerIndex) { + selectTarget(movePosition: number, targetIndex?: BattlerIndex) { this.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { const handler = this.scene.ui.getHandler() as TargetSelectUiHandler; const move = (this.scene.getCurrentPhase() as SelectTargetPhase).getPokemon().getMoveset()[movePosition]!.getMove(); // TODO: is the bang correct? @@ -387,7 +387,7 @@ export default class GameManager { * @param path - The path to the data file. * @returns A promise that resolves with a tuple containing a boolean indicating success and an integer status code. */ - async importData(path): Promise<[boolean, integer]> { + async importData(path): Promise<[boolean, number]> { const saveKey = "x0i2O7WRiANTqPmZ"; const dataRaw = fs.readFileSync(path, { encoding: "utf8", flag: "r" }); let dataStr = AES.decrypt(dataRaw, saveKey).toString(enc.Utf8); diff --git a/src/test/utils/helpers/moveHelper.ts b/src/test/utils/helpers/moveHelper.ts index ad39755b556..ee026c06a8d 100644 --- a/src/test/utils/helpers/moveHelper.ts +++ b/src/test/utils/helpers/moveHelper.ts @@ -102,7 +102,7 @@ export class MoveHelper extends GameManagerHelper { * defaults to 0 (first slot) and 4 aborts the procedure * @returns a promise that resolves once the move has been successfully learnt */ - public async learnMove(move: Moves | integer, partyIndex: integer = 0, moveSlotIndex: integer = 0) { + public async learnMove(move: Moves | number, partyIndex: number = 0, moveSlotIndex: number = 0) { return new Promise(async (resolve, reject) => { this.game.scene.pushPhase(new LearnMovePhase(partyIndex, move)); diff --git a/src/test/utils/inputsHandler.ts b/src/test/utils/inputsHandler.ts index 8b8a89e45dc..e2591def447 100644 --- a/src/test/utils/inputsHandler.ts +++ b/src/test/utils/inputsHandler.ts @@ -30,7 +30,7 @@ export default class InputsHandler { this.init(); } - pressTouch(button: string, duration: integer): Promise { + pressTouch(button: string, duration: number): Promise { return new Promise(async (resolve) => { this.fakeMobile.touchDown(button); await holdOn(duration); @@ -39,7 +39,7 @@ export default class InputsHandler { }); } - pressGamepadButton(button: integer, duration: integer): Promise { + pressGamepadButton(button: number, duration: number): Promise { return new Promise(async (resolve) => { this.scene.input.gamepad?.emit("down", this.fakePad, { index: button }); await holdOn(duration); @@ -48,7 +48,7 @@ export default class InputsHandler { }); } - pressKeyboardKey(key: integer, duration: integer): Promise { + pressKeyboardKey(key: number, duration: number): Promise { return new Promise(async (resolve) => { this.scene.input.keyboard?.emit("keydown", { keyCode: key }); await holdOn(duration); diff --git a/src/test/utils/mocks/mocksContainer/mockText.ts b/src/test/utils/mocks/mocksContainer/mockText.ts index 604679af372..5550e801386 100644 --- a/src/test/utils/mocks/mocksContainer/mockText.ts +++ b/src/test/utils/mocks/mocksContainer/mockText.ts @@ -81,11 +81,11 @@ export default class MockText implements MockGameObject { showText( text: string, - delay?: integer | null, + delay?: number | null, callback?: Function | null, - callbackDelay?: integer | null, + callbackDelay?: number | null, prompt?: boolean | null, - promptDelay?: integer | null + promptDelay?: number | null ) { this.scene.messageWrapper.showText(text, delay, callback, callbackDelay, prompt, promptDelay); if (callback) { @@ -93,7 +93,7 @@ export default class MockText implements MockGameObject { } } - showDialogue(keyOrText: string, name: string | undefined, delay: integer | null = 0, callback: Function, callbackDelay?: integer, promptDelay?: integer) { + showDialogue(keyOrText: string, name: string | undefined, delay: number | null = 0, callback: Function, callbackDelay?: number, promptDelay?: number) { this.scene.messageWrapper.showDialogue(keyOrText, name, delay, callback, callbackDelay, promptDelay); if (callback) { callback(); diff --git a/src/test/utils/saves/data_new.prsv b/src/test/utils/saves/data_new.prsv new file mode 100644 index 00000000000..04d13a791a1 --- /dev/null +++ b/src/test/utils/saves/data_new.prsv @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/src/test/utils/testUtils.ts b/src/test/utils/testUtils.ts index a8410f8ba40..40e4bbe8775 100644 --- a/src/test/utils/testUtils.ts +++ b/src/test/utils/testUtils.ts @@ -18,7 +18,7 @@ export function mockI18next() { * @param end end number e.g. 10 * @returns an array of numbers */ -export function arrayOfRange(start: integer, end: integer) { +export function arrayOfRange(start: number, end: number) { return Array.from({ length: end - start }, (_v, k) => k + start); } diff --git a/src/ui/abstact-option-select-ui-handler.ts b/src/ui/abstact-option-select-ui-handler.ts index df592fc45b1..fb5ce9bc5aa 100644 --- a/src/ui/abstact-option-select-ui-handler.ts +++ b/src/ui/abstact-option-select-ui-handler.ts @@ -11,8 +11,8 @@ export interface OptionSelectConfig { xOffset?: number; yOffset?: number; options: OptionSelectItem[]; - maxOptions?: integer; - delay?: integer; + maxOptions?: number; + delay?: number; noCancel?: boolean; supportHover?: boolean; } @@ -40,7 +40,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { protected blockInput: boolean; - protected scrollCursor: integer = 0; + protected scrollCursor: number = 0; protected scale: number = 0.1666666667; @@ -50,9 +50,9 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { super(mode); } - abstract getWindowWidth(): integer; + abstract getWindowWidth(): number; - getWindowHeight(): integer { + getWindowHeight(): number { return (Math.min((this.config?.options || []).length, this.config?.maxOptions || 99) + 1) * 96 * this.scale; } @@ -118,7 +118,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { this.optionSelectText.setPositionRelative(this.optionSelectBg, 12 + 24 * this.scale, 2 + 42 * this.scale); - options.forEach((option: OptionSelectItem, i: integer) => { + options.forEach((option: OptionSelectItem, i: number) => { if (option.item) { const itemIcon = globalScene.add.sprite(0, 0, "items", option.item); itemIcon.setScale(3 * this.scale); @@ -295,7 +295,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { return options; } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const changed = this.cursor !== cursor; let isScroll = false; diff --git a/src/ui/achvs-ui-handler.ts b/src/ui/achvs-ui-handler.ts index ff1e2ee9184..74a121c231b 100644 --- a/src/ui/achvs-ui-handler.ts +++ b/src/ui/achvs-ui-handler.ts @@ -302,7 +302,7 @@ export default class AchvsUiHandler extends MessageUiHandler { return success; } - setCursor(cursor: integer, pageChange?: boolean): boolean { + setCursor(cursor: number, pageChange?: boolean): boolean { const ret = super.setCursor(cursor); let update = ret; @@ -340,12 +340,12 @@ export default class AchvsUiHandler extends MessageUiHandler { } /** - * setScrollCursor(scrollCursor: integer) : boolean + * setScrollCursor(scrollCursor: number) : boolean * scrollCursor refers to the page's position within the entire sum of the data, unlike cursor, which refers to a user's position within displayed data - * @param takes a scrollCursor that has been updated based on user behavior + * @param scrollCursor takes a value that has been updated based on user behavior * @returns returns a boolean that indicates whether the updated scrollCursor led to an update in the data displayed. */ - setScrollCursor(scrollCursor: integer): boolean { + setScrollCursor(scrollCursor: number): boolean { if (scrollCursor === this.scrollCursor) { return false; } @@ -391,7 +391,7 @@ export default class AchvsUiHandler extends MessageUiHandler { const achvRange = Object.values(achvs).slice(itemOffset, itemLimit + itemOffset); - achvRange.forEach((achv: Achv, i: integer) => { + achvRange.forEach((achv: Achv, i: number) => { const icon = this.icons[i]; const unlocked = achvUnlocks.hasOwnProperty(achv.id); const hidden = !unlocked && achv.secret && (!achv.parentId || !achvUnlocks.hasOwnProperty(achv.parentId)); @@ -431,7 +431,7 @@ export default class AchvsUiHandler extends MessageUiHandler { const voucherRange = Object.values(vouchers).slice(itemOffset, itemLimit + itemOffset); - voucherRange.forEach((voucher: Voucher, i: integer) => { + voucherRange.forEach((voucher: Voucher, i: number) => { const icon = this.icons[i]; const unlocked = voucherUnlocks.hasOwnProperty(voucher.id); diff --git a/src/ui/autocomplete-ui-handler.ts b/src/ui/autocomplete-ui-handler.ts index 8754e65db77..23abdb85772 100644 --- a/src/ui/autocomplete-ui-handler.ts +++ b/src/ui/autocomplete-ui-handler.ts @@ -8,7 +8,7 @@ export default class AutoCompleteUiHandler extends AbstractOptionSelectUiHandler super(mode); } - getWindowWidth(): integer { + getWindowWidth(): number { return 64; } diff --git a/src/ui/ball-ui-handler.ts b/src/ui/ball-ui-handler.ts index 2c1a53a9a52..a402d11ef1d 100644 --- a/src/ui/ball-ui-handler.ts +++ b/src/ui/ball-ui-handler.ts @@ -110,7 +110,7 @@ export default class BallUiHandler extends UiHandler { this.countsText.setText(Object.values(globalScene.pokeballCounts).map(c => `x${c}`).join("\n")); } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const ret = super.setCursor(cursor); if (!this.cursorObj) { diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index ca98d4c9d10..fa8767f5eb0 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -22,17 +22,17 @@ export default class BattleInfo extends Phaser.GameObjects.Container { private player: boolean; private mini: boolean; private boss: boolean; - private bossSegments: integer; + private bossSegments: number; private offset: boolean; private lastName: string | null; private lastTeraType: Type; private lastStatus: StatusEffect; - private lastHp: integer; - private lastMaxHp: integer; + private lastHp: number; + private lastMaxHp: number; private lastHpFrame: string | null; - private lastExp: integer; - private lastLevelExp: integer; - private lastLevel: integer; + private lastExp: number; + private lastLevelExp: number; + private lastLevel: number; private lastLevelCapped: boolean; private lastStats: string; @@ -739,7 +739,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { }); } - setLevel(level: integer): void { + setLevel(level: number): void { const isCapped = level >= globalScene.getMaxExpLevel(); this.levelNumbersContainer.removeAll(true); const levelStr = level.toString(); @@ -749,7 +749,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.levelContainer.setX((this.player ? -41 : -50) - 8 * Math.max(levelStr.length - 3, 0)); } - setHpNumbers(hp: integer, maxHp: integer): void { + setHpNumbers(hp: number, maxHp: number): void { if (!this.player || !globalScene) { return; } @@ -766,7 +766,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { } } - updateStats(stats: integer[]): void { + updateStats(stats: number[]): void { this.statOrder.map((s, i) => { if (s !== Stat.HP) { this.statNumbers[i].setFrame(stats[s - 1].toString()); diff --git a/src/ui/battle-message-ui-handler.ts b/src/ui/battle-message-ui-handler.ts index 2c0998b79ab..93de69240c3 100644 --- a/src/ui/battle-message-ui-handler.ts +++ b/src/ui/battle-message-ui-handler.ts @@ -154,19 +154,19 @@ export default class BattleMessageUiHandler extends MessageUiHandler { super.clear(); } - showText(text: string, delay?: integer | null, callback?: Function | null, callbackDelay?: integer | null, prompt?: boolean | null, promptDelay?: integer | null) { + showText(text: string, delay?: number | null, callback?: Function | null, callbackDelay?: number | null, prompt?: boolean | null, promptDelay?: number | null) { this.hideNameText(); super.showText(text, delay, callback, callbackDelay, prompt, promptDelay); } - showDialogue(text: string, name?: string, delay?: integer | null, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) { + showDialogue(text: string, name?: string, delay?: number | null, callback?: Function, callbackDelay?: number, prompt?: boolean, promptDelay?: number) { if (name) { this.showNameText(name); } super.showDialogue(text, name, delay, callback, callbackDelay, prompt, promptDelay); } - promptLevelUpStats(partyMemberIndex: integer, prevStats: integer[], showTotals: boolean): Promise { + promptLevelUpStats(partyMemberIndex: number, prevStats: number[], showTotals: boolean): Promise { return new Promise(resolve => { if (!globalScene.showLevelUpStats) { return resolve(); @@ -191,7 +191,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler { }); } - promptIvs(pokemonId: integer, ivs: integer[], shownIvsCount: integer): Promise { + promptIvs(pokemonId: number, ivs: number[], shownIvsCount: number): Promise { return new Promise(resolve => { globalScene.executeWithSeedOffset(() => { let levelUpStatsValuesText = ""; @@ -211,7 +211,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler { }); } - getTopIvs(ivs: integer[], shownIvsCount: integer): Stat[] { + getTopIvs(ivs: number[], shownIvsCount: number): Stat[] { let shownStats: Stat[] = []; if (shownIvsCount < 6) { const statsPool = PERMANENT_STATS.slice(); @@ -226,7 +226,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler { return shownStats; } - getIvDescriptor(value: integer, typeIv: integer, pokemonId: integer): string { + getIvDescriptor(value: number, typeIv: number, pokemonId: number): string { const starterSpecies = globalScene.getPokemonById(pokemonId)!.species.getRootSpeciesId(); // we are using getRootSpeciesId() here because we want to check against the baby form, not the mid form if it exists const starterIvs: number[] = globalScene.gameData.dexData[starterSpecies].ivs; const uiTheme = globalScene.uiTheme; // Assuming uiTheme is accessible diff --git a/src/ui/candy-bar.ts b/src/ui/candy-bar.ts index 81478f6fa7c..d58fd040a7c 100644 --- a/src/ui/candy-bar.ts +++ b/src/ui/candy-bar.ts @@ -47,7 +47,7 @@ export default class CandyBar extends Phaser.GameObjects.Container { this.shown = false; } - showStarterSpeciesCandy(starterSpeciesId: Species, count: integer): Promise { + showStarterSpeciesCandy(starterSpeciesId: Species, count: number): Promise { return new Promise(resolve => { if (this.shown) { if (this.speciesId === starterSpeciesId) { diff --git a/src/ui/challenges-select-ui-handler.ts b/src/ui/challenges-select-ui-handler.ts index 9c13d54bf55..31ee91388fc 100644 --- a/src/ui/challenges-select-ui-handler.ts +++ b/src/ui/challenges-select-ui-handler.ts @@ -20,7 +20,7 @@ export default class GameChallengesUiHandler extends UiHandler { private challengesContainer: Phaser.GameObjects.Container; private valuesContainer: Phaser.GameObjects.Container; - private scrollCursor: integer; + private scrollCursor: number; private optionsBg: Phaser.GameObjects.NineSlice; @@ -430,7 +430,7 @@ export default class GameChallengesUiHandler extends UiHandler { return success; } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { let ret = super.setCursor(cursor); if (!this.cursorObj) { @@ -447,7 +447,7 @@ export default class GameChallengesUiHandler extends UiHandler { return ret; } - setScrollCursor(scrollCursor: integer): boolean { + setScrollCursor(scrollCursor: number): boolean { if (scrollCursor === this.scrollCursor) { return false; } diff --git a/src/ui/command-ui-handler.ts b/src/ui/command-ui-handler.ts index 32a3bb764a9..de75f29ff6f 100644 --- a/src/ui/command-ui-handler.ts +++ b/src/ui/command-ui-handler.ts @@ -19,8 +19,8 @@ export default class CommandUiHandler extends UiHandler { private commandsContainer: Phaser.GameObjects.Container; private cursorObj: Phaser.GameObjects.Image | null; - protected fieldIndex: integer = 0; - protected cursor2: integer = 0; + protected fieldIndex: number = 0; + protected cursor2: number = 0; constructor() { super(Mode.COMMAND); @@ -50,7 +50,7 @@ export default class CommandUiHandler extends UiHandler { show(args: any[]): boolean { super.show(args); - this.fieldIndex = args.length ? args[0] as integer : 0; + this.fieldIndex = args.length ? args[0] as number : 0; this.commandsContainer.setVisible(true); @@ -144,11 +144,11 @@ export default class CommandUiHandler extends UiHandler { return success; } - getCursor(): integer { + getCursor(): number { return !this.fieldIndex ? this.cursor : this.cursor2; } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const changed = this.getCursor() !== cursor; if (changed) { if (!this.fieldIndex) { diff --git a/src/ui/confirm-ui-handler.ts b/src/ui/confirm-ui-handler.ts index b53a350cce0..3a3a5dfbfe7 100644 --- a/src/ui/confirm-ui-handler.ts +++ b/src/ui/confirm-ui-handler.ts @@ -8,16 +8,16 @@ import { globalScene } from "#app/global-scene"; export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { - public static readonly windowWidth: integer = 48; + public static readonly windowWidth: number = 48; private switchCheck: boolean; - private switchCheckCursor: integer; + private switchCheckCursor: number; constructor() { super(Mode.CONFIRM); } - getWindowWidth(): integer { + getWindowWidth(): number { return ConfirmUiHandler.windowWidth; } @@ -45,7 +45,7 @@ export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { } } ], - delay: args.length >= 8 && args[7] !== null ? args[7] as integer : 0 + delay: args.length >= 8 && args[7] !== null ? args[7] as number : 0 }; super.show([ config ]); @@ -105,7 +105,7 @@ export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { return super.processInput(button); } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const ret = super.setCursor(cursor); if (ret && this.switchCheck) { diff --git a/src/ui/daily-run-scoreboard.ts b/src/ui/daily-run-scoreboard.ts index 0c7ac0d60b3..d9131150262 100644 --- a/src/ui/daily-run-scoreboard.ts +++ b/src/ui/daily-run-scoreboard.ts @@ -6,10 +6,10 @@ import { WindowVariant, addWindow } from "./ui-theme"; import { pokerogueApi } from "#app/plugins/api/pokerogue-api"; export interface RankingEntry { - rank: integer, + rank: number, username: string, - score: integer, - wave: integer + score: number, + wave: number } // Don't forget to update translations when adding a new category @@ -28,8 +28,8 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { private pageNumberLabel: Phaser.GameObjects.Text; private nextPageButton: Phaser.GameObjects.Sprite; - private pageCount: integer; - private page: integer; + private pageCount: number; + private page: number; private category: ScoreboardCategory; private _isUpdating: boolean; @@ -157,7 +157,7 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { this.rankingsContainer.add(getEntry(i18next.t("menu:positionIcon"), i18next.t("menu:usernameScoreboard"), i18next.t("menu:score"), i18next.t("menu:wave"))); - rankings.forEach((r: RankingEntry, i: integer) => { + rankings.forEach((r: RankingEntry, i: number) => { const entryContainer = getEntry(r.rank.toString(), r.username, r.score.toString(), r.wave.toString()); entryContainer.setY((i + 1) * 9); this.rankingsContainer.add(entryContainer); @@ -176,7 +176,7 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { * @param {ScoreboardCategory} [category=this.category] - The category to fetch rankings for. Defaults to the current category. * @param {number} [page=this.page] - The page number to fetch. Defaults to the current page. */ - update(category: ScoreboardCategory = this.category, page: integer = this.page) { + update(category: ScoreboardCategory = this.category, page: number = this.page) { if (this.isUpdating) { return; } diff --git a/src/ui/dropdown.ts b/src/ui/dropdown.ts index 8c318b29d64..67599b843d8 100644 --- a/src/ui/dropdown.ts +++ b/src/ui/dropdown.ts @@ -370,7 +370,7 @@ export class DropDown extends Phaser.GameObjects.Container { return this.setCursor(this.defaultCursor); } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { this.cursor = cursor; if (cursor < 0) { cursor = 0; diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index 82e361fac39..3cd8a7e8dc9 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -30,7 +30,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { private voucherCountLabels: Phaser.GameObjects.Text[]; - private gachaCursor: integer; + private gachaCursor: number; private cursorObj: Phaser.GameObjects.Image; private transitioning: boolean; @@ -331,14 +331,14 @@ export default class EggGachaUiHandler extends MessageUiHandler { return true; } - getDelayValue(delay: integer) { + getDelayValue(delay: number) { if (this.transitioning && this.transitionCancelled) { delay = Math.ceil(delay / 5); } return Utils.fixedInt(delay); } - pull(pullCount: integer = 0, count: integer = 0, eggs?: Egg[]): void { + pull(pullCount: number = 0, count: number = 0, eggs?: Egg[]): void { if (Overrides.EGG_GACHA_PULL_COUNT_OVERRIDE && !count) { pullCount = Overrides.EGG_GACHA_PULL_COUNT_OVERRIDE; } @@ -575,7 +575,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { } } - consumeVouchers(voucherType: VoucherType, count: integer): void { + consumeVouchers(voucherType: VoucherType, count: number): void { globalScene.gameData.voucherCounts[voucherType] = Math.max(globalScene.gameData.voucherCounts[voucherType] - count, 0); this.updateVoucherCounts(); } @@ -751,7 +751,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { return success || error; } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const ret = super.setCursor(cursor); if (!this.cursorObj) { @@ -765,7 +765,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { return ret; } - setGachaCursor(cursor: integer): boolean { + setGachaCursor(cursor: number): boolean { const oldCursor = this.gachaCursor; const changed = oldCursor !== cursor; diff --git a/src/ui/egg-hatch-scene-handler.ts b/src/ui/egg-hatch-scene-handler.ts index 189d2f295d1..791c488c91a 100644 --- a/src/ui/egg-hatch-scene-handler.ts +++ b/src/ui/egg-hatch-scene-handler.ts @@ -54,7 +54,7 @@ export default class EggHatchSceneHandler extends UiHandler { return globalScene.ui.getMessageHandler().processInput(button); } - setCursor(_cursor: integer): boolean { + setCursor(_cursor: number): boolean { return false; } diff --git a/src/ui/evolution-scene-handler.ts b/src/ui/evolution-scene-handler.ts index e7866dfea53..b35aa8f6cc0 100644 --- a/src/ui/evolution-scene-handler.ts +++ b/src/ui/evolution-scene-handler.ts @@ -82,7 +82,7 @@ export default class EvolutionSceneHandler extends MessageUiHandler { return false; } - setCursor(_cursor: integer): boolean { + setCursor(_cursor: number): boolean { return false; } diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index 220e5d817ef..72fb90066e7 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -32,8 +32,8 @@ export default class FightUiHandler extends UiHandler implements InfoToggle { private moveCategoryIcon: Phaser.GameObjects.Sprite; private moveInfoOverlay : MoveInfoOverlay; - protected fieldIndex: integer = 0; - protected cursor2: integer = 0; + protected fieldIndex: number = 0; + protected cursor2: number = 0; constructor() { super(Mode.FIGHT); @@ -113,7 +113,7 @@ export default class FightUiHandler extends UiHandler implements InfoToggle { show(args: any[]): boolean { super.show(args); - this.fieldIndex = args.length ? args[0] as integer : 0; + this.fieldIndex = args.length ? args[0] as number : 0; const messageHandler = this.getUi().getMessageHandler(); messageHandler.bg.setVisible(false); @@ -206,11 +206,11 @@ export default class FightUiHandler extends UiHandler implements InfoToggle { return this.active; } - getCursor(): integer { + getCursor(): number { return !this.fieldIndex ? this.cursor : this.cursor2; } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const ui = this.getUi(); this.moveInfoOverlay.clear(); diff --git a/src/ui/game-stats-ui-handler.ts b/src/ui/game-stats-ui-handler.ts index 2fa5b54ac76..09fd178e101 100644 --- a/src/ui/game-stats-ui-handler.ts +++ b/src/ui/game-stats-ui-handler.ts @@ -372,7 +372,7 @@ export default class GameStatsUiHandler extends UiHandler { return success; } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const ret = super.setCursor(cursor); if (ret) { diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index 7ea8dbe7a4e..aadb39cdcfe 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -21,7 +21,6 @@ enum MenuOptions { GAME_SETTINGS, ACHIEVEMENTS, STATS, - RUN_HISTORY, EGG_LIST, EGG_GACHA, MANAGE_DATA, @@ -172,7 +171,7 @@ export default class MenuUiHandler extends MessageUiHandler { const manageDataOptions: any[] = []; // TODO: proper type - const confirmSlot = (message: string, slotFilter: (i: integer) => boolean, callback: (i: integer) => void) => { + const confirmSlot = (message: string, slotFilter: (i: number) => boolean, callback: (i: number) => void) => { ui.revertMode(); ui.showText(message, null, () => { const config: OptionSelectConfig = { @@ -213,7 +212,7 @@ export default class MenuUiHandler extends MessageUiHandler { manageDataOptions.push({ label: i18next.t("menuUiHandler:exportSession"), handler: () => { - const dataSlots: integer[] = []; + const dataSlots: number[] = []; Promise.all( new Array(5).fill(null).map((_, i) => { const slotId = i; @@ -508,10 +507,6 @@ export default class MenuUiHandler extends MessageUiHandler { ui.setOverlayMode(Mode.GAME_STATS); success = true; break; - case MenuOptions.RUN_HISTORY: - ui.setOverlayMode(Mode.RUN_HISTORY); - success = true; - break; case MenuOptions.EGG_LIST: if (globalScene.gameData.eggs.length) { ui.revertMode(); @@ -685,7 +680,7 @@ export default class MenuUiHandler extends MessageUiHandler { super.showText(text, delay, callback, callbackDelay, prompt, promptDelay); } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const ret = super.setCursor(cursor); if (!this.cursorObj) { diff --git a/src/ui/message-ui-handler.ts b/src/ui/message-ui-handler.ts index 81a09e90167..18e1dfb1aff 100644 --- a/src/ui/message-ui-handler.ts +++ b/src/ui/message-ui-handler.ts @@ -34,24 +34,24 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler { } } - showText(text: string, delay?: integer | null, callback?: Function | null, callbackDelay?: integer | null, prompt?: boolean | null, promptDelay?: integer | null) { + showText(text: string, delay?: number | null, callback?: Function | null, callbackDelay?: number | null, prompt?: boolean | null, promptDelay?: number | null) { this.showTextInternal(text, delay, callback, callbackDelay, prompt, promptDelay); } - showDialogue(text: string, name?: string, delay?: integer | null, callback?: Function | null, callbackDelay?: integer | null, prompt?: boolean | null, promptDelay?: integer | null) { + showDialogue(text: string, name?: string, delay?: number | null, callback?: Function | null, callbackDelay?: number | null, prompt?: boolean | null, promptDelay?: number | null) { this.showTextInternal(text, delay, callback, callbackDelay, prompt, promptDelay); } - private showTextInternal(text: string, delay?: integer | null, callback?: Function | null, callbackDelay?: integer | null, prompt?: boolean | null, promptDelay?: integer | null) { + private showTextInternal(text: string, delay?: number | null, callback?: Function | null, callbackDelay?: number | null, prompt?: boolean | null, promptDelay?: number | null) { if (delay === null || delay === undefined) { delay = 20; } // Pattern matching regex that checks for @c{}, @f{}, @s{}, and @f{} patterns within message text and parses them to their respective behaviors. - const charVarMap = new Map(); - const delayMap = new Map(); - const soundMap = new Map(); - const fadeMap = new Map(); + const charVarMap = new Map(); + const delayMap = new Map(); + const soundMap = new Map(); + const fadeMap = new Map(); const actionPattern = /@(c|d|s|f)\{(.*?)\}/; let actionMatch: RegExpExecArray | null; while ((actionMatch = actionPattern.exec(text))) { @@ -188,7 +188,7 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler { } } - showPrompt(callback?: Function | null, callbackDelay?: integer | null) { + showPrompt(callback?: Function | null, callbackDelay?: number | null) { const wrappedTextLines = this.message.runWordWrap(this.message.text).split(/\n/g); const textLinesCount = wrappedTextLines.length; const lastTextLine = wrappedTextLines[wrappedTextLines.length - 1]; diff --git a/src/ui/modifier-select-ui-handler.ts b/src/ui/modifier-select-ui-handler.ts index 0cca087ce8d..a3508532631 100644 --- a/src/ui/modifier-select-ui-handler.ts +++ b/src/ui/modifier-select-ui-handler.ts @@ -35,15 +35,15 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { private moveInfoOverlay: MoveInfoOverlay; private moveInfoOverlayActive: boolean = false; - private rowCursor: integer = 0; + private rowCursor: number = 0; private player: boolean; /** * If reroll cost is negative, it is assumed there are 0 items in the shop. * It will cause reroll button to be disabled, and a "Continue" button to show in the place of shop items */ - private rerollCost: integer; - private transferButtonWidth: integer; - private checkButtonWidth: integer; + private rerollCost: number; + private transferButtonWidth: number; + private checkButtonWidth: number; public options: ModifierOption[]; public shopOptionsRows: ModifierOption[][]; @@ -185,7 +185,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { this.rerollButtonContainer.setPositionRelative(this.lockRarityButtonContainer, 0, canLockRarities ? -12 : 0); - this.rerollCost = args[3] as integer; + this.rerollCost = args[3] as number; this.updateRerollCostText(); @@ -460,7 +460,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { return success; } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const ui = this.getUi(); const ret = super.setCursor(cursor); @@ -516,7 +516,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { return ret; } - setRowCursor(rowCursor: integer): boolean { + setRowCursor(rowCursor: number): boolean { const lastRowCursor = this.rowCursor; if (rowCursor !== lastRowCursor) { @@ -553,7 +553,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { return false; } - private getRowItems(rowCursor: integer): integer { + private getRowItems(rowCursor: number): number { switch (rowCursor) { case 0: return 3; @@ -564,7 +564,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { } } - setRerollCost(rerollCost: integer): void { + setRerollCost(rerollCost: number): void { this.rerollCost = rerollCost; } @@ -730,7 +730,7 @@ class ModifierOption extends Phaser.GameObjects.Container { } } - show(remainingDuration: integer, upgradeCountOffset: integer) { + show(remainingDuration: number, upgradeCountOffset: number) { if (!this.modifierTypeOption.cost) { globalScene.tweens.add({ targets: this.pb, @@ -847,8 +847,8 @@ class ModifierOption extends Phaser.GameObjects.Container { }); } - getPbAtlasKey(tierOffset: integer = 0) { - return getPokeballAtlasKey((this.modifierTypeOption.type?.tier! + tierOffset) as integer as PokeballType); // TODO: is this bang correct? + getPbAtlasKey(tierOffset: number = 0) { + return getPokeballAtlasKey((this.modifierTypeOption.type?.tier! + tierOffset) as number as PokeballType); // TODO: is this bang correct? } updateCostText(): void { diff --git a/src/ui/party-exp-bar.ts b/src/ui/party-exp-bar.ts index 93e4117157a..75970a5908b 100644 --- a/src/ui/party-exp-bar.ts +++ b/src/ui/party-exp-bar.ts @@ -29,7 +29,7 @@ export default class PartyExpBar extends Phaser.GameObjects.Container { this.shown = false; } - showPokemonExp(pokemon: Pokemon, expValue: integer, showOnlyLevelUp: boolean, newLevel: number): Promise { + showPokemonExp(pokemon: Pokemon, expValue: number, showOnlyLevelUp: boolean, newLevel: number): Promise { return new Promise(resolve => { if (this.shown) { return resolve(); diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 4a7716f7e62..3ffd470b6ca 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -125,16 +125,16 @@ export enum PartyOption { ALL = 4000, } -export type PartySelectCallback = (cursor: integer, option: PartyOption) => void; -export type PartyModifierTransferSelectCallback = (fromCursor: integer, index: integer, itemQuantity?: integer, toCursor?: integer) => void; -export type PartyModifierSpliceSelectCallback = (fromCursor: integer, toCursor?: integer) => void; +export type PartySelectCallback = (cursor: number, option: PartyOption) => void; +export type PartyModifierTransferSelectCallback = (fromCursor: number, index: number, itemQuantity?: number, toCursor?: number) => void; +export type PartyModifierSpliceSelectCallback = (fromCursor: number, toCursor?: number) => void; export type PokemonSelectFilter = (pokemon: PlayerPokemon) => string | null; export type PokemonModifierTransferSelectFilter = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => string | null; export type PokemonMoveSelectFilter = (pokemonMove: PokemonMove) => string | null; export default class PartyUiHandler extends MessageUiHandler { private partyUiMode: PartyUiMode; - private fieldIndex: integer; + private fieldIndex: number; private partyBg: Phaser.GameObjects.Image; private partyContainer: Phaser.GameObjects.Container; @@ -146,26 +146,26 @@ export default class PartyUiHandler extends MessageUiHandler { private optionsMode: boolean; private optionsScroll: boolean; - private optionsCursor: integer = 0; - private optionsScrollCursor: integer = 0; - private optionsScrollTotal: integer = 0; + private optionsCursor: number = 0; + private optionsScrollCursor: number = 0; + private optionsScrollTotal: number = 0; /** This is only public for test/ui/transfer-item.test.ts */ public optionsContainer: Phaser.GameObjects.Container; private optionsBg: Phaser.GameObjects.NineSlice; private optionsCursorObj: Phaser.GameObjects.Image | null; - private options: integer[]; + private options: number[]; private transferMode: boolean; - private transferOptionCursor: integer; - private transferCursor: integer; + private transferOptionCursor: number; + private transferCursor: number; /** Current quantity selection for every item held by the pokemon selected for the transfer */ - private transferQuantities: integer[]; + private transferQuantities: number[]; /** Stack size of every item that the selected pokemon is holding */ - private transferQuantitiesMax: integer[]; + private transferQuantitiesMax: number[]; /** Whether to transfer all items */ private transferAll: boolean; - private lastCursor: integer = 0; + private lastCursor: number = 0; private selectCallback: PartySelectCallback | PartyModifierTransferSelectCallback | null; private selectFilter: PokemonSelectFilter | PokemonModifierTransferSelectFilter; private moveSelectFilter: PokemonMoveSelectFilter; @@ -304,7 +304,7 @@ export default class PartyUiHandler extends MessageUiHandler { this.partyUiMode = args[0] as PartyUiMode; - this.fieldIndex = args.length > 1 ? args[1] as integer : -1; + this.fieldIndex = args.length > 1 ? args[1] as number : -1; this.selectCallback = args.length > 2 && args[2] instanceof Function ? args[2] : undefined; this.selectFilter = args.length > 3 && args[3] instanceof Function @@ -689,7 +689,7 @@ export default class PartyUiHandler extends MessageUiHandler { } } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { let changed: boolean; if (this.optionsMode) { @@ -749,7 +749,7 @@ export default class PartyUiHandler extends MessageUiHandler { return changed; } - showText(text: string, delay?: integer | null, callback?: Function | null, callbackDelay?: integer | null, prompt?: boolean | null, promptDelay?: integer | null) { + showText(text: string, delay?: number | null, callback?: Function | null, callbackDelay?: number | null, prompt?: boolean | null, promptDelay?: number | null) { if (text.length === 0) { text = defaultMessage; } @@ -1060,7 +1060,7 @@ export default class PartyUiHandler extends MessageUiHandler { } } - doRelease(slotIndex: integer): void { + doRelease(slotIndex: number): void { this.showText(this.getReleaseMessage(getPokemonNameWithAffix(globalScene.getPlayerParty()[slotIndex])), null, () => { this.clearPartySlots(); globalScene.removePartyMemberModifiers(slotIndex); @@ -1121,7 +1121,7 @@ export default class PartyUiHandler extends MessageUiHandler { return formChangeItemModifiers; } - getOptionsCursorWithScroll(): integer { + getOptionsCursorWithScroll(): number { return this.optionsCursor + this.optionsScrollCursor + (this.options && this.options[0] === PartyOption.SCROLL_UP ? -1 : 0); } @@ -1164,7 +1164,7 @@ export default class PartyUiHandler extends MessageUiHandler { class PartySlot extends Phaser.GameObjects.Container { private selected: boolean; private transfer: boolean; - private slotIndex: integer; + private slotIndex: number; private pokemon: PlayerPokemon; private slotBg: Phaser.GameObjects.Image; @@ -1179,7 +1179,7 @@ class PartySlot extends Phaser.GameObjects.Container { private pokemonIcon: Phaser.GameObjects.Container; private iconAnimHandler: PokemonIconAnimHandler; - constructor(slotIndex: integer, pokemon: PlayerPokemon, iconAnimHandler: PokemonIconAnimHandler, partyUiMode: PartyUiMode, tmMoveId: Moves) { + constructor(slotIndex: number, pokemon: PlayerPokemon, iconAnimHandler: PokemonIconAnimHandler, partyUiMode: PartyUiMode, tmMoveId: Moves) { super(globalScene, slotIndex >= globalScene.currentBattle.getBattlerCount() ? 230.5 : 64, slotIndex >= globalScene.currentBattle.getBattlerCount() ? -184 + (globalScene.currentBattle.double ? -40 : 0) + (28 + (globalScene.currentBattle.double ? 8 : 0)) * slotIndex : -124 + (globalScene.currentBattle.double ? -8 : 0) + slotIndex * 64); diff --git a/src/ui/pokemon-info-container.ts b/src/ui/pokemon-info-container.ts index 4f7a28f1d6d..554cea39731 100644 --- a/src/ui/pokemon-info-container.ts +++ b/src/ui/pokemon-info-container.ts @@ -17,8 +17,8 @@ import { Species } from "#enums/species"; interface LanguageSetting { infoContainerTextSize: string; - infoContainerLabelXPos?: integer; - infoContainerTextXPos?: integer; + infoContainerLabelXPos?: number; + infoContainerTextXPos?: number; } const languageSettings: { [key: string]: LanguageSetting } = { @@ -330,7 +330,7 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container { } const starterSpeciesId = pokemon.species.getRootSpeciesId(); - const originalIvs: integer[] | null = eggInfo ? (dexEntry.caughtAttr ? dexEntry.ivs : null) : (globalScene.gameData.dexData[starterSpeciesId].caughtAttr + const originalIvs: number[] | null = eggInfo ? (dexEntry.caughtAttr ? dexEntry.ivs : null) : (globalScene.gameData.dexData[starterSpeciesId].caughtAttr ? globalScene.gameData.dexData[starterSpeciesId].ivs : null); this.statsContainer.updateIvs(pokemon.ivs, originalIvs!); // TODO: is this bang correct? diff --git a/src/ui/run-info-ui-handler.ts b/src/ui/run-info-ui-handler.ts index 43b95cb3793..02bcba17a73 100644 --- a/src/ui/run-info-ui-handler.ts +++ b/src/ui/run-info-ui-handler.ts @@ -59,7 +59,7 @@ export default class RunInfoUiHandler extends UiHandler { private runResultContainer: Phaser.GameObjects.Container; private runInfoContainer: Phaser.GameObjects.Container; private partyContainer: Phaser.GameObjects.Container; - private statsBgWidth: integer; + private statsBgWidth: number; private hallofFameContainer: Phaser.GameObjects.Container; private endCardContainer: Phaser.GameObjects.Container; @@ -534,7 +534,7 @@ export default class RunInfoUiHandler extends UiHandler { // Luck // Uses the parameters windowX and windowY to dynamically position the luck value neatly into the bottom right corner const luckText = addBBCodeTextObject(0, 0, "", TextStyle.WINDOW, { fontSize: "55px" }); - const luckValue = Phaser.Math.Clamp(this.runInfo.party.map(p => p.toPokemon().getLuck()).reduce((total: integer, value: integer) => total += value, 0), 0, 14); + const luckValue = Phaser.Math.Clamp(this.runInfo.party.map(p => p.toPokemon().getLuck()).reduce((total: number, value: number) => total += value, 0), 0, 14); let luckInfo = i18next.t("runHistory:luck") + ": " + getLuckString(luckValue); if (luckValue < 14) { luckInfo = "[color=#" + (getLuckTextTint(luckValue)).toString(16) + "]" + luckInfo + "[/color]"; @@ -621,7 +621,7 @@ export default class RunInfoUiHandler extends UiHandler { const currentLanguage = i18next.resolvedLanguage ?? "en"; const windowHeight = ((globalScene.game.canvas.height / 6) - 23) / 6; - party.forEach((p: PokemonData, i: integer) => { + party.forEach((p: PokemonData, i: number) => { const pokemonInfoWindow = new RoundRectangle(globalScene, 0, 14, (this.statsBgWidth * 2) + 10, windowHeight - 2, 3); const pokemon = p.toPokemon(); diff --git a/src/ui/save-slot-select-ui-handler.ts b/src/ui/save-slot-select-ui-handler.ts index fe2ac9e1221..e746c9302d0 100644 --- a/src/ui/save-slot-select-ui-handler.ts +++ b/src/ui/save-slot-select-ui-handler.ts @@ -20,7 +20,7 @@ export enum SaveSlotUiMode { SAVE } -export type SaveSlotSelectCallback = (cursor: integer) => void; +export type SaveSlotSelectCallback = (cursor: number) => void; export default class SaveSlotSelectUiHandler extends MessageUiHandler { @@ -33,7 +33,7 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { private uiMode: SaveSlotUiMode; private saveSlotSelectCallback: SaveSlotSelectCallback | null; - private scrollCursor: integer = 0; + private scrollCursor: number = 0; private cursorObj: Phaser.GameObjects.Container | null; @@ -210,7 +210,7 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { } } - showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) { + showText(text: string, delay?: number, callback?: Function, callbackDelay?: number, prompt?: boolean, promptDelay?: number) { super.showText(text, delay, callback, callbackDelay, prompt, promptDelay); if (text?.indexOf("\n") === -1) { @@ -230,7 +230,7 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { * @param prevSlotIndex index of the previous session occupied by the cursor, between `0` and `SESSION_SLOTS_COUNT - 1` - optional * @returns `true` if the cursor position has changed | `false` if it has not */ - override setCursor(cursor: integer, prevSlotIndex?: integer): boolean { + override setCursor(cursor: number, prevSlotIndex?: number): boolean { const changed = super.setCursor(cursor); if (!this.cursorObj) { @@ -267,7 +267,7 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { /** * Helper function that resets the given session slot to its default central position */ - revertSessionSlot(slotIndex: integer): void { + revertSessionSlot(slotIndex: number): void { const sessionSlot = this.sessionSlots[slotIndex]; if (sessionSlot) { sessionSlot.setPosition(0, slotIndex * 56); @@ -291,7 +291,7 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { * @param prevSlotIndex index of the previous slot occupied by the cursor, between `0` and `SESSION_SLOTS_COUNT-1` - optional * @returns `true` if the cursor position has changed | `false` if it has not */ - setScrollCursor(scrollCursor: integer, prevSlotIndex?: integer): boolean { + setScrollCursor(scrollCursor: number, prevSlotIndex?: number): boolean { const changed = scrollCursor !== this.scrollCursor; if (changed) { @@ -331,13 +331,13 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { } class SessionSlot extends Phaser.GameObjects.Container { - public slotId: integer; + public slotId: number; public hasData: boolean; private loadingLabel: Phaser.GameObjects.Text; public saveData: SessionSaveData; - constructor(slotId: integer) { + constructor(slotId: number) { super(globalScene, 0, slotId * 56); this.slotId = slotId; @@ -367,7 +367,7 @@ class SessionSlot extends Phaser.GameObjects.Container { this.add(playTimeLabel); const pokemonIconsContainer = globalScene.add.container(144, 4); - data.party.forEach((p: PokemonData, i: integer) => { + data.party.forEach((p: PokemonData, i: number) => { const iconContainer = globalScene.add.container(26 * i, 0); iconContainer.setScale(0.75); diff --git a/src/ui/settings/abstract-binding-ui-handler.ts b/src/ui/settings/abstract-binding-ui-handler.ts index d0f9a5c8a90..e8c3e20c38f 100644 --- a/src/ui/settings/abstract-binding-ui-handler.ts +++ b/src/ui/settings/abstract-binding-ui-handler.ts @@ -203,7 +203,7 @@ export default abstract class AbstractBindingUiHandler extends UiHandler { * @param cursor - The cursor position to set. * @returns `true` if the cursor was set successfully. */ - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { this.cursor = cursor; if (cursor === 1) { this.actionLabel.setColor(this.getTextColor(TextStyle.SETTINGS_SELECTED)); diff --git a/src/ui/settings/abstract-settings-ui-handler.ts b/src/ui/settings/abstract-settings-ui-handler.ts index a0287f80f79..7300b6d3266 100644 --- a/src/ui/settings/abstract-settings-ui-handler.ts +++ b/src/ui/settings/abstract-settings-ui-handler.ts @@ -463,7 +463,7 @@ export default class AbstractSettingsUiHandler extends MessageUiHandler { this.cursorObj = null; } - override showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) { + override showText(text: string, delay?: number, callback?: Function, callbackDelay?: number, prompt?: boolean, promptDelay?: number) { this.messageBoxContainer.setVisible(!!text?.length); super.showText(text, delay, callback, callbackDelay, prompt, promptDelay); } diff --git a/src/ui/settings/option-select-ui-handler.ts b/src/ui/settings/option-select-ui-handler.ts index 5deaba5cfc5..b3d1735dc19 100644 --- a/src/ui/settings/option-select-ui-handler.ts +++ b/src/ui/settings/option-select-ui-handler.ts @@ -6,7 +6,7 @@ export default class OptionSelectUiHandler extends AbstractOptionSelectUiHandler super(mode); } - getWindowWidth(): integer { + getWindowWidth(): number { return 64; } } diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 0ea14fd47e0..e225ea3968d 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -62,7 +62,7 @@ export type StarterSelectCallback = (starters: Starter[]) => void; export interface Starter { species: PokemonSpecies; dexAttr: bigint; - abilityIndex: integer, + abilityIndex: number, passive: boolean; nature: Nature; moveset?: StarterMoveset; @@ -73,8 +73,8 @@ export interface Starter { interface LanguageSetting { starterInfoTextSize: string, instructionTextSize: string, - starterInfoXPos?: integer, - starterInfoYOffset?: integer + starterInfoXPos?: number, + starterInfoYOffset?: number } const languageSettings: { [key: string]: LanguageSetting } = { @@ -210,11 +210,11 @@ function findClosestStarterRow(index: number, numberOfRows: number) { interface SpeciesDetails { shiny?: boolean, - formIndex?: integer + formIndex?: number female?: boolean, variant?: Variant, - abilityIndex?: integer, - natureIndex?: integer, + abilityIndex?: number, + natureIndex?: number, forSeen?: boolean, // default = false } @@ -296,7 +296,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private dexAttrCursor: bigint = 0n; private abilityCursor: number = -1; private natureCursor: number = -1; - private filterBarCursor: integer = 0; + private filterBarCursor: number = 0; private starterMoveset: StarterMoveset | null; private scrollCursor: number; @@ -306,7 +306,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { public starterSpecies: PokemonSpecies[] = []; private pokerusSpecies: PokemonSpecies[] = []; private starterAttr: bigint[] = []; - private starterAbilityIndexes: integer[] = []; + private starterAbilityIndexes: number[] = []; private starterNatures: Nature[] = []; private starterMovesets: StarterMoveset[] = []; private speciesStarterDexEntry: DexEntry | null; @@ -1076,7 +1076,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } - showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer, moveToTop?: boolean) { + showText(text: string, delay?: number, callback?: Function, callbackDelay?: number, prompt?: boolean, promptDelay?: number, moveToTop?: boolean) { super.showText(text, delay, callback, callbackDelay, prompt, promptDelay); const singleLine = text?.indexOf("\n") === -1; @@ -2109,7 +2109,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const natureIndex = natures.indexOf(this.natureCursor); const newNature = natures[natureIndex < natures.length - 1 ? natureIndex + 1 : 0]; // store cycled nature as default - starterAttributes.nature = newNature as unknown as integer; + starterAttributes.nature = newNature as unknown as number; this.setSpeciesDetails(this.lastSpecies, { natureIndex: newNature }); success = true; } @@ -2278,7 +2278,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { return [ isDupe, removeIndex ]; } - addToParty(species: PokemonSpecies, dexAttr: bigint, abilityIndex: integer, nature: Nature, moveset: StarterMoveset, randomSelection: boolean = false) { + addToParty(species: PokemonSpecies, dexAttr: bigint, abilityIndex: number, nature: Nature, moveset: StarterMoveset, randomSelection: boolean = false) { const props = globalScene.gameData.getSpeciesDexAttrProps(species, dexAttr); this.starterIcons[this.starterSpecies.length].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant)); this.starterIcons[this.starterSpecies.length].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant)); @@ -2787,7 +2787,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { }); }; - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { let changed = false; if (this.filterMode) { @@ -3383,7 +3383,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { ? speciesMoveData : speciesMoveData[formIndex!] // TODO: is this bang correct? : null; - const availableStarterMoves = this.speciesStarterMoves.concat(speciesEggMoves.hasOwnProperty(species.speciesId) ? speciesEggMoves[species.speciesId].filter((_, em: integer) => globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em)) : []); + const availableStarterMoves = this.speciesStarterMoves.concat(speciesEggMoves.hasOwnProperty(species.speciesId) ? speciesEggMoves[species.speciesId].filter((_, em: number) => globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em)) : []); this.starterMoveset = (moveData || (this.speciesStarterMoves.slice(0, 4) as StarterMoveset)).filter(m => availableStarterMoves.find(sm => sm === m)) as StarterMoveset; // Consolidate move data if it contains an incompatible move if (this.starterMoveset.length < 4 && this.starterMoveset.length < availableStarterMoves.length) { @@ -3552,8 +3552,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } - tryUpdateValue(add?: integer, addingToParty?: boolean): boolean { - const value = this.starterSpecies.map(s => s.generation).reduce((total: integer, _gen: integer, i: integer) => total += globalScene.gameData.getSpeciesStarterValue(this.starterSpecies[i].speciesId), 0); + tryUpdateValue(add?: number, addingToParty?: boolean): boolean { + const value = this.starterSpecies.map(s => s.generation).reduce((total: number, _gen: number, i: number) => total += globalScene.gameData.getSpeciesStarterValue(this.starterSpecies[i].speciesId), 0); const newValue = value + (add || 0); const valueLimit = this.getValueLimit(); const overLimit = newValue > valueLimit; diff --git a/src/ui/stats-container.ts b/src/ui/stats-container.ts index 8d8d3c101b2..add7eeedbb8 100644 --- a/src/ui/stats-container.ts +++ b/src/ui/stats-container.ts @@ -17,7 +17,7 @@ const defaultIvChartData = new Array(12).fill(null).map(() => 0); export class StatsContainer extends Phaser.GameObjects.Container { private showDiff: boolean; - private statsIvsCache: integer[]; + private statsIvsCache: number[]; private ivChart: Phaser.GameObjects.Polygon; private ivStatValueTexts: BBCodeText[]; @@ -31,7 +31,7 @@ export class StatsContainer extends Phaser.GameObjects.Container { setup() { this.setName("stats"); - const ivChartBgData = new Array(6).fill(null).map((_, i: integer) => [ ivChartSize * ivChartStatCoordMultipliers[ivChartStatIndexes[i]][0], ivChartSize * ivChartStatCoordMultipliers[ivChartStatIndexes[i]][1] ] ).flat(); + const ivChartBgData = new Array(6).fill(null).map((_, i: number) => [ ivChartSize * ivChartStatCoordMultipliers[ivChartStatIndexes[i]][0], ivChartSize * ivChartStatCoordMultipliers[ivChartStatIndexes[i]][1] ] ).flat(); const ivChartBg = globalScene.add.polygon(48, 44, ivChartBgData, 0xd8e0f0, 0.625); ivChartBg.setOrigin(0, 0); @@ -74,14 +74,14 @@ export class StatsContainer extends Phaser.GameObjects.Container { } } - updateIvs(ivs: integer[], originalIvs?: integer[]): void { + updateIvs(ivs: number[], originalIvs?: number[]): void { if (ivs) { const ivChartData = new Array(6).fill(null).map((_, i) => [ (ivs[ivChartStatIndexes[i]] / 31) * ivChartSize * ivChartStatCoordMultipliers[ivChartStatIndexes[i]][0], (ivs[ivChartStatIndexes[i]] / 31) * ivChartSize * ivChartStatCoordMultipliers[ivChartStatIndexes[i]][1] ] ).flat(); const lastIvChartData = this.statsIvsCache || defaultIvChartData; const perfectIVColor: string = getTextColor(TextStyle.SUMMARY_GOLD, false, globalScene.uiTheme); this.statsIvsCache = ivChartData.slice(0); - this.ivStatValueTexts.map((t: BBCodeText, i: integer) => { + this.ivStatValueTexts.map((t: BBCodeText, i: number) => { let label = ""; // Check to see if IVs are 31, if so change the text style to gold, otherwise leave them be. @@ -114,7 +114,7 @@ export class StatsContainer extends Phaser.GameObjects.Container { ease: "Cubic.easeOut", onUpdate: (tween: Phaser.Tweens.Tween) => { const progress = tween.getValue(); - const interpolatedData = ivChartData.map((v: number, i: integer) => v * progress + (lastIvChartData[i] * (1 - progress))); + const interpolatedData = ivChartData.map((v: number, i: number) => v * progress + (lastIvChartData[i] * (1 - progress))); if (interpolateColor) { this.ivChart.setFillStyle( Phaser.Display.Color.ValueToColor( diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index 3fe6a372737..3305b3f7aa2 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -110,8 +110,8 @@ export default class SummaryUiHandler extends UiHandler { private moveEffectsVisible: boolean; private moveSelect: boolean; - private moveCursor: integer; - private selectedMoveIndex: integer; + private moveCursor: number; + private selectedMoveIndex: number; private selectCallback: Function | null; constructor() { @@ -289,7 +289,7 @@ export default class SummaryUiHandler extends UiHandler { this.summaryPageTransitionContainer.setVisible(false); } - getPageKey(page?: integer) { + getPageKey(page?: number) { if (page === undefined) { page = this.cursor; } @@ -597,7 +597,7 @@ export default class SummaryUiHandler extends UiHandler { return success || error; } - setCursor(cursor: integer, overrideChanged: boolean = false): boolean { + setCursor(cursor: number, overrideChanged: boolean = false): boolean { let changed: boolean = overrideChanged || this.moveCursor !== cursor; if (this.moveSelect) { @@ -756,7 +756,7 @@ export default class SummaryUiHandler extends UiHandler { typeLabel.setOrigin(0, 0); profileContainer.add(typeLabel); - const getTypeIcon = (index: integer, type: Type, tera: boolean = false) => { + const getTypeIcon = (index: number, type: Type, tera: boolean = false) => { const xCoord = typeLabel.width * typeLabel.scale + 9 + 34 * index; const typeIcon = !tera ? globalScene.add.sprite(xCoord, 42, Utils.getLocalizedSpriteKey("types"), Type[type].toLowerCase()) diff --git a/src/ui/target-select-ui-handler.ts b/src/ui/target-select-ui-handler.ts index 232ec887b0a..681c5ff40c0 100644 --- a/src/ui/target-select-ui-handler.ts +++ b/src/ui/target-select-ui-handler.ts @@ -41,7 +41,7 @@ export default class TargetSelectUiHandler extends UiHandler { super.show(args); - this.fieldIndex = args[0] as integer; + this.fieldIndex = args[0] as number; this.move = args[1] as Moves; this.targetSelectCallback = args[2] as TargetSelectCallback; const user = globalScene.getPlayerField()[this.fieldIndex]; @@ -131,7 +131,7 @@ export default class TargetSelectUiHandler extends UiHandler { return success; } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const singleTarget = globalScene.getField()[cursor]; const multipleTargets = this.targets.map(index => globalScene.getField()[index]); diff --git a/src/ui/text.ts b/src/ui/text.ts index cdd1142e7ee..fc48c4ea86e 100644 --- a/src/ui/text.ts +++ b/src/ui/text.ts @@ -362,7 +362,7 @@ export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: Ui } } -export function getModifierTierTextTint(tier: ModifierTier): integer { +export function getModifierTierTextTint(tier: ModifierTier): number { switch (tier) { case ModifierTier.COMMON: return 0xf8f8f8; @@ -379,7 +379,7 @@ export function getModifierTierTextTint(tier: ModifierTier): integer { } } -export function getEggTierTextTint(tier: EggTier): integer { +export function getEggTierTextTint(tier: EggTier): number { switch (tier) { case EggTier.COMMON: return getModifierTierTextTint(ModifierTier.COMMON); diff --git a/src/ui/ui-handler.ts b/src/ui/ui-handler.ts index 89f8d9e65b6..f001ab5bd6f 100644 --- a/src/ui/ui-handler.ts +++ b/src/ui/ui-handler.ts @@ -8,8 +8,8 @@ import type { Button } from "#enums/buttons"; * A basic abstract class to act as a holder and processor for UI elements. */ export default abstract class UiHandler { - protected mode: integer | null; - protected cursor: integer = 0; + protected mode: number | null; + protected cursor: number = 0; public active: boolean = false; /** @@ -37,11 +37,11 @@ export default abstract class UiHandler { return getTextColor(style, shadow, globalScene.uiTheme); } - getCursor(): integer { + getCursor(): number { return this.cursor; } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const changed = this.cursor !== cursor; if (changed) { this.cursor = cursor; diff --git a/src/ui/ui-theme.ts b/src/ui/ui-theme.ts index 0d42815f842..36e2e844a56 100644 --- a/src/ui/ui-theme.ts +++ b/src/ui/ui-theme.ts @@ -70,7 +70,7 @@ export function addWindow(x: number, y: number, width: number, height: number, m return window; } -export function updateWindowType(windowTypeIndex: integer): void { +export function updateWindowType(windowTypeIndex: number): void { const windowObjects: [Phaser.GameObjects.NineSlice, WindowVariant][] = []; const themedObjects: (Phaser.GameObjects.Image | Phaser.GameObjects.NineSlice)[] = []; const traverse = (object: any) => { diff --git a/src/ui/ui.ts b/src/ui/ui.ts index 682ef836765..72147e8ccb1 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -296,13 +296,13 @@ export default class UI extends Phaser.GameObjects.Container { return handler.processInput(button); } - showTextPromise(text: string, callbackDelay: number = 0, prompt: boolean = true, promptDelay?: integer | null): Promise { + showTextPromise(text: string, callbackDelay: number = 0, prompt: boolean = true, promptDelay?: number | null): Promise { return new Promise(resolve => { this.showText(text ?? "", null, () => resolve(), callbackDelay, prompt, promptDelay); }); } - showText(text: string, delay?: integer | null, callback?: Function | null, callbackDelay?: integer | null, prompt?: boolean | null, promptDelay?: integer | null): void { + showText(text: string, delay?: number | null, callback?: Function | null, callbackDelay?: number | null, prompt?: boolean | null, promptDelay?: number | null): void { if (prompt && text.indexOf("$") > -1) { const messagePages = text.split(/\$/g).map(m => m.trim()); let showMessageAndCallback = () => callback && callback(); @@ -322,7 +322,7 @@ export default class UI extends Phaser.GameObjects.Container { } } - showDialogue(keyOrText: string, name: string | undefined, delay: integer | null = 0, callback: Function, callbackDelay?: integer, promptDelay?: integer): void { + showDialogue(keyOrText: string, name: string | undefined, delay: number | null = 0, callback: Function, callbackDelay?: number, promptDelay?: number): void { // Get localized dialogue (if available) let hasi18n = false; let text = keyOrText; @@ -443,7 +443,7 @@ export default class UI extends Phaser.GameObjects.Container { } } - setCursor(cursor: integer): boolean { + setCursor(cursor: number): boolean { const changed = this.getHandler().setCursor(cursor); if (changed) { this.playSelect(); @@ -460,7 +460,7 @@ export default class UI extends Phaser.GameObjects.Container { globalScene.playSound("ui/error"); } - fadeOut(duration: integer): Promise { + fadeOut(duration: number): Promise { return new Promise(resolve => { if (this.overlayActive) { return resolve(); @@ -478,7 +478,7 @@ export default class UI extends Phaser.GameObjects.Container { }); } - fadeIn(duration: integer): Promise { + fadeIn(duration: number): Promise { return new Promise(resolve => { if (!this.overlayActive) { return resolve(); diff --git a/src/utils.ts b/src/utils.ts index 4a284c1e7fd..9a7517a18d0 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -11,7 +11,7 @@ export function toReadableString(str: string): string { return str.replace(/\_/g, " ").split(" ").map(s => `${s.slice(0, 1)}${s.slice(1).toLowerCase()}`).join(" "); } -export function randomString(length: integer, seeded: boolean = false) { +export function randomString(length: number, seeded: boolean = false) { const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let result = ""; @@ -23,7 +23,7 @@ export function randomString(length: integer, seeded: boolean = false) { return result; } -export function shiftCharCodes(str: string, shiftCount: integer) { +export function shiftCharCodes(str: string, shiftCount: number) { if (!shiftCount) { shiftCount = 0; } @@ -59,7 +59,7 @@ export function randSeedGauss(stdev: number, mean: number = 0): number { return z * stdev + mean; } -export function padInt(value: integer, length: integer, padWith?: string): string { +export function padInt(value: number, length: number, padWith?: string): string { if (!padWith) { padWith = "0"; } @@ -75,7 +75,7 @@ export function padInt(value: integer, length: integer, padWith?: string): strin * @param range The amount of possible numbers * @param min The starting number */ -export function randInt(range: integer, min: integer = 0): integer { +export function randInt(range: number, min: number = 0): number { if (range === 1) { return min; } @@ -88,7 +88,7 @@ export function randInt(range: integer, min: integer = 0): integer { * @param min The minimum integer to pick, default `0` * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) */ -export function randSeedInt(range: integer, min: integer = 0): integer { +export function randSeedInt(range: number, min: number = 0): number { if (range <= 1) { return min; } @@ -100,7 +100,7 @@ export function randSeedInt(range: integer, min: integer = 0): integer { * @param min The lowest number * @param max The highest number */ -export function randIntRange(min: integer, max: integer): integer { +export function randIntRange(min: number, max: number): number { return randInt(max - min, min); } @@ -139,7 +139,7 @@ export function randSeedShuffle(items: T[]): T[] { return newArray; } -export function getFrameMs(frameCount: integer): integer { +export function getFrameMs(frameCount: number): number { return Math.floor((1 / 60) * 1000 * frameCount); } @@ -150,7 +150,7 @@ export function getCurrentTime(): number { const secondsInHour = 3600; -export function getPlayTimeString(totalSeconds: integer): string { +export function getPlayTimeString(totalSeconds: number): string { const days = `${Math.floor(totalSeconds / (secondsInHour * 24))}`; const hours = `${Math.floor(totalSeconds % (secondsInHour * 24) / secondsInHour)}`; const minutes = `${Math.floor(totalSeconds % secondsInHour / 60)}`; @@ -176,7 +176,7 @@ export function getIvsFromId(id: number): number[] { ]; } -export function formatLargeNumber(count: integer, threshold: integer): string { +export function formatLargeNumber(count: number, threshold: number): string { if (count < threshold) { return count.toString(); } @@ -236,7 +236,7 @@ export function formatMoney(format: MoneyFormat, amount: number) { return amount.toLocaleString(); } -export function formatStat(stat: integer, forHp: boolean = false): string { +export function formatStat(stat: number, forHp: boolean = false): string { return formatLargeNumber(stat, forHp ? 100000 : 1000000); } @@ -244,7 +244,7 @@ export function getEnumKeys(enumType: any): string[] { return Object.values(enumType).filter(v => isNaN(parseInt(v!.toString()))).map(v => v!.toString()); } -export function getEnumValues(enumType: any): integer[] { +export function getEnumValues(enumType: any): number[] { return Object.values(enumType).filter(v => !isNaN(parseInt(v!.toString()))).map(v => parseInt(v!.toString())); } @@ -344,7 +344,7 @@ export class NumberHolder { /** @deprecated Use {@linkcode NumberHolder} */ export class IntegerHolder extends NumberHolder { - constructor(value: integer) { + constructor(value: number) { super(value); } } @@ -357,8 +357,8 @@ export class FixedInt { } } -export function fixedInt(value: integer): integer { - return new FixedInt(value) as unknown as integer; +export function fixedInt(value: number): number { + return new FixedInt(value) as unknown as number; } /** @@ -382,7 +382,7 @@ export function toCamelCaseString(unformattedText: string): string { return unformattedText.split(/[_ ]/).filter(f => f).map((f, i) => i ? `${f[0].toUpperCase()}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join(""); } -export function rgbToHsv(r: integer, g: integer, b: integer) { +export function rgbToHsv(r: number, g: number, b: number) { const v = Math.max(r, g, b); const c = v - Math.min(r, g, b); const h = c && ((v === r) ? (g - b) / c : ((v === g) ? 2 + (b - r) / c : 4 + (r - g) / c)); @@ -394,7 +394,7 @@ export function rgbToHsv(r: integer, g: integer, b: integer) { * @param {Array} rgb1 First RGB color in array * @param {Array} rgb2 Second RGB color in array */ -export function deltaRgb(rgb1: integer[], rgb2: integer[]): integer { +export function deltaRgb(rgb1: number[], rgb2: number[]): number { const [ r1, g1, b1 ] = rgb1; const [ r2, g2, b2 ] = rgb2; const drp2 = Math.pow(r1 - r2, 2); @@ -415,7 +415,7 @@ export function rgbHexToRgba(hex: string) { }; } -export function rgbaToInt(rgba: integer[]): integer { +export function rgbaToInt(rgba: number[]): number { return (rgba[0] << 24) + (rgba[1] << 16) + (rgba[2] << 8) + rgba[3]; }