From 69f600f4cda02ad799cf7bd253de4de8a05a5523 Mon Sep 17 00:00:00 2001 From: Blounard Date: Tue, 12 Dec 2023 00:01:15 +0100 Subject: [PATCH 01/12] Rotation 1st attempt at adding rotation to infodisplay. Unfinished. Mainly a test of using github --- .../__pycache__/__init__.cpython-38.pyc | Bin 0 -> 180 bytes .../__pycache__/framesequence.cpython-38.pyc | Bin 0 -> 7426 bytes .../__pycache__/input_display.cpython-38.pyc | Bin 0 -> 6031 bytes .../mkw_translations.cpython-38.pyc | Bin 0 -> 2850 bytes .../__pycache__/mkw_utils.cpython-38.pyc | Bin 0 -> 3701 bytes .../__pycache__/ttk_config.cpython-38.pyc | Bin 0 -> 734 bytes .../__pycache__/ttk_lib.cpython-38.pyc | Bin 0 -> 12306 bytes scripts/Modules/infodisplay.ini | 25 +++++++++++++++ .../__pycache__/__init__.cpython-38.pyc | Bin 0 -> 2702 bytes .../__pycache__/ai_input.cpython-38.pyc | Bin 0 -> 2903 bytes .../__pycache__/bsp.cpython-38.pyc | Bin 0 -> 8568 bytes .../__pycache__/common.cpython-38.pyc | Bin 0 -> 10501 bytes .../competition_settings.cpython-38.pyc | Bin 0 -> 4127 bytes .../__pycache__/controller.cpython-38.pyc | Bin 0 -> 1983 bytes .../controller_info.cpython-38.pyc | Bin 0 -> 1765 bytes .../ghost_buttons_stream.cpython-38.pyc | Bin 0 -> 1590 bytes .../ghost_controller.cpython-38.pyc | Bin 0 -> 1531 bytes .../__pycache__/ghost_writer.cpython-38.pyc | Bin 0 -> 1790 bytes .../__pycache__/gp_stats.cpython-38.pyc | Bin 0 -> 2779 bytes .../__pycache__/input_mgr.cpython-38.pyc | Bin 0 -> 5763 bytes .../__pycache__/kart_action.cpython-38.pyc | Bin 0 -> 1208 bytes .../__pycache__/kart_body.cpython-38.pyc | Bin 0 -> 2966 bytes .../__pycache__/kart_boost.cpython-38.pyc | Bin 0 -> 4237 bytes .../__pycache__/kart_collide.cpython-38.pyc | Bin 0 -> 3030 bytes .../__pycache__/kart_half_pipe.cpython-38.pyc | Bin 0 -> 2951 bytes .../__pycache__/kart_input.cpython-38.pyc | Bin 0 -> 2978 bytes .../__pycache__/kart_jump.cpython-38.pyc | Bin 0 -> 9032 bytes .../__pycache__/kart_move.cpython-38.pyc | Bin 0 -> 39032 bytes .../__pycache__/kart_object.cpython-38.pyc | Bin 0 -> 4001 bytes .../kart_object_manager.cpython-38.pyc | Bin 0 -> 1774 bytes .../__pycache__/kart_param.cpython-38.pyc | Bin 0 -> 1588 bytes .../__pycache__/kart_settings.cpython-38.pyc | Bin 0 -> 4315 bytes .../__pycache__/kart_state.cpython-38.pyc | Bin 0 -> 6591 bytes .../__pycache__/kart_sub.cpython-38.pyc | Bin 0 -> 2561 bytes .../__pycache__/player_input.cpython-38.pyc | Bin 0 -> 2521 bytes .../__pycache__/player_stats.cpython-38.pyc | Bin 0 -> 12951 bytes .../__pycache__/race_config.cpython-38.pyc | Bin 0 -> 2634 bytes .../race_config_player.cpython-38.pyc | Bin 0 -> 3587 bytes .../race_config_scenario.cpython-38.pyc | Bin 0 -> 2256 bytes .../race_config_settings.cpython-38.pyc | Bin 0 -> 4797 bytes .../race_input_state.cpython-38.pyc | Bin 0 -> 2541 bytes .../__pycache__/race_manager.cpython-38.pyc | Bin 0 -> 9852 bytes .../race_manager_player.cpython-38.pyc | Bin 0 -> 11157 bytes .../__pycache__/race_stats.cpython-38.pyc | Bin 0 -> 2502 bytes .../__pycache__/time_manager.cpython-38.pyc | Bin 0 -> 3510 bytes .../__pycache__/timer.cpython-38.pyc | Bin 0 -> 1316 bytes .../__pycache__/ui_input_state.cpython-38.pyc | Bin 0 -> 2211 bytes .../vehicle_dynamics.cpython-38.pyc | Bin 0 -> 7133 bytes .../vehicle_physics.cpython-38.pyc | Bin 0 -> 11317 bytes scripts/Modules/mkw_utils.py | 29 +++++++++++++++++- scripts/RMC/_draw_info_display.py | 9 +++++- 51 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 scripts/Modules/__pycache__/__init__.cpython-38.pyc create mode 100644 scripts/Modules/__pycache__/framesequence.cpython-38.pyc create mode 100644 scripts/Modules/__pycache__/input_display.cpython-38.pyc create mode 100644 scripts/Modules/__pycache__/mkw_translations.cpython-38.pyc create mode 100644 scripts/Modules/__pycache__/mkw_utils.cpython-38.pyc create mode 100644 scripts/Modules/__pycache__/ttk_config.cpython-38.pyc create mode 100644 scripts/Modules/__pycache__/ttk_lib.cpython-38.pyc create mode 100644 scripts/Modules/infodisplay.ini create mode 100644 scripts/Modules/mkw_classes/__pycache__/__init__.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/ai_input.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/bsp.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/common.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/competition_settings.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/controller.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/controller_info.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/ghost_buttons_stream.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/ghost_controller.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/ghost_writer.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/gp_stats.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/input_mgr.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_action.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_body.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_boost.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_collide.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_half_pipe.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_input.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_jump.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_move.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_object.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_object_manager.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_param.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_settings.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_state.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_sub.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/player_input.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/player_stats.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/race_config.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/race_config_player.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/race_config_scenario.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/race_config_settings.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/race_input_state.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/race_manager.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/race_manager_player.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/race_stats.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/time_manager.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/timer.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/ui_input_state.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/vehicle_dynamics.cpython-38.pyc create mode 100644 scripts/Modules/mkw_classes/__pycache__/vehicle_physics.cpython-38.pyc diff --git a/scripts/Modules/__pycache__/__init__.cpython-38.pyc b/scripts/Modules/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..33ffeffb22ac501e0fb1781fa67bdde223c852ce GIT binary patch literal 180 zcmWIL<>g`kf}=-DQ$h4&5P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;x_yi&czEeojF~ zW}ZSoWpaK|YD@}*tDBoxT#{M@-x7%)o! literal 0 HcmV?d00001 diff --git a/scripts/Modules/__pycache__/framesequence.cpython-38.pyc b/scripts/Modules/__pycache__/framesequence.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f8e98d61102fcced21670a09b9434e27961f19aa GIT binary patch literal 7426 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 E0i1rwJ^%m! literal 0 HcmV?d00001 diff --git a/scripts/Modules/__pycache__/input_display.cpython-38.pyc b/scripts/Modules/__pycache__/input_display.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..96e2440ab9664f0427fb6c709be7c80922ba262a GIT binary patch literal 6031 zcmeHLOK;=I5#~z|zdai7cy>3BhLB_}$DRxp*&r~2AhNA-ggCNc%ZtpcHVQ{g+ssHL z(WJ%_AR(9i4LJ>h-Q(nUB-fk+BDb9U2Xe?Eld5WxB4ydx-Q*A~mH?aV>ZVe8+MEON4o0a=Y(`xsKa)MMp=j=)wOyynFEa zYfuErr|L)^X;D9H3bV? zY${iGfAzG?p7(>mbso)=WK~@FJM@Qoq-ks;=zCqOvcsB}R!noxSpYRD%xs5h=dS26 zX!&Tc#fBe0O7zH~u?^b^A}tXmqh-QRQ;=qtgbX)x`$5-stm(cV531FZlY@iZU8(Py z!Gtv`n$X}IE^uL9wdHgOoY&Win1jzhf4#rc+IPF&B@E?w*l~r`;z zjwyz%!H<5}I`e^k=$gEB+7Y%F_^n^Myx+C_mhE``pv`UH>zczy-Y{J6kWbou#}k(C zTf8l&&VbH+G)TQVNb!7z63xC?Wa-od?s3@Kdi07R7iyLl@<5^gpz;rG!q%Tb`8`uz& zJ^Y$mp0vww$IkdqlZ~|34uCS@=1T zK)`e=*Hoa(lO-}oO9ZD>ECYRdWz33P?DiYL>(kD(kXIilnxefC2+sdA_wU_se;n0c zyZ?>_dIJy8PHT)l?srqNSDzRlE zL0o_;6H2Tj!=2KWl1Nc!N@4#}cg%_Sb<>L2=7>MT5lcqsmm1lWE*NQAPmGqS-f%7^ z*2nzm-m)BsylG0BGc~_)uX6TLf+$&TnxBj|97#f*Au;ja#O9PlG7{>C>#!RbW&xH4 zov4!2-7N6uHi847xY=c%$^ZLZV1N7A{iv}O37nnQh~B6jRGak=YwW}7;aQD6 zIXYqWCTkwC>hW={dcyXOPEKlj&BLdgnz>#UOG#TsXSMMuiJlF=f&pYsC^Fi&SRXPA4Aze8{I>595U?vdxMV3u%hOo>9GGG4(mGDH zvhzr83xX38A82=di<#o0--ArmhbR@6T)-F%cx)!)Fq+E~-<1;yW_q4*Jz+yi+8urk zNKH(lF~^V3*-_HLBrwg$sHaafh?SF>&K}~WI4+P_?MC^`D{ry#zI)~1_YhJS_=59( z05+6QFmEYWXsMy%JwRHs)3LmO_4?hwhRmP6G`oGvk6ibEiHM0@!2uD8xNu#JP zM{t+^lda;rzzyAE9*EgvA2vhhq8(lKEc$`nc@ftZa9@cl1=%zRqo1M7EfE6a2klI9 z%YQ&+WN`Jz%Gem?=$ngjO8`i&zN^rgQQ5f~JHk(e#&?E7DXX=tNud+`z0D z>Ka&31c=sR8qWb(=FP`9&qjcNfpEKwrcq*`$>RBs?nP#T(X2}^ne?*h3^`(ra@S0c zlax2^GjeP?_no>0ixx*>9EKx4=|yt8_$}S1*3=AHMD2_q>p=X|`NoDjLD_$7!62<* zux$?DKr}ria=JGjZ@>S+2bDV&48M?qyU%nn*4+xB;G$_1z5X3U4BZJ(a(Io`$c>6l z_k;o~ViAhU9EGm<9unTe0xxky1q(z1iptxuV=dZQqd9KV^!y&=d_)>JX{kjG&Ps3c z`kGo&*VI*b>8q`(VjDObm4&bn-9*YO%pBduhB{oP(v6|Ot0}s9pd^&eR)jhvp8_+2 sHN3D0i$CenJ>^d^H6}n?)Juz{MFVr$H;XH4E79Nkc}dx%FWqtc8v%p^Z~y=R literal 0 HcmV?d00001 diff --git a/scripts/Modules/__pycache__/mkw_translations.cpython-38.pyc b/scripts/Modules/__pycache__/mkw_translations.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd4ae281db773b265667aa01ac31195dc80697c8 GIT binary patch literal 2850 zcmb^z%Wm67kfbC_qMvbIcH6XUnzm8euxpg?CyDUoG4mzKm1cjvXUv-9Bn#YI!Y=l9C`y>H(FK z`<5eUN1;je-ob&0C@_(jE)Th7Gb-bxy2}HwcF|wS{6;`~%-RUhpUGmq%UIv4cd6*8 zr8nrKZaat~{3gpyE@;@LR#QZe1EsRX!=csUXf`n&I*bMHBO|HaVX?&fK$dws7@&3< z_)$nIUSIG~*=24;AshM;>Yq52%@5g$V`qrTV`qp4Y8?ati!HTGsxI}r`E(&a%+4ST zaqo)FbC%Tf1|2G-A4PFu?y7Lg_|x()1L_|lYnkxAg#(Y=MJ9BNg_j}Hd6#zhp%`$9 z(N^_BMh}%=(~{R`6diyEwd}$Ee!!9?Ckpyq9$F5SU1TXYyEKfWUac%tz6b+Bx+pNn z_v9$1g$m7dE{}lJJYrq$2W*c+S~{ZWw^~uCL`*MaQs_aLfPTK`J91@|7ko zqv+q%`My0itcea6tPQ!HH+vWfOpKRpn`530+fTmzrhOkz+iqakv^^iMG?r~Qf{W9RB=X1u8Ok6 zwCVoPYBG#aQr^Wo`NB5F>$HY66!-r*-oUCTT`;R05s6y0J+MfvaRAC zD+;R1EVS;3TgZ`FmRr0r2oFaFRCXds0}PsE&E?#>H;4}~-F~vJyVkMQ;GJ$l@n>-<+u>B*uyC`iZiF~FT{m77$3Fz> zSKzDY&kSlTBi5J|ISGgBW#}6r6336m~a}(x?-|!QpPeIE65*bAC9^Ky; z?1*QLlE%6`$_;)aui=EX(!*Q`AA#f-#oul7;IyKKwzMI~$knyI@Mx)-XM*9eHMU z+}&$wU9$HYPtuQ-1^ymSDM6u!t2r;>;3U*tuOekyE&lTX>OI_>ph$4)8$~ z6bsQp(TO_1S;Ea1qebBf{|hTx5`kDizbrOIM=XB9q7|_umVsFnD`FM>nphL((4Q0M z#Rc@|#k#nN{({&Lm(Z^Z_qo-*e2jNlUEX*_S`6j5aYs7K)iEQi)3`;fZ{2R(SEE?> z8|QVJ+-f=x4&y|>$cj{U?Pm4!bdV)^dVgHTMV6>$Wr}z@7%Q5edlo0@FDLtNCTCcHc6{fXA1??u$XDLj2=!kmgk? z!~UpDbT%wQJq+VKA0C9oDA!q)r(vaKC{mgB(aI#nxv~?s->XrUybRSS0b1eo_3(GG zN_(*o5(v6r?w|3C z`)ATUBE-p1#5(Tjah1*nDz!XvJCmm5CX zY3$L~Ho&c$kv-bJ9dWf2*=lPWfKUo3yHBJ3_H9Wzl`a7fpt~wLx+aimEP9~O`0Z$C zh63g3;`Z(7qM9w@j_D#UnvJlnJ%B4`qv^ekL&WE9_oJnG6-542xY5FioTAlaB%w+@ z(^KQMo1*2{aXvaxU(`7{qW)ybtKjNC(fzx-_lJ2k$jb2PI2p=xSG3a~6|vH(oK1Is z38~8Q?&0?B-Om*8pAKWO`#h0ZrPc1^p%~?<+AUrl^o$E$ug1-CG9crrhFJ+h2HzIeG5bI`m@R42FMel5knOr~*R4y~CA_QHzhO-fT5A^p)F*mf|A{0?8@u>3 zM%sd8eig&K1KoiHj`UeIi&+)i<&X2Z4Ah$AYEtxl4CC&`CY;Yw%KBBXoCC=wF{#P@ha`5 zl(46=eh4DU)GUmG$QqcGH-Y;KYbWMK*S;?TwWb?gF$=2&atCd_$)z+kZLxfzv~<~)^l z9q?>r-K&;%;C=29uoG_%=OZTbBb=Q0r?4o93^vd~?F(na zssjT(g2qSPHy=KY5jVrTp(*5MWkL8X)gxH~O@&=}OcBOt?D#Jj9SbHYQDtT0qS7dDntV??Up4%2E8>SYBR)nyzA1kSLdeL&Ja618)5)N* z$ML~gWnV;fl8ka=tH^?~2Sdrz&v8~!(zEP`>>&%G@eTasuYftFb$T~70h zQ3cSxqa^0#xjgi1RoWq1pF9YXQ@qqHNMH#c@P9w1FsVVtHDCx2aAFC EKcFaGS^xk5 literal 0 HcmV?d00001 diff --git a/scripts/Modules/__pycache__/ttk_config.cpython-38.pyc b/scripts/Modules/__pycache__/ttk_config.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2179d063fdad13cc4778b357b051793b8f4583fa GIT binary patch literal 734 zcmZ8f&1w`u5bo}oot@q6ZWeM-K|#oA4kj0oAR-cjBAO5gK^O;`-sw(u*!iQoC&`A* z&Bxe7a`Zj)<`eYQQ(j>~v3ka=s|EE@Rb4+{)y#3f-$fwbzE5UWYeohvdUGxPuf75`xIX#f33`Ytakt+uUsn6jymefhx%Z=CM21F9r!Q79FN-9BBT4>5f zBPq_3`YeGX?Y72i62f&YE;Kz!QbFyV)E6WN@V@x8_dMDw(sG>Sj}NDDAw|R+_esW- z7V^%Gc9WdRX>{@IX>_b0{-IzzI*MgdY8CAlyh??Nw4Tto$WM~ft#WDx{|@cIK-B|4 z*e6}w#e<)oCx_rm4*m65M-KO|2vYPEn`+L-UdammZ*J@6`egkhI#6|!B literal 0 HcmV?d00001 diff --git a/scripts/Modules/__pycache__/ttk_lib.cpython-38.pyc b/scripts/Modules/__pycache__/ttk_lib.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a0d86f7cade19c989091e97d66b4842960d168c GIT binary patch literal 12306 zcmcgyTWlQHd7kTDW-nYWDPDB*N|bG_V#|^x+p?|Dy4qGGQHm~cJXN|`?irFx?u9xt zlqGsLaY7eX3$%68Bu!g2UG)-F1=_x}FF~896bRZP0g5&a=Al5*yzr?HMPFQ_>i7R= zcDbZvv_*j~Isg3UKlgL~^WV-~&*dBqzrXsyinr^uru_>g27gH;PT=wH8k#0Fp*OUq z?&?j$HJYYt>O?adR?~KE#?3~enRJtkTaA>PLcY~VyJ@`bhSSWrnP%3_Hgj$+E|Yij zA|aBEp=QA?fR+%c#&EOf78y@BMw+AUXmgvpjnfX&WA0dU+#Tn12I&cRqB-eKHn+Rm zn>*Yc&7JN}&dVZim%FRE+uhxK!hM2iInYXOskz79qib(yA}@yC*Tj&QTr=IhNEgH~ z(!-pd5=AlczUJ-|qhcH0Pl_=yj`veyLQLZQwAe0o;Jsh$6ua;)dsE(C?||5S&lFFH z()*VCDenL%S^PaSsZDBP4|4X3DdaqhvN^8++P-^+cv3tC+Ck682%Z-EF@pVT#+vRv z=RJeJz20-8e9saG#HUc|kXPU~pF`be(B8A+AgG5y&8U79oHLOB9NIo44kQ10L3znL!nHn)GSlKU zP>x|f1)j?ZaT4j5#VK(bYx0UXBhKRes`tv8<{tN61^hHxfBl{=-Vkr1h*o8JY7d^(fKwnr(R}vR8t7!!PSm zT2zB-tx@$UVV!NQG-puOzP7U5@FMF%-4CMFrRAXBZdDuWI<=%nxz}a2>0R}1u6V7Q z2Z9p>OO;x?HCLZ68&T#;wdP%{wyN`8t8m;Bvk5=Ra9)AMB(_CF>t|4^S z6ozXF)3tdI>}X_Tj67&+Oj2b@GG!eCLz^ilqEw~Q!qQeMkyEKO+hV0bc(zixxl(P! zIo9hZPoIs9Gv}~NSI(V2|3H&d)DVG>K7Zzw8)w>$<%N2ybooxLExj8;C7*3peXL?H zdE-v8AC?H7;UxbA~~puGVCIIq+{>{4gMp5w5B>_uXk)sxQ^D4}gZMh3|G@#dwg*EZ&!(0qX#;7y|vTc5(KhdTT&g;2z_c$)8$dX z8qJ~ivw`$?=r|HW?^vNGCqf+$4%1RnP6)GO1sKMf4ydo`!WzZS1Bdt*HsPT)u3>=^ zGkmnlmO5dyf9urxI%(*2nv2>~ngyhnS#Jeky)w~>JLIPT-1M^aZdGt-mfYm+V~jj9 zONhTM8%eVY5ik!cJpGGJS4kw`<_FdE#(v=Ayo2$lHOjrghA~49%`}AItO0V28jCt!^St z*`eJ{-q(WEVtUE&PX*3b^&k^uySX?&5hl9%P+uInuXmC`Axv@`sW8Tz?FdsVOT4yL2?@okyv{DF-U@|NS zbIo{(W|S8e-uZ$2g0L~-k5O}I$(BF7`SHykhIFbEGY_DEt3pVn5@=Bro6<=vZ)dS4 zp8_t&2$0N+a*||>AL}+bNwkF8hsdIhklTsmTseF4Lgm7x(Z29$7PtsOK1y#4!SM73$ z$a&R>AGadu6hDZwb+LKx*5!%8S!{Ne#n+dEiv4$F9LYPoC*3EsPMe;RFfW4Ef4fQZNsu5G) z+}8@wa%xM{|h z3)5uQ50>I%l2o!?oeUORCuw2mjP!nllYqU7hh;Gd*oj!uy$GU`uX?24-nxyc(Ac49z5P?*QyPF8i*=ecGwV-dr>^HWwkZ$MP|cmv6_=5P+8lv zij6F0ZL?WjMz!mdM_ey21Gt$10qbUNA3k)bf@bD}g-EZ%D9(rOU2z+Tc&`_39gaMFc-phhREnTG($Q?CO`fgoTPzU;m4=MBE z;Bu1~r-#nA|JMM4*3}_gb%;Z>}ry9RKs^MUq({(&)P z3R76`r-FPibQe~{ntldnqhkaGQaMmK!y%6(B{EuLnkC z96TgHhpG=uH!12YN8B{qk+l1+qZovR!W4=r_3Ruco~pH*%hUI$Z`zCmPQdCx7D{s~ zjYdT=f#^%8K`!o9E*E7ERU_LccTJw74)R1upT2Z`=GvJ{Z_P-WWHbcXS!w&C(u9D8 zmj{RN+|0SFZ=O94dIGs}0p)9W zHvNdhPvGH(dY;X7%`-hq=*QLDIIb~&X>k2)QtMIb%K10go#x{nCFaO^_BXK(9Vcr1 zG&N2tmdxBmxF?IS_}6qaqqA2|r{7mnV-clbyIQ{2nA>0>wGQbD%L%_y`7Sj`d#35D z#ojm$_Osz~Zt=JzsjXnxV5~`acWpFtcQTsLNDnbaO!-bj)teWT|aqrk1c_9ay2$F>i*jEhuFJ zd!%%~q%wPzlSX>E{t!mv`a@uB0+)v#D@4elitK8w<~1UFR#uk~r$T(FDaqxDl72ug z=j|SHN0NIIrNlC9PUy-gQC(h!MW^;SE0?J^Qo+!qUZ5nd!>%8zQ@KQ085o1Iq7JT` zto!WRyEYI}cT;$=TxO1U9WKk2U5Be&s5k4u!0BQB8;$v|XI8MQ^rz^|KLwyc3#&h} z66su7`WT)GBg?o&5==85CQy!O(A)Tf6{(ZfCjBk%pcUwBp5G%no9xE^*&`#E1Wo{b z4bB30G7c98T2bK^aU2C8z=I|%LdZK|z((UZ$(+d=6dVxRbF`=C%qHnZ2ZlOhdu$X4 zE5s^ zt_*zN%_?OZXE;@8(HPJ1JGRXpHMq76>!&nm5)_(JHQ20CU9KVxjb23CyS_yIgN{m6Iv%HOq|)oG|}@S zDN-U$(it&}Y?uQlI3g3~=N!oAjDV#jCcbIHC5G!xR|fZuP60Vd%E3DoztdcD@|#v? zc=ZQ?O_vGau_B!OA;_~4yod1~4QyCt+d>=Ct=Jh0x50N9Thk#~wtcAG{1NIELuY~{ z;CNUJN5Gv0jBz5I2uH(hNR5w^$1)KlyQy#j?)hYp?mFS57}=pAwLMOap3uZLrtF9* zW1wW2vNNV+$Ee1xZ~`OS9_|QthP&o19tnDT3%qS=Vj)K9-T`uQcT)s!FRIIc!$4?G>fzRh6=Ohc!cFts*=g*)>@^@_b}9tMJwAxkkG! zBj~~C6D#7m;0E2*sDXpEFcu)NjKH3$KFQVM2}t<%9M162a3m} zqUuc*jcIDkDiPT{P()Ipde!nd+={|YEShUo<@{lW&oey2@aPudALVM;gTMn*zK&7< zGnUK$T>uTTl!7QJNK}~d_I5o*)WIKZ?&E*|yPS`$hek4s;0*WhFku?#8RjnBg_K@k z6-6XG8t|WqA$mWO;iQjQZhsL-&t{Z)p~D6vEo^j6 z@=6gBwHDz=lRUc*O$^zJD0w#>TK9E%A#l1GVRo|=t+~%WY^%UD3pChiJ^vbBEiP6# zSc{7liurvs{%!|8E-p2EKJ9CL<&j##MIfWvajt8f>&>a5>xtl$Jtaw|h+`@Pis zTevP)ZkL8o2+Svw0v|A@9?IXr2;<$0a`Y*c;eT*az$=b`1gT#Y8t5q`GPBrJ;6=JsWGrO`PJ+R*k8t)x^869C}`K5HF%t zmEQ!2lG4M}Yo7cqBK;P0>e+6!d3H8YzJN*frwtJK{c=b1!snLT4KN(7hETX)O@ax8aM}G<)dp zL;$~~n~Ccu5r=_ivzUXAWOeh5fy=u?j5!q0r(itlWr8AnMR-V|6K2-zPBs_`vunD% z7mUI>LCjOvT28R7J0@^ORD22iFJHrmS@6^Cb<9L{aeH<5Oq&&=PyEm8LI^2CV&jA5 zagMvI2>dB(V*(&TL_*ypa|B+}N#>BcBx^TvmT*u@QGept*HwDpVYH##csJCoy zIY=JJKOmB`G1kYaF8M1o=q+5ei_Ue^3#uHqtRe{CXEO|TKk?U2RMQakrauznc?eLB zikk%k5lKV-3G%_d+&o2v9zAr#f@wUoHuf0V3m_S@~;}`UU{J+b0QsiU1vKH%Go;Us`_Rd5)|$9N5U_<=ohGmIP7q+$AP|t7VhOlOZ$Z{!Gt!7kP-qKroc<-hzhOs9sY|3e85?($@}BS8)@1^R@2&+72hDd;^(fvLm{ zTj$;VzlR_!qod6}`i;3hdhFtT6nJ1oi7OXRpFMP#-gTN3iI@N zNL|2FCU<)4EJvuw#$m1CqN4T|&5jIV1pIY_g9h?1korH&ul}{h-<+@i<$i!K90d6H z^M89@{yB~3djJrr_(B3IdF$wgl}KpTmhV&$xM|fEZaije-{&UOQ3u-p(H8XiEkG*3 zCcxWcy+g+qUkMoSzm}ng5Dycuf#7>79Nz^9dmxQlEs-2Zr;tt$q;aV$G6U%>(z$_j z9%*>C{r2H?is6BD5$TbE^yrrI@J+?oKtB9bF)@&y+){o!(mMw7cOt!OAiW#uCkE0b zr1uP@_aZ$tklu&%lLP6ekbZg~y&vCISaBNng`!M2+a?EQ>OaNWGh0t+(}kGBC$#?@ zF*N=zgtIPc-={Qrxb^oQ{^*5ul5q7y+IuJ2o9&f30{4}4B&So__hDkJlSZvu+Lw>5 z@9gEwXw$>UDN)Y#j~eUq@P_LXDueZmS__t^SnVDdcxglvYkoUcun+VBF?O3$qT z&Eadi4Q7vq>n+@(*P#$`glpB>0=}Ii?{Rc6Oy#EffVzu{YQ@wwymCV*eihrF2{>KyCn&dR&?X4< z@Stf;1_vEmku+qzYsV?NcZQwap8!64;jt&x*oh65(MBeZn#y+x`v-uY4b54Pn?h_u z51LN?cW4f*R^TL(jU)e&n$jgTu*sOFiS&(W;yPT9;v#_zY6{IEkcA5aJeDvh2nWoj z;M@is;VO%Qb>rG8Ek3qX6Jic!@x}1?AQi$6)Z`XwnyBPf@=L({l0WwYa#mL5?gB4y2^rmcK;cTSQFYTOBN#q`M?ZEF;ONm3IN$ zoVs_2uRz)4iIl|{WtvOxRC=xFs79UuZc#M;Qb(Od8u^AhqBwhuXyXJ(+$y()%o-Ia zXB&*fDSxw|zGI+k7rtWQ3l;ful)OfOCeu0EBW#y)BO8~}%dI6O1T-!@R- zrl9YHJzFpecEL&|Q;C$xk5znjduep1p%;>)2?GXF;$gO2O0%g1^UQddJzC5c?c#WG TsE|(CDLa8Xmi*B|qLBD6wx8Nn literal 0 HcmV?d00001 diff --git a/scripts/Modules/infodisplay.ini b/scripts/Modules/infodisplay.ini new file mode 100644 index 0000000..b41fb24 --- /dev/null +++ b/scripts/Modules/infodisplay.ini @@ -0,0 +1,25 @@ +[DEBUG] +debug = False + +[INFO DISPLAY] +frame count = True +lap splits = False +speed = True +internal velocity (x, y, z) = False +internal velocity (xyz) = False +external velocity (x, y, z) = False +external velocity (xyz) = True +moving road velocity (x, y, z) = False +moving road velocity (xyz) = False +moving water velocity (x, y, z) = False +moving water velocity (xyz) = False +charges and boosts = True +checkpoints and completion = True +airtime = True +miscellaneous = False +surface properties = False +position = False +stick = True +text color (argb) = 0xFFFFFFFF +digits (to round to) = 6 + diff --git a/scripts/Modules/mkw_classes/__pycache__/__init__.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9050d45144d8002d68afd0ece5719571545521ac GIT binary patch literal 2702 zcmZWq*;?CH5Viq>H;h?BAOr{@#33vJvajqR35km#NvCd9Aq%7AjHMpQN&QHDkM<>W z+pE4puR1fbvD2E5(f|LmNN3I&>7>6u9i!i$f7I=(saWhUCY`@7A}{FQSA;6DN?gS- z4)HkSF2Y^Vh27ANJo^bdg7fMIF2I7|L3I-gP!K$%Zs8&<3LaLsaS4_L zkEmr_ffZbZRpFz=@4y{ggEiq}#Mfb6@Flf@cj2z!adi*x!+pV*)dPG84+T%CNB9^X z3!YR@@F_eMd__IO=kQ$clzM@iu!&o+CH$(|#vRxZJgs(d5B3DlsC|41F9px41AGOq z1Yc9H@eRBYJf{xvExZ+cUA@C16a~+#AMgl{1m934JceVz3+e>l!+XIu)d&0t9|afG zj|c#QZ>gWK3}wNK>Sz1}pU?n9_-*wInqUfEQm1HvC3sm?&<30EN-0)Y{X0(Qt`HA1 zM|Rb5Yr9&zy3iB$e6_7LvFl+1&0u{aO#E6mgEIKn*VSR_SUc7i zc7=nbx;`^4yQp2y)`4UD;m8s3ZMSyjREx@N*jj4D!{kBDs|SZw&5MaVq7Y5JHg(V< zY03?>s}wzbSD52!;wlAZV2Ax%^&oI-n^r*0@F_QYa?o}Y&$ZJJYG*FrZ2#Q#gAdxF zWfC0{8kO-&fwoN~wQtjDJ-~njw9Ak;-Ch${XtR=K*G%p3ZSrk3S{*%oXQUkjPOa*P zqwToeTGgr9+sgF)?}PVEv=7~i-C2OOW-Eu=B{*tNnN@DZ@V1Md9XQ;YQuB5s4{~?k zoqo2h;Lxm@Rp~;yEmBAyvr_$(U{+u|JIVae{c6(_%06wm)Xgv@m)6#D%&R(jt^Aj! zIx9MKbf|Ugi?)kchS@f4u2W&B6qJo^ks_T(-jC)9VIME8Z{KUd6feF-y0=P2a?3+* zxs?Xtf#%WOY1B+~EY8j~rQ&(RXQhj#iHbD45nfc}N6O0Fv>TO(=7`$ZkrHk2+rnAc zYq^MSP4gE*ceCkXlVH=!rjJdM4SiT*n!htT!zRn7pG}U<0Gm9UK{AkXcv=jsYCXg} z>&Yw`BI{w2!t@vFWm6at!Md0nJ<3UWO{wnXsg^U)>5J&jg4Mp9_`gBkB+`gf?jGzeWt!CCrMZNZ(;8svqs~T3hgVn)JFPH4hNS_n;p@AS zB3+LB_gLsY^*w!`QM8;>8ZiBUdH!qk2{9_oA=3|89%#v4G-&z}t68br>gi*W^b^qo z`a)gw`YB5Zmb89GI2`UwGn%{poIJnB^bTFb{A2GtD(|?;J9la`#fIf-yIhIr5}H1p z_!cd1IrOG(lz+RoQ9kiWf8&~!a>>$;7x-m*jn=?TRY=3zYaBr2qf` literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/ai_input.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/ai_input.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b67497a4e8c8c2016caacb5b615b779115e2c7d6 GIT binary patch literal 2903 zcmb7F%Wm676rCAT5=~38Ez5T6KAfgaTcwRxK~WS%5XUKs0*z6?$VL!A5E>?CEK%-| zMq@+SH2#2Y3v`hz^&jm&6tnHhztC0h8Hy6g%5_6v?mT!o_sp4l4<9!gE~Dp<-%o>I z9mf8`B>z}6xlb*ApNwRZ57>}*IcMK8DWrA5r1esCg|rV@r*g^3sl&DNU37AqJbJ47 zG%q|An%$=skI4kA%O&dy+KNj-TM63Ak}X-0)eGLWgNj@asf0ZhB=kjMJe13+;YK!pcj+Fe%);;?<*p2FJQ3-?D+qDF&3 zpe_jsJLuy!vIk?deQNP-GGn2fv54G+J>##$n7`&@=2>I*%%;9VeU=u){m7TS!@denlDPM1Bu@uH+#4SM-944NJ{EMq(7~d2Q zKYwo#*}IwdgzKsbl2aA+k=faU@r-$tPr_ai*RS~@QwY!zDYp%RFsE$7)e5~d=T6NU zrZqCl)M7z~iSzA+h|IkdKmfoD#9K6(UOT~f!N*+kE%ri;DWxXjK-u(uVi{Blr#DeM zmI0*K3NSqtJkiZLY|P7;ab}z)Wm42RF}brC_bht~;Bi*8eQeSsL)l3pK#&PKvA9J` z#1}G!$b^I1hC$BcxLcy>2DKRHW8CHEA1y>tO5_5RH{tQ}7Yd_5_LMvIHjQ<=ob-!0 ztCJ_Z^PJsUh_<|20q%9oy-Oj~J7hB6pxb5MkZ(KG=Dgirh-6`n)5f6tpuXuP! zkv|MPPrIHsG=)jyy663P>JQR4szn>n>&C> z0aH0hWFU#Lo5S6z;4O<-4seM*l;?kZBqcHV3CRX|0R_=fdwN6R<`W{Tj`} zUYT$f6)P?OR749(RVOs*-^Pg49N40Q`-Jx21ui4^!i7k+GHmlt3$$EUUC^aMb$yP7 z(xrS%Yj+WNrb=5`SaY{m#4ZTY)#Q+zU;c@x;5?I|&#(Y>DPuwAd`T@&!bXOskYsPf z!ySamtIVRI!nDZoqs1V}4@DesvQDHIRx2Ze8I9(xL%| v94B+}$k>kC8l|g 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 literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/competition_settings.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/competition_settings.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ee01f9f9077bdb5eed7a0e58b0f82d1028e5459 GIT binary patch literal 4127 zcmb_fTW=dh6yBRJacn0|)1(b8-IkWd6$A<;l#5ECMNm|tickqzmR8%HNxaQo+?jEy zE%ycTGk9np^FQEE>?=?H3p^msnO)nv=|lpHvG#b*&Y9isoH@6B)M(T+7=QfUrwJwdL?e2jg?d}pac%@gXtqr`Hv_9}eWMYJlnymg`qgNch`Fn^%4684 zwe+MM(lBNNm{|{eE_OV;pC1-5ci`fG1EE@5CtBMeIx!Blwn;5w{-(>PTkTTDl}Y8$ zYL_#vN)~{tWL%9b0$0trI%xp6ka1121Y9lSmdPpL7Bg;zoCdB=8`L_d$#<@jGjOMw zt*?=F;FdD(EI9|i|tH-I~pap%be;8w`n8Gn)3ho$yuaxLR8k;}lZlFf{Ni(CQz z47mzcYbB@e#$k^NU-)sfONH>GeeM}xnaRL8UU%W*c!nc=q&aXvu-zDTe(d_(_5zo4 zyX$g0><7Z{1=RK9#t-yq-)GboT~`31w&w-`Wj60o&)@SYmp5HP80CCx z2M-aMmXTPT279ao??2L51^)hedhgTDy*TJ~{m6be@M1H%|aW)p{JM%n5OlB(nQkuMyljK+{w zGKc3C7TlT$qC+w&`YiHv*fSZp6+K=WbrmKf?FpE4U3;Mm{iQL|UrF=sFx+%xO1&9w zN~(;y#OdGIZW#e>w+?})arA#puj#{!D&RTkc@Ph; z?ZzP$a3=dUp*UT~8AYP03@1$=L+@XdthLx;JffNq&a`+h{z zWT0}zdS1XTAXHi~FFqf}cMxMfR+_>OsT24iBqK%4*JjIC3iy;3oC(i|?ma}8^TGCp z7e|7{nArgx7tDvSjw2P)HMQtw0rhp&xvMu8G{6jtu`ILfWtbe#vc!00yfB3M5~}_P z=1|hC;m$7B5^l4!RuNmow(E6$`i$DljSdP0?Y_9iZ8x%A#@vA&@7aAn5*#N19J}b+ z+vE4)#bXS#VdeIHIa;M$La)i(@^~O9Ps(7cz9*7$KkB*OLCc(^czCVDB`h>zQj+4Y zXZo2KdJM-#yI}6j*FABKSg>UjC+2a&iPK;Z;WZYu-5PhUuaO*&4tHe0a z_(o*tn$UiMR`iKZ%yno=iM6Uh|746HijPWZ=QPHgIc@`CO(4)lHoxT10b(}#nz5M4 zILyKMV6<}MIOd{+fT-rvmhD4S zTs*Z`e)IpTa0$*fr*NyBo-o7DMTUt)p70p^Wp)e5>uR6FrDJNZ&eWdu5j!AQRC-ex zSW~5QTU)wx=VO0s_~j5mYIK~W<~X7J>QpuU0V~|C AYXATM literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/controller.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/controller.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d657479a46229dd7312ffe9bdfa27c02ca2dbd91 GIT binary patch literal 1983 zcmbVNL2uJA6t52->fo5&K~v^jjI(ri1Ye zy4Zk$B8q*~$6buk3q&=lpCGD#(YhKnc2T=91`KNBxY%d?kPlsDX4_e?BUojqiz$Mw zm})1et22Y@Uokak;l$_`rdE-bz$&s*;xp+2Smx9!(?zfrrpOAdf>oaSYIF&##i_4O zm%*yg29RvV<*hJ~JoJ6WT`faT%~jumE|e-GJVFFM8Fp#MqrC&hndLz5N51q1KC`?) zNGEWau)>}t4?JPHz9YnD*_ySz&~iC*By0`NHr%mT&EGLp%?# zQdkb9oI$|ODUJDBhxVt35A1yb>n}rx+Pg0I22$9sLK^u@*!{zgB>4`QyJu2u4u-Kwh!=R05XclH z67BTk=1k7b)UR@YGa2!~#Q;rPPT?A?j?jD1w}n3AQKE8ZtRizYv^8FYM|XugE`!$& zB1u4P$p~k?381)s9<%_fLWM!NjE~nd6wf37mEcW?nI#xEBJVnSwLGMnBe#|z zm&aY8rtVLYovSdJX(#bFZG^wWJv!7OSM|<#N0C&@pXy1baHV`)f;^-odX!3A_XL3h z4wx$$ohNH03s{B_Gf7(+)>+j5bAFw2=ITu;$7RaBo+R)JCz9bjlGPmIMvmobhGhqxk8!+AtYQ{P&SVk1Lw3b>ryb?5#DLMP{* z)36c3-3fc-3U0ML-cc8=;sM$I|k zPP?j#Sm5*-A#s_Iep2&bULoW|YTD~{3|RmCJr_UOhVd^7 zSC<9Cx3JZxK)At4Vx)u;g1niSsYNYfJT@l&E*0( zdzj7B2-Q~?1g!%2zzBm9Zcq~(5^jP+Q&_JpaH-wX25<1@pMOWW#U9U7Tk;6i+5bUY}#P>R-!&nxkg0Zs0Seo;Bf_#^;U*};` zozT6($e)~yj@fuLJsAwy)c?UBJ@@HuO+Of&4Cx0o<##8;;dt`%@$j0P!SUgEd^Di@ zwHr?lpA84o$3uFre(?QhJfU}L+QXy240#LSX!1UJ@>TF8PiALv=Ki>daw!5{i4W6I z6+&*r;BlOVauNLYC0CvN?=Qc2UHO@V6%|NJ%Fun_LpR7Fqk*!t9ky%@(w!g<(lMfBt=+&zwE-xXRZJMFeTtB zEPx0%3UNN&nT866Zd@og|CT;w;5kTrh?uP#Ujw zzF!;Cjg7=&;ioA@F_&3{L%Lab6_0g!J_KfIyny2D8^4o+yfq8!t-U1g;D_b%^^kjw zDkU6lU2lm_N(Z2GHvjyQXUbhr(7Wp?5$h%yF-lDOkc&KrR0Gvx9npvDZf_!=O0hT6OXsL9uX$cPSlwB%!rH1;^N5LRYB3luikQ<3Y4FIej-2Qg{LMB#(78iiH=YN(X5ul$Q-WJ&cqW z#(`41EpNHK6=!(_fqEEdFv1IiI2O_y$?RjqaUM42TndQofmRNJu2ncn!~^L7m7he` z;rHk4;HiI*#iL=AdT+*ICWX&S_#g?C7IF^#{U{CO*#Eru#6MOr|0)Z(e-z4Sq?P|V z<9RHUpM3bl3}qOfqB`uPl!qy!&+cekxQs<CE`~3>;RZ***1#j{XBNLQXZlFOC literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/ghost_controller.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/ghost_controller.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ad3cd192c993726f1a3a33238bfa308e8072fb67 GIT binary patch literal 1531 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 Ch&yut literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/input_mgr.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/input_mgr.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..133d69eb66f61392e1c41c97e1c67a9071bea5b9 GIT binary patch literal 5763 zcmcIoTW=f36`t8$UL=teMNwDV3Z1rT*u;+Sb{yMrV!Li)TL|nJP6?u0hO?G8;zgNV zB9`y`;hpfBxrW_O3X6m2A_vc%lZ+|GRGGG}?c9_UK zH5wU_y~pagJ9ik1^*W%9JRm zF%#l^L@A0A#!Tv!r$u>(R-TIbXGCSkY7}(;tf;E~V$?q;=Fwlm9v33Yf>>00OpCW8 z%92>d9%YQV7*P(1!)nZocqgJ95i1x|!I(=CZ6|bu`7R0*|r7nJlH5RePl0xzg@upg1Icgsh$FasC-T#(2q52O; z{U^mK^dAwYA?K?>{)67ez`wI5+a%lgqq>1~4as|m%xBN|bGFTFW1D?uqO?$EP-ao) zQ07ripqxZGg|dLMh_Zxo8f6*f49W`1S(H_jb13IgE}&c#4E*rb`jX6IzaZ0o)N*@) z)e=GmGj7lG?Tt=r(~-7I3ha9c7lVghMX1L+nqdv}-+;AVIsy38^?x!8c_8i}L zduv`Wy^o-VZM1~#`7M9o1(S(-Np-rOz0n$YjtC}(Ro&Hf$)HtNScR!up3`}_%VZ5g z`Om}a7n|4nosCCsulCVqyDy!l2%E=3DC1`HeYe+=o6X1P&NT0Pj%?oUw?y+^Te=&* z*SymggO1}hyX#-r?M}<{P*+m5yKD0J#%7SWAw$=4 zrnA!V2eOxPO{C6wB&E{VQ3+N03ENsB=Oj#WN#9#fxNkf&xA`_(V$b;lD5b@GYkg8) z;f#KM=4<{()-yhVONGK_S34%wx;=fK8%$LT4|KJ2Q&(?aK8pc$tC78X=h}@ECsp}T zRDKwhw@#d_XCE{T6umNs47UUGD##cxG`Iy$jQ?hhGB5G1lEzONoFvOnxdLK`(lsRS95MlHERfc@ ztO{eDdCNUqC_ej|`}~>loIT;&z;gl4LYP&yz@8Y}#yz%ct*W*6EG)72Z)Ce>PYNIRsBxo*RSxJzCA!Vg+6QQOvWuVh&-b5M#v!ZubI`dK%QXb_; zyU!PzsH}q%x3)kTJV$JzrD6Pl3nMhtppp(r#$ijB!Yw*m%26)p^QBifV8gwLjZ=pE z4iPR&rk&=dcSTm`FFv2O^m;Qbc5j+F4dw<6skqD$>o*ZN_lM3_3!A?f< z04WXo&|Rh$IAGMt#`mNCE>UYbQ>f3P`6r|#>Lczl&FC)<`k$`=^uH08;nkD?y*e5- zkHa1QhqdWMDRmz@lhHK}82YQkdGe-GI`ckJYdTZVQ^fWeQWE+Rud|O=4ApsLgR?fuH1%>2gguWD3+r!GZH*1KM8SR7dpY$``zhgOoEk zj8&p*oPt(d!h%0q{MM388i9mPNC}c~ZeTfu7h7fZoF9lhG6AaTI=@B7D za`9G>jRrm8W9d2gTDK7X0I!b;FOH$R)-VPNpD?-b33DO7{)_qzIu1G#&QsbqhAz*y zDjGUHb)SA|eo0MZmNIBAs#HJu%$+7V=b zL3$ZLAs4H4t~BIeixv9Yphr(;JD9ZXuKJS!^@44GK4^8q9{DOb3<~rIiQDcv{-eGK zOc#Il&^uYuyHO&nVv-&-lHLoFB5Fy&v7|s$QZy(jY?2g|NV>`8EM;V;lKi$Ly_4jm zBw4>C+Y78u`~8k2m6oJPlH{cjOQ2XInu3xvp5FEzX(|5nm^OHM!r+x`ITPpQOvwUO zd3ekVwE~qhS0G D1%#>r literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_action.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_action.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c286b7f0425ebad07c684e472bee3922fde9ac9b GIT binary patch literal 1208 zcmZ8g!EV$r5Vf6TH=FKuQK9035Z55l10W6vp#qgSPzutjmnf1IVpp3s$u4$QbgT5# zJ@E}3+GGEt{DiNZ`U{+xadz7jOEcq{IG#6e#`}XoKw$m8n#rGxkU!|Omjli=h<*x6 z5J7WN(1=nZm~e7dIFUoiMdUu7 znN}&DXfF?(Z4kW+N|J~Q5;4&ij&K(=a-=H;(i7e$4jCHVE&GG zUdKC=d^*m`Ctv63M9Ek*?z1A%l~gM?exH?zn#aelUdH(#frpVQ5 z;U1Z?EaBK7J2knWBckxqkSV;@thF+SRP`Zdi*3|8x?NCfAR1XG?Brexg=O?kVoZ9I z_z^g(#HX~Tf<7dttYYU*%@E2Z+q=GkGofocWK$_jV|*nO!Dla?hmHjm4O>9Dk_V<| zn}*x}0b{vC5RHWr7Eqtw0d0T00~%A_fPMfDOc1;u081-+&T49T+kg)M2S>t!RCp4I zL~_(7Djbs*b3Je|zU*K?Pc~cJ-3}n!VdoqgfOchiI0q#RDCZ{Nys&cv`#$I2XGz|C zQCO+z>nf?Tw2;+!B8-!jRl_Axp%6w3ngwY)i?0GjW7~Zic#Lj1AkBM$cVoKC0dJZ@ a?94Q+x-IqQKI6Y>FuuhqY|(wzXa4}o69ZBJ literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_body.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_body.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6cb1dd9a55b0cc6dd0f47d09661009113bb4e48d GIT binary patch literal 2966 zcmb7G-EQMV6rS-<;-pFX-|o_G*X)9p2(}XJ3M4>Km6Z@G6r|FdD3axRoUL2O4l@qB ziBbt^`xsobm%ZX8;0?H%Tdw*FTyf6WapJT>T}ShCj*n-~`Q|%ka#*id2|R!O+4ujb z5b_TS(~l0q4m7b19V3i}q)S_r5~eXd)Vg|0?;0(Gl5Yt!n0Zc^`9^D*taLz{d z82@g}1{`tO_YmswgL7=(KodLAjWlkJw8%=x1s%~#IwFoXA}2bG28bzXv%r0E^IK_m^AF)o*bNF>fFc;Xy^E6$NCeA$?hr;K{aa$+=* z*C#6}C65y~3F1gDsnv?QRb~9Ee;jzB@32ASb^}kyg&UfxGIXPtp)XA}G<9hRKkUeA zFLVb!cLMgB19iz2;cGDb+j;SM`$Zh~j)TblY2d}&Z?jZ<+I2vm$^ql7$k#jmGNU-5v?(<^9r6xD$WL32U~<9Mb@~9Y@UyW2>%b+hp-%f zfZY~$m_li%IEA!+1T95XzZKQn_e6H(4BG@@mSJaFqFv}C4T+9i!>yV|$~BCWBYUKQ zxHWY}yXjJb>_P6yH3eCryxhh~OpGVc1acWUY0=?EPLZ2y6!0rB1j#pM<{3@sg@y$g zIBLTS@Dyv2@|`1aaI%W6@1b@E+y>~LLQ7AR!fD#MM-$Q(LMyoS))4;&n~fnx+Hnj_ zS_rYzfA&cRb1SXbd9o;&S7uAI(@XelK#Q>4$IzxhzMqFQyFwwB0>p^Zh+L3MmHq{g z--lP=XYM`6Lmh+s0nBH8!V>lwv<&1L9d6|w-FgcZ+KS9Jpm3CDcrm|z@9$&m%p?1ZtKaKw~jJX0~M%v2Q*fyVn* zV8&XsTG8l|4$Wv_Uuu}pn++rHOR8e+H%qdd{mn?TDyspwR9e#}$)9f~tuNDfze2PW Jv^8x(`w!qgf0Y0L literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_boost.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_boost.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47b8931e933f00171e030637178d1d9ed135086a GIT binary patch literal 4237 zcmbVPTXWM!6kc6y%Z}qXAvY2(0?Nfe(gH2L(GJ&AhQvupn9iu4(FpIFsOaLZ!+im6$0PifA!cOV}$&J zjqImF<2Iz=JIE-Zl0#g{kR+_jj_fLi0(FI|j_MYSf-#~tzS(6QH?SwNI@FqtVx*a-XSvKYql#&|KJ7VJubSpB zJNNpFFzvScr{BtE&&5 z>=Isu6-4&$^ZQ@5?)y%6!}j#m&9={3i^k0b*9t<$_nWP|wrBCp*2|lpww?wcU-B*5 zT5EH=8wRaqfi7sdFMc!IjuiwfXuSY(%xAd2#qK6A!jhN*%rr@bKOs9rT><)Uqv9-( zctG7pcyv2JAXDjiR-lDHC0eAVox*F$D1z)lBGYJD$Vy4OLPvH~Lj#SAiKI$Lg+@7P z*XS5%R6yfWBB|4Hp)r!QC+IQIsDeg=jf#~g>6Fl@CGBZC0~%wXahcVH#wqu%bpgJH`2EBR@x?}yiI;qpj4qOKv{&c1f>RL8OjQjBT!bM z9EGw5X@3&BKLhu}296@kZcR_ann0e+y1I!V-J-QHtw&P?w7kLSg z?yAD*#eO;NHPSepwzDSv!-$$gq~(P!7w`yy=MI5N}iQmNQSSLA0HQu|FZ&3~iZP@6a4Mq(@`z7Q)N2 z_ALtfSUUwW3vnEHZYJPnSj%h&4gsHWO?a4LIean0%P@}P^N){Ub{4Xz3eTX>Zo4ep z@M)yjUKqc5@UbGE2pq3mjsbwHET(408 literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_collide.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_collide.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..01102695c71fe152624e7f04f5b48b694c98ca36 GIT binary patch literal 3030 zcmbVO&2Aev5GMCWTFa7u70YfC+lkW_Y8#_TiWF#r!mR_e=#Lt}$VCvaSTAXK6YZ`_ zu9DbLPWEH;;2ixP?HlyOYfpZKo;t%_NxPB?I9+2noY9c{_;EP&^IEM!;QRBBK5szp zZ#43s3C13Xd)BENPazh!Tm%nAN0kM=ksSG?s1U>Tq^4o_aFH

LP?19L? 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 F`u|`Lx-kF% literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_jump.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_jump.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a2aa24a00c7423048ccba8fd4ec419e2c4c86617 GIT binary patch literal 9032 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 literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_object_manager.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_object_manager.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8eda652e2f4576bb0bed4f041ada08a0f6d2e409 GIT binary patch literal 1774 zcmaJ>TW=dh6rP#A_!1{|OCc?S$d!1&54BpZ5mZ&dsgMW>A)%tIEUlKEiM@C)W@apE zD-lwgpV5cpvHt`9#J=+6e*nC|IkR5Zxrnvr?9AD-JLi1gcjn3JYMsFK$M0kDw@t{O zxLCd{SUiHEI$${AG$sl4Xu>>331{4jt;F_hO1>i8=FSP>&I{%_+&v)e$_(BiZI-)< zNHRIeow1H$HKXXI`O3cNM_Kw<%1nkBxqLaWcmzWYzzE_|PCOX-isqt0F_*#B_JCOR@pMDmh-U-s6FC=8@ zN}cx>5n93PXSy=z}<}z@#c4*Qbx@5uUnht^l5D|-Tdui@V4#T-QVdxzIWf;_vZJn z=lAV<_uH<-@8v6fq5Xc42tVQyQ_rhX1l%8g_(5LX7865)M9_gQ7V*3ia4v;XuZX-3 z-hW10pY^t~cr=L8*4`w{r0DTtc{d4^7P4ISzKqg9PI}Ki`Kb3qf&ZH<;Jt%TMkB3y zI~gCxLiLj2uYMQ@O2K>xi2Ip=+)oP3J0lQFI0&NDh0WCsFoabpqc&8{{&iWCuF>iG zC9XQ=opU^)*g)6?PjA7b?f?fw+0C~1MYr)f3w!|&v8)y(Hxe5j}&@9vRlfLw& zI5fBv2J_3Wl>s0fKajEsPK7&T=F>ZubG;BRG1CxDc_DK+x-irOFdSrLgKJ3Tt)h$} zQ5z|AqGr!2cq|YgMX_;qldO|trtMSbh?xSdU9-asQvz9Fm3dZ?=lm+=CEia<8Qa%K9-h}Te>>a{3Xq7hT^xgkO z=NzB-+Ja969)UnE&z88He*XO+QZ4w0*(egcbtto>wI76{o27?Q|L(&C7YCsLtwvcV z*)uqF5r)p}J@{(dF50A0w8`d@DzG0elqYY4?;RKlB}1&~#^r*Rp*~j;zOtbCZCI2F z1sXw}yz2WY z9u|IH_x;55EX*6e|I0Xt=T90+2RaH9p$8eyttiz+(-_qt76ugA!r4`jVMci1sGDH0 xx0^K>HlsJ(;%*?{ZM%78e$o_LM5uCN&Z>fxD?XlA9~4=`DGNKGUYe}I{sWK-m}&q3 literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_param.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_param.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e6675360e0b305e21d24d5b893e2a804bd0ac4b GIT binary patch literal 1588 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 literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/player_input.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/player_input.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42b584bd8243d8b7fd2ec2228847a2cf31a37189 GIT binary patch literal 2521 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 literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/race_config.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/race_config.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a92629dafb646a85472057321fb7f426a651d81 GIT binary patch literal 2634 zcmbUjU2hvjaCh&{-(UGCNh8q)%0~?}N(&STK~+eqAVRGup(8G5ikr6Z^_j-gxE(X7+67&JC5yS~IgdyEijCU+YK3VvfN0Dl!&7^tnm&hbNR{bS zS9E*wNIU(|@2GQ%T&nZCV&Crt52WnLCZ3EB2Nw4M)Ngt ztnM5&dr~xbw7k{zR4C+R+4$NAV~-k7?|#yFq=5fj&*P1~rt}X()p*$B{fT!+hfwX4wn-n1<}c8qy)TN>1rxh=@%>`yeOpQG&nFc}9OE0s8@}1frFy zb+B~W<uo3VZqc&K= z{zOh$V7NhjfpevD*16?42=_w?-vcRgMMHm7=BR z3}ceL$eJ}4qq_{CFxF@+gm^h-U_wBm>d?rkp?F`YshElKIoN70HC%~rM8XiPd4vs=a~BYY24n;4fXYSA4v1O_ z;2{plGaAwpc4{h*TT77U++HM5iEPNA9XW%A@7rQ^cYABK<#)vDPyJR)NTcr@!*KrB z4M1cEqHXEYSI}=|IC-06#cS!T>H5%oo<=(T9K_g)tSPGPj~Kzl99^S2G*8GVtyJ zM2SOJ=sX=+yx_XO^u12BBQeu;L4{uEH@hNi z_qewFAT;e!VyBbXZ6sE<#QKt$$r7_kqE98-7qi(^q-p8c9I^8&>{QSrGmKWU08YtH s;`y|RX|0;l>GA7q-je8vA?EprqJB~CQ#CsCMRYNE_&^sXcZC($zg#;j`v3p{ literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/race_config_player.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/race_config_player.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b02057664a28cdf19d49585e119d1a045796ce34 GIT binary patch literal 3587 zcmbVPTaVjR5cVav%_iyI+UC%i>Zw_o>J0TZeLA>%UAGnUkakzEQcKFS}@4I_ zgYk$vv_|$Y@ZtuZ@&^=L>*}C&4bZ`OrFBg(p@bTdKm~Ofs!&5+ffcBuuEHubP}iUd zEz~P;4AxNBVI4M5ufis5p>Du&IDxte+i((f3r@jl)W_fqoJG9`=iof*b=U!hdIK(? zzi-8B^By>aHa%!e=S@5%QGcKxXcqE{&l>yP2Lo3!$Frqm16#6T1+NF_2q=v8euIZ#1hE~yS0Sf_phdIw4Np3^%4BmXVaUw z$PD_K0`!^X@}Ox?Q_$q80xgcy-AOpCIcZWl0&yd2u${wvu7EjfyFBW(3~Ci86v#Q$ zwGdO}q5vt;#F-q*;{}vtQ$R=WP=V0G!7LCCk}Tz^EG0t`IU#eUe<@^<)ULAA0HRF47MAD409IiyW9iGY)od8=Q*Ig;GIMIz=aC9 z$u3oguDi%x6YuX#y*2SeEfkXuniQPS>npI6!gYO@Mmri zNlQ}US;S*2Z*n;Yd#3<9Z@nDu7~df-qDWyj_C`kotfiAza?pweEwx(?)bI14PSARx zEi7UCPmYGSQ8fE72lQfr!{QUmLH>gvXKULkuB^~5sJPY1+($WZCl`UEC6+_<=RBgc zkOl(N)1vTeOe&``_%w&DnD(=_%K`jr9$>4Fy^$&fv_ z{iJQh{{fNhF`=qP=kOnN;!suS?DtnsrWX-VNv6J>I&Zf0{p~{3Bv!laP3k^zXXe}YM%7GOs2qA<}ON#&r0_xIBWNBnPlg)G;J3Hfu zCJGl=@hLdKalZ$A312xy;=q{`?~Uzj(pW2XXXO|FX5O3qy}y3mZZ`?6zy6$xZ!3iS zjbMG*03N}k?}Olk(~ykmfKu`W;TE^g3AcZ-1{QaYNw2a59nzy|bu7lQngs~gmjmDt zJo;AKf{sm1P1U)Ntvp>y>DVZ4Tbi`r#~{|2fQl?2@6b2 zn9hT8G?}G!#$+TD#xRxIM9H4t+YaDSp@-F=L^4%TK*6L~Xo;m|V%mk51$hAx-6ucM zg#KdYh9rM zI~wmKv`Oa=N{Fv(Uym}TNVPz$DC$575nVxXU7-z@S5sWqz8*!4+y=$lVGM=H)}1el zWoKLM<_6t&N+P;#a~;z2HxD1XKZpd%+Kv1%HckZC9YWsu;Sw8S!=oFcDbFMRu*{X6 zwewpmA1tVf`z1cCDJ!hwjRAp$yej7R0C2jX4s4xL)#cVH(Fc)5NkV>x!SRA}dmly! zce(`1-C9^UIs4|;C05N6t9JP>2x$7<#~S)Ik#Y37Qn509(6h73Z)Dl}ioYB*^Td^u ze>FQgfcrG2ozMf?q4T>XPG*{0$yv?5U9i6F(?!;y^2;5FJhoI(?kx>jlF^AS3wymd zd;k`gWnMNy3eDFgw0M=!ogf}hL?SVathlv|T(?Z|?G2)bC2=dW+9JIwkSnI0{0FE* zdd&ne)2^OPyZ0X!!EKz3Vx6!_qF$YI6?1a9!S+rGTcg(RQB!ffHjZ@cC&tnyV`K9z zfcF+-XH!4SP85#K)Rs}Aum;o~iVg~NM%_h$1*YzycngK;$4h}Vt%^R;Xj-TB%C2Mn jDtqS5ocDWnTFbv;X5gFMvg^|NCmGvMu_4X3sAc^R4B7^| literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/race_config_settings.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/race_config_settings.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1075f516d462cc99f786038372d8e17da1d6cf23 GIT binary patch literal 4797 zcmcgw$#UC95Cyn^B)Cepyf1LJGLu-b<)s{#<1$Ur3M&$*kdTy2=%8TENMg**12BnH z&dL6a9GqkRBe~@ZaLtLokW;z`1PPi@MWsVPO>=qy@TR+`d#J5!R+ZrT^N%5WmXV~t zkqKTgU>?J;4}nmL${ndI6IsT2q!Z~zNfhQ$8tcTmaT4z;M3JR6iN>k&MxqLfzK)Uv z@Clj(J}LMl@F}VSuL?c|e41u}&j?-xK1*}J=Uzuhn&ul)u`q)7OGVjLx~$vh2QZ6O zdc*EWMsdVVmit3)vnqAt<>8=8TWB7<(C#q|`w|c)5t&LPLS+)A5fYuf5j*sBzkWmCl6o_6-xJlFOSzTtDu4kLqw`VU84tN6ItH7|6K$3Dye1!C9H$Dc_quodnR3S;4ASs$8DosHYRg$4;lBF4v zqgj%tIdFB}U7Wgl4V(z5+0@S*@$eLok#Kt)X9#qJh)1X$2`%RED2)Vi7=lvZDB&pK zC?V=vy`-<2oAv59B(dEv>!osqs77_8VjA^oX`N@$YH_35XjE&uY1FprdTFDg8*t~B zwT2;Xa1&elS9)znCn`K>yJS?%?FLD0ZarDAmT{ULPray;oNqPemC{bBzS048;nN{7W*N9RV0#Y!lutCh4UNO<2QuigsPR*Arcs5TVXuc>nd7}5Y z)OvLrqE)TzklZvC%$=%E(v8}B4Wj2UMy0gjGpZLip@^^78jTea!>`b|U4*6K_^-I3 z&Czi~FNN-Acl#Bp&Ak}lUaHY?yW z$n?;qV1@h`hK*azOF@pZIoMGUK89ic1!M}FM&3vy%Al(LD$^K^zlo7JQv|2b1aQy{ zXbNnSRHbS7PBB$zGc*g@^q9-hJaCyYSD*{PWm!&GF49xL+r|A-K3uDVO^ek|T zW9}S158NqsT3BA77lB(E>n_pDz?~U$SLjvX&Qc9reJxm+8sk#g!m{sQILA?jVPmy< zCBKqPXpnGs& zeWtanPKR;L>1zYt|FKOysYNMgw!N%l2Sf&%U(9BmU48{X1mcO+1bb7v*LF zqlXu#S>!Km*|)b zeivgN9xT}$?{<@%S=1cfUMWWSRS=MDOSEjWO-;^r-$kC9XzzltjW3sERX)5F0)Aq8 za?H4Oe9YKf1ZMsoO2=>uOdJKgW*UY#6Eyf7?wo?Y8Ui|KeRAAbWqsV(I_7a__waB6 z=MokMIyKRLF@reF%@fm;!^H;R!^KKC4>#WexZFAta5|tb%|N~q;^ctw9B8awBA>Bc z1@rlB1hX0Uu|7hd{vP#m8Pj+sCGyWL$AQzH1AQ^fx#@tu0yj?+A`EN5_+(f`+r19& z@l!U_8VrwgWYSkwXOM*z2jB8!utet%!pgQC);$teYNFkk0Tz~#6VsC*J503pE&kn| zXCrKG#XyiG1*0zU$E>sm;5&f3qd;kX5N zq#^!s!Ns0EzpK>NaBxJSRXo-91T9wC^C4(GyE&A{+D0G1(}UZ{O?chlzVF^V$KNLK zgYG%_H>4e;19~z8HEb&dj8B61@TP(78UC;jJAKFMXdX0d-5qOSYu9gUyM3-fi`MFf zT^xOgZodP>Ur-jz;J4PW=Y%aMHPL=QSqx@LSdvdn=azEp1QEM$oFJI&^9hm@4PqA$ zlwo+)sk$`*jEQnNBvAsk@17x!l`Nkk!eGHrZN{j1D-4+8srF_-g=Md2H|N4*0m8#m z2%wdt0j<0^9-tMyc4ELRri z)&UoIMIl&0^*to_k%-toz}Z72kC06M^We?IkI>7Y_zZ@PXUe3UjOSvxSQ0+?4IjaK zl%uU)%(#j1e#Z NkwT=P6!P$i{|hJf@LvD` literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/race_input_state.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/race_input_state.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..153dbfe978e1a7e35bb6d157e89026b69b27622f GIT binary patch literal 2541 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 O{u9-j5lOX&75)WP^(eal diff --git a/scripts/Modules/mkw_classes/__pycache__/ai_input.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/ai_input.cpython-38.pyc deleted file mode 100644 index b67497a4e8c8c2016caacb5b615b779115e2c7d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2903 zcmb7F%Wm676rCAT5=~38Ez5T6KAfgaTcwRxK~WS%5XUKs0*z6?$VL!A5E>?CEK%-| zMq@+SH2#2Y3v`hz^&jm&6tnHhztC0h8Hy6g%5_6v?mT!o_sp4l4<9!gE~Dp<-%o>I z9mf8`B>z}6xlb*ApNwRZ57>}*IcMK8DWrA5r1esCg|rV@r*g^3sl&DNU37AqJbJ47 zG%q|An%$=skI4kA%O&dy+KNj-TM63Ak}X-0)eGLWgNj@asf0ZhB=kjMJe13+;YK!pcj+Fe%);;?<*p2FJQ3-?D+qDF&3 zpe_jsJLuy!vIk?deQNP-GGn2fv54G+J>##$n7`&@=2>I*%%;9VeU=u){m7TS!@denlDPM1Bu@uH+#4SM-944NJ{EMq(7~d2Q zKYwo#*}IwdgzKsbl2aA+k=faU@r-$tPr_ai*RS~@QwY!zDYp%RFsE$7)e5~d=T6NU zrZqCl)M7z~iSzA+h|IkdKmfoD#9K6(UOT~f!N*+kE%ri;DWxXjK-u(uVi{Blr#DeM zmI0*K3NSqtJkiZLY|P7;ab}z)Wm42RF}brC_bht~;Bi*8eQeSsL)l3pK#&PKvA9J` z#1}G!$b^I1hC$BcxLcy>2DKRHW8CHEA1y>tO5_5RH{tQ}7Yd_5_LMvIHjQ<=ob-!0 ztCJ_Z^PJsUh_<|20q%9oy-Oj~J7hB6pxb5MkZ(KG=Dgirh-6`n)5f6tpuXuP! zkv|MPPrIHsG=)jyy663P>JQR4szn>n>&C> z0aH0hWFU#Lo5S6z;4O<-4seM*l;?kZBqcHV3CRX|0R_=fdwN6R<`W{Tj`} zUYT$f6)P?OR749(RVOs*-^Pg49N40Q`-Jx21ui4^!i7k+GHmlt3$$EUUC^aMb$yP7 z(xrS%Yj+WNrb=5`SaY{m#4ZTY)#Q+zU;c@x;5?I|&#(Y>DPuwAd`T@&!bXOskYsPf z!ySamtIVRI!nDZoqs1V}4@DesvQDHIRx2Ze8I9(xL%| v94B+}$k>kC8l|g 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 diff --git a/scripts/Modules/mkw_classes/__pycache__/competition_settings.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/competition_settings.cpython-38.pyc deleted file mode 100644 index 2ee01f9f9077bdb5eed7a0e58b0f82d1028e5459..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4127 zcmb_fTW=dh6yBRJacn0|)1(b8-IkWd6$A<;l#5ECMNm|tickqzmR8%HNxaQo+?jEy zE%ycTGk9np^FQEE>?=?H3p^msnO)nv=|lpHvG#b*&Y9isoH@6B)M(T+7=QfUrwJwdL?e2jg?d}pac%@gXtqr`Hv_9}eWMYJlnymg`qgNch`Fn^%4684 zwe+MM(lBNNm{|{eE_OV;pC1-5ci`fG1EE@5CtBMeIx!Blwn;5w{-(>PTkTTDl}Y8$ zYL_#vN)~{tWL%9b0$0trI%xp6ka1121Y9lSmdPpL7Bg;zoCdB=8`L_d$#<@jGjOMw zt*?=F;FdD(EI9|i|tH-I~pap%be;8w`n8Gn)3ho$yuaxLR8k;}lZlFf{Ni(CQz z47mzcYbB@e#$k^NU-)sfONH>GeeM}xnaRL8UU%W*c!nc=q&aXvu-zDTe(d_(_5zo4 zyX$g0><7Z{1=RK9#t-yq-)GboT~`31w&w-`Wj60o&)@SYmp5HP80CCx z2M-aMmXTPT279ao??2L51^)hedhgTDy*TJ~{m6be@M1H%|aW)p{JM%n5OlB(nQkuMyljK+{w zGKc3C7TlT$qC+w&`YiHv*fSZp6+K=WbrmKf?FpE4U3;Mm{iQL|UrF=sFx+%xO1&9w zN~(;y#OdGIZW#e>w+?})arA#puj#{!D&RTkc@Ph; z?ZzP$a3=dUp*UT~8AYP03@1$=L+@XdthLx;JffNq&a`+h{z zWT0}zdS1XTAXHi~FFqf}cMxMfR+_>OsT24iBqK%4*JjIC3iy;3oC(i|?ma}8^TGCp z7e|7{nArgx7tDvSjw2P)HMQtw0rhp&xvMu8G{6jtu`ILfWtbe#vc!00yfB3M5~}_P z=1|hC;m$7B5^l4!RuNmow(E6$`i$DljSdP0?Y_9iZ8x%A#@vA&@7aAn5*#N19J}b+ z+vE4)#bXS#VdeIHIa;M$La)i(@^~O9Ps(7cz9*7$KkB*OLCc(^czCVDB`h>zQj+4Y zXZo2KdJM-#yI}6j*FABKSg>UjC+2a&iPK;Z;WZYu-5PhUuaO*&4tHe0a z_(o*tn$UiMR`iKZ%yno=iM6Uh|746HijPWZ=QPHgIc@`CO(4)lHoxT10b(}#nz5M4 zILyKMV6<}MIOd{+fT-rvmhD4S zTs*Z`e)IpTa0$*fr*NyBo-o7DMTUt)p70p^Wp)e5>uR6FrDJNZ&eWdu5j!AQRC-ex zSW~5QTU)wx=VO0s_~j5mYIK~W<~X7J>QpuU0V~|C AYXATM diff --git a/scripts/Modules/mkw_classes/__pycache__/controller.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/controller.cpython-38.pyc deleted file mode 100644 index d657479a46229dd7312ffe9bdfa27c02ca2dbd91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1983 zcmbVNL2uJA6t52->fo5&K~v^jjI(ri1Ye zy4Zk$B8q*~$6buk3q&=lpCGD#(YhKnc2T=91`KNBxY%d?kPlsDX4_e?BUojqiz$Mw zm})1et22Y@Uokak;l$_`rdE-bz$&s*;xp+2Smx9!(?zfrrpOAdf>oaSYIF&##i_4O zm%*yg29RvV<*hJ~JoJ6WT`faT%~jumE|e-GJVFFM8Fp#MqrC&hndLz5N51q1KC`?) zNGEWau)>}t4?JPHz9YnD*_ySz&~iC*By0`NHr%mT&EGLp%?# zQdkb9oI$|ODUJDBhxVt35A1yb>n}rx+Pg0I22$9sLK^u@*!{zgB>4`QyJu2u4u-Kwh!=R05XclH z67BTk=1k7b)UR@YGa2!~#Q;rPPT?A?j?jD1w}n3AQKE8ZtRizYv^8FYM|XugE`!$& zB1u4P$p~k?381)s9<%_fLWM!NjE~nd6wf37mEcW?nI#xEBJVnSwLGMnBe#|z zm&aY8rtVLYovSdJX(#bFZG^wWJv!7OSM|<#N0C&@pXy1baHV`)f;^-odX!3A_XL3h z4wx$$ohNH03s{B_Gf7(+)>+j5bAFw2=ITu;$7RaBo+R)JCz9bjlGPmIMvmobhGhqxk8!+AtYQ{P&SVk1Lw3b>ryb?5#DLMP{* z)36c3-3fc-3U0ML-cc8=;sM$I|k zPP?j#Sm5*-A#s_Iep2&bULoW|YTD~{3|RmCJr_UOhVd^7 zSC<9Cx3JZxK)At4Vx)u;g1niSsYNYfJT@l&E*0( zdzj7B2-Q~?1g!%2zzBm9Zcq~(5^jP+Q&_JpaH-wX25<1@pMOWW#U9U7Tk;6i+5bUY}#P>R-!&nxkg0Zs0Seo;Bf_#^;U*};` zozT6($e)~yj@fuLJsAwy)c?UBJ@@HuO+Of&4Cx0o<##8;;dt`%@$j0P!SUgEd^Di@ zwHr?lpA84o$3uFre(?QhJfU}L+QXy240#LSX!1UJ@>TF8PiALv=Ki>daw!5{i4W6I z6+&*r;BlOVauNLYC0CvN?=Qc2UHO@V6%|NJ%Fun_LpR7Fqk*!t9ky%@(w!g<(lMfBt=+&zwE-xXRZJMFeTtB zEPx0%3UNN&nT866Zd@og|CT;w;5kTrh?uP#Ujw zzF!;Cjg7=&;ioA@F_&3{L%Lab6_0g!J_KfIyny2D8^4o+yfq8!t-U1g;D_b%^^kjw zDkU6lU2lm_N(Z2GHvjyQXUbhr(7Wp?5$h%yF-lDOkc&KrR0Gvx9npvDZf_!=O0hT6OXsL9uX$cPSlwB%!rH1;^N5LRYB3luikQ<3Y4FIej-2Qg{LMB#(78iiH=YN(X5ul$Q-WJ&cqW z#(`41EpNHK6=!(_fqEEdFv1IiI2O_y$?RjqaUM42TndQofmRNJu2ncn!~^L7m7he` z;rHk4;HiI*#iL=AdT+*ICWX&S_#g?C7IF^#{U{CO*#Eru#6MOr|0)Z(e-z4Sq?P|V z<9RHUpM3bl3}qOfqB`uPl!qy!&+cekxQs<CE`~3>;RZ***1#j{XBNLQXZlFOC diff --git a/scripts/Modules/mkw_classes/__pycache__/ghost_controller.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/ghost_controller.cpython-38.pyc deleted file mode 100644 index ad3cd192c993726f1a3a33238bfa308e8072fb67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1531 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 Ch&yut diff --git a/scripts/Modules/mkw_classes/__pycache__/input_mgr.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/input_mgr.cpython-38.pyc deleted file mode 100644 index 133d69eb66f61392e1c41c97e1c67a9071bea5b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5763 zcmcIoTW=f36`t8$UL=teMNwDV3Z1rT*u;+Sb{yMrV!Li)TL|nJP6?u0hO?G8;zgNV zB9`y`;hpfBxrW_O3X6m2A_vc%lZ+|GRGGG}?c9_UK zH5wU_y~pagJ9ik1^*W%9JRm zF%#l^L@A0A#!Tv!r$u>(R-TIbXGCSkY7}(;tf;E~V$?q;=Fwlm9v33Yf>>00OpCW8 z%92>d9%YQV7*P(1!)nZocqgJ95i1x|!I(=CZ6|bu`7R0*|r7nJlH5RePl0xzg@upg1Icgsh$FasC-T#(2q52O; z{U^mK^dAwYA?K?>{)67ez`wI5+a%lgqq>1~4as|m%xBN|bGFTFW1D?uqO?$EP-ao) zQ07ripqxZGg|dLMh_Zxo8f6*f49W`1S(H_jb13IgE}&c#4E*rb`jX6IzaZ0o)N*@) z)e=GmGj7lG?Tt=r(~-7I3ha9c7lVghMX1L+nqdv}-+;AVIsy38^?x!8c_8i}L zduv`Wy^o-VZM1~#`7M9o1(S(-Np-rOz0n$YjtC}(Ro&Hf$)HtNScR!up3`}_%VZ5g z`Om}a7n|4nosCCsulCVqyDy!l2%E=3DC1`HeYe+=o6X1P&NT0Pj%?oUw?y+^Te=&* z*SymggO1}hyX#-r?M}<{P*+m5yKD0J#%7SWAw$=4 zrnA!V2eOxPO{C6wB&E{VQ3+N03ENsB=Oj#WN#9#fxNkf&xA`_(V$b;lD5b@GYkg8) z;f#KM=4<{()-yhVONGK_S34%wx;=fK8%$LT4|KJ2Q&(?aK8pc$tC78X=h}@ECsp}T zRDKwhw@#d_XCE{T6umNs47UUGD##cxG`Iy$jQ?hhGB5G1lEzONoFvOnxdLK`(lsRS95MlHERfc@ ztO{eDdCNUqC_ej|`}~>loIT;&z;gl4LYP&yz@8Y}#yz%ct*W*6EG)72Z)Ce>PYNIRsBxo*RSxJzCA!Vg+6QQOvWuVh&-b5M#v!ZubI`dK%QXb_; zyU!PzsH}q%x3)kTJV$JzrD6Pl3nMhtppp(r#$ijB!Yw*m%26)p^QBifV8gwLjZ=pE z4iPR&rk&=dcSTm`FFv2O^m;Qbc5j+F4dw<6skqD$>o*ZN_lM3_3!A?f< z04WXo&|Rh$IAGMt#`mNCE>UYbQ>f3P`6r|#>Lczl&FC)<`k$`=^uH08;nkD?y*e5- zkHa1QhqdWMDRmz@lhHK}82YQkdGe-GI`ckJYdTZVQ^fWeQWE+Rud|O=4ApsLgR?fuH1%>2gguWD3+r!GZH*1KM8SR7dpY$``zhgOoEk zj8&p*oPt(d!h%0q{MM388i9mPNC}c~ZeTfu7h7fZoF9lhG6AaTI=@B7D za`9G>jRrm8W9d2gTDK7X0I!b;FOH$R)-VPNpD?-b33DO7{)_qzIu1G#&QsbqhAz*y zDjGUHb)SA|eo0MZmNIBAs#HJu%$+7V=b zL3$ZLAs4H4t~BIeixv9Yphr(;JD9ZXuKJS!^@44GK4^8q9{DOb3<~rIiQDcv{-eGK zOc#Il&^uYuyHO&nVv-&-lHLoFB5Fy&v7|s$QZy(jY?2g|NV>`8EM;V;lKi$Ly_4jm zBw4>C+Y78u`~8k2m6oJPlH{cjOQ2XInu3xvp5FEzX(|5nm^OHM!r+x`ITPpQOvwUO zd3ekVwE~qhS0G D1%#>r diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_action.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_action.cpython-38.pyc deleted file mode 100644 index c286b7f0425ebad07c684e472bee3922fde9ac9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1208 zcmZ8g!EV$r5Vf6TH=FKuQK9035Z55l10W6vp#qgSPzutjmnf1IVpp3s$u4$QbgT5# zJ@E}3+GGEt{DiNZ`U{+xadz7jOEcq{IG#6e#`}XoKw$m8n#rGxkU!|Omjli=h<*x6 z5J7WN(1=nZm~e7dIFUoiMdUu7 znN}&DXfF?(Z4kW+N|J~Q5;4&ij&K(=a-=H;(i7e$4jCHVE&GG zUdKC=d^*m`Ctv63M9Ek*?z1A%l~gM?exH?zn#aelUdH(#frpVQ5 z;U1Z?EaBK7J2knWBckxqkSV;@thF+SRP`Zdi*3|8x?NCfAR1XG?Brexg=O?kVoZ9I z_z^g(#HX~Tf<7dttYYU*%@E2Z+q=GkGofocWK$_jV|*nO!Dla?hmHjm4O>9Dk_V<| zn}*x}0b{vC5RHWr7Eqtw0d0T00~%A_fPMfDOc1;u081-+&T49T+kg)M2S>t!RCp4I zL~_(7Djbs*b3Je|zU*K?Pc~cJ-3}n!VdoqgfOchiI0q#RDCZ{Nys&cv`#$I2XGz|C zQCO+z>nf?Tw2;+!B8-!jRl_Axp%6w3ngwY)i?0GjW7~Zic#Lj1AkBM$cVoKC0dJZ@ a?94Q+x-IqQKI6Y>FuuhqY|(wzXa4}o69ZBJ diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_body.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_body.cpython-38.pyc deleted file mode 100644 index 6cb1dd9a55b0cc6dd0f47d09661009113bb4e48d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2966 zcmb7G-EQMV6rS-<;-pFX-|o_G*X)9p2(}XJ3M4>Km6Z@G6r|FdD3axRoUL2O4l@qB ziBbt^`xsobm%ZX8;0?H%Tdw*FTyf6WapJT>T}ShCj*n-~`Q|%ka#*id2|R!O+4ujb z5b_TS(~l0q4m7b19V3i}q)S_r5~eXd)Vg|0?;0(Gl5Yt!n0Zc^`9^D*taLz{d z82@g}1{`tO_YmswgL7=(KodLAjWlkJw8%=x1s%~#IwFoXA}2bG28bzXv%r0E^IK_m^AF)o*bNF>fFc;Xy^E6$NCeA$?hr;K{aa$+=* z*C#6}C65y~3F1gDsnv?QRb~9Ee;jzB@32ASb^}kyg&UfxGIXPtp)XA}G<9hRKkUeA zFLVb!cLMgB19iz2;cGDb+j;SM`$Zh~j)TblY2d}&Z?jZ<+I2vm$^ql7$k#jmGNU-5v?(<^9r6xD$WL32U~<9Mb@~9Y@UyW2>%b+hp-%f zfZY~$m_li%IEA!+1T95XzZKQn_e6H(4BG@@mSJaFqFv}C4T+9i!>yV|$~BCWBYUKQ zxHWY}yXjJb>_P6yH3eCryxhh~OpGVc1acWUY0=?EPLZ2y6!0rB1j#pM<{3@sg@y$g zIBLTS@Dyv2@|`1aaI%W6@1b@E+y>~LLQ7AR!fD#MM-$Q(LMyoS))4;&n~fnx+Hnj_ zS_rYzfA&cRb1SXbd9o;&S7uAI(@XelK#Q>4$IzxhzMqFQyFwwB0>p^Zh+L3MmHq{g z--lP=XYM`6Lmh+s0nBH8!V>lwv<&1L9d6|w-FgcZ+KS9Jpm3CDcrm|z@9$&m%p?1ZtKaKw~jJX0~M%v2Q*fyVn* zV8&XsTG8l|4$Wv_Uuu}pn++rHOR8e+H%qdd{mn?TDyspwR9e#}$)9f~tuNDfze2PW Jv^8x(`w!qgf0Y0L diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_boost.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_boost.cpython-38.pyc deleted file mode 100644 index 47b8931e933f00171e030637178d1d9ed135086a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4237 zcmbVPTXWM!6kc6y%Z}qXAvY2(0?Nfe(gH2L(GJ&AhQvupn9iu4(FpIFsOaLZ!+im6$0PifA!cOV}$&J zjqImF<2Iz=JIE-Zl0#g{kR+_jj_fLi0(FI|j_MYSf-#~tzS(6QH?SwNI@FqtVx*a-XSvKYql#&|KJ7VJubSpB zJNNpFFzvScr{BtE&&5 z>=Isu6-4&$^ZQ@5?)y%6!}j#m&9={3i^k0b*9t<$_nWP|wrBCp*2|lpww?wcU-B*5 zT5EH=8wRaqfi7sdFMc!IjuiwfXuSY(%xAd2#qK6A!jhN*%rr@bKOs9rT><)Uqv9-( zctG7pcyv2JAXDjiR-lDHC0eAVox*F$D1z)lBGYJD$Vy4OLPvH~Lj#SAiKI$Lg+@7P z*XS5%R6yfWBB|4Hp)r!QC+IQIsDeg=jf#~g>6Fl@CGBZC0~%wXahcVH#wqu%bpgJH`2EBR@x?}yiI;qpj4qOKv{&c1f>RL8OjQjBT!bM z9EGw5X@3&BKLhu}296@kZcR_ann0e+y1I!V-J-QHtw&P?w7kLSg z?yAD*#eO;NHPSepwzDSv!-$$gq~(P!7w`yy=MI5N}iQmNQSSLA0HQu|FZ&3~iZP@6a4Mq(@`z7Q)N2 z_ALtfSUUwW3vnEHZYJPnSj%h&4gsHWO?a4LIean0%P@}P^N){Ub{4Xz3eTX>Zo4ep z@M)yjUKqc5@UbGE2pq3mjsbwHET(408 diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_collide.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_collide.cpython-38.pyc deleted file mode 100644 index 01102695c71fe152624e7f04f5b48b694c98ca36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3030 zcmbVO&2Aev5GMCWTFa7u70YfC+lkW_Y8#_TiWF#r!mR_e=#Lt}$VCvaSTAXK6YZ`_ zu9DbLPWEH;;2ixP?HlyOYfpZKo;t%_NxPB?I9+2noY9c{_;EP&^IEM!;QRBBK5szp zZ#43s3C13Xd)BENPazh!Tm%nAN0kM=ksSG?s1U>Tq^4o_aFH

    LP?19L? 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 F`u|`Lx-kF% diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_jump.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_jump.cpython-38.pyc deleted file mode 100644 index a2aa24a00c7423048ccba8fd4ec419e2c4c86617..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9032 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 diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_object_manager.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_object_manager.cpython-38.pyc deleted file mode 100644 index 8eda652e2f4576bb0bed4f041ada08a0f6d2e409..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1774 zcmaJ>TW=dh6rP#A_!1{|OCc?S$d!1&54BpZ5mZ&dsgMW>A)%tIEUlKEiM@C)W@apE zD-lwgpV5cpvHt`9#J=+6e*nC|IkR5Zxrnvr?9AD-JLi1gcjn3JYMsFK$M0kDw@t{O zxLCd{SUiHEI$${AG$sl4Xu>>331{4jt;F_hO1>i8=FSP>&I{%_+&v)e$_(BiZI-)< zNHRIeow1H$HKXXI`O3cNM_Kw<%1nkBxqLaWcmzWYzzE_|PCOX-isqt0F_*#B_JCOR@pMDmh-U-s6FC=8@ zN}cx>5n93PXSy=z}<}z@#c4*Qbx@5uUnht^l5D|-Tdui@V4#T-QVdxzIWf;_vZJn z=lAV<_uH<-@8v6fq5Xc42tVQyQ_rhX1l%8g_(5LX7865)M9_gQ7V*3ia4v;XuZX-3 z-hW10pY^t~cr=L8*4`w{r0DTtc{d4^7P4ISzKqg9PI}Ki`Kb3qf&ZH<;Jt%TMkB3y zI~gCxLiLj2uYMQ@O2K>xi2Ip=+)oP3J0lQFI0&NDh0WCsFoabpqc&8{{&iWCuF>iG zC9XQ=opU^)*g)6?PjA7b?f?fw+0C~1MYr)f3w!|&v8)y(Hxe5j}&@9vRlfLw& zI5fBv2J_3Wl>s0fKajEsPK7&T=F>ZubG;BRG1CxDc_DK+x-irOFdSrLgKJ3Tt)h$} zQ5z|AqGr!2cq|YgMX_;qldO|trtMSbh?xSdU9-asQvz9Fm3dZ?=lm+=CEia<8Qa%K9-h}Te>>a{3Xq7hT^xgkO z=NzB-+Ja969)UnE&z88He*XO+QZ4w0*(egcbtto>wI76{o27?Q|L(&C7YCsLtwvcV z*)uqF5r)p}J@{(dF50A0w8`d@DzG0elqYY4?;RKlB}1&~#^r*Rp*~j;zOtbCZCI2F z1sXw}yz2WY z9u|IH_x;55EX*6e|I0Xt=T90+2RaH9p$8eyttiz+(-_qt76ugA!r4`jVMci1sGDH0 xx0^K>HlsJ(;%*?{ZM%78e$o_LM5uCN&Z>fxD?XlA9~4=`DGNKGUYe}I{sWK-m}&q3 diff --git a/scripts/Modules/mkw_classes/__pycache__/kart_param.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/kart_param.cpython-38.pyc deleted file mode 100644 index 3e6675360e0b305e21d24d5b893e2a804bd0ac4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1588 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 diff --git a/scripts/Modules/mkw_classes/__pycache__/player_input.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/player_input.cpython-38.pyc deleted file mode 100644 index 42b584bd8243d8b7fd2ec2228847a2cf31a37189..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2521 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 diff --git a/scripts/Modules/mkw_classes/__pycache__/race_config.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/race_config.cpython-38.pyc deleted file mode 100644 index 0a92629dafb646a85472057321fb7f426a651d81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2634 zcmbUjU2hvjaCh&{-(UGCNh8q)%0~?}N(&STK~+eqAVRGup(8G5ikr6Z^_j-gxE(X7+67&JC5yS~IgdyEijCU+YK3VvfN0Dl!&7^tnm&hbNR{bS zS9E*wNIU(|@2GQ%T&nZCV&Crt52WnLCZ3EB2Nw4M)Ngt ztnM5&dr~xbw7k{zR4C+R+4$NAV~-k7?|#yFq=5fj&*P1~rt}X()p*$B{fT!+hfwX4wn-n1<}c8qy)TN>1rxh=@%>`yeOpQG&nFc}9OE0s8@}1frFy zb+B~W<uo3VZqc&K= z{zOh$V7NhjfpevD*16?42=_w?-vcRgMMHm7=BR z3}ceL$eJ}4qq_{CFxF@+gm^h-U_wBm>d?rkp?F`YshElKIoN70HC%~rM8XiPd4vs=a~BYY24n;4fXYSA4v1O_ z;2{plGaAwpc4{h*TT77U++HM5iEPNA9XW%A@7rQ^cYABK<#)vDPyJR)NTcr@!*KrB z4M1cEqHXEYSI}=|IC-06#cS!T>H5%oo<=(T9K_g)tSPGPj~Kzl99^S2G*8GVtyJ zM2SOJ=sX=+yx_XO^u12BBQeu;L4{uEH@hNi z_qewFAT;e!VyBbXZ6sE<#QKt$$r7_kqE98-7qi(^q-p8c9I^8&>{QSrGmKWU08YtH s;`y|RX|0;l>GA7q-je8vA?EprqJB~CQ#CsCMRYNE_&^sXcZC($zg#;j`v3p{ diff --git a/scripts/Modules/mkw_classes/__pycache__/race_config_player.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/race_config_player.cpython-38.pyc deleted file mode 100644 index b02057664a28cdf19d49585e119d1a045796ce34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3587 zcmbVPTaVjR5cVav%_iyI+UC%i>Zw_o>J0TZeLA>%UAGnUkakzEQcKFS}@4I_ zgYk$vv_|$Y@ZtuZ@&^=L>*}C&4bZ`OrFBg(p@bTdKm~Ofs!&5+ffcBuuEHubP}iUd zEz~P;4AxNBVI4M5ufis5p>Du&IDxte+i((f3r@jl)W_fqoJG9`=iof*b=U!hdIK(? zzi-8B^By>aHa%!e=S@5%QGcKxXcqE{&l>yP2Lo3!$Frqm16#6T1+NF_2q=v8euIZ#1hE~yS0Sf_phdIw4Np3^%4BmXVaUw z$PD_K0`!^X@}Ox?Q_$q80xgcy-AOpCIcZWl0&yd2u${wvu7EjfyFBW(3~Ci86v#Q$ zwGdO}q5vt;#F-q*;{}vtQ$R=WP=V0G!7LCCk}Tz^EG0t`IU#eUe<@^<)ULAA0HRF47MAD409IiyW9iGY)od8=Q*Ig;GIMIz=aC9 z$u3oguDi%x6YuX#y*2SeEfkXuniQPS>npI6!gYO@Mmri zNlQ}US;S*2Z*n;Yd#3<9Z@nDu7~df-qDWyj_C`kotfiAza?pweEwx(?)bI14PSARx zEi7UCPmYGSQ8fE72lQfr!{QUmLH>gvXKULkuB^~5sJPY1+($WZCl`UEC6+_<=RBgc zkOl(N)1vTeOe&``_%w&DnD(=_%K`jr9$>4Fy^$&fv_ z{iJQh{{fNhF`=qP=kOnN;!suS?DtnsrWX-VNv6J>I&Zf0{p~{3Bv!laP3k^zXXe}YM%7GOs2qA<}ON#&r0_xIBWNBnPlg)G;J3Hfu zCJGl=@hLdKalZ$A312xy;=q{`?~Uzj(pW2XXXO|FX5O3qy}y3mZZ`?6zy6$xZ!3iS zjbMG*03N}k?}Olk(~ykmfKu`W;TE^g3AcZ-1{QaYNw2a59nzy|bu7lQngs~gmjmDt zJo;AKf{sm1P1U)Ntvp>y>DVZ4Tbi`r#~{|2fQl?2@6b2 zn9hT8G?}G!#$+TD#xRxIM9H4t+YaDSp@-F=L^4%TK*6L~Xo;m|V%mk51$hAx-6ucM zg#KdYh9rM zI~wmKv`Oa=N{Fv(Uym}TNVPz$DC$575nVxXU7-z@S5sWqz8*!4+y=$lVGM=H)}1el zWoKLM<_6t&N+P;#a~;z2HxD1XKZpd%+Kv1%HckZC9YWsu;Sw8S!=oFcDbFMRu*{X6 zwewpmA1tVf`z1cCDJ!hwjRAp$yej7R0C2jX4s4xL)#cVH(Fc)5NkV>x!SRA}dmly! zce(`1-C9^UIs4|;C05N6t9JP>2x$7<#~S)Ik#Y37Qn509(6h73Z)Dl}ioYB*^Td^u ze>FQgfcrG2ozMf?q4T>XPG*{0$yv?5U9i6F(?!;y^2;5FJhoI(?kx>jlF^AS3wymd zd;k`gWnMNy3eDFgw0M=!ogf}hL?SVathlv|T(?Z|?G2)bC2=dW+9JIwkSnI0{0FE* zdd&ne)2^OPyZ0X!!EKz3Vx6!_qF$YI6?1a9!S+rGTcg(RQB!ffHjZ@cC&tnyV`K9z zfcF+-XH!4SP85#K)Rs}Aum;o~iVg~NM%_h$1*YzycngK;$4h}Vt%^R;Xj-TB%C2Mn jDtqS5ocDWnTFbv;X5gFMvg^|NCmGvMu_4X3sAc^R4B7^| diff --git a/scripts/Modules/mkw_classes/__pycache__/race_config_settings.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/race_config_settings.cpython-38.pyc deleted file mode 100644 index 1075f516d462cc99f786038372d8e17da1d6cf23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4797 zcmcgw$#UC95Cyn^B)Cepyf1LJGLu-b<)s{#<1$Ur3M&$*kdTy2=%8TENMg**12BnH z&dL6a9GqkRBe~@ZaLtLokW;z`1PPi@MWsVPO>=qy@TR+`d#J5!R+ZrT^N%5WmXV~t zkqKTgU>?J;4}nmL${ndI6IsT2q!Z~zNfhQ$8tcTmaT4z;M3JR6iN>k&MxqLfzK)Uv z@Clj(J}LMl@F}VSuL?c|e41u}&j?-xK1*}J=Uzuhn&ul)u`q)7OGVjLx~$vh2QZ6O zdc*EWMsdVVmit3)vnqAt<>8=8TWB7<(C#q|`w|c)5t&LPLS+)A5fYuf5j*sBzkWmCl6o_6-xJlFOSzTtDu4kLqw`VU84tN6ItH7|6K$3Dye1!C9H$Dc_quodnR3S;4ASs$8DosHYRg$4;lBF4v zqgj%tIdFB}U7Wgl4V(z5+0@S*@$eLok#Kt)X9#qJh)1X$2`%RED2)Vi7=lvZDB&pK zC?V=vy`-<2oAv59B(dEv>!osqs77_8VjA^oX`N@$YH_35XjE&uY1FprdTFDg8*t~B zwT2;Xa1&elS9)znCn`K>yJS?%?FLD0ZarDAmT{ULPray;oNqPemC{bBzS048;nN{7W*N9RV0#Y!lutCh4UNO<2QuigsPR*Arcs5TVXuc>nd7}5Y z)OvLrqE)TzklZvC%$=%E(v8}B4Wj2UMy0gjGpZLip@^^78jTea!>`b|U4*6K_^-I3 z&Czi~FNN-Acl#Bp&Ak}lUaHY?yW z$n?;qV1@h`hK*azOF@pZIoMGUK89ic1!M}FM&3vy%Al(LD$^K^zlo7JQv|2b1aQy{ zXbNnSRHbS7PBB$zGc*g@^q9-hJaCyYSD*{PWm!&GF49xL+r|A-K3uDVO^ek|T zW9}S158NqsT3BA77lB(E>n_pDz?~U$SLjvX&Qc9reJxm+8sk#g!m{sQILA?jVPmy< zCBKqPXpnGs& zeWtanPKR;L>1zYt|FKOysYNMgw!N%l2Sf&%U(9BmU48{X1mcO+1bb7v*LF zqlXu#S>!Km*|)b zeivgN9xT}$?{<@%S=1cfUMWWSRS=MDOSEjWO-;^r-$kC9XzzltjW3sERX)5F0)Aq8 za?H4Oe9YKf1ZMsoO2=>uOdJKgW*UY#6Eyf7?wo?Y8Ui|KeRAAbWqsV(I_7a__waB6 z=MokMIyKRLF@reF%@fm;!^H;R!^KKC4>#WexZFAta5|tb%|N~q;^ctw9B8awBA>Bc z1@rlB1hX0Uu|7hd{vP#m8Pj+sCGyWL$AQzH1AQ^fx#@tu0yj?+A`EN5_+(f`+r19& z@l!U_8VrwgWYSkwXOM*z2jB8!utet%!pgQC);$teYNFkk0Tz~#6VsC*J503pE&kn| zXCrKG#XyiG1*0zU$E>sm;5&f3qd;kX5N zq#^!s!Ns0EzpK>NaBxJSRXo-91T9wC^C4(GyE&A{+D0G1(}UZ{O?chlzVF^V$KNLK zgYG%_H>4e;19~z8HEb&dj8B61@TP(78UC;jJAKFMXdX0d-5qOSYu9gUyM3-fi`MFf zT^xOgZodP>Ur-jz;J4PW=Y%aMHPL=QSqx@LSdvdn=azEp1QEM$oFJI&^9hm@4PqA$ zlwo+)sk$`*jEQnNBvAsk@17x!l`Nkk!eGHrZN{j1D-4+8srF_-g=Md2H|N4*0m8#m z2%wdt0j<0^9-tMyc4ELRri z)&UoIMIl&0^*to_k%-toz}Z72kC06M^We?IkI>7Y_zZ@PXUe3UjOSvxSQ0+?4IjaK zl%uU)%(#j1e#Z NkwT=P6!P$i{|hJf@LvD` diff --git a/scripts/Modules/mkw_classes/__pycache__/race_input_state.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/race_input_state.cpython-38.pyc deleted file mode 100644 index 153dbfe978e1a7e35bb6d157e89026b69b27622f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2541 zcmbVO&u`pB6rQoYYwypbZAeOmkOc^35k#UwRfP~r(jbHywkX>O$y#Y-JQKx@*Is7q zwp)c$bKuIILpkREfPcbQPWvx#;=Qq*>~6PE?X2dlzkP4UpWplDd5=4tCV}zSpPBfu zPRQQ~W`_x27pA%oh7(RBGNK-(gd5z9jFIV?lzdCL#cLOY*IpW)1*pz#KsKNncLt=_ zn8Iq(qj`NKMv0tEX#uULBDfo%Z*~{}c44Y*FoJlL6VKq38yCbgx#?Nlf_-aVo!32^ z+n!V0Bk$~IX_~})K^i8p3UHfh;5E(%Fcm)WIXx!~9%w)=X&;Eyp88QHdPZ(35uHdI zLN1AHz}G*cgD-~%Ni;qUWA}$ikVrA)1^jH}t5nDe4)?>@my_Z1dtVHX75sjf_kkx;|Y*)tYIzEW^4{XnoV9%m_2sh^6S@g#Q`{1T>&K{<%h4?$mS&OO>r z6(X@bQ;eBfXdE;yn0~K;8^!)eFqStN8|k~lb(^uDGe0UkvIVg@-OK5IP7gijh#mKj z2j3ic-NQ$Z9STJ31KXM9dh>psazxsoG#1>X;TSKHBqIRgvm0hW`rYx~fo7 zP!d$u5;bo9PI-;jFD$PvY>jO00CGe_qXusRYL>nhZv$$TsKdK}+9g`!>wr2Xy1{P( z>Xzsh-vG46-vMQA=G`MG!gpAM0hZv!Z;wxf6s`|*ltpPcj)WV=P@Xst%1ut(^fXki zuAsXeg=Zp~xKA>bx}ZPGJRzrPt9_wGiMeo zk)V7ROvP!d^wZ8+%D>Szhb6SSg?D(jGsHlDk<+2o(fva)70ozL#%o1*s z|KT?I_$|3jR^xVaky|5`Z>p&Fd@{#pv7$O;H73{|=Cag5?Y@ysAqucryb7&-72aJgDU$lJ{$E(DOkxx`Q@*S0AKB+3#6&7cSErlga{b?+p!g~ix;yw9P%cogtUdg6+(XW!# zoJ7T})cCp+U$skRE2}#CY<0D=tCBS4q~{7nbGlYtEG;?x&FA@|SuOBV&FP#omrAwj zEax>|q#or&eOy7d4x%uXyvmfk#?*X_X?dN+@^Pl;6D$sG5>ARbpSKIP$*CESquAA` zAS80x4ku|C)k4KI3@2?El^RCU*{=|mq50XD3Yo!{sgxLK|hh^V(4ZBFIwvp(W*6uX2^&1qn zvaRkYn~I@rDj&x{bav2OR(%1RVk$1|0$2 z4>}4u26_PWAm|~`anQq{8PFr3M?sH)PJkWe<^9mti5Hg(rK+PB z7~@WNscP8Gy;T!dGVcq1;fb0z#%pR$FjhRl$twfLg zLS&aJCU5u;cqeckp#o3|lVL-5yKTB?DXQqcW5njO31p25YoY8p~#B zY1uZ4%Vu%K>5t&KIAUg~N26R@LnCfl^}<@!a)zV%6arXgd9k@U@;+J;*neR!wqbPB zsy>B6QPWydeg5CZpyVjdHoCz$32xe}yc*c{$ZycbD165Z9$eq?MA;Z;D$^+3Vev2Z zC#tP&$2QeXWmMTwA7J(Bimk7t`P-^Oe|G#c^;=3+`v}1j1sJ(<41Lx2T~akgJf3^t zKYnrDf2_atDk@}kCoy+>diLC;pm#m`o=0z;o6IIS_2+ahnYOV+VM&Q`QXNjfEHGpB zJlw%8b6o^RoW2L4mR4d;2YD3JvO?(c0aTelw#fY`fK@|Spefo{39VP{Q8)Tz2!(TM zL5&oerY^=%G*H__=s2P@(ArVwm1kOxccR8KUAQ_ivQV8o{h5B>#Azp07#vJV^Pt_+X!xGdX zUQzkPrn(*5QC1Y|bQPx*TmMY8r%&s?f0u2hh>u!!+6oZx6u~K*cvGS?p<&t zaB*1LRDE#a?}FfB$;3Ta6WbjER@H};p;>NRck;BM1WPFHejRQU}0WKyI$TF?oCmBT@nt{S;8*`F=^v zrHo8pAXbb*XB=ZaM3&JBIL$y0Z6Ne*bRIzHJH!YfbO^jf(!zJ#<1Gm7tw>-Ik!4GZ zsBI7Bd8d@SjGo0j??lc#o8EglMYtZP!wm{9XX8$?5u3Yy2*g5*#sN+J^n#0y{7Y*z^$^@fbTArurV^V@XfBVU z)u+hvY7ER`WKV6ZN`^rKq18h$8ZpEYp2Gki0dEVrxk6i^jaCkg{Pcp*l3U>97aB+& z+Vhwhh2{iW{uo(C^SEpfd-m1_q9xLG+0|73h2^*|fgmq|rRd+^sLd_n$(o zUm?r52F{A2WgCcc(%}uKMPZR>Q1e(Ik1cgaq$n>K@!6c~XswTMJg;@&I@$(K?8_sBAm0YeilTY&S` zq_9a2pxx^mS3&+5!mRF|L|POR*0+HgVKiR??+?gLG+V9D)e4pT6tKQ%@aSS`2bWDN zI<8A%xn25p_h%`2D;jFKM2y0Xu15ZdEaP@4IO*j0q^rml3}a|6raFwFdr#u($-hTR z%G=KqVuTFv40wM+ZbBAV4Z;9hK5K91_s!s=L0jSL58katVRsG<|4iB@P<|yc<(E6{)GIRlr zBl>9*zaNmIvf(`?MhL%2@cu^n_@1xzmLN(cH1Sg#Akwt8g4h?hgO7sm0^0o@S%xog zC=T?{CU9G%oDAF#i4g+sJb3>gO?=>555_@dP}xsyKt_wM6|((NKSo3$cM;A1g)AeN zk^Nm%M{NT5BT`ic@F&Cw0r)C-|0ace00Sogv2r7ILK{B?aD4tX%nTZ0KWpx`)ZPo4 z7tc>M!n)zspKPKay^O~HL6#v67(r_{djm>0MDjlD-?je~f~*`u|BM*krSi}590v9h zc>hCg0((rJX8~-4W@zE30Ic6+Guh~w!B11AYAtiOT-YeQvwH)5wOZ>~^iNw+;J%Iy zzCw1vbq^+iJu$kgy#fB(P5N_ESGL$Mh!L{b*T75QH*^`yNfPV!A$hvR>w@Ovn}j~eu~D@ftt~Ef4WD#>B=5BtSMSvLyUiD;|%wXVJpG+%pS^h@@hu zRNhHBm6Q)Y;2cs#RSr4jkW&s$RSr4jXa!BR-duDg%wZN(>6{)8G>3{z2 z`TFa>|L*DDTRlB#34ee3s;=KVCP{y%jQcN!%tc(rTS%D1F(S(4&u|xg_#QmO?)DIFd`TZA(%ny@~pyjBF*!db!Hi zaTlAb)XSSPsUuc=xmeb@)wQVQ^&476yRGv)m2m%&=|x<|6cSy^$xO;cn4F8UNG`^r zxj2jE5-grevIO3m%xz;Sym^~7M3v503e|;@wyyIlCGEDssiB(@O2l1??)oWFD7lCv zn@L+KRjp`cT~)2Ls+Oy)UZVSMRsE!{mFy?EM*dbGh!>`K8M@v)Q@J%P5gtTE4lkfSZxaH*ZkM>oZHs z>P&Y2#?12k&FnLY4*-%#{#~0rzcO1b)z*p?Wnn#E<@ySl;_2oX{_83%`sNWckiqDl4cmXvBJTWTDJLDYl5!n+B#3--3eSq zFOrlTbN!2Ffv$?f?jjW!i@Lh%V{)7)=rBFTG(FDZU&t)Ml277~;NoA zU{Q3iPq2f+V!M-{WQSle3X40AW{PEm#h8;n%#Off2Q2P7nxpKPuo!pp)9g4bcEY0M zXil(`!eW<`KgCYNVmBs2o_wQ5`BA( z%?pc+lYfi74U5CDF!UqB;ySw_ERHhM(PY`pC-K}d*wh`(0((c;Ogs5SwuD-a!{VOv z=4EzESe$V3@3Qw`aS|5y9nJgf17UH>$>-RIus98i2aaZieN$MRaq=HA6&A0s2tw1k zHQkh>svL+*jx3#mZv zgWL~!0CEEIAmk+EA;>An4CGG`|0YOz93tR8Q6SeS_Dm9Lg-CEYAmD^{OhF&1Wqc=x~>@|gXL$HB610YDuf9EpFsfCJqG)BRdDkr- zaNVeB_bXPiaWf#)tD0$I_A+R`u)00DeqoTWbFPD3yv^!zXY6Xhl6aJC+;~gf&AUob zrd5h^q7>cOomt>CtLCfq3Z^To$D6e~Q|Jt}SWyc_ZkSe|Uy&B53pATsaa-6WiLOGi zQZ&|76RQfV&#xGA7+nMZ1(onTEU1O>ZV<=2H zYQq({ij~`Hv)2agH@bD1s1-BxQo%~wHPKk$+c8dBs{lSo!v^aURA{OyEnSRhB$7NF zNy#t!|8RVG=ES~vV!AGDwjLV?)m=t+98U!W6g9nEvD(*tL298IFiA)}q9!1Q^)96NokUfiJ zIbnSk6X8a@k<;5~l%U`0=Q2?N%^DR>;DxPnyvIG-t-&y!~zLiyXk;fa_<7DnSZ%+BF*)3`TCqbqcwC}J zxO{Y9uo;{pVr#nE0=>%w-0iRLLD8W1ecb!$-3c8zd5hl3ATB}g^T2gVFz+HL?;`O~ zX^;ID0kjAR^VK~lNQ2K!=fNOsA7ZL)3zX&v>IVeX8TKEN!Z+-9Lr31*qVaGLPZ*5> zP@Ph_NwF(P<%nxE*h{1^A{CUSUT_n6AP78A*A{48A((C&KO%*X#=X#yVT;D8AR7N* zx0~mI)G>)Pi3CYJ;A(i-axsk3{ix|TB0SYM9JRRZWHlaazl z<^kwx1g1%5NDvZaJ_k>y+;N(l_&gF%=bSPbghnh2V5ovjxIv zu=6DX=Qvi06h6W-(ESuwi?EPMOc2%GBq>8zwEB5B0 zQZy8t6pCF`QswpOw9@)pUZdxRQsdQCZMC$nR4Yj8hF++bltPs&R~Hl<73yzp(h%q0 zLIOHw>0WH@4B0PiZq$Z#)md17h0E@$nAjr=*?;iWw1v+44#A=o)H7$g{*)9xuYU!) zzu>YvD2hF@c6$!b14La!!{##8q#y~~e>9^{W3&VL*xrNOJO{f>+_eWuC#zy3l9OBU z?^5D}OJ)9w%kAeOJEUUkIY3zx;TURgZ!wC!QEW02GX4Y)GckLc(TC_U9{CZy3fgpXmZ_+?u`U9OQ ztD1qdT2b(6q=<6}&!Ct$4;jju#@VqvT%RdsRnbcKwRJ;T)s@p!$ne-_aiV`-X$&PA zdq%xXZ`VpCj4b_Lv067oG564$Do*Ru0>LSTPAa(ahRB^%j<~cLaU{4&q;0;Agx^Av zNm#uzXe_5ApgGQ~+~rinx9v~FHvDZC!ioa5Gi2#|&~?tC)=X{<`IRC2i04ty-*6eU z_bVmFvA>*>2jzz$W7$_*-t7bAluaMFfJ}QIfXm9F@0*+X&AyMCv5ly3-|wLcwDJcK zuB~!0pacOid%ygL^!!JZ{FoBoFnbNUf8a7wNTfKm4J~UI8T`$YsgU#MY2E~sVUfW; znSe_>ji3{X9@u)KgRdiFuCP1IeaBa#6NB22UL+^_Coa3C;=}?mFl3SBe}yNyPzN?U zaThY~=wcsW-~zHpq_b*&_{6n_@?4dUCrZdFt z`$e1>ZC)cZG~s!^OnX~rfW)~UF8T9+nsDv&ppfv`s>H)8anod#wpN3zB3}O-55zRr zSciN@3LkH8Ko^5wwxV>%FcqH-ZLkD-_(gmz5DH2>e2v=65YG{57;zU-FhzJ>>$#8( zt&rNbz~C60d;?8d`=1hhL6|BSosL)1xi6U8+$7#$ab{S8^ zrplhSAA>{p*ejm_zQkNP^~{YE?~R?~w&bTpV6QgfX@*UwOw=M~{UbDW*D?QS!-he;pQdOA* zlUU4dXsR~8_k`>PQijo4;-gQoS)e?Dp8O6&K>C!EKI8Yf!OctBHv*GC2rO>>MtOx- zFRjihLJlAMIzPqx@lLtjza0iauf*HkEfAT?NviZyPd_-#eY(#W?9|RE>eX4i_D>3 zP`ZXPlVChl&iUAz!A2o}DQrM~O~ej}f6ktMId~e6&qrZ&^3%+ZMKIv0`tig|WFQvm z;F~b=#BA{L@#ll*3D|##JwE99B0QJL;K!Ix$3Zffy!h4i$6k`aw}7*76FiJZ=QCxy zKnMikR$$vir#;N0=Z_V zHwdC@>Lk%S3EV~5BJj97{Or@Np)sje4$~FEQ0=Xy3Yu4;W84^0f)NwuAccoH{IxYo zp&*bYgUAG=HdGb}fl7MC@FD=0_u&r!iK(KYivu(;v5f{KU=>phY&a>w$O(1m#Yv86 z^TjB^x--K%i~ob+>5^e_2x!#K%Ej75Y6BcGup+4s@(@;5C}F=Hr4M28>msEmU|3N4 zHhiyAS_j)Z&~r+Ub3B_0ND0)P2}J_LTQFqFnNqi1DmR;m!%Or&!YpLteh#!Wzl891 zw7rY4kcI_S@1X&US32m++ywO_=s8tKIfC^fT7q$BqPB4FHKN*uvb%{Uob?GpEYP%< zgDlK0p}QSP$bX5X574keQX6cK5yA3`9_0J4J|n=kenO#oqWoX6h1EUsCV}fJ$8{(A zF@W!e>;5wJ#_2y|50+64d=Nr^639`^l@Uf#mq%p{$FU~`RyKj9MCfe98z3;h1Rk)^ z#A6hN$aIW42k=40o*ctqQ^#hsV?eiB=IW^H@@dyn)$FlL%QMk$M_ROV?v^_!`>Qmx MuaObWVuLlam$=tHS?VX~Q)l*kzB~VEE4pZRc4zj+GryggUEY?2pBjzXp}Zm%l)N;M zSH&XA%R~8+s44l}K)x(iP(DAj>WcV4$t#23UlmtTzA%(u6W5izI*_l4b(Aj(j&N;- zr8jQJfdMi*Ee#Qf8_lVIfnC19p~s=n<6bUcXZ)P?n5FgD4?0o^1^bOvb= z=`7L`(lXLH!FJgN->J_7VIG>TecSay!xjR2za)kH53gvQYSivoj$Dx8;UC=i-x$7a;hFGY9Hf7@E$Xe zb--asXa`KLdKyQYe&GURR~Sodg`Mz#pK0gpMC)lij%&TAW2BlpN`Ig9^+|CbYZa^O z;oMWi5hx(O1n@ycvog1Cgfo$2u6P&b{JlNtV7z90#hBZRcj0u@YbuOO*rlqF+A1%p za~SbnY0RW+#_OHJO;p_;3YP zAgHnR7*~n)a1(_WxQ=_Eq{$8#cvhD@FC7(FqaexsbV?_OR65Xv8S=To-uh;%O#q3;*_wU8AxTd0L;?+9|)+%b<#-4`t zRwfdr>zj@*mFe+R$BXV$6lBu;J~HAor`kM<^8)f-U{7$qov|*7(}^xmkJx_){3|kt zawLX!SwWF`piF|4od23kPDSc^#^`Z9mw=Lz0X~b&Q)&K)7$af2h`iU>6ZmdsEJ@(Y zxK+oeC|8*plO=i!dGuVf!lGq$)Z+=~CCmD;Yqui_P>Byq_{I#}R>ukUeG%%e7pNBi z(6tS8A%@0xzTXDAT!6|rP-z6JNI+Q*lv_Z733U2Ecmg?+a!$FaZdiIRQ&;~G6?n0z z@rthTYQB=gnK@@n9@YK0Q#Zr>;O!V)lT5wAqRTUZa`Wx~p)RrBT+O_1%HIzEax1L?Oj?$X!;nV%9wWm`BF~+bY+S7WD%TSmz zK4Su7zyr?7o4v6%L7YU!1mnmAX_*vylBhsuriijwnayr+L9f+usX+zBI4Y2-AdZqm zK`?>*otDZ3Q5Hl}f-+`^De!1Na4OHJg4ABEd_G8yYEcr}f4P@$ZQ z_tMA|3KnAcOlJ{H!w*{z!hM7Kojj7^ZVY--nDAvT%S4$lJ$f%}5V$WW1)Gy;ws;)Z{t zx`RjmE~0dfXlC8vIZXyo3&0g*OL#aF;t;#YjFntf!Cuqh7M{E)V-2tAFdTHLE3+t7 zLR4KLQro|{?+I~SM#AZtHPk`QOv=Y@CsGopZmX@7!pZl#1 gk3Op(4&16!&zNmht6gbwe=}#Za^biUM6QAk9TEKxiV3sL|I* zYOMqBwA_c@duWgOKh}Rj*Pik(^tAVADUnidC`^MiANlm&Pmhn!-d|nq5oquK$;IC- zLO!5SZ#D=IpsQOjaKdRsV(L*!xW(<9j{$VUA_WR zr<8iU4^p?327DEy711+R*7y*lekrZ<4Uh(6)$DEZEs)muHt=662K!H+CRwicw68^A z)o^i+{SkD9;hWJJVGtX5&N_Pi{6I+I`q1M%(qR?}H%yfFlRzjpow)iSRBjOYO1U?q z@K8ik_eHL>8>Cq%)M%&Yp10?z8%O~FuAiJ)x$TN%lFC4UDPO}N+`x|_A>9m&f|C$* zwQ_yVrBG^T_k

    3L~p1JEZ#uE5vF!^ii=kJBhSfTw<)2B{QdJ{P}>eWiu0 z#PP#0@#S><>h6!@eFf{!QlF3a0vTpnjekjb9tky$4_`9#axl+B7Gek)yuB7X*|g{~ zSP3;_ZH%1>s(o~+9_gJ*19L|Toy#P^+^Je4_-n8_BQGHIm&u=WW)5KY)PYrr4n~&j z!dKD%E!R3t6q90NUV1*@(G{I?uMdL4CkgG*qwNM#sqzU2rmabWZJ3;MX!_Qg(RU>c zf}GeUK94ZD&Zop8HttcG^hl|42 zGCNxhn#~4{QCN=S3Ycw#tTPYUPbHVP%|iwELJP<&1bnp!as8swfC4$UTYlt1#`<$-bTPrZ}{YgI~DeN@*Pgng9?XEwd2ita|UDsXpyMy6t2r(uXrHr|_7k38Ve0S!~ zVElM|Ja6Fl_rLA%ua*ttU!-*YQc!N<3a+7G1~V&0)hwE(!7P@lSk+W9RZSPu)l4x{ z%@(t!ao1pJmU&^Y%y(9Cgk>KYg^>f)H40{wt@5fb8V4q+=_vh_m)4`qZ+G0V9A&C* zxPCRted&tuw$B>nC#1(Lo0A@sNElQ80N8IFfcpQVr=gM-1os}N*Nm!-#w(yy>}c&x(XzOr0p?@A9_>DSnM@Hh#NO=WqX zeIPwfDg8tC5j;-AXiaPV{5ZS z!?yXOd%Eu63Vx4b-x9fftCkCmm*&3t%G@^`Yv1@y3Nj6ufy_dVK;|GvA@h(&Ajcrb zAtxXwA*UdZLQX@@K+ZzWK^}vghg^VMggg$p1i1`(0&;~JkBrymW?@z2fGEn8wq36l zrCr8EH0#xZ(0Lkn%&BiT0(2~z)D5v)$*)wr!1HU)6XEaFqek)H7eX1{&9aN(Cf;U4}Cf(8wl#WR#+Dj6I1 zlu^lilNHXQ45;9&kc!d)uau*Fz2Y{wa6Gmvj$pLBHpJTy|E+F(xV7O|>f2t;e%L7a zf^V@{y;yaFkc+0eb=#}CqOrAm?dsO!0QP&n%eEesgjWxPt@}RPsqkQ{`t38PRB?j< z_sy}!)U;ZwH=>;5cr`C{oGe}*te`N=Su1BA_P4j7&CRuD1GE$f9`1-*iKc7wNB6CX zO3RX*pvEinks(H*7A!FW5l!jn3Z^LFfn+5v-XWEmSiluv!7vPKZ%)S}CtVkWu3Ulj zum#~cG6gf|jptTqy-e*}1nRZ5d60(B>$IH2@_mBd73BnXnX|KgrI3=yqFEiXBX~KQ zX$lItv9U2$s0* zw3L@b<0Kr<;p$7H*3J+#(k@B7i=s*0`()6ln}F>it{BG)uuo~L*A7O>-3d6ef8DT!TdiN(b}Qw& zSLg8r4Awd)*n?W7VV8YjGcTZR)0(~E^T4k8q3xE-ycF7MtzA2iT=ax-R^Nsug>D|~ zJSK)ZW|OURq&L(>$(yapckzy{aM5_t!*vX{UlN$s)H$m|kyEEHo&iI&dGIwM>0z&( zlDfCcNhB_!g%aVGB*r_N!&6dsdqZ&f1p)3H`uE774SiZAJ;Efpq+LzojC5LQs1K}x zDP;txhf*!CbiXi(*CjMlr9O1Uh2y*We^iFagkU=B&IDw+8MedvAl|I-8 zW;i5NJq%BGzaoj#6R7x%pm%V(qR+DKW`#@{g=TwHw!roJIKHwcbm=VxTl#+?n@_qf{QZb=6q*-1b#FhBpK_xJJ>pPwZ0 za~c)?NZ|VM6IUOCpPv()PJVtt28|#382%GMXwA!HeiBd&%+J5+{k{CeM@dQioJECK z1g;-HarGhi*&;Zd{QQax8b4=X`!hlK5q=U-49w4e=>0wXjLKuRBzn%n|1X5CgPxw# zB3XL~b{qoJ$&O0~jh%C_{gn{3*g2j!yCeuqQxm?MIQJs?e-P*B^baTO+;O73<5cC5 zA@0W<2mgIjiJyoI027VjD=73zRUU5pEJ}H`Fg_R?$3sDa3tc1wkM3 zLVhXIm#U!8K|vo#f<8tB?Y9N(a|LZ01?|$r5*4(i5VSZ8S{4O`PtckoR;V~hg-r$J z2SGDb&`c0C76k=e5bqtakWrC`hji3Lc!DB|oSC1t%;^-a%tRVxR+jPo$V66JGAQHw z*xp%YC+KOXMcvDj!_7i28c|2L@d2WuMiL@BH9|P$@mG7`w7^EW>v2SG&~T7LXv|u$ F{s;J>P{sfN diff --git a/scripts/Modules/mkw_classes/__pycache__/vehicle_physics.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/vehicle_physics.cpython-38.pyc deleted file mode 100644 index e63880b935b0415dd00d6ffa62be8245b6093c2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11317 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 From 3215e2664f0495b7bae07c9d88e3d0e6004724ae Mon Sep 17 00:00:00 2001 From: xi <104683822+ximk@users.noreply.github.com> Date: Tue, 26 Dec 2023 17:42:45 -0500 Subject: [PATCH 08/12] Appease linter --- scripts/Modules/agc_lib.py | 18 +++++++++--------- scripts/Modules/mkw_utils.py | 12 ++++++------ scripts/RMC/Adv. Ghost Comp/Load_data.py | 6 +++--- scripts/RMC/Adv. Ghost Comp/Save_to_file.py | 2 +- scripts/RMC/_draw_info_display.py | 4 ++-- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/scripts/Modules/agc_lib.py b/scripts/Modules/agc_lib.py index 40152e6..92fd1f6 100644 --- a/scripts/Modules/agc_lib.py +++ b/scripts/Modules/agc_lib.py @@ -1,6 +1,6 @@ from dolphin import gui, memory -from .mkw_classes import quatf, vec3 -from .mkw_classes import VehiclePhysics, KartMove, RaceConfig, Timer, RaceManagerPlayer +from .mkw_classes import vec3 +from .mkw_classes import VehiclePhysics, KartMove, RaceConfig, RaceManagerPlayer import math class FrameData: @@ -198,8 +198,8 @@ def frame_to_file(filename, readid): def get_framedata(readid): return FrameData(get_addr(readid)) -def timerdata_to_file(filename, rid): - timerdata = TimerData(readid = rid) +def timerdata_to_file(filename, read_id): + timerdata = TimerData(read_id) file = open(filename, 'a') if file is None : gui.add_osd_message("Error : could not create the data file") @@ -207,8 +207,8 @@ def timerdata_to_file(filename, rid): file.write(str(timerdata)) file.close() -def get_timerdata(rid): - return TimerData(readid = rid) +def get_timerdata(read_id): + return TimerData(read_id) def file_to_framedatalist(filename): datalist = [] @@ -234,9 +234,9 @@ def file_to_framedatalist(filename): return metadata, datalist, timerdata, rkg_metadata -def framedatalist_to_file(filename, datalist, rid): - metadata = get_metadata(rid) - timerdata = get_timerdata(rid) +def framedatalist_to_file(filename, datalist, read_id): + metadata = get_metadata(read_id) + timerdata = get_timerdata(read_id) file = open(filename, 'w') if file is None : gui.add_osd_message("Error : could not create the data file") diff --git a/scripts/Modules/mkw_utils.py b/scripts/Modules/mkw_utils.py index 0ee0c80..89461c9 100644 --- a/scripts/Modules/mkw_utils.py +++ b/scripts/Modules/mkw_utils.py @@ -304,17 +304,17 @@ def get_time_difference_racecompletion(history): inf = float('inf') if curframe.prc>=curframe.grc: if curframe.grc>lastframe.prc: - l = [history.get_older_frame(k).prc for k in range(history.size)] + length = [history.get_older_frame(k).prc for k in range(history.size)] i = find_index(curframe.grc, l) - t = i + (curframe.grc - l[i])/ (l[i+1] - l[i]) - return -t + time = i + (curframe.grc - length[i])/ (length[i+1] - length[i]) + return -time return -inf else: if curframe.prc>lastframe.grc: - l =[history.get_older_frame(k).grc for k in range(history.size)] + length = [history.get_older_frame(k).grc for k in range(history.size)] i = find_index(curframe.prc, l) - t = i + (curframe.prc - l[i])/ (l[i+1] - l[i]) - return t + time = i + (curframe.prc - length[i])/ (length[i+1] - length[i]) + return time return inf diff --git a/scripts/RMC/Adv. Ghost Comp/Load_data.py b/scripts/RMC/Adv. Ghost Comp/Load_data.py index a73bdf0..54cbc3b 100644 --- a/scripts/RMC/Adv. Ghost Comp/Load_data.py +++ b/scripts/RMC/Adv. Ghost Comp/Load_data.py @@ -1,4 +1,4 @@ -from dolphin import event, gui, utils +from dolphin import event, utils import Modules.agc_lib as lib from Modules.mkw_classes import RaceManager, RaceState import Modules.mkw_utils as mkw_utils @@ -19,7 +19,7 @@ def main(): metadata, framedatalist, timerdata, rkg_metadata = lib.file_to_framedatalist(filename) - if not timerdata is None: + if timerdata is not None: timerdata.add_delay(delay) @@ -34,7 +34,7 @@ def on_frame_advance(): delayed_frame = floor(delay)+frame decimal_delay = delay - floor(delay) - if not metadata is None: + if metadata is not None: metadata.write(lib.get_metadata_addr(1)) if lib.is_rkg(): diff --git a/scripts/RMC/Adv. Ghost Comp/Save_to_file.py b/scripts/RMC/Adv. Ghost Comp/Save_to_file.py index fe6e5ba..0718c68 100644 --- a/scripts/RMC/Adv. Ghost Comp/Save_to_file.py +++ b/scripts/RMC/Adv. Ghost Comp/Save_to_file.py @@ -1,4 +1,4 @@ -from dolphin import event, gui, utils +from dolphin import event, utils import Modules.agc_lib as lib from Modules.mkw_classes import RaceManager, RaceState import Modules.mkw_utils as mkw_utils diff --git a/scripts/RMC/_draw_info_display.py b/scripts/RMC/_draw_info_display.py index 7e7f89e..6fb098a 100644 --- a/scripts/RMC/_draw_info_display.py +++ b/scripts/RMC/_draw_info_display.py @@ -3,11 +3,11 @@ import math import os -from Modules.mkw_classes.common import SurfaceProperties, eulerAngle +from Modules.mkw_classes.common import SurfaceProperties from Modules.mkw_utils import History import Modules.mkw_utils as mkw_utils -from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState, TimerManager +from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState from Modules.mkw_classes import RaceConfig, RaceConfigScenario, RaceConfigSettings from Modules.mkw_classes import KartObject, KartMove, KartSettings, KartBody from Modules.mkw_classes import VehicleDynamics, VehiclePhysics, KartBoost, KartJump From 5eea673c1d348ed1b8c99ffe5bd7c2657b4cfc20 Mon Sep 17 00:00:00 2001 From: xi <104683822+ximk@users.noreply.github.com> Date: Tue, 26 Dec 2023 17:59:15 -0500 Subject: [PATCH 09/12] Update scripts/RMC/Adv. Ghost Comp/Load_data.py --- scripts/RMC/Adv. Ghost Comp/Load_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/RMC/Adv. Ghost Comp/Load_data.py b/scripts/RMC/Adv. Ghost Comp/Load_data.py index 54cbc3b..8de974a 100644 --- a/scripts/RMC/Adv. Ghost Comp/Load_data.py +++ b/scripts/RMC/Adv. Ghost Comp/Load_data.py @@ -38,7 +38,7 @@ def on_frame_advance(): metadata.write(lib.get_metadata_addr(1)) if lib.is_rkg(): - if not rkg_metadata is None: + if rkg_metadata is not None: rkg_metadata.write(lib.get_rkg_metadata_addr()) #if not timerdata is None: #timerdata.write_rkg() From d7ddb7067d2e44f794d70fcae2baa5f484ec895a Mon Sep 17 00:00:00 2001 From: xi <104683822+ximk@users.noreply.github.com> Date: Tue, 26 Dec 2023 17:42:45 -0500 Subject: [PATCH 10/12] Appease linter --- scripts/Modules/agc_lib.py | 215 +++++++++++--------- scripts/Modules/mkw_utils.py | 101 +++++---- scripts/RMC/Adv. Ghost Comp/Load_data.py | 6 +- scripts/RMC/Adv. Ghost Comp/Save_to_file.py | 2 +- scripts/RMC/_draw_info_display.py | 4 +- 5 files changed, 187 insertions(+), 141 deletions(-) diff --git a/scripts/Modules/agc_lib.py b/scripts/Modules/agc_lib.py index 40152e6..e814100 100644 --- a/scripts/Modules/agc_lib.py +++ b/scripts/Modules/agc_lib.py @@ -1,19 +1,21 @@ from dolphin import gui, memory -from .mkw_classes import quatf, vec3 -from .mkw_classes import VehiclePhysics, KartMove, RaceConfig, Timer, RaceManagerPlayer +from .mkw_classes import vec3 +from .mkw_classes import VehiclePhysics, KartMove, RaceConfig, RaceManagerPlayer import math + class FrameData: """Class to represent a set of value accessible each frame in the memory""" - def __init__(self, addrlist = None, string = None , usedefault=False): - self.values = [] #List of bytearray + + def __init__(self, addrlist=None, string=None, usedefault=False): + self.values = [] # List of bytearray if string is not None: self.read_from_string(string) - + elif addrlist is not None: if not usedefault: for addr, size in addrlist: - self.values.append(memory.read_bytes(addr, size)) + self.values.append(memory.read_bytes(addr, size)) else: for addr, size in addrlist: self.values.append(bytearray(size)) @@ -23,10 +25,10 @@ def __str__(self): for array in self.values: for byte in array: text += str(byte)+',' - if len(array)>0: + if len(array) > 0: text = text[:-1] text += ';' - if len(self.values)>0: + if len(self.values) > 0: text = text[:-1] return text+'\n' @@ -35,8 +37,8 @@ def read_from_string(self, string): for value in values: self.values.append(bytearray([int(s) for s in value.split(',')])) - def interpolate(self,other, selfi, otheri): - #Call only if self.value[0] represent a vec3 + def interpolate(self, other, selfi, otheri): + # Call only if self.value[0] represent a vec3 v1 = vec3.from_bytes(self.values[0]) v2 = vec3.from_bytes(other.values[0]) v = (v1*selfi)+(v2*otheri) @@ -48,73 +50,82 @@ def write(self, addrlist): val = self.values[index] memory.write_bytes(addr, val) + def float_to_str(f): - ms = round((f%1)*1000) - s = math.floor(f)%60 + ms = round((f % 1)*1000) + s = math.floor(f) % 60 m = math.floor(f)//60 return f"{m},{s},{ms}" + def floats_to_str(fs): return f"{float_to_str(fs[0])};{float_to_str(fs[1])};{float_to_str(fs[2])}" + class Split: """Class for a lap split. Contain just a float, representing the split in s""" + def __init__(self, f): self.val = f + def __str__(self): return f"{self.val:.3f}" - def __add__(self,other): - return Split(max(0, self.val+other.val)) + + def __add__(self, other): + return Split(max(0, self.val+other.val)) @staticmethod def from_string(string): return Split(float(string)) @staticmethod - def from_time_format(m,s,ms): + def from_time_format(m, s, ms): return Split(m*60+s+ms/1000) - + @staticmethod def from_bytes(b): data_int = b[0]*256*256+b[1]*256+b[2] - ms = data_int%1024 + ms = data_int % 1024 data_int = data_int//1024 - s = data_int%128 + s = data_int % 128 data_int = data_int//128 - m = data_int%128 + m = data_int % 128 return Split(m*60+s+ms/1000) - + def time_format(self): - #return m,s,ms corresponding + # return m,s,ms corresponding f = self.val - ms = round((f%1)*1000) - s = math.floor(f)%60 + ms = round((f % 1)*1000) + s = math.floor(f) % 60 m = math.floor(f)//60 - return m,s,ms - + return m, s, ms + def bytes_format(self): - #return a bytearray of size 3 for rkg format - m,s,ms = self.time_format() + # return a bytearray of size 3 for rkg format + m, s, ms = self.time_format() data_int = ms+s*1024+m*1024*128 - b3 = data_int%256 + b3 = data_int % 256 data_int = data_int//256 - b2 = data_int%256 + b2 = data_int % 256 data_int = data_int//256 - b1 = data_int%256 - return bytearray((b1,b2,b3)) + b1 = data_int % 256 + return bytearray((b1, b2, b3)) class TimerData: """Class for the laps splits, both in RKG and Timer format Cumulative convention (lap2 split is stored as lap1+lap2)""" - def __init__(self,string =None, readid=0, splits = None): - #Call with a string OR when the race is finished + + def __init__(self, string=None, readid=0, splits=None): + # Call with a string OR when the race is finished if string is None: if splits is None: - self.splits = [] #List of Split (size 3) - timerlist = [RaceManagerPlayer.lap_finish_time(readid, lap) for lap in range(3)] + self.splits = [] # List of Split (size 3) + timerlist = [RaceManagerPlayer.lap_finish_time( + readid, lap) for lap in range(3)] for timer in timerlist: - self.splits.append(Split.from_time_format(timer.minutes(), timer.seconds(), timer.milliseconds())) + self.splits.append(Split.from_time_format( + timer.minutes(), timer.seconds(), timer.milliseconds())) else: self.splits = splits else: @@ -129,7 +140,7 @@ def from_sliced_rkg(rkg_metadata): l1 = Split.from_bytes(sliced_bytes[1:4]) l2 = Split.from_bytes(sliced_bytes[4:7])+l1 l3 = Split.from_bytes(sliced_bytes[7:10])+l2 - return TimerData(splits = [l1,l2,l3]) + return TimerData(splits=[l1, l2, l3]) def __str__(self): text = 't' @@ -143,102 +154,109 @@ def add_delay(self, delay): for i in range(len(self.splits)): self.splits[i] = Split(max(self.splits[i].val+s, 0)) - def to_bytes(self): - #A lap split is 3 bytes, so there is 9 bytes total - #Non cumulative format, ready to be written in a rkg + # A lap split is 3 bytes, so there is 9 bytes total + # Non cumulative format, ready to be written in a rkg r = bytearray() prev = 0 for split in self.splits: r = r + Split(split.val - prev).bytes_format() prev = split.val return r - + def write_rkg(self): r = rkg_addr() memory.write_bytes(r+0x11, self.to_bytes()) - - -def metadata_to_file(filename, readid): - #Should be called before the countdown - metadata = FrameData(get_metadata_addr(readid)) + + +def metadata_to_file(filename, read_id): + # Should be called before the countdown + metadata = FrameData(get_metadata_addr(read_id)) file = open(filename, 'w') - if file is None : + if file is None: gui.add_osd_message("Error : could not create the data file") - else : + else: file.write(str(metadata)) file.close() gui.add_osd_message(f"{filename} successfully opened") -def get_metadata(readid): - return FrameData(get_metadata_addr(readid)) + +def get_metadata(read_id): + return FrameData(get_metadata_addr(read_id)) + def get_rkg_metadata(): return FrameData(get_rkg_metadata_addr()) + def rkg_metadata_to_file(filename): rkg_metadata = get_rkg_metadata() file = open(filename, 'w') - if file is None : + if file is None: gui.add_osd_message("Error : could not create the data file") - else : + else: file.write("r"+str(rkg_metadata)) file.close() - gui.add_osd_message(f"{filename} successfully opened") + gui.add_osd_message(f"{filename} successfully opened") -def frame_to_file(filename, readid): - frame = FrameData(get_addr(readid)) + +def frame_to_file(filename, read_id): + frame = FrameData(get_addr(read_id)) file = open(filename, 'a') - if file is None : + if file is None: gui.add_osd_message("Error : could not create the data file") - else : + else: file.write(str(frame)) file.close() -def get_framedata(readid): - return FrameData(get_addr(readid)) - -def timerdata_to_file(filename, rid): - timerdata = TimerData(readid = rid) + +def get_framedata(read_id): + return FrameData(get_addr(read_id)) + + +def timerdata_to_file(filename, read_id): + timerdata = TimerData(read_id) file = open(filename, 'a') - if file is None : + if file is None: gui.add_osd_message("Error : could not create the data file") - else : + else: file.write(str(timerdata)) file.close() -def get_timerdata(rid): - return TimerData(readid = rid) - + +def get_timerdata(read_id): + return TimerData(read_id) + + def file_to_framedatalist(filename): datalist = [] file = open(filename, 'r') - if file is None : + if file is None: gui.add_osd_message("Error : could not load the data file") else: timerdata = None metadata = None rkg_metadata = None listlines = file.readlines() - if listlines[0][0] == 'r': - rkg_metadata = FrameData(string = listlines[0][1:]) + if listlines[0][0] == 'r': + rkg_metadata = FrameData(string=listlines[0][1:]) timerdata = TimerData.from_sliced_rkg(rkg_metadata) else: - metadata = FrameData(string = listlines[0]) - if listlines[-1][0]=='t': - timerdata = TimerData(string = listlines.pop()[1:]) + metadata = FrameData(string=listlines[0]) + if listlines[-1][0] == 't': + timerdata = TimerData(string=listlines.pop()[1:]) for i in range(1, len(listlines)): - datalist.append(FrameData(string = listlines[i])) + datalist.append(FrameData(string=listlines[i])) file.close() gui.add_osd_message(f"Data successfully loaded from {filename}") return metadata, datalist, timerdata, rkg_metadata -def framedatalist_to_file(filename, datalist, rid): - metadata = get_metadata(rid) - timerdata = get_timerdata(rid) +def framedatalist_to_file(filename, datalist, read_id): + metadata = get_metadata(read_id) + timerdata = get_timerdata(read_id) file = open(filename, 'w') - if file is None : + if file is None: gui.add_osd_message("Error : could not create the data file") else: file.write(str(metadata)) @@ -246,14 +264,15 @@ def framedatalist_to_file(filename, datalist, rid): if frame in datalist.keys(): file.write(str(datalist[frame])) else: - file.write(str(FrameData(get_addr(rid), usedefault=True))) + file.write(str(FrameData(get_addr(read_id), usedefault=True))) file.write(str(timerdata)) file.close() + def framedatalist_to_file_rkg(filename, datalist): metadata = get_rkg_metadata() file = open(filename, 'w') - if file is None : + if file is None: gui.add_osd_message("Error : could not create the data file") else: file.write('r'+str(metadata)) @@ -261,37 +280,41 @@ def framedatalist_to_file_rkg(filename, datalist): if frame in datalist.keys(): file.write(str(datalist[frame])) else: - file.write(str(FrameData(get_addr(rid), usedefault=True))) + file.write(str(FrameData(get_addr(1), usedefault=True))) file.close() def get_addr(player_id): a = VehiclePhysics.chain(player_id) b = KartMove.chain(player_id) - return [(a+0x68, 12), #Position - (a+0xF0, 16), #Rotation - (a+0x74, 12), #EV - (a+0x14C, 12), #IV - (b+0x18, 4), #MaxEngineSpd - (b+0x20, 4), #EngineSpd - (b+0x9C, 4), #OutsideDriftAngle - (b+0x5C, 12)]#Dir + return [(a+0x68, 12), # Position + (a+0xF0, 16), # Rotation + (a+0x74, 12), # EV + (a+0x14C, 12), # IV + (b+0x18, 4), # MaxEngineSpd + (b+0x20, 4), # EngineSpd + (b+0x9C, 4), # OutsideDriftAngle + (b+0x5C, 12)] # Dir + def get_metadata_addr(player_id): a = RaceConfig.chain() + player_id*0xF0 - return [(a+0x30, 8)]#CharacterID and VehicleID + return [(a+0x30, 8)] # CharacterID and VehicleID + def rkg_addr(): return memory.read_u32(RaceConfig.chain() + 0xC0C) + def get_rkg_metadata_addr(): r = rkg_addr() - return [(r+0x4, 3), #Skipping track ID - (r+0x8, 4), #Skipping Compression flag - (r+0xD, 1), #Skipping Input Data Length + return [(r+0x4, 3), # Skipping track ID + (r+0x8, 4), # Skipping Compression flag + (r+0xD, 1), # Skipping Input Data Length (r+0x10, 0x78)] + def is_rkg(): - s = bytearray('RKGD', 'ASCII') - r = rkg_addr() - return s == memory.read_bytes(r, 4) + s = bytearray('RKGD', 'ASCII') + r = rkg_addr() + return s == memory.read_bytes(r, 4) diff --git a/scripts/Modules/mkw_utils.py b/scripts/Modules/mkw_utils.py index 0ee0c80..f4f132e 100644 --- a/scripts/Modules/mkw_utils.py +++ b/scripts/Modules/mkw_utils.py @@ -1,4 +1,4 @@ -from dolphin import memory, utils, event +from dolphin import memory, utils from .mkw_classes import mat34, quatf, vec3, ExactTimer, eulerAngle from .mkw_classes import VehicleDynamics, VehiclePhysics, RaceManagerPlayer, KartObjectManager, RaceManager, RaceState @@ -14,20 +14,21 @@ class FrameData: def __init__(self): - #Default values - self.prc = 0 #PlayerRaceCompletion - self.grc = 0 #GhostRaceCompletion + # Default values + self.prc = 0 # PlayerRaceCompletion + self.grc = 0 # GhostRaceCompletion self.euler = eulerAngle() self.movangle = eulerAngle() - #Value for current frame (if available) + # Value for current frame (if available) if RaceManager().state().value >= RaceState.COUNTDOWN.value: self.prc = RaceManagerPlayer(0).race_completion() self.euler = get_facing_angle(0) self.movangle = get_moving_angle(0) if not is_single_player(): self.grc = RaceManagerPlayer(1).race_completion() - + + class History: def __init__(self, size): self.size = size @@ -38,15 +39,15 @@ def __init__(self, size): def update(self): """Add a new frameData to the array, and move the index""" - self.index = (self.index+1)%self.size + self.index = (self.index+1) % self.size self.array[self.index] = FrameData() - def get_older_frame(self,i): + def get_older_frame(self, i): """Return the FrameData i frame older""" - assert i 1: @@ -115,6 +120,7 @@ def update_exact_finish(lap, player): return currentLapTime - pastLapTime + def get_unrounded_time(lap, player): t = ExactTimer(0, 0, 0) for i in range(lap): @@ -122,6 +128,8 @@ def get_unrounded_time(lap, player): return t # TODO: Rotation display helper functions + + def quaternion_to_euler_angle(q): """Param : quatf Return : eulerAngle """ @@ -133,21 +141,24 @@ def quaternion_to_euler_angle(q): yaw = -180/math.pi * math.atan2(y1, y2) return eulerAngle(pitch, yaw, roll) + def get_facing_angle(player): """Param : int player_id Return : eulerAngle , correspond to facing angles""" quaternion = VehiclePhysics(player).main_rotation() return quaternion_to_euler_angle(quaternion) + def speed_to_euler_angle(speed): """Param : vec3 speed Return : eulerAngle""" s = speed - pitch = 180/math.pi * math.atan2(s.z, s.y) #unsure and unused + pitch = 180/math.pi * math.atan2(s.z, s.y) # unsure and unused yaw = -180/math.pi * math.atan2(s.x, s.z) - roll = -180/math.pi * math.atan2(s.y, s.x)#unsure and unused + roll = -180/math.pi * math.atan2(s.y, s.x) # unsure and unused return eulerAngle(pitch, yaw, roll) + def get_moving_angle(player): """Param : int player_id Return : eulerAngle , correspond to moving angles""" @@ -169,12 +180,13 @@ def get_moving_angle(player): It's the function called in draw_infodisplay.py """ + def get_physics(player1, player2): """Take the Player1 and Player2 ID's, return their P1, S1, P2, S2 data""" P1, S1 = VehiclePhysics(player1).position(), delta_position(player1) P2, S2 = VehiclePhysics(player2).position(), delta_position(player2) - return P1,S1,P2,S2 + return P1, S1, P2, S2 def get_distance_ghost_vec(): @@ -184,43 +196,50 @@ def get_distance_ghost_vec(): ghost_position = VehiclePhysics(1).position() return (ghost_position - player_position) + def get_distance_ghost(): """Give the distance(float) between the player and the ghost""" return get_distance_ghost_vec().length() + def time_difference_absolute(P1, P2, S1, S2): s = S1.length() if s != 0: return (P2-P1).length() / s return float('inf') - + + def get_time_difference_absolute(player1, player2): """Time difference "Absolute" (simple and bad) Simply takes the distance player-ghost, and divide it by raw speed (always positive)""" P1, S1, P2, S2 = get_physics(player1, player2) return time_difference_absolute(P1, P2, S1, S2) + def time_difference_relative(P1, P2, S1, S2): L = (P2 - P1).length() if L == 0: return 0 s = S1*(P2-P1)/L if s == 0: - return float('inf') + return float('inf') return (P2-P1).length() / s + def get_time_difference_relative(player1, player2): """Time difference "Relative" Take distance player-ghost. Divide it by the player's speed "toward" the ghost (dot product)""" P1, S1, P2, S2 = get_physics(player1, player2) return time_difference_relative(P1, P2, S1, S2) + def time_difference_projected(P1, P2, S1, S2): s = S1.length() if s == 0: return float('inf') return (P2-P1)*S1/(s**2) + def get_time_difference_projected(player1, player2): """ Time difference "Projected" Take the distance between the player and the plane oriented by the player speed, covering the ghost. @@ -235,12 +254,13 @@ def time_to_cross(A, S, B, C): to cross the vertical plan containing B and C Param : A, S, B, C : (vec3),(vec3),(vec3),(vec3) Return t (float) """ - N = (B-C)@vec3(0,1,0) #normal vector to the plan containing B,C + N = (B-C)@vec3(0, 1, 0) # normal vector to the plan containing B,C ns = N*S if ns != 0: return N*(B-A)/ns return float('inf') + def time_difference_crosspath(P1, P2, S1, S2): t1 = time_to_cross(P1, S1, P2, P2+S2) t2 = time_to_cross(P2, S2, P1, P1+S1) @@ -256,7 +276,6 @@ def get_time_difference_crosspath(player1, player2): return time_difference_crosspath(P1, P2, S1, S2) - def get_finish_line_coordinate(): """pointA is the position of the left side of the finish line (vec3) point B ---------------------right------------------------------ @@ -266,17 +285,20 @@ def get_finish_line_coordinate(): "RMCJ01": 0x809BC748, "RMCK01": 0x809ABD28} kmp_ref = chase_pointer(address[game_id], [0x4, 0x0], 'u32') offset = memory.read_u32(kmp_ref+0x24) - pointA = vec3(memory.read_f32(kmp_ref+0x4C+offset+0x8+0x0), 0, memory.read_f32(kmp_ref+0x4C+offset+0x8+0x4)) - pointB = vec3(memory.read_f32(kmp_ref+0x4C+offset+0x8+0x8), 0, memory.read_f32(kmp_ref+0x4C+offset+0x8+0xC)) + pointA = vec3(memory.read_f32(kmp_ref+0x4C+offset+0x8+0x0), + 0, memory.read_f32(kmp_ref+0x4C+offset+0x8+0x4)) + pointB = vec3(memory.read_f32(kmp_ref+0x4C+offset+0x8+0x8), + 0, memory.read_f32(kmp_ref+0x4C+offset+0x8+0xC)) return pointA, pointB def time_difference_tofinish(P1, P2, S1, S2): - A,B = get_finish_line_coordinate() + A, B = get_finish_line_coordinate() t1 = time_to_cross(P1, S1, A, B) t2 = time_to_cross(P2, S2, A, B) return t1-t2 + def get_time_difference_tofinish(player1, player2): """Assume player and ghost are not accelerated. Calculate the time to the finish line for both, and takes the difference.""" @@ -289,32 +311,35 @@ def find_index(value, value_list): We suppose value_list[i+1] < value_list[i] and value_list[0]>= value>=value_list[-1]""" n = len(value_list) - if n == 1 : + if n == 1: return 0 h = n//2 if value <= value_list[h]: return h+find_index(value, value_list[h:]) return find_index(value, value_list[:h]) - + + def get_time_difference_racecompletion(history): """Use RaceCompletionData History to calculate the frame difference The function assume that RaceCompletion is increasing every frames""" curframe = history.get_older_frame(0) lastframe = history.get_older_frame(-1) inf = float('inf') - if curframe.prc>=curframe.grc: - if curframe.grc>lastframe.prc: - l = [history.get_older_frame(k).prc for k in range(history.size)] - i = find_index(curframe.grc, l) - t = i + (curframe.grc - l[i])/ (l[i+1] - l[i]) - return -t + if curframe.prc >= curframe.grc: + if curframe.grc > lastframe.prc: + length = [history.get_older_frame( + k).prc for k in range(history.size)] + i = find_index(curframe.grc, length) + time = i + (curframe.grc - length[i]) / (length[i+1] - length[i]) + return -time return -inf else: - if curframe.prc>lastframe.grc: - l =[history.get_older_frame(k).grc for k in range(history.size)] - i = find_index(curframe.prc, l) - t = i + (curframe.prc - l[i])/ (l[i+1] - l[i]) - return t + if curframe.prc > lastframe.grc: + length = [history.get_older_frame( + k).grc for k in range(history.size)] + i = find_index(curframe.prc, length) + time = i + (curframe.prc - length[i]) / (length[i+1] - length[i]) + return time return inf @@ -323,8 +348,8 @@ def get_timediff_settings(string): return 0, 1 if string == 'ghost': return 1, 0 - pp, sp, pg, sg = get_physics(0,1) - player_is_ahead = int(sp*(pg-pp)>0) + pp, sp, pg, sg = get_physics(0, 1) + player_is_ahead = int(sp*(pg-pp) > 0) if string == 'ahead': return 1-player_is_ahead, player_is_ahead if string == 'behind': @@ -332,5 +357,3 @@ def get_timediff_settings(string): else: print('TimeDiff setting value not recognized. Default to "player"') return 0, 1 - - diff --git a/scripts/RMC/Adv. Ghost Comp/Load_data.py b/scripts/RMC/Adv. Ghost Comp/Load_data.py index a73bdf0..54cbc3b 100644 --- a/scripts/RMC/Adv. Ghost Comp/Load_data.py +++ b/scripts/RMC/Adv. Ghost Comp/Load_data.py @@ -1,4 +1,4 @@ -from dolphin import event, gui, utils +from dolphin import event, utils import Modules.agc_lib as lib from Modules.mkw_classes import RaceManager, RaceState import Modules.mkw_utils as mkw_utils @@ -19,7 +19,7 @@ def main(): metadata, framedatalist, timerdata, rkg_metadata = lib.file_to_framedatalist(filename) - if not timerdata is None: + if timerdata is not None: timerdata.add_delay(delay) @@ -34,7 +34,7 @@ def on_frame_advance(): delayed_frame = floor(delay)+frame decimal_delay = delay - floor(delay) - if not metadata is None: + if metadata is not None: metadata.write(lib.get_metadata_addr(1)) if lib.is_rkg(): diff --git a/scripts/RMC/Adv. Ghost Comp/Save_to_file.py b/scripts/RMC/Adv. Ghost Comp/Save_to_file.py index fe6e5ba..0718c68 100644 --- a/scripts/RMC/Adv. Ghost Comp/Save_to_file.py +++ b/scripts/RMC/Adv. Ghost Comp/Save_to_file.py @@ -1,4 +1,4 @@ -from dolphin import event, gui, utils +from dolphin import event, utils import Modules.agc_lib as lib from Modules.mkw_classes import RaceManager, RaceState import Modules.mkw_utils as mkw_utils diff --git a/scripts/RMC/_draw_info_display.py b/scripts/RMC/_draw_info_display.py index 7e7f89e..6fb098a 100644 --- a/scripts/RMC/_draw_info_display.py +++ b/scripts/RMC/_draw_info_display.py @@ -3,11 +3,11 @@ import math import os -from Modules.mkw_classes.common import SurfaceProperties, eulerAngle +from Modules.mkw_classes.common import SurfaceProperties from Modules.mkw_utils import History import Modules.mkw_utils as mkw_utils -from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState, TimerManager +from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState from Modules.mkw_classes import RaceConfig, RaceConfigScenario, RaceConfigSettings from Modules.mkw_classes import KartObject, KartMove, KartSettings, KartBody from Modules.mkw_classes import VehicleDynamics, VehiclePhysics, KartBoost, KartJump From 70086c4792358adf5efcfb65fd0c7d094cbd4bdf Mon Sep 17 00:00:00 2001 From: xi <104683822+ximk@users.noreply.github.com> Date: Tue, 26 Dec 2023 18:23:35 -0500 Subject: [PATCH 11/12] Final touches --- .gitignore | 4 - scripts/Modules/infodisplay.ini | 39 ---- scripts/RMC/_draw_info_display.py | 208 +++++++++++------- ...nput_display.py => _draw_input_display.py} | 0 4 files changed, 126 insertions(+), 125 deletions(-) delete mode 100644 scripts/Modules/infodisplay.ini rename scripts/RMC/{draw_input_display.py => _draw_input_display.py} (100%) diff --git a/.gitignore b/.gitignore index 06aae8c..438d0f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,2 @@ /scripts/MKW_Inputs/*.csv -scripts/Modules/test_del_me_later.py -scripts/Modules/test.bit -scripts/Modules/test_del_me_later.py -scripts/Modules/test_del_me_later.py scripts/AGC_Data/ghost.data diff --git a/scripts/Modules/infodisplay.ini b/scripts/Modules/infodisplay.ini deleted file mode 100644 index 7ea4226..0000000 --- a/scripts/Modules/infodisplay.ini +++ /dev/null @@ -1,39 +0,0 @@ -[DEBUG] -debug = True - -[INFO DISPLAY] -frame count = True -lap splits = False -speed = True -oriented speed = True -internal velocity (x, y, z) = False -oriented internal velocity = False -internal velocity (xyz) = False -external velocity (x, y, z) = False -oriented external velocity = True -external velocity (xyz) = True -moving road velocity (x, y, z) = False -oriented moving road velocity = False -moving road velocity (xyz) = False -moving water velocity (x, y, z) = False -oriented moving water velocity = False -moving water velocity (xyz) = False -charges and boosts = True -checkpoints and completion = True -airtime = True -miscellaneous = False -surface properties = False -position = False -rotation = True -stick = True -text color (argb) = 0xFFFFFFFF -digits (to round to) = 6 -timediff absolute = True -timediff relative = True -timediff projected = True -timediff crosspath = True -timediff tofinish = True -timediff racecomp = True -timediff setting = ahead -history size = 200 - diff --git a/scripts/RMC/_draw_info_display.py b/scripts/RMC/_draw_info_display.py index 6fb098a..70f7ee4 100644 --- a/scripts/RMC/_draw_info_display.py +++ b/scripts/RMC/_draw_info_display.py @@ -4,7 +4,7 @@ import os from Modules.mkw_classes.common import SurfaceProperties -from Modules.mkw_utils import History +from Modules.mkw_utils import History import Modules.mkw_utils as mkw_utils from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState @@ -13,12 +13,13 @@ from Modules.mkw_classes import VehicleDynamics, VehiclePhysics, KartBoost, KartJump from Modules.mkw_classes import KartState, KartCollide, KartInput, RaceInputState + def populate_default_config(file_path): config = configparser.ConfigParser() - + config['DEBUG'] = {} config['DEBUG']['Debug'] = "False" - + config['INFO DISPLAY'] = {} config['INFO DISPLAY']["Frame Count"] = "True" config['INFO DISPLAY']["Lap Splits"] = "False" @@ -48,56 +49,77 @@ def populate_default_config(file_path): config['INFO DISPLAY']["Digits (to round to)"] = "6" config['INFO DISPLAY']["TimeDiff Absolute"] = "False" config['INFO DISPLAY']["TimeDiff Relative"] = "False" - config['INFO DISPLAY']["TimeDiff Projected"] = "True" + config['INFO DISPLAY']["TimeDiff Projected"] = "False" config['INFO DISPLAY']["TimeDiff CrossPath"] = "False" - config['INFO DISPLAY']["TimeDiff ToFinish"] = "True" - config['INFO DISPLAY']["TimeDiff RaceComp"] = "True" + config['INFO DISPLAY']["TimeDiff ToFinish"] = "False" + config['INFO DISPLAY']["TimeDiff RaceComp"] = "False" config['INFO DISPLAY']["TimeDiff Setting"] = "behind" config['INFO DISPLAY']["History Size"] = "200" - - + with open(file_path, 'w') as f: config.write(f) - + return config + class ConfigInstance(): - def __init__(self, config : configparser.ConfigParser): + def __init__(self, config: configparser.ConfigParser): self.debug = config['DEBUG'].getboolean('Debug') self.frame_count = config['INFO DISPLAY'].getboolean('Frame Count') self.lap_splits = config['INFO DISPLAY'].getboolean('Lap Splits') self.speed = config['INFO DISPLAY'].getboolean('Speed') - self.speed_oriented = config['INFO DISPLAY'].getboolean('Oriented Speed') - self.iv = config['INFO DISPLAY'].getboolean('Internal Velocity (X, Y, Z)') - self.iv_oriented = config['INFO DISPLAY'].getboolean('Oriented Internal Velocity') - self.iv_xyz = config['INFO DISPLAY'].getboolean('Internal Velocity (XYZ)') - self.ev = config['INFO DISPLAY'].getboolean('External Velocity (X, Y, Z)') - self.ev_oriented = config['INFO DISPLAY'].getboolean('Oriented External Velocity') - self.ev_xyz = config['INFO DISPLAY'].getboolean('External Velocity (XYZ)') - self.mrv = config['INFO DISPLAY'].getboolean('Moving Road Velocity (X, Y, Z)') - self.mrv_oriented = config['INFO DISPLAY'].getboolean('Oriented Moving Road Velocity') - self.mrv_xyz = config['INFO DISPLAY'].getboolean('Moving Road Velocity (XYZ)') - self.mwv = config['INFO DISPLAY'].getboolean('Moving Water Velocity (X, Y, Z)') - self.mwv_oriented = config['INFO DISPLAY'].getboolean('Oriented Moving Water Velocity') - self.mwv_xyz = config['INFO DISPLAY'].getboolean('Moving Water Velocity (XYZ)') + self.speed_oriented = config['INFO DISPLAY'].getboolean( + 'Oriented Speed') + self.iv = config['INFO DISPLAY'].getboolean( + 'Internal Velocity (X, Y, Z)') + self.iv_oriented = config['INFO DISPLAY'].getboolean( + 'Oriented Internal Velocity') + self.iv_xyz = config['INFO DISPLAY'].getboolean( + 'Internal Velocity (XYZ)') + self.ev = config['INFO DISPLAY'].getboolean( + 'External Velocity (X, Y, Z)') + self.ev_oriented = config['INFO DISPLAY'].getboolean( + 'Oriented External Velocity') + self.ev_xyz = config['INFO DISPLAY'].getboolean( + 'External Velocity (XYZ)') + self.mrv = config['INFO DISPLAY'].getboolean( + 'Moving Road Velocity (X, Y, Z)') + self.mrv_oriented = config['INFO DISPLAY'].getboolean( + 'Oriented Moving Road Velocity') + self.mrv_xyz = config['INFO DISPLAY'].getboolean( + 'Moving Road Velocity (XYZ)') + self.mwv = config['INFO DISPLAY'].getboolean( + 'Moving Water Velocity (X, Y, Z)') + self.mwv_oriented = config['INFO DISPLAY'].getboolean( + 'Oriented Moving Water Velocity') + self.mwv_xyz = config['INFO DISPLAY'].getboolean( + 'Moving Water Velocity (XYZ)') self.charges = config['INFO DISPLAY'].getboolean('Charges and Boosts') - self.cps = config['INFO DISPLAY'].getboolean('Checkpoints and Completion') + self.cps = config['INFO DISPLAY'].getboolean( + 'Checkpoints and Completion') self.air = config['INFO DISPLAY'].getboolean('Airtime') self.misc = config['INFO DISPLAY'].getboolean('Miscellaneous') self.surfaces = config['INFO DISPLAY'].getboolean('Surface Properties') self.position = config['INFO DISPLAY'].getboolean('Position') self.rotation = config['INFO DISPLAY'].getboolean('Rotation') - self.td_absolute = config['INFO DISPLAY'].getboolean('TimeDiff Absolute') - self.td_relative = config['INFO DISPLAY'].getboolean('TimeDiff Relative') - self.td_projected = config['INFO DISPLAY'].getboolean('TimeDiff Projected') - self.td_crosspath = config['INFO DISPLAY'].getboolean('TimeDiff CrossPath') - self.td_tofinish = config['INFO DISPLAY'].getboolean('TimeDiff ToFinish') - self.td_racecomp = config['INFO DISPLAY'].getboolean('TimeDiff RaceComp') + self.td_absolute = config['INFO DISPLAY'].getboolean( + 'TimeDiff Absolute') + self.td_relative = config['INFO DISPLAY'].getboolean( + 'TimeDiff Relative') + self.td_projected = config['INFO DISPLAY'].getboolean( + 'TimeDiff Projected') + self.td_crosspath = config['INFO DISPLAY'].getboolean( + 'TimeDiff CrossPath') + self.td_tofinish = config['INFO DISPLAY'].getboolean( + 'TimeDiff ToFinish') + self.td_racecomp = config['INFO DISPLAY'].getboolean( + 'TimeDiff RaceComp') self.td_set = config['INFO DISPLAY']['TimeDiff Setting'] self.td = self.td_absolute or self.td_relative or self.td_projected or self.td_crosspath or self.td_tofinish or self.td_racecomp self.stick = config['INFO DISPLAY'].getboolean('Stick') self.color = int(config['INFO DISPLAY']['Text Color (ARGB)'], 16) - self.digits = min(7, config['INFO DISPLAY'].getint('Digits (to round to)')) + self.digits = min( + 7, config['INFO DISPLAY'].getint('Digits (to round to)')) self.history_size = config['INFO DISPLAY'].getint('History Size') @@ -111,7 +133,8 @@ def make_line_text_speed(left_text_prefix, left_text_suffix, size, speed): float speed Return str text""" return left_text_prefix+" "*(size - len(left_text_prefix+left_text_suffix))+left_text_suffix + f"{speed:.{c.digits}f}\n" - + + def make_text_speed(speed, speedname, player, boolspd, boolspdoriented, boolspdxyz): """Function to generate the text for a certain speed Parameters : vec3 speed : the speed to generate the text for. @@ -124,23 +147,29 @@ def make_text_speed(speed, speedname, player, boolspd, boolspdoriented, boolspdx text = "" facing_yaw = mkw_utils.get_facing_angle(player).yaw offset_size = 13 - if boolspd and boolspdoriented : - text += make_line_text_speed(speedname,"X: ", offset_size, speed.x) - text += make_line_text_speed(speedname,"Y: ", offset_size, speed.y) - text += make_line_text_speed(speedname,"Z: ", offset_size, speed.z) - text += make_line_text_speed(speedname,"Forward: ", offset_size, speed.forward(facing_yaw)) - text += make_line_text_speed(speedname,"Sideway: ", offset_size, speed.sideway(facing_yaw)) - elif boolspd : - text += make_line_text_speed(speedname,"X: ", offset_size, speed.x) - text += make_line_text_speed(speedname,"Y: ", offset_size, speed.y) - text += make_line_text_speed(speedname,"Z: ", offset_size, speed.z) - elif boolspdoriented : - text += make_line_text_speed(speedname,"Forward: ", offset_size, speed.forward(facing_yaw)) - text += make_line_text_speed(speedname,"Sideway: ", offset_size, speed.sideway(facing_yaw)) - text += make_line_text_speed(speedname,"Y: ", offset_size, speed.y) - if boolspdxyz : - text += make_line_text_speed(speedname,"XZ: ", offset_size, speed.length_xz()) - text += make_line_text_speed(speedname,"XYZ: ", offset_size, speed.length()) + if boolspd and boolspdoriented: + text += make_line_text_speed(speedname, "X: ", offset_size, speed.x) + text += make_line_text_speed(speedname, "Y: ", offset_size, speed.y) + text += make_line_text_speed(speedname, "Z: ", offset_size, speed.z) + text += make_line_text_speed(speedname, "Forward: ", + offset_size, speed.forward(facing_yaw)) + text += make_line_text_speed(speedname, "Sideway: ", + offset_size, speed.sideway(facing_yaw)) + elif boolspd: + text += make_line_text_speed(speedname, "X: ", offset_size, speed.x) + text += make_line_text_speed(speedname, "Y: ", offset_size, speed.y) + text += make_line_text_speed(speedname, "Z: ", offset_size, speed.z) + elif boolspdoriented: + text += make_line_text_speed(speedname, "Forward: ", + offset_size, speed.forward(facing_yaw)) + text += make_line_text_speed(speedname, "Sideway: ", + offset_size, speed.sideway(facing_yaw)) + text += make_line_text_speed(speedname, "Y: ", offset_size, speed.y) + if boolspdxyz: + text += make_line_text_speed(speedname, + "XZ: ", offset_size, speed.length_xz()) + text += make_line_text_speed(speedname, + "XYZ: ", offset_size, speed.length()) return text @@ -163,9 +192,10 @@ def make_text_rotation(rot, rotspd, prefix_text, prefix_size, rotsize): return prefix_text+":"+" "*(prefix_size - len(prefix_text))+rot_text+"| "+rotspd_text+"\n" # draw information to the screen + def create_infodisplay(): text = "" - + race_mgr_player = RaceManagerPlayer() race_scenario = RaceConfigScenario(addr=RaceConfig.race_scenario()) race_settings = RaceConfigSettings(race_scenario.settings()) @@ -176,13 +206,13 @@ def create_infodisplay(): vehicle_dynamics = VehicleDynamics(addr=kart_body.vehicle_dynamics()) vehicle_physics = VehiclePhysics(addr=vehicle_dynamics.vehicle_physics()) - if c.debug : + if c.debug: value = mkw_utils.delta_position(0) - VehiclePhysics.speed(0) text += f"Debug : {value.length()}\n" - + if c.frame_count: text += f"Frame: {mkw_utils.frame_of_input()}\n\n" - + if c.lap_splits: # The actual max lap address does not update when crossing the finish line # for the final time to finish the race. However, for whatever reason, @@ -193,10 +223,12 @@ def create_infodisplay(): if player_max_lap >= 2 and lap_count > 1: for lap in range(1, player_max_lap): - text += "Lap {}: {}\n".format(lap, mkw_utils.update_exact_finish(lap, 0)) + text += "Lap {}: {}\n".format(lap, + mkw_utils.update_exact_finish(lap, 0)) if player_max_lap > lap_count: - text += "Final: {}\n".format(mkw_utils.get_unrounded_time(lap_count, 0)) + text += "Final: {}\n".format( + mkw_utils.get_unrounded_time(lap_count, 0)) text += "\n" if c.speed: @@ -206,7 +238,7 @@ def create_infodisplay(): text += make_text_speed(speed, "", 0, False, c.speed_oriented, c.speed) text += f" Engine: {round(engine_speed, c.digits)} / {round(cap, c.digits)}\n" text += "\n" - + if (c.iv or c.iv_xyz or c.iv_oriented): iv = vehicle_physics.internal_velocity() text += make_text_speed(iv, "IV ", 0, c.iv, c.iv_oriented, c.iv_xyz) @@ -219,20 +251,22 @@ def create_infodisplay(): if (c.mrv or c.mrv_xyz or c.mrv_oriented): mrv = vehicle_physics.moving_road_velocity() - text += make_text_speed(mrv, "MRV ", 0, c.mrv, c.mrv_oriented, c.mrv_xyz) + text += make_text_speed(mrv, "MRV ", 0, c.mrv, + c.mrv_oriented, c.mrv_xyz) text += "\n" if (c.mwv or c.mwv_xyz or c.mwv_oriented): mwv = vehicle_physics.moving_water_velocity() - text += make_text_speed(mwv, "MWV ", 0, c.mwv, c.mwv_oriented, c.mwv_xyz) + text += make_text_speed(mwv, "MWV ", 0, c.mwv, + c.mwv_oriented, c.mwv_xyz) text += "\n" - + if c.charges or c.misc: kart_settings = KartSettings(addr=kart_object.kart_settings()) if c.charges: kart_boost = KartBoost(addr=kart_move.kart_boost()) - + mt = kart_move.mt_charge() smt = kart_move.smt_charge() ssmt = kart_move.ssmt_charge() @@ -243,7 +277,7 @@ def create_infodisplay(): text += f"MT Charge: {mt} | SSMT Charge: {ssmt}\n" else: text += f"MT Charge: {mt} ({smt}) | SSMT Charge: {ssmt}\n" - + text += f"MT: {mt_boost} | Trick: {trick_boost} | Mushroom: {shroom_boost}\n\n" if c.cps: @@ -281,7 +315,8 @@ def create_infodisplay(): if c.surfaces: surface_properties = kart_collide.surface_properties() is_offroad = (surface_properties.value & SurfaceProperties.OFFROAD) > 0 - is_trickable = (surface_properties.value & SurfaceProperties.TRICKABLE) > 0 + is_trickable = (surface_properties.value & + SurfaceProperties.TRICKABLE) > 0 kcl_speed_mod = kart_move.kcl_speed_factor() text += f" Offroad: {is_offroad}\n" text += f"Trickable: {is_trickable}\n" @@ -293,7 +328,7 @@ def create_infodisplay(): text += f"Y Pos: {pos.y}\n" text += f"Z Pos: {pos.z}\n\n" - if c.rotation : + if c.rotation: fac = mkw_utils.get_facing_angle(0) mov = mkw_utils.get_moving_angle(0) prevfac = Memory_History.get_older_frame(1).euler @@ -303,10 +338,14 @@ def create_infodisplay(): prefix_size = 10 rotsize = c.digits+4 text += " "*(prefix_size+1)+"Rotation"+" "*(rotsize - 8)+"| Speed\n" - text += make_text_rotation(fac.pitch, facdiff.pitch, "Pitch", prefix_size, rotsize) - text += make_text_rotation(fac.yaw, facdiff.yaw, "Yaw", prefix_size, rotsize) - text += make_text_rotation(mov.yaw, movdiff.yaw, "Moving Y", prefix_size, rotsize) - text += make_text_rotation(fac.roll, facdiff.roll, "Roll", prefix_size, rotsize) + text += make_text_rotation(fac.pitch, facdiff.pitch, + "Pitch", prefix_size, rotsize) + text += make_text_rotation(fac.yaw, facdiff.yaw, + "Yaw", prefix_size, rotsize) + text += make_text_rotation(mov.yaw, movdiff.yaw, + "Moving Y", prefix_size, rotsize) + text += make_text_rotation(fac.roll, facdiff.roll, + "Roll", prefix_size, rotsize) text += "\n" if c.td and not mkw_utils.is_single_player(): @@ -316,31 +355,33 @@ def create_infodisplay(): s = 1 if 1-p1 else -1 text += "TimeDiff:"+" "*(timesize+size-16)+"Seconds | Frames\n" if c.td_absolute: - absolute = mkw_utils.get_time_difference_absolute(p1,p2) + absolute = mkw_utils.get_time_difference_absolute(p1, p2) text += make_text_timediff(absolute, "Absolute", size, timesize) if c.td_relative: - relative = s*mkw_utils.get_time_difference_relative(p1,p2) + relative = s*mkw_utils.get_time_difference_relative(p1, p2) text += make_text_timediff(relative, "Relative", size, timesize) if c.td_projected: - projected = s*mkw_utils.get_time_difference_projected(p1,p2) + projected = s*mkw_utils.get_time_difference_projected(p1, p2) text += make_text_timediff(projected, "Projected", size, timesize) if c.td_crosspath: - crosspath = s*mkw_utils.get_time_difference_crosspath(p1,p2) + crosspath = s*mkw_utils.get_time_difference_crosspath(p1, p2) text += make_text_timediff(crosspath, "CrossPath", size, timesize) if c.td_tofinish: - tofinish = s*mkw_utils.get_time_difference_tofinish(p1,p2) + tofinish = s*mkw_utils.get_time_difference_tofinish(p1, p2) text += make_text_timediff(tofinish, "ToFinish", size, timesize) if c.td_racecomp: - racecomp = mkw_utils.get_time_difference_racecompletion(Memory_History) - text += make_text_timediff(racecomp, "RaceComp", size, timesize) + racecomp = mkw_utils.get_time_difference_racecompletion( + Memory_History) + text += make_text_timediff(racecomp, "RaceComp", size, timesize) text += "\n" - # TODO: figure out why classes.RaceInfoPlayer.stick_x() and + # TODO: figure out why classes.RaceInfoPlayer.stick_x() and # classes.RaceInfoPlayer.stick_y() do not update # (using these as placeholders until further notice) if c.stick: kart_input = KartInput(addr=race_mgr_player.kart_input()) - current_input_state = RaceInputState(addr=kart_input.current_input_state()) + current_input_state = RaceInputState( + addr=kart_input.current_input_state()) stick_x = current_input_state.raw_stick_x() - 7 stick_y = current_input_state.raw_stick_y() - 7 @@ -348,6 +389,7 @@ def create_infodisplay(): return text + """ @event.on_savestateload def on_state_load(fromSlot: bool, slot: int): @@ -356,26 +398,28 @@ def on_state_load(fromSlot: bool, slot: int): gui.draw_text((10, 10), c.color, create_infodisplay()) """ - + def main(): config = configparser.ConfigParser() - file_path = os.path.join(utils.get_script_dir(), 'modules', 'infodisplay.ini') + file_path = os.path.join(utils.get_script_dir(), + 'modules', 'infodisplay.ini') config.read(file_path) if not config.sections(): config = populate_default_config(file_path) - + global c c = ConfigInstance(config) - - #Those 2 variables are used to store some parameters from previous frames + + # Those 2 variables are used to store some parameters from previous frames global Frame_of_input Frame_of_input = 0 global Memory_History size = max(c.history_size, int(c.rotation)+1) Memory_History = History(size) + if __name__ == '__main__': main() @@ -384,7 +428,7 @@ def main(): def on_frame_advance(): global Frame_of_input global Memory_History - + race_mgr = RaceManager() newframe = Frame_of_input != mkw_utils.frame_of_input() draw = race_mgr.state().value >= RaceState.COUNTDOWN.value diff --git a/scripts/RMC/draw_input_display.py b/scripts/RMC/_draw_input_display.py similarity index 100% rename from scripts/RMC/draw_input_display.py rename to scripts/RMC/_draw_input_display.py From ffbfb209cc916ed617f6975ff28cd4977c02ec08 Mon Sep 17 00:00:00 2001 From: Blounard Date: Mon, 8 Apr 2024 01:53:08 +0200 Subject: [PATCH 12/12] Implemented the 7 column version of TTK First attempt at implementing TTK with 7 columns --- scripts/Modules/framesequence.py | 117 ++++++++++++++++++++++++++----- scripts/Modules/ttk_lib.py | 7 +- 2 files changed, 104 insertions(+), 20 deletions(-) diff --git a/scripts/Modules/framesequence.py b/scripts/Modules/framesequence.py index 99c48fc..139ce5a 100644 --- a/scripts/Modules/framesequence.py +++ b/scripts/Modules/framesequence.py @@ -22,6 +22,8 @@ class Frame: accel: bool brake: bool item: bool + drift: bool + brakedrift: bool stick_x: int stick_y: int @@ -43,10 +45,11 @@ def __init__(self, raw: List): * raw[0] (str) - A * raw[1] (str) - B/R * raw[2] (str) - L - * raw[3] (str) - Horizontal stick - * raw[4] (str) - Vertical stick - * raw[5] (str) - Dpad - + * raw[5] (str) - Horizontal stick + * raw[6] (str) - Vertical stick + * raw[7] (str) - Dpad + * raw[3] (str) - Drift "ghost" button + * raw[4] (str) - BrakeDrift "ghost" button Args: raw (List): CSV line to be read """ @@ -55,9 +58,12 @@ def __init__(self, raw: List): self.accel = self.read_button(raw[0]) self.brake = self.read_button(raw[1]) self.item = self.read_button(raw[2]) - self.stick_x = self.read_stick(raw[3]) - self.stick_y = self.read_stick(raw[4]) - self.read_dpad(raw[5]) + self.drift = self.read_button(raw[3]) + self.brakedrift = self.read_button(raw[4]) + self.stick_x = self.read_stick(raw[5]) + self.stick_y = self.read_stick(raw[6]) + self.read_dpad(raw[7]) + def __iter__(self): self.iter_idx = 0 @@ -73,11 +79,16 @@ def __next__(self): if (self.iter_idx == 3): return int(self.item) if (self.iter_idx == 4): - return self.stick_x + return int(self.drift) if (self.iter_idx == 5): - return self.stick_y + return int(self.brakedrift) if (self.iter_idx == 6): + return self.stick_x + if (self.iter_idx == 7): + return self.stick_y + if (self.iter_idx == 8): return self.dpad_raw() + raise StopIteration def read_button(self, button: str) -> bool: @@ -142,7 +153,80 @@ def dpad_raw(self) -> int: return 4 return 0 +def compressInputList(rawInputList): + """A function that convert Raw Input List (List of Frames) to + Compressed Input List (List of 7-int-list, TTK .csv format)""" + compressedInputList = [] + prevInputRaw = Frame(["0"]*8) + prevInputCompressed = [0,0,0,0,0,0,-1] + for rawInput in rawInputList: + compressedInput = [int(rawInput.accel), + 0, + int(rawInput.item), + rawInput.stick_x, + rawInput.stick_y, + rawInput.dpad_raw(), + -1] + if not rawInput.brake: + compressedInput[1] = 0 + elif rawInput.brakedrift: + compressedInput[1] = 3 + elif not prevInputRaw.brake: + compressedInput[1] = 1 + elif rawInput.drift and not prevInputRaw.drift: + compressedInput[1] = 3-prevInputCompressed + else: + compressedInput[1] = prevInputCompressed[1] + + if rawInput.accel and rawInput.brake and (not rawInput.drift): + if prevInputRaw.accel and prevInputRaw.brake and prevInputRaw.drift: + compressedInput[6] = 0 + elif not prevInputRaw.brake: + compressedInput[6] = 0 + + if ((not rawInput.accel) or (not rawInput.brake)) and rawInput.drift: + compressedInput[6] = 1 + prevInputRaw = rawInput + prevInputCompressed = compressedInput + compressedInputList.append(compressedInput) + return compressedInputList + +def decompressInputList(compressedInputList): + """A function that convert Compressed Input List (List of 7-int-list, TTK .csv format) to + Raw Input List (List of Frames)""" + prevInputRaw = Frame(["0"]*8) + prevInputCompressed = [0,0,0,0,0,0,-1] + rawInputList = [] + for compressedInput in compressedInputList: + accel = compressedInput[0] + brake = int(compressedInput[1]>0) + item = compressedInput[2] + X = compressedInput[3] + Y = compressedInput[4] + dpad = compressedInput[5] + brakedrift = int(compressedInput[1]==3) + + if accel + brake < 2: + drift = 0 + elif prevInputRaw.drift: + drift = 1 + elif prevInputCompressed[1] == compressedInput[1]: + drift = 0 + else: + drift = 1 + + if compressedInput[6] != -1: + drift = compressedInput[6] + + rawInput = Frame(list(map(str, (accel, brake, item, drift, brakedrift, X, Y, dpad)))) + prevInputRaw = rawInput + prevInputCompressed = compressedInput + rawInputList.append(rawInput) + return rawInputList + + + class FrameSequence: """ A class representing a sequence of inputs, indexed by frames. @@ -205,13 +289,11 @@ def read_from_file(self) -> None: try: with open(self.filename, 'r') as f: reader = csv.reader(f) + compressedInputList = [] for row in reader: - frame = self.process(row) - if not frame: - # TODO: Handle error - pass - - self.frames.append(frame) + compressedInputList.append(list(map(int,row))) + for frame in decompressInputList(compressedInputList): + self.frames.append(frame) except IOError: return @@ -227,7 +309,7 @@ def write_to_file(self, filename: str) -> bool: try: with open(filename, 'w', newline='') as f: writer = csv.writer(f, delimiter=',') - writer.writerows(self.frames) + writer.writerows(compressInputList(self.frames)) except IOError: return False return True @@ -244,7 +326,8 @@ def process(self, raw_frame: List) -> Optional[Frame]: A new Frame object initialized with the raw frame, or None if the frame is invalid. """ - if len(raw_frame) != 6: + assert len(raw_frame) == 8 + if len(raw_frame) != 8: return None frame = Frame(raw_frame) diff --git a/scripts/Modules/ttk_lib.py b/scripts/Modules/ttk_lib.py index bd9540a..925dfce 100644 --- a/scripts/Modules/ttk_lib.py +++ b/scripts/Modules/ttk_lib.py @@ -28,8 +28,10 @@ def decode_face_button(input): A = input % 0x2 B = (input >> 1) % 0x2 L = (input >> 2) % 0x2 + D = (input >> 3) % 0x2 #drift button + BD = (input >> 4) % 0x2 #breakdrift button - return [A, B, L] + return [A, B, L, D, BD] def decode_direction_input(input): X = input >> 4 @@ -421,8 +423,7 @@ def set_buttons(inputs, controller : Controller): """This writes button data to addresses with implicit padding in structs. This must be called only after controller_patch()""" addr = controller.addr - memory.write_u8(addr + 0x4d, inputs.accel + (inputs.brake << 1) + - (inputs.item << 2) | ((inputs.accel & inputs.brake) << 3) + 0x80) + memory.write_u8(addr + 0x4d, inputs.accel + (inputs.brake << 1) + (inputs.item << 2) + (inputs.drift << 3) + (inputs.brakedrift << 4) + 0x80) memory.write_u8(addr + 0x4e, inputs.stick_x + 7) memory.write_u8(addr + 0x4f, inputs.stick_y + 7) memory.write_u8(addr + 0x52, inputs.dpad_raw())

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 F{s;J>P{sfN literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_classes/__pycache__/vehicle_physics.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/vehicle_physics.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e63880b935b0415dd00d6ffa62be8245b6093c2b GIT binary patch literal 11317 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 literal 0 HcmV?d00001 diff --git a/scripts/Modules/mkw_utils.py b/scripts/Modules/mkw_utils.py index d2d2dfd..afa977b 100644 --- a/scripts/Modules/mkw_utils.py +++ b/scripts/Modules/mkw_utils.py @@ -3,6 +3,8 @@ from .mkw_classes import mat34, quatf, vec3, ExactTimer from .mkw_classes import VehicleDynamics, VehiclePhysics, RaceManagerPlayer +import math + # These are helper functions that don't quite fit in common.py # This file also contains getter functions for a few global variables. @@ -81,5 +83,30 @@ def get_unrounded_time(lap, player): return t # TODO: Rotation display helper functions +def calculate_euler_angle(q): + """Param : quatf + Return : vec3 """ + x1, x2 = 2*q.x*q.w-2*q.y*q.z, 1-2*q.x*q.x-2*q.z*q.z + y1, y2 = 2*q.y*q.w-2*q.x*q.z, 1-2*q.y*q.y-2*q.z*q.z + z = 2*q.x*q.y + 2*q.z*q.w + roll = 180/math.pi * math.asin(z) + pitch = 180/math.pi * math.atan2(x1, x2) + yaw = 180/math.pi * math.atan2(y1, y2) + return vec3(pitch%360, yaw%360, roll%360) + +def get_facing_angle(player): + """Param : int player_id + Return : vec3 , correspond to facing angles""" + quaternion = VehiclePhysics(player).main_rotation() + return calculate_euler_angle(quaternion) + +def get_moving_angle(player): + """Param : int player_id + Return : vec3 , correspond to moving angles""" + s = delta_position(player) + roll = 180/math.pi * math.atan2(s.z, s.y) + pitch = 180/math.pi * math.atan2(s.x, s.z) + yaw = 180/math.pi * math.atan2(s.y, s.x) + return vec3(roll%360, pitch%360, yaw%360) -# TODO: Time difference display helper functions \ No newline at end of file +# TODO: Time difference display helper functions diff --git a/scripts/RMC/_draw_info_display.py b/scripts/RMC/_draw_info_display.py index b460731..71da179 100644 --- a/scripts/RMC/_draw_info_display.py +++ b/scripts/RMC/_draw_info_display.py @@ -256,7 +256,14 @@ def create_infodisplay(): stick_x = current_input_state.raw_stick_x() - 7 stick_y = current_input_state.raw_stick_y() - 7 - text += f"X: {stick_x} | Y: {stick_y}\n\n" + text += f"X: {stick_x} | Y: {stick_y}\n\n" + + if True : + fac = mkw_utils.get_facing_angle(0) + mov = mkw_utils.get_moving_angle(0) + text += f"X Fac: {fac.x:4.4f} | X Mov: {mov.x:4.4f}\n" + text += f"Y Fac: {fac.y:4.4f} | Y Mov: {mov.y:4.4f}\n" + text += f"Z Fac: {fac.z:4.4f} | Z Mov: {mov.z:4.4f}\n\n" return text From 4617d83ea4871e883ed9d4cbfb9f164a9f6fe004 Mon Sep 17 00:00:00 2001 From: Blounard Date: Tue, 12 Dec 2023 14:10:50 +0100 Subject: [PATCH 02/12] Rotation + Rotation speed Added rotation and rotation speed to the infodisplay. Should be ready to use. --- .../__pycache__/mkw_utils.cpython-38.pyc | Bin 3701 -> 3771 bytes scripts/Modules/infodisplay.ini | 3 +- scripts/Modules/mkw_utils.py | 18 ++++---- scripts/RMC/_draw_info_display.py | 43 ++++++++++++++---- ...input_display.py => draw_input_display.py} | 0 5 files changed, 45 insertions(+), 19 deletions(-) rename scripts/RMC/{_draw_input_display.py => draw_input_display.py} (100%) diff --git a/scripts/Modules/__pycache__/mkw_utils.cpython-38.pyc b/scripts/Modules/__pycache__/mkw_utils.cpython-38.pyc index af93e7679bc3d37a2d9228388f7975162574af6f..d1203797c34214ef37d0ea20be13cd85c4d85dd9 100644 GIT binary patch delta 1220 zcmZ8g&1)n@6z{6)ubH0C=40}qW|B3*ktR88W|80;vMVdD%dU8k6)7R1$!n5{-80$h z&d0zkE4W^~Nr8%o7*C!S6ufzmJqi04EOqm;IN(VTyv6r=3CvhfzxV3(uU@_Sz3PAF ze{F>K!mw)L7(6{rzWpj}Jp39LU;#_5j7gSp$ul7Zvw(w0?aYx*=1Mp7q?h^9FXJ}G zE3%SRWi<1I|g%5h2RmBm!JkAM#fdNYqL&6#Y9x%CC0SSXjB{AD)7&`8QPL@Xes-M)J`$8m;OQli zP0-rdDv9ADdM38mygnDFY(byeKP`?^N^W=?j28o_B+u16B`BexGbdtA{f%?aC81QH z|8{N#!-RL-WwxUC+{a4}5>kQiFS9Ie4QzDVe_|l=RE0Lz^t!h?J%?`O8m zUZT`%`o!B9N&B0(%3As_?~~Ult-_4fF3xg9T(!_ClSa0>LjIcW_^*y+_|9KtSM~3{ ze1kGXqNE!~#hu+mU8T^)R`d-k3~P_v{G&?5*7awV2CM7S%9D>l%vxa2SRm%C2QD~; zz3;qY7516eXMO$yuj7{?hBv|xeY<4f{s(^H_r1Q~cRv@{RagI5U7ey52fq;P;Z+BB z&(F{GAJygtH883ecHi)mHOWs}lK0T|TIxDgZL4mY8t0&0?CcrQi;qWca5Gr(FS8}~ zGE=wpQSiljKzqV0Zg;j-w}^{&x1(;;30$qAk=6T$agnGF#fN*`sx2?xLBbBT;bKt9 zG;iX}ztlx-`2%1m07r=!N`!w*!S*>y#Lh&Y?YlT%h%n3&|6@7CET!Tz`e|*R+4^y? z`7rAqwL80)v3F^bt2gmTb&cRHgveJbJ{+qzS(7a=^*$0JR=&t+Mn4IsCKbJO6J(zrZ||gWo+r6} z9xiUxDDe$~1%f6)S!nrq=>@8F0_uPwdCSy8rIbZA@PqL;vMwB^$tE=*r$4B!x5j4w E11q2ecmMzZ delta 1164 zcmZ8gOK%iM5T5RN^~`wvfVFY5tQ=w<8gK-*6kc+S5(rKdMIaEDMgomogT2no?$R^H zUTG~PFegq)M>$3$QVu9W0*PBraNrP;OOAcbi64M+ij=Cckap=-f7SDKcXid*HGeeU z?yp^|)j|u~t9zU2x8K*AcYnYSuz+P&&LqpZqtXQ4 zvA^3lSVM=-&#b8*J5OiEc75>{7(W3}X;G*KIjCU2-g0AhNdM|y^8#W+{hzxW4Q{yP z&9bAq@SZS7AMhKVply-Km9p2umAP0A93g? zLs-R8wV11UoG5Y{JL)*iPw1XFFy!GkF~=74-$H&$9%8%NZd{eLS5vhxcogS`m4>y3 za!i7lozxG5CZ_N>c=6S?2X^VKyA7*!9{GLN=fCi}we1hFcHgO3QHs6~&Xm;`6?%mC zZG0$KzYOO_DWo^g3Dz(*&7#AL^eS;+*lokN<|W@+ki3Vsx1c_w03FrIGUIkz<;t3| zd&%Zduq)9qQD;-w)w2F6dT@%W*3|N()xN1ZWm2{}ZM94{aCHKW3~z5FWvbf54?f(L zk=dEAal;BJ{;pB&&^V8yXzL$GW-o7ZU?p4Us0Mpv_u0CKV>fsEy%m>MD^;A*?{na& zid~^YSgB&`zoMmEdFM{6z4{TpP?i?zG~TApAjCo)rTG%UIfBm#NEWq7aF(Fb&#kgE ztWXz-`;y=y!C;QBYagHakWp9P;9AV8@`@*o51p*L)@mzGM{EQW<=<`IT*;E6z=%i# zePnc|TSd~OO@|1o=&F*Wx>6?zNNhz)R(A~CzxxZ}f)R^(2R5>FiL@@J5yts6t8*bl PLwKPOV= RaceState.COUNTDOWN.value: gui.draw_text((10, 10), c.color, create_infodisplay()) + @event.on_frameadvance def on_frame_advance(): - race_mgr = RaceManager() + global Prev_frame_data + global Frame_of_input + + race_mgr = RaceManager() if race_mgr.state().value >= RaceState.COUNTDOWN.value: gui.draw_text((10, 10), c.color, create_infodisplay()) + if Frame_of_input != mkw_utils.frame_of_input(): + Frame_of_input = mkw_utils.frame_of_input() + fac = mkw_utils.get_facing_angle(0) + mov = mkw_utils.get_moving_angle(0) + Prev_frame_data = (fac.x, fac.y, fac.z, mov.y) diff --git a/scripts/RMC/_draw_input_display.py b/scripts/RMC/draw_input_display.py similarity index 100% rename from scripts/RMC/_draw_input_display.py rename to scripts/RMC/draw_input_display.py From 6ee3ccee41f85095a25140e2d7f39cc726bd7c34 Mon Sep 17 00:00:00 2001 From: Blounard Date: Tue, 12 Dec 2023 15:40:52 +0100 Subject: [PATCH 03/12] Bugfix Fixed an issue in race manager : RaceState is 4 when the race is finished, not 3. (atleast for TTs). It was previously causing the info display to turn off on the race finish state, despite the code not aiming to do that. Fixed the Rotation speed calculation to not trigger error while not in a race. (It wasn't a big issue, it was just spamming the python log) --- .../__pycache__/race_manager.cpython-38.pyc | Bin 9852 -> 9852 bytes scripts/Modules/mkw_classes/race_manager.py | 4 ++-- scripts/RMC/_draw_info_display.py | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/Modules/mkw_classes/__pycache__/race_manager.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/race_manager.cpython-38.pyc index 377944c31246335cd50bd21150e488d19fc40ab3..b4585b2ae97bd1f29a5d5cff58873afae0d47d01 100644 GIT binary patch delta 924 zcmez4^T&rbl$V!_0SLHrD^mS8^2#wXvTW924B})e;-1{Vb%fDt@q#Ww}M39AGqmn?Z zWUzHX!V@{bia;UwT6nr#3Q%q(Gg1gZWx*kk4%V|-q>48Us0LVrk|phfq{QktXVDxD2HN0K9b@Bu;NDXMI3n$QP0WR66Hcg zKu%F1lDZPGy5kaA959zmwv?PHR0>juY-TX7mNoSBp+%5?!1Xd=gC4@iIs jl9qdciWi~8qSRzZ6|u=>%1uIj=q679nY>w6C7uZYC&8~De{4cScBO9V0HOCn;AVOEAtjHdQG0jd(ABXq=KV}9i)N{LeA#S*5yTsAmvc!CxI*k8_n4E(cV&2qUwITRZTkQ5h!6*r16;>d@HdQH}rC>JUQ za*B$O)RltO9hb=BfVpI{rQ}SZGLSlC%PYX@zDv&G0y~wnxFoS;vY@Q!oKbajnjbsJ@C5b8|jrVBNpt7`$P z`zY6lP*)}2E!2vxt{tpSOQ9N}Zmq&hp$>F)U0`+DiqnAM%%n6?t{bR86FDY(K>|#W iwA=?&ya**0r6xP7h)ph2ZW8K8H+dq+ bool: def inst_disable_lower_respawns(self) -> bool: """Delfino Plaza?""" disable_lower_respawns_ref = self.addr + 0x48 - return memory.read_u8(disable_lower_respawns_ref) > 0 \ No newline at end of file + return memory.read_u8(disable_lower_respawns_ref) > 0 diff --git a/scripts/RMC/_draw_info_display.py b/scripts/RMC/_draw_info_display.py index 757e990..cf6a7d3 100644 --- a/scripts/RMC/_draw_info_display.py +++ b/scripts/RMC/_draw_info_display.py @@ -297,8 +297,8 @@ def on_frame_advance(): race_mgr = RaceManager() if race_mgr.state().value >= RaceState.COUNTDOWN.value: gui.draw_text((10, 10), c.color, create_infodisplay()) - if Frame_of_input != mkw_utils.frame_of_input(): - Frame_of_input = mkw_utils.frame_of_input() - fac = mkw_utils.get_facing_angle(0) - mov = mkw_utils.get_moving_angle(0) - Prev_frame_data = (fac.x, fac.y, fac.z, mov.y) + if Frame_of_input != mkw_utils.frame_of_input(): + Frame_of_input = mkw_utils.frame_of_input() + fac = mkw_utils.get_facing_angle(0) + mov = mkw_utils.get_moving_angle(0) + Prev_frame_data = (fac.x, fac.y, fac.z, mov.y) From 379a4e4de96cd62347d6203bfc05787557e6b917 Mon Sep 17 00:00:00 2001 From: Blounard Date: Sat, 16 Dec 2023 18:06:57 +0100 Subject: [PATCH 04/12] info_display timediff Added time difference to info display Changed some code for the rotation speed. Added a class to store data from previous frames. Added Oriented speed to infodisplay --- .../__pycache__/mkw_utils.cpython-38.pyc | Bin 3771 -> 12339 bytes scripts/Modules/agc_lib.py | 118 ++++++++ scripts/Modules/infodisplay.ini | 14 +- scripts/Modules/infodisplay.ini.back | 26 ++ scripts/Modules/mkw_classes/__init__.py | 4 +- .../__pycache__/__init__.cpython-38.pyc | Bin 2702 -> 2723 bytes .../__pycache__/common.cpython-38.pyc | Bin 10501 -> 12264 bytes scripts/Modules/mkw_classes/common.py | 41 +++ scripts/Modules/mkw_utils.py | 265 +++++++++++++++-- scripts/Modules/test_del_me_later.py | 11 + scripts/RMC/_draw_info_display.py | 273 ++++++++++++------ scripts/RMC/test.py | 25 ++ 12 files changed, 664 insertions(+), 113 deletions(-) create mode 100644 scripts/Modules/agc_lib.py create mode 100644 scripts/Modules/infodisplay.ini.back create mode 100644 scripts/Modules/test_del_me_later.py create mode 100644 scripts/RMC/test.py diff --git a/scripts/Modules/__pycache__/mkw_utils.cpython-38.pyc b/scripts/Modules/__pycache__/mkw_utils.cpython-38.pyc index d1203797c34214ef37d0ea20be13cd85c4d85dd9..4a9774c34eaee14da95ee237184306cda924150a 100644 GIT binary patch literal 12339 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 delta 1452 zcmZux&2Jk;6yG=d;jwqU{!R={f{P%qYG_G}r2+{N8Wgym`MFKfLk7 zqJ2G|&nfs!AKmu8DBQOf$Y;v^m6Zu7j4&ZD2L$5U)`2EP^w)i-A z0hYwKxdFWk!+^pCuWWG46#SUqIh6EaE7!JKXJgtwE>d_lKj%L0@PgC_q62 zqL3#B;mi2D4dS<@y7)RnlstNHLFs(fT7Spkn?TA&xzlyU%?XJ=T~ZV z^g1+A19zAh!@wPToWCd@=Qry!S&)-tx?a@syU~W&wV#7E@sT|&uVH{^Wd@DED#xqh zPy6h}Q!^{0A#)?I@d|Aa#&Q6ScI>O?ZUM!N8RHfbLld#nx;>5 z?)JMLUze_@OW`7OlM&<-VjkT14^N(mm<4jCr32Aq?t|DZy)u#YI@ttnCggCnNeK>g+WUz*c5lz_S`un)H)xN7w9%u$<1Or1;C+ap&_+=|Fm4oH_Bw`JLevnQKYHvV^p(^qR`M!#5;I?NbHP=`#zbC8U2q jbh9^Lc#5{<5eemgM3vN`N+_jgsF9Mra@iM6%3RDr49^G2tvYl6o(;95r|L}q7;J|#UV}!NJza?)w`jal8~enq^Jja z#CKsY^+BI-2-B2-jBptHX#fUg@TUZu;d`)UKn=533cl|M>e8>IhbvdtI+A?o|sx#Ho69-=GR} zpU&eRnpZX(qB*TpEBd|3{-x8@r^vZF?Lq`49r-p%Sl*mSNp9Mx&6-FLeNk7*r~ZIvxM6&`Q? z92yQzG=B{Z9#86O`lG5*vwh#GR%)D6C7#k@T89}OW>tW+<&tOnj;{{&wtcSoUudW? zuNqo0IR>}*-nM+s>yfaSTD`~%x*^d{Z+2SLE+UTHOPiN;-agBst6rOzmEe`zuJ?8F zcva=lEmIdJmJQGG>;@OKZ9jl%=_lkhJr|cgOWlN1vUy#r_6F@s*w9mL;hAg_Z)$OK z!@8%&ceM&vJh`_TZ^?+9T)V!lL<2gCHIH``UcXS$EnV@h&Qq86g=3*@l&-2KIaZDL zv`*e=@8YVa?LB27E(?=cH7n}A_m$%N;(do~H;h?BAOr{@#33vJvajqR35km#NvCd9Aq%7AjHMpQN&QHDkM<>W z+pE4puR1fbvD2E5(f|LmNN3I&>7>6u9i!i$f7I=(saWhUCY`@7A}{FQSA;6DN?gS- z4)HkSF2Y^Vh27ANJo^bdg7fMIF2I7|L3I-gP!K$%Zs8&<3LaLsaS4_L zkEmr_ffZbZRpFz=@4y{ggEiq}#Mfb6@Flf@cj2z!adi*x!+pV*)dPG84+T%CNB9^X z3!YR@@F_eMd__IO=kQ$clzM@iu!&o+CH$(|#vRxZJgs(d5B3DlsC|41F9px41AGOq z1Yc9H@eRBYJf{xvExZ+cUA@C16a~+#AMgl{1m934JceVz3+e>l!+XIu)d&0t9|afG zj|c#QZ>gWK3}wNK>Sz1}pU?n9_-*wInqUfEQm1HvC3sm?&<30EN-0)Y{X0(Qt`HA1 zM|Rb5Yr9&zy3iB$e6_7LvFl+1&0u{aO#E6mgEIKn*VSR_SUc7i zc7=nbx;`^4yQp2y)`4UD;m8s3ZMSyjREx@N*jj4D!{kBDs|SZw&5MaVq7Y5JHg(V< zY03?>s}wzbSD52!;wlAZV2Ax%^&oI-n^r*0@F_QYa?o}Y&$ZJJYG*FrZ2#Q#gAdxF zWfC0{8kO-&fwoN~wQtjDJ-~njw9Ak;-Ch${XtR=K*G%p3ZSrk3S{*%oXQUkjPOa*P zqwToeTGgr9+sgF)?}PVEv=7~i-C2OOW-Eu=B{*tNnN@DZ@V1Md9XQ;YQuB5s4{~?k zoqo2h;Lxm@Rp~;yEmBAyvr_$(U{+u|JIVae{c6(_%06wm)Xgv@m)6#D%&R(jt^Aj! zIx9MKbf|Ugi?)kchS@f4u2W&B6qJo^ks_T(-jC)9VIME8Z{KUd6feF-y0=P2a?3+* zxs?Xtf#%WOY1B+~EY8j~rQ&(RXQhj#iHbD45nfc}N6O0Fv>TO(=7`$ZkrHk2+rnAc zYq^MSP4gE*ceCkXlVH=!rjJdM4SiT*n!htT!zRn7pG}U<0Gm9UK{AkXcv=jsYCXg} z>&Yw`BI{w2!t@vFWm6at!Md0nJ<3UWO{wnXsg^U)>5J&jg4Mp9_`gBkB+`gf?jGzeWt!CCrMZNZ(;8svqs~T3hgVn)JFPH4hNS_n;p@AS zB3+LB_gLsY^*w!`QM8;>8ZiBUdH!qk2{9_oA=3|89%#v4G-&z}t68br>gi*W^b^qo z`a)gw`YB5Zmb89GI2`UwGn%{poIJnB^bTFb{A2GtD(|?;J9la`#fIf-yIhIr5}H1p z_!cd1IrOG(lz+RoQ9kiWf8&~!a>>$;7x-m*jn=?TRY=3zYaBr2qf` diff --git a/scripts/Modules/mkw_classes/__pycache__/common.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/common.cpython-38.pyc index dda51bfbfa4b5395452bca436d399dc34074b0de..ad30a58eb1565245a6fcb09a9438c99d4cd82593 100644 GIT binary patch delta 3153 zcmcguYiwLc6~1%t-KY2EeRwy1^~TTLyy`rf78TOCjgyup&cjVfw<+7(ooi>E^{$z_ zu8CQ*fNh>hX*5k+nhG@tAtHekWQ0(EmB0J|et=Z%j|z~Gh!9i=ejxsY@64`ir>&|Y zB<|IG_nb55oH=vm%-LN#^XEe3Y&aa$@I-&L>|7bR8tG;Et2^ZgkMh{6mX99Ocqfmq zYCOK8=VOiuKEadVlPmfPyZX2K4#&G<$CfiHC?XSH7m=jHEUi}`9iUl3tES*&8My3 z(u0BGvu@EY+rpY#DA!8!~YWfNVC=?1g?8f!dK^Y-7 zq%VcY#~w8)|K+>P_R2N?sor}rpEJc?e8fJ2G{H`S{qpbrK6XGx13e8Lf{n)n;lX$W z!#xGytftMf9^~!~U1bUxx`C`MBYSl{1NkiS!Sx<(*?^9RbhwdFnWS%8y8#bxc`BKwk*X+u^ErC+pO`}+KZ<>NCvl*PWi>1m; z;gY?W54iJ=!xb6frRnK{U70C61z~d$A@>TRWaXQ#ibY%S`@ysl$GTaZQQ{iNTzj_o ze@%rrh+uNQ;no2?KmmV(VDpq(n|DhU@gUACG3s+m+*!0Qee#35z$V(0MJC_%X5{hk zkemq|>KP|pI#x{&v88}26yex>GS?~J3hYnq!HhUSa38^^2p*CrLj$rW80gP{4Z;ww z?lH-lo#8Iyu4qI3bOs#kc{sKz0N{erEW`yGuP%v|L zZ5p<&su?EEP|OVjlEWn30dTZD<62(lEN}22H@LaV@+S9iFM6Ga`?w!pFApG)j%LtV zC_7@D3V3N^+$xrB*R`;WH9>MqO}Kl4)J9sgRjOEAMdR+Wo^xu8j#Ft^yZ1gYX4w^P z;VUQsMRoQd=pp*Oj0}KjwZytsz$LAtg@e*T8HzGEawL3ELl>b2+VsqqYQ+mp1DCI9 zifXxx3A&Zy34*iaUpy)IjHVl92-+7d$bxJsvAI3;sZym>D-`a!Zq#)sJat&q7tl%2 zuV>Lg&}-0TK;!V14bZA{gEnhMU9TH;llrj=6kS4vk~<3z;z@!jz)epp%pMZ7V{OmN z-$#>;&q40`0UA|0-lh0m@!Fh!+;B5n!Ug?axS&56uJ{ZEbgn^ocgGTakS$_-R9No9 zbA`fW&QJ%v323NP?V^()4xrx+UM&_1B0!>E0`kAHrtJ2H)0C$YhFZ|iOg-rFd&QKx z<3}SGS&VL-c$(lm!87s~(fw>q{x~)$GqJ_~&yw(2f)Clr6{!8F;~AP&#!pM$IpQgR zzb3!kxfI*tmUQUnDIs^o{p`BDFMh92JVnx?tj055G7^rAdNcP>M9Ua1Z8xZ!x}V|I z{dgi?kw@r#@(=MNY)pnSG?|!Fp0;mW-{Of`((X14{RM(L0c}Bikw6u~mx%f@!B+@Y2v!N!2)?@B=w^E43h3WrxQ_xToMXDUqJsHn z@1OpQV9x()-2tTlc&G`rop#y~JK<<$d5lM=S57bU{uG z%%-n_+=X_vQGCqAE3PU19}L|i^}+bYrrsIql4FDCQZK_~ADPhqAk-@vysQk~96XxZ zvH-0@g)L@fYUrt+S3urRcJu?%vLjnqztUcA_m=QV@|~d*saK);(EHYU724;!KXe^h z?4tbH@SAg}U5yLj)DNpz;!QaDq-oP_6|fPEaNU?Mht76->*wvQc(W{wCWM&gv|d O!07NBk)(V#+w~t;ABC9! delta 1675 zcmd6nO>7%g5Xb%OUDvz**o~9eaUA26)M*?ib{i)YTGAHs)zUx!^iUUGwPn8fNfT*}|0U_p}#*wKwaKx+k z^US`P_n)^rZ-2}$z7W{&_v;S+eg4^;J=(GqXc2=;DcWQ!BM!^3%ms&KmYrphGuW@Q zg6s!vciELQ*{`=6*l&Qp^!;mk*_n%2%9taWs9X_0D`J*DcD2(DceK}5EbWG{bj!P- zRg85BK}WPJB1u1J`?hv-kx4~n_)l&E!axex z3>22fD^_^_Scoc#Rox}NZdR!h?fG?+zo!5d5H0{oox&<|_}b^tqpr%-^}$7U~mVI)M~subzwZPtL&UJ`YKVi1AR z0S?^7qu^t#R?4+22!kJd>lh(lL>vTj{uZiTw?9I~{hzN;cCk>4ZP0*fVpdrOJ0?h91eZ#qmXw z_}WOES&6eLaYiH>O_pe9qREZ= float (dot product) + vec3 * float -> vec3 (scalar multiplication)""" + if type(other) == vec3: + return self.x * other.x + self.y * other.y + self.z * other.z + else: + return vec3(self.x * other, self.y * other, self.z * other) + def length(self) -> float: return math.sqrt(self.x**2 + self.y**2 + self.z**2) def length_xz(self) -> float: return math.sqrt(self.x**2 + self.z**2) + def forward(self, facing_yaw) -> float: + speed_yaw = -180/math.pi * math.atan2(self.x, self.z) + diff_angle_rad = (facing_yaw - speed_yaw)*math.pi/180 + return math.sqrt(self.x**2 + self.z**2)*math.cos(diff_angle_rad) + + def sideway(self, facing_yaw) -> float: + speed_yaw = -180/math.pi * math.atan2(self.x, self.z) + diff_angle_rad = (facing_yaw - speed_yaw)*math.pi/180 + return math.sqrt(self.x**2 + self.z**2)*math.sin(diff_angle_rad) + @staticmethod def read(ptr) -> "vec3": bytes = memory.read_bytes(ptr, 0xC) @@ -81,6 +99,29 @@ def read(ptr) -> "quatf": bytes = memory.read_bytes(ptr, 0x10) return quatf(*struct.unpack('>' + 'f'*4, bytes)) +def angle_degree_format(angle): + return ((angle+180)%360) - 180 + +class eulerAngle: + """A class for Euler Angles. + Angles in degrees, between -180 and 180""" + def __init__(self, pitch=0, yaw=0, roll=0): + self.pitch = angle_degree_format(pitch) + self.yaw = angle_degree_format(yaw) + self.roll = angle_degree_format(roll) + + def __add__(self, other): + pitch = self.pitch + other.pitch + yaw = self.yaw + other.yaw + roll = self.roll + other.roll + return eulerAngle(pitch, yaw, roll) + + def __sub__(self, other): + pitch = self.pitch - other.pitch + yaw = self.yaw - other.yaw + roll = self.roll - other.roll + return eulerAngle(pitch, yaw, roll) + @dataclass class ExactTimer: """This is used in conjunction with the Exact Finish Code. diff --git a/scripts/Modules/mkw_utils.py b/scripts/Modules/mkw_utils.py index 17165de..6e1d718 100644 --- a/scripts/Modules/mkw_utils.py +++ b/scripts/Modules/mkw_utils.py @@ -1,7 +1,7 @@ from dolphin import memory, utils, event -from .mkw_classes import mat34, quatf, vec3, ExactTimer -from .mkw_classes import VehicleDynamics, VehiclePhysics, RaceManagerPlayer +from .mkw_classes import mat34, quatf, vec3, ExactTimer, eulerAngle +from .mkw_classes import VehicleDynamics, VehiclePhysics, RaceManagerPlayer, KartObjectManager, RaceManager, RaceState import math @@ -11,6 +11,42 @@ # NOTE (xi): wait for get_game_id() to be put in dolphin.memory before clearing # these commented-out lines: + +class FrameData: + def __init__(self): + #Default values + self.prc = 0 #PlayerRaceCompletion + self.grc = 0 #GhostRaceCompletion + self.euler = eulerAngle() + self.movangle = eulerAngle() + + #Value for current frame (if available) + if RaceManager().state().value >= RaceState.COUNTDOWN.value: + self.prc = RaceManagerPlayer(0).race_completion() + self.euler = get_facing_angle(0) + self.movangle = get_moving_angle(0) + if not is_single_player(): + self.grc = RaceManagerPlayer(1).race_completion() + +class History: + def __init__(self, size): + self.size = size + self.array = [] + self.index = 0 + for _ in range(size): + self.array.append(FrameData()) + + def update(self): + """Add a new frameData to the array, and move the index""" + self.index = (self.index+1)%self.size + self.array[self.index] = FrameData() + + def get_older_frame(self,i): + """Return the FrameData i frame older""" + assert i=value>value_list[i+1] + We suppose value_list[i+1] < value_list[i] + and value_list[0]>= value>=value_list[-1]""" + n = len(value_list) + if n == 1 : + return 0 + h = n//2 + if value <= value_list[h]: + return h+find_index(value, value_list[h:]) + return find_index(value, value_list[:h]) + +def get_time_difference_racecompletion(history): + """Use RaceCompletionData History to calculate the frame difference + The function assume that RaceCompletion is increasing every frames""" + curframe = history.get_older_frame(0) + lastframe = history.get_older_frame(-1) + inf = float('inf') + if curframe.prc>=curframe.grc: + if curframe.grc>lastframe.prc: + l = [history.get_older_frame(k).prc for k in range(history.size)] + i = find_index(curframe.grc, l) + t = i + (curframe.grc - l[i])/ (l[i+1] - l[i]) + return -t, t + return -inf, inf + else: + if curframe.prc>lastframe.grc: + l =[history.get_older_frame(k).grc for k in range(history.size)] + i = find_index(curframe.prc, l) + t = i + (curframe.prc - l[i])/ (l[i+1] - l[i]) + return t, -t + return inf, -inf diff --git a/scripts/Modules/test_del_me_later.py b/scripts/Modules/test_del_me_later.py new file mode 100644 index 0000000..039a936 --- /dev/null +++ b/scripts/Modules/test_del_me_later.py @@ -0,0 +1,11 @@ +def find_index(value, value_list): + """Find the index i so value_list[i]>=value>value_list[i+1] + We suppose value_list[i+1] < value_list[i] + and value_list[0]>= value>=value_list[-1]""" + n = len(value_list) + if n == 1 : + return 0 + h = n//2 + if value <= value_list[h]: + return h+find_index(value, value_list[h:]) + return find_index(value, value_list[:h]) diff --git a/scripts/RMC/_draw_info_display.py b/scripts/RMC/_draw_info_display.py index cf6a7d3..037ef3f 100644 --- a/scripts/RMC/_draw_info_display.py +++ b/scripts/RMC/_draw_info_display.py @@ -3,7 +3,8 @@ import math import os -from Modules.mkw_classes.common import SurfaceProperties +from Modules.mkw_classes.common import SurfaceProperties, eulerAngle +from Modules.mkw_utils import History import Modules.mkw_utils as mkw_utils from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState @@ -22,13 +23,18 @@ def populate_default_config(file_path): config['INFO DISPLAY']["Frame Count"] = "True" config['INFO DISPLAY']["Lap Splits"] = "False" config['INFO DISPLAY']["Speed"] = "True" + config['INFO DISPLAY']["Oriented Speed"] = "False" config['INFO DISPLAY']["Internal Velocity (X, Y, Z)"] = "False" + config['INFO DISPLAY']["Oriented Internal Velocity"] = "False" config['INFO DISPLAY']["Internal Velocity (XYZ)"] = "False" config['INFO DISPLAY']["External Velocity (X, Y, Z)"] = "False" + config['INFO DISPLAY']["Oriented External Velocity"] = "False" config['INFO DISPLAY']["External Velocity (XYZ)"] = "True" config['INFO DISPLAY']["Moving Road Velocity (X, Y, Z)"] = "False" + config['INFO DISPLAY']["Oriented Moving Road Velocity"] = "False" config['INFO DISPLAY']["Moving Road Velocity (XYZ)"] = "False" config['INFO DISPLAY']["Moving Water Velocity (X, Y, Z)"] = "False" + config['INFO DISPLAY']["Oriented Moving Water Velocity"] = "False" config['INFO DISPLAY']["Moving Water Velocity (XYZ)"] = "False" config['INFO DISPLAY']["Charges and Boosts"] = "True" config['INFO DISPLAY']["Checkpoints and Completion"] = "True" @@ -36,10 +42,18 @@ def populate_default_config(file_path): config['INFO DISPLAY']["Miscellaneous"] = "False" config['INFO DISPLAY']["Surface Properties"] = "False" config['INFO DISPLAY']["Position"] = "False" - config['INFO DISPLAY']["Rotation"] = "False" + config['INFO DISPLAY']["Rotation"] = "True" config['INFO DISPLAY']["Stick"] = "True" config['INFO DISPLAY']["Text Color (ARGB)"] = "0xFFFFFFFF" config['INFO DISPLAY']["Digits (to round to)"] = "6" + config['INFO DISPLAY']["TimeDiff Absolute"] = "True" + config['INFO DISPLAY']["TimeDiff Relative"] = "True" + config['INFO DISPLAY']["TimeDiff Projected"] = "True" + config['INFO DISPLAY']["TimeDiff CrossPath"] = "True" + config['INFO DISPLAY']["TimeDiff ToFinish"] = "True" + config['INFO DISPLAY']["TimeDiff RaceComp"] = "True" + config['INFO DISPLAY']["History Size"] = "50" + with open(file_path, 'w') as f: config.write(f) @@ -52,13 +66,18 @@ def __init__(self, config : configparser.ConfigParser): self.frame_count = config['INFO DISPLAY'].getboolean('Frame Count') self.lap_splits = config['INFO DISPLAY'].getboolean('Lap Splits') self.speed = config['INFO DISPLAY'].getboolean('Speed') + self.speed_oriented = config['INFO DISPLAY'].getboolean('Oriented Speed') self.iv = config['INFO DISPLAY'].getboolean('Internal Velocity (X, Y, Z)') + self.iv_oriented = config['INFO DISPLAY'].getboolean('Oriented Internal Velocity') self.iv_xyz = config['INFO DISPLAY'].getboolean('Internal Velocity (XYZ)') self.ev = config['INFO DISPLAY'].getboolean('External Velocity (X, Y, Z)') + self.ev_oriented = config['INFO DISPLAY'].getboolean('Oriented External Velocity') self.ev_xyz = config['INFO DISPLAY'].getboolean('External Velocity (XYZ)') self.mrv = config['INFO DISPLAY'].getboolean('Moving Road Velocity (X, Y, Z)') + self.mrv_oriented = config['INFO DISPLAY'].getboolean('Oriented Moving Road Velocity') self.mrv_xyz = config['INFO DISPLAY'].getboolean('Moving Road Velocity (XYZ)') self.mwv = config['INFO DISPLAY'].getboolean('Moving Water Velocity (X, Y, Z)') + self.mwv_oriented = config['INFO DISPLAY'].getboolean('Oriented Moving Water Velocity') self.mwv_xyz = config['INFO DISPLAY'].getboolean('Moving Water Velocity (XYZ)') self.charges = config['INFO DISPLAY'].getboolean('Charges and Boosts') self.cps = config['INFO DISPLAY'].getboolean('Checkpoints and Completion') @@ -67,42 +86,82 @@ def __init__(self, config : configparser.ConfigParser): self.surfaces = config['INFO DISPLAY'].getboolean('Surface Properties') self.position = config['INFO DISPLAY'].getboolean('Position') self.rotation = config['INFO DISPLAY'].getboolean('Rotation') + self.td_absolute = config['INFO DISPLAY'].getboolean('TimeDiff Absolute') + self.td_relative = config['INFO DISPLAY'].getboolean('TimeDiff Relative') + self.td_projected = config['INFO DISPLAY'].getboolean('TimeDiff Projected') + self.td_crosspath = config['INFO DISPLAY'].getboolean('TimeDiff CrossPath') + self.td_tofinish = config['INFO DISPLAY'].getboolean('TimeDiff ToFinish') + self.td_racecomp = config['INFO DISPLAY'].getboolean('TimeDiff RaceComp') + self.td = self.td_absolute or self.td_relative or self.td_projected or self.td_crosspath or self.td_tofinish or self.td_racecomp self.stick = config['INFO DISPLAY'].getboolean('Stick') self.color = int(config['INFO DISPLAY']['Text Color (ARGB)'], 16) self.digits = min(7, config['INFO DISPLAY'].getint('Digits (to round to)')) + self.history_size = config['INFO DISPLAY'].getint('History Size') + + +def make_line_text_speed(left_text_prefix, left_text_suffix, size, speed): + """Function to generate a line of text + It has "left_text" as a str on the left, + enough spaces to make the text on the left exactly size length + then it has ":" followed by the speed, finished with a \n. + Param: str left_text + int size + float speed + Return str text""" + return left_text_prefix+" "*(size - len(left_text_prefix+left_text_suffix))+left_text_suffix + f"{speed:.{c.digits}f}\n" + +def make_text_speed(speed, speedname, player, boolspd, boolspdoriented, boolspdxyz): + """Function to generate the text for a certain speed + Parameters : vec3 speed : the speed to generate the text for. + str speedname : the string to write before each line + int player : ID of the player (used for oriented speed, 0 if player) + bool boolspd : True if we draw the (X, Y, Z) speed + bool boolspdoriented : True if we draw (Forward, Sideway, Y) + bool boolspdxyz : True if we draw (XZ, XYZ) + Return str text ready to be displayed""" + text = "" + facing_yaw = mkw_utils.get_facing_angle(player).yaw + offset_size = 13 + if boolspd and boolspdoriented : + text += make_line_text_speed(speedname,"X: ", offset_size, speed.x) + text += make_line_text_speed(speedname,"Y: ", offset_size, speed.y) + text += make_line_text_speed(speedname,"Z: ", offset_size, speed.z) + text += make_line_text_speed(speedname,"Forward: ", offset_size, speed.forward(facing_yaw)) + text += make_line_text_speed(speedname,"Sideway: ", offset_size, speed.sideway(facing_yaw)) + elif boolspd : + text += make_line_text_speed(speedname,"X: ", offset_size, speed.x) + text += make_line_text_speed(speedname,"Y: ", offset_size, speed.y) + text += make_line_text_speed(speedname,"Z: ", offset_size, speed.z) + elif boolspdoriented : + text += make_line_text_speed(speedname,"Forward: ", offset_size, speed.forward(facing_yaw)) + text += make_line_text_speed(speedname,"Sideway: ", offset_size, speed.sideway(facing_yaw)) + text += make_line_text_speed(speedname,"Y: ", offset_size, speed.y) + if boolspdxyz : + text += make_line_text_speed(speedname,"XZ: ", offset_size, speed.length_xz()) + text += make_line_text_speed(speedname,"XYZ: ", offset_size, speed.length()) + return text -def main(): - config = configparser.ConfigParser() - - file_path = os.path.join(utils.get_script_dir(), 'modules', 'infodisplay.ini') - config.read(file_path) - - if not config.sections(): - config = populate_default_config(file_path) - - global c - c = ConfigInstance(config) - #Those 2 variables are used to store some parameters from the previous frame - global Prev_frame_data - Prev_frame_data = (0,0,0,0) - global Frame_of_input - Frame_of_input = 0 +def make_text_timediff(timediff, prefix_text, prefix_size, timesize): + player_text = f"{timediff[0]:.{c.digits}f}" + ghost_text = f"{timediff[1]:.{c.digits}f}" + player_text += " "*(timesize - len(player_text)) + player_text = player_text[:timesize]+"f" + ghost_text = ghost_text[:timesize]+"f" + return prefix_text+":"+" "*(prefix_size - len(prefix_text))+player_text+"| "+ghost_text+"\n" -if __name__ == '__main__': - main() +def make_text_rotation(rot, rotspd, prefix_text, prefix_size, rotsize): + rot_text = f"{rot:.{c.digits}f}" + rotspd_text = f"{rotspd:.{c.digits}f}" + rot_text += " "*(rotsize - len(rot_text)) + rot_text = rot_text[:rotsize] + rotspd_text = rotspd_text[:rotsize] + return prefix_text+":"+" "*(prefix_size - len(prefix_text))+rot_text+"| "+rotspd_text+"\n" # draw information to the screen def create_infodisplay(): text = "" - - if c.debug: - # test values here - text += f"{utils.get_game_id()}\n\n" - - if c.frame_count: - text += f"Frame: {mkw_utils.frame_of_input()}\n\n" race_mgr_player = RaceManagerPlayer() race_scenario = RaceConfigScenario(addr=RaceConfig.race_scenario()) @@ -114,7 +173,13 @@ def create_infodisplay(): vehicle_dynamics = VehicleDynamics(addr=kart_body.vehicle_dynamics()) vehicle_physics = VehiclePhysics(addr=vehicle_dynamics.vehicle_physics()) - + if c.debug : + value = mkw_utils.time_to_finish(0) + #text += f"Debug : {value}\n" + + if c.frame_count: + text += f"Frame: {mkw_utils.frame_of_input()}\n\n" + if c.lap_splits: # The actual max lap address does not update when crossing the finish line # for the final time to finish the race. However, for whatever reason, @@ -135,60 +200,30 @@ def create_infodisplay(): speed = mkw_utils.delta_position(playerIdx=0) engine_speed = kart_move.speed() cap = kart_move.soft_speed_limit() - text += f" XZ: {round(speed.length_xz(), c.digits)}\n" - text += f" XYZ: {round(speed.length(), c.digits)}\n" - text += f" Y: {round(speed.y, c.digits)}\n" - text += f" Engine: {round(engine_speed, c.digits)} / {round(cap, c.digits)}" - text += "\n\n" - - if (c.iv or c.iv_xyz): + text += make_text_speed(speed, "", 0, False, c.speed_oriented, c.speed) + text += f" Engine: {round(engine_speed, c.digits)} / {round(cap, c.digits)}\n" + text += "\n" + + if (c.iv or c.iv_xyz or c.iv_oriented): iv = vehicle_physics.internal_velocity() + text += make_text_speed(iv, "IV ", 0, c.iv, c.iv_oriented, c.iv_xyz) + text += "\n" - if c.iv: - text += f" IV X: {round(iv.x,c.digits)}\n" - text += f" IV Y: {round(iv.y,c.digits)}\n" - text += f" IV Z: {round(iv.z,c.digits)}\n\n" - - if c.iv_xyz: - text += f" IV XZ: {round(iv.length_xz(),c.digits)}\n" - text += f" IV XYZ: {round(iv.length(),c.digits)}\n\n" - - if (c.ev or c.ev_xyz): + if (c.ev or c.ev_xyz or c.ev_oriented): ev = vehicle_physics.external_velocity() + text += make_text_speed(ev, "EV ", 0, c.ev, c.ev_oriented, c.ev_xyz) + text += "\n" - if c.ev: - text += f" EV X: {round(ev.x,c.digits)}\n" - text += f" EV Y: {round(ev.y,c.digits)}\n" - text += f" EV Z: {round(ev.z,c.digits)}\n\n" - - if c.ev_xyz: - text += f" EV XZ: {round(ev.length_xz(),c.digits)}\n" - text += f" EV XYZ: {round(ev.length(),c.digits)}\n\n" - - if (c.mrv or c.mrv_xyz): + if (c.mrv or c.mrv_xyz or c.mrv_oriented): mrv = vehicle_physics.moving_road_velocity() + text += make_text_speed(mrv, "MRV ", 0, c.mrv, c.mrv_oriented, c.mrv_xyz) + text += "\n" - if c.mrv: - text += f" MRV X: {round(mrv.x,c.digits)}\n" - text += f" MRV Y: {round(mrv.y,c.digits)}\n" - text += f" MRV Z: {round(mrv.z,c.digits)}\n\n" - - if c.mrv_xyz: - text += f" MRV XZ: {round(mrv.length_xz(),c.digits)}\n" - text += f" MRV XYZ: {round(mrv.length(),c.digits)}\n\n" - - if (c.mwv or c.mwv_xyz): + if (c.mwv or c.mwv_xyz or c.mwv_oriented): mwv = vehicle_physics.moving_water_velocity() - - if c.mwv: - text += f" MWV X: {round(mwv.x,c.digits)}\n" - text += f" MWV Y: {round(mwv.y,c.digits)}\n" - text += f" MWV Z: {round(mwv.z,c.digits)}\n\n" - - if c.mwv_xyz: - text += f" MWV XZ: {round(mwv.length_xz(),c.digits)}\n" - text += f" MWV XYZ: {round(mwv.length(),c.digits)}\n\n" - + text += make_text_speed(mwv, "MWV ", 0, c.mwv, c.mwv_oriented, c.mwv_xyz) + text += "\n" + if c.charges or c.misc: kart_settings = KartSettings(addr=kart_object.kart_settings()) @@ -258,15 +293,42 @@ def create_infodisplay(): if c.rotation : fac = mkw_utils.get_facing_angle(0) mov = mkw_utils.get_moving_angle(0) - prev = Prev_frame_data - text += f"Facing X (Pitch): {fac.x:.4f}\n" - text += f"Facing Y (Yaw): {fac.y:.4f}\n" - text += f"Moving Y (Yaw): {mov.y:.4f}\n" - text += f"Facing Z (Roll): {fac.z:4.4f}\n" - text += f"Facing X' (Pitch): {fac.x-prev[0]:.4f}\n" - text += f"Facing Y' (Yaw): {fac.y-prev[1]:.4f}\n" - text += f"Moving Y' (Yaw): {mov.y-prev[3]:.4f}\n" - text += f"Facing Z' (Roll): {fac.z-prev[2]:4.4f}\n\n" + prevfac = Memory_History.get_older_frame(1).euler + prevmov = Memory_History.get_older_frame(1).movangle + facdiff = fac - prevfac + movdiff = mov - prevmov + prefix_size = 10 + rotsize = c.digits+4 + text += " "*(prefix_size+1)+"Rotation"+" "*(rotsize - 8)+"| Speed\n" + text += make_text_rotation(fac.pitch, facdiff.pitch, "Pitch", prefix_size, rotsize) + text += make_text_rotation(fac.yaw, facdiff.yaw, "Yaw", prefix_size, rotsize) + text += make_text_rotation(mov.yaw, movdiff.yaw, "Moving Y", prefix_size, rotsize) + text += make_text_rotation(fac.roll, facdiff.roll, "Roll", prefix_size, rotsize) + text += "\n" + + if c.td and not mkw_utils.is_single_player(): + size = 10 + timesize = c.digits+4 + text += "TimeDiff:"+" "*(timesize+size-15)+" Player | Ghost\n" + if c.td_absolute: + absolute = mkw_utils.get_time_difference_absolute() + text += make_text_timediff(absolute, "Absolute", size, timesize) + if c.td_relative: + relative = mkw_utils.get_time_difference_relative() + text += make_text_timediff(relative, "Relative", size, timesize) + if c.td_projected: + projected = mkw_utils.get_time_difference_projected() + text += make_text_timediff(projected, "Projected", size, timesize) + if c.td_crosspath: + crosspath = mkw_utils.get_time_difference_crosspath() + text += make_text_timediff(crosspath, "CrossPath", size, timesize) + if c.td_tofinish: + tofinish = mkw_utils.get_time_difference_tofinish() + text += make_text_timediff(tofinish, "ToFinish", size, timesize) + if c.td_racecomp: + racecomp = mkw_utils.get_time_difference_racecompletion(Memory_History) + text += make_text_timediff(racecomp, "RaceComp", size, timesize) + text += "\n" # TODO: figure out why classes.RaceInfoPlayer.stick_x() and # classes.RaceInfoPlayer.stick_y() do not update @@ -281,24 +343,49 @@ def create_infodisplay(): return text - +""" @event.on_savestateload def on_state_load(fromSlot: bool, slot: int): race_mgr = RaceManager() if race_mgr.state().value >= RaceState.COUNTDOWN.value: gui.draw_text((10, 10), c.color, create_infodisplay()) +""" + + +def main(): + config = configparser.ConfigParser() + + file_path = os.path.join(utils.get_script_dir(), 'modules', 'infodisplay.ini') + config.read(file_path) + + if not config.sections(): + config = populate_default_config(file_path) + + global c + c = ConfigInstance(config) + #Those 2 variables are used to store some parameters from previous frames + global Frame_of_input + Frame_of_input = 0 + + global Memory_History + size = max(c.history_size, int(c.rotation)+1) + Memory_History = History(size) + +if __name__ == '__main__': + main() @event.on_frameadvance def on_frame_advance(): - global Prev_frame_data global Frame_of_input + global Memory_History - race_mgr = RaceManager() - if race_mgr.state().value >= RaceState.COUNTDOWN.value: + race_mgr = RaceManager() + newframe = Frame_of_input != mkw_utils.frame_of_input() + draw = race_mgr.state().value >= RaceState.COUNTDOWN.value + if newframe: + Frame_of_input = mkw_utils.frame_of_input() + Memory_History.update() + + if draw: gui.draw_text((10, 10), c.color, create_infodisplay()) - if Frame_of_input != mkw_utils.frame_of_input(): - Frame_of_input = mkw_utils.frame_of_input() - fac = mkw_utils.get_facing_angle(0) - mov = mkw_utils.get_moving_angle(0) - Prev_frame_data = (fac.x, fac.y, fac.z, mov.y) diff --git a/scripts/RMC/test.py b/scripts/RMC/test.py new file mode 100644 index 0000000..7adbbaa --- /dev/null +++ b/scripts/RMC/test.py @@ -0,0 +1,25 @@ +from dolphin import event, gui, utils + +def main(): + global counter + counter = 0 + +if __name__ == '__main__': + main() + + + + + +""" +@event.on_savestateload +def on_state_load(fromSlot: bool, slot: int): +""" + +@event.on_frameadvance +def on_frame_advance(): + global counter + counter +=1 + print(counter) + + From 50592682dcfa3c7b79412b9c2f17ccaca60df8ab Mon Sep 17 00:00:00 2001 From: Blounard Date: Sat, 23 Dec 2023 01:14:00 +0100 Subject: [PATCH 05/12] TimeDiff Update + AGC + Bruteforcer Small changes to TimeDiff, to make the code more clean, and do less computations. Added Advanced Ghost Comp. (might still change a bit) Added a Bruteforcer (still wip) --- .gitignore | 4 + .../__pycache__/agc_lib.cpython-38.pyc | Bin 0 -> 8398 bytes .../bruteforcer_lib.cpython-38.pyc | Bin 0 -> 7504 bytes .../__pycache__/mkw_utils.cpython-38.pyc | Bin 12339 -> 11589 bytes scripts/Modules/agc_lib.py | 318 ++++++++++++------ scripts/Modules/bruteforcer_lib.py | 224 ++++++++++++ scripts/Modules/infodisplay.ini | 7 +- scripts/Modules/infodisplay.ini.back | 26 -- .../__pycache__/common.cpython-38.pyc | Bin 12264 -> 12998 bytes scripts/Modules/mkw_classes/common.py | 20 ++ scripts/Modules/mkw_utils.py | 221 ++++++------ scripts/Modules/test_del_me_later.py | 71 +++- scripts/RMC/Adv. Ghost Comp/Load_data.py | 46 +++ scripts/RMC/Adv. Ghost Comp/Save to file.py | 47 +++ scripts/RMC/Bruteforce.py | 67 ++++ scripts/RMC/_draw_info_display.py | 46 +-- scripts/RMC/test.py | 20 +- 17 files changed, 833 insertions(+), 284 deletions(-) create mode 100644 scripts/Modules/__pycache__/agc_lib.cpython-38.pyc create mode 100644 scripts/Modules/__pycache__/bruteforcer_lib.cpython-38.pyc create mode 100644 scripts/Modules/bruteforcer_lib.py delete mode 100644 scripts/Modules/infodisplay.ini.back create mode 100644 scripts/RMC/Adv. Ghost Comp/Load_data.py create mode 100644 scripts/RMC/Adv. Ghost Comp/Save to file.py create mode 100644 scripts/RMC/Bruteforce.py diff --git a/.gitignore b/.gitignore index 2c0ddba..7b29787 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ /scripts/MKW_Inputs/*.csv +scripts/Modules/test_del_me_later.py +scripts/Modules/test.bit +scripts/Modules/test_del_me_later.py +scripts/Modules/test_del_me_later.py diff --git a/scripts/Modules/__pycache__/agc_lib.cpython-38.pyc b/scripts/Modules/__pycache__/agc_lib.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5428c93aac147fd9d3dcc9fb465150470dee6448 GIT binary patch literal 8398 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 SvT!q)3*4ZTU(3N_Q28H@RkJk! literal 0 HcmV?d00001 diff --git a/scripts/Modules/__pycache__/bruteforcer_lib.cpython-38.pyc b/scripts/Modules/__pycache__/bruteforcer_lib.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a22b27ee100111a7d12a17619f981b39d6e9d95c GIT binary patch literal 7504 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 delta 3752 zcmdT{-)|gO6~1?V?d;m#IEiC#Vw+5xIPuh*rglNJAyrhU(y9tpNfZeUMdQuR+TP99 zyWG7=oMo1!I4Xhi&}68PB9+>rF9;-%!V?eliB~|Ccv+!JJXP=j5^wZ@@SQX3T|1(G z0JFMh&OP_sJNKOLoOAE~K6tp2zdAOS6L^04QK$03(!KnQeC6K4U3vcAZ#G9?7Ev)e zb4NsHwv1#+e#y442>*qL_vK56FG!lye~7oyzJk{J97rU!sL5%e#kLWPnu%uZ7!x8g zCIyx-+Y3qQ@RLic^+rj1w@bIw>zGts$2z{PO5oKsA`y|0$TvZJsp`qfRACwu!d2CH zBWyJ*mFPVTwG0qpsz&mcBcC4pfFuq}M&+nf&1Ae+=~&^XU9lmcHS z)!m2epfR@Pa`Nes=@+%JB|3&SBXdi3%-HN$F)X}ps&g@{n--8s?!SsYtj4$*TdM{v zwMt)vQAtv`)6IE!E?4vowc*XPPp?-zU3~)tOtW6PT~Xex z#*KR9>C$yb8(z7j%j-P6w%%xIUYeHwtOtvCA77Yfe&)LAXB8o<$R$0qy0Pk8YMBJz zB0`?)*{KC~Z#12dLed-I#rqvMsPK*}feNeb@}w)D0TBNhEb-a%^_-_@B}5r%>t?a?7YJa8n(W zzS*t^or(x#BmyInff>QrJ0h?mE3)ynBL}gZ=~ z&*d@>fE6s$lO-rdMFYGTdkvmJ<3SMHiG~<$LJEYwRGqfipt^;fiMWrKhJyGnhO9u9qEr|DWi#@*u(}^z&&(&d7G2 zy*N-?_8oNsO6nw$Ignl^91EjHISd&E^;Ys`rtmD4}8q*hCM9E#=pg*fKg6dI+1?y?c)y&i71{gEKouZzt_E6AqB z5bQAXgB&6A8s77u=i4tdFBc6KiLqnADNZ|Juu zi_+saEvpVEQXchVUnP0_;V0e`Mow)(TipRk3MUr2hY*u#^|46X5XK|Nn7|6p;iuk# z+P-R$g@&UOY;lZti6ja|BlwZG86e62Tbd8?(C_DWuwb89FnYaVW*e4q5ns?ka>VRiU7 zMVF38uGhZ17ewS>dN<{om8RoelF<#x&jvPsKvA*jS+rU(cC%7%l&ku7$cxjxmgfc; z{`h7)$np2niC?E-Z$LPE$LMMp>P85?S!|RL7>9~5r~r;LZdCu({p7i)X1kxq2zhx+ zZcAK>B)kZouCrSLd4tO=athZ~WS6aN0: + text = text[:-1] + text += ';' + if len(self.values)>0: + text = text[:-1] + return text+'\n' + + def read_from_string(self, string): + values = string.split(';') + for value in values: + self.values.append(bytearray([int(s) for s in value.split(',')])) + + def interpolate(self,other, selfi, otheri): + #Call only if self.value[0] represent a vec3 + v1 = vec3.from_bytes(self.values[0]) + v2 = vec3.from_bytes(other.values[0]) + v = (v1*selfi)+(v2*otheri) + self.values[0] = v.to_bytes() + + def write(self, addrlist): + for index in range(len(self.values)): + addr = addrlist[index][0] + val = self.values[index] + memory.write_bytes(addr, val) + +def float_to_str(f): + ms = round((f%1)*1000) + s = math.floor(f)%60 + m = math.floor(f)//60 + return f"{m},{s},{ms}" + +def floats_to_str(fs): + return f"{float_to_str(fs[0])};{float_to_str(fs[1])};{float_to_str(fs[2])}" + +class Split: + """Class for a lap split. Contain just a float, representing the split in s""" + def __init__(self, f): + self.val = f + def __str__(self): + return f"{self.val:.3f}" + def __add__(self,other): + return Split(max(0, self.val+other.val)) + + @staticmethod + def from_string(string): + return Split(float(string)) + + @staticmethod + def from_time_format(m,s,ms): + return Split(m*60+s+ms/1000) + + def time_format(self): + #return m,s,ms corresponding + f = self.val + ms = round((f%1)*1000) + s = math.floor(f)%60 + m = math.floor(f)//60 + return m,s,ms + + def bytes_format(self): + #return a bytearray of size 3 for rkg format + m,s,ms = self.time_format() + data_int = ms+s*1024+m*1024*128 + b3 = data_int%256 + data_int = data_int//256 + b2 = data_int%256 + data_int = data_int//256 + b1 = data_int%256 + return bytearray((b1,b2,b3)) + + +class TimerData: + """Class for the laps splits, both in RKG and Timer format + Cumulative convention (lap2 split is stored as lap1+lap2)""" + def __init__(self,string =None, readid=0): + #Call with a string OR when the race is finished + if string is None: + self.splits = [] #List of Split (size 3) + timerlist = [RaceManagerPlayer.lap_finish_time(readid, lap) for lap in range(3)] + for timer in timerlist: + self.splits.append(Split.from_time_format(timer.minutes(), timer.seconds(), timer.milliseconds())) + else: + self.splits = [] + laps = string.split(';') + for lap in laps: + self.splits.append(Split.from_string(lap)) + + def __str__(self): + text = 't' + for split in self.splits: + text += str(split)+";" + text = text[:-1] + return text+'\n' + + def add_delay(self, delay): + s = -delay/59.94 + for i in range(len(self.splits)): + self.splits[i] = Split(max(self.splits[i].val+s, 0)) + + + def to_bytes(self): + #A lap split is 3 bytes, so there is 9 bytes total + #Non cumulative format, ready to be written in a rkg + r = bytearray() + prev = 0 + for split in self.splits: + r = r + Split(split.val - prev).bytes_format() + prev = split.val + return r - file = open(csvfilename, 'w') + def write_rkg(self, ghostid): + s = bytearray('RKGD', 'ASCII') + rkg_addr = memory.read_u32(RaceConfig.chain() + 0xC0C) + if s == memory.read_bytes(rkg_addr, 4): + memory.write_bytes(rkg_addr+0x11, self.to_bytes()) + + +def metadata_to_file(filename, readid): + #Should be called before the countdown + metadata = FrameData(get_metadata_addr(readid)) + file = open(filename, 'w') if file is None : - gui.add_osd_message("Error : could not create the csv file") + gui.add_osd_message("Error : could not create the data file") else : - #Write the first line with CharaID and VehicleID - file.write(f"{data['CharaID']},{data['VehicleID']}\n") - - #Write the other lines with data[i] - for i in range(len(data.keys())-2): - pos = data[i]["Pos"] - qua = data[i]["Qua"] - iv = data[i]["IV"] - ev = data[i]["EV"] - spd1 = data[i]["BaseSpd"] - spd2 = data[i]["MaxSpd"] - angle = data[i]["Angle"] - dire = data[i]["Dire"] - dive = data[i]["Dive"] - - writeline = '' - writeline += f"{pos.x},{pos.y},{pos.z}," - writeline += f"{qua.x},{qua.y},{qua.z},{qua.w}," - writeline += f"{iv.x},{iv.y},{iv.z}," - writeline += f"{ev.x},{ev.y},{ev.z}," - writeline += f"{spd1}," - writeline += f"{spd2}," - writeline += f"{angle}," - writeline += f"{dire.x},{dire.y},{dire.z}," - writeline += f"{dive}\n" - file.write(writeline) + file.write(str(metadata)) + file.close() + gui.add_osd_message(f"{filename} successfully opened") + +def get_metadata(readid): + return FrameData(get_metadata_addr(readid)) +def frame_to_file(filename, readid): + frame = FrameData(get_addr(readid)) + file = open(filename, 'a') + if file is None : + gui.add_osd_message("Error : could not create the data file") + else : + file.write(str(frame)) + file.close() +def get_framedata(readid): + return FrameData(get_addr(readid)) + +def timerdata_to_file(filename, rid): + timerdata = TimerData(readid = rid) + file = open(filename, 'a') + if file is None : + gui.add_osd_message("Error : could not create the data file") + else : + file.write(str(timerdata)) file.close() - gui.add_osd_message(f"Data successfully stored to {csvfilename}") -def csv_to_data(csvfilename): - """Invert data_to_csv""" - data = {} - file = open(csvfilename, 'r') +def get_timerdata(rid): + return TimerData(readid = rid) + +def file_to_framedatalist(filename): + datalist = [] + file = open(filename, 'r') if file is None : - gui.add_osd_message("Error : could not load the csv file") + gui.add_osd_message("Error : could not load the data file") else: listlines = file.readlines() - #Read the first line for CharaID and VehicleID - values = listlines[0].split(",") - data["CharaID"] = values[0] - data["VehicleID"] = values[1] - - #Read the other lines for data[i] + metadata = FrameData(string = listlines[0]) + timerdata = None + if listlines[-1][0]=='t': + timerdata = TimerData(string = listlines.pop()[1:]) for i in range(1, len(listlines)): - data[i-1] = {} - values_string = listlines[i].split(",") - values = [float(string) for string in values_string] - data[i-1]["Pos"] = vec3(values[0], values[1], values[2]) - data[i-1]["Qua"] = quatf(values[3], values[4], values[5], values[6]) - data[i-1]["IV"] = vec3(values[7], values[8], values[9]) - data[i-1]["EV"] = vec3(values[10], values[11], values[12]) - data[i-1]["BaseSpd"] = values[13] - data[i-1]["MaxSpd"] = values[14] - data[i-1]["Angle"] = values[15] - data[i-1]["Dire"] = vec3(values[16], values[17], values[18]) - data[i-1]["Dive"] = values[19] + datalist.append(FrameData(string = listlines[i])) + file.close() + gui.add_osd_message(f"Data successfully loaded from {filename}") + return metadata, datalist, timerdata + +def framedatalist_to_file(filename, datalist, rid): + metadata = get_metadata(rid) + timerdata = get_timerdata(rid) + file = open(filename, 'w') + if file is None : + gui.add_osd_message("Error : could not create the data file") + else: + file.write(str(metadata)) + for frame in range(max(datalist.keys())+1): + if frame in datalist.keys(): + file.write(str(datalist[frame])) + else: + file.write(str(FrameData(get_addr(rid), usedefault=True))) + file.write(str(timerdata)) file.close() - gui.add_osd_message(f"Data successfully loaded from {csvfilename}") - return data - -def init_data(): - """Return a data dic, with default values - for each frame before the current frame""" - data = {} - default_frame_data = {} - default_frame_data["Pos"] = vec3(0,0,0) - default_frame_data["Qua"] = quatf(0,0,0,0) - default_frame_data["IV"] = vec3(0,0,0) - default_frame_data["EV"] = vec3(0,0,0) - default_frame_data["BaseSpd"] = 0 - default_frame_data["MaxSpd"] = 0 - default_frame_data["Angle"] = 0 - default_frame_data["Dire"] = vec3(0,0,0) - default_frame_data["Dive"] = 0 - frame = mkw_utils.frame_of_input() - for i in range(frame): - data[i] = default_frame_data - return data - - -def update_data(data): - """Update data to the currentn frame""" - frame = mkw_utils.frame_of_input() - currframe_data = {} - currframe_data["Pos"] = VehiclePhysics(0).position() - currframe_data["Qua"] = VehiclePhysics(0).main_rotation() - currframe_data["IV"] = VehiclePhysics(0).internal_velocity() - currframe_data["EV"] = VehiclePhysics(0).external_velocity() - currframe_data["BaseSpd"] = KartMove(0).speed() - currframe_data["MaxSpd"] = KartMove(0).soft_speed_limit() - currframe_data["Angle"] = KartMove(0).outside_drift_angle() - currframe_data["Dire"] = KartMove(0).dir() - currframe_data["Dive"] = KartMove(0).diving_rotation() - data[frame] = currframe_data - - +def get_addr(player_id): + a = VehiclePhysics.chain(player_id) + b = KartMove.chain(player_id) + return [(a+0x68, 12), #Position + (a+0xF0, 16), #Rotation + (a+0x74, 12), #EV + (a+0x14C, 12), #IV + (b+0x18, 4), #MaxEngineSpd + (b+0x20, 4), #EngineSpd + (b+0x9C, 4), #OutsideDriftAngle + (b+0x5C, 12)]#Dir + +def get_metadata_addr(player_id): + a = RaceConfig.chain() + player_id*0xF0 + return [(a+0x30, 8)]#CharacterID and VehicleID + diff --git a/scripts/Modules/bruteforcer_lib.py b/scripts/Modules/bruteforcer_lib.py new file mode 100644 index 0000000..bd7aba5 --- /dev/null +++ b/scripts/Modules/bruteforcer_lib.py @@ -0,0 +1,224 @@ +from dolphin import controller, event, savestate + +from Modules.framesequence import Frame +from Modules import ttk_lib + +def save(name): + b = savestate.save_to_bytes() + f = open(name, 'wb') + f.write(b) + f.close() + +def load(name): + f = open(name, 'rb') + b = f.read() + f.close() + savestate.load_from_bytes(b) + +def prevframe(frame, frequency): + return frame-1 - (frame-2)%frequency + + +class Input: + def __init__(self, A, B=None, L=None, H=None, V=None, D=None): + if B is None: + if type(A) == int: + r = A + self.A = r%2 == 1 + r= r//2 + self.B = r%2 == 1 + r= r//2 + self.L = r%2 == 1 + r= r//2 + self.H = r%15 + r= r//15 + self.V = r%15 + r= r//15 + self.D = r%5 + else : + raise TypeError("When calling Input(i) with 1 argument, i must be int") + else : + self.A = A + self.B = B + self.L = L + self.H = H + self.V = V + self.D = D + + def __int__(self): + r = 0 + r+= int(self.A) + r+= int(self.B)*2 + r+= int(self.L)*4 + r+= int(self.H)*8 + r+= int(self.V)*120 + r+= int(self.D)*1800 + return r + + def __str__(self): + return f"{str(self.A)}, {str(self.B)}, {str(self.L)}, {str(self.H)}, {str(self.V)}, {str(self.D)}" + + +class InputIterable: + def __init__(self, iterable, rule=None): + if rule is None: + rule = lambda x : True + self.rule = rule + try: + inp = next(iterable) + while not rule(inp): + inp = next(iterable) + self.val = inp + self.iterator = iterable + except StopIteration: + self.val = None + self.iterator = iterable + print("Tried to Init a InputIterable with iterator not letting any rule(value)") + + def __next__(self): + self.val = next(self.iterator) + while not self.rule(self.val): + self.val = next(self.iterator) + + + + + +class InputList: + """Class for List of InputRuled iterator + Accessing with an index not in the list will create a new InputRuled iterator + InputList[frame] should be an Input + InputList.inputlist[frame] is an InputIterable + ruleset must be a function : int -> rule + rule type is a function : Input -> bool + iterset must be a function : int -> itergen + itergen type is a function : list(Input) -> Iter(Input) """ + def __init__(self, ruleset, iterset): + self.inputlist = {} + self.ruleset = ruleset + self.iterset = iterset + + def __getitem__(self, index): + if not index in list(self.inputlist.keys()): + if index>0: + iterable = self.iterset(index)([self[index-1]]) + self.inputlist[index] = InputIterable(iterable, self.ruleset(index)) + else: + iterable = self.iterset(index)([]) + self.inputlist[index] = InputIterable(iterable, self.ruleset(index)) + return self.inputlist[index].val + + def __str__(self): + return str([int(self[i]) for i in range(10)]) + + def update(self,frame): + """Update the list. + Return the frame of last modification""" + if frame<0: + raise ValueError('Tried to update a InputList with from a negative frame') + self[frame] + self[frame+1] + self[frame+2] + del self.inputlist[frame+1] + del self.inputlist[frame+2] + try: + next(self.inputlist[frame]) + return frame + except StopIteration: + del self.inputlist[frame] + return self.update(frame-1) + +def first_input_ruled(rule): + for i in range(9000): + if rule(i): + return Input(i) + +def last_input_ruled(rule): + for i in range(8999, -1, -1): + if rule(i): + return Input(i) + + +def simple_order_iterator(l): + for i in range(9000): + yield Input(i) + +def last_input_iterator(l): + j = 0 + if len(l)>0: + j = int(l[0]) + for i in range(9000): + yield Input((i+j)%9000) + +def _123rule(inp): + return int(inp)<4 + +def basic_rule(inp): + #Rule for 3 possible inputs : Gi straight, turn left, turn right + return inp.A and (not inp.B) and (not inp.L) and (inp.H in [0,7,14]) and (inp.V==7) and (inp.D==0) +def forward_rule(inp): + #Rule for 1 possible input : Press A. + return inp.A and (not inp.B) and (not inp.L) and (inp.H ==7) and (inp.V==7) and (inp.D==0) + +forward = Input(True, False, False, 7, 7, 0) +ruleset123 = lambda x : _123rule + +itersetconst = lambda x : simple_order_iterator + +big = InputList(ruleset123, itersetconst) + +def run_input(inp): + gc_input = {} + #trick input + gc_input['Left'] = inp.D==3 + gc_input['Right'] = inp.D==4 + gc_input['Up'] = inp.D==1 + gc_input['Down'] = inp.D==2 + + #button input + gc_input['A'] = inp.A + gc_input['B'] = inp.B + gc_input['L'] = inp.L + + #stick input + match = {0 : 59, + 1 : 68, + 2 : 77, + 3 : 86, + 4 : 95, + 5 : 104, + 6 : 112, + 7 : 128, + 8 : 152, + 9 : 161, + 10 : 170, + 11 : 179, + 12 : 188, + 13 : 197, + 14 : 205} + gc_input['StickX'] = match[inp.H] + gc_input['StickY'] = match[inp.V] + + #Everything else, irrelevant + gc_input['Z'] = False + gc_input['R'] = False + gc_input['X'] = False + gc_input['Y'] = False + gc_input['Start'] = False + gc_input['CStickX'] = 0 + gc_input['CStickY'] = 0 + gc_input['TriggerLeft'] = 0 + gc_input['TriggerRight'] = 0 + gc_input['AnalogA'] = 0 + gc_input['AnalogB'] = 0 + gc_input['Connected'] = True + + controller.set_gc_buttons(0, gc_input) + +def makeFrame(inp): + f = Frame([str(int(i)) for i in [inp.A, inp.B, inp.L, inp.H-7, inp.V-7, inp.D]]) + return f + +def run_input2(inp): + f = makeFrame(inp) + ttk_lib.write_player_inputs(f) diff --git a/scripts/Modules/infodisplay.ini b/scripts/Modules/infodisplay.ini index 3e20cd4..42dc53d 100644 --- a/scripts/Modules/infodisplay.ini +++ b/scripts/Modules/infodisplay.ini @@ -5,12 +5,12 @@ debug = False frame count = True lap splits = False speed = True -oriented speed = True +oriented speed = False internal velocity (x, y, z) = False oriented internal velocity = False internal velocity (xyz) = False external velocity (x, y, z) = False -oriented external velocity = True +oriented external velocity = False external velocity (xyz) = True moving road velocity (x, y, z) = False oriented moving road velocity = False @@ -34,5 +34,6 @@ timediff projected = True timediff crosspath = True timediff tofinish = True timediff racecomp = True -history size = 50 +timediff setting = ahead +history size = 200 diff --git a/scripts/Modules/infodisplay.ini.back b/scripts/Modules/infodisplay.ini.back deleted file mode 100644 index 7eb7939..0000000 --- a/scripts/Modules/infodisplay.ini.back +++ /dev/null @@ -1,26 +0,0 @@ -[DEBUG] -debug = False - -[INFO DISPLAY] -frame count = True -lap splits = False -speed = True -internal velocity (x, y, z) = False -internal velocity (xyz) = False -external velocity (x, y, z) = False -external velocity (xyz) = True -moving road velocity (x, y, z) = False -moving road velocity (xyz) = False -moving water velocity (x, y, z) = False -moving water velocity (xyz) = False -charges and boosts = True -checkpoints and completion = True -airtime = True -miscellaneous = False -surface properties = False -position = True -rotation = True -stick = True -text color (argb) = 0xFFFFFFFF -digits (to round to) = 6 - diff --git a/scripts/Modules/mkw_classes/__pycache__/common.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/common.cpython-38.pyc index ad30a58eb1565245a6fcb09a9438c99d4cd82593..5c677e850240863a0be7017efc61cf6765b45901 100644 GIT binary patch delta 5332 zcmd5=+jAS$8Q1D!OR^+O^4+=E;D$tYY*Ra-G=;!wwURbk?JB#g2$_%*$C8OdVuvGz z5MxH6N!rp-E;%hNlorxHr7uj&OrLmYXF7D+2YBqvVWu;E>5zxQbeL&p+LwOcu5LE@ z11in_bk4Wmp6~vhv-*sDRE-qF;h+mX&%SY^dUW5fBd_}e&ffLi5cab|Y?M9P^RVzC z`_S_Md#7irQR%CMuDh1{s@_WY9ibAb^k4Tbg_^TyB?hx_a~7`*z%0_74OWI=)?bZQ zT=tX0m67Y-Yr;~jO&P6>*_3#7z~&gQ?1Co-E4xisVh{H|S6x}8Y`FKy=nN=JM-WC4 z4zibeUle8mN7;z~-}kyb!VU)>Xsoz_z4h_I051uy+P4Aft}Wr3P#2zY)6-k7bM7tS zoM+GlBM*$+gRW86i|*#kYty|B2hcr0#~E-np9Bt|d+WlMd&{%sz2-4p^^=0b)?#Wc zKIp>R6#>k2Z$34Nc1}L-{LCJ8eh;kBjaqH;BHgH5TB#?3lU*N&pZ(RJXwW&ZgWB$K zJcCnoRKiCw#B^7S(DWQmBW>u15f2h_VYz3#c!B)i;qbLQdBn)C?j@GXRnUe1!WwRQR^n+@#}GE51b8vKv<=<4b!co8#*-iI*5 zLjCve-VZ|+u9_FXhX; zbw7;h6cPmPIa9Cg^h8g3_gcmPE#Q@VVGqDtI*ae3t#$2XmHx>w-*^$kb8B0T1(Cv1k% z5skUlEiExb(HS&`5J#}RegH=agpQ2eINgIVkMJPELkQnM5D~C!=`;d{fMyXCgd9RU zvDj0wzIiMNT&*?<5QHGX*X{Sf*YEF(c;M@c_}oI&3m1gsR(z11?+JYHtMIZQs2FA+ z%2;EI{WEGFMzo`|hEpA(fPmql27-xTA)rs_34{{D69|st*j{~@JxlD5{rd#9DVPPL z7kaTsxNw=hKQhdY`exbhqocx7TbD~rh&?#bQKRF!C$}%ZYYFD-aM^X-v>mK>3v`KH ziye-A6Yi~@g>12X1_{Xi6q^oj;uCh73G~#h_&>C)Tn{cB(f@{18SIrOL7rgGE z&)-AIt@xe~4h)?UQma6wPa~W~SOegJ^$mJq`TW{u^^V8s2p)R2#yzxJ@8krG`(w+d!ORcSc@*2$ysgM={*9wq8%Ton?J1P$yS*uK5hG-C<`(H>2D2 zqKDZR-VtA&67oKaj6L|ZDz5x2LIU9cLMQ2Q8Ctiq1C4xxHO9t-Rm_gxO$FF*$5O%q z`|sGC$wT>~nKg7hPo!dj2h*xvk_~(8H!aZ_^_c}(Qbg4z2h6OjI>TU6)ZpuItFoB3 zM{H|+YT^Bc`U8lDcT5h-B!d$)hEdXp)SsrWz!# zXfhA0MJ1!Ol?bOq#Vog{QP4*_p~xkYRWjLFQkEnUc?=2LT{3{AlIW-i@k}Yj zJh%afU|e1=Y8FW25%57-H?s09Zk0WJ= zJBE>#%9-R?QOkha3Zjuiw+&>HVw1P&IkE^2NY03`W|?G)<)%|YEhP(zZ1BFMs!KUi zP{k#YvrkapaJs1F%B1C-u$3+8`9jlv$5)cB=M>pd5)3C+Nl_u1;2pha%6!naI4N2X zKO*Tx!<5OPriR;yi#%c*ohzG?0Wmaagqh(1-*rgr57`S7PYKssh4HV654sAYF$o;> z2Eum`zKei`LBEIaGQ#%}P9oeycm?4H2(Kc%hVVMV8wj@$7{U(`euVHQ!jBPtg76l? z+Xz2}BY=y(gTtQzXo>whc46KR-qTW8COHw31~O zO+|uS7c)ra0X?0@5`bYa-%vCK<7rwv0KQL=lA>jJUs@IOGD)jtUpu3X9;B2l96L;xOb`V-z(F zg!q$6lO<>tGY!!&Aqg!WwEK_qY%f%ulmp)0C8a>%0;99Q1g^ns1_Sb9M#(|vfJ){8 zNK!FpyVeKo9Bv1}RFW(vp&>#C(A7d#fwmxGN%G!8R@5v#-`t(p6X8hkV~G7{aMiNx z>O{^>KX!8U^Z%nf-QS(3^yiqd?;^a1a2w$l2)|^P_boQK&+e5RcClpHX>Yu@*(-UE z(}$Wj?Vip9*oc!5d}ze>GtToqySs8P?j^i0rE588c{v>t)MqzU?z4l|e8yq+TY3X> z8}f{YoStsM9$XN)&k^ObyDj%66(glXf-0$0b4`B^;|s;Z1CEO17=+T%3^x+k!tH)$ zE8vGsOH>t2*7k1uX0IW;gVWhvAm4iO}ET} zE>c6h7h_XuH)C6D_kvBi-F$7qQ5AbYx7>I)rD;T?i>+mAhpjENi>qa8hpR0z*f9($ zt>tPSXtVO5vw!Agt%warF?-9zp0I-lrh;EWT1MamT{{i6Rbp4CLT>tHYcKfpz@cN# zAqkWBGJpoJw0N-Uya@3CIYdg(0%5lfkcHMT)*g~pw_xSO%;+@8dK~5XVU^bLj7|$o zh!5BÊJ*k2OyR&9Tg7@FrpdeJhKlnhN;N!x7(yZt@Lc57pc)6>KAAR~=(dfIa6 zd`HS_)9Lbd%jolH))fFP5!h*C(2(H}3Ol%{a*tFf@?J=FIH76WXP-BCk0IxEs41@o zRmzTshjuT5@Ej@-YAfKJMd@NkjTdHS`#Neo&%oL#=+n4C!GS}QRj6HiVu<+y_a7_5 z`Jf=CP{8mJSlrxU;gQbL3kM%-be6{0bu6U#ililiJI#!l797mrgs8w#B`LzT$OrAs zBdtQCcgUKK2alapIL)a%*2PvPsyv;xczhepz{3lV*?V=@jU~>;XJ_^v1#6x_i}1YN z%8jPejyje-H~Y$123U5!yx`IO4BIugzssE`S$-}t$-U57Rj3VJRZ>LPlk^dIp7%C) zdCuOPJLJPmS!SQijf~?cv77f+HqKu>3xA~GdnEM$@LThHghjS@es6vTY53|(@dcHh zLckY3YQNRt3kb!76~%pvVu3+^17J!*@BuJ%6s@IcfgO(xvv=nofPbAnn!o>lw_H2E delta 4587 zcmcIoTWlOx8TQ&8n=m) zj!i-$!cv+LN=XHrCM`)tUy#~Lpem|(K;i*jkU$86)EE3fpAZD`z+<^o;{RvXyK5&% z2#Kub^Ev;V^WXpfoXIb$f95?-JRWI-f4#rCQoS*Dx98iz02A*7uLZ`%(a~Y?MAzei zH^fgn#>EGTn0T*i$f$N!qHhN(u}b`ECyUl+J(XUV#p<&}B?+^5eb!g$hgnaxx63BPa-2gd9R1K}9%*P(aWSiU_`fn6JI) z65O_ic17C7-M)bkC|-8# z&tjiFh2(oIc?8HSrvso9rc@eA>D|;s&neu20c;Dnrmx1QLt*jH)V+Wyem$@=YQrnn zL0H114~AiQM#Kg$O}4zj*A~G0K^H659YJV$@9jjhUlJ#Vc8fm^mb*&0+4RB&*SqVtV6{WfOlCwG2g4iRO{RR$kHkVI)Iz z`1z|fg=D>vU_1Bi!JvO1o;9pQaPyX*d&*biCp&+oJrD0)Y%%U>1PqP)0>X<3XAt%P z+{dK2kCDG01#pkzD2{-scHeW_qWJBu@77qnNKBP-Ni`)$wOMbGQtmwpk!i_dJq?R< z)XXWYH)lG>$L2+%X{=8!a7(A93?-(_C6ihf zOO#Ne#dB1XYrLrH3X5xwno}D}#ATvd<;FAt`sholQsQ|vmoJerDs6xYwy7vM?a6?q zifM6)Shl9Hm`PL}Xxs$VSX?&C93RtBb&Ev`lo}8PVt_HVoTPI@AyS@a5LprlTV2wR zq!RH}gec3ZQv^2v5sWKRN4G&5>j58>sg+m36PjkRUYN@YXk~-eNJs#|my`ovD4C}=UKl;&E=_O^Ce)fl=&P>>W3HVD@`JKjz}O0GS18> zHrI$Qvp%G3bI%~sUM}ub}(ccs0vE%J${qp%}?8B%3 z%kptoVY7P<;XJ}ogqILpgf)akgmr{3B3uwR_U){F8HZO8zJgFg_$tE72wy{Z1>q{f zHH5DN=;{62j$qacuF_?!nF4_ff^^zSfCSu1&{!-(Ymgt%jx2@PEFo#cvQ!B&pX89t z!Ze%3f`DNJs!qjVS~d%VpJiTB^&E?4HBwY~Rx87rxRh5E10qSF>|ts-2JnVhQ~1kz z4b>!io^ZpYB@J2Hs$MH|TLr~gL?&h1R1I7iK88_-EbubL0ro_L4#7f}VX8WkBYCPT zWr!(OWW%hCT2Qta?h#rI_Xrx~p92+P^Nd<6C@fs`iWxSum~W2h=sHLVWmH@P^oZp^ z30jbFHj8-8$ftKh2}%W6+Raph!vjX=VG+0nQy26vlAKzAHUe48!cdc>;CVI(9Uopt z_JOH9<7A*cLO-CIk%v-{2^J*lHu6NbX;I9k1|l~g>L0W^px0$tC!Q%RDpS1xt*$^JH-lbtWkD}q^*#RLkWFil)!1iZes8zogf<8Z z`l5nf*JZ(sYRVK+Q0Ydwt7OAOwdO(NvwVgoS4t zoLnj=c+4rR*4IkPDjubZI-~iZG7&qFkj#$ z=yh;Lhxy#*FxeRL&9)$p9Go1!37ZeXrG4{8>|NE|o4&mA)Nb+PgMD4TO!1wmfoV2C z9otf61sbuM^?C`m^oNkW-XxNTCI)YTj5(Ci1q1&&=-xsJ&y}}Y)4Txc>F{>DBBlbD zP&k{3#yTX!Vcn3-a2L~A(7Q>nE>kH|sG3e4>JaTHpPfSuYnE2V$uEDo})l=JydCTXPn0~6(Ab zaN~ljp9*)541p7lrM!b6t3lKD$vVXg!*(iM(=?WBSytwn(vh{9_}z4WiY2|1w&gWr z;*;sgUAIAh8TH4jbE{7}1MclML1x|wyxsT^)5YIs_P2OwQB2OJ_pnZAg&O2G)l`{N znsL7eyf(V)2Qm}uvkSpHKq`tK%?|CrQF?TvyK?T#`P1;J?|sg90FjA5% vec3 (cross product) + vec3 @ float -> vec3 (scalar multiplication)""" + if type(other) == vec3: + x = self.y*other.z - self.z*other.y + y = self.z*other.x - self.x*other.z + z = self.x*other.y - self.y*other.x + return vec3(x,y,z) + else: + return vec3(self.x * other, self.y * other, self.z * other) + def length(self) -> float: return math.sqrt(self.x**2 + self.y**2 + self.z**2) @@ -67,6 +78,15 @@ def read(ptr) -> "vec3": bytes = memory.read_bytes(ptr, 0xC) return vec3(*struct.unpack('>' + 'f'*3, bytes)) + @staticmethod + def from_bytes(bts) -> "vec3": + return vec3(*struct.unpack('>' + 'f'*3, bts)) + + def to_bytes(self) -> bytearray: + return bytearray(struct.pack('>fff', self.x, self.y, self.z)) + + + @dataclass class mat34: e00: float = 0.0 diff --git a/scripts/Modules/mkw_utils.py b/scripts/Modules/mkw_utils.py index 6e1d718..0ee0c80 100644 --- a/scripts/Modules/mkw_utils.py +++ b/scripts/Modules/mkw_utils.py @@ -154,12 +154,28 @@ def get_moving_angle(player): speed = delta_position(player) return speed_to_euler_angle(speed) -def get_yaw_from_speed(speed): - """Param : vec3 speed - Return float yaw""" - return (-180/math.pi * math.atan2(speed.y, speed.x))%360 # TODO: Time difference display helper functions +"""The time difference functions. +time_difference_[name](P1, S1, P2, S2) is a function that takes as arguments +P1,S1 : Player1's Position and Speed vec3. +P2,S2 : Player2's Position and Speed vec3 +Return the time it would take for Player1 to catch Player2 (not always symmetric) + +get_time_difference_[name](Player1, Player2) takes as arguments +Player1 : Player1 ID +Player2 : Player2 ID +Return the time it would take for Player1 to catch Player2 (not always symmetric) +It's the function called in draw_infodisplay.py +""" + +def get_physics(player1, player2): + """Take the Player1 and Player2 ID's, return their + P1, S1, P2, S2 data""" + P1, S1 = VehiclePhysics(player1).position(), delta_position(player1) + P2, S2 = VehiclePhysics(player2).position(), delta_position(player2) + return P1,S1,P2,S2 + def get_distance_ghost_vec(): """Give the distance (vec3) between the player and the ghost @@ -172,102 +188,72 @@ def get_distance_ghost(): """Give the distance(float) between the player and the ghost""" return get_distance_ghost_vec().length() -def get_time_difference_absolute(): +def time_difference_absolute(P1, P2, S1, S2): + s = S1.length() + if s != 0: + return (P2-P1).length() / s + return float('inf') + +def get_time_difference_absolute(player1, player2): """Time difference "Absolute" (simple and bad) - Simply takes the distance player-ghost, and divide it by raw speed (always positive) - Return (float, float) t1, t2 : t1 is the time the player would take to catch the ghost - t2 is the time the ghost would take to catch the player""" - player_speed = delta_position(0).length() - ghost_speed = delta_position(1).length() - distance = get_distance_ghost() - t1 = float('inf') - t2 = t1 - if player_speed != 0: - t1 = distance/player_speed - if ghost_speed != 0: - t2 = distance/ghost_speed - return t1, t2 - -def get_time_difference_relative(): + Simply takes the distance player-ghost, and divide it by raw speed (always positive)""" + P1, S1, P2, S2 = get_physics(player1, player2) + return time_difference_absolute(P1, P2, S1, S2) + +def time_difference_relative(P1, P2, S1, S2): + L = (P2 - P1).length() + if L == 0: + return 0 + s = S1*(P2-P1)/L + if s == 0: + return float('inf') + return (P2-P1).length() / s + +def get_time_difference_relative(player1, player2): """Time difference "Relative" - Take distance player-ghost. Divide it by the player's speed "toward" the ghost (dot product) - Return (float, float) t1, t2 : t1 is the time the player would take to catch the ghost - t2 is the time the ghost would take to catch the player""" - player_speed_vec = delta_position(0) - ghost_speed_vec = delta_position(1) - distance_vec = get_distance_ghost_vec() - distance = distance_vec.length() - t1 = float('inf') - t2 = t1 - if distance != 0: - player_relative_speed = player_speed_vec * distance_vec * (1/distance) - if player_relative_speed != 0: - t1 = distance/player_relative_speed - ghost_relative_speed = ghost_speed_vec * distance_vec * (-1/distance) - if ghost_relative_speed != 0: - t2 = distance/ghost_relative_speed - return t1, t2 - return 0, 0 - - -def get_time_difference_projected(): + Take distance player-ghost. Divide it by the player's speed "toward" the ghost (dot product)""" + P1, S1, P2, S2 = get_physics(player1, player2) + return time_difference_relative(P1, P2, S1, S2) + +def time_difference_projected(P1, P2, S1, S2): + s = S1.length() + if s == 0: + return float('inf') + return (P2-P1)*S1/(s**2) + +def get_time_difference_projected(player1, player2): """ Time difference "Projected" Take the distance between the player and the plane oriented by the player speed, covering the ghost. Then divide it by the player raw speed This is the 2D version because no numpy""" - distance_p_g = get_distance_ghost_vec() - player_speed = delta_position(0) - ghost_speed = delta_position(1) - t1 = float('inf') - t2 = t1 - if player_speed.length() != 0: - t1 = distance_p_g * player_speed * (1/player_speed.length()**2) - if ghost_speed.length() != 0: - t2 = distance_p_g * ghost_speed * (-1/ghost_speed.length()**2) - return t1, t2 - - - -class Line: - """2D lines - ax + bz + c = 0""" - def __init__(self, pointA, pointB): - self.a = pointB.z - pointA.z - self.b = pointA.x - pointB.x - self.c = -(self.b*pointA.z + self.a*pointA.x) - - def intersect(self,other): - """2 Lines intersecting, return point of intersection, (x,y)""" - det = self.a*other.b-other.a*self.b - x = float('inf') - y = x - if det!=0: - x = (other.c*self.b - self.c*other.b)/det - y = (self.c*other.a - other.c*self.a)/det - return x,y - -def get_time_difference_crosspath(): + P1, S1, P2, S2 = get_physics(player1, player2) + return time_difference_projected(P1, P2, S1, S2) + + +def time_to_cross(A, S, B, C): + """If A is going at a constant speed S, how many frame will it take + to cross the vertical plan containing B and C + Param : A, S, B, C : (vec3),(vec3),(vec3),(vec3) + Return t (float) """ + N = (B-C)@vec3(0,1,0) #normal vector to the plan containing B,C + ns = N*S + if ns != 0: + return N*(B-A)/ns + return float('inf') + +def time_difference_crosspath(P1, P2, S1, S2): + t1 = time_to_cross(P1, S1, P2, P2+S2) + t2 = time_to_cross(P2, S2, P1, P1+S1) + return t1-t2 + + +def get_time_difference_crosspath(player1, player2): """Time difference "CrossPath" Take both XZ trajectories of the player and the ghost Calculate how much time it takes them to reach the crosspoint. (2D only) Return the difference.""" - player_pos = VehiclePhysics(0).position() - ghost_pos = VehiclePhysics(1).position() - player_speed = delta_position(0) - player_speed.y = 0 - ghost_speed = delta_position(1) - ghost_speed.y = 0 - LinePlayer = Line(player_pos, player_pos+player_speed) - LineGhost = Line(ghost_pos, ghost_pos+ghost_speed) - x,z = LinePlayer.intersect(LineGhost) - intersectpoint = vec3(x, 0, z) - t_player = float('inf') - t_ghost = t_player - if player_speed.length_xz() != 0 : - t_player = (intersectpoint - player_pos)*player_speed / (player_speed.length_xz()**2) - if ghost_speed.length_xz() != 0 : - t_ghost = (intersectpoint - ghost_pos)*ghost_speed / (ghost_speed.length_xz()**2) - return t_player-t_ghost, t_ghost-t_player + P1, S1, P2, S2 = get_physics(player1, player2) + return time_difference_crosspath(P1, P2, S1, S2) @@ -285,30 +271,17 @@ def get_finish_line_coordinate(): return pointA, pointB -def time_to_cross(point, speed, line): - """Return how fast a point going at speed cross the line""" - velocity_line = Line(point, point+speed) - x,z = line.intersect(velocity_line) - speedxz = vec3(speed.x, 0, speed.z) - crosspoint = vec3(x,0,z) - t = float('inf') - if speed.length_xz() != 0: - t = (crosspoint - point)*speedxz/(speedxz.length() **2) - return t +def time_difference_tofinish(P1, P2, S1, S2): + A,B = get_finish_line_coordinate() + t1 = time_to_cross(P1, S1, A, B) + t2 = time_to_cross(P2, S2, A, B) + return t1-t2 -def time_to_finish(player): - pos = VehiclePhysics(player).position() - speed = delta_position(player) - pointA, pointB = get_finish_line_coordinate() - finish_line = Line(pointA, pointB) - return time_to_cross(pos, speed, finish_line) - -def get_time_difference_tofinish(): +def get_time_difference_tofinish(player1, player2): """Assume player and ghost are not accelerated. Calculate the time to the finish line for both, and takes the difference.""" - t_player = time_to_finish(0) - t_ghost = time_to_finish(1) - return t_player-t_ghost, t_ghost-t_player + P1, S1, P2, S2 = get_physics(player1, player2) + return time_difference_tofinish(P1, P2, S1, S2) def find_index(value, value_list): @@ -334,12 +307,30 @@ def get_time_difference_racecompletion(history): l = [history.get_older_frame(k).prc for k in range(history.size)] i = find_index(curframe.grc, l) t = i + (curframe.grc - l[i])/ (l[i+1] - l[i]) - return -t, t - return -inf, inf + return -t + return -inf else: if curframe.prc>lastframe.grc: l =[history.get_older_frame(k).grc for k in range(history.size)] i = find_index(curframe.prc, l) t = i + (curframe.prc - l[i])/ (l[i+1] - l[i]) - return t, -t - return inf, -inf + return t + return inf + + +def get_timediff_settings(string): + if string == 'player': + return 0, 1 + if string == 'ghost': + return 1, 0 + pp, sp, pg, sg = get_physics(0,1) + player_is_ahead = int(sp*(pg-pp)>0) + if string == 'ahead': + return 1-player_is_ahead, player_is_ahead + if string == 'behind': + return player_is_ahead, 1-player_is_ahead + else: + print('TimeDiff setting value not recognized. Default to "player"') + return 0, 1 + + diff --git a/scripts/Modules/test_del_me_later.py b/scripts/Modules/test_del_me_later.py index 039a936..10ef031 100644 --- a/scripts/Modules/test_del_me_later.py +++ b/scripts/Modules/test_del_me_later.py @@ -1,11 +1,60 @@ -def find_index(value, value_list): - """Find the index i so value_list[i]>=value>value_list[i+1] - We suppose value_list[i+1] < value_list[i] - and value_list[0]>= value>=value_list[-1]""" - n = len(value_list) - if n == 1 : - return 0 - h = n//2 - if value <= value_list[h]: - return h+find_index(value, value_list[h:]) - return find_index(value, value_list[:h]) +import math +import struct + +class vec3: + x: float = 0.0 + y: float = 0.0 + z: float = 0.0 + + def __add__(self, other): + return vec3(self.x + other.x, self.y + other.y, self.z + other.z) + + def __sub__(self, other): + return vec3(self.x - other.x, self.y - other.y, self.z - other.z) + + def __mul__(self, other): + """ vec3 * vec3 -> float (dot product) + vec3 * float -> vec3 (scalar multiplication)""" + if type(other) == vec3: + return self.x * other.x + self.y * other.y + self.z * other.z + else: + return vec3(self.x * other, self.y * other, self.z * other) + + def __matmul__(self, other): + """ vec3 @ vec3 -> vec3 (cross product) + vec3 @ float -> vec3 (scalar multiplication)""" + if type(other) == vec3: + x = self.y*other.z - self.z*other.y + y = self.z*other.x - self.x*other.z + z = self.x*other.y - self.y*other.x + return vec3(x,y,z) + else: + return vec3(self.x * other, self.y * other, self.z * other) + + def length(self) -> float: + return math.sqrt(self.x**2 + self.y**2 + self.z**2) + + def length_xz(self) -> float: + return math.sqrt(self.x**2 + self.z**2) + + def forward(self, facing_yaw) -> float: + speed_yaw = -180/math.pi * math.atan2(self.x, self.z) + diff_angle_rad = (facing_yaw - speed_yaw)*math.pi/180 + return math.sqrt(self.x**2 + self.z**2)*math.cos(diff_angle_rad) + + def sideway(self, facing_yaw) -> float: + speed_yaw = -180/math.pi * math.atan2(self.x, self.z) + diff_angle_rad = (facing_yaw - speed_yaw)*math.pi/180 + return math.sqrt(self.x**2 + self.z**2)*math.sin(diff_angle_rad) + + @staticmethod + def read(ptr) -> "vec3": + bytes = memory.read_bytes(ptr, 0xC) + return vec3(*struct.unpack('>' + 'f'*3, bytes)) + + @staticmethod + def from_bytes(bts) -> "vec3": + return vec3(*struct.unpack('>' + 'f'*3, bts)) + + def to_bytes(self) -> bytearray: + return bytearray(struct.pack('>fff', self.x, self.y, self.z)) diff --git a/scripts/RMC/Adv. Ghost Comp/Load_data.py b/scripts/RMC/Adv. Ghost Comp/Load_data.py new file mode 100644 index 0000000..4409040 --- /dev/null +++ b/scripts/RMC/Adv. Ghost Comp/Load_data.py @@ -0,0 +1,46 @@ +from dolphin import event, gui, utils +import Modules.agc_lib as lib +from Modules.mkw_classes import RaceManager, RaceState +import Modules.mkw_utils as mkw_utils +import os +from math import floor + +def main(): + global filename + filename = os.path.join(utils.get_script_dir(), r'AGC_Data\ghost.data') + + global delay + delay = 2500 + + global framedatalist + global timerdata + global metadata + + metadata, framedatalist, timerdata = lib.file_to_framedatalist(filename) + + timerdata.add_delay(delay) + + +if __name__ == '__main__': + main() + + +@event.on_frameadvance +def on_frame_advance(): + racestate = RaceManager().state().value + frame = mkw_utils.frame_of_input() + delayed_frame = floor(delay)+frame + decimal_delay = delay - floor(delay) + + metadata.write(lib.get_metadata_addr(1)) + + timerdata.write_rkg(0) + if 0 < delayed_frame+1 < len(framedatalist) and racestate >= RaceState.COUNTDOWN.value and not mkw_utils.is_single_player(): + + #print(timerdata) + f1 = lib.FrameData(string = str(framedatalist[delayed_frame])) #Makes a copy so you can modify f1 without affecting the framedatalist + f2 = framedatalist[delayed_frame+1] + f1.interpolate(f2, 1-decimal_delay, decimal_delay) + f1.write(lib.get_addr(1)) + + diff --git a/scripts/RMC/Adv. Ghost Comp/Save to file.py b/scripts/RMC/Adv. Ghost Comp/Save to file.py new file mode 100644 index 0000000..c03069b --- /dev/null +++ b/scripts/RMC/Adv. Ghost Comp/Save to file.py @@ -0,0 +1,47 @@ +from dolphin import event, gui, utils +import Modules.agc_lib as lib +from Modules.mkw_classes import RaceManager, RaceState +import Modules.mkw_utils as mkw_utils +import os + + +def main(): + global filename + filename = os.path.join(utils.get_script_dir(), r'AGC_Data\ghost.data') + + global framedatalist + framedatalist = {} + + global end + end = False + + global metadata_saved + metadata_saved = False + +if __name__ == '__main__': + main() + + +@event.on_frameadvance +def on_frame_advance(): + global framedatalist + global end + global metadata_saved + + racestate = RaceManager().state().value + frame = mkw_utils.frame_of_input() + + if (not metadata_saved) and racestate >= RaceState.COUNTDOWN.value: + lib.metadata_to_file(filename, 0) + metadata_saved = True + + if RaceState.RACE.value >= racestate >= RaceState.COUNTDOWN.value: + framedatalist[frame] = lib.get_framedata(0) + lib.frame_to_file(filename, 0) + end = False + + if (not end) and racestate == RaceState.FINISHED_RACE.value: + lib.framedatalist_to_file(filename, framedatalist, 0) + end = True + + diff --git a/scripts/RMC/Bruteforce.py b/scripts/RMC/Bruteforce.py new file mode 100644 index 0000000..68ea0d3 --- /dev/null +++ b/scripts/RMC/Bruteforce.py @@ -0,0 +1,67 @@ +from dolphin import controller, event +from Modules import bruteforcer_lib as bfl +from Modules import mkw_utils as utils +from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState + +def main(): + def ruleset(x): + if x<250: + return bfl.forward_rule + return bfl.basic_rule + + iterset = lambda x : bfl.last_input_iterator + + global IptList + IptList = bfl.InputList(ruleset, iterset) + + global ss_frequency + ss_frequency = 60 + + global distance_key + distance_key = 0 + + global delay_input + delay_input = 1 + + + +if __name__ == '__main__': + main() + +def savename(frame): + return str(frame)+'.rawsav' + + +@event.on_frameadvance +def on_frame_advance(): + frame = utils.frame_of_input() + if RaceManager().state().value >= RaceState.COUNTDOWN.value and not utils.is_single_player(): + if utils.get_distance_ghost() <= distance_key : + if frame%ss_frequency == 1: + bfl.save(savename(frame)) + bfl.run_input(IptList[frame]) + else: + modif_frame = IptList.update(frame-delay_input) + frame_to_load = bfl.prevframe(modif_frame, ss_frequency) + print(f"desync at {frame}, modifying input at {modif_frame}, loading {frame_to_load}") + bfl.run_input(IptList[frame_to_load]) + bfl.load(savename(frame_to_load)) + #bfl.run_input2(bfl.forward) + + + + + + + + + + + + + + + + + + diff --git a/scripts/RMC/_draw_info_display.py b/scripts/RMC/_draw_info_display.py index 037ef3f..2991b9d 100644 --- a/scripts/RMC/_draw_info_display.py +++ b/scripts/RMC/_draw_info_display.py @@ -7,7 +7,7 @@ from Modules.mkw_utils import History import Modules.mkw_utils as mkw_utils -from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState +from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState, TimerManager from Modules.mkw_classes import RaceConfig, RaceConfigScenario, RaceConfigSettings from Modules.mkw_classes import KartObject, KartMove, KartSettings, KartBody from Modules.mkw_classes import VehicleDynamics, VehiclePhysics, KartBoost, KartJump @@ -46,13 +46,14 @@ def populate_default_config(file_path): config['INFO DISPLAY']["Stick"] = "True" config['INFO DISPLAY']["Text Color (ARGB)"] = "0xFFFFFFFF" config['INFO DISPLAY']["Digits (to round to)"] = "6" - config['INFO DISPLAY']["TimeDiff Absolute"] = "True" - config['INFO DISPLAY']["TimeDiff Relative"] = "True" + config['INFO DISPLAY']["TimeDiff Absolute"] = "False" + config['INFO DISPLAY']["TimeDiff Relative"] = "False" config['INFO DISPLAY']["TimeDiff Projected"] = "True" - config['INFO DISPLAY']["TimeDiff CrossPath"] = "True" + config['INFO DISPLAY']["TimeDiff CrossPath"] = "False" config['INFO DISPLAY']["TimeDiff ToFinish"] = "True" config['INFO DISPLAY']["TimeDiff RaceComp"] = "True" - config['INFO DISPLAY']["History Size"] = "50" + config['INFO DISPLAY']["TimeDiff Setting"] = "behind" + config['INFO DISPLAY']["History Size"] = "200" with open(file_path, 'w') as f: @@ -92,6 +93,7 @@ def __init__(self, config : configparser.ConfigParser): self.td_crosspath = config['INFO DISPLAY'].getboolean('TimeDiff CrossPath') self.td_tofinish = config['INFO DISPLAY'].getboolean('TimeDiff ToFinish') self.td_racecomp = config['INFO DISPLAY'].getboolean('TimeDiff RaceComp') + self.td_set = config['INFO DISPLAY']['TimeDiff Setting'] self.td = self.td_absolute or self.td_relative or self.td_projected or self.td_crosspath or self.td_tofinish or self.td_racecomp self.stick = config['INFO DISPLAY'].getboolean('Stick') self.color = int(config['INFO DISPLAY']['Text Color (ARGB)'], 16) @@ -143,12 +145,13 @@ def make_text_speed(speed, speedname, player, boolspd, boolspdoriented, boolspdx def make_text_timediff(timediff, prefix_text, prefix_size, timesize): - player_text = f"{timediff[0]:.{c.digits}f}" - ghost_text = f"{timediff[1]:.{c.digits}f}" - player_text += " "*(timesize - len(player_text)) - player_text = player_text[:timesize]+"f" - ghost_text = ghost_text[:timesize]+"f" - return prefix_text+":"+" "*(prefix_size - len(prefix_text))+player_text+"| "+ghost_text+"\n" + timediffms = timediff/59.94 + ms = f"{timediffms:.{c.digits}f}" + frame = f"{timediff:.{c.digits}f}" + ms += " "*(timesize - len(ms)) + ms = ms[:timesize] + frame = frame[:timesize]+"f" + return prefix_text+":"+" "*(prefix_size - len(prefix_text))+ms+"| "+frame+"\n" def make_text_rotation(rot, rotspd, prefix_text, prefix_size, rotsize): @@ -174,8 +177,9 @@ def create_infodisplay(): vehicle_physics = VehiclePhysics(addr=vehicle_dynamics.vehicle_physics()) if c.debug : - value = mkw_utils.time_to_finish(0) - #text += f"Debug : {value}\n" + t = TimerManager() + value = t.race_frame_counter() + text += f"Debug : {value}\n" if c.frame_count: text += f"Frame: {mkw_utils.frame_of_input()}\n\n" @@ -309,21 +313,23 @@ def create_infodisplay(): if c.td and not mkw_utils.is_single_player(): size = 10 timesize = c.digits+4 - text += "TimeDiff:"+" "*(timesize+size-15)+" Player | Ghost\n" + p1, p2 = mkw_utils.get_timediff_settings(c.td_set) + s = 1 if 1-p1 else -1 + text += "TimeDiff:"+" "*(timesize+size-16)+"Seconds | Frames\n" if c.td_absolute: - absolute = mkw_utils.get_time_difference_absolute() + absolute = mkw_utils.get_time_difference_absolute(p1,p2) text += make_text_timediff(absolute, "Absolute", size, timesize) if c.td_relative: - relative = mkw_utils.get_time_difference_relative() + relative = s*mkw_utils.get_time_difference_relative(p1,p2) text += make_text_timediff(relative, "Relative", size, timesize) if c.td_projected: - projected = mkw_utils.get_time_difference_projected() + projected = s*mkw_utils.get_time_difference_projected(p1,p2) text += make_text_timediff(projected, "Projected", size, timesize) if c.td_crosspath: - crosspath = mkw_utils.get_time_difference_crosspath() + crosspath = s*mkw_utils.get_time_difference_crosspath(p1,p2) text += make_text_timediff(crosspath, "CrossPath", size, timesize) if c.td_tofinish: - tofinish = mkw_utils.get_time_difference_tofinish() + tofinish = s*mkw_utils.get_time_difference_tofinish(p1,p2) text += make_text_timediff(tofinish, "ToFinish", size, timesize) if c.td_racecomp: racecomp = mkw_utils.get_time_difference_racecompletion(Memory_History) @@ -363,10 +369,10 @@ def main(): global c c = ConfigInstance(config) + #Those 2 variables are used to store some parameters from previous frames global Frame_of_input Frame_of_input = 0 - global Memory_History size = max(c.history_size, int(c.rotation)+1) Memory_History = History(size) diff --git a/scripts/RMC/test.py b/scripts/RMC/test.py index 7adbbaa..3115151 100644 --- a/scripts/RMC/test.py +++ b/scripts/RMC/test.py @@ -1,15 +1,25 @@ -from dolphin import event, gui, utils +from dolphin import event, gui, utils, savestate, memory +import Modules.mkw_utils as mkw_utils +import sys +from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState, TimerManager def main(): global counter counter = 0 + global listsave + listsave = {} + seter() if __name__ == '__main__': main() - +def seter(): + addr = TimerManager().addr + l = addr+0x48 + c = memory.read_u32(l) + memory.write_u32(l,c+60) """ @event.on_savestateload @@ -18,8 +28,6 @@ def on_state_load(fromSlot: bool, slot: int): @event.on_frameadvance def on_frame_advance(): - global counter - counter +=1 - print(counter) - + pass + #seter() From d13686a8d84399b3a5a2a1c88ecc672c75953536 Mon Sep 17 00:00:00 2001 From: Blounard Date: Sun, 24 Dec 2023 19:21:07 +0100 Subject: [PATCH 06/12] Added doc and removed personal files --- .gitignore | 1 + scripts/AGC_Data/save your AGC data here.txt | 0 .../Modules/TimeDifference information.txt | 58 +++++ .../__pycache__/agc_lib.cpython-38.pyc | Bin 8398 -> 10388 bytes scripts/Modules/agc_lib.py | 99 ++++++-- scripts/Modules/bruteforcer_lib.py | 224 ------------------ scripts/Modules/infodisplay.ini | 6 +- scripts/Modules/test_del_me_later.py | 60 ----- scripts/RMC/Adv. Ghost Comp/Load_data.py | 20 +- .../{Save to file.py => Save_to_file.py} | 3 +- scripts/RMC/Bruteforce.py | 67 ------ scripts/RMC/_draw_info_display.py | 5 +- scripts/RMC/test.py | 33 --- 13 files changed, 162 insertions(+), 414 deletions(-) create mode 100644 scripts/AGC_Data/save your AGC data here.txt create mode 100644 scripts/Modules/TimeDifference information.txt delete mode 100644 scripts/Modules/bruteforcer_lib.py delete mode 100644 scripts/Modules/test_del_me_later.py rename scripts/RMC/Adv. Ghost Comp/{Save to file.py => Save_to_file.py} (92%) delete mode 100644 scripts/RMC/Bruteforce.py delete mode 100644 scripts/RMC/test.py diff --git a/.gitignore b/.gitignore index 7b29787..06aae8c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ scripts/Modules/test_del_me_later.py scripts/Modules/test.bit scripts/Modules/test_del_me_later.py scripts/Modules/test_del_me_later.py +scripts/AGC_Data/ghost.data diff --git a/scripts/AGC_Data/save your AGC data here.txt b/scripts/AGC_Data/save your AGC data here.txt new file mode 100644 index 0000000..e69de29 diff --git a/scripts/Modules/TimeDifference information.txt b/scripts/Modules/TimeDifference information.txt new file mode 100644 index 0000000..7b66c9b --- /dev/null +++ b/scripts/Modules/TimeDifference information.txt @@ -0,0 +1,58 @@ +This file contain some information about the TimeDifference scripts in infodisplay. + +In infodisplay.ini, you can chose to display or not each time difference calculation. + +In infodisplay.ini, "timediff setting" is a setting with 4 possible value : + "player" which will use the TimeDifference (Player -> Ghost) + "ghost" which will use the TimeDifference (Ghost -> Player) + "ahead" which will use the TimeDifference (the one ahead -> the one behind) + "behind" which will use the TimeDifference (the one behind -> the one ahead) + any other value will default to "player". + +In infodisplay.ini "history size" is a setting used for the TimeDifference RaceComp. +history size = 200 means the TimeDiff RaceComp can at best detect a timedifference of 200 frames or less. +It uses memory, so don't use an unecessary large number. + +Some TimeDifference calculations are not symmetrical. It means this calculation gives different result +for the time difference between the ghost and the player, and between the player and the ghost. +Here's an example : For the TimeDifference Absolute (Player1 -> Player2) : + We take Player1's speed, we take the distance between both players. + And we simply define the TimeDiff as the distance divided by the speed. + Player1 and Player2 have asymmetrical roles in the calculation. + Therefore : we talk about the timedifference from Player1 to Player2 (and not the timedifference between Player1 and Player2) + +This is how each one is calculated : + +-TimeDifference Absolute (P1 -> P2) (Not very relevant imo) + Take S1 the speed of P1 + Take D the distance between P1 and P2 + Return D / S1 + +-TimeDifference Relative (P1 -> P2) (A bit more relevant maybe) + Take S1 the speed of P1 directed "toward" P2. (mathematically, it's a dot product) + Take D the distance between P1 and P2 + Return D / S1 + +-TimeDifference Projected (P1 -> P2) (A good one for short distances) + Take S1 the speed of P1 + Take D the distance represented here : https://blounard.s-ul.eu/iMDYhZDI.png + Return D / S1 + +-TimeDifference CrossPath (P1 -> P2) (Another good one for short distances) +this one is symmetrical + With the notation here : https://blounard.s-ul.eu/WYbotlks.png + Calculate t1 = TimeDifference (P1 -> C) (in this case, all 3 above timedifference formula will give the same result) + Calculate t2 = TimeDifference (P2 -> C) (--------------------------------------------------------------------------) + Return t1-t2 + +-TimeDifference ToFinish (P1 -> P2) (Perfectly precise when both player are going straight to the finish line at constant speed. Useless otherwise) +this one is symmetrical + Calculate t1, the time needed for P1 to cross the finish line if P1 keep going at a constant speed. + Calculate t2, the time needed for P2 to cross the finish line if P2 keep going at a constant speed. + Return t1-t2 + +-TimeDifference RaceComp (P1 -> P2) (Useful even for long distances. Based on RaceCompletion data. Has several flaws) +this one is symmetrical + Store in memory the racecompletion data for both players for the last few frames. + Make the player ahead go "back in time" until it's behind the other player. + How much frame you had to go "back in time" is how much frame the player was ahead. \ No newline at end of file diff --git a/scripts/Modules/__pycache__/agc_lib.cpython-38.pyc b/scripts/Modules/__pycache__/agc_lib.cpython-38.pyc index 5428c93aac147fd9d3dcc9fb465150470dee6448..40d05be8da0585f9529ea0c9679341f84bc452df 100644 GIT binary patch delta 3891 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 JQo<66e*q1FlobE~ diff --git a/scripts/Modules/agc_lib.py b/scripts/Modules/agc_lib.py index 66c3028..40152e6 100644 --- a/scripts/Modules/agc_lib.py +++ b/scripts/Modules/agc_lib.py @@ -74,6 +74,16 @@ def from_string(string): def from_time_format(m,s,ms): return Split(m*60+s+ms/1000) + @staticmethod + def from_bytes(b): + data_int = b[0]*256*256+b[1]*256+b[2] + ms = data_int%1024 + data_int = data_int//1024 + s = data_int%128 + data_int = data_int//128 + m = data_int%128 + return Split(m*60+s+ms/1000) + def time_format(self): #return m,s,ms corresponding f = self.val @@ -97,19 +107,30 @@ def bytes_format(self): class TimerData: """Class for the laps splits, both in RKG and Timer format Cumulative convention (lap2 split is stored as lap1+lap2)""" - def __init__(self,string =None, readid=0): + def __init__(self,string =None, readid=0, splits = None): #Call with a string OR when the race is finished if string is None: - self.splits = [] #List of Split (size 3) - timerlist = [RaceManagerPlayer.lap_finish_time(readid, lap) for lap in range(3)] - for timer in timerlist: - self.splits.append(Split.from_time_format(timer.minutes(), timer.seconds(), timer.milliseconds())) + if splits is None: + self.splits = [] #List of Split (size 3) + timerlist = [RaceManagerPlayer.lap_finish_time(readid, lap) for lap in range(3)] + for timer in timerlist: + self.splits.append(Split.from_time_format(timer.minutes(), timer.seconds(), timer.milliseconds())) + else: + self.splits = splits else: self.splits = [] laps = string.split(';') for lap in laps: self.splits.append(Split.from_string(lap)) + @staticmethod + def from_sliced_rkg(rkg_metadata): + sliced_bytes = rkg_metadata.values[3] + l1 = Split.from_bytes(sliced_bytes[1:4]) + l2 = Split.from_bytes(sliced_bytes[4:7])+l1 + l3 = Split.from_bytes(sliced_bytes[7:10])+l2 + return TimerData(splits = [l1,l2,l3]) + def __str__(self): text = 't' for split in self.splits: @@ -133,11 +154,9 @@ def to_bytes(self): prev = split.val return r - def write_rkg(self, ghostid): - s = bytearray('RKGD', 'ASCII') - rkg_addr = memory.read_u32(RaceConfig.chain() + 0xC0C) - if s == memory.read_bytes(rkg_addr, 4): - memory.write_bytes(rkg_addr+0x11, self.to_bytes()) + def write_rkg(self): + r = rkg_addr() + memory.write_bytes(r+0x11, self.to_bytes()) def metadata_to_file(filename, readid): @@ -154,6 +173,19 @@ def metadata_to_file(filename, readid): def get_metadata(readid): return FrameData(get_metadata_addr(readid)) +def get_rkg_metadata(): + return FrameData(get_rkg_metadata_addr()) + +def rkg_metadata_to_file(filename): + rkg_metadata = get_rkg_metadata() + file = open(filename, 'w') + if file is None : + gui.add_osd_message("Error : could not create the data file") + else : + file.write("r"+str(rkg_metadata)) + file.close() + gui.add_osd_message(f"{filename} successfully opened") + def frame_to_file(filename, readid): frame = FrameData(get_addr(readid)) file = open(filename, 'a') @@ -184,16 +216,22 @@ def file_to_framedatalist(filename): if file is None : gui.add_osd_message("Error : could not load the data file") else: - listlines = file.readlines() - metadata = FrameData(string = listlines[0]) timerdata = None - if listlines[-1][0]=='t': - timerdata = TimerData(string = listlines.pop()[1:]) + metadata = None + rkg_metadata = None + listlines = file.readlines() + if listlines[0][0] == 'r': + rkg_metadata = FrameData(string = listlines[0][1:]) + timerdata = TimerData.from_sliced_rkg(rkg_metadata) + else: + metadata = FrameData(string = listlines[0]) + if listlines[-1][0]=='t': + timerdata = TimerData(string = listlines.pop()[1:]) for i in range(1, len(listlines)): datalist.append(FrameData(string = listlines[i])) file.close() gui.add_osd_message(f"Data successfully loaded from {filename}") - return metadata, datalist, timerdata + return metadata, datalist, timerdata, rkg_metadata def framedatalist_to_file(filename, datalist, rid): @@ -212,6 +250,21 @@ def framedatalist_to_file(filename, datalist, rid): file.write(str(timerdata)) file.close() +def framedatalist_to_file_rkg(filename, datalist): + metadata = get_rkg_metadata() + file = open(filename, 'w') + if file is None : + gui.add_osd_message("Error : could not create the data file") + else: + file.write('r'+str(metadata)) + for frame in range(max(datalist.keys())+1): + if frame in datalist.keys(): + file.write(str(datalist[frame])) + else: + file.write(str(FrameData(get_addr(rid), usedefault=True))) + file.close() + + def get_addr(player_id): a = VehiclePhysics.chain(player_id) b = KartMove.chain(player_id) @@ -227,4 +280,18 @@ def get_addr(player_id): def get_metadata_addr(player_id): a = RaceConfig.chain() + player_id*0xF0 return [(a+0x30, 8)]#CharacterID and VehicleID - + +def rkg_addr(): + return memory.read_u32(RaceConfig.chain() + 0xC0C) + +def get_rkg_metadata_addr(): + r = rkg_addr() + return [(r+0x4, 3), #Skipping track ID + (r+0x8, 4), #Skipping Compression flag + (r+0xD, 1), #Skipping Input Data Length + (r+0x10, 0x78)] + +def is_rkg(): + s = bytearray('RKGD', 'ASCII') + r = rkg_addr() + return s == memory.read_bytes(r, 4) diff --git a/scripts/Modules/bruteforcer_lib.py b/scripts/Modules/bruteforcer_lib.py deleted file mode 100644 index bd7aba5..0000000 --- a/scripts/Modules/bruteforcer_lib.py +++ /dev/null @@ -1,224 +0,0 @@ -from dolphin import controller, event, savestate - -from Modules.framesequence import Frame -from Modules import ttk_lib - -def save(name): - b = savestate.save_to_bytes() - f = open(name, 'wb') - f.write(b) - f.close() - -def load(name): - f = open(name, 'rb') - b = f.read() - f.close() - savestate.load_from_bytes(b) - -def prevframe(frame, frequency): - return frame-1 - (frame-2)%frequency - - -class Input: - def __init__(self, A, B=None, L=None, H=None, V=None, D=None): - if B is None: - if type(A) == int: - r = A - self.A = r%2 == 1 - r= r//2 - self.B = r%2 == 1 - r= r//2 - self.L = r%2 == 1 - r= r//2 - self.H = r%15 - r= r//15 - self.V = r%15 - r= r//15 - self.D = r%5 - else : - raise TypeError("When calling Input(i) with 1 argument, i must be int") - else : - self.A = A - self.B = B - self.L = L - self.H = H - self.V = V - self.D = D - - def __int__(self): - r = 0 - r+= int(self.A) - r+= int(self.B)*2 - r+= int(self.L)*4 - r+= int(self.H)*8 - r+= int(self.V)*120 - r+= int(self.D)*1800 - return r - - def __str__(self): - return f"{str(self.A)}, {str(self.B)}, {str(self.L)}, {str(self.H)}, {str(self.V)}, {str(self.D)}" - - -class InputIterable: - def __init__(self, iterable, rule=None): - if rule is None: - rule = lambda x : True - self.rule = rule - try: - inp = next(iterable) - while not rule(inp): - inp = next(iterable) - self.val = inp - self.iterator = iterable - except StopIteration: - self.val = None - self.iterator = iterable - print("Tried to Init a InputIterable with iterator not letting any rule(value)") - - def __next__(self): - self.val = next(self.iterator) - while not self.rule(self.val): - self.val = next(self.iterator) - - - - - -class InputList: - """Class for List of InputRuled iterator - Accessing with an index not in the list will create a new InputRuled iterator - InputList[frame] should be an Input - InputList.inputlist[frame] is an InputIterable - ruleset must be a function : int -> rule - rule type is a function : Input -> bool - iterset must be a function : int -> itergen - itergen type is a function : list(Input) -> Iter(Input) """ - def __init__(self, ruleset, iterset): - self.inputlist = {} - self.ruleset = ruleset - self.iterset = iterset - - def __getitem__(self, index): - if not index in list(self.inputlist.keys()): - if index>0: - iterable = self.iterset(index)([self[index-1]]) - self.inputlist[index] = InputIterable(iterable, self.ruleset(index)) - else: - iterable = self.iterset(index)([]) - self.inputlist[index] = InputIterable(iterable, self.ruleset(index)) - return self.inputlist[index].val - - def __str__(self): - return str([int(self[i]) for i in range(10)]) - - def update(self,frame): - """Update the list. - Return the frame of last modification""" - if frame<0: - raise ValueError('Tried to update a InputList with from a negative frame') - self[frame] - self[frame+1] - self[frame+2] - del self.inputlist[frame+1] - del self.inputlist[frame+2] - try: - next(self.inputlist[frame]) - return frame - except StopIteration: - del self.inputlist[frame] - return self.update(frame-1) - -def first_input_ruled(rule): - for i in range(9000): - if rule(i): - return Input(i) - -def last_input_ruled(rule): - for i in range(8999, -1, -1): - if rule(i): - return Input(i) - - -def simple_order_iterator(l): - for i in range(9000): - yield Input(i) - -def last_input_iterator(l): - j = 0 - if len(l)>0: - j = int(l[0]) - for i in range(9000): - yield Input((i+j)%9000) - -def _123rule(inp): - return int(inp)<4 - -def basic_rule(inp): - #Rule for 3 possible inputs : Gi straight, turn left, turn right - return inp.A and (not inp.B) and (not inp.L) and (inp.H in [0,7,14]) and (inp.V==7) and (inp.D==0) -def forward_rule(inp): - #Rule for 1 possible input : Press A. - return inp.A and (not inp.B) and (not inp.L) and (inp.H ==7) and (inp.V==7) and (inp.D==0) - -forward = Input(True, False, False, 7, 7, 0) -ruleset123 = lambda x : _123rule - -itersetconst = lambda x : simple_order_iterator - -big = InputList(ruleset123, itersetconst) - -def run_input(inp): - gc_input = {} - #trick input - gc_input['Left'] = inp.D==3 - gc_input['Right'] = inp.D==4 - gc_input['Up'] = inp.D==1 - gc_input['Down'] = inp.D==2 - - #button input - gc_input['A'] = inp.A - gc_input['B'] = inp.B - gc_input['L'] = inp.L - - #stick input - match = {0 : 59, - 1 : 68, - 2 : 77, - 3 : 86, - 4 : 95, - 5 : 104, - 6 : 112, - 7 : 128, - 8 : 152, - 9 : 161, - 10 : 170, - 11 : 179, - 12 : 188, - 13 : 197, - 14 : 205} - gc_input['StickX'] = match[inp.H] - gc_input['StickY'] = match[inp.V] - - #Everything else, irrelevant - gc_input['Z'] = False - gc_input['R'] = False - gc_input['X'] = False - gc_input['Y'] = False - gc_input['Start'] = False - gc_input['CStickX'] = 0 - gc_input['CStickY'] = 0 - gc_input['TriggerLeft'] = 0 - gc_input['TriggerRight'] = 0 - gc_input['AnalogA'] = 0 - gc_input['AnalogB'] = 0 - gc_input['Connected'] = True - - controller.set_gc_buttons(0, gc_input) - -def makeFrame(inp): - f = Frame([str(int(i)) for i in [inp.A, inp.B, inp.L, inp.H-7, inp.V-7, inp.D]]) - return f - -def run_input2(inp): - f = makeFrame(inp) - ttk_lib.write_player_inputs(f) diff --git a/scripts/Modules/infodisplay.ini b/scripts/Modules/infodisplay.ini index 42dc53d..7ea4226 100644 --- a/scripts/Modules/infodisplay.ini +++ b/scripts/Modules/infodisplay.ini @@ -1,16 +1,16 @@ [DEBUG] -debug = False +debug = True [INFO DISPLAY] frame count = True lap splits = False speed = True -oriented speed = False +oriented speed = True internal velocity (x, y, z) = False oriented internal velocity = False internal velocity (xyz) = False external velocity (x, y, z) = False -oriented external velocity = False +oriented external velocity = True external velocity (xyz) = True moving road velocity (x, y, z) = False oriented moving road velocity = False diff --git a/scripts/Modules/test_del_me_later.py b/scripts/Modules/test_del_me_later.py deleted file mode 100644 index 10ef031..0000000 --- a/scripts/Modules/test_del_me_later.py +++ /dev/null @@ -1,60 +0,0 @@ -import math -import struct - -class vec3: - x: float = 0.0 - y: float = 0.0 - z: float = 0.0 - - def __add__(self, other): - return vec3(self.x + other.x, self.y + other.y, self.z + other.z) - - def __sub__(self, other): - return vec3(self.x - other.x, self.y - other.y, self.z - other.z) - - def __mul__(self, other): - """ vec3 * vec3 -> float (dot product) - vec3 * float -> vec3 (scalar multiplication)""" - if type(other) == vec3: - return self.x * other.x + self.y * other.y + self.z * other.z - else: - return vec3(self.x * other, self.y * other, self.z * other) - - def __matmul__(self, other): - """ vec3 @ vec3 -> vec3 (cross product) - vec3 @ float -> vec3 (scalar multiplication)""" - if type(other) == vec3: - x = self.y*other.z - self.z*other.y - y = self.z*other.x - self.x*other.z - z = self.x*other.y - self.y*other.x - return vec3(x,y,z) - else: - return vec3(self.x * other, self.y * other, self.z * other) - - def length(self) -> float: - return math.sqrt(self.x**2 + self.y**2 + self.z**2) - - def length_xz(self) -> float: - return math.sqrt(self.x**2 + self.z**2) - - def forward(self, facing_yaw) -> float: - speed_yaw = -180/math.pi * math.atan2(self.x, self.z) - diff_angle_rad = (facing_yaw - speed_yaw)*math.pi/180 - return math.sqrt(self.x**2 + self.z**2)*math.cos(diff_angle_rad) - - def sideway(self, facing_yaw) -> float: - speed_yaw = -180/math.pi * math.atan2(self.x, self.z) - diff_angle_rad = (facing_yaw - speed_yaw)*math.pi/180 - return math.sqrt(self.x**2 + self.z**2)*math.sin(diff_angle_rad) - - @staticmethod - def read(ptr) -> "vec3": - bytes = memory.read_bytes(ptr, 0xC) - return vec3(*struct.unpack('>' + 'f'*3, bytes)) - - @staticmethod - def from_bytes(bts) -> "vec3": - return vec3(*struct.unpack('>' + 'f'*3, bts)) - - def to_bytes(self) -> bytearray: - return bytearray(struct.pack('>fff', self.x, self.y, self.z)) diff --git a/scripts/RMC/Adv. Ghost Comp/Load_data.py b/scripts/RMC/Adv. Ghost Comp/Load_data.py index 4409040..a73bdf0 100644 --- a/scripts/RMC/Adv. Ghost Comp/Load_data.py +++ b/scripts/RMC/Adv. Ghost Comp/Load_data.py @@ -10,15 +10,17 @@ def main(): filename = os.path.join(utils.get_script_dir(), r'AGC_Data\ghost.data') global delay - delay = 2500 + delay = 0 global framedatalist global timerdata global metadata + global rkg_metadata - metadata, framedatalist, timerdata = lib.file_to_framedatalist(filename) + metadata, framedatalist, timerdata, rkg_metadata = lib.file_to_framedatalist(filename) - timerdata.add_delay(delay) + if not timerdata is None: + timerdata.add_delay(delay) if __name__ == '__main__': @@ -32,9 +34,15 @@ def on_frame_advance(): delayed_frame = floor(delay)+frame decimal_delay = delay - floor(delay) - metadata.write(lib.get_metadata_addr(1)) - - timerdata.write_rkg(0) + if not metadata is None: + metadata.write(lib.get_metadata_addr(1)) + + if lib.is_rkg(): + if not rkg_metadata is None: + rkg_metadata.write(lib.get_rkg_metadata_addr()) + #if not timerdata is None: + #timerdata.write_rkg() + if 0 < delayed_frame+1 < len(framedatalist) and racestate >= RaceState.COUNTDOWN.value and not mkw_utils.is_single_player(): #print(timerdata) diff --git a/scripts/RMC/Adv. Ghost Comp/Save to file.py b/scripts/RMC/Adv. Ghost Comp/Save_to_file.py similarity index 92% rename from scripts/RMC/Adv. Ghost Comp/Save to file.py rename to scripts/RMC/Adv. Ghost Comp/Save_to_file.py index c03069b..fe6e5ba 100644 --- a/scripts/RMC/Adv. Ghost Comp/Save to file.py +++ b/scripts/RMC/Adv. Ghost Comp/Save_to_file.py @@ -35,10 +35,9 @@ def on_frame_advance(): lib.metadata_to_file(filename, 0) metadata_saved = True - if RaceState.RACE.value >= racestate >= RaceState.COUNTDOWN.value: + if (not end) and RaceState.RACE.value >= racestate >= RaceState.COUNTDOWN.value: framedatalist[frame] = lib.get_framedata(0) lib.frame_to_file(filename, 0) - end = False if (not end) and racestate == RaceState.FINISHED_RACE.value: lib.framedatalist_to_file(filename, framedatalist, 0) diff --git a/scripts/RMC/Bruteforce.py b/scripts/RMC/Bruteforce.py deleted file mode 100644 index 68ea0d3..0000000 --- a/scripts/RMC/Bruteforce.py +++ /dev/null @@ -1,67 +0,0 @@ -from dolphin import controller, event -from Modules import bruteforcer_lib as bfl -from Modules import mkw_utils as utils -from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState - -def main(): - def ruleset(x): - if x<250: - return bfl.forward_rule - return bfl.basic_rule - - iterset = lambda x : bfl.last_input_iterator - - global IptList - IptList = bfl.InputList(ruleset, iterset) - - global ss_frequency - ss_frequency = 60 - - global distance_key - distance_key = 0 - - global delay_input - delay_input = 1 - - - -if __name__ == '__main__': - main() - -def savename(frame): - return str(frame)+'.rawsav' - - -@event.on_frameadvance -def on_frame_advance(): - frame = utils.frame_of_input() - if RaceManager().state().value >= RaceState.COUNTDOWN.value and not utils.is_single_player(): - if utils.get_distance_ghost() <= distance_key : - if frame%ss_frequency == 1: - bfl.save(savename(frame)) - bfl.run_input(IptList[frame]) - else: - modif_frame = IptList.update(frame-delay_input) - frame_to_load = bfl.prevframe(modif_frame, ss_frequency) - print(f"desync at {frame}, modifying input at {modif_frame}, loading {frame_to_load}") - bfl.run_input(IptList[frame_to_load]) - bfl.load(savename(frame_to_load)) - #bfl.run_input2(bfl.forward) - - - - - - - - - - - - - - - - - - diff --git a/scripts/RMC/_draw_info_display.py b/scripts/RMC/_draw_info_display.py index 2991b9d..7e7f89e 100644 --- a/scripts/RMC/_draw_info_display.py +++ b/scripts/RMC/_draw_info_display.py @@ -177,9 +177,8 @@ def create_infodisplay(): vehicle_physics = VehiclePhysics(addr=vehicle_dynamics.vehicle_physics()) if c.debug : - t = TimerManager() - value = t.race_frame_counter() - text += f"Debug : {value}\n" + value = mkw_utils.delta_position(0) - VehiclePhysics.speed(0) + text += f"Debug : {value.length()}\n" if c.frame_count: text += f"Frame: {mkw_utils.frame_of_input()}\n\n" diff --git a/scripts/RMC/test.py b/scripts/RMC/test.py deleted file mode 100644 index 3115151..0000000 --- a/scripts/RMC/test.py +++ /dev/null @@ -1,33 +0,0 @@ -from dolphin import event, gui, utils, savestate, memory -import Modules.mkw_utils as mkw_utils -import sys -from Modules.mkw_classes import RaceManager, RaceManagerPlayer, RaceState, TimerManager - -def main(): - global counter - counter = 0 - global listsave - listsave = {} - seter() - -if __name__ == '__main__': - main() - - - -def seter(): - addr = TimerManager().addr - l = addr+0x48 - c = memory.read_u32(l) - memory.write_u32(l,c+60) - -""" -@event.on_savestateload -def on_state_load(fromSlot: bool, slot: int): -""" - -@event.on_frameadvance -def on_frame_advance(): - pass - #seter() - From dcc7f4c6bd044c9641046e89895aa43ff0d71d29 Mon Sep 17 00:00:00 2001 From: xi <104683822+ximk@users.noreply.github.com> Date: Tue, 26 Dec 2023 17:02:26 -0500 Subject: [PATCH 07/12] Remove compiled code from PR. Dolphin will do this already, no need to clutter the PR with this. --- .../Modules/__pycache__/__init__.cpython-38.pyc | Bin 180 -> 0 bytes .../Modules/__pycache__/agc_lib.cpython-38.pyc | Bin 10388 -> 0 bytes .../__pycache__/bruteforcer_lib.cpython-38.pyc | Bin 7504 -> 0 bytes .../__pycache__/framesequence.cpython-38.pyc | Bin 7426 -> 0 bytes .../__pycache__/input_display.cpython-38.pyc | Bin 6031 -> 0 bytes .../__pycache__/mkw_translations.cpython-38.pyc | Bin 2850 -> 0 bytes .../__pycache__/mkw_utils.cpython-38.pyc | Bin 11589 -> 0 bytes .../__pycache__/ttk_config.cpython-38.pyc | Bin 734 -> 0 bytes .../Modules/__pycache__/ttk_lib.cpython-38.pyc | Bin 12306 -> 0 bytes .../__pycache__/__init__.cpython-38.pyc | Bin 2723 -> 0 bytes .../__pycache__/ai_input.cpython-38.pyc | Bin 2903 -> 0 bytes .../mkw_classes/__pycache__/bsp.cpython-38.pyc | Bin 8568 -> 0 bytes .../__pycache__/common.cpython-38.pyc | Bin 12998 -> 0 bytes .../competition_settings.cpython-38.pyc | Bin 4127 -> 0 bytes .../__pycache__/controller.cpython-38.pyc | Bin 1983 -> 0 bytes .../__pycache__/controller_info.cpython-38.pyc | Bin 1765 -> 0 bytes .../ghost_buttons_stream.cpython-38.pyc | Bin 1590 -> 0 bytes .../__pycache__/ghost_controller.cpython-38.pyc | Bin 1531 -> 0 bytes .../__pycache__/ghost_writer.cpython-38.pyc | Bin 1790 -> 0 bytes .../__pycache__/gp_stats.cpython-38.pyc | Bin 2779 -> 0 bytes .../__pycache__/input_mgr.cpython-38.pyc | Bin 5763 -> 0 bytes .../__pycache__/kart_action.cpython-38.pyc | Bin 1208 -> 0 bytes .../__pycache__/kart_body.cpython-38.pyc | Bin 2966 -> 0 bytes .../__pycache__/kart_boost.cpython-38.pyc | Bin 4237 -> 0 bytes .../__pycache__/kart_collide.cpython-38.pyc | Bin 3030 -> 0 bytes .../__pycache__/kart_half_pipe.cpython-38.pyc | Bin 2951 -> 0 bytes .../__pycache__/kart_input.cpython-38.pyc | Bin 2978 -> 0 bytes .../__pycache__/kart_jump.cpython-38.pyc | Bin 9032 -> 0 bytes .../__pycache__/kart_move.cpython-38.pyc | Bin 39032 -> 0 bytes .../__pycache__/kart_object.cpython-38.pyc | Bin 4001 -> 0 bytes .../kart_object_manager.cpython-38.pyc | Bin 1774 -> 0 bytes .../__pycache__/kart_param.cpython-38.pyc | Bin 1588 -> 0 bytes .../__pycache__/kart_settings.cpython-38.pyc | Bin 4315 -> 0 bytes .../__pycache__/kart_state.cpython-38.pyc | Bin 6591 -> 0 bytes .../__pycache__/kart_sub.cpython-38.pyc | Bin 2561 -> 0 bytes .../__pycache__/player_input.cpython-38.pyc | Bin 2521 -> 0 bytes .../__pycache__/player_stats.cpython-38.pyc | Bin 12951 -> 0 bytes .../__pycache__/race_config.cpython-38.pyc | Bin 2634 -> 0 bytes .../race_config_player.cpython-38.pyc | Bin 3587 -> 0 bytes .../race_config_scenario.cpython-38.pyc | Bin 2256 -> 0 bytes .../race_config_settings.cpython-38.pyc | Bin 4797 -> 0 bytes .../__pycache__/race_input_state.cpython-38.pyc | Bin 2541 -> 0 bytes .../__pycache__/race_manager.cpython-38.pyc | Bin 9852 -> 0 bytes .../race_manager_player.cpython-38.pyc | Bin 11157 -> 0 bytes .../__pycache__/race_stats.cpython-38.pyc | Bin 2502 -> 0 bytes .../__pycache__/time_manager.cpython-38.pyc | Bin 3510 -> 0 bytes .../__pycache__/timer.cpython-38.pyc | Bin 1316 -> 0 bytes .../__pycache__/ui_input_state.cpython-38.pyc | Bin 2211 -> 0 bytes .../__pycache__/vehicle_dynamics.cpython-38.pyc | Bin 7133 -> 0 bytes .../__pycache__/vehicle_physics.cpython-38.pyc | Bin 11317 -> 0 bytes 50 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 scripts/Modules/__pycache__/__init__.cpython-38.pyc delete mode 100644 scripts/Modules/__pycache__/agc_lib.cpython-38.pyc delete mode 100644 scripts/Modules/__pycache__/bruteforcer_lib.cpython-38.pyc delete mode 100644 scripts/Modules/__pycache__/framesequence.cpython-38.pyc delete mode 100644 scripts/Modules/__pycache__/input_display.cpython-38.pyc delete mode 100644 scripts/Modules/__pycache__/mkw_translations.cpython-38.pyc delete mode 100644 scripts/Modules/__pycache__/mkw_utils.cpython-38.pyc delete mode 100644 scripts/Modules/__pycache__/ttk_config.cpython-38.pyc delete mode 100644 scripts/Modules/__pycache__/ttk_lib.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/__init__.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/ai_input.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/bsp.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/common.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/competition_settings.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/controller.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/controller_info.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/ghost_buttons_stream.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/ghost_controller.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/ghost_writer.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/gp_stats.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/input_mgr.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_action.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_body.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_boost.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_collide.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_half_pipe.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_input.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_jump.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_move.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_object.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_object_manager.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_param.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_settings.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_state.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/kart_sub.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/player_input.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/player_stats.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/race_config.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/race_config_player.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/race_config_scenario.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/race_config_settings.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/race_input_state.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/race_manager.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/race_manager_player.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/race_stats.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/time_manager.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/timer.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/ui_input_state.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/vehicle_dynamics.cpython-38.pyc delete mode 100644 scripts/Modules/mkw_classes/__pycache__/vehicle_physics.cpython-38.pyc diff --git a/scripts/Modules/__pycache__/__init__.cpython-38.pyc b/scripts/Modules/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 33ffeffb22ac501e0fb1781fa67bdde223c852ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 180 zcmWIL<>g`kf}=-DQ$h4&5P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;x_yi&czEeojF~ zW}ZSoWpaK|YD@}*tDBoxT#{M@-x7%)o! diff --git a/scripts/Modules/__pycache__/agc_lib.cpython-38.pyc b/scripts/Modules/__pycache__/agc_lib.cpython-38.pyc deleted file mode 100644 index 40d05be8da0585f9529ea0c9679341f84bc452df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10388 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 J`yTq){{^qsBZ2?` diff --git a/scripts/Modules/__pycache__/bruteforcer_lib.cpython-38.pyc b/scripts/Modules/__pycache__/bruteforcer_lib.cpython-38.pyc deleted file mode 100644 index a22b27ee100111a7d12a17619f981b39d6e9d95c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7504 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 E0i1rwJ^%m! diff --git a/scripts/Modules/__pycache__/input_display.cpython-38.pyc b/scripts/Modules/__pycache__/input_display.cpython-38.pyc deleted file mode 100644 index 96e2440ab9664f0427fb6c709be7c80922ba262a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6031 zcmeHLOK;=I5#~z|zdai7cy>3BhLB_}$DRxp*&r~2AhNA-ggCNc%ZtpcHVQ{g+ssHL z(WJ%_AR(9i4LJ>h-Q(nUB-fk+BDb9U2Xe?Eld5WxB4ydx-Q*A~mH?aV>ZVe8+MEON4o0a=Y(`xsKa)MMp=j=)wOyynFEa zYfuErr|L)^X;D9H3bV? zY${iGfAzG?p7(>mbso)=WK~@FJM@Qoq-ks;=zCqOvcsB}R!noxSpYRD%xs5h=dS26 zX!&Tc#fBe0O7zH~u?^b^A}tXmqh-QRQ;=qtgbX)x`$5-stm(cV531FZlY@iZU8(Py z!Gtv`n$X}IE^uL9wdHgOoY&Win1jzhf4#rc+IPF&B@E?w*l~r`;z zjwyz%!H<5}I`e^k=$gEB+7Y%F_^n^Myx+C_mhE``pv`UH>zczy-Y{J6kWbou#}k(C zTf8l&&VbH+G)TQVNb!7z63xC?Wa-od?s3@Kdi07R7iyLl@<5^gpz;rG!q%Tb`8`uz& zJ^Y$mp0vww$IkdqlZ~|34uCS@=1T zK)`e=*Hoa(lO-}oO9ZD>ECYRdWz33P?DiYL>(kD(kXIilnxefC2+sdA_wU_se;n0c zyZ?>_dIJy8PHT)l?srqNSDzRlE zL0o_;6H2Tj!=2KWl1Nc!N@4#}cg%_Sb<>L2=7>MT5lcqsmm1lWE*NQAPmGqS-f%7^ z*2nzm-m)BsylG0BGc~_)uX6TLf+$&TnxBj|97#f*Au;ja#O9PlG7{>C>#!RbW&xH4 zov4!2-7N6uHi847xY=c%$^ZLZV1N7A{iv}O37nnQh~B6jRGak=YwW}7;aQD6 zIXYqWCTkwC>hW={dcyXOPEKlj&BLdgnz>#UOG#TsXSMMuiJlF=f&pYsC^Fi&SRXPA4Aze8{I>595U?vdxMV3u%hOo>9GGG4(mGDH zvhzr83xX38A82=di<#o0--ArmhbR@6T)-F%cx)!)Fq+E~-<1;yW_q4*Jz+yi+8urk zNKH(lF~^V3*-_HLBrwg$sHaafh?SF>&K}~WI4+P_?MC^`D{ry#zI)~1_YhJS_=59( z05+6QFmEYWXsMy%JwRHs)3LmO_4?hwhRmP6G`oGvk6ibEiHM0@!2uD8xNu#JP zM{t+^lda;rzzyAE9*EgvA2vhhq8(lKEc$`nc@ftZa9@cl1=%zRqo1M7EfE6a2klI9 z%YQ&+WN`Jz%Gem?=$ngjO8`i&zN^rgQQ5f~JHk(e#&?E7DXX=tNud+`z0D z>Ka&31c=sR8qWb(=FP`9&qjcNfpEKwrcq*`$>RBs?nP#T(X2}^ne?*h3^`(ra@S0c zlax2^GjeP?_no>0ixx*>9EKx4=|yt8_$}S1*3=AHMD2_q>p=X|`NoDjLD_$7!62<* zux$?DKr}ria=JGjZ@>S+2bDV&48M?qyU%nn*4+xB;G$_1z5X3U4BZJ(a(Io`$c>6l z_k;o~ViAhU9EGm<9unTe0xxky1q(z1iptxuV=dZQqd9KV^!y&=d_)>JX{kjG&Ps3c z`kGo&*VI*b>8q`(VjDObm4&bn-9*YO%pBduhB{oP(v6|Ot0}s9pd^&eR)jhvp8_+2 sHN3D0i$CenJ>^d^H6}n?)Juz{MFVr$H;XH4E79Nkc}dx%FWqtc8v%p^Z~y=R diff --git a/scripts/Modules/__pycache__/mkw_translations.cpython-38.pyc b/scripts/Modules/__pycache__/mkw_translations.cpython-38.pyc deleted file mode 100644 index dd4ae281db773b265667aa01ac31195dc80697c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2850 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 diff --git a/scripts/Modules/__pycache__/ttk_config.cpython-38.pyc b/scripts/Modules/__pycache__/ttk_config.cpython-38.pyc deleted file mode 100644 index 2179d063fdad13cc4778b357b051793b8f4583fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 734 zcmZ8f&1w`u5bo}oot@q6ZWeM-K|#oA4kj0oAR-cjBAO5gK^O;`-sw(u*!iQoC&`A* z&Bxe7a`Zj)<`eYQQ(j>~v3ka=s|EE@Rb4+{)y#3f-$fwbzE5UWYeohvdUGxPuf75`xIX#f33`Ytakt+uUsn6jymefhx%Z=CM21F9r!Q79FN-9BBT4>5f zBPq_3`YeGX?Y72i62f&YE;Kz!QbFyV)E6WN@V@x8_dMDw(sG>Sj}NDDAw|R+_esW- z7V^%Gc9WdRX>{@IX>_b0{-IzzI*MgdY8CAlyh??Nw4Tto$WM~ft#WDx{|@cIK-B|4 z*e6}w#e<)oCx_rm4*m65M-KO|2vYPEn`+L-UdammZ*J@6`egkhI#6|!B diff --git a/scripts/Modules/__pycache__/ttk_lib.cpython-38.pyc b/scripts/Modules/__pycache__/ttk_lib.cpython-38.pyc deleted file mode 100644 index 6a0d86f7cade19c989091e97d66b4842960d168c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12306 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 TsE|(CDLa8Xmi*B|qLBD6wx8Nn diff --git a/scripts/Modules/mkw_classes/__pycache__/__init__.cpython-38.pyc b/scripts/Modules/mkw_classes/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index a40e685aaf90858b57a85485167d0900e9420a8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2723 zcmZWq?OM}V5T-z(UzGACAc%;F6af(s6%m1gh>D^GS;x9HO+$&EX|gA&%ClFr7qB;z zzx!)%VSnw+q@{JYJWSsAosZzxhj4QAr{0i|^SQR|1?&BJ)2_8`o@F6@DJgOeyI;;!6 zsvhG8YzQ7xPjC}91&^zzxCL8+uc>X^fgQ|2PWXh{#XZ;)d|f@meb^T~sh;Bj90