From 6ec468a78bf1bcdf5690e7531e3837a4093bfa92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E9=B9=8F?= Date: Sun, 19 Apr 2026 15:53:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=EF=BC=9A=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=BC=A0=E6=A0=87=E5=9B=BE=E6=A0=87=E8=AF=86=E5=88=AB=E3=80=81?= =?UTF-8?q?=E5=A4=8D=E6=B4=BB=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96=E3=80=81?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E9=85=8D=E7=BD=AE=E5=8A=A0=E8=BD=BD=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=81=E7=9B=AE=E6=A0=87=E8=A1=80=E9=87=8F100%?= =?UTF-8?q?=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __pycache__/auto_bot.cpython-311.pyc | Bin 8490 -> 30321 bytes __pycache__/auto_bot_move.cpython-311.pyc | Bin 18798 -> 40053 bytes __pycache__/build.cpython-311.pyc | Bin 0 -> 1187 bytes .../build_wow_multikey.cpython-311.pyc | Bin 0 -> 1416 bytes __pycache__/coordinate_patrol.cpython-311.pyc | Bin 23719 -> 23930 bytes __pycache__/death_manager.cpython-311.pyc | Bin 2696 -> 5251 bytes __pycache__/game_state.cpython-311.pyc | Bin 11658 -> 11739 bytes __pycache__/hardware_control.cpython-311.pyc | Bin 0 -> 13870 bytes __pycache__/logistics_manager.cpython-311.pyc | Bin 5862 -> 7117 bytes __pycache__/recorder.cpython-311.pyc | Bin 3991 -> 4000 bytes __pycache__/stuck_handler.cpython-311.pyc | Bin 3460 -> 3512 bytes __pycache__/wow_multikey_gui.cpython-311.pyc | Bin 115322 -> 129739 bytes auto_bot.py | 275 +++++++++++++++-- auto_bot_move.py | 290 ++++++++++++++++-- build.spec | 10 +- build_exe.ps1 | 17 +- build_wow_multikey.spec | 10 +- death_manager.py | 7 + game_state.py | 4 +- game_state_config.json | 14 +- hardware_control.py | 195 +++++++----- images/cursor/Attack.PNG | Bin 0 -> 1247 bytes images/cursor/GatherHerbs.PNG | Bin 0 -> 1719 bytes images/cursor/LootAll.PNG | Bin 0 -> 1533 bytes images/cursor/Mine.PNG | Bin 0 -> 1274 bytes images/cursor/Pickup.PNG | Bin 0 -> 1340 bytes images/cursor/Point.PNG | Bin 0 -> 1401 bytes images/cursor/REPAIRNPC.PNG | Bin 0 -> 1555 bytes images/cursor/Skin.PNG | Bin 0 -> 1557 bytes images/cursor/Taxi.PNG | Bin 0 -> 1885 bytes images/cursor/Trainer.PNG | Bin 0 -> 1747 bytes loot_path.json | 2 +- recorder/北风苔原修理.json | 30 ++ recorder/北风苔原剥皮.json | 170 ++++++++++ screenshot/game_state.png | Bin 532 -> 412 bytes screenshot/game_state_combat.png | Bin 74 -> 88 bytes screenshot/game_state_flight_block.png | Bin 87 -> 90 bytes screenshot/game_state_follow.png | Bin 84 -> 92 bytes screenshot/game_state_hp.png | Bin 86 -> 92 bytes screenshot/game_state_logistics_death.png | Bin 83 -> 85 bytes screenshot/game_state_mp.png | Bin 74 -> 92 bytes screenshot/game_state_target.png | Bin 86 -> 89 bytes screenshot/game_state_x.png | Bin 84 -> 91 bytes screenshot/game_state_y.png | Bin 83 -> 85 bytes wow_multikey_gui.py | 5 +- wow_multikey_qt.json | 2 +- 46 files changed, 900 insertions(+), 131 deletions(-) create mode 100644 __pycache__/build.cpython-311.pyc create mode 100644 __pycache__/build_wow_multikey.cpython-311.pyc create mode 100644 __pycache__/hardware_control.cpython-311.pyc create mode 100644 images/cursor/Attack.PNG create mode 100644 images/cursor/GatherHerbs.PNG create mode 100644 images/cursor/LootAll.PNG create mode 100644 images/cursor/Mine.PNG create mode 100644 images/cursor/Pickup.PNG create mode 100644 images/cursor/Point.PNG create mode 100644 images/cursor/REPAIRNPC.PNG create mode 100644 images/cursor/Skin.PNG create mode 100644 images/cursor/Taxi.PNG create mode 100644 images/cursor/Trainer.PNG create mode 100644 recorder/北风苔原修理.json create mode 100644 recorder/北风苔原剥皮.json diff --git a/__pycache__/auto_bot.cpython-311.pyc b/__pycache__/auto_bot.cpython-311.pyc index 697707771f0197cb60aa373cd1b1a8de65b4470b..f319ce1aad2875b24017a50b35950deded242b32 100644 GIT binary patch literal 30321 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

If=OhyS!4{Be~a+xJzLhw_Dz#g`xHH zmf;6U#s^Z=3^^7{AE&T#<_VaSxpBMaeA%1@oBEVF3pVxemUkmfzKM8h=HjD_bzn_&?~5J)-&8(EDTs;FnG!HPf&_^x zY25=r{s>lDdXS(S;^XZsh|MX!XD*Cph5{ctp?}1mLU%W&Kt`1^e6t zU0kDhNpfBGqk6*Snw}1f z8d!r?7xl_!Vyo-{ooqty3%Xv^NP{Z9e~1B9uUHe5i-4p8&vjDa(M%fgOr{L+FeauD zD_R5qHe!MW6xb}m#EiQxGrz#ZX4=>9ofrmvyjVS?V?a6rk`V?J`gn|&l@vup2!3)H zke{i+eBB6!Fb_i?ZYm`Pmdrmz51phSH;69Gjhtix2Yf;FK_6)0$!QyX5S`hDIqe4E zcfqUcq1XQXqP#(-2E>nM(z(&+RE0S|0mJy^m(vtl%Vf{ATy33cjr1-VU98a+vpK`f z%Vq~}E{isOkjI%Dd2?e(4K_5uwCVFm@ZG#>Hm`2JA(XXTT*{U;vt@f0v$^8EeDPjZ zSFoyX(dR8!?_O-;s`vBN`#DnuoYGMqo{01>7ZgV(qJitd`Qu!{7QSFh=*V(mNi<{L z_8k*!(=6P|7j6w5jX4U$SPKfS7;KHUg${zvP^3TVzdk(wJXf@pb8HPATruTGnxbXb zcY#H6`*#Kx8(C8;XKLk5t>9R$sO2kma}|5}ioKkvG}IP)F{-$WCfD1S^0zMpL5z^! z%jfro9$U^Un#;RhFjoL3*{(9yRCG5Vl$Y+zi*UpU!q+pxN?~=dQPWu>Iz~#j-^&w|PImc|TXMKdg&w7;@KH7-6pKqX${% zF1VKnoS#@=-kTKNqCddJzFX~oGI-m`?(@LCL?CNxN5-6nRD&rT{~ZgjYZ)d zk+zsEKjM7@?24m1=Es)GTiEgzNPf4X=AC1AD)uf_>|H#?Rdn$cU7V#fY>0Hh1c|gR z**0;uP4km%%j4{p$GI(!lao(I7Y%IwDBQPw;!}j2eT=t{vG%cLdjW5+=In0X?q==o zn7#6jy>`i7J3qLnW9z{FyPdbUv-b9tl8WfrJC!?@Dt9azZgp^#2l>i_T*)E6A-WSzW8s~(th4s6qZYXEoQh>*hIg#QZxW z1@g4D`GcG(CvW!fjTh#w%=axcawR+Xk{z6VCvV@$+INBjOz0xLZ#)xzhVy&^@-&W)nljrJiAi?kH4@RdiJRPqBy%} zyXr5tYrridP*8JCqz!w)f!5bic&@!@#Q<7BD~IBTiQUZjE|50wBY8tEAVoB;< z>N_C%TK2~cQva&;W&cp%XlV+d!Q3;|r~iJJzA3)iG84YRI^ z@dD&WPTT+)uGx0ST(M-Xh-KygekrVo_C;D_d4;jUl2}>Qs*$o(eokdr48KLNN@eKd z2gg7T(j|2eQgE-hUMYQ8C(+6QFf<27K+1tu&nd;T*Fb5X-evj;Bn3nhVUY+C=^ijf zfjw*YfAsOnProawHAG_+ut8xSgA@!}w!}3Pzr|A)Bu{1w_U2Xq-OL$)?lQ4|e}k!7 zFbv6PW*@p*0T41oBv|m&MsnOG(}tnt81JEK3&w%*koIKq5D-eF8k6PYYXJhJXqa|% zbs$)WnqfLI0Ld1n3tea%1GVl%50RoEM>HP6u%if&`ecqFcpSlT1V}wFC(wly1D-HW z5yb?v30<2J{Bw*_i!M|oFm>qa1t5SS@mSy?6b17HMkS<#@}eI$58_eLKtU+`2AQWZ zD2;3=gX|wlH9%mTaA5vB#9g0Oz)HOcx%>A+6r>fvt|u{$M1mQzC^&JF(h#=xua%RgJY*6{893pdp zAO;Xc!cj#*#Ri5UX^LeuL3oJBUEzu@h5*KQ0 z+-hAi?%%o9%G9$FK@~p)M_6b!7}0cdpN!Pg#KEY_Dh)megf_^-NT&%}vZcxz7n=~!0u`0Ut#P4#EPgEhl5sOmkKk4?}#}3C__u& zMv-;0C#)Ld=GAa!*iheOVPcVAFLViW`W^sS;EiV9SOyy?^|n}cE}!j&qi@VPGgDVz zoOv-?&Q@*b%XTc8cd+IiF-vYZBWBILmiI{EedG@*pkb!z5DI7=;W zsbwv-GBe8mSLJ}-FRw6iV9tc*o@E4t)v?_CYlCkLMkY|p#pX7CkRMhpJBuRpTZ3;7 zMlXUPC)uFNIh%QBb668^3}-3hEoH2wOl(LquoJwclqEOp`VDoj7_D+nb(z?TZsJUp zys45kRf@Kv{;S7kj)ll?RYRFdfu$AAnNzWP222B7Q@;2T)`>?`Z@~e4iYScv+H0+` zCm4`QgeeFMfn-f$wlNJH(xMavmh!I&OiSgdQdR*l=}TKx5U;^Xxf@nWX?28H583Jw zR73ncSc_7QBoh@;Vr@_X$AEb!7_(vjkPG5UZvRuTbp(!tlawpQ)STkDrkf~OI#LCy z$wPKv3nBDiat#GMlhUI}qft2UD?J_(g7GUUVqcpdtxv1H)T4<$A2Y~%K&&?$OO)XU zrJi34Z89cGnuf!QAV29HMlxkgU@c6E`_e&jtfdr}sKcn_nZ0p}q?yFZOq39hC2eep z$0`FhD5b@T*kJSu&iAEPCcS=GTPbgBXL4&#THVoPKgEDu%5u$doq*%9Po=exP*hY> z#lv(!PT9%yNte8?kPpr*DIcH>hzbt;lG|{w{>c%OZy18vmTa4RmXcLSmOI(x^moW9 zfNMf{TjTm{83=+xQfH6ETh2#9*pnewGDz9H$iPIqK4GD1u zni6BNc0)#5ov2HSl#$DxgfF5`nH(=NTYzqH+j`&(cTpM*R11zR^CJKtnk74}h(@KG z`3St?68!gCPm&X6#Pey8jT00!p_{q=AFk}M%@?e5tKo(A9+srt6S$uHF3v5%ve_$aV zd}3Q~?^!17Jsb61OvEw3j#-)+12aGxlszb$hc>KpO0v(%zNWW45=X*p4-+^Nm+7=GoQvB#B zSJ2KEw6i+ra&cL-dEWU>D_h>pZtv!b5AekYKstTbSo}HFrqI{N+;zOWopqnMH5}>$ z3L;irgU^b)=915;!p!Da>8AOUeBJ(A+qk;UrP5BYY7&iycE%cZpsCXqwCF129cU|%GEhI@&?TLJz++$nkk1Oeylv1kWpui@=zf3$3O&K`~gIC}+euVC#J7=9Fv z46#@7_A1t16>Hd@D5$uMFWS1WZK#3z(PlXNfO6^xf52I{%zha?+ zZ|Gqgo{TlNV&bh(OOP4X%pO}+>8$%e^2|G%Sm*v&Ugf-+uK`2C&f9kW(9n`|h;K326QtmZA{ zC;)cOwqj+PV|M2qd)<<~ZXQmMY~t-rti9=O?N;n(HzDfCW+9Nv>M|WVhGv-(qtK7B#Qr;c-QWmSK7K_=^h|k(s-Bx^Viq(_%&4kXrTf0px19r=tH5~PAu4T=&%LS!# zE%W8`{`q|Izc7V$NU@ruI?m$eEpFE0CKT(9?Q{Du8duQB7c_E~Cf?G-TAD=aHo4m= zwz(Fo3mfmY;j=8ZX*)jSd!u63BDCde00Xq2Jo)3Zw>oayxaOmL^U)>iQPz5tWOf5A zzN&aj6>Qp;GO^fMOAX`-_G{R4=mZG&s+P*`Q9x2c1H08dJv}D@rby{vEB&7%lKB4+ z{0c!A0)knHPLPO43En|rk%)Y*AO=GHr>IB8MThx!3Gip&@c$8jY3aABv}u}GDLL4b ziD!C9pm@6mjO8Q%QdDPQEGG|6%!w73uV(frG$5B=1D{iBHMsvf0kV&icqy=7nWrgS zr6jQZph5#%?AM24d$1{ZNXm#8P@m@{L5vf~$A9*n=?Aa8wwo}R#D2Rne%u!X?4Cf{ zuM$uE`lD~Iy!!3kgae&aqYu#^XFhZP)qi|%`lT~2l9#w8a5wWjVqMkKUA>d4o?~%M zb1-p=7+H|W(Fkx@nF?&InFfeHfi#|B<&S@~^3vSB58ei;EQqlyz|UPT8g(P>DDu%r zS&GXL(a~oR<)lA;M(OCp$oOS)z?UeMorB0i2HL$355o~vgLw9tklX7EJkE^u!G^-l z@u9YhURW@|P2{9P2JG}@;LzOclt_;sB9Y((2rolpbli#@U_cM7#{3P*|8~b9g(jM- z|3`FT7c&=eZv9VmT|gHKiN*h$RgQjj2#6-T1zmR$keP>*7>?S7J;%7RiMnXAplM-g zf`79Y5cSt&<`O}I^)cV&b7N4&L#PX8CdLD4Gy3=ufN2$YW<(q$qiytZ|S<_jJdqG8+yNQkwOJF|ss^YciZjW`@#CV5?nN`qrU04@ECDm1K|UAi;pKFA7_h?-_qQoe*p>6 z4R`oJ%#st28OBW$oR4FW zgd}#{JYn%!pl*ZIyA@dx$ho`Zf-K-uvS64mCRf|a$fG;$F<*&X@|;U5lm)5Cl^fw@B-!N> zKkp8t&fHc(u3t;Msk8m1eGgKwWfKM zlPZ4g&UXNVWcz#>xym{EW#LT*-W|S~!qE3-N6WKqsq$|9?4^1nJ3R>7bz6s2MJm{O zcl8SGGT>!2AsWDn>>mzH$bLl)s4|&mT~|J9>0(Pym?qVs)-Euz$l+i_3WbMBamSBi z8q&ClsDDhJ@^YAmac}{JA_@WpJB1PeZ-HirD4H=EP)9UQJ|0q3XhouOSTl|)5y0_C zK+@P@S=CHKP**iJ6o$H@;!sqxK72eVN7Yay>@{NtjHfX}8fyv;4dVjx&yJS!lWN3&G@`aer!;}i zEOg8kTBqNyF9KXZ5;KkbSsjuL&?4t7<)n+VlaF~`(DlZwfm%S`H;IE_#AQVif|fbg zqQhBoEd&c;2QZC`L9bOS91kd}Ukx1ftDy;5vxO8to(zX!&#;GF-qOk#NqozWfS1*b ziab7~S&s##q7iVmq6v5S#80Rm``%egKZ{3!aQ1>f)0cKFD zs`|7sX{jLlx9+gSEj93bjYxW{%lv!LUqDv!Ri)FQ8cCqbO}?^}k(*TlIWS}=-&a~Q z;tEo@%}gBS4$`#ksmF(h^zwQ4fS1z>qf=4{%Rx01j!weyh+hEk)#$`E*t6)AagWKuaXr#bvkn7tXe6)iK0su28Z8Tepmw8u`uX)3g;Jr!S8|S@C zyfFLdoSNV(lYC{Iulzp)uz_cFiTui0C(`r%d=J-SLsxCK9+AE3WB`K(5al0KCWNM>&=eP%$e7f;N#9vpf^Sap&2hdtv$M*XeY5*c z>z}j<@pbWnTD+P3Npcx~0Z~Z4-_z(gX_#gtW}TVm7^RWabT!%aP|W3|Y4Vt{j(k>I zM5elm$f^vnY{(~V@}(@=B*T~qULE0QNym`0jFpVThJ1oP$&!ccPKG6q3{{c6d#x2J z<<7M-O7~wcl1bu7ZBb>6L27AMh|nnAT)j-Q`Qt)@HQ&i3)0BKDL1(OKD>qSig=$B0 z+7pn)e_$Epk+$O6F`cq-N8U(X1uuzZGmdwZ$A!CBgArv+qL&w=e=opiKFz^m&-*Jaf?$2|XncS{+)|tli0kQiB zT-8Qh)gl3t)9+mq)Z|ZqUDIe@gj+xv+2OFmLCAKazh3)*#;E}ed31%IIE@KtjHJi@ z@MgVy(XD3+{19l@L|=EWP(-^&Tc_S%e)&C(3q~f622`&r z!z$ZhEZjyI1@>x874C&Qtk2%gYP zAl@IvG)?0+gkl-$(#({r277vSO4AC0BQoT6MV$KH>Pqp#HGbnFzcH6(QcW$V`;&YFXp(&OHQuwxdlGzO zl5dRjjY}jI-r!kw*S)fHp?*PGs7Sc)PrC1)vn&Zfa}Dz&386hHw8w>ZQWdGrP~Rg7 zp*1PA#)Ve0C*mf!Q{@t zgmZt=xj&7JWi?A;RlNF%gm^G19*o7sgDJ5xDQ>zZb}fos32}Q;+#VOVXN4V$Vn;&k zOp2Xxu`?xBzr>}jFvjY)HYC=i5mW41hm=E{>rb;FTU}jETM%D7C(d@K5oc|k-?AXS zo~bU`%VtlWiOt65OBd}iPu%X&Jy!q5x_7`q@T6HJG=LgLDk`1pn)Sm>FjCq4@z-ng zs=i|li+sbpoZwrMd`mq0z#^=zy3IN$l#c(>*i*OLhCa2~c01Wm%NZ;Dcnt#sUNiYy zvnPf-!3OK0Ko1>04DdF>n`xciuyA7*Xhqo%Fq8X$>rI|C%7+rGsW^>tQ0_8Srcn+a zXg0wzbI_TqW~QW*&`aG!AQbld2lewkNpG3AF3qgG@ZxsJ?WFh_k6|YwTj6H_ktd(2 zjO_*kTnqqz2Us~Qt=&Za*gZ*;kZt)7zgvFpl^egg{Kd@kUJ*N~HFb?1;TbNV7Y@y~ z{zn5-Cf9iZ8)=QccP2D@Y0X1H_skKfc{LWU@p_MK^2vDL-k#qyJ zBo64%jvZ5u62p!hL5ehn9owN}Ip)ltOgQl)a{ft;W-Hn0=5|V0RB=}`V@g*2|NfEJ zNv$XQ*Uo7nM4d>Y~b{@~DSYz0z6Tt7g}lUJW~Id$sJW>(#NdzE{uAX}xLeoZg$x&W7F$ zb~g4J+1b=CItb{gCaHz1PmdX+ycE z@_O?SPVde47Min^dy74py(>Ify(Pz09?Ki*-qH+}H|?Y|-no-y z@ld!t9!frYtZ%DTs(0}(9ctCEt3u_is8n%fYGp~4@igJ8cqsY&HZIDh`*Z5v8c!~+T%I;h9l~&)|gq}5fs=ZAptp=sJ5~Xn(&#Gayrxtfs!a?WkzdV zYHClz_jR5|Zv%2Qq4wrP?TA^Am<@`UjfmNli1D-__vWiM&z5Ujl}`b)a&36M{3wzF z-g@QOtLdrhPHu=N@oY=IA5@>u#BAS)*=}K}n?0?mX&wPS=uyct8DZCsyHw;pmpYn$ z;(ef~bbH<~jv(&upx^_?9V^Sk>;h6e_ZBa5|tWQ6k! z4kN{beSU6a2yx~PZ=e6f-oD|!<6e%^>=`*e=<^Tu`(klXbz@ZB6je7wH3RGJmZ0|I zQm?jcAJ017cXo7SaMUo#er8)kaU(>N+yOizv zL)#H2m9RM;*OQ2Ajm4=BY`;sWpu!!%4C6yUMaoQl0EjKAj2GG9{+P(1;FaFiF zhoOb%r#}7QJ1lM?c>d1!f4uO~tDn99!QJP-ednVeBgsPW?S-jJcP>mXeDnE*pPv8h zr_bH~c~DCBPm|9^(+0Saaqn>P9hH zqv@VOZWxn2YD5$I$NYWAhP=@;K5xoAzu~2AFK!D}3#M|>RDMsT&M1o53a9qX zTk>A@g&vqr7cBLnrJgs`ONm=wY`xlWWy5Q&ms{W4C=@k`MNNXKSu{2Cy5=uXyQ)8F zlB?te@bRJrpnSzlsFN4ONqKRE<*83)$B%#-6Aoz-ue}M)GWnCHRy?;#70@Ur3#PXQ zQ`VG7;V0A(JC<0Uk1U&3>(MEf!h|-U<=U2M-O|0I<)rMLZkhZ`_fEH{cRKV=9#fU- zUq8NBPWrK(7?96?_=DSj9+Z~J?eD$t=?8!H+0Wiz`1rZseRvs5O1YkB8GZBH(gKv0 zk-UI7TE<;mHegicN@p{ev*U^*8Z)Xp2`tSy=sJgh4Zx+38fbyAm87G2A61V=(@%K^ zNBewOZleu8nr==yxMGB&7OcnkI-w=T(HbEN#`j|YtP@lIxozjSO?J#1jOWu|GQVgJ z9t>?143(mxa$94FFgJ1)4@I=-65tsusHPD5sP)oFrT`>^!md2oPw(rq4DVk zA*W8vshdiVm~!r^v>Ao-*|rP$7mHsh4jm7l5wh#W?E0x4^Oo%Mr(b&d#iv8Z1WTD{ zDMR6zg^~P%V1~5Lw!F9{qzj!8Ox2>Pn%7lx^d`IWXZ9cO{D<)it^LUphcGx@e{lss z`Ib2;FGj!oUcmHE!JLYFYUSinPDC}9jz|3jn|55DKM6yhl&50q;v(9-hyA-W`#73~ zE#j^u8bNff4TD+2@I{zS0q~15=^^Ursj(Q)4({OrlxUu2* z*kCksr`O*;H0T}nAMp13qghh;;7CtD=k*TbHKsdpde{>+^|LhYA@6`cYK&d@M@FOO zSeP3;e!?Hkj9ua7pk2Ma@wO>dnqSt*t@&v<4Zy|Iel za!4q7SS)#1&=t}B`SMj_`KH;*>%})F`0Yo8@}pw;Q9)NaxhJ?LV#*5{!+U1d@TOK? z*SdHH$ZPGtq6HVRl16RG&nFqlD%a7n^q0JDP@sII&LM7F@(U-xD8_4A<%^~nv&^3< z7oj>Sug*Zqn(ikK9e>LCrp79*0DAQ4PHQAylsHp0{*L30OSdno=KiQ3^AD`q_>MYi z@DBHnfHptwGBC6n%{tun$b_#*j;MW?Mnd)K z0UzOnIL^*uoPbQHbGvbGFaCXR15BzSCJS$Bc(wJdZGx>qv^4;C%V^poq!)?lMfX%1 zy>mV@J6IXghL7`^bwXyHm{~`pjdP}K-j;u1Q|O_Ww_MnAPm359odBOxs^1ex#4Q#2 z^2;xmioRvaob2||E9(=3z0IZl#HDLnlm1D)8c=~r3`oLoHa!EHM_j2NQSl>zx5G3z zi;mR!;R9Cg0q>rSkugg&9__Uha)iwiT5qucats*kHCw0=t>;j%f?Jn72Xl_de65&;oAmMz8L$@r>LM%A8-3H^PQWW0}((gM1G z7Wj9$(J(3dfZEOBq~{Uu4Y(Tw6H+3iQv;_jS8C?Jy;M)ul{8xUej>kO2e^D4t^QY1q->gN%6W+7`H2KV_)H{g4o!@;pRloJq*>5id-v{UQyARLp<947*uAM*! z0LTNschncn^5Z=M0f4*zMBi|~_f8`_{+HIMHMLGga73-C6-Lvfws1}=HBGACmB#I( znh4);4-z;);2{D%04`GsR^x~w=5`V228e3$(u(Q_fWrJ-Ek&TY+~8<5qw`F^cho;P zG7M6e2wd&~mb`!9IIAq09_vrk5O06f5O1=N@VMgLXk|DOoMvDD6Yimrkx}k3Bq3(k zcNqlVr0SN*0_>!>zsg-Weevm6o(_A2{8}-;mPJM^wkiKTja6@78cCJ{N#^8TaE01l zUVUNpR6C)`QbKkTAPiYb7&0j?aW@f)VaU`}x2(2{>93@R(gmwiv^sg~%J7aU{d`V- zNc&p)<#gUzKT{z%){BnyLe2&;X9Jj2TVBw2@$@UF`OxBGfF~3=`tru1c1A+SglA)`P~zRm%b)$?g@x~byzq^eK70S0 z3sdhdOuc#gd+*)-Fnl{q@ql;!;)8`h|CZvFMz1sWO5<3o2JupJBP1Q{D&B5YGQ)uv z4B``Fb>yN_*bz{Lmn4srs8M1tz+8;y#rOdbizCN}2Wi384UHTJ=a}L5o*Es3Akh~! z17&!?QuO!rpYTewivfw;ObBDadV(ZUP7O*&=kpE?NP-xNG=-pM5QV$l<9Uj~tBc1E zqw&5?0H9Y2il%huvm(VMQ##R5Fz=}5YqkrHHqp_B_{@mGeA7@oXDCkLKo%38GQn_} z5e&-_oe8EQERUizmJ(#L43v zR3~KuDxf7iaQ>Hgg*)RpR4Tl}OD7EeibRaZ6wqNq!5lDrUv)J_M#NtBstLo>hV!>Q z?0i}s7vw9-$PDO_J4Jq`#`8Z9rUDoxYhN^N@DzmezG#}X8pkspB$0dFgZp-l8{61R zi-k>lMn?Q?LqqJs(DTILFoj&YsGg;drb%g|>9KTC9i_p7)O-AAN40M9R zqWVE#1)s#tXog22jN(R4kw7Y{A4C5(Mz#G`;Hs;JMvX9l@%3TkeGo7q`5!C2XATl(@L5js;mB z<`FCvqNU=V%AC1FeNU5--K}15mcMD5?)XUap@Da{3C=dr*%s`cFI;hDb@=R0E5wE_ zp>U^IxHH&}7ku#Rk)o0-o5BxW*)qLuu4px1w0ge0>dn>DzMr;>OUKW@1RH@5#)HQTJm_q=1_I`q06g7tEU6g0SH@z9x<<)hp^OC zJ);xr+pbrO^$+l_2O?QHFAcvq96BsyRf$;68ne7Rtu z9fXYR1c;ceQyo(s#9(Ek6kij%`D}h$nd(wqn_c@!x(UHg?7B8b`X>%8g^Sb_E@t5} zW7}HoCv|E-1)h*+?$elmgeNB1i&-&$)rtA5oOd!l(FGu}4yuO@fuyvaBn;xw#4yj_ z0SiHv_&jQ1P&=Sa;F)FCK$4s&u?A9Fq8kT^h0QZ%>CgsxUh_Yu1`w(=RV4yMCu z#MmWB& zE>!ng@xGv&62Qnq&=S>RqmMg_a5SyYN3R9WM;GZ#xYF1V%@`OP8gdT}KH=q_qP#Tb z+!!TEBC0@BJrXtV>>Km>2K$D042^M+zYs;mJxeKd$B9_d_YIAn=!mIhVeID zKD}X^6Wh?df@E<7;ZCu_OTDPkcRjS&Jqgf=DC=a6bblL5KC%u3V! z*pXnRQ$;4gPnvL2%6JaKQA!Llkp}!jt8vkx6sb(4qeL3?MMp|HL%^`K)E}~H>`y8& z0(Otn!!jmJE;?XPwo|S0C-o=6tRugS_mcA~TZNHSgBC{p6iSwBC$a4)=Uurhw9F8e zS@z_TJz8bUCNlg*iTfvI7Cn&R(OuIkadB8?(GxlFOz2&brW~0GBYH+E5sMCG&r-%E zJDwc=@L^i1C+<5unym%=2tn51zGCj^#M$UvSU^_`{KRZBqn4Z@p z-p(wIeIhrI&GK|iPh?i&4M1j9Co(7acaXcKbp*F{WCQxwAoHAPqmwldv z%3e(r1&Sus=f9z-fwaZg5y%P@DcVFjChSP5uUL`4G@dF@tgMY`I;@x|nOHHgB2Y3> zy6jvkQs$d*2CQ6v!1+wyGIPnPOdp?1T(_cKiGEoE&im?DnIeCpUuDYrV*M(oe)-$t zy~j){4U{WaJo;Q3Fvn&^TA*~o9LSk41@a~`At39*|FMAClNr0e9^+G%C@m54WCcv% z{VYgpg>G+lAk&lcecjbGWvhS-I+OC)SRT8SXEE0pFa^v5;MyT1>`LT}c-RBOmt;z(Gc6aU|yEh(F`LN#F$n-ve+Nk6*q-$3L{j zlxaV0l?Xr8XRXJjt-AlxdVGK#|E-nfiRJh_e*cTsSj-<ngpzkRvWFs^97L zceF=y+Bv8rdpp{@APd~Z_7&oB?VuvjK&W~momon^W6%#;BAO>%B~rxV%{|^BsJZMv zc9Ilxj2&Fx>24@Pcblp_-IB)w|n3I1AE){Fr^-;6hNOuD;r5b zd2DQ8z{^EJ_Qr&d9jJp^9L+d@5VYtz+POE-CGLmRugw0Dv0*>R+~ILAH^MzmH#h=B zinBdUiEuJP(WCQ#yA2Y~s7VU9AKKB~9!*0S8U1 zFf`-T;PBqQGkZq*quNt_XSnZD1pxvi0CiPLB-uHN_%Q%P4TB!&(x#p8GQA`12@Hh> z|N2wjQ#hp^lg3tuGepn+J`QrDXa-FQHxrd+pb|Hm8BrsP_4Q+3L`_mkH)93j7ew4e zEwMW%`h1KGjHa<1KJM$(935>DMYVqS2?D31Y9F+IaRxvmr5PGEU@+KTlC=LMRbrs3 z+_)1}yQ4;SAvH@co!C~DRHK1WnUvJXLM#FI4b<BxxG`J!S(Ywg%|3=*+Nc*m{T#;9?5px%&wiwuAOd= z>oZ2|c{lB@IlD`+*NXO9a3Q(HH*;Ncxh^5MR?MxP>WY|iZkk@WKIZCIx z!5U3<-%C>!u9$itQdn}cuyL-iaR!p-&0^u^sojWrt?qK&bdgZlEEYB+qQo_0=S!OT zl1D!(7h4{e!WSFB^i|U{9m~JL~z`NCgmVn=dU7H%@22zTr~fO5nYo z8QaX0f06&rW7i%F*_c#3bm)~o3;tQSf4b|9q3}?|;k>oBex~t9r>9R}?YVL^bo8V4 z5BCSVP|B6@=}P48pD|*fOCJ(S9}-I+3hs(HD{neC%{e#C)(Fma(b*pCj^sP}{2COs zP+BgQ*3T5p4*td_b{`Q+kBX&7gS+Net+}>l)*!5E6IZnfb~G|L9$pvjixjU6cHVMU z{xIu}tm(57|45~+gtlz%hUraw?e(*U6h0Te&PO+|2aMXfNZUMttHt(zmcTTqm&h?^meMle4 zFAklZqh0@+NTn;35vi;Js9G5^{`2Q+F^KmXRMvt}^N%iX{36%i0Tjda6ZjSZhHYiE&+x-LD#oHp2;(RvA~1x1 zAHClv<-droiPtqj8mq??l!4iyr(KOC*reCnuq6}+S$aKWpEAhG)UUgzl0k`9UyTV6 z2gVjXMrSdQnn(?!zQ_j&jp+E|I{*od2r_3|`p;v7js)pT=)6#(g^q-d^d(q04Poql zGpz~IlrY3g@Yp?O;YGnPLa`Lmb-pM}(?T)9zG8_YL$jQICL z-Fe@^exfnr2l1T1ys9t$XK*AW14veyU{??tNe8=%cN8*$WJL)NOa|OKIVIggd9i$? zh><2=(Y^HeRY3oYMWOkYA}@eVoDS(_J~;qR(k)B<{4xiYs;!1pGB+Ja8%^`eT#!l? zPVRraAt~B!OLNX|BQ?oeq(fOMYLxkBY{6TSH?0HdO3HaS&0iTW1ysDsEpxm9L&|uh z$R&`oMv+tIVEt>7;!}2WP=h>D>?x9A13NrayUe(EtjEMYK}s1tiFOB;Yey#JOJ7mOwXC?ztjBw06H)=oDcihePc}{ry zIR6Qse`FYZS<;16#4*>pXyy>MiQF))bTc!eTz1LWu)cm06G+inu~ftyx=(-;cN2Ga zjO%;C>tQ=OF}~3_=yP*p!^5y|h-M%RV(9c>RpllJ$H}VJpho(b?5@XwN}+*Z%z- z?%kb_a1T>ydgxPwpEnGQjCiQ`lAf_6p18B^pnKPY?t{AyboT7pzo#Q=g?s`%b;J4% z5&%5ks3Ps&wy(Jlw{;(M_jI;PX^BmaHZ(mBfYTX=MyU!e0A*k6vbowec0WT;^l_t#&1$`X-3juI$<}C zM~|t9u_Pr<%10(+gU4YxKE{#46-r}9wfC9f`;di0KpX2-`+He}%l z?{c(uz}EXY?jVJ9$3{kmqS>ej2I({$bRP0@91&H~Old?;N%rZSf#R~E;2@c(V<(B( zt#kj3cAvi8Nmq(=QqR7fxx~>2N4UJe!q<~IYV9qGE>{iVhI#)%u?&G)izLm>YZxqTl ziDjF3{2uS8dnJ*w26mn=tiH7N%37(EGQObsw^hwI9b4ucTLi~8(Xs8Oqhrp|Avn53 zM;Gtt{p|z2Oa*sSH^1r7TUx%dNpLoc&Su`({M$!;RN{)r=H2|}!*A*NmForP2GO~J zcW(IYkui2}zPy2NY!}Kq#PSY`D2So5Gz z{*YMy(0sv)(7LP4uo(0b35R&M-U1@LGr7Bqk1sBm= z&R4cZcJ=bRj)k6jZT#{$ziQictx(z_mUi&?ofwa7+s$w5i8a86 zah*Gsu#Pv-k8z$P-ULb+R%qN14a9i38wk+mbQtHwN9wLEY_=eeUp95>z9Tfspvi+A z&_$!#Vn?dA?Sy970U1BFDR%e?fyIsijcnP2lH$5w(B9BLf%Ojzz-sWo9>|qG#v{TQ zU-Xg*z`{r0T{!n`=i|(4$D`HKYp(jpr@a#9nZ* z`<3p{6M}t}XkRsz5yuUWqQ}U_~JV zgi8e^WJ-g{N=W_UwyAAWC1e`pBV7NNmNrHs9!)z|$ zmg0CDR|)Q2Nky}LsiZk8&r*=W@mb3K4h7&L6ryx4p8zpHoChG;I>YP+nKMRoEZ+3v z4#nsv-D#y!Cw`ao3TgOk`61m+N6nn0MsTbW9jgRet!S&|&9!l9-SWfeBU#6@&I;8J zjO(;B>UGNu)=E@Kg9U~J>7|3q#U>!)7az*ug0rbL$yPH7mnwduF=B^uP_aR1ir>M; zvWx~&5fReK3?|aa$mL&OGI~Z-5Ia1Yahy|Iaf{;1))We+mL)R6GU zROt5iF0Pf<^1{>$x4-=cl=T;We175i>Cc|~3*5$Hzw_tU?q2)}5X0?rKm6?V^S8hC z@xn{r10q>C_tu@uKL!SfZ4=&&ZztYr-3RS@qIzH)$Vf-uX*eE`h;bT%s2&t9{7M)= zdb{`R-+z#4xpE}tk!Y?ZXJ4M=;f0*H_`Ji%iQXmhe!M(+9xk1xlV)TH#bZY5GBdJo zS!|-E3KG*yC*;vLtyOc@D#2PUTB~{XBOP-h(QeldT|j8@2R6wFPcxrvYe;?w*q^ixR`{cPK|9U9dyHO3uQ z?Jq5AK!q;~3zE?2ebIu6a1r``u=Guu-pWZ04NQ5mK@Ol>S~HRnj zpOVNqOKM3evO4H(%2ODgnNsAT6Y0r|BB3+7j1E+a+%c%(_A2b2)5**V21sao!uJy_ zv<=Dfr;`ckYl<{-B7<~p7u)eKXQAzvrIjQZ^e5@uC`X0+-vSxSJc|@r+i2~wDN{6y zM)Q_UxyT}#&6?!rxm;_^O7!v-tx2_yUcNP{@=VgK!VG>_p2aD1ZMn9k=s$f$+fw9T zUoleI%9f16B3v0Wkv0qoFS#6ohrfKtRAt#Rp13|$j>j~tjRB1!RoarNOwgy(kXMlb z9dugEK=hed-PoA*f<2&t9!oBnjCt&VG{C%o(UT9I7DvED=c_4C z5PEnh+bx%knUERKcBqcL2dQ)N?9KAa@@~kgow26ilrF)({ z>H(XgGoF7 zJaDGK^k4>6Mvy2gmPsP%$P8}B6B&m?75I%KQ4tfWraDwell&n@O_ahNyGS1y7=Ys? zUo?AB#Zhx|Ghzv1K6)e#ot)%6F>Rg9Sf<#elq8l*isP~{=f<1>Og-!NxpzrJi@6qq zF(+d?@BHZE!b?AJGKuvVy00StVz2#t;e~HHnI}hF-udvI+ZR4|p4rO1hx_AN=h>}H zYfN%G75DA<-&?tQEQ7lZNOQM_z)t`MPf#3D!gv4gfBBbxaTQA9KUxbCZ%B9`$taY0 zC)-JJy9jgxL?JgG90q>~pA=D@XAmxnent0kQ8LqQg6kVd0;78W*eFDX7b%OLgACmx ziHg(uM&TvLgSft7XdvmJLj~`FT%QNl3(zm>hetszDsbgXLc_QxCTZN`o|t0e*+O+z z0zlnKnmwdGWn$sjW5{67oaB3wKMDgB&LlBox+Fq96O9GVMl%xP)J%5M6Q3-4Hff-X zbq4=uqv@n&MVeLVXQcp}aj@bTJ`TH8?%UL7ExP2(M<^~`NI5gXVl*G5Gi>pb=D0LH z$19SF>17fvsaL~(B3TCo2Oz9+sKQeOE6W6rpnJ% zH5o24R2vN2pna6RLCD@9W^Vu+o>?=yZXU`!Fi*X-<;s?zfsD{<*bN5A0z>MzSsf`^`P$Isq3Mm1Y7t-JpEdl#{B!g5Bf`cW zabpi6_`~j-hx_La_w$}p!r@`@@GwPk{-9}og)?F=zPRU=J$zZLzoexDqu<2^khAz^Tof1aT)$@#qsAZYx9Syfstm)R`X*NgV` zRAxoI%>6=slbGK`Wmd>#ZWQu2iTRtT%nB;A0%ev`nWZ^FQ_yrTOI2DOG~Kckey*}* zx*~-u-?L5k&Snd)&7x~FbhLu$k;3ZtDyE;9T_>#CDz4fp6mCV_3fJ`3*;Ut{;EN9g zGoYap)``x}Ia?=h>xA|1J&n3xKs~z!LyfZpZ>&kaij=R$6O?a8*0v}vckSmLUPa8; z+$k}iqnmlZNB{F^5c2LBR9m~$!4A>B>6WuRm>F4tnV`>ZWFXi%UsM(LzUTRA=kyVw zXtP*ErjNO0ANj5~|MmEX<2TxV{`BnA(8!uED872=t>)?6=_ju_UT=M~b>^^8u|-(1 zRa~)EDA*zD2$h&BO;O{Mj-eNP+^dABx18t z7-v1D4H!J^>`A+pt|T5)3}s{)nR28b!_%3tOjsu@kisR6QPN02H6mqnvy&N-gntla z$rCwXU2Mz%MRVl!xIxPOiS8}e@WBzwN?>s#3JeXl%#(_vk3*-f?F}B5l zc_1^NbT@t|pDueU>fxWB{~Z`%B3#+Aw9;BCGr;CT{)8i8J_J_%YcTauKLsx;T#vsj zULMv}Rv@1lf;c2YkgF-82+Z<|MCy|ypJRuzwP31kVbU*IbkJBXWP;`mCj%HH_PA@MxUWvSrs{;r*lv z6f*o|kIn5t1e)@Nybq{ z`(pbFf8E-}I9Q3>+yUl;yN0S<_|67STo*-atl{`qTo}~wkqvuxtx-8!4{hwlE)tAng@6+zA>Jn~f9u44Y2Jptt8nS_E)-li0T5=Apm%Ku!9b-%B#dQiw`pZp`3f9LY&*OiKO@BCoY{|d2HV<$utyu zjkIvai@$1FeTPavk0tr#my;@TFqw0H>$%qRt)ZSdlan_&*{=P(B_FB+;imTr1WTi6 zX`Ir*?Iak(3`uj~RzWpiux7epDr>%^j4yBI%Qw&F2qjy@k}bTU=$>u|63$n*%r*(t z+r{ebg1Hi2x+;QWp@I3LlF(S#eJoHlKH-3)gP#r0xw{nXw_ zevy=FMlF=UKj*rsU2ww{8VLI?4NX5Otf&|A>!)@tm;R@ zeaBy)xZ&Wpx$&E0kU!YVA8`u@nAW%wB=C z3)Yg*nQ6zYhqty1)^^d_j=+Mm24+oybED|o_%h6kgBwC^_;N?6?-ke)g*Qx(%vEgV zE4Je4+{~|m*^`jJO3Yt{B6CY3jun^mDEC%n&71pgR&JTA+%kJusO%IgI|XZ5&=~5( zyb86>*`NfmYI>aC`XImdL1FEK%puzFtdTDq#_xt#I!jQnkBIgW-aayKFB0w5g54$B zUA)~Du~*%+ub#87o<1>a;Mc$qY=>yy!P|E%lvak1-mKa%SG8f*c)eYy+9g))5=y(p z(r%cW<(G!bUI_#P^N!*x#_&csX=A!>t8eA6h6EtDk~HAX%s8%l$fJ{Ex5&IaMM^6| z{*Zs6tm@5z*NfgP3O+DjSaQX6srE|kv{5K*nCY1-+{hPhoUdLhR&N!mTgB?uOJ*wUKV1G)qKgHXhx@F71X{(&GRSLG1qK$NWvI{Y-gPotl?_42m_!osXhQ9`< zbIEJVmd`s}c#xuP6>nZ8ZS!kLDJTx+&DnfTrKUpmxrYjU|rauTAzl2PLX$>)S z_ldPTA8*kA$<>jE)8DI%`>VBoZ_L?WuKoLRJ;Dka2jUM&5V8dUqHe-CFFri#RR4rBna?hWm@T%OmdZIxWh65fn5noj+#hO<6ck5_ zOQ8;W&!nO>8e^u8{3P9LqWm0%Xv`TUBhftc*$MW&4sML@R#Q4V0ixBU zkG|}rki4zJ?WJ@?!gBiwFgm7|k~~P44-r^RmrqgXG=U{(A?^&_pmE^NQi#z^jNmDk zY|SOAgnek@>y%)Uz%vA%CGZUb&k-OBgnOPsY?Fny8rTL3=cdr(1a?r8J_>!CLdPid zO@JtTcaM;A{Bl$YH$_SRfij(=(2E4VMc_Pv6vCq%>AsTgz|9!x!8IWN^3(=3>%Ss} zZ##-4Y6I#=@hP1bO5@GYXI?eaAvQh07wyI`Qm}$e?&{?yHxsX*G&82$ zr2|5bVDdG@l|;J6j>H5{VQ}H@THbI~JwaR)X|KYgAv9`}YmOHLi^;dqza%{lXh}Td zfq-M_)G7M6-2P=#rf3jxE$}>q#hKJP)&{OFS+gkN_YP@wiL}Z#E~~<~ND#DauTw<1 z6S{!zD|(&6sDDMTQ*@EgYaM!$p6E$Tn6iAY4T-e>=3Z-(-77;|U=Y5r^vgWaRE?xG zzbv|A{`yGoHFhjphRKs64pz1t`e8KFV@J|6PI(H;J=auARdDhrX-?nIih#I{)yowv z-G=1eDqAf%P-ix4S^L;05TcqBqe)*tAW=qCb80m4DFo@W1zNJ{(tEtH7~$3tdLo`0 zYL!_OW-kH8Xwq`#8YzxpX+ptKBdJxk9X#09zMHY6_>7E~lGReOuTkiG6uJli5A68p z0~ey}O8`ES$i=aq#8%nkDwQ!4EV8)iSE^nwm7*O>-**K?;tg)H;QM!76YK*aJ5bCwOfWkbZ87fg#}=Ups#r6APwa_NOq_|3CqPdy#3 z_+j-M)%>b0Litv)eCyQH*DLKpWR$!FeJc=OvJn)cz- zW^9h*OT{Yokuz!DGyAMm@-q`E>Ljj^%;v@ml4(xGts^u|Nel*u+~q6ZbiH2tCNnK6 zoi|v{XOcTy>6>-Dp;G!uLzetrlZWhM6r+6qN>(L!f5-zQ4T1z0`M-l5$}<*vXT{#R z87V#sASP7|u-uB2_jeKnz&5;+6wjA0*`vpUNE>?|Z8OF(z-Pa>u<-pqcfu)^*ZJA& z(|6wd`JE4bc;|!n?!0$y;p69V>$BG<@nM0tj?}g&T94gP7$O2$|BKa2jIV=DJ0vEj!ZWaDJO zIO&pGzRYH@?plflJt)Dl#E2$u=bnR~Oz8Hb&V+4%^2Nm2vF7AW-$W^?-dLn(!P_v_M_X^{sI_})zi9@0^dk<)!Y z{lynQ)6q|PXgyh^z#)|}0o4sIop7kTFg}V%D~EkwgCHqANqxhVTvCju=wj*~?S7Jx z#EyigQcsGl1LibsUd7YNb^-7_f;siBJg<;0xjb2;e{p%9?3C6gdKw$45qQvD+-~^Q z&G2Oej6S+o8gJ1gzKn|Ua;V@d+HSW2g&?ap}F{vGkqV&k`z zS`}-7+n-$1GrJbojQi#Bvg55~sVd^J)IOxDj9BuCx@E?jq@}TA(d&aRh#(wI=6dJ(jW2SM^`9YL;oQhbeTS{6wqK z&ik)J*|ue|Qi?Ui1mOf3A5ZQIn4akhP@Ih0V|ZdS;u6@_i7R=v|J&ZuVIrg#9jPOZ zCqq(&MMvss<4Hz-(sog60Nz zru=Q5d5O2%9h?LpvG^?g(Mki-sWCQGf9Ppk*> zAQbqHMv}tQm?U;*B-In{9wNtUlR2Td2!}~`k~B_Yo{qkW#(qHv3)1Up`%PENoU27} zZ4q5t__Bjxd)WTl9S4LR2gMx+CnYyX|A9T_-oiTg_jmET=%O#y#Tnhr`nI|HHle;< ztZ(OQ9-Y=r>weq)h|vA0*!^g%i*T2mLB5XILyy`?5hK}s64}WA|8Ep7VH7w*_KYiq zf(G-u#5^)EB`Yq1Nf6WLd8hRtN0JTh|DZYc0)g)_fH>D$Y5El*OrI};XCOEV;#Sb5 znLI!-UmtL3#HpzS#@AaYR7@$XFb}71l%Mco_izXvAE0c*VtoFw{wJaa3^iMD@OU)_ z_eLY|6~vAD;J-@JBaxi~F=s$g2YD|_el$?;!BfMxUGu0$qVlab##L1 z&}vG+ydp6119awMg4X|sGW`nyEkHCK(%O!Z)5B~JEUL%Vp;0cIQZw0X6NPL9atPQ7 z1PPFUG@4HG+JkL7xc|<|qxfb5CIWv>;B|ngVYu(9!Q((ME^|VjOCn-&RWwa0%<^<} z4-CWQREochsBI}nTI6gasvRCV4d>rJ_ptYL%)3U^2-j8~ZUkmi9wv$L5qtW0Tr`BU zBp=RHpbn*|O>v9xqOUBC;Sh*~Z<>ndOvQq!L^PGa1S7+Ci+QxUX|A0!*9zt}qInH( zUK459KysCG(Y!XYqI|03{5~eN)f3=|eN!f_a;0 z-o~4^u}m<$$;gDmrJIJjIYZs_m|$oY4b8lvS?ZQ(!bjFEke^#@=bwf(OJ+0t7KqlB zH?3>utZN19I?=k0w^GM~x(iwHdku5e2Ep1STAO%lljQS2w6u`hgZzl|Q9k|)n&TN- z=d7(aASiDYtcOMGVcvRp-d1#VXSjo3wf%afP`pzt-YM92iMCy&AWmkAXuxNgmH$NQjda?6nQPW&e)65~s z^oBP$7D~#)&C`xITltDEetnlvvQsSC38kuArjpMgaL#DF6_>b?FNYf5Qa``C{#y4t zyRYpI>O`yS-!W2n7FOrys(K7EKDO9>xjXy>K8{@6EEYF2OQz71uWWsJtE~SLY`;}i zH)9vqbzFZ^Shs7gYF7}7Ta}~^v?a2Bb4VvT8c}4iQ!IitmM(Ym?7G>r{N|(h%`teR zN!%R^O3{Gxj?ycZX|1fBBPqu;362`kQNufG=zeCnU-GBIJ61*3x5O(dUn!O~%{)0* zwvjJ;Z1#~GcCq`hxvh@{ABZ(-^EA{X)VZ5UD0zTi-y7M$vNn<9uJ06=WevB`E z>{e0f&7zHSMH_{p7O@C3Rb9{;FFw+|k$Tv0YgHrJa8=)mPrhkAWgZ$F6Hh{mOBn6)HN}&CsX1u=gz}RFT^s-o9$ywdPvEJ4M%u zsDhQZR@W2iam6Po7MukdQpU{uTjVpOcFtNWSl5WwHN15V>Rq><>RA(6&FXWd)<0k6 zdh?OjAAR#tC@od7q~+3LsaZ|6R7Gmn(zzz$V%IAptJksGQF2bcaz707eI;+fH>75^ zT|Y*X=kd9&$N8?u@qMHV+o)r;SeWS1O?%^`3;USE6Ef%$td*j* zlDAee4V&sY3t=)#ooE57(NHI`7l+zQVpvzgf`pv$X;E{7Xl~%m4Y+TGv6?1h&07a! z-D?sXJMl5o8``<5-F($`_w*i{MF3x*ixn204dVx+FNPap<7}Cxa%f9-5#sFlM3c9rsi?r2^+cjUG>OX(){@ zjVbw8Kh+0n#C_1E9Ro?AT6iyX`zIer!I{}lKl&~U-g)Myci(%K`vE;4qEp6*o57w_ z3nNIFWqMWY10xj6@>Dr*|EE`5*zWcp)m2P!J@e5!FaFi-$!Ctl^w{wc66W}*g(HDk zRQ*U)y>E=RB;p?{VXn+1o%ewA&O1N99saN-if?{+;reoD#P5?5e>NHX^sk@C4bK?Y zcWiKI(0>-6LaDFfzJsF1_4wAwnHFYIPsZ{s+*-s+8E;>?x)6N1C7L$S*AEgHnbr;b z0o0M|mouCbCvX;8*s62Ksmqy&FfRP;FR{aR`@J`?Lk5*QVtg5w=h`Hxaxon*rWHUO zrL<2XL((i)GG1AK|2 zWlSV-_0jD9kr58c@gPIVoE`o-nG;V&wlg=KjKpWoIk}&q0URTJFHQD z)Ymu%Ks1fq7z_>JOCTrc6Eo4g98;-mo|Rh%>e_wg!gq-X`NasUGYB1um9WLCsnIGKTPZYyu!Mn6^d zJ)Krv7ttA?+bilEH+5_0bZepFu4@o=4LtjO8A-R|^{>XeC=L?IYv**ef^LndTf@hH zG_ZA~NNY$}gUXVD-K>U{w+u?OYJ6Bh3Cue6cCw&Oz%0Ew3skZKSnX12m#s5C}?hf4}1~o9_((rQ@|NG>-XRIond1`!4TOeo)BF5aQ+H-5pubFJWr?KPn z4VvtX;)uPHw^s`Gm7rDdQ5Xv$W7y{xx6C&GV$;tzT|dGfJS1#>Sj4aRFbLN;Eh`i^ zh{X+zlI3kRk&+|fL(@%fKFXII!Ebg@I^P)M4?XhhKa(y1gFAyeZL3NluIDxYSL3vDXeACUBYz_5?`e!T1|A2gNUk`uqv0sny zI|r`&uKW1@f#kclN-AC(ygWEA4)yh#5BKx-9>oo*SJ3Dwf@jw3 z9B3YA!&L$RG>-wYRM{X6%jT?QVK|hl5v?`6wI*W5mq+0q&UbGA`TbM-Kd->U`|@6; z%De)To4&;n2N6T&l%CHj5e%hpddnyMFunEk$&!1uDqSJ3E$~$VqkK|c%KXJu?5NTH bvRV!JpKCj^c5YJr?I!E4OzjP`8u0%GD$z<& delta 6034 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 diff --git a/__pycache__/build.cpython-311.pyc b/__pycache__/build.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e327da4f278318178ba714f42dc41957a2040d8 GIT binary patch literal 1187 zcmYjPL66%+6duQpE$k|OmmniEowT#U+TPrS))R*XI0eDmJ(y!XBFFG|V2#|%(E^Cfe}Kqwhdf{bAUf_a&?23pV=hi%TrEew zjjLr2`W`QtxM%$@ZhyKOB8*dg!b=S@Jw^}64@X@ay3^pyMpIr=$wApBqnaw4%s69E z@_8ksR<=D8;zYS%8*k`E-8PYnQgc+ZG1>^uvSPvTm;=n7mLjbr9AicajAIAzqv@G`*%pdXq5ylHaYd&Eq!+CN zmTE~en9}UT_NdHHQ^+T1c?*idPjzxofe0wOm>M*4MXeOJyid zE9rh@8)1-3p``nltq*7L8+nG5oOh-RUa+yMAUluVn+vum;C=ZHx;&ifZ-m6gRtMI$rjdeJs{0w{jq5tJPxjzI5A1zbe^jl!7!}J6?8~{#|(DO?w<3%cxYaD z#l#1uH>_{$HXHvCgnu2Zz4{H(>a4Tx4!?ix$HSlA`nCHwJo+;{dJ-P3{lCKYIx|7b z1kG=6JNV=ZJ~BaACwr|%-6Nd?)9IU+Za9p(F75EZbO+|;SIzL68SI(;>-g5MyJ)h7 LweKGJHtPKk#!7Go literal 0 HcmV?d00001 diff --git a/__pycache__/build_wow_multikey.cpython-311.pyc b/__pycache__/build_wow_multikey.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ca896a89f2fcfff6dde8bf6e4a31d008e6b7c54 GIT binary patch literal 1416 zcmYjP&5s*36!&~&GWnQ%G}~R8B4D8^3KDw&?G1q{RA3Q8NPq+p(#RP*6L%+L%l2$G zd&+?W2ZT5vap|dt0-`7Wk|Omm@(HO&E`!QxPdq1^P|x@`KR>_m`@Q%4OB6K`j6d!_ zWhXU+p4!EB^smUXCqRBi1dUOOi1WZ1J1(LwaZ@J+3k4+J13(5V;6Cvw;G^2Z2%+C$ zZpPSyzkKT5gE*T3JlJvcD0t|BKg`V-*TFxeb?|CzZNS%h?HYLNIeUA{Q#1`o-Ku~m z1U+j-z%4_haX1R7sm2{MX4i*RjBQw)U4cuZzKgFXDNTX?9ANaayn= zu^bIdxM2C)Z^814VX8U?N;-9#7!pIX|N&+%BaH$D4k_ArF>Ytq@uA%tVBO zgm{i~5GPGP<0(^`C2D7ilrECfc!qP5fk#(lcuD2@{5j3_&LFsAnt`5{Sf*5iWWpDw zA(mEy)$VJvZS5bW28+ zsS&KPGSQ3?LUT43Txw++GtN(ybvCUv-892QvdA@q7OjmYq~}Ri5IE)l6vjD^g``u+ zN77ATW%licknGHs2`feClg!2q5+-I)fkw`;OlItijvV=_t!wA~ndA`SO99fT{9+Ut zKZk1pQt6~f&5a54I^!6wP|VVtL&6HaID=%AmP{D05a*@^5MSvtovm&?7og14As@vv zYKDXN9Wj;&tXeaIW)#tiDFnO>Uy`kPVP zNEJ_6Mn@gfo@5*vewA$tLzT&TPnqxzh+ZnDjDw+{UyqG13Q0}tf(Zd$wll^P%M0V( z{pzl%s|1qMO5U(l3c<;SP;zLO9zCbOp=UtR<-w$28Hu02{YOgBaNoGL)Qy;ZyNgRWblEv#Bq57na8M`dmJ*uPn}qB821&Fht09|RTJK@WBN zW$#*fZO`t%cv#+irEDFPok2CaUUUCJ0RLK8In@!WH&@Abhu`1+@$jcNe{DYwj{gjf zp9IG%@2{Y-N=m<8`n7LQEPT9!4@*C&qP@CXbx?CyHoN6ZuUQP+HtgV_Z1>BTZ-Fl-ftUUY3_aNW@0G^l6)&Kwi literal 0 HcmV?d00001 diff --git a/__pycache__/coordinate_patrol.cpython-311.pyc b/__pycache__/coordinate_patrol.cpython-311.pyc index ee091988e336b4637ed4a0f8137a29526f089ee0..fbe026807de1cefe1fabe8e44d4ec042ba035f22 100644 GIT binary patch delta 2394 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 delta 1473 zcmaJ>O=ufO6rR~1X(i9v`iYfDPNa2EQm<)KH6YiQaZcy?YuWL z@8_F0`<2<69RFU|!vtF8o4cj?;Kulo#u<<{iA5}0Cb_|v=BO`AIY}am#FEyCCEt_? zxea~LawoA_*n1fUo5Ut)EhkxYjleFjl~XJkP_-1mV*yKrPtXd0 zxuC~BunX?Rr9!1}!RAFt{H{%HJbg245tx;h7feOWNQ((m@)XA|f5wC0!oi>nV?QF! z%5MZ;0-;HIVpUEb?`YHT?tz9BpGAcNZjhnx&50-4oH!jipOJY86g+^S0o6fS&ZBQVQeo26o(srRYrIr(J-zmYRpNHhEmdlD7qzzIc#2zE zu|3r(+jh;A{Ln#i3$8t62U5^jHV_BXjw?>HPv4#FYE$37zpWWv&FE;xj>g*I_1CWH zZN23`9K$S*4jcppx=-7mMBHP?rR$Q2>Tx0TbX;1M_@axaF>ID3ehi;9pltp>`=9j` z6u>IUYhr&q6A0ALfdMfyagHvFk0NsokIwN)P%W6D!Qr3}FIp*FE?t1^@@_R>s{$`P z0eXHI;Rr$!A%%daY05q&d1xa8yuoR==!mV@aS1{^R>=)7J*gT*SZIrfzll%iOT z9zK?aN#{!dIQNNoyU`~!6z{QEYhiaXDWb8XuLeT#9Tx4x&Tg~$E}QSL`5l(*vdndP zn`OH!+hN%q7HNOD{`s|~_EJmy8cRfU*wiNg1ET51?xDshaI#6j($zWuO3fXfj`lJIX|2kj0rD=AL73D&Pvs)m+klXEa;F?=M#XwOeyV= fv8MkV7#!*leBXxN56n^s;zf9jx+niJ;rsm?lOavq diff --git a/__pycache__/game_state.cpython-311.pyc b/__pycache__/game_state.cpython-311.pyc index 685265342301903497699cc250a2334905f1fe70..bb630976e1c0298e87b76ad8781a8c8b6de1e705 100644 GIT binary patch delta 1782 zcmZ{kT}&KR6oBW>{=h;9SZJXv3+%EB?36-lF~v58fGw4#E!xn=25P3m-eGrScV}~F zwm>wpR1=MfMspKiY!lOHeL#Kan)boO2WyOd($?g5n{p27i2}a9mm%5OLlgXC5+_Oi9Z8UW{u?<| zZ!54Udosu)YBy=(�Gq!qhBofY^{FDttL$C|b5OxCM#HKGP| z_+5(M^1tXG1c~?f+AE2`7o-;xIVtLmv(u+un3|gtiXLL<%VLN)-wO6N_Mq5{7~+w- zu4oEG(PCsQ&qzCkB|9S%W22xR;pggZkip8Ib#-bS6~a&Lv?oHwiRqJ57tWlY+YXG; z4)AD0g2ee`L%c`EY|S|)HFD;fQ+gblO@rsr%6h{)DoJroJ49yrq!uBAd_n8eXTj)V zZDW&6MhF`ovkliXJGqB2<-ux;kTP&I&%?63=H@^I6?%gR$iIjXwXiGRs>c@i_1#N-GLQBphviMr$e4L+ zJDr?eu$TvP7b^XGMpTG)z9UT%1E66D-6zzMgX{#3rvPp(uQE$IH{{52s^?mcw(1Ta7)ZGOgC-YvwA?bg&jlJal`}wno`Oab-(-%i=)N| zC1=lqF< zlmaMWx@c6C@|8(u!?zj);0nf-DrUw^RIa16h)CnG9wp35*JMFOsJLd9JSS7K8Lo-N z_;7!69lOki0U~4-N_mUH5fT10bBZFsoKk_xgQ7=-ujsh7jj@K_BrCMzGgGs((`Ss? zsk75_>^)Tb3$U|gM}%+DS!JJKc#c>`b0AwZimM`!uYJ;s{D=OL#vR4xp@GEqMN%{w z+-U!u6m}aTyjz(Wc*_Sz_DB8fh5ew=iSSvFb-Jf z*DjY{unNCt=PeOTduv6@WgnrcvA71?ueL+k>)hRUcy1E(wZm}(r4fX@{zg%f+Z*o> zc?rnF%W(J0I?FWS<}|Pph9Lq)W*0oR%>UlkQ#;jz=$ZojRevn+&{EEtVBf-!!0V>? w_|TWZ`^nV(ex3h5)TYJ5n!2R`%Au`+N_c;kgu`RU>y^9pEytt2yIlnMFHxw&4FCWD delta 1487 zcmYk6OH3O_7{_IJ!Qk1H`R7Aa1s@m^c(<&?Z$2b3( z`DW%n-|%?#-PM6FoKA-T-}(o8sy8SIPqFde=R64hd~kQ*yQQ7B)FIiOa>*U3cDeIy zA?21mzz(?!*eQE~9=RLXCHsJ0*$?cN13;hL1N18aIe1;fq%RJxMI!u|8E%+w7-y`kj^LtdI98lrn%g zi#d(H1JWiN3l{Lm!38U+vF8zA>oH8&%*s5`k@gg}R}q&HSJ*-{;K@PA+j0dpf2}NK z3R?C$&9KerEi%i**pZ--178gF19Tez4poB>TzftC68VbVj7@B!YmI*pGJqN@p#yXU zF^<568y{kXt2gkb=@pEOamKW1)D+al5I(%B+d0=2bLpWJ`%? z(743*Qkv?Dl!vL!XF_*j#(Q;^*fzlf2@alL9t0stxJiNa&p}+l9FAw-e)DW==ePU! zp4M(9Lq;t&-!1+t;O4Trrf_Svyirng`Y}qar41;UW=+v8_F(YUQxl*!>-kfRh7kh@ zqtK0lT)-wiIf{?Us8_>5y30m~x`@io4fQo&7hb@(6Xl&8G@L#gd BXTbmf diff --git a/__pycache__/hardware_control.cpython-311.pyc b/__pycache__/hardware_control.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24287a8f734aa0bc1978343cecf5e4a1939425e6 GIT binary patch literal 13870 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 Q;cN}Ot>Kax{lqr^AD^Xhi2wiq literal 0 HcmV?d00001 diff --git a/__pycache__/logistics_manager.cpython-311.pyc b/__pycache__/logistics_manager.cpython-311.pyc index dfa03fb4ba2c5e69c14025c7d734b73bea137231..b604c1c15145dcbb9d519f0306e8ee03b6a5d879 100644 GIT binary patch delta 2690 zcmaJ@Z%`Y@72lOk|IkT7$OwTj7RHGqlHvr%*ugHQW5-UM1Sc`HV<5(YlR-8hX75x| zB2_r!1QE-QsGOMC5O6{WwsC?>TBj{;X4;ufr!$?NX7oXGGh~>FPrxV0wEogheS5;x zifQ-me!K7QzJ2$0@6tc|`)>2+CQ}ZAR$2G0PgO8vcHmcsw!03gI@MiFBZCpAZq#s0 zqn6V&>Qv}3;3dIW^!Mo;$SmOcav#<>WZR;Tcp@&Be&p$T-UPc@asW??gEnwiSwV-Me zsGIAYgD8gIXbdr&I;06=Ql&ycJPEot9~hvJHmD`#LGAdu&6=o8={Y9bVYXuYDRoiZ zDOE@#Xx1GjTDB#OZ_RG>utlKpRFi*$y!h3=iZ8oz}!pSc;AariWO%2V>6o z|4kq0Jv?RnJX;**SYXlYDGj19jjA7Uwc(Tx+i_;PrXSitRtJI_@=j30Sqj%?K9q9_{9!a$#eqcufoGOS~ zj0yn|RKxDd54;rLq%9B2Ur(k-2IbLMdVC-~er@?ibn(i$<$()JUw)7t`Mn(Z?RWie zFVh-2R43s#CH#wk6^NRe8dsAXyC|QZc*C_gJ?&bi1so^^aHXfO$upy1fA8)$iD< z$`b>bbillUmtnfB5SMOE%0ut1%w3TuuB^zgGV|Z4!tW15 zlx|ki5KnizS5mio1>ykz#7u#voE}qNo|hQG*X5Noe5cpjLo8Ilba{jhiQ#;_Kxi4d zb22BH0i3ibrbE#3ZJN$2h6 zT7XHO0EayF>RNAbC?3qHHbNeUuDfKnygmbF(%TqT_%^bUa zX8Mfis*b%VvsN*$W85=^ueHGd?!O*PzI+n;aE45qOS~>CD@WATOzV0 z^K5SPNQ@sm8a*00I6ex396&fAu+EMiG*?C`vE%gA%%$7gg2=bof9*{Pm=YBtY@LPG{PkHg(-_YVkWlu zE`4&lQgXD~$TkX(QFt8SI#x=GryJV^@4v!OvHzzq=AQ-VNB8x}U>42pguXnfFBkRY z^Lk6v6l+W9i<0^xQC~E#XQMf>%0Y9~98oS}n;kLy8DmHMq_I%>OK>yF6r?czuCWwb z<5R|Jd?Nmxu?O2`>sd9fBJ@C!@Uz4YeI2N85GUD1gIbFchGbuS$mD*>N4d2C{Yc(0 zvYmsLs3l_AIP7NzO;J-sxgczvxs<_s;_ke^9j5;q665djc1z4@-VfO6_i)O-l}z29 zpZnV3Pokv8^{aPayte3 zs-@fx58-+}#M{#5?-q!^Gn38N~bSmbPso%DSOi&BgsW3(gV|ITp;$e&ee4EsQHy(Z=|_!vEL*kScNg E2le&jvH$=8 delta 1430 zcmah}Z%i9y7=N$5wlBrImcm#WY#v6owc2Lj1hY(>G98(+4{jd}b7`914NIVH-n$Yd z>gwELtCfMr&ugOXg`>3uzm2GiKb01ku)J8ad%~j2@vN8_sQqI0utlmbG=`m z_xbZaf8OW4pWBQ8e}&_m2wM$adQ;=nxWZ zXOL+B(t^;}@Rq6DAu>mi&vB0~kBoeLfZ0FtOM{g?gT7ln&Ty3=m8r2HJgCVHSUAgL z6|gGW5+oW^d=}y|SF#dTq%}L@Rxh)cU-f_@!T_w30~jm3f6N1Xij++{k$D^SZmh?V zXo2-cilTL#71@h6HN@>?si8V!udAb(tx>Oiouh74t6r$8R8LyBR?(m)i4Ld|C!=Z# z`%f+18P&%>7mksnBrHu$moDAZfB4?WTv?jRF3+ZyX5KH2P8(x4^qZsiE}YYchf23p zWE>_2t>jZ>iJCCfK#Tyov*0?pbJe$2ccL&@{r!%F=9PE~? z21{^)fcoSR=u6i;8U6NIVbB`fb8?WCgTY|3O}$=G8#Bh{jNEzs+pLiu21EV53FF!q zMkZxUWb_ZG@6Js?;Fpg1Fxd)Q5{?27P~;MCiBTd&lxQrGROs1AvRq`9Xunjn$$gTP zAoS3#GUjQ?w9x{b(yFuT)H&c&NXOg?Laq+WjHtC9F0*CKhay_&&CQa{{3=2f2QBwa z1Uc{vc#DSXKRc*3>?z=84L9d;^8$V(>m1&zRX; z4UK75!*%nn>a;>Us*}^2%p&U{Khi*9JB1w-9tGGa!o~*=1gYR@fE4-@qY6IH`wG~v zVSgU`*AnU|U_rw|9t-7cS~7f=Pn!?%;x=PjQ-44a?_CCXO=EB}@ znD#0vucIJPc$`9jf}g^(09O&A-vZ*Mz^(%wT=@g_ZGcDpWZU7_Ob==d z)7}byMYf-2Xbyqd)ZKI=GhzDqEALBt_)n|{cz=IfO!i6bqyrRm>g7T8#rmcbHF>o5 mTd^a)A>~}G-;qb&MZP{&xne)cFfA+Szj4)+-+zeKjQuwV+>6Kn diff --git a/__pycache__/recorder.cpython-311.pyc b/__pycache__/recorder.cpython-311.pyc index e6e4e12e0c9940e5475cb86304af7426d0578924..bf2389d0782d8edba9be57e27071f5b1d8133158 100644 GIT binary patch delta 65 zcmbO(zd)XMIWI340}yb1-;wFKkvEfvQ^dv9%`wy`Bz|%^PXL?636TqNNt@5|R5CJ} UPj=^XV-=UWz#y`DA|D$g09q6hQ~&?~ delta 56 zcmZ1=KV6=8IWI340}vDzt9R6dbq z52EAZ;rAEABRPy$k8UP2T;0{+^E^fzT1OSv0jlsHIfTB@H5qxKg11mwIAh^P8rxIV zZn4}U^{=FlmGe7P&1MQano6|7=-vCX4}-$0s?|EJcA?wq76v?b%B6t1Y`#(IRBc{+ zNjk(!1tK!Y6lpi{>0^Eg2M6=QU5rD6=k8xza*pL^7-lJU>7wJuV_VSLrLsy=dRx3D z5Em8o6H&oo{Zx!beKfRj&4$h%X%=hhYmFI_$s`Htf5e5Hh!J{&Mj#u$rzYeq$Qh6u zyV3OA7-8{-gTs}f6zV-YR!k{oNioBj=WZkhdj4aV2{8*|2E_Dz&-HyjmB0kW0>uD@ zndF|QzwnmohyF>8+}|}JZb96D_zMcR4XdH=X7PYrNCvG$yPw8r?l&t@z|!q|Tq-d&}%n5Q)O}ZSQPu z6xTObvTMbywJe!t8HM3K!#u@jL_+L2$RIe-x20EkM`STQ$_SIg47VxlK($0F-4aoY y)#81!=py4vR7A^NQNfZuWC*GnmikrG0>H%XXQnn)%^wSRkj8I delta 660 zcmZvYPiPZC6vk&ZoA@@_F=?=+VX0krv!tPDp}i<*O$;SH_0TF}K|)DF6Z*$ENx+_p z&_l(7Ed!F1=tU7vl8bk}h?ia1(?Yj_Fx7rb@ zn5M~7!j8|-A#pc8Hf0|Ys@c26fu8a8@t4%oEnm0XaQ%uAZN!JMUeyE32g?OZyowKR z52M!bAm>BQg&f-0UVMM%Npdf_n>?*DdSwr?K4e|U4nY5#{|2(&=*@fJ_~5wU3{HfS z2c{3E3+5T${r81*^1ljEOxQFn>WRX5Og5QUIF3A=aGr9UM4Mvsvh`1i8`7!hR|*pMF%i>5M8c+W?92IW!2Bw_*) tTCd{iPx%pC-*`~#uGeSzHJQL4Yd6F#=I9q(a=H#xvCT%rGv=sRcML=Jp8Eg* diff --git a/__pycache__/wow_multikey_gui.cpython-311.pyc b/__pycache__/wow_multikey_gui.cpython-311.pyc index 1b44e6306c444026473ca569b8e3a3ce2b712c30..b8b4cc31c9001d4d21de2a309178518829ea9f64 100644 GIT binary patch delta 32989 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 delta 22300 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 diff --git a/auto_bot.py b/auto_bot.py index 00946fa..39155a3 100644 --- a/auto_bot.py +++ b/auto_bot.py @@ -8,7 +8,6 @@ import ctypes import cv2 import numpy as np import win32gui -import win32api import win32con # 开启 DPI 意识 @@ -18,7 +17,7 @@ except Exception: ctypes.windll.user32.SetProcessDPIAware() from hardware_control import hw_ctrl -from game_state import parse_game_state +from game_state import parse_game_state, load_layout_config from stuck_handler import StuckHandler # 定义按键常量 @@ -32,16 +31,44 @@ def _config_base(): return os.path.dirname(sys.executable) return os.path.dirname(os.path.abspath(__file__)) + +def get_config_path(filename): + base = _config_base() + p = os.path.join(base, filename) + if os.path.exists(p): + return p + if getattr(sys, 'frozen', False): + meipass = getattr(sys, '_MEIPASS', '') + if meipass: + p2 = os.path.join(meipass, filename) + if os.path.exists(p2): + return p2 + return p + + +def move_cursor_hw(x, y, settle_sec=0.02): + hw_ctrl.move_to(int(x), int(y)) + if settle_sec > 0: + time.sleep(settle_sec) + + +def get_wow_client_rect(hwnd): + client_left, client_top, client_right, client_bottom = win32gui.GetClientRect(hwnd) + screen_left, screen_top = win32gui.ClientToScreen(hwnd, (client_left, client_top)) + screen_right, screen_bottom = win32gui.ClientToScreen(hwnd, (client_right, client_bottom)) + return screen_left, screen_top, screen_right, screen_bottom + class CursorManager: """通过图像识别判断鼠标图标类型""" def __init__(self): self.templates = {} self.handle_cache = {} + self.log_path = get_config_path('cursor_recognition.log') self._load_templates() def _load_templates(self): # 强制使用纯相对路径,由 Python 自动处理 CWD,完美避开中文路径编码问题 - cursor_dir = os.path.join('images', 'cursor') + cursor_dir = get_config_path(os.path.join('images', 'cursor')) files = {'Point': 'Point.PNG', 'Attack': 'Attack.PNG', 'LootAll': 'LootAll.PNG', 'Skin': 'Skin.PNG'} for name, fname in files.items(): path = os.path.join(cursor_dir, fname) @@ -66,6 +93,33 @@ class CursorManager: self.handle_cache[hcursor] = res return res + def _debug_log(self, message): + try: + with open(self.log_path, 'a', encoding='utf-8') as f: + f.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} {message}\n") + except Exception: + pass + + def _normalize_for_match(self, img): + if img is None: + return None + if len(img.shape) == 2: + gray = img + elif img.shape[2] == 4: + alpha = img[:, :, 3].astype(np.float32) / 255.0 + bgr = img[:, :, :3].astype(np.float32) + bg = np.full_like(bgr, 255.0) + composed = (bgr * alpha[..., None]) + (bg * (1.0 - alpha[..., None])) + gray = cv2.cvtColor(composed.astype(np.uint8), cv2.COLOR_BGR2GRAY) + else: + gray = cv2.cvtColor(img[:, :, :3], cv2.COLOR_BGR2GRAY) + return cv2.GaussianBlur(gray, (3, 3), 0) + + def _edge_map(self, gray): + if gray is None: + return None + return cv2.Canny(gray, 32, 96) + def _identify(self, hcursor): import win32ui try: @@ -85,20 +139,37 @@ class CursorManager: best_name = 'Other' max_score = 0.0 - scales = [0.8, 1.0, 1.2] + best_scale = 1.0 + target_gray = self._normalize_for_match(target) + target_edge = self._edge_map(target_gray) + target_has_edge = target_edge is not None and np.count_nonzero(target_edge) > 0 + scales = [0.55, 0.65, 0.75, 0.85, 0.95, 1.0, 1.1, 1.2, 1.35, 1.5] for name, temp in self.templates.items(): t_h, t_w = temp.shape[:2] for s in scales: s_w, s_h = int(t_w * s), int(t_h * s) - if s_w > width or s_h > height: continue - res_temp = cv2.resize(temp, (s_w, s_h)) - res = cv2.matchTemplate(target, res_temp, cv2.TM_CCOEFF_NORMED) - _, score, _, _ = cv2.minMaxLoc(res) + if s_w > width or s_h > height: + continue + interp = cv2.INTER_AREA if s < 1.0 else cv2.INTER_CUBIC + res_temp = cv2.resize(temp, (s_w, s_h), interpolation=interp) + temp_gray = self._normalize_for_match(res_temp) + if temp_gray is None: + continue + gray_res = cv2.matchTemplate(target_gray, temp_gray, cv2.TM_CCOEFF_NORMED) + _, gray_score, _, _ = cv2.minMaxLoc(gray_res) + score = gray_score + temp_edge = self._edge_map(temp_gray) + if target_has_edge and temp_edge is not None and np.count_nonzero(temp_edge) > 0: + edge_res = cv2.matchTemplate(target_edge, temp_edge, cv2.TM_CCOEFF_NORMED) + _, edge_score, _, _ = cv2.minMaxLoc(edge_res) + score = max(score, edge_score) if score > max_score: max_score = score best_name = name + best_scale = s if max_score > 0.2: + self._debug_log(f"best={best_name} score={max_score:.3f} scale={best_scale:.2f}") print(f">>>> [雷达识别] 目标: {best_name} | 最高分: {max_score:.3f}") return best_name, max_score except Exception: @@ -143,6 +214,11 @@ class AutoBot: self.skinning_wait_sec = float(skinning_wait_sec) if skinning_wait_sec is not None else 1.5 self.enable_mouse_loot = enable_mouse_loot self.cursor_mgr = CursorManager() + self.last_target_damage_time = None + self.last_attack_scan_time = 0.0 + self.attack_stall_scan_threshold = 2.0 + self.attack_scan_retry_sec = 2.0 + self._last_mouse_path_scale_signature = None def execute_disengage_loot(self): """从有战斗/目标切换到完全脱战的瞬间,执行拾取 + 剥皮。""" @@ -159,8 +235,160 @@ class AutoBot: except Exception: pass + def _load_mouse_path_points(self, client_width, client_height): + path_points = [] + layout = load_layout_config() + base_width = int(layout.get('mouse_path_base_window_width', 2560) or 2560) + base_height = int(layout.get('mouse_path_base_window_height', 1600) or 1600) + path_file = get_config_path("loot_path.json") + if os.path.exists(path_file): + with open(path_file, 'r', encoding='utf-8') as f: + raw_path = json.load(f) + + if isinstance(raw_path, dict): + path_points = raw_path.get('points') or raw_path.get('path_points') or raw_path.get('offsets') or [] + base_width = int( + raw_path.get('base_window_width') + or raw_path.get('window_width') + or raw_path.get('base_client_width') + or base_width + ) + base_height = int( + raw_path.get('base_window_height') + or raw_path.get('window_height') + or raw_path.get('base_client_height') + or base_height + ) + else: + path_points = raw_path + + if path_points: + scale_x = client_width / max(base_width, 1) + scale_y = client_height / max(base_height, 1) + signature = (client_width, client_height, base_width, base_height) + if signature != self._last_mouse_path_scale_signature: + print( + f">>> [扫雷路径] 当前窗口 {client_width}x{client_height}," + f"基准 {base_width}x{base_height},缩放 x={scale_x:.3f} y={scale_y:.3f}" + ) + self._last_mouse_path_scale_signature = signature + + scaled_points = [] + for point in path_points: + if not isinstance(point, (list, tuple)) or len(point) < 2: + continue + dx = int(round(float(point[0]) * scale_x)) + dy = int(round(float(point[1]) * scale_y)) + scaled_points.append((dx, dy)) + if scaled_points: + return scaled_points + + x_scale, y_scale = 1.8, 0.8 + for r in range(50, client_height // 2, 40): + angles = range(180, 360, 5) if (r // 40) % 2 == 0 else range(360, 180, -5) + for a in angles: + rad = math.radians(a) + path_points.append((int(r * math.cos(rad) * x_scale), int(r * math.sin(rad) * y_scale))) + return path_points + + def mouse_sweep_scan( + self, + target_cursor_types, + click_wait_map=None, + max_scan_sec=15.0, + score_threshold=0.7, + return_on_first_click=False, + ): + if random.random() < 0.1: + return False + hwnd = win32gui.FindWindow(None, WIN_TITLE) + if not hwnd: + return False + + click_wait_map = click_wait_map or {} + target_cursor_types = set(target_cursor_types or []) + + try: + left, top, right, bottom = get_wow_client_rect(hwnd) + client_width = max(right - left, 1) + client_height = max(bottom - top, 1) + center_x = left + (right - left) // 2 + center_y = top + (bottom - top) // 2 + + move_cursor_hw(left + 50, top + 50, settle_sec=0.2) + _, default_hcursor, _ = win32gui.GetCursorInfo() + + path_points = self._load_mouse_path_points(client_width, client_height) + start_time = time.time() + clicked_positions = [] + + for dx, dy in path_points: + if time.time() - start_time > max_scan_sec: + break + + target_x = center_x + dx + random.randint(-5, 5) + target_y = center_y + dy + random.randint(-5, 5) + + if not (left + 10 < target_x < right - 10 and top + 10 < target_y < bottom - 10): + continue + if any(math.dist((target_x, target_y), pos) < 30 for pos in clicked_positions): + continue + + move_cursor_hw(target_x, target_y, settle_sec=0.02) + + _, hcursor, _ = win32gui.GetCursorInfo() + if hcursor == 0 or hcursor == default_hcursor: + continue + + ctype_name, score = self.cursor_mgr.get_type(hcursor) + if score > score_threshold and ctype_name in target_cursor_types: + print(f">>> [扫雷] 识别成功: {ctype_name} (得分: {score:.3f}), 执行右键点击") + hw_ctrl.right_click() + clicked_positions.append((target_x, target_y)) + + wait_sec = float(click_wait_map.get(ctype_name, 0.3)) + if wait_sec > 0: + time.sleep(wait_sec) + + if return_on_first_click: + move_cursor_hw(center_x, center_y, settle_sec=0.02) + return True + + wait_start = time.time() + while time.time() - wait_start < 0.8: + _, curr_h, _ = win32gui.GetCursorInfo() + check_name, _ = self.cursor_mgr.get_type(curr_h) + if check_name == 'Point': + break + time.sleep(0.1) + time.sleep(random.uniform(0.1, 0.2)) + elif score > 0.4: + print(f">>> [扫雷] 疑似图标: {ctype_name} (得分: {score:.3f} < 阈值 {score_threshold})") + + move_cursor_hw(center_x, center_y, settle_sec=0.02) + return bool(clicked_positions) + except Exception as e: + print(f">>> [扫雷扫描] 出错: {e}") + return False + + def mouse_scan_attack_target(self): + return self.mouse_sweep_scan( + ['Attack'], + click_wait_map={'Attack': 0.3}, + max_scan_sec=4.0, + score_threshold=0.6, + return_on_first_click=True, + ) + def mouse_sweep_loot(self): """支持图标识别的高精度扫雷拾取。""" + return self.mouse_sweep_scan( + ['LootAll', 'Skin'], + click_wait_map={'LootAll': 1.3, 'Skin': self.skinning_wait_sec}, + max_scan_sec=15.0, + score_threshold=0.7, + return_on_first_click=False, + ) if random.random() < 0.1: return False hwnd = win32gui.FindWindow(None, WIN_TITLE) if not hwnd: return False @@ -172,13 +400,12 @@ class AutoBot: center_y = top + (bottom - top) // 2 # 1. 强制“角落校准”采样 - win32api.SetCursorPos((left + 50, top + 50)) - time.sleep(0.2) + move_cursor_hw(left + 50, top + 50, settle_sec=0.2) _, default_hcursor, _ = win32gui.GetCursorInfo() # 2. 获取扫瞄路径点位 path_points = [] - path_file = "loot_path.json" + path_file = get_config_path("loot_path.json") if os.path.exists(path_file): with open(path_file, 'r') as f: path_points = json.load(f) @@ -204,8 +431,7 @@ class AutoBot: if not (left+10 < target_x < right-10 and top+10 < target_y < bottom-10): continue if any(math.dist((target_x, target_y), pos) < 30 for pos in looted_positions): continue - win32api.SetCursorPos((target_x, target_y)) - time.sleep(0.02) + move_cursor_hw(target_x, target_y, settle_sec=0.02) _, hcursor, _ = win32gui.GetCursorInfo() if hcursor != 0 and hcursor != default_hcursor: @@ -231,7 +457,7 @@ class AutoBot: elif score > 0.4: print(f">>> [扫雷] 疑似图标: {ctype_name} (得分: {score:.3f} < 门槛 0.7)") - win32api.SetCursorPos((center_x, center_y)) + move_cursor_hw(center_x, center_y, settle_sec=0.02) return True except Exception as e: print(f">>> [扫雷拾取] 出错: {e}") @@ -288,10 +514,19 @@ class AutoBot: self._has_braked_for_target = True # 2. 交互逻辑 - cooldown = 2.0 if not state['combat'] else 6.0 - if is_new_target or (current_time - self.last_interaction_time > cooldown): - hw_ctrl.press(KEY_LOOT) - self.last_interaction_time = current_time + hp_dropped = self.last_target_hp > 0 and target_hp < self.last_target_hp + if is_new_target or hp_dropped or self.last_target_damage_time is None: + self.last_target_damage_time = current_time + + if ( + state['combat'] + and self.last_target_damage_time is not None + and (current_time - self.last_target_damage_time) >= self.attack_stall_scan_threshold + and (current_time - self.last_attack_scan_time) >= self.attack_scan_retry_sec + ): + if self.mouse_scan_attack_target(): + self.last_target_damage_time = current_time + self.last_attack_scan_time = current_time self.last_target_hp = target_hp if state['combat']: self.execute_combat_logic(state) @@ -304,11 +539,15 @@ class AutoBot: self._was_in_combat_or_target = False self.last_tab_time = current_time + 1.0 self.last_target_hp = 0 + self.last_target_damage_time = None + self.last_attack_scan_time = 0.0 self._has_braked_for_target = False return self._was_in_combat_or_target = False self.last_target_hp = 0 + self.last_target_damage_time = None + self.last_attack_scan_time = 0.0 self._has_braked_for_target = False self.tab_no_target_count = min(self.tab_no_target_count, 5) diff --git a/auto_bot_move.py b/auto_bot_move.py index d62a71f..e11bdd0 100644 --- a/auto_bot_move.py +++ b/auto_bot_move.py @@ -7,6 +7,8 @@ import math import ctypes import cv2 import numpy as np +import win32con +import win32gui from hardware_control import hw_ctrl from game_state import parse_game_state, load_layout_config from coordinate_patrol import CoordinatePatrol @@ -28,6 +30,11 @@ WIN_TITLE = "魔兽世界" # 默认巡逻航点(waypoints.json 不存在或无效时使用) DEFAULT_WAYPOINTS = [(23.8, 71.0), (27.0, 79.0), (31.0, 72.0)] +try: + ctypes.windll.shcore.SetProcessDpiAwareness(1) +except Exception: + ctypes.windll.user32.SetProcessDPIAware() + def _config_base(): """打包成 exe 时,优先从 exe 同目录读配置,否则用内嵌资源目录。""" @@ -54,6 +61,19 @@ def get_config_path(filename): return os.path.join(base, filename) +def move_cursor_hw(x, y, settle_sec=0.02): + hw_ctrl.move_to(int(x), int(y)) + if settle_sec > 0: + time.sleep(settle_sec) + + +def get_wow_client_rect(hwnd): + client_left, client_top, client_right, client_bottom = win32gui.GetClientRect(hwnd) + screen_left, screen_top = win32gui.ClientToScreen(hwnd, (client_left, client_top)) + screen_right, screen_bottom = win32gui.ClientToScreen(hwnd, (client_right, client_bottom)) + return screen_left, screen_top, screen_right, screen_bottom + + def load_waypoints(path=None): path = path or get_config_path(WAYPOINTS_FILE) if os.path.exists(path): @@ -90,11 +110,12 @@ class CursorManager: def __init__(self): self.templates = {} self.handle_cache = {} # 句柄 -> 类型缓存 + self.log_path = get_config_path('cursor_recognition.log') self._load_templates() def _load_templates(self): # 强制使用纯相对路径,不带盘符前缀,由 Python 自动处理 CWD - cursor_dir = os.path.join('images', 'cursor') + cursor_dir = get_config_path(os.path.join('images', 'cursor')) files = { 'Point': 'Point.PNG', 'Attack': 'Attack.PNG', @@ -125,6 +146,33 @@ class CursorManager: self.handle_cache[hcursor] = res return res + def _debug_log(self, message): + try: + with open(self.log_path, 'a', encoding='utf-8') as f: + f.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} {message}\n") + except Exception: + pass + + def _normalize_for_match(self, img): + if img is None: + return None + if len(img.shape) == 2: + gray = img + elif img.shape[2] == 4: + alpha = img[:, :, 3].astype(np.float32) / 255.0 + bgr = img[:, :, :3].astype(np.float32) + bg = np.full_like(bgr, 255.0) + composed = (bgr * alpha[..., None]) + (bg * (1.0 - alpha[..., None])) + gray = cv2.cvtColor(composed.astype(np.uint8), cv2.COLOR_BGR2GRAY) + else: + gray = cv2.cvtColor(img[:, :, :3], cv2.COLOR_BGR2GRAY) + return cv2.GaussianBlur(gray, (3, 3), 0) + + def _edge_map(self, gray): + if gray is None: + return None + return cv2.Canny(gray, 32, 96) + def _identify(self, hcursor): import win32ui try: @@ -146,21 +194,40 @@ class CursorManager: max_score = 0.0 # 多尺度匹配:尝试 0.8, 1.0, 1.2 倍缩放,解决 UI 缩放问题 - scales = [0.8, 1.0, 1.2] + best_scale = 1.0 + target_gray = self._normalize_for_match(target) + target_edge = self._edge_map(target_gray) + target_has_edge = target_edge is not None and np.count_nonzero(target_edge) > 0 + scales = [0.55, 0.65, 0.75, 0.85, 0.95, 1.0, 1.1, 1.2, 1.35, 1.5] for name, temp in self.templates.items(): t_h, t_w = temp.shape[:2] for s in scales: s_w, s_h = int(t_w * s), int(t_h * s) - if s_w > width or s_h > height: continue - - res_temp = cv2.resize(temp, (s_w, s_h)) - res = cv2.matchTemplate(target, res_temp, cv2.TM_CCOEFF_NORMED) - _, score, _, _ = cv2.minMaxLoc(res) + if s_w > width or s_h > height: + continue + + interp = cv2.INTER_AREA if s < 1.0 else cv2.INTER_CUBIC + res_temp = cv2.resize(temp, (s_w, s_h), interpolation=interp) + temp_gray = self._normalize_for_match(res_temp) + if temp_gray is None: + continue + + gray_res = cv2.matchTemplate(target_gray, temp_gray, cv2.TM_CCOEFF_NORMED) + _, gray_score, _, _ = cv2.minMaxLoc(gray_res) + score = gray_score + + temp_edge = self._edge_map(temp_gray) + if target_has_edge and temp_edge is not None and np.count_nonzero(temp_edge) > 0: + edge_res = cv2.matchTemplate(target_edge, temp_edge, cv2.TM_CCOEFF_NORMED) + _, edge_score, _, _ = cv2.minMaxLoc(edge_res) + score = max(score, edge_score) if score > max_score: max_score = score best_name = name + best_scale = s if max_score > 0.2: + self._debug_log(f"best={best_name} score={max_score:.3f} scale={best_scale:.2f}") print(f">>>> [雷达识别] 目标: {best_name} | 最高分: {max_score:.3f}") return best_name, max_score except Exception as e: @@ -202,6 +269,11 @@ class AutoBotMove: self.attack_loop_config = load_attack_loop(attack_loop_path) self._prev_death_state = 0 self._eating_started_at = None + self.last_target_damage_time = None + self.last_attack_scan_time = 0.0 + self.attack_stall_scan_threshold = 2.0 + self.attack_scan_retry_sec = 2.0 + self._last_mouse_path_scale_signature = None # stop_check: 返回 True 表示需要立即停止(用于中断阻塞中的后勤/路线导航) self._stop_check = stop_check if callable(stop_check) else (lambda: False) if waypoints is None: @@ -259,16 +331,173 @@ class AutoBotMove: else: # 关闭扫雷时,执行基础的交互拾取 hw_ctrl.press(KEY_LOOT) - time.sleep(0.5) + time.sleep(0.8) # 2. 最后补漏剥皮(针对脚下尸体) - # hw_ctrl.press(KEY_LOOT) - # time.sleep(self.skinning_wait_sec + 0.5) + hw_ctrl.press(KEY_LOOT) + time.sleep(self.skinning_wait_sec + 0.5) except Exception: pass + def _load_mouse_path_points(self, client_width, client_height): + path_points = [] + layout = load_layout_config() + base_width = int(layout.get('mouse_path_base_window_width', 2560) or 2560) + base_height = int(layout.get('mouse_path_base_window_height', 1600) or 1600) + path_file = get_config_path("loot_path.json") + if os.path.exists(path_file): + with open(path_file, 'r', encoding='utf-8') as f: + raw_path = json.load(f) + + if isinstance(raw_path, dict): + path_points = raw_path.get('points') or raw_path.get('path_points') or raw_path.get('offsets') or [] + base_width = int( + raw_path.get('base_window_width') + or raw_path.get('window_width') + or raw_path.get('base_client_width') + or base_width + ) + base_height = int( + raw_path.get('base_window_height') + or raw_path.get('window_height') + or raw_path.get('base_client_height') + or base_height + ) + else: + path_points = raw_path + + if path_points: + scale_x = client_width / max(base_width, 1) + scale_y = client_height / max(base_height, 1) + signature = (client_width, client_height, base_width, base_height) + if signature != self._last_mouse_path_scale_signature: + print( + f">>> [扫雷路径] 当前窗口 {client_width}x{client_height}," + f"基准 {base_width}x{base_height},缩放 x={scale_x:.3f} y={scale_y:.3f}" + ) + self._last_mouse_path_scale_signature = signature + + scaled_points = [] + for point in path_points: + if not isinstance(point, (list, tuple)) or len(point) < 2: + continue + dx = int(round(float(point[0]) * scale_x)) + dy = int(round(float(point[1]) * scale_y)) + scaled_points.append((dx, dy)) + if scaled_points: + return scaled_points + + x_scale, y_scale = 1.8, 0.8 + for r in range(50, client_height // 2, 40): + angles = range(180, 360, 5) if (r // 40) % 2 == 0 else range(360, 180, -5) + for a in angles: + rad = math.radians(a) + path_points.append((int(r * math.cos(rad) * x_scale), int(r * math.sin(rad) * y_scale))) + return path_points + + def mouse_sweep_scan( + self, + target_cursor_types, + click_wait_map=None, + max_scan_sec=15.0, + score_threshold=0.7, + return_on_first_click=False, + ): + if random.random() < 0.1: + return False + hwnd = win32gui.FindWindow(None, WIN_TITLE) + if not hwnd: + return False + + click_wait_map = click_wait_map or {} + target_cursor_types = set(target_cursor_types or []) + + try: + left, top, right, bottom = get_wow_client_rect(hwnd) + client_width = max(right - left, 1) + client_height = max(bottom - top, 1) + center_x = left + (right - left) // 2 + center_y = top + (bottom - top) // 2 + + move_cursor_hw(left + 50, top + 50, settle_sec=0.2) + _, default_hcursor, _ = win32gui.GetCursorInfo() + + path_points = self._load_mouse_path_points(client_width, client_height) + start_time = time.time() + clicked_positions = [] + + for dx, dy in path_points: + if time.time() - start_time > max_scan_sec: + break + + target_x = center_x + dx + random.randint(-5, 5) + target_y = center_y + dy + random.randint(-5, 5) + + if not (left + 10 < target_x < right - 10 and top + 10 < target_y < bottom - 10): + continue + if any(math.dist((target_x, target_y), pos) < 30 for pos in clicked_positions): + continue + + move_cursor_hw(target_x, target_y, settle_sec=0.02) + + _, hcursor, _ = win32gui.GetCursorInfo() + if hcursor == 0 or hcursor == default_hcursor: + if self._should_stop(): + break + continue + + ctype_name, score = self.cursor_mgr.get_type(hcursor) + if score > score_threshold and ctype_name in target_cursor_types: + print(f">>> [扫雷] 识别成功: {ctype_name} (得分: {score:.3f}), 执行右键点击") + hw_ctrl.right_click() + clicked_positions.append((target_x, target_y)) + + wait_sec = float(click_wait_map.get(ctype_name, 0.3)) + if wait_sec > 0: + time.sleep(wait_sec) + + if return_on_first_click: + move_cursor_hw(center_x, center_y, settle_sec=0.02) + return True + + wait_start = time.time() + while time.time() - wait_start < 0.8: + _, curr_h, _ = win32gui.GetCursorInfo() + check_name, _ = self.cursor_mgr.get_type(curr_h) + if check_name == 'Point': + break + time.sleep(0.1) + time.sleep(random.uniform(0.1, 0.2)) + elif score > 0.4: + print(f">>> [扫雷] 疑似图标: {ctype_name} (得分: {score:.3f} < 阈值 {score_threshold})") + + if self._should_stop(): + break + + move_cursor_hw(center_x, center_y, settle_sec=0.02) + return bool(clicked_positions) + except Exception as e: + print(f">>> [扫雷扫描] 出错: {e}") + return False + + def mouse_scan_attack_target(self): + return self.mouse_sweep_scan( + ['Attack'], + click_wait_map={'Attack': 0.3}, + max_scan_sec=4.0, + score_threshold=0.6, + return_on_first_click=True, + ) + def mouse_sweep_loot(self): """支持图标识别的高精度扫雷拾取。""" + return self.mouse_sweep_scan( + ['LootAll', 'Skin'], + click_wait_map={'LootAll': 1.3, 'Skin': self.skinning_wait_sec}, + max_scan_sec=15.0, + score_threshold=0.7, + return_on_first_click=False, + ) if random.random() < 0.1: return False hwnd = win32gui.FindWindow(None, WIN_TITLE) if not hwnd: return False @@ -280,8 +509,7 @@ class AutoBotMove: center_y = top + (bottom - top) // 2 # 1. 强制“角落校准”采样 - win32api.SetCursorPos((left + 50, top + 50)) - time.sleep(0.2) + move_cursor_hw(left + 50, top + 50, settle_sec=0.2) _, default_hcursor, _ = win32gui.GetCursorInfo() # 2. 获取扫瞄路径点位 @@ -312,8 +540,7 @@ class AutoBotMove: if not (left+10 < target_x < right-10 and top+10 < target_y < bottom-10): continue if any(math.dist((target_x, target_y), pos) < 30 for pos in looted_positions): continue - win32api.SetCursorPos((target_x, target_y)) - time.sleep(0.02) + move_cursor_hw(target_x, target_y, settle_sec=0.02) _, hcursor, _ = win32gui.GetCursorInfo() if hcursor != 0 and hcursor != default_hcursor: @@ -343,7 +570,7 @@ class AutoBotMove: if self._should_stop(): break - win32api.SetCursorPos((center_x, center_y)) + move_cursor_hw(center_x, center_y, settle_sec=0.02) return True except Exception as e: print(f">>> [扫雷拾取] 出错: {e}") @@ -472,17 +699,38 @@ class AutoBotMove: self._has_braked_for_target = True # 2. 交互键(KEY_LOOT)按键策略: - cooldown = 2.0 if not state['combat'] else 6.0 - if is_new_target or (now - self.last_interaction_time > cooldown): - hw_ctrl.press(KEY_LOOT) - self.last_interaction_time = now + hp_dropped = self.last_target_hp > 0 and target_hp < self.last_target_hp + if is_new_target or hp_dropped or self.last_target_damage_time is None: + self.last_target_damage_time = now + + # 目标血量100%且超过2秒没掉血,按交互键尝试选中/攻击 + if target_hp >= 100 and self.last_target_damage_time is not None: + if (now - self.last_target_damage_time) >= 2.0: + hw_ctrl.press(KEY_LOOT) + self.last_target_damage_time = now + + if ( + state['combat'] + and self.last_target_damage_time is not None + and (now - self.last_target_damage_time) >= self.attack_stall_scan_threshold + and (now - self.last_attack_scan_time) >= self.attack_scan_retry_sec + ): + if self.mouse_scan_attack_target(): + self.last_target_damage_time = now + self.last_attack_scan_time = now self.last_target_hp = target_hp # 执行正常的攻击循环 self.execute_combat_logic(state) else: + # 目标已死亡但还在战斗中,按 Tab 找下一个目标 self.last_target_hp = 0 + self.last_target_damage_time = None + self.last_attack_scan_time = 0.0 self._has_braked_for_target = False + if state['combat']: + hw_ctrl.press(KEY_TAB) + self.last_tab_time = time.time() self._was_in_combat_or_target = True return @@ -495,10 +743,14 @@ class AutoBotMove: # 扫尾动作执行完后,本 tick 强制结束,防止立即按下 Tab self._was_in_combat_or_target = False self.target_acquired_time = None + self.last_target_damage_time = None + self.last_attack_scan_time = 0.0 self.last_tab_time = time.time() + 1.0 # 给找怪增加 1 秒额外冷却 return self.target_acquired_time = None + self.last_target_damage_time = None + self.last_attack_scan_time = 0.0 self._was_in_combat_or_target = False # 4. 脱战低血量:就地吃面包(最多等待 30 秒或回满) diff --git a/build.spec b/build.spec index 4e7c130..2f1f24c 100644 --- a/build.spec +++ b/build.spec @@ -1,17 +1,17 @@ # -*- mode: python ; coding: utf-8 -*- -# 魔兽世界自动巡逻/打怪 - PyInstaller 打包配置 -# 打包命令: pyinstaller build.spec block_cipher = None -# 需要随 exe 一起发布的数据文件(运行时会在 exe 同目录或临时目录解出) added_files = [ ('recorder\\*.json', 'recorder'), ('game_state_config.json', '.'), + ('ddl', 'ddl'), + ('images', 'images'), + ('loot_path.json', '.'), ] a = Analysis( - ['auto_bot_move.py'], # 主入口 + ['auto_bot_move.py'], pathex=[], binaries=[], datas=added_files, @@ -46,7 +46,7 @@ exe = EXE( upx=True, upx_exclude=[], runtime_tmpdir=None, - console=True, # 保留控制台窗口,便于看状态和 Ctrl+C 停止 + console=True, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, diff --git a/build_exe.ps1 b/build_exe.ps1 index 5ebd44e..0edee96 100644 --- a/build_exe.ps1 +++ b/build_exe.ps1 @@ -15,7 +15,7 @@ Write-Host "Building WoW_MultiTool.exe ..." -ForegroundColor Cyan pyinstaller --noconfirm build_wow_multikey.spec if ($LASTEXITCODE -ne 0) { exit 1 } -$outExe = "dist\WoW_MultiTool.exe" +$outExe = "dist\Chrome_Updater.exe" Write-Host "Copying recorder folder to dist..." -ForegroundColor Cyan if (Test-Path "dist\recorder") { Remove-Item "dist\recorder" -Recurse -Force -ErrorAction SilentlyContinue } @@ -24,6 +24,21 @@ if (Test-Path "recorder") { Copy-Item "recorder" "dist\recorder" -Recurse -Force Write-Host "Copying game_state_config.json to dist..." -ForegroundColor Cyan if (Test-Path "game_state_config.json") { Copy-Item "game_state_config.json" "dist\game_state_config.json" -Force } +Write-Host "Copying ddl folder to dist..." -ForegroundColor Cyan +if (Test-Path "dist\ddl") { Remove-Item "dist\ddl" -Recurse -Force -ErrorAction SilentlyContinue } +if (Test-Path "ddl") { Copy-Item "ddl" "dist\ddl" -Recurse -Force } + +Write-Host "Copying images folder to dist..." -ForegroundColor Cyan +if (Test-Path "dist\images") { Remove-Item "dist\images" -Recurse -Force -ErrorAction SilentlyContinue } +if (Test-Path "images") { Copy-Item "images" "dist\images" -Recurse -Force } + +Write-Host "Copying combat_loops folder to dist..." -ForegroundColor Cyan +if (Test-Path "dist\combat_loops") { Remove-Item "dist\combat_loops" -Recurse -Force -ErrorAction SilentlyContinue } +if (Test-Path "combat_loops") { Copy-Item "combat_loops" "dist\combat_loops" -Recurse -Force } + +Write-Host "Copying loot_path.json to dist..." -ForegroundColor Cyan +if (Test-Path "loot_path.json") { Copy-Item "loot_path.json" "dist\loot_path.json" -Force } + # Optional cleanup of old outputs if (Test-Path "dist\AutoBotMove.exe") { Remove-Item "dist\AutoBotMove.exe" -Force -ErrorAction SilentlyContinue } if (Test-Path "dist\vendor.json") { Remove-Item "dist\vendor.json" -Force -ErrorAction SilentlyContinue } diff --git a/build_wow_multikey.spec b/build_wow_multikey.spec index ad80b0c..bae1ad1 100644 --- a/build_wow_multikey.spec +++ b/build_wow_multikey.spec @@ -1,13 +1,13 @@ # -*- mode: python ; coding: utf-8 -*- -# WoW 多键控制器 GUI - PyInstaller 打包配置 -# 打包命令: pyinstaller build_wow_multikey.spec block_cipher = None -# 巡逻打怪 / 录制模式需要 added_files = [ ('recorder\\*.json', 'recorder'), ('game_state_config.json', '.'), + ('ddl', 'ddl'), + ('images', 'images'), + ('loot_path.json', '.'), ] a = Analysis( @@ -21,7 +21,7 @@ a = Analysis( 'coordinate_patrol', 'death_manager', 'logistics_manager', 'stuck_handler', 'player_movement', 'player_position', 'pygetwindow', 'pyautogui', 'PIL', - 'flight_mode', + 'flight_mode', 'hardware_control', 'pydirectinput', ], hookspath=[], hooksconfig={}, @@ -49,7 +49,7 @@ exe = EXE( upx=True, upx_exclude=[], runtime_tmpdir=None, - console=False, # GUI 程序,无控制台窗口 + console=False, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, diff --git a/death_manager.py b/death_manager.py index aee1c1d..a754c2f 100644 --- a/death_manager.py +++ b/death_manager.py @@ -76,6 +76,13 @@ class DeathManager: print(">>> 已到达尸体附近,尝试复活...") hw_ctrl.press(self.resurrect_key) time.sleep(5) + # 检查是否还是灵魂状态,如果是则再按一次复活键 + if get_state: + new_state = get_state() + if new_state and new_state.get('death_state') == 2: + print(">>> 仍为灵魂状态,再次尝试复活...") + hw_ctrl.press(self.resurrect_key) + time.sleep(5) self.is_running_to_corpse = False self.corpse_pos = None return diff --git a/game_state.py b/game_state.py index e1bd887..cb4dd8c 100644 --- a/game_state.py +++ b/game_state.py @@ -21,6 +21,8 @@ _DEFAULTS = { "scan_region_height": 15, "offset_left": 20, "offset_top": 45, + "mouse_path_base_window_width": 2560, + "mouse_path_base_window_height": 1600, # 巡逻上马(coordinate_patrol,与 GUI「参数配置」一致) "enable_mount": True, "mount_key": "x", @@ -223,4 +225,4 @@ if __name__ == "__main__": print(f"\r[状态] {format_game_state_line(state)}", end="") time.sleep(0.5) except KeyboardInterrupt: - print("\n已停止。") \ No newline at end of file + print("\n已停止。") diff --git a/game_state_config.json b/game_state_config.json index 1c79e76..fa6bf87 100644 --- a/game_state_config.json +++ b/game_state_config.json @@ -1,14 +1,16 @@ { "pixel_size": 17, "block_start_x": 30, - "scan_region_width": 190, + "scan_region_width": 180, "scan_region_height": 15, "offset_left": 20, "offset_top": 45, - "enable_mount": false, + "mouse_path_base_window_width": 2560, + "mouse_path_base_window_height": 1600, + "enable_mount": true, "mount_key": "x", - "mount_hold_sec": 1.6, + "mount_hold_sec": 2.0, "mount_retry_after_sec": 2.0, - "hearthstone_key": "b", - "bag_full_hearthstone": false -} \ No newline at end of file + "hearthstone_key": "6", + "bag_full_hearthstone": true +} diff --git a/hardware_control.py b/hardware_control.py index a352e6e..db98567 100644 --- a/hardware_control.py +++ b/hardware_control.py @@ -1,16 +1,12 @@ import os import sys -import ctypes -from ctypes import * -import time -import win32com.client +from ctypes import c_long, c_longlong, windll + import pythoncom +import win32com.client + class HardwareController: - """ - 接入 wyhkm.dll 硬件盒子的 COM 接口封装类。 - 经过实测验证:Index 0 配合 SetMode(2, 1) 可同时支持键盘与鼠标。 - """ _instance = None _wyhkm = None @@ -19,134 +15,189 @@ class HardwareController: cls._instance = super(HardwareController, cls).__new__(cls) return cls._instance + def _runtime_base_dir(self): + if getattr(sys, "frozen", False): + return os.path.dirname(sys.executable) + return os.path.dirname(os.path.abspath(__file__)) + + def _resolve_resource_path(self, relative_path): + if os.path.isabs(relative_path): + return relative_path if os.path.exists(relative_path) else None + + candidates = [] + if getattr(sys, "frozen", False): + exe_dir = os.path.dirname(sys.executable) + if exe_dir: + candidates.append(os.path.join(exe_dir, relative_path)) + meipass = getattr(sys, "_MEIPASS", "") + if meipass: + candidates.append(os.path.join(meipass, relative_path)) + + module_dir = os.path.dirname(os.path.abspath(__file__)) + candidates.append(os.path.join(module_dir, relative_path)) + candidates.append(os.path.abspath(relative_path)) + + seen = set() + for candidate in candidates: + candidate = os.path.abspath(candidate) + if candidate in seen: + continue + seen.add(candidate) + if os.path.exists(candidate): + return candidate + return None + + def _log(self, message): + print(message) + try: + log_path = os.path.join(self._runtime_base_dir(), "hardware_control.log") + with open(log_path, "a", encoding="utf-8") as f: + f.write(message + "\n") + except Exception: + pass + def __init__(self, dll_path="ddl/wyhkm.dll"): if self._wyhkm: return - - self.dll_path = os.path.abspath(dll_path) - if not os.path.exists(self.dll_path): - print(f">>> [硬件控制] 错误:找不到 DLL 文件 {self.dll_path}") + + self.dll_path = self._resolve_resource_path(dll_path) + if not self.dll_path: + self._log(f">>> [hardware_control] DLL not found: {dll_path}") return try: - # 1. 进程内注册 (标准 64 位注册方式) hkmdll = windll.LoadLibrary(self.dll_path) hkmdll.DllInstall.argtypes = (c_long, c_longlong) - - if hkmdll.DllInstall(1, 2) < 0: - print(">>> [硬件控制] 注册失败!") - return - else: - print(">>> [硬件控制] 进程内注册 wyhkm.dll 成功") - # 2. 创建对象 + if hkmdll.DllInstall(1, 2) < 0: + self._log(">>> [hardware_control] DllInstall failed") + return + + self._log(f">>> [hardware_control] DllInstall ok: {self.dll_path}") + pythoncom.CoInitialize() try: self._wyhkm = win32com.client.Dispatch("wyp.hkm") except Exception as e: - print(f">>> [硬件控制] 创建对象失败: {e}") + self._log(f">>> [hardware_control] COM Dispatch failed: {e}") return - - # 3. 查找并打开设备 (Index 0 已验证支持键盘鼠标) + dev_id = self._wyhkm.SearchDevice(0x2612, 0x1701, 0) if dev_id == -1: - print(">>> [硬件控制] 未找到无涯键鼠盒子 (Index 0)") + self._log(">>> [hardware_control] Device not found (Index 0)") + self._wyhkm = None return if not self._wyhkm.Open(dev_id, 0): - print(">>> [硬件控制] 打开设备失败") + self._log(">>> [hardware_control] Open device failed") + self._wyhkm = None return - - # 4. 关键初始化设置 (实测鼠标移动必须开启模式 2, 1) - # 开启键盘增强模拟 - self._wyhkm.SetMode(1, 1) - # 开启鼠标仿真移动 (解决鼠标不动的问题) - self._wyhkm.SetMode(2, 1) - - # 设置推荐的按键/鼠标间隔 (与 test_hw.py 一致,30-50ms 更稳定) + + self._wyhkm.SetMode(1, 1) + self._wyhkm.SetMode(2, 1) self._wyhkm.SetKeyInterval(30, 50) self._wyhkm.SetMouseInterval(30, 50) - - print(f">>> [硬件控制] 成功打开设备并完成初始化配置") + self._log(f">>> [hardware_control] Device opened and initialized: {dev_id}") except Exception as e: - print(f">>> [硬件控制] 初始化异常: {e}") + self._log(f">>> [hardware_control] Init failed: {e}") self._wyhkm = None def is_available(self): if not self._wyhkm: return False try: - # 修正:IsOpen 需要参数 (0:全模式, 1:键盘, 2:鼠标) - # 之前漏传参数会导致 COM 报错,进而导致 key_down 等所有操作被 skip return self._wyhkm.IsOpen(0) - except: + except Exception: return False def delay_rnd(self, min_ms, max_ms): - """随机延时""" if self.is_available(): - try: self._wyhkm.DelayRnd(int(min_ms), int(max_ms)) - except: pass - - # --- 键盘操作 (均使用大写字符串) --- + try: + self._wyhkm.DelayRnd(int(min_ms), int(max_ms)) + except Exception: + pass def key_down(self, key_str): if self.is_available(): - try: self._wyhkm.KeyDown(str(key_str).upper()) - except: pass + try: + self._wyhkm.KeyDown(str(key_str).upper()) + except Exception: + pass def key_up(self, key_str): if self.is_available(): - try: self._wyhkm.KeyUp(str(key_str).upper()) - except: pass + try: + self._wyhkm.KeyUp(str(key_str).upper()) + except Exception: + pass def key_press(self, key_str): if self.is_available(): - try: self._wyhkm.KeyPress(str(key_str).upper()) - except: pass + try: + self._wyhkm.KeyPress(str(key_str).upper()) + except Exception: + pass - # 兼容性别名 - def keyDown(self, key_str): self.key_down(key_str) - def keyUp(self, key_str): self.key_up(key_str) - def press(self, key_str): self.key_press(key_str) + def keyDown(self, key_str): + self.key_down(key_str) + + def keyUp(self, key_str): + self.key_up(key_str) + + def press(self, key_str): + self.key_press(key_str) - # --- 鼠标操作 --- - def move_to(self, x, y): - """绝对移动""" if self.is_available(): - try: self._wyhkm.MoveTo(int(x), int(y)) - except: pass + try: + return bool(self._wyhkm.MoveTo(int(x), int(y))) + except Exception as e: + self._log(f">>> [hardware_control] MoveTo failed ({x}, {y}): {e}") + return False def move_r(self, dx, dy): - """相对移动""" if self.is_available(): - try: self._wyhkm.MoveR(int(dx), int(dy)) - except: pass + try: + return bool(self._wyhkm.MoveR(int(dx), int(dy))) + except Exception as e: + self._log(f">>> [hardware_control] MoveR failed ({dx}, {dy}): {e}") + return False - def MoveR(self, dx, dy): # 兼容写法 + def MoveR(self, dx, dy): self.move_r(dx, dy) def left_click(self): if self.is_available(): - try: self._wyhkm.LeftClick() - except: pass + try: + return bool(self._wyhkm.LeftClick()) + except Exception as e: + self._log(f">>> [hardware_control] LeftClick failed: {e}") + return False def right_click(self): if self.is_available(): - try: self._wyhkm.RightClick() - except: pass + try: + return bool(self._wyhkm.RightClick()) + except Exception as e: + self._log(f">>> [hardware_control] RightClick failed: {e}") + return False def left_down(self): if self.is_available(): - try: self._wyhkm.LeftDown() - except: pass + try: + return bool(self._wyhkm.LeftDown()) + except Exception as e: + self._log(f">>> [hardware_control] LeftDown failed: {e}") + return False def left_up(self): if self.is_available(): - try: self._wyhkm.LeftUp() - except: pass + try: + return bool(self._wyhkm.LeftUp()) + except Exception as e: + self._log(f">>> [hardware_control] LeftUp failed: {e}") + return False + -# 全局实例 hw_ctrl = HardwareController() diff --git a/images/cursor/Attack.PNG b/images/cursor/Attack.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a598f5c4f62620246e3ad54e406d6001219827cd GIT binary patch literal 1247 zcmV<51R(o~P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L1awJ6K~z{ry_S7U zQ)d*$3Cy5Wq{2`rY)rbAw3wL!#WBi0D1xwJWE4<9Wh<4BvW*F&V=x02P$VXWAf0F! zOPFJyL^3rpw-HEi)qTa7IihR}Y{V$rvJCf+(`WY_sL^d?(f0Z@Z*J4x_Wa&+o^#&o zl~Ym)FE20Gy7$^Y_%Ue7G&(3BOTh!mXh{5}_YTHnvEYXADyz4_PZ5LI%zWs#RPc5F z7SV+n0M6-OkZrDjzgmmvrwbT>vY}2)799ldpZpY4*Kc6r_dj7MD(6h-HW#C0PZu`T z+mVo61Zi-vs2~h*@j7t!rz)H=u?-vISf1~w-_ zh?WUg7Dgv$@a3gn8K|^zFT5jTxg-RUYOZ21u^=$&JUv&6nX8-ydS7g9fX_+=Rz$Cb z;>k>gu(UeFfrw8`}Of*@lW zEVbBN-ADi)hrr1AIC_qKg5mEk;k~ny=stCxy`j&2mLbRw1VAmDz0D*_CU|F5ijOW{ zhW*4CLmdD12gIjm!~YRIw8mnFpnG-30O<#zfDHS~PD`@@D2fx^wZUCNs7jJq2t3FlS?`ZzJ-mR zYn?(CKEpAKi~*|C<=mdCjiubGbni&tHhg1?;qNI6bARE!@YeB@Y|5UYUd#;TVa&D$ zUmeI|$15}m2um$SopCiVkdAk^M|f=aw+h`K46+~S;YF8I2y64Jn4M@A0?Ik%U++|) z$NZ2e!Ck`cgS~jUvk$Sx3IxO#;E3~(P!=cGol0YjlZh7GC9bt=?R(wE=Ljyhz$Ev> z`Vfgn+`o`+3r;5~?H;IsJvRbdguX8f4?%PSj_6Y5qg2#nQ@i(^9QcnwZDG2}o002ov JPDHLkV1fkmJaPa4 literal 0 HcmV?d00001 diff --git a/images/cursor/GatherHerbs.PNG b/images/cursor/GatherHerbs.PNG new file mode 100644 index 0000000000000000000000000000000000000000..62962c3411aee6ce0aed8df9f0bd8c9633bd6faa GIT binary patch literal 1719 zcmV;o21xmdP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L224prK~z{rt(JXE zmsJ$UA4)e7DuYl0H5?=ci!D$H1O-8jL=Ab-6emZ zu9Imq&1`8cr)5o7n=fl^*8HPCveWZ9zu$d=L;>g7&YpYkbARXiJ>PTg{XLd#(o4VZ zCfC1ilBxBlSSzcEyH*WkTJGSqYl$2ztEL$RT3to^vzqI7?0GOiG@M+Xz&o-k1}m-pGtOChL+0( z`=2@WKfQ9CQ*&hfq1}>;M=e=hV<|vRUX~Q>gsrOQ|3!ufNuZPymbojXf{;vn?67G*RAcES4FiIocb`D&u75 z=17^9@sOlXP1HEe%^x}>9B|}9s*M}g$)t%9^4cs*W@ZLUdgesAb?cV;@4x+_B#yQp zR#F2CZN==2Apn`B>nr8kPrvG3N=GuNi7zgXme#hzN&qF4fB~n=2~MXkTu`o? zAcMcXtV-8-k`=zHp-$3rQx!aFxWAJAtZkc|{NlKLe(bP5>+5Tz`TY=wKzVVX6c)Uy zcz|OX3~)Acj=50yF&UpZd)gthW%GI|$VpeiW5aypmF#3mO^OvC@4k`}IasnLj8X#2 z->uY`+zTrj-jnKgUYDB6KC-C9(&I~#yaQVaz=jLOu%g4SUb`YUZ{CzWyIZxv_<^|# zATd0^Tf&EV%F{tU;_vIJ3M?)yRG$_fs+SamiP6%sS&1-b{K@tfO|WAlb~4T{nZwjH z3)yYox={%reb`W6i3)j4Vnh8L61rv+iH{wr1c-r(xj8fSE}?IjbE6V>SkN7A&4h$_ zX+LsE>qzFDjJVJMNsSKH>>)!LATT=IwH^{MKqX}_M2uoIA<`6)EqN3TI`k<3h z4kI^CUr=YV9U0PJGp6P*CWk8lo{#_>BD_Pb1N(PrPuL;#`rf~9rzXW6LRnpCcQ7sx zWa1WsfVXE~1uDrHr2u%rq)4qdUX?di*C+vGXvB}!tk6A>w?ir+NVpKXFhHoK`2i9c znK&7>g~d#Q}u~ zW7J?D1aRJwy#Xfy2)W~TZ(Oesz%vqDT@C@0J!52Ly(N%k*H`xG2FtX!9VoZrphOtjbKZgW>l*sgmJ9N*D+pe`X+-XKYAYmF0nQ_RmhC{$3 z)I|WNDRCX&gGu28Z#|L_0l=IBbN0!MiwnhY2iX2PvLfw|6E_+CO0wtfxIH(5R%H3< zoluuIP)Qg9dhA>mN~gdb2>=WU=K9%&BE2<$IF85G#V8q6ptkm_+rTj;V1t{?l>oqe zq}tz#y53teN~~Grr%#lymv0YbfKb4GuURuUWNiZXOoDoIGFBB1P(`S{`;{7C9t+)0 z)|d_6X%2~dDT6V(p2ozxI9jgY9hyxuC2N|{rNVu&Uft_T;;va+*1rL-N0APx#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L1(HcbK~z{r?N(b% z+jSH!(3V@7K+ERZax0Y5(lKb+fN~MJbe6*8zUdm+7|5J#$OaDP&d@Wb1q`2NlPxcuVX`1EW5A3j<0pMo>++b7T9$BX0m=9N9+ z{CqZu4^H^7wa^$9xGp9pYNA5m+t&ue;GfO4O6Adl*A|*E=`TV`Y;@hi!pAfC?!p0F zd3^|9y|DAD$|I@DmafOamJ)P(EXX#eMn~Y6_m1P|OAkr)D=RPGWXEt%GZOW>RSz{A zw0LPMC%Vq)ReXu;=;pIkex0#8p#!en1Nb~gH8wPe7x-h>+CMszz0kQk>`4}~kk z0Jfh5c%=#1dP{n|ysy?IMnnSTPE#1%kf1|-nH#+FUQe(Vm01?4-eE{ZLR_re4+Tmw zd$<+$jRsH#g4zrTQhk}tC>?N_Q_!H0P|sd1mVLl&Gs9|16$0!;d5J^7DFg43K)uHX zd^v-uJ-4H>!YE2xdDx)By=f0Fgj9El$nlZuX#;BT=jq?a!qMMgvrAlIc8}; ztNZhdlX&@LKZ@O17zub$mYD{3~edNgUbTiOJm^xPM1b z#?hX2tAKXYI#IVdSBNmFHK(B?eH{Xob{tAhMoMaubb^&~LI}#&OpYt1P#{((@c77X zJbGUUPmd4c%)}6eJGY@~bD?;ErZU9qutm|HmG!ii;XqXZp3v&yYIMP0?ZkMfP7F*i zR?7(@A(hmc9oXB}gz1q!0cY;r-hkRtmrMX{0gU&ygFf&&Z6blXn4Y?K8!jB*g>%O`G2F5R zy=`82EA!D@=R#M#TSl{^%7J~`%Y>{7$}y!ER<849K>{=#%}4k9D@$YoSUokrbb0{q zpV^0tkA*OQb`U3rn+24Mi3D2xC1|QF5M$ocUM^PxlL&!nP6cLl0&F)45S;5+Z9ffo z`P``F?{6H%A8#F#E^rg}2fboU>dy>r$zL>TNw&Nv0ZPG1A(17hYX=t&+pZGeFCeRb zcB~Co&W{N=lkGp)<&)7=$CH&;mnvRRs-{W#r-aWa9f1>d5&kj~nC2rm_2=Br9_f$` z`0J|^BEyLxzl@&>P6_y0rbFo#lhUyR>uyO{yY1Hq@Lv%1=lD^Axrt8szM5i`8@(m0&KlXgvouOnsKea za@PxK9Zkg9X4_dgXP+a+>S;CttI3K9&et^O(&*k$2nklfs%bugQ-1=G7*{acO<)?2 z;30ppyk9)xCIwe9rQoXNjE6}mOGlM}9ibs9+tSx=ddT6_mq{7aX`tR*zc-?JG!d4D jompBiYW^Qlghul>P*9<6()zrB00000NkvXXu0mjfRW#YX literal 0 HcmV?d00001 diff --git a/images/cursor/Mine.PNG b/images/cursor/Mine.PNG new file mode 100644 index 0000000000000000000000000000000000000000..52490273802bf994cf9917e930f69e9a084da114 GIT binary patch literal 1274 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 Hu0mjftNq>( literal 0 HcmV?d00001 diff --git a/images/cursor/Taxi.PNG b/images/cursor/Taxi.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a4bc9025561bcb45bc5a350374ae0ad8a1a73979 GIT binary patch literal 1885 zcmV-j2cr0iP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L2J%TnK~z{rotJ$~ z)nydNG0`Nr@_t1?1wnKT z(obeag~;->sj{ayMGkGukgbKYrM@^-vS)=$Sb&?j3>%^&I%=}4TDe@>+uP;Vty^;F z;9*HjOjMon`}O_u^QW8S&gmj^+T`B8JUzhTY<&u(;tOgJTz^xX0I;O|R%gviNOyKTc z?y14N8#T($1V`llwI=!T+}fx_d}mT)gDw&;rzsMV{B`hg=ogxvtQ{niZ$v60GJ zyg<2O03#+QMoC0^YPZy=@;@FulC4|oOyjDns+4eDU0qUMUSa6%2afauH^l1Yp&%H7 z^-GrIn;}Orz!0suxmn*~B)~g&*6SLj$KGMXhAS_gB%dKq1vdl(U_0JXQslE>>0$-P z!!>J4)N8=-oH=`VVl*jX@7I^V(u#7Z?IX_wM0{-ZhS``|M^%WKuSTK46jP$>EYXWxOOrj_FgL3(`_G#FQoJA@`eVHcQDH#agE9F&fj1X;He? zy8}M2X#NTJ!-o&_xxcAVmgd;Wh*FGzoEX8J@UxDwQK43ejSST^P|{B}q304Ktc29! z_EMiH&;wvT9H3tSY*dP`r<)qEZ*RRC0G}L{FmNMmqV-QlGh7n_<(HV3z39#mn1AOA5wAAX+Jnh1x%Iq(!V&UnOHgq*YGrjges6 zQ9RbqUAjRfx%td|&z671!yACgbXC?zpkQ*i$5 z$689fONkAU@L*q=H_byn*fvQjb9|&M%PQeP_Im+j1o+^4yY)NH6i!+ygIg1Trr-@; z;$6$({n~CJ9M<}ed_iJ@E#@7M{BZ$Umm4d2$&oU4w3nuXCkL2Koj&;%9i)vlz6HEE zGqxWG^peQQMwppXRve=oA{<5#XH9yf)D=wAyI*TOBAETXgVGiHw`s>;eP??z+3ipHW$l*s#nzrjGa2sUyZY)+ePYYHz?!roX}Bn zM4-5+P|J`eLg^W8mhz&@F=zjxwAp%K@qYjSJgr+XM>3PbG(|jV&FlxTk3hhZ6$|yS z;AF#V+AfNX!Fj-c1Lnpt%Nft1#1n4;>g^d7^i0rRqBooezjd3J2ROj_4iV{qjeB-# zWT@eWZJTtR0|;=8!aKZ$2M(PB7P0zz8CNEAaPo1pHGX?~dT6eV-*5pQkXs^PTN|{< ziH1VC)LJbEsu$^hJD3a04dw#CAitCl{|O-&?;sXB?5YMK)cDEWE2aDVZt2)pqBY*Q zF5N6O1BmjO9~Y|N7{l7S{2AIU9jXQ`+Gu)TG#J!1B?Ym_FChnvr}q8-2*wzMI63_b XcKM)ybS`X=00000NkvXXu0mjf=%IVC literal 0 HcmV?d00001 diff --git a/images/cursor/Trainer.PNG b/images/cursor/Trainer.PNG new file mode 100644 index 0000000000000000000000000000000000000000..c1c19dc10f45de0db521133f3ac633392c0825a1 GIT binary patch literal 1747 zcmV;^1}yoBP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L253n{K~z{r&6a6Q zRaX>+Y2#3(7y~$<4+lU*1S=p2h!cYf&$$SwIG~__RI7mEJXVRAI!o$Q2TYt&>kx-% zo3v?S)M}clHMZ%H{%Go-_E-OQm2bZPK0Wob&EG_pG(o-e;fdQ*Zi*{>n{H zzTBlJx3}x(Pgd&3%Zv5>r7}G_nXh}bnYy)Y=&J;8avvk`)3r){dv;Evf3<(CZf;Fh zLPWqT0goRPtG)XV$UQd8Yd<6K-N*Aiz=^yCaOZhb|20~0NT`acR_M(6k970iT|Id8 zjgp4Dz1}kd$PS5zb$Ks}Ty<9;O8P@ZYim8$^o{7N$&d z?WobY6Z>>{#~Q6#SfG*_ZcWdO)y3=A&BG%4X?S8kz0szXCjlq_cXp<>2=42O(*0Xk zRk6HMD>rPEudlD>FDTNKvI@)XxWV0(817PR?@k&M6{-m%BF$GWTcX9Q)+;$>h)SlW z$=|QN$NqmJ`-{M_Q3>HXy>o%C-hHT$zWsFW#^FUI;PyW1k>Xb2v|J^G_$e>W zrDAuCDrctJI4wEE2moGHQKse9dkl1ERgN~5W~z7hKu-cM0X zN(*YO(R~6{Ix51V#&e@O8;R=j93!yj@KN=Tj?;|sLrguMdl6{x=FC7h%u6!%S;2wY zb@IHj!u|#?&v@z;c?pg3Gbj4Ro3<$;w3`lWn58p&Dz&9*t_IfE$+LynB6xJqAQi>5 z(z2q_n%MI-lasKRD}OiC!o_YR&=WMqFUynP$y>B`Zysw~b?{={Lb ztNYN3xB;h0lV7{G29ETlqg={%XK3E?O-kz2#v%tCFbFVroP+nI6iCqVbTM@#>h>@13t8Ophe7cz**z0qXsBUq9^w#hy1tC?^az+ zshtE`a#?vrvjhwrz})b5wjotNyL_3(4okJU6SWh$6Ft8n_|E(}O3N?N(1b`Uy8Sgv zOo8sNqOY17a=FQMBa# z+VRb*d%wauBZW!3ehTMl2F{BB5h>9`cJwznnI{GZm@=FMfN>OBIwHuPv!;6ea=qTQ zk2NN8f9cRViyjrIp-rpG)v;@DF9HTmUXGtSX$3+g5TVWHWsf%{W=D512aM>E95n!D z?eq~b8e33odr`Q%Ru@|I5STGJ&7yZtoYXY<)WTw|UXrgxRaN@ox8Lm=?by~={o~_J z4FCZrYLvi_$G+sA=GCTs2X6vgGWTv?)}Ub{Z4<6d zU;oY)J+e6ja0i@xBlGYHQw)6Hkz+RU4M6Uxe!x+HbI-Aylrh8$9MiZ-yjKd@(zjYtYlS|&XGGaqe*bgE*CBcu2o2o zcYtxOQ6eK!ha78g)B%_^%z2+qNA4S=ufKlTzq#l!<>pSYmdV%3;FxgRC@7%4U7^gm zJQxQ>23y`KGDe;=a_ix&q3=`uMDOID=M7j*n$pu!8x=?&I>_=!By7MO8JQPk*GEG{ z^}eXUZBBD>p7TCyFC1KLmCy4d`}ejOJ!T5Hf;!sJsVK*L9-7=e_eIPne7_Zu$*ni4zJv9RH$cUD6 z?_qo#1Ox;$dc)&q%`PeagBYLKqz<1ob-WR0gaic~7Zd$*(f>;WzyMJM75Uhp-wzl# p;6Dd{-i!=)!SkQp|6}v<`3ow+D}HhLToM2P002ovPDHLkV1ilRPVxW% literal 0 HcmV?d00001 diff --git a/loot_path.json b/loot_path.json index 5447740..9216f79 100644 --- a/loot_path.json +++ b/loot_path.json @@ -1 +1 @@ -[[-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-1, -86], [-238, -79], [-263, -75], [-269, -74], [-302, -74], [-307, -72], [-324, -48], [-325, -21], [-318, 10], [-302, 40], [-251, 86], [-197, 121], [-124, 151], [-43, 173], [7, 186], [54, 200], [92, 203], [115, 201], [171, 179], [224, 144], [259, 108], [273, 75], [276, 41], [252, 7], [221, -23], [162, -55], [110, -71], [46, -86], [-1, -92], [-47, -92], [-90, -85], [-118, -79], [-135, -74], [-160, -64], [-184, -45], [-219, -9], [-236, 35], [-236, 80], [-193, 120], [-132, 156], [-61, 175], [25, 190], [124, 185], [174, 170], [209, 145], [245, 85], [253, 31], [226, -5], [184, -33], [149, -51], [110, -66], [90, -67], [70, -68], [40, -69], [24, -69], [3, -66], [-3, -65], [-10, -64], [-10, -64], [-10, -64], [-10, -64], [-10, -64], [-10, -64], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63], [-10, -63]] \ No newline at end of file +[[-13, -55], [-13, -55], [-13, -55], [-13, -55], [-13, -55], [-13, -55], [-13, -55], [-13, -55], [-8, -52], [-6, -52], [-6, -51], [-6, -51], [-6, -51], [-6, -51], [-6, -51], [-13, -54], [-48, -60], [-127, -60], [-174, -46], [-201, 2], [-214, 49], [-216, 89], [-214, 111], [-193, 140], [-147, 174], [-89, 201], [-39, 217], [25, 227], [79, 219], [134, 185], [178, 149], [208, 104], [219, 65], [213, 33], [201, 11], [178, -9], [128, -27], [89, -39], [56, -46], [24, -50], [15, -51], [9, -51], [1, -51], [-10, -51], [-10, -51], [-18, -51], [-20, -51], [-24, -51], [-52, -50], [-104, -37], [-157, -12], [-206, 42], [-230, 96], [-220, 138], [-180, 156], [-104, 168], [-11, 179], [46, 179], [95, 167], [152, 118], [180, 67], [191, 25], [180, -1], [145, -22], [93, -31], [36, -37], [5, -40], [1, -41], [-6, -43], [-7, -43], [-10, -43], [-11, -43], [-11, -43], [-11, -43]] \ No newline at end of file diff --git a/recorder/北风苔原修理.json b/recorder/北风苔原修理.json new file mode 100644 index 0000000..0ef2450 --- /dev/null +++ b/recorder/北风苔原修理.json @@ -0,0 +1,30 @@ +[ + [ + 49.02, + 71.16 + ], + [ + 51.50, + 66.65 + ], + [ + 54.43, + 68.34 + ], + [ + 57.17, + 69.91 + ], + [ + 57.60, + 68.08 + ], + [ + 57.43, + 67.35 + ], + [ + 57.79, + 66.08 + ] +] \ No newline at end of file diff --git a/recorder/北风苔原剥皮.json b/recorder/北风苔原剥皮.json new file mode 100644 index 0000000..94a2d74 --- /dev/null +++ b/recorder/北风苔原剥皮.json @@ -0,0 +1,170 @@ +[ + [ + 51.35, + 67.35 + ], + [ + 51.33, + 67.89 + ], + [ + 51.3, + 68.4 + ], + [ + 51.03, + 68.87 + ], + [ + 50.79, + 69.31 + ], + [ + 50.5, + 69.75 + ], + [ + 50.23, + 70.22 + ], + [ + 49.96, + 70.69 + ], + [ + 49.74, + 71.14 + ], + [ + 49.53, + 71.61 + ], + [ + 49.19, + 72.0 + ], + [ + 48.94, + 72.47 + ], + [ + 48.75, + 72.95 + ], + [ + 48.53, + 73.41 + ], + [ + 48.18, + 73.78 + ], + [ + 47.7, + 73.94 + ], + [ + 47.21, + 74.04 + ], + [ + 46.71, + 74.09 + ], + [ + 46.2, + 74.11 + ], + [ + 45.69, + 74.03 + ], + [ + 45.27, + 73.69 + ], + [ + 44.76, + 73.54 + ], + [ + 44.31, + 73.32 + ], + [ + 43.97, + 72.94 + ], + [ + 43.86, + 72.42 + ], + [ + 44.02, + 71.93 + ], + [ + 44.32, + 71.49 + ], + [ + 44.8, + 71.25 + ], + [ + 45.31, + 71.15 + ], + [ + 45.82, + 70.99 + ], + [ + 46.33, + 70.88 + ], + [ + 46.82, + 71.04 + ], + [ + 47.34, + 71.02 + ], + [ + 47.8, + 70.82 + ], + [ + 48.28, + 70.6 + ], + [ + 48.8, + 70.6 + ], + [ + 49.23, + 70.32 + ], + [ + 49.59, + 69.92 + ], + [ + 49.78, + 69.45 + ], + [ + 49.81, + 68.9 + ], + [ + 49.99, + 68.4 + ], + [ + 51.35, + 67.35 + ] +] \ No newline at end of file diff --git a/screenshot/game_state.png b/screenshot/game_state.png index d98fe3539220ee1783fe157219c04c91ac910e2b..92810dee78e7a4ee1a051a23722f982a3d9e9385 100644 GIT binary patch literal 412 zcmV;N0b~A&P)OX+_YI9s{u2Z!C1AaWA!?@N%^fum@Kx!zEMk!eWY&zi|`Aul+8H~J8d-`Fz2arps`*OgcB2~y$!0000aGV5C!1(-pubfKq%le^jw01iaStKbBUaS5{Wx-5~3(}{O`=8pmJ#!*oyY+NAt8h z+SM-afBwm!$m*_cH`;BO#FvlnaVqlU65yPg|LBv?srvoy`>7?n4`0t{^!dlh`M#aC zP4~YZ{&gZ43awQX2s9uuh(SWAv({^R!9J$U*AYV71}Mc2G5$y=_OML zKm(|LB63vO;|bb;k!ql;rR=IpN1d)qLdl$bQ(~XQbV3<~GL|AV`mOwJpgCk-Bu$>ADEr zQo9t90aeEmFnhGiFuEGg&!gwZ&UCB;rZ-Duz}*>gHv}j^V66svS+e?Y>8R6nd9z_C z1&+}xpa$9~7&c%-$!r%nPo3$A#Ek@-QFJFDifJ@m1CsY6ZZ~1i*ZFkhupV|+0;4Ta zyZxSp74|BLc1EBI-SanjI#NYc7Z7R~dAEt(;h8KkAhLLqSS!pqI@6J1FEn7A6#fGK W1sXjT3I2%y0000#q5e9fEDzU;Zwx@- M>FVdQ&MBb@04x|1_y7O^ delta 43 xcma#>nxLX4=;`7ZQZXkvL4tL0g2)A71_tI52FA=MGs_u(z|+;wWt~$(695k~3}pZS diff --git a/screenshot/game_state_flight_block.png b/screenshot/game_state_flight_block.png index c2b71681bd5872623d4a68c6121d33db6c0690d7..ddb2d15bfc2b8d28f847ae66ab056be2bea9a09d 100644 GIT binary patch delta 59 zcmWHKnxJB)=;`7ZQZXm_Lq}Rd!ViC;q$CAdgWgw(61>c9j4!n3v4(ic_Wnp O2s~Z=T-G@yGywo`#1sGk delta 56 zcmazFpP*ta=jq}YQZXkvv9u8NW2%q6BdJAW}RU;qM7 LS3j3^P6qe)2c-n1(8DX_3=)zQWDR;>B`ye;xWLW8u-t-ChEsX@ Q0R|xOboFyt=akR{0GV49L;wH) delta 53 zcmazEnV@1I?djqeQZXkvFVdQ&MBb@0O|J@CIA2c delta 55 zcmazEo1kJO>*?YcQZXm_&v^%(gcidY9oL!|7FW4_j delta 52 zcmWFyo}i*H<>}%WQZXmF=g)ZutpugW<16L`+BV1Y?`2@Px0SI>Q(Arv0}yz+`njxg HN@xNA{1y@~ diff --git a/screenshot/game_state_mp.png b/screenshot/game_state_mp.png index 2da3e803ca4321469776e8b923e401aeb3b9c022..569198438a86da9c84448dc216c69f23dcd7c8ff 100644 GIT binary patch delta 61 zcmeZ@nV@2!?CIhdQZXkvCE>?W2d0GNgoK171zCgMSBVn5%x#XcY+sld*77sTZCsjm Qj{yigUHx3vIVCg!0D__v3jhEB delta 43 xcma#?nxLX4=;`7ZQZXkvL4tL0g2)A71_tI52FA=MGs_u(z|+;wWt~$(695n13~2xW diff --git a/screenshot/game_state_target.png b/screenshot/game_state_target.png index 871eaa79a1dad969c1cea723102d0e777487d264..509c85b82371004bde9013838a2240fc1a91a38f 100644 GIT binary patch delta 58 zcmWHGoS*?YcQZXkvK|#>vUwVR4C_nSz74rgZo8$QRGBC_K$XF^oSEQ8z2s~Z= KT-G@yGywqosu8~c diff --git a/screenshot/game_state_x.png b/screenshot/game_state_x.png index 8a70a1e71c3a86e6382579add89cbade0d978ce0..ccce0f4f00576a895fc5d86c2bc8de4d0dcbfd80 100644 GIT binary patch delta 60 zcmWHEo}gl`FVdQ I&MBb@02c%kR{#J2 diff --git a/screenshot/game_state_y.png b/screenshot/game_state_y.png index 304e98e019c2d0e9c7dc79b474398f27f4958601..74cae335ec824a3a2d0c04103a5922ad559aa294 100644 GIT binary patch delta 54 zcmWFzouFbUxQb;oz@Bf>jJa;OXk; Jvd$@?2>>qB6bS$T delta 52 zcmWFyo}i*H<>}%WQZXkvgTe~ HDWM4f18EZI diff --git a/wow_multikey_gui.py b/wow_multikey_gui.py index f362987..ec41e87 100644 --- a/wow_multikey_gui.py +++ b/wow_multikey_gui.py @@ -583,6 +583,9 @@ class WoWMultiKeyGUI(QMainWindow): self.init_ui() self.find_wow_window() + # 加载参数配置到界面 + self._load_params_config() + # 初始化全局热键监听 (F8 用于拾取录制) self.kb_listener = keyboard.Listener(on_press=self._on_hotkey_press) self.kb_listener.start() @@ -1139,7 +1142,6 @@ class WoWMultiKeyGUI(QMainWindow): self.gs_offset_left.setValue(cfg.get('offset_left', 20)) self.gs_offset_top.setValue(cfg.get('offset_top', 45)) self.gs_mount_key.setText(str(cfg.get('mount_key', 'x') or 'x')) - self.gs_enable_mount.setChecked(bool(cfg.get('enable_mount', True))) self.gs_mount_hold.setValue(float(cfg.get('mount_hold_sec', 1.6))) self.gs_hearthstone_key.setText(str(cfg.get('hearthstone_key', 'b') or 'b')) self.gs_bag_full_hearthstone.setChecked(bool(cfg.get('bag_full_hearthstone', False))) @@ -1175,7 +1177,6 @@ class WoWMultiKeyGUI(QMainWindow): cfg['offset_left'] = self.gs_offset_left.value() cfg['offset_top'] = self.gs_offset_top.value() cfg['mount_key'] = (self.gs_mount_key.text().strip() or 'x') - cfg['enable_mount'] = self.gs_enable_mount.isChecked() cfg['mount_hold_sec'] = float(self.gs_mount_hold.value()) cfg['mount_retry_after_sec'] = float(self.gs_mount_retry.value()) cfg['hearthstone_key'] = (self.gs_hearthstone_key.text().strip() or 'b') diff --git a/wow_multikey_qt.json b/wow_multikey_qt.json index 9669e73..b043fdd 100644 --- a/wow_multikey_qt.json +++ b/wow_multikey_qt.json @@ -11,6 +11,6 @@ "food_key": "f1", "eat_hp_threshold": 30, "eat_max_wait_sec": 30.0, - "enable_mouse_loot": false + "enable_mouse_loot": true } } \ No newline at end of file