From a027c98cd9b0acb7bb1da219f1d0a87910d6ea27 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Mon, 6 Jan 2025 23:08:33 +0100 Subject: [PATCH 01/13] update player controller --- charmap.txt | 1 + graphics/types/battle_icons1.pal | 15 + graphics/types/battle_icons1.png | Bin 0 -> 354 bytes graphics/types/battle_icons2.pal | 15 + graphics/types/battle_icons2.png | Bin 0 -> 372 bytes graphics/types/bug.png | Bin 0 -> 204 bytes graphics/types/contest_beauty.png | Bin 0 -> 224 bytes graphics/types/contest_cool.png | Bin 0 -> 213 bytes graphics/types/contest_cute.png | Bin 0 -> 214 bytes graphics/types/contest_smart.png | Bin 0 -> 223 bytes graphics/types/contest_tough.png | Bin 0 -> 217 bytes graphics/types/dark.png | Bin 0 -> 219 bytes graphics/types/dragon.png | Bin 0 -> 223 bytes graphics/types/electric.png | Bin 0 -> 227 bytes graphics/types/fairy.png | Bin 0 -> 324 bytes graphics/types/fight.png | Bin 0 -> 227 bytes graphics/types/fire.png | Bin 0 -> 216 bytes graphics/types/flying.png | Bin 0 -> 229 bytes graphics/types/ghost.png | Bin 0 -> 233 bytes graphics/types/grass.png | Bin 0 -> 230 bytes graphics/types/ground.png | Bin 0 -> 231 bytes graphics/types/ice.png | Bin 0 -> 208 bytes graphics/types/move_types_1.pal | 19 + graphics/types/move_types_2.pal | 19 + graphics/types/move_types_3.pal | 19 + graphics/types/mystery.png | Bin 0 -> 215 bytes graphics/types/none.png | Bin 0 -> 215 bytes graphics/types/normal.png | Bin 0 -> 221 bytes graphics/types/poison.png | Bin 0 -> 236 bytes graphics/types/psychic.png | Bin 0 -> 234 bytes graphics/types/rock.png | Bin 0 -> 220 bytes graphics/types/steel.png | Bin 0 -> 221 bytes graphics/types/stellar.png | Bin 0 -> 5861 bytes graphics/types/water.png | Bin 0 -> 218 bytes include/battle_controllers.h | 14 +- include/battle_main.h | 1 + include/graphics.h | 5 + include/item.h | 5 +- include/item_menu.h | 2 +- include/line_break.h | 33 + include/party_menu.h | 2 +- include/pokemon.h | 1 + include/type_icons.h | 18 + src/battle_controller_link_opponent.c | 2 +- src/battle_controller_link_partner.c | 2 +- src/battle_controller_oak_old_man.c | 4 +- src/battle_controller_opponent.c | 2 +- src/battle_controller_player.c | 711 ++++++++++++++-------- src/battle_controller_player_partner.c | 2 +- src/battle_controller_pokedude.c | 2 +- src/battle_controller_recorded_opponent.c | 2 +- src/battle_controller_recorded_player.c | 2 +- src/battle_controller_safari.c | 2 +- src/data/items.h | 5 + src/graphics.c | 5 + src/item.c | 5 + src/item_menu.c | 10 +- src/line_break.c | 281 +++++++++ src/party_menu.c | 12 +- src/pokemon.c | 8 + src/tm_case.c | 2 +- src/type_icons.c | 552 +++++++++++++++++ 62 files changed, 1508 insertions(+), 272 deletions(-) create mode 100644 graphics/types/battle_icons1.pal create mode 100644 graphics/types/battle_icons1.png create mode 100644 graphics/types/battle_icons2.pal create mode 100644 graphics/types/battle_icons2.png create mode 100644 graphics/types/bug.png create mode 100644 graphics/types/contest_beauty.png create mode 100644 graphics/types/contest_cool.png create mode 100644 graphics/types/contest_cute.png create mode 100644 graphics/types/contest_smart.png create mode 100644 graphics/types/contest_tough.png create mode 100644 graphics/types/dark.png create mode 100644 graphics/types/dragon.png create mode 100644 graphics/types/electric.png create mode 100644 graphics/types/fairy.png create mode 100644 graphics/types/fight.png create mode 100644 graphics/types/fire.png create mode 100644 graphics/types/flying.png create mode 100644 graphics/types/ghost.png create mode 100644 graphics/types/grass.png create mode 100644 graphics/types/ground.png create mode 100644 graphics/types/ice.png create mode 100644 graphics/types/move_types_1.pal create mode 100644 graphics/types/move_types_2.pal create mode 100644 graphics/types/move_types_3.pal create mode 100644 graphics/types/mystery.png create mode 100644 graphics/types/none.png create mode 100644 graphics/types/normal.png create mode 100644 graphics/types/poison.png create mode 100644 graphics/types/psychic.png create mode 100644 graphics/types/rock.png create mode 100644 graphics/types/steel.png create mode 100644 graphics/types/stellar.png create mode 100644 graphics/types/water.png create mode 100644 include/line_break.h create mode 100644 include/type_icons.h create mode 100644 src/line_break.c create mode 100644 src/type_icons.c diff --git a/charmap.txt b/charmap.txt index 1c0367e7c..71e7a3aec 100644 --- a/charmap.txt +++ b/charmap.txt @@ -45,6 +45,7 @@ SUPER_ER = 2C LV = 34 '=' = 35 ';' = 36 +V_D_ARROW = 38 '¿' = 51 '¡' = 52 PK = 53 diff --git a/graphics/types/battle_icons1.pal b/graphics/types/battle_icons1.pal new file mode 100644 index 000000000..972dfd02a --- /dev/null +++ b/graphics/types/battle_icons1.pal @@ -0,0 +1,15 @@ +JASC-PAL +0100 +12 +120 152 128 +49 49 49 +255 255 255 +164 82 57 +172 189 32 +184 160 90 +213 180 90 +98 98 180 +180 90 164 +172 164 148 +172 172 197 +152 172 246 diff --git a/graphics/types/battle_icons1.png b/graphics/types/battle_icons1.png new file mode 100644 index 0000000000000000000000000000000000000000..c47b07f1171a309220fe403e7ed17b544dce61b2 GIT binary patch literal 354 zcmeAS@N?(olHy`uVBq!ia0vp^96-E)gBeJ&&AV#_q!^2X+?^QKos)S9f0+Ah^6AeDr5qSvozYT0U{!x$`s_r#^L~O? zW`;68@OaH&_v*B4*$Iv5&s|*w(yuXeG{_swkC``BYN3?2$6ECzR%;a2T$7x3-fpK2 zw`)VQ%vH99|B6*k<|Py^@Yg%OV literal 0 HcmV?d00001 diff --git a/graphics/types/battle_icons2.pal b/graphics/types/battle_icons2.pal new file mode 100644 index 000000000..bddf49ad9 --- /dev/null +++ b/graphics/types/battle_icons2.pal @@ -0,0 +1,15 @@ +JASC-PAL +0100 +12 +120 152 128 +49 49 49 +255 255 255 +240 82 48 +120 200 80 +248 197 49 +80 120 136 +123 98 230 +248 115 164 +57 156 255 +90 205 230 +246 180 246 diff --git a/graphics/types/battle_icons2.png b/graphics/types/battle_icons2.png new file mode 100644 index 0000000000000000000000000000000000000000..44aa4f89547f478a290231112e03bd84f350a08e GIT binary patch literal 372 zcmeAS@N?(olHy`uVBq!ia0vp^96-E)gBeJ&&AV#_q!^2X+?^QKos)S9%Lb!>Ej>Uc_m{DK*PN@0NW zNPrqp{F$eVV~9oX*+~b5njCnX4YfG_{QrMTEphh)*Y7EA%lmU~y*2PL&)#)cl~Kxp z!IERaWLAYID;xWC%9j?$eC*AdA1ZV};4{aCCrl!1c&{l7|6f;|Grv9M#7Uhdjs6y$ zGhY@M>?)gc>-e`yFYyM(vV;e(KVEcyW|W>Ye|kyVjwuaK7z8*qp3hmScV6;#`s8yB zY&Rw}_zHyodQqSi96QT++j%9)ga_;kyc`1Lo)&ZKm)+^(*_kc*uP*H+Qv<_C?~dro zBk$AS%{>(|{aMf3&E9MR8$NG+Qmi1Wad_8vzv-E=vp%1;t6yfmv6;^}dj^LH(8mm( Lu6{1-oD!M!|EvlSxcrApWUL6l>}7QTwVPC|9^8=`D;KbP0l+XkK`G`ub literal 0 HcmV?d00001 diff --git a/graphics/types/contest_beauty.png b/graphics/types/contest_beauty.png new file mode 100644 index 0000000000000000000000000000000000000000..b52fe3ca47a7eeab2f51191b2899c95ab3b3395e GIT binary patch literal 224 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!VDx^^%AmxltF+`h%1mjd-VUBDc_2t=44Iz zHs{{GtN-75SqA-&>i&Op%ao*~C5}t(HSe7=Wl3{&@&Et-cbFcu1?tK6ba4!kn3~$Z zk?*hqkIUYav*8m(%QODlA3pos-s1YgiCQO^bqXIv9?MDn?X&02T{XUJ?rTAD(R@pn zaEUmEH8$-(z`Qu7zeM}QANJ`@3oV+uA4zzHRHuL9J8{lRp=#|n8J^F3Z=dV@{PDMb Y;MP{&cNw)hKx-L1UHx3vIVCg!0Nf>D6aWAK literal 0 HcmV?d00001 diff --git a/graphics/types/contest_cool.png b/graphics/types/contest_cool.png new file mode 100644 index 0000000000000000000000000000000000000000..f0ca72323009e51795bd13a6f23e53f22d291b8b GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!VDx^^%AmxltF+`h%1o(f7S3?v*A%g&1Xlm z_AasP&NBS}zk1D@>U;N&7Dst`Ia==Bdljgxxw`oO|NkCw+!8=ef~SjPh{V*^^9MN_ z40u`}c5ttdmU!R!;@|0%hLq-TQLR~3AM9CvIVz}Ty*_ruL3nxEqh;J8F+K~+n3ZIn zS2!GEsAYUDpRrl!!=pxx6$>t9QU(A3 literal 0 HcmV?d00001 diff --git a/graphics/types/contest_cute.png b/graphics/types/contest_cute.png new file mode 100644 index 0000000000000000000000000000000000000000..eeb86c431be05f1289f2322bd99691e3ee7992db GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!VDx^^%AmxltF+`h%1mjd-VUBDc_2t=44Iz zHs{{GtN-75SqA-&>i&Op%ao*~C5}t(HSe7=Wl3{&@&Et-cbFcu1?oxkba4!kn3~#e z$k*V&!IJs)X+~j0R(fWQr0Ac7k3Kw{&r5u6=m_-sxF;^2%gz1qfHun_4wo0|57rel zFU^Skvb3k+sc56)fuIutg%J_`Dc;6rxmh=Z_;;K Mr>mdKI;Vst01C=i{r~^~ literal 0 HcmV?d00001 diff --git a/graphics/types/contest_smart.png b/graphics/types/contest_smart.png new file mode 100644 index 0000000000000000000000000000000000000000..7659cc4f291c987aa09c8c80dbb435e32da30535 GIT binary patch literal 223 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!VDx^^%AmxltF+`h%1mj`ah}qY*19QW3lCb zFUu)=m;7I|SK;0>!|EvlSxcrApWUL6l>}7QTwVPC|9^8=`D;KU;N&7Dst`Ia==Bdljgxxw`oO|NkCw+!8=eil>WXh{V*?{*Am1 z4jitTJ*KT2t-~%IvfWY?C)U7wKscG_N7wuh94ri4k7wR^c;E<6#EV0{JwG}Hw3eL` z6MXdU9@9#W@bgZ;bA-OU4GU;N&7Dst`Ia==Bdljgxxw`oO|NkCw+!8=enx~6nh{V*?en-9r z1s;}alaH6>di4!W1<(IlEO&}uOj~G!1t+ghL{vvr+fBoZhx(@Ocr3^{M@5mN%b|x$ z+n42bbmt|PCf5VLPfmPy>(j`Z9)86=w0z^zMXo;%`qkgd*dufN{daSYrOPZ7g)~9V OXYh3Ob6Mw<&;$U(mr!|EvlSxcrApWUL6l>}7QTwVPC|9^8=`D;KBD<6WO`n?!TA6JF87~ T$xb~ppsfs^u6{1-oD!MU;N&7Dst`Ia==Bdljgxxw`oO|NkCw+!8=eo~Mgrh{V*?ervu4 z1p$}shSx-n@vU3Z`u)PG&*xaDNx!lBp&2HZA`~}+x8slG`2%|HTxTZLc@(WrXgGaG z!$(shE4Num^v*)oFpW7sT@FTPntu`7m=u3h`}po(=Faj9PF(2umzZtiZ&U>cv7h@-A}f$@5a1I6GVbir|7)gvD~_6zHRao!d-tyXf9GWx^gpWm|IsZ|l9HA< zF1gpdcgmC{&DF*K|Nq}%de9cAhcU_9-G!lpRn`N@$?$Y>45^rt+JBI@!GObcr_}WC zS&sznl`N{|^g;(q*d+2d1&6s;k!3 zmWe;D>Xeo|TC~LJ$ZowOOS*kJjg5t$YaL2_ZgJm0p85Ct-|S|ScKG!D$~y$Klfl!~ K&t;ucLK6T1m2+kQ literal 0 HcmV?d00001 diff --git a/graphics/types/fight.png b/graphics/types/fight.png new file mode 100644 index 0000000000000000000000000000000000000000..95ff5a9281fbcf044378cad52b4cec504b3278a5 GIT binary patch literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!VDx^^%AmxltF+`h%1o(f7S3?v*A%g&1Xlm z_AasP&NBS}zk1D@>U;N&7Dst`Ia==Bdljgxxw`oO|NkCw+!8=eo~Mgrh{V*?{w@$d%)&aF8=PJhG%j1V!lTag zpw1elC5L<`OrQ2RwmU#lyqZN^QEsapyJYv8e1mz7f4Bc- Xy_t}fF3EorU;N&7Dst`Ia==Bdljgxxw`oO|NkCw+!8=evZsq0uvPhP+h`Gl^I3W_mBngYE(*$E4KnXNxIbjO?tx1GfxvW&|_ zu{1iYQuySf&M!;2{GXT$>V>(^pVY#r@i&Op%ao*~C5}t(HSe7=Wl3{&@&Et-cbFcu1?nmAba4!kn3{V2 zB5#8N56cB9@c{D;|C%rUo&J*HI&V~TQqqCn3J(u1budYb+O4ytaQfT|j*YvyX77v? zozCFQ+`9UZ&3$L?7MiwA_z^}XJfCDVfCpsWl5JcjFhUREcc!|EvlSxcrApWUL6l>}7QTwVPC|9^8=`D;KwA0~qr)qP`8Q0&@2E?5s@Jo)7@v;2@#4WDPn(Oa4o<9dQaN@= z&s(G!Au{3K198WSjF#4_&J_!7C;qE;k%;$v=#iM%CvtYyt%_SZ=|0`DTk9|W(%kcZ b-G0UeU*jtTL#(a>Eobm_^>bP0l+XkK9Ryj= literal 0 HcmV?d00001 diff --git a/graphics/types/ground.png b/graphics/types/ground.png new file mode 100644 index 0000000000000000000000000000000000000000..d3f6787b29a0a580e5e184a1f3ce4522ac832ac0 GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!VDx^^%AmxltF+`h%1o(f7S3?v*A%g&1Xlm z_AasP&NBS}zk1D@>U;N&7Dst`Ia==Bdljgxxw`oO|NkCw+!8=ek*AAeh{V*?enY+% z10I&`yME6oE%_*}Az;dSsrJU#U+jFxOjwphIei~i26+Ea&3dA@Dtv>>Yo65Q?st;}q-I~dHFL=x`E5O~ax literal 0 HcmV?d00001 diff --git a/graphics/types/ice.png b/graphics/types/ice.png new file mode 100644 index 0000000000000000000000000000000000000000..5ff2f69aa7845da1ad97254ac48f73a06e2b06ee GIT binary patch literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!VDx^^%AmxltF+`h%1mjd-VUBDc_2t=44Iz zHs{{GtN-75SqA-&>i&Op%ao*~C5}t(HSe7=Wl3{&@&Et-cbFcu1?q|Rba4!kn3~$J zDAW+Z;o@o5-|oBdMWwErvS|K>4z||!w~x%e$=DIKYpcQKL#>TF9tu8^Dy%))a+%>b zi}RHUTH6!cl@mf0!jI@q+CIbW)3ll!anC3ITD;-!zWofFkL8{BubkZmw1&ac)z4*} HQ$iB}#qe1+ literal 0 HcmV?d00001 diff --git a/graphics/types/move_types_1.pal b/graphics/types/move_types_1.pal new file mode 100644 index 000000000..951aa69cb --- /dev/null +++ b/graphics/types/move_types_1.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +0 0 0 +255 213 49 +246 131 49 +197 49 41 +230 197 106 +189 164 57 +139 106 49 +255 255 123 +172 172 123 +222 222 197 +115 90 74 +74 65 57 +189 189 213 +0 0 0 +131 123 115 +255 255 255 diff --git a/graphics/types/move_types_2.pal b/graphics/types/move_types_2.pal new file mode 100644 index 000000000..08dcea47c --- /dev/null +++ b/graphics/types/move_types_2.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +0 0 0 +205 197 255 +172 148 246 +115 90 156 +106 148 246 +156 222 222 +213 255 238 +74 57 82 +255 90 139 +255 197 180 +148 98 98 +164 65 164 +222 131 189 +148 148 164 +131 123 115 +255 255 255 diff --git a/graphics/types/move_types_3.pal b/graphics/types/move_types_3.pal new file mode 100644 index 000000000..4db37235b --- /dev/null +++ b/graphics/types/move_types_3.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +0 0 0 +197 255 98 +123 205 82 +90 131 65 +115 57 255 +74 57 148 +189 164 255 +172 189 32 +222 230 49 +123 148 16 +106 164 148 +115 205 180 +32 106 98 +0 0 0 +131 123 115 +255 255 255 diff --git a/graphics/types/mystery.png b/graphics/types/mystery.png new file mode 100644 index 0000000000000000000000000000000000000000..a2ea01d556a3d6b1a638c078c3dc702e1013b9bf GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!VDx^^%AmxltF+`h%1mj`ah}qY*19QW3lCb zFUu)=m;7I|SK;0>!|EvlSxcrApWUL6l>}7QTwVPC|9^8=`D;K&o zHRe)O$(h6=HMycCA;*6STa|sT!|EvlSxcrApWUL6l>}7QTwVPC|9^8=`D;K&o zHRe)O$(h6=HMycCA;*6STa|sTU;N&7Dst`Ia==Bdljgxxw`oO|NkCw+!8=ehNp{Th{V*?enY+n z0}j{7uTQQz%9IwH%i&Op%ao*~C5}t(HSe7=Wl3{&@&Et-cbFcu1?nmHba4!kn3~#e z$j7Y6!*X}&$>hti6Wf>G;JBo2?-*tOV9D1+Z_ORjiIH*!Y@3b0-#>JGUqpqppM+C~ z;H#Ne+8y78tdo4Gx$AkK!D5#cEz3imaDEdx`&U08>Ac@n*^GlX)!DMS82L6C21{RW kx4r%=b$jl^!k>Q`Q%$$bxLT}o4(J31Pgg&ebxsLQ0L;8&#sB~S literal 0 HcmV?d00001 diff --git a/graphics/types/psychic.png b/graphics/types/psychic.png new file mode 100644 index 0000000000000000000000000000000000000000..975d1fb553b1abdb287a6b63b496049766c62680 GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!VDx^^%AmxltF+`h%1mjd-VUBDc_2t=44Iz zHs{{GtN-75SqA-&>i&Op%ao*~C5}t(HSe7=Wl3{&@&Et-cbFcu1?nmFba4!kn3~#e z$mit9;gb3F$zs-stn^G9$*Tp-*ACuz^IcSBPl{SX*^@6fcHESe7C+2*IBU(DzP>9H zUTAGwF=^eD4lj=%9OpX=lzJnigcWaiDgF@VsNq%@y382gqa#|jm4$KH^2?L`{>Xp3 i^?mi+`_kw4zqhyLnHSNt>8U)>0Sun5elF{r5}E*RCSx=J literal 0 HcmV?d00001 diff --git a/graphics/types/rock.png b/graphics/types/rock.png new file mode 100644 index 0000000000000000000000000000000000000000..3793597f94d29e898af980f3f64a74e3d97b6b27 GIT binary patch literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!VDx^^%AmxltF+`h%1o(f7S3?v*A%g&1Xlm z_AasP&NBS}zk1D@>U;N&7Dst`Ia==Bdljgxxw`oO|NkCw+!8=ex~Gd{h{V*?enY+n z0}fZop65juq&t!eFU~GsYW`zt*5$TeY)e7%6VnzkN((ywHIov&)xsZpYW{Evfum5 Q9iWvAp00i_>zopr0Cz%Hc>n+a literal 0 HcmV?d00001 diff --git a/graphics/types/steel.png b/graphics/types/steel.png new file mode 100644 index 0000000000000000000000000000000000000000..29748639c5d345adfdba463631daf0462f309394 GIT binary patch literal 221 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!VDx^^%AmxltF+`h%1o(f7S3?v*A%g&1Xlm z_AasP&NBS}zk1D@>U;N&7Dst`Ia==Bdljgxxw`oO|NkCw+!8=ehNp{Th{V*?en+kb z2M*V}+g`rOZPpXvc`RzxP@^w!f62;(W$g-fKUOFyU%s{RM3_~XCbQ-gDY>44?4~{) zf%zwbPA}^(SjNGn7*m)I%Fdbd!FC@yYKt=+|Tnq?;aPYHL7qu zI0OPwr8(HSfp-LW&Q+KVUU#7bf*}wk!zd3Qi5o+T5Q+pGZYY3|L<#`}Amef%5ZS}C zJ|PjKWca7^o{btRutlgfx5XT#s}q;%BTg=({e5tq^h3MXDCEXfL^gKn<6HPtRf=cI z+*Z*tlZ9io8gsk}!(o&CTmPE(UOY9XSKWj8wEYcq^}$D|=f@};M&53Xf{{0Ap|)sb zj1%u{R9gGTljqK{==2+?;dd1Z`yKZUQdS&{iQ*49Ea@20erVOx*G;o|`zR%IQ`6+| z#j0rA+%=i``wV0yH(DS=mcJBUaSbzHng)A_)OFq;?I^65ZlxYAf**5@EVIc?>xn_W z%$|2=sK0SkwyneYW8svBPI=-ng5!0+iHAMCajv(W-bJ5Ht??V_+>oSiS3I>!Q!NX~>)leP_n<}~~^!5%x4yNt%w3d=c<+!y_}*rftG%k3%Dl#=jkO!|XxR?^+04YvYGBJCI# z8Z+jUgQC~GJ*pEIGOKb==ec^OXK_$|=_fJ?C)t0dZz5g@3jVXPMC**Ns4>gEJlht1 zNgEyeq+p4b>7@)e(+n?%b3PkzxovfHztD$nr3d`EzwfZIj(A<@e>?Z!MkRIK`uU4h z^&>M}jp;7jx&dEYC|*l<9+z0y8TJb zE2K_|3ma{gS?UI#51gYsaYZU44R*XY2`Y>&hb4IJoD1aetC!9+sdW&vE-!x(J>(i8tp5a7BDg%EQ9l0s&leA@=_*EZ=(5*brtv=Tt z(5<0=wKX(g?CplFIXP?R;89Zr4(f~tgsjjh}$9}?QPfA zJgeC0t$CU!%M=IQK+&zvuw`n#HC&3H|L-pp*BvIZJ~}!6@oBbi<|^xGYWt*$dR%bB zfaLiST?p)b_x;f0tnvEQR(=bc`>IR*?S{)7TVc08D95R~3RJa{yWFH}cMKKJd8)y# zdIjz16Lv7J2HV9496sz7qt$sZ#S{IPeqvy5w=ljFFQ)2i(Fm7|XBjIwA8v6!w$f<5 znqX7W$b_o!;9oZkOwZnf9zgoOE7?0gIr|OSj{ZVDy32z-PE`3|F!W2sVaghwSd#OL z;Hh1cZc^6ZDGSF#3+_BNcIdO)Qu|TApe8DARM|YIN&i&>ET(!wc(-=;X2bZ!`g*;r zX4jjJ`-D~VPUqjf-)61$sK8XEv8FOYCtv`!L#Pqi7TZ*1p0BidTPF_3i@(}=WOtXU zIz=$YBBD3SRwqEWa=-7%E74(@HQaGCRI%pG$ak-;E}c|8>e04ruF4YSn|^e~@OR$N z*4z2??TGe?ozyuPID4OyQ&YWqceBC1Ymosh&yrtP zgjP3^+cZidlSgFD=gGQtFA82!o3l!~6xUlgJl^{{qR!%NyCGltZur5-IO=$MW-jOK zr?qp(VUV;+H7z(6q8fZx$ba!XJBqc5sgI3WMc%ZA?bg z0Kb+RyJ-BKa_5He&X(i3d-Y=TbV=3sCXPV~My!pQPmdf5y?bupPLXBmr2tJ1apLtY zao2s%9y9pzmiK|-;A+%r8U8r%<75$fVr35n=G14did~d7bm^YDf5VwiQ_%C}R&l-Y zLOuin-Nm)Fb)nhXe)&>@-^c7Nsn!lPD|B}EoLXzYOwDUvSiQ>;v-pJgbdL)#?X~{7 zo=WMCQ#mx-wBFv|DzptIe2b_R9BQ|02T1$3~Wy>0K=4dPzZHV}gB(7p?58S<1B05U8Gt++P!)JLB zJbF!fi}QjrFzoeSWI>o$gJ;_x#@iU!{Ie%2oI-SPW{Z*)?CJ~hcH+(Kg6=!uQcsK& z#BHk|GOk~eenw$+vZ6=MD$&HFZG%@Xa<+=9>G0Ltn-_FU>Of~*S#g}x(Q~uBiwvE( zUAez)*t@^7(fH->2efTwMP1yUIB;O;Tj)W{%17yF-L%CYxXK@_2Dh&6$x!^r-~NVp zQP3pLwt;Z_TZdJJLfBsI-=e$vx;DJtGJf&YgX>0r_KR*c7-6O0mPUsQZe4un>!>UN z56xf;m;hSF6M|bC2*hf+Ovqq`01^Zf2;}muk#DbDMIhm5d4!@Bj$|A>)Pe#Z;L!a+;S4KFgaiNW?Tm5@Lq0 zjEo_~;LunMkB9lzLM*Y507+&7`d16F2e<>oxB+58xQGSVM*w`u;%_O~tgrUMa8c-V zI&2mO2nBc`R1A8>edlrwjqdW*LM}ldmnWRI0>%CgDdBSd5$n6yaU8{+0JT z^q1VH!61rGr`icv;qvfkcGgI_e=1wR;ieNz`pqOkT4n-ufu`C=G z%OIO$zoBpzalxu&gnk>9oQe%nu?ZZa1&ho?Q5a+via^3qPz)BpMwt@{L<)<+?Nmp@Qjv(lX?g3KC4W zgV|7RMF2x05P1j$q1H%w2nf05bb%wRJ`alnR}3N|_p6n0NB%xK)cUftRMzI5CCWROi6ud=l;uZVF89YhlB&=<&eoJ0)xy(k>yVu zGC;6k0vsYZmfy3B1ssW#Ap%wgf|-KZfF(4Y4dS;MF-^Y5OM?KpQdm3zg~g-rcn_R8 z)tpQv5|NmhWHItN{Uuu~%zx=&H4XS?5diHzw}FcbxK?4lE><&o$tC#br(8dzzz>0cR@YCten^2I0{^V8|CwCye|~oWKDYytfn zorgVmubpB>H@W%kSShAVt)*mKJuy{u718|+7o9OT_(X=dsSFX!1YtX(#ZyyLBzvPa z@I_hZ;46ke=FFF$P)Js`4%nz9q0#M?Ud+)E>6&*R!NGra`4m!7Oz)UTVeJ1K&nxyLeIQNs|DC_*T9A~>FvL`CyA zQmwS=RP#}KLdepOOY?({oq*YG2v1~&)*2>EZY~1y7(5@F`i&Op%ao*~C5}t(HSe7=Wl3{&@&Et-cbFcu1?oxlba4!kn3~#e z$ag@2!!>f(w~(@{d~g3+8`S4BC~fpys4w*Rvi}5)&379ouM@IZq2l9_oGN;C-5!_r z8%{{wk{_q~Fmc&%X+c8THTFlda%VD$sK7Y7O%{D!K S#lt`g89ZJ6T-G@yGywoXgbufferA[battler][0] < NELEMS(sPlayerBufferCommands)) + if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sPlayerBufferCommands)) sPlayerBufferCommands[gBattleResources->bufferA[battler][0]](battler); else PlayerBufferExecCompleted(battler); @@ -240,6 +253,11 @@ static void HandleInputChooseAction(u32 battler) DoBounceEffect(battler, BOUNCE_HEALTHBOX, 7, 1); DoBounceEffect(battler, BOUNCE_MON, 7, 1); + if (JOY_REPT(DPAD_ANY) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) + gPlayerDpadHoldFrames++; + else + gPlayerDpadHoldFrames = 0; + if (B_LAST_USED_BALL == TRUE && B_LAST_USED_BALL_CYCLE == TRUE) { if (!gLastUsedBallMenuPresent) @@ -305,16 +323,16 @@ static void HandleInputChooseAction(u32 battler) switch (gActionSelectionCursor[battler]) { - case 0: + case 0: // Top left BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_USE_MOVE, 0); break; - case 1: + case 1: // Top right BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_USE_ITEM, 0); break; - case 2: + case 2: // Bottom left BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_SWITCH, 0); break; - case 3: + case 3: // Bottom right BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_RUN, 0); break; } @@ -360,16 +378,16 @@ static void HandleInputChooseAction(u32 battler) ActionSelectionCreateCursorAt(gActionSelectionCursor[battler], 0); } } - else if (JOY_NEW(B_BUTTON)) + else if (JOY_NEW(B_BUTTON) || gPlayerDpadHoldFrames > 59) { - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle() && GetBattlerPosition(battler) == B_POSITION_PLAYER_RIGHT - && !(gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)]) + && !(gAbsentBattlerFlags & (1u << GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { - if (gBattleResources->bufferA[battler][1] == B_ACTION_USE_ITEM) + // Return item to bag if partner had selected one (if consumable). + if (gBattleResources->bufferA[battler][1] == B_ACTION_USE_ITEM && ItemId_GetConsumability(itemId)) { - // Return item to bag if partner had selected one. AddBagItem(itemId, 1); } PlaySE(SE_SELECT); @@ -406,7 +424,7 @@ static void HandleInputChooseAction(u32 battler) } } -static void HandleInputChooseTarget(u32 battler) +void HandleInputChooseTarget(u32 battler) { s32 i; static const u8 identities[MAX_BATTLERS_COUNT] = {B_POSITION_PLAYER_LEFT, B_POSITION_PLAYER_RIGHT, B_POSITION_OPPONENT_RIGHT, B_POSITION_OPPONENT_LEFT}; @@ -420,6 +438,11 @@ static void HandleInputChooseTarget(u32 battler) EndBounceEffect(i, BOUNCE_HEALTHBOX); } + if (JOY_HELD(DPAD_ANY) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) + gPlayerDpadHoldFrames++; + else + gPlayerDpadHoldFrames = 0; + if (JOY_NEW(A_BUTTON)) { PlaySE(SE_SELECT); @@ -433,7 +456,7 @@ static void HandleInputChooseTarget(u32 battler) HideGimmickTriggerSprite(); PlayerBufferExecCompleted(battler); } - else if (JOY_NEW(B_BUTTON)) + else if (JOY_NEW(B_BUTTON) || gPlayerDpadHoldFrames > 59) { PlaySE(SE_SELECT); gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCB_HideAsMoveTarget; @@ -485,7 +508,7 @@ static void HandleInputChooseTarget(u32 battler) break; } - if (gAbsentBattlerFlags & gBitTable[gMultiUsePlayerCursor] + if (gAbsentBattlerFlags & (1u << gMultiUsePlayerCursor) || !CanTargetBattler(battler, gMultiUsePlayerCursor, move)) i = 0; } while (i == 0); @@ -535,7 +558,7 @@ static void HandleInputChooseTarget(u32 battler) break; } - if (gAbsentBattlerFlags & gBitTable[gMultiUsePlayerCursor] + if (gAbsentBattlerFlags & (1u << gMultiUsePlayerCursor) || !CanTargetBattler(battler, gMultiUsePlayerCursor, move)) i = 0; } while (i == 0); @@ -571,7 +594,7 @@ static void HideShownTargets(u32 battler) } } -static void HandleInputShowEntireFieldTargets(u32 battler) +void HandleInputShowEntireFieldTargets(u32 battler) { if (JOY_HELD(DPAD_ANY) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) gPlayerDpadHoldFrames++; @@ -599,7 +622,7 @@ static void HandleInputShowEntireFieldTargets(u32 battler) } } -static void HandleInputShowTargets(u32 battler) +void HandleInputShowTargets(u32 battler) { if (JOY_HELD(DPAD_ANY) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) gPlayerDpadHoldFrames++; @@ -657,13 +680,13 @@ void HandleInputChooseMove(u32 battler) if (gBattleStruct->zmove.viewing) { gBattleStruct->zmove.viewing = FALSE; - if (gMovesInfo[moveInfo->moves[gMoveSelectionCursor[battler]]].category != DAMAGE_CATEGORY_STATUS) + if (GetMoveCategory(moveInfo->moves[gMoveSelectionCursor[battler]]) != DAMAGE_CATEGORY_STATUS) moveTarget = MOVE_TARGET_SELECTED; //damaging z moves always have selected target } // Status moves turn into Max Guard when Dynamaxed, targets user. if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX || IsGimmickSelected(battler, GIMMICK_DYNAMAX)) - moveTarget = gMovesInfo[GetMaxMove(battler, moveInfo->moves[gMoveSelectionCursor[battler]])].target; + moveTarget = GetMoveTarget(GetMaxMove(battler, moveInfo->moves[gMoveSelectionCursor[battler]])); if (moveTarget & MOVE_TARGET_USER) gMultiUsePlayerCursor = battler; @@ -731,7 +754,7 @@ void HandleInputChooseMove(u32 battler) if (moveTarget & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED)) gMultiUsePlayerCursor = battler; - else if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)]) + else if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT))) gMultiUsePlayerCursor = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); else gMultiUsePlayerCursor = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); @@ -865,7 +888,7 @@ void HandleInputChooseMove(u32 battler) } else if (JOY_NEW(START_BUTTON)) { - if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE) + if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE && !HasTrainerUsedGimmick(battler, gBattleStruct->gimmick.usableGimmick[battler])) { gBattleStruct->gimmick.playerSelect ^= 1; ReloadMoveNames(battler); @@ -875,7 +898,6 @@ void HandleInputChooseMove(u32 battler) } } - static void ReloadMoveNames(u32 battler) { if (gBattleStruct->zmove.viable && !gBattleStruct->zmove.viewing) @@ -894,14 +916,65 @@ static void ReloadMoveNames(u32 battler) } } -static void HandleMoveSwitching(u32 battler) +static u32 UNUSED HandleMoveInputUnused(u32 battler) { - u8 perMovePPBonuses[4]; + u32 var = 0; + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + var = 1; + } + if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + gBattle_BG0_X = 0; + gBattle_BG0_Y = DISPLAY_HEIGHT * 2; + var = 0xFF; + } + if (JOY_NEW(DPAD_LEFT) && gMoveSelectionCursor[battler] & 1) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[battler]); + gMoveSelectionCursor[battler] ^= 1; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 0); + } + if (JOY_NEW(DPAD_RIGHT) && !(gMoveSelectionCursor[battler] & 1) + && (gMoveSelectionCursor[battler] ^ 1) < gNumberOfMovesToChoose) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[battler]); + gMoveSelectionCursor[battler] ^= 1; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 0); + } + if (JOY_NEW(DPAD_UP) && gMoveSelectionCursor[battler] & 2) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[battler]); + gMoveSelectionCursor[battler] ^= 2; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 0); + } + if (JOY_NEW(DPAD_DOWN) && !(gMoveSelectionCursor[battler] & 2) + && (gMoveSelectionCursor[battler] ^ 2) < gNumberOfMovesToChoose) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[battler]); + gMoveSelectionCursor[battler] ^= 2; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 0); + } + + return var; +} + +void HandleMoveSwitching(u32 battler) +{ + u8 perMovePPBonuses[MAX_MON_MOVES]; struct ChooseMoveStruct moveStruct; u8 totalPPBonuses; if (JOY_NEW(A_BUTTON | SELECT_BUTTON)) { + struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]); PlaySE(SE_SELECT); if (gMoveSelectionCursor[battler] != gMultiUsePlayerCursor) @@ -913,75 +986,89 @@ static void HandleMoveSwitching(u32 battler) i = moveInfo->moves[gMoveSelectionCursor[battler]]; moveInfo->moves[gMoveSelectionCursor[battler]] = moveInfo->moves[gMultiUsePlayerCursor]; moveInfo->moves[gMultiUsePlayerCursor] = i; + i = moveInfo->currentPp[gMoveSelectionCursor[battler]]; moveInfo->currentPp[gMoveSelectionCursor[battler]] = moveInfo->currentPp[gMultiUsePlayerCursor]; moveInfo->currentPp[gMultiUsePlayerCursor] = i; + i = moveInfo->maxPp[gMoveSelectionCursor[battler]]; moveInfo->maxPp[gMoveSelectionCursor[battler]] = moveInfo->maxPp[gMultiUsePlayerCursor]; moveInfo->maxPp[gMultiUsePlayerCursor] = i; - if (gDisableStructs[battler].mimickedMoves & gBitTable[gMoveSelectionCursor[battler]]) + + if (gDisableStructs[battler].mimickedMoves & (1u << gMoveSelectionCursor[battler])) { - gDisableStructs[battler].mimickedMoves &= (~gBitTable[gMoveSelectionCursor[battler]]); - gDisableStructs[battler].mimickedMoves |= gBitTable[gMultiUsePlayerCursor]; + gDisableStructs[battler].mimickedMoves &= ~(1u << gMoveSelectionCursor[battler]); + gDisableStructs[battler].mimickedMoves |= 1u << gMultiUsePlayerCursor; } + MoveSelectionDisplayMoveNames(battler); - for (i = 0; i < MAX_MON_MOVES; ++i) + + for (i = 0; i < MAX_MON_MOVES; i++) perMovePPBonuses[i] = (gBattleMons[battler].ppBonuses & (3 << (i * 2))) >> (i * 2); + totalPPBonuses = perMovePPBonuses[gMoveSelectionCursor[battler]]; perMovePPBonuses[gMoveSelectionCursor[battler]] = perMovePPBonuses[gMultiUsePlayerCursor]; perMovePPBonuses[gMultiUsePlayerCursor] = totalPPBonuses; + totalPPBonuses = 0; - for (i = 0; i < MAX_MON_MOVES; ++i) + for (i = 0; i < MAX_MON_MOVES; i++) totalPPBonuses |= perMovePPBonuses[i] << (i * 2); gBattleMons[battler].ppBonuses = totalPPBonuses; - for (i = 0; i < MAX_MON_MOVES; ++i) + + for (i = 0; i < MAX_MON_MOVES; i++) { gBattleMons[battler].moves[i] = moveInfo->moves[i]; gBattleMons[battler].pp[i] = moveInfo->currentPp[i]; } + if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) { - for (i = 0; i < MAX_MON_MOVES; ++i) + for (i = 0; i < MAX_MON_MOVES; i++) { moveStruct.moves[i] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_MOVE1 + i); moveStruct.currentPp[i] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_PP1 + i); } totalPPBonuses = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_PP_BONUSES); - for (i = 0; i < MAX_MON_MOVES; ++i) + for (i = 0; i < MAX_MON_MOVES; i++) perMovePPBonuses[i] = (totalPPBonuses & (3 << (i * 2))) >> (i * 2); + i = moveStruct.moves[gMoveSelectionCursor[battler]]; moveStruct.moves[gMoveSelectionCursor[battler]] = moveStruct.moves[gMultiUsePlayerCursor]; moveStruct.moves[gMultiUsePlayerCursor] = i; + i = moveStruct.currentPp[gMoveSelectionCursor[battler]]; moveStruct.currentPp[gMoveSelectionCursor[battler]] = moveStruct.currentPp[gMultiUsePlayerCursor]; moveStruct.currentPp[gMultiUsePlayerCursor] = i; + totalPPBonuses = perMovePPBonuses[gMoveSelectionCursor[battler]]; perMovePPBonuses[gMoveSelectionCursor[battler]] = perMovePPBonuses[gMultiUsePlayerCursor]; perMovePPBonuses[gMultiUsePlayerCursor] = totalPPBonuses; + totalPPBonuses = 0; - for (i = 0; i < MAX_MON_MOVES; ++i) + for (i = 0; i < MAX_MON_MOVES; i++) totalPPBonuses |= perMovePPBonuses[i] << (i * 2); - for (i = 0; i < MAX_MON_MOVES; ++i) + + for (i = 0; i < MAX_MON_MOVES; i++) { SetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_MOVE1 + i, &moveStruct.moves[i]); SetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_PP1 + i, &moveStruct.currentPp[i]); } + SetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_PP_BONUSES, &totalPPBonuses); } } - if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) - gBattlerControllerFuncs[battler] = OakOldManHandleInputChooseMove; - else - gBattlerControllerFuncs[battler] = HandleInputChooseMove; + + gBattlerControllerFuncs[battler] = HandleInputChooseMove; gMoveSelectionCursor[battler] = gMultiUsePlayerCursor; MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 0); - MoveSelectionDisplayPpString(); + MoveSelectionDisplayPpString(battler); MoveSelectionDisplayPpNumber(battler); MoveSelectionDisplayMoveType(battler); + AssignUsableZMoves(battler, moveInfo->moves); } - if (JOY_NEW(B_BUTTON)) + else if (JOY_NEW(B_BUTTON | SELECT_BUTTON)) { PlaySE(SE_SELECT); MoveSelectionDestroyCursorAt(gMultiUsePlayerCursor); @@ -990,11 +1077,11 @@ static void HandleMoveSwitching(u32 battler) gBattlerControllerFuncs[battler] = OakOldManHandleInputChooseMove; else gBattlerControllerFuncs[battler] = HandleInputChooseMove; - MoveSelectionDisplayPpString(); + MoveSelectionDisplayPpString(battler); MoveSelectionDisplayPpNumber(battler); MoveSelectionDisplayMoveType(battler); } - if (JOY_NEW(DPAD_LEFT)) + else if (JOY_NEW(DPAD_LEFT)) { if (gMultiUsePlayerCursor & 1) { @@ -1002,15 +1089,17 @@ static void HandleMoveSwitching(u32 battler) MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 29); else MoveSelectionDestroyCursorAt(gMultiUsePlayerCursor); + gMultiUsePlayerCursor ^= 1; PlaySE(SE_SELECT); + if (gMultiUsePlayerCursor == gMoveSelectionCursor[battler]) MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 0); else MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 27); } } - if (JOY_NEW(DPAD_RIGHT)) + else if (JOY_NEW(DPAD_RIGHT)) { if (!(gMultiUsePlayerCursor & 1) && (gMultiUsePlayerCursor ^ 1) < gNumberOfMovesToChoose) { @@ -1018,15 +1107,17 @@ static void HandleMoveSwitching(u32 battler) MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 29); else MoveSelectionDestroyCursorAt(gMultiUsePlayerCursor); + gMultiUsePlayerCursor ^= 1; PlaySE(SE_SELECT); + if (gMultiUsePlayerCursor == gMoveSelectionCursor[battler]) MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 0); else MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 27); } } - if (JOY_NEW(DPAD_UP)) + else if (JOY_NEW(DPAD_UP)) { if (gMultiUsePlayerCursor & 2) { @@ -1034,15 +1125,17 @@ static void HandleMoveSwitching(u32 battler) MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 29); else MoveSelectionDestroyCursorAt(gMultiUsePlayerCursor); + gMultiUsePlayerCursor ^= 2; PlaySE(SE_SELECT); + if (gMultiUsePlayerCursor == gMoveSelectionCursor[battler]) MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 0); else MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 27); } } - if (JOY_NEW(DPAD_DOWN)) + else if (JOY_NEW(DPAD_DOWN)) { if (!(gMultiUsePlayerCursor & 2) && (gMultiUsePlayerCursor ^ 2) < gNumberOfMovesToChoose) { @@ -1050,8 +1143,10 @@ static void HandleMoveSwitching(u32 battler) MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 29); else MoveSelectionDestroyCursorAt(gMultiUsePlayerCursor); + gMultiUsePlayerCursor ^= 2; PlaySE(SE_SELECT); + if (gMultiUsePlayerCursor == gMoveSelectionCursor[battler]) MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 0); else @@ -1064,36 +1159,44 @@ static void SetLinkBattleEndCallbacks(u32 battler) { if (gWirelessCommType == 0) { - if (!gReceivedRemoteLinkPlayers) + if (gReceivedRemoteLinkPlayers == 0) { m4aSongNumStop(SE_LOW_HEALTH); - gMain.inBattle = 0; + gMain.inBattle = FALSE; gMain.callback1 = gPreBattleCallback1; SetMainCallback2(CB2_InitEndLinkBattle); FreeAllWindowBuffers(); } } - else if (IsLinkTaskFinished()) + else { - m4aSongNumStop(SE_LOW_HEALTH); - gMain.inBattle = 0; - gMain.callback1 = gPreBattleCallback1; - SetMainCallback2(CB2_InitEndLinkBattle); - FreeAllWindowBuffers(); + if (IsLinkTaskFinished()) + { + m4aSongNumStop(SE_LOW_HEALTH); + gMain.inBattle = FALSE; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(CB2_InitEndLinkBattle); + FreeAllWindowBuffers(); + } } } +// Despite handling link battles separately, this is only ever used by link battles void SetBattleEndCallbacks(u32 battler) { if (!gPaletteFade.active) { if (gBattleTypeFlags & BATTLE_TYPE_LINK) { - if (gWirelessCommType == 0) - SetCloseLinkCallback(); - else - SetLinkStandbyCallback(); - gBattlerControllerFuncs[battler] = SetLinkBattleEndCallbacks; + if (IsLinkTaskFinished()) + { + if (gWirelessCommType == 0) + SetCloseLinkCallback(); + else + SetLinkStandbyCallback(); + + gBattlerControllerFuncs[battler] = SetLinkBattleEndCallbacks; + } } else { @@ -1242,14 +1345,21 @@ static void Intro_TryShinyAnimShowHealthbox(u32 battler) static void SwitchIn_CleanShinyAnimShowSubstitute(u32 battler) { if (gSprites[gHealthboxSpriteIds[battler]].callback == SpriteCallbackDummy - && gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim) + && gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim + && gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy) { + CopyBattleSpriteInvisibility(battler); + + // Reset shiny anim (even if it didn't occur) gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); + + // Check if Substitute should be shown if (gBattleSpritesDataPtr->battlerData[battler].behindSubstitute) InitAndLaunchSpecialAnimation(battler, battler, battler, B_ANIM_MON_TO_SUBSTITUTE); + gBattlerControllerFuncs[battler] = SwitchIn_HandleSoundAndEnd; } } @@ -1257,7 +1367,7 @@ static void SwitchIn_CleanShinyAnimShowSubstitute(u32 battler) static void SwitchIn_HandleSoundAndEnd(u32 battler) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].specialAnimActive - && !IsCryPlayingOrClearCrySongs()) + && !IsCryPlayingOrClearCrySongs()) { m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[battler]], battler); @@ -1267,19 +1377,19 @@ static void SwitchIn_HandleSoundAndEnd(u32 battler) static void SwitchIn_TryShinyAnimShowHealthbox(u32 battler) { + // Start shiny animation if applicable if (!gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim - && !gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive) + && !gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive) TryShinyAnimation(battler, &gPlayerParty[gBattlerPartyIndexes[battler]]); + + // Wait for ball anim, then show healthbox if (gSprites[gBattleControllerData[battler]].callback == SpriteCallbackDummy - && !(gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive)) + && !gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive) { DestroySprite(&gSprites[gBattleControllerData[battler]]); - UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], - &gPlayerParty[gBattlerPartyIndexes[battler]], - HEALTHBOX_ALL); + UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &gPlayerParty[gBattlerPartyIndexes[battler]], HEALTHBOX_ALL); StartHealthboxSlideIn(battler); SetHealthboxSpriteVisible(gHealthboxSpriteIds[battler]); - CopyBattleSpriteInvisibility(battler); gBattlerControllerFuncs[battler] = SwitchIn_CleanShinyAnimShowSubstitute; } } @@ -1293,17 +1403,11 @@ void Task_PlayerController_RestoreBgmAfterCry(u8 taskId) } } -void CompleteOnInactiveTextPrinter(u32 battler) -{ - if (!IsTextPrinterActive(0)) - PlayerBufferExecCompleted(battler); -} - -#define tExpTask_monId data[0] -#define tExpTask_battler data[2] -#define tExpTask_gainedExp_1 data[3] -#define tExpTask_gainedExp_2 data[4] -#define tExpTask_frames data[10] +#define tExpTask_monId data[0] +#define tExpTask_battler data[2] +#define tExpTask_gainedExp_1 data[3] +#define tExpTask_gainedExp_2 data[4] // Stored as two half-words containing a word. +#define tExpTask_frames data[10] static s32 GetTaskExpValue(u8 taskId) { @@ -1346,7 +1450,7 @@ static void Task_GiveExpToMon(u8 taskId) && (monId == gBattlerPartyIndexes[battler] || monId == gBattlerPartyIndexes[BATTLE_PARTNER(battler)])) gTasks[taskId].func = Task_LaunchLvlUpAnim; else - gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter; + gTasks[taskId].func = Task_SetControllerToWaitForString; } else { @@ -1457,15 +1561,17 @@ static void Task_UpdateLvlInHealthbox(u8 taskId) if (!gBattleSpritesDataPtr->healthBoxesData[battler].specialAnimActive) { u8 monIndex = gTasks[taskId].tExpTask_monId; + if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[BATTLE_PARTNER(battler)]) UpdateHealthboxAttribute(gHealthboxSpriteIds[BATTLE_PARTNER(battler)], &gPlayerParty[monIndex], HEALTHBOX_ALL); else UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &gPlayerParty[monIndex], HEALTHBOX_ALL); - gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter; + + gTasks[taskId].func = Task_SetControllerToWaitForString; } } -static void DestroyExpTaskAndCompleteOnInactiveTextPrinter(u8 taskId) +static void Task_SetControllerToWaitForString(u8 taskId) { s32 battlerId = gTasks[taskId].tExpTask_battler; @@ -1572,7 +1678,7 @@ static void OpenPartyMenuToChooseMon(u32 battler) caseId = gTasks[gBattleControllerData[battler]].data[0]; DestroyTask(gBattleControllerData[battler]); FreeAllWindowBuffers(); - OpenPartyMenuInTutorialBattle(caseId); + OpenPartyMenuInBattle(caseId); } } @@ -1581,11 +1687,13 @@ static void WaitForMonSelection(u32 battler) if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) { if (gPartyMenuUseExitCallback == TRUE) - BtlController_EmitChosenMonReturnValue(battler, 1, gSelectedMonPartyId, gBattlePartyCurrentOrder); + BtlController_EmitChosenMonReturnValue(battler, BUFFER_B, gSelectedMonPartyId, gBattlePartyCurrentOrder); else - BtlController_EmitChosenMonReturnValue(battler, 1, 6, NULL); + BtlController_EmitChosenMonReturnValue(battler, BUFFER_B, PARTY_SIZE, NULL); + if ((gBattleResources->bufferA[battler][1] & 0xF) == 1) PrintLinkStandbyMsg(); + PlayerBufferExecCompleted(battler); } } @@ -1605,7 +1713,43 @@ static void CompleteWhenChoseItem(u32 battler) { if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) { - BtlController_EmitOneReturnValue(battler, 1, gSpecialVar_ItemId); + BtlController_EmitOneReturnValue(battler, BUFFER_B, gSpecialVar_ItemId); + PlayerBufferExecCompleted(battler); + } +} + +static void PlayerHandleYesNoInput(u32 battler) +{ + if (JOY_NEW(DPAD_UP) && gMultiUsePlayerCursor != 0) + { + PlaySE(SE_SELECT); + BattleDestroyYesNoCursorAt(gMultiUsePlayerCursor); + gMultiUsePlayerCursor = 0; + BattleCreateYesNoCursorAt(0); + } + if (JOY_NEW(DPAD_DOWN) && gMultiUsePlayerCursor == 0) + { + PlaySE(SE_SELECT); + BattleDestroyYesNoCursorAt(gMultiUsePlayerCursor); + gMultiUsePlayerCursor = 1; + BattleCreateYesNoCursorAt(1); + } + if (JOY_NEW(A_BUTTON)) + { + HandleBattleWindow(YESNOBOX_X_Y, WINDOW_CLEAR); + PlaySE(SE_SELECT); + + if (gMultiUsePlayerCursor != 0) + BtlController_EmitTwoReturnValues(battler, BUFFER_B, 0xE, 0); + else + BtlController_EmitTwoReturnValues(battler, BUFFER_B, 0xD, 0); + + PlayerBufferExecCompleted(battler); + } + if (JOY_NEW(B_BUTTON)) + { + HandleBattleWindow(YESNOBOX_X_Y, WINDOW_CLEAR); + PlaySE(SE_SELECT); PlayerBufferExecCompleted(battler); } } @@ -1630,7 +1774,7 @@ static void MoveSelectionDisplayMoveNames(u32 battler) } } -static void MoveSelectionDisplayPpString(void) +static void MoveSelectionDisplayPpString(u32 battler) { StringCopy(gDisplayedStringBattle, gText_MoveInterfacePP); BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_PP); @@ -1643,11 +1787,13 @@ static void MoveSelectionDisplayPpNumber(u32 battler) if (gBattleResources->bufferA[battler][2] == TRUE) // check if we didn't want to display pp number return; + SetPpNumbersPaletteInMoveSelection(battler); moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]); txtPtr = ConvertIntToDecimalStringN(gDisplayedStringBattle, moveInfo->currentPp[gMoveSelectionCursor[battler]], STR_CONV_MODE_RIGHT_ALIGN, 2); - *txtPtr = CHAR_SLASH; - ConvertIntToDecimalStringN(++txtPtr, moveInfo->maxPp[gMoveSelectionCursor[battler]], STR_CONV_MODE_RIGHT_ALIGN, 2); + *(txtPtr)++ = CHAR_SLASH; + ConvertIntToDecimalStringN(txtPtr, moveInfo->maxPp[gMoveSelectionCursor[battler]], STR_CONV_MODE_RIGHT_ALIGN, 2); + BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_PP_REMAINING); } @@ -1658,13 +1804,12 @@ static void MoveSelectionDisplayMoveType(u32 battler) u32 speciesId; struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]); txtPtr = StringCopy(gDisplayedStringBattle, gText_MoveInterfaceType); - type = gMovesInfo[moveInfo->moves[gMoveSelectionCursor[battler]]].type; + type = GetMoveType(moveInfo->moves[gMoveSelectionCursor[battler]]); if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_TERA_BLAST) { if (IsGimmickSelected(battler, GIMMICK_TERA) || GetActiveGimmick(battler) == GIMMICK_TERA) type = GetBattlerTeraType(battler); - end = StringCopy(txtPtr, gTypesInfo[type].name); } else if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_IVY_CUDGEL) { @@ -1674,26 +1819,24 @@ static void MoveSelectionDisplayMoveType(u32 battler) || speciesId == SPECIES_OGERPON_HEARTHFLAME || speciesId == SPECIES_OGERPON_HEARTHFLAME_TERA || speciesId == SPECIES_OGERPON_CORNERSTONE || speciesId == SPECIES_OGERPON_CORNERSTONE_TERA) type = gBattleMons[battler].types[1]; - end = StringCopy(txtPtr, gTypesInfo[type].name); } - // Max Guard is a Normal-type move - else if (gMovesInfo[moveInfo->moves[gMoveSelectionCursor[battler]]].category == DAMAGE_CATEGORY_STATUS + else if (GetMoveCategory(moveInfo->moves[gMoveSelectionCursor[battler]]) == DAMAGE_CATEGORY_STATUS && (GetActiveGimmick(battler) == GIMMICK_DYNAMAX || IsGimmickSelected(battler, GIMMICK_DYNAMAX))) { - type = TYPE_NORMAL; - end = StringCopy(txtPtr, gTypesInfo[type].name); + type = TYPE_NORMAL; // Max Guard is always a Normal-type move } else if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_TERA_STARSTORM) { if (gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR || (IsGimmickSelected(battler, GIMMICK_TERA) && gBattleMons[battler].species == SPECIES_TERAPAGOS_TERASTAL)) type = TYPE_STELLAR; - end = StringCopy(txtPtr, gTypesInfo[type].name); } - else + else if (P_SHOW_DYNAMIC_TYPES) // Non-vanilla changes to battle UI showing dynamic types { - end = StringCopy(txtPtr, gTypesInfo[type].name); + struct Pokemon *mon = &gPlayerParty[gBattlerPartyIndexes[battler]]; + type = CheckDynamicMoveType(mon, moveInfo->moves[gMoveSelectionCursor[battler]], battler); } + end = StringCopy(txtPtr, gTypesInfo[type].name); PrependFontIdToFit(txtPtr, end, FONT_NORMAL, WindowWidthPx(B_WIN_MOVE_TYPE) - 25); BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_MOVE_TYPE); @@ -1703,9 +1846,8 @@ static void MoveSelectionDisplayMoveDescription(u32 battler) { struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleResources->bufferA[battler][4]); u16 move = moveInfo->moves[gMoveSelectionCursor[battler]]; - u16 pwr = gMovesInfo[move].power; - u16 acc = gMovesInfo[move].accuracy; - u8 cat = gMovesInfo[move].category; + u16 pwr = GetMovePower(move); + u16 acc = GetMoveAccuracy(move); u8 pwr_num[3], acc_num[3]; u8 cat_desc[7] = _("CAT: "); @@ -1733,26 +1875,23 @@ static void MoveSelectionDisplayMoveDescription(u32 battler) StringAppend(gDisplayedStringBattle, acc_desc); StringAppend(gDisplayedStringBattle, acc_num); StringAppend(gDisplayedStringBattle, gText_NewLine); - if (gMovesInfo[move].effect == EFFECT_PLACEHOLDER) - StringAppend(gDisplayedStringBattle, gNotDoneYetDescription); - else - StringAppend(gDisplayedStringBattle, gMovesInfo[move].description); + StringAppend(gDisplayedStringBattle, GetMoveDescription(move)); BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_MOVE_DESCRIPTION); if (gCategoryIconSpriteId == 0xFF) gCategoryIconSpriteId = CreateSprite(&gSpriteTemplate_CategoryIcons, 38, 64, 1); - StartSpriteAnim(&gSprites[gCategoryIconSpriteId], cat); + StartSpriteAnim(&gSprites[gCategoryIconSpriteId], GetBattleMoveCategory(move)); CopyWindowToVram(B_WIN_MOVE_DESCRIPTION, COPYWIN_FULL); } -void MoveSelectionCreateCursorAt(u8 cursorPosition, u8 arg1) +void MoveSelectionCreateCursorAt(u8 cursorPosition, u8 baseTileNum) { u16 src[2]; + src[0] = baseTileNum + 1; + src[1] = baseTileNum + 2; - src[0] = arg1 + 1; - src[1] = arg1 + 2; CopyToBgTilemapBufferRect_ChangePalette(0, src, 9 * (cursorPosition & 1) + 1, 55 + (cursorPosition & 2), 1, 2, 0x11); CopyBgTilemapBufferToVram(0); } @@ -1760,19 +1899,19 @@ void MoveSelectionCreateCursorAt(u8 cursorPosition, u8 arg1) void MoveSelectionDestroyCursorAt(u8 cursorPosition) { u16 src[2]; - src[0] = 32; src[1] = 32; + CopyToBgTilemapBufferRect_ChangePalette(0, src, 9 * (cursorPosition & 1) + 1, 55 + (cursorPosition & 2), 1, 2, 0x11); CopyBgTilemapBufferToVram(0); } -void ActionSelectionCreateCursorAt(u8 cursorPosition, u8 arg1) +void ActionSelectionCreateCursorAt(u8 cursorPosition, u8 baseTileNum) { u16 src[2]; - src[0] = 1; src[1] = 2; + CopyToBgTilemapBufferRect_ChangePalette(0, src, 7 * (cursorPosition & 1) + 16, 35 + (cursorPosition & 2), 1, 2, 0x11); CopyBgTilemapBufferToVram(0); } @@ -1780,19 +1919,19 @@ void ActionSelectionCreateCursorAt(u8 cursorPosition, u8 arg1) void ActionSelectionDestroyCursorAt(u8 cursorPosition) { u16 src[2]; - src[0] = 32; src[1] = 32; + CopyToBgTilemapBufferRect_ChangePalette(0, src, 7 * (cursorPosition & 1) + 16, 35 + (cursorPosition & 2), 1, 2, 0x11); CopyBgTilemapBufferToVram(0); } -void SetCB2ToReshowScreenAfterMenu(void) +void CB2_SetUpReshowBattleScreenAfterMenu(void) { SetMainCallback2(ReshowBattleScreenAfterMenu); } -void SetCB2ToReshowScreenAfterMenu2(void) +void CB2_SetUpReshowBattleScreenAfterMenu2(void) { SetMainCallback2(ReshowBattleScreenAfterMenu); } @@ -1848,6 +1987,9 @@ static u32 PlayerGetTrainerBackPicId(void) return trainerPicId; } +// In emerald it's possible to have a tag battle in the battle frontier facilities with AI +// which use the front sprite for both the player and the partner as opposed to any other battles (including the one with Steven) +// that use an animated back pic. static void PlayerHandleDrawTrainerPic(u32 battler) { bool32 isFrontPic; @@ -1922,17 +2064,28 @@ void PlayerHandleBallThrowAnim(u32 battler) static void PlayerHandlePause(u32 battler) { - u8 var = gBattleResources->bufferA[battler][1]; + u8 timer = gBattleResources->bufferA[battler][1]; + + while (timer != 0) + timer--; - while (var) - --var; PlayerBufferExecCompleted(battler); } +static void PlayerHandleMoveAnimation(u32 battler) +{ + BtlController_HandleMoveAnimation(battler); +} + +static void PlayerHandlePrintString(u32 battler) +{ + BtlController_HandlePrintString(battler); +} + static void PlayerHandlePrintSelectionString(u32 battler) { if (GetBattlerSide(battler) == B_SIDE_PLAYER) - BtlController_HandlePrintString(battler); + PlayerHandlePrintString(battler); else PlayerBufferExecCompleted(battler); } @@ -1974,43 +2127,116 @@ static void PlayerHandleChooseAction(u32 battler) ActionSelectionCreateCursorAt(gActionSelectionCursor[battler], 0); PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, battler, gBattlerPartyIndexes[battler]); BattleStringExpandPlaceholdersToDisplayedString(gText_WhatWillPkmnDo); - BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_ACTION_PROMPT); + BreakStringAutomatic(gDisplayedStringBattle, WindowWidthPx(B_WIN_ACTION_PROMPT), 2, FONT_NORMAL); + + if (B_SHOW_PARTNER_TARGET && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && IsBattlerAlive(B_POSITION_PLAYER_RIGHT)) + { + StringCopy(gStringVar1, COMPOUND_STRING("Partner will use:\n")); + u32 move = gBattleMons[B_POSITION_PLAYER_RIGHT].moves[*(gBattleStruct->chosenMovePositions + B_POSITION_PLAYER_RIGHT)]; + StringAppend(gStringVar1, GetMoveName(move)); + u32 moveTarget = GetBattlerMoveTargetType(B_POSITION_PLAYER_RIGHT, move); + if (moveTarget == MOVE_TARGET_SELECTED) + { + if (gBattleStruct->aiChosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_OPPONENT_LEFT) + StringAppend(gStringVar1, COMPOUND_STRING(" -{UP_ARROW}")); + else if (gBattleStruct->aiChosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_OPPONENT_RIGHT) + StringAppend(gStringVar1, COMPOUND_STRING(" {UP_ARROW}-")); + else if (gBattleStruct->aiChosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_PLAYER_LEFT) + StringAppend(gStringVar1, COMPOUND_STRING(" {DOWN_ARROW}-")); + else if (gBattleStruct->aiChosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_PLAYER_RIGHT) + StringAppend(gStringVar1, COMPOUND_STRING(" {DOWN_ARROW}-")); + } + else if (moveTarget == MOVE_TARGET_BOTH) + { + StringAppend(gStringVar1, COMPOUND_STRING(" {UP_ARROW}{UP_ARROW}")); + } + else if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) + { + StringAppend(gStringVar1, COMPOUND_STRING(" {V_D_ARROW}{UP_ARROW}")); + } + else if (moveTarget == MOVE_TARGET_ALL_BATTLERS) + { + StringAppend(gStringVar1, COMPOUND_STRING(" {V_D_ARROW}{V_D_ARROW}")); + } + BattlePutTextOnWindow(gStringVar1, B_WIN_ACTION_PROMPT); + } + else + { + BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_ACTION_PROMPT); + } } -static void HandleChooseMoveAfterDma3(u32 battler) +static void PlayerHandleYesNoBox(u32 battler) +{ + if (GetBattlerSide(battler) == B_SIDE_PLAYER) + { + HandleBattleWindow(YESNOBOX_X_Y, 0); + BattlePutTextOnWindow(gText_BattleYesNoChoice, B_WIN_YESNO); + gMultiUsePlayerCursor = 1; + BattleCreateYesNoCursorAt(1); + gBattlerControllerFuncs[battler] = PlayerHandleYesNoInput; + } + else + { + PlayerBufferExecCompleted(battler); + } +} + +void HandleChooseMoveAfterDma3(u32 battler) { if (!IsDma3ManagerBusyWithBgCopy()) { gBattle_BG0_X = 0; - gBattle_BG0_Y = 320; + gBattle_BG0_Y = DISPLAY_HEIGHT * 2; gBattlerControllerFuncs[battler] = HandleInputChooseMove; } } -static void PlayerHandleChooseMove(u32 battler) +// arenaMindPoints is used here as a placeholder for a timer. + +// static void PlayerChooseMoveInBattlePalace(u32 battler) +// { +// if (--*(gBattleStruct->arenaMindPoints + battler) == 0) +// { +// gBattlePalaceMoveSelectionRngValue = gRngValue; +// BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, ChooseMoveAndTargetInBattlePalace(battler)); +// PlayerBufferExecCompleted(battler); +// } +// } + +void PlayerHandleChooseMove(u32 battler) { - struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]); + if (gBattleTypeFlags & BATTLE_TYPE_PALACE) + { + // *(gBattleStruct->arenaMindPoints + battler) = 8; + // gBattlerControllerFuncs[battler] = PlayerChooseMoveInBattlePalace; + } + else + { + struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]); - InitMoveSelectionsVarsAndStrings(battler); - gBattleStruct->gimmick.playerSelect = FALSE; + InitMoveSelectionsVarsAndStrings(battler); + gBattleStruct->gimmick.playerSelect = FALSE; - AssignUsableZMoves(battler, moveInfo->moves); - gBattleStruct->zmove.viable = (gBattleStruct->zmove.possibleZMoves[battler] & gBitTable[gMoveSelectionCursor[battler]]) != 0; + AssignUsableZMoves(battler, moveInfo->moves); + gBattleStruct->zmove.viable = (gBattleStruct->zmove.possibleZMoves[battler] & (1u << gMoveSelectionCursor[battler])) != 0; - if (!IsGimmickTriggerSpriteActive()) - gBattleStruct->gimmick.triggerSpriteId = 0xFF; - if (!(gBattleStruct->gimmick.usableGimmick[battler] == GIMMICK_Z_MOVE && !gBattleStruct->zmove.viable)) - CreateGimmickTriggerSprite(battler); + if (!IsGimmickTriggerSpriteActive()) + gBattleStruct->gimmick.triggerSpriteId = 0xFF; + if (!(gBattleStruct->gimmick.usableGimmick[battler] == GIMMICK_Z_MOVE && !gBattleStruct->zmove.viable)) + CreateGimmickTriggerSprite(battler); - gBattlerControllerFuncs[battler] = HandleChooseMoveAfterDma3; + gBattlerControllerFuncs[battler] = HandleChooseMoveAfterDma3; + } } void InitMoveSelectionsVarsAndStrings(u32 battler) { + LoadTypeIcons(battler); MoveSelectionDisplayMoveNames(battler); gMultiUsePlayerCursor = 0xFF; MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 0); - MoveSelectionDisplayPpString(); + MoveSelectionDisplayPpString(battler); MoveSelectionDisplayPpNumber(battler); MoveSelectionDisplayMoveType(battler); } @@ -2034,14 +2260,23 @@ static void PlayerHandleChoosePokemon(u32 battler) for (i = 0; i < ARRAY_COUNT(gBattlePartyCurrentOrder); i++) gBattlePartyCurrentOrder[i] = gBattleResources->bufferA[battler][4 + i]; - gBattleControllerData[battler] = CreateTask(TaskDummy, 0xFF); - gTasks[gBattleControllerData[battler]].data[0] = gBattleResources->bufferA[battler][1] & 0xF; - *(&gBattleStruct->battlerPreventingSwitchout) = gBattleResources->bufferA[battler][1] >> 4; - *(&gBattleStruct->prevSelectedPartySlot) = gBattleResources->bufferA[battler][2]; - *(&gBattleStruct->abilityPreventingSwitchout) = (gBattleResources->bufferA[battler][3] & 0xFF) | (gBattleResources->bufferA[battler][7] << 8); - BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK); - gBattlerControllerFuncs[battler] = OpenPartyMenuToChooseMon; - gBattlerInMenuId = battler; + if (gBattleTypeFlags & BATTLE_TYPE_ARENA && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CANT_SWITCH + && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CHOOSE_FAINTED_MON) + { + // BtlController_EmitChosenMonReturnValue(battler, BUFFER_B, gBattlerPartyIndexes[battler] + 1, gBattlePartyCurrentOrder); + // PlayerBufferExecCompleted(battler); + } + else + { + gBattleControllerData[battler] = CreateTask(TaskDummy, 0xFF); + gTasks[gBattleControllerData[battler]].data[0] = gBattleResources->bufferA[battler][1] & 0xF; + *(&gBattleStruct->battlerPreventingSwitchout) = gBattleResources->bufferA[battler][1] >> 4; + *(&gBattleStruct->prevSelectedPartySlot) = gBattleResources->bufferA[battler][2]; + *(&gBattleStruct->abilityPreventingSwitchout) = (gBattleResources->bufferA[battler][3] & 0xFF) | (gBattleResources->bufferA[battler][7] << 8); + BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK); + gBattlerControllerFuncs[battler] = OpenPartyMenuToChooseMon; + gBattlerInMenuId = battler; + } } static void PlayerHandleCmd23(u32 battler) @@ -2056,7 +2291,6 @@ static void PlayerHandleHealthBarUpdate(u32 battler) BtlController_HandleHealthBarUpdate(battler, TRUE); } -// consider moving to battle_controller, shared with battle_controller_pokedude void PlayerHandleExpUpdate(u32 battler) { u8 monId = gBattleResources->bufferA[battler][1]; @@ -2096,16 +2330,16 @@ static void PlayerHandleStatusXor(u32 battler) static void PlayerHandleDMA3Transfer(u32 battler) { u32 dstArg = gBattleResources->bufferA[battler][1] - | (gBattleResources->bufferA[battler][2] << 8) - | (gBattleResources->bufferA[battler][3] << 16) - | (gBattleResources->bufferA[battler][4] << 24); + | (gBattleResources->bufferA[battler][2] << 8) + | (gBattleResources->bufferA[battler][3] << 16) + | (gBattleResources->bufferA[battler][4] << 24); u16 sizeArg = gBattleResources->bufferA[battler][5] | (gBattleResources->bufferA[battler][6] << 8); const u8 *src = &gBattleResources->bufferA[battler][7]; u8 *dst = (u8 *)(dstArg); u32 size = sizeArg; - while (TRUE) + while (1) { if (size <= 0x1000) { @@ -2156,19 +2390,8 @@ static void PlayerHandleIntroTrainerBallThrow(u32 battler) BtlController_HandleIntroTrainerBallThrow(battler, 0xD6F8, trainerPal, 31, Intro_TryShinyAnimShowHealthbox, PlayerThrowBall_StartAnimLinearTranslation); } -void SpriteCB_FreePlayerSpriteLoadMonSpriteOld(struct Sprite *sprite) -{ - u8 battlerId = sprite->data[5]; - - FreeSpriteOamMatrix(sprite); - FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(sprite->oam.paletteNum)); - DestroySprite(sprite); - BattleLoadMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[battlerId]], battlerId); - StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], 0); -} - static void PlayerHandleDrawPartyStatusSummary(u32 battler) -{ +{ BtlController_HandleDrawPartyStatusSummary(battler, B_SIDE_PLAYER, TRUE); } @@ -2223,7 +2446,9 @@ static void PlayerHandleResetActionMoveSelection(u32 battler) static void PlayerHandleEndLinkBattle(u32 battler) { + // RecordedBattle_RecordAllBattlerData(&gBattleResources->bufferA[battler][4]); gBattleOutcome = gBattleResources->bufferA[battler][1]; + // gSaveBlock2Ptr->frontier.disableRecordBattle = gBattleResources->bufferA[battler][2]; FadeOutMapMusic(5); BeginFastPaletteFade(3); PlayerBufferExecCompleted(battler); diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index f5775beed..de3dd0659 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -70,7 +70,7 @@ static void (*const sPlayerPartnerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 bat [CONTROLLER_PRINTSTRING] = BtlController_HandlePrintString, [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, [CONTROLLER_CHOOSEACTION] = PlayerPartnerHandleChooseAction, - [CONTROLLER_UNKNOWNYESNOBOX] = BtlController_Empty, + [CONTROLLER_YESNOBOX] = BtlController_Empty, [CONTROLLER_CHOOSEMOVE] = PlayerPartnerHandleChooseMove, [CONTROLLER_OPENBAG] = BtlController_Empty, [CONTROLLER_CHOOSEPOKEMON] = PlayerPartnerHandleChoosePokemon, diff --git a/src/battle_controller_pokedude.c b/src/battle_controller_pokedude.c index 850ccc269..9eb6ff936 100644 --- a/src/battle_controller_pokedude.c +++ b/src/battle_controller_pokedude.c @@ -95,7 +95,7 @@ static void (*const sPokedudeBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) [CONTROLLER_PRINTSTRING] = BtlController_HandlePrintString, // done [CONTROLLER_PRINTSTRINGPLAYERONLY] = PokedudeHandlePrintSelectionString, // done [CONTROLLER_CHOOSEACTION] = PokedudeHandleChooseAction, // done - [CONTROLLER_UNKNOWNYESNOBOX] = BtlController_Empty, // done + [CONTROLLER_YESNOBOX] = BtlController_Empty, // done [CONTROLLER_CHOOSEMOVE] = PokedudeHandleChooseMove, // done [CONTROLLER_OPENBAG] = PokedudeHandleChooseItem, // done [CONTROLLER_CHOOSEPOKEMON] = PokedudeHandleChoosePokemon, // done diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index da36608cf..c3450e63b 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -74,7 +74,7 @@ static void (*const sRecordedOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 [CONTROLLER_PRINTSTRING] = RecordedOpponentHandlePrintString, [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, [CONTROLLER_CHOOSEACTION] = RecordedOpponentHandleChooseAction, - [CONTROLLER_UNKNOWNYESNOBOX] = BtlController_Empty, + [CONTROLLER_YESNOBOX] = BtlController_Empty, [CONTROLLER_CHOOSEMOVE] = RecordedOpponentHandleChooseMove, [CONTROLLER_OPENBAG] = RecordedOpponentHandleChooseItem, [CONTROLLER_CHOOSEPOKEMON] = RecordedOpponentHandleChoosePokemon, diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index e49a9e7e8..2852b30c8 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -72,7 +72,7 @@ static void (*const sRecordedPlayerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 ba [CONTROLLER_PRINTSTRING] = RecordedPlayerHandlePrintString, [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, [CONTROLLER_CHOOSEACTION] = RecordedPlayerHandleChooseAction, - [CONTROLLER_UNKNOWNYESNOBOX] = BtlController_Empty, + [CONTROLLER_YESNOBOX] = BtlController_Empty, [CONTROLLER_CHOOSEMOVE] = RecordedPlayerHandleChooseMove, [CONTROLLER_OPENBAG] = RecordedPlayerHandleChooseItem, [CONTROLLER_CHOOSEPOKEMON] = RecordedPlayerHandleChoosePokemon, diff --git a/src/battle_controller_safari.c b/src/battle_controller_safari.c index 141cfe7dd..24488746f 100644 --- a/src/battle_controller_safari.c +++ b/src/battle_controller_safari.c @@ -52,7 +52,7 @@ static void (*const sSafariBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = [CONTROLLER_PRINTSTRING] = BtlController_HandlePrintString, // done [CONTROLLER_PRINTSTRINGPLAYERONLY] = SafariHandlePrintSelectionString, // done [CONTROLLER_CHOOSEACTION] = SafariHandleChooseAction, // done - [CONTROLLER_UNKNOWNYESNOBOX] = BtlController_Empty, // done + [CONTROLLER_YESNOBOX] = BtlController_Empty, // done [CONTROLLER_CHOOSEMOVE] = BtlController_Empty, // done [CONTROLLER_OPENBAG] = SafariHandleChooseItem, // done [CONTROLLER_CHOOSEPOKEMON] = BtlController_Empty, // done diff --git a/src/data/items.h b/src/data/items.h index e8531ab06..9a7110891 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -2052,6 +2052,7 @@ const struct Item gItemsInfo[] = "A glass flute that " "awakens\nsleeping " "Pokémon."), + .notConsumed = TRUE, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, @@ -2070,6 +2071,7 @@ const struct Item gItemsInfo[] = "A glass flute that " "snaps Pokémon\n" "out of confusion."), + .notConsumed = TRUE, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -2088,6 +2090,7 @@ const struct Item gItemsInfo[] = "A glass flute that " "snaps Pokémon\n" "out of attraction."), + .notConsumed = TRUE, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -2109,6 +2112,7 @@ const struct Item gItemsInfo[] = "A glass flute that " "keeps away\nwild " "Pokémon."), + .notConsumed = TRUE, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_BlackWhiteFlute, @@ -2125,6 +2129,7 @@ const struct Item gItemsInfo[] = .description = COMPOUND_STRING( "A glass flute that " "lures wild\nPokémon."), + .notConsumed = TRUE, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_BlackWhiteFlute, diff --git a/src/graphics.c b/src/graphics.c index 3fc34e902..cf9a8a587 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1937,3 +1937,8 @@ const u32 gBattleAnimBgPalette_ZMoveMountain[] = INCBIN_U32("graphics/battle_ani const u32 gBattleAnimBgTilemap_ZMoveMountain[] = INCBIN_U32("graphics/battle_anims/backgrounds/zmove_mountain.bin.lz"); const u32 gBattleAnimBgPalette_SteelBeam[] = INCBIN_U32("graphics/battle_anims/backgrounds/steel_beam.gbapal.lz"); + +const u32 gBattleIcons_Gfx1[] = INCBIN_U32("graphics/types/battle_icons1.4bpp.lz"); +const u32 gBattleIcons_Gfx2[] = INCBIN_U32("graphics/types/battle_icons2.4bpp.lz"); +const u32 gBattleIcons_Pal1[] = INCBIN_U32("graphics/types/battle_icons1.gbapal.lz"); +const u32 gBattleIcons_Pal2[] = INCBIN_U32("graphics/types/battle_icons2.gbapal.lz"); diff --git a/src/item.c b/src/item.c index 337309a23..8b86828b3 100644 --- a/src/item.c +++ b/src/item.c @@ -662,6 +662,11 @@ u8 ItemId_GetImportance(u16 itemId) return gItemsInfo[SanitizeItemId(itemId)].importance; } +u8 ItemId_GetConsumability(u16 itemId) +{ + return !gItemsInfo[SanitizeItemId(itemId)].notConsumed; +} + u8 ItemId_GetPocket(u16 itemId) { return gItemsInfo[SanitizeItemId(itemId)].pocket; diff --git a/src/item_menu.c b/src/item_menu.c index 29fd9f057..7c566ba28 100644 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -351,7 +351,7 @@ void CB2_BagMenuFromStartMenu(void) void CB2_BagMenuFromBattle(void) { - GoToBagMenu(ITEMMENULOCATION_BATTLE, OPEN_BAG_LAST, SetCB2ToReshowScreenAfterMenu2); + GoToBagMenu(ITEMMENULOCATION_BATTLE, OPEN_BAG_LAST, CB2_SetUpReshowBattleScreenAfterMenu2); } static void CB2_BagMenuRun(void) @@ -949,7 +949,7 @@ void Bag_BeginCloseWin0Animation(void) gBagMenuState.bagOpen = FALSE; } -void CB2_SetUpReshowBattleScreenAfterMenu(void) +void SetBagOpenFalse(void) { gBagMenuState.bagOpen = FALSE; } @@ -2101,7 +2101,7 @@ void InitOldManBag(void) BackUpPlayerBag(); AddBagItem(ITEM_POTION, 1); AddBagItem(ITEM_POKE_BALL, 1); - GoToBagMenu(ITEMMENULOCATION_OLD_MAN, OPEN_BAG_ITEMS, SetCB2ToReshowScreenAfterMenu2); + GoToBagMenu(ITEMMENULOCATION_OLD_MAN, OPEN_BAG_ITEMS, CB2_SetUpReshowBattleScreenAfterMenu2); } #define tFrameCounter data[8] @@ -2183,11 +2183,11 @@ void InitPokedudeBag(u8 a0) location = a0; break; case ITEMMENULOCATION_TTVSCR_STATUS: - cb2 = SetCB2ToReshowScreenAfterMenu2; + cb2 = CB2_SetUpReshowBattleScreenAfterMenu2; location = ITEMMENULOCATION_TTVSCR_STATUS; break; case ITEMMENULOCATION_TTVSCR_CATCHING: - cb2 = SetCB2ToReshowScreenAfterMenu2; + cb2 = CB2_SetUpReshowBattleScreenAfterMenu2; location = ITEMMENULOCATION_TTVSCR_CATCHING; break; } diff --git a/src/line_break.c b/src/line_break.c new file mode 100644 index 000000000..b8888f501 --- /dev/null +++ b/src/line_break.c @@ -0,0 +1,281 @@ +#include "global.h" +#include "line_break.h" +#include "text.h" +#include "malloc.h" + +void StripLineBreaks(u8 *src) +{ + u32 currIndex = 0; + while (src[currIndex] != EOS) + { + if (src[currIndex] == CHAR_PROMPT_SCROLL || src[currIndex] == CHAR_NEWLINE) + src[currIndex] = CHAR_SPACE; + currIndex++; + } +} + +void BreakStringAutomatic(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId) +{ + u32 currIndex = 0; + u8 *currSrc = src; + while (src[currIndex] != EOS) + { + if (src[currIndex] == CHAR_PROMPT_CLEAR) + { + u8 replacedChar = src[currIndex + 1]; + src[currIndex + 1] = EOS; + BreakSubStringAutomatic(currSrc, maxWidth, screenLines, fontId); + src[currIndex + 1] = replacedChar; + currSrc = &src[currIndex + 1]; + } + currIndex++; + } + BreakSubStringAutomatic(currSrc, maxWidth, screenLines, fontId); +} + +void BreakSubStringAutomatic(u8 *src, u32 maxWidth, u32 screenLines, u8 fontId) +{ + // If the string already has line breaks, don't interfere with them + if (StringHasManualBreaks(src)) + return; + // Sanity check + if (src[0] == EOS) + return; + u32 numChars = 1; + u32 numWords = 1; + u32 currWordIndex = 0; + u32 currWordLength = 1; + bool32 isPrevCharSplitting = FALSE; + bool32 isCurrCharSplitting; + // Get numbers of chars in string and count words + while (src[numChars] != EOS) + { + isCurrCharSplitting = IsWordSplittingChar(src, numChars); + if (isCurrCharSplitting && !isPrevCharSplitting) + numWords++; + isPrevCharSplitting = isCurrCharSplitting; + numChars++; + } + // Allocate enough space for word data + struct StringWord *allWords = Alloc(numWords*sizeof(struct StringWord)); + + allWords[currWordIndex].startIndex = 0; + allWords[currWordIndex].width = 0; + isPrevCharSplitting = FALSE; + // Fill in word begin index and lengths + for (u32 i = 1; i < numChars; i++) + { + isCurrCharSplitting = IsWordSplittingChar(src, i); + if (isCurrCharSplitting && !isPrevCharSplitting) + { + allWords[currWordIndex].length = currWordLength; + currWordIndex++; + currWordLength = 0; + } + else if (!isCurrCharSplitting && isPrevCharSplitting) + { + allWords[currWordIndex].startIndex = i; + allWords[currWordIndex].width = 0; + currWordLength++; + } + else + { + currWordLength++; + } + isPrevCharSplitting = isCurrCharSplitting; + } + allWords[currWordIndex].length = currWordLength; + + // Fill in individual word widths + for (u32 i = 0; i < numWords; i++) + { + for (u32 j = 0; j < allWords[i].length; j++) + allWords[i].width += GetGlyphWidth(src[allWords[i].startIndex + j], FALSE, fontId); + } + + // Step 1: Does it all fit one one line? Then no break + // Step 2: Try to split across minimum number of lines + u32 spaceWidth = GetGlyphWidth(0, FALSE, fontId); + u32 totalWidth = allWords[0].width; + // Calculate total widths without any line breaks + for (u32 i = 1; i < numWords; i++) + totalWidth += allWords[i].width + spaceWidth; + + // If it doesn't fit on 1 line, do fancy line break calculation + // NOTE: Currently the line break calculation isn't fancy + if (totalWidth > maxWidth) + { + // Figure out how many lines are needed with naive method + u32 currLineWidth = 0; + u32 totalLines = 1; + bool32 shouldTryAgain; + for (currWordIndex = 0; currWordIndex < numWords; currWordIndex++) + { + if (currLineWidth + allWords[currWordIndex].length > maxWidth) + { + totalLines++; + currLineWidth = allWords[currWordIndex].width; + } + else + { + currLineWidth += allWords[currWordIndex].width + spaceWidth; + } + } + // LINE LAYOUT STARTS HERE + struct StringLine *stringLines; + do + { + shouldTryAgain = FALSE; + u16 targetLineWidth = totalWidth/totalLines; + stringLines = Alloc(totalLines*sizeof(struct StringLine)); + for (u32 lineIndex = 0; lineIndex < totalLines; lineIndex++) + { + stringLines[lineIndex].numWords = 0; + stringLines[lineIndex].spaceWidth = spaceWidth; + stringLines[lineIndex].extraSpaceWidth = 0; + } + currWordIndex = 0; + u16 currLineIndex = 0; + stringLines[currLineIndex].words = &allWords[currWordIndex]; + stringLines[currLineIndex].numWords = 1; + currLineWidth = allWords[currWordIndex].width; + currWordIndex++; + while (currWordIndex < numWords) + { + if (currLineWidth + spaceWidth + allWords[currWordIndex].width > maxWidth) + { + // go to next line + currLineIndex++; + if (currLineIndex == totalLines) + { + totalLines++; + Free(stringLines); + shouldTryAgain = TRUE; + break; + } + stringLines[currLineIndex].words = &allWords[currWordIndex]; + stringLines[currLineIndex].numWords = 1; + currLineWidth = allWords[currWordIndex].width; + currWordIndex++; + } + else if (currLineWidth > targetLineWidth) + { + // go to next line + currLineIndex++; + if (currLineIndex == totalLines) + { + totalLines++; + Free(stringLines); + shouldTryAgain = TRUE; + break; + } + stringLines[currLineIndex].words = &allWords[currWordIndex]; + stringLines[currLineIndex].numWords = 1; + currLineWidth = allWords[currWordIndex].width; + currWordIndex++; + } + else + { + // continue on current line + // add word and space width + currLineWidth += spaceWidth + allWords[currWordIndex].width; + stringLines[currLineIndex].numWords++; + currWordIndex++; + } + } + } while (shouldTryAgain); + //u32 currBadness = GetStringBadness(stringLines, totalLines, maxWidth); + BuildNewString(stringLines, totalLines, screenLines, src); + Free(stringLines); + } + + Free(allWords); +} + +// Only allow word splitting on allowed chars +bool32 IsWordSplittingChar(const u8 *src, u32 index) +{ + switch (src[index]) + { + case CHAR_SPACE: + return TRUE; + default: + return FALSE; + } +} + +// Badness calculation +// unfilled lines scale linerarly +// jagged lines scales by the square +// runts scale linearly +// numbers not final +// ISN'T ACTUALLY USED RIGHT NOW +u32 GetStringBadness(struct StringLine *stringLines, u32 numLines, u32 maxWidth) +{ + u32 badness = 0; + u32 *lineWidths = Alloc(numLines*4); + u32 widestWidth = 0; + for (u32 i = 0; i < numLines; i++) + { + lineWidths[i] = 0; + for (u32 j = 0; j < stringLines[i].numWords; j++) + lineWidths[i] += stringLines[i].words[j].width; + lineWidths[i] += (stringLines[i].numWords-1)*stringLines[i].spaceWidth; + if (lineWidths[i] > widestWidth) + widestWidth = lineWidths[i]; + if (stringLines[i].numWords == 1) + badness += BADNESS_RUNT; + } + for (u32 i = 0; i < numLines; i++) + { + u32 extraSpaceWidth = 0; + if (lineWidths[i] != widestWidth) + { + // Not the best way to do this, ideally a line should be allowed to get longer than current widest + // line. But then the widest line has to be recalculated. + while (lineWidths[i] + (extraSpaceWidth + 1) * (stringLines[i].numWords - 1) < widestWidth && extraSpaceWidth < MAX_SPACE_WIDTH) + extraSpaceWidth++; + lineWidths[i] += extraSpaceWidth*(stringLines[i].numWords-1); + } + badness += (maxWidth - lineWidths[i]) * BADNESS_UNFILLED; + u32 baseBadness = (widestWidth - lineWidths[i]) * BADNESS_JAGGED; + badness += baseBadness*baseBadness; + stringLines[i].extraSpaceWidth = extraSpaceWidth; + } + Free(lineWidths); + return badness; +} + +// Build the new string from the data stored in the StringLine structs +void BuildNewString(struct StringLine *stringLines, u32 numLines, u32 maxLines, u8 *str) +{ + u32 srcCharIndex = 0; + for (u32 lineIndex = 0; lineIndex < numLines; lineIndex++) + { + srcCharIndex += stringLines[lineIndex].words[0].length; + for (u32 wordIndex = 1; wordIndex < stringLines[lineIndex].numWords; wordIndex++) + // Add length of word and a space + srcCharIndex += stringLines[lineIndex].words[wordIndex].length + 1; + if (lineIndex + 1 < numLines) + { + // Add the appropriate line break depending on line number + if (lineIndex >= maxLines - 1 && numLines > maxLines) + str[srcCharIndex] = CHAR_PROMPT_SCROLL; + else + str[srcCharIndex] = CHAR_NEWLINE; + srcCharIndex++; + } + } +} + +bool32 StringHasManualBreaks(u8 *src) +{ + u32 charIndex = 0; + while (src[charIndex] != EOS) + { + if (src[charIndex] == CHAR_PROMPT_SCROLL || src[charIndex] == CHAR_NEWLINE) + return TRUE; + charIndex++; + } + return FALSE; +} diff --git a/src/party_menu.c b/src/party_menu.c index e11ddbf3a..3e8c277f6 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -6562,7 +6562,7 @@ static u8 GetPartyLayoutFromBattleType(void) return PARTY_LAYOUT_DOUBLE; } -void OpenPartyMenuInTutorialBattle(u8 partyAction) +void OpenPartyMenuInBattle(u8 partyAction) { if (!BtlCtrl_OakOldMan_TestState2Flag(FIRST_BATTLE_MSG_FLAG_PARTY_MENU) && (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)) { @@ -6572,7 +6572,7 @@ void OpenPartyMenuInTutorialBattle(u8 partyAction) FALSE, PARTY_MSG_NONE, Task_FirstBattleEnterParty_WaitFadeIn, - SetCB2ToReshowScreenAfterMenu); + CB2_SetUpReshowBattleScreenAfterMenu); BtlCtrl_OakOldMan_SetState2Flag(FIRST_BATTLE_MSG_FLAG_PARTY_MENU); } else @@ -6583,7 +6583,7 @@ void OpenPartyMenuInTutorialBattle(u8 partyAction) FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, - SetCB2ToReshowScreenAfterMenu); + CB2_SetUpReshowBattleScreenAfterMenu); } ReshowBattleScreenDummy(); UpdatePartyToBattleOrder(); @@ -6591,7 +6591,7 @@ void OpenPartyMenuInTutorialBattle(u8 partyAction) void Pokedude_OpenPartyMenuInBattle(void) { - InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE, GetPartyLayoutFromBattleType(), PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_CHOOSE_MON, Task_PartyMenu_Pokedude, SetCB2ToReshowScreenAfterMenu); + InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE, GetPartyLayoutFromBattleType(), PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_CHOOSE_MON, Task_PartyMenu_Pokedude, CB2_SetUpReshowBattleScreenAfterMenu); ReshowBattleScreenDummy(); UpdatePartyToBattleOrder(); } @@ -6948,8 +6948,8 @@ static void UpdatePartyToFieldOrder(void) static void CB2_SetUpExitToBattleScreen(void) { - CB2_SetUpReshowBattleScreenAfterMenu(); - SetMainCallback2(SetCB2ToReshowScreenAfterMenu); + SetBagOpenFalse(); + SetMainCallback2(CB2_SetUpReshowBattleScreenAfterMenu); } void ShowPartyMenuToShowcaseMultiBattleParty(void) diff --git a/src/pokemon.c b/src/pokemon.c index 46000d437..dfc4be449 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -6561,3 +6561,11 @@ void UpdateDaysPassedSinceFormChange(u16 days) } } } + +u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler) +{ + u32 moveType = GetDynamicMoveType(mon, move, battler, NULL); + if (moveType != TYPE_NONE) + return moveType; + return GetMoveType(move); +} diff --git a/src/tm_case.c b/src/tm_case.c index 2ebe80203..3a6f384de 100644 --- a/src/tm_case.c +++ b/src/tm_case.c @@ -1466,7 +1466,7 @@ static void Task_Pokedude_Run(u8 taskId) sTMCaseStaticResources.scrollOffset = sPokedudeBagBackup->scrollOffset; Free(sPokedudeBagBackup); CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_SIZE); - CB2_SetUpReshowBattleScreenAfterMenu(); + SetBagOpenFalse(); BeginNormalPaletteFade(PALETTES_ALL, -2, 0, 16, 0); tPokedudeState++; } diff --git a/src/type_icons.c b/src/type_icons.c new file mode 100644 index 000000000..bd940ec84 --- /dev/null +++ b/src/type_icons.c @@ -0,0 +1,552 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_controllers.h" +#include "battle_gimmick.h" +#include "decompress.h" +#include "graphics.h" +#include "pokedex.h" +#include "sprite.h" +#include "type_icons.h" + +static void LoadTypeSpritesAndPalettes(void); +static void LoadTypeIconsPerBattler(u32, u32); + +static bool32 UseDoubleBattleCoords(u32); + +static u32 GetMonPublicType(u32, u32); +static bool32 ShouldHideUncaughtType(u32); +static u32 GetMonDefensiveTeraType(struct Pokemon *, struct Pokemon*, u32, u32, u32, u32); +static u32 IsIllusionActiveAndTypeUnchanged(struct Pokemon*, u32, u32); + +static void CreateSpriteFromType(u32, bool32, u32[], u32, u32); +static bool32 ShouldSkipSecondType(u32[], u32); +static void SetTypeIconXY(s32*, s32*, u32, bool32, u32); + +static void CreateSpriteAndSetTypeSpriteAttributes(u32, u32 x, u32 y, u32, u32, bool32); +static bool32 ShouldFlipTypeIcon(bool32, u32, u32); + +static void SpriteCB_TypeIcon(struct Sprite*); +static void DestroyTypeIcon(struct Sprite*); +static void FreeAllTypeIconResources(void); +static bool32 ShouldHideTypeIcon(u32); +static s32 GetTypeIconHideMovement(bool32, u32); +static s32 GetTypeIconSlideMovement(bool32, u32, s32); +static s32 GetTypeIconBounceMovement(s32, u32); + +const struct Coords16 sTypeIconPositions[][2] = +{ + [B_POSITION_PLAYER_LEFT] = + { + [FALSE] = {221, 86}, + [TRUE] = {144, 71}, + }, + [B_POSITION_OPPONENT_LEFT] = + { + [FALSE] = {20, 26}, + [TRUE] = {97, 14}, + }, + [B_POSITION_PLAYER_RIGHT] = + { + [TRUE] = {156, 96}, + }, + [B_POSITION_OPPONENT_RIGHT] = + { + [TRUE] = {85, 39}, + }, +}; + +const union AnimCmd sSpriteAnim_TypeIcon_Normal[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_NORMAL), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Fighting[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_FIGHTING), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Flying[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_FLYING), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Poison[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_POISON), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Ground[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_GROUND), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Rock[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_ROCK), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Bug[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_BUG), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Ghost[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_GHOST), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Steel[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_STEEL), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Mystery[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_MYSTERY), 0), + ANIMCMD_END +}; + +const union AnimCmd sSpriteAnim_TypeIcon_Fire[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_FIRE), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Water[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_WATER), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Grass[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_GRASS), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Electric[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_ELECTRIC), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Psychic[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_PSYCHIC), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Ice[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_ICE), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Dragon[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_DRAGON), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Dark[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_DARK), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Fairy[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_FAIRY), 0), + ANIMCMD_END +}; + +const union AnimCmd *const sSpriteAnimTable_TypeIcons[] = +{ + [TYPE_NONE] = sSpriteAnim_TypeIcon_Mystery, + [TYPE_NORMAL] = sSpriteAnim_TypeIcon_Normal, + [TYPE_FIGHTING] = sSpriteAnim_TypeIcon_Fighting, + [TYPE_FLYING] = sSpriteAnim_TypeIcon_Flying, + [TYPE_POISON] = sSpriteAnim_TypeIcon_Poison, + [TYPE_GROUND] = sSpriteAnim_TypeIcon_Ground, + [TYPE_ROCK] = sSpriteAnim_TypeIcon_Rock, + [TYPE_BUG] = sSpriteAnim_TypeIcon_Bug, + [TYPE_GHOST] = sSpriteAnim_TypeIcon_Ghost, + [TYPE_STEEL] = sSpriteAnim_TypeIcon_Steel, + [TYPE_MYSTERY] = sSpriteAnim_TypeIcon_Mystery, + [TYPE_FIRE] = sSpriteAnim_TypeIcon_Fire, + [TYPE_WATER] = sSpriteAnim_TypeIcon_Water, + [TYPE_GRASS] = sSpriteAnim_TypeIcon_Grass, + [TYPE_ELECTRIC] = sSpriteAnim_TypeIcon_Electric, + [TYPE_PSYCHIC] = sSpriteAnim_TypeIcon_Psychic, + [TYPE_ICE] = sSpriteAnim_TypeIcon_Ice, + [TYPE_DRAGON] = sSpriteAnim_TypeIcon_Dragon, + [TYPE_DARK] = sSpriteAnim_TypeIcon_Dark, + [TYPE_FAIRY] = sSpriteAnim_TypeIcon_Fairy, + [TYPE_STELLAR] = sSpriteAnim_TypeIcon_Mystery, +}; + +const struct CompressedSpritePalette sTypeIconPal1 = +{ + .data = gBattleIcons_Pal1, + .tag = TYPE_ICON_TAG +}; + +const struct CompressedSpritePalette sTypeIconPal2 = +{ + .data = gBattleIcons_Pal2, + .tag = TYPE_ICON_TAG_2 +}; + +const struct OamData sOamData_TypeIcons = +{ + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .shape = SPRITE_SHAPE(8x16), + .size = SPRITE_SIZE(8x16), + .priority = 1, +}; + +const struct CompressedSpriteSheet sSpriteSheet_TypeIcons2 = +{ + .data = gBattleIcons_Gfx2, + .size = (8*16) * 9, + .tag = TYPE_ICON_TAG_2, +}; + +const struct CompressedSpriteSheet sSpriteSheet_TypeIcons1 = +{ + .data = gBattleIcons_Gfx1, + .size = (8*16) * 10, + .tag = TYPE_ICON_TAG, +}; + +const struct SpriteTemplate sSpriteTemplate_TypeIcons1 = +{ + .tileTag = TYPE_ICON_TAG, + .paletteTag = TYPE_ICON_TAG, + .oam = &sOamData_TypeIcons, + .anims = sSpriteAnimTable_TypeIcons, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_TypeIcon +}; + +const struct SpriteTemplate sSpriteTemplate_TypeIcons2 = +{ + .tileTag = TYPE_ICON_TAG_2, + .paletteTag = TYPE_ICON_TAG_2, + .oam = &sOamData_TypeIcons, + .anims = sSpriteAnimTable_TypeIcons, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_TypeIcon +}; + +void LoadTypeIcons(u32 battler) +{ + u32 position; + + if (B_SHOW_TYPES == SHOW_TYPES_NEVER) + return; + + LoadTypeSpritesAndPalettes(); + + for (position = 0; position < gBattlersCount; ++position) + LoadTypeIconsPerBattler(battler, position); +} + +static void LoadTypeSpritesAndPalettes(void) +{ + if (IndexOfSpritePaletteTag(TYPE_ICON_TAG) != UCHAR_MAX) + return; + + LoadCompressedSpriteSheet(&sSpriteSheet_TypeIcons1); + LoadCompressedSpriteSheet(&sSpriteSheet_TypeIcons2); + LoadCompressedSpritePalette(&sTypeIconPal1); + LoadCompressedSpritePalette(&sTypeIconPal2); +} + +static void LoadTypeIconsPerBattler(u32 battler, u32 position) +{ + u32 typeNum, types[2]; + u32 battlerId = GetBattlerAtPosition(position); + bool32 useDoubleBattleCoords = UseDoubleBattleCoords(battlerId); + + if (!IsBattlerAlive(battlerId)) + return; + + for (typeNum = 0; typeNum < 2; ++typeNum) + types[typeNum] = GetMonPublicType(battlerId, typeNum); + + for (typeNum = 0; typeNum < 2; ++typeNum) + CreateSpriteFromType(position, useDoubleBattleCoords, types, typeNum, battler); +} + +static bool32 UseDoubleBattleCoords(u32 position) +{ + if (!IsDoubleBattle()) + return FALSE; + + if ((position == B_POSITION_PLAYER_LEFT) && (gBattleMons[B_POSITION_PLAYER_RIGHT].species == SPECIES_NONE)) + return FALSE; + + if ((position == B_POSITION_OPPONENT_LEFT) && (gBattleMons[B_POSITION_OPPONENT_RIGHT].species == SPECIES_NONE)) + return FALSE; + + return TRUE; +} + +static u32 GetMonPublicType(u32 battlerId, u32 typeNum) +{ + struct Pokemon* mon = GetPartyBattlerData(battlerId); + u32 monSpecies = GetMonData(mon,MON_DATA_SPECIES,NULL); + struct Pokemon* monIllusion; + u32 illusionSpecies; + + if (ShouldHideUncaughtType(monSpecies)) + return TYPE_MYSTERY; + + monIllusion = GetIllusionMonPtr(battlerId); + illusionSpecies = GetMonData(monIllusion,MON_DATA_SPECIES,NULL); + + if (GetActiveGimmick(battlerId) == GIMMICK_TERA) + return GetMonDefensiveTeraType(mon,monIllusion,battlerId,typeNum,illusionSpecies,monSpecies); + + if (IsIllusionActiveAndTypeUnchanged(monIllusion,monSpecies, battlerId)) + return gSpeciesInfo[illusionSpecies].types[typeNum]; + + return gBattleMons[battlerId].types[typeNum]; +} + +static bool32 ShouldHideUncaughtType(u32 species) +{ + if (B_SHOW_TYPES != SHOW_TYPES_CAUGHT) + return FALSE; + + if (GetSetPokedexFlag(SpeciesToNationalDexNum(species),FLAG_GET_CAUGHT)) + return FALSE; + + return TRUE; +} + +static u32 GetMonDefensiveTeraType(struct Pokemon * mon, struct Pokemon* monIllusion, u32 battlerId, u32 typeNum, u32 illusionSpecies, u32 monSpecies) +{ + u32 teraType = GetBattlerTeraType(battlerId); + u32 targetSpecies; + + if (teraType != TYPE_STELLAR) + return teraType; + + targetSpecies = (monIllusion != NULL) ? illusionSpecies : monSpecies; + + return gSpeciesInfo[targetSpecies].types[typeNum]; +} + +static u32 IsIllusionActiveAndTypeUnchanged(struct Pokemon* monIllusion, u32 monSpecies, u32 battlerId) +{ + u32 typeNum; + + if (monIllusion == NULL) + return FALSE; + + for (typeNum = 0; typeNum < 2; typeNum++) + if (gSpeciesInfo[monSpecies].types[typeNum] != gBattleMons[battlerId].types[typeNum]) + return FALSE; + + return TRUE; +} + +static void CreateSpriteFromType(u32 position, bool32 useDoubleBattleCoords, u32 types[], u32 typeNum, u32 battler) +{ + s32 x = 0, y = 0; + + if (ShouldSkipSecondType(types, typeNum)) + return; + + SetTypeIconXY(&x, &y, position, useDoubleBattleCoords, typeNum); + + CreateSpriteAndSetTypeSpriteAttributes(types[typeNum], x, y, position, battler, useDoubleBattleCoords); +} + +static bool32 ShouldSkipSecondType(u32 types[], u32 typeNum) +{ + if (!typeNum) + return FALSE; + + if (types[0] != types[1]) + return FALSE; + + return TRUE; +} + +static void SetTypeIconXY(s32* x, s32* y, u32 position, bool32 useDoubleBattleCoords, u32 typeNum) +{ + *x = sTypeIconPositions[position][useDoubleBattleCoords].x; + *y = sTypeIconPositions[position][useDoubleBattleCoords].y + (11 * typeNum); +} + +static void CreateSpriteAndSetTypeSpriteAttributes(u32 type, u32 x, u32 y, u32 position, u32 battler, bool32 useDoubleBattleCoords) +{ + struct Sprite* sprite; + const struct SpriteTemplate* spriteTemplate = gTypesInfo[type].useSecondTypeIconPalette ? &sSpriteTemplate_TypeIcons2 : &sSpriteTemplate_TypeIcons1; + u32 spriteId = CreateSpriteAtEnd(spriteTemplate, x, y, UCHAR_MAX); + + if (spriteId == MAX_SPRITES) + return; + + sprite = &gSprites[spriteId]; + sprite->tMonPosition = position; + sprite->tBattlerId = battler; + sprite->tVerticalPosition = y; + + sprite->hFlip = ShouldFlipTypeIcon(useDoubleBattleCoords, position, type); + + StartSpriteAnim(sprite, type); +} + +static bool32 ShouldFlipTypeIcon(bool32 useDoubleBattleCoords, u32 position, u32 typeId) +{ + bool32 side = (useDoubleBattleCoords) ? B_SIDE_OPPONENT : B_SIDE_PLAYER; + + if (GetBattlerSide(GetBattlerAtPosition(position)) != side) + return FALSE; + + return !gTypesInfo[typeId].isSpecialCaseType; +} + +static void SpriteCB_TypeIcon(struct Sprite* sprite) +{ + u32 position = sprite->tMonPosition; + u32 battlerId = sprite->tBattlerId; + bool32 useDoubleBattleCoords = UseDoubleBattleCoords(GetBattlerAtPosition(position)); + + if (sprite->tHideIconTimer == NUM_FRAMES_HIDE_TYPE_ICON) + { + DestroyTypeIcon(sprite); + return; + } + + if (ShouldHideTypeIcon(battlerId)) + { + sprite->x += GetTypeIconHideMovement(useDoubleBattleCoords, position); + ++sprite->tHideIconTimer; + return; + } + + sprite->x += GetTypeIconSlideMovement(useDoubleBattleCoords,position, sprite->x); + sprite->y = GetTypeIconBounceMovement(sprite->tVerticalPosition,position); +} + +static const u32 typeIconTags[] = +{ + TYPE_ICON_TAG, + TYPE_ICON_TAG_2 +}; + +static void DestroyTypeIcon(struct Sprite* sprite) +{ + u32 spriteId, tag; + + DestroySpriteAndFreeResources(sprite); + + for (spriteId = 0; spriteId < MAX_SPRITES; ++spriteId) + { + if (!gSprites[spriteId].inUse) + continue; + + for (tag = 0; tag < 2; tag++) + { + if (gSprites[spriteId].template->paletteTag == typeIconTags[tag]) + return; + + if (gSprites[spriteId].template->tileTag == typeIconTags[tag]) + return; + } + } + + FreeAllTypeIconResources(); +} + +static void FreeAllTypeIconResources(void) +{ + u32 tag; + + for (tag = 0; tag < 2; tag++) + { + FreeSpriteTilesByTag(typeIconTags[tag]); + FreeSpritePaletteByTag(typeIconTags[tag]); + } +} + +static void (* const sShowTypesControllerFuncs[])(u32 battler) = +{ + PlayerHandleChooseMove, + HandleChooseMoveAfterDma3, + HandleInputChooseTarget, + HandleInputShowTargets, + HandleInputShowEntireFieldTargets, + HandleMoveSwitching, + HandleInputChooseMove, +}; + + +static bool32 ShouldHideTypeIcon(u32 battlerId) +{ + u32 funcIndex; + + for (funcIndex = 0; funcIndex < ARRAY_COUNT(sShowTypesControllerFuncs); funcIndex++) + if (gBattlerControllerFuncs[battlerId] == sShowTypesControllerFuncs[funcIndex]) + return FALSE; + + return TRUE; +} + +static s32 GetTypeIconHideMovement(bool32 useDoubleBattleCoords, u32 position) +{ + if (useDoubleBattleCoords) + { + if (position == B_POSITION_PLAYER_LEFT || position == B_POSITION_PLAYER_RIGHT) + return 1; + else + return -1; + } + + if (position == B_POSITION_PLAYER_LEFT) + return -1; + else + return 1; +} + +static s32 GetTypeIconSlideMovement(bool32 useDoubleBattleCoords, u32 position, s32 xPos) +{ + if (useDoubleBattleCoords) + { + switch (position) + { + case B_POSITION_PLAYER_LEFT: + case B_POSITION_PLAYER_RIGHT: + if (xPos > sTypeIconPositions[position][useDoubleBattleCoords].x - 10) + return -1; + break; + default: + case B_POSITION_OPPONENT_LEFT: + case B_POSITION_OPPONENT_RIGHT: + if (xPos < sTypeIconPositions[position][useDoubleBattleCoords].x + 10) + return 1; + break; + } + return 0; + } + + if (position == B_POSITION_PLAYER_LEFT) + { + if (xPos < sTypeIconPositions[position][useDoubleBattleCoords].x + 10) + return 1; + } + else + { + if (xPos > sTypeIconPositions[position][useDoubleBattleCoords].x - 10) + return -1; + } + return 0; +} + +static s32 GetTypeIconBounceMovement(s32 originalY, u32 position) +{ + struct Sprite* healthbox = &gSprites[gHealthboxSpriteIds[GetBattlerAtPosition(position)]]; + return originalY + healthbox->y2; +} + From 320ab747b3823f5ccca7834402ac7dbbedb4ba99 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Mon, 6 Jan 2025 23:26:18 +0100 Subject: [PATCH 02/13] sync battle controller opponent --- src/battle_controller_opponent.c | 320 ++++++++++++++++++------------- 1 file changed, 189 insertions(+), 131 deletions(-) diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 744762f9a..de548b158 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -1,38 +1,49 @@ #include "global.h" -#include "gflib.h" -#include "data.h" -#include "m4a.h" -#include "task.h" -#include "util.h" -#include "pokeball.h" -#include "random.h" #include "battle.h" #include "battle_ai_main.h" -#include "battle_ai_switch_items.h" #include "battle_ai_util.h" +#include "constants/battle_ai.h" #include "battle_anim.h" #include "battle_controllers.h" -#include "battle_gfx_sfx_util.h" -#include "battle_interface.h" #include "battle_message.h" +#include "battle_interface.h" #include "battle_setup.h" #include "battle_tower.h" #include "battle_z_move.h" +#include "bg.h" +#include "data.h" +#include "item.h" #include "link.h" +#include "main.h" +#include "m4a.h" +#include "palette.h" #include "party_menu.h" +#include "pokeball.h" +#include "pokemon.h" +#include "random.h" +#include "reshow_battle_screen.h" +#include "sound.h" +#include "string_util.h" +#include "task.h" +#include "text.h" #include "trainer_tower.h" -#include "constants/battle_ai.h" +#include "util.h" +#include "window.h" #include "constants/battle_anim.h" +#include "constants/items.h" #include "constants/moves.h" #include "constants/party_menu.h" #include "constants/songs.h" -#include "constants/sound.h" +#include "constants/trainers.h" +#include "test_runner.h" static void OpponentHandleLoadMonSprite(u32 battler); static void OpponentHandleSwitchInAnim(u32 battler); static void OpponentHandleDrawTrainerPic(u32 battler); static void OpponentHandleTrainerSlide(u32 battler); static void OpponentHandleTrainerSlideBack(u32 battler); +static void OpponentHandleMoveAnimation(u32 battler); +static void OpponentHandlePrintString(u32 battler); static void OpponentHandleChooseAction(u32 battler); static void OpponentHandleChooseMove(u32 battler); static void OpponentHandleChooseItem(u32 battler); @@ -49,64 +60,64 @@ static void SwitchIn_HandleSoundAndEnd(u32 battler); static void (*const sOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = { - [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, // done - [CONTROLLER_GETRAWMONDATA] = BtlController_HandleGetRawMonData, // done - [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, // done - [CONTROLLER_SETRAWMONDATA] = BtlController_HandleSetRawMonData, // done - [CONTROLLER_LOADMONSPRITE] = OpponentHandleLoadMonSprite, // done - [CONTROLLER_SWITCHINANIM] = OpponentHandleSwitchInAnim, // done - [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, // done - [CONTROLLER_DRAWTRAINERPIC] = OpponentHandleDrawTrainerPic, // done - [CONTROLLER_TRAINERSLIDE] = OpponentHandleTrainerSlide, // done - [CONTROLLER_TRAINERSLIDEBACK] = OpponentHandleTrainerSlideBack, // done - [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, // done - [CONTROLLER_PALETTEFADE] = BtlController_Empty, // done - [CONTROLLER_SUCCESSBALLTHROWANIM] = BtlController_Empty, // done - [CONTROLLER_BALLTHROWANIM] = BtlController_Empty, // done - [CONTROLLER_PAUSE] = BtlController_Empty, // done - [CONTROLLER_MOVEANIMATION] = BtlController_HandleMoveAnimation, // done - [CONTROLLER_PRINTSTRING] = BtlController_HandlePrintString, // done - [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, // done - [CONTROLLER_CHOOSEACTION] = OpponentHandleChooseAction, // done - [CONTROLLER_YESNOBOX] = BtlController_Empty, // done - [CONTROLLER_CHOOSEMOVE] = OpponentHandleChooseMove, // done - [CONTROLLER_OPENBAG] = OpponentHandleChooseItem, // done - [CONTROLLER_CHOOSEPOKEMON] = OpponentHandleChoosePokemon, // done - [CONTROLLER_23] = BtlController_Empty, // done - [CONTROLLER_HEALTHBARUPDATE] = OpponentHandleHealthBarUpdate, // done - [CONTROLLER_EXPUPDATE] = BtlController_Empty, // done - [CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate, // done - [CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation, // done - [CONTROLLER_STATUSXOR] = BtlController_Empty, // done - [CONTROLLER_DATATRANSFER] = BtlController_Empty, // done - [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, // done - [CONTROLLER_PLAYBGM] = BtlController_Empty, // done - [CONTROLLER_32] = BtlController_Empty, // done - [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, // done - [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, // done - [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, // done - [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, // done - [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, // done - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, // done - [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, // done - [CONTROLLER_CANTSWITCH] = BtlController_Empty, // done - [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, // done - [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, // done - [CONTROLLER_FAINTINGCRY] = BtlController_HandleFaintingCry, // done - [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, // done - [CONTROLLER_INTROTRAINERBALLTHROW] = OpponentHandleIntroTrainerBallThrow, // done - [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = OpponentHandleDrawPartyStatusSummary, // done - [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_HandleHidePartyStatusSummary, // done - [CONTROLLER_ENDBOUNCE] = BtlController_Empty, // done - [CONTROLLER_SPRITEINVISIBILITY] = BtlController_HandleSpriteInvisibility, // done - [CONTROLLER_BATTLEANIMATION] = OpponentHandleBattleAnimation, // done - [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, // done - [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done - [CONTROLLER_ENDLINKBATTLE] = OpponentHandleEndLinkBattle, // done + [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, + [CONTROLLER_GETRAWMONDATA] = BtlController_HandleGetRawMonData, + [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, + [CONTROLLER_SETRAWMONDATA] = BtlController_HandleSetRawMonData, + [CONTROLLER_LOADMONSPRITE] = OpponentHandleLoadMonSprite, + [CONTROLLER_SWITCHINANIM] = OpponentHandleSwitchInAnim, + [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, + [CONTROLLER_DRAWTRAINERPIC] = OpponentHandleDrawTrainerPic, + [CONTROLLER_TRAINERSLIDE] = OpponentHandleTrainerSlide, + [CONTROLLER_TRAINERSLIDEBACK] = OpponentHandleTrainerSlideBack, + [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, + [CONTROLLER_PALETTEFADE] = BtlController_Empty, + [CONTROLLER_SUCCESSBALLTHROWANIM] = BtlController_Empty, + [CONTROLLER_BALLTHROWANIM] = BtlController_Empty, + [CONTROLLER_PAUSE] = BtlController_Empty, + [CONTROLLER_MOVEANIMATION] = OpponentHandleMoveAnimation, + [CONTROLLER_PRINTSTRING] = OpponentHandlePrintString, + [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, + [CONTROLLER_CHOOSEACTION] = OpponentHandleChooseAction, + [CONTROLLER_YESNOBOX] = BtlController_Empty, + [CONTROLLER_CHOOSEMOVE] = OpponentHandleChooseMove, + [CONTROLLER_OPENBAG] = OpponentHandleChooseItem, + [CONTROLLER_CHOOSEPOKEMON] = OpponentHandleChoosePokemon, + [CONTROLLER_23] = BtlController_Empty, + [CONTROLLER_HEALTHBARUPDATE] = OpponentHandleHealthBarUpdate, + [CONTROLLER_EXPUPDATE] = BtlController_Empty, + [CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate, + [CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation, + [CONTROLLER_STATUSXOR] = BtlController_Empty, + [CONTROLLER_DATATRANSFER] = BtlController_Empty, + [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, + [CONTROLLER_PLAYBGM] = BtlController_Empty, + [CONTROLLER_32] = BtlController_Empty, + [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, + [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, + [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, + [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, + [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, + [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, + [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, + [CONTROLLER_CANTSWITCH] = BtlController_Empty, + [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, + [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, + [CONTROLLER_FAINTINGCRY] = BtlController_HandleFaintingCry, + [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, + [CONTROLLER_INTROTRAINERBALLTHROW] = OpponentHandleIntroTrainerBallThrow, + [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = OpponentHandleDrawPartyStatusSummary, + [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_HandleHidePartyStatusSummary, + [CONTROLLER_ENDBOUNCE] = BtlController_Empty, + [CONTROLLER_SPRITEINVISIBILITY] = BtlController_HandleSpriteInvisibility, + [CONTROLLER_BATTLEANIMATION] = OpponentHandleBattleAnimation, + [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, + [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, + [CONTROLLER_ENDLINKBATTLE] = OpponentHandleEndLinkBattle, [CONTROLLER_DEBUGMENU] = BtlController_Empty, - [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop // done + [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop }; void SetControllerToOpponent(u32 battler) @@ -117,9 +128,9 @@ void SetControllerToOpponent(u32 battler) static void OpponentBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { - if (gBattleResources->bufferA[battler][0] < NELEMS(sOpponentBufferCommands)) + if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sOpponentBufferCommands)) sOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler); else OpponentBufferExecCompleted(battler); @@ -170,7 +181,9 @@ static void Intro_WaitForShinyAnimAndHealthbox(u32 battler) FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); } else + { return; + } } else if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim) { @@ -183,13 +196,17 @@ static void Intro_WaitForShinyAnimAndHealthbox(u32 battler) FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); } else + { return; + } } - gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; - gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; + gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; + gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; } else + { return; + } gBattleSpritesDataPtr->healthBoxesData[battler].introEndDelay = 3; gBattlerControllerFuncs[battler] = Intro_DelayAndEnd; @@ -259,7 +276,9 @@ static void Intro_TryShinyAnimShowHealthbox(u32 battler) m4aMPlayContinue(&gMPlayInfo_BGM); } else + { m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); + } } gBattleSpritesDataPtr->healthBoxesData[battler].bgmRestored = TRUE; bgmRestored = TRUE; @@ -337,8 +356,12 @@ static void SwitchIn_HandleSoundAndEnd(u32 battler) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].specialAnimActive && !IsCryPlayingOrClearCrySongs()) { - m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); - OpponentBufferExecCompleted(battler); + if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy + || gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy_2) + { + m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); + OpponentBufferExecCompleted(battler); + } } } @@ -362,14 +385,12 @@ static void SwitchIn_ShowHealthbox(u32 battler) static void SwitchIn_TryShinyAnim(u32 battler) { - if (!gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive - && !gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim) - { + if (!gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim + && !gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive) TryShinyAnimation(battler, &gEnemyParty[gBattlerPartyIndexes[battler]]); - } if (gSprites[gBattleControllerData[battler]].callback == SpriteCallbackDummy - && !gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive) + && !gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive) { DestroySprite(&gSprites[gBattleControllerData[battler]]); SetBattlerShadowSpriteCallback(battler, GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES)); @@ -389,7 +410,7 @@ void OpponentBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } @@ -404,11 +425,11 @@ static void OpponentHandleSwitchInAnim(u32 battler) BtlController_HandleSwitchInAnim(battler, FALSE, SwitchIn_TryShinyAnim); } -static u32 OpponentGetTrainerPicId(u32 battlerId) // TODO: trainer refactoring +static u32 OpponentGetTrainerPicId(u32 battlerId) { u32 trainerPicId; - if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) { if (gBattleTypeFlags & (BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TOWER_LINK_MULTI)) { @@ -423,9 +444,13 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) // TODO: trainer refactoring } } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_TOWER) + { trainerPicId = GetTrainerTowerTrainerFrontSpriteId(); + } else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) + { trainerPicId = GetEreaderTrainerFrontSpriteId(); + } else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { if (battlerId != 1) @@ -434,7 +459,9 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) // TODO: trainer refactoring trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A); } else + { trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A); + } return trainerPicId; } @@ -470,6 +497,16 @@ static void OpponentHandleTrainerSlideBack(u32 battler) BtlController_HandleTrainerSlideBack(battler, 35, FALSE); } +static void OpponentHandleMoveAnimation(u32 battler) +{ + BtlController_HandleMoveAnimation(battler); +} + +static void OpponentHandlePrintString(u32 battler) +{ + BtlController_HandlePrintString(battler); +} + static void OpponentHandleChooseAction(u32 battler) { AI_TrySwitchOrUseItem(battler); @@ -484,43 +521,50 @@ static void OpponentHandleChooseMove(u32 battler) if (gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER) || IsWildMonSmart()) { - chosenMoveId = gBattleStruct->aiMoveOrAction[battler]; - gBattlerTarget = gBattleStruct->aiChosenTarget[battler]; - switch (chosenMoveId) + if (gBattleTypeFlags & BATTLE_TYPE_PALACE) { - case AI_CHOICE_WATCH: - BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_SAFARI_WATCH_CAREFULLY, 0); - break; - case AI_CHOICE_FLEE: - BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_RUN, 0); - break; - case 6: - BtlController_EmitTwoReturnValues(battler, BUFFER_B, 15, gBattlerTarget); - break; - default: + // BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, ChooseMoveAndTargetInBattlePalace(battler)); + } + else + { + chosenMoveId = gBattleStruct->aiMoveOrAction[battler]; + gBattlerTarget = gBattleStruct->aiChosenTarget[battler]; + switch (chosenMoveId) { - u16 chosenMove = moveInfo->moves[chosenMoveId]; - if (GetBattlerMoveTargetType(battler, chosenMove) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) - gBattlerTarget = battler; - if (GetBattlerMoveTargetType(battler, chosenMove) & MOVE_TARGET_BOTH) + case AI_CHOICE_WATCH: + BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_SAFARI_WATCH_CAREFULLY, 0); + break; + case AI_CHOICE_FLEE: + BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_RUN, 0); + break; + case 6: + BtlController_EmitTwoReturnValues(battler, BUFFER_B, 15, gBattlerTarget); + break; + default: { - gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); - if (gAbsentBattlerFlags & (1u << gBattlerTarget)) - gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); - } - // If opponent can and should use a gimmick (considering trainer data), do it - if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE - && !(gBattleStruct->gimmick.usableGimmick[battler] == GIMMICK_Z_MOVE - && !ShouldUseZMove(battler, gBattlerTarget, moveInfo->moves[chosenMoveId]))) - { - BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, (chosenMoveId) | (RET_GIMMICK) | (gBattlerTarget << 8)); - } - else - { - BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, (chosenMoveId) | (gBattlerTarget << 8)); + u16 chosenMove = moveInfo->moves[chosenMoveId]; + if (GetBattlerMoveTargetType(battler, chosenMove) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) + gBattlerTarget = battler; + if (GetBattlerMoveTargetType(battler, chosenMove) & MOVE_TARGET_BOTH) + { + gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + if (gAbsentBattlerFlags & (1u << gBattlerTarget)) + gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); + } + // If opponent can and should use a gimmick (considering trainer data), do it + if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE + && !(gBattleStruct->gimmick.usableGimmick[battler] == GIMMICK_Z_MOVE + && !ShouldUseZMove(battler, gBattlerTarget, moveInfo->moves[chosenMoveId]))) + { + BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, (chosenMoveId) | (RET_GIMMICK) | (gBattlerTarget << 8)); + } + else + { + BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, (chosenMoveId) | (gBattlerTarget << 8)); + } } + break; } - break; } OpponentBufferExecCompleted(battler); } @@ -543,7 +587,7 @@ static void OpponentHandleChooseMove(u32 battler) } while (!CanTargetBattler(battler, target, move)); // Don't bother to loop through table if the move can't attack ally - if (B_WILD_NATURAL_ENEMIES == TRUE && !(gMovesInfo[move].target & MOVE_TARGET_BOTH)) + if (B_WILD_NATURAL_ENEMIES == TRUE && !(GetBattlerMoveTargetType(battler, move) & MOVE_TARGET_BOTH)) { u16 i, speciesAttacker, speciesTarget, isPartnerEnemy = FALSE; static const u16 naturalEnemies[][2] = @@ -590,6 +634,22 @@ static void OpponentHandleChooseItem(u32 battler) OpponentBufferExecCompleted(battler); } +static inline bool32 IsAcePokemon(u32 chosenMonId, u32 pokemonInBattle, u32 battler) +{ + return AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_ACE_POKEMON + && (chosenMonId == CalculateEnemyPartyCountInSide(battler) - 1) + && CountAIAliveNonEggMonsExcept(PARTY_SIZE) != pokemonInBattle; +} + +static inline bool32 IsDoubleAcePokemon(u32 chosenMonId, u32 pokemonInBattle, u32 battler) +{ + return AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON + && (chosenMonId == CalculateEnemyPartyCountInSide(battler) - 1) + && (chosenMonId == CalculateEnemyPartyCountInSide(battler) - 2) + && CountAIAliveNonEggMonsExcept(PARTY_SIZE) != pokemonInBattle + && CountAIAliveNonEggMonsExcept(PARTY_SIZE-1) != pokemonInBattle; +} + static void OpponentHandleChoosePokemon(u32 battler) { s32 chosenMonId; @@ -601,14 +661,14 @@ static void OpponentHandleChoosePokemon(u32 battler) chosenMonId = gSelectedMonPartyId = GetFirstFaintedPartyIndex(battler); } // Switching out - else if (*(gBattleStruct->AI_monToSwitchIntoId + battler) == PARTY_SIZE) + else if (gBattleStruct->AI_monToSwitchIntoId[battler] == PARTY_SIZE) { chosenMonId = GetMostSuitableMonToSwitchInto(battler, TRUE); if (chosenMonId == PARTY_SIZE) { s32 battler1, battler2, firstId, lastId; - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!IsDoubleBattle()) { battler2 = battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); } @@ -620,27 +680,25 @@ static void OpponentHandleChoosePokemon(u32 battler) } GetAIPartyIndexes(battler, &firstId, &lastId); - for (chosenMonId = (lastId-1); chosenMonId >= firstId; chosenMonId--) { - if (IsValidForBattle(&gEnemyParty[chosenMonId]) - && chosenMonId != gBattlerPartyIndexes[battler1] - && chosenMonId != gBattlerPartyIndexes[battler2] - && (!(AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_ACE_POKEMON) - || chosenMonId != CalculateEnemyPartyCount() - 1 - || CountAIAliveNonEggMonsExcept(PARTY_SIZE) == pokemonInBattle)) - { + if (!IsValidForBattle(&gEnemyParty[chosenMonId]) + || chosenMonId == gBattlerPartyIndexes[battler1] + || chosenMonId == gBattlerPartyIndexes[battler2]) + continue; + + if (!IsAcePokemon(chosenMonId, pokemonInBattle, battler) + && !IsDoubleAcePokemon(chosenMonId, pokemonInBattle, battler)) break; - } } } - *(gBattleStruct->monToSwitchIntoId + battler) = chosenMonId; + gBattleStruct->monToSwitchIntoId[battler] = chosenMonId; } else { - chosenMonId = *(gBattleStruct->AI_monToSwitchIntoId + battler); - *(gBattleStruct->AI_monToSwitchIntoId + battler) = PARTY_SIZE; - *(gBattleStruct->monToSwitchIntoId + battler) = chosenMonId; + chosenMonId = gBattleStruct->AI_monToSwitchIntoId[battler]; + gBattleStruct->AI_monToSwitchIntoId[battler] = PARTY_SIZE; + gBattleStruct->monToSwitchIntoId[battler] = chosenMonId; } #if TESTING TestRunner_Battle_CheckSwitch(battler, chosenMonId); From 562cdb48068c38d8d4c9ec73b13cc632432f5e1f Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Mon, 6 Jan 2025 23:33:20 +0100 Subject: [PATCH 03/13] update battle controller link opponent --- src/battle_controller_link_opponent.c | 183 +++++++++++++++++--------- 1 file changed, 118 insertions(+), 65 deletions(-) diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index ee1293c10..990130217 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -1,30 +1,46 @@ #include "global.h" #include "battle.h" +#include "battle_ai_main.h" #include "battle_anim.h" #include "battle_controllers.h" #include "battle_interface.h" #include "battle_message.h" #include "battle_setup.h" -#include "gflib.h" +#include "battle_tower.h" +#include "bg.h" #include "data.h" #include "link.h" +#include "main.h" #include "m4a.h" +#include "palette.h" #include "pokeball.h" +#include "pokemon.h" +#include "recorded_battle.h" +#include "reshow_battle_screen.h" +#include "sound.h" +#include "string_util.h" #include "task.h" +#include "text.h" #include "util.h" +#include "window.h" #include "constants/battle_anim.h" #include "constants/songs.h" -#include "constants/sound.h" #include "constants/trainers.h" +#include "recorded_battle.h" +#include "random.h" static void LinkOpponentHandleLoadMonSprite(u32 battler); static void LinkOpponentHandleSwitchInAnim(u32 battler); static void LinkOpponentHandleDrawTrainerPic(u32 battler); +static void LinkOpponentHandleTrainerSlide(u32 battler); static void LinkOpponentHandleTrainerSlideBack(u32 battler); +static void LinkOpponentHandleMoveAnimation(u32 battler); +static void LinkOpponentHandlePrintString(u32 battler); static void LinkOpponentHandleHealthBarUpdate(u32 battler); static void LinkOpponentHandleIntroTrainerBallThrow(u32 battler); static void LinkOpponentHandleDrawPartyStatusSummary(u32 battler); static void LinkOpponentHandleBattleAnimation(u32 battler); +static void LinkOpponentHandleLinkStandbyMsg(u32 battler); static void LinkOpponentHandleEndLinkBattle(u32 battler); static void LinkOpponentBufferRunCommand(u32 battler); @@ -33,64 +49,64 @@ static void SwitchIn_HandleSoundAndEnd(u32 battler); static void (*const sLinkOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = { - [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, // done - [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, // done - [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, // done - [CONTROLLER_SETRAWMONDATA] = BtlController_HandleSetRawMonData, // done - [CONTROLLER_LOADMONSPRITE] = LinkOpponentHandleLoadMonSprite, // done - [CONTROLLER_SWITCHINANIM] = LinkOpponentHandleSwitchInAnim, // done - [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, // done - [CONTROLLER_DRAWTRAINERPIC] = LinkOpponentHandleDrawTrainerPic, // done - [CONTROLLER_TRAINERSLIDE] = BtlController_Empty, // done - [CONTROLLER_TRAINERSLIDEBACK] = LinkOpponentHandleTrainerSlideBack, // done - [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, // done - [CONTROLLER_PALETTEFADE] = BtlController_Empty, // done - [CONTROLLER_SUCCESSBALLTHROWANIM] = BtlController_Empty, // done - [CONTROLLER_BALLTHROWANIM] = BtlController_Empty, // done - [CONTROLLER_PAUSE] = BtlController_Empty, // done - [CONTROLLER_MOVEANIMATION] = BtlController_HandleMoveAnimation, // done - [CONTROLLER_PRINTSTRING] = BtlController_HandlePrintString, // done - [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, // done - [CONTROLLER_CHOOSEACTION] = BtlController_Empty, // done - [CONTROLLER_YESNOBOX] = BtlController_Empty, // done - [CONTROLLER_CHOOSEMOVE] = BtlController_Empty, // done - [CONTROLLER_OPENBAG] = BtlController_Empty, // done - [CONTROLLER_CHOOSEPOKEMON] = BtlController_Empty, // done - [CONTROLLER_23] = BtlController_Empty, // done - [CONTROLLER_HEALTHBARUPDATE] = LinkOpponentHandleHealthBarUpdate, // done - [CONTROLLER_EXPUPDATE] = BtlController_Empty, // done - [CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate, // done - [CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation, // done - [CONTROLLER_STATUSXOR] = BtlController_Empty, // done - [CONTROLLER_DATATRANSFER] = BtlController_Empty, // done - [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, // done - [CONTROLLER_PLAYBGM] = BtlController_Empty, // done - [CONTROLLER_32] = BtlController_Empty, // done - [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, // done - [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, // done - [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, // done - [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, // done - [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, // done - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, // done - [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, // done - [CONTROLLER_CANTSWITCH] = BtlController_Empty, // done - [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, // done - [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, // done - [CONTROLLER_FAINTINGCRY] = BtlController_HandleFaintingCry, // done - [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, // done - [CONTROLLER_INTROTRAINERBALLTHROW] = LinkOpponentHandleIntroTrainerBallThrow, // done - [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = LinkOpponentHandleDrawPartyStatusSummary, // done - [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_HandleHidePartyStatusSummary, // done - [CONTROLLER_ENDBOUNCE] = BtlController_Empty, // done - [CONTROLLER_SPRITEINVISIBILITY] = BtlController_HandleSpriteInvisibility, // done - [CONTROLLER_BATTLEANIMATION] = LinkOpponentHandleBattleAnimation, // done - [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, // done - [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done - [CONTROLLER_ENDLINKBATTLE] = LinkOpponentHandleEndLinkBattle, // done + [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, + [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, + [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, + [CONTROLLER_SETRAWMONDATA] = BtlController_HandleSetRawMonData, + [CONTROLLER_LOADMONSPRITE] = LinkOpponentHandleLoadMonSprite, + [CONTROLLER_SWITCHINANIM] = LinkOpponentHandleSwitchInAnim, + [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, + [CONTROLLER_DRAWTRAINERPIC] = LinkOpponentHandleDrawTrainerPic, + [CONTROLLER_TRAINERSLIDE] = LinkOpponentHandleTrainerSlide, + [CONTROLLER_TRAINERSLIDEBACK] = LinkOpponentHandleTrainerSlideBack, + [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, + [CONTROLLER_PALETTEFADE] = BtlController_Empty, + [CONTROLLER_SUCCESSBALLTHROWANIM] = BtlController_Empty, + [CONTROLLER_BALLTHROWANIM] = BtlController_Empty, + [CONTROLLER_PAUSE] = BtlController_Empty, + [CONTROLLER_MOVEANIMATION] = LinkOpponentHandleMoveAnimation, + [CONTROLLER_PRINTSTRING] = LinkOpponentHandlePrintString, + [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, + [CONTROLLER_CHOOSEACTION] = BtlController_Empty, + [CONTROLLER_YESNOBOX] = BtlController_Empty, + [CONTROLLER_CHOOSEMOVE] = BtlController_Empty, + [CONTROLLER_OPENBAG] = BtlController_Empty, + [CONTROLLER_CHOOSEPOKEMON] = BtlController_Empty, + [CONTROLLER_23] = BtlController_Empty, + [CONTROLLER_HEALTHBARUPDATE] = LinkOpponentHandleHealthBarUpdate, + [CONTROLLER_EXPUPDATE] = BtlController_Empty, + [CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate, + [CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation, + [CONTROLLER_STATUSXOR] = BtlController_Empty, + [CONTROLLER_DATATRANSFER] = BtlController_Empty, + [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, + [CONTROLLER_PLAYBGM] = BtlController_Empty, + [CONTROLLER_32] = BtlController_Empty, + [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, + [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, + [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, + [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, + [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, + [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, + [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, + [CONTROLLER_CANTSWITCH] = BtlController_Empty, + [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, + [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, + [CONTROLLER_FAINTINGCRY] = BtlController_HandleFaintingCry, + [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, + [CONTROLLER_INTROTRAINERBALLTHROW] = LinkOpponentHandleIntroTrainerBallThrow, + [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = LinkOpponentHandleDrawPartyStatusSummary, + [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_HandleHidePartyStatusSummary, + [CONTROLLER_ENDBOUNCE] = BtlController_Empty, + [CONTROLLER_SPRITEINVISIBILITY] = BtlController_HandleSpriteInvisibility, + [CONTROLLER_BATTLEANIMATION] = LinkOpponentHandleBattleAnimation, + [CONTROLLER_LINKSTANDBYMSG] = LinkOpponentHandleLinkStandbyMsg, + [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, + [CONTROLLER_ENDLINKBATTLE] = LinkOpponentHandleEndLinkBattle, [CONTROLLER_DEBUGMENU] = BtlController_Empty, - [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop // done + [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop }; void SetControllerToLinkOpponent(u32 battler) @@ -101,7 +117,7 @@ void SetControllerToLinkOpponent(u32 battler) static void LinkOpponentBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sLinkOpponentBufferCommands)) sLinkOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -267,7 +283,7 @@ static void Intro_TryShinyAnimShowHealthbox(u32 battler) static void TryShinyAnimAfterMonAnim(u32 battler) { - if (gSprites[gBattlerSpriteIds[battler]].animEnded == TRUE + if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy && gSprites[gBattlerSpriteIds[battler]].x2 == 0) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim) @@ -300,14 +316,19 @@ static void SwitchIn_HandleSoundAndEnd(u32 battler) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].specialAnimActive && !IsCryPlayingOrClearCrySongs()) { - m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); - LinkOpponentBufferExecCompleted(battler); + if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy + || gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy_2) + { + m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); + LinkOpponentBufferExecCompleted(battler); + } } } static void SwitchIn_ShowHealthbox(u32 battler) { - if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim) + if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim + && gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy) { gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; @@ -354,7 +375,7 @@ static void LinkOpponentBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } @@ -426,11 +447,34 @@ static void LinkOpponentHandleDrawTrainerPic(u32 battler) BtlController_HandleDrawTrainerPic(battler, trainerPicId, TRUE, xPos, 40, -1); } +static void LinkOpponentHandleTrainerSlide(u32 battler) +{ + u32 trainerPicId; + + if (battler == B_POSITION_OPPONENT_LEFT) + trainerPicId = GetBattleTowerTrainerFrontSpriteId(gTrainerBattleOpponent_A); + else + trainerPicId = GetBattleTowerTrainerFrontSpriteId(gTrainerBattleOpponent_B); + + BtlController_HandleTrainerSlide(battler, trainerPicId); + LinkOpponentBufferExecCompleted(battler); // Possibly a bug, because execution should be completed after the slide in finishes. See Controller_WaitForTrainerPic. +} + static void LinkOpponentHandleTrainerSlideBack(u32 battler) { BtlController_HandleTrainerSlideBack(battler, 35, FALSE); } +static void LinkOpponentHandleMoveAnimation(u32 battler) +{ + BtlController_HandleMoveAnimation(battler); +} + +static void LinkOpponentHandlePrintString(u32 battler) +{ + BtlController_HandlePrintString(battler); +} + static void LinkOpponentHandleHealthBarUpdate(u32 battler) { BtlController_HandleHealthBarUpdate(battler, FALSE); @@ -451,13 +495,22 @@ static void LinkOpponentHandleBattleAnimation(u32 battler) BtlController_HandleBattleAnimation(battler, FALSE); } +static void LinkOpponentHandleLinkStandbyMsg(u32 battler) +{ + // RecordedBattle_RecordAllBattlerData(&gBattleResources->bufferA[battler][2]); + LinkOpponentBufferExecCompleted(battler); +} + static void LinkOpponentHandleEndLinkBattle(u32 battler) { + // RecordedBattle_RecordAllBattlerData(&gBattleResources->bufferA[battler][4]); + if (gBattleResources->bufferA[battler][1] == B_OUTCOME_DREW) gBattleOutcome = gBattleResources->bufferA[battler][1]; else gBattleOutcome = gBattleResources->bufferA[battler][1] ^ B_OUTCOME_DREW; + // gSaveBlock2Ptr->frontier.disableRecordBattle = gBattleResources->bufferA[battler][2]; FadeOutMapMusic(5); BeginFastPaletteFade(3); LinkOpponentBufferExecCompleted(battler); From da483e8b2b0ef15374d6071a98215bf7dc2e4796 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Mon, 6 Jan 2025 23:35:27 +0100 Subject: [PATCH 04/13] sync battle controller link partner --- src/battle_controller_link_partner.c | 174 ++++++++++++++++----------- 1 file changed, 106 insertions(+), 68 deletions(-) diff --git a/src/battle_controller_link_partner.c b/src/battle_controller_link_partner.c index 48b81e918..bec93f474 100644 --- a/src/battle_controller_link_partner.c +++ b/src/battle_controller_link_partner.c @@ -1,27 +1,45 @@ #include "global.h" -#include "gflib.h" -#include "data.h" -#include "link.h" -#include "pokeball.h" -#include "task.h" -#include "util.h" #include "battle.h" +#include "battle_ai_main.h" #include "battle_anim.h" #include "battle_controllers.h" #include "battle_interface.h" #include "battle_message.h" +#include "battle_setup.h" +#include "battle_tower.h" +#include "bg.h" +#include "data.h" +#include "link.h" +#include "main.h" +#include "m4a.h" +#include "palette.h" +#include "pokeball.h" +#include "pokemon.h" +#include "recorded_battle.h" +#include "reshow_battle_screen.h" +#include "sound.h" +#include "string_util.h" +#include "task.h" +#include "text.h" +#include "util.h" +#include "window.h" #include "constants/battle_anim.h" #include "constants/songs.h" -#include "constants/sound.h" +#include "constants/trainers.h" +#include "recorded_battle.h" +#include "random.h" static void LinkPartnerHandleLoadMonSprite(u32 battler); static void LinkPartnerHandleSwitchInAnim(u32 battler); static void LinkPartnerHandleDrawTrainerPic(u32 battler); static void LinkPartnerHandleTrainerSlideBack(u32 battler); +static void LinkPartnerHandleMoveAnimation(u32 battler); +static void LinkPartnerHandlePrintString(u32 battler); static void LinkPartnerHandleHealthBarUpdate(u32 battler); static void LinkPartnerHandleIntroTrainerBallThrow(u32 battler); static void LinkPartnerHandleDrawPartyStatusSummary(u32 battler); static void LinkPartnerHandleBattleAnimation(u32 battler); +static void LinkPartnerHandleLinkStandbyMsg(u32 battler); static void LinkPartnerHandleEndLinkBattle(u32 battler); static void LinkPartnerBufferRunCommand(u32 battler); @@ -30,64 +48,64 @@ static void SwitchIn_WaitAndEnd(u32 battler); static void (*const sLinkPartnerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = { - [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, // done - [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, // done - [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, // done - [CONTROLLER_SETRAWMONDATA] = BtlController_HandleSetRawMonData, // done - [CONTROLLER_LOADMONSPRITE] = LinkPartnerHandleLoadMonSprite, // done - [CONTROLLER_SWITCHINANIM] = LinkPartnerHandleSwitchInAnim, // done - [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, // done - [CONTROLLER_DRAWTRAINERPIC] = LinkPartnerHandleDrawTrainerPic, // done - [CONTROLLER_TRAINERSLIDE] = BtlController_Empty, // done - [CONTROLLER_TRAINERSLIDEBACK] = LinkPartnerHandleTrainerSlideBack, // done - [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, // done - [CONTROLLER_PALETTEFADE] = BtlController_Empty, // done - [CONTROLLER_SUCCESSBALLTHROWANIM] = BtlController_Empty, // done - [CONTROLLER_BALLTHROWANIM] = BtlController_Empty, // done - [CONTROLLER_PAUSE] = BtlController_Empty, // done - [CONTROLLER_MOVEANIMATION] = BtlController_HandleMoveAnimation, // done - [CONTROLLER_PRINTSTRING] = BtlController_HandlePrintString, // done - [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, // done - [CONTROLLER_CHOOSEACTION] = BtlController_Empty, // done - [CONTROLLER_YESNOBOX] = BtlController_Empty, // done - [CONTROLLER_CHOOSEMOVE] = BtlController_Empty, // done - [CONTROLLER_OPENBAG] = BtlController_Empty, // done - [CONTROLLER_CHOOSEPOKEMON] = BtlController_Empty, // done - [CONTROLLER_23] = BtlController_Empty, // done - [CONTROLLER_HEALTHBARUPDATE] = LinkPartnerHandleHealthBarUpdate, // done - [CONTROLLER_EXPUPDATE] = BtlController_Empty, // done - [CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate, // done - [CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation, // done - [CONTROLLER_STATUSXOR] = BtlController_Empty, // done - [CONTROLLER_DATATRANSFER] = BtlController_Empty, // done - [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, // done - [CONTROLLER_PLAYBGM] = BtlController_Empty, // done - [CONTROLLER_32] = BtlController_Empty, // done - [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, // done - [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, // done - [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, // done - [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, // done - [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, // done - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, // done - [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, // done - [CONTROLLER_CANTSWITCH] = BtlController_Empty, // done - [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, // done - [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, // done - [CONTROLLER_FAINTINGCRY] = BtlController_HandleFaintingCry, // done - [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, // done - [CONTROLLER_INTROTRAINERBALLTHROW] = LinkPartnerHandleIntroTrainerBallThrow, // done - [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = LinkPartnerHandleDrawPartyStatusSummary, // done - [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_HandleHidePartyStatusSummary, // done - [CONTROLLER_ENDBOUNCE] = BtlController_Empty, // done - [CONTROLLER_SPRITEINVISIBILITY] = BtlController_HandleSpriteInvisibility, // done - [CONTROLLER_BATTLEANIMATION] = LinkPartnerHandleBattleAnimation, // done - [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, // done - [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done - [CONTROLLER_ENDLINKBATTLE] = LinkPartnerHandleEndLinkBattle, // done + [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, + [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, + [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, + [CONTROLLER_SETRAWMONDATA] = BtlController_HandleSetRawMonData, + [CONTROLLER_LOADMONSPRITE] = LinkPartnerHandleLoadMonSprite, + [CONTROLLER_SWITCHINANIM] = LinkPartnerHandleSwitchInAnim, + [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, + [CONTROLLER_DRAWTRAINERPIC] = LinkPartnerHandleDrawTrainerPic, + [CONTROLLER_TRAINERSLIDE] = BtlController_Empty, + [CONTROLLER_TRAINERSLIDEBACK] = LinkPartnerHandleTrainerSlideBack, + [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, + [CONTROLLER_PALETTEFADE] = BtlController_Empty, + [CONTROLLER_SUCCESSBALLTHROWANIM] = BtlController_Empty, + [CONTROLLER_BALLTHROWANIM] = BtlController_Empty, + [CONTROLLER_PAUSE] = BtlController_Empty, + [CONTROLLER_MOVEANIMATION] = LinkPartnerHandleMoveAnimation, + [CONTROLLER_PRINTSTRING] = LinkPartnerHandlePrintString, + [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, + [CONTROLLER_CHOOSEACTION] = BtlController_Empty, + [CONTROLLER_YESNOBOX] = BtlController_Empty, + [CONTROLLER_CHOOSEMOVE] = BtlController_Empty, + [CONTROLLER_OPENBAG] = BtlController_Empty, + [CONTROLLER_CHOOSEPOKEMON] = BtlController_Empty, + [CONTROLLER_23] = BtlController_Empty, + [CONTROLLER_HEALTHBARUPDATE] = LinkPartnerHandleHealthBarUpdate, + [CONTROLLER_EXPUPDATE] = BtlController_Empty, + [CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate, + [CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation, + [CONTROLLER_STATUSXOR] = BtlController_Empty, + [CONTROLLER_DATATRANSFER] = BtlController_Empty, + [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, + [CONTROLLER_PLAYBGM] = BtlController_Empty, + [CONTROLLER_32] = BtlController_Empty, + [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, + [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, + [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, + [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, + [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, + [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, + [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, + [CONTROLLER_CANTSWITCH] = BtlController_Empty, + [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, + [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, + [CONTROLLER_FAINTINGCRY] = BtlController_HandleFaintingCry, + [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, + [CONTROLLER_INTROTRAINERBALLTHROW] = LinkPartnerHandleIntroTrainerBallThrow, + [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = LinkPartnerHandleDrawPartyStatusSummary, + [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_HandleHidePartyStatusSummary, + [CONTROLLER_ENDBOUNCE] = BtlController_Empty, + [CONTROLLER_SPRITEINVISIBILITY] = BtlController_HandleSpriteInvisibility, + [CONTROLLER_BATTLEANIMATION] = LinkPartnerHandleBattleAnimation, + [CONTROLLER_LINKSTANDBYMSG] = LinkPartnerHandleLinkStandbyMsg, + [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, + [CONTROLLER_ENDLINKBATTLE] = LinkPartnerHandleEndLinkBattle, [CONTROLLER_DEBUGMENU] = BtlController_Empty, - [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop // done + [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop }; void SetControllerToLinkPartner(u32 battler) @@ -98,7 +116,7 @@ void SetControllerToLinkPartner(u32 battler) static void LinkPartnerBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sLinkPartnerBufferCommands)) sLinkPartnerBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -117,6 +135,7 @@ static void SwitchIn_ShowSubstitute(u32 battler) { if (gSprites[gHealthboxSpriteIds[battler]].callback == SpriteCallbackDummy) { + CopyBattleSpriteInvisibility(battler); if (gBattleSpritesDataPtr->battlerData[battler].behindSubstitute) InitAndLaunchSpecialAnimation(battler, battler, battler, B_ANIM_MON_TO_SUBSTITUTE); @@ -126,7 +145,8 @@ static void SwitchIn_ShowSubstitute(u32 battler) static void SwitchIn_WaitAndEnd(u32 battler) { - if (!gBattleSpritesDataPtr->healthBoxesData[battler].specialAnimActive) + if (!gBattleSpritesDataPtr->healthBoxesData[battler].specialAnimActive + && gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy) { LinkPartnerBufferExecCompleted(battler); } @@ -148,7 +168,7 @@ static void SwitchIn_ShowHealthbox(u32 battler) UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &gPlayerParty[gBattlerPartyIndexes[battler]], HEALTHBOX_ALL); StartHealthboxSlideIn(battler); SetHealthboxSpriteVisible(gHealthboxSpriteIds[battler]); - CopyBattleSpriteInvisibility(battler); + gBattlerControllerFuncs[battler] = SwitchIn_ShowSubstitute; } } @@ -181,7 +201,7 @@ static void LinkPartnerBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } @@ -223,6 +243,16 @@ static void LinkPartnerHandleTrainerSlideBack(u32 battler) BtlController_HandleTrainerSlideBack(battler, 35, FALSE); } +static void LinkPartnerHandleMoveAnimation(u32 battler) +{ + BtlController_HandleMoveAnimation(battler); +} + +static void LinkPartnerHandlePrintString(u32 battler) +{ + BtlController_HandlePrintString(battler); +} + static void LinkPartnerHandleHealthBarUpdate(u32 battler) { BtlController_HandleHealthBarUpdate(battler, FALSE); @@ -246,9 +276,17 @@ static void LinkPartnerHandleBattleAnimation(u32 battler) BtlController_HandleBattleAnimation(battler, FALSE); } +static void LinkPartnerHandleLinkStandbyMsg(u32 battler) +{ + // RecordedBattle_RecordAllBattlerData(&gBattleResources->bufferA[battler][2]); + LinkPartnerBufferExecCompleted(battler); +} + static void LinkPartnerHandleEndLinkBattle(u32 battler) { + // RecordedBattle_RecordAllBattlerData(&gBattleResources->bufferA[battler][4]); gBattleOutcome = gBattleResources->bufferA[battler][1]; + // gSaveBlock2Ptr->frontier.disableRecordBattle = gBattleResources->bufferA[battler][2]; FadeOutMapMusic(5); BeginFastPaletteFade(3); LinkPartnerBufferExecCompleted(battler); From 5a7a4422d50ea9ef2a72bd3e90ef8c38770a41d9 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Mon, 6 Jan 2025 23:37:52 +0100 Subject: [PATCH 05/13] sync player partner controller --- src/battle_controller_player_partner.c | 32 ++++++++++++++++++-------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index de3dd0659..b8b4dc01a 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -36,6 +36,8 @@ static void PlayerPartnerHandleLoadMonSprite(u32 battler); static void PlayerPartnerHandleSwitchInAnim(u32 battler); static void PlayerPartnerHandleDrawTrainerPic(u32 battler); static void PlayerPartnerHandleTrainerSlideBack(u32 battler); +static void PlayerPartnerHandleMoveAnimation(u32 battler); +static void PlayerPartnerHandlePrintString(u32 battler); static void PlayerPartnerHandleChooseAction(u32 battler); static void PlayerPartnerHandleChooseMove(u32 battler); static void PlayerPartnerHandleChoosePokemon(u32 battler); @@ -66,11 +68,11 @@ static void (*const sPlayerPartnerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 bat [CONTROLLER_SUCCESSBALLTHROWANIM] = BtlController_Empty, [CONTROLLER_BALLTHROWANIM] = BtlController_Empty, [CONTROLLER_PAUSE] = BtlController_Empty, - [CONTROLLER_MOVEANIMATION] = BtlController_HandleMoveAnimation, - [CONTROLLER_PRINTSTRING] = BtlController_HandlePrintString, + [CONTROLLER_MOVEANIMATION] = PlayerPartnerHandleMoveAnimation, + [CONTROLLER_PRINTSTRING] = PlayerPartnerHandlePrintString, [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, [CONTROLLER_CHOOSEACTION] = PlayerPartnerHandleChooseAction, - [CONTROLLER_YESNOBOX] = BtlController_Empty, + [CONTROLLER_YESNOBOX] = BtlController_Empty, [CONTROLLER_CHOOSEMOVE] = PlayerPartnerHandleChooseMove, [CONTROLLER_OPENBAG] = BtlController_Empty, [CONTROLLER_CHOOSEPOKEMON] = PlayerPartnerHandleChoosePokemon, @@ -119,7 +121,7 @@ void SetControllerToPlayerPartner(u32 battler) static void PlayerPartnerBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sPlayerPartnerBufferCommands)) sPlayerPartnerBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -272,7 +274,7 @@ static void PlayerPartnerBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } @@ -328,6 +330,16 @@ static void PlayerPartnerHandleTrainerSlideBack(u32 battler) BtlController_HandleTrainerSlideBack(battler, 35, FALSE); } +static void PlayerPartnerHandleMoveAnimation(u32 battler) +{ + BtlController_HandleMoveAnimation(battler); +} + +static void PlayerPartnerHandlePrintString(u32 battler) +{ + BtlController_HandlePrintString(battler); +} + static void PlayerPartnerHandleChooseAction(u32 battler) { AI_TrySwitchOrUseItem(battler); @@ -341,10 +353,11 @@ static void PlayerPartnerHandleChooseMove(u32 battler) chosenMoveId = gBattleStruct->aiMoveOrAction[battler]; gBattlerTarget = gBattleStruct->aiChosenTarget[battler]; + u32 moveTarget = GetBattlerMoveTargetType(battler, moveInfo->moves[chosenMoveId]); - if (gMovesInfo[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED)) + if (moveTarget & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED)) gBattlerTarget = battler; - else if (gMovesInfo[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH) + else if (moveTarget & MOVE_TARGET_BOTH) { gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); if (gAbsentBattlerFlags & (1u << gBattlerTarget)) @@ -365,7 +378,6 @@ static void PlayerPartnerHandleChooseMove(u32 battler) PlayerPartnerBufferExecCompleted(battler); } - static void PlayerPartnerHandleChoosePokemon(u32 battler) { s32 chosenMonId; @@ -419,9 +431,9 @@ static void PlayerPartnerHandleIntroTrainerBallThrow(u32 battler) if (gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) trainerPal = gTrainerBacksprites[gBattlePartners[gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerPic].palette.data; else if (IsAiVsAiBattle()) - trainerPal = gTrainerBacksprites[GetTrainerPicFromId(gPartnerTrainerId)].palette.data; + trainerPal = gTrainerSprites[GetTrainerPicFromId(gPartnerTrainerId)].palette.data; else - trainerPal = gTrainerBacksprites[GetBattleTowerTrainerFrontSpriteId(gPartnerTrainerId)].palette.data; // 2 vs 2 multi battle in Battle Frontier, load front sprite and pal. + trainerPal = gTrainerSprites[GetBattleTowerTrainerFrontSpriteId(gPartnerTrainerId)].palette.data; // 2 vs 2 multi battle in Battle Frontier, load front sprite and pal. BtlController_HandleIntroTrainerBallThrow(battler, 0xD6F9, trainerPal, 24, Controller_PlayerPartnerShowIntroHealthbox, StartAnimLinearTranslation); } From 69faaef6a1e6b21db5813febd2271a59c084fda9 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Mon, 6 Jan 2025 23:39:03 +0100 Subject: [PATCH 06/13] sync recorded opponent --- src/battle_controller_recorded_opponent.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index c3450e63b..5ae5ccfb4 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -74,7 +74,7 @@ static void (*const sRecordedOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 [CONTROLLER_PRINTSTRING] = RecordedOpponentHandlePrintString, [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, [CONTROLLER_CHOOSEACTION] = RecordedOpponentHandleChooseAction, - [CONTROLLER_YESNOBOX] = BtlController_Empty, + [CONTROLLER_YESNOBOX] = BtlController_Empty, [CONTROLLER_CHOOSEMOVE] = RecordedOpponentHandleChooseMove, [CONTROLLER_OPENBAG] = RecordedOpponentHandleChooseItem, [CONTROLLER_CHOOSEPOKEMON] = RecordedOpponentHandleChoosePokemon, @@ -460,9 +460,16 @@ static void RecordedOpponentHandleChooseAction(u32 battler) static void RecordedOpponentHandleChooseMove(u32 battler) { - u8 moveId = RecordedBattle_GetBattlerAction(RECORDED_MOVE_SLOT, battler); - u8 target = RecordedBattle_GetBattlerAction(RECORDED_MOVE_TARGET, battler); - BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, moveId | (target << 8)); + if (gBattleTypeFlags & BATTLE_TYPE_PALACE) + { + // BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, ChooseMoveAndTargetInBattlePalace(battler)); + } + else + { + u8 moveId = RecordedBattle_GetBattlerAction(RECORDED_MOVE_SLOT, battler); + u8 target = RecordedBattle_GetBattlerAction(RECORDED_MOVE_TARGET, battler); + BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, moveId | (target << 8)); + } RecordedOpponentBufferExecCompleted(battler); } From 81fc30df2f4929c5afc0856eed971908876db844 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Mon, 6 Jan 2025 23:40:41 +0100 Subject: [PATCH 07/13] sync recorded player --- src/battle_controller_recorded_player.c | 39 ++++++++++++++++++++----- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index 2852b30c8..bc8554aae 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -72,7 +72,7 @@ static void (*const sRecordedPlayerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 ba [CONTROLLER_PRINTSTRING] = RecordedPlayerHandlePrintString, [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, [CONTROLLER_CHOOSEACTION] = RecordedPlayerHandleChooseAction, - [CONTROLLER_YESNOBOX] = BtlController_Empty, + [CONTROLLER_YESNOBOX] = BtlController_Empty, [CONTROLLER_CHOOSEMOVE] = RecordedPlayerHandleChooseMove, [CONTROLLER_OPENBAG] = RecordedPlayerHandleChooseItem, [CONTROLLER_CHOOSEPOKEMON] = RecordedPlayerHandleChoosePokemon, @@ -121,7 +121,7 @@ void SetControllerToRecordedPlayer(u32 battler) static void RecordedPlayerBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sRecordedPlayerBufferCommands)) sRecordedPlayerBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -351,7 +351,7 @@ static void RecordedPlayerBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } @@ -430,17 +430,40 @@ static void RecordedPlayerHandlePrintString(u32 battler) BtlController_HandlePrintString(battler); } +// static void ChooseActionInBattlePalace(u32 battler) +// { +// if (gBattleCommunication[4] >= gBattlersCount / 2) +// { +// BtlController_EmitTwoReturnValues(battler, BUFFER_B, RecordedBattle_GetBattlerAction(RECORDED_BATTLE_PALACE_ACTION, battler), 0); +// RecordedPlayerBufferExecCompleted(battler); +// } +// } + static void RecordedPlayerHandleChooseAction(u32 battler) { - BtlController_EmitTwoReturnValues(battler, BUFFER_B, RecordedBattle_GetBattlerAction(RECORDED_ACTION_TYPE, battler), 0); - RecordedPlayerBufferExecCompleted(battler); + if (gBattleTypeFlags & BATTLE_TYPE_PALACE) + { + // gBattlerControllerFuncs[battler] = ChooseActionInBattlePalace; + } + else + { + BtlController_EmitTwoReturnValues(battler, BUFFER_B, RecordedBattle_GetBattlerAction(RECORDED_ACTION_TYPE, battler), 0); + RecordedPlayerBufferExecCompleted(battler); + } } static void RecordedPlayerHandleChooseMove(u32 battler) { - u8 moveId = RecordedBattle_GetBattlerAction(RECORDED_MOVE_SLOT, battler); - u8 target = RecordedBattle_GetBattlerAction(RECORDED_MOVE_TARGET, battler); - BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, moveId | (target << 8)); + if (gBattleTypeFlags & BATTLE_TYPE_PALACE) + { + // BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, ChooseMoveAndTargetInBattlePalace(battler)); + } + else + { + u8 moveId = RecordedBattle_GetBattlerAction(RECORDED_MOVE_SLOT, battler); + u8 target = RecordedBattle_GetBattlerAction(RECORDED_MOVE_TARGET, battler); + BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, moveId | (target << 8)); + } RecordedPlayerBufferExecCompleted(battler); } From ea7b00786e7a997ae000976f34b3d05a8024021e Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Mon, 6 Jan 2025 23:46:08 +0100 Subject: [PATCH 08/13] sync safari controller --- src/battle_controller_safari.c | 168 +++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 73 deletions(-) diff --git a/src/battle_controller_safari.c b/src/battle_controller_safari.c index 24488746f..f59b68806 100644 --- a/src/battle_controller_safari.c +++ b/src/battle_controller_safari.c @@ -1,23 +1,35 @@ #include "global.h" -#include "gflib.h" #include "battle.h" #include "battle_anim.h" #include "battle_controllers.h" #include "battle_interface.h" #include "battle_message.h" +#include "bg.h" #include "data.h" #include "item_menu.h" #include "link.h" #include "main.h" +#include "m4a.h" +#include "palette.h" #include "pokeball.h" -#include "util.h" +#include "pokemon.h" +#include "reshow_battle_screen.h" +#include "sound.h" #include "strings.h" -#include "constants/songs.h" +#include "task.h" +#include "text.h" +#include "util.h" +#include "window.h" +#include "line_break.h" #include "constants/battle_anim.h" +#include "constants/songs.h" +#include "constants/trainers.h" +#include "constants/rgb.h" static void SafariHandleDrawTrainerPic(u32 battler); static void SafariHandleSuccessBallThrowAnim(u32 battler); static void SafariHandleBallThrowAnim(u32 battler); +static void SafariHandlePrintString(u32 battler); static void SafariHandlePrintSelectionString(u32 battler); static void SafariHandleChooseAction(u32 battler); static void SafariHandleChooseItem(u32 battler); @@ -33,64 +45,64 @@ static void CompleteWhenChosePokeblock(u32 battler); static void (*const sSafariBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = { - [CONTROLLER_GETMONDATA] = BtlController_Empty, // done - [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, // done - [CONTROLLER_SETMONDATA] = BtlController_Empty, // done - [CONTROLLER_SETRAWMONDATA] = BtlController_Empty, // done - [CONTROLLER_LOADMONSPRITE] = BtlController_Empty, // done - [CONTROLLER_SWITCHINANIM] = BtlController_Empty, // done - [CONTROLLER_RETURNMONTOBALL] = BtlController_Empty, // done - [CONTROLLER_DRAWTRAINERPIC] = SafariHandleDrawTrainerPic, // done - [CONTROLLER_TRAINERSLIDE] = BtlController_Empty, // done - [CONTROLLER_TRAINERSLIDEBACK] = BtlController_Empty, // done - [CONTROLLER_FAINTANIMATION] = BtlController_Empty, // done - [CONTROLLER_PALETTEFADE] = BtlController_Empty, // done - [CONTROLLER_SUCCESSBALLTHROWANIM] = SafariHandleSuccessBallThrowAnim, // done - [CONTROLLER_BALLTHROWANIM] = SafariHandleBallThrowAnim, // done - [CONTROLLER_PAUSE] = BtlController_Empty, // done - [CONTROLLER_MOVEANIMATION] = BtlController_Empty, // done - [CONTROLLER_PRINTSTRING] = BtlController_HandlePrintString, // done - [CONTROLLER_PRINTSTRINGPLAYERONLY] = SafariHandlePrintSelectionString, // done - [CONTROLLER_CHOOSEACTION] = SafariHandleChooseAction, // done - [CONTROLLER_YESNOBOX] = BtlController_Empty, // done - [CONTROLLER_CHOOSEMOVE] = BtlController_Empty, // done - [CONTROLLER_OPENBAG] = SafariHandleChooseItem, // done - [CONTROLLER_CHOOSEPOKEMON] = BtlController_Empty, // done - [CONTROLLER_23] = BtlController_Empty, // done - [CONTROLLER_HEALTHBARUPDATE] = BtlController_Empty, // done - [CONTROLLER_EXPUPDATE] = BtlController_Empty, // done - [CONTROLLER_STATUSICONUPDATE] = SafariHandleStatusIconUpdate, // done - [CONTROLLER_STATUSANIMATION] = BtlController_Empty, // done - [CONTROLLER_STATUSXOR] = BtlController_Empty, // done - [CONTROLLER_DATATRANSFER] = BtlController_Empty, // done - [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, // done - [CONTROLLER_PLAYBGM] = BtlController_Empty, // done - [CONTROLLER_32] = BtlController_Empty, // done - [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, // done - [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, // done - [CONTROLLER_CLEARUNKVAR] = BtlController_Empty, // done - [CONTROLLER_SETUNKVAR] = BtlController_Empty, // done - [CONTROLLER_CLEARUNKFLAG] = BtlController_Empty, // done - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_Empty, // done - [CONTROLLER_HITANIMATION] = BtlController_Empty, // done - [CONTROLLER_CANTSWITCH] = BtlController_Empty, // done - [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, // done - [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, // done - [CONTROLLER_FAINTINGCRY] = SafariHandleFaintingCry, // done - [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, // done - [CONTROLLER_INTROTRAINERBALLTHROW] = SafariHandleIntroTrainerBallThrow, // done - [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = BtlController_Empty, // done - [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_Empty, // done - [CONTROLLER_ENDBOUNCE] = BtlController_Empty, // done - [CONTROLLER_SPRITEINVISIBILITY] = BtlController_Empty, // done - [CONTROLLER_BATTLEANIMATION] = SafariHandleBattleAnimation, // done - [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, // done - [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done - [CONTROLLER_ENDLINKBATTLE] = SafariHandleEndLinkBattle, // done + [CONTROLLER_GETMONDATA] = BtlController_Empty, + [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, + [CONTROLLER_SETMONDATA] = BtlController_Empty, + [CONTROLLER_SETRAWMONDATA] = BtlController_Empty, + [CONTROLLER_LOADMONSPRITE] = BtlController_Empty, + [CONTROLLER_SWITCHINANIM] = BtlController_Empty, + [CONTROLLER_RETURNMONTOBALL] = BtlController_Empty, + [CONTROLLER_DRAWTRAINERPIC] = SafariHandleDrawTrainerPic, + [CONTROLLER_TRAINERSLIDE] = BtlController_Empty, + [CONTROLLER_TRAINERSLIDEBACK] = BtlController_Empty, + [CONTROLLER_FAINTANIMATION] = BtlController_Empty, + [CONTROLLER_PALETTEFADE] = BtlController_Empty, + [CONTROLLER_SUCCESSBALLTHROWANIM] = SafariHandleSuccessBallThrowAnim, + [CONTROLLER_BALLTHROWANIM] = SafariHandleBallThrowAnim, + [CONTROLLER_PAUSE] = BtlController_Empty, + [CONTROLLER_MOVEANIMATION] = BtlController_Empty, + [CONTROLLER_PRINTSTRING] = SafariHandlePrintString, + [CONTROLLER_PRINTSTRINGPLAYERONLY] = SafariHandlePrintSelectionString, + [CONTROLLER_CHOOSEACTION] = SafariHandleChooseAction, + [CONTROLLER_YESNOBOX] = BtlController_Empty, + [CONTROLLER_CHOOSEMOVE] = BtlController_Empty, + [CONTROLLER_OPENBAG] = SafariHandleChooseItem, + [CONTROLLER_CHOOSEPOKEMON] = BtlController_Empty, + [CONTROLLER_23] = BtlController_Empty, + [CONTROLLER_HEALTHBARUPDATE] = BtlController_Empty, + [CONTROLLER_EXPUPDATE] = BtlController_Empty, + [CONTROLLER_STATUSICONUPDATE] = SafariHandleStatusIconUpdate, + [CONTROLLER_STATUSANIMATION] = BtlController_Empty, + [CONTROLLER_STATUSXOR] = BtlController_Empty, + [CONTROLLER_DATATRANSFER] = BtlController_Empty, + [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, + [CONTROLLER_PLAYBGM] = BtlController_Empty, + [CONTROLLER_32] = BtlController_Empty, + [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, + [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, + [CONTROLLER_CLEARUNKVAR] = BtlController_Empty, + [CONTROLLER_SETUNKVAR] = BtlController_Empty, + [CONTROLLER_CLEARUNKFLAG] = BtlController_Empty, + [CONTROLLER_TOGGLEUNKFLAG] = BtlController_Empty, + [CONTROLLER_HITANIMATION] = BtlController_Empty, + [CONTROLLER_CANTSWITCH] = BtlController_Empty, + [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, + [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, + [CONTROLLER_FAINTINGCRY] = SafariHandleFaintingCry, + [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, + [CONTROLLER_INTROTRAINERBALLTHROW] = SafariHandleIntroTrainerBallThrow, + [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = BtlController_Empty, + [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_Empty, + [CONTROLLER_ENDBOUNCE] = BtlController_Empty, + [CONTROLLER_SPRITEINVISIBILITY] = BtlController_Empty, + [CONTROLLER_BATTLEANIMATION] = SafariHandleBattleAnimation, + [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, + [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, + [CONTROLLER_ENDLINKBATTLE] = SafariHandleEndLinkBattle, [CONTROLLER_DEBUGMENU] = BtlController_Empty, - [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop, // done + [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop }; void SetControllerToSafari(u32 battler) @@ -101,9 +113,9 @@ void SetControllerToSafari(u32 battler) static void SafariBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { - if (gBattleResources->bufferA[battler][0] < NELEMS(sSafariBufferCommands)) + if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sSafariBufferCommands)) sSafariBufferCommands[gBattleResources->bufferA[battler][0]](battler); else SafariBufferExecCompleted(battler); @@ -119,16 +131,16 @@ static void HandleInputChooseAction(u32 battler) switch (gActionSelectionCursor[battler]) { case 0: - BtlController_EmitTwoReturnValues(battler, 1, B_ACTION_SAFARI_BALL, 0); + BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_SAFARI_BALL, 0); break; case 1: - BtlController_EmitTwoReturnValues(battler, 1, B_ACTION_SAFARI_BAIT, 0); + BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_SAFARI_BAIT, 0); break; case 2: - BtlController_EmitTwoReturnValues(battler, 1, B_ACTION_SAFARI_GO_NEAR, 0); + BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_SAFARI_GO_NEAR, 0); break; case 3: - BtlController_EmitTwoReturnValues(battler, 1, B_ACTION_SAFARI_RUN, 0); + BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_SAFARI_RUN, 0); break; } SafariBufferExecCompleted(battler); @@ -188,7 +200,7 @@ static void Controller_WaitForHealthbox(u32 battler) SafariBufferExecCompleted(battler); } -static void Safari_SetBattleEndCallbacks(u32 battler) +static void SafariSetBattleEndCallbacks(u32 battler) { if (!gPaletteFade.active) { @@ -201,14 +213,16 @@ static void Safari_SetBattleEndCallbacks(u32 battler) static void SafariOpenPokeblockCase(u32 battler) { if (!gPaletteFade.active) + { gBattlerControllerFuncs[battler] = CompleteWhenChosePokeblock; + } } static void CompleteWhenChosePokeblock(u32 battler) { if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) { - BtlController_EmitOneReturnValue(battler, 1, gSpecialVar_ItemId); + BtlController_EmitOneReturnValue(battler, BUFFER_B, gSpecialVar_ItemId); SafariBufferExecCompleted(battler); } } @@ -225,7 +239,7 @@ static void SafariBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } @@ -248,10 +262,15 @@ static void SafariHandleBallThrowAnim(u32 battler) BtlController_HandleBallThrowAnim(battler, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), B_ANIM_BALL_THROW_WITH_TRAINER, FALSE); } +static void SafariHandlePrintString(u32 battler) +{ + BtlController_HandlePrintString(battler); +} + static void SafariHandlePrintSelectionString(u32 battler) { if (GetBattlerSide(battler) == B_SIDE_PLAYER) - BtlController_HandlePrintString(battler); + SafariHandlePrintString(battler); else SafariBufferExecCompleted(battler); } @@ -261,7 +280,7 @@ static void HandleChooseActionAfterDma3(u32 battler) if (!IsDma3ManagerBusyWithBgCopy()) { gBattle_BG0_X = 0; - gBattle_BG0_Y = 160; + gBattle_BG0_Y = DISPLAY_HEIGHT; gBattlerControllerFuncs[battler] = HandleInputChooseAction; } } @@ -273,10 +292,13 @@ static void SafariHandleChooseAction(u32 battler) gBattlerControllerFuncs[battler] = HandleChooseActionAfterDma3; BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG); BattlePutTextOnWindow(gText_SafariZoneMenu, B_WIN_ACTION_MENU); - for (i = 0; i < 4; ++i) + + for (i = 0; i < 4; i++) ActionSelectionDestroyCursorAt(i); + ActionSelectionCreateCursorAt(gActionSelectionCursor[battler], 0); BattleStringExpandPlaceholdersToDisplayedString(gText_WhatWillPlayerThrow); + BreakStringAutomatic(gDisplayedStringBattle, WindowWidthPx(B_WIN_ACTION_PROMPT), 2, FONT_NORMAL); BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_ACTION_PROMPT); } @@ -321,5 +343,5 @@ static void SafariHandleEndLinkBattle(u32 battler) BeginFastPaletteFade(3); SafariBufferExecCompleted(battler); if ((gBattleTypeFlags & BATTLE_TYPE_LINK) && !(gBattleTypeFlags & BATTLE_TYPE_IS_MASTER)) - gBattlerControllerFuncs[battler] = Safari_SetBattleEndCallbacks; + gBattlerControllerFuncs[battler] = SafariSetBattleEndCallbacks; } From c393f5dc07ce40ce347f3f64cd1c6ab330fe0f4b Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Tue, 7 Jan 2025 21:52:43 +0100 Subject: [PATCH 09/13] sync battle_controllers.c --- include/battle_gfx_sfx_util.h | 1 + include/battle_message.h | 2 +- src/battle_controller_oak_old_man.c | 2 +- src/battle_controllers.c | 306 ++++++++++++++++++++++++---- src/battle_gfx_sfx_util.c | 12 ++ src/battle_message.c | 2 +- 6 files changed, 279 insertions(+), 46 deletions(-) diff --git a/include/battle_gfx_sfx_util.h b/include/battle_gfx_sfx_util.h index e11499198..1fbdd6141 100644 --- a/include/battle_gfx_sfx_util.h +++ b/include/battle_gfx_sfx_util.h @@ -5,6 +5,7 @@ void AllocateBattleSpritesData(void); void FreeBattleSpritesData(void); void SpriteCB_WaitForBattlerBallReleaseAnim(struct Sprite *sprite); void SpriteCB_TrainerSlideIn(struct Sprite *sprite); +void SpriteCB_TrainerSpawn(struct Sprite *sprite); void InitAndLaunchChosenStatusAnimation(u32 battler, bool8 isStatus2, u32 status); bool8 TryHandleLaunchBattleTableAnimation(u8 activeBattler, u8 atkBattler, u8 defBattler, u8 tableId, u16 argument); void InitAndLaunchSpecialAnimation(u8 activeBattler, u8 atkBattler, u8 defBattler, u8 tableId); diff --git a/include/battle_message.h b/include/battle_message.h index fe930a737..ec571629a 100644 --- a/include/battle_message.h +++ b/include/battle_message.h @@ -256,7 +256,7 @@ enum TRAINER_SLIDE_DYNAMAX, }; -void BufferStringBattle(u32 battler, u16 stringID); +void BufferStringBattle(u16 stringID, u32 battler); u32 BattleStringExpandPlaceholdersToDisplayedString(const u8 *src); u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize); void BattleHandleAddTextPrinter(const u8 *text, u8 arg1); diff --git a/src/battle_controller_oak_old_man.c b/src/battle_controller_oak_old_man.c index af66b3a6b..71989a1d9 100644 --- a/src/battle_controller_oak_old_man.c +++ b/src/battle_controller_oak_old_man.c @@ -699,7 +699,7 @@ static void OakOldManHandlePrintString(u32 battler) } else { - BufferStringBattle(battler, *stringId); + BufferStringBattle(*stringId, battler); if (BattleStringShouldBeColored(*stringId)) BattlePutTextOnWindow(gDisplayedStringBattle, (B_WIN_MSG | B_TEXT_FLAG_NPC_CONTEXT_FONT)); else diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 581cc95f7..503ea3cec 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -4,6 +4,7 @@ #include "battle_ai_util.h" #include "battle_anim.h" #include "battle_controllers.h" +#include "battle_gfx_sfx_util.h" #include "battle_interface.h" #include "battle_message.h" #include "battle_setup.h" @@ -13,14 +14,13 @@ #include "link_rfu.h" #include "palette.h" #include "party_menu.h" -#include "pokeball.h" #include "recorded_battle.h" -#include "sound.h" #include "string_util.h" +#include "sound.h" #include "task.h" #include "test_runner.h" -#include "text.h" #include "util.h" +#include "text.h" #include "constants/abilities.h" #include "constants/battle_string_ids.h" #include "constants/songs.h" @@ -28,12 +28,11 @@ static EWRAM_DATA u8 sLinkSendTaskId = 0; static EWRAM_DATA u8 sLinkReceiveTaskId = 0; -static EWRAM_DATA u8 sUnused = 0; // Debug? Never read EWRAM_DATA struct UnusedControllerStruct gUnusedControllerStruct = {}; // Debug? Unused code that writes to it, never read -void (*gBattlerControllerFuncs[MAX_BATTLERS_COUNT])(u32 battler); -u8 gBattleControllerData[MAX_BATTLERS_COUNT]; -void (*gBattlerControllerEndFuncs[MAX_BATTLERS_COUNT])(u32 battler); // Controller's buffer complete function for each battler +COMMON_DATA void (*gBattlerControllerFuncs[MAX_BATTLERS_COUNT])(u32 battler) = {0}; +COMMON_DATA u8 gBattleControllerData[MAX_BATTLERS_COUNT] = {0}; // Used by the battle controllers to store misc sprite/task IDs for each battler +COMMON_DATA void (*gBattlerControllerEndFuncs[MAX_BATTLERS_COUNT])(u32 battler) = {0}; // Controller's buffer complete function for each battler static void CreateTasksForSendRecvLinkBuffers(void); static void InitLinkBtlControllers(void); @@ -103,6 +102,12 @@ void InitBattleControllers(void) for (i = 0; i < gBattlersCount; i++) BufferBattlePartyCurrentOrderBySide(i, 0); } + + // for (i = 0; i < sizeof(gBattleStruct->tvMovePoints); i++) + // *((u8 *)(&gBattleStruct->tvMovePoints) + i) = 0; + + // for (i = 0; i < sizeof(gBattleStruct->tv); i++) + // *((u8 *)(&gBattleStruct->tv) + i) = 0; } static void InitSinglePlayerBtlControllers(void) @@ -180,7 +185,7 @@ static void InitSinglePlayerBtlControllers(void) gBattlerPartyIndexes[3] = 3; } } - else if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + else if (!IsDoubleBattle()) { gBattleMainFunc = BeginBattleIntro; @@ -422,7 +427,7 @@ static void InitLinkBtlControllers(void) s32 i; u8 multiplayerId; - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!IsDoubleBattle()) { if (gBattleTypeFlags & BATTLE_TYPE_IS_MASTER) { @@ -447,7 +452,7 @@ static void InitLinkBtlControllers(void) gBattlersCount = 2; } } - else if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + else if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && IsDoubleBattle()) { if (gBattleTypeFlags & BATTLE_TYPE_IS_MASTER) { @@ -484,6 +489,52 @@ static void InitLinkBtlControllers(void) gBattlersCount = MAX_BATTLERS_COUNT; } } + else if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + { + if (gBattleTypeFlags & BATTLE_TYPE_IS_MASTER) + { + gBattleMainFunc = BeginBattleIntro; + + gBattlerControllerFuncs[0] = SetControllerToPlayer; + gBattlerPositions[0] = B_POSITION_PLAYER_LEFT; + + gBattlerControllerFuncs[1] = SetControllerToOpponent; + gBattlerPositions[1] = B_POSITION_OPPONENT_LEFT; + + gBattlerControllerFuncs[2] = SetControllerToLinkPartner; + gBattlerPositions[2] = B_POSITION_PLAYER_RIGHT; + + gBattlerControllerFuncs[3] = SetControllerToOpponent; + gBattlerPositions[3] = B_POSITION_OPPONENT_RIGHT; + + gBattlersCount = MAX_BATTLERS_COUNT; + } + else + { + gBattlerControllerFuncs[0] = SetControllerToLinkPartner; + gBattlerPositions[0] = B_POSITION_PLAYER_LEFT; + + gBattlerControllerFuncs[1] = SetControllerToLinkOpponent; + gBattlerPositions[1] = B_POSITION_OPPONENT_LEFT; + + gBattlerControllerFuncs[2] = SetControllerToPlayer; + gBattlerPositions[2] = B_POSITION_PLAYER_RIGHT; + + gBattlerControllerFuncs[3] = SetControllerToLinkOpponent; + gBattlerPositions[3] = B_POSITION_OPPONENT_RIGHT; + + gBattlersCount = MAX_BATTLERS_COUNT; + } + + BufferBattlePartyCurrentOrderBySide(0, 0); + BufferBattlePartyCurrentOrderBySide(1, 0); + BufferBattlePartyCurrentOrderBySide(2, 1); + BufferBattlePartyCurrentOrderBySide(3, 1); + gBattlerPartyIndexes[0] = 0; + gBattlerPartyIndexes[1] = 0; + gBattlerPartyIndexes[2] = 3; + gBattlerPartyIndexes[3] = 3; + } else { multiplayerId = GetMultiplayerId(); @@ -513,7 +564,7 @@ static void InitLinkBtlControllers(void) case 0: case 3: gBattlerPositions[gLinkPlayers[i].id] = B_POSITION_PLAYER_LEFT; - gBattlerPartyIndexes[gLinkPlayers[i].id] = B_POSITION_PLAYER_LEFT; + gBattlerPartyIndexes[gLinkPlayers[i].id] = 0; break; case 1: case 2: @@ -533,12 +584,12 @@ static void InitLinkBtlControllers(void) case 0: case 3: gBattlerPositions[gLinkPlayers[i].id] = B_POSITION_PLAYER_LEFT; - gBattlerPartyIndexes[gLinkPlayers[i].id] = B_POSITION_PLAYER_LEFT; + gBattlerPartyIndexes[gLinkPlayers[i].id] = 0; break; case 1: case 2: gBattlerPositions[gLinkPlayers[i].id] = B_POSITION_PLAYER_RIGHT; - gBattlerPartyIndexes[gLinkPlayers[i].id] = B_POSITION_OPPONENT_RIGHT; + gBattlerPartyIndexes[gLinkPlayers[i].id] = 3; break; } } @@ -550,12 +601,12 @@ static void InitLinkBtlControllers(void) case 0: case 3: gBattlerPositions[gLinkPlayers[i].id] = B_POSITION_OPPONENT_LEFT; - gBattlerPartyIndexes[gLinkPlayers[i].id] = B_POSITION_PLAYER_LEFT; + gBattlerPartyIndexes[gLinkPlayers[i].id] = 0; break; case 1: case 2: gBattlerPositions[gLinkPlayers[i].id] = B_POSITION_OPPONENT_RIGHT; - gBattlerPartyIndexes[gLinkPlayers[i].id] = B_POSITION_OPPONENT_RIGHT; + gBattlerPartyIndexes[gLinkPlayers[i].id] = 3; break; } } @@ -569,9 +620,10 @@ static void InitLinkBtlControllers(void) bool32 IsValidForBattle(struct Pokemon *mon) { u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG); - return (species != SPECIES_NONE && species != SPECIES_EGG - && GetMonData(mon, MON_DATA_HP) != 0 - && GetMonData(mon, MON_DATA_IS_EGG) == FALSE); + return (species != SPECIES_NONE + && species != SPECIES_EGG + && GetMonData(mon, MON_DATA_HP) != 0 + && GetMonData(mon, MON_DATA_IS_EGG) == FALSE); } static void SetBattlePartyIds(void) @@ -674,8 +726,6 @@ static void CreateTasksForSendRecvLinkBuffers(void) gTasks[sLinkReceiveTaskId].data[13] = 0; gTasks[sLinkReceiveTaskId].data[14] = 0; gTasks[sLinkReceiveTaskId].data[15] = 0; - - sUnused = 0; } enum @@ -804,7 +854,7 @@ void TryReceiveLinkBattleData(void) DestroyTask_RfuIdle(); for (i = 0; i < GetLinkPlayerCount(); i++) { - if (GetBlockReceivedStatus() & gBitTable[i]) + if (GetBlockReceivedStatus() & (1 << (i))) { ResetBlockReceivedFlag(i); recvBuffer = (u8 *)gBlockRecvBuffer[i]; @@ -834,7 +884,7 @@ void TryReceiveLinkBattleData(void) static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) { u16 blockSize; - u8 battlerId; + u8 battler; u8 var; if (gTasks[taskId].data[15] != gTasks[taskId].data[14]) @@ -845,17 +895,17 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) gTasks[taskId].data[12] = 0; gTasks[taskId].data[15] = 0; } - battlerId = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_ACTIVE_BATTLER]; + battler = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_ACTIVE_BATTLER]; blockSize = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_LO] | (gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_HI] << 8); switch (gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 0]) { case 0: - if (gBattleControllerExecFlags & gBitTable[battlerId]) + if (gBattleControllerExecFlags & (1u << battler)) return; - memcpy(gBattleResources->bufferA[battlerId], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_DATA], blockSize); - MarkBattlerReceivedLinkData(battlerId); + memcpy(gBattleResources->bufferA[battler], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_DATA], blockSize); + MarkBattlerReceivedLinkData(battler); if (!(gBattleTypeFlags & BATTLE_TYPE_IS_MASTER)) { @@ -866,11 +916,11 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) } break; case 1: - memcpy(gBattleResources->bufferB[battlerId], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_DATA], blockSize); + memcpy(gBattleResources->bufferB[battler], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_DATA], blockSize); break; case 2: var = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_DATA]; - gBattleControllerExecFlags &= ~(gBitTable[battlerId] << (var * 4)); + gBattleControllerExecFlags &= ~(1u << (battler + var * 4)); break; } @@ -887,6 +937,15 @@ void BtlController_EmitGetMonData(u32 battler, u32 bufferId, u8 requestId, u8 mo PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); } +static void UNUSED BtlController_EmitGetRawMonData(u32 battler, u32 bufferId, u8 monId, u8 bytes) +{ + gBattleResources->transferBuffer[0] = CONTROLLER_GETRAWMONDATA; + gBattleResources->transferBuffer[1] = monId; + gBattleResources->transferBuffer[2] = bytes; + gBattleResources->transferBuffer[3] = 0; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); +} + void BtlController_EmitSetMonData(u32 battler, u32 bufferId, u8 requestId, u8 monToCheck, u8 bytes, void *data) { s32 i; @@ -899,6 +958,18 @@ void BtlController_EmitSetMonData(u32 battler, u32 bufferId, u8 requestId, u8 mo PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 3 + bytes); } +static void UNUSED BtlController_EmitSetRawMonData(u32 battler, u32 bufferId, u8 monId, u8 bytes, void *data) +{ + s32 i; + + gBattleResources->transferBuffer[0] = CONTROLLER_SETRAWMONDATA; + gBattleResources->transferBuffer[1] = monId; + gBattleResources->transferBuffer[2] = bytes; + for (i = 0; i < bytes; i++) + gBattleResources->transferBuffer[3 + i] = *(u8 *)(data++); + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, bytes + 3); +} + void BtlController_EmitLoadMonSprite(u32 battler, u32 bufferId) { gBattleResources->transferBuffer[0] = CONTROLLER_LOADMONSPRITE; @@ -960,6 +1031,24 @@ void BtlController_EmitFaintAnimation(u32 battler, u32 bufferId) PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); } +static void UNUSED BtlController_EmitPaletteFade(u32 battler, u32 bufferId) +{ + gBattleResources->transferBuffer[0] = CONTROLLER_PALETTEFADE; + gBattleResources->transferBuffer[1] = CONTROLLER_PALETTEFADE; + gBattleResources->transferBuffer[2] = CONTROLLER_PALETTEFADE; + gBattleResources->transferBuffer[3] = CONTROLLER_PALETTEFADE; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); +} + +static void UNUSED BtlController_EmitSuccessBallThrowAnim(u32 battler, u32 bufferId) +{ + gBattleResources->transferBuffer[0] = CONTROLLER_SUCCESSBALLTHROWANIM; + gBattleResources->transferBuffer[1] = CONTROLLER_SUCCESSBALLTHROWANIM; + gBattleResources->transferBuffer[2] = CONTROLLER_SUCCESSBALLTHROWANIM; + gBattleResources->transferBuffer[3] = CONTROLLER_SUCCESSBALLTHROWANIM; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); +} + void BtlController_EmitBallThrowAnim(u32 battler, u32 bufferId, u8 caseId) { gBattleResources->transferBuffer[0] = CONTROLLER_BALLTHROWANIM; @@ -967,6 +1056,17 @@ void BtlController_EmitBallThrowAnim(u32 battler, u32 bufferId, u8 caseId) PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 2); } +static void UNUSED BtlController_EmitPause(u32 battler, u32 bufferId, u8 toWait, void *data) +{ + s32 i; + + gBattleResources->transferBuffer[0] = CONTROLLER_PAUSE; + gBattleResources->transferBuffer[1] = toWait; + for (i = 0; i < toWait * 3; i++) + gBattleResources->transferBuffer[2 + i] = *(u8 *)(data++); + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, toWait * 3 + 2); +} + void BtlController_EmitMoveAnimation(u32 battler, u32 bufferId, u16 move, u8 turnOfMove, u16 movePower, s32 dmg, u8 friendship, struct DisableStruct *disableStructPtr, u8 multihit) { gBattleResources->transferBuffer[0] = CONTROLLER_MOVEANIMATION; @@ -980,7 +1080,7 @@ void BtlController_EmitMoveAnimation(u32 battler, u32 bufferId, u16 move, u8 tur gBattleResources->transferBuffer[8] = (dmg & 0x00FF0000) >> 16; gBattleResources->transferBuffer[9] = (dmg & 0xFF000000) >> 24; gBattleResources->transferBuffer[10] = friendship; - gBattleResources->transferBuffer[11] = multihit; // multihit in pokeem + gBattleResources->transferBuffer[11] = multihit; if (WEATHER_HAS_EFFECT) { gBattleResources->transferBuffer[12] = gBattleWeather; @@ -1016,7 +1116,7 @@ void BtlController_EmitPrintString(u32 battler, u32 bufferId, u16 stringID) stringInfo->bakScriptPartyIdx = gBattleStruct->scriptPartyIdx; stringInfo->hpScale = gBattleStruct->hpScale; stringInfo->itemEffectBattler = gPotentialItemEffectBattler; - stringInfo->moveType = gMovesInfo[gCurrentMove].type; + stringInfo->moveType = GetMoveType(gCurrentMove); for (i = 0; i < MAX_BATTLERS_COUNT; i++) stringInfo->abilities[i] = gBattleMons[i].ability; @@ -1068,6 +1168,17 @@ void BtlController_EmitChooseAction(u32 battler, u32 bufferId, u8 action, u16 it PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); } +// Only used by the forfeit prompt in the Battle Frontier +// For other Yes/No boxes in battle, see Cmd_yesnobox +void BtlController_EmitYesNoBox(u32 battler, u32 bufferId) +{ + gBattleResources->transferBuffer[0] = CONTROLLER_YESNOBOX; + gBattleResources->transferBuffer[1] = CONTROLLER_YESNOBOX; + gBattleResources->transferBuffer[2] = CONTROLLER_YESNOBOX; + gBattleResources->transferBuffer[3] = CONTROLLER_YESNOBOX; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); +} + void BtlController_EmitChooseMove(u32 battler, u32 bufferId, bool8 isDoubleBattle, bool8 NoPpNumber, struct ChooseMoveStruct *movePpData) { s32 i; @@ -1102,9 +1213,19 @@ void BtlController_EmitChoosePokemon(u32 battler, u32 bufferId, u8 caseId, u8 sl gBattleResources->transferBuffer[7] = (abilityId >> 8) & 0xFF; for (i = 0; i < 3; i++) gBattleResources->transferBuffer[4 + i] = data[i]; - PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 8); + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 8); // Only 7 bytes were written. } +static void UNUSED BtlController_EmitCmd23(u32 battler, u32 bufferId) +{ + gBattleResources->transferBuffer[0] = CONTROLLER_23; + gBattleResources->transferBuffer[1] = CONTROLLER_23; + gBattleResources->transferBuffer[2] = CONTROLLER_23; + gBattleResources->transferBuffer[3] = CONTROLLER_23; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); +} + +// why is the argument u16 if it's being cast to s16 anyway? void BtlController_EmitHealthBarUpdate(u32 battler, u32 bufferId, u16 hpValue) { gBattleResources->transferBuffer[0] = CONTROLLER_HEALTHBARUPDATE; @@ -1150,6 +1271,13 @@ void BtlController_EmitStatusAnimation(u32 battler, u32 bufferId, bool8 status2, PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 6); } +static void UNUSED BtlController_EmitStatusXor(u32 battler, u32 bufferId, u8 b) +{ + gBattleResources->transferBuffer[0] = CONTROLLER_STATUSXOR; + gBattleResources->transferBuffer[1] = b; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 2); +} + void BtlController_EmitDataTransfer(u32 battler, u32 bufferId, u16 size, void *data) { s32 i; @@ -1163,14 +1291,59 @@ void BtlController_EmitDataTransfer(u32 battler, u32 bufferId, u16 size, void *d PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, size + 4); } +static void UNUSED BtlController_EmitDMA3Transfer(u32 battler, u32 bufferId, void *dst, u16 size, void *data) +{ + s32 i; + + gBattleResources->transferBuffer[0] = CONTROLLER_DMA3TRANSFER; + gBattleResources->transferBuffer[1] = (u32)(dst); + gBattleResources->transferBuffer[2] = ((u32)(dst) & 0x0000FF00) >> 8; + gBattleResources->transferBuffer[3] = ((u32)(dst) & 0x00FF0000) >> 16; + gBattleResources->transferBuffer[4] = ((u32)(dst) & 0xFF000000) >> 24; + gBattleResources->transferBuffer[5] = size; + gBattleResources->transferBuffer[6] = (size & 0xFF00) >> 8; + for (i = 0; i < size; i++) + gBattleResources->transferBuffer[7 + i] = *(u8 *)(data++); + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, size + 7); +} + +static void UNUSED BtlController_EmitPlayBGM(u32 battler, u32 bufferId, u16 songId, void *data) +{ + s32 i; + + gBattleResources->transferBuffer[0] = CONTROLLER_PLAYBGM; + gBattleResources->transferBuffer[1] = songId; + gBattleResources->transferBuffer[2] = (songId & 0xFF00) >> 8; + + // Nonsense loop using songId as a size + // Would go out of bounds for any song id after SE_RG_BAG_POCKET (253) + for (i = 0; i < songId; i++) + gBattleResources->transferBuffer[3 + i] = *(u8 *)(data++); + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, songId + 3); +} + +static void UNUSED BtlController_EmitCmd32(u32 battler, u32 bufferId, u16 size, void *data) +{ + s32 i; + + gBattleResources->transferBuffer[0] = CONTROLLER_32; + gBattleResources->transferBuffer[1] = size; + gBattleResources->transferBuffer[2] = (size & 0xFF00) >> 8; + for (i = 0; i < size; i++) + gBattleResources->transferBuffer[3 + i] = *(u8 *)(data++); + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, size + 3); +} + + +//TODO: compare values to pokeemerald? void BtlController_EmitTwoReturnValues(u32 battler, u32 bufferId, u8 ret8, u32 ret32) { gBattleResources->transferBuffer[0] = CONTROLLER_TWORETURNVALUES; gBattleResources->transferBuffer[1] = ret8; gBattleResources->transferBuffer[2] = ret32; gBattleResources->transferBuffer[3] = (ret32 & 0x0000FF00) >> 8; - gBattleResources->transferBuffer[4] = (ret32 & 0x0000FF00) >> 16; - gBattleResources->transferBuffer[5] = (ret32 & 0x0000FF00) >> 24; + gBattleResources->transferBuffer[4] = (ret32 & 0x00FF0000) >> 16; + gBattleResources->transferBuffer[5] = (ret32 & 0xFF000000) >> 24; PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 6); } @@ -1203,6 +1376,40 @@ void BtlController_EmitOneReturnValue_Duplicate(u32 battler, u32 bufferId, u16 r PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); } +static void UNUSED BtlController_EmitClearUnkVar(u32 battler, u32 bufferId) +{ + gBattleResources->transferBuffer[0] = CONTROLLER_CLEARUNKVAR; + gBattleResources->transferBuffer[1] = CONTROLLER_CLEARUNKVAR; + gBattleResources->transferBuffer[2] = CONTROLLER_CLEARUNKVAR; + gBattleResources->transferBuffer[3] = CONTROLLER_CLEARUNKVAR; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); +} + +static void UNUSED BtlController_EmitSetUnkVar(u32 battler, u32 bufferId, u8 b) +{ + gBattleResources->transferBuffer[0] = CONTROLLER_SETUNKVAR; + gBattleResources->transferBuffer[1] = b; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 2); +} + +static void UNUSED BtlController_EmitClearUnkFlag(u32 battler, u32 bufferId) +{ + gBattleResources->transferBuffer[0] = CONTROLLER_CLEARUNKFLAG; + gBattleResources->transferBuffer[1] = CONTROLLER_CLEARUNKFLAG; + gBattleResources->transferBuffer[2] = CONTROLLER_CLEARUNKFLAG; + gBattleResources->transferBuffer[3] = CONTROLLER_CLEARUNKFLAG; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); +} + +static void UNUSED BtlController_EmitToggleUnkFlag(u32 battler, u32 bufferId) +{ + gBattleResources->transferBuffer[0] = CONTROLLER_TOGGLEUNKFLAG; + gBattleResources->transferBuffer[1] = CONTROLLER_TOGGLEUNKFLAG; + gBattleResources->transferBuffer[2] = CONTROLLER_TOGGLEUNKFLAG; + gBattleResources->transferBuffer[3] = CONTROLLER_TOGGLEUNKFLAG; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); +} + void BtlController_EmitHitAnimation(u32 battler, u32 bufferId) { gBattleResources->transferBuffer[0] = CONTROLLER_HITANIMATION; @@ -1339,6 +1546,9 @@ void BtlController_EmitEndLinkBattle(u32 battler, u32 bufferId, u8 battleOutcome { gBattleResources->transferBuffer[0] = CONTROLLER_ENDLINKBATTLE; gBattleResources->transferBuffer[1] = battleOutcome; + // gBattleResources->transferBuffer[2] = gSaveBlock2Ptr->frontier.disableRecordBattle; + // gBattleResources->transferBuffer[3] = gSaveBlock2Ptr->frontier.disableRecordBattle; + // gBattleResources->transferBuffer[5] = gBattleResources->transferBuffer[4] = RecordedBattle_BufferNewBattlerData(&gBattleResources->transferBuffer[6]); PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 2); } @@ -1398,12 +1608,22 @@ static u32 GetBattlerMonData(u32 battler, struct Pokemon *party, u32 monId, u8 * battleMon.abilityNum = GetMonData(&party[monId], MON_DATA_ABILITY_NUM); battleMon.otId = GetMonData(&party[monId], MON_DATA_OT_ID); battleMon.metLevel = GetMonData(&party[monId], MON_DATA_MET_LEVEL); + battleMon.isShiny = GetMonData(&party[monId], MON_DATA_IS_SHINY); GetMonData(&party[monId], MON_DATA_NICKNAME, nickname); StringCopy_Nickname(battleMon.nickname, nickname); GetMonData(&party[monId], MON_DATA_OT_NAME, battleMon.otName); src = (u8 *)&battleMon; for (size = 0; size < sizeof(battleMon); size++) dst[size] = src[size]; + #if TESTING + if (gTestRunnerEnabled) + { + u32 side = GetBattlerSide(battler); + u32 partyIndex = gBattlerPartyIndexes[battler]; + if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) + gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + } + #endif break; case REQUEST_SPECIES_BATTLE: data16 = GetMonData(&party[monId], MON_DATA_SPECIES); @@ -1890,7 +2110,7 @@ static bool8 ShouldDoSlideInAnim(void) if (gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_OLD_MAN_TUTORIAL | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TWO_OPPONENTS | - BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_RECORDED | BATTLE_TYPE_POKEDUDE | BATTLE_TYPE_TRAINER_TOWER) + BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_RECORDED | BATTLE_TYPE_TRAINER_HILL | BATTLE_TYPE_POKEDUDE) ) return FALSE; return TRUE; @@ -2348,7 +2568,10 @@ void BtlController_HandleDrawTrainerPic(u32 battler, u32 trainerPicId, bool32 is gSprites[gBattlerSpriteIds[battler]].x2 = DISPLAY_WIDTH; gSprites[gBattlerSpriteIds[battler]].sSpeedX = -2; } - gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn; + if (B_FAST_INTRO_NO_SLIDE || gTestRunnerHeadless) + gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSpawn; + else + gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn; gBattlerControllerFuncs[battler] = Controller_WaitForTrainerPic; } @@ -2486,7 +2709,7 @@ void BtlController_HandlePrintString(u32 battler) gBattle_BG0_X = 0; gBattle_BG0_Y = 0; stringId = (u16 *)(&gBattleResources->bufferA[battler][2]); - BufferStringBattle(battler, *stringId); + BufferStringBattle(*stringId, battler); if (gTestRunnerEnabled) { @@ -2550,7 +2773,7 @@ void DoStatusIconUpdate(u32 battler) struct Pokemon *party = GetBattlerParty(battler); UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &party[gBattlerPartyIndexes[battler]], HEALTHBOX_STATUS_ICON); - gBattleSpritesDataPtr->healthBoxesData[battler].statusAnimActive = FALSE; + gBattleSpritesDataPtr->healthBoxesData[battler].statusAnimActive = 0; gBattlerControllerFuncs[battler] = Controller_WaitForStatusAnimation; } @@ -2717,7 +2940,7 @@ void BtlController_HandleIntroTrainerBallThrow(u32 battler, u16 tagTrainerPal, c if (side == B_SIDE_PLAYER) { StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[battler]], SpriteCB_FreePlayerSpriteLoadMonSprite); - StartSpriteAnim(&gSprites[gBattlerSpriteIds[battler]], 1); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battler]], ShouldDoSlideInAnim() ? 2 : 1); paletteNum = AllocSpritePalette(tagTrainerPal); LoadCompressedPalette(trainerPal, OBJ_PLTT_ID(paletteNum), PLTT_SIZE_4BPP); @@ -2778,7 +3001,7 @@ static void Task_StartSendOutAnim(u8 taskId) gBattleResources->bufferA[battler][1] = gBattlerPartyIndexes[battler]; StartSendOutAnim(battler, FALSE, ShouldDoSlideInAnim()); - battlerPartner = BATTLE_PARTNER(battler); + battlerPartner = battler ^ BIT_FLANK; gBattleResources->bufferA[battlerPartner][1] = gBattlerPartyIndexes[battlerPartner]; BattleLoadMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[battlerPartner]], battlerPartner); StartSendOutAnim(battlerPartner, FALSE, ShouldDoSlideInAnim()); @@ -2830,7 +3053,7 @@ void BtlController_HandleDrawPartyStatusSummary(u32 battler, u32 side, bool32 co } else { - gBattleSpritesDataPtr->healthBoxesData[battler].partyStatusSummaryShown = TRUE; + gBattleSpritesDataPtr->healthBoxesData[battler].partyStatusSummaryShown = 1; if (side == B_SIDE_OPPONENT && gBattleResources->bufferA[battler][2] != 0) { @@ -2878,6 +3101,3 @@ void BtlController_HandleBattleAnimation(u32 battler, bool32 ignoreSE) gBattlerControllerFuncs[battler] = Controller_WaitForBattleAnimation; } } - - - diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index f783e2863..a7131a727 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -213,6 +213,18 @@ void SpriteCB_TrainerSlideIn(struct Sprite *sprite) } } +void SpriteCB_TrainerSpawn(struct Sprite *sprite) +{ + if (!(gIntroSlideFlags & 1)) + { + sprite->x2 = 0; + if (sprite->y2 != 0) + sprite->callback = SpriteCB_TrainerSlideVertical; + else + sprite->callback = SpriteCallbackDummy; + } +} + // Slide up to 0 if necessary (used by multi battle intro) static void SpriteCB_TrainerSlideVertical(struct Sprite *sprite) { diff --git a/src/battle_message.c b/src/battle_message.c index f7c494e61..0c033b7b6 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2423,7 +2423,7 @@ static const u16 sGrammarMoveUsedTable[] = static const u8 sRecordedBattleTextSpeeds[] = {8, 4, 1, 0}; -void BufferStringBattle(u32 battler, u16 stringId) +void BufferStringBattle(u16 stringId, u32 battler) { s32 i; const u8 *stringPtr = NULL; From d0dbc7036cf60d4a8066e8d7da2bb52d90d9ee1f Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Tue, 7 Jan 2025 22:22:05 +0100 Subject: [PATCH 10/13] update oak/old man/pokedude controllers --- src/battle_controller_oak_old_man.c | 8 ++++---- src/battle_controller_pokedude.c | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/battle_controller_oak_old_man.c b/src/battle_controller_oak_old_man.c index 71989a1d9..00679e290 100644 --- a/src/battle_controller_oak_old_man.c +++ b/src/battle_controller_oak_old_man.c @@ -123,9 +123,9 @@ void SetControllerToOakOrOldMan(u32 battler) static void OakOldManBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { - if (gBattleResources->bufferA[battler][0] < NELEMS(sOakOldManBufferCommands)) + if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sOakOldManBufferCommands)) sOakOldManBufferCommands[gBattleResources->bufferA[battler][0]](battler); else OakOldManBufferExecCompleted(battler); @@ -277,7 +277,7 @@ static void OakOldManSetBattleEndCallbacks(u32 battler) void OakOldManHandleInputChooseMove(u32 battler) { HandleInputChooseMove(battler); - if (!(gBattleControllerExecFlags & gBitTable[battler])) + if (!(gBattleControllerExecFlags & (1u << battler))) OakOldManBufferExecCompleted(battler); } @@ -660,7 +660,7 @@ static void OakOldManBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } diff --git a/src/battle_controller_pokedude.c b/src/battle_controller_pokedude.c index 9eb6ff936..0cdfee846 100644 --- a/src/battle_controller_pokedude.c +++ b/src/battle_controller_pokedude.c @@ -151,9 +151,9 @@ void SetControllerToPokedude(u32 battler) static void PokedudeBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { - if (gBattleResources->bufferA[battler][0] < NELEMS(sPokedudeBufferCommands)) + if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sPokedudeBufferCommands)) { if (!HandlePokedudeVoiceoverEtc(battler)) sPokedudeBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -377,7 +377,7 @@ static void PokedudeBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } @@ -1219,7 +1219,7 @@ static void PokedudeAction_PrintMessageWithHealthboxPals(u32 battler) case 1: if (!gPaletteFade.active) { - u32 mask = (gBitTable[gBattleStruct->pdHealthboxPal2] | gBitTable[gBattleStruct->pdHealthboxPal1]) << 16; + u32 mask = ((1u << gBattleStruct->pdHealthboxPal2) | (1u << gBattleStruct->pdHealthboxPal1)) << 16; ++mask; // It's possible that this is influenced by other functions, as --mask; // this also striked in battle_controller_oak_old_man.c but was naturally fixed. @@ -1245,7 +1245,7 @@ static void PokedudeAction_PrintMessageWithHealthboxPals(u32 battler) u32 mask; PlaySE(SE_SELECT); - mask = (gBitTable[gBattleStruct->pdHealthboxPal2] | gBitTable[gBattleStruct->pdHealthboxPal1]) << 16; + mask = ((1u << gBattleStruct->pdHealthboxPal2) | (1u << gBattleStruct->pdHealthboxPal1)) << 16; ++mask; --mask; BeginNormalPaletteFade(mask, 4, 0, 8, RGB_BLACK); From 9bdc8f6f3a7bec4fa80c3072e8cd567ccbd56bab Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Tue, 7 Jan 2025 22:33:30 +0100 Subject: [PATCH 11/13] formatting --- src/battle_controller_oak_old_man.c | 114 ++++++++++++++-------------- src/battle_controller_pokedude.c | 114 ++++++++++++++-------------- 2 files changed, 114 insertions(+), 114 deletions(-) diff --git a/src/battle_controller_oak_old_man.c b/src/battle_controller_oak_old_man.c index 00679e290..69e438b4c 100644 --- a/src/battle_controller_oak_old_man.c +++ b/src/battle_controller_oak_old_man.c @@ -51,64 +51,64 @@ static void HandleInputChooseAction(u32 battler); static void (*const sOakOldManBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = { - [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, // done - [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, // done - [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, // done - [CONTROLLER_SETRAWMONDATA] = BtlController_Empty, // done - [CONTROLLER_LOADMONSPRITE] = BtlController_Empty, // done - [CONTROLLER_SWITCHINANIM] = BtlController_Empty, // done - [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, // done - [CONTROLLER_DRAWTRAINERPIC] = OakOldManHandleDrawTrainerPic, // done - [CONTROLLER_TRAINERSLIDE] = OakOldManHandleTrainerSlide, // done - [CONTROLLER_TRAINERSLIDEBACK] = BtlController_Empty, // done - [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, // done - [CONTROLLER_PALETTEFADE] = BtlController_Empty, // done - [CONTROLLER_SUCCESSBALLTHROWANIM] = OakOldManHandleSuccessBallThrowAnim, // done - [CONTROLLER_BALLTHROWANIM] = OakOldManHandleBallThrowAnim, // done - [CONTROLLER_PAUSE] = BtlController_Empty, // done - [CONTROLLER_MOVEANIMATION] = BtlController_HandleMoveAnimation, // done - [CONTROLLER_PRINTSTRING] = OakOldManHandlePrintString, // done - [CONTROLLER_PRINTSTRINGPLAYERONLY] = OakOldManHandlePrintSelectionString, // done - [CONTROLLER_CHOOSEACTION] = OakOldManHandleChooseAction, // done - [CONTROLLER_YESNOBOX] = BtlController_Empty, // done - [CONTROLLER_CHOOSEMOVE] = OakOldManHandleChooseMove, // done - [CONTROLLER_OPENBAG] = OakOldManHandleChooseItem, // done - [CONTROLLER_CHOOSEPOKEMON] = OakOldManHandleChoosePokemon, // done - [CONTROLLER_23] = BtlController_Empty, // done - [CONTROLLER_HEALTHBARUPDATE] = OakOldManHandleHealthBarUpdate, // done - [CONTROLLER_EXPUPDATE] = PlayerHandleExpUpdate, // done - [CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate, // done - [CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation, // done - [CONTROLLER_STATUSXOR] = BtlController_Empty, // done - [CONTROLLER_DATATRANSFER] = BtlController_Empty, // done - [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, // done - [CONTROLLER_PLAYBGM] = BtlController_Empty, // done - [CONTROLLER_32] = BtlController_Empty, // done - [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, // done - [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, // done - [CONTROLLER_CLEARUNKVAR] = BtlController_Empty, // done - [CONTROLLER_SETUNKVAR] = BtlController_Empty, // done - [CONTROLLER_CLEARUNKFLAG] = BtlController_Empty, // done - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_Empty, // done - [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, // done - [CONTROLLER_CANTSWITCH] = BtlController_Empty, // done - [CONTROLLER_PLAYSE] = OakOldManHandlePlaySE, // done - [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, // done - [CONTROLLER_FAINTINGCRY] = OakOldManHandleFaintingCry, // done - [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, // done - [CONTROLLER_INTROTRAINERBALLTHROW] = OakOldManHandleIntroTrainerBallThrow, // done - [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = OakOldManHandleDrawPartyStatusSummary, // done - [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_Empty, // done - [CONTROLLER_ENDBOUNCE] = OakOldManHandleEndBounceEffect, // done - [CONTROLLER_SPRITEINVISIBILITY] = BtlController_Empty, // done - [CONTROLLER_BATTLEANIMATION] = OakOldManHandleBattleAnimation, // done - [CONTROLLER_LINKSTANDBYMSG] = OakOldManHandleLinkStandbyMsg, // done - [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done - [CONTROLLER_ENDLINKBATTLE] = OakOldManHandleEndLinkBattle, // done + [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, + [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, + [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, + [CONTROLLER_SETRAWMONDATA] = BtlController_Empty, + [CONTROLLER_LOADMONSPRITE] = BtlController_Empty, + [CONTROLLER_SWITCHINANIM] = BtlController_Empty, + [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, + [CONTROLLER_DRAWTRAINERPIC] = OakOldManHandleDrawTrainerPic, + [CONTROLLER_TRAINERSLIDE] = OakOldManHandleTrainerSlide, + [CONTROLLER_TRAINERSLIDEBACK] = BtlController_Empty, + [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, + [CONTROLLER_PALETTEFADE] = BtlController_Empty, + [CONTROLLER_SUCCESSBALLTHROWANIM] = OakOldManHandleSuccessBallThrowAnim, + [CONTROLLER_BALLTHROWANIM] = OakOldManHandleBallThrowAnim, + [CONTROLLER_PAUSE] = BtlController_Empty, + [CONTROLLER_MOVEANIMATION] = BtlController_HandleMoveAnimation, + [CONTROLLER_PRINTSTRING] = OakOldManHandlePrintString, + [CONTROLLER_PRINTSTRINGPLAYERONLY] = OakOldManHandlePrintSelectionString, + [CONTROLLER_CHOOSEACTION] = OakOldManHandleChooseAction, + [CONTROLLER_YESNOBOX] = BtlController_Empty, + [CONTROLLER_CHOOSEMOVE] = OakOldManHandleChooseMove, + [CONTROLLER_OPENBAG] = OakOldManHandleChooseItem, + [CONTROLLER_CHOOSEPOKEMON] = OakOldManHandleChoosePokemon, + [CONTROLLER_23] = BtlController_Empty, + [CONTROLLER_HEALTHBARUPDATE] = OakOldManHandleHealthBarUpdate, + [CONTROLLER_EXPUPDATE] = PlayerHandleExpUpdate, + [CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate, + [CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation, + [CONTROLLER_STATUSXOR] = BtlController_Empty, + [CONTROLLER_DATATRANSFER] = BtlController_Empty, + [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, + [CONTROLLER_PLAYBGM] = BtlController_Empty, + [CONTROLLER_32] = BtlController_Empty, + [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, + [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, + [CONTROLLER_CLEARUNKVAR] = BtlController_Empty, + [CONTROLLER_SETUNKVAR] = BtlController_Empty, + [CONTROLLER_CLEARUNKFLAG] = BtlController_Empty, + [CONTROLLER_TOGGLEUNKFLAG] = BtlController_Empty, + [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, + [CONTROLLER_CANTSWITCH] = BtlController_Empty, + [CONTROLLER_PLAYSE] = OakOldManHandlePlaySE, + [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, + [CONTROLLER_FAINTINGCRY] = OakOldManHandleFaintingCry, + [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, + [CONTROLLER_INTROTRAINERBALLTHROW] = OakOldManHandleIntroTrainerBallThrow, + [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = OakOldManHandleDrawPartyStatusSummary, + [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_Empty, + [CONTROLLER_ENDBOUNCE] = OakOldManHandleEndBounceEffect, + [CONTROLLER_SPRITEINVISIBILITY] = BtlController_Empty, + [CONTROLLER_BATTLEANIMATION] = OakOldManHandleBattleAnimation, + [CONTROLLER_LINKSTANDBYMSG] = OakOldManHandleLinkStandbyMsg, + [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, + [CONTROLLER_ENDLINKBATTLE] = OakOldManHandleEndLinkBattle, [CONTROLLER_DEBUGMENU] = BtlController_Empty, - [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop, // done + [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop, }; void SetControllerToOakOrOldMan(u32 battler) diff --git a/src/battle_controller_pokedude.c b/src/battle_controller_pokedude.c index 0cdfee846..fe2c94137 100644 --- a/src/battle_controller_pokedude.c +++ b/src/battle_controller_pokedude.c @@ -76,64 +76,64 @@ static const u8 *GetPokedudeText(void); static void (*const sPokedudeBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = { - [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, // done - [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, // done - [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, // done - [CONTROLLER_SETRAWMONDATA] = BtlController_Empty, // done - [CONTROLLER_LOADMONSPRITE] = PokedudeHandleLoadMonSprite, // done - [CONTROLLER_SWITCHINANIM] = PokedudeHandleSwitchInAnim, // done - [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, // done - [CONTROLLER_DRAWTRAINERPIC] = PokedudeHandleDrawTrainerPic, // done - [CONTROLLER_TRAINERSLIDE] = PokedudeHandleTrainerSlide, // done - [CONTROLLER_TRAINERSLIDEBACK] = BtlController_Empty, // done - [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, // done - [CONTROLLER_PALETTEFADE] = BtlController_Empty, // done - [CONTROLLER_SUCCESSBALLTHROWANIM] = PokedudeHandleSuccessBallThrowAnim, // done - [CONTROLLER_BALLTHROWANIM] = PokedudeHandleBallThrowAnim, // done - [CONTROLLER_PAUSE] = BtlController_Empty, // done - [CONTROLLER_MOVEANIMATION] = BtlController_HandleMoveAnimation, // done - [CONTROLLER_PRINTSTRING] = BtlController_HandlePrintString, // done - [CONTROLLER_PRINTSTRINGPLAYERONLY] = PokedudeHandlePrintSelectionString, // done - [CONTROLLER_CHOOSEACTION] = PokedudeHandleChooseAction, // done - [CONTROLLER_YESNOBOX] = BtlController_Empty, // done - [CONTROLLER_CHOOSEMOVE] = PokedudeHandleChooseMove, // done - [CONTROLLER_OPENBAG] = PokedudeHandleChooseItem, // done - [CONTROLLER_CHOOSEPOKEMON] = PokedudeHandleChoosePokemon, // done - [CONTROLLER_23] = BtlController_Empty, // done - [CONTROLLER_HEALTHBARUPDATE] = PokedudeHandleHealthBarUpdate, // done - [CONTROLLER_EXPUPDATE] = PlayerHandleExpUpdate, // done - [CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate, // done - [CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation, // done - [CONTROLLER_STATUSXOR] = PokedudeHandleStatusXor, // done - [CONTROLLER_DATATRANSFER] = BtlController_Empty, // done - [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, // done - [CONTROLLER_PLAYBGM] = BtlController_Empty, // done - [CONTROLLER_32] = BtlController_Empty, // done - [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, // done - [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, // done - [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, // done - [CONTROLLER_CLEARUNKVAR] = BtlController_Empty, // done - [CONTROLLER_SETUNKVAR] = BtlController_Empty, // done - [CONTROLLER_CLEARUNKFLAG] = BtlController_Empty, // done - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_Empty, // done - [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, // done - [CONTROLLER_CANTSWITCH] = BtlController_Empty, // done - [CONTROLLER_PLAYSE] = PokedudeHandlePlaySE, // done - [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, // done - [CONTROLLER_FAINTINGCRY] = BtlController_HandleFaintingCry, // done - [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, // done - [CONTROLLER_INTROTRAINERBALLTHROW] = PokedudeHandleIntroTrainerBallThrow, // done - [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = PokedudeHandleDrawPartyStatusSummary, // done - [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_Empty, // done - [CONTROLLER_ENDBOUNCE] = PokedudeHandleEndBounceEffect, // done - [CONTROLLER_SPRITEINVISIBILITY] = BtlController_Empty, // done - [CONTROLLER_BATTLEANIMATION] = PokedudeHandleBattleAnimation, // done - [CONTROLLER_LINKSTANDBYMSG] = PokedudeHandleLinkStandbyMsg, // done - [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done - [CONTROLLER_ENDLINKBATTLE] = PokedudeHandleEndLinkBattle, // done + [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, + [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, + [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, + [CONTROLLER_SETRAWMONDATA] = BtlController_Empty, + [CONTROLLER_LOADMONSPRITE] = PokedudeHandleLoadMonSprite, + [CONTROLLER_SWITCHINANIM] = PokedudeHandleSwitchInAnim, + [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, + [CONTROLLER_DRAWTRAINERPIC] = PokedudeHandleDrawTrainerPic, + [CONTROLLER_TRAINERSLIDE] = PokedudeHandleTrainerSlide, + [CONTROLLER_TRAINERSLIDEBACK] = BtlController_Empty, + [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, + [CONTROLLER_PALETTEFADE] = BtlController_Empty, + [CONTROLLER_SUCCESSBALLTHROWANIM] = PokedudeHandleSuccessBallThrowAnim, + [CONTROLLER_BALLTHROWANIM] = PokedudeHandleBallThrowAnim, + [CONTROLLER_PAUSE] = BtlController_Empty, + [CONTROLLER_MOVEANIMATION] = BtlController_HandleMoveAnimation, + [CONTROLLER_PRINTSTRING] = BtlController_HandlePrintString, + [CONTROLLER_PRINTSTRINGPLAYERONLY] = PokedudeHandlePrintSelectionString, + [CONTROLLER_CHOOSEACTION] = PokedudeHandleChooseAction, + [CONTROLLER_YESNOBOX] = BtlController_Empty, + [CONTROLLER_CHOOSEMOVE] = PokedudeHandleChooseMove, + [CONTROLLER_OPENBAG] = PokedudeHandleChooseItem, + [CONTROLLER_CHOOSEPOKEMON] = PokedudeHandleChoosePokemon, + [CONTROLLER_23] = BtlController_Empty, + [CONTROLLER_HEALTHBARUPDATE] = PokedudeHandleHealthBarUpdate, + [CONTROLLER_EXPUPDATE] = PlayerHandleExpUpdate, + [CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate, + [CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation, + [CONTROLLER_STATUSXOR] = PokedudeHandleStatusXor, + [CONTROLLER_DATATRANSFER] = BtlController_Empty, + [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, + [CONTROLLER_PLAYBGM] = BtlController_Empty, + [CONTROLLER_32] = BtlController_Empty, + [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, + [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, + [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, + [CONTROLLER_CLEARUNKVAR] = BtlController_Empty, + [CONTROLLER_SETUNKVAR] = BtlController_Empty, + [CONTROLLER_CLEARUNKFLAG] = BtlController_Empty, + [CONTROLLER_TOGGLEUNKFLAG] = BtlController_Empty, + [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, + [CONTROLLER_CANTSWITCH] = BtlController_Empty, + [CONTROLLER_PLAYSE] = PokedudeHandlePlaySE, + [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, + [CONTROLLER_FAINTINGCRY] = BtlController_HandleFaintingCry, + [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, + [CONTROLLER_INTROTRAINERBALLTHROW] = PokedudeHandleIntroTrainerBallThrow, + [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = PokedudeHandleDrawPartyStatusSummary, + [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_Empty, + [CONTROLLER_ENDBOUNCE] = PokedudeHandleEndBounceEffect, + [CONTROLLER_SPRITEINVISIBILITY] = BtlController_Empty, + [CONTROLLER_BATTLEANIMATION] = PokedudeHandleBattleAnimation, + [CONTROLLER_LINKSTANDBYMSG] = PokedudeHandleLinkStandbyMsg, + [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, + [CONTROLLER_ENDLINKBATTLE] = PokedudeHandleEndLinkBattle, [CONTROLLER_DEBUGMENU] = BtlController_Empty, - [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop, // done + [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop, }; #define pdHealthboxPal1 simulatedInputState[0] From 3757c6b6343f979da62b37c1936885c280902eef Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Tue, 7 Jan 2025 23:19:16 +0100 Subject: [PATCH 12/13] readd first battle condition --- src/battle_controller_player.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index e9c281ac9..30921fafd 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1060,7 +1060,10 @@ void HandleMoveSwitching(u32 battler) } } - gBattlerControllerFuncs[battler] = HandleInputChooseMove; + if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) + gBattlerControllerFuncs[battler] = OakOldManHandleInputChooseMove; + else + gBattlerControllerFuncs[battler] = HandleInputChooseMove; gMoveSelectionCursor[battler] = gMultiUsePlayerCursor; MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 0); MoveSelectionDisplayPpString(battler); From bf1d036acd4b32c07b8e90ee487ef188db9dd5c2 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Tue, 7 Jan 2025 23:29:11 +0100 Subject: [PATCH 13/13] remove comment --- src/battle_controllers.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 503ea3cec..01132838a 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -1334,8 +1334,6 @@ static void UNUSED BtlController_EmitCmd32(u32 battler, u32 bufferId, u16 size, PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, size + 3); } - -//TODO: compare values to pokeemerald? void BtlController_EmitTwoReturnValues(u32 battler, u32 bufferId, u8 ret8, u32 ret32) { gBattleResources->transferBuffer[0] = CONTROLLER_TWORETURNVALUES;