From 4e1ee9e50b315f4275d87d1079f28b98cfe9d64d Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Thu, 13 Mar 2025 14:32:35 -0700 Subject: [PATCH 1/4] Revert "[Enhancement] Add form changes for Solgaleo, Lunala, & Marshadow cosmetic forms" (#5512) --- .../pokemon/icons/7/791-radiant-sun.png | Bin 491 -> 0 bytes .../pokemon/icons/7/791s-radiant-sun.png | Bin 508 -> 0 bytes .../images/pokemon/icons/7/792-full-moon.png | Bin 461 -> 0 bytes .../images/pokemon/icons/7/792s-full-moon.png | Bin 470 -> 0 bytes public/images/pokemon_icons_7.json | 7080 ++++++++--------- public/images/pokemon_icons_7.png | Bin 52044 -> 51451 bytes src/data/pokemon-forms.ts | 12 - src/data/pokemon-species.ts | 14 +- 8 files changed, 3501 insertions(+), 3605 deletions(-) delete mode 100644 public/images/pokemon/icons/7/791-radiant-sun.png delete mode 100644 public/images/pokemon/icons/7/791s-radiant-sun.png delete mode 100644 public/images/pokemon/icons/7/792-full-moon.png delete mode 100644 public/images/pokemon/icons/7/792s-full-moon.png diff --git a/public/images/pokemon/icons/7/791-radiant-sun.png b/public/images/pokemon/icons/7/791-radiant-sun.png deleted file mode 100644 index ac53b40b0e637f33a74f5474bc35f8ac55b7ecb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 491 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<^!3-obnb*7rQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{174DbnYRZvj)`EkOJA3s*Lo8H+Tf9UuzS@rgyps1)dZ-7d4Opav(DXx+r zzu^Bcz_96z&Uv6HXMsm#F#`kNK@eu#F){ls&_V}K7sn6_|D}^T`&tZmSc)G={QLiK z?KwxGgr!rrnKH47zb#{W_-pY$?zRs)dmIE6kKEweyr(hA!KrIyOkk)6PrI2!8R(ILV$xpK-j;z`$yJV-pp_=AD-f<_V@twZI?LVRP z`Nn{1`6$5-iTt!7ie}0^BXM6nLS(8__o8F6#kX3I#;A0-O=1tU^|3FnTH-2mc zQrsm$e!>6YfWgb3@e@#(v%n*=n1O-sFbFdq&tH)OwA9zr#WBRff9d4Lyu$_@E(aSj zfB%=?W1XX3ILmW#S=Qw%dk!?p{`?d8pVjqUqyB`Jj#nIW9`dR%yUe=9koxI@=#fn` zR<54eTl#TZgKUZM@#{KbFZMUCFW!ZM&afv+b-C zDYuP3Mp{i+f4kdFTXlKoPW^Wbfro#+zA7$qq-cu%T=VzaOWl?;&3Gzk=eVpT?P9{Q zo~xWCJ3lM5eH5AHvEv+D>CWu9-9cv$$nJ<}XSQ;jP+V?trlV#0@-zjXUTcZQM=lA^ zB#+piR%*A-Je&T2FX`P&n`a3>Ki}YK)lD}&*%Dq-zK0`TA+1^TiBsIXk30F^KIl4l uSGRz@y{z2X|3O~fE6c}MV_ts#$ym>zaB|sxx5>cJX7F_Nb6Mw<&;$TCN#RWZ diff --git a/public/images/pokemon/icons/7/792-full-moon.png b/public/images/pokemon/icons/7/792-full-moon.png deleted file mode 100644 index 6e77f626e94687596e0a4031512b52b96724ddd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 461 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<^!3-obnb*7rQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`)dPG&Ton`)etw*=s@?STv2&4|kF9zA;orZ1cecm3UU;CwpA^X3_g}3a zs5VcNZx@i_EeY}q{*MG0Y+op~0VOyKJR*x382Ao?FyoGi*>8cCi+Q>@hFJLbUgi{P zR^Va1z>rwD^MB><$sA6Ox6hPpc_zrDF}MC0@5@@B)02wVZ&G`BFO_|-ydv+}nD37c zO_yF?(Q?aMUHXg8hS|M)-aqA4R*5`hp?bnJ<+vdKiPTD;PV2}-wv_3XS zl00rq<61mlamj%Vxxe@AgfkA4V%;cVJOJbuY%t_`lTl@K} zt%Iht_p#mIITVExbk+%+GBtOOnFW{JG?bD5GqV@sYg8 t?LPtqReNhw(=Nn{1`bpw1tTt!7ie}0^>s@>FA+wxpf!KXdjs@>8orIem5opxt?yb6C(AaCD) zwf_JAJ^^(oFKbl*Qv4-Be!>4y0K=6#GZq4+I14-?iy0XB4ude`@%$AjKu3ssx;Tbd z`1f9BoYbtq!+ODCLc^|m|9AWrX4$wPH%%t`GY8|8KKaK@U+k8pp4=H8Il18drsjM1 z74OcntY7_@zkL29!6^N?ITzSl@8&$I)z{zQ5acQ1Cs@SSJh_Ga$tJsH5>}CkY&?42 zo7jBp4o(S}Ancyw-P$d$xWp;$dTw-Vo6d$)W)6vBY`!`&FfVW2nsVpgx4Uy~ z-D1zN2zmC*w$#oLE$w)En%8mKlUs?J7R|0kPDf%KF7VtsIZ;8PedT983Cm`wBTdCm zjMjcWdp1$PaqpCm?`)k;Fzis7&hd1X^ul%SM;1#-y}6`(WLD5Ox!YC$^bH;UF8LzL zxc8}B$K7MCKY|2RxqqMN33&N;^0pZVJ!OvDZ@Z#DMI&hGMPRrwc)I$ztaD0e0ss_R B#w7p% diff --git a/public/images/pokemon_icons_7.json b/public/images/pokemon_icons_7.json index d5faa4e8b02..03eeba88a70 100644 --- a/public/images/pokemon_icons_7.json +++ b/public/images/pokemon_icons_7.json @@ -4,8 +4,8 @@ "image": "pokemon_icons_7.png", "format": "RGBA8888", "size": { - "w": 250, - "h": 672 + "w": 502, + "h": 325 }, "scale": 1, "frames": [ @@ -345,132 +345,6 @@ "h": 29 } }, - { - "filename": "795", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 28, - "h": 30 - }, - "frame": { - "x": 0, - "y": 322, - "w": 28, - "h": 30 - } - }, - { - "filename": "795s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 28, - "h": 30 - }, - "frame": { - "x": 0, - "y": 352, - "w": 28, - "h": 30 - } - }, - { - "filename": "800", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 28, - "h": 30 - }, - "frame": { - "x": 0, - "y": 382, - "w": 28, - "h": 30 - } - }, - { - "filename": "800s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 28, - "h": 30 - }, - "frame": { - "x": 0, - "y": 412, - "w": 28, - "h": 30 - } - }, - { - "filename": "805", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 0, - "w": 28, - "h": 30 - }, - "frame": { - "x": 0, - "y": 442, - "w": 28, - "h": 30 - } - }, - { - "filename": "805s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 0, - "w": 28, - "h": 30 - }, - "frame": { - "x": 0, - "y": 472, - "w": 28, - "h": 30 - } - }, { "filename": "809-gigantamax", "rotated": false, @@ -513,27 +387,6 @@ "h": 28 } }, - { - "filename": "791-radiant-sun", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 2, - "w": 29, - "h": 28 - }, - "frame": { - "x": 142, - "y": 0, - "w": 29, - "h": 28 - } - }, { "filename": "791", "rotated": false, @@ -549,28 +402,7 @@ "h": 28 }, "frame": { - "x": 138, - "y": 28, - "w": 29, - "h": 28 - } - }, - { - "filename": "791s-radiant-sun", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 2, - "w": 29, - "h": 28 - }, - "frame": { - "x": 171, + "x": 142, "y": 0, "w": 29, "h": 28 @@ -591,138 +423,12 @@ "h": 28 }, "frame": { - "x": 167, + "x": 138, "y": 28, "w": 29, "h": 28 } }, - { - "filename": "773-bug", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 0, - "y": 502, - "w": 26, - "h": 30 - } - }, - { - "filename": "773-dark", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 0, - "y": 532, - "w": 26, - "h": 30 - } - }, - { - "filename": "773-dragon", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 0, - "y": 562, - "w": 26, - "h": 30 - } - }, - { - "filename": "773-electric", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 0, - "y": 592, - "w": 26, - "h": 30 - } - }, - { - "filename": "773-fairy", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 0, - "y": 622, - "w": 26, - "h": 30 - } - }, - { - "filename": "789", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 6, - "w": 23, - "h": 20 - }, - "frame": { - "x": 0, - "y": 652, - "w": 23, - "h": 20 - } - }, { "filename": "784", "rotated": false, @@ -737,6 +443,27 @@ "w": 29, "h": 27 }, + "frame": { + "x": 171, + "y": 0, + "w": 29, + "h": 27 + } + }, + { + "filename": "784s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 3, + "w": 29, + "h": 27 + }, "frame": { "x": 200, "y": 0, @@ -745,7 +472,7 @@ } }, { - "filename": "2103", + "filename": "730", "rotated": false, "trimmed": true, "sourceSize": { @@ -753,20 +480,83 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, - "y": 0, - "w": 21, - "h": 30 + "x": 6, + "y": 2, + "w": 28, + "h": 27 }, "frame": { "x": 229, "y": 0, - "w": 21, - "h": 30 + "w": 28, + "h": 27 } }, { - "filename": "773-fighting", + "filename": "730s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 2, + "w": 28, + "h": 27 + }, + "frame": { + "x": 257, + "y": 0, + "w": 28, + "h": 27 + } + }, + { + "filename": "740", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 32, + "h": 23 + }, + "frame": { + "x": 285, + "y": 0, + "w": 32, + "h": 23 + } + }, + { + "filename": "740s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 32, + "h": 23 + }, + "frame": { + "x": 317, + "y": 0, + "w": 32, + "h": 23 + } + }, + { + "filename": "795", "rotated": false, "trimmed": true, "sourceSize": { @@ -776,18 +566,18 @@ "spriteSourceSize": { "x": 7, "y": 0, - "w": 26, + "w": 28, "h": 30 }, "frame": { "x": 34, "y": 85, - "w": 26, + "w": 28, "h": 30 } }, { - "filename": "773-fire", + "filename": "795s", "rotated": false, "trimmed": true, "sourceSize": { @@ -797,18 +587,18 @@ "spriteSourceSize": { "x": 7, "y": 0, - "w": 26, + "w": 28, "h": 30 }, "frame": { "x": 34, "y": 115, - "w": 26, + "w": 28, "h": 30 } }, { - "filename": "773-flying", + "filename": "800", "rotated": false, "trimmed": true, "sourceSize": { @@ -818,18 +608,18 @@ "spriteSourceSize": { "x": 7, "y": 0, - "w": 26, + "w": 28, "h": 30 }, "frame": { "x": 32, "y": 145, - "w": 26, + "w": 28, "h": 30 } }, { - "filename": "773-ghost", + "filename": "800s", "rotated": false, "trimmed": true, "sourceSize": { @@ -839,18 +629,18 @@ "spriteSourceSize": { "x": 7, "y": 0, - "w": 26, + "w": 28, "h": 30 }, "frame": { "x": 32, "y": 175, - "w": 26, + "w": 28, "h": 30 } }, { - "filename": "773-grass", + "filename": "805", "rotated": false, "trimmed": true, "sourceSize": { @@ -858,20 +648,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 7, + "x": 6, "y": 0, - "w": 26, + "w": 28, "h": 30 }, "frame": { "x": 31, "y": 205, - "w": 26, + "w": 28, "h": 30 } }, { - "filename": "773-ground", + "filename": "805s", "rotated": false, "trimmed": true, "sourceSize": { @@ -879,20 +669,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 7, + "x": 6, "y": 0, - "w": 26, + "w": 28, "h": 30 }, "frame": { "x": 31, "y": 235, - "w": 26, + "w": 28, "h": 30 } }, { - "filename": "773-ice", + "filename": "773-bug", "rotated": false, "trimmed": true, "sourceSize": { @@ -913,7 +703,7 @@ } }, { - "filename": "730", + "filename": "773-dark", "rotated": false, "trimmed": true, "sourceSize": { @@ -921,20 +711,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 6, - "y": 2, - "w": 28, - "h": 27 + "x": 7, + "y": 0, + "w": 26, + "h": 30 }, "frame": { "x": 31, "y": 295, - "w": 28, - "h": 27 + "w": 26, + "h": 30 } }, { - "filename": "773-poison", + "filename": "2038", "rotated": false, "trimmed": true, "sourceSize": { @@ -942,20 +732,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 7, + "x": 8, + "y": 4, + "w": 30, + "h": 25 + }, + "frame": { + "x": 349, "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 28, - "y": 322, - "w": 26, - "h": 30 + "w": 30, + "h": 25 } }, { - "filename": "773-psychic", + "filename": "2038s", "rotated": false, "trimmed": true, "sourceSize": { @@ -963,230 +753,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 7, + "x": 8, + "y": 4, + "w": 30, + "h": 25 + }, + "frame": { + "x": 379, "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 28, - "y": 352, - "w": 26, - "h": 30 + "w": 30, + "h": 25 } }, { - "filename": "773-rock", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 28, - "y": 382, - "w": 26, - "h": 30 - } - }, - { - "filename": "773-steel", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 28, - "y": 412, - "w": 26, - "h": 30 - } - }, - { - "filename": "773-water", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 28, - "y": 442, - "w": 26, - "h": 30 - } - }, - { - "filename": "773", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 28, - "y": 472, - "w": 26, - "h": 30 - } - }, - { - "filename": "773s-bug", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 26, - "y": 502, - "w": 26, - "h": 30 - } - }, - { - "filename": "773s-dark", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 26, - "y": 532, - "w": 26, - "h": 30 - } - }, - { - "filename": "773s-dragon", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 26, - "y": 562, - "w": 26, - "h": 30 - } - }, - { - "filename": "773s-electric", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 26, - "y": 592, - "w": 26, - "h": 30 - } - }, - { - "filename": "773s-fairy", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 26, - "h": 30 - }, - "frame": { - "x": 26, - "y": 622, - "w": 26, - "h": 30 - } - }, - { - "filename": "789s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 6, - "w": 23, - "h": 20 - }, - "frame": { - "x": 23, - "y": 652, - "w": 23, - "h": 20 - } - }, - { - "filename": "784s", + "filename": "785", "rotated": false, "trimmed": true, "sourceSize": { @@ -1196,18 +776,18 @@ "spriteSourceSize": { "x": 7, "y": 3, - "w": 29, - "h": 27 + "w": 28, + "h": 26 }, "frame": { - "x": 70, - "y": 57, - "w": 29, - "h": 27 + "x": 409, + "y": 0, + "w": 28, + "h": 26 } }, { - "filename": "747", + "filename": "785s", "rotated": false, "trimmed": true, "sourceSize": { @@ -1215,16 +795,226 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 22, - "h": 20 + "x": 7, + "y": 3, + "w": 28, + "h": 26 }, "frame": { - "x": 46, - "y": 652, - "w": 22, - "h": 20 + "x": 437, + "y": 0, + "w": 28, + "h": 26 + } + }, + { + "filename": "792", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 1, + "w": 28, + "h": 28 + }, + "frame": { + "x": 465, + "y": 0, + "w": 28, + "h": 28 + } + }, + { + "filename": "792s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 1, + "w": 28, + "h": 28 + }, + "frame": { + "x": 70, + "y": 57, + "w": 28, + "h": 28 + } + }, + { + "filename": "773-dragon", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 62, + "y": 85, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-electric", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 62, + "y": 115, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-fairy", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 60, + "y": 145, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-fighting", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 60, + "y": 175, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-fire", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 59, + "y": 205, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-flying", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 59, + "y": 235, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-ghost", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 57, + "y": 265, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-grass", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 57, + "y": 295, + "w": 26, + "h": 30 } }, { @@ -1242,7 +1032,7 @@ "h": 30 }, "frame": { - "x": 60, + "x": 88, "y": 85, "w": 25, "h": 30 @@ -1263,12 +1053,306 @@ "h": 30 }, "frame": { - "x": 60, + "x": 88, "y": 115, "w": 25, "h": 30 } }, + { + "filename": "773-ground", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 86, + "y": 145, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-ice", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 86, + "y": 175, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-poison", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 85, + "y": 205, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-psychic", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 85, + "y": 235, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-rock", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 83, + "y": 265, + "w": 26, + "h": 30 + } + }, + { + "filename": "773-steel", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 83, + "y": 295, + "w": 26, + "h": 30 + } + }, + { + "filename": "772", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 2, + "w": 25, + "h": 28 + }, + "frame": { + "x": 98, + "y": 57, + "w": 25, + "h": 28 + } + }, + { + "filename": "773-water", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 123, + "y": 56, + "w": 26, + "h": 30 + } + }, + { + "filename": "773", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 149, + "y": 56, + "w": 26, + "h": 30 + } + }, + { + "filename": "773s-bug", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 113, + "y": 86, + "w": 26, + "h": 30 + } + }, + { + "filename": "773s-dark", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 139, + "y": 86, + "w": 26, + "h": 30 + } + }, + { + "filename": "773s-dragon", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 113, + "y": 116, + "w": 26, + "h": 30 + } + }, + { + "filename": "773s-electric", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 139, + "y": 116, + "w": 26, + "h": 30 + } + }, + { + "filename": "773s-fairy", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 0, + "w": 26, + "h": 30 + }, + "frame": { + "x": 112, + "y": 146, + "w": 26, + "h": 30 + } + }, { "filename": "773s-fighting", "rotated": false, @@ -1284,8 +1368,8 @@ "h": 30 }, "frame": { - "x": 58, - "y": 145, + "x": 138, + "y": 146, "w": 26, "h": 30 } @@ -1305,8 +1389,8 @@ "h": 30 }, "frame": { - "x": 58, - "y": 175, + "x": 112, + "y": 176, "w": 26, "h": 30 } @@ -1326,8 +1410,8 @@ "h": 30 }, "frame": { - "x": 57, - "y": 205, + "x": 138, + "y": 176, "w": 26, "h": 30 } @@ -1347,8 +1431,8 @@ "h": 30 }, "frame": { - "x": 57, - "y": 235, + "x": 111, + "y": 206, "w": 26, "h": 30 } @@ -1368,33 +1452,12 @@ "h": 30 }, "frame": { - "x": 57, - "y": 265, + "x": 137, + "y": 206, "w": 26, "h": 30 } }, - { - "filename": "730s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 2, - "w": 28, - "h": 27 - }, - "frame": { - "x": 59, - "y": 295, - "w": 28, - "h": 27 - } - }, { "filename": "773s-ground", "rotated": false, @@ -1410,8 +1473,8 @@ "h": 30 }, "frame": { - "x": 54, - "y": 322, + "x": 111, + "y": 236, "w": 26, "h": 30 } @@ -1431,8 +1494,8 @@ "h": 30 }, "frame": { - "x": 54, - "y": 352, + "x": 137, + "y": 236, "w": 26, "h": 30 } @@ -1452,12 +1515,33 @@ "h": 30 }, "frame": { - "x": 54, - "y": 382, + "x": 109, + "y": 266, "w": 26, "h": 30 } }, + { + "filename": "794", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 1, + "w": 25, + "h": 29 + }, + "frame": { + "x": 109, + "y": 296, + "w": 25, + "h": 29 + } + }, { "filename": "773s-psychic", "rotated": false, @@ -1473,12 +1557,54 @@ "h": 30 }, "frame": { - "x": 54, - "y": 412, + "x": 135, + "y": 266, "w": 26, "h": 30 } }, + { + "filename": "794s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 1, + "w": 25, + "h": 29 + }, + "frame": { + "x": 134, + "y": 296, + "w": 25, + "h": 29 + } + }, + { + "filename": "796", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 18, + "h": 29 + }, + "frame": { + "x": 159, + "y": 296, + "w": 18, + "h": 29 + } + }, { "filename": "773s-rock", "rotated": false, @@ -1494,12 +1620,54 @@ "h": 30 }, "frame": { - "x": 54, - "y": 442, + "x": 161, + "y": 266, "w": 26, "h": 30 } }, + { + "filename": "796s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 1, + "w": 18, + "h": 29 + }, + "frame": { + "x": 177, + "y": 296, + "w": 18, + "h": 29 + } + }, + { + "filename": "772s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 2, + "w": 25, + "h": 28 + }, + "frame": { + "x": 167, + "y": 28, + "w": 25, + "h": 28 + } + }, { "filename": "773s-steel", "rotated": false, @@ -1515,8 +1683,8 @@ "h": 30 }, "frame": { - "x": 54, - "y": 472, + "x": 192, + "y": 27, "w": 26, "h": 30 } @@ -1536,8 +1704,8 @@ "h": 30 }, "frame": { - "x": 52, - "y": 502, + "x": 218, + "y": 27, "w": 26, "h": 30 } @@ -1557,98 +1725,14 @@ "h": 30 }, "frame": { - "x": 52, - "y": 532, + "x": 244, + "y": 27, "w": 26, "h": 30 } }, { - "filename": "792-full-moon", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 1, - "w": 28, - "h": 28 - }, - "frame": { - "x": 52, - "y": 562, - "w": 28, - "h": 28 - } - }, - { - "filename": "792", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 1, - "w": 28, - "h": 28 - }, - "frame": { - "x": 52, - "y": 590, - "w": 28, - "h": 28 - } - }, - { - "filename": "792s-full-moon", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 1, - "w": 28, - "h": 28 - }, - "frame": { - "x": 52, - "y": 618, - "w": 28, - "h": 28 - } - }, - { - "filename": "785", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 28, - "h": 26 - }, - "frame": { - "x": 68, - "y": 646, - "w": 28, - "h": 26 - } - }, - { - "filename": "2103s", + "filename": "2103", "rotated": false, "trimmed": true, "sourceSize": { @@ -1662,264 +1746,12 @@ "h": 30 }, "frame": { - "x": 85, - "y": 84, + "x": 270, + "y": 27, "w": 21, "h": 30 } }, - { - "filename": "794", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 1, - "w": 25, - "h": 29 - }, - "frame": { - "x": 85, - "y": 114, - "w": 25, - "h": 29 - } - }, - { - "filename": "783", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 3, - "w": 21, - "h": 27 - }, - "frame": { - "x": 99, - "y": 57, - "w": 21, - "h": 27 - } - }, - { - "filename": "792s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 1, - "w": 28, - "h": 28 - }, - "frame": { - "x": 120, - "y": 56, - "w": 28, - "h": 28 - } - }, - { - "filename": "740", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 4, - "y": 4, - "w": 32, - "h": 23 - }, - "frame": { - "x": 106, - "y": 84, - "w": 32, - "h": 23 - } - }, - { - "filename": "740s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 4, - "y": 4, - "w": 32, - "h": 23 - }, - "frame": { - "x": 148, - "y": 56, - "w": 32, - "h": 23 - } - }, - { - "filename": "785s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 3, - "w": 28, - "h": 26 - }, - "frame": { - "x": 110, - "y": 107, - "w": 28, - "h": 26 - } - }, - { - "filename": "724", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 4, - "w": 19, - "h": 25 - }, - "frame": { - "x": 180, - "y": 56, - "w": 19, - "h": 25 - } - }, - { - "filename": "794s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 1, - "w": 25, - "h": 29 - }, - "frame": { - "x": 138, - "y": 84, - "w": 25, - "h": 29 - } - }, - { - "filename": "725", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 7, - "w": 25, - "h": 21 - }, - "frame": { - "x": 138, - "y": 113, - "w": 25, - "h": 21 - } - }, - { - "filename": "746-school", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 28, - "h": 22 - }, - "frame": { - "x": 110, - "y": 133, - "w": 28, - "h": 22 - } - }, - { - "filename": "725s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 7, - "w": 25, - "h": 21 - }, - "frame": { - "x": 138, - "y": 134, - "w": 25, - "h": 21 - } - }, - { - "filename": "734", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 25, - "h": 16 - }, - "frame": { - "x": 85, - "y": 143, - "w": 25, - "h": 16 - } - }, { "filename": "2026", "rotated": false, @@ -1935,75 +1767,12 @@ "h": 28 }, "frame": { - "x": 84, - "y": 159, + "x": 291, + "y": 23, "w": 26, "h": 28 } }, - { - "filename": "2038", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 30, - "h": 25 - }, - "frame": { - "x": 110, - "y": 155, - "w": 30, - "h": 25 - } - }, - { - "filename": "745-dusk", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 25, - "h": 25 - }, - "frame": { - "x": 140, - "y": 155, - "w": 25, - "h": 25 - } - }, - { - "filename": "746s-school", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 28, - "h": 22 - }, - "frame": { - "x": 84, - "y": 187, - "w": 28, - "h": 22 - } - }, { "filename": "2026s", "rotated": false, @@ -2019,14 +1788,14 @@ "h": 28 }, "frame": { - "x": 83, - "y": 209, + "x": 317, + "y": 23, "w": 26, "h": 28 } }, { - "filename": "772", + "filename": "2075", "rotated": false, "trimmed": true, "sourceSize": { @@ -2034,62 +1803,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 8, - "y": 2, - "w": 25, - "h": 28 - }, - "frame": { - "x": 83, - "y": 237, - "w": 25, - "h": 28 - } - }, - { - "filename": "772s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 2, - "w": 25, - "h": 28 - }, - "frame": { - "x": 83, - "y": 265, - "w": 25, - "h": 28 - } - }, - { - "filename": "2038s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, + "x": 7, "y": 4, - "w": 30, - "h": 25 + "w": 29, + "h": 24 }, "frame": { - "x": 112, - "y": 180, - "w": 30, - "h": 25 + "x": 343, + "y": 25, + "w": 29, + "h": 24 } }, { - "filename": "745s-dusk", + "filename": "2075s", "rotated": false, "trimmed": true, "sourceSize": { @@ -2097,20 +1824,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 8, + "x": 7, "y": 4, - "w": 25, - "h": 25 + "w": 29, + "h": 24 }, "frame": { - "x": 142, - "y": 180, - "w": 25, - "h": 25 + "x": 372, + "y": 25, + "w": 29, + "h": 24 } }, { - "filename": "783s", + "filename": "746-school", "rotated": false, "trimmed": true, "sourceSize": { @@ -2118,16 +1845,37 @@ "h": 30 }, "spriteSourceSize": { - "x": 9, - "y": 3, - "w": 21, - "h": 27 + "x": 7, + "y": 5, + "w": 28, + "h": 22 }, "frame": { - "x": 87, - "y": 293, - "w": 21, - "h": 27 + "x": 401, + "y": 26, + "w": 28, + "h": 22 + } + }, + { + "filename": "746s-school", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 28, + "h": 22 + }, + "frame": { + "x": 429, + "y": 26, + "w": 28, + "h": 22 } }, { @@ -2145,54 +1893,12 @@ "h": 24 }, "frame": { - "x": 163, - "y": 79, + "x": 175, + "y": 56, "w": 17, "h": 24 } }, - { - "filename": "796", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 1, - "w": 18, - "h": 29 - }, - "frame": { - "x": 163, - "y": 103, - "w": 18, - "h": 29 - } - }, - { - "filename": "745", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 6, - "w": 25, - "h": 23 - }, - "frame": { - "x": 163, - "y": 132, - "w": 25, - "h": 23 - } - }, { "filename": "748", "rotated": false, @@ -2208,8 +1914,8 @@ "h": 25 }, "frame": { - "x": 165, - "y": 155, + "x": 192, + "y": 57, "w": 26, "h": 25 } @@ -2229,264 +1935,12 @@ "h": 25 }, "frame": { - "x": 167, - "y": 180, + "x": 218, + "y": 57, "w": 26, "h": 25 } }, - { - "filename": "732", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 6, - "w": 19, - "h": 22 - }, - "frame": { - "x": 180, - "y": 81, - "w": 19, - "h": 22 - } - }, - { - "filename": "796s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 1, - "w": 18, - "h": 29 - }, - "frame": { - "x": 181, - "y": 103, - "w": 18, - "h": 29 - } - }, - { - "filename": "741-sensu", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 5, - "w": 17, - "h": 23 - }, - "frame": { - "x": 188, - "y": 132, - "w": 17, - "h": 23 - } - }, - { - "filename": "724s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 4, - "w": 19, - "h": 25 - }, - "frame": { - "x": 191, - "y": 155, - "w": 19, - "h": 25 - } - }, - { - "filename": "766", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 24, - "h": 26 - }, - "frame": { - "x": 193, - "y": 180, - "w": 24, - "h": 26 - } - }, - { - "filename": "801-original", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 2, - "w": 20, - "h": 28 - }, - "frame": { - "x": 80, - "y": 322, - "w": 20, - "h": 28 - } - }, - { - "filename": "801", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 2, - "w": 20, - "h": 28 - }, - "frame": { - "x": 80, - "y": 350, - "w": 20, - "h": 28 - } - }, - { - "filename": "801s-original", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 2, - "w": 20, - "h": 28 - }, - "frame": { - "x": 80, - "y": 378, - "w": 20, - "h": 28 - } - }, - { - "filename": "801s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 2, - "w": 20, - "h": 28 - }, - "frame": { - "x": 80, - "y": 406, - "w": 20, - "h": 28 - } - }, - { - "filename": "766s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 24, - "h": 26 - }, - "frame": { - "x": 80, - "y": 434, - "w": 24, - "h": 26 - } - }, - { - "filename": "776", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 23, - "h": 26 - }, - "frame": { - "x": 80, - "y": 460, - "w": 23, - "h": 26 - } - }, - { - "filename": "726", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 23, - "h": 24 - }, - "frame": { - "x": 80, - "y": 486, - "w": 23, - "h": 24 - } - }, { "filename": "2089", "rotated": false, @@ -2502,12 +1956,33 @@ "h": 25 }, "frame": { - "x": 78, - "y": 510, + "x": 244, + "y": 57, "w": 26, "h": 25 } }, + { + "filename": "745-dusk", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 25, + "h": 25 + }, + "frame": { + "x": 270, + "y": 57, + "w": 25, + "h": 25 + } + }, { "filename": "2089s", "rotated": false, @@ -2523,14 +1998,14 @@ "h": 25 }, "frame": { - "x": 78, - "y": 535, + "x": 295, + "y": 51, "w": 26, "h": 25 } }, { - "filename": "776s", + "filename": "745s-dusk", "rotated": false, "trimmed": true, "sourceSize": { @@ -2540,123 +2015,123 @@ "spriteSourceSize": { "x": 8, "y": 4, - "w": 23, - "h": 26 + "w": 25, + "h": 25 }, "frame": { - "x": 80, - "y": 560, - "w": 23, - "h": 26 - } - }, - { - "filename": "787", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 2, - "w": 22, - "h": 26 - }, - "frame": { - "x": 80, - "y": 586, - "w": 22, - "h": 26 - } - }, - { - "filename": "787s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 2, - "w": 22, - "h": 26 - }, - "frame": { - "x": 80, - "y": 612, - "w": 22, - "h": 26 - } - }, - { - "filename": "2075", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 29, - "h": 24 - }, - "frame": { - "x": 200, - "y": 27, - "w": 29, - "h": 24 - } - }, - { - "filename": "745-midnight", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 21, - "h": 24 - }, - "frame": { - "x": 229, - "y": 30, - "w": 21, - "h": 24 - } - }, - { - "filename": "2075s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 29, - "h": 24 - }, - "frame": { - "x": 199, + "x": 321, "y": 51, - "w": 29, + "w": 25, + "h": 25 + } + }, + { + "filename": "766", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 24, + "h": 26 + }, + "frame": { + "x": 346, + "y": 49, + "w": 24, + "h": 26 + } + }, + { + "filename": "766s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 24, + "h": 26 + }, + "frame": { + "x": 370, + "y": 49, + "w": 24, + "h": 26 + } + }, + { + "filename": "765", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 28, + "h": 21 + }, + "frame": { + "x": 457, + "y": 28, + "w": 28, + "h": 21 + } + }, + { + "filename": "760s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 4, + "w": 17, + "h": 24 + }, + "frame": { + "x": 485, + "y": 28, + "w": 17, "h": 24 } }, { - "filename": "788", + "filename": "2103s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 0, + "w": 21, + "h": 30 + }, + "frame": { + "x": 165, + "y": 86, + "w": 21, + "h": 30 + } + }, + { + "filename": "783", "rotated": false, "trimmed": true, "sourceSize": { @@ -2665,15 +2140,15 @@ }, "spriteSourceSize": { "x": 9, - "y": 2, - "w": 22, - "h": 26 + "y": 3, + "w": 21, + "h": 27 }, "frame": { - "x": 228, - "y": 54, - "w": 22, - "h": 26 + "x": 165, + "y": 116, + "w": 21, + "h": 27 } }, { @@ -2691,8 +2166,8 @@ "h": 24 }, "frame": { - "x": 199, - "y": 75, + "x": 186, + "y": 82, "w": 25, "h": 24 } @@ -2712,12 +2187,33 @@ "h": 24 }, "frame": { - "x": 199, - "y": 99, + "x": 211, + "y": 82, "w": 25, "h": 24 } }, + { + "filename": "765s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 28, + "h": 21 + }, + "frame": { + "x": 186, + "y": 106, + "w": 28, + "h": 21 + } + }, { "filename": "2028", "rotated": false, @@ -2733,12 +2229,432 @@ "h": 24 }, "frame": { - "x": 224, - "y": 80, + "x": 236, + "y": 82, "w": 25, "h": 24 } }, + { + "filename": "2028s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 25, + "h": 24 + }, + "frame": { + "x": 261, + "y": 82, + "w": 25, + "h": 24 + } + }, + { + "filename": "725", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 214, + "y": 106, + "w": 25, + "h": 21 + } + }, + { + "filename": "725s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 7, + "w": 25, + "h": 21 + }, + "frame": { + "x": 239, + "y": 106, + "w": 25, + "h": 21 + } + }, + { + "filename": "726", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 23, + "h": 24 + }, + "frame": { + "x": 264, + "y": 106, + "w": 23, + "h": 24 + } + }, + { + "filename": "780", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 27, + "h": 19 + }, + "frame": { + "x": 186, + "y": 127, + "w": 27, + "h": 19 + } + }, + { + "filename": "780s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 27, + "h": 19 + }, + "frame": { + "x": 213, + "y": 127, + "w": 27, + "h": 19 + } + }, + { + "filename": "758", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 24, + "h": 22 + }, + "frame": { + "x": 240, + "y": 127, + "w": 24, + "h": 22 + } + }, + { + "filename": "726s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 23, + "h": 24 + }, + "frame": { + "x": 264, + "y": 130, + "w": 23, + "h": 24 + } + }, + { + "filename": "727", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 4, + "w": 23, + "h": 24 + }, + "frame": { + "x": 286, + "y": 82, + "w": 23, + "h": 24 + } + }, + { + "filename": "776", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 23, + "h": 26 + }, + "frame": { + "x": 287, + "y": 106, + "w": 23, + "h": 26 + } + }, + { + "filename": "727s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 4, + "w": 23, + "h": 24 + }, + "frame": { + "x": 287, + "y": 132, + "w": 23, + "h": 24 + } + }, + { + "filename": "776s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 23, + "h": 26 + }, + "frame": { + "x": 309, + "y": 76, + "w": 23, + "h": 26 + } + }, + { + "filename": "783s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 3, + "w": 21, + "h": 27 + }, + "frame": { + "x": 310, + "y": 102, + "w": 21, + "h": 27 + } + }, + { + "filename": "787", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 2, + "w": 22, + "h": 26 + }, + "frame": { + "x": 310, + "y": 129, + "w": 22, + "h": 26 + } + }, + { + "filename": "787s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 2, + "w": 22, + "h": 26 + }, + "frame": { + "x": 332, + "y": 76, + "w": 22, + "h": 26 + } + }, + { + "filename": "788", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 2, + "w": 22, + "h": 26 + }, + "frame": { + "x": 331, + "y": 102, + "w": 22, + "h": 26 + } + }, + { + "filename": "745", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 6, + "w": 25, + "h": 23 + }, + "frame": { + "x": 354, + "y": 75, + "w": 25, + "h": 23 + } + }, + { + "filename": "788s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 2, + "w": 22, + "h": 26 + }, + "frame": { + "x": 332, + "y": 128, + "w": 22, + "h": 26 + } + }, + { + "filename": "724", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 4, + "w": 19, + "h": 25 + }, + "frame": { + "x": 379, + "y": 75, + "w": 19, + "h": 25 + } + }, + { + "filename": "724s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 4, + "w": 19, + "h": 25 + }, + "frame": { + "x": 394, + "y": 49, + "w": 19, + "h": 25 + } + }, { "filename": "745s", "rotated": false, @@ -2754,8 +2670,8 @@ "h": 23 }, "frame": { - "x": 224, - "y": 104, + "x": 413, + "y": 48, "w": 25, "h": 23 } @@ -2775,327 +2691,12 @@ "h": 25 }, "frame": { - "x": 205, - "y": 123, + "x": 438, + "y": 48, "w": 19, "h": 25 } }, - { - "filename": "2020", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 6, - "w": 25, - "h": 22 - }, - "frame": { - "x": 224, - "y": 127, - "w": 25, - "h": 22 - } - }, - { - "filename": "765", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 28, - "h": 21 - }, - "frame": { - "x": 112, - "y": 205, - "w": 28, - "h": 21 - } - }, - { - "filename": "765s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 28, - "h": 21 - }, - "frame": { - "x": 140, - "y": 205, - "w": 28, - "h": 21 - } - }, - { - "filename": "2020s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 6, - "w": 25, - "h": 22 - }, - "frame": { - "x": 168, - "y": 205, - "w": 25, - "h": 22 - } - }, - { - "filename": "758", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 24, - "h": 22 - }, - "frame": { - "x": 193, - "y": 206, - "w": 24, - "h": 22 - } - }, - { - "filename": "780", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 27, - "h": 19 - }, - "frame": { - "x": 109, - "y": 226, - "w": 27, - "h": 19 - } - }, - { - "filename": "2028s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 25, - "h": 24 - }, - "frame": { - "x": 108, - "y": 245, - "w": 25, - "h": 24 - } - }, - { - "filename": "788s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 2, - "w": 22, - "h": 26 - }, - "frame": { - "x": 108, - "y": 269, - "w": 22, - "h": 26 - } - }, - { - "filename": "803", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 3, - "w": 23, - "h": 25 - }, - "frame": { - "x": 108, - "y": 295, - "w": 23, - "h": 25 - } - }, - { - "filename": "780s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 27, - "h": 19 - }, - "frame": { - "x": 136, - "y": 226, - "w": 27, - "h": 19 - } - }, - { - "filename": "726s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 23, - "h": 24 - }, - "frame": { - "x": 133, - "y": 245, - "w": 23, - "h": 24 - } - }, - { - "filename": "803s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 3, - "w": 23, - "h": 25 - }, - "frame": { - "x": 130, - "y": 269, - "w": 23, - "h": 25 - } - }, - { - "filename": "806", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 3, - "w": 22, - "h": 25 - }, - "frame": { - "x": 131, - "y": 294, - "w": 22, - "h": 25 - } - }, - { - "filename": "727", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 4, - "w": 23, - "h": 24 - }, - "frame": { - "x": 100, - "y": 320, - "w": 23, - "h": 24 - } - }, - { - "filename": "727s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 4, - "w": 23, - "h": 24 - }, - "frame": { - "x": 100, - "y": 344, - "w": 23, - "h": 24 - } - }, { "filename": "729", "rotated": false, @@ -3111,14 +2712,14 @@ "h": 24 }, "frame": { - "x": 100, - "y": 368, + "x": 457, + "y": 49, "w": 23, "h": 24 } }, { - "filename": "729s", + "filename": "806", "rotated": false, "trimmed": true, "sourceSize": { @@ -3126,20 +2727,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, - "y": 5, - "w": 23, - "h": 24 + "x": 9, + "y": 3, + "w": 22, + "h": 25 }, "frame": { - "x": 100, - "y": 392, - "w": 23, - "h": 24 + "x": 480, + "y": 52, + "w": 22, + "h": 25 } }, { - "filename": "752", + "filename": "801-original", "rotated": false, "trimmed": true, "sourceSize": { @@ -3148,15 +2749,57 @@ }, "spriteSourceSize": { "x": 10, - "y": 8, - "w": 23, - "h": 18 + "y": 2, + "w": 20, + "h": 28 }, "frame": { - "x": 100, - "y": 416, + "x": 398, + "y": 74, + "w": 20, + "h": 28 + } + }, + { + "filename": "801", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 2, + "w": 20, + "h": 28 + }, + "frame": { + "x": 418, + "y": 71, + "w": 20, + "h": 28 + } + }, + { + "filename": "803", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 3, "w": 23, - "h": 18 + "h": 25 + }, + "frame": { + "x": 438, + "y": 73, + "w": 23, + "h": 25 } }, { @@ -3174,138 +2817,12 @@ "h": 25 }, "frame": { - "x": 104, - "y": 434, + "x": 461, + "y": 73, "w": 19, "h": 25 } }, - { - "filename": "758s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 24, - "h": 22 - }, - "frame": { - "x": 163, - "y": 227, - "w": 24, - "h": 22 - } - }, - { - "filename": "768", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 24, - "h": 23 - }, - "frame": { - "x": 187, - "y": 228, - "w": 24, - "h": 23 - } - }, - { - "filename": "768s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 24, - "h": 23 - }, - "frame": { - "x": 156, - "y": 249, - "w": 24, - "h": 23 - } - }, - { - "filename": "770", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 4, - "w": 23, - "h": 24 - }, - "frame": { - "x": 153, - "y": 272, - "w": 23, - "h": 24 - } - }, - { - "filename": "770s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 4, - "w": 23, - "h": 24 - }, - "frame": { - "x": 153, - "y": 296, - "w": 23, - "h": 24 - } - }, - { - "filename": "2053", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 24, - "h": 22 - }, - "frame": { - "x": 180, - "y": 251, - "w": 24, - "h": 22 - } - }, { "filename": "806s", "rotated": false, @@ -3321,14 +2838,14 @@ "h": 25 }, "frame": { - "x": 176, - "y": 273, + "x": 480, + "y": 77, "w": 22, "h": 25 } }, { - "filename": "756", + "filename": "734", "rotated": false, "trimmed": true, "sourceSize": { @@ -3337,19 +2854,124 @@ }, "spriteSourceSize": { "x": 9, + "y": 10, + "w": 25, + "h": 16 + }, + "frame": { + "x": 354, + "y": 98, + "w": 25, + "h": 16 + } + }, + { + "filename": "767", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 11, + "w": 24, + "h": 14 + }, + "frame": { + "x": 353, + "y": 114, + "w": 24, + "h": 14 + } + }, + { + "filename": "803s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 3, + "w": 23, + "h": 25 + }, + "frame": { + "x": 354, + "y": 128, + "w": 23, + "h": 25 + } + }, + { + "filename": "732", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 6, + "w": 19, + "h": 22 + }, + "frame": { + "x": 379, + "y": 100, + "w": 19, + "h": 22 + } + }, + { + "filename": "801s-original", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 2, + "w": 20, + "h": 28 + }, + "frame": { + "x": 377, + "y": 122, + "w": 20, + "h": 28 + } + }, + { + "filename": "729s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, "y": 5, - "w": 22, + "w": 23, "h": 24 }, "frame": { - "x": 176, - "y": 298, - "w": 22, + "x": 398, + "y": 102, + "w": 23, "h": 24 } }, { - "filename": "786", + "filename": "768", "rotated": false, "trimmed": true, "sourceSize": { @@ -3357,20 +2979,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, - "y": 3, - "w": 20, - "h": 25 + "x": 8, + "y": 5, + "w": 24, + "h": 23 }, "frame": { - "x": 123, - "y": 320, - "w": 20, - "h": 25 + "x": 397, + "y": 126, + "w": 24, + "h": 23 } }, { - "filename": "786s", + "filename": "801s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3378,16 +3000,37 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, - "y": 3, + "x": 10, + "y": 2, "w": 20, - "h": 25 + "h": 28 }, "frame": { - "x": 123, - "y": 345, + "x": 421, + "y": 99, "w": 20, - "h": 25 + "h": 28 + } + }, + { + "filename": "768s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 24, + "h": 23 + }, + "frame": { + "x": 441, + "y": 98, + "w": 24, + "h": 23 } }, { @@ -3405,14 +3048,14 @@ "h": 24 }, "frame": { - "x": 123, - "y": 370, + "x": 421, + "y": 127, "w": 20, "h": 24 } }, { - "filename": "735s", + "filename": "770", "rotated": false, "trimmed": true, "sourceSize": { @@ -3420,20 +3063,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, + "x": 9, "y": 4, - "w": 20, + "w": 23, "h": 24 }, "frame": { - "x": 123, - "y": 394, - "w": 20, + "x": 441, + "y": 121, + "w": 23, "h": 24 } }, { - "filename": "745s-midnight", + "filename": "2050", "rotated": false, "trimmed": true, "sourceSize": { @@ -3441,15 +3084,120 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 21, + "x": 13, + "y": 10, + "w": 15, + "h": 18 + }, + "frame": { + "x": 465, + "y": 98, + "w": 15, + "h": 18 + } + }, + { + "filename": "756", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 22, "h": 24 }, "frame": { - "x": 123, - "y": 418, - "w": 21, + "x": 480, + "y": 102, + "w": 22, + "h": 24 + } + }, + { + "filename": "2050s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 10, + "w": 15, + "h": 18 + }, + "frame": { + "x": 465, + "y": 116, + "w": 15, + "h": 18 + } + }, + { + "filename": "756s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 5, + "w": 22, + "h": 24 + }, + "frame": { + "x": 480, + "y": 126, + "w": 22, + "h": 24 + } + }, + { + "filename": "761", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 8, + "w": 16, + "h": 19 + }, + "frame": { + "x": 464, + "y": 134, + "w": 16, + "h": 19 + } + }, + { + "filename": "802-zenith", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 4, + "w": 22, + "h": 24 + }, + "frame": { + "x": 480, + "y": 150, + "w": 22, "h": 24 } }, @@ -3468,14 +3216,14 @@ "h": 21 }, "frame": { - "x": 123, - "y": 442, + "x": 441, + "y": 145, "w": 23, "h": 21 } }, { - "filename": "2051", + "filename": "761s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3483,20 +3231,41 @@ "h": 30 }, "spriteSourceSize": { - "x": 9, + "x": 13, + "y": 8, + "w": 16, + "h": 19 + }, + "frame": { + "x": 464, + "y": 153, + "w": 16, + "h": 19 + } + }, + { + "filename": "745-midnight", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, "y": 4, - "w": 23, + "w": 21, "h": 24 }, "frame": { - "x": 143, - "y": 320, - "w": 23, + "x": 165, + "y": 143, + "w": 21, "h": 24 } }, { - "filename": "2051s", + "filename": "2020", "rotated": false, "trimmed": true, "sourceSize": { @@ -3504,20 +3273,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 9, - "y": 4, - "w": 23, - "h": 24 + "x": 8, + "y": 6, + "w": 25, + "h": 22 }, "frame": { - "x": 143, - "y": 344, - "w": 23, - "h": 24 + "x": 186, + "y": 146, + "w": 25, + "h": 22 } }, { - "filename": "756s", + "filename": "2020s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3525,20 +3294,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 9, - "y": 5, - "w": 22, - "h": 24 + "x": 8, + "y": 6, + "w": 25, + "h": 22 }, "frame": { - "x": 143, - "y": 368, - "w": 22, - "h": 24 + "x": 211, + "y": 146, + "w": 25, + "h": 22 } }, { - "filename": "802-zenith", + "filename": "802", "rotated": false, "trimmed": true, "sourceSize": { @@ -3552,54 +3321,12 @@ "h": 24 }, "frame": { - "x": 143, - "y": 392, + "x": 164, + "y": 167, "w": 22, "h": 24 } }, - { - "filename": "763", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 4, - "w": 21, - "h": 24 - }, - "frame": { - "x": 144, - "y": 416, - "w": 21, - "h": 24 - } - }, - { - "filename": "749", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 21, - "h": 23 - }, - "frame": { - "x": 146, - "y": 440, - "w": 21, - "h": 23 - } - }, { "filename": "2105", "rotated": false, @@ -3615,8 +3342,8 @@ "h": 23 }, "frame": { - "x": 166, - "y": 322, + "x": 186, + "y": 168, "w": 24, "h": 23 } @@ -3636,14 +3363,14 @@ "h": 23 }, "frame": { - "x": 166, - "y": 345, + "x": 210, + "y": 168, "w": 24, "h": 23 } }, { - "filename": "802", + "filename": "734s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3651,18 +3378,186 @@ "h": 30 }, "spriteSourceSize": { - "x": 13, + "x": 9, + "y": 10, + "w": 25, + "h": 16 + }, + "frame": { + "x": 164, + "y": 191, + "w": 25, + "h": 16 + } + }, + { + "filename": "770s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, "y": 4, - "w": 22, + "w": 23, "h": 24 }, "frame": { - "x": 165, - "y": 368, - "w": 22, + "x": 163, + "y": 207, + "w": 23, "h": 24 } }, + { + "filename": "2051", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 4, + "w": 23, + "h": 24 + }, + "frame": { + "x": 163, + "y": 231, + "w": 23, + "h": 24 + } + }, + { + "filename": "758s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 24, + "h": 22 + }, + "frame": { + "x": 189, + "y": 191, + "w": 24, + "h": 22 + } + }, + { + "filename": "2051s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, + "y": 4, + "w": 23, + "h": 24 + }, + "frame": { + "x": 186, + "y": 213, + "w": 23, + "h": 24 + } + }, + { + "filename": "745s-midnight", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 4, + "w": 21, + "h": 24 + }, + "frame": { + "x": 213, + "y": 191, + "w": 21, + "h": 24 + } + }, + { + "filename": "2053", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 24, + "h": 22 + }, + "frame": { + "x": 209, + "y": 215, + "w": 24, + "h": 22 + } + }, + { + "filename": "2053s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 24, + "h": 22 + }, + "frame": { + "x": 186, + "y": 237, + "w": 24, + "h": 22 + } + }, + { + "filename": "769", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 8, + "y": 6, + "w": 23, + "h": 22 + }, + "frame": { + "x": 210, + "y": 237, + "w": 23, + "h": 22 + } + }, { "filename": "802s-zenith", "rotated": false, @@ -3678,8 +3573,8 @@ "h": 24 }, "frame": { - "x": 165, - "y": 392, + "x": 187, + "y": 259, "w": 22, "h": 24 } @@ -3699,14 +3594,14 @@ "h": 24 }, "frame": { - "x": 165, - "y": 416, + "x": 209, + "y": 259, "w": 22, "h": 24 } }, { - "filename": "749s", + "filename": "746", "rotated": false, "trimmed": true, "sourceSize": { @@ -3714,83 +3609,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 21, - "h": 23 - }, - "frame": { - "x": 167, - "y": 440, - "w": 21, - "h": 23 - } - }, - { - "filename": "755", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 14, - "y": 4, - "w": 13, - "h": 24 - }, - "frame": { - "x": 190, - "y": 322, - "w": 13, - "h": 24 - } - }, - { - "filename": "723", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 5, - "w": 17, - "h": 22 - }, - "frame": { - "x": 190, - "y": 346, - "w": 17, - "h": 22 - } - }, - { - "filename": "763s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 4, - "w": 21, - "h": 24 + "x": 12, + "y": 11, + "w": 18, + "h": 13 }, "frame": { "x": 187, - "y": 368, - "w": 21, - "h": 24 + "y": 283, + "w": 18, + "h": 13 } }, { - "filename": "793", + "filename": "733s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3798,121 +3630,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 21, - "h": 24 + "x": 8, + "y": 7, + "w": 23, + "h": 21 }, "frame": { - "x": 187, - "y": 392, - "w": 21, - "h": 24 - } - }, - { - "filename": "793s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 4, - "w": 21, - "h": 24 - }, - "frame": { - "x": 187, - "y": 416, - "w": 21, - "h": 24 - } - }, - { - "filename": "782", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 188, - "y": 440, - "w": 22, - "h": 23 - } - }, - { - "filename": "755s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 14, - "y": 4, - "w": 13, - "h": 24 - }, - "frame": { - "x": 210, - "y": 148, - "w": 13, - "h": 24 - } - }, - { - "filename": "2053s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 24, - "h": 22 - }, - "frame": { - "x": 223, + "x": 236, "y": 149, - "w": 24, - "h": 22 - } - }, - { - "filename": "760s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 4, - "w": 17, - "h": 24 - }, - "frame": { - "x": 198, - "y": 273, - "w": 17, - "h": 24 + "w": 23, + "h": 21 } }, { @@ -3930,14 +3657,14 @@ "h": 24 }, "frame": { - "x": 198, - "y": 297, + "x": 234, + "y": 170, "w": 22, "h": 24 } }, { - "filename": "723s", + "filename": "738", "rotated": false, "trimmed": true, "sourceSize": { @@ -3945,16 +3672,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, - "y": 5, - "w": 17, - "h": 22 + "x": 9, + "y": 6, + "w": 22, + "h": 21 }, "frame": { - "x": 204, - "y": 251, - "w": 17, - "h": 22 + "x": 234, + "y": 194, + "w": 22, + "h": 21 } }, { @@ -3972,14 +3699,14 @@ "h": 24 }, "frame": { - "x": 203, - "y": 321, + "x": 233, + "y": 215, "w": 22, "h": 24 } }, { - "filename": "762", + "filename": "738s", "rotated": false, "trimmed": true, "sourceSize": { @@ -3987,20 +3714,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, - "y": 4, - "w": 18, - "h": 23 + "x": 9, + "y": 6, + "w": 22, + "h": 21 }, "frame": { - "x": 207, - "y": 345, - "w": 18, - "h": 23 + "x": 233, + "y": 239, + "w": 22, + "h": 21 } }, { - "filename": "741s-sensu", + "filename": "769s", "rotated": false, "trimmed": true, "sourceSize": { @@ -4008,36 +3735,162 @@ "h": 30 }, "spriteSourceSize": { - "x": 13, + "x": 8, + "y": 6, + "w": 23, + "h": 22 + }, + "frame": { + "x": 231, + "y": 260, + "w": 23, + "h": 22 + } + }, + { + "filename": "767s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 11, + "w": 24, + "h": 14 + }, + "frame": { + "x": 205, + "y": 283, + "w": 24, + "h": 14 + } + }, + { + "filename": "763", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 4, + "w": 21, + "h": 24 + }, + "frame": { + "x": 195, + "y": 297, + "w": 21, + "h": 24 + } + }, + { + "filename": "735s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 4, + "w": 20, + "h": 24 + }, + "frame": { + "x": 216, + "y": 297, + "w": 20, + "h": 24 + } + }, + { + "filename": "752", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 23, + "h": 18 + }, + "frame": { + "x": 259, + "y": 154, + "w": 23, + "h": 18 + } + }, + { + "filename": "763s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 4, + "w": 21, + "h": 24 + }, + "frame": { + "x": 256, + "y": 172, + "w": 21, + "h": 24 + } + }, + { + "filename": "747", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 22, + "h": 20 + }, + "frame": { + "x": 256, + "y": 196, + "w": 22, + "h": 20 + } + }, + { + "filename": "782", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 9, "y": 5, - "w": 17, + "w": 22, "h": 23 }, "frame": { - "x": 208, - "y": 368, - "w": 17, - "h": 23 - } - }, - { - "filename": "762s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 4, - "w": 18, - "h": 23 - }, - "frame": { - "x": 208, - "y": 391, - "w": 18, + "x": 255, + "y": 216, + "w": 22, "h": 23 } }, @@ -4056,14 +3909,14 @@ "h": 23 }, "frame": { - "x": 208, - "y": 414, + "x": 255, + "y": 239, "w": 22, "h": 23 } }, { - "filename": "2076", + "filename": "789", "rotated": false, "trimmed": true, "sourceSize": { @@ -4071,16 +3924,37 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, - "y": 5, - "w": 21, - "h": 23 + "x": 10, + "y": 6, + "w": 23, + "h": 20 }, "frame": { - "x": 210, - "y": 437, - "w": 21, - "h": 23 + "x": 254, + "y": 262, + "w": 23, + "h": 20 + } + }, + { + "filename": "752s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 23, + "h": 18 + }, + "frame": { + "x": 282, + "y": 156, + "w": 23, + "h": 18 } }, { @@ -4098,71 +3972,8 @@ "h": 22 }, "frame": { - "x": 230, - "y": 171, - "w": 20, - "h": 22 - } - }, - { - "filename": "743s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 5, - "w": 20, - "h": 22 - }, - "frame": { - "x": 230, - "y": 193, - "w": 20, - "h": 22 - } - }, - { - "filename": "754", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 6, - "w": 20, - "h": 22 - }, - "frame": { - "x": 230, - "y": 215, - "w": 20, - "h": 22 - } - }, - { - "filename": "754s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 6, - "w": 20, - "h": 22 - }, - "frame": { - "x": 230, - "y": 237, + "x": 277, + "y": 174, "w": 20, "h": 22 } @@ -4182,12 +3993,54 @@ "h": 22 }, "frame": { - "x": 211, - "y": 228, + "x": 278, + "y": 196, "w": 19, "h": 22 } }, + { + "filename": "786", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 3, + "w": 20, + "h": 25 + }, + "frame": { + "x": 277, + "y": 218, + "w": 20, + "h": 25 + } + }, + { + "filename": "786s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 3, + "w": 20, + "h": 25 + }, + "frame": { + "x": 277, + "y": 243, + "w": 20, + "h": 25 + } + }, { "filename": "739", "rotated": false, @@ -4203,14 +4056,14 @@ "h": 21 }, "frame": { - "x": 230, - "y": 259, + "x": 277, + "y": 268, "w": 20, "h": 21 } }, { - "filename": "739s", + "filename": "755", "rotated": false, "trimmed": true, "sourceSize": { @@ -4218,20 +4071,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 20, - "h": 21 + "x": 14, + "y": 4, + "w": 13, + "h": 24 }, "frame": { - "x": 230, - "y": 280, - "w": 20, - "h": 21 + "x": 297, + "y": 174, + "w": 13, + "h": 24 } }, { - "filename": "2050", + "filename": "755s", "rotated": false, "trimmed": true, "sourceSize": { @@ -4239,20 +4092,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 13, - "y": 10, - "w": 15, - "h": 18 + "x": 14, + "y": 4, + "w": 13, + "h": 24 }, "frame": { - "x": 215, - "y": 273, - "w": 15, - "h": 18 + "x": 297, + "y": 198, + "w": 13, + "h": 24 } }, { - "filename": "744", + "filename": "793", "rotated": false, "trimmed": true, "sourceSize": { @@ -4260,20 +4113,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 19, - "h": 22 + "x": 10, + "y": 4, + "w": 21, + "h": 24 }, "frame": { - "x": 231, - "y": 301, - "w": 19, - "h": 22 + "x": 297, + "y": 222, + "w": 21, + "h": 24 } }, { - "filename": "734s", + "filename": "793s", "rotated": false, "trimmed": true, "sourceSize": { @@ -4281,20 +4134,20 @@ "h": 30 }, "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 25, - "h": 16 + "x": 10, + "y": 4, + "w": 21, + "h": 24 }, "frame": { - "x": 225, - "y": 323, - "w": 25, - "h": 16 + "x": 297, + "y": 246, + "w": 21, + "h": 24 } }, { - "filename": "769", + "filename": "747s", "rotated": false, "trimmed": true, "sourceSize": { @@ -4302,37 +4155,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 8, - "y": 6, - "w": 23, - "h": 22 + "x": 10, + "y": 7, + "w": 22, + "h": 20 }, "frame": { - "x": 225, - "y": 339, - "w": 23, - "h": 22 - } - }, - { - "filename": "769s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 6, - "w": 23, - "h": 22 - }, - "frame": { - "x": 225, - "y": 361, - "w": 23, - "h": 22 + "x": 297, + "y": 270, + "w": 22, + "h": 20 } }, { @@ -4350,12 +4182,516 @@ "h": 15 }, "frame": { - "x": 226, - "y": 383, + "x": 231, + "y": 282, "w": 24, "h": 15 } }, + { + "filename": "2037", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 22, + "h": 21 + }, + "frame": { + "x": 255, + "y": 282, + "w": 22, + "h": 21 + } + }, + { + "filename": "744", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 19, + "h": 22 + }, + "frame": { + "x": 236, + "y": 297, + "w": 19, + "h": 22 + } + }, + { + "filename": "743s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 5, + "w": 20, + "h": 22 + }, + "frame": { + "x": 255, + "y": 303, + "w": 20, + "h": 22 + } + }, + { + "filename": "754", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 6, + "w": 20, + "h": 22 + }, + "frame": { + "x": 275, + "y": 303, + "w": 20, + "h": 22 + } + }, + { + "filename": "746s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 18, + "h": 13 + }, + "frame": { + "x": 277, + "y": 290, + "w": 18, + "h": 13 + } + }, + { + "filename": "749", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 21, + "h": 23 + }, + "frame": { + "x": 295, + "y": 290, + "w": 21, + "h": 23 + } + }, + { + "filename": "722", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 8, + "w": 17, + "h": 18 + }, + "frame": { + "x": 305, + "y": 156, + "w": 17, + "h": 18 + } + }, + { + "filename": "741-sensu", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 5, + "w": 17, + "h": 23 + }, + "frame": { + "x": 310, + "y": 174, + "w": 17, + "h": 23 + } + }, + { + "filename": "741s-sensu", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 5, + "w": 17, + "h": 23 + }, + "frame": { + "x": 310, + "y": 197, + "w": 17, + "h": 23 + } + }, + { + "filename": "737", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 8, + "w": 18, + "h": 19 + }, + "frame": { + "x": 322, + "y": 155, + "w": 18, + "h": 19 + } + }, + { + "filename": "749s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 21, + "h": 23 + }, + "frame": { + "x": 327, + "y": 174, + "w": 21, + "h": 23 + } + }, + { + "filename": "2076", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 5, + "w": 21, + "h": 23 + }, + "frame": { + "x": 327, + "y": 197, + "w": 21, + "h": 23 + } + }, + { + "filename": "2076s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 5, + "w": 21, + "h": 23 + }, + "frame": { + "x": 318, + "y": 220, + "w": 21, + "h": 23 + } + }, + { + "filename": "754s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 6, + "w": 20, + "h": 22 + }, + "frame": { + "x": 318, + "y": 243, + "w": 20, + "h": 22 + } + }, + { + "filename": "728", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 8, + "w": 17, + "h": 20 + }, + "frame": { + "x": 340, + "y": 154, + "w": 17, + "h": 20 + } + }, + { + "filename": "739s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 20, + "h": 21 + }, + "frame": { + "x": 357, + "y": 153, + "w": 20, + "h": 21 + } + }, + { + "filename": "789s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 6, + "w": 23, + "h": 20 + }, + "frame": { + "x": 348, + "y": 174, + "w": 23, + "h": 20 + } + }, + { + "filename": "2037s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 22, + "h": 21 + }, + "frame": { + "x": 348, + "y": 194, + "w": 22, + "h": 21 + } + }, + { + "filename": "744s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 6, + "w": 19, + "h": 22 + }, + "frame": { + "x": 377, + "y": 150, + "w": 19, + "h": 22 + } + }, + { + "filename": "762", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 4, + "w": 18, + "h": 23 + }, + "frame": { + "x": 319, + "y": 265, + "w": 18, + "h": 23 + } + }, + { + "filename": "762s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 4, + "w": 18, + "h": 23 + }, + "frame": { + "x": 339, + "y": 220, + "w": 18, + "h": 23 + } + }, + { + "filename": "741-pau", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 14, + "y": 6, + "w": 18, + "h": 22 + }, + "frame": { + "x": 338, + "y": 243, + "w": 18, + "h": 22 + } + }, + { + "filename": "741s-pau", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 14, + "y": 6, + "w": 18, + "h": 22 + }, + "frame": { + "x": 337, + "y": 265, + "w": 18, + "h": 22 + } + }, + { + "filename": "723", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 5, + "w": 17, + "h": 22 + }, + "frame": { + "x": 357, + "y": 215, + "w": 17, + "h": 22 + } + }, { "filename": "2074s", "rotated": false, @@ -4371,8 +4707,8 @@ "h": 15 }, "frame": { - "x": 226, - "y": 398, + "x": 397, + "y": 149, "w": 24, "h": 15 } @@ -4392,54 +4728,12 @@ "h": 20 }, "frame": { - "x": 230, - "y": 413, + "x": 421, + "y": 151, "w": 20, "h": 20 } }, - { - "filename": "744s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 6, - "w": 19, - "h": 22 - }, - "frame": { - "x": 231, - "y": 433, - "w": 19, - "h": 22 - } - }, - { - "filename": "742", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 5, - "w": 19, - "h": 20 - }, - "frame": { - "x": 231, - "y": 455, - "w": 19, - "h": 20 - } - }, { "filename": "775", "rotated": false, @@ -4455,14 +4749,14 @@ "h": 20 }, "frame": { - "x": 210, - "y": 460, + "x": 396, + "y": 164, "w": 21, "h": 20 } }, { - "filename": "742s", + "filename": "742", "rotated": false, "trimmed": true, "sourceSize": { @@ -4476,180 +4770,12 @@ "h": 20 }, "frame": { - "x": 231, - "y": 475, + "x": 377, + "y": 172, "w": 19, "h": 20 } }, - { - "filename": "733s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 8, - "y": 7, - "w": 23, - "h": 21 - }, - "frame": { - "x": 103, - "y": 463, - "w": 23, - "h": 21 - } - }, - { - "filename": "2076s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 5, - "w": 21, - "h": 23 - }, - "frame": { - "x": 103, - "y": 484, - "w": 21, - "h": 23 - } - }, - { - "filename": "738", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 22, - "h": 21 - }, - "frame": { - "x": 126, - "y": 463, - "w": 22, - "h": 21 - } - }, - { - "filename": "738s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 22, - "h": 21 - }, - "frame": { - "x": 124, - "y": 484, - "w": 22, - "h": 21 - } - }, - { - "filename": "2037", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 22, - "h": 21 - }, - "frame": { - "x": 148, - "y": 463, - "w": 22, - "h": 21 - } - }, - { - "filename": "2037s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 22, - "h": 21 - }, - "frame": { - "x": 146, - "y": 484, - "w": 22, - "h": 21 - } - }, - { - "filename": "747s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 22, - "h": 20 - }, - "frame": { - "x": 170, - "y": 463, - "w": 22, - "h": 20 - } - }, - { - "filename": "741-pau", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 14, - "y": 6, - "w": 18, - "h": 22 - }, - "frame": { - "x": 192, - "y": 463, - "w": 18, - "h": 22 - } - }, { "filename": "775s", "rotated": false, @@ -4665,495 +4791,12 @@ "h": 20 }, "frame": { - "x": 210, - "y": 480, + "x": 417, + "y": 171, "w": 21, "h": 20 } }, - { - "filename": "757", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 19, - "h": 18 - }, - "frame": { - "x": 231, - "y": 495, - "w": 19, - "h": 18 - } - }, - { - "filename": "2019", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 21, - "h": 21 - }, - "frame": { - "x": 104, - "y": 507, - "w": 21, - "h": 21 - } - }, - { - "filename": "2019s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 5, - "w": 21, - "h": 21 - }, - "frame": { - "x": 104, - "y": 528, - "w": 21, - "h": 21 - } - }, - { - "filename": "2052", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 7, - "w": 21, - "h": 21 - }, - "frame": { - "x": 125, - "y": 505, - "w": 21, - "h": 21 - } - }, - { - "filename": "2052s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 11, - "y": 7, - "w": 21, - "h": 21 - }, - "frame": { - "x": 125, - "y": 526, - "w": 21, - "h": 21 - } - }, - { - "filename": "779", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 21, - "h": 20 - }, - "frame": { - "x": 146, - "y": 505, - "w": 21, - "h": 20 - } - }, - { - "filename": "779s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 21, - "h": 20 - }, - "frame": { - "x": 146, - "y": 525, - "w": 21, - "h": 20 - } - }, - { - "filename": "752s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 23, - "h": 18 - }, - "frame": { - "x": 104, - "y": 549, - "w": 23, - "h": 18 - } - }, - { - "filename": "790", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 21, - "h": 19 - }, - "frame": { - "x": 103, - "y": 567, - "w": 21, - "h": 19 - } - }, - { - "filename": "741s-pau", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 14, - "y": 6, - "w": 18, - "h": 22 - }, - "frame": { - "x": 102, - "y": 586, - "w": 18, - "h": 22 - } - }, - { - "filename": "731", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 6, - "w": 17, - "h": 22 - }, - "frame": { - "x": 102, - "y": 608, - "w": 17, - "h": 22 - } - }, - { - "filename": "741s-pompom", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 20, - "h": 20 - }, - "frame": { - "x": 127, - "y": 547, - "w": 20, - "h": 20 - } - }, - { - "filename": "790s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 7, - "w": 21, - "h": 19 - }, - "frame": { - "x": 124, - "y": 567, - "w": 21, - "h": 19 - } - }, - { - "filename": "731s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 6, - "w": 17, - "h": 22 - }, - "frame": { - "x": 120, - "y": 586, - "w": 17, - "h": 22 - } - }, - { - "filename": "778-disguised", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 5, - "w": 17, - "h": 22 - }, - "frame": { - "x": 119, - "y": 608, - "w": 17, - "h": 22 - } - }, - { - "filename": "778s-disguised", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 5, - "w": 17, - "h": 22 - }, - "frame": { - "x": 147, - "y": 545, - "w": 17, - "h": 22 - } - }, - { - "filename": "737", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 8, - "w": 18, - "h": 19 - }, - "frame": { - "x": 145, - "y": 567, - "w": 18, - "h": 19 - } - }, - { - "filename": "2027", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 10, - "w": 21, - "h": 18 - }, - "frame": { - "x": 137, - "y": 586, - "w": 21, - "h": 18 - } - }, - { - "filename": "767", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 24, - "h": 14 - }, - "frame": { - "x": 102, - "y": 630, - "w": 24, - "h": 14 - } - }, - { - "filename": "2027s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 10, - "w": 21, - "h": 18 - }, - "frame": { - "x": 96, - "y": 644, - "w": 21, - "h": 18 - } - }, - { - "filename": "722", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 8, - "w": 17, - "h": 18 - }, - "frame": { - "x": 117, - "y": 644, - "w": 17, - "h": 18 - } - }, - { - "filename": "767s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 24, - "h": 14 - }, - "frame": { - "x": 126, - "y": 630, - "w": 24, - "h": 14 - } - }, - { - "filename": "722s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 8, - "w": 17, - "h": 18 - }, - "frame": { - "x": 134, - "y": 644, - "w": 17, - "h": 18 - } - }, { "filename": "778-busted", "rotated": false, @@ -5169,14 +4812,14 @@ "h": 16 }, "frame": { - "x": 137, - "y": 604, + "x": 396, + "y": 184, "w": 21, "h": 16 } }, { - "filename": "728", + "filename": "778s-busted", "rotated": false, "trimmed": true, "sourceSize": { @@ -5184,18 +4827,60 @@ "h": 30 }, "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 17, + "x": 9, + "y": 12, + "w": 21, + "h": 16 + }, + "frame": { + "x": 417, + "y": 191, + "w": 21, + "h": 16 + } + }, + { + "filename": "779", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 21, "h": 20 }, "frame": { - "x": 158, - "y": 586, - "w": 17, + "x": 441, + "y": 166, + "w": 21, "h": 20 } }, + { + "filename": "2019", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 21, + "h": 21 + }, + "frame": { + "x": 438, + "y": 186, + "w": 21, + "h": 21 + } + }, { "filename": "737s", "rotated": false, @@ -5211,14 +4896,14 @@ "h": 19 }, "frame": { - "x": 163, - "y": 567, + "x": 462, + "y": 172, "w": 18, "h": 19 } }, { - "filename": "728s", + "filename": "779s", "rotated": false, "trimmed": true, "sourceSize": { @@ -5226,15 +4911,225 @@ "h": 30 }, "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 17, + "x": 10, + "y": 7, + "w": 21, "h": 20 }, "frame": { - "x": 158, - "y": 606, + "x": 480, + "y": 174, + "w": 21, + "h": 20 + } + }, + { + "filename": "790", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 21, + "h": 19 + }, + "frame": { + "x": 459, + "y": 191, + "w": 21, + "h": 19 + } + }, + { + "filename": "790s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 21, + "h": 19 + }, + "frame": { + "x": 480, + "y": 194, + "w": 21, + "h": 19 + } + }, + { + "filename": "2019s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 5, + "w": 21, + "h": 21 + }, + "frame": { + "x": 370, + "y": 194, + "w": 21, + "h": 21 + } + }, + { + "filename": "723s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 5, "w": 17, + "h": 22 + }, + "frame": { + "x": 374, + "y": 215, + "w": 17, + "h": 22 + } + }, + { + "filename": "2052", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 7, + "w": 21, + "h": 21 + }, + "frame": { + "x": 391, + "y": 200, + "w": 21, + "h": 21 + } + }, + { + "filename": "2027", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 10, + "w": 21, + "h": 18 + }, + "frame": { + "x": 391, + "y": 221, + "w": 21, + "h": 18 + } + }, + { + "filename": "2052s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 11, + "y": 7, + "w": 21, + "h": 21 + }, + "frame": { + "x": 412, + "y": 207, + "w": 21, + "h": 21 + } + }, + { + "filename": "741s-pompom", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 7, + "w": 20, + "h": 20 + }, + "frame": { + "x": 433, + "y": 207, + "w": 20, + "h": 20 + } + }, + { + "filename": "2027s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 10, + "y": 10, + "w": 21, + "h": 18 + }, + "frame": { + "x": 412, + "y": 228, + "w": 21, + "h": 18 + } + }, + { + "filename": "742s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 5, + "w": 19, + "h": 20 + }, + "frame": { + "x": 433, + "y": 227, + "w": 19, "h": 20 } }, @@ -5253,8 +5148,8 @@ "h": 18 }, "frame": { - "x": 150, - "y": 626, + "x": 453, + "y": 210, "w": 21, "h": 18 } @@ -5274,14 +5169,14 @@ "h": 18 }, "frame": { - "x": 151, - "y": 644, + "x": 452, + "y": 228, "w": 21, "h": 18 } }, { - "filename": "751", + "filename": "757", "rotated": false, "trimmed": true, "sourceSize": { @@ -5289,37 +5184,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 14, - "h": 20 + "x": 11, + "y": 9, + "w": 19, + "h": 18 }, "frame": { - "x": 175, - "y": 586, - "w": 14, - "h": 20 - } - }, - { - "filename": "751s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 14, - "h": 20 - }, - "frame": { - "x": 175, - "y": 606, - "w": 14, - "h": 20 + "x": 474, + "y": 213, + "w": 19, + "h": 18 } }, { @@ -5337,12 +5211,138 @@ "h": 18 }, "frame": { - "x": 171, - "y": 626, + "x": 473, + "y": 231, "w": 19, "h": 18 } }, + { + "filename": "731", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 6, + "w": 17, + "h": 22 + }, + "frame": { + "x": 316, + "y": 290, + "w": 17, + "h": 22 + } + }, + { + "filename": "771", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 11, + "w": 18, + "h": 13 + }, + "frame": { + "x": 316, + "y": 312, + "w": 18, + "h": 13 + } + }, + { + "filename": "731s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 6, + "w": 17, + "h": 22 + }, + "frame": { + "x": 333, + "y": 288, + "w": 17, + "h": 22 + } + }, + { + "filename": "736", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 12, + "w": 17, + "h": 13 + }, + "frame": { + "x": 334, + "y": 310, + "w": 17, + "h": 13 + } + }, + { + "filename": "778-disguised", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 5, + "w": 17, + "h": 22 + }, + "frame": { + "x": 350, + "y": 287, + "w": 17, + "h": 22 + } + }, + { + "filename": "778s-disguised", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 5, + "w": 17, + "h": 22 + }, + "frame": { + "x": 355, + "y": 265, + "w": 17, + "h": 22 + } + }, { "filename": "741", "rotated": false, @@ -5358,14 +5358,14 @@ "h": 19 }, "frame": { - "x": 172, - "y": 644, + "x": 356, + "y": 246, "w": 17, "h": 19 } }, { - "filename": "778s-busted", + "filename": "728s", "rotated": false, "trimmed": true, "sourceSize": { @@ -5373,16 +5373,79 @@ "h": 30 }, "spriteSourceSize": { - "x": 9, - "y": 12, - "w": 21, - "h": 16 + "x": 13, + "y": 8, + "w": 17, + "h": 20 }, "frame": { - "x": 189, - "y": 485, - "w": 21, - "h": 16 + "x": 373, + "y": 237, + "w": 17, + "h": 20 + } + }, + { + "filename": "722s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 8, + "w": 17, + "h": 18 + }, + "frame": { + "x": 390, + "y": 239, + "w": 17, + "h": 18 + } + }, + { + "filename": "736s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 12, + "w": 17, + "h": 13 + }, + "frame": { + "x": 351, + "y": 309, + "w": 17, + "h": 13 + } + }, + { + "filename": "771s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 11, + "w": 18, + "h": 13 + }, + "frame": { + "x": 373, + "y": 257, + "w": 18, + "h": 13 } }, { @@ -5400,54 +5463,12 @@ "h": 19 }, "frame": { - "x": 164, - "y": 545, + "x": 372, + "y": 270, "w": 17, "h": 19 } }, - { - "filename": "753", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 14, - "y": 8, - "w": 14, - "h": 19 - }, - "frame": { - "x": 168, - "y": 484, - "w": 14, - "h": 19 - } - }, - { - "filename": "753s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 14, - "y": 8, - "w": 14, - "h": 19 - }, - "frame": { - "x": 189, - "y": 644, - "w": 14, - "h": 19 - } - }, { "filename": "759", "rotated": false, @@ -5463,12 +5484,33 @@ "h": 19 }, "frame": { - "x": 167, - "y": 505, + "x": 367, + "y": 289, "w": 17, "h": 19 } }, + { + "filename": "808", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 17, + "h": 17 + }, + "frame": { + "x": 368, + "y": 308, + "w": 17, + "h": 17 + } + }, { "filename": "759s", "rotated": false, @@ -5484,117 +5526,12 @@ "h": 19 }, "frame": { - "x": 167, - "y": 524, + "x": 391, + "y": 257, "w": 17, "h": 19 } }, - { - "filename": "777", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 17, - "h": 19 - }, - "frame": { - "x": 184, - "y": 501, - "w": 17, - "h": 19 - } - }, - { - "filename": "777s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 17, - "h": 19 - }, - "frame": { - "x": 184, - "y": 520, - "w": 17, - "h": 19 - } - }, - { - "filename": "761", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 16, - "h": 19 - }, - "frame": { - "x": 201, - "y": 501, - "w": 16, - "h": 19 - } - }, - { - "filename": "761s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 16, - "h": 19 - }, - "frame": { - "x": 201, - "y": 520, - "w": 16, - "h": 19 - } - }, - { - "filename": "746", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 11, - "w": 18, - "h": 13 - }, - "frame": { - "x": 184, - "y": 539, - "w": 18, - "h": 13 - } - }, { "filename": "774-blue", "rotated": false, @@ -5610,14 +5547,14 @@ "h": 18 }, "frame": { - "x": 181, - "y": 552, + "x": 389, + "y": 276, "w": 17, "h": 18 } }, { - "filename": "736", + "filename": "777", "rotated": false, "trimmed": true, "sourceSize": { @@ -5625,37 +5562,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, - "y": 12, + "x": 13, + "y": 8, "w": 17, - "h": 13 + "h": 19 }, "frame": { - "x": 181, - "y": 570, + "x": 408, + "y": 246, "w": 17, - "h": 13 - } - }, - { - "filename": "736s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 12, - "w": 17, - "h": 13 - }, - "frame": { - "x": 202, - "y": 539, - "w": 17, - "h": 13 + "h": 19 } }, { @@ -5673,14 +5589,14 @@ "h": 18 }, "frame": { - "x": 198, - "y": 552, + "x": 408, + "y": 265, "w": 17, "h": 18 } }, { - "filename": "746s", + "filename": "777s", "rotated": false, "trimmed": true, "sourceSize": { @@ -5688,16 +5604,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 12, - "y": 11, - "w": 18, - "h": 13 + "x": 13, + "y": 8, + "w": 17, + "h": 19 }, "frame": { - "x": 198, - "y": 570, - "w": 18, - "h": 13 + "x": 425, + "y": 247, + "w": 17, + "h": 19 } }, { @@ -5715,12 +5631,33 @@ "h": 18 }, "frame": { - "x": 189, - "y": 583, + "x": 425, + "y": 266, "w": 17, "h": 18 } }, + { + "filename": "751", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 8, + "w": 14, + "h": 20 + }, + "frame": { + "x": 442, + "y": 247, + "w": 14, + "h": 20 + } + }, { "filename": "774-orange", "rotated": false, @@ -5736,8 +5673,8 @@ "h": 18 }, "frame": { - "x": 189, - "y": 601, + "x": 456, + "y": 246, "w": 17, "h": 18 } @@ -5757,12 +5694,33 @@ "h": 18 }, "frame": { - "x": 206, - "y": 583, + "x": 473, + "y": 249, "w": 17, "h": 18 } }, + { + "filename": "751s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 8, + "w": 14, + "h": 20 + }, + "frame": { + "x": 442, + "y": 267, + "w": 14, + "h": 20 + } + }, { "filename": "774-violet", "rotated": false, @@ -5778,8 +5736,8 @@ "h": 18 }, "frame": { - "x": 206, - "y": 601, + "x": 456, + "y": 264, "w": 17, "h": 18 } @@ -5799,8 +5757,8 @@ "h": 18 }, "frame": { - "x": 190, - "y": 619, + "x": 473, + "y": 267, "w": 17, "h": 18 } @@ -5820,8 +5778,8 @@ "h": 18 }, "frame": { - "x": 207, - "y": 619, + "x": 406, + "y": 283, "w": 17, "h": 18 } @@ -5841,33 +5799,12 @@ "h": 18 }, "frame": { - "x": 203, - "y": 637, + "x": 423, + "y": 284, "w": 17, "h": 18 } }, - { - "filename": "808", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 11, - "w": 17, - "h": 17 - }, - "frame": { - "x": 203, - "y": 655, - "w": 17, - "h": 17 - } - }, { "filename": "774s-green", "rotated": false, @@ -5883,14 +5820,14 @@ "h": 18 }, "frame": { - "x": 215, - "y": 552, + "x": 440, + "y": 287, "w": 17, "h": 18 } }, { - "filename": "771", + "filename": "753", "rotated": false, "trimmed": true, "sourceSize": { @@ -5898,58 +5835,16 @@ "h": 30 }, "spriteSourceSize": { - "x": 13, - "y": 11, - "w": 18, - "h": 13 + "x": 14, + "y": 8, + "w": 14, + "h": 19 }, "frame": { - "x": 216, - "y": 570, - "w": 18, - "h": 13 - } - }, - { - "filename": "771s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 11, - "w": 18, - "h": 13 - }, - "frame": { - "x": 232, - "y": 513, - "w": 18, - "h": 13 - } - }, - { - "filename": "2050s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 13, - "y": 10, - "w": 15, - "h": 18 - }, - "frame": { - "x": 217, - "y": 513, - "w": 15, - "h": 18 + "x": 457, + "y": 282, + "w": 14, + "h": 19 } }, { @@ -5967,12 +5862,33 @@ "h": 18 }, "frame": { - "x": 223, - "y": 583, + "x": 471, + "y": 285, "w": 17, "h": 18 } }, + { + "filename": "753s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 14, + "y": 8, + "w": 14, + "h": 19 + }, + "frame": { + "x": 488, + "y": 285, + "w": 14, + "h": 19 + } + }, { "filename": "774s-orange", "rotated": false, @@ -5988,8 +5904,8 @@ "h": 18 }, "frame": { - "x": 223, - "y": 601, + "x": 385, + "y": 294, "w": 17, "h": 18 } @@ -6009,8 +5925,8 @@ "h": 18 }, "frame": { - "x": 224, - "y": 619, + "x": 402, + "y": 301, "w": 17, "h": 18 } @@ -6030,33 +5946,12 @@ "h": 18 }, "frame": { - "x": 220, - "y": 637, + "x": 419, + "y": 302, "w": 17, "h": 18 } }, - { - "filename": "808s", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 40, - "h": 30 - }, - "spriteSourceSize": { - "x": 12, - "y": 11, - "w": 17, - "h": 17 - }, - "frame": { - "x": 220, - "y": 655, - "w": 17, - "h": 17 - } - }, { "filename": "774s-yellow", "rotated": false, @@ -6072,8 +5967,8 @@ "h": 18 }, "frame": { - "x": 219, - "y": 531, + "x": 436, + "y": 305, "w": 17, "h": 18 } @@ -6093,11 +5988,32 @@ "h": 18 }, "frame": { - "x": 232, - "y": 549, + "x": 453, + "y": 305, "w": 17, "h": 18 } + }, + { + "filename": "808s", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 12, + "y": 11, + "w": 17, + "h": 17 + }, + "frame": { + "x": 470, + "y": 303, + "w": 17, + "h": 17 + } } ] } @@ -6105,6 +6021,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:be37a6c6f866e26c7e4deba1514c5a68:cb56f7bd9b13cc1604b5814449582c05:2e7c5873ead8fd8fce82a0b3fcc86b42$" + "smartupdate": "$TexturePacker:SmartUpdate:5861cb99c3db0943f1ccef3b0e1b4683:26656a692718930d92be5b6aba391ced:2e7c5873ead8fd8fce82a0b3fcc86b42$" } } diff --git a/public/images/pokemon_icons_7.png b/public/images/pokemon_icons_7.png index 8c8311b1d0b9269c18570345f54b5b734b6b3612..5e6421360fdbbcfce36acf687bd3395ea46656c1 100644 GIT binary patch literal 51451 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 Ef{{h_p#T5? diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index 1a3e463de3f..4636e68d6d6 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -912,24 +912,12 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.MIMIKYU, "disguised", "busted", new SpeciesFormChangeAbilityTrigger(), true), new SpeciesFormChange(Species.MIMIKYU, "busted", "disguised", new SpeciesFormChangeAbilityTrigger(), true) ], - [Species.SOLGALEO]: [ - new SpeciesFormChange(Species.SOLGALEO, "", "radiant-sun", new SpeciesFormChangePreMoveTrigger(Moves.SUNSTEEL_STRIKE), true), - new SpeciesFormChange(Species.SOLGALEO, "radiant-sun", "", new SpeciesFormChangeActiveTrigger(false), true) - ], - [Species.LUNALA]: [ - new SpeciesFormChange(Species.LUNALA, "", "full-moon", new SpeciesFormChangePreMoveTrigger(Moves.MOONGEIST_BEAM), true), - new SpeciesFormChange(Species.LUNALA, "full-moon", "", new SpeciesFormChangeActiveTrigger(false), true) - ], [Species.NECROZMA]: [ new SpeciesFormChange(Species.NECROZMA, "", "dawn-wings", new SpeciesFormChangeItemTrigger(FormChangeItem.N_LUNARIZER), false, getSpeciesDependentFormChangeCondition(Species.LUNALA)), new SpeciesFormChange(Species.NECROZMA, "", "dusk-mane", new SpeciesFormChangeItemTrigger(FormChangeItem.N_SOLARIZER), false, getSpeciesDependentFormChangeCondition(Species.SOLGALEO)), new SpeciesFormChange(Species.NECROZMA, "dawn-wings", "ultra", new SpeciesFormChangeItemTrigger(FormChangeItem.ULTRANECROZIUM_Z)), new SpeciesFormChange(Species.NECROZMA, "dusk-mane", "ultra", new SpeciesFormChangeItemTrigger(FormChangeItem.ULTRANECROZIUM_Z)) ], - [Species.MARSHADOW]: [ - new SpeciesFormChange(Species.MARSHADOW, "", "zenith", new SpeciesFormChangePreMoveTrigger(Moves.SPECTRAL_THIEF), true), - new SpeciesFormChange(Species.MARSHADOW, "zenith", "", new SpeciesFormChangeActiveTrigger(false), true) - ], [Species.MELMETAL]: [ new SpeciesFormChange(Species.MELMETAL, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) ], diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index fee2bc5c9da..1bf97209613 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -63,8 +63,6 @@ export const normalForm: Species[] = [ Species.FROGADIER, Species.GRENINJA, Species.ROCKRUFF, - Species.SOLGALEO, - Species.LUNALA, Species.NECROZMA, Species.MAGEARNA, Species.MARSHADOW, @@ -2678,14 +2676,8 @@ export function initSpecies() { new PokemonSpecies(Species.TAPU_FINI, 7, true, false, false, "Land Spirit Pokémon", PokemonType.WATER, PokemonType.FAIRY, 1.3, 21.2, Abilities.MISTY_SURGE, Abilities.NONE, Abilities.TELEPATHY, 570, 70, 75, 115, 95, 130, 85, 3, 50, 285, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.COSMOG, 7, true, false, false, "Nebula Pokémon", PokemonType.PSYCHIC, null, 0.2, 0.1, Abilities.UNAWARE, Abilities.NONE, Abilities.NONE, 200, 43, 29, 31, 29, 31, 37, 45, 0, 40, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.COSMOEM, 7, true, false, false, "Protostar Pokémon", PokemonType.PSYCHIC, null, 0.1, 999.9, Abilities.STURDY, Abilities.NONE, Abilities.NONE, 400, 43, 29, 131, 29, 131, 37, 45, 0, 140, GrowthRate.SLOW, null, false), - new PokemonSpecies(Species.SOLGALEO, 7, false, true, false, "Sunne Pokémon", PokemonType.PSYCHIC, PokemonType.STEEL, 3.4, 230, Abilities.FULL_METAL_BODY, Abilities.NONE, Abilities.NONE, 680, 137, 137, 107, 113, 89, 97, 45, 0, 340, GrowthRate.SLOW, null, false, true, - new PokemonForm("Normal", "", PokemonType.PSYCHIC, PokemonType.STEEL, 3.4, 230, Abilities.FULL_METAL_BODY, Abilities.NONE, Abilities.NONE, 680, 137, 137, 107, 113, 89, 97, 45, 0, 340, false, null, true), - new PokemonForm("Radiant Sun", "radiant-sun", PokemonType.PSYCHIC, PokemonType.STEEL, 3.4, 230, Abilities.FULL_METAL_BODY, Abilities.NONE, Abilities.NONE, 680, 137, 137, 107, 113, 89, 97, 45, 0, 340), - ), - new PokemonSpecies(Species.LUNALA, 7, false, true, false, "Moone Pokémon", PokemonType.PSYCHIC, PokemonType.GHOST, 4, 120, Abilities.SHADOW_SHIELD, Abilities.NONE, Abilities.NONE, 680, 137, 113, 89, 137, 107, 97, 45, 0, 340, GrowthRate.SLOW, null, false, true, - new PokemonForm("Normal", "", PokemonType.PSYCHIC, PokemonType.GHOST, 4, 120, Abilities.SHADOW_SHIELD, Abilities.NONE, Abilities.NONE, 680, 137, 113, 89, 137, 107, 97, 45, 0, 340, false, null, true), - new PokemonForm("Full Moon", "full-moon", PokemonType.PSYCHIC, PokemonType.GHOST, 4, 120, Abilities.SHADOW_SHIELD, Abilities.NONE, Abilities.NONE, 680, 137, 113, 89, 137, 107, 97, 45, 0, 340), - ), + new PokemonSpecies(Species.SOLGALEO, 7, false, true, false, "Sunne Pokémon", PokemonType.PSYCHIC, PokemonType.STEEL, 3.4, 230, Abilities.FULL_METAL_BODY, Abilities.NONE, Abilities.NONE, 680, 137, 137, 107, 113, 89, 97, 45, 0, 340, GrowthRate.SLOW, null, false), + new PokemonSpecies(Species.LUNALA, 7, false, true, false, "Moone Pokémon", PokemonType.PSYCHIC, PokemonType.GHOST, 4, 120, Abilities.SHADOW_SHIELD, Abilities.NONE, Abilities.NONE, 680, 137, 113, 89, 137, 107, 97, 45, 0, 340, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.NIHILEGO, 7, true, false, false, "Parasite Pokémon", PokemonType.ROCK, PokemonType.POISON, 1.2, 55.5, Abilities.BEAST_BOOST, Abilities.NONE, Abilities.NONE, 570, 109, 53, 47, 127, 131, 103, 45, 0, 285, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.BUZZWOLE, 7, true, false, false, "Swollen Pokémon", PokemonType.BUG, PokemonType.FIGHTING, 2.4, 333.6, Abilities.BEAST_BOOST, Abilities.NONE, Abilities.NONE, 570, 107, 139, 139, 53, 53, 79, 45, 0, 285, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.PHEROMOSA, 7, true, false, false, "Lissome Pokémon", PokemonType.BUG, PokemonType.FIGHTING, 1.8, 25, Abilities.BEAST_BOOST, Abilities.NONE, Abilities.NONE, 570, 71, 137, 37, 137, 37, 151, 45, 0, 285, GrowthRate.SLOW, null, false), @@ -2705,7 +2697,7 @@ export function initSpecies() { ), new PokemonSpecies(Species.MARSHADOW, 7, false, false, true, "Gloomdweller Pokémon", PokemonType.FIGHTING, PokemonType.GHOST, 0.7, 22.2, Abilities.TECHNICIAN, Abilities.NONE, Abilities.NONE, 600, 90, 125, 80, 90, 90, 125, 3, 0, 300, GrowthRate.SLOW, null, false, true, new PokemonForm("Normal", "", PokemonType.FIGHTING, PokemonType.GHOST, 0.7, 22.2, Abilities.TECHNICIAN, Abilities.NONE, Abilities.NONE, 600, 90, 125, 80, 90, 90, 125, 3, 0, 300, false, null, true), - new PokemonForm("Zenith", "zenith", PokemonType.FIGHTING, PokemonType.GHOST, 0.7, 22.2, Abilities.TECHNICIAN, Abilities.NONE, Abilities.NONE, 600, 90, 125, 80, 90, 90, 125, 3, 0, 300), + new PokemonForm("Zenith", "zenith", PokemonType.FIGHTING, PokemonType.GHOST, 0.7, 22.2, Abilities.TECHNICIAN, Abilities.NONE, Abilities.NONE, 600, 90, 125, 80, 90, 90, 125, 3, 0, 300, false, null, false, true) ), new PokemonSpecies(Species.POIPOLE, 7, true, false, false, "Poison Pin Pokémon", PokemonType.POISON, null, 0.6, 1.8, Abilities.BEAST_BOOST, Abilities.NONE, Abilities.NONE, 420, 67, 73, 67, 73, 67, 73, 45, 0, 210, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.NAGANADEL, 7, true, false, false, "Poison Pin Pokémon", PokemonType.POISON, PokemonType.DRAGON, 3.6, 150, Abilities.BEAST_BOOST, Abilities.NONE, Abilities.NONE, 540, 73, 73, 73, 127, 73, 121, 45, 0, 270, GrowthRate.SLOW, null, false), From e8e0041ed0865d1aeb3dee17826d5480239fe9c6 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Thu, 13 Mar 2025 14:48:53 -0700 Subject: [PATCH 2/4] [Misc] `OPP_FORM_OVERRIDES` now accepts 0 as a valid form index (#5514) --- src/field/pokemon.ts | 4 ++-- src/overrides.ts | 2 -- src/phases/select-starter-phase.ts | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 3cd25e4d10a..890c6bab0d6 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -6916,10 +6916,10 @@ export class EnemyPokemon extends Pokemon { if ( speciesId in Overrides.OPP_FORM_OVERRIDES && - Overrides.OPP_FORM_OVERRIDES[speciesId] && + !isNullOrUndefined(Overrides.OPP_FORM_OVERRIDES[speciesId]) && this.species.forms[Overrides.OPP_FORM_OVERRIDES[speciesId]] ) { - this.formIndex = Overrides.OPP_FORM_OVERRIDES[speciesId] ?? 0; + this.formIndex = Overrides.OPP_FORM_OVERRIDES[speciesId]; } if (!dataSource) { diff --git a/src/overrides.ts b/src/overrides.ts index dc04f72049a..882a634ff90 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* eslint-disable @typescript-eslint/consistent-type-imports */ import { type PokeballCounts } from "#app/battle-scene"; import { EvolutionItem } from "#app/data/balance/pokemon-evolutions"; import { Gender } from "#app/data/gender"; diff --git a/src/phases/select-starter-phase.ts b/src/phases/select-starter-phase.ts index 103174a4c83..0f4360b0af6 100644 --- a/src/phases/select-starter-phase.ts +++ b/src/phases/select-starter-phase.ts @@ -53,6 +53,7 @@ export class SelectStarterPhase extends Phase { let starterFormIndex = Math.min(starterProps.formIndex, Math.max(starter.species.forms.length - 1, 0)); if ( starter.species.speciesId in Overrides.STARTER_FORM_OVERRIDES && + !Utils.isNullOrUndefined(Overrides.STARTER_FORM_OVERRIDES[starter.species.speciesId]) && starter.species.forms[Overrides.STARTER_FORM_OVERRIDES[starter.species.speciesId]!] ) { starterFormIndex = Overrides.STARTER_FORM_OVERRIDES[starter.species.speciesId]!; From 7aa5649aa8f303a158725b9ff4b0b27668e35b50 Mon Sep 17 00:00:00 2001 From: AJ Fontaine <36677462+Fontbane@users.noreply.github.com> Date: Fri, 14 Mar 2025 17:06:19 -0400 Subject: [PATCH 3/4] [Refactor] Move signature species to separate file (#5519) --- src/data/balance/signature-species.ts | 162 ++++++++++++++++++++++++++ src/data/trainer-config.ts | 143 +---------------------- src/field/trainer.ts | 2 +- 3 files changed, 164 insertions(+), 143 deletions(-) create mode 100644 src/data/balance/signature-species.ts diff --git a/src/data/balance/signature-species.ts b/src/data/balance/signature-species.ts new file mode 100644 index 00000000000..a1b73af40cd --- /dev/null +++ b/src/data/balance/signature-species.ts @@ -0,0 +1,162 @@ +import { Species } from "#enums/species"; + +export type SignatureSpecies = { + [key in string]: (Species | Species[])[]; +}; + +/* + * The signature species for each Gym Leader, Elite Four member, and Champion. + * The key is the trainer type, and the value is an array of Species or Species arrays. + * This is in a separate const so it can be accessed from other places and not just the trainerConfigs + */ +export const signatureSpecies: SignatureSpecies = { + // Gym Leaders- Kanto + BROCK: [Species.GEODUDE, Species.ONIX], + MISTY: [Species.STARYU, Species.PSYDUCK], + LT_SURGE: [Species.VOLTORB, Species.PIKACHU, Species.ELECTABUZZ], + ERIKA: [Species.ODDISH, Species.BELLSPROUT, Species.TANGELA, Species.HOPPIP], + JANINE: [Species.VENONAT, Species.SPINARAK, Species.ZUBAT], + SABRINA: [Species.ABRA, Species.MR_MIME, Species.ESPEON], + BLAINE: [Species.GROWLITHE, Species.PONYTA, Species.MAGMAR], + GIOVANNI: [Species.SANDILE, Species.MURKROW, Species.NIDORAN_M, Species.NIDORAN_F], + // Gym Leaders- Johto + FALKNER: [Species.PIDGEY, Species.HOOTHOOT, Species.DODUO], + BUGSY: [Species.SCYTHER, Species.HERACROSS, Species.SHUCKLE, Species.PINSIR], + WHITNEY: [Species.JIGGLYPUFF, Species.MILTANK, Species.AIPOM, Species.GIRAFARIG], + MORTY: [Species.GASTLY, Species.MISDREAVUS, Species.SABLEYE], + CHUCK: [Species.POLIWRATH, Species.MANKEY], + JASMINE: [Species.MAGNEMITE, Species.STEELIX], + PRYCE: [Species.SEEL, Species.SWINUB], + CLAIR: [Species.DRATINI, Species.HORSEA, Species.GYARADOS], + // Gym Leaders- Hoenn + ROXANNE: [Species.GEODUDE, Species.NOSEPASS], + BRAWLY: [Species.MACHOP, Species.MAKUHITA], + WATTSON: [Species.MAGNEMITE, Species.VOLTORB, Species.ELECTRIKE], + FLANNERY: [Species.SLUGMA, Species.TORKOAL, Species.NUMEL], + NORMAN: [Species.SLAKOTH, Species.SPINDA, Species.ZIGZAGOON, Species.KECLEON], + WINONA: [Species.SWABLU, Species.WINGULL, Species.TROPIUS, Species.SKARMORY], + TATE: [Species.SOLROCK, Species.NATU, Species.CHIMECHO, Species.GALLADE], + LIZA: [Species.LUNATONE, Species.SPOINK, Species.BALTOY, Species.GARDEVOIR], + JUAN: [Species.HORSEA, Species.BARBOACH, Species.SPHEAL, Species.RELICANTH], + // Gym Leaders- Sinnoh + ROARK: [Species.CRANIDOS, Species.LARVITAR, Species.GEODUDE], + GARDENIA: [Species.ROSELIA, Species.TANGELA, Species.TURTWIG], + MAYLENE: [Species.LUCARIO, Species.MEDITITE, Species.CHIMCHAR], + CRASHER_WAKE: [Species.BUIZEL, Species.WOOPER, Species.PIPLUP, Species.MAGIKARP], + FANTINA: [Species.MISDREAVUS, Species.DRIFLOON, Species.SPIRITOMB], + BYRON: [Species.SHIELDON, Species.BRONZOR, Species.AGGRON], + CANDICE: [Species.SNEASEL, Species.SNOVER, Species.SNORUNT], + VOLKNER: [Species.SHINX, Species.CHINCHOU, Species.ROTOM], + // Gym Leaders- Unova + CILAN: [Species.PANSAGE, Species.FOONGUS, Species.PETILIL], + CHILI: [Species.PANSEAR, Species.DARUMAKA, Species.NUMEL], + CRESS: [Species.PANPOUR, Species.TYMPOLE, Species.SLOWPOKE], + CHEREN: [Species.LILLIPUP, Species.MINCCINO, Species.PIDOVE], + LENORA: [Species.PATRAT, Species.DEERLING, Species.AUDINO], + ROXIE: [Species.VENIPEDE, Species.TRUBBISH, Species.SKORUPI], + BURGH: [Species.SEWADDLE, Species.SHELMET, Species.KARRABLAST], + ELESA: [Species.EMOLGA, Species.BLITZLE, Species.JOLTIK], + CLAY: [Species.DRILBUR, Species.SANDILE, Species.GOLETT], + SKYLA: [Species.DUCKLETT, Species.WOOBAT, Species.RUFFLET], + BRYCEN: [Species.CRYOGONAL, Species.VANILLITE, Species.CUBCHOO], + DRAYDEN: [Species.DRUDDIGON, Species.AXEW, Species.DEINO], + MARLON: [Species.WAILMER, Species.FRILLISH, Species.TIRTOUGA], + // Gym Leaders- Kalos + VIOLA: [Species.SURSKIT, Species.SCATTERBUG], + GRANT: [Species.AMAURA, Species.TYRUNT], + KORRINA: [Species.HAWLUCHA, Species.LUCARIO, Species.MIENFOO], + RAMOS: [Species.SKIDDO, Species.HOPPIP, Species.BELLSPROUT], + CLEMONT: [Species.HELIOPTILE, Species.MAGNEMITE, Species.EMOLGA], + VALERIE: [Species.SYLVEON, Species.MAWILE, Species.MR_MIME], + OLYMPIA: [Species.ESPURR, Species.SIGILYPH, Species.SLOWKING], + WULFRIC: [Species.BERGMITE, Species.SNOVER, Species.CRYOGONAL], + // Gym Leaders- Galar + MILO: [Species.GOSSIFLEUR, Species.APPLIN, Species.BOUNSWEET], + NESSA: [Species.CHEWTLE, Species.ARROKUDA, Species.WIMPOD], + KABU: [Species.SIZZLIPEDE, Species.VULPIX, Species.TORKOAL], + BEA: [Species.GALAR_FARFETCHD, Species.MACHOP, Species.CLOBBOPUS], + ALLISTER: [Species.GALAR_YAMASK, Species.GALAR_CORSOLA, Species.GASTLY], + OPAL: [Species.MILCERY, Species.TOGETIC, Species.GALAR_WEEZING], + BEDE: [Species.HATENNA, Species.GALAR_PONYTA, Species.GARDEVOIR], + GORDIE: [Species.ROLYCOLY, Species.STONJOURNER, Species.BINACLE], + MELONY: [Species.SNOM, Species.GALAR_DARUMAKA, Species.GALAR_MR_MIME], + PIERS: [Species.GALAR_ZIGZAGOON, Species.SCRAGGY, Species.INKAY], + MARNIE: [Species.IMPIDIMP, Species.PURRLOIN, Species.MORPEKO], + RAIHAN: [Species.DURALUDON, Species.TURTONATOR, Species.GOOMY], + // Gym Leaders- Paldea; First slot is Tera + KATY: [Species.TEDDIURSA, Species.NYMBLE, Species.TAROUNTULA], // Tera Bug Teddiursa + BRASSIUS: [Species.SUDOWOODO, Species.BRAMBLIN, Species.SMOLIV], // Tera Grass Sudowoodo + IONO: [Species.MISDREAVUS, Species.TADBULB, Species.WATTREL], // Tera Ghost Misdreavus + KOFU: [Species.CRABRAWLER, Species.VELUZA, Species.WIGLETT, Species.WINGULL], // Tera Water Crabrawler + LARRY: [Species.STARLY, Species.DUNSPARCE, Species.LECHONK, Species.KOMALA], // Tera Normal Starly + RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel + TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe + GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.CUBCHOO, Species.ALOLA_VULPIX], // Tera Ice Swablu + + // Elite Four- Kanto + LORELEI: [ + Species.JYNX, + [Species.SLOWBRO, Species.GALAR_SLOWBRO], + Species.LAPRAS, + [Species.CLOYSTER, Species.ALOLA_SANDSLASH], + ], + BRUNO: [Species.MACHAMP, Species.HITMONCHAN, Species.HITMONLEE, [Species.GOLEM, Species.ALOLA_GOLEM]], + AGATHA: [Species.GENGAR, [Species.ARBOK, Species.WEEZING], Species.CROBAT, Species.ALOLA_MAROWAK], + LANCE: [Species.DRAGONITE, Species.GYARADOS, Species.AERODACTYL, Species.ALOLA_EXEGGUTOR], + // Elite Four- Johto (Bruno included) + WILL: [Species.XATU, Species.JYNX, [Species.SLOWBRO, Species.SLOWKING], Species.EXEGGUTOR], + KOGA: [[Species.MUK, Species.WEEZING], [Species.VENOMOTH, Species.ARIADOS], Species.CROBAT, Species.TENTACRUEL], + KAREN: [Species.UMBREON, Species.HONCHKROW, Species.HOUNDOOM, Species.WEAVILE], + // Elite Four- Hoenn + SIDNEY: [ + [Species.SHIFTRY, Species.CACTURNE], + [Species.SHARPEDO, Species.CRAWDAUNT], + Species.ABSOL, + Species.MIGHTYENA, + ], + PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, [Species.DRIFBLIM, Species.MISMAGIUS]], + GLACIA: [Species.GLALIE, Species.WALREIN, Species.FROSLASS, Species.ABOMASNOW], + DRAKE: [Species.ALTARIA, Species.SALAMENCE, Species.FLYGON, Species.KINGDRA], + // Elite Four- Sinnoh + AARON: [[Species.SCIZOR, Species.KLEAVOR], Species.HERACROSS, [Species.VESPIQUEN, Species.YANMEGA], Species.DRAPION], + BERTHA: [Species.WHISCASH, Species.HIPPOWDON, Species.GLISCOR, Species.RHYPERIOR], + FLINT: [ + [Species.RAPIDASH, Species.FLAREON], + Species.MAGMORTAR, + [Species.STEELIX, Species.LOPUNNY], + Species.INFERNAPE, + ], // Tera Fire Steelix or Lopunny + LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, [Species.ALAKAZAM, Species.ESPEON]], + // Elite Four- Unova + SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.JELLICENT], + MARSHAL: [Species.CONKELDURR, Species.MIENSHAO, Species.THROH, Species.SAWK], + GRIMSLEY: [Species.LIEPARD, Species.KINGAMBIT, Species.SCRAFTY, Species.KROOKODILE], + CAITLIN: [Species.MUSHARNA, Species.GOTHITELLE, Species.SIGILYPH, Species.REUNICLUS], + // Elite Four- Kalos + MALVA: [Species.PYROAR, Species.TORKOAL, Species.CHANDELURE, Species.TALONFLAME], + SIEBOLD: [Species.CLAWITZER, Species.GYARADOS, Species.BARBARACLE, Species.STARMIE], + WIKSTROM: [Species.KLEFKI, Species.PROBOPASS, Species.SCIZOR, Species.AEGISLASH], + DRASNA: [Species.DRAGALGE, Species.DRUDDIGON, Species.ALTARIA, Species.NOIVERN], + // Elite Four- Alola + HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, [Species.POLIWRATH, Species.ANNIHILAPE]], + MOLAYNE: [Species.KLEFKI, Species.MAGNEZONE, Species.METAGROSS, Species.ALOLA_DUGTRIO], + OLIVIA: [Species.RELICANTH, Species.CARBINK, Species.ALOLA_GOLEM, Species.LYCANROC], + ACEROLA: [[Species.BANETTE, Species.DRIFBLIM], Species.MIMIKYU, Species.DHELMISE, Species.PALOSSAND], + KAHILI: [[Species.BRAVIARY, Species.MANDIBUZZ], Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON], + // Elite Four- Galar + MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, [Species.TOXICROAK, Species.SCRAFTY], Species.GRIMMSNARL], + NESSA_ELITE: [Species.GOLISOPOD, [Species.QUAGSIRE, Species.PELIPPER], Species.TOXAPEX, Species.DREDNAW], + BEA_ELITE: [Species.HAWLUCHA, [Species.GRAPPLOCT, Species.SIRFETCHD], Species.FALINKS, Species.MACHAMP], + ALLISTER_ELITE: [Species.DUSKNOIR, [Species.POLTEAGEIST, Species.RUNERIGUS], Species.CURSOLA, Species.GENGAR], + RAIHAN_ELITE: [Species.GOODRA, [Species.TORKOAL, Species.TURTONATOR], Species.FLYGON, Species.ARCHALUDON], + // Elite Four- Paldea + RIKA: [Species.CLODSIRE, [Species.DUGTRIO, Species.DONPHAN], Species.CAMERUPT, Species.WHISCASH], // Tera Ground Clodsire + POPPY: [Species.TINKATON, Species.BRONZONG, Species.CORVIKNIGHT, Species.COPPERAJAH], // Tera Steel Tinkaton + LARRY_ELITE: [Species.FLAMIGO, Species.STARAPTOR, [Species.ALTARIA, Species.TROPIUS], Species.ORICORIO], // Tera Flying Flamigo; random Oricorio + HASSEL: [Species.BAXCALIBUR, [Species.FLAPPLE, Species.APPLETUN], Species.DRAGALGE, Species.NOIVERN], // Tera Dragon Baxcalibur + // Elite Four- BBL + CRISPIN: [Species.BLAZIKEN, Species.MAGMORTAR, [Species.CAMERUPT, Species.TALONFLAME], Species.ROTOM], // Tera Fire Blaziken; Heat Rotom + AMARYS: [Species.METAGROSS, Species.SCIZOR, Species.EMPOLEON, Species.SKARMORY], // Tera Steel Metagross + LACEY: [Species.EXCADRILL, Species.PRIMARINA, [Species.WHIMSICOTT, Species.ALCREMIE], Species.GRANBULL], // Tera Fairy Excadrill + DRAYTON: [Species.ARCHALUDON, Species.DRAGONITE, Species.HAXORUS, Species.SCEPTILE], // Tera Dragon Archaludon +}; diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 693338c145e..3884aa05b13 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -22,6 +22,7 @@ import { PartyMemberStrength } from "#enums/party-member-strength"; import { Species } from "#enums/species"; import { TrainerType } from "#enums/trainer-type"; import { Gender } from "#app/data/gender"; +import { signatureSpecies } from "./balance/signature-species"; /** Minimum BST for Pokemon generated onto the Elite Four's teams */ const ELITE_FOUR_MINIMUM_BST = 460; @@ -1744,148 +1745,6 @@ function getSpeciesFilterRandomPartyMemberFunc( }; } -type SignatureSpecies = { - [key in string]: (Species | Species[])[]; -}; - -/* - * The signature species for each Gym Leader, Elite Four member, and Champion. - * The key is the trainer type, and the value is an array of Species or Species arrays. - * This is in a separate const so it can be accessed from other places and not just the trainerConfigs - */ -export const signatureSpecies: SignatureSpecies = { - BROCK: [Species.GEODUDE, Species.ONIX], - MISTY: [Species.STARYU, Species.PSYDUCK], - LT_SURGE: [Species.VOLTORB, Species.PIKACHU, Species.ELECTABUZZ], - ERIKA: [Species.ODDISH, Species.BELLSPROUT, Species.TANGELA, Species.HOPPIP], - JANINE: [Species.VENONAT, Species.SPINARAK, Species.ZUBAT], - SABRINA: [Species.ABRA, Species.MR_MIME, Species.ESPEON], - BLAINE: [Species.GROWLITHE, Species.PONYTA, Species.MAGMAR], - GIOVANNI: [Species.SANDILE, Species.MURKROW, Species.NIDORAN_M, Species.NIDORAN_F], - FALKNER: [Species.PIDGEY, Species.HOOTHOOT, Species.DODUO], - BUGSY: [Species.SCYTHER, Species.HERACROSS, Species.SHUCKLE, Species.PINSIR], - WHITNEY: [Species.JIGGLYPUFF, Species.MILTANK, Species.AIPOM, Species.GIRAFARIG], - MORTY: [Species.GASTLY, Species.MISDREAVUS, Species.SABLEYE], - CHUCK: [Species.POLIWRATH, Species.MANKEY], - JASMINE: [Species.MAGNEMITE, Species.STEELIX], - PRYCE: [Species.SEEL, Species.SWINUB], - CLAIR: [Species.DRATINI, Species.HORSEA, Species.GYARADOS], - ROXANNE: [Species.GEODUDE, Species.NOSEPASS], - BRAWLY: [Species.MACHOP, Species.MAKUHITA], - WATTSON: [Species.MAGNEMITE, Species.VOLTORB, Species.ELECTRIKE], - FLANNERY: [Species.SLUGMA, Species.TORKOAL, Species.NUMEL], - NORMAN: [Species.SLAKOTH, Species.SPINDA, Species.ZIGZAGOON, Species.KECLEON], - WINONA: [Species.SWABLU, Species.WINGULL, Species.TROPIUS, Species.SKARMORY], - TATE: [Species.SOLROCK, Species.NATU, Species.CHIMECHO, Species.GALLADE], - LIZA: [Species.LUNATONE, Species.SPOINK, Species.BALTOY, Species.GARDEVOIR], - JUAN: [Species.HORSEA, Species.BARBOACH, Species.SPHEAL, Species.RELICANTH], - ROARK: [Species.CRANIDOS, Species.LARVITAR, Species.GEODUDE], - GARDENIA: [Species.ROSELIA, Species.TANGELA, Species.TURTWIG], - MAYLENE: [Species.LUCARIO, Species.MEDITITE, Species.CHIMCHAR], - CRASHER_WAKE: [Species.BUIZEL, Species.WOOPER, Species.PIPLUP, Species.MAGIKARP], - FANTINA: [Species.MISDREAVUS, Species.DRIFLOON, Species.SPIRITOMB], - BYRON: [Species.SHIELDON, Species.BRONZOR, Species.AGGRON], - CANDICE: [Species.SNEASEL, Species.SNOVER, Species.SNORUNT], - VOLKNER: [Species.SHINX, Species.CHINCHOU, Species.ROTOM], - CILAN: [Species.PANSAGE, Species.FOONGUS, Species.PETILIL], - CHILI: [Species.PANSEAR, Species.DARUMAKA, Species.NUMEL], - CRESS: [Species.PANPOUR, Species.TYMPOLE, Species.SLOWPOKE], - CHEREN: [Species.LILLIPUP, Species.MINCCINO, Species.PIDOVE], - LENORA: [Species.PATRAT, Species.DEERLING, Species.AUDINO], - ROXIE: [Species.VENIPEDE, Species.TRUBBISH, Species.SKORUPI], - BURGH: [Species.SEWADDLE, Species.SHELMET, Species.KARRABLAST], - ELESA: [Species.EMOLGA, Species.BLITZLE, Species.JOLTIK], - CLAY: [Species.DRILBUR, Species.SANDILE, Species.GOLETT], - SKYLA: [Species.DUCKLETT, Species.WOOBAT, Species.RUFFLET], - BRYCEN: [Species.CRYOGONAL, Species.VANILLITE, Species.CUBCHOO], - DRAYDEN: [Species.DRUDDIGON, Species.AXEW, Species.DEINO], - MARLON: [Species.WAILMER, Species.FRILLISH, Species.TIRTOUGA], - VIOLA: [Species.SURSKIT, Species.SCATTERBUG], - GRANT: [Species.AMAURA, Species.TYRUNT], - KORRINA: [Species.HAWLUCHA, Species.LUCARIO, Species.MIENFOO], - RAMOS: [Species.SKIDDO, Species.HOPPIP, Species.BELLSPROUT], - CLEMONT: [Species.HELIOPTILE, Species.MAGNEMITE, Species.EMOLGA], - VALERIE: [Species.SYLVEON, Species.MAWILE, Species.MR_MIME], - OLYMPIA: [Species.ESPURR, Species.SIGILYPH, Species.SLOWKING], - WULFRIC: [Species.BERGMITE, Species.SNOVER, Species.CRYOGONAL], - MILO: [Species.GOSSIFLEUR, Species.APPLIN, Species.BOUNSWEET], - NESSA: [Species.CHEWTLE, Species.ARROKUDA, Species.WIMPOD], - KABU: [Species.SIZZLIPEDE, Species.VULPIX, Species.TORKOAL], - BEA: [Species.GALAR_FARFETCHD, Species.MACHOP, Species.CLOBBOPUS], - ALLISTER: [Species.GALAR_YAMASK, Species.GALAR_CORSOLA, Species.GASTLY], - OPAL: [Species.MILCERY, Species.TOGETIC, Species.GALAR_WEEZING], - BEDE: [Species.HATENNA, Species.GALAR_PONYTA, Species.GARDEVOIR], - GORDIE: [Species.ROLYCOLY, Species.STONJOURNER, Species.BINACLE], - MELONY: [Species.SNOM, Species.GALAR_DARUMAKA, Species.GALAR_MR_MIME], - PIERS: [Species.GALAR_ZIGZAGOON, Species.SCRAGGY, Species.INKAY], - MARNIE: [Species.IMPIDIMP, Species.PURRLOIN, Species.MORPEKO], - RAIHAN: [Species.DURALUDON, Species.TURTONATOR, Species.GOOMY], - KATY: [Species.TEDDIURSA, Species.NYMBLE, Species.TAROUNTULA], // Tera Bug Teddiursa - BRASSIUS: [Species.SUDOWOODO, Species.BRAMBLIN, Species.SMOLIV], // Tera Grass Sudowoodo - IONO: [Species.MISDREAVUS, Species.TADBULB, Species.WATTREL], // Tera Ghost Misdreavus - KOFU: [Species.CRABRAWLER, Species.VELUZA, Species.WIGLETT, Species.WINGULL], // Tera Water Crabrawler - LARRY: [Species.STARLY, Species.DUNSPARCE, Species.LECHONK, Species.KOMALA], // Tera Normal Starly - RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel - TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe - GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.CUBCHOO, Species.ALOLA_VULPIX], // Tera Ice Swablu - LORELEI: [ - Species.JYNX, - [Species.SLOWBRO, Species.GALAR_SLOWBRO], - Species.LAPRAS, - [Species.CLOYSTER, Species.ALOLA_SANDSLASH], - ], - BRUNO: [Species.MACHAMP, Species.HITMONCHAN, Species.HITMONLEE, [Species.GOLEM, Species.ALOLA_GOLEM]], - AGATHA: [Species.GENGAR, [Species.ARBOK, Species.WEEZING], Species.CROBAT, Species.ALOLA_MAROWAK], - LANCE: [Species.DRAGONITE, Species.GYARADOS, Species.AERODACTYL, Species.ALOLA_EXEGGUTOR], - WILL: [Species.XATU, Species.JYNX, [Species.SLOWBRO, Species.SLOWKING], Species.EXEGGUTOR], - KOGA: [[Species.MUK, Species.WEEZING], [Species.VENOMOTH, Species.ARIADOS], Species.CROBAT, Species.TENTACRUEL], - KAREN: [Species.UMBREON, Species.HONCHKROW, Species.HOUNDOOM, Species.WEAVILE], - SIDNEY: [ - [Species.SHIFTRY, Species.CACTURNE], - [Species.SHARPEDO, Species.CRAWDAUNT], - Species.ABSOL, - Species.MIGHTYENA, - ], - PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, [Species.DRIFBLIM, Species.MISMAGIUS]], - GLACIA: [Species.GLALIE, Species.WALREIN, Species.FROSLASS, Species.ABOMASNOW], - DRAKE: [Species.ALTARIA, Species.SALAMENCE, Species.FLYGON, Species.KINGDRA], - AARON: [[Species.SCIZOR, Species.KLEAVOR], Species.HERACROSS, [Species.VESPIQUEN, Species.YANMEGA], Species.DRAPION], - BERTHA: [Species.WHISCASH, Species.HIPPOWDON, Species.GLISCOR, Species.RHYPERIOR], - FLINT: [ - [Species.RAPIDASH, Species.FLAREON], - Species.MAGMORTAR, - [Species.STEELIX, Species.LOPUNNY], - Species.INFERNAPE, - ], // Tera Fire Steelix or Lopunny - LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, [Species.ALAKAZAM, Species.ESPEON]], - SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.JELLICENT], - MARSHAL: [Species.CONKELDURR, Species.MIENSHAO, Species.THROH, Species.SAWK], - GRIMSLEY: [Species.LIEPARD, Species.KINGAMBIT, Species.SCRAFTY, Species.KROOKODILE], - CAITLIN: [Species.MUSHARNA, Species.GOTHITELLE, Species.SIGILYPH, Species.REUNICLUS], - MALVA: [Species.PYROAR, Species.TORKOAL, Species.CHANDELURE, Species.TALONFLAME], - SIEBOLD: [Species.CLAWITZER, Species.GYARADOS, Species.BARBARACLE, Species.STARMIE], - WIKSTROM: [Species.KLEFKI, Species.PROBOPASS, Species.SCIZOR, Species.AEGISLASH], - DRASNA: [Species.DRAGALGE, Species.DRUDDIGON, Species.ALTARIA, Species.NOIVERN], - HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, [Species.POLIWRATH, Species.ANNIHILAPE]], - MOLAYNE: [Species.KLEFKI, Species.MAGNEZONE, Species.METAGROSS, Species.ALOLA_DUGTRIO], - OLIVIA: [Species.RELICANTH, Species.CARBINK, Species.ALOLA_GOLEM, Species.LYCANROC], - ACEROLA: [[Species.BANETTE, Species.DRIFBLIM], Species.MIMIKYU, Species.DHELMISE, Species.PALOSSAND], - KAHILI: [[Species.BRAVIARY, Species.MANDIBUZZ], Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON], - MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, [Species.TOXICROAK, Species.SCRAFTY], Species.GRIMMSNARL], - NESSA_ELITE: [Species.GOLISOPOD, [Species.QUAGSIRE, Species.PELIPPER], Species.TOXAPEX, Species.DREDNAW], - BEA_ELITE: [Species.HAWLUCHA, [Species.GRAPPLOCT, Species.SIRFETCHD], Species.FALINKS, Species.MACHAMP], - ALLISTER_ELITE: [Species.DUSKNOIR, [Species.POLTEAGEIST, Species.RUNERIGUS], Species.CURSOLA, Species.GENGAR], - RAIHAN_ELITE: [Species.GOODRA, [Species.TORKOAL, Species.TURTONATOR], Species.FLYGON, Species.ARCHALUDON], - RIKA: [Species.CLODSIRE, [Species.DUGTRIO, Species.DONPHAN], Species.CAMERUPT, Species.WHISCASH], // Tera Ground Clodsire - POPPY: [Species.TINKATON, Species.BRONZONG, Species.CORVIKNIGHT, Species.COPPERAJAH], // Tera Steel Tinkaton - LARRY_ELITE: [Species.FLAMIGO, Species.STARAPTOR, [Species.ALTARIA, Species.TROPIUS], Species.ORICORIO], // Tera Flying Flamigo; random Oricorio - HASSEL: [Species.BAXCALIBUR, [Species.FLAPPLE, Species.APPLETUN], Species.DRAGALGE, Species.NOIVERN], // Tera Dragon Baxcalibur - CRISPIN: [Species.BLAZIKEN, Species.MAGMORTAR, [Species.CAMERUPT, Species.TALONFLAME], Species.ROTOM], // Tera Fire Blaziken; Heat Rotom - AMARYS: [Species.METAGROSS, Species.SCIZOR, Species.EMPOLEON, Species.SKARMORY], // Tera Steel Metagross - LACEY: [Species.EXCADRILL, Species.PRIMARINA, [Species.WHIMSICOTT, Species.ALCREMIE], Species.GRANBULL], // Tera Fairy Excadrill - DRAYTON: [Species.ARCHALUDON, Species.DRAGONITE, Species.HAXORUS, Species.SCEPTILE], // Tera Dragon Archaludon -}; - export const trainerConfigs: TrainerConfigs = { [TrainerType.UNKNOWN]: new TrainerConfig(0).setHasGenders(), [TrainerType.ACE_TRAINER]: new TrainerConfig(++t) diff --git a/src/field/trainer.ts b/src/field/trainer.ts index 4325b54a783..98919ebfa93 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -9,7 +9,6 @@ import { TrainerSlot, trainerConfigs, trainerPartyTemplates, - signatureSpecies, TeraAIMode, } from "#app/data/trainer-config"; import type { EnemyPokemon } from "#app/field/pokemon"; @@ -22,6 +21,7 @@ import i18next from "i18next"; import { PartyMemberStrength } from "#enums/party-member-strength"; import { Species } from "#enums/species"; import { TrainerType } from "#enums/trainer-type"; +import { signatureSpecies } from "#app/data/balance/signature-species"; export enum TrainerVariant { DEFAULT, From 1d7f916240c351bdb376a7c8bc7bdb33dff5c163 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Sat, 15 Mar 2025 19:51:02 -0700 Subject: [PATCH 4/4] [Refactor] Align ability display with mainline (#5267) * Stop ShowAbilityPhase from ending until the bar has popped out * Remove ability bar hiding from messagePhase * Remove abilityBar reference from base Phase class * Add HideAbilityPhase to hide ability bar after effects * Add willSucceed to ability attrs * Update AbAttrs and PostInitAbAttrs * Update PreDefendAbAttrs * Update postDefend, postMoveUsed, StatStage, postSetStatus, and PostDamage * Update preAttack and fieldStat * Partially implement postAttack * Finish PostAttack * Update PostSummon * Update PreSwitchOut * Update preStatStageChange * Update PostStatStageChange, PreSetStatus, PreApplyBattlerTag * Update postTurn and preWeatherEffect * Update postWeatherChange * Update postWeatherChange * Update PostTerrainChange * Update CheckTrapped and PostBattle * Update postFaint * Update PostItemLost * Bug fixes from test cases * Fix intimidate display * Stop trace from displaying itself * Rename to canApply * Fix ability displays using getTriggerMessage * Ensure abilities which are mistakenly shown are still hidden * Fix ability bar showing the wrong ability with imposter * Add canApply for imposter * Update abilities using promises and `trySet...` functions * Committing overrides changes is bad * Document apply and canApply * Update PreLeaveFieldAbAttr * Remove boolean return type apply functions * Remove redundant assignment * Remove ability display from abilities that shouldn't have it * Move queueAbilityDisplay to battlescene * Remove unused shown variable * Minor changes * Fix using id instead of battlerindex in queueAbilityDisplay * Fix PostBattleInitFormChangeAbAttr displaying * Prevent crashes in case an ability for a pokemon not on the field is shown * Stop more abilities from displaying * Move enemy ability bar to the right side * Automatically reload bar if shown while already out, fix specific abilities * Remove duplicate call to clearPhaseQueueSplice * Remove ShowAbilityPhase import from ability.ts * Update PostDefendTypeChangeAbAttr to use PokemonType * Update PostSummonAddArenaTagAbAttr * Minor changes --- src/battle-scene.ts | 57 + src/data/ability.ts | 2996 +++++++++++++------------ src/field/arena.ts | 14 +- src/loading-scene.ts | 1 + src/phase.ts | 6 +- src/phases/hide-ability-phase.ts | 27 + src/phases/message-phase.ts | 8 - src/phases/pokemon-transform-phase.ts | 9 + src/phases/show-ability-phase.ts | 46 +- src/ui/ability-bar.ts | 134 +- test/moves/secret_power.test.ts | 6 +- 11 files changed, 1729 insertions(+), 1575 deletions(-) create mode 100644 src/phases/hide-ability-phase.ts diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 1712cf9236f..a6c986d3d0f 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -168,6 +168,8 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters"; import { StatusEffect } from "#enums/status-effect"; import { initGlobalScene } from "#app/global-scene"; +import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; +import { HideAbilityPhase } from "#app/phases/hide-ability-phase"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; @@ -2904,6 +2906,21 @@ export default class BattleScene extends SceneBase { } } + /** + * Queues an ability bar flyout phase + * @param pokemon The pokemon who has the ability + * @param passive Whether the ability is a passive + * @param show Whether to show or hide the bar + */ + public queueAbilityDisplay(pokemon: Pokemon, passive: boolean, show: boolean): void { + this.unshiftPhase( + show + ? new ShowAbilityPhase(pokemon.getBattlerIndex(), passive) + : new HideAbilityPhase(pokemon.getBattlerIndex(), passive), + ); + this.clearPhaseQueueSplice(); + } + /** * Moves everything from nextCommandPhaseQueue to phaseQueue (keeping order) */ @@ -3133,6 +3150,41 @@ export default class BattleScene extends SceneBase { return false; } + canTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, transferQuantity = 1): boolean { + const mod = itemModifier.clone() as PokemonHeldItemModifier; + const source = mod.pokemonId ? mod.getPokemon() : null; + const cancelled = new Utils.BooleanHolder(false); + + if (source && source.isPlayer() !== target.isPlayer()) { + applyAbAttrs(BlockItemTheftAbAttr, source, cancelled); + } + + if (cancelled.value) { + return false; + } + + const matchingModifier = this.findModifier( + m => m instanceof PokemonHeldItemModifier && m.matchType(mod) && m.pokemonId === target.id, + target.isPlayer(), + ) as PokemonHeldItemModifier; + + if (matchingModifier) { + const maxStackCount = matchingModifier.getMaxStackCount(); + if (matchingModifier.stackCount >= maxStackCount) { + return false; + } + const countTaken = Math.min(transferQuantity, mod.stackCount, maxStackCount - matchingModifier.stackCount); + mod.stackCount -= countTaken; + } else { + const countTaken = Math.min(transferQuantity, mod.stackCount); + mod.stackCount -= countTaken; + } + + const removeOld = mod.stackCount === 0; + + return !removeOld || !source || this.hasModifier(itemModifier, !source.isPlayer()); + } + removePartyMemberModifiers(partyMemberIndex: number): Promise { return new Promise(resolve => { const pokemonId = this.getPlayerParty()[partyMemberIndex].id; @@ -3290,6 +3342,11 @@ export default class BattleScene extends SceneBase { }); } + hasModifier(modifier: PersistentModifier, enemy = false): boolean { + const modifiers = !enemy ? this.modifiers : this.enemyModifiers; + return modifiers.indexOf(modifier) > -1; + } + /** * Removes a currently owned item. If the item is stacked, the entire item stack * gets removed. This function does NOT apply in-battle effects, such as Unburden. diff --git a/src/data/ability.ts b/src/data/ability.ts index 5d8b7ce681a..0b5b3624c73 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -35,7 +35,6 @@ import { Species } from "#enums/species"; import { Stat, type BattleStat, type EffectiveStat, BATTLE_STATS, EFFECTIVE_STATS, getStatKey } from "#app/enums/stat"; import { MovePhase } from "#app/phases/move-phase"; import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; -import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { globalScene } from "#app/global-scene"; import { SwitchType } from "#app/enums/switch-type"; @@ -147,7 +146,8 @@ export class Ability implements Localizable { } } -type AbAttrApplyFunc = (attr: TAttr, passive: boolean) => boolean; +type AbAttrApplyFunc = (attr: TAttr, passive: boolean) => void; +type AbAttrSuccessFunc = (attr: TAttr, passive: boolean) => boolean; type AbAttrCondition = (pokemon: Pokemon) => boolean; // TODO: Can this be improved? @@ -163,9 +163,15 @@ export abstract class AbAttr { this.showAbility = showAbility; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { - return false; - } + /** + * Applies ability effects without checking conditions + * @param pokemon - The pokemon to apply this ability to + * @param passive - Whether or not the ability is a passive + * @param simulated - Whether the call is simulated + * @param args - Extra args passed to the function. Handled by child classes. + * @see {@linkcode canApply} + */ + apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder | null, args: any[]): void {} getTriggerMessage(_pokemon: Pokemon, _abilityName: string, ..._args: any[]): string | null { return null; @@ -179,13 +185,28 @@ export abstract class AbAttr { this.extraCondition = condition; return this; } + + /** + * Returns a boolean describing whether the ability can be applied under current conditions + * @param pokemon - The pokemon to apply this ability to + * @param passive - Whether or not the ability is a passive + * @param simulated - Whether the call is simulated + * @param args - Extra args passed to the function. Handled by child classes. + * @returns `true` if the ability can be applied, `false` otherwise + * @see {@linkcode apply} + */ + canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return true; + } } export class BlockRecoilDamageAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - cancelled.value = true; + constructor() { + super(false); + } - return true; + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]) { @@ -196,7 +217,7 @@ export class BlockRecoilDamageAttr extends AbAttr { /** * Attribute for abilities that increase the chance of a double battle * occurring. - * @see apply + * @see {@linkcode apply} */ export class DoubleBattleChanceAbAttr extends AbAttr { constructor() { @@ -206,40 +227,39 @@ export class DoubleBattleChanceAbAttr extends AbAttr { /** * Increases the chance of a double battle occurring * @param args [0] {@linkcode Utils.NumberHolder} for double battle chance - * @returns true if the ability was applied */ - apply(_pokemon: Pokemon, _passive: boolean, _simulated: boolean, _cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(_pokemon: Pokemon, _passive: boolean, _simulated: boolean, _cancelled: Utils.BooleanHolder, args: any[]): void { const doubleBattleChance = args[0] as Utils.NumberHolder; // This is divided because the chance is generated as a number from 0 to doubleBattleChance.value using Utils.randSeedInt // A double battle will initiate if the generated number is 0 doubleBattleChance.value = doubleBattleChance.value / 4; - - return true; } } export class PostBattleInitAbAttr extends AbAttr { - applyPostBattleInit(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - return false; + canApplyPostBattleInit(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return true; } + + applyPostBattleInit(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {} } export class PostBattleInitFormChangeAbAttr extends PostBattleInitAbAttr { private formFunc: (p: Pokemon) => number; constructor(formFunc: ((p: Pokemon) => number)) { - super(true); + super(false); this.formFunc = formFunc; } - applyPostBattleInit(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override canApplyPostBattleInit(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); - if (formIndex !== pokemon.formIndex && !simulated) { - return globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); - } + return formIndex !== pokemon.formIndex && !simulated; + } - return false; + override applyPostBattleInit(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); } } @@ -254,7 +274,7 @@ export class PostTeraFormChangeStatChangeAbAttr extends AbAttr { this.stages = stages; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder | null, args: any[]): void { const statStageChangePhases: StatStageChangePhase[] = []; if (!simulated) { @@ -264,8 +284,6 @@ export class PostTeraFormChangeStatChangeAbAttr extends AbAttr { globalScene.unshiftPhase(statStageChangePhase); } } - - return true; } } @@ -284,11 +302,14 @@ export class ClearWeatherAbAttr extends AbAttr { this.weather = weather; } - apply(pokemon: Pokemon, passive: boolean, simulated:boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + public override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return globalScene.arena.canSetWeather(WeatherType.NONE); + } + + public override apply(pokemon: Pokemon, passive: boolean, simulated:boolean, cancelled: Utils.BooleanHolder, args: any[]): void { if (!simulated) { globalScene.arena.trySetWeather(WeatherType.NONE, true); } - return true; } } @@ -307,17 +328,31 @@ export class ClearTerrainAbAttr extends AbAttr { this.terrain = terrain; } - apply(pokemon: Pokemon, passive: boolean, simulated:boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + public override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return globalScene.arena.canSetTerrain(TerrainType.NONE); + } + + public override apply(pokemon: Pokemon, passive: boolean, simulated:boolean, cancelled: Utils.BooleanHolder, args: any[]): void { if (!simulated) { globalScene.arena.trySetTerrain(TerrainType.NONE, true, true); } - return true; } } type PreDefendAbAttrCondition = (pokemon: Pokemon, attacker: Pokemon, move: Move) => boolean; export class PreDefendAbAttr extends AbAttr { + canApplyPreDefend( + pokemon: Pokemon, + passive: boolean, + simulated: boolean, + attacker: Pokemon, + move: Move | null, + cancelled: Utils.BooleanHolder | null, + args: any[]): boolean { + return true; + } + applyPreDefend( pokemon: Pokemon, passive: boolean, @@ -326,28 +361,26 @@ export class PreDefendAbAttr extends AbAttr { move: Move | null, cancelled: Utils.BooleanHolder | null, args: any[], - ): boolean { - return false; - } + ): void {} } export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr { - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (pokemon.isFullHp() - && pokemon.getMaxHp() > 1 //Checks if pokemon has wonder_guard (which forces 1hp) - && (args[0] as Utils.NumberHolder).value >= pokemon.hp) { //Damage >= hp - return simulated || pokemon.addTag(BattlerTagType.STURDY, 1); - } + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move | null, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return pokemon.isFullHp() + && pokemon.getMaxHp() > 1 //Checks if pokemon has wonder_guard (which forces 1hp) + && (args[0] as Utils.NumberHolder).value >= pokemon.hp; //Damage >= hp + } - return false; + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { + if (!simulated) { + pokemon.addTag(BattlerTagType.STURDY, 1); + } } } export class BlockItemTheftAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { cancelled.value = true; - - return true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]) { @@ -359,13 +392,16 @@ export class BlockItemTheftAbAttr extends AbAttr { } export class StabBoostAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if ((args[0] as Utils.NumberHolder).value > 1) { - (args[0] as Utils.NumberHolder).value += 0.5; - return true; - } + constructor() { + super(false); + } - return false; + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return (args[0] as Utils.NumberHolder).value > 1; + } + + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + (args[0] as Utils.NumberHolder).value += 0.5; } } @@ -373,21 +409,19 @@ export class ReceivedMoveDamageMultiplierAbAttr extends PreDefendAbAttr { protected condition: PokemonDefendCondition; private damageMultiplier: number; - constructor(condition: PokemonDefendCondition, damageMultiplier: number) { - super(); + constructor(condition: PokemonDefendCondition, damageMultiplier: number, showAbility: boolean = false) { + super(showAbility); this.condition = condition; this.damageMultiplier = damageMultiplier; } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.condition(pokemon, attacker, move)) { - (args[0] as Utils.NumberHolder).value = Utils.toDmgValue((args[0] as Utils.NumberHolder).value * this.damageMultiplier); + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return this.condition(pokemon, attacker, move); + } - return true; - } - - return false; + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { + (args[0] as Utils.NumberHolder).value = Utils.toDmgValue((args[0] as Utils.NumberHolder).value * this.damageMultiplier); } } @@ -408,16 +442,15 @@ export class AlliedFieldDamageReductionAbAttr extends PreDefendAbAttr { * @param args * - `[0]` {@linkcode Utils.NumberHolder} - The damage being dealt */ - override applyPreDefend(_pokemon: Pokemon, _passive: boolean, _simulated: boolean, _attacker: Pokemon, _move: Move, _cancelled: Utils.BooleanHolder, args: any[]): boolean { + override applyPreDefend(_pokemon: Pokemon, _passive: boolean, _simulated: boolean, _attacker: Pokemon, _move: Move, _cancelled: Utils.BooleanHolder, args: any[]): void { const damage = args[0] as Utils.NumberHolder; damage.value = Utils.toDmgValue(damage.value * this.damageMultiplier); - return true; } } export class ReceivedTypeDamageMultiplierAbAttr extends ReceivedMoveDamageMultiplierAbAttr { constructor(moveType: PokemonType, damageMultiplier: number) { - super((target, user, move) => user.getMoveType(move) === moveType, damageMultiplier); + super((target, user, move) => user.getMoveType(move) === moveType, damageMultiplier, false); } } @@ -432,12 +465,16 @@ export class TypeImmunityAbAttr extends PreDefendAbAttr { private condition: AbAttrCondition | null; constructor(immuneType: PokemonType | null, condition?: AbAttrCondition) { - super(); + super(true); this.immuneType = immuneType; this.condition = condition ?? null; } + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return ![ MoveTarget.BOTH_SIDES, MoveTarget.ENEMY_SIDE, MoveTarget.USER_SIDE ].includes(move.moveTarget) && attacker !== pokemon && attacker.getMoveType(move) === this.immuneType; + } + /** * Applies immunity if this ability grants immunity to the type of the given move. * @param pokemon {@linkcode Pokemon} The defending Pokemon. @@ -448,16 +485,8 @@ export class TypeImmunityAbAttr extends PreDefendAbAttr { * @param args [0] {@linkcode Utils.NumberHolder} gets set to 0 if move is immuned by an ability. * @param args [1] - Whether the move is simulated. */ - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - // Field moves should ignore immunity - if ([ MoveTarget.BOTH_SIDES, MoveTarget.ENEMY_SIDE, MoveTarget.USER_SIDE ].includes(move.moveTarget)) { - return false; - } - if (attacker !== pokemon && attacker.getMoveType(move) === this.immuneType) { - (args[0] as Utils.NumberHolder).value = 0; - return true; - } - return false; + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { + (args[0] as Utils.NumberHolder).value = 0; } getImmuneType(): PokemonType | null { @@ -474,17 +503,19 @@ export class AttackTypeImmunityAbAttr extends TypeImmunityAbAttr { super(immuneType, condition); } + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return move.category !== MoveCategory.STATUS && !move.hasAttr(NeutralDamageAgainstFlyingTypeMultiplierAttr) + && super.canApplyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + } + /** * Applies immunity if the move used is not a status move. * Type immunity abilities that do not give additional benefits (HP recovery, stat boosts, etc) are not immune to status moves of the type * Example: Levitate */ - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { // this is a hacky way to fix the Levitate/Thousand Arrows interaction, but it works for now... - if (move.category !== MoveCategory.STATUS && !move.hasAttr(NeutralDamageAgainstFlyingTypeMultiplierAttr)) { - return super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); - } - return false; + super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); } } @@ -493,20 +524,18 @@ export class TypeImmunityHealAbAttr extends TypeImmunityAbAttr { super(immuneType); } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return super.canApplyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + } - if (ret) { - if (!pokemon.isFullHp() && !simulated) { - const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; - globalScene.unshiftPhase(new PokemonHealPhase(pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / 4), i18next.t("abilityTriggers:typeImmunityHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); - cancelled.value = true; // Suppresses "No Effect" message - } - return true; + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { + super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + if (!pokemon.isFullHp() && !simulated) { + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; + globalScene.unshiftPhase(new PokemonHealPhase(pokemon.getBattlerIndex(), + Utils.toDmgValue(pokemon.getMaxHp() / 4), i18next.t("abilityTriggers:typeImmunityHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); + cancelled.value = true; // Suppresses "No Effect" message } - - return false; } } @@ -521,17 +550,16 @@ class TypeImmunityStatStageChangeAbAttr extends TypeImmunityAbAttr { this.stages = stages; } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return super.canApplyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + } - if (ret) { - cancelled.value = true; // Suppresses "No Effect" message - if (!simulated) { - globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ this.stat ], this.stages)); - } + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { + super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + cancelled.value = true; // Suppresses "No Effect" message + if (!simulated) { + globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ this.stat ], this.stages)); } - - return ret; } } @@ -546,17 +574,16 @@ class TypeImmunityAddBattlerTagAbAttr extends TypeImmunityAbAttr { this.turnCount = turnCount; } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return super.canApplyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + } - if (ret) { - cancelled.value = true; // Suppresses "No Effect" message - if (!simulated) { - pokemon.addTag(this.tagType, this.turnCount, undefined, pokemon.id); - } + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { + super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + cancelled.value = true; // Suppresses "No Effect" message + if (!simulated) { + pokemon.addTag(this.tagType, this.turnCount, undefined, pokemon.id); } - - return ret; } } @@ -565,18 +592,16 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr { super(null, condition); } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { const modifierValue = args.length > 0 ? (args[0] as Utils.NumberHolder).value : pokemon.getAttackTypeEffectiveness(attacker.getMoveType(move), attacker, undefined, undefined, move); + return move instanceof AttackMove && modifierValue < 2; + } - if (move instanceof AttackMove && modifierValue < 2) { - cancelled.value = true; // Suppresses "No Effect" message - (args[0] as Utils.NumberHolder).value = 0; - return true; - } - - return false; + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; // Suppresses "No Effect" message + (args[0] as Utils.NumberHolder).value = 0; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -593,6 +618,12 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr { * @extends PreDefendAbAttr */ export class FullHpResistTypeAbAttr extends PreDefendAbAttr { + + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move | null, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + const typeMultiplier = args[0]; + return (typeMultiplier && typeMultiplier instanceof Utils.NumberHolder) && !(move && move.hasAttr(FixedDamageAttr)) && pokemon.isFullHp() && typeMultiplier.value > 0.5; + } + /** * Reduces a type multiplier to 0.5 if the source is at full HP. * @param pokemon {@linkcode Pokemon} the Pokemon with this ability @@ -602,7 +633,6 @@ export class FullHpResistTypeAbAttr extends PreDefendAbAttr { * @param move {@linkcode Move} the move being used on the source * @param cancelled n/a * @param args `[0]` a container for the move's current type effectiveness multiplier - * @returns `true` if the move's effectiveness is reduced; `false` otherwise */ override applyPreDefend( pokemon: Pokemon, @@ -611,23 +641,10 @@ export class FullHpResistTypeAbAttr extends PreDefendAbAttr { attacker: Pokemon, move: Move | null, cancelled: Utils.BooleanHolder | null, - args: any[], - ): boolean { + args: any[]): void { const typeMultiplier = args[0]; - if (!(typeMultiplier && typeMultiplier instanceof Utils.NumberHolder)) { - return false; - } - - if (move && move.hasAttr(FixedDamageAttr)) { - return false; - } - - if (pokemon.isFullHp() && typeMultiplier.value > 0.5) { - typeMultiplier.value = 0.5; - pokemon.turnData.moveEffectiveness = 0.5; - return true; - } - return false; + typeMultiplier.value = 0.5; + pokemon.turnData.moveEffectiveness = 0.5; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -638,6 +655,17 @@ export class FullHpResistTypeAbAttr extends PreDefendAbAttr { } export class PostDefendAbAttr extends AbAttr { + canApplyPostDefend( + pokemon: Pokemon, + passive: boolean, + simulated: boolean, + attacker: Pokemon, + move: Move, + hitResult: HitResult | null, + args: any[]): boolean { + return true; + } + applyPostDefend( pokemon: Pokemon, passive: boolean, @@ -646,37 +674,39 @@ export class PostDefendAbAttr extends AbAttr { move: Move, hitResult: HitResult | null, args: any[], - ): boolean { - return false; - } + ): void {} } export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr { - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (move.moveTarget === MoveTarget.USER || move.moveTarget === MoveTarget.NEAR_ALLY) { - return false; - } - if (move.getPriority(attacker) > 0 && !move.isMultiTarget()) { - cancelled.value = true; - return true; - } + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return !(move.moveTarget === MoveTarget.USER || move.moveTarget === MoveTarget.NEAR_ALLY) && move.getPriority(attacker) > 0 && !move.isMultiTarget(); + } - return false; + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; } } export class PostStatStageChangeAbAttr extends AbAttr { + canApplyPostStatStageChange( + pokemon: Pokemon, + simulated: boolean, + statsChanged: BattleStat[], + stagesChanged: number, + selfTarget: boolean, + args: any[]): boolean { + return true; + } + applyPostStatStageChange( pokemon: Pokemon, simulated: boolean, statsChanged: BattleStat[], - stagesChanged: integer, + stagesChanged: number, selfTarget: boolean, args: any[], - ): boolean { - return false; - } + ): void {} } export class MoveImmunityAbAttr extends PreDefendAbAttr { @@ -688,13 +718,12 @@ export class MoveImmunityAbAttr extends PreDefendAbAttr { this.immuneCondition = immuneCondition; } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.immuneCondition(pokemon, attacker, move)) { - cancelled.value = true; - return true; - } + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return this.immuneCondition(pokemon, attacker, move); + } - return false; + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -709,14 +738,19 @@ export class MoveImmunityAbAttr extends PreDefendAbAttr { * @extends PreDefendAbAttr */ export class WonderSkinAbAttr extends PreDefendAbAttr { - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const moveAccuracy = args[0] as Utils.NumberHolder; - if (move.category === MoveCategory.STATUS && moveAccuracy.value >= 50) { - moveAccuracy.value = 50; - return true; - } - return false; + constructor() { + super(false); + } + + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + const moveAccuracy = args[0] as Utils.NumberHolder; + return move.category === MoveCategory.STATUS && moveAccuracy.value >= 50; + } + + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { + const moveAccuracy = args[0] as Utils.NumberHolder; + moveAccuracy.value = 50; } } @@ -730,13 +764,13 @@ export class MoveImmunityStatStageChangeAbAttr extends MoveImmunityAbAttr { this.stages = stages; } - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); - if (ret && !simulated) { - globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ this.stat ], this.stages)); - } + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return !simulated && super.canApplyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + } - return ret; + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { + super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args); + globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ this.stat ], this.stages)); } } /** @@ -745,6 +779,11 @@ export class MoveImmunityStatStageChangeAbAttr extends MoveImmunityAbAttr { * @see {@linkcode applyPostDefend} */ export class ReverseDrainAbAttr extends PostDefendAbAttr { + + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return move.hasAttr(HitHealAttr) && !move.hitsSubstitute(attacker, pokemon); + } + /** * Determines if a damage and draining move was used to check if this ability should stop the healing. * Examples include: Absorb, Draining Kiss, Bitter Blade, etc. @@ -755,16 +794,11 @@ export class ReverseDrainAbAttr extends PostDefendAbAttr { * @param move {@linkcode PokemonMove} that is being used * @param _hitResult N/A * @param _args N/A - * @returns true if healing should be reversed on a healing move, false otherwise. */ - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (move.hasAttr(HitHealAttr) && !move.hitsSubstitute(attacker, pokemon)) { - if (!simulated) { - globalScene.queueMessage(i18next.t("abilityTriggers:reverseDrain", { pokemonNameWithAffix: getPokemonNameWithAffix(attacker) })); - } - return true; + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + if (!simulated) { + globalScene.queueMessage(i18next.t("abilityTriggers:reverseDrain", { pokemonNameWithAffix: getPokemonNameWithAffix(attacker) })); } - return false; } } @@ -785,24 +819,23 @@ export class PostDefendStatStageChangeAbAttr extends PostDefendAbAttr { this.allOthers = allOthers; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) { - if (simulated) { - return true; - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon); + } - if (this.allOthers) { - const otherPokemon = pokemon.getAlly() ? pokemon.getOpponents().concat([ pokemon.getAlly() ]) : pokemon.getOpponents(); - for (const other of otherPokemon) { - globalScene.unshiftPhase(new StatStageChangePhase((other).getBattlerIndex(), false, [ this.stat ], this.stages)); - } - return true; - } - globalScene.unshiftPhase(new StatStageChangePhase((this.selfTarget ? pokemon : attacker).getBattlerIndex(), this.selfTarget, [ this.stat ], this.stages)); - return true; + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + if (simulated) { + return; } - return false; + if (this.allOthers) { + const otherPokemon = pokemon.getAlly() ? pokemon.getOpponents().concat([ pokemon.getAlly() ]) : pokemon.getOpponents(); + for (const other of otherPokemon) { + globalScene.unshiftPhase(new StatStageChangePhase((other).getBattlerIndex(), false, [ this.stat ], this.stages)); + } + } else { + globalScene.unshiftPhase(new StatStageChangePhase((this.selfTarget ? pokemon : attacker).getBattlerIndex(), this.selfTarget, [ this.stat ], this.stages)); + } } } @@ -823,19 +856,17 @@ export class PostDefendHpGatedStatStageChangeAbAttr extends PostDefendAbAttr { this.selfTarget = selfTarget; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { const hpGateFlat: number = Math.ceil(pokemon.getMaxHp() * this.hpGate); const lastAttackReceived = pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1]; const damageReceived = lastAttackReceived?.damage || 0; + return this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + damageReceived) > hpGateFlat) && !move.hitsSubstitute(attacker, pokemon); + } - if (this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + damageReceived) > hpGateFlat) && !move.hitsSubstitute(attacker, pokemon)) { - if (!simulated) { - globalScene.unshiftPhase(new StatStageChangePhase((this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, this.stats, this.stages)); - } - return true; + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + if (!simulated) { + globalScene.unshiftPhase(new StatStageChangePhase((this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, this.stats, this.stages)); } - - return false; } } @@ -850,17 +881,16 @@ export class PostDefendApplyArenaTrapTagAbAttr extends PostDefendAbAttr { this.tagType = tagType; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) { - const tag = globalScene.arena.getTag(this.tagType) as ArenaTrapTag; - if (!globalScene.arena.getTag(this.tagType) || tag.layers < tag.maxLayers) { - if (!simulated) { - globalScene.arena.addTag(this.tagType, 0, undefined, pokemon.id, pokemon.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER); - } - return true; - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + const tag = globalScene.arena.getTag(this.tagType) as ArenaTrapTag; + return (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) + && (!globalScene.arena.getTag(this.tagType) || tag.layers < tag.maxLayers); + } + + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + if (!simulated) { + globalScene.arena.addTag(this.tagType, 0, undefined, pokemon.id, pokemon.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER); } - return false; } } @@ -874,40 +904,37 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr { this.tagType = tagType; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) { - if (!pokemon.getTag(this.tagType) && !simulated) { - pokemon.addTag(this.tagType, undefined, undefined, pokemon.id); - globalScene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name })); - } - return true; + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon); + } + + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + if (!pokemon.getTag(this.tagType) && !simulated) { + pokemon.addTag(this.tagType, undefined, undefined, pokemon.id); + globalScene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name })); } - return false; } } export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr { - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): boolean { - if (hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon)) { - if (simulated) { - return true; - } - const type = attacker.getMoveType(move); - const pokemonTypes = pokemon.getTypes(true); - if (pokemonTypes.length !== 1 || pokemonTypes[0] !== type) { - pokemon.summonData.types = [ type ]; - return true; - } - } + private type: PokemonType; - return false; + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + this.type = attacker.getMoveType(move); + const pokemonTypes = pokemon.getTypes(true); + return hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon) && (simulated || pokemonTypes.length !== 1 || pokemonTypes[0] !== this.type); + } + + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): void { + const type = attacker.getMoveType(move); + pokemon.summonData.types = [ type ]; } override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { return i18next.t("abilityTriggers:postDefendTypeChange", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName, - typeName: i18next.t(`pokemonInfo:Type.${PokemonType[pokemon.getTypes(true)[0]]}`) + typeName: i18next.t(`pokemonInfo:Type.${PokemonType[this.type]}`) }); } } @@ -921,16 +948,14 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr { this.terrainType = terrainType; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): boolean { - if (hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon)) { - if (simulated) { - return globalScene.arena.terrain?.terrainType !== (this.terrainType || undefined); - } else { - return globalScene.arena.trySetTerrain(this.terrainType, true); - } - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + return hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon) && globalScene.arena.canSetTerrain(this.terrainType); + } - return false; + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): void { + if (!simulated) { + globalScene.arena.trySetTerrain(this.terrainType, true); + } } } @@ -939,24 +964,22 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { private effects: StatusEffect[]; constructor(chance: number, ...effects: StatusEffect[]) { - super(); + super(true); this.chance = chance; this.effects = effects; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status - && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !move.hitsSubstitute(attacker, pokemon)) { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; - if (simulated) { - return attacker.canSetStatus(effect, true, false, pokemon); - } else { - return attacker.trySetStatus(effect, true, pokemon); - } - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + return move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status + && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !move.hitsSubstitute(attacker, pokemon) + && attacker.canSetStatus(effect, true, false, pokemon); + } - return false; + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + attacker.trySetStatus(effect, true, pokemon); } } @@ -965,11 +988,13 @@ export class EffectSporeAbAttr extends PostDefendContactApplyStatusEffectAbAttr super(10, StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP); } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (attacker.hasAbility(Abilities.OVERCOAT) || attacker.isOfType(PokemonType.GRASS)) { - return false; - } - return super.applyPostDefend(pokemon, passive, simulated, attacker, move, hitResult, args); + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return !(attacker.hasAbility(Abilities.OVERCOAT) || attacker.isOfType(PokemonType.GRASS)) + && super.canApplyPostDefend(pokemon, passive, simulated, attacker, move, hitResult, args); + } + + override applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): void { + super.applyPostDefend(pokemon, passive, simulated, attacker, move, hitResult, args); } } @@ -986,16 +1011,15 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { this.turnCount = turnCount; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance && !move.hitsSubstitute(attacker, pokemon)) { - if (simulated) { - return attacker.canAddTag(this.tagType); - } else { - return attacker.addTag(this.tagType, this.turnCount, move.id, attacker.id); - } - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance + && !move.hitsSubstitute(attacker, pokemon) && attacker.canAddTag(this.tagType); + } - return false; + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + if (!simulated) { + attacker.addTag(this.tagType, this.turnCount, move.id, attacker.id); + } } } @@ -1010,16 +1034,14 @@ export class PostDefendCritStatStageChangeAbAttr extends PostDefendAbAttr { this.stages = stages; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (move.hitsSubstitute(attacker, pokemon)) { - return false; - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return !move.hitsSubstitute(attacker, pokemon); + } + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { if (!simulated) { globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ this.stat ], this.stages)); } - - return true; } override getCondition(): AbAttrCondition { @@ -1036,15 +1058,14 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { this.damageRatio = damageRatio; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (!simulated && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) - && !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr) && !move.hitsSubstitute(attacker, pokemon)) { - attacker.damageAndUpdate(Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); - attacker.turnData.damageTaken += Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)); - return true; - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return !simulated && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) + && !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr) && !move.hitsSubstitute(attacker, pokemon); + } - return false; + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + attacker.damageAndUpdate(Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); + attacker.turnData.damageTaken += Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)); } override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { @@ -1070,19 +1091,16 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr { this.turns = turns; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !move.hitsSubstitute(attacker, pokemon)) { - if (attacker.getTag(BattlerTagType.PERISH_SONG)) { - return false; - } else { - if (!simulated) { - attacker.addTag(BattlerTagType.PERISH_SONG, this.turns); - pokemon.addTag(BattlerTagType.PERISH_SONG, this.turns); - } - return true; - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !move.hitsSubstitute(attacker, pokemon)) + && !attacker.getTag(BattlerTagType.PERISH_SONG); + } + + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + if (!simulated) { + attacker.addTag(BattlerTagType.PERISH_SONG, this.turns); + pokemon.addTag(BattlerTagType.PERISH_SONG, this.turns); } - return false; } override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { @@ -1101,18 +1119,15 @@ export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr { this.condition = condition; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (this.condition && !this.condition(pokemon, attacker, move) || move.hitsSubstitute(attacker, pokemon)) { - return false; - } - if (!globalScene.arena.weather?.isImmutable()) { - if (simulated) { - return globalScene.arena.weather?.weatherType !== this.weatherType; - } - return globalScene.arena.trySetWeather(this.weatherType, true); - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return (!(this.condition && !this.condition(pokemon, attacker, move) || move.hitsSubstitute(attacker, pokemon)) + && !globalScene.arena.weather?.isImmutable() && globalScene.arena.canSetWeather(this.weatherType)); + } - return false; + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + if (!simulated) { + globalScene.arena.trySetWeather(this.weatherType, true); + } } } @@ -1121,18 +1136,17 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr { super(); } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, args: any[]): boolean { - if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) - && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr) && !move.hitsSubstitute(attacker, pokemon)) { - if (!simulated) { - const tempAbility = attacker.getAbility(); - attacker.setTempAbility(pokemon.getAbility()); - pokemon.setTempAbility(tempAbility); - } - return true; - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) + && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr) && !move.hitsSubstitute(attacker, pokemon); + } - return false; + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, args: any[]): void { + if (!simulated) { + const tempAbility = attacker.getAbility(); + attacker.setTempAbility(pokemon.getAbility()); + pokemon.setTempAbility(tempAbility); + } } override getTriggerMessage(pokemon: Pokemon, _abilityName: string, ..._args: any[]): string { @@ -1148,17 +1162,15 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr { this.ability = ability; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) - && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr) && !move.hitsSubstitute(attacker, pokemon)) { - if (!simulated) { - attacker.setTempAbility(allAbilities[this.ability]); - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) + && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr) && !move.hitsSubstitute(attacker, pokemon); + } - return true; + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + if (!simulated) { + attacker.setTempAbility(allAbilities[this.ability]); } - - return false; } override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { @@ -1180,20 +1192,17 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr { this.chance = chance; } - override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { - if (attacker.getTag(BattlerTagType.DISABLED) === null && !move.hitsSubstitute(attacker, pokemon)) { - if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) { - if (simulated) { - return true; - } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return attacker.getTag(BattlerTagType.DISABLED) === null && !move.hitsSubstitute(attacker, pokemon) + && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance); + } - this.attacker = attacker; - this.move = move; - this.attacker.addTag(BattlerTagType.DISABLED, 4, 0, pokemon.id); - return true; - } + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): void { + if (!simulated) { + this.attacker = attacker; + this.move = move; + this.attacker.addTag(BattlerTagType.DISABLED, 4, 0, pokemon.id); } - return false; } } @@ -1210,19 +1219,28 @@ export class PostStatStageChangeStatStageChangeAbAttr extends PostStatStageChang this.stages = stages; } - applyPostStatStageChange(pokemon: Pokemon, simulated: boolean, statStagesChanged: BattleStat[], stagesChanged: number, selfTarget: boolean, args: any[]): boolean { - if (this.condition(pokemon, statStagesChanged, stagesChanged) && !selfTarget) { - if (!simulated) { - globalScene.unshiftPhase(new StatStageChangePhase((pokemon).getBattlerIndex(), true, this.statsToChange, this.stages)); - } - return true; - } + override canApplyPostStatStageChange(pokemon: Pokemon, simulated: boolean, statStagesChanged: BattleStat[], stagesChanged: integer, selfTarget: boolean, args: any[]): boolean { + return this.condition(pokemon, statStagesChanged, stagesChanged) && !selfTarget; + } - return false; + override applyPostStatStageChange(pokemon: Pokemon, simulated: boolean, statStagesChanged: BattleStat[], stagesChanged: number, selfTarget: boolean, args: any[]): void { + if (!simulated) { + globalScene.unshiftPhase(new StatStageChangePhase((pokemon).getBattlerIndex(), true, this.statsToChange, this.stages)); + } } } export class PreAttackAbAttr extends AbAttr { + canApplyPreAttack( + pokemon: Pokemon, + passive: boolean, + simulated: boolean, + defender: Pokemon | null, + move: Move, + args: any[]): boolean { + return true; + } + applyPreAttack( pokemon: Pokemon, passive: boolean, @@ -1230,9 +1248,7 @@ export class PreAttackAbAttr extends AbAttr { defender: Pokemon | null, move: Move, args: any[], - ): boolean { - return false; - } + ): void {} } /** @@ -1244,26 +1260,22 @@ export class MoveEffectChanceMultiplierAbAttr extends AbAttr { private chanceMultiplier: number; constructor(chanceMultiplier: number) { - super(true); + super(false); this.chanceMultiplier = chanceMultiplier; } + + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + const exceptMoves = [ Moves.ORDER_UP, Moves.ELECTRO_SHOT ]; + return !((args[0] as Utils.NumberHolder).value <= 0 || exceptMoves.includes((args[1] as Move).id)); + } + /** * @param args [0]: {@linkcode Utils.NumberHolder} Move additional effect chance. Has to be higher than or equal to 0. * [1]: {@linkcode Moves } Move used by the ability user. */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - // Disable showAbility during getTargetBenefitScore - this.showAbility = args[4]; - - const exceptMoves = [ Moves.ORDER_UP, Moves.ELECTRO_SHOT ]; - if ((args[0] as Utils.NumberHolder).value <= 0 || exceptMoves.includes((args[1] as Move).id)) { - return false; - } - + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { (args[0] as Utils.NumberHolder).value *= this.chanceMultiplier; (args[0] as Utils.NumberHolder).value = Math.min((args[0] as Utils.NumberHolder).value, 100); - return true; - } } @@ -1273,25 +1285,22 @@ export class MoveEffectChanceMultiplierAbAttr extends AbAttr { * @see {@linkcode applyPreDefend} */ export class IgnoreMoveEffectsAbAttr extends PreDefendAbAttr { + + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move | null, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return (args[0] as Utils.NumberHolder).value > 0; + } + /** * @param args [0]: {@linkcode Utils.NumberHolder} Move additional effect chance. */ - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - - if ((args[0] as Utils.NumberHolder).value <= 0) { - return false; - } - + override applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): void { (args[0] as Utils.NumberHolder).value = 0; - return true; - } } export class VariableMovePowerAbAttr extends PreAttackAbAttr { - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { - //const power = args[0] as Utils.NumberHolder; - return false; + override canApplyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + return true; } } @@ -1302,9 +1311,8 @@ export class FieldPreventExplosiveMovesAbAttr extends AbAttr { simulated: boolean, cancelled: Utils.BooleanHolder, args: any[], - ): boolean { + ): void { cancelled.value = true; - return true; } } @@ -1328,6 +1336,11 @@ export class FieldMultiplyStatAbAttr extends AbAttr { this.canStack = canStack; } + canApplyFieldStat(pokemon: Pokemon, passive: boolean, simulated: boolean, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, args: any[]): boolean { + return this.canStack || !hasApplied.value + && this.stat === stat && checkedPokemon.getAbilityAttrs(FieldMultiplyStatAbAttr).every(attr => (attr as FieldMultiplyStatAbAttr).stat !== stat); + } + /** * applyFieldStat: Tries to multiply a Pokemon's Stat * @param pokemon {@linkcode Pokemon} the Pokemon using this ability @@ -1337,19 +1350,10 @@ export class FieldMultiplyStatAbAttr extends AbAttr { * @param checkedPokemon {@linkcode Pokemon} the Pokemon this ability is targeting * @param hasApplied {@linkcode Utils.BooleanHolder} whether or not another multiplier has been applied to this stat * @param args {any[]} unused - * @returns true if this changed the checked stat, false otherwise. */ - applyFieldStat(pokemon: Pokemon, passive: boolean, simulated: boolean, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, args: any[]): boolean { - if (!this.canStack && hasApplied.value) { - return false; - } - - if (this.stat === stat && checkedPokemon.getAbilityAttrs(FieldMultiplyStatAbAttr).every(attr => (attr as FieldMultiplyStatAbAttr).stat !== stat)) { - statValue.value *= this.multiplier; - hasApplied.value = true; - return true; - } - return false; + applyFieldStat(pokemon: Pokemon, passive: boolean, simulated: boolean, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, args: any[]): void { + statValue.value *= this.multiplier; + hasApplied.value = true; } } @@ -1360,22 +1364,21 @@ export class MoveTypeChangeAbAttr extends PreAttackAbAttr { private powerMultiplier: number, private condition?: PokemonAttackCondition ) { - super(true); + super(false); + } + + override canApplyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean { + return (this.condition && this.condition(pokemon, defender, move)) ?? false; } // TODO: Decouple this into two attributes (type change / power boost) - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { - if (this.condition && this.condition(pokemon, defender, move)) { - if (args[0] && args[0] instanceof Utils.NumberHolder) { - args[0].value = this.newType; - } - if (args[1] && args[1] instanceof Utils.NumberHolder) { - args[1].value *= this.powerMultiplier; - } - return true; + override applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): void { + if (args[0] && args[0] instanceof Utils.NumberHolder) { + args[0].value = this.newType; + } + if (args[1] && args[1] instanceof Utils.NumberHolder) { + args[1].value *= this.powerMultiplier; } - - return false; } } @@ -1387,37 +1390,37 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr { super(true); } - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { - if ( - !pokemon.isTerastallized && - move.id !== Moves.STRUGGLE && - /** - * Skip moves that call other moves because these moves generate a following move that will trigger this ability attribute - * @see {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_call_other_moves} - */ - !move.findAttr((attr) => - attr instanceof RandomMovesetMoveAttr || - attr instanceof RandomMoveAttr || - attr instanceof NaturePowerAttr || - attr instanceof CopyMoveAttr - ) - ) { + override canApplyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean { + if (!pokemon.isTerastallized && + move.id !== Moves.STRUGGLE && + /** + * Skip moves that call other moves because these moves generate a following move that will trigger this ability attribute + * @see {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_call_other_moves} + */ + !move.findAttr((attr) => + attr instanceof RandomMovesetMoveAttr || + attr instanceof RandomMoveAttr || + attr instanceof NaturePowerAttr || + attr instanceof CopyMoveAttr)) { const moveType = pokemon.getMoveType(move); - if (pokemon.getTypes().some((t) => t !== moveType)) { - if (!simulated) { - this.moveType = moveType; - pokemon.summonData.types = [ moveType ]; - pokemon.updateInfo(); - } - + this.moveType = moveType; return true; } } - return false; } + override applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): void { + const moveType = pokemon.getMoveType(move); + + if (!simulated) { + this.moveType = moveType; + pokemon.summonData.types = [ moveType ]; + pokemon.updateInfo(); + } + } + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { return i18next.t("abilityTriggers:pokemonTypeChange", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), @@ -1439,6 +1442,10 @@ export class AddSecondStrikeAbAttr extends PreAttackAbAttr { this.damageMultiplier = damageMultiplier; } + override canApplyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean { + return move.canBeMultiStrikeEnhanced(pokemon, true); + } + /** * If conditions are met, this doubles the move's hit count (via args[1]) * or multiplies the damage of secondary strikes (via args[2]) @@ -1449,24 +1456,17 @@ export class AddSecondStrikeAbAttr extends PreAttackAbAttr { * @param args Additional arguments: * - `[0]` the number of strikes this move currently has ({@linkcode Utils.NumberHolder}) * - `[1]` the damage multiplier for the current strike ({@linkcode Utils.NumberHolder}) - * @returns */ - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + override applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): void { const hitCount = args[0] as Utils.NumberHolder; const multiplier = args[1] as Utils.NumberHolder; - - if (move.canBeMultiStrikeEnhanced(pokemon, true)) { - this.showAbility = !!hitCount?.value; - if (hitCount?.value) { - hitCount.value += 1; - } - - if (multiplier?.value && pokemon.turnData.hitsLeft === 1) { - multiplier.value = this.damageMultiplier; - } - return true; + if (hitCount?.value) { + hitCount.value += 1; + } + + if (multiplier?.value && pokemon.turnData.hitsLeft === 1) { + multiplier.value = this.damageMultiplier; } - return false; } } @@ -1481,11 +1481,15 @@ export class DamageBoostAbAttr extends PreAttackAbAttr { private condition: PokemonAttackCondition; constructor(damageMultiplier: number, condition: PokemonAttackCondition) { - super(true); + super(false); this.damageMultiplier = damageMultiplier; this.condition = condition; } + override canApplyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean { + return this.condition(pokemon, defender, move); + } + /** * * @param pokemon the attacker pokemon @@ -1493,16 +1497,10 @@ export class DamageBoostAbAttr extends PreAttackAbAttr { * @param defender the target pokemon * @param move the move used by the attacker pokemon * @param args Utils.NumberHolder as damage - * @returns true if the function succeeds */ - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { - if (this.condition(pokemon, defender, move)) { - const power = args[0] as Utils.NumberHolder; - power.value = Utils.toDmgValue(power.value * this.damageMultiplier); - return true; - } - - return false; + override applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): void { + const power = args[0] as Utils.NumberHolder; + power.value = Utils.toDmgValue(power.value * this.damageMultiplier); } } @@ -1510,26 +1508,24 @@ export class MovePowerBoostAbAttr extends VariableMovePowerAbAttr { private condition: PokemonAttackCondition; private powerMultiplier: number; - constructor(condition: PokemonAttackCondition, powerMultiplier: number, showAbility = true) { + constructor(condition: PokemonAttackCondition, powerMultiplier: number, showAbility: boolean = false) { super(showAbility); this.condition = condition; this.powerMultiplier = powerMultiplier; } - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { - if (this.condition(pokemon, defender, move)) { - (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; + override canApplyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean { + return this.condition(pokemon, defender, move); + } - return true; - } - - return false; + override applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): void { + (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; } } export class MoveTypePowerBoostAbAttr extends MovePowerBoostAbAttr { constructor(boostedType: PokemonType, powerMultiplier?: number) { - super((pokemon, defender, move) => pokemon?.getMoveType(move) === boostedType, powerMultiplier || 1.5); + super((pokemon, defender, move) => pokemon?.getMoveType(move) === boostedType, powerMultiplier || 1.5, false); } } @@ -1560,17 +1556,13 @@ export class VariableMovePowerBoostAbAttr extends VariableMovePowerAbAttr { this.mult = mult; } - /** - * @override - */ - applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move, args: any[]): boolean { - const multiplier = this.mult(pokemon, defender, move); - if (multiplier !== 1) { - (args[0] as Utils.NumberHolder).value *= multiplier; - return true; - } + override canApplyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean { + return this.mult(pokemon, defender, move) !== 1; + } - return false; + override applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): void { + const multiplier = this.mult(pokemon, defender, move); + (args[0] as Utils.NumberHolder).value *= multiplier; } } @@ -1579,6 +1571,7 @@ export class VariableMovePowerBoostAbAttr extends VariableMovePowerAbAttr { * @extends AbAttr */ export class FieldMovePowerBoostAbAttr extends AbAttr { + // TODO: Refactor this class? It extends from base AbAttr but has preAttack methods and gets called directly instead of going through applyAbAttrsInternal private condition: PokemonAttackCondition; private powerMultiplier: number; @@ -1592,14 +1585,14 @@ export class FieldMovePowerBoostAbAttr extends AbAttr { this.powerMultiplier = powerMultiplier; } - applyPreAttack(pokemon: Pokemon | null, passive: boolean | null, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean { + canApplyPreAttack(pokemon: Pokemon | null, passive: boolean | null, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): boolean { + return true; // logic for this attr is handled in move.ts instead of normally + } + + applyPreAttack(pokemon: Pokemon | null, passive: boolean | null, simulated: boolean, defender: Pokemon | null, move: Move, args: any[]): void { if (this.condition(pokemon, defender, move)) { (args[0] as Utils.NumberHolder).value *= this.powerMultiplier; - - return true; } - - return false; } } @@ -1656,21 +1649,25 @@ export class StatMultiplierAbAttr extends AbAttr { this.condition = condition ?? null; } + canApplyStatStage( + pokemon: Pokemon, + _passive: boolean, + simulated: boolean, + stat: BattleStat, + statValue: Utils.NumberHolder, + args: any[]): boolean { + const move = (args[0] as Move); + return stat === this.stat && (!this.condition || this.condition(pokemon, null, move)); + } + applyStatStage( pokemon: Pokemon, _passive: boolean, simulated: boolean, stat: BattleStat, statValue: Utils.NumberHolder, - args: any[], - ): boolean { - const move = args[0] as Move; - if (stat === this.stat && (!this.condition || this.condition(pokemon, null, move))) { - statValue.value *= this.multiplier; - return true; - } - - return false; + args: any[]): void { + statValue.value *= this.multiplier; } } @@ -1685,10 +1682,23 @@ export class PostAttackAbAttr extends AbAttr { } /** - * Please override {@link applyPostAttackAfterMoveTypeCheck} instead of this method. By default, this method checks that the move used is a damaging attack before + * By default, this method checks that the move used is a damaging attack before * applying the effect of any inherited class. This can be changed by providing a different {@link attackCondition} to the constructor. See {@link ConfusionOnStatusEffectAbAttr} * for an example of an effect that does not require a damaging move. */ + canApplyPostAttack( + pokemon: Pokemon, + passive: boolean, + simulated: boolean, + defender: Pokemon, + move: Move, + hitResult: HitResult | null, + args: any[]): boolean { + // When attackRequired is true, we require the move to be an attack move and to deal damage before checking secondary requirements. + // If attackRequired is false, we always defer to the secondary requirements. + return this.attackCondition(pokemon, defender, move); + } + applyPostAttack( pokemon: Pokemon, passive: boolean, @@ -1696,31 +1706,7 @@ export class PostAttackAbAttr extends AbAttr { defender: Pokemon, move: Move, hitResult: HitResult | null, - args: any[], - ): boolean { - // When attackRequired is true, we require the move to be an attack move and to deal damage before checking secondary requirements. - // If attackRequired is false, we always defer to the secondary requirements. - if (this.attackCondition(pokemon, defender, move)) { - return this.applyPostAttackAfterMoveTypeCheck(pokemon, passive, simulated, defender, move, hitResult, args); - } else { - return false; - } - } - - /** - * This method is only called after {@link applyPostAttack} has already been applied. Use this for handling checks specific to the ability in question. - */ - applyPostAttackAfterMoveTypeCheck( - pokemon: Pokemon, - passive: boolean, - simulated: boolean, - defender: Pokemon, - move: Move, - hitResult: HitResult | null, - args: any[], - ): boolean { - return false; - } + args: any[]): void {} } /** @@ -1732,6 +1718,18 @@ export class GorillaTacticsAbAttr extends PostAttackAbAttr { super((user, target, move) => true, false); } + override canApplyPostAttack( + pokemon: Pokemon, + passive: boolean, + simulated: boolean, + defender: Pokemon, + move: Move, + hitResult: HitResult | null, + args: any[]): boolean { + return super.canApplyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args) + && simulated || !pokemon.getTag(BattlerTagType.GORILLA_TACTICS); + } + /** * * @param {Pokemon} pokemon the {@linkcode Pokemon} with this ability @@ -1741,32 +1739,24 @@ export class GorillaTacticsAbAttr extends PostAttackAbAttr { * @param move n/a * @param hitResult n/a * @param args n/a - * @returns `true` if the ability is applied */ - override applyPostAttackAfterMoveTypeCheck( + override applyPostAttack( pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, - args: any[], - ): boolean { - if (simulated) { - return simulated; + args: any[]): void { + if (!simulated) { + pokemon.addTag(BattlerTagType.GORILLA_TACTICS); } - - if (pokemon.getTag(BattlerTagType.GORILLA_TACTICS)) { - return false; - } - - pokemon.addTag(BattlerTagType.GORILLA_TACTICS); - return true; } } export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { private stealCondition: PokemonAttackCondition | null; + private stolenItem?: PokemonHeldItemModifier; constructor(stealCondition?: PokemonAttackCondition) { super(); @@ -1774,7 +1764,34 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { this.stealCondition = stealCondition ?? null; } - override applyPostAttackAfterMoveTypeCheck( + override canApplyPostAttack( + pokemon: Pokemon, + passive: boolean, + simulated: boolean, + defender: Pokemon, + move: Move, + hitResult: HitResult, + args: any[]): boolean { + if ( + super.canApplyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args) && + !simulated && + hitResult < HitResult.NO_EFFECT && + (!this.stealCondition || this.stealCondition(pokemon, defender, move)) + ) { + const heldItems = this.getTargetHeldItems(defender).filter((i) => i.isTransferable); + if (heldItems.length) { + // Ensure that the stolen item in testing is the same as when the effect is applied + this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; + if (globalScene.canTransferHeldItemModifier(this.stolenItem, pokemon)) { + return true; + } + } + } + this.stolenItem = undefined; + return false; + } + + override applyPostAttack( pokemon: Pokemon, passive: boolean, simulated: boolean, @@ -1782,28 +1799,21 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { move: Move, hitResult: HitResult, args: any[], - ): boolean { - if ( - !simulated && - hitResult < HitResult.NO_EFFECT && - (!this.stealCondition || this.stealCondition(pokemon, defender, move)) - ) { - const heldItems = this.getTargetHeldItems(defender).filter((i) => i.isTransferable); - if (heldItems.length) { - const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; - if (globalScene.tryTransferHeldItemModifier(stolenItem, pokemon, false)) { - globalScene.queueMessage( - i18next.t("abilityTriggers:postAttackStealHeldItem", { - pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - defenderName: defender.name, - stolenItemType: stolenItem.type.name, - }), - ); - return true; - } - } + ): void { + const heldItems = this.getTargetHeldItems(defender).filter((i) => i.isTransferable); + if (!this.stolenItem) { + this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; } - return false; + if (globalScene.tryTransferHeldItemModifier(this.stolenItem, pokemon, false)) { + globalScene.queueMessage( + i18next.t("abilityTriggers:postAttackStealHeldItem", { + pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), + defenderName: defender.name, + stolenItemType: this.stolenItem.type.name, + }), + ); + } + this.stolenItem = undefined; } getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] { @@ -1825,18 +1835,23 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { this.effects = effects; } - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (pokemon !== attacker && move.hitsSubstitute(attacker, pokemon)) { - return false; - } - - /**Status inflicted by abilities post attacking are also considered additional effects.*/ - if (!attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && !simulated && pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) { + override canApplyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + if ( + super.canApplyPostAttack(pokemon, passive, simulated, attacker, move, hitResult, args) + && !(pokemon !== attacker && move.hitsSubstitute(attacker, pokemon)) + && (simulated || !attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker + && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) + ) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; - return attacker.trySetStatus(effect, true, pokemon); + return simulated || attacker.canSetStatus(effect, true, false, pokemon); } - return simulated; + return false; + } + + applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): void { + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + attacker.trySetStatus(effect, true, pokemon); } } @@ -1853,26 +1868,32 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr { constructor(contactRequired: boolean, chance: (user: Pokemon, target: Pokemon, move: Move) => number, ...effects: BattlerTagType[]) { - super(); + super(undefined, false); this.contactRequired = contactRequired; this.chance = chance; this.effects = effects; } - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + override canApplyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { /**Battler tags inflicted by abilities post attacking are also considered additional effects.*/ - if (!attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status) { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; - return simulated || attacker.addTag(effect); - } + return super.canApplyPostAttack(pokemon, passive, simulated, attacker, move, hitResult, args) && + !attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker && + (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && + pokemon.randSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status; + } - return false; + override applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): void { + if (!simulated) { + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; + attacker.addTag(effect); + } } } export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { private condition?: PokemonDefendCondition; + private stolenItem?: PokemonHeldItemModifier; constructor(condition?: PokemonDefendCondition) { super(); @@ -1880,6 +1901,24 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { this.condition = condition; } + override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + if ( + !simulated && + hitResult < HitResult.NO_EFFECT && + (!this.condition || this.condition(pokemon, attacker, move)) && + !move.hitsSubstitute(attacker, pokemon) + ) { + const heldItems = this.getTargetHeldItems(attacker).filter((i) => i.isTransferable); + if (heldItems.length) { + this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; + if (globalScene.canTransferHeldItemModifier(this.stolenItem, pokemon)) { + return true; + } + } + } + return false; + } + override applyPostDefend( pokemon: Pokemon, _passive: boolean, @@ -1888,29 +1927,22 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { move: Move, hitResult: HitResult, _args: any[], - ): boolean { - if ( - !simulated && - hitResult < HitResult.NO_EFFECT && - (!this.condition || this.condition(pokemon, attacker, move)) && - !move.hitsSubstitute(attacker, pokemon) - ) { - const heldItems = this.getTargetHeldItems(attacker).filter((i) => i.isTransferable); - if (heldItems.length) { - const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; - if (globalScene.tryTransferHeldItemModifier(stolenItem, pokemon, false)) { - globalScene.queueMessage( - i18next.t("abilityTriggers:postDefendStealHeldItem", { - pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - attackerName: attacker.name, - stolenItemType: stolenItem.type.name, - }), - ); - return true; - } - } + ): void { + + const heldItems = this.getTargetHeldItems(attacker).filter((i) => i.isTransferable); + if (!this.stolenItem) { + this.stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; } - return false; + if (globalScene.tryTransferHeldItemModifier(this.stolenItem, pokemon, false)) { + globalScene.queueMessage( + i18next.t("abilityTriggers:postDefendStealHeldItem", { + pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), + attackerName: attacker.name, + stolenItemType: this.stolenItem.type.name, + }), + ); + } + this.stolenItem = undefined; } getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] { @@ -1924,6 +1956,16 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { * @see {@linkcode applyPostSetStatus()}. */ export class PostSetStatusAbAttr extends AbAttr { + canApplyPostSetStatus( + pokemon: Pokemon, + sourcePokemon: Pokemon | null = null, + passive: boolean, + effect: StatusEffect, + simulated: boolean, + rgs: any[]): boolean { + return true; + } + /** * Does nothing after a status condition is set. * @param pokemon {@linkcode Pokemon} that status condition was set on. @@ -1931,7 +1973,6 @@ export class PostSetStatusAbAttr extends AbAttr { * @param passive Whether this ability is a passive. * @param effect {@linkcode StatusEffect} that was set. * @param args Set of unique arguments needed by this attribute. - * @returns `true` if application of the ability succeeds. */ applyPostSetStatus( pokemon: Pokemon, @@ -1940,9 +1981,7 @@ export class PostSetStatusAbAttr extends AbAttr { effect: StatusEffect, simulated: boolean, args: any[], - ): boolean { - return false; - } + ): void {} } /** @@ -1951,17 +1990,7 @@ export class PostSetStatusAbAttr extends AbAttr { * ability attribute. For Synchronize ability. */ export class SynchronizeStatusAbAttr extends PostSetStatusAbAttr { - /** - * If the `StatusEffect` that was set is Burn, Paralysis, Poison, or Toxic, and the status - * was set by a source Pokemon, set the source Pokemon's status to the same `StatusEffect`. - * @param pokemon {@linkcode Pokemon} that status condition was set on. - * @param sourcePokemon {@linkcode Pokemon} that that set the status condition. Is null if status was not set by a Pokemon. - * @param passive Whether this ability is a passive. - * @param effect {@linkcode StatusEffect} that was set. - * @param args Set of unique arguments needed by this attribute. - * @returns `true` if application of the ability succeeds. - */ - override applyPostSetStatus(pokemon: Pokemon, sourcePokemon: Pokemon | null = null, passive: boolean, effect: StatusEffect, simulated: boolean, args: any[]): boolean { + override canApplyPostSetStatus(pokemon: Pokemon, sourcePokemon: (Pokemon | null) | undefined, passive: boolean, effect: StatusEffect, simulated: boolean, args: any[]): boolean { /** Synchronizable statuses */ const syncStatuses = new Set([ StatusEffect.BURN, @@ -1970,21 +1999,32 @@ export class SynchronizeStatusAbAttr extends PostSetStatusAbAttr { StatusEffect.TOXIC ]); - if (sourcePokemon && syncStatuses.has(effect)) { - if (!simulated) { - sourcePokemon.trySetStatus(effect, true, pokemon); - } - return true; - } + // synchronize does not need to check canSetStatus because the ability shows even if it fails to set the status + return ((sourcePokemon ?? false) && syncStatuses.has(effect)); + } - return false; + /** + * If the `StatusEffect` that was set is Burn, Paralysis, Poison, or Toxic, and the status + * was set by a source Pokemon, set the source Pokemon's status to the same `StatusEffect`. + * @param pokemon {@linkcode Pokemon} that status condition was set on. + * @param sourcePokemon {@linkcode Pokemon} that that set the status condition. Is null if status was not set by a Pokemon. + * @param passive Whether this ability is a passive. + * @param effect {@linkcode StatusEffect} that was set. + * @param args Set of unique arguments needed by this attribute. + */ + override applyPostSetStatus(pokemon: Pokemon, sourcePokemon: Pokemon | null = null, passive: boolean, effect: StatusEffect, simulated: boolean, args: any[]): void { + if (!simulated && sourcePokemon) { + sourcePokemon.trySetStatus(effect, true, pokemon); + } } } export class PostVictoryAbAttr extends AbAttr { - applyPostVictory(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - return false; + canApplyPostVictory(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return true; } + + applyPostVictory(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {} } class PostVictoryStatStageChangeAbAttr extends PostVictoryAbAttr { @@ -1998,12 +2038,11 @@ class PostVictoryStatStageChangeAbAttr extends PostVictoryAbAttr { this.stages = stages; } - applyPostVictory(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override applyPostVictory(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { const stat = typeof this.stat === "function" ? this.stat(pokemon) : this.stat; if (!simulated) { globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ stat ], this.stages)); } - return true; } } @@ -2016,23 +2055,24 @@ export class PostVictoryFormChangeAbAttr extends PostVictoryAbAttr { this.formFunc = formFunc; } - applyPostVictory(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override canApplyPostVictory(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { const formIndex = this.formFunc(pokemon); - if (formIndex !== pokemon.formIndex) { - if (!simulated) { - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); - } - return true; - } + return formIndex !== pokemon.formIndex; + } - return false; + override applyPostVictory(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); + } } } export class PostKnockOutAbAttr extends AbAttr { - applyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): boolean { - return false; + canApplyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): boolean { + return true; } + + applyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): void {} } export class PostKnockOutStatStageChangeAbAttr extends PostKnockOutAbAttr { @@ -2046,12 +2086,11 @@ export class PostKnockOutStatStageChangeAbAttr extends PostKnockOutAbAttr { this.stages = stages; } - applyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): boolean { + override applyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): void { const stat = typeof this.stat === "function" ? this.stat(pokemon) : this.stat; if (!simulated) { globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ stat ], this.stages)); } - return true; } } @@ -2060,16 +2099,15 @@ export class CopyFaintedAllyAbilityAbAttr extends PostKnockOutAbAttr { super(); } - applyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): boolean { - if (pokemon.isPlayer() === knockedOut.isPlayer() && !knockedOut.getAbility().hasAttr(UncopiableAbilityAbAttr)) { - if (!simulated) { - globalScene.queueMessage(i18next.t("abilityTriggers:copyFaintedAllyAbility", { pokemonNameWithAffix: getPokemonNameWithAffix(knockedOut), abilityName: allAbilities[knockedOut.getAbility().id].name })); - pokemon.setTempAbility(knockedOut.getAbility()); - } - return true; - } + override canApplyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): boolean { + return pokemon.isPlayer() === knockedOut.isPlayer() && !knockedOut.getAbility().hasAttr(UncopiableAbilityAbAttr); + } - return false; + override applyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): void { + if (!simulated) { + pokemon.setTempAbility(knockedOut.getAbility()); + globalScene.queueMessage(i18next.t("abilityTriggers:copyFaintedAllyAbility", { pokemonNameWithAffix: getPokemonNameWithAffix(knockedOut), abilityName: allAbilities[knockedOut.getAbility().id].name })); + } } } @@ -2086,6 +2124,10 @@ export class IgnoreOpponentStatStagesAbAttr extends AbAttr { this.stats = stats ?? BATTLE_STATS; } + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return this.stats.includes(args[0]); + } + /** * Modifies a BooleanHolder and returns the result to see if a stat is ignored or not * @param _pokemon n/a @@ -2093,14 +2135,9 @@ export class IgnoreOpponentStatStagesAbAttr extends AbAttr { * @param simulated n/a * @param _cancelled n/a * @param args A BooleanHolder that represents whether or not to ignore a stat's stat changes - * @returns true if the stat is ignored, false otherwise */ - apply(_pokemon: Pokemon, _passive: boolean, simulated: boolean, _cancelled: Utils.BooleanHolder, args: any[]) { - if (this.stats.includes(args[0])) { - (args[1] as Utils.BooleanHolder).value = true; - return true; - } - return false; + override apply(_pokemon: Pokemon, _passive: boolean, simulated: boolean, _cancelled: Utils.BooleanHolder, args: any[]): void { + (args[1] as Utils.BooleanHolder).value = true; } } @@ -2109,9 +2146,8 @@ export class IntimidateImmunityAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { cancelled.value = true; - return true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -2134,12 +2170,11 @@ export class PostIntimidateStatStageChangeAbAttr extends AbAttr { this.overwrites = !!overwrites; } - apply(pokemon: Pokemon, passive: boolean, simulated:boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated:boolean, cancelled: Utils.BooleanHolder, args: any[]): void { if (!simulated) { globalScene.pushPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), false, this.stats, this.stages)); } cancelled.value = this.overwrites; - return true; } } @@ -2163,16 +2198,17 @@ export class PostSummonAbAttr extends AbAttr { return this.activateOnGain; } + canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return true; + } + /** * Applies ability post summon (after switching in) * @param pokemon {@linkcode Pokemon} with this ability * @param passive Whether this ability is a passive * @param args Set of unique arguments needed by this attribute - * @returns true if application of the ability succeeds */ - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - return false; - } + applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {} } /** @@ -2190,13 +2226,16 @@ export class PostSummonRemoveArenaTagAbAttr extends PostSummonAbAttr { this.arenaTags = arenaTags; } - override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return globalScene.arena.tags.some(tag => this.arenaTags.includes(tag.tagType)); + } + + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { if (!simulated) { for (const arenaTag of this.arenaTags) { globalScene.arena.removeTag(arenaTag); } } - return true; } } @@ -2211,20 +2250,19 @@ export class PostSummonAddArenaTagAbAttr extends PostSummonAbAttr { private sourceId: number; - constructor(tagType: ArenaTagType, turnCount: number, side?: ArenaTagSide, quiet?: boolean) { - super(false); + constructor(showAbility: boolean, tagType: ArenaTagType, turnCount: number, side?: ArenaTagSide, quiet?: boolean) { + super(showAbility); this.tagType = tagType; this.turnCount = turnCount; this.side = side; this.quiet = quiet; } - public override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + public override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { this.sourceId = pokemon.id; if (!simulated) { globalScene.arena.addTag(this.tagType, this.turnCount, undefined, this.sourceId, this.side, this.quiet); } - return true; } } @@ -2237,12 +2275,10 @@ export class PostSummonMessageAbAttr extends PostSummonAbAttr { this.messageFunc = messageFunc; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { if (!simulated) { globalScene.queueMessage(this.messageFunc(pokemon)); } - - return true; } } @@ -2256,12 +2292,10 @@ export class PostSummonUnnamedMessageAbAttr extends PostSummonAbAttr { this.message = message; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { if (!simulated) { globalScene.queueMessage(this.message); } - - return true; } } @@ -2276,11 +2310,13 @@ export class PostSummonAddBattlerTagAbAttr extends PostSummonAbAttr { this.turnCount = turnCount; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (simulated) { - return pokemon.canAddTag(this.tagType); - } else { - return pokemon.addTag(this.tagType, this.turnCount); + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return pokemon.canAddTag(this.tagType); + } + + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + pokemon.addTag(this.tagType, this.turnCount); } } } @@ -2292,7 +2328,7 @@ export class PostSummonStatStageChangeAbAttr extends PostSummonAbAttr { private intimidate: boolean; constructor(stats: BattleStat[], stages: number, selfTarget?: boolean, intimidate?: boolean) { - super(false); + super(true); this.stats = stats; this.stages = stages; @@ -2300,33 +2336,31 @@ export class PostSummonStatStageChangeAbAttr extends PostSummonAbAttr { this.intimidate = !!intimidate; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { if (simulated) { - return true; + return; } - queueShowAbility(pokemon, passive); // TODO: Better solution than manually showing the ability here if (this.selfTarget) { // we unshift the StatStageChangePhase to put it right after the showAbility and not at the end of the // phase list (which could be after CommandPhase for example) globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, this.stats, this.stages)); - return true; - } - for (const opponent of pokemon.getOpponents()) { - const cancelled = new Utils.BooleanHolder(false); - if (this.intimidate) { - applyAbAttrs(IntimidateImmunityAbAttr, opponent, cancelled, simulated); - applyAbAttrs(PostIntimidateStatStageChangeAbAttr, opponent, cancelled, simulated); + } else { + for (const opponent of pokemon.getOpponents()) { + const cancelled = new Utils.BooleanHolder(false); + if (this.intimidate) { + applyAbAttrs(IntimidateImmunityAbAttr, opponent, cancelled, simulated); + applyAbAttrs(PostIntimidateStatStageChangeAbAttr, opponent, cancelled, simulated); - if (opponent.getTag(BattlerTagType.SUBSTITUTE)) { - cancelled.value = true; + if (opponent.getTag(BattlerTagType.SUBSTITUTE)) { + cancelled.value = true; + } + } + if (!cancelled.value) { + globalScene.unshiftPhase(new StatStageChangePhase(opponent.getBattlerIndex(), false, this.stats, this.stages)); } } - if (!cancelled.value) { - globalScene.unshiftPhase(new StatStageChangePhase(opponent.getBattlerIndex(), false, this.stats, this.stages)); - } } - return true; } } @@ -2341,18 +2375,16 @@ export class PostSummonAllyHealAbAttr extends PostSummonAbAttr { this.showAnim = showAnim; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return pokemon.getAlly()?.isActive(true); + } + + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { const target = pokemon.getAlly(); - if (target?.isActive(true)) { - if (!simulated) { - globalScene.unshiftPhase(new PokemonHealPhase(target.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / this.healRatio), i18next.t("abilityTriggers:postSummonAllyHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(target), pokemonName: pokemon.name }), true, !this.showAnim)); - } - - return true; + if (!simulated) { + globalScene.unshiftPhase(new PokemonHealPhase(target.getBattlerIndex(), + Utils.toDmgValue(pokemon.getMaxHp() / this.healRatio), i18next.t("abilityTriggers:postSummonAllyHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(target), pokemonName: pokemon.name }), true, !this.showAnim)); } - - return false; } } @@ -2369,21 +2401,19 @@ export class PostSummonClearAllyStatStagesAbAttr extends PostSummonAbAttr { super(); } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - const target = pokemon.getAlly(); - if (target?.isActive(true)) { - if (!simulated) { - for (const s of BATTLE_STATS) { - target.setStatStage(s, 0); - } + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return pokemon.getAlly()?.isActive(true); + } - globalScene.queueMessage(i18next.t("abilityTriggers:postSummonClearAllyStats", { pokemonNameWithAffix: getPokemonNameWithAffix(target) })); + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + const target = pokemon.getAlly(); + if (!simulated) { + for (const s of BATTLE_STATS) { + target.setStatStage(s, 0); } - return true; + globalScene.queueMessage(i18next.t("abilityTriggers:postSummonClearAllyStats", { pokemonNameWithAffix: getPokemonNameWithAffix(target) })); } - - return false; } } @@ -2400,15 +2430,7 @@ export class DownloadAbAttr extends PostSummonAbAttr { private enemyCountTally: number; private stats: BattleStat[]; - /** - * Checks to see if it is the opening turn (starting a new game), if so, Download won't work. This is because Download takes into account - * vitamins and items, so it needs to use the Stat and the stat alone. - * @param {Pokemon} pokemon Pokemon that is using the move, as well as seeing the opposing pokemon. - * @param {boolean} passive N/A - * @param {any[]} args N/A - * @returns Returns true if ability is used successful, false if not. - */ - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { this.enemyDef = 0; this.enemySpDef = 0; this.enemyCountTally = 0; @@ -2420,21 +2442,26 @@ export class DownloadAbAttr extends PostSummonAbAttr { } this.enemyDef = Math.round(this.enemyDef / this.enemyCountTally); this.enemySpDef = Math.round(this.enemySpDef / this.enemyCountTally); + return this.enemyDef > 0 && this.enemySpDef > 0; + } + /** + * Checks to see if it is the opening turn (starting a new game), if so, Download won't work. This is because Download takes into account + * vitamins and items, so it needs to use the Stat and the stat alone. + * @param {Pokemon} pokemon Pokemon that is using the move, as well as seeing the opposing pokemon. + * @param {boolean} passive N/A + * @param {any[]} args N/A + */ + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { if (this.enemyDef < this.enemySpDef) { this.stats = [ Stat.ATK ]; } else { this.stats = [ Stat.SPATK ]; } - if (this.enemyDef > 0 && this.enemySpDef > 0) { // only activate if there's actually an enemy to download from - if (!simulated) { - globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), false, this.stats, 1)); - } - return true; + if (!simulated) { + globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), false, this.stats, 1)); } - - return false; } } @@ -2447,18 +2474,17 @@ export class PostSummonWeatherChangeAbAttr extends PostSummonAbAttr { this.weatherType = weatherType; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if ((this.weatherType === WeatherType.HEAVY_RAIN || + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + const weatherReplaceable = (this.weatherType === WeatherType.HEAVY_RAIN || this.weatherType === WeatherType.HARSH_SUN || - this.weatherType === WeatherType.STRONG_WINDS) || !globalScene.arena.weather?.isImmutable()) { - if (simulated) { - return globalScene.arena.weather?.weatherType !== this.weatherType; - } else { - return globalScene.arena.trySetWeather(this.weatherType, true); - } - } + this.weatherType === WeatherType.STRONG_WINDS) || !globalScene.arena.weather?.isImmutable(); + return weatherReplaceable && globalScene.arena.canSetWeather(this.weatherType); + } - return false; + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + globalScene.arena.trySetWeather(this.weatherType, true); + } } } @@ -2471,11 +2497,13 @@ export class PostSummonTerrainChangeAbAttr extends PostSummonAbAttr { this.terrainType = terrainType; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (simulated) { - return globalScene.arena.terrain?.terrainType !== this.terrainType; - } else { - return globalScene.arena.trySetTerrain(this.terrainType, true); + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return globalScene.arena.canSetTerrain(this.terrainType); + } + + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + globalScene.arena.trySetTerrain(this.terrainType, true); } } } @@ -2489,13 +2517,14 @@ export class PostSummonFormChangeAbAttr extends PostSummonAbAttr { this.formFunc = formFunc; } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - const formIndex = this.formFunc(pokemon); - if (formIndex !== pokemon.formIndex) { - return simulated || globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); - } + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return this.formFunc(pokemon) !== pokemon.formIndex; + } - return false; + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); + } } } @@ -2504,7 +2533,7 @@ export class PostSummonCopyAbilityAbAttr extends PostSummonAbAttr { private target: Pokemon; private targetAbilityName: string; - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { const targets = pokemon.getOpponents(); if (!targets.length) { return false; @@ -2525,15 +2554,17 @@ export class PostSummonCopyAbilityAbAttr extends PostSummonAbAttr { return false; } + this.target = target!; + this.targetAbilityName = allAbilities[target!.getAbility().id].name; + return true; + } + + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { if (!simulated) { - this.target = target!; - this.targetAbilityName = allAbilities[target!.getAbility().id].name; - pokemon.setTempAbility(target!.getAbility()); - setAbilityRevealed(target!); + pokemon.setTempAbility(this.target!.getAbility()); + setAbilityRevealed(this.target!); pokemon.updateInfo(); } - - return true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -2560,22 +2591,22 @@ export class PostSummonUserFieldRemoveStatusEffectAbAttr extends PostSummonAbAtt this.statusEffect = statusEffect; } + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + const party = pokemon instanceof PlayerPokemon ? globalScene.getPlayerField() : globalScene.getEnemyField(); + return party.filter(p => p.isAllowedInBattle()).length > 0; + } + /** * Removes supplied status effect from the user's field when user of the ability is summoned. * * @param pokemon - The Pokémon that triggered the ability. * @param passive - n/a * @param args - n/a - * @returns A boolean that resolves to a boolean indicating the result of the ability application. */ - override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { const party = pokemon instanceof PlayerPokemon ? globalScene.getPlayerField() : globalScene.getEnemyField(); const allowedParty = party.filter(p => p.isAllowedInBattle()); - if (allowedParty.length < 1) { - return false; - } - if (!simulated) { for (const pokemon of allowedParty) { if (pokemon.status && this.statusEffect.includes(pokemon.status.effect)) { @@ -2585,14 +2616,13 @@ export class PostSummonUserFieldRemoveStatusEffectAbAttr extends PostSummonAbAtt } } } - return true; } } /** Attempt to copy the stat changes on an ally pokemon */ export class PostSummonCopyAllyStatsAbAttr extends PostSummonAbAttr { - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { if (!globalScene.currentBattle.double) { return false; } @@ -2602,14 +2632,17 @@ export class PostSummonCopyAllyStatsAbAttr extends PostSummonAbAttr { return false; } + return true; + } + + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + const ally = pokemon.getAlly(); if (!simulated) { for (const s of BATTLE_STATS) { pokemon.setStatStage(s, ally.getStatStage(s)); } pokemon.updateInfo(); } - - return true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -2628,12 +2661,7 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr { super(true, false); } - override applyPostSummon(pokemon: Pokemon, _passive: boolean, simulated: boolean, _args: any[]): boolean { - const targets = pokemon.getOpponents(); - if (simulated || !targets.length) { - return simulated; - } - + private getTarget(targets: Pokemon[]): Pokemon { let target: Pokemon; if (targets.length > 1) { globalScene.executeWithSeedOffset(() => { @@ -2653,21 +2681,28 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr { } target = target!; + return target; + } + + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + const targets = pokemon.getOpponents(); + if (simulated || !targets.length) { + return simulated; + } + // transforming from or into fusion pokemon causes various problems (including crashes and save corruption) - if (target.fusionSpecies || pokemon.fusionSpecies) { + if (this.getTarget(targets).fusionSpecies || pokemon.fusionSpecies) { return false; } + return true; + } + + override applyPostSummon(pokemon: Pokemon, _passive: boolean, simulated: boolean, _args: any[]): void { + const target = this.getTarget(pokemon.getOpponents()); + globalScene.unshiftPhase(new PokemonTransformPhase(pokemon.getBattlerIndex(), target.getBattlerIndex(), true)); - globalScene.queueMessage( - i18next.t("abilityTriggers:postSummonTransform", { - pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - targetName: target.name, - }), - ); - - return true; } } @@ -2677,25 +2712,20 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr { * @extends PostSummonAbAttr */ export class PostSummonWeatherSuppressedFormChangeAbAttr extends PostSummonAbAttr { + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return getPokemonWithWeatherBasedForms().length > 0; + } + /** * Triggers {@linkcode Arena.triggerWeatherBasedFormChangesToNormal | triggerWeatherBasedFormChangesToNormal} * @param {Pokemon} pokemon the Pokemon with this ability * @param passive n/a * @param args n/a - * @returns whether a Pokemon was reverted to its normal form */ - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]) { - const pokemonToTransform = getPokemonWithWeatherBasedForms(); - - if (pokemonToTransform.length < 1) { - return false; - } - + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { if (!simulated) { globalScene.arena.triggerWeatherBasedFormChangesToNormal(); } - - return true; } } @@ -2713,6 +2743,12 @@ export class PostSummonFormChangeByWeatherAbAttr extends PostSummonAbAttr { this.ability = ability; } + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + const isCastformWithForecast = (pokemon.species.speciesId === Species.CASTFORM && this.ability === Abilities.FORECAST); + const isCherrimWithFlowerGift = (pokemon.species.speciesId === Species.CHERRIM && this.ability === Abilities.FLOWER_GIFT); + return isCastformWithForecast || isCherrimWithFlowerGift; + } + /** * Calls the {@linkcode BattleScene.triggerPokemonFormChange | triggerPokemonFormChange} for both * {@linkcode SpeciesFormChange.SpeciesFormChangeWeatherTrigger | SpeciesFormChangeWeatherTrigger} and @@ -2721,23 +2757,13 @@ export class PostSummonFormChangeByWeatherAbAttr extends PostSummonAbAttr { * @param {Pokemon} pokemon the Pokemon with this ability * @param passive n/a * @param args n/a - * @returns whether the form change was triggered */ - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - const isCastformWithForecast = (pokemon.species.speciesId === Species.CASTFORM && this.ability === Abilities.FORECAST); - const isCherrimWithFlowerGift = (pokemon.species.speciesId === Species.CHERRIM && this.ability === Abilities.FLOWER_GIFT); - - if (isCastformWithForecast || isCherrimWithFlowerGift) { - if (simulated) { - return simulated; - } - + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeWeatherTrigger); globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeRevertWeatherFormTrigger); - queueShowAbility(pokemon, passive); - return true; + globalScene.queueAbilityDisplay(pokemon, passive, true); } - return false; } } @@ -2752,53 +2778,55 @@ export class CommanderAbAttr extends AbAttr { super(true); } - override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: null, args: any[]): boolean { - // TODO: Should this work with X + Dondozo fusions? - if (globalScene.currentBattle?.double && pokemon.getAlly()?.species.speciesId === Species.DONDOZO) { - // If the ally Dondozo is fainted or was previously "commanded" by - // another Pokemon, this effect cannot apply. - if (pokemon.getAlly().isFainted() || pokemon.getAlly().getTag(BattlerTagType.COMMANDED)) { - return false; - } + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + // If the ally Dondozo is fainted or was previously "commanded" by + // another Pokemon, this effect cannot apply. - if (!simulated) { - // Lapse the source's semi-invulnerable tags (to avoid visual inconsistencies) - pokemon.lapseTags(BattlerTagLapseType.MOVE_EFFECT); - // Play an animation of the source jumping into the ally Dondozo's mouth - globalScene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.COMMANDER_APPLY); - // Apply boosts from this effect to the ally Dondozo - pokemon.getAlly().addTag(BattlerTagType.COMMANDED, 0, Moves.NONE, pokemon.id); - // Cancel the source Pokemon's next move (if a move is queued) - globalScene.tryRemovePhase((phase) => phase instanceof MovePhase && phase.pokemon === pokemon); - } - return true; + // TODO: Should this work with X + Dondozo fusions? + return !(pokemon.getAlly().isFainted() || pokemon.getAlly().getTag(BattlerTagType.COMMANDED)) + && globalScene.currentBattle?.double && pokemon.getAlly()?.species.speciesId === Species.DONDOZO; + } + + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: null, args: any[]): void { + if (!simulated) { + // Lapse the source's semi-invulnerable tags (to avoid visual inconsistencies) + pokemon.lapseTags(BattlerTagLapseType.MOVE_EFFECT); + // Play an animation of the source jumping into the ally Dondozo's mouth + globalScene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.COMMANDER_APPLY); + // Apply boosts from this effect to the ally Dondozo + pokemon.getAlly().addTag(BattlerTagType.COMMANDED, 0, Moves.NONE, pokemon.id); + // Cancel the source Pokemon's next move (if a move is queued) + globalScene.tryRemovePhase((phase) => phase instanceof MovePhase && phase.pokemon === pokemon); } - return false; } } export class PreSwitchOutAbAttr extends AbAttr { - constructor() { - super(true); + constructor(showAbility: boolean = true) { + super(showAbility); } - applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - return false; + canApplyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return true; } + + applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {} } export class PreSwitchOutResetStatusAbAttr extends PreSwitchOutAbAttr { - override applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (pokemon.status) { - if (!simulated) { - pokemon.resetStatus(); - pokemon.updateInfo(); - } + constructor() { + super(false); + } - return true; + override canApplyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return !Utils.isNullOrUndefined(pokemon.status); + } + + override applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + pokemon.resetStatus(); + pokemon.updateInfo(); } - - return false; } } @@ -2867,18 +2895,16 @@ export class PreSwitchOutClearWeatherAbAttr extends PreSwitchOutAbAttr { } export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr { - override applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (!pokemon.isFullHp()) { - if (!simulated) { - const healAmount = Utils.toDmgValue(pokemon.getMaxHp() * 0.33); - pokemon.heal(healAmount); - pokemon.updateInfo(); - } + override canApplyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return !pokemon.isFullHp(); + } - return true; + override applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + const healAmount = Utils.toDmgValue(pokemon.getMaxHp() * 0.33); + pokemon.heal(healAmount); + pokemon.updateInfo(); } - - return false; } } @@ -2896,80 +2922,73 @@ export class PreSwitchOutFormChangeAbAttr extends PreSwitchOutAbAttr { this.formFunc = formFunc; } + override canApplyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return this.formFunc(pokemon) !== pokemon.formIndex; + } + /** * On switch out, trigger the form change to the one defined in the ability * @param pokemon The pokemon switching out and changing form {@linkcode Pokemon} * @param passive N/A * @param args N/A - * @returns true if the form change was successful */ - override applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - const formIndex = this.formFunc(pokemon); - if (formIndex !== pokemon.formIndex) { - if (!simulated) { - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); - } - return true; + override applyPreSwitchOut(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); } - - return false; } } export class PreLeaveFieldAbAttr extends AbAttr { - applyPreLeaveField(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - return false; + canApplyPreLeaveField(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return true; } + + applyPreLeaveField(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {} } /** * Clears Desolate Land/Primordial Sea/Delta Stream upon the Pokemon switching out. */ export class PreLeaveFieldClearWeatherAbAttr extends PreLeaveFieldAbAttr { - /** - * @param pokemon The {@linkcode Pokemon} with the ability - * @param passive N/A - * @param args N/A - * @returns Returns `true` if the weather clears, otherwise `false`. - */ - applyPreLeaveField(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - const weatherType = globalScene.arena.weather?.weatherType; - let turnOffWeather = false; + override canApplyPreLeaveField(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + const weatherType = globalScene.arena.weather?.weatherType; // Clear weather only if user's ability matches the weather and no other pokemon has the ability. switch (weatherType) { case (WeatherType.HARSH_SUN): if (pokemon.hasAbility(Abilities.DESOLATE_LAND) && globalScene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) { - turnOffWeather = true; + return true; } break; case (WeatherType.HEAVY_RAIN): if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA) && globalScene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) { - turnOffWeather = true; + return true; } break; case (WeatherType.STRONG_WINDS): if (pokemon.hasAbility(Abilities.DELTA_STREAM) && globalScene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) { - turnOffWeather = true; + return true; } break; } - - if (simulated) { - return turnOffWeather; - } - - if (turnOffWeather) { - globalScene.arena.trySetWeather(WeatherType.NONE, false); - return true; - } - return false; } + + /** + * @param pokemon The {@linkcode Pokemon} with the ability + * @param passive N/A + * @param args N/A + */ + override applyPreLeaveField(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + globalScene.arena.trySetWeather(WeatherType.NONE, false); + } + } } /** @@ -2980,19 +2999,27 @@ export class PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr extends PreLeaveFi super(false); } - public override applyPreLeaveField(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (!simulated) { - const suppressTag = globalScene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS) as SuppressAbilitiesTag; - if (suppressTag) { - suppressTag.onSourceLeave(globalScene.arena); - return true; - } - } - return simulated; + public override canApplyPreLeaveField(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return !!globalScene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS); + } + + public override applyPreLeaveField(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + const suppressTag = globalScene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS) as SuppressAbilitiesTag; + suppressTag.onSourceLeave(globalScene.arena); } } export class PreStatStageChangeAbAttr extends AbAttr { + canApplyPreStatStageChange( + pokemon: Pokemon | null, + passive: boolean, + simulated: boolean, + stat: BattleStat, + cancelled: Utils.BooleanHolder, + args: any[]): boolean { + return true; + } + applyPreStatStageChange( pokemon: Pokemon | null, passive: boolean, @@ -3000,9 +3027,7 @@ export class PreStatStageChangeAbAttr extends AbAttr { stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[], - ): boolean { - return false; - } + ): void {} } /** @@ -3021,9 +3046,8 @@ export class ReflectStatStageChangeAbAttr extends PreStatStageChangeAbAttr { * @param stat the {@linkcode BattleStat} being affected * @param cancelled The {@linkcode Utils.BooleanHolder} that will be set to true due to reflection * @param args - * @returns true because it reflects any stat being lowered */ - applyPreStatStageChange(_pokemon: Pokemon, _passive: boolean, simulated: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override applyPreStatStageChange(_pokemon: Pokemon, _passive: boolean, simulated: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): void { const attacker: Pokemon = args[0]; const stages = args[1]; this.reflectedStat = stat; @@ -3031,7 +3055,6 @@ export class ReflectStatStageChangeAbAttr extends PreStatStageChangeAbAttr { globalScene.unshiftPhase(new StatStageChangePhase(attacker.getBattlerIndex(), false, [ stat ], stages, true, false, true, null, true)); } cancelled.value = true; - return true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { @@ -3056,6 +3079,10 @@ export class ProtectStatAbAttr extends PreStatStageChangeAbAttr { this.protectedStat = protectedStat; } + override canApplyPreStatStageChange(pokemon: Pokemon | null, passive: boolean, simulated: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { + return Utils.isNullOrUndefined(this.protectedStat) || stat === this.protectedStat; + } + /** * Apply the {@linkcode ProtectedStatAbAttr} to an interaction * @param _pokemon @@ -3064,15 +3091,9 @@ export class ProtectStatAbAttr extends PreStatStageChangeAbAttr { * @param stat the {@linkcode BattleStat} being affected * @param cancelled The {@linkcode Utils.BooleanHolder} that will be set to true if the stat is protected * @param _args - * @returns true if the stat is protected, false otherwise */ - applyPreStatStageChange(_pokemon: Pokemon, _passive: boolean, _simulated: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, _args: any[]): boolean { - if (Utils.isNullOrUndefined(this.protectedStat) || stat === this.protectedStat) { - cancelled.value = true; - return true; - } - - return false; + override applyPreStatStageChange(_pokemon: Pokemon, _passive: boolean, _simulated: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, _args: any[]): void { + cancelled.value = true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { @@ -3100,6 +3121,13 @@ export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr { super((user, target, move) => true); this.effects = effects; } + + override canApplyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean { + return super.canApplyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args) + && this.effects.indexOf(args[0]) > -1 && !defender.isFainted() && defender.canAddTag(BattlerTagType.CONFUSED); + } + + /** * Applies confusion to the target pokemon. * @param pokemon {@link Pokemon} attacking @@ -3108,21 +3136,25 @@ export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr { * @param move {@link Move} used to apply status effect and confusion * @param hitResult N/A * @param args [0] {@linkcode StatusEffect} applied by move - * @returns true if defender is confused */ - applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (this.effects.indexOf(args[0]) > -1 && !defender.isFainted()) { - if (simulated) { - return defender.canAddTag(BattlerTagType.CONFUSED); - } else { - return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedIntRange(2, 5), move.id, defender.id); - } + override applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): void { + if (!simulated) { + defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedIntRange(2, 5), move.id, defender.id); } - return false; } } export class PreSetStatusAbAttr extends AbAttr { + canApplyPreSetStatus( + pokemon: Pokemon, + passive: boolean, + simulated: boolean, + effect: StatusEffect | undefined, + cancelled: Utils.BooleanHolder, + args: any[]): boolean { + return true; + } + applyPreSetStatus( pokemon: Pokemon, passive: boolean, @@ -3130,9 +3162,7 @@ export class PreSetStatusAbAttr extends AbAttr { effect: StatusEffect | undefined, cancelled: Utils.BooleanHolder, args: any[], - ): boolean { - return false; - } + ): void {} } /** @@ -3150,6 +3180,10 @@ export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { this.immuneEffects = immuneEffects; } + override canApplyPreSetStatus(pokemon: Pokemon, passive: boolean, simulated: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { + return effect !== StatusEffect.FAINT && this.immuneEffects.length < 1 || this.immuneEffects.includes(effect); + } + /** * Applies immunity to supplied status effects. * @@ -3158,15 +3192,9 @@ export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { * @param effect - The status effect being applied. * @param cancelled - A holder for a boolean value indicating if the status application was cancelled. * @param args - n/a - * @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 (effect !== StatusEffect.FAINT && this.immuneEffects.length < 1 || this.immuneEffects.includes(effect)) { - cancelled.value = true; - return true; - } - - return false; + override applyPreSetStatus(pokemon: Pokemon, passive: boolean, simulated: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -3196,7 +3224,7 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusEffectImmunityAbAttr export class UserFieldStatusEffectImmunityAbAttr extends PreSetStatusEffectImmunityAbAttr { } export class PreApplyBattlerTagAbAttr extends AbAttr { - applyPreApplyBattlerTag( + canApplyPreApplyBattlerTag( pokemon: Pokemon, passive: boolean, simulated: boolean, @@ -3204,8 +3232,17 @@ export class PreApplyBattlerTagAbAttr extends AbAttr { cancelled: Utils.BooleanHolder, args: any[], ): boolean { - return false; + return true; } + + applyPreApplyBattlerTag( + pokemon: Pokemon, + passive: boolean, + simulated: boolean, + tag: BattlerTag, + cancelled: Utils.BooleanHolder, + args: any[], + ): void {} } /** @@ -3216,21 +3253,19 @@ export class PreApplyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { private battlerTag: BattlerTag; constructor(immuneTagTypes: BattlerTagType | BattlerTagType[]) { - super(); + super(true); this.immuneTagTypes = Array.isArray(immuneTagTypes) ? immuneTagTypes : [ immuneTagTypes ]; } - applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, simulated: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.immuneTagTypes.includes(tag.tagType)) { - cancelled.value = true; - if (!simulated) { - this.battlerTag = tag; - } - return true; - } + override canApplyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, simulated: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { + this.battlerTag = tag; - return false; + return this.immuneTagTypes.includes(tag.tagType); + } + + override applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, simulated: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -3255,16 +3290,21 @@ export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagImmunityAbAttr { export class UserFieldBattlerTagImmunityAbAttr extends PreApplyBattlerTagImmunityAbAttr { } export class BlockCritAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + constructor() { + super(false); + } + + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { (args[0] as Utils.BooleanHolder).value = true; - return true; } } export class BonusCritAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + constructor() { + super(false); + } + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { (args[0] as Utils.BooleanHolder).value = true; - return true; } } @@ -3272,19 +3312,19 @@ export class MultCritAbAttr extends AbAttr { public multAmount: number; constructor(multAmount: number) { - super(true); + super(false); this.multAmount = multAmount; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { const critMult = args[0] as Utils.NumberHolder; - if (critMult.value > 1) { - critMult.value *= this.multAmount; - return true; - } + return critMult.value > 1; + } - return false; + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + const critMult = args[0] as Utils.NumberHolder; + critMult.value *= this.multAmount; } } @@ -3297,33 +3337,35 @@ export class ConditionalCritAbAttr extends AbAttr { private condition: PokemonAttackCondition; constructor(condition: PokemonAttackCondition, checkUser?: boolean) { - super(); + super(false); this.condition = condition; } + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + const target = (args[1] as Pokemon); + const move = (args[2] as Move); + return this.condition(pokemon, target, move); + } + /** * @param pokemon {@linkcode Pokemon} user. * @param args [0] {@linkcode Utils.BooleanHolder} If true critical hit is guaranteed. * [1] {@linkcode Pokemon} Target. * [2] {@linkcode Move} used by ability user. */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - const target = (args[1] as Pokemon); - const move = (args[2] as Move); - if (!this.condition(pokemon, target, move)) { - return false; - } - + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { (args[0] as Utils.BooleanHolder).value = true; - return true; } } export class BlockNonDirectDamageAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + constructor() { + super(false); + } + + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { cancelled.value = true; - return true; } } @@ -3342,26 +3384,27 @@ export class BlockStatusDamageAbAttr extends AbAttr { this.effects = effects; } + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + if (pokemon.status && this.effects.includes(pokemon.status.effect)) { + return true; + } + return false; + } + /** * @param {Pokemon} pokemon The pokemon with the ability * @param {boolean} passive N/A * @param {Utils.BooleanHolder} cancelled Whether to cancel the status damage * @param {any[]} args N/A - * @returns Returns true if status damage is blocked */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (pokemon.status && this.effects.includes(pokemon.status.effect)) { - cancelled.value = true; - return true; - } - return false; + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; } } export class BlockOneHitKOAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { cancelled.value = true; - return true; } } @@ -3379,25 +3422,34 @@ export class ChangeMovePriorityAbAttr extends AbAttr { * @param {number} changeAmount the amount of priority added or subtracted */ constructor(moveFunc: (pokemon: Pokemon, move: Move) => boolean, changeAmount: number) { - super(true); + super(false); this.moveFunc = moveFunc; this.changeAmount = changeAmount; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (!this.moveFunc(pokemon, args[0] as Move)) { - return false; - } + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return this.moveFunc(pokemon, args[0] as Move); + } + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { (args[1] as Utils.NumberHolder).value += this.changeAmount; - return true; } } export class IgnoreContactAbAttr extends AbAttr { } export class PreWeatherEffectAbAttr extends AbAttr { + canApplyPreWeatherEffect( + pokemon: Pokemon, + passive: Boolean, + simulated: boolean, + weather: Weather | null, + cancelled: Utils.BooleanHolder, + args: any[]): boolean { + return true; + } + applyPreWeatherEffect( pokemon: Pokemon, passive: boolean, @@ -3405,9 +3457,7 @@ export class PreWeatherEffectAbAttr extends AbAttr { weather: Weather | null, cancelled: Utils.BooleanHolder, args: any[], - ): boolean { - return false; - } + ): void {} } export class PreWeatherDamageAbAttr extends PreWeatherEffectAbAttr { } @@ -3416,17 +3466,17 @@ export class BlockWeatherDamageAttr extends PreWeatherDamageAbAttr { private weatherTypes: WeatherType[]; constructor(...weatherTypes: WeatherType[]) { - super(); + super(false); this.weatherTypes = weatherTypes; } - applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (!this.weatherTypes.length || this.weatherTypes.indexOf(weather?.weatherType) > -1) { - cancelled.value = true; - } + override canApplyPreWeatherEffect(pokemon: Pokemon, passive: Boolean, simulated: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { + return !this.weatherTypes.length || this.weatherTypes.indexOf(weather?.weatherType) > -1; + } - return true; + override applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; } } @@ -3434,18 +3484,17 @@ export class SuppressWeatherEffectAbAttr extends PreWeatherEffectAbAttr { public affectsImmutable: boolean; constructor(affectsImmutable?: boolean) { - super(); + super(true); this.affectsImmutable = !!affectsImmutable; } - applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.affectsImmutable || weather.isImmutable()) { - cancelled.value = true; - return true; - } + override canApplyPreWeatherEffect(pokemon: Pokemon, passive: Boolean, simulated: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean { + return this.affectsImmutable || weather.isImmutable(); + } - return false; + override applyPreWeatherEffect(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; } } @@ -3550,7 +3599,7 @@ export class ForewarnAbAttr extends PostSummonAbAttr { super(true); } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { let maxPowerSeen = 0; let maxMove = ""; let movePower = 0; @@ -3577,7 +3626,6 @@ export class ForewarnAbAttr extends PostSummonAbAttr { if (!simulated) { globalScene.queueMessage(i18next.t("abilityTriggers:forewarn", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: maxMove })); } - return true; } } @@ -3586,21 +3634,22 @@ export class FriskAbAttr extends PostSummonAbAttr { super(true); } - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { if (!simulated) { for (const opponent of pokemon.getOpponents()) { globalScene.queueMessage(i18next.t("abilityTriggers:frisk", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), opponentName: opponent.name, opponentAbilityName: opponent.getAbility().name })); setAbilityRevealed(opponent); } } - return true; } } export class PostWeatherChangeAbAttr extends AbAttr { - applyPostWeatherChange(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: WeatherType, args: any[]): boolean { - return false; + canApplyPostWeatherChange(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: WeatherType, args: any[]): boolean { + return true; } + + applyPostWeatherChange(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: WeatherType, args: any[]): void {} } /** @@ -3619,6 +3668,13 @@ export class PostWeatherChangeFormChangeAbAttr extends PostWeatherChangeAbAttr { this.formRevertingWeathers = formRevertingWeathers; } + override canApplyPostWeatherChange(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: WeatherType, args: any[]): boolean { + const isCastformWithForecast = (pokemon.species.speciesId === Species.CASTFORM && this.ability === Abilities.FORECAST); + const isCherrimWithFlowerGift = (pokemon.species.speciesId === Species.CHERRIM && this.ability === Abilities.FLOWER_GIFT); + + return isCastformWithForecast || isCherrimWithFlowerGift; + } + /** * Calls {@linkcode Arena.triggerWeatherBasedFormChangesToNormal | triggerWeatherBasedFormChangesToNormal} when the * weather changed to form-reverting weather, otherwise calls {@linkcode Arena.triggerWeatherBasedFormChanges | triggerWeatherBasedFormChanges} @@ -3626,27 +3682,19 @@ export class PostWeatherChangeFormChangeAbAttr extends PostWeatherChangeAbAttr { * @param passive n/a * @param weather n/a * @param args n/a - * @returns whether the form change was triggered */ - applyPostWeatherChange(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: WeatherType, args: any[]): boolean { - const isCastformWithForecast = (pokemon.species.speciesId === Species.CASTFORM && this.ability === Abilities.FORECAST); - const isCherrimWithFlowerGift = (pokemon.species.speciesId === Species.CHERRIM && this.ability === Abilities.FLOWER_GIFT); - - if (isCastformWithForecast || isCherrimWithFlowerGift) { - if (simulated) { - return simulated; - } - - const weatherType = globalScene.arena.weather?.weatherType; - - if (weatherType && this.formRevertingWeathers.includes(weatherType)) { - globalScene.arena.triggerWeatherBasedFormChangesToNormal(); - } else { - globalScene.arena.triggerWeatherBasedFormChanges(); - } - return true; + override applyPostWeatherChange(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: WeatherType, args: any[]): void { + if (simulated) { + return; + } + + const weatherType = globalScene.arena.weather?.weatherType; + + if (weatherType && this.formRevertingWeathers.includes(weatherType)) { + globalScene.arena.triggerWeatherBasedFormChangesToNormal(); + } else { + globalScene.arena.triggerWeatherBasedFormChanges(); } - return false; } } @@ -3663,16 +3711,13 @@ export class PostWeatherChangeAddBattlerTagAttr extends PostWeatherChangeAbAttr this.weatherTypes = weatherTypes; } - applyPostWeatherChange(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: WeatherType, args: any[]): boolean { - console.log(this.weatherTypes.find(w => weather === w), WeatherType[weather]); - if (!this.weatherTypes.find(w => weather === w)) { - return false; - } + override canApplyPostWeatherChange(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: WeatherType, args: any[]): boolean { + return !!this.weatherTypes.find(w => weather === w) && pokemon.canAddTag(this.tagType); + } - if (simulated) { - return pokemon.canAddTag(this.tagType); - } else { - return pokemon.addTag(this.tagType, this.turnCount); + override applyPostWeatherChange(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: WeatherType, args: any[]): void { + if (!simulated) { + pokemon.addTag(this.tagType, this.turnCount); } } } @@ -3686,15 +3731,22 @@ export class PostWeatherLapseAbAttr extends AbAttr { this.weatherTypes = weatherTypes; } + canApplyPostWeatherLapse( + pokemon: Pokemon, + passive: boolean, + simulated: boolean, + weather: Weather | null, + args: any[]): boolean { + return true; + } + applyPostWeatherLapse( pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather | null, args: any[], - ): boolean { - return false; - } + ): void {} getCondition(): AbAttrCondition { return getWeatherCondition(...this.weatherTypes); @@ -3710,17 +3762,16 @@ export class PostWeatherLapseHealAbAttr extends PostWeatherLapseAbAttr { this.healFactor = healFactor; } - applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, args: any[]): boolean { - if (!pokemon.isFullHp()) { - const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; - if (!simulated) { - globalScene.unshiftPhase(new PokemonHealPhase(pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / (16 / this.healFactor)), i18next.t("abilityTriggers:postWeatherLapseHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); - } - return true; - } + override canApplyPostWeatherLapse(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather | null, args: any[]): boolean { + return !pokemon.isFullHp(); + } - return false; + override applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, args: any[]): void { + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; + if (!simulated) { + globalScene.unshiftPhase(new PokemonHealPhase(pokemon.getBattlerIndex(), + Utils.toDmgValue(pokemon.getMaxHp() / (16 / this.healFactor)), i18next.t("abilityTriggers:postWeatherLapseHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); + } } } @@ -3733,25 +3784,25 @@ export class PostWeatherLapseDamageAbAttr extends PostWeatherLapseAbAttr { this.damageFactor = damageFactor; } - applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, args: any[]): boolean { - if (pokemon.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { - return false; - } + override canApplyPostWeatherLapse(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather | null, args: any[]): boolean { + return !pokemon.hasAbilityWithAttr(BlockNonDirectDamageAbAttr); + } + override applyPostWeatherLapse(pokemon: Pokemon, passive: boolean, simulated: boolean, weather: Weather, args: any[]): void { if (!simulated) { const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; globalScene.queueMessage(i18next.t("abilityTriggers:postWeatherLapseDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName })); pokemon.damageAndUpdate(Utils.toDmgValue(pokemon.getMaxHp() / (16 / this.damageFactor)), HitResult.OTHER); } - - return true; } } export class PostTerrainChangeAbAttr extends AbAttr { - applyPostTerrainChange(pokemon: Pokemon, passive: boolean, simulated: boolean, terrain: TerrainType, args: any[]): boolean { - return false; + canApplyPostTerrainChange(pokemon: Pokemon, passive: boolean, simulated: boolean, terrain: TerrainType, args: any[]): boolean { + return true; } + + applyPostTerrainChange(pokemon: Pokemon, passive: boolean, simulated: boolean, terrain: TerrainType, args: any[]): void {} } export class PostTerrainChangeAddBattlerTagAttr extends PostTerrainChangeAbAttr { @@ -3767,15 +3818,13 @@ export class PostTerrainChangeAddBattlerTagAttr extends PostTerrainChangeAbAttr this.terrainTypes = terrainTypes; } - applyPostTerrainChange(pokemon: Pokemon, passive: boolean, simulated: boolean, terrain: TerrainType, args: any[]): boolean { - if (!this.terrainTypes.find(t => t === terrain)) { - return false; - } + override canApplyPostTerrainChange(pokemon: Pokemon, passive: boolean, simulated: boolean, terrain: TerrainType, args: any[]): boolean { + return !!this.terrainTypes.find(t => t === terrain) && pokemon.canAddTag(this.tagType); + } - if (simulated) { - return pokemon.canAddTag(this.tagType); - } else { - return pokemon.addTag(this.tagType, this.turnCount); + override applyPostTerrainChange(pokemon: Pokemon, passive: boolean, simulated: boolean, terrain: TerrainType, args: any[]): void { + if (!simulated) { + pokemon.addTag(this.tagType, this.turnCount); } } } @@ -3788,9 +3837,11 @@ function getTerrainCondition(...terrainTypes: TerrainType[]): AbAttrCondition { } export class PostTurnAbAttr extends AbAttr { - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - return false; + canApplyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return true; } + + applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {} } /** @@ -3808,24 +3859,21 @@ export class PostTurnStatusHealAbAttr extends PostTurnAbAttr { this.effects = effects; } + override canApplyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return (pokemon.status !== null) && this.effects.includes(pokemon.status.effect) && !pokemon.isFullHp(); + } + /** * @param {Pokemon} pokemon The pokemon with the ability that will receive the healing * @param {Boolean} passive N/A * @param {any[]} args N/A - * @returns Returns true if healed from status, false if not */ - override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (pokemon.status && this.effects.includes(pokemon.status.effect)) { - if (!pokemon.isFullHp()) { - if (!simulated) { - const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; - globalScene.unshiftPhase(new PokemonHealPhase(pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / 8), i18next.t("abilityTriggers:poisonHeal", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName }), true)); - } - return true; - } + override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; + globalScene.unshiftPhase(new PokemonHealPhase(pokemon.getBattlerIndex(), + Utils.toDmgValue(pokemon.getMaxHp() / 8), i18next.t("abilityTriggers:poisonHeal", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName }), true)); } - return false; } } @@ -3842,23 +3890,21 @@ export class PostTurnResetStatusAbAttr extends PostTurnAbAttr { this.allyTarget = allyTarget; } - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override canApplyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { if (this.allyTarget) { this.target = pokemon.getAlly(); } else { this.target = pokemon; } - if (this.target?.status) { - if (!simulated) { - globalScene.queueMessage(getStatusEffectHealText(this.target.status?.effect, getPokemonNameWithAffix(this.target))); - this.target.resetStatus(false); - this.target.updateInfo(); - } + return !Utils.isNullOrUndefined(this.target.status); + } - return true; + override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated && this.target.status) { + globalScene.queueMessage(getStatusEffectHealText(this.target.status?.effect, getPokemonNameWithAffix(this.target))); + this.target.resetStatus(false); + this.target.updateInfo(); } - - return false; } } @@ -3879,18 +3925,14 @@ export class PostTurnLootAbAttr extends PostTurnAbAttr { super(); } - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - const pass = Phaser.Math.RND.realInRange(0, 1); + override canApplyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { // Clamp procChance to [0, 1]. Skip if didn't proc (less than pass) - if (Math.max(Math.min(this.procChance(pokemon), 1), 0) < pass) { - return false; - } + const pass = Phaser.Math.RND.realInRange(0, 1); + return !(Math.max(Math.min(this.procChance(pokemon), 1), 0) < pass) && this.itemType === "EATEN_BERRIES" && !!pokemon.battleData.berriesEaten; + } - if (this.itemType === "EATEN_BERRIES") { - return this.createEatenBerry(pokemon, simulated); - } else { - return false; - } + override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + this.createEatenBerry(pokemon, simulated); } /** @@ -3951,13 +3993,12 @@ export class MoodyAbAttr extends PostTurnAbAttr { * @param passive N/A * @param simulated true if applying in a simulated call. * @param args N/A - * @returns true * * Any stat stages at +6 or -6 are excluded from being increased or decreased, respectively * If the pokemon already has all stat stages raised to 6, it will only decrease one stat stage by 1 * If the pokemon already has all stat stages lowered to -6, it will only increase one stat stage by 2 */ - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { const canRaise = EFFECTIVE_STATS.filter(s => pokemon.getStatStage(s) < 6); let canLower = EFFECTIVE_STATS.filter(s => pokemon.getStatStage(s) > -6); @@ -3972,8 +4013,6 @@ export class MoodyAbAttr extends PostTurnAbAttr { globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ loweredStat ], -1)); } } - - return true; } } @@ -3983,31 +4022,26 @@ export class SpeedBoostAbAttr extends PostTurnAbAttr { super(true); } - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (!simulated) { - if (!pokemon.turnData.switchedInThisTurn && !pokemon.turnData.failedRunAway) { - globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ Stat.SPD ], 1)); - } else { - return false; - } - } - return true; + override canApplyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return simulated || (!pokemon.turnData.switchedInThisTurn && !pokemon.turnData.failedRunAway); + } + + override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, [ Stat.SPD ], 1)); } } export class PostTurnHealAbAttr extends PostTurnAbAttr { - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (!pokemon.isFullHp()) { - if (!simulated) { - const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; - globalScene.unshiftPhase(new PokemonHealPhase(pokemon.getBattlerIndex(), - Utils.toDmgValue(pokemon.getMaxHp() / 16), i18next.t("abilityTriggers:postTurnHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); - } + override canApplyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return !pokemon.isFullHp(); + } - return true; + override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; + globalScene.unshiftPhase(new PokemonHealPhase(pokemon.getBattlerIndex(), + Utils.toDmgValue(pokemon.getMaxHp() / 16), i18next.t("abilityTriggers:postTurnHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true)); } - - return false; } } @@ -4020,17 +4054,14 @@ export class PostTurnFormChangeAbAttr extends PostTurnAbAttr { this.formFunc = formFunc; } - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - const formIndex = this.formFunc(pokemon); - if (formIndex !== pokemon.formIndex) { - if (!simulated) { - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); - } + override canApplyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return this.formFunc(pokemon) !== pokemon.formIndex; + } - return true; + override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + if (!simulated) { + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false); } - - return false; } } @@ -4039,28 +4070,25 @@ export class PostTurnFormChangeAbAttr extends PostTurnAbAttr { * Attribute used for abilities (Bad Dreams) that damages the opponents for being asleep */ export class PostTurnHurtIfSleepingAbAttr extends PostTurnAbAttr { - + override canApplyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return pokemon.getOpponents().some(opp => (opp.status?.effect === StatusEffect.SLEEP || opp.hasAbility(Abilities.COMATOSE)) && !opp.hasAbilityWithAttr(BlockNonDirectDamageAbAttr) && !opp.switchOutStatus); + } /** * Deals damage to all sleeping opponents equal to 1/8 of their max hp (min 1) * @param pokemon Pokemon that has this ability * @param passive N/A * @param simulated `true` if applying in a simulated call. * @param args N/A - * @returns `true` if any opponents are sleeping */ - override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - let hadEffect = false; + override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { for (const opp of pokemon.getOpponents()) { if ((opp.status?.effect === StatusEffect.SLEEP || opp.hasAbility(Abilities.COMATOSE)) && !opp.hasAbilityWithAttr(BlockNonDirectDamageAbAttr) && !opp.switchOutStatus) { if (!simulated) { opp.damageAndUpdate(Utils.toDmgValue(opp.getMaxHp() / 8), HitResult.OTHER); globalScene.queueMessage(i18next.t("abilityTriggers:badDreams", { pokemonName: getPokemonNameWithAffix(opp) })); } - hadEffect = true; } - } - return hadEffect; } } @@ -4073,25 +4101,22 @@ export class FetchBallAbAttr extends PostTurnAbAttr { constructor() { super(); } + + override canApplyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return !simulated && globalScene.currentBattle.lastUsedPokeball !== null && !!pokemon.isPlayer; + } + /** * Adds the last used Pokeball back into the player's inventory * @param pokemon {@linkcode Pokemon} with this ability * @param passive N/A * @param args N/A - * @returns true if player has used a pokeball and this pokemon is owned by the player */ - applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (simulated) { - return false; - } + override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { const lastUsed = globalScene.currentBattle.lastUsedPokeball; - if (lastUsed !== null && !!pokemon.isPlayer) { - globalScene.pokeballCounts[lastUsed]++; - globalScene.currentBattle.lastUsedPokeball = null; - globalScene.queueMessage(i18next.t("abilityTriggers:fetchBall", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), pokeballName: getPokeballName(lastUsed) })); - return true; - } - return false; + globalScene.pokeballCounts[lastUsed!]++; + globalScene.currentBattle.lastUsedPokeball = null; + globalScene.queueMessage(i18next.t("abilityTriggers:fetchBall", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), pokeballName: getPokeballName(lastUsed!) })); } } @@ -4106,16 +4131,14 @@ export class PostBiomeChangeWeatherChangeAbAttr extends PostBiomeChangeAbAttr { this.weatherType = weatherType; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (!globalScene.arena.weather?.isImmutable()) { - if (simulated) { - return globalScene.arena.weather?.weatherType !== this.weatherType; - } else { - return globalScene.arena.trySetWeather(this.weatherType, true); - } - } + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return ((globalScene.arena.weather?.isImmutable() ?? false) && globalScene.arena.canSetWeather(this.weatherType)); + } - return false; + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + if (!simulated) { + globalScene.arena.trySetWeather(this.weatherType, true); + } } } @@ -4128,11 +4151,13 @@ export class PostBiomeChangeTerrainChangeAbAttr extends PostBiomeChangeAbAttr { this.terrainType = terrainType; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (simulated) { - return globalScene.arena.terrain?.terrainType !== this.terrainType; - } else { - return globalScene.arena.trySetTerrain(this.terrainType, true); + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return globalScene.arena.canSetTerrain(this.terrainType); + } + + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + if (!simulated) { + globalScene.arena.trySetTerrain(this.terrainType, true); } } } @@ -4142,6 +4167,16 @@ export class PostBiomeChangeTerrainChangeAbAttr extends PostBiomeChangeAbAttr { * @extends AbAttr */ export class PostMoveUsedAbAttr extends AbAttr { + canApplyPostMoveUsed( + pokemon: Pokemon, + move: PokemonMove, + source: Pokemon, + targets: BattlerIndex[], + simulated: boolean, + args: any[]): boolean { + return true; + } + applyPostMoveUsed( pokemon: Pokemon, move: PokemonMove, @@ -4149,9 +4184,7 @@ export class PostMoveUsedAbAttr extends AbAttr { targets: BattlerIndex[], simulated: boolean, args: any[], - ): boolean { - return false; - } + ): void {} } /** @@ -4159,6 +4192,15 @@ export class PostMoveUsedAbAttr extends AbAttr { * @extends PostMoveUsedAbAttr */ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr { + override canApplyPostMoveUsed(dancer: Pokemon, move: PokemonMove, source: Pokemon, targets: BattlerIndex[], simulated: boolean, args: any[]): boolean { + // List of tags that prevent the Dancer from replicating the move + const forbiddenTags = [ BattlerTagType.FLYING, BattlerTagType.UNDERWATER, + BattlerTagType.UNDERGROUND, BattlerTagType.HIDDEN ]; + // The move to replicate cannot come from the Dancer + return source.getBattlerIndex() !== dancer.getBattlerIndex() + && !dancer.summonData.tags.some(tag => forbiddenTags.includes(tag.tagType)); + } + /** * Resolves the Dancer ability by replicating the move used by the source of the dance * either on the source itself or on the target of the dance @@ -4167,8 +4209,6 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr { * @param source {@linkcode Pokemon} that used the dancing move * @param targets {@linkcode BattlerIndex}Targets of the dancing move * @param args N/A - * - * @return true if the Dancer ability was resolved */ override applyPostMoveUsed( dancer: Pokemon, @@ -4176,27 +4216,17 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr { source: Pokemon, targets: BattlerIndex[], simulated: boolean, - args: any[], - ): boolean { - // List of tags that prevent the Dancer from replicating the move - const forbiddenTags = [ BattlerTagType.FLYING, BattlerTagType.UNDERWATER, - BattlerTagType.UNDERGROUND, BattlerTagType.HIDDEN ]; - // The move to replicate cannot come from the Dancer - if (source.getBattlerIndex() !== dancer.getBattlerIndex() - && !dancer.summonData.tags.some(tag => forbiddenTags.includes(tag.tagType))) { - if (!simulated) { - // If the move is an AttackMove or a StatusMove the Dancer must replicate the move on the source of the Dance - if (move.getMove() instanceof AttackMove || move.getMove() instanceof StatusMove) { - const target = this.getTarget(dancer, source, targets); - globalScene.unshiftPhase(new MovePhase(dancer, target, move, true, true)); - } else if (move.getMove() instanceof SelfStatusMove) { - // If the move is a SelfStatusMove (ie. Swords Dance) the Dancer should replicate it on itself - globalScene.unshiftPhase(new MovePhase(dancer, [ dancer.getBattlerIndex() ], move, true, true)); - } + args: any[]): void { + if (!simulated) { + // If the move is an AttackMove or a StatusMove the Dancer must replicate the move on the source of the Dance + if (move.getMove() instanceof AttackMove || move.getMove() instanceof StatusMove) { + const target = this.getTarget(dancer, source, targets); + globalScene.unshiftPhase(new MovePhase(dancer, target, move, true, true)); + } else if (move.getMove() instanceof SelfStatusMove) { + // If the move is a SelfStatusMove (ie. Swords Dance) the Dancer should replicate it on itself + globalScene.unshiftPhase(new MovePhase(dancer, [ dancer.getBattlerIndex() ], move, true, true)); } - return true; } - return false; } /** @@ -4219,9 +4249,11 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr { * @extends AbAttr */ export class PostItemLostAbAttr extends AbAttr { - applyPostItemLost(pokemon: Pokemon, simulated: boolean, args: any[]): boolean { - return false; + canApplyPostItemLost(pokemon: Pokemon, simulated: boolean, args: any[]): boolean { + return true; } + + applyPostItemLost(pokemon: Pokemon, simulated: boolean, args: any[]): void {} } /** @@ -4231,21 +4263,21 @@ export class PostItemLostAbAttr extends AbAttr { export class PostItemLostApplyBattlerTagAbAttr extends PostItemLostAbAttr { private tagType: BattlerTagType; constructor(tagType: BattlerTagType) { - super(true); + super(false); this.tagType = tagType; } + + override canApplyPostItemLost(pokemon: Pokemon, simulated: boolean, args: any[]): boolean { + return !pokemon.getTag(this.tagType) && !simulated; + } + /** * Adds the last used Pokeball back into the player's inventory * @param pokemon {@linkcode Pokemon} with this ability * @param args N/A - * @returns true if BattlerTag was applied */ - override applyPostItemLost(pokemon: Pokemon, simulated: boolean, args: any[]): boolean { - if (!pokemon.getTag(this.tagType) && !simulated) { - pokemon.addTag(this.tagType); - return true; - } - return false; + override applyPostItemLost(pokemon: Pokemon, simulated: boolean, args: any[]): void { + pokemon.addTag(this.tagType); } } @@ -4253,15 +4285,13 @@ export class StatStageChangeMultiplierAbAttr extends AbAttr { private multiplier: number; constructor(multiplier: number) { - super(true); + super(false); this.multiplier = multiplier; } - override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { (args[0] as Utils.NumberHolder).value *= this.multiplier; - - return true; } } @@ -4272,11 +4302,10 @@ export class StatStageChangeCopyAbAttr extends AbAttr { simulated: boolean, cancelled: Utils.BooleanHolder, args: any[], - ): boolean { + ): void { if (!simulated) { globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, (args[0] as BattleStat[]), (args[1] as number), true, false, false)); } - return true; } } @@ -4285,10 +4314,8 @@ export class BypassBurnDamageReductionAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { cancelled.value = true; - - return true; } } @@ -4307,28 +4334,21 @@ export class ReduceBurnDamageAbAttr extends AbAttr { * @param passive N/A * @param cancelled N/A * @param args `[0]` {@linkcode Utils.NumberHolder} The damage value being modified - * @returns `true` */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { (args[0] as Utils.NumberHolder).value = Utils.toDmgValue((args[0] as Utils.NumberHolder).value * this.multiplier); - - return true; } } export class DoubleBerryEffectAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { (args[0] as Utils.NumberHolder).value *= 2; - - return true; } } export class PreventBerryUseAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { cancelled.value = true; - - return true; } } @@ -4348,7 +4368,7 @@ export class HealFromBerryUseAbAttr extends AbAttr { this.healPercent = Math.max(Math.min(healPercent, 1), 0); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, ...args: [Utils.BooleanHolder, any[]]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, ...args: [Utils.BooleanHolder, any[]]): void { const { name: abilityName } = passive ? pokemon.getPassiveAbility() : pokemon.getAbility(); if (!simulated) { globalScene.unshiftPhase( @@ -4360,15 +4380,12 @@ export class HealFromBerryUseAbAttr extends AbAttr { ) ); } - return true; } } export class RunSuccessAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { (args[0] as Utils.NumberHolder).value = 256; - - return true; } } @@ -4388,6 +4405,16 @@ export class CheckTrappedAbAttr extends AbAttr { this.arenaTrapCondition = condition; } + canApplyCheckTrapped( + pokemon: Pokemon, + passive: boolean, + simulated: boolean, + trapped: Utils.BooleanHolder, + otherPokemon: Pokemon, + args: any[]): boolean { + return true; + } + applyCheckTrapped( pokemon: Pokemon, passive: boolean, @@ -4395,9 +4422,7 @@ export class CheckTrappedAbAttr extends AbAttr { trapped: Utils.BooleanHolder, otherPokemon: Pokemon, args: any[], - ): boolean { - return false; - } + ): void {} } /** @@ -4407,6 +4432,12 @@ export class CheckTrappedAbAttr extends AbAttr { * @see {@linkcode applyCheckTrapped} */ export class ArenaTrapAbAttr extends CheckTrappedAbAttr { + override canApplyCheckTrapped(pokemon: Pokemon, passive: boolean, simulated: boolean, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, args: any[]): boolean { + return this.arenaTrapCondition(pokemon, otherPokemon) + && !(otherPokemon.getTypes(true).includes(PokemonType.GHOST) || (otherPokemon.getTypes(true).includes(PokemonType.STELLAR) && otherPokemon.getTypes().includes(PokemonType.GHOST))) + && !otherPokemon.hasAbility(Abilities.RUN_AWAY); + } + /** * Checks if enemy Pokemon is trapped by an Arena Trap-esque ability * If the enemy is a Ghost type, it is not trapped @@ -4418,22 +4449,9 @@ export class ArenaTrapAbAttr extends CheckTrappedAbAttr { * @param trapped {@link Utils.BooleanHolder} indicating whether the other Pokemon is trapped or not * @param otherPokemon The {@link Pokemon} that is affected by an Arena Trap ability * @param args N/A - * @returns if enemy Pokemon is trapped or not */ - applyCheckTrapped(pokemon: Pokemon, passive: boolean, simulated: boolean, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, args: any[]): boolean { - if (this.arenaTrapCondition(pokemon, otherPokemon)) { - if (otherPokemon.getTypes(true).includes(PokemonType.GHOST) || (otherPokemon.getTypes(true).includes(PokemonType.STELLAR) && otherPokemon.getTypes().includes(PokemonType.GHOST))) { - trapped.value = false; - return false; - } else if (otherPokemon.hasAbility(Abilities.RUN_AWAY)) { - trapped.value = false; - return false; - } - trapped.value = true; - return true; - } - trapped.value = false; - return false; + override applyCheckTrapped(pokemon: Pokemon, passive: boolean, simulated: boolean, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, args: any[]): void { + trapped.value = true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -4442,10 +4460,12 @@ export class ArenaTrapAbAttr extends CheckTrappedAbAttr { } export class MaxMultiHitAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - (args[0] as Utils.NumberHolder).value = 0; + constructor() { + super(false); + } - return true; + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + (args[0] as Utils.NumberHolder).value = 0; } } @@ -4454,36 +4474,48 @@ export class PostBattleAbAttr extends AbAttr { super(true); } - applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - return false; + canApplyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return true; } + + applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {} } export class PostBattleLootAbAttr extends PostBattleAbAttr { - /** - * @param args - `[0]`: boolean for if the battle ended in a victory - * @returns `true` if successful - */ - applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + private randItem?: PokemonHeldItemModifier; + + override canApplyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { const postBattleLoot = globalScene.currentBattle.postBattleLoot; if (!simulated && postBattleLoot.length && args[0]) { - const randItem = Utils.randSeedItem(postBattleLoot); - //@ts-ignore - TODO see below - if (globalScene.tryTransferHeldItemModifier(randItem, pokemon, true, 1, true, undefined, false)) { - postBattleLoot.splice(postBattleLoot.indexOf(randItem), 1); - globalScene.queueMessage(i18next.t("abilityTriggers:postBattleLoot", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), itemName: randItem.type.name })); - return true; - } + this.randItem = Utils.randSeedItem(postBattleLoot); + return globalScene.canTransferHeldItemModifier(this.randItem, pokemon, 1); + } + return false; + } + + /** + * @param args - `[0]`: boolean for if the battle ended in a victory + */ + override applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + const postBattleLoot = globalScene.currentBattle.postBattleLoot; + if (!this.randItem) { + this.randItem = Utils.randSeedItem(postBattleLoot); } - return false; + if (globalScene.tryTransferHeldItemModifier(this.randItem, pokemon, true, 1, true, undefined, false)) { + postBattleLoot.splice(postBattleLoot.indexOf(this.randItem), 1); + globalScene.queueMessage(i18next.t("abilityTriggers:postBattleLoot", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), itemName: this.randItem.type.name })); + } + this.randItem = undefined; } } export class PostFaintAbAttr extends AbAttr { - applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean { - return false; + canApplyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean { + return true; } + + applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): void {} } /** @@ -4492,6 +4524,10 @@ export class PostFaintAbAttr extends AbAttr { * @extends PostFaintAbAttr */ export class PostFaintUnsuppressedWeatherFormChangeAbAttr extends PostFaintAbAttr { + override canApplyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean { + return getPokemonWithWeatherBasedForms().length > 0; + } + /** * Triggers {@linkcode Arena.triggerWeatherBasedFormChanges | triggerWeatherBasedFormChanges} * when the user of the ability faints @@ -4501,20 +4537,11 @@ export class PostFaintUnsuppressedWeatherFormChangeAbAttr extends PostFaintAbAtt * @param move n/a * @param hitResult n/a * @param args n/a - * @returns whether the form change was triggered */ - applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - const pokemonToTransform = getPokemonWithWeatherBasedForms(); - - if (pokemonToTransform.length < 1) { - return false; - } - + override applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): void { if (!simulated) { globalScene.arena.triggerWeatherBasedFormChanges(); } - - return true; } } @@ -4522,26 +4549,27 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { private damageRatio: number; constructor(damageRatio: number) { - super(); + super(true); this.damageRatio = damageRatio; } - applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean { - if (move !== undefined && attacker !== undefined && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { //If the mon didn't die to indirect damage - const cancelled = new Utils.BooleanHolder(false); - globalScene.getField(true).map(p => applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled, simulated)); - if (cancelled.value || attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { - return false; - } - if (!simulated) { - attacker.damageAndUpdate(Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); - attacker.turnData.damageTaken += Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)); - } - return true; + override canApplyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean { + const diedToDirectDamage = move !== undefined && attacker !== undefined && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon); + const cancelled = new Utils.BooleanHolder(false); + globalScene.getField(true).map(p => applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled, simulated)); + if (!diedToDirectDamage || cancelled.value || attacker!.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { + return false; } - return false; + return true; + } + + override applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): void { + if (!simulated) { + attacker!.damageAndUpdate(Utils.toDmgValue(attacker!.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); + attacker!.turnData.damageTaken += Utils.toDmgValue(attacker!.getMaxHp() * (1 / this.damageRatio)); + } } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -4557,13 +4585,12 @@ export class PostFaintHPDamageAbAttr extends PostFaintAbAttr { super (); } - applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean { + override applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): void { if (move !== undefined && attacker !== undefined && !simulated) { //If the mon didn't die to indirect damage const damage = pokemon.turnData.attacksReceived[0].damage; attacker.damageAndUpdate((damage), HitResult.OTHER); attacker.turnData.damageTaken += damage; } - return true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -4582,17 +4609,20 @@ export class RedirectMoveAbAttr extends AbAttr { * - `[1]` - The target's battler index (before redirection) * - `[2]` - The Pokemon that used the move being redirected */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.canRedirect(args[0] as Moves, args[2] as Pokemon)) { - const target = args[1] as Utils.NumberHolder; - const newTarget = pokemon.getBattlerIndex(); - if (target.value !== newTarget) { - target.value = newTarget; - return true; - } - } - return false; + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + if (!this.canRedirect(args[0] as Moves, args[2] as Pokemon)) { + return false; + } + const target = args[1] as Utils.NumberHolder; + const newTarget = pokemon.getBattlerIndex(); + return target.value !== newTarget; + } + + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + const target = args[1] as Utils.NumberHolder; + const newTarget = pokemon.getBattlerIndex(); + target.value = newTarget; } canRedirect(moveId: Moves, user: Pokemon): boolean { @@ -4625,28 +4655,23 @@ export class ReduceStatusEffectDurationAbAttr extends AbAttr { private statusEffect: StatusEffect; constructor(statusEffect: StatusEffect) { - super(true); + super(false); this.statusEffect = statusEffect; } + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return args[1] instanceof Utils.NumberHolder && args[0] === this.statusEffect; + } + /** * Reduces the number of sleep turns remaining by an extra 1 when applied * @param args - The args passed to the `AbAttr`: * - `[0]` - The {@linkcode StatusEffect} of the Pokemon * - `[1]` - The number of turns remaining until the status is healed - * @returns `true` if the ability was applied */ - apply(_pokemon: Pokemon, _passive: boolean, _simulated: boolean, _cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (!(args[1] instanceof Utils.NumberHolder)) { - return false; - } - if (args[0] === this.statusEffect) { - args[1].value -= 1; - return true; - } - - return false; + override apply(_pokemon: Pokemon, _passive: boolean, _simulated: boolean, _cancelled: Utils.BooleanHolder, args: any[]): void { + args[1].value -= 1; } } @@ -4669,20 +4694,18 @@ export class FlinchStatStageChangeAbAttr extends FlinchEffectAbAttr { this.stages = stages; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { if (!simulated) { globalScene.unshiftPhase(new StatStageChangePhase(pokemon.getBattlerIndex(), true, this.stats, this.stages)); } - return true; } } export class IncreasePpAbAttr extends AbAttr { } export class ForceSwitchOutImmunityAbAttr extends AbAttr { - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { cancelled.value = true; - return true; } } @@ -4691,15 +4714,13 @@ export class ReduceBerryUseThresholdAbAttr extends AbAttr { super(); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { const hpRatio = pokemon.getHpRatio(); + return args[0].value < hpRatio; + } - if (args[0].value < hpRatio) { - args[0].value *= 2; - return args[0].value >= hpRatio; - } - - return false; + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + args[0].value *= 2; } } @@ -4711,15 +4732,13 @@ export class WeightMultiplierAbAttr extends AbAttr { private multiplier: number; constructor(multiplier: number) { - super(); + super(false); this.multiplier = multiplier; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { (args[0] as Utils.NumberHolder).value *= this.multiplier; - - return true; } } @@ -4728,10 +4747,8 @@ export class SyncEncounterNatureAbAttr extends AbAttr { super(false); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { (args[0] as Pokemon).setNature(pokemon.getNature()); - - return true; } } @@ -4744,12 +4761,12 @@ export class MoveAbilityBypassAbAttr extends AbAttr { this.moveIgnoreFunc = moveIgnoreFunc || ((pokemon, move) => true); } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.moveIgnoreFunc(pokemon, (args[0] as Move))) { - cancelled.value = true; - return true; - } - return false; + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return this.moveIgnoreFunc(pokemon, (args[0] as Move)); + } + + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; } } @@ -4763,6 +4780,14 @@ export class IgnoreProtectOnContactAbAttr extends AbAttr { } * Allows the source's moves to bypass the effects of opposing Light Screen, Reflect, Aurora Veil, Safeguard, Mist, and Substitute. */ export class InfiltratorAbAttr extends AbAttr { + constructor() { + super(false); + } + + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return args[0] instanceof Utils.BooleanHolder; + } + /** * Sets a flag to bypass screens, Substitute, Safeguard, and Mist * @param pokemon n/a @@ -4770,15 +4795,10 @@ export class InfiltratorAbAttr extends AbAttr { * @param simulated n/a * @param cancelled n/a * @param args `[0]` a {@linkcode Utils.BooleanHolder | BooleanHolder} containing the flag - * @returns `true` if the bypass flag was successfully set; `false` otherwise. */ - override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: null, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: null, args: any[]): void { const bypassed = args[0]; - if (args[0] instanceof Utils.BooleanHolder) { - bypassed.value = true; - return true; - } - return false; + bypassed.value = true; } } @@ -4824,17 +4844,17 @@ export class IgnoreTypeImmunityAbAttr extends AbAttr { private allowedMoveTypes: PokemonType[]; constructor(defenderType: PokemonType, allowedMoveTypes: PokemonType[]) { - super(true); + super(false); this.defenderType = defenderType; this.allowedMoveTypes = allowedMoveTypes; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.defenderType === (args[1] as PokemonType) && this.allowedMoveTypes.includes(args[0] as PokemonType)) { - cancelled.value = true; - return true; - } - return false; + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return this.defenderType === (args[1] as PokemonType) && this.allowedMoveTypes.includes(args[0] as PokemonType); + } + + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; } } @@ -4846,19 +4866,18 @@ export class IgnoreTypeStatusEffectImmunityAbAttr extends AbAttr { private defenderType: PokemonType[]; constructor(statusEffect: StatusEffect[], defenderType: PokemonType[]) { - super(true); + super(false); this.statusEffect = statusEffect; this.defenderType = defenderType; } - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.statusEffect.includes(args[0] as StatusEffect) && this.defenderType.includes(args[1] as PokemonType)) { - cancelled.value = true; - return true; - } + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return this.statusEffect.includes(args[0] as StatusEffect) && this.defenderType.includes(args[1] as PokemonType); + } - return false; + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { + cancelled.value = true; } } @@ -4873,18 +4892,17 @@ export class MoneyAbAttr extends PostBattleAbAttr { super(); } + override canApplyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return !simulated && args[0]; + } + /** * @param pokemon {@linkcode Pokemon} that is the user of this ability. * @param passive N/A * @param args - `[0]`: boolean for if the battle ended in a victory - * @returns `true` if successful */ - applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (!simulated && args[0]) { - globalScene.currentBattle.moneyScattered += globalScene.getWaveMoneyAmount(0.2); - return true; - } - return false; + override applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + globalScene.currentBattle.moneyScattered += globalScene.getWaveMoneyAmount(0.2); } } @@ -4912,6 +4930,12 @@ export class PostSummonStatStageChangeOnArenaAbAttr extends PostSummonStatStageC this.tagType = tagType; } + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + const side = pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; + return (globalScene.arena.getTagOnSide(this.tagType, side) ?? false) + && super.canApplyPostSummon(pokemon, passive, simulated, args); + } + /** * Applies the post-summon stat change if the specified arena tag is present on pokemon's side. * This is used in Wind Rider ability. @@ -4919,15 +4943,9 @@ export class PostSummonStatStageChangeOnArenaAbAttr extends PostSummonStatStageC * @param {Pokemon} pokemon - The Pokémon being summoned. * @param {boolean} passive - Whether the effect is passive. * @param {any[]} args - Additional arguments. - * @returns {boolean} - Returns true if the stat change was applied, otherwise false. */ - applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - const side = pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; - - if (globalScene.arena.getTagOnSide(this.tagType, side)) { - return super.applyPostSummon(pokemon, passive, simulated, args); - } - return false; + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + super.applyPostSummon(pokemon, passive, simulated, args); } } @@ -4951,6 +4969,10 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr { this.triggerMessageFunc = triggerMessageFunc; } + override canApplyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder | null, args: any[]): boolean { + return this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon); + } + /** * Applies the pre-defense ability to the Pokémon. * Removes the appropriate `BattlerTagType` when hit by an attack and is in its defense form. @@ -4961,21 +4983,15 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr { * @param move The move being used. * @param _cancelled n/a * @param args Additional arguments. - * @returns `true` if the immunity was applied. */ - override applyPreDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) { - if (!simulated) { - (args[0] as Utils.NumberHolder).value = this.multiplier; - pokemon.removeTag(this.tagType); - if (this.recoilDamageFunc) { - pokemon.damageAndUpdate(this.recoilDamageFunc(pokemon), HitResult.OTHER, false, false, true, true); - } + override applyPreDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _cancelled: Utils.BooleanHolder, args: any[]): void { + if (!simulated) { + (args[0] as Utils.NumberHolder).value = this.multiplier; + pokemon.removeTag(this.tagType); + if (this.recoilDamageFunc) { + pokemon.damageAndUpdate(this.recoilDamageFunc(pokemon), HitResult.OTHER, false, false, true, true); } - return true; } - - return false; } /** @@ -5006,34 +5022,25 @@ export class BypassSpeedChanceAbAttr extends AbAttr { this.chance = chance; } + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + const bypassSpeed = args[0] as Utils.BooleanHolder; + const turnCommand = globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]; + const isCommandFight = turnCommand?.command === Command.FIGHT; + const move = turnCommand?.move?.move ? allMoves[turnCommand.move.move] : null; + const isDamageMove = move?.category === MoveCategory.PHYSICAL || move?.category === MoveCategory.SPECIAL; + return !simulated && !bypassSpeed.value && pokemon.randSeedInt(100) < this.chance && isCommandFight && isDamageMove; + } + /** * bypass move order in their priority bracket when pokemon choose damaging move * @param {Pokemon} pokemon {@linkcode Pokemon} the Pokemon applying this ability * @param {boolean} passive N/A * @param {Utils.BooleanHolder} cancelled N/A * @param {any[]} args [0] {@linkcode Utils.BooleanHolder} set to true when the ability activated - * @returns {boolean} - whether the ability was activated. */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (simulated) { - return false; - } + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { const bypassSpeed = args[0] as Utils.BooleanHolder; - - if (!bypassSpeed.value && pokemon.randSeedInt(100) < this.chance) { - const turnCommand = - globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]; - const isCommandFight = turnCommand?.command === Command.FIGHT; - const move = turnCommand?.move?.move ? allMoves[turnCommand.move.move] : null; - const isDamageMove = move?.category === MoveCategory.PHYSICAL || move?.category === MoveCategory.SPECIAL; - - if (isCommandFight && isDamageMove) { - bypassSpeed.value = true; - return true; - } - } - - return false; + bypassSpeed.value = true; } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { @@ -5056,23 +5063,22 @@ export class PreventBypassSpeedChanceAbAttr extends AbAttr { this.condition = condition; } + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + const turnCommand = globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]; + const isCommandFight = turnCommand?.command === Command.FIGHT; + const move = turnCommand?.move?.move ? allMoves[turnCommand.move.move] : null; + return isCommandFight && this.condition(pokemon, move!); + } + /** * @argument {boolean} bypassSpeed - determines if a Pokemon is able to bypass speed at the moment * @argument {boolean} canCheckHeldItems - determines if a Pokemon has access to Quick Claw's effects or not */ - apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): void { const bypassSpeed = args[0] as Utils.BooleanHolder; const canCheckHeldItems = args[1] as Utils.BooleanHolder; - - const turnCommand = globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]; - const isCommandFight = turnCommand?.command === Command.FIGHT; - const move = turnCommand?.move?.move ? allMoves[turnCommand.move.move] : null; - if (isCommandFight && this.condition(pokemon, move!)) { - bypassSpeed.value = false; - canCheckHeldItems.value = false; - return false; - } - return true; + bypassSpeed.value = false; + canCheckHeldItems.value = false; } } @@ -5085,10 +5091,11 @@ export class TerrainEventTypeChangeAbAttr extends PostSummonAbAttr { super(true); } - override apply(pokemon: Pokemon, _passive: boolean, _simulated: boolean, _cancelled: Utils.BooleanHolder, _args: any[]): boolean { - if (pokemon.isTerastallized) { - return false; - } + override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return !pokemon.isTerastallized; + } + + override apply(pokemon: Pokemon, _passive: boolean, _simulated: boolean, _cancelled: Utils.BooleanHolder, _args: any[]): void { const currentTerrain = globalScene.arena.getTerrainType(); const typeChange: PokemonType[] = this.determineTypeChange(pokemon, currentTerrain); if (typeChange.length !== 0) { @@ -5098,7 +5105,6 @@ export class TerrainEventTypeChangeAbAttr extends PostSummonAbAttr { pokemon.summonData.types = typeChange; pokemon.updateInfo(); } - return true; } /** @@ -5131,15 +5137,16 @@ export class TerrainEventTypeChangeAbAttr extends PostSummonAbAttr { return typeChange; } + override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { + return globalScene.arena.getTerrainType() !== TerrainType.NONE && + this.canApply(pokemon, passive, simulated, args); + } + /** * Checks if the Pokemon should change types if summoned into an active terrain - * @returns `true` if there is an active terrain requiring a type change | `false` if not */ - override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { - if (globalScene.arena.getTerrainType() !== TerrainType.NONE) { - return this.apply(pokemon, passive, simulated, new Utils.BooleanHolder(false), []); - } - return false; + override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { + this.apply(pokemon, passive, simulated, new Utils.BooleanHolder(false), []); } override getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]) { @@ -5159,10 +5166,10 @@ function applySingleAbAttrs( passive: boolean, attrType: Constructor, applyFunc: AbAttrApplyFunc, + successFunc: AbAttrSuccessFunc, args: any[], - gainedMidTurn = false, - simulated = false, - showAbilityInstant = false, + gainedMidTurn: boolean = false, + simulated: boolean = false, messages: string[] = [] ) { if (!pokemon?.canApplyAbility(passive) || (passive && (pokemon.getPassiveAbility().id === pokemon.getAbility().id))) { @@ -5176,33 +5183,39 @@ function applySingleAbAttrs( for (const attr of ability.getAttrs(attrType)) { const condition = attr.getCondition(); - if (condition && !condition(pokemon)) { + let abShown = false; + if (condition && !condition(pokemon) || !successFunc(attr, passive)) { continue; } globalScene.setPhaseQueueSplice(); - if (applyFunc(attr, passive)) { - if (pokemon.summonData && !pokemon.summonData.abilitiesApplied.includes(ability.id)) { - pokemon.summonData.abilitiesApplied.push(ability.id); - } - if (pokemon.battleData && !simulated && !pokemon.battleData.abilitiesApplied.includes(ability.id)) { - pokemon.battleData.abilitiesApplied.push(ability.id); - } - if (attr.showAbility && !simulated) { - if (showAbilityInstant) { - globalScene.abilityBar.showAbility(pokemon, passive); - } else { - queueShowAbility(pokemon, passive); - } - } - const message = attr.getTriggerMessage(pokemon, ability.name, args); - if (message) { - if (!simulated) { - globalScene.queueMessage(message); - } - } - messages.push(message!); + + if (attr.showAbility && !simulated) { + globalScene.queueAbilityDisplay(pokemon, passive, true); + abShown = true; } + const message = attr.getTriggerMessage(pokemon, ability.name, args); + if (message) { + if (!simulated) { + globalScene.queueMessage(message); + } + messages.push(message); + } + + applyFunc(attr, passive); + + if (abShown) { + globalScene.queueAbilityDisplay(pokemon, passive, false); + } + + if (pokemon.summonData && !pokemon.summonData.abilitiesApplied.includes(ability.id)) { + pokemon.summonData.abilitiesApplied.push(ability.id); + } + if (pokemon.battleData && !simulated && !pokemon.battleData.abilitiesApplied.includes(ability.id)) { + pokemon.battleData.abilitiesApplied.push(ability.id); + } + + globalScene.clearPhaseQueueSplice(); } } @@ -5346,6 +5359,16 @@ function calculateShellBellRecovery(pokemon: Pokemon): number { * @extends AbAttr */ export class PostDamageAbAttr extends AbAttr { + public canApplyPostDamage( + pokemon: Pokemon, + damage: number, + passive: boolean, + simulated: boolean, + args: any[], + source?: Pokemon): boolean { + return true; + } + public applyPostDamage( pokemon: Pokemon, damage: number, @@ -5353,9 +5376,7 @@ export class PostDamageAbAttr extends AbAttr { simulated: boolean, args: any[], source?: Pokemon, - ): boolean { - return false; - } + ): void {} } /** @@ -5377,27 +5398,13 @@ export class PostDamageForceSwitchAbAttr extends PostDamageAbAttr { this.hpRatio = hpRatio; } - /** - * Applies the switch-out logic after the Pokémon takes damage. - * Checks various conditions based on the moves used by the Pokémon, the opponents' moves, and - * the Pokémon's health after damage to determine whether the switch-out should occur. - * - * @param pokemon The Pokémon that took damage. - * @param damage The amount of damage taken by the Pokémon. - * @param passive N/A - * @param simulated Whether the ability is being simulated. - * @param args N/A - * @param source The Pokemon that dealt damage - * @returns `true` if the switch-out logic was successfully applied - */ - public override applyPostDamage( + public override canApplyPostDamage( pokemon: Pokemon, damage: number, passive: boolean, simulated: boolean, args: any[], - source?: Pokemon, - ): boolean { + source?: Pokemon): boolean { const moveHistory = pokemon.getMoveHistory(); // Will not activate when the Pokémon's HP is lowered by cutting its own HP const fordbiddenAttackingMoves = [ Moves.BELLY_DRUM, Moves.SUBSTITUTE, Moves.CURSE, Moves.PAIN_SPLIT ]; @@ -5431,7 +5438,6 @@ export class PostDamageForceSwitchAbAttr extends PostDamageAbAttr { } if (pokemon.hp + damage >= pokemon.getMaxHp() * this.hpRatio) { - // Activates if it falls below half and recovers back above half from a Shell Bell const shellBellHeal = calculateShellBellRecovery(pokemon); if (pokemon.hp - shellBellHeal < pokemon.getMaxHp() * this.hpRatio) { for (const opponent of pokemon.getOpponents()) { @@ -5439,31 +5445,42 @@ export class PostDamageForceSwitchAbAttr extends PostDamageAbAttr { return false; } } - return this.helper.switchOutLogic(pokemon); - } else { - return false; + return true; } - } else { - return false; } + + return false; } - public getFailedText(user: Pokemon, target: Pokemon, move: Move, cancelled: Utils.BooleanHolder): string | null { - return this.helper.getFailedText(target); + + /** + * Applies the switch-out logic after the Pokémon takes damage. + * Checks various conditions based on the moves used by the Pokémon, the opponents' moves, and + * the Pokémon's health after damage to determine whether the switch-out should occur. + * + * @param pokemon The Pokémon that took damage. + * @param damage N/A + * @param passive N/A + * @param simulated Whether the ability is being simulated. + * @param args N/A + * @param source N/A + */ + public override applyPostDamage(pokemon: Pokemon, damage: number, passive: boolean, simulated: boolean, args: any[], source?: Pokemon): void { + this.helper.switchOutLogic(pokemon); } } function applyAbAttrsInternal( attrType: Constructor, pokemon: Pokemon | null, applyFunc: AbAttrApplyFunc, + successFunc: AbAttrSuccessFunc, args: any[], - showAbilityInstant = false, - simulated = false, + simulated: boolean = false, messages: string[] = [], gainedMidTurn = false ) { for (const passive of [ false, true ]) { if (pokemon) { - applySingleAbAttrs(pokemon, passive, attrType, applyFunc, args, gainedMidTurn, simulated, showAbilityInstant, messages); + applySingleAbAttrs(pokemon, passive, attrType, applyFunc, successFunc, args, gainedMidTurn, simulated, messages); globalScene.clearPhaseQueueSplice(); } } @@ -5480,8 +5497,8 @@ export function applyAbAttrs( attrType, pokemon, (attr, passive) => attr.apply(pokemon, passive, simulated, cancelled, args), + (attr, passive) => attr.canApply(pokemon, passive, simulated, args), args, - false, simulated, ); } @@ -5496,8 +5513,8 @@ export function applyPostBattleInitAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostBattleInit(pokemon, passive, simulated, args), + (attr, passive) => attr.canApplyPostBattleInit(pokemon, passive, simulated, args), args, - false, simulated, ); } @@ -5515,8 +5532,8 @@ export function applyPreDefendAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args), + (attr, passive) => attr.canApplyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args), args, - false, simulated, ); } @@ -5534,8 +5551,7 @@ export function applyPostDefendAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostDefend(pokemon, passive, simulated, attacker, move, hitResult, args), - args, - false, + (attr, passive) => attr.canApplyPostDefend(pokemon, passive, simulated, attacker, move, hitResult, args), args, simulated, ); } @@ -5553,8 +5569,8 @@ export function applyPostMoveUsedAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostMoveUsed(pokemon, move, source, targets, simulated, args), + (attr, passive) => attr.canApplyPostMoveUsed(pokemon, move, source, targets, simulated, args), args, - false, simulated, ); } @@ -5571,6 +5587,7 @@ export function applyStatMultiplierAbAttrs( attrType, pokemon, (attr, passive) => attr.applyStatStage(pokemon, passive, simulated, stat, statValue, args), + (attr, passive) => attr.canApplyStatStage(pokemon, passive, simulated, stat, statValue, args), args, ); } @@ -5586,8 +5603,7 @@ export function applyPostSetStatusAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostSetStatus(pokemon, sourcePokemon, passive, effect, simulated, args), - args, - false, + (attr, passive) => attr.canApplyPostSetStatus(pokemon, sourcePokemon, passive, effect, simulated, args), args, simulated, ); } @@ -5605,6 +5621,7 @@ export function applyPostDamageAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostDamage(pokemon, damage, passive, simulated, args, source), + (attr, passive) => attr.canApplyPostDamage(pokemon, damage, passive, simulated, args, source), args, ); } @@ -5632,9 +5649,8 @@ export function applyFieldStatMultiplierAbAttrs( applyAbAttrsInternal( attrType, pokemon, - (attr, passive) => - attr.applyFieldStat(pokemon, passive, simulated, stat, statValue, checkedPokemon, hasApplied, args), - args, + (attr, passive) => attr.applyFieldStat(pokemon, passive, simulated, stat, statValue, checkedPokemon, hasApplied, args), + (attr, passive) => attr.canApplyFieldStat(pokemon, passive, simulated, stat, statValue, checkedPokemon, hasApplied, args), args, ); } @@ -5650,8 +5666,8 @@ export function applyPreAttackAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPreAttack(pokemon, passive, simulated, defender, move, args), + (attr, passive) => attr.canApplyPreAttack(pokemon, passive, simulated, defender, move, args), args, - false, simulated, ); } @@ -5669,8 +5685,7 @@ export function applyPostAttackAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args), - args, - false, + (attr, passive) => attr.canApplyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args), args, simulated, ); } @@ -5686,8 +5701,8 @@ export function applyPostKnockOutAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostKnockOut(pokemon, passive, simulated, knockedOut, args), + (attr, passive) => attr.canApplyPostKnockOut(pokemon, passive, simulated, knockedOut, args), args, - false, simulated, ); } @@ -5702,8 +5717,8 @@ export function applyPostVictoryAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostVictory(pokemon, passive, simulated, args), + (attr, passive) => attr.canApplyPostVictory(pokemon, passive, simulated, args), args, - false, simulated, ); } @@ -5718,8 +5733,8 @@ export function applyPostSummonAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostSummon(pokemon, passive, simulated, args), + (attr, passive) => attr.canApplyPostSummon(pokemon, passive, simulated, args), args, - false, simulated, ); } @@ -5734,8 +5749,8 @@ export function applyPreSwitchOutAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPreSwitchOut(pokemon, passive, simulated, args), + (attr, passive) => attr.canApplyPreSwitchOut(pokemon, passive, simulated, args), args, - true, simulated, ); } @@ -5751,8 +5766,8 @@ export function applyPreLeaveFieldAbAttrs( pokemon, (attr, passive) => attr.applyPreLeaveField(pokemon, passive, simulated, args), + (attr, passive) => attr.canApplyPreLeaveField(pokemon, passive, simulated, args), args, - true, simulated ); } @@ -5769,8 +5784,7 @@ export function applyPreStatStageChangeAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPreStatStageChange(pokemon, passive, simulated, stat, cancelled, args), - args, - false, + (attr, passive) => attr.canApplyPreStatStageChange(pokemon, passive, simulated, stat, cancelled, args), args, simulated, ); } @@ -5788,8 +5802,7 @@ export function applyPostStatStageChangeAbAttrs( attrType, pokemon, (attr, _passive) => attr.applyPostStatStageChange(pokemon, simulated, stats, stages, selfTarget, args), - args, - false, + (attr, _passive) => attr.canApplyPostStatStageChange(pokemon, simulated, stats, stages, selfTarget, args), args, simulated, ); } @@ -5806,8 +5819,8 @@ export function applyPreSetStatusAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPreSetStatus(pokemon, passive, simulated, effect, cancelled, args), + (attr, passive) => attr.canApplyPreSetStatus(pokemon, passive, simulated, effect, cancelled, args), args, - false, simulated, ); } @@ -5824,8 +5837,7 @@ export function applyPreApplyBattlerTagAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPreApplyBattlerTag(pokemon, passive, simulated, tag, cancelled, args), - args, - false, + (attr, passive) => attr.canApplyPreApplyBattlerTag(pokemon, passive, simulated, tag, cancelled, args), args, simulated, ); } @@ -5842,8 +5854,7 @@ export function applyPreWeatherEffectAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPreWeatherEffect(pokemon, passive, simulated, weather, cancelled, args), - args, - true, + (attr, passive) => attr.canApplyPreWeatherEffect(pokemon, passive, simulated, weather, cancelled, args), args, simulated, ); } @@ -5858,8 +5869,8 @@ export function applyPostTurnAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostTurn(pokemon, passive, simulated, args), + (attr, passive) => attr.canApplyPostTurn(pokemon, passive, simulated, args), args, - false, simulated, ); } @@ -5875,8 +5886,8 @@ export function applyPostWeatherChangeAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostWeatherChange(pokemon, passive, simulated, weather, args), + (attr, passive) => attr.canApplyPostWeatherChange(pokemon, passive, simulated, weather, args), args, - false, simulated, ); } @@ -5892,8 +5903,8 @@ export function applyPostWeatherLapseAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostWeatherLapse(pokemon, passive, simulated, weather, args), + (attr, passive) => attr.canApplyPostWeatherLapse(pokemon, passive, simulated, weather, args), args, - false, simulated, ); } @@ -5909,8 +5920,8 @@ export function applyPostTerrainChangeAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostTerrainChange(pokemon, passive, simulated, terrain, args), + (attr, passive) => attr.canApplyPostTerrainChange(pokemon, passive, simulated, terrain, args), args, - false, simulated, ); } @@ -5928,8 +5939,7 @@ export function applyCheckTrappedAbAttrs( attrType, pokemon, (attr, passive) => attr.applyCheckTrapped(pokemon, passive, simulated, trapped, otherPokemon, args), - args, - false, + (attr, passive) => attr.canApplyCheckTrapped(pokemon, passive, simulated, trapped, otherPokemon, args), args, simulated, messages, ); @@ -5945,8 +5955,8 @@ export function applyPostBattleAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostBattle(pokemon, passive, simulated, args), + (attr, passive) => attr.canApplyPostBattle(pokemon, passive, simulated, args), args, - false, simulated, ); } @@ -5964,8 +5974,8 @@ export function applyPostFaintAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, simulated, attacker, move, hitResult, args), + (attr, passive) => attr.canApplyPostFaint(pokemon, passive, simulated, attacker, move, hitResult, args), args, - false, simulated, ); } @@ -5980,6 +5990,7 @@ export function applyPostItemLostAbAttrs( attrType, pokemon, (attr, passive) => attr.applyPostItemLost(pokemon, simulated, args), + (attr, passive) => attr.canApplyPostItemLost(pokemon, simulated, args), args, ); } @@ -5989,19 +6000,36 @@ export function applyPostItemLostAbAttrs( * * Ignores passives as they don't change and shouldn't be reapplied when main abilities change */ -export function applyOnGainAbAttrs(pokemon: Pokemon, passive = false, simulated = false, ...args: any[]): void { - applySingleAbAttrs(pokemon, passive, PostSummonAbAttr, (attr, passive) => attr.applyPostSummon(pokemon, passive, simulated, args), args, true, simulated); +export function applyOnGainAbAttrs( + pokemon: Pokemon, + passive: boolean = false, + simulated: boolean = false, + ...args: any[]): void { + applySingleAbAttrs( + pokemon, + passive, + PostSummonAbAttr, + (attr, passive) => attr.applyPostSummon(pokemon, passive, simulated, args), + (attr, passive) => attr.canApplyPostSummon(pokemon, passive, simulated, args), + args, + true, + simulated, + ); } /** * Clears primal weather/neutralizing gas during the turn if {@linkcode pokemon}'s ability corresponds to one */ export function applyOnLoseAbAttrs(pokemon: Pokemon, passive = false, simulated = false, ...args: any[]): void { - applySingleAbAttrs(pokemon, passive, PreLeaveFieldAbAttr, (attr, passive) => attr.applyPreLeaveField(pokemon, passive, simulated, [ ...args, true ]), args, true, simulated); -} -function queueShowAbility(pokemon: Pokemon, passive: boolean): void { - globalScene.unshiftPhase(new ShowAbilityPhase(pokemon.id, passive)); - globalScene.clearPhaseQueueSplice(); + applySingleAbAttrs( + pokemon, + passive, + PreLeaveFieldAbAttr, + (attr, passive) => attr.applyPreLeaveField(pokemon, passive, simulated, [ ...args, true ]), + (attr, passive) => attr.canApplyPreLeaveField(pokemon, passive, simulated, [ ...args, true ]), + args, + true, + simulated); } /** @@ -6888,7 +6916,7 @@ export function initAbilities() { new Ability(Abilities.GORILLA_TACTICS, 8) .attr(GorillaTacticsAbAttr), new Ability(Abilities.NEUTRALIZING_GAS, 8) - .attr(PostSummonAddArenaTagAbAttr, ArenaTagType.NEUTRALIZING_GAS, 0) + .attr(PostSummonAddArenaTagAbAttr, true, ArenaTagType.NEUTRALIZING_GAS, 0) .attr(PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) diff --git a/src/field/arena.ts b/src/field/arena.ts index 2ed94e0e3e3..997b80b3237 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -303,6 +303,11 @@ export class Arena { return true; } + /** Returns weather or not the weather can be changed to {@linkcode weather} */ + canSetWeather(weather: WeatherType): boolean { + return !(this.weather?.weatherType === (weather || undefined)); + } + /** * Attempts to set a new weather to the battle * @param weather {@linkcode WeatherType} new {@linkcode WeatherType} to set @@ -314,7 +319,7 @@ export class Arena { return this.trySetWeatherOverride(Overrides.WEATHER_OVERRIDE); } - if (this.weather?.weatherType === (weather || undefined)) { + if (!this.canSetWeather(weather)) { return false; } @@ -388,8 +393,13 @@ export class Arena { }); } + /** Returns whether or not the terrain can be set to {@linkcode terrain} */ + canSetTerrain(terrain: TerrainType): boolean { + return !(this.terrain?.terrainType === (terrain || undefined)); + } + trySetTerrain(terrain: TerrainType, hasPokemonSource: boolean, ignoreAnim = false): boolean { - if (this.terrain?.terrainType === (terrain || undefined)) { + if (!this.canSetTerrain(terrain)) { return false; } diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 1e98c175487..295dc318db4 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -79,6 +79,7 @@ export class LoadingScene extends SceneBase { this.loadImage("icon_owned", "ui"); this.loadImage("icon_egg_move", "ui"); this.loadImage("ability_bar_left", "ui"); + this.loadImage("ability_bar_right", "ui"); this.loadImage("bgm_bar", "ui"); this.loadImage("party_exp_bar", "ui"); this.loadImage("achv_bar", "ui"); diff --git a/src/phase.ts b/src/phase.ts index 8da00d78b61..20cc7cc4063 100644 --- a/src/phase.ts +++ b/src/phase.ts @@ -1,11 +1,7 @@ import { globalScene } from "#app/global-scene"; export class Phase { - start() { - if (globalScene.abilityBar.shown) { - globalScene.abilityBar.resetAutoHideTimer(); - } - } + start() {} end() { globalScene.shiftPhase(); diff --git a/src/phases/hide-ability-phase.ts b/src/phases/hide-ability-phase.ts new file mode 100644 index 00000000000..0745b3f832a --- /dev/null +++ b/src/phases/hide-ability-phase.ts @@ -0,0 +1,27 @@ +import { globalScene } from "#app/global-scene"; +import type { BattlerIndex } from "#app/battle"; +import { PokemonPhase } from "./pokemon-phase"; + +export class HideAbilityPhase extends PokemonPhase { + private passive: boolean; + + constructor(battlerIndex: BattlerIndex, passive = false) { + super(battlerIndex); + + this.passive = passive; + } + + start() { + super.start(); + + const pokemon = this.getPokemon(); + + if (pokemon) { + globalScene.abilityBar.hide().then(() => { + this.end(); + }); + } else { + this.end(); + } + } +} diff --git a/src/phases/message-phase.ts b/src/phases/message-phase.ts index af4e63c6916..f671307d86a 100644 --- a/src/phases/message-phase.ts +++ b/src/phases/message-phase.ts @@ -61,12 +61,4 @@ export class MessagePhase extends Phase { ); } } - - end() { - if (globalScene.abilityBar.shown) { - globalScene.abilityBar.hide(); - } - - super.end(); - } } diff --git a/src/phases/pokemon-transform-phase.ts b/src/phases/pokemon-transform-phase.ts index 70b390dc6de..b33689321b5 100644 --- a/src/phases/pokemon-transform-phase.ts +++ b/src/phases/pokemon-transform-phase.ts @@ -5,6 +5,8 @@ import { EFFECTIVE_STATS, BATTLE_STATS } from "#enums/stat"; import { PokemonMove } from "#app/field/pokemon"; import { globalScene } from "#app/global-scene"; import { PokemonPhase } from "./pokemon-phase"; +import { getPokemonNameWithAffix } from "#app/messages"; +import i18next from "i18next"; /** * Transforms a Pokemon into another Pokemon on the field. @@ -62,6 +64,13 @@ export class PokemonTransformPhase extends PokemonPhase { globalScene.playSound("battle_anims/PRSFX- Transform"); } + globalScene.queueMessage( + i18next.t("abilityTriggers:postSummonTransform", { + pokemonNameWithAffix: getPokemonNameWithAffix(user), + targetName: target.name, + }), + ); + promises.push( user.loadAssets(false).then(() => { user.playAnim(); diff --git a/src/phases/show-ability-phase.ts b/src/phases/show-ability-phase.ts index 326b3a55ce3..1b3c6dde568 100644 --- a/src/phases/show-ability-phase.ts +++ b/src/phases/show-ability-phase.ts @@ -1,36 +1,60 @@ import { globalScene } from "#app/global-scene"; import type { BattlerIndex } from "#app/battle"; import { PokemonPhase } from "./pokemon-phase"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { HideAbilityPhase } from "#app/phases/hide-ability-phase"; export class ShowAbilityPhase extends PokemonPhase { private passive: boolean; + private pokemonName: string; + private abilityName: string; + private pokemonOnField: boolean; constructor(battlerIndex: BattlerIndex, passive = false) { super(battlerIndex); this.passive = passive; + + const pokemon = this.getPokemon(); + if (pokemon) { + // Set these now as the pokemon object may change before the queued phase is run + this.pokemonName = getPokemonNameWithAffix(pokemon); + this.abilityName = (passive ? this.getPokemon().getPassiveAbility() : this.getPokemon().getAbility()).name; + this.pokemonOnField = true; + } else { + this.pokemonOnField = false; + } } start() { super.start(); + if (!this.pokemonOnField || !this.getPokemon()) { + return this.end(); + } + + // If the bar is already out, hide it before showing the new one + if (globalScene.abilityBar.isVisible()) { + globalScene.unshiftPhase(new HideAbilityPhase(this.battlerIndex, this.passive)); + globalScene.unshiftPhase(new ShowAbilityPhase(this.battlerIndex, this.passive)); + return this.end(); + } + const pokemon = this.getPokemon(); - if (pokemon) { - if (!pokemon.isPlayer()) { - /** If its an enemy pokemon, list it as last enemy to use ability or move */ - globalScene.currentBattle.lastEnemyInvolved = pokemon.getBattlerIndex() % 2; - } else { - globalScene.currentBattle.lastPlayerInvolved = pokemon.getBattlerIndex() % 2; - } - - globalScene.abilityBar.showAbility(pokemon, this.passive); + if (!pokemon.isPlayer()) { + /** If its an enemy pokemon, list it as last enemy to use ability or move */ + globalScene.currentBattle.lastEnemyInvolved = pokemon.getBattlerIndex() % 2; + } else { + globalScene.currentBattle.lastPlayerInvolved = pokemon.getBattlerIndex() % 2; + } + globalScene.abilityBar.showAbility(this.pokemonName, this.abilityName, this.passive, this.player).then(() => { if (pokemon?.battleData) { pokemon.battleData.abilityRevealed = true; } - } - this.end(); + this.end(); + }); } } diff --git a/src/ui/ability-bar.ts b/src/ui/ability-bar.ts index 7fe9c0d8052..5481791de64 100644 --- a/src/ui/ability-bar.ts +++ b/src/ui/ability-bar.ts @@ -1,31 +1,33 @@ -import { getPokemonNameWithAffix } from "#app/messages"; import { globalScene } from "#app/global-scene"; -import type Pokemon from "../field/pokemon"; import { TextStyle, addTextObject } from "./text"; import i18next from "i18next"; -const hiddenX = -118; -const shownX = 0; +const barWidth = 118; +const screenLeft = 0; const baseY = -116; export default class AbilityBar extends Phaser.GameObjects.Container { - private bg: Phaser.GameObjects.Image; + private abilityBars: Phaser.GameObjects.Image[]; private abilityBarText: Phaser.GameObjects.Text; - - private tween: Phaser.Tweens.Tween | null; - private autoHideTimer: NodeJS.Timeout | null; - - public shown: boolean; + private player: boolean; + private screenRight: number; // hold screenRight in case size changes between show and hide + private shown: boolean; constructor() { - super(globalScene, hiddenX, baseY); + super(globalScene, barWidth, baseY); + this.abilityBars = []; + this.player = true; + this.shown = false; } setup(): void { - this.bg = globalScene.add.image(0, 0, "ability_bar_left"); - this.bg.setOrigin(0, 0); - - this.add(this.bg); + for (const key of ["ability_bar_right", "ability_bar_left"]) { + const bar = globalScene.add.image(0, 0, key); + bar.setOrigin(0, 0); + bar.setVisible(false); + this.add(bar); + this.abilityBars.push(bar); + } this.abilityBarText = addTextObject(15, 3, "", TextStyle.MESSAGE, { fontSize: "72px", @@ -33,72 +35,80 @@ export default class AbilityBar extends Phaser.GameObjects.Container { this.abilityBarText.setOrigin(0, 0); this.abilityBarText.setWordWrapWidth(600, true); this.add(this.abilityBarText); + this.bringToTop(this.abilityBarText); this.setVisible(false); - this.shown = false; + this.setX(-barWidth); // start hidden (right edge of bar at x=0) } - showAbility(pokemon: Pokemon, passive = false): void { - this.abilityBarText.setText( - `${i18next.t("fightUiHandler:abilityFlyInText", { pokemonName: getPokemonNameWithAffix(pokemon), passive: passive ? i18next.t("fightUiHandler:passive") : "", abilityName: !passive ? pokemon.getAbility().name : pokemon.getPassiveAbility().name })}`, - ); + public override setVisible(value: boolean): this { + this.abilityBars[+this.player].setVisible(value); + this.shown = value; + return this; + } - if (this.shown) { - return; + public async startTween(config: any, text?: string): Promise { + this.setVisible(true); + if (text) { + this.abilityBarText.setText(text); } + return new Promise(resolve => { + globalScene.tweens.add({ + ...config, + onComplete: () => { + if (config.onComplete) { + config.onComplete(); + } + resolve(); + }, + }); + }); + } + public async showAbility(pokemonName: string, abilityName: string, passive = false, player = true): Promise { + const text = `${i18next.t("fightUiHandler:abilityFlyInText", { pokemonName: pokemonName, passive: passive ? i18next.t("fightUiHandler:passive") : "", abilityName: abilityName })}`; + this.screenRight = globalScene.scaledCanvas.width; + if (player !== this.player) { + // Move the bar if it has changed from the player to enemy side (or vice versa) + this.setX(player ? -barWidth : this.screenRight); + this.player = player; + } globalScene.fieldUI.bringToTop(this); - this.y = baseY + (globalScene.currentBattle.double ? 14 : 0); - this.tween = globalScene.tweens.add({ - targets: this, - x: shownX, - duration: 500, - ease: "Sine.easeOut", - onComplete: () => { - this.tween = null; - this.resetAutoHideTimer(); - }, - }); + let y = baseY; + if (this.player) { + y += globalScene.currentBattle.double ? 14 : 0; + } else { + y -= globalScene.currentBattle.double ? 28 : 14; + } - this.setVisible(true); - this.shown = true; + this.setY(y); + + return this.startTween( + { + targets: this, + x: this.player ? screenLeft : this.screenRight - barWidth, + duration: 500, + ease: "Sine.easeOut", + hold: 1000, + }, + text, + ); } - hide(): void { - if (!this.shown) { - return; - } - - if (this.autoHideTimer) { - clearInterval(this.autoHideTimer); - } - - if (this.tween) { - this.tween.stop(); - } - - this.tween = globalScene.tweens.add({ + public async hide(): Promise { + return this.startTween({ targets: this, - x: -91, - duration: 500, + x: this.player ? -barWidth : this.screenRight, + duration: 200, ease: "Sine.easeIn", onComplete: () => { - this.tween = null; this.setVisible(false); }, }); - - this.shown = false; } - resetAutoHideTimer(): void { - if (this.autoHideTimer) { - clearInterval(this.autoHideTimer); - } - this.autoHideTimer = setTimeout(() => { - this.hide(); - this.autoHideTimer = null; - }, 2500); + public isVisible(): boolean { + return this.shown; } } diff --git a/test/moves/secret_power.test.ts b/test/moves/secret_power.test.ts index 28dc7efc434..37f1664251b 100644 --- a/test/moves/secret_power.test.ts +++ b/test/moves/secret_power.test.ts @@ -68,7 +68,7 @@ describe("Moves - Secret Power", () => { await game.classicMode.startBattle([Species.BLASTOISE, Species.CHARIZARD]); const sereneGraceAttr = allAbilities[Abilities.SERENE_GRACE].getAttrs(MoveEffectChanceMultiplierAbAttr)[0]; - vi.spyOn(sereneGraceAttr, "apply"); + vi.spyOn(sereneGraceAttr, "canApply"); game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY); game.move.select(Moves.FIRE_PLEDGE, 1, BattlerIndex.ENEMY_2); @@ -86,8 +86,8 @@ describe("Moves - Secret Power", () => { await game.phaseInterceptor.to("BerryPhase", false); - expect(sereneGraceAttr.apply).toHaveBeenCalledOnce(); - expect(sereneGraceAttr.apply).toHaveLastReturnedWith(true); + expect(sereneGraceAttr.canApply).toHaveBeenCalledOnce(); + expect(sereneGraceAttr.canApply).toHaveLastReturnedWith(true); expect(rainbowEffect.apply).toHaveBeenCalledTimes(0); });