From 5188b5423bd52e2eb5dea109aa073139262f282e Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Sun, 30 Jun 2024 22:37:01 +0800 Subject: [PATCH 01/27] Add: Switch among relic pages --- assets/cn/relics/ui/ENHANCE_CHECK.png | Bin 0 -> 7288 bytes assets/cn/relics/ui/FILTER_CONFIRM.png | Bin 0 -> 7506 bytes assets/cn/relics/ui/FILTER_RESET.png | Bin 0 -> 6993 bytes assets/en/relics/ui/ENHANCE_CHECK.png | Bin 0 -> 7379 bytes assets/en/relics/ui/FILTER_CONFIRM.png | Bin 0 -> 7710 bytes assets/en/relics/ui/FILTER_RESET.png | Bin 0 -> 7473 bytes assets/share/relics/ui/ENHANCE_FILTER.png | Bin 0 -> 6442 bytes .../share/relics/ui/ENHANCE_GOTO_SALVAGE.png | Bin 0 -> 6476 bytes .../relics/ui/SALVAGE_CHECK_OFF.SEARCH.png | Bin 0 -> 9365 bytes assets/share/relics/ui/SALVAGE_CHECK_OFF.png | Bin 0 -> 7095 bytes .../relics/ui/SALVAGE_CHECK_ON.SEARCH.png | Bin 0 -> 9365 bytes assets/share/relics/ui/SALVAGE_CHECK_ON.png | Bin 0 -> 7075 bytes assets/share/relics/ui/SALVAGE_FILTER.png | Bin 0 -> 6307 bytes tasks/relics/assets/assets_relics_ui.py | 106 ++++++++ tasks/relics/ui.py | 257 ++++++++++++++++++ 15 files changed, 363 insertions(+) create mode 100644 assets/cn/relics/ui/ENHANCE_CHECK.png create mode 100644 assets/cn/relics/ui/FILTER_CONFIRM.png create mode 100644 assets/cn/relics/ui/FILTER_RESET.png create mode 100644 assets/en/relics/ui/ENHANCE_CHECK.png create mode 100644 assets/en/relics/ui/FILTER_CONFIRM.png create mode 100644 assets/en/relics/ui/FILTER_RESET.png create mode 100644 assets/share/relics/ui/ENHANCE_FILTER.png create mode 100644 assets/share/relics/ui/ENHANCE_GOTO_SALVAGE.png create mode 100644 assets/share/relics/ui/SALVAGE_CHECK_OFF.SEARCH.png create mode 100644 assets/share/relics/ui/SALVAGE_CHECK_OFF.png create mode 100644 assets/share/relics/ui/SALVAGE_CHECK_ON.SEARCH.png create mode 100644 assets/share/relics/ui/SALVAGE_CHECK_ON.png create mode 100644 assets/share/relics/ui/SALVAGE_FILTER.png create mode 100644 tasks/relics/assets/assets_relics_ui.py create mode 100644 tasks/relics/ui.py diff --git a/assets/cn/relics/ui/ENHANCE_CHECK.png b/assets/cn/relics/ui/ENHANCE_CHECK.png new file mode 100644 index 0000000000000000000000000000000000000000..e63ed7a8b1c27daf7ed49356e48f80b3a98edb3e GIT binary patch literal 7288 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 HTRs0j@rIKa literal 0 HcmV?d00001 diff --git a/assets/en/relics/ui/ENHANCE_CHECK.png b/assets/en/relics/ui/ENHANCE_CHECK.png new file mode 100644 index 0000000000000000000000000000000000000000..415ab95a68d618a8b84b04ed2491a4e2bf9950a2 GIT binary patch literal 7379 zcmeI1_cPp2_`u&ib08nT-DJ$#hzJz*1yuRQ-*)$eIykx7 z1AzZjwt=5X5{^-R9%p|8q%^TxndbTm;O0S)_0X8YX+8kf;WV_0oe|L#AbN(IS*k`I zug54t?ld?)c^Ca6#>iZ9hjXU5HaGyYy?yrktQnn!J|Bb)-3Yr$%b&OgcLt>N zBV?r~IOBCxJAR&jXBA9=O_g95;f(j@=2)K{k=cVmlyn2Jw z339k2^E_FE2CHXLWFJKfjopF_kH5Fa)L0^Ix!W(Fcb;k8)uSmL(vKd zOIH%=2X0Fe0?Hh814OqqiSk58TNg^e?hy^D1VCF~%0QaNs5pH?$}p?n{_esO*V1>_ zN+oNiyEG2uE8JOWnLKo=Xd=zQ>j1!dGV<+GQXv7owz9b9fOf?kcET@RcA?zzTzm7E z&F=|`0UGTg%oKQab)3k(o8YTYt4oO)Fa-i$&YxI_Pm|}ppcoD~iGfL;D{|!I>-Na9 z-=d(T+~%{%M~N=S$X|&sLKk8}j_{+G(*e7HM}}g0SzE!I3lD2I-*WvpbRV(O12-I+ z=dwE@^dj!=$kM|~b0LOzdnRuibh)*bvh68}4){}TeK>}bPt#BCtn*T7He@>>kzr+KgLeSJcD{Tn@^jXLWadvhBTq4l+=ir0DDWNDPHt%Tj8$Y)M{!eZDaJwaUi zm54R(X2v2-&9?`VROkg-^H-bhOxLWKbG|b-N0Jji=^>-D=8}%SX%jcWJxIos9!Jb= zt@`joSmEvUXnH;F&K}P~!V)FtLA*> zm`tlKVXv@C{3%yVDLt=LZ=fXS7g=evbnXi^NS?2*h(S~d-9w)YzJW|e<-S7Ug0bNY zCr2mTOObVNB>C(cj%R7ZX`?QGNY~NpZw~#gQ$AY1|V;v?=8BQOm}x>SRmPm*kAiS0qr=K-sI*0pXD7kiF(HKtSD9xv(oWnWa9+ zHApoWC`=@*AY3`_T;@;~QucT%V5()xX4`X{aeH$LV5I@Mzy#dN1mr3Uqpq-v$& z5FbJEAQ%V>`i)QarPUUeA=y?5q1+mRZ)}n+chxU!sq{J9-yu;5PMO z>wJr1D`V^0w$zdJ5#JHyXo$W47A^a@jJHgXr?*ePud93WX5r$)_L7d0_H|=NHphIg z>;nm=B8`MT+BDxZCId+EyJEN8fWDMf)*a+%?N4k$W>e-&*(BuGY` zaGglLOP(+{AUCR|sD*o8u7xLLJS07Y^gQQG=Cto3{qxMi_d@vKd~mor?DJ zYjTX=jEfv1o2LnZ7M*CW_t%j{FQ~XiH*h+!q%)la)8D-(R(gL!ug1XJ!y6|wj#x20 zb411M#h1Kql$my}^YnE@IJ@e*+HPewgf)~lyz-AaezuoJ>rKZ?zWsKkW1>Uu?Xnjk z+BHKwYbC=l)!Vjwbq3zZw6;Fjm*XdEDq)%sBpLCMHmyow_04T1T@hxT)nYd-cDnuW z%m|%lE$~>lUS)lQy6lIwY*5OPHq^Mrp3eSnx!8C(wgyu*=jefZ< zHKV4;XF-26W;6c=Rg~(BU*hu)mm4QMl&=|sPzhgk8@^UgH29nDEpWF!YhvVyF<|n$ z|G+{YY3J{>I~v^gvac%jLU+kT-)P?%HnSh6|7P^lCuPCc#t&0Ul7IBMl^?!nv}LeP zu`|Lrr;V9`Lhmu9fD!J9&*jHopEs;68Eb>bg0L{i)YP1Meed?B>Sp1l8vW8(&D26_jGB&;R2&HC#Q)BE|43XTG@LoND17iC}S zTPFFZ##?9o0uQL)urtWaVUo9+YX$v{T~N=0v2LR~uV>>~ZP<{lYaz1@DtaRjD50-6xx+UU`bMmt9 z$nBl1yiQs!wkyub)>e@Fl|BQ*X`ZLMSm;@x9F>Q16qvksH0!~*9|v>jc#GX;_d{-+ z%`{)VMwwi>oJxrM#iDA38FbSg*SBpfTkd_RwJ9@#`5AiZ+&1R*`}p^Li(D8A)3wD` z@5VoStAP)RJ@!4?X7Z!h(VVdei1)8JZ<)H-AU(aY5n6LuY2OA}IJRoD8frJafuSak z%DGIw`Wdx2s?x7A#`ByfHa?q^lZ}cMwQo0=v{+nKOgGdU0=j~2dVN99Uo4$z44Iry z>{6b@47HZSN)9|RUrH*ZyLq}fn+IWXdqwAEgVVv71`Kk(8^xJ^=Unkp_h97Iw!3&( z2PcmXx;z)bg&&;pjpmBuv(4MKs`^?05WoijVQ&E78y9FhM_n zJD&ppEui-FiJ|}0)@-n=(JDLXF1lty9TH>mP1H3X(ahUSrbNShT>#EYUDmAmtD(Py z&!BC9ILmYi-X%;|9P_q!*Zv1!??LxyUR3`*H7woEzRC)eJ^JCE6_*nEFk`?`cSOMS z+%!WJ9V&MSjGjYF4V}yeo(|Oy1?SNH&5!@dKLY;<{3Gy>z&`^22>c`PkHG&i0dRAV zF@8!r1bc0*lZ{>$zjP;9Da9k|kTFWTFGl-T?$f2s`HEwg(5CA1P9gwc5!!g@QAe5T zF={$;)zl>!?6ckHA}8$ohQtb=MJDi{)@4GsC2?#%tU0ZP8~VutM3im#`2_@|QR>ms zCHK{RimnHlKL+Ego{D7F7WS*7^Y_(Kc$aCucc>+;4dl*u=381+uleaHWP^2gR}6Hr zPnDLn$BDYv#lN!W5&vC;Mv3g~XuGVuT>JM_YfX)EkETpD(hoDYv9WP}er~`Lpgd}C zkW9l@MjR)deD8t+zrJEojLiMdsFT!paJZK~$-t!TH0Ig7PxXpw%2OE z7jL+zWo2XgedTj8I5oB9HrXCY%_ik+NMEal)zZ>}mVvV&~yX*!v88z*QwjDx+sQGd4C13$NYCt+b>+-x8eDUZcs z86M9!+jhsT80;S$aQg3l^H}cUv-I^Xd)HVt2AQeZbM%|Vt{3Ol#fjT=M3XWqOf>mn zp01kJxi)SV`|Zq{%}-e$@7}y2cb*A{a}(f8)3=p*MF9Dnz{hSA!>sIdH>(>83mY1E zrIiW{+Zm<_6Om@Ae!sHXV@cQ87`IG9nUR@ENl7W7b$XP@qcRtC5DS^EgG}s# zU?*c-;qmgPFXtfjk0d0hnMD^yHHtZ8{dXgnE~_BZGL&mWW-UwUzI2^`&rR`K#9|<( zvDl*hhFi18x9$4+K(9r(4BA{qAY9kLz-wS@5|143iWYSnS9nAW<3QulRB|xNb6}R~}!ijS@f`4|!E(>V( zWU*zfLT};WnrdrnXWfFAQ%q>oG@M*(#_+lE~QBB|PEbDVP^dwODmS*d4eXlP&n;^uaVDSoz1 zw^M1`twg2=@-&AUIBRHVkS*>mw*Sbq!u}cI33qqE?fiGDk^xMw})&>6ZOz}G_&Jw0vA{KK;|PphX7?V zEv?uy90pnzG%;+=72aFx63;HfsFZcwjDI$lL1|~|;zaoGgkcAcRuyaOCfT5G zJ(LdpSw0jZlVAKW_$y>=83H>GCr1TfOUueGuuGk}wpm|#`+ggNTCOh7Vi@mdNdz7( zDo5q|+u(nJ+6&_4LHeU2;i6vSTgG6EgSo)51Ggq@hLjft1w|cn{_diC>boYlth4S!k8ny?bl30h=6xf=^Rs5B5KV%F6}xf85&Idh&); zz%n%@MGJ2kXlc1mGKFPP2s!`oNh8;y5?)lqFCgG}`0+u#p`q;gu(F3n-=t&i?3f3f zX2~5ltB@<{v7{l=(%^+2L?E{E+aoRgF0l6VLNarECcKX%(!{wRh9v*V*s`b!naep2A_q3K-TrS9_-Y Kv|P#R_5T1ltWNl7ZJT?wNZ`BrPQLelxaaI`(n>r4#4xy%zYY+WMW8Z0?Mj1JKCK(C7q=wbqX=vKTW0}=qh8Rjp~0TfaI8~Z9U#K3q#{4^slo_(u; z1c)R6lJ6>U5y~|HR{C#s_z7EDflP!P$Ac>^B?Q67)xt`I!AN4jE6ON_O3n%hPL}8I z1MY|u0t&Zj`-$$T5oJCcYMw2ybPugnCIDJ`6Z?}?heYUV6Mr*%?{3e|v(L9Wm&sc* z-lMi7UF3i#rE=0LV~NxTt^)w`G3w`qxNHn|d2w#p4(p8DZ_mDP+IHiRVc)@AG=3($ z0#IuV;wCMZmd1$OI|+VxHaiuV0+R-SJ?7Y4WQsJ?gzUHPaRf~KOzw7imR6S(>n$>J z@=b1=Eabz52$@TfIk(w}z(ert#gy+h@H#~{xK;sIN+4lrSwGI*h zc$WG0{*R~EuK%P%v{1r-vNpCb5?Wt2yMT%Pf>SFLMvMi=APjBkANRD5r`a#5; zc_U?xy7H%xI0bf=#_a97JL6R=ru0^(#t)=do_3MYTC+=jykQeH&M`p3m>hM5!&+H1 zE;#qj>PI?lj`prMxr7Dsj@VTx9tjF@>k z8Elt~#0;XvY*~#Sd(pGBq+8=ixCkSHX*WnLLa1Av-^Iiz8L1g5eCOWatfZ+YF(iE- zBGk&u5&vDYlG~T&xXs5#vMk2vIf7@4{Wg0#w*@aHt!2D27iD+cq6Qf|cZ{$Kxr&qW zl(ImsZm!G_wF6v@XFbNH`_Cdtc`)KmQfy5ORg7lbY4@+i8am1LkMnAz*<3og2{bRn zUdb+9`IaFppPX5!-CvMCLQ?oqGQ&j0CDThwP&cfAR@5_vyFZmdp*L3`XY_Z91H=Ju zFSrV=C!KkJTQTW((vZ{2wN>ou`+e{06dx$wcPiW5z3Ft*?`A$z%}v2%wLIeCq~tEW zhiGAzWXM;luWtHA_Yd#;)5rGEBuXY4BnBp83-$Cp^kqk3h2(lg`cy?01_61`^((X% z3P?v7ibe}q^&1Kvl?>>3>qKh}YFp+sS)RW;v85>g5c)jxgL00ZZB56`NOpz};a59G z@?&odh}QX?zN*`pmLG4Zc@dwocnSKc=_+^>+9B*>?b4QC_Y+Wdl+A8SOu%0Zun$lS z_z4gR$O@E=ITqU$2Npk`^qp*)wAp;K$*{RTiSu+%lS|`IJCJmd#Cwv~KdRTR53Qf_ z99)wbwq1va}F5SaAPFW#*$RU!i1{$e*dg3**&sy!yqb2BvbJ#$p2}^@ZC`A<*Pq~& zVpor<9ESGwb@5Ll#u42cQ4*tYr*!M4iN>k3$k144t)D3{$VCN~ZQ!e=klgZu3fY!O+dqMc*5`ccAM!DYS96 zLAH^yadlJT(E5=3(B*KDweJ=U>(~?M6aP0*&pt0__r~?yIniGQZ3Vwp4IwO$ERVE3 zF~&UAm|mJBuOvoYm;CU2*9_m@#3kmf`k|`fgPhcc)al|0mywx1>Gpu4Q}qX_EZye6 zq;XI8xA8{vulp9#@>BC$_hPVu7G4&{7N^MDniX)K^s$F7T~lqQv&ddQD@hsYS0@9j zL^2&Rgc-gWVNH2W92n^)&cLz28DRlde5Ven&)7<3_BXcRs=r@mI#noWB6*GVai+1|vvwJ`3o9NUUaL-AP5Bqr3 zZjarF`Y=d>p$>G*J62omt0wt4tK|H#md)X2GUIUo-M#z5g%8%WD|Ml-p?Ll=#G>&j z1R1pxUGTZ?$&_RD8!rgL(OJjYb|bYmxVEtNtxwpI;!Y9`l$MKh^V4G6c$@U61rI{3 zbBYLjF-7kS)V5@4I=hZ>d3B&S-CN37%s9qhJoGC~Qn~EX`#bVlf=rrA`L61$w7Vgx zp_+tnn#%h9aZz`z-y%jo?; z$XuuXrH{k*P(ZJJZ~2#Vt$8CI{ar`c^lp^S`=M{&6!_j5iY68$boaWJ?3>it(px9K z)W1qpKhP{+$AhT;%Kn~yA~9>RP1C+=#MExqqntzEv>@|dgY)8| znx+Y!$+6}cZ@)dt_pJ0!{@@Ze8mstx44sgQ0SB%_TkmF~nQd6=o0kJ;YL&b-+tZ`{ zzWH4{RK%@2LfxFFOPia^NnLavMc!7HbYDshcAHGyO!2OAH@Q#Q`gG|hFDB35Z$WD% zYv9-PuYOE&P|X3!x-yJ!NV3@zA&}#eDV>GHt$fZ&W3^yaYO1*m#0f3fdUlFM8>VNb z-Id-sUVIn7kpD72JxxPadL(%ohF3dFb~4vCM?w?^(`6Z85y0%#>PUyjNE-W5I>h+o=-d26KHS=TlXl!V$SDJRR@jE z#<$6jBLfjj>7Bf@;(@6ETrI91(}`qDzI!Hjp|yuPvF*(N zt%;Yx`d^$0;zRaMxrZ`Dz+anpY?XD?0l=3V0D|8G!0{zGt^$DPLjYK_0szUc0Kn)L zXW9N70BBWJo;}s`ncSFhu{V5m32d)#pqHzwyTj#GO`dAFDX1mUJ6O-zX5|_WbTM*d z35IYvX+PBxBx}9iO0pWNLq`AQ2EB34EoST1T^@Oo9c!D#M`$9Rs=Bn(c294~t<}S^ z1IXn}#vu9eu{6fR9D8{8#@F_=mth1pXoL4}pIO{6pX$0{=G%T*`7c zfoqdiOp;z3MkMSian$lDc|oHOgG{+D9;*-geAm>7Rk-N%PLV@MeX1_y9N07}N zGiSgcvs8XV!xL#kO-*kZUfHCKpY6kh6aa7?lkJ@uILj7vw$uL@;|!LQlWN@JT2ZM* zqtEMrfB<7-W2Sc&E9s(SMH&naMm>3%$pRAW+ z9cR+H?u8GMVxMd5MeiPVtIV&t#&NN8IZV=el=Ft|EgY%b4JH7BZ}6cN{WUJP=YD}R z9nD2WMIrQL0?&^4N*i}4AQ>)`m8-kGf;c?llIggjNTQz%?c+XG?ZWcd^|M2cQnW_g z;z)rmCg?IiQBe`0S0PX;uN=P!pA=Jxd-}#EjpbqzSGY0=|6}-_*yKNGUIt_YM2^lb zM9cm`p|tPP85Em{c`Wx;Kn4T%QA)U`)2*NHuVn;X98<77I_rekUt_Mrz*(Pog;4XT zr&KzQ78aG%-w$~haI$}}j!sHUTtd4oaJZDlR@D2(z|FXBu8`5UkXeBuSVXrRzYq@j zJu(74+Mc6s<&2gpw`mXefv$}dEG;cf)wl@?2yCvc-GA_4%X2KK%Fn~Bq8~2)nj_?g z&(3_qRy|){B%5qgb@e06)Gf5ru&9?hzL^|a3J+pC!MCx8q+3+EVqR+jL;%3~TaLBY z55Gmho{*S0ibi8S#y~QhC(2(hbSw?7ZEQ?8c;iqxN~)@=ylP*y3=Nam>Z+;^R!}+Z z?d`*P>Q1h%7t5(`aa?r=W2Too(JE!nH@CJfKUR%B?wIW4z2E#ZD<-Bkg1`=(f1~ ztemzs3e=U<>-jcnc|X6?bZNiI$;rZ^B1nIVXFI*&{>kl;7KOu{U3yUGzqG(sn*=0G zUCoic2WZP6Y4Ea|KfZkMsd~6&90mIZruniUKi$#IZIH&bcJ4!xW#DlSU+HHF5LV0& zYXunW`0RKOzYQeOJGQhlfl1 z9k%)0Dy*!89`7!hRy%+C2_B@9J#*h*K}|f{TkfB#^ME{>>`CP7{Cu+l1Qygj=aVH+ zqLHfobAyVrM|XC_&}IvUuVWjpl7d!_I`O*E*|j>HuRsFQeeT5!iKXS$K!7GeB9VoK zYw3Pl$zo0hSz1S14Y)CcF|8rAqGA9pQQ?6dxG7@CZ}cOxyu3U=A6tdC011j(vIjk= zR#a4ET4vKeUFYFv4heKQ#AAXm^`7f}$s&yWMq2v%Rd1GhK&BxQkO4UC@*H3BNuC6J z8rWPYqdW;XGjea>33+HM*j9%BZnti}#(|%u8JECs0BCtQinHiP_MqQ-`TVJNF$L2@ zQL!E5Qrc@{oVs;urU6}S>J3U+u<3}SWZmw)sHiBvWs{WpFlfUErqzgwii)zboemZ^ z{(JWv?Cn3Q_IqOj@B#Q4#uHPI0d&hcx-@7dD{M$q+GAPG!NH+4CtCW@DByfoK5J#X z%oco-An=}XT&a)U(uJ2gsE0IV&-Xv^rmt*lI6FFqdo1B1A|S-z|2s^1Co{>%QkN-SNDm$iF6@4Jx_1HH!7`=1vOn zz|f4i2|~dONZ9>cA1${fF{Metgo6xVFqn#p3JLocc#^r7G0EJlXlq;7Kild=3gXw)jG@X|sSoqrGa6zNB(P!p& z>3nAtx9qjfDcLQ-<%x&WOMD&cB@GWk+(9dX?%>YY8`hK!xH!fd+fBbJ%*o-**xMVF z4WlkBEc~$TJ0L5p$C(3M1%T&PsHvJkiLGDLqoW641lUP{FRMXm{B%yV%t;Fo71Yy{ zTZP85>~tx~vg6w>yOl8?A!X3YoD&mQ2rOTZ9O<>Vszutd;};137>5%-T%r9 z`lk`LK2{td;XVDjbLg9@_r^GC{BJSQl7+U43`*&mn@j)h3esJa!Z~e|{5Mw!x@AY9 znjt06L0^BA#jUZ-30>0B(E*y5jx01KB}FlUq5rE8XD=zc)cO9f2xQ=F_C1w}iAi`w z1emVd;Lh0Cn4JWeTIa2yrol{_nVCUb__;9Llnp!szp}s= zu^W4|meYiWt0y!^h@(PCX?H6IlST58$bg|-mGh`yio1-&fA!($;IKNSc-DNY+hVni zxPp}7FVp7ZCB2+t?+E`|n!604fv;I|L7sl7W><&ilWA|5_zk4{{yaCF5UnD literal 0 HcmV?d00001 diff --git a/assets/en/relics/ui/FILTER_RESET.png b/assets/en/relics/ui/FILTER_RESET.png new file mode 100644 index 0000000000000000000000000000000000000000..f70608e19d83be4b685453bcfd3cbb2d8aff4bd7 GIT binary patch literal 7473 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 V&vT{ss==R;YH8@+D^;_L`X75kopb;I literal 0 HcmV?d00001 diff --git a/assets/share/relics/ui/ENHANCE_FILTER.png b/assets/share/relics/ui/ENHANCE_FILTER.png new file mode 100644 index 0000000000000000000000000000000000000000..a570309c4efe949a9b71288ba7b58d93644d8268 GIT binary patch literal 6442 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%0D*T zIO+9rhdP9vLHZXVajm}Uj<=x`PStPEWnd$CGM3evt+sK|e-f+arPY=h`!fF}`MxS) z)zKa4JWFNzT%X*gZdP3QdSmK?@5?#u<@Y@;6D{3S z=zy9%$SMqVXF#ga10$G=$d-MNBP_qk&0sfYS8J#__a}(V*?6=|#2RL1XWW$CI-Czq zm@9Z%keTsVUiJri0(GEyf_5^~F~iv__h!m7xo>FJSR8cj{91}N+pKrpG zB3mk}=I?qs11mE@uG${p*9~P#-FF|YO7{~61CAVs@xzFn0Qz{OHQ>fXcIS+a|>HAIm1o-WKC41Zs+~%(KMv z!LXSDwJx}q*gE5u-bWa5Gzd^ z@rFGug){n>u+Q%F^z=Isn*lOjUS9j&eN&FwbPMgc`w+lt3Ai+4IPSw6QM#g|jM0no zPxSRgszh}%!yoLFl^$B1H>A|m|L~e=J|UyZGQsf+32C{2S20%|K!-Vd#-yyQeWrQU zZM5^l>)&e{%1Z<|8eJADBgbEdg$=F>d2OV^;nt+Afqk7I!q&g#OXB&18g z@r6w0g4lIo#c($T1g;@SSuX^z>*!Wz0T~(DmiKJUe$3PM2phzD``B1)*0PVYs)tNw zcspJ3Pt567)7O}ujTSW%`=0uO?Cj|buPJH&oZ{TiCO-eo?P2oW(nEINu&sA18Rx9`7~O4?&$*#2=j+GSCsQQ?VCPfvIH zH_4;p7cWF^k z(SRP30;EHZwDmo_=S}G9LES)pdC)eXk=Y zthQDvpIl*?Ip|X0+K{%zfpyCc4u@M=ZwWvR>OWX4b6e_xLZQ)|^5#CkA&@ArPttvP zNjAD}JfU;fvva_$&$A)l2rWP;P1q|%xOqD{Ws70`jQF)2pJN` zx$KCag&pi$Em4u=WBz%rUJAQQ_9LFg%M-yiZob~i{EC2cdXO91O+#I zJbGEj&s^vyH0`~&G1}`QnqjmExUgiz$MI)E!-A+nN zVe1Kbe{|@XKv6N?O}v;R{Qt7^Q2C32 b$oV-5&;yQU>y-GefAd#YeXLTdWEuQFonmxS literal 0 HcmV?d00001 diff --git a/assets/share/relics/ui/SALVAGE_CHECK_OFF.SEARCH.png b/assets/share/relics/ui/SALVAGE_CHECK_OFF.SEARCH.png new file mode 100644 index 0000000000000000000000000000000000000000..97c66bd6b81df9ce143a5c5ba22a9e28acf21975 GIT binary patch literal 9365 zcmeHN`8U+x|9_!nRF*7BLXxF~BC=$iMA^mINkZ1KGnOGKAxqh^XB~_^3}el%v1H%( zWr#8MF$_M_`(OC}^gXA0&gAwON!SoFBZ67{ef-o^( zO;OQn4H~|rlKN@kJAbu}Lf9vxa6J==P0lGqrN0jzhdUlUuEVBaNxiT>y1=UpykAx_ z?Ep!g4^O1VIHNRGTD$54DVbH~&fTJ4!8F^PZv%iWDwsFiy;P1wQ33@h0q0?%I}9E3 zXYbKky!ybcFTmVw2JB^uXdR$aNVk&-=)4Y;zWnj#5)caj4lqB(+du&gu(9`C_B=3_ zA2Y=QjAh=;2LTZjKq9~L9ZLCH;FaDxo%@tc&A|6U`P)M0nu;j`4XZ?yDFf@z1D=rv z(RA{!fWSn>``y4T2}%IW!PrA}OO5LLgMr4md~@dy)hZM~6DF=FL3KcssXFfW4X>T8 zxdpC;W`{CG3zoa|*3?V4QxcN78C9@UYQ0wg;0Ce(=c$BTGcwT4JKUfTxJrkXW&V|Dd$bU~KeYOCXB>BXmrmXiTE*4In#X6B# z%sIt}P6RCXX~&0vlgPXM3y;c7?lXsN8-!MC-B#~_)#!YA%GDLOz_1n|vdtNPLLK8p z0~CJLY|^N@Sc!3Hf^Sk#hSM4hcmne9UBS;cE`I^&Z61lh2mlb%NQ{yfpa6OjvKIlM zZuPoJUM!1RI|u-tet&nbRN>;4pG<{Kv?)K?>zY_7EiOEjzjCMP3BBTlrNEn)GOouf zuiIL}STc|wx8kl`+?Guys?Y2(WY|4B^yDz3H+&hA za30SFcLf6)q)+`m_+c~O?U+2x3LYN@VypLSsj_H;XNA0*TpV0!JZ5~fjOH;acWAr5 zE@@oi;)xb{e)+k*%A|^5_RDP90eagMHQx1T$F7+rPLi}}<;*O0^c?0U8N;>Eo>UOG`)ecI+(4dy37N0v0@A3r?%{!t}M z*Amsv8o_m~UBqhJKykzsLbZP1{+s%1<8tDLn&lddTHj{%KhNT;=G_djSrqeTk+m*_-h5s7XvS*F{)xqF zTan4^*6g;WhPyqn_DR<0{)$2O?(WX}Q-x!NT^o^-!zuP@77gQdlcb0bIZ7#QFT%yc zJK`te{V?a_)#C|;-ypIO7-SzZTKIg#Wc~iSivg0h% z0#nr8fxG)JohBY`kTx!DByC*4Ngh}n@EkZE^s#r}WMChWc9-^Zb@%A@ba1X)&z^tO zlHZ!&vZimtW|QHTx+}(#s~U}ANbpQxdFhA-bHuE$yG&`>6(EO3Yn>O;mv2(K3 zc&;Af`$|ey#_FhdjY_s%mNMNZJ)|MG;r6Ud12=pGo(R84N;{T5!kk1MHqOI#u5D|a ze?{?=Vws};-HmrYsO+gY&n2GAxhQr%;(YA|;VZJtidU#<3^`q6piL}0Y(z`ZDVzIA z{mj2Wsmw-fM-RGr)i_43Mt zSG;t0aVOj#DO@r`XBBRy$X5gV7ZZ89avpZ{mwh&P-#1X!JY9A zH7<0ib*xn;bkU6x>yRXxvXrD7?`~PVJe66)va;5TN%MMQC}tS#C-LDMLqfUS^7~tg zTEf>gml00t?2J3X$saV88Zsj?waZY|FP?l|Nrl86NK8xngOA>R)O_aAE=sMbBLMrt z`n868R~_N^A=Mcf1lF`RLCRpI1L zhIrP2PilZE269q_L^X`_PK-28d-?9tzGr8ap25d%)Kv<2>)Y2W`R_XoYz9q7-FVH0 zZd`#+S1WsIwxvb+=J;MbP{OasU3C1BREu~oR^aWp%cltB(F+mqkFW? z3d=wFW^?^~7qwP1dRwMidS(*?Q2U^D6_~()RHH|sV3y-|nT&e;>gTLfb~AS62GkiG z|8UXLqeCo8Kka)ezsxpqDJW(U@dlBWsv##clsE+=sF4!wO|?zyZNPnLaxCtfYAAC; z*X|59%59Bfy`vx1ziFf*DH4l3K(DMMt;&o|LZOYUq%DaTrFmdwd;t}1SfQr*Ht0u>} z!&gnO`dSR>@U+w+X{WJggCX++%H7Jt+|RfpqEb0I*=TOm@4V@anMaf(82f&~A!o34 zHzaoUWZ_t~&wwUxH~xOdSNo#xul}rNq>Ab9zEMp&zZXGu$YT9YNy3ES-D94CbWt+fyk)7PqYeN*JOB{*9sr1E ziekL)N|f#e#`rM`%np&{kw&N^r1=I&KB1dE7UDZc*79HbhrmAs{vq%Wfqw}6L*O3* z{}A}UARuu`=>>UxNVo^yLEZ9yf>B-LDWx=CIO+K$YI@yw#aO9VmDRR-@kPf3t7rA-*8K43J_i9lo zEV4-vQLlXkz;8_R0rHXBO^!9xhce9zkdNH&?*0Y<=b_x$)fTJ5e%a%S2ZCpn>D=R` zKMEX_*FHKXLq>F+if0X36;&{u&!N*9jtQsZxJdFyHjE)eYy1Ghb?y}a%xS4NT4=IL zI8{xENqMiKa$Pa#$19tK_mDy*hl3dVs#r(^K>-Gu|JI9>TB?*?Ze@0K+bMUg^}xxA z)O#F*`A^`k%nR~6mgmXpiPQeJj9#dJ(#2=z`DZQ{y|ci)KKl)2yBpt;W>U2}EXEbg zA2z@cO0Q@t!rI{ive?5OM@i*F`+|fzuAI6~_WEZ%{bf!}U6ddn!DN$`mpwc@czAeB zYdxoj2TZ_Vu&u3avbf{G;9&BIZ94PL^=vRCi~#_e=3noKjglI(pksp%42FUhsWzsU zHJM9Hs^@B~8V`HIp(TRP?_>(4?r2Crw#JA`Tb{W51Qc{8}=}{Hd z48385!e3Pi=s^?|6rh(^l2H!R6Da6xY;0@*S+J3I|M#EoYu(q%Q3-`+^+$LoJKnw-l{m26eR8*KmO&VYc4CxhjbjRGL_vea|^gB_rz^wu<^`a zNvVy9P3KhX#9)r+-qWRdleXVcUF2o(HF#xWY%E=w_jVfXVH3qhAno>r&`&HaG11=i zCbouR5`>{MXDh}|GP~WP(`J<9vc#GHZTTjO_;iMM{T&_TXj&U>ak9RfW=c9JN%s~E zc0OP=uRir<$Y_Z_a-enFO~UXmF)?nKB9wUhbUz{;e&$aQG$@^8V=>j$()vx}akK7&ueGtX zIJMNgkCHiHp?k8`)}M8e=~}PK)A1aeF7 zi9c_&Kozpds?}Mb9O`@*6%OTH%H0>sJ@8IGr18i0;FfWll)V#VM*FPd$btMfW&(lvDt~Go%2y(LojIpmMwyX4q=c4h zX?eM3lGZ<0o(gEXdP~-MeE&P1ROe{C_LZ3}i{8{_e*Es;(B#d-zJ;$vYefSSRkr@) zA1syAr5*)utuprYCJ{P(Ia3ni68m}ijzhe9Ri0{t=KB%xX|i=^kpo^LMqXq1$^y@g zZz5K|Vl-vPk@_XR@S{Ob+yo9T&cm}@E>P^fUWDREmy;6|#Qj1R|LW;c=Z&G0Ih-qq z699v}G!k90v3Da<$$knyg<;i`o=6G^*w0MWw0xv7CLT-<=4uob7f)2XSfZS!Psyl~$huY{-1?kTJlh~arN^VDlMV00(z z#ZHTT>|&==+5ukMbYYt(9+s-$n<4ZI{G_!UF=G7)3J)j2zk0%mbkO?!8f@D7R1O9w zccksK$&t%XSQ|vVou~+?UP+StVN+s^+PwI9dgzBuU$}719X>uRb`Wtkt>5r9Ir*5A zFe|s2;zqveK#-RBpd|)nZ~HSzBof}-clsbKOb-cB(!TC8VQT|lQynPzFD(qUPA*AI z%;xi6tPPph zh^gb`Csyr{qf>l*T%?3Y>mfDc zX-OXFFX|M`I4k1jCaZVjI-GFmbkP)SI()QH{_)LD&M4%{@c_!pKUX+Kq7;VhN6=0) z2eNUVv4tF_s^{!i>K!+{@bvT~Y)(&Nmz6?WHw=FqOcTlS@D0bC%AEdtUz9l{tx@b5 z_(sCa-sjH}kv31Znx<;pkVqsL)Ir1g*G`O8Q7c%iura#ASAj54WDEwav9gYjk2|ST zkS_@(@>r{R?xKho;~AoSSWK5hs|(0B|L*=iO@Qs^#m{??<4YBWteSoIjtVl?alzsO%`sVsUM2X>#m5*#t2h^m=s-A%UscZY^?(Xi$ zR4G%~u%0=Gbd^nCT5T_6bZBUJG=$#H&hB27WB8&(aH-#T`O(o4ad)LB{jqTH1DoCr zNjK{d`t~&cgCf-QL1+TwUu7fxwog61X$7VCpLbLa?Tt*=E)^Tp+pf;Rl~4hMgIYMT zRa7{be&tDnbF==l$7@fp+aDq>rnBuN(kpJ~3UURfnNA{dP&4=sBBG*T(82oe@WVazr}|5onyb9%$1GN5gX*5_nc_7}Ai}Jd`FvnA)YNZ#7X6=bItL?WOA%LYCRr_3kLNe$ zjKHQt(zo(Mu#Gz9H5ZvT&i0dQ_un=-skyp9o~$X@LW496GE?!+kh8u;gt0t5Z;)sl$4bA^X;`m z8&j+u+kFVls7(GuwO;SJcNYVQ7&IFF^!7uaz10+P$scf0f#Bc2f0x<~7a0Dq`9M$J zGEGThY)Z<_$9ew+fzNxBQw=}1XW@b69>-~plPjqbdDvamkyFgjna|Rxamm@t`O&l8 zdbaS#3GsSUejNegYqPcbsJkc=Lr8=Fg#QmkP`X@|zNcsM##B(edD-j9sv0*eFGHyC z70#KZp(@8oMUdk}h3!DYc0EB6G-~E$>hFJI>NO(?Zw_Akc!l_r<}sNu2>Be0t0#+# zd6K=(7gwpDAZUC;adoV0@w>wNbFco|?cp8KEv_Oxh!e7K%B}Z$g{%Mbu9fmy_(A7v z0M=gaWLr!w>F776q~z^D4IXiMvjO*~%JD~lYhMdbGG+p66|h#(XT9XE0^Md>CG)gN zr&?SDkE)dCANM0xn@5tzGqw1S^b=%#v;CKU#f3gyD12x+Qe?`exH?@+Ag4SX9UVo` znNJ71M`dM1;~ljW@3qb^+&xSetw-Ab>2hvT<}YG&B@Ryu!7IoAlDRWek0Ke85ijHjd`~ zXTSv@uw}TIy=bAng7bppeKJW8`e~_&ES{;(@tY4v+K~Qq$qD)R4=iK-=iR8FryWq4 z?GP445XxMxtg32r_%TF-xK{E)Jb^cJHOPhUGsz@9h{7ft<K5GkXV6#mlqV_0OpFgF273+|1$>w8U z34PtaZfF@)9}=;BWZ}r-2DHn8D`>veqD3fGqU_;OmHlY3=4?X;yO&9f;CBH5fs1q; zemh-!A@oOkYohkODFKbxv}H^}6sxH9P@Z-z;XXfqXAdS0PFE5j`M2b-n3iUfeeyZ^ zB;oWyav&QY+dWx>N_ZDEJY1FI_@q1`z8FfPrQu>#1a;B#WX4vkR>RLD(x)0r%}at5 zEZwBw_g-XI?42wgo)Bj7138%Dy-C+e6twTxuZjKUH-GD+UBY;|l`1*)T zap+3ifSh2KI(Z_ zJ+q6!!B>H^nc;7FyfxbH#Y0b~x5CVcg=)Fqsy#^E!6zNg}NKr5tx+#c z0T02k^0E_r$-1D?S7B5@A{mf#Q$vtkxdpH_dJeur-rfNe!j<{&UTCi*i#BU`pg|suqy&PJOj8(? zZGq?RL*m2xqbfRA3&&z@euz*%6w1+PP0N3&8*E1QVl+~4`Un@?l9$Wie#b@r@-u#N! zcjnGo-;!Sd7@v-8VQrR|F%&*MWYvLf?l21gYYe!|9b1V{Q5Txid=EQL2$dl!^A;58 z^~&>HrJ<$W5V9{q-djviJQx4vJ)ZzMB)vVG3fl&JbCq){+Dl?ieeJx0D#1ys0~b{8 zdl6Oz&U#{_PLpnpE=bf^-eG&QWBMAQ$FI{9+5}EjyWW?vz`PdqV23aBlsY|_4uHSX zZGYNuseZtt9kNMAoAp?f8J}d%2>+dU; zpWbn3cT)j?TH*8C)sHS+{>ln(r_cM!)7s8KZg){l`LbZUJfq6RrRb|PMOQK(aT>PE zPF$$3rr;`M%KgRoIg4w?dqelYl;h-P%n(-y|1c=pXMQPoDnuVtk+rZA-Frk(VCTWVyL?TTN} zrY;r)e|X2NCHYKg`NGHd4^(mr%k_s~1wX0E<7MBQYkC$2>4_P{!B`{$bA^VW?5YDF zL`%lL=ejz(5?sXA0-C93Vt5~Cea}L>|Gu=gx)!q^e3|YQT}%(i{wAk8XEd+@;6c%3oWNL{A|SV z+1fa=RNbgfZxKfQll}7;jK`=2CRI5M4hARdjp*ByplnWG{BfYGeHE)-_zF~F=+M~B znRuPO`@ypvQx%M#F$M09d$x|fMeQ+OJBadxJ4h^C+d$R7+zIZK>Xg6YJ48m`T{FM^ za57J8`1&y2aJVRisFG+6#;wAs0#YH34a1_a_8Wd1>>D`jR-jM5a{itC16fa5LLhas zRI`3_Z1Ys$$hzVW2VCeH^+Epu{o2f^#)0R4$pOdu7G`UdPx_t&l~f9+$9)-x?ZFg> z-|pG2h|%qrzdkVyxHPABx|ED+mfS!HZ^k(EiK+QTJgpG~{V+u6H5nEKH9 zp=$|sYv`SOu2b{qmmdLxgS~gA;S=yaeA2_QJof@S)MV=vF){Yz`j^1`>=tGWv?_$a z8S**T^EwK53cd?D7d~E+q)eo2xhQs7kxk_?HJursU%GcY$1eA=gZQ-bo!n8jeyV&n zbM8O)28FeGF-%FXMyTc(A>O6O+G~RiRPpl~9`Oi1SI!)c<4D$9w;z<>UDy9&5a1g? zxPyT&nVmQzlXj9}Z=2+%+#39XoZ)UBU=Ig86cLRmM?4RSJ9@m6#T>vQNWJlTsdJ)J z;q{_F`Km{*c-~U3VP=3soHgi_3(sIl-6+N*ly31u= zIy@}9FQKuzk5R>m#ridk2rc=vm3-rjLzx-5NYy_suXNP|yTz$>!6KoloM}x0dpgEy zm|6J9r0=BY!*_Y_@=CyTu9;s%#_u)WY}9oU5lN?83SIH+=T497CoBmZ`|nM$dBkdu zmV5zM>d~`ni+vIavAALpf&d{w=0C;foX*yd1!!NeM<7$G^$^u{6NnJAoq7JY$1Usv z2?iX&ckf$)n;k=3x6zRUE(5ihr+N#fV542P(COVIa18q6M^%v*CK4I2cYOn1mHXyR z4s3QAjz(KWGyElczRg5eK23SnRA;WB&#Yg!_Q=f)mWz zswDme_xkFpvt zKCSrNh?*3}V%lbc!}sW8c-Z7-x8C7f>qSCL+>wtX54_NuFJ_Xt?75rURvaz;g=2{Z{gemygjC?+S+QVJ;73mydYVhWoWcF7P^reT<>Fko4(`G^4A-4r4iwa zdcTW?zfFG|n#+l5JfOmXLPgNBZGmvn63;?~BIMTZw3+Ko1ZzP;JiWUK8~ zpM8FU{ghDSlM01O1r3PL=`T=~g*WaQVPL~VzA|862PZeW^&{$!Tl<**_|f=XtM{SE zt!_MbqnGf^RfJIU!BNoR21hW>ruMW|SaL`e5rsWnzx0P;J?hI@&9ipT`6JtQ+mUZ( z3|sWnaRq1Z&VR)HLTe0aj0varL@!07S z0O0UWv*}U?0LCRvwMT{_Sp3X@x1}@ZrFp{OQRc+r6FhctdSg0QRtNjt!u$=@V=Ap! zEagJ;Bm1v3oxD;+GB*23IyfV%K1@&0+(;P;b}5(e%uVao$xGnr$(nEock&ns!GE(y z8}l=R`RzE@LO%#3T1Wb`D-ErbZOQrblScV3{Uh*?z&`^22>c`PkH9|y{|Nja6F8cC zqDFEFhfW_VNGp9j5b1MDJH(Vm5LTW?RDMP_)qlK>zA0A4`X=MacmhjZ!rt<_c`k&Q z0ev&B{<3ewjgfS7Sq(wQFa0>2%5jGfL8wT72ZOZZZS>FIzjyH+_G%t$6Vn*%Zm$Be z-dt9)F<|!_Or^$ek3MJzVE~Z>fc8Iqp4>zP*^QVfET2-IO{MYNLvg8y(Arr&t_PZG z;3wnjCrH)sleoi`DXh75xHqw1%~ulHL~D7qj$+Vr;0LykC z)H0O>DV73syrYl%NhJ#NE45F04$0~|JvOt`>7a4AxjEug$K?AbCc!oGT>5o=ef{z} z7FJi1kdbl1u$f(8!^LUC$WKGsKv(Ywohm>{!SJDELU#u<;t^3UBL=$i*?mqQxMKnHucajey+{XZ!=gyJ zIY@9w5X3bcRZ`}^R}b4o6XExotT>rS$Z*2rSVWx|;p}*)YuQbsaszgQH`nIo`Fe0w zl4U+3(AU*>ZINMssiqdp{XTbY_6MdJrk^%Vrcp=+L?4Jx%+01GeqM}?mx17C1=ERV zBT?@yZc0lzTA1f1@ySK}Zm*1&30&#uBfL8QvyxNV-K`_4BZeZ52)-t@2kpeW24%p0XNIfAaPu4g-h_s5Qt-!!%$N55y}dq1ul{bloWVGyTC&H%`JXRI~ciD+}>hO(sc8YKLg#2 z?43-JV^OHkYjV;xuZN3h;^dl&tEZ>u(t76zqN=cqI_J~8FTv5B{R*gJvZmJ(0jCSgrhTL7?Cg=U-K zd+Qy=`w}N($HwZbu0|Cqp7+4~8}FVu9t~#k>7*@n<5i^6k{U8qVEq5<)S}peh^m%O zb3~b<)cSckK1DR(&&AF4%6r zvyWj`K5%m(12>jouC{*=06AG3srqS5QlVPC`BY;|umuXYuOYqSrA^C1N&0&+(M}m+ zu)29RofOfN;a=B;29refeWoRj9-mu~BQ}_I=HQEJ#L4OM&HY60_v6aMl64yDrJ@d> zD=aUMiE}vLrlqti1}Ff4+r%Jz+|bU|#rBD+u(+&#cI*8tHT)Fv09B+w@>XtWBJ4f* zxU-0&1w}{{i(L6W>mjvQ*4BEu*{06FP$bZ@g-r`T_*wr^tHRtcT0fekVLJH3@p?HC+R1=A83Qenka$~1Y^>L>fzliZ z4AXUG=ZS*8Z}QA=bg$^0d!a-LepuEO zN>V0G+XQ9ENkO~>T9;c>IL*?1v7rESwuz~1C>^%+mr7^V%7AsCKjOO3=zhx@KmSGP m3L8zqzu)oy*Tns!?Gg|I4l(FCnqT-Egy!R?YLzOsFa870*WW$> literal 0 HcmV?d00001 diff --git a/assets/share/relics/ui/SALVAGE_CHECK_ON.SEARCH.png b/assets/share/relics/ui/SALVAGE_CHECK_ON.SEARCH.png new file mode 100644 index 0000000000000000000000000000000000000000..97c66bd6b81df9ce143a5c5ba22a9e28acf21975 GIT binary patch literal 9365 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 W%ntVH$!Px`LQ`E&tyabE+5Z63=C~pN literal 0 HcmV?d00001 diff --git a/assets/share/relics/ui/SALVAGE_FILTER.png b/assets/share/relics/ui/SALVAGE_FILTER.png new file mode 100644 index 0000000000000000000000000000000000000000..f2cc65104d62e10ed7762f2022b3d9945a41e1b9 GIT binary patch literal 6307 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 literal 0 HcmV?d00001 diff --git a/tasks/relics/assets/assets_relics_ui.py b/tasks/relics/assets/assets_relics_ui.py new file mode 100644 index 000000000..04640dc9a --- /dev/null +++ b/tasks/relics/assets/assets_relics_ui.py @@ -0,0 +1,106 @@ +from module.base.button import Button, ButtonWrapper + +# This file was auto-generated, do not modify it manually. To generate: +# ``` python -m dev_tools.button_extract ``` + +ENHANCE_CHECK = ButtonWrapper( + name='ENHANCE_CHECK', + cn=Button( + file='./assets/cn/relics/ui/ENHANCE_CHECK.png', + area=(1134, 645, 1185, 670), + search=(1114, 625, 1205, 690), + color=(179, 180, 180), + button=(1134, 645, 1185, 670), + ), + en=Button( + file='./assets/en/relics/ui/ENHANCE_CHECK.png', + area=(1115, 646, 1204, 671), + search=(1095, 626, 1224, 691), + color=(183, 184, 184), + button=(1115, 646, 1204, 671), + ), +) +ENHANCE_FILTER = ButtonWrapper( + name='ENHANCE_FILTER', + share=Button( + file='./assets/share/relics/ui/ENHANCE_FILTER.png', + area=(159, 650, 185, 676), + search=(139, 630, 205, 696), + color=(193, 195, 196), + button=(159, 650, 185, 676), + ), +) +ENHANCE_GOTO_SALVAGE = ButtonWrapper( + name='ENHANCE_GOTO_SALVAGE', + share=Button( + file='./assets/share/relics/ui/ENHANCE_GOTO_SALVAGE.png', + area=(685, 653, 705, 673), + search=(665, 633, 725, 693), + color=(140, 142, 143), + button=(685, 653, 705, 673), + ), +) +FILTER_CONFIRM = ButtonWrapper( + name='FILTER_CONFIRM', + cn=Button( + file='./assets/cn/relics/ui/FILTER_CONFIRM.png', + area=(1103, 651, 1151, 677), + search=(1083, 631, 1171, 697), + color=(180, 180, 180), + button=(1103, 651, 1151, 677), + ), + en=Button( + file='./assets/en/relics/ui/FILTER_CONFIRM.png', + area=(1081, 652, 1172, 677), + search=(1061, 632, 1192, 697), + color=(189, 189, 189), + button=(1081, 652, 1172, 677), + ), +) +FILTER_RESET = ButtonWrapper( + name='FILTER_RESET', + cn=Button( + file='./assets/cn/relics/ui/FILTER_RESET.png', + area=(887, 652, 936, 675), + search=(867, 632, 956, 695), + color=(160, 160, 160), + button=(887, 652, 936, 675), + ), + en=Button( + file='./assets/en/relics/ui/FILTER_RESET.png', + area=(879, 652, 946, 677), + search=(859, 632, 966, 697), + color=(185, 185, 185), + button=(879, 652, 946, 677), + ), +) +SALVAGE_CHECK_OFF = ButtonWrapper( + name='SALVAGE_CHECK_OFF', + share=Button( + file='./assets/share/relics/ui/SALVAGE_CHECK_OFF.png', + area=(1067, 646, 1091, 670), + search=(1002, 641, 1143, 675), + color=(54, 55, 48), + button=(1067, 646, 1091, 670), + ), +) +SALVAGE_CHECK_ON = ButtonWrapper( + name='SALVAGE_CHECK_ON', + share=Button( + file='./assets/share/relics/ui/SALVAGE_CHECK_ON.png', + area=(1067, 646, 1091, 670), + search=(1002, 641, 1143, 675), + color=(124, 116, 99), + button=(1067, 646, 1091, 670), + ), +) +SALVAGE_FILTER = ButtonWrapper( + name='SALVAGE_FILTER', + share=Button( + file='./assets/share/relics/ui/SALVAGE_FILTER.png', + area=(441, 645, 467, 671), + search=(421, 625, 487, 691), + color=(193, 194, 195), + button=(441, 645, 467, 671), + ), +) diff --git a/tasks/relics/ui.py b/tasks/relics/ui.py new file mode 100644 index 000000000..7710def06 --- /dev/null +++ b/tasks/relics/ui.py @@ -0,0 +1,257 @@ +from module.logger import logger +from tasks.base.assets.assets_base_page import CLOSE +from tasks.base.page import page_item +from tasks.item.keywords import KEYWORDS_ITEM_TAB +from tasks.item.ui import ItemUI +from tasks.relics.assets.assets_relics_ui import * + + +class RelicsUI(ItemUI): + def is_in_relics_enhance(self, interval=0): + if self.appear(ENHANCE_CHECK, interval=interval): + return True + return False + + def is_in_relics_salvage(self, interval=0): + if self.appear(SALVAGE_CHECK_OFF, interval=interval): + return True + if self.appear(SALVAGE_CHECK_ON, interval=interval): + return True + return False + + def is_filter_active(self, button, interval=0) -> bool: + """ + Args: + button: ENHANCE_FILTER or SALVAGE_FILTER + interval: + + Returns: + bool: + """ + self.device.stuck_record_add(button) + + if interval and not self.interval_is_reached(button, interval=interval): + return False + + appear = self.image_color_count(button, color=(242, 158, 56), threshold=180, count=20) + + if appear and interval: + self.interval_reset(button, interval=interval) + + return appear + + def is_filter_appear(self, button, interval=0) -> bool: + if self.appear(button, interval=interval): + return True + if self.is_filter_active(button, interval=interval): + return True + return False + + def is_filter_opened(self, interval=0) -> bool: + return self.appear(FILTER_CONFIRM, interval=interval) + + def handle_filter_confirm(self, button, interval=2) -> bool: + """ + Confirm filter aside + + Args: + button: ENHANCE_FILTER or SALVAGE_FILTER + interval: + + Returns: + bool: If clicked + """ + if self.appear(button): + if self.appear_then_click(FILTER_CONFIRM, interval=interval): + self.interval_clear(FILTER_RESET) + return True + return False + + def handle_filter_reset(self, button, interval=2): + """ + Reset filter aside + + Args: + button: ENHANCE_FILTER or SALVAGE_FILTER + interval: + + Returns: + bool: If clicked + """ + if self.is_filter_active(button): + if self.appear_then_click(FILTER_RESET, interval=interval): + self.interval_clear(FILTER_CONFIRM) + return True + return False + + def handle_filter_close(self, opened=None, interval=2): + """ + Args: + opened: ENHANCE_FILTER or SALVAGE_FILTER + Keep this filter opened + interval: + + Returns: + bool: If clicked + """ + # If filter opened, reset it + if self.handle_filter_reset(SALVAGE_FILTER, interval=interval): + self.interval_reset([SALVAGE_FILTER], interval=interval) + return True + if self.handle_filter_reset(ENHANCE_FILTER, interval=interval): + self.interval_reset([ENHANCE_FILTER], interval=interval) + return True + # If filter opened, close it + if opened != SALVAGE_FILTER: + if self.handle_filter_confirm(SALVAGE_FILTER, interval=interval): + self.interval_clear([FILTER_CONFIRM, SALVAGE_CHECK_OFF, SALVAGE_CHECK_ON], interval=interval) + return True + if opened != ENHANCE_FILTER: + if self.handle_filter_confirm(ENHANCE_FILTER, interval=interval): + self.interval_clear([FILTER_CONFIRM, ENHANCE_CHECK], interval=interval) + return True + # If filter activated, open it + if self.is_filter_active(SALVAGE_FILTER, interval=interval): + logger.info(f'is_filter_active -> {SALVAGE_FILTER}') + self.device.click(SALVAGE_FILTER) + self.interval_reset([FILTER_CONFIRM, SALVAGE_CHECK_OFF, SALVAGE_CHECK_ON], interval=interval) + return True + if self.is_filter_active(ENHANCE_FILTER, interval=interval): + logger.info(f'is_filter_active -> {ENHANCE_FILTER}') + self.device.click(ENHANCE_FILTER) + self.interval_reset([FILTER_CONFIRM, ENHANCE_CHECK], interval=interval) + return True + return False + + def relics_goto_salvage_filter(self, skip_first_screenshot=True): + """ + Pages: + in: page_item, any subpage of relics + out: salvage filter, with filter reset + """ + logger.info('Relics goto salvage filter') + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if self.is_filter_opened() and self.appear(SALVAGE_FILTER): + logger.info('Arrive SALVAGE_FILTER') + break + + # Close filter + if self.handle_filter_close(opened=SALVAGE_FILTER): + continue + # Open filter + if not self.is_filter_opened(): + # if self.is_filter_appear(ENHANCE_FILTER, interval=2): + # self.device.click(ENHANCE_FILTER) + # continue + if self.is_filter_appear(SALVAGE_FILTER, interval=2): + self.device.click(SALVAGE_FILTER) + continue + # UI switch + if self.is_in_relics_enhance(interval=2): + self.device.click(ENHANCE_GOTO_SALVAGE) + continue + # if self.is_in_relics_salvage(interval=2): + # logger.info(f'is_in_relics_salvage -> {CLOSE}') + # self.device.click(CLOSE) + # continue + + def relics_goto_salvage(self, skip_first_screenshot=True): + """ + Pages: + in: page_item, any subpage of relics + out: salvage, with filter reset + """ + logger.info('Relics goto salvage') + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if self.is_in_relics_salvage() and self.appear(SALVAGE_FILTER): + logger.info('Arrive is_in_relics_salvage') + break + + # Close filter + if self.handle_filter_close(): + continue + # UI switch + if self.is_in_relics_enhance(interval=2): + self.device.click(ENHANCE_GOTO_SALVAGE) + continue + + def relics_goto_enhance_filter(self, skip_first_screenshot=True): + """ + Pages: + in: page_item, any subpage of relics + out: enhance filter, with filter reset + """ + logger.info('Relics goto enhance filter') + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if self.is_filter_opened() and self.appear(ENHANCE_FILTER): + logger.info('Arrive ENHANCE_FILTER') + break + + # Close filter + if self.handle_filter_close(opened=ENHANCE_FILTER): + continue + # Open filter + if not self.is_filter_opened(): + if self.is_filter_appear(ENHANCE_FILTER, interval=2): + self.device.click(ENHANCE_FILTER) + continue + # UI switch + if self.is_in_relics_salvage(interval=2): + logger.info(f'is_in_relics_salvage -> {CLOSE}') + self.device.click(CLOSE) + continue + + def relics_goto_enhance(self, skip_first_screenshot=True): + """ + Pages: + in: page_item, any subpage of relics + out: enhance, with filter reset + """ + logger.info('Relics goto enhance') + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if self.is_in_relics_enhance() and self.appear(ENHANCE_FILTER): + logger.info('Arrive is_in_relics_enhance') + break + + # Close filter + if self.handle_filter_close(): + continue + # UI switch + if self.is_in_relics_salvage(interval=2): + logger.info(f'is_in_relics_salvage -> {CLOSE}') + self.device.click(CLOSE) + continue + + def ui_goto_relics(self): + self.ui_ensure(page_item) + self.item_goto(KEYWORDS_ITEM_TAB.Relics, wait_until_stable=False) + + +if __name__ == '__main__': + self = RelicsUI('src') + self.device.screenshot() + self.relics_goto_salvage_filter() From 694cb51b5fc4b77e3edadaf268e1242d4dcbb42e Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 1 Jul 2024 00:01:50 +0800 Subject: [PATCH 02/27] Fix: [EN] "I" prefix in RadiantFeldspar --- tasks/base/main_page.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/base/main_page.py b/tasks/base/main_page.py index 1238ee9ed..2638165d9 100644 --- a/tasks/base/main_page.py +++ b/tasks/base/main_page.py @@ -55,6 +55,8 @@ class OcrPlaneName(OcrWhiteLetterOnComplexBackground): if '星港' in result: result = '迴星港' result = result.replace('太司', '太卜司') + # IRadiantFeldspar + result = re.sub('[Ii1|]\s*Radiant', 'Radiant', result) result = result.replace(' ', '') From f478058cb9ddbc3a2abe22a097dc34685f93deda Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 1 Jul 2024 00:09:19 +0800 Subject: [PATCH 03/27] Fix: Enlarge search area of SURVIVAL_INDEX_OE_LOADED so it can be detected during double rogue event --- .../SURVIVAL_INDEX_OE_LOADED.SEARCH.png | Bin 0 -> 11562 bytes tasks/dungeon/assets/assets_dungeon_ui_rogue.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 assets/share/dungeon/ui_rogue/SURVIVAL_INDEX_OE_LOADED.SEARCH.png diff --git a/assets/share/dungeon/ui_rogue/SURVIVAL_INDEX_OE_LOADED.SEARCH.png b/assets/share/dungeon/ui_rogue/SURVIVAL_INDEX_OE_LOADED.SEARCH.png new file mode 100644 index 0000000000000000000000000000000000000000..82948de991ee8c1d8e531b1d719be109f7ccc77e GIT binary patch literal 11562 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 Date: Mon, 1 Jul 2024 00:38:37 +0800 Subject: [PATCH 04/27] Add: dungeon_goto Ornament_Extraction --- dev_tools/keywords/dungeon_list.py | 15 ++- tasks/dungeon/keywords/classes.py | 7 ++ tasks/dungeon/keywords/dungeon.py | 144 ++++++++++++++--------------- tasks/dungeon/ui.py | 3 +- 4 files changed, 95 insertions(+), 74 deletions(-) diff --git a/dev_tools/keywords/dungeon_list.py b/dev_tools/keywords/dungeon_list.py index 10f362a87..deb90ce2e 100644 --- a/dev_tools/keywords/dungeon_list.py +++ b/dev_tools/keywords/dungeon_list.py @@ -91,6 +91,8 @@ class GenerateDungeonList(GenerateKeyword): def iter_rows(self) -> t.Iterable[dict]: dungeons = list(super().iter_rows()) + + # Sort by path calyx = [] order = [ 'Calyx_Golden', @@ -108,9 +110,20 @@ class GenerateDungeonList(GenerateKeyword): dungeons = [d for d in dungeons if not condition(d)] dungeons = calyx + dungeons + # Reverse Divergent_Universe + start = 0 + end = 0 + for index, dungeon in enumerate(dungeons): + if dungeon['name'].startswith('Divergent_Universe'): + if start == 0: + start = index + end = index + 1 + if start > 0 and end > 0: + dungeons = dungeons[:start] + dungeons[start:end][::-1] + dungeons[end:] + + # Re-sort ID self.keyword_index = 0 for row in dungeons: - # Re-sort ID self.keyword_index += 1 row['id'] = self.keyword_index yield row diff --git a/tasks/dungeon/keywords/classes.py b/tasks/dungeon/keywords/classes.py index d9c504aa2..40c3b9891 100644 --- a/tasks/dungeon/keywords/classes.py +++ b/tasks/dungeon/keywords/classes.py @@ -117,6 +117,11 @@ class DungeonList(Keyword): def is_Simulated_Universe(self): return 'Simulated_Universe' in self.name + @cached_property + def is_Ornament_Extraction(self): + # Farm Ornament_Extraction from Ornament_Extraction_xxx + return 'Divergent_Universe' in self.name + @cached_property def is_Forgotten_Hall(self): for word in [ @@ -151,6 +156,8 @@ class DungeonList(Keyword): import tasks.dungeon.keywords.nav as KEYWORDS_DUNGEON_NAV if self.is_Simulated_Universe: return KEYWORDS_DUNGEON_NAV.Simulated_Universe + if self.is_Ornament_Extraction: + return KEYWORDS_DUNGEON_NAV.Ornament_Extraction if self.is_Calyx_Golden: return KEYWORDS_DUNGEON_NAV.Calyx_Golden if self.is_Calyx_Crimson: diff --git a/tasks/dungeon/keywords/dungeon.py b/tasks/dungeon/keywords/dungeon.py index 7552d1450..12540eecf 100644 --- a/tasks/dungeon/keywords/dungeon.py +++ b/tasks/dungeon/keywords/dungeon.py @@ -707,74 +707,19 @@ Simulated_Universe_World_9 = DungeonList( dungeon_id=190, plane_id=100000104, ) -Divergent_Universe_Untoppled_Walls = DungeonList( +Divergent_Universe_Eternal_Comedy = DungeonList( id=65, - name='Divergent_Universe_Untoppled_Walls', - cn='坚城不倒•差分宇宙', - cht='堅城不倒•差分宇宙', - en='Divergent Universe: Untoppled Walls', - jp='階差宇宙・不動の砦', - es='Muros inquebrantables: Universo Diferenciado', - dungeon_id=230, - plane_id=0, -) -Divergent_Universe_Smelted_Heart = DungeonList( - id=66, - name='Divergent_Universe_Smelted_Heart', - cn='浴火钢心•差分宇宙', - cht='浴火鋼心•差分宇宙', - en='Divergent Universe: Smelted Heart', - jp='階差宇宙・鋼の意志', - es='Corazón de fundición: Universo Diferenciado', - dungeon_id=240, - plane_id=0, -) -Divergent_Universe_Gentle_Words = DungeonList( - id=67, - name='Divergent_Universe_Gentle_Words', - cn='温柔话语•差分宇宙', - cht='溫柔話語•差分宇宙', - en='Divergent Universe: Gentle Words', - jp='階差宇宙・優しい言葉', - es='Palabras amables: Universo Diferenciado', - dungeon_id=250, - plane_id=0, -) -Divergent_Universe_Permafrost = DungeonList( - id=68, - name='Divergent_Universe_Permafrost', - cn='百年冻土•差分宇宙', - cht='百年凍土•差分宇宙', - en='Divergent Universe: Permafrost', - jp='階差宇宙・永久凍土', - es='Permafrost: Universo Diferenciado', - dungeon_id=260, - plane_id=0, -) -Divergent_Universe_Fruit_of_Evil = DungeonList( - id=69, - name='Divergent_Universe_Fruit_of_Evil', - cn='孽果盘生•差分宇宙', - cht='孽果盤生•差分宇宙', - en='Divergent Universe: Fruit of Evil', - jp='階差宇宙・渦巻く罪', - es='Fruta del desastre: Universo Diferenciado', - dungeon_id=270, - plane_id=0, -) -Divergent_Universe_Pouring_Blades = DungeonList( - id=70, - name='Divergent_Universe_Pouring_Blades', - cn='天剑如雨•差分宇宙', - cht='天劍如雨•差分宇宙', - en='Divergent Universe: Pouring Blades', - jp='階差宇宙・剣の雨', - es='Lluvia de espadas: Universo Diferenciado', - dungeon_id=280, + name='Divergent_Universe_Eternal_Comedy', + cn='永恒笑剧•差分宇宙', + cht='永恆笑劇•差分宇宙', + en='Divergent Universe: Eternal Comedy', + jp='階差宇宙・永遠の喜劇', + es='Universo Diferenciado: Comedia eterna', + dungeon_id=300, plane_id=0, ) Divergent_Universe_To_Sweet_Dreams = DungeonList( - id=71, + id=66, name='Divergent_Universe_To_Sweet_Dreams', cn='伴你入眠•差分宇宙', cht='伴你入眠•差分宇宙', @@ -784,15 +729,70 @@ Divergent_Universe_To_Sweet_Dreams = DungeonList( dungeon_id=290, plane_id=0, ) -Divergent_Universe_Eternal_Comedy = DungeonList( +Divergent_Universe_Pouring_Blades = DungeonList( + id=67, + name='Divergent_Universe_Pouring_Blades', + cn='天剑如雨•差分宇宙', + cht='天劍如雨•差分宇宙', + en='Divergent Universe: Pouring Blades', + jp='階差宇宙・剣の雨', + es='Lluvia de espadas: Universo Diferenciado', + dungeon_id=280, + plane_id=0, +) +Divergent_Universe_Fruit_of_Evil = DungeonList( + id=68, + name='Divergent_Universe_Fruit_of_Evil', + cn='孽果盘生•差分宇宙', + cht='孽果盤生•差分宇宙', + en='Divergent Universe: Fruit of Evil', + jp='階差宇宙・渦巻く罪', + es='Fruta del desastre: Universo Diferenciado', + dungeon_id=270, + plane_id=0, +) +Divergent_Universe_Permafrost = DungeonList( + id=69, + name='Divergent_Universe_Permafrost', + cn='百年冻土•差分宇宙', + cht='百年凍土•差分宇宙', + en='Divergent Universe: Permafrost', + jp='階差宇宙・永久凍土', + es='Permafrost: Universo Diferenciado', + dungeon_id=260, + plane_id=0, +) +Divergent_Universe_Gentle_Words = DungeonList( + id=70, + name='Divergent_Universe_Gentle_Words', + cn='温柔话语•差分宇宙', + cht='溫柔話語•差分宇宙', + en='Divergent Universe: Gentle Words', + jp='階差宇宙・優しい言葉', + es='Palabras amables: Universo Diferenciado', + dungeon_id=250, + plane_id=0, +) +Divergent_Universe_Smelted_Heart = DungeonList( + id=71, + name='Divergent_Universe_Smelted_Heart', + cn='浴火钢心•差分宇宙', + cht='浴火鋼心•差分宇宙', + en='Divergent Universe: Smelted Heart', + jp='階差宇宙・鋼の意志', + es='Corazón de fundición: Universo Diferenciado', + dungeon_id=240, + plane_id=0, +) +Divergent_Universe_Untoppled_Walls = DungeonList( id=72, - name='Divergent_Universe_Eternal_Comedy', - cn='永恒笑剧•差分宇宙', - cht='永恆笑劇•差分宇宙', - en='Divergent Universe: Eternal Comedy', - jp='階差宇宙・永遠の喜劇', - es='Universo Diferenciado: Comedia eterna', - dungeon_id=300, + name='Divergent_Universe_Untoppled_Walls', + cn='坚城不倒•差分宇宙', + cht='堅城不倒•差分宇宙', + en='Divergent Universe: Untoppled Walls', + jp='階差宇宙・不動の砦', + es='Muros inquebrantables: Universo Diferenciado', + dungeon_id=230, plane_id=0, ) Simulated_Universe_The_Swarm_Disaster = DungeonList( diff --git a/tasks/dungeon/ui.py b/tasks/dungeon/ui.py index f1a4d3279..8caa5d512 100644 --- a/tasks/dungeon/ui.py +++ b/tasks/dungeon/ui.py @@ -732,7 +732,8 @@ class DungeonUI(DungeonState): if dungeon.is_Calyx_Crimson \ or dungeon.is_Stagnant_Shadow \ or dungeon.is_Cavern_of_Corrosion \ - or dungeon.is_Echo_of_War: + or dungeon.is_Echo_of_War \ + or dungeon.is_Ornament_Extraction: self._dungeon_nav_goto(dungeon.dungeon_nav) self._dungeon_wait_until_dungeon_list_loaded() self._dungeon_insight(dungeon) From 85ac47d6b63c1c715c67cc9efea1d3843ea898f0 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 1 Jul 2024 02:17:43 +0800 Subject: [PATCH 05/27] Add: Combat preparation in ornament --- .../share/combat/support/FIRST_CHARACTER.png | Bin 0 -> 5587 bytes .../combat/CHARACTER_EMPTY_OE.SEARCH.png | Bin 0 -> 30016 bytes .../ornament/combat/CHARACTER_EMPTY_OE.png | Bin 0 -> 6256 bytes .../combat/OCR_DOUBLE_EVENT_REMAIN_AT_OE.png | Bin 0 -> 37710 bytes assets/share/ornament/combat/SUPPORT_ADD.png | Bin 0 -> 6892 bytes .../share/ornament/combat/SUPPORT_DISMISS.png | Bin 0 -> 6623 bytes tasks/combat/assets/assets_combat_support.py | 10 ++ tasks/combat/support.py | 24 ++- tasks/dungeon/dungeon.py | 8 + tasks/dungeon/event.py | 12 +- .../ornament/assets/assets_ornament_combat.py | 45 ++++++ tasks/ornament/combat.py | 142 ++++++++++++++++++ 12 files changed, 233 insertions(+), 8 deletions(-) create mode 100644 assets/share/combat/support/FIRST_CHARACTER.png create mode 100644 assets/share/ornament/combat/CHARACTER_EMPTY_OE.SEARCH.png create mode 100644 assets/share/ornament/combat/CHARACTER_EMPTY_OE.png create mode 100644 assets/share/ornament/combat/OCR_DOUBLE_EVENT_REMAIN_AT_OE.png create mode 100644 assets/share/ornament/combat/SUPPORT_ADD.png create mode 100644 assets/share/ornament/combat/SUPPORT_DISMISS.png create mode 100644 tasks/ornament/assets/assets_ornament_combat.py create mode 100644 tasks/ornament/combat.py diff --git a/assets/share/combat/support/FIRST_CHARACTER.png b/assets/share/combat/support/FIRST_CHARACTER.png new file mode 100644 index 0000000000000000000000000000000000000000..5fdf9e2cac1d22b9b062b2ea52d96b9a02f70bda GIT binary patch literal 5587 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 V6i;C(8vY{zeO=@8725U@{{e^GbIt$& literal 0 HcmV?d00001 diff --git a/assets/share/ornament/combat/CHARACTER_EMPTY_OE.SEARCH.png b/assets/share/ornament/combat/CHARACTER_EMPTY_OE.SEARCH.png new file mode 100644 index 0000000000000000000000000000000000000000..d629ad01991765b864558f712acc7accc7764b55 GIT binary patch literal 30016 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 literal 0 HcmV?d00001 diff --git a/assets/share/ornament/combat/OCR_DOUBLE_EVENT_REMAIN_AT_OE.png b/assets/share/ornament/combat/OCR_DOUBLE_EVENT_REMAIN_AT_OE.png new file mode 100644 index 0000000000000000000000000000000000000000..67c2919154730eeb652cda63406d539ac88a4a9c GIT binary patch literal 37710 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

LCcZ}|`)5mPoZUBxXERd0wL1H*zEto~sK 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�ttqc(!qI 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

-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 Ag8%>k literal 0 HcmV?d00001 diff --git a/assets/share/ornament/combat/SUPPORT_ADD.png b/assets/share/ornament/combat/SUPPORT_ADD.png new file mode 100644 index 0000000000000000000000000000000000000000..fd190786afe74243ce2a9c217c00ebe1b756371d GIT binary patch literal 6892 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 literal 0 HcmV?d00001 diff --git a/assets/share/ornament/combat/SUPPORT_DISMISS.png b/assets/share/ornament/combat/SUPPORT_DISMISS.png new file mode 100644 index 0000000000000000000000000000000000000000..587a43ef0cea7c796a24da06c4f6f527d71175f3 GIT binary patch literal 6623 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 0: + rogue = self.get_double_event_remain_at_combat() + if rogue is not None and rogue < self.config.stored.DungeonDouble.rogue: + self.config.stored.DungeonDouble.rogue = rogue + wave_limit = rogue + if rogue == 0: + return 0 # Combat self.dungeon = dungeon count = self.combat(team=team, wave_limit=wave_limit, support_character=support_character) diff --git a/tasks/dungeon/event.py b/tasks/dungeon/event.py index aad0108ae..300a2aae3 100644 --- a/tasks/dungeon/event.py +++ b/tasks/dungeon/event.py @@ -61,19 +61,19 @@ class DungeonEvent(UI): logger.attr('Double rogue', has) return has - def has_double_event_at_combat(self) -> bool: + def has_double_event_at_combat(self, button=OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT) -> bool: """ Pages: in: COMBAT_PREPARE """ has = self.image_color_count( - OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT, + button, color=(231, 188, 103), threshold=240, count=1000 ) # Anniversary 3x event has |= self.image_color_count( - OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT, + button, color=(229, 62, 44), threshold=221, count=50 ) @@ -109,16 +109,16 @@ class DungeonEvent(UI): logger.attr('Double event remain', remain) return remain - def get_double_event_remain_at_combat(self) -> int | None: + def get_double_event_remain_at_combat(self, button=OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT) -> int | None: """ Pages: in: COMBAT_PREPARE """ - if not self.has_double_event_at_combat(): + if not self.has_double_event_at_combat(button=button): logger.attr('Double event remain at combat', 0) return 0 - ocr = DoubleEventOcr(OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT) + ocr = DoubleEventOcr(button) for row in ocr.detect_and_ocr(self.device.image): if not ocr.is_format_matched(row.ocr_text): continue diff --git a/tasks/ornament/assets/assets_ornament_combat.py b/tasks/ornament/assets/assets_ornament_combat.py new file mode 100644 index 000000000..4779e6b17 --- /dev/null +++ b/tasks/ornament/assets/assets_ornament_combat.py @@ -0,0 +1,45 @@ +from module.base.button import Button, ButtonWrapper + +# This file was auto-generated, do not modify it manually. To generate: +# ``` python -m dev_tools.button_extract ``` + +CHARACTER_EMPTY_OE = ButtonWrapper( + name='CHARACTER_EMPTY_OE', + share=Button( + file='./assets/share/ornament/combat/CHARACTER_EMPTY_OE.png', + area=(549, 513, 559, 537), + search=(525, 498, 824, 554), + color=(112, 112, 112), + button=(549, 513, 559, 537), + ), +) +OCR_DOUBLE_EVENT_REMAIN_AT_OE = ButtonWrapper( + name='OCR_DOUBLE_EVENT_REMAIN_AT_OE', + share=Button( + file='./assets/share/ornament/combat/OCR_DOUBLE_EVENT_REMAIN_AT_OE.png', + area=(812, 577, 1248, 631), + search=(792, 557, 1268, 651), + color=(124, 103, 61), + button=(812, 577, 1248, 631), + ), +) +SUPPORT_ADD = ButtonWrapper( + name='SUPPORT_ADD', + share=Button( + file='./assets/share/ornament/combat/SUPPORT_ADD.png', + area=(848, 518, 876, 537), + search=(828, 498, 896, 557), + color=(167, 200, 176), + button=(848, 518, 876, 537), + ), +) +SUPPORT_DISMISS = ButtonWrapper( + name='SUPPORT_DISMISS', + share=Button( + file='./assets/share/ornament/combat/SUPPORT_DISMISS.png', + area=(853, 513, 872, 538), + search=(833, 493, 892, 558), + color=(135, 135, 135), + button=(853, 513, 872, 538), + ), +) diff --git a/tasks/ornament/combat.py b/tasks/ornament/combat.py new file mode 100644 index 000000000..13a05c65d --- /dev/null +++ b/tasks/ornament/combat.py @@ -0,0 +1,142 @@ +from module.base.decorator import run_once +from module.exception import RequestHumanTakeover +from module.logger import logger +from tasks.base.assets.assets_base_popup import POPUP_CANCEL +from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE +from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_LIST +from tasks.combat.combat import Combat +from tasks.dungeon.event import DungeonEvent +from tasks.ornament.assets.assets_ornament_combat import * + + +class OrnamentCombat(DungeonEvent, Combat): + def combat_enter_from_map(self, skip_first_screenshot=True): + # Don't enter from map, UI too deep inside + # Enter from survival index instead + pass + + def get_double_event_remain_at_combat(self, button=OCR_DOUBLE_EVENT_REMAIN_AT_OE): + # Different position to OCR + return super().get_double_event_remain_at_combat(button) + + def support_set(self, support_character_name: str = "FirstCharacter"): + """ + Args: + support_character_name: Support character name + + Returns: + bool: If clicked + + Pages: + in: COMBAT_PREPARE + mid: COMBAT_SUPPORT_LIST + out: COMBAT_PREPARE + """ + logger.hr("Combat support") + self.interval_clear(SUPPORT_ADD) + skip_first_screenshot = True + selected_support = False + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if self.appear(SUPPORT_DISMISS): + return True + + # Click + if self.appear(SUPPORT_ADD, interval=2): + self.device.click(SUPPORT_ADD) + self.interval_reset(SUPPORT_ADD) + continue + if self.appear(POPUP_CANCEL, interval=1): + logger.warning( + "selected identical character, trying select another") + self._cancel_popup() + self._select_next_support() + self.interval_reset(POPUP_CANCEL) + continue + if self.appear(COMBAT_SUPPORT_LIST, interval=2): + if not selected_support: + # In Ornament Extraction, first character isn't selected by default + if support_character_name == "FirstCharacter": + self._select_first() + else: + self._search_support(support_character_name) # Search support + selected_support = True + self.device.click(OCR_DOUBLE_EVENT_REMAIN_AT_OE) + self.interval_reset(COMBAT_SUPPORT_LIST) + continue + + def is_team_prepared(self) -> bool: + """ + Pages: + in: COMBAT_PREPARE + """ + slots = CHARACTER_EMPTY_OE.match_multi_template(self.device.image) + slots = 4 - len(slots) + logger.attr('TeamSlotsPrepared', slots) + return slots > 0 + + def combat_prepare(self, team=1, support_character: str = None): + """ + Args: + team: 1 to 6. + support_character: Support character name + + Returns: + bool: True + + Pages: + in: COMBAT_PREPARE + out: is_in_main + """ + + @run_once + def check_team_prepare(): + if not self.is_team_prepared(): + logger.error(f'Please prepare your team in Ornament Extraction') + raise RequestHumanTakeover + + logger.hr('Combat prepare') + skip_first_screenshot = True + if support_character: + # Block COMBAT_TEAM_PREPARE before support set + support_set = False + else: + support_set = True + logger.info([support_character, support_set]) + trial = 0 + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if self.is_in_main(): + logger.info('Combat entered') + return True + # Relics full + # Clicking between COMBAT_PREPARE and COMBAT_TEAM_PREPARE + if trial > 5: + logger.critical('Failed to enter dungeon after 5 trial, probably because relics are full') + raise RequestHumanTakeover + if self.appear(SUPPORT_ADD): + check_team_prepare() + + # Click + if support_character and self.appear(SUPPORT_ADD, interval=2): + self.support_set(support_character) + self.interval_reset(SUPPORT_ADD) + support_set = True + continue + if support_set and self.appear(COMBAT_PREPARE, interval=5): + # Long loading after COMBAT_PREPARE + self.device.click(COMBAT_PREPARE) + trial += 1 + continue + if self.handle_popup_confirm(): + continue From d238838ddae7d89f5fd05a4bbe28bab697b65f19 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:07:11 +0800 Subject: [PATCH 06/27] Add: oe_leave() --- assets/share/ornament/ui/DU_MAIN_CHECK.png | Bin 0 -> 6326 bytes assets/share/ornament/ui/DU_MODE_CHECK.png | Bin 0 -> 6757 bytes .../share/ornament/ui/DU_OE_SELECT_CHECK.png | Bin 0 -> 6463 bytes tasks/ornament/assets/assets_ornament_ui.py | 35 ++++++++++++++++++ tasks/ornament/combat.py | 32 ++++++++++++++++ 5 files changed, 67 insertions(+) create mode 100644 assets/share/ornament/ui/DU_MAIN_CHECK.png create mode 100644 assets/share/ornament/ui/DU_MODE_CHECK.png create mode 100644 assets/share/ornament/ui/DU_OE_SELECT_CHECK.png create mode 100644 tasks/ornament/assets/assets_ornament_ui.py diff --git a/assets/share/ornament/ui/DU_MAIN_CHECK.png b/assets/share/ornament/ui/DU_MAIN_CHECK.png new file mode 100644 index 0000000000000000000000000000000000000000..95aa772ae4fc09d436073e57c04ebd64a69b0d58 GIT binary patch literal 6326 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 literal 0 HcmV?d00001 diff --git a/assets/share/ornament/ui/DU_MODE_CHECK.png b/assets/share/ornament/ui/DU_MODE_CHECK.png new file mode 100644 index 0000000000000000000000000000000000000000..c756e98b50891c6406a97e3932cc5b89a7cff33d GIT binary patch literal 6757 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 literal 0 HcmV?d00001 diff --git a/tasks/ornament/assets/assets_ornament_ui.py b/tasks/ornament/assets/assets_ornament_ui.py new file mode 100644 index 000000000..23f2b1cb1 --- /dev/null +++ b/tasks/ornament/assets/assets_ornament_ui.py @@ -0,0 +1,35 @@ +from module.base.button import Button, ButtonWrapper + +# This file was auto-generated, do not modify it manually. To generate: +# ``` python -m dev_tools.button_extract ``` + +DU_MAIN_CHECK = ButtonWrapper( + name='DU_MAIN_CHECK', + share=Button( + file='./assets/share/ornament/ui/DU_MAIN_CHECK.png', + area=(774, 631, 796, 653), + search=(754, 611, 816, 673), + color=(149, 132, 98), + button=(774, 631, 796, 653), + ), +) +DU_MODE_CHECK = ButtonWrapper( + name='DU_MODE_CHECK', + share=Button( + file='./assets/share/ornament/ui/DU_MODE_CHECK.png', + area=(125, 175, 142, 205), + search=(105, 155, 162, 225), + color=(117, 98, 63), + button=(125, 175, 142, 205), + ), +) +DU_OE_SELECT_CHECK = ButtonWrapper( + name='DU_OE_SELECT_CHECK', + share=Button( + file='./assets/share/ornament/ui/DU_OE_SELECT_CHECK.png', + area=(1058, 24, 1084, 50), + search=(1038, 4, 1104, 70), + color=(196, 195, 193), + button=(1058, 24, 1084, 50), + ), +) diff --git a/tasks/ornament/combat.py b/tasks/ornament/combat.py index 13a05c65d..eff9d4637 100644 --- a/tasks/ornament/combat.py +++ b/tasks/ornament/combat.py @@ -1,12 +1,14 @@ from module.base.decorator import run_once from module.exception import RequestHumanTakeover from module.logger import logger +from tasks.base.assets.assets_base_page import MAP_EXIT from tasks.base.assets.assets_base_popup import POPUP_CANCEL from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_LIST from tasks.combat.combat import Combat from tasks.dungeon.event import DungeonEvent from tasks.ornament.assets.assets_ornament_combat import * +from tasks.ornament.assets.assets_ornament_ui import * class OrnamentCombat(DungeonEvent, Combat): @@ -19,6 +21,36 @@ class OrnamentCombat(DungeonEvent, Combat): # Different position to OCR return super().get_double_event_remain_at_combat(button) + def oe_leave(self, skip_first_screenshot=True): + self.interval_clear([COMBAT_PREPARE, MAP_EXIT]) + logger.hr('OE leave') + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + exit_ = self.is_in_map_exit() + if not exit_ and self.is_in_main(): + logger.info('OE left') + break + + # Click + if self.handle_ui_back(DU_OE_SELECT_CHECK, interval=2): + continue + if self.handle_ui_back(DU_MODE_CHECK, interval=2): + continue + if self.handle_ui_back(DU_MAIN_CHECK, interval=2): + continue + if self.handle_ui_back(COMBAT_PREPARE, interval=2): + continue + if exit_ and self.is_in_map_exit(interval=3): + self.device.click(MAP_EXIT) + continue + if self.handle_popup_confirm(): + continue + def support_set(self, support_character_name: str = "FirstCharacter"): """ Args: From a637a5cfb97016aed914ceeb8eb016d91e46698e Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:40:56 +0800 Subject: [PATCH 07/27] Upd: Floor data in Penacony --- tasks/map/keywords/__init__.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tasks/map/keywords/__init__.py b/tasks/map/keywords/__init__.py index 0391e0d68..ca8ad0640 100644 --- a/tasks/map/keywords/__init__.py +++ b/tasks/map/keywords/__init__.py @@ -26,3 +26,15 @@ KEYWORDS_MAP_PLANE.Luofu_ArtisanshipCommission.page = 'bottom' KEYWORDS_MAP_PLANE.Luofu_FyxestrollGarden.page = 'bottom' KEYWORDS_MAP_PLANE.Luofu_AlchemyCommission.page = 'bottom' KEYWORDS_MAP_PLANE.Luofu_ScalegorgeWaterscape.page = 'bottom' +# Penacony +KEYWORDS_MAP_PLANE.Penacony_TheReverieReality.floors = ['F1', 'F2', 'F3'] +KEYWORDS_MAP_PLANE.Penacony_GoldenHour.floors = ['F1', 'F2', 'F3'] +KEYWORDS_MAP_PLANE.Penacony_TheReverieDreamscape.floors = ['F1', 'F2', 'F3'] +KEYWORDS_MAP_PLANE.Penacony_DewlightPavilion.floors = ['F1', 'F2'] +KEYWORDS_MAP_PLANE.Penacony_ClockStudiosThemePark.floors = ['F1', 'F2'] +KEYWORDS_MAP_PLANE.Penacony_DreamfluxReef.floors = ['F1', 'F2'] +KEYWORDS_MAP_PLANE.Penacony_DewlightPavilion.page = 'bottom' +KEYWORDS_MAP_PLANE.Penacony_ClockStudiosThemePark.page = 'bottom' +KEYWORDS_MAP_PLANE.Penacony_DreamfluxReef.page = 'bottom' +KEYWORDS_MAP_PLANE.Penacony_SoulGladScorchsandAuditionVenue.page = 'bottom' +KEYWORDS_MAP_PLANE.Penacony_PenaconyGrandTheater.page = 'bottom' From 3045c32f389ad15472916f9761a13258cc2bb83a Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 1 Jul 2024 15:18:28 +0800 Subject: [PATCH 08/27] Dep: srcmap==2.3.20240701 for ornament extraction --- requirements-in.txt | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-in.txt b/requirements-in.txt index 656bef808..9b76852e6 100644 --- a/requirements-in.txt +++ b/requirements-in.txt @@ -33,7 +33,7 @@ uvicorn[standard]==0.17.6 aiofiles # Game resources -srcmap==1.3.6 +srcmap==2.3.20240701 # For dev # pip-tools diff --git a/requirements.txt b/requirements.txt index 0c79b502b..a1d750521 100644 --- a/requirements.txt +++ b/requirements.txt @@ -67,7 +67,7 @@ scipy==1.10.1 # via -r requirements-in.txt shapely==2.0.1 # via pponnxcr six==1.16.0 # via pynput, uiautomator2 sniffio==1.3.0 # via anyio -srcmap==1.3.6 # via -r requirements-in.txt +srcmap==2.3.20240701 # via -r requirements-in.txt starlette==0.14.2 # via -r requirements-in.txt sympy==1.12 # via onnxruntime tornado==6.3.1 # via pywebio From 09acc8f0766542d6645340885055943ff2c69a8e Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:18:58 +0800 Subject: [PATCH 09/27] Add: GUI option of Ornament --- config/template.json | 18 ++++ module/config/argument/args.json | 137 +++++++++++++++++++++++++++ module/config/argument/argument.yaml | 17 ++++ module/config/argument/menu.json | 3 +- module/config/argument/task.yaml | 4 + module/config/config_generated.py | 6 ++ module/config/config_updater.py | 21 +++- module/config/i18n/en-US.json | 46 ++++++++- module/config/i18n/es-ES.json | 44 ++++++++- module/config/i18n/ja-JP.json | 36 +++++++ module/config/i18n/zh-CN.json | 40 +++++++- module/config/i18n/zh-TW.json | 42 +++++++- 12 files changed, 395 insertions(+), 19 deletions(-) diff --git a/config/template.json b/config/template.json index efb5b222d..20d8dccad 100644 --- a/config/template.json +++ b/config/template.json @@ -264,6 +264,24 @@ "DebugMode": false } }, + "Ornament": { + "Scheduler": { + "Enable": false, + "NextRun": "2020-01-01 00:00:00", + "Command": "Ornament", + "ServerUpdate": "04:00" + }, + "Ornament": { + "Dungeon": "Divergent_Universe_Eternal_Comedy", + "UseImmersifier": true, + "DoubleEvent": true, + "UseStamina": false + }, + "DungeonSupport": { + "Use": "when_daily", + "Character": "FirstCharacter" + } + }, "Daemon": { "Daemon": { "Enable": true, diff --git a/module/config/argument/args.json b/module/config/argument/args.json index 993559321..d1946f162 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -1790,6 +1790,143 @@ } } }, + "Ornament": { + "Scheduler": { + "Enable": { + "type": "checkbox", + "value": false, + "option": [ + true, + false + ] + }, + "NextRun": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + }, + "Command": { + "type": "input", + "value": "Ornament", + "display": "hide" + }, + "ServerUpdate": { + "type": "input", + "value": "04:00", + "display": "hide" + } + }, + "Ornament": { + "Dungeon": { + "type": "select", + "value": "Divergent_Universe_Eternal_Comedy", + "option": [ + "Divergent_Universe_Eternal_Comedy", + "Divergent_Universe_To_Sweet_Dreams", + "Divergent_Universe_Pouring_Blades", + "Divergent_Universe_Fruit_of_Evil", + "Divergent_Universe_Permafrost", + "Divergent_Universe_Gentle_Words", + "Divergent_Universe_Smelted_Heart", + "Divergent_Universe_Untoppled_Walls" + ] + }, + "UseImmersifier": { + "type": "state", + "value": true, + "option": [ + true + ], + "option_bold": [ + true + ] + }, + "DoubleEvent": { + "type": "state", + "value": true, + "option": [ + true + ], + "option_bold": [ + true + ] + }, + "UseStamina": { + "type": "checkbox", + "value": false + } + }, + "DungeonSupport": { + "Use": { + "type": "select", + "value": "when_daily", + "option": [ + "always_use", + "when_daily", + "do_not_use" + ] + }, + "Character": { + "type": "select", + "value": "FirstCharacter", + "option": [ + "FirstCharacter", + "Acheron", + "Argenti", + "Arlan", + "Asta", + "Aventurine", + "Bailu", + "BlackSwan", + "Blade", + "Boothill", + "Bronya", + "Clara", + "DanHeng", + "DanHengImbibitorLunae", + "DrRatio", + "Firefly", + "FuXuan", + "Gallagher", + "Gepard", + "Guinaifen", + "Hanya", + "Herta", + "Himeko", + "Hook", + "Huohuo", + "JingYuan", + "Jingliu", + "Kafka", + "Luka", + "Luocha", + "Lynx", + "March7th", + "Misha", + "Natasha", + "Pela", + "Qingque", + "Robin", + "RuanMei", + "Sampo", + "Seele", + "Serval", + "SilverWolf", + "Sparkle", + "Sushang", + "Tingyun", + "TopazNumby", + "TrailblazerDestruction", + "TrailblazerHarmony", + "TrailblazerPreservation", + "Welt", + "Xueyi", + "Yanqing", + "Yukong" + ] + } + } + }, "Daemon": { "Daemon": { "Enable": { diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index 1a7052d33..7d217a1f5 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -285,6 +285,23 @@ RogueBlessing: RogueDebug: DebugMode: false +Ornament: + Dungeon: + value: Divergent_Universe_Eternal_Comedy + # OrnamentExtraction will be injected in config updater + option: [ ] + UseImmersifier: + type: state + value: true + option: [ true, ] + option_bold: [ true, ] + DoubleEvent: + type: state + value: true + option: [ true, ] + option_bold: [ true, ] + UseStamina: false + # ==================== Tool ==================== Daemon: diff --git a/module/config/argument/menu.json b/module/config/argument/menu.json index 43ff195a6..81e6c68fa 100644 --- a/module/config/argument/menu.json +++ b/module/config/argument/menu.json @@ -24,7 +24,8 @@ "page": "setting", "tasks": [ "Weekly", - "Rogue" + "Rogue", + "Ornament" ] }, "Tool": { diff --git a/module/config/argument/task.yaml b/module/config/argument/task.yaml index 80cfb4dda..293d135e0 100644 --- a/module/config/argument/task.yaml +++ b/module/config/argument/task.yaml @@ -61,6 +61,10 @@ Weekly: - RogueWorld - RogueBlessing - RogueDebug + Ornament: + - Scheduler + - Ornament + - DungeonSupport # ==================== Tool ==================== diff --git a/module/config/config_generated.py b/module/config/config_generated.py index 27dc6367e..ebb709122 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -202,6 +202,12 @@ class GeneratedConfig: # Group `RogueDebug` RogueDebug_DebugMode = False + # Group `Ornament` + Ornament_Dungeon = 'Divergent_Universe_Eternal_Comedy' # Divergent_Universe_Eternal_Comedy, Divergent_Universe_To_Sweet_Dreams, Divergent_Universe_Pouring_Blades, Divergent_Universe_Fruit_of_Evil, Divergent_Universe_Permafrost, Divergent_Universe_Gentle_Words, Divergent_Universe_Smelted_Heart, Divergent_Universe_Untoppled_Walls + Ornament_UseImmersifier = True # True + Ornament_DoubleEvent = True # True + Ornament_UseStamina = False + # Group `Daemon` Daemon_Enable = True # True Daemon_AimClicker = 'do_not_click' # item_enemy, item, enemy, do_not_click diff --git a/module/config/config_updater.py b/module/config/config_updater.py index 6de81c39b..96922eba2 100644 --- a/module/config/config_updater.py +++ b/module/config/config_updater.py @@ -95,6 +95,9 @@ class ConfigGenerator: option_add( keys='Weekly.Name.option', options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Echo_of_War]) + # OrnamentExtraction + ornament = [dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Ornament_Extraction] + option_add(keys='Ornament.Dungeon.option', options=ornament) # Insert characters from tasks.character.keywords import CharacterList unsupported_characters = ["Jade"] @@ -415,12 +418,8 @@ class ConfigGenerator: from tasks.dungeon.keywords import DungeonList, DungeonDetailed for dungeon in DungeonList.instances.values(): dungeon: DungeonList = dungeon - if not dungeon.plane: - continue dungeon_name = dungeon.__getattribute__(ingame_lang) dungeon_name = re.sub('[「」]', '', dungeon_name) - plane = dungeon.plane.__getattribute__(ingame_lang) - plane = re.sub('[「」]', '', plane) if dungeon.is_Calyx_Golden_Memories: deep_set(new, keys=['Dungeon', 'Name', dungeon.name], value=i18n_memories[ingame_lang].format(dungeon=dungeon_name)) @@ -431,6 +430,8 @@ class ConfigGenerator: deep_set(new, keys=['Dungeon', 'Name', dungeon.name], value=i18n_treasure[ingame_lang].format(dungeon=dungeon_name)) if dungeon.is_Calyx_Crimson: + plane = dungeon.plane.__getattribute__(ingame_lang) + plane = re.sub('[「」]', '', plane) path = dungeon.Calyx_Crimson_Path.__getattribute__(ingame_lang) deep_set(new, keys=['Dungeon', 'Name', dungeon.name], value=i18n_crimson[ingame_lang].format(path=path, plane=plane)) @@ -439,6 +440,18 @@ class ConfigGenerator: suffix = i18n_relic[ingame_lang].format(dungeon=dungeon_name).replace('Cavern of Corrosion: ', '') if not value.endswith(suffix): deep_set(new, keys=['Dungeon', 'Name', dungeon.name], value=f'{value}{suffix}') + if dungeon.is_Ornament_Extraction: + value = deep_get(new, keys=['Ornament', 'Dungeon', dungeon.name], default='') + suffix = i18n_relic[ingame_lang].format(dungeon=dungeon_name) + suffix = re.sub( + r'(•差分宇宙' + r'|Divergent Universe: ' + r'|階差宇宙・' + r'|: Universo Diferenciado' + r'|Universo Diferenciado: ' + r')', '', suffix) + if not value.endswith(suffix): + deep_set(new, keys=['Ornament', 'Dungeon', dungeon.name], value=f'{value}{suffix}') # Stagnant shadows with character names for dungeon in DungeonDetailed.instances.values(): diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index 0c5dd1271..4210ec046 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -58,6 +58,10 @@ "name": "Simulated Universe", "help": "" }, + "Ornament": { + "name": "Ornament", + "help": "The followings must be satisfied:\n1. Manually clear Divergent Universe once this week and have a save file.\n2. Enter the dungeon once on current device to have dungeon team saved." + }, "Daemon": { "name": "Dialogue Clicker", "help": "" @@ -1121,11 +1125,11 @@ "occurrence": "Prefer Occurrence" }, "UseImmersifier": { - "name": "Claim Planers Using Immersifiers", + "name": "Claim Planars Using Immersifiers", "help": "" }, "DoubleEvent": { - "name": "Participate in Double Planer Event", + "name": "Participate in Double Planar Event", "help": "" }, "WeeklyFarming": { @@ -1133,11 +1137,11 @@ "help": "" }, "UseStamina": { - "name": "Farm Planers Using Trailblase Power", - "help": "Task \"Dungeon\" will no longer run, and all trailblaze power will be used first to claim immersion rewards, except for double events." + "name": "Farm Planars Using Trailblaze Power", + "help": "Prioritize trailblaze power to farm planar ornaments, only taking priority over character planner" }, "SimulatedUniverseFarm": { - "name": "Progress of elite boss farmed", + "name": "Elites/bosses Farmed", "help": "" } }, @@ -1194,6 +1198,38 @@ "help": "No stop conditions, no error handling, stop when encountering an error. Please report errors according to the doc: https://github.com/LmeSzinc/StarRailCopilot/wiki/RogueMap_cn" } }, + "Ornament": { + "_info": { + "name": "Ornament Extraction Settings", + "help": "" + }, + "Dungeon": { + "name": "Dungeon Name", + "help": "", + "Divergent_Universe_Eternal_Comedy": "Running Wolves & Kalpagni Lantern (Eternal Comedy)", + "Divergent_Universe_To_Sweet_Dreams": "Sigonia & Izumo Gensei (To Sweet Dreams)", + "Divergent_Universe_Pouring_Blades": "Firmament & Penacony (Pouring Blades)", + "Divergent_Universe_Fruit_of_Evil": "Rutilant Arena & Broken Keel (Fruit of Evil)", + "Divergent_Universe_Permafrost": "Belobog & Salsotto (Permafrost)", + "Divergent_Universe_Gentle_Words": "Commercial Enterprise & Differentiator (Gentle Words)", + "Divergent_Universe_Smelted_Heart": "Banditry & Vonwacq (Smelted Heart)", + "Divergent_Universe_Untoppled_Walls": "Space Station & Ageless (Untoppled Walls)" + }, + "UseImmersifier": { + "name": "Claim Planars Using Immersifiers", + "help": "", + "True": "Enabled" + }, + "DoubleEvent": { + "name": "Participate in Double Planar Event", + "help": "", + "True": "Enabled" + }, + "UseStamina": { + "name": "Farm Planars Using Trailblaze Power", + "help": "Prioritize trailblaze power to farm planar ornaments, taking priority over character planner and simulated universe" + } + }, "Daemon": { "_info": { "name": "Dialogue Clicker", diff --git a/module/config/i18n/es-ES.json b/module/config/i18n/es-ES.json index faa680bbe..18e0cb0ec 100644 --- a/module/config/i18n/es-ES.json +++ b/module/config/i18n/es-ES.json @@ -58,6 +58,10 @@ "name": "Universo Simulado", "help": "" }, + "Ornament": { + "name": "Ornamentos", + "help": "Se deben cumplir los siguientes requisitos:\n1. Borre manualmente Universo Diferenciado una vez esta semana y tenga un archivo guardado.\n2. Ingrese a la mazmorra una vez en el dispositivo actual para guardar el equipo de la mazmorra." + }, "Daemon": { "name": "Clic de diálogo", "help": "" @@ -1121,11 +1125,11 @@ "occurrence": "Prefiero Evento" }, "UseImmersifier": { - "name": "Reclamar de planers mediante inmersor", + "name": "Reclamar de planars mediante inmersor", "help": "" }, "DoubleEvent": { - "name": "Participa en doble planer evento", + "name": "Participa en doble planar evento", "help": "" }, "WeeklyFarming": { @@ -1133,8 +1137,8 @@ "help": "" }, "UseStamina": { - "name": "Reclamar de planers mediante poder trazacaminos", - "help": "La tarea de mazmorra ya no se ejecutará y todo el poder trazacaminos se usará primero para reclamar recompensas de inmersión, excepto para eventos dobles" + "name": "Reclamar de planars mediante poder trazacaminos", + "help": "Prioriza el poder trazacaminos para cultivar planar ornaments, teniendo prioridad solo sobre el planificador de personajes." }, "SimulatedUniverseFarm": { "name": "Progreso de élites derrotadas", @@ -1194,6 +1198,38 @@ "help": "Sin condiciones de parada, sin manejo de errores, deténgase cuando encuentre un error. Informe el error de acuerdo con el documento: https://github.com/LmeSzinc/StarRailCopilot/wiki/RogueMap_cn" } }, + "Ornament": { + "_info": { + "name": "Ajustes de ornamentos extracción", + "help": "" + }, + "Dungeon": { + "name": "Nombre de la Mazmorra", + "help": "", + "Divergent_Universe_Eternal_Comedy": " (Comedia eterna)", + "Divergent_Universe_To_Sweet_Dreams": " (Hasta los dulces sueños)", + "Divergent_Universe_Pouring_Blades": " (Lluvia de espadas)", + "Divergent_Universe_Fruit_of_Evil": " (Fruta del desastre)", + "Divergent_Universe_Permafrost": " (Permafrost)", + "Divergent_Universe_Gentle_Words": " (Palabras amables)", + "Divergent_Universe_Smelted_Heart": " (Corazón de fundición)", + "Divergent_Universe_Untoppled_Walls": " (Muros inquebrantables)" + }, + "UseImmersifier": { + "name": "Reclamar de planars mediante inmersor", + "help": "", + "True": "Activado" + }, + "DoubleEvent": { + "name": "Participa en doble planar evento", + "help": "", + "True": "Activado" + }, + "UseStamina": { + "name": "Reclamar de planars mediante poder trazacaminos", + "help": "Prioriza el poder trazacaminos para cultivar planar ornamentos, teniendo prioridad sobre el planificador de personajes y el universo simulado." + } + }, "Daemon": { "_info": { "name": "Clic de diálogo", diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index c951429aa..52cd0cb66 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -58,6 +58,10 @@ "name": "Task.Rogue.name", "help": "Task.Rogue.help" }, + "Ornament": { + "name": "Task.Ornament.name", + "help": "Task.Ornament.help" + }, "Daemon": { "name": "Task.Daemon.name", "help": "Task.Daemon.help" @@ -1194,6 +1198,38 @@ "help": "RogueDebug.DebugMode.help" } }, + "Ornament": { + "_info": { + "name": "Ornament._info.name", + "help": "Ornament._info.help" + }, + "Dungeon": { + "name": "Ornament.Dungeon.name", + "help": "Ornament.Dungeon.help", + "Divergent_Universe_Eternal_Comedy": "(永遠の喜劇)", + "Divergent_Universe_To_Sweet_Dreams": "(寄り添い眠る)", + "Divergent_Universe_Pouring_Blades": "(剣の雨)", + "Divergent_Universe_Fruit_of_Evil": "(渦巻く罪)", + "Divergent_Universe_Permafrost": "(永久凍土)", + "Divergent_Universe_Gentle_Words": "(優しい言葉)", + "Divergent_Universe_Smelted_Heart": "(鋼の意志)", + "Divergent_Universe_Untoppled_Walls": "(不動の砦)" + }, + "UseImmersifier": { + "name": "Ornament.UseImmersifier.name", + "help": "Ornament.UseImmersifier.help", + "True": "True" + }, + "DoubleEvent": { + "name": "Ornament.DoubleEvent.name", + "help": "Ornament.DoubleEvent.help", + "True": "True" + }, + "UseStamina": { + "name": "Ornament.UseStamina.name", + "help": "Ornament.UseStamina.help" + } + }, "Daemon": { "_info": { "name": "Daemon._info.name", diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index 8a88b780c..7df14bdb3 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -58,6 +58,10 @@ "name": "模拟宇宙", "help": "" }, + "Ornament": { + "name": "饰品提取", + "help": "运行 \"饰品提取\" 任务需要:\n1. 每周事先手动通关差分宇宙一次并保存存档\n2. 在当前设备进入过副本一次,有保存的编队" + }, "Daemon": { "name": "剧情连点器", "help": "" @@ -1125,7 +1129,7 @@ "help": "" }, "DoubleEvent": { - "name": "参与双倍内圈仪器活动", + "name": "参与双倍内圈遗器活动", "help": "" }, "WeeklyFarming": { @@ -1134,7 +1138,7 @@ }, "UseStamina": { "name": "使用开拓力刷内圈遗器", - "help": "每日副本任务将不再打本,所有开拓力将优先被用于领取浸器奖励,双倍活动时除外" + "help": "优先将体力用于刷内圈遗器,仅优先于养成规划" }, "SimulatedUniverseFarm": { "name": "刷精英怪进度", @@ -1194,6 +1198,38 @@ "help": "无停止条件,无异常处理,遇错误即停止,请按文档上报异常:https://github.com/LmeSzinc/StarRailCopilot/wiki/RogueMap_cn" } }, + "Ornament": { + "_info": { + "name": "饰品提取设置", + "help": "" + }, + "Dungeon": { + "name": "副本名称", + "help": "", + "Divergent_Universe_Eternal_Comedy": "奔狼+火宫(永恒笑剧)", + "Divergent_Universe_To_Sweet_Dreams": "茨冈尼亚+出云神国(伴你入眠)", + "Divergent_Universe_Pouring_Blades": "苍穹+匹诺康尼(天剑如雨)", + "Divergent_Universe_Fruit_of_Evil": "繁星+龙骨(孽果盘生)", + "Divergent_Universe_Permafrost": "贝洛伯格+萨尔索图(百年冻土)", + "Divergent_Universe_Gentle_Words": "商业公司+差分(温柔话语)", + "Divergent_Universe_Smelted_Heart": "盗贼+翁瓦克(浴火钢心)", + "Divergent_Universe_Untoppled_Walls": "太空+仙舟(坚城不倒)" + }, + "UseImmersifier": { + "name": "使用沉浸器领取遗器", + "help": "", + "True": "已启用" + }, + "DoubleEvent": { + "name": "参与双倍内圈仪器活动", + "help": "", + "True": "已启用" + }, + "UseStamina": { + "name": "使用开拓力刷内圈遗器", + "help": "优先将体力用于刷内圈遗器,优先于模拟宇宙和养成规划" + } + }, "Daemon": { "_info": { "name": "剧情连点器", diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index 8e4a69861..5009af9ef 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -58,6 +58,10 @@ "name": "模擬宇宙", "help": "" }, + "Ornament": { + "name": "飾品提取", + "help": "運行 \"飾品提取\" 任務需要:\n1. 每週事先手動通關差分宇宙一次並保存檔案\n2. 在當前設備進入過副本一次,有保存的編隊" + }, "Daemon": { "name": "劇情連點器", "help": "" @@ -1125,7 +1129,7 @@ "help": "" }, "DoubleEvent": { - "name": "參與雙倍內圈儀器活動", + "name": "參與雙倍內圈遺器活動", "help": "" }, "WeeklyFarming": { @@ -1133,8 +1137,8 @@ "help": "" }, "UseStamina": { - "name": "用開拓力農遺器", - "help": "每日副本任務將不再打本,所有開拓力將優先被用於領取浸器獎勵,雙倍活動時除外" + "name": "用開拓力農內圈遺器", + "help": "優先將體力用於農內圈遺器,僅優先於養成規劃" }, "SimulatedUniverseFarm": { "name": "農精英怪進度", @@ -1194,6 +1198,38 @@ "help": "無停止條件,無異常處理,遇錯誤即停止,請依檔案回報異常:https://github.com/LmeSzinc/StarRailCopilot/wiki/RogueMap_cn" } }, + "Ornament": { + "_info": { + "name": "飾品提取設定", + "help": "" + }, + "Dungeon": { + "name": "副本名稱", + "help": "", + "Divergent_Universe_Eternal_Comedy": "奔狼+火宮(永恆笑劇)", + "Divergent_Universe_To_Sweet_Dreams": "茨岡尼亞+出雲神國(伴你入眠)", + "Divergent_Universe_Pouring_Blades": "天空+匹諾康尼(天劍如雨)", + "Divergent_Universe_Fruit_of_Evil": "繁星+龍骨(孽果盤生)", + "Divergent_Universe_Permafrost": "貝洛伯格+薩爾索圖(百年凍土)", + "Divergent_Universe_Gentle_Words": "商業公司+差分(溫柔話語)", + "Divergent_Universe_Smelted_Heart": "盜賊+翁瓦克(浴火鋼心)", + "Divergent_Universe_Untoppled_Walls": "太空+仙舟(堅城不倒)" + }, + "UseImmersifier": { + "name": "使用沉浸器領取遺器", + "help": "", + "True": "已啟用" + }, + "DoubleEvent": { + "name": "參與雙倍內圈儀器活動", + "help": "", + "True": "已啟用" + }, + "UseStamina": { + "name": "參與雙倍內圈遺器活動", + "help": "優先將體力用於農內圈遺器,優先於模擬宇宙和養成規劃" + } + }, "Daemon": { "_info": { "name": "劇情連點器", From fe7dc5ac3ce93f533d56535aa3c0382983701da9 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 1 Jul 2024 23:06:41 +0800 Subject: [PATCH 10/27] Add: Goto ornament boss --- route/daily/OrnamentExtraction.py | 21 +++++++++++++++++++++ tasks/map/route/route/daily.py | 7 +++++++ tasks/ornament/combat.py | 11 ++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 route/daily/OrnamentExtraction.py diff --git a/route/daily/OrnamentExtraction.py b/route/daily/OrnamentExtraction.py new file mode 100644 index 000000000..07e8cfcd9 --- /dev/null +++ b/route/daily/OrnamentExtraction.py @@ -0,0 +1,21 @@ +from module.logger import logger +from tasks.combat.combat import Combat +from tasks.map.control.waypoint import Waypoint +from tasks.map.keywords.plane import Penacony_TheReverieReality +from tasks.map.route.base import RouteBase + + +class Route(RouteBase, Combat): + def route(self): + """ + Pages: + in: Any + out: page_forgotten_hall + """ + logger.hr('Route Ornament Extraction', level=1) + self.map_init(plane=Penacony_TheReverieReality, position=(245.3, 233.3)) + boss = Waypoint((245.2, 193.6)) + boss.expected_end = [self.is_combat_executing] + self.clear_enemy( + boss + ) diff --git a/tasks/map/route/route/daily.py b/tasks/map/route/route/daily.py index 090df0d4a..f3744efc7 100644 --- a/tasks/map/route/route/daily.py +++ b/tasks/map/route/route/daily.py @@ -38,3 +38,10 @@ HimekoTrial__exit = RouteModel( floor='F1', position=(519.9, 361.5), ) +OrnamentExtraction__route = RouteModel( + name='OrnamentExtraction__route', + route='route.daily.OrnamentExtraction:route', + plane='Penacony_TheReverieReality', + floor='F1', + position=(245.3, 233.3), +) diff --git a/tasks/ornament/combat.py b/tasks/ornament/combat.py index eff9d4637..d35a3b838 100644 --- a/tasks/ornament/combat.py +++ b/tasks/ornament/combat.py @@ -7,11 +7,13 @@ from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_LIST from tasks.combat.combat import Combat from tasks.dungeon.event import DungeonEvent +from tasks.map.route.loader import RouteLoader +from tasks.map.route.route.daily import OrnamentExtraction__route from tasks.ornament.assets.assets_ornament_combat import * from tasks.ornament.assets.assets_ornament_ui import * -class OrnamentCombat(DungeonEvent, Combat): +class OrnamentCombat(DungeonEvent, Combat, RouteLoader): def combat_enter_from_map(self, skip_first_screenshot=True): # Don't enter from map, UI too deep inside # Enter from survival index instead @@ -149,8 +151,8 @@ class OrnamentCombat(DungeonEvent, Combat): # End if self.is_in_main(): - logger.info('Combat entered') - return True + logger.info('Combat map entered') + break # Relics full # Clicking between COMBAT_PREPARE and COMBAT_TEAM_PREPARE if trial > 5: @@ -172,3 +174,6 @@ class OrnamentCombat(DungeonEvent, Combat): continue if self.handle_popup_confirm(): continue + + self.route_run(OrnamentExtraction__route) + return True From 0d54d22ac395293027a68a4a8e4fef3afb7c7b64 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 1 Jul 2024 23:36:36 +0800 Subject: [PATCH 11/27] Opt: Slower screenshot interval during combat --- tasks/combat/combat.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tasks/combat/combat.py b/tasks/combat/combat.py index d7355e97e..a34165c95 100644 --- a/tasks/combat/combat.py +++ b/tasks/combat/combat.py @@ -160,6 +160,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo skip_first_screenshot = True is_executing = True self.combat_state_reset() + self.device.screenshot_interval_set('combat') while 1: if skip_first_screenshot: skip_first_screenshot = False @@ -192,6 +193,8 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo if self.handle_battle_pass_notification(): continue + self.device.screenshot_interval_set() + def _combat_can_again(self) -> bool: """ Pages: From 8e10b9989f260ad60a6813b027f168233512ac15 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 1 Jul 2024 23:37:38 +0800 Subject: [PATCH 12/27] Opt: [ALAS] Dynamic nemu_ipc timeout to fit screenshot interval --- module/device/method/nemu_ipc.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/module/device/method/nemu_ipc.py b/module/device/method/nemu_ipc.py index b79e1c322..b69cf9dd5 100644 --- a/module/device/method/nemu_ipc.py +++ b/module/device/method/nemu_ipc.py @@ -8,6 +8,7 @@ import cv2 import numpy as np from module.base.decorator import cached_property, del_cached_property, has_cached_property +from module.base.timer import Timer from module.base.utils import ensure_time from module.device.method.minitouch import insert_swipe, random_rectangle_point from module.device.method.utils import RETRY_TRIES, retry_sleep @@ -277,11 +278,12 @@ class NemuIpcImpl: def _ev(self): return asyncio.new_event_loop() - async def ev_run_async(self, func, *args, **kwargs): + async def ev_run_async(self, func, *args, timeout=0.15, **kwargs): """ Args: func: Sync function to call *args: + timeout: **kwargs: Raises: @@ -290,7 +292,7 @@ class NemuIpcImpl: func_wrapped = partial(func, *args, **kwargs) # Increased timeout for slow PCs # Default screenshot interval is 0.2s, so a 0.15s timeout would have a fast retry without extra time costs - result = await asyncio.wait_for(self._ev.run_in_executor(None, func_wrapped), timeout=0.15) + result = await asyncio.wait_for(self._ev.run_in_executor(None, func_wrapped), timeout=timeout) return result def ev_run_sync(self, func, *args, **kwargs): @@ -343,7 +345,7 @@ class NemuIpcImpl: self.height = height_ptr.contents.value @retry - def screenshot(self): + def screenshot(self, timeout=0.15): """ Returns: np.ndarray: Image array in RGBA color space @@ -361,7 +363,8 @@ class NemuIpcImpl: ret = self.ev_run_sync( self.lib.nemu_capture_display, - self.connect_id, self.display_id, length, width_ptr, height_ptr, pixels_pointer + self.connect_id, self.display_id, length, width_ptr, height_ptr, pixels_pointer, + timeout=timeout, ) if ret > 0: raise NemuIpcError('nemu_capture_display failed during screenshot()') @@ -439,6 +442,8 @@ def serial_to_id(serial: str): class NemuIpc(Platform): + _screenshot_interval = Timer(0.1) + @cached_property def nemu_ipc(self) -> NemuIpcImpl: """ @@ -494,7 +499,8 @@ class NemuIpc(Platform): logger.info('nemu_ipc released') def screenshot_nemu_ipc(self): - image = self.nemu_ipc.screenshot() + timeout = max(self._screenshot_interval.limit - 0.01, 0.15) + image = self.nemu_ipc.screenshot(timeout=timeout) image = cv2.cvtColor(image, cv2.COLOR_BGRA2BGR) cv2.flip(image, 0, dst=image) From 3152876e4c77d42c95b9b1e067408a1d06911f13 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 1 Jul 2024 23:52:06 +0800 Subject: [PATCH 13/27] Dep: Lock dependency versions things changed too much in these years --- requirements-in.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements-in.txt b/requirements-in.txt index 9b76852e6..45e225c27 100644 --- a/requirements-in.txt +++ b/requirements-in.txt @@ -1,11 +1,11 @@ # Image processing -numpy -scipy -pillow -opencv-python +numpy==1.24.3 +scipy==1.10.1 +pillow==9.5.0 +opencv-python==4.7.0.72 # Device connection -adbutils +adbutils==1.2.9 uiautomator2==2.16.17 uiautomator2cache==0.3.0.1 wrapt>=1.14.0 From 763806150ec1156005295402d7314cc8e9ad4f55 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 00:49:22 +0800 Subject: [PATCH 14/27] Dep: [ALAS] Upgrade to uiautomator2cache==0.3.1 --- requirements-in.txt | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-in.txt b/requirements-in.txt index 45e225c27..89cfec9fb 100644 --- a/requirements-in.txt +++ b/requirements-in.txt @@ -7,7 +7,7 @@ opencv-python==4.7.0.72 # Device connection adbutils==1.2.9 uiautomator2==2.16.17 -uiautomator2cache==0.3.0.1 +uiautomator2cache==0.3.1 wrapt>=1.14.0 lz4 av==10.0.0 diff --git a/requirements.txt b/requirements.txt index a1d750521..9b9760b69 100644 --- a/requirements.txt +++ b/requirements.txt @@ -75,7 +75,7 @@ tqdm==4.65.0 # via -r requirements-in.txt typing-extensions==4.8.0 # via pydantic, pydantic-core ua-parser==0.16.1 # via user-agents uiautomator2==2.16.17 # via -r requirements-in.txt -uiautomator2cache==0.3.0.1 # via -r requirements-in.txt +uiautomator2cache==0.3.1 # via -r requirements-in.txt urllib3==2.0.2 # via requests user-agents==2.2.0 # via pywebio uvicorn[standard]==0.17.6 # via -r requirements-in.txt From 487dbf140837cbfcd9c09833daa408b938391069 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 01:16:30 +0800 Subject: [PATCH 15/27] Fix: [ALAS] Patch to fix atx_agent_url on arm64-v8a --- deploy/Windows/patch.py | 32 ++++++++++++++++++++++++++++++-- module/device/method/utils.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/deploy/Windows/patch.py b/deploy/Windows/patch.py index a1d3be03f..2d1e4fb29 100644 --- a/deploy/Windows/patch.py +++ b/deploy/Windows/patch.py @@ -59,17 +59,34 @@ def patch_uiautomator2(): https://tool.appetizer.io is added to bypass the wall in China but https://tool.appetizer.io is slow outside of CN plus some CN users cannot access it for unknown reason. - So we patch `uiautomator2/init.py` to a local assets cache `uiautomator2cache/cache`. + 1. So we patch `uiautomator2/init.py` to a local assets cache `uiautomator2cache/cache`. appdir = os.path.join(os.path.expanduser('~'), '.uiautomator2') to: appdir = os.path.join(__file__, '../../uiautomator2cache') - And we also remove minicap installations since emulators doesn't need it. + 2. And we also remove minicap installations since emulators doesn't need it. for url in self.minicap_urls: self.push_url(url) to: for url in []: self.push_url(url) + + 3. Fix atx_agent_url so ARM Mac can have correct ATX installed + ``` + @property + def atx_agent_url(self): + files = { + 'armeabi-v7a': 'atx-agent_{v}_linux_armv7.tar.gz', + 'arm64-v8a': 'atx-agent_{v}_linux_armv7.tar.gz', + 'armeabi': 'atx-agent_{v}_linux_armv6.tar.gz', + 'x86': 'atx-agent_{v}_linux_386.tar.gz', + 'x86_64': 'atx-agent_{v}_linux_386.tar.gz', + } + ``` + where + 'arm64-v8a': 'atx-agent_{v}_linux_armv7.tar.gz', + to + 'arm64-v8a': 'atx-agent_{v}_linux_arm64.tar.gz', """ init_file = './toolkit/Lib/site-packages/uiautomator2/init.py' cache_dir = './toolkit/Lib/site-packages/uiautomator2cache/cache' @@ -92,6 +109,17 @@ def patch_uiautomator2(): else: logger.info(f'{init_file} minicap_urls no need to patch') + # Patch atx_agent_url + res = re.search(r"'arm64-v8a': 'atx-agent_\{v}_linux_armv7.tar.gz'", content) + if res: + content = re.sub(r"'arm64-v8a': 'atx-agent_\{v}_linux_armv7.tar.gz'", + "'arm64-v8a': 'atx-agent_{v}_linux_arm64.tar.gz'", + content) + modified = True + logger.info(f'{init_file} atx_agent_url patched') + else: + logger.info(f'{init_file} atx_agent_url no need to patch') + # Patch appdir if os.path.exists(cache_dir): res = re.search(r'appdir ?=(.*)\n', content) diff --git a/module/device/method/utils.py b/module/device/method/utils.py index 352d4361b..18aceef55 100644 --- a/module/device/method/utils.py +++ b/module/device/method/utils.py @@ -73,6 +73,38 @@ u2.setup_logger = setup_logger u2.init.setup_logger = setup_logger +# Patch Initer +class PatchedIniter(u2.init.Initer): + @property + def atx_agent_url(self): + files = { + 'armeabi-v7a': 'atx-agent_{v}_linux_armv7.tar.gz', + # 'arm64-v8a': 'atx-agent_{v}_linux_armv7.tar.gz', + 'arm64-v8a': 'atx-agent_{v}_linux_arm64.tar.gz', + 'armeabi': 'atx-agent_{v}_linux_armv6.tar.gz', + 'x86': 'atx-agent_{v}_linux_386.tar.gz', + 'x86_64': 'atx-agent_{v}_linux_386.tar.gz', + } + name = None + for abi in self.abis: + name = files.get(abi) + if name: + break + if not name: + raise Exception( + "arch(%s) need to be supported yet, please report an issue in github" + % self.abis) + return u2.init.GITHUB_BASEURL + '/atx-agent/releases/download/%s/%s' % ( + u2.version.__atx_agent_version__, name.format(v=u2.version.__atx_agent_version__)) + + @property + def minicap_urls(self): + return [] + + +u2.init.Initer = PatchedIniter + + def is_port_using(port_num): """ if port is using by others, return True. else return False """ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -394,6 +426,7 @@ class HierarchyButton: """ Element props """ + def _get_bool_prop(self, prop: str) -> bool: return self.attrib.get(prop, "").lower() == 'true' From 71e01d9bd832e45475fede588caa40e0228889f4 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 01:25:59 +0800 Subject: [PATCH 16/27] Fix: Check save file before entering ornament --- .../DIVERGENT_UNIVERSE_SAVE_UNAVAILABLE.png | Bin 0 -> 27047 bytes .../dungeon/assets/assets_dungeon_ui_rogue.py | 10 ++++++++++ tasks/ornament/combat.py | 17 +++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 assets/share/dungeon/ui_rogue/DIVERGENT_UNIVERSE_SAVE_UNAVAILABLE.png diff --git a/assets/share/dungeon/ui_rogue/DIVERGENT_UNIVERSE_SAVE_UNAVAILABLE.png b/assets/share/dungeon/ui_rogue/DIVERGENT_UNIVERSE_SAVE_UNAVAILABLE.png new file mode 100644 index 0000000000000000000000000000000000000000..977d2e3cc34ec2572f787376dacb4bc13edb162b GIT binary patch literal 27047 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 literal 0 HcmV?d00001 diff --git a/tasks/dungeon/assets/assets_dungeon_ui_rogue.py b/tasks/dungeon/assets/assets_dungeon_ui_rogue.py index 67deaf095..abf1ebbdf 100644 --- a/tasks/dungeon/assets/assets_dungeon_ui_rogue.py +++ b/tasks/dungeon/assets/assets_dungeon_ui_rogue.py @@ -13,6 +13,16 @@ DIVERGENT_UNIVERSE_LOADED = ButtonWrapper( button=(893, 608, 911, 628), ), ) +DIVERGENT_UNIVERSE_SAVE_UNAVAILABLE = ButtonWrapper( + name='DIVERGENT_UNIVERSE_SAVE_UNAVAILABLE', + share=Button( + file='./assets/share/dungeon/ui_rogue/DIVERGENT_UNIVERSE_SAVE_UNAVAILABLE.png', + area=(437, 316, 1169, 378), + search=(417, 296, 1189, 398), + color=(197, 105, 95), + button=(437, 316, 1169, 378), + ), +) LAST_TELEPORT = ButtonWrapper( name='LAST_TELEPORT', share=Button( diff --git a/tasks/ornament/combat.py b/tasks/ornament/combat.py index d35a3b838..ee8693697 100644 --- a/tasks/ornament/combat.py +++ b/tasks/ornament/combat.py @@ -23,6 +23,23 @@ class OrnamentCombat(DungeonEvent, Combat, RouteLoader): # Different position to OCR return super().get_double_event_remain_at_combat(button) + def _dungeon_wait_until_dungeon_list_loaded(self, skip_first_screenshot=True): + # Check save file before entering + result = super()._dungeon_wait_until_dungeon_list_loaded(skip_first_screenshot) + + if self.image_color_count( + DIVERGENT_UNIVERSE_SAVE_UNAVAILABLE, + color=(195, 89, 79), threshold=221, count=1000, + ): + logger.error( + 'Divergent Universe save unavailable, ' + 'please clear Divergent Universe once before running Ornament Extraction' + ) + self.config.task_delay(server_update=True) + self.config.task_stop() + + return result + def oe_leave(self, skip_first_screenshot=True): self.interval_clear([COMBAT_PREPARE, MAP_EXIT]) logger.hr('OE leave') From 4afe0bf90875d94aa533b9a59a1609a6a8deee80 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 02:41:12 +0800 Subject: [PATCH 17/27] Add: Task Ornament --- module/config/config_manual.py | 2 +- src.py | 4 ++ tasks/dungeon/dungeon.py | 66 +++++++++++++---------- tasks/dungeon/state.py | 4 +- tasks/dungeon/ui.py | 7 +++ tasks/ornament/combat.py | 54 ++++++++++++------- tasks/ornament/ornament.py | 99 ++++++++++++++++++++++++++++++++++ 7 files changed, 184 insertions(+), 52 deletions(-) create mode 100644 tasks/ornament/ornament.py diff --git a/module/config/config_manual.py b/module/config/config_manual.py index 49d693536..6fe63ba21 100644 --- a/module/config/config_manual.py +++ b/module/config/config_manual.py @@ -10,7 +10,7 @@ class ManualConfig: SCHEDULER_PRIORITY = """ Restart - > Weekly > Dungeon > Assignment + > Weekly > Ornament > Dungeon > Assignment > BattlePass > DailyQuest > Freebies > DataUpdate > Rogue diff --git a/src.py b/src.py index 2cea26a13..8acdf1957 100644 --- a/src.py +++ b/src.py @@ -58,6 +58,10 @@ class StarRailCopilot(AzurLaneAutoScript): from tasks.rogue.rogue import Rogue Rogue(config=self.config, device=self.device).run() + def ornament(self): + from tasks.ornament.ornament import Ornament + Ornament(config=self.config, device=self.device).run() + def benchmark(self): from module.daemon.benchmark import run_benchmark run_benchmark(config=self.config) diff --git a/tasks/dungeon/dungeon.py b/tasks/dungeon/dungeon.py index bb4a40a49..aeffbe13c 100644 --- a/tasks/dungeon/dungeon.py +++ b/tasks/dungeon/dungeon.py @@ -15,6 +15,7 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): achieved_daily_quest = False achieved_weekly_quest = False running_double = False + support_once = True daily_quests = [] weekly_quests = [] @@ -76,14 +77,16 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): wave_limit = relic if relic == 0: return 0 - if dungeon.is_Ornament_Extraction and self.running_double and \ - self.config.stored.DungeonDouble.rogue > 0: - rogue = self.get_double_event_remain_at_combat() - if rogue is not None and rogue < self.config.stored.DungeonDouble.rogue: - self.config.stored.DungeonDouble.rogue = rogue - wave_limit = rogue - if rogue == 0: - return 0 + # No need, already checked in Survival_Index + # if dungeon.is_Ornament_Extraction and self.running_double and \ + # self.config.stored.DungeonDouble.rogue > 0: + # rogue = self.get_double_event_remain_at_combat() + # if rogue is not None and rogue < self.config.stored.DungeonDouble.rogue: + # self.config.stored.DungeonDouble.rogue = rogue + # wave_limit = rogue + # if rogue == 0: + # return 0 + # Combat self.dungeon = dungeon count = self.combat(team=team, wave_limit=wave_limit, support_character=support_character) @@ -177,7 +180,7 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): out: page_main """ require = self.require_compulsory_support() - if require: + if require and self.support_once: logger.info('Run once with support') count = self._dungeon_run(dungeon=dungeon, team=team, wave_limit=1, support_character=self.config.DungeonSupport_Character) @@ -192,22 +195,22 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): return count + elif require and not self.support_once: + # Run with support all the way + return self._dungeon_run(dungeon=dungeon, team=team, wave_limit=1, + support_character=self.config.DungeonSupport_Character) + else: # Normal run return self._dungeon_run(dungeon=dungeon, team=team, wave_limit=wave_limit, support_character=support_character) - def run(self): - self.config.update_battle_pass_quests() - self.config.update_daily_quests() - self.check_synthesize() - self.called_daily_support = False - self.achieved_daily_quest = False - self.achieved_weekly_quest = False - self.running_double = False - self.daily_quests = self.config.stored.DailyQuest.load_quests() - self.weekly_quests = self.config.stored.BattlePassWeeklyQuest.load_quests() - + def update_double_event_record(self): + """ + Pages: + in: Any + out: page_guide, Survival_Index + """ # Update double event records if (self.config.stored.DungeonDouble.is_expired() or self.config.stored.DungeonDouble.calyx > 0 @@ -216,7 +219,8 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): logger.info('Get dungeon double remains') # UI switches switched = self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) - if not switched: + if not switched and not self._dungeon_survival_index_top_appear(): + logger.info('Reset nav states') # Nav must at top, reset nav states self.ui_goto_main() self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) @@ -237,6 +241,18 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): self.config.stored.DungeonDouble.relic = relic self.config.stored.DungeonDouble.rogue = rogue + def run(self): + self.config.update_battle_pass_quests() + self.config.update_daily_quests() + self.check_synthesize() + self.called_daily_support = False + self.achieved_daily_quest = False + self.achieved_weekly_quest = False + self.running_double = False + self.daily_quests = self.config.stored.DailyQuest.load_quests() + self.weekly_quests = self.config.stored.BattlePassWeeklyQuest.load_quests() + self.update_double_event_record() + # Run double events planner = self.planner.get_dungeon(double_calyx=True) # Double calyx @@ -274,14 +290,6 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): final = planner self.is_doing_planner = True - # Check daily - if self.achieved_daily_quest: - self.config.task_call('DailyQuest') - self.config.task_stop() - if self.achieved_weekly_quest: - self.config.task_call('BattlePass') - self.config.task_stop() - # Use all stamina if do_rogue: # Use support if prioritize rogue diff --git a/tasks/dungeon/state.py b/tasks/dungeon/state.py index 5db8b98a0..6a1a042ed 100644 --- a/tasks/dungeon/state.py +++ b/tasks/dungeon/state.py @@ -131,7 +131,7 @@ class DungeonState(UI): """ Delay tasks that use stamina """ - if dungeon.is_Simulated_Universe: + if dungeon.is_Simulated_Universe or dungeon.is_Ornament_Extraction: limit = 80 elif dungeon.is_Cavern_of_Corrosion: limit = 80 @@ -182,7 +182,7 @@ class DungeonState(UI): logger.info(f'Approaching next monday, delay to {next_monday} instead') future = next_monday - tasks = ['Dungeon', 'Weekly'] + tasks = ['Dungeon', 'Weekly', 'Ornament'] with self.config.multi_set(): for task in tasks: next_run = self.config.cross_get(keys=f'{task}.Scheduler.NextRun', default=DEFAULT_TIME) diff --git a/tasks/dungeon/ui.py b/tasks/dungeon/ui.py index 8caa5d512..08b48554c 100644 --- a/tasks/dungeon/ui.py +++ b/tasks/dungeon/ui.py @@ -311,6 +311,13 @@ class DungeonUI(DungeonState): logger.info('Survival index loaded, SURVIVAL_INDEX_OE_LOADED') return True + def _dungeon_survival_index_top_appear(self): + if self.appear(SURVIVAL_INDEX_SU_LOADED): + return True + if self.appear(SURVIVAL_INDEX_OE_LOADED): + return True + return False + def _dungeon_wait_treasures_lightward_loaded(self, skip_first_screenshot=True): """ Returns: diff --git a/tasks/ornament/combat.py b/tasks/ornament/combat.py index ee8693697..37c434003 100644 --- a/tasks/ornament/combat.py +++ b/tasks/ornament/combat.py @@ -5,15 +5,15 @@ from tasks.base.assets.assets_base_page import MAP_EXIT from tasks.base.assets.assets_base_popup import POPUP_CANCEL from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_LIST -from tasks.combat.combat import Combat -from tasks.dungeon.event import DungeonEvent +from tasks.dungeon.dungeon import Dungeon +from tasks.dungeon.state import DungeonState from tasks.map.route.loader import RouteLoader from tasks.map.route.route.daily import OrnamentExtraction__route from tasks.ornament.assets.assets_ornament_combat import * from tasks.ornament.assets.assets_ornament_ui import * -class OrnamentCombat(DungeonEvent, Combat, RouteLoader): +class OrnamentCombat(Dungeon, RouteLoader, DungeonState): def combat_enter_from_map(self, skip_first_screenshot=True): # Don't enter from map, UI too deep inside # Enter from survival index instead @@ -23,23 +23,6 @@ class OrnamentCombat(DungeonEvent, Combat, RouteLoader): # Different position to OCR return super().get_double_event_remain_at_combat(button) - def _dungeon_wait_until_dungeon_list_loaded(self, skip_first_screenshot=True): - # Check save file before entering - result = super()._dungeon_wait_until_dungeon_list_loaded(skip_first_screenshot) - - if self.image_color_count( - DIVERGENT_UNIVERSE_SAVE_UNAVAILABLE, - color=(195, 89, 79), threshold=221, count=1000, - ): - logger.error( - 'Divergent Universe save unavailable, ' - 'please clear Divergent Universe once before running Ornament Extraction' - ) - self.config.task_delay(server_update=True) - self.config.task_stop() - - return result - def oe_leave(self, skip_first_screenshot=True): self.interval_clear([COMBAT_PREPARE, MAP_EXIT]) logger.hr('OE leave') @@ -121,6 +104,32 @@ class OrnamentCombat(DungeonEvent, Combat, RouteLoader): self.interval_reset(COMBAT_SUPPORT_LIST) continue + def combat_get_trailblaze_power(self, expect_reduce=False, skip_first_screenshot=True) -> int: + """ + Args: + expect_reduce: Current value is supposed to be lower than the previous. + skip_first_screenshot: + + Returns: + int: Equivalent stamina + + Pages: + in: COMBAT_PREPARE or COMBAT_REPEAT + """ + before = self.config.stored.TrailblazePower.value + self.config.stored.Immersifier.value * 40 + + after = before + for _ in range(3): + self.dungeon_update_stamina() + after = self.config.stored.TrailblazePower.value + self.config.stored.Immersifier.value * 40 + if expect_reduce: + if before > after: + break + else: + break + + return after + def is_team_prepared(self) -> bool: """ Pages: @@ -169,7 +178,11 @@ class OrnamentCombat(DungeonEvent, Combat, RouteLoader): # End if self.is_in_main(): logger.info('Combat map entered') + self.device.screenshot_interval_set() break + if self.is_combat_executing(): + self.device.screenshot_interval_set() + return True # Relics full # Clicking between COMBAT_PREPARE and COMBAT_TEAM_PREPARE if trial > 5: @@ -187,6 +200,7 @@ class OrnamentCombat(DungeonEvent, Combat, RouteLoader): if support_set and self.appear(COMBAT_PREPARE, interval=5): # Long loading after COMBAT_PREPARE self.device.click(COMBAT_PREPARE) + self.device.screenshot_interval_set('combat') trial += 1 continue if self.handle_popup_confirm(): diff --git a/tasks/ornament/ornament.py b/tasks/ornament/ornament.py new file mode 100644 index 000000000..6b998dd1d --- /dev/null +++ b/tasks/ornament/ornament.py @@ -0,0 +1,99 @@ +from datetime import timedelta + +from module.config.stored.classes import now +from module.config.utils import DEFAULT_TIME +from module.exception import ScriptError +from module.logger import logger +from tasks.dungeon.assets.assets_dungeon_ui_rogue import DIVERGENT_UNIVERSE_SAVE_UNAVAILABLE +from tasks.dungeon.keywords import DungeonList +from tasks.ornament.combat import OrnamentCombat + + +class Ornament(OrnamentCombat): + # Reuse support, cause exit and re-enter is so time-wasting in Divergent Universe + support_once = False + + def _dungeon_wait_until_dungeon_list_loaded(self, skip_first_screenshot=True): + + result = super()._dungeon_wait_until_dungeon_list_loaded(skip_first_screenshot) + + # Check save file before entering + if self.image_color_count( + DIVERGENT_UNIVERSE_SAVE_UNAVAILABLE, + color=(195, 89, 79), threshold=221, count=1000, + ): + logger.error( + 'Divergent Universe save unavailable, ' + 'please clear Divergent Universe once before running Ornament Extraction' + ) + self.config.task_delay(server_update=True) + self.config.task_stop() + + # Always update double rogue + record = self.config.stored.DungeonDouble.time + if now() - record < timedelta(seconds=5): + # Updated just now + pass + else: + if self.has_double_relic_event(): + rogue = self.get_double_rogue_remain() + self.config.stored.DungeonDouble.rogue = rogue + else: + logger.info('No double rogue event') + + # Check stamina + logger.info('Check stamina') + stamina = self.combat_get_trailblaze_power() + if stamina < self.combat_wave_cost: + logger.info('Current trailblaze power is not enough for a run') + self.delay_dungeon_task(self.dungeon) + self.config.task_stop() + if not self.config.Ornament_UseStamina and self.config.stored.DungeonDouble.rogue <= 0: + if self.config.stored.Immersifier.value <= 0: + logger.info('Current immersifier is not enough for a run') + self.delay_dungeon_task(self.dungeon) + self.config.task_stop() + + return result + + def run(self): + self.config.update_battle_pass_quests() + self.config.update_daily_quests() + # self.check_synthesize() + self.called_daily_support = False + self.achieved_daily_quest = False + self.achieved_weekly_quest = False + self.running_double = False + self.daily_quests = self.config.stored.DailyQuest.load_quests() + self.weekly_quests = self.config.stored.BattlePassWeeklyQuest.load_quests() + self.update_double_event_record() + + # During double event, do it first + if self.config.stored.DungeonDouble.calyx or self.config.stored.DungeonDouble.relic: + logger.info('During double calyx or relic event, delay Ornament') + future = self.config.cross_get('Dungeon.Scheduler.NextRun', default=DEFAULT_TIME) + future = future + timedelta(minutes=1) + with self.config.multi_set(): + self.config.task_delay(target=future) + self.config.task_stop() + + # Run + dungeon = DungeonList.find(self.config.Ornament_Dungeon) + self.combat_wave_cost = 40 + self.dungeon = dungeon + if self.config.Ornament_UseStamina: + # No limit + self.dungeon_run(dungeon, wave_limit=0) + # Stamina should have exhausted in dungeon_run + raise ScriptError('Ornament finished but stamina was not exhausted') + elif self.config.stored.DungeonDouble.rogue > 0: + # Limited in double events + self.running_double = True + self.dungeon_run(dungeon, wave_limit=self.config.stored.DungeonDouble.rogue) + self.running_double = False + + self.config.task_delay(server_update=True) + else: + # Use immersifier only, wave limited in _dungeon_wait_until_dungeon_list_loaded + self.dungeon_run(dungeon, wave_limit=0) + self.config.task_delay(server_update=True) From 6c80316a0c4ca5ae7c8732d7ccaec80ee2ad5644 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 02:52:09 +0800 Subject: [PATCH 18/27] Fix: combat_wave_cost was cleared after battle --- tasks/combat/combat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/combat/combat.py b/tasks/combat/combat.py index a34165c95..fd58c9d1b 100644 --- a/tasks/combat/combat.py +++ b/tasks/combat/combat.py @@ -402,10 +402,10 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo finish = self.combat_finish() if self._combat_should_reenter(): continue - # Reset combat_wave_cost, so handle_combat_interact() won't activate before handle_combat_prepare() - self.combat_wave_cost = 10 if finish: break + # Reset combat_wave_cost, so handle_combat_interact() won't activate before handle_combat_prepare() + self.combat_wave_cost = 10 logger.attr('combat_wave_done', self.combat_wave_done) return self.combat_wave_done From a11118dd491bd117cf060a5710d0faaf0607d178 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 03:00:21 +0800 Subject: [PATCH 19/27] Fix: Limit combinations --- module/config/argument/args.json | 3 +-- module/config/argument/override.yaml | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/module/config/argument/args.json b/module/config/argument/args.json index d1946f162..d1b6c1ecc 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -1861,9 +1861,8 @@ "type": "select", "value": "when_daily", "option": [ - "always_use", "when_daily", - "do_not_use" + "always_use" ] }, "Character": { diff --git a/module/config/argument/override.yaml b/module/config/argument/override.yaml index 29fb499e7..119d52a03 100644 --- a/module/config/argument/override.yaml +++ b/module/config/argument/override.yaml @@ -68,3 +68,7 @@ Weekly: DungeonSupport: Use: option: [ always_use, do_not_use ] +Ornament: + DungeonSupport: + Use: + option: [ when_daily, always_use ] From 02df312daa0acf3eb0008aa515f6f4029191c3be Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 03:40:23 +0800 Subject: [PATCH 20/27] Opt: Remove DailyQuest states, show stored values --- config/template.json | 38 +- module/config/argument/args.json | 456 ++--------------------- module/config/argument/argument.yaml | 37 +- module/config/argument/stored.json | 72 ++-- module/config/argument/task.yaml | 3 +- module/config/config_generated.py | 38 +- module/config/config_updater.py | 62 --- module/config/i18n/en-US.json | 240 ++---------- module/config/i18n/es-ES.json | 238 ++---------- module/config/i18n/ja-JP.json | 224 +---------- module/config/i18n/zh-CN.json | 240 ++---------- module/config/i18n/zh-TW.json | 240 ++---------- module/config/stored/stored_generated.py | 6 +- 13 files changed, 226 insertions(+), 1668 deletions(-) diff --git a/config/template.json b/config/template.json index 20d8dccad..32ab57133 100644 --- a/config/template.json +++ b/config/template.json @@ -24,11 +24,6 @@ "ScreenshotInterval": 0.2, "CombatScreenshotInterval": 1.0, "WhenTaskQueueEmpty": "goto_main" - }, - "CloudStorage": { - "CloudRemainSeasonPass": {}, - "CloudRemainPaid": {}, - "CloudRemainFree": {} } }, "Restart": { @@ -125,34 +120,6 @@ "Command": "DailyQuest", "ServerUpdate": "04:00" }, - "AchievableQuest": { - "Complete_1_Daily_Mission": "not_supported", - "Clear_Calyx_Golden_1_times": "not_set", - "Clear_Stagnant_Shadow_1_times": "not_set", - "Clear_Cavern_of_Corrosion_1_times": "not_set", - "In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": "achievable", - "Inflict_Weakness_Break_5_times": "achievable", - "Defeat_a_total_of_20_enemies": "achievable", - "Complete_Forgotten_Hall_1_time": "achievable", - "Complete_Echo_of_War_1_times": "not_set", - "Use_an_Ultimate_to_deal_the_final_blow_1_time": "achievable", - "Salvage_any_Relic": "achievable", - "Use_Consumables_1_time": "achievable", - "Log_in_to_the_game": "achievable", - "Dispatch_1_assignments": "achievable", - "Complete_Divergent_Universe_or_Simulated_Universe_1_times": "not_set", - "Clear_Calyx_Crimson_1_times": "not_set", - "Enter_combat_by_attacking_enemie_Weakness_and_win_3_times": "achievable", - "Use_Technique_2_times": "achievable", - "Destroy_3_destructible_objects": "achievable", - "Obtain_victory_in_combat_with_Support_Characters_1_times": "achievable", - "Level_up_any_character_1_times": "not_supported", - "Level_up_any_Light_Cone_1_times": "not_supported", - "Use_the_Omni_Synthesizer_1_times": "achievable", - "Take_photos_1_times": "achievable", - "Consume_120_Trailblaze_Power": "achievable", - "Level_up_any_Relic_1_times": "not_supported" - }, "DailyStorage": { "DailyActivity": {}, "DailyQuest": {} @@ -204,6 +171,11 @@ "ItemStorage": { "Credit": {}, "StallerJade": {} + }, + "CloudStorage": { + "CloudRemainSeasonPass": {}, + "CloudRemainPaid": {}, + "CloudRemainFree": {} } }, "Freebies": { diff --git a/module/config/argument/args.json b/module/config/argument/args.json index d1b6c1ecc..ff7a1a043 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -140,26 +140,6 @@ "close_game" ] } - }, - "CloudStorage": { - "CloudRemainSeasonPass": { - "type": "stored", - "value": {}, - "display": "hide", - "stored": "StoredInt" - }, - "CloudRemainPaid": { - "type": "stored", - "value": {}, - "display": "hide", - "stored": "StoredInt" - }, - "CloudRemainFree": { - "type": "stored", - "value": {}, - "display": "hide", - "stored": "StoredInt" - } } }, "Restart": { @@ -788,403 +768,11 @@ "display": "hide" } }, - "AchievableQuest": { - "Complete_1_Daily_Mission": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Clear_Calyx_Golden_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Clear_Stagnant_Shadow_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Clear_Cavern_of_Corrosion_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Inflict_Weakness_Break_5_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Defeat_a_total_of_20_enemies": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Complete_Forgotten_Hall_1_time": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Complete_Echo_of_War_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Use_an_Ultimate_to_deal_the_final_blow_1_time": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Salvage_any_Relic": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Use_Consumables_1_time": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Log_in_to_the_game": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Dispatch_1_assignments": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Complete_Divergent_Universe_or_Simulated_Universe_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Clear_Calyx_Crimson_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Enter_combat_by_attacking_enemie_Weakness_and_win_3_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Use_Technique_2_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Destroy_3_destructible_objects": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Obtain_victory_in_combat_with_Support_Characters_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Level_up_any_character_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Level_up_any_Light_Cone_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Use_the_Omni_Synthesizer_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Take_photos_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Consume_120_Trailblaze_Power": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - }, - "Level_up_any_Relic_1_times": { - "type": "state", - "value": "achievable", - "option": [ - "achievable", - "not_set", - "not_supported" - ], - "option_bold": [ - "achievable" - ], - "option_light": [ - "not_supported" - ] - } - }, "DailyStorage": { "DailyActivity": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredDailyActivity", "order": 2, "color": "#ffcf70" @@ -1192,7 +780,7 @@ "DailyQuest": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredDaily" } } @@ -1229,7 +817,7 @@ "BattlePassLevel": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredBattlePassLevel", "order": 5, "color": "#cbe45b" @@ -1243,43 +831,43 @@ "BattlePassSimulatedUniverse": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredBattlePassSimulatedUniverse" }, "BattlePassQuestCalyx": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredBattlePassQuestCalyx" }, "BattlePassQuestEchoOfWar": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredBattlePassQuestEchoOfWar" }, "BattlePassQuestCredits": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredBattlePassQuestCredits" }, "BattlePassQuestSynthesizeConsumables": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredBattlePassQuestSynthesizeConsumables" }, "BattlePassQuestCavernOfCorrosion": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredBattlePassQuestCavernOfCorrosion" }, "BattlePassQuestTrailblazePower": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredBattlePassQuestTrailblazePower" } } @@ -1469,7 +1057,7 @@ "Credit": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredInt", "order": 7, "color": "#ab7cf2" @@ -1477,11 +1065,31 @@ "StallerJade": { "type": "stored", "value": {}, - "display": "hide", + "display": "display", "stored": "StoredInt", "order": 8, "color": "#fc8f8b" } + }, + "CloudStorage": { + "CloudRemainSeasonPass": { + "type": "stored", + "value": {}, + "display": "display", + "stored": "StoredInt" + }, + "CloudRemainPaid": { + "type": "stored", + "value": {}, + "display": "display", + "stored": "StoredInt" + }, + "CloudRemainFree": { + "type": "stored", + "value": {}, + "display": "display", + "stored": "StoredInt" + } } }, "Freebies": { diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index 7d217a1f5..f98b1d85b 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -86,13 +86,6 @@ Optimization: WhenTaskQueueEmpty: value: goto_main option: [ stay_there, goto_main, close_game ] -CloudStorage: - CloudRemainSeasonPass: - stored: StoredInt - CloudRemainPaid: - stored: StoredInt - CloudRemainFree: - stored: StoredInt # ==================== Daily ==================== @@ -152,43 +145,46 @@ Weekly: value: 1 option: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] -AchievableQuest: -# Quests will be injected in config updater -# Complete_1_Daily_Mission: -# type: state -# value: achievable -# option: [ achievable, not_set, not_supported ] -# option_bold: [ achievable, ] DailyStorage: DailyActivity: stored: StoredDailyActivity order: 2 color: "#ffcf70" + display: display DailyQuest: stored: StoredDaily + display: display BattlePassStorage: BattlePassLevel: stored: StoredBattlePassLevel order: 5 color: "#cbe45b" + display: display BattlePassWeeklyQuest: stored: StoredBattlePassWeeklyQuest # Quests progress BattlePassSimulatedUniverse: stored: StoredBattlePassSimulatedUniverse + display: display BattlePassQuestCalyx: stored: StoredBattlePassQuestCalyx + display: display BattlePassQuestEchoOfWar: stored: StoredBattlePassQuestEchoOfWar + display: display BattlePassQuestCredits: stored: StoredBattlePassQuestCredits + display: display BattlePassQuestSynthesizeConsumables: stored: StoredBattlePassQuestSynthesizeConsumables + display: display BattlePassQuestCavernOfCorrosion: stored: StoredBattlePassQuestCavernOfCorrosion + display: display BattlePassQuestTrailblazePower: stored: StoredBattlePassQuestTrailblazePower + display: display Assignment: # Options in Name_x will be injected in config updater @@ -218,10 +214,23 @@ ItemStorage: stored: StoredInt order: 7 color: "#ab7cf2" + display: display StallerJade: stored: StoredInt order: 8 color: "#fc8f8b" + display: display + +CloudStorage: + CloudRemainSeasonPass: + stored: StoredInt + display: display + CloudRemainPaid: + stored: StoredInt + display: display + CloudRemainFree: + stored: StoredInt + display: display # ==================== Rogue ==================== diff --git a/module/config/argument/stored.json b/module/config/argument/stored.json index eb2211c04..4886e0a0d 100644 --- a/module/config/argument/stored.json +++ b/module/config/argument/stored.json @@ -101,42 +101,6 @@ "order": 8, "color": "#fc8f8b" }, - "CloudRemainSeasonPass": { - "name": "CloudRemainSeasonPass", - "path": "Alas.CloudStorage.CloudRemainSeasonPass", - "i18n": "CloudStorage.CloudRemainSeasonPass.name", - "stored": "StoredInt", - "attrs": { - "time": "2020-01-01 00:00:00", - "value": 0 - }, - "order": 0, - "color": "#777777" - }, - "CloudRemainPaid": { - "name": "CloudRemainPaid", - "path": "Alas.CloudStorage.CloudRemainPaid", - "i18n": "CloudStorage.CloudRemainPaid.name", - "stored": "StoredInt", - "attrs": { - "time": "2020-01-01 00:00:00", - "value": 0 - }, - "order": 0, - "color": "#777777" - }, - "CloudRemainFree": { - "name": "CloudRemainFree", - "path": "Alas.CloudStorage.CloudRemainFree", - "i18n": "CloudStorage.CloudRemainFree.name", - "stored": "StoredInt", - "attrs": { - "time": "2020-01-01 00:00:00", - "value": 0 - }, - "order": 0, - "color": "#777777" - }, "Item_Credit": { "name": "Item_Credit", "path": "Dungeon.Planner.Item_Credit", @@ -868,6 +832,42 @@ "order": 0, "color": "#777777" }, + "CloudRemainSeasonPass": { + "name": "CloudRemainSeasonPass", + "path": "DataUpdate.CloudStorage.CloudRemainSeasonPass", + "i18n": "CloudStorage.CloudRemainSeasonPass.name", + "stored": "StoredInt", + "attrs": { + "time": "2020-01-01 00:00:00", + "value": 0 + }, + "order": 0, + "color": "#777777" + }, + "CloudRemainPaid": { + "name": "CloudRemainPaid", + "path": "DataUpdate.CloudStorage.CloudRemainPaid", + "i18n": "CloudStorage.CloudRemainPaid.name", + "stored": "StoredInt", + "attrs": { + "time": "2020-01-01 00:00:00", + "value": 0 + }, + "order": 0, + "color": "#777777" + }, + "CloudRemainFree": { + "name": "CloudRemainFree", + "path": "DataUpdate.CloudStorage.CloudRemainFree", + "i18n": "CloudStorage.CloudRemainFree.name", + "stored": "StoredInt", + "attrs": { + "time": "2020-01-01 00:00:00", + "value": 0 + }, + "order": 0, + "color": "#777777" + }, "SimulatedUniverseFarm": { "name": "SimulatedUniverseFarm", "path": "Rogue.RogueWorld.SimulatedUniverseFarm", diff --git a/module/config/argument/task.yaml b/module/config/argument/task.yaml index 293d135e0..38d173565 100644 --- a/module/config/argument/task.yaml +++ b/module/config/argument/task.yaml @@ -13,7 +13,6 @@ Alas: - EmulatorInfo - Error - Optimization - - CloudStorage Restart: - Scheduler @@ -31,7 +30,6 @@ Daily: - DungeonStorage DailyQuest: - Scheduler - - AchievableQuest - DailyStorage BattlePass: - Scheduler @@ -42,6 +40,7 @@ Daily: DataUpdate: - Scheduler - ItemStorage + - CloudStorage Freebies: - Scheduler - SupportReward diff --git a/module/config/config_generated.py b/module/config/config_generated.py index ebb709122..8bc01c1ef 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -40,11 +40,6 @@ class GeneratedConfig: Optimization_CombatScreenshotInterval = 1.0 Optimization_WhenTaskQueueEmpty = 'goto_main' # stay_there, goto_main, close_game - # Group `CloudStorage` - CloudStorage_CloudRemainSeasonPass = {} - CloudStorage_CloudRemainPaid = {} - CloudStorage_CloudRemainFree = {} - # Group `Dungeon` Dungeon_Name = 'Calyx_Golden_Treasures_Jarilo_VI' # Calyx_Golden_Memories_Jarilo_VI, Calyx_Golden_Memories_The_Xianzhou_Luofu, Calyx_Golden_Memories_Penacony, Calyx_Golden_Aether_Jarilo_VI, Calyx_Golden_Aether_The_Xianzhou_Luofu, Calyx_Golden_Aether_Penacony, Calyx_Golden_Treasures_Jarilo_VI, Calyx_Golden_Treasures_The_Xianzhou_Luofu, Calyx_Golden_Treasures_Penacony, Calyx_Crimson_Destruction_Herta_StorageZone, Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape, Calyx_Crimson_Preservation_Herta_SupplyZone, Calyx_Crimson_Preservation_Penacony_ClockStudiosThemePark, Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains, Calyx_Crimson_The_Hunt_Penacony_SoulGladScorchsandAuditionVenue, Calyx_Crimson_Abundance_Jarilo_BackwaterPass, Calyx_Crimson_Abundance_Luofu_FyxestrollGarden, Calyx_Crimson_Erudition_Jarilo_RivetTown, Calyx_Crimson_Erudition_Penacony_PenaconyGrandTheater, Calyx_Crimson_Harmony_Jarilo_RobotSettlement, Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape, Calyx_Crimson_Nihility_Jarilo_GreatMine, Calyx_Crimson_Nihility_Luofu_AlchemyCommission, Stagnant_Shadow_Spike, Stagnant_Shadow_Perdition, Stagnant_Shadow_Duty, Stagnant_Shadow_Blaze, Stagnant_Shadow_Scorch, Stagnant_Shadow_Ire, Stagnant_Shadow_Rime, Stagnant_Shadow_Icicle, Stagnant_Shadow_Nectar, Stagnant_Shadow_Fulmination, Stagnant_Shadow_Doom, Stagnant_Shadow_Gust, Stagnant_Shadow_Celestial, Stagnant_Shadow_Quanta, Stagnant_Shadow_Abomination, Stagnant_Shadow_Roast, Stagnant_Shadow_Mirage, Stagnant_Shadow_Puppetry, Cavern_of_Corrosion_Path_of_Gelid_Wind, Cavern_of_Corrosion_Path_of_Jabbing_Punch, Cavern_of_Corrosion_Path_of_Drifting, Cavern_of_Corrosion_Path_of_Providence, Cavern_of_Corrosion_Path_of_Holy_Hymn, Cavern_of_Corrosion_Path_of_Conflagration, Cavern_of_Corrosion_Path_of_Elixir_Seekers, Cavern_of_Corrosion_Path_of_Darkness, Cavern_of_Corrosion_Path_of_Dreamdive, Cavern_of_Corrosion_Path_of_Cavalier Dungeon_NameAtDoubleCalyx = 'Calyx_Golden_Treasures_Jarilo_VI' # Calyx_Golden_Memories_Jarilo_VI, Calyx_Golden_Memories_The_Xianzhou_Luofu, Calyx_Golden_Memories_Penacony, Calyx_Golden_Aether_Jarilo_VI, Calyx_Golden_Aether_The_Xianzhou_Luofu, Calyx_Golden_Aether_Penacony, Calyx_Golden_Treasures_Jarilo_VI, Calyx_Golden_Treasures_The_Xianzhou_Luofu, Calyx_Golden_Treasures_Penacony, Calyx_Crimson_Destruction_Herta_StorageZone, Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape, Calyx_Crimson_Preservation_Herta_SupplyZone, Calyx_Crimson_Preservation_Penacony_ClockStudiosThemePark, Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains, Calyx_Crimson_The_Hunt_Penacony_SoulGladScorchsandAuditionVenue, Calyx_Crimson_Abundance_Jarilo_BackwaterPass, Calyx_Crimson_Abundance_Luofu_FyxestrollGarden, Calyx_Crimson_Erudition_Jarilo_RivetTown, Calyx_Crimson_Erudition_Penacony_PenaconyGrandTheater, Calyx_Crimson_Harmony_Jarilo_RobotSettlement, Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape, Calyx_Crimson_Nihility_Jarilo_GreatMine, Calyx_Crimson_Nihility_Luofu_AlchemyCommission @@ -123,34 +118,6 @@ class GeneratedConfig: Weekly_Name = 'Echo_of_War_Divine_Seed' # Echo_of_War_Destruction_Beginning, Echo_of_War_End_of_the_Eternal_Freeze, Echo_of_War_Divine_Seed, Echo_of_War_Borehole_Planet_Old_Crater, Echo_of_War_Salutations_of_Ashen_Dreams Weekly_Team = 1 # 1, 2, 3, 4, 5, 6, 7, 8, 9 - # Group `AchievableQuest` - AchievableQuest_Complete_1_Daily_Mission = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Clear_Calyx_Golden_1_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Clear_Stagnant_Shadow_1_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Clear_Cavern_of_Corrosion_1_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_In_a_single_battle_inflict_3_Weakness_Break_of_different_Types = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Inflict_Weakness_Break_5_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Defeat_a_total_of_20_enemies = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Complete_Forgotten_Hall_1_time = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Complete_Echo_of_War_1_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Use_an_Ultimate_to_deal_the_final_blow_1_time = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Salvage_any_Relic = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Use_Consumables_1_time = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Log_in_to_the_game = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Dispatch_1_assignments = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Complete_Divergent_Universe_or_Simulated_Universe_1_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Clear_Calyx_Crimson_1_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Enter_combat_by_attacking_enemie_Weakness_and_win_3_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Use_Technique_2_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Destroy_3_destructible_objects = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Obtain_victory_in_combat_with_Support_Characters_1_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Level_up_any_character_1_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Level_up_any_Light_Cone_1_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Use_the_Omni_Synthesizer_1_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Take_photos_1_times = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Consume_120_Trailblaze_Power = 'achievable' # achievable, not_set, not_supported - AchievableQuest_Level_up_any_Relic_1_times = 'achievable' # achievable, not_set, not_supported - # Group `DailyStorage` DailyStorage_DailyActivity = {} DailyStorage_DailyQuest = {} @@ -179,6 +146,11 @@ class GeneratedConfig: ItemStorage_Credit = {} ItemStorage_StallerJade = {} + # Group `CloudStorage` + CloudStorage_CloudRemainSeasonPass = {} + CloudStorage_CloudRemainPaid = {} + CloudStorage_CloudRemainFree = {} + # Group `RogueWorld` RogueWorld_World = 'Simulated_Universe_World_7' # Simulated_Universe_World_3, Simulated_Universe_World_4, Simulated_Universe_World_5, Simulated_Universe_World_6, Simulated_Universe_World_7, Simulated_Universe_World_8 RogueWorld_Path = 'The_Hunt' # Preservation, Remembrance, Nihility, Abundance, The_Hunt, Destruction, Elation, Propagation, Erudition diff --git a/module/config/config_updater.py b/module/config/config_updater.py index 96922eba2..2f10e12cf 100644 --- a/module/config/config_updater.py +++ b/module/config/config_updater.py @@ -104,17 +104,6 @@ class ConfigGenerator: characters = [character.name for character in CharacterList.instances.values() if character.name not in unsupported_characters] option_add(keys='DungeonSupport.Character.option', options=characters) - # Insert daily quests - from tasks.daily.keywords import DailyQuest - for quest in DailyQuest.instances.values(): - quest: DailyQuest - deep_set(raw, keys=['AchievableQuest', quest.name], value={ - 'type': 'state', - 'value': 'achievable', - 'option': ['achievable', 'not_set', 'not_supported'], - 'option_bold': ['achievable'], - 'option_light': ['not_supported'], - }) # Insert assignments from tasks.assignment.keywords import AssignmentEntry assignments = [entry.name for entry in AssignmentEntry.instances.values()] @@ -479,18 +468,6 @@ class ConfigGenerator: continue deep_set(new, keys=['DungeonSupport', 'Character', character.name], value=value) - # Daily quests - from tasks.daily.keywords import DailyQuest - for quest in DailyQuest.instances.values(): - value = quest.__getattribute__(ingame_lang) - deep_set(new, keys=['AchievableQuest', quest.name, 'name'], value=value) - # deep_set(new, keys=['DailyQuest', quest.name, 'help'], value='') - copy_from = 'Complete_1_Daily_Mission' - if quest.name != copy_from: - for option in deep_get(self.args, keys=['DailyQuest', 'AchievableQuest', copy_from, 'option']): - value = deep_get(new, keys=['AchievableQuest', copy_from, option]) - deep_set(new, keys=['AchievableQuest', quest.name, option], value=value) - # Assignments from tasks.assignment.keywords import AssignmentEntryDetailed for entry in AssignmentEntryDetailed.instances.values(): @@ -791,45 +768,6 @@ class ConfigUpdater: @staticmethod def update_state(data): - def set_daily(quest, value): - if value is True: - value = 'achievable' - if value is False: - value = 'not_set' - deep_set(data, keys=['DailyQuest', 'AchievableQuest', quest], value=value) - - set_daily('Complete_1_Daily_Mission', 'not_supported') - # Dungeon - dungeon = deep_get(data, keys='Dungeon.Scheduler.Enable') - set_daily('Clear_Calyx_Golden_1_times', 'not_set') - set_daily('Clear_Calyx_Crimson_1_times', 'not_set') - set_daily('Clear_Stagnant_Shadow_1_times', 'not_set') - set_daily('Clear_Cavern_of_Corrosion_1_times', 'not_set') - # Combat requirements - set_daily('In_a_single_battle_inflict_3_Weakness_Break_of_different_Types', 'achievable') - set_daily('Inflict_Weakness_Break_5_times', 'achievable') - set_daily('Defeat_a_total_of_20_enemies', 'achievable') - set_daily('Enter_combat_by_attacking_enemie_Weakness_and_win_3_times', 'achievable') - set_daily('Use_Technique_2_times', 'achievable') - # Other game systems - set_daily('Dispatch_1_assignments', deep_get(data, 'Assignment.Scheduler.Enable')) - set_daily('Take_photos_1_times', 'achievable') - set_daily('Destroy_3_destructible_objects', 'achievable') - set_daily('Complete_Forgotten_Hall_1_time', 'achievable') - set_daily('Complete_Echo_of_War_1_times', deep_get(data, 'Weekly.Scheduler.Enable')) - set_daily('Complete_Divergent_Universe_or_Simulated_Universe_1_times',deep_get(data, 'Rogue.Scheduler.Enable')) - set_daily('Obtain_victory_in_combat_with_Support_Characters_1_times', - dungeon and deep_get(data, 'Dungeon.DungeonSupport.Use') in ['when_daily', 'always_use']) - set_daily('Use_an_Ultimate_to_deal_the_final_blow_1_time', 'achievable') - # Build - set_daily('Level_up_any_character_1_times', 'not_supported') - set_daily('Level_up_any_Light_Cone_1_times', 'not_supported') - set_daily('Level_up_any_Relic_1_times', 'not_supported') - # Items - set_daily('Salvage_any_Relic', 'achievable') - set_daily('Use_the_Omni_Synthesizer_1_times', 'achievable') - set_daily('Use_Consumables_1_time', 'achievable') - # Limit setting combinations if deep_get(data, keys='Rogue.RogueWorld.UseImmersifier') is False: deep_set(data, keys='Rogue.RogueWorld.UseStamina', value=False) diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index 4210ec046..fbb5a3e79 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -230,24 +230,6 @@ "close_game": "Close Game" } }, - "CloudStorage": { - "_info": { - "name": "CloudStorage._info.name", - "help": "CloudStorage._info.help" - }, - "CloudRemainSeasonPass": { - "name": "CloudStorage.CloudRemainSeasonPass.name", - "help": "CloudStorage.CloudRemainSeasonPass.help" - }, - "CloudRemainPaid": { - "name": "CloudStorage.CloudRemainPaid.name", - "help": "CloudStorage.CloudRemainPaid.help" - }, - "CloudRemainFree": { - "name": "CloudStorage.CloudRemainFree.name", - "help": "CloudStorage.CloudRemainFree.help" - } - }, "Dungeon": { "_info": { "name": "Dungeon Settings", @@ -435,8 +417,8 @@ }, "DungeonStorage": { "_info": { - "name": "DungeonStorage._info.name", - "help": "DungeonStorage._info.help" + "name": "Dungeon", + "help": "" }, "TrailblazePower": { "name": "Power", @@ -711,198 +693,10 @@ "9": "9" } }, - "AchievableQuest": { - "_info": { - "name": "Achievable Quests", - "help": "When the task status is \"Not Set\", you need to configure the SRC as required to achieve the quest\nNote: Please keep more tasks in \"Achievable\" status, otherwise SRC may not be able to grind 500 activity" - }, - "Complete_1_Daily_Mission": { - "name": "Complete 1 Daily Mission", - "help": "", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Clear_Calyx_Golden_1_times": { - "name": "Clear Calyx (Golden) 1 time(s)", - "help": "Need to configure and enable the \"Dungeon\" task", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Clear_Stagnant_Shadow_1_times": { - "name": "Clear Stagnant Shadow 1 time(s)", - "help": "Need to configure and enable the \"Dungeon\" task", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Clear_Cavern_of_Corrosion_1_times": { - "name": "Clear Cavern of Corrosion 1 time(s)", - "help": "Need to configure and enable the \"Dungeon\" task", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": { - "name": "In a single battle, inflict 3 Weakness Break of different Types", - "help": "Achievable by default, will do Himeko trial", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Inflict_Weakness_Break_5_times": { - "name": "Inflict Weakness Break 5 times", - "help": "Achievable by default, will do Himeko trial", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Defeat_a_total_of_20_enemies": { - "name": "Defeat a total of 20 enemies", - "help": "Achievable by default, will do Himeko trial", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Complete_Forgotten_Hall_1_time": { - "name": "Complete Forgotten Hall 1 time", - "help": "Achievable by default, will choose the first four characters to do stage 1 once, please ensure that account build is sufficient to do stage 1", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Complete_Echo_of_War_1_times": { - "name": "Complete Echo of War 1 time(s)", - "help": "Need to configure and enable the \"Echo of War\" task", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Use_an_Ultimate_to_deal_the_final_blow_1_time": { - "name": "Use an Ultimate to deal the final blow 1 time", - "help": "Achievable by default, will do Himeko trial", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Salvage_any_Relic": { - "name": "Salvage any Relic", - "help": "Achievable by default, will salvage the first one in reverse order of rarity", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Use_Consumables_1_time": { - "name": "Use Consumables 1 time", - "help": "Achievable by default, will use gear. If there is no material, synthesized before use", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Log_in_to_the_game": { - "name": "Log in to the game", - "help": "", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Dispatch_1_assignments": { - "name": "Dispatch 1 assignment(s)", - "help": "Need to configure and enable the \"Assignment\" task", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Complete_Divergent_Universe_or_Simulated_Universe_1_times": { - "name": "Complete Divergent Universe or Simulated Universe 1 time(s)", - "help": "Need to configure and enable the \"Simulated Universe\" task", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Clear_Calyx_Crimson_1_times": { - "name": "Clear Calyx (Crimson) 1 time(s)", - "help": "AchievableQuest.Clear_Calyx_Crimson_1_times.help", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Enter_combat_by_attacking_enemie_Weakness_and_win_3_times": { - "name": "Enter combat by attacking enemies' Weakness and win 3 time(s)", - "help": "Achievable by default, will do Himeko trial", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Use_Technique_2_times": { - "name": "Use Technique 2 time(s)", - "help": "Achievable by default, will go to the abyssal 1 and use technique twice", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Destroy_3_destructible_objects": { - "name": "Destroy 3 destructible object(s)", - "help": "Achievable by default, will do Himeko trial", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Obtain_victory_in_combat_with_Support_Characters_1_times": { - "name": "Obtain victory in combat with Support Characters 1 time(s)", - "help": "Need to configure and enable the \"Dungeon\" task, configure support settings also", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Level_up_any_character_1_times": { - "name": "Level up any character 1 time(s)", - "help": "", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Level_up_any_Light_Cone_1_times": { - "name": "Level up any Light Cone 1 time(s)", - "help": "", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Use_the_Omni_Synthesizer_1_times": { - "name": "Use the Omni-Synthesizer 1 time(s)", - "help": "Achievable by default, will synthesize low-rarity material", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Take_photos_1_times": { - "name": "Take photos 1 time(s)", - "help": "Achievable by default", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Consume_120_Trailblaze_Power": { - "name": "Consume 120 Trailblaze Power", - "help": "", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - }, - "Level_up_any_Relic_1_times": { - "name": "Level up any Relic 1 time(s)", - "help": "", - "achievable": "Achievable", - "not_set": "Not Set", - "not_supported": "Not Supported Yet" - } - }, "DailyStorage": { "_info": { - "name": "DailyStorage._info.name", - "help": "DailyStorage._info.help" + "name": "Daily Quest", + "help": "" }, "DailyActivity": { "name": "Activity", @@ -915,8 +709,8 @@ }, "BattlePassStorage": { "_info": { - "name": "BattlePassStorage._info.name", - "help": "BattlePassStorage._info.help" + "name": "Honor", + "help": "" }, "BattlePassLevel": { "name": "Honor", @@ -1071,8 +865,8 @@ }, "ItemStorage": { "_info": { - "name": "ItemStorage._info.name", - "help": "ItemStorage._info.help" + "name": "Dashboard", + "help": "" }, "Credit": { "name": "Credit", @@ -1083,6 +877,24 @@ "help": "" } }, + "CloudStorage": { + "_info": { + "name": "Cloud HSR", + "help": "" + }, + "CloudRemainSeasonPass": { + "name": "Season Pass Remain X day(s)", + "help": "" + }, + "CloudRemainPaid": { + "name": "Paid Time Remain X minute(s)", + "help": "" + }, + "CloudRemainFree": { + "name": "Free Time Remain X minute(s)", + "help": "" + } + }, "RogueWorld": { "_info": { "name": "Simulated Universe Settings", diff --git a/module/config/i18n/es-ES.json b/module/config/i18n/es-ES.json index 18e0cb0ec..4a49c5fe4 100644 --- a/module/config/i18n/es-ES.json +++ b/module/config/i18n/es-ES.json @@ -230,24 +230,6 @@ "close_game": "Cerrar el juego" } }, - "CloudStorage": { - "_info": { - "name": "CloudStorage._info.name", - "help": "CloudStorage._info.help" - }, - "CloudRemainSeasonPass": { - "name": "CloudStorage.CloudRemainSeasonPass.name", - "help": "CloudStorage.CloudRemainSeasonPass.help" - }, - "CloudRemainPaid": { - "name": "CloudStorage.CloudRemainPaid.name", - "help": "CloudStorage.CloudRemainPaid.help" - }, - "CloudRemainFree": { - "name": "CloudStorage.CloudRemainFree.name", - "help": "CloudStorage.CloudRemainFree.help" - } - }, "Dungeon": { "_info": { "name": "Ajustes de Mazmorra", @@ -435,8 +417,8 @@ }, "DungeonStorage": { "_info": { - "name": "DungeonStorage._info.name", - "help": "DungeonStorage._info.help" + "name": "Mazmorra", + "help": "" }, "TrailblazePower": { "name": "Poder", @@ -711,198 +693,10 @@ "9": "9" } }, - "AchievableQuest": { - "_info": { - "name": "Misiones completables", - "help": "Cuando el estado de una tarea sea \"No configurado\", deberás de configurar SRC para que pueda realizarla.\nNota: Por favor, ten más tareas en estado \"Completable\", sino SRC podría no llegar a los 500 pts. de actividad" - }, - "Complete_1_Daily_Mission": { - "name": "Completa 1 misión diaria", - "help": "", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Clear_Calyx_Golden_1_times": { - "name": "Completa Cáliz (oro) 1 vez", - "help": "Necesitas configurar y activar la tarea \"Mazmorra\"", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Clear_Stagnant_Shadow_1_times": { - "name": "Completa Sombra paralizada 1 veces", - "help": "Necesitas configurar y activar la tarea \"Mazmorra\"", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Clear_Cavern_of_Corrosion_1_times": { - "name": "Completa Caverna de la corrosión 1 veces", - "help": "Necesitas configurar y activar la tarea \"Mazmorra\"", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": { - "name": "En una sola batalla, inflige 3 tipos de Ruptura de Debilidad", - "help": "Completable por defecto, se hará el desafío de Himeko", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Inflict_Weakness_Break_5_times": { - "name": "Inflige Ruptura de Debilidad 5 veces", - "help": "Completable por defecto, se hará el desafío de Himeko", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Defeat_a_total_of_20_enemies": { - "name": "Derrota a 20 enemigos", - "help": "Completable por defecto, se hará el desafío de Himeko", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Complete_Forgotten_Hall_1_time": { - "name": "Completa el Salón olvidado 1 vez", - "help": "Completable por defecto, se seleccionarán los primeros 4 personajes y se hará el primer nivel. Por favor, asegúrate de que estos pueden hacerlo.", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Complete_Echo_of_War_1_times": { - "name": "Completa Ecos de la guerra 1 vez", - "help": "Necesitas configurar y activar la tarea \"Ecos de la guerra\"", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Use_an_Ultimate_to_deal_the_final_blow_1_time": { - "name": "Asesta el golpe final con una habilidad definitiva 1 vez", - "help": "Completable por defecto, se hará el desafío de Himeko", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Salvage_any_Relic": { - "name": "Destruye 1 artefacto", - "help": "Completable por defecto. Se destruirá la última ordenado ascendentemente por rareza.", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Use_Consumables_1_time": { - "name": "Usa 1 consumible", - "help": "Completable por defecto. Se sintetizará uno si no tienes ninguno.", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Log_in_to_the_game": { - "name": "Inicia sesión en el juego", - "help": "", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Dispatch_1_assignments": { - "name": "Asigna 1 encargo", - "help": "Necesitas configurar y activar la tarea de \"Encargos\"", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Complete_Divergent_Universe_or_Simulated_Universe_1_times": { - "name": "Completa el Universo Simulado o el Universo Diferenciado 1 vez", - "help": "Necesitas configurar y activar la tarea \"Universo Simulado\"", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Clear_Calyx_Crimson_1_times": { - "name": "Completa Cáliz (carmesí) 1 vez", - "help": "Necesitas configurar y activar la tarea \"Mazmorra\"", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Enter_combat_by_attacking_enemie_Weakness_and_win_3_times": { - "name": "Entra en combate atacando la debilidad del enemigo y gana 3 veces", - "help": "Completable por defecto, se hará el desafío de Himeko", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Use_Technique_2_times": { - "name": "Usa técnicas 2 veces", - "help": "Alcanzable por defecto, irá al abismo y usará la técnica 2 veces.", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Destroy_3_destructible_objects": { - "name": "Destruye 3 objetos destruibles", - "help": "Completable por defecto, se hará el desafío de Himeko", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Obtain_victory_in_combat_with_Support_Characters_1_times": { - "name": "Gana 1 batalla(s) utilizando personajes de apoyo", - "help": "Necesitas configurar la tarea de \"Mazmorra\", así como configurar a los héroes de apoyo.", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Level_up_any_character_1_times": { - "name": "Mejora el nivel de cualquier personaje 1 vez", - "help": "", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Level_up_any_Light_Cone_1_times": { - "name": "Mejora cualquier cono de luz 1 vez", - "help": "", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Use_the_Omni_Synthesizer_1_times": { - "name": "Utiliza la máquina sintetizadora multiusos 1 veces", - "help": "Achievable by default, will synthesize low-rarity material", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Take_photos_1_times": { - "name": "Haz 1 foto(s)", - "help": "Completable por defecto.", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Consume_120_Trailblaze_Power": { - "name": "Consume 120 pts. de Poder trazacaminos", - "help": "", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - }, - "Level_up_any_Relic_1_times": { - "name": "Mejora cualquier artefacto 1 vez", - "help": "", - "achievable": "Completable", - "not_set": "No configurado", - "not_supported": "No soportado aún" - } - }, "DailyStorage": { "_info": { - "name": "DailyStorage._info.name", - "help": "DailyStorage._info.help" + "name": "Misión Diaria", + "help": "" }, "DailyActivity": { "name": "Actividad", @@ -915,8 +709,8 @@ }, "BattlePassStorage": { "_info": { - "name": "BattlePassStorage._info.name", - "help": "BattlePassStorage._info.help" + "name": "Misión de Honor", + "help": "" }, "BattlePassLevel": { "name": "Honor", @@ -1071,7 +865,7 @@ }, "ItemStorage": { "_info": { - "name": "", + "name": "Panel", "help": "" }, "Credit": { @@ -1083,6 +877,24 @@ "help": "" } }, + "CloudStorage": { + "_info": { + "name": "Nube de HSR", + "help": "" + }, + "CloudRemainSeasonPass": { + "name": "Pase de Temporada Permanece X día(s)", + "help": "" + }, + "CloudRemainPaid": { + "name": "Tiempo restante pagado X minuto(s)", + "help": "" + }, + "CloudRemainFree": { + "name": "Tiempo libre restante X minuto(s)", + "help": "" + } + }, "RogueWorld": { "_info": { "name": "Ajustes de Universo Simulado", diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index 52cd0cb66..31d977902 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -230,24 +230,6 @@ "close_game": "close_game" } }, - "CloudStorage": { - "_info": { - "name": "CloudStorage._info.name", - "help": "CloudStorage._info.help" - }, - "CloudRemainSeasonPass": { - "name": "CloudStorage.CloudRemainSeasonPass.name", - "help": "CloudStorage.CloudRemainSeasonPass.help" - }, - "CloudRemainPaid": { - "name": "CloudStorage.CloudRemainPaid.name", - "help": "CloudStorage.CloudRemainPaid.help" - }, - "CloudRemainFree": { - "name": "CloudStorage.CloudRemainFree.name", - "help": "CloudStorage.CloudRemainFree.help" - } - }, "Dungeon": { "_info": { "name": "Dungeon._info.name", @@ -711,194 +693,6 @@ "9": "9" } }, - "AchievableQuest": { - "_info": { - "name": "AchievableQuest._info.name", - "help": "AchievableQuest._info.help" - }, - "Complete_1_Daily_Mission": { - "name": "デイリークエストを1回クリアする", - "help": "AchievableQuest.Complete_1_Daily_Mission.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Clear_Calyx_Golden_1_times": { - "name": "「疑似花萼(金)」を1回クリアする", - "help": "AchievableQuest.Clear_Calyx_Golden_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Clear_Stagnant_Shadow_1_times": { - "name": "「凝結虚影」を1回クリアする", - "help": "AchievableQuest.Clear_Stagnant_Shadow_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Clear_Cavern_of_Corrosion_1_times": { - "name": "「侵蝕トンネル」を1回クリアする", - "help": "AchievableQuest.Clear_Cavern_of_Corrosion_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": { - "name": "一度の戦闘で、異なる3種の属性の弱点撃破を発動する", - "help": "AchievableQuest.In_a_single_battle_inflict_3_Weakness_Break_of_different_Types.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Inflict_Weakness_Break_5_times": { - "name": "累計で弱点撃破効果を5回発動させる", - "help": "AchievableQuest.Inflict_Weakness_Break_5_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Defeat_a_total_of_20_enemies": { - "name": "敵を累計で20体倒す", - "help": "AchievableQuest.Defeat_a_total_of_20_enemies.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Complete_Forgotten_Hall_1_time": { - "name": "「忘却の庭」を1回クリアする", - "help": "AchievableQuest.Complete_Forgotten_Hall_1_time.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Complete_Echo_of_War_1_times": { - "name": "「歴戦余韻」を1回クリアする", - "help": "AchievableQuest.Complete_Echo_of_War_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Use_an_Ultimate_to_deal_the_final_blow_1_time": { - "name": "必殺技で最後の一撃を1回与える", - "help": "AchievableQuest.Use_an_Ultimate_to_deal_the_final_blow_1_time.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Salvage_any_Relic": { - "name": "任意の遺物1つを分解する", - "help": "AchievableQuest.Salvage_any_Relic.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Use_Consumables_1_time": { - "name": "消耗品を1個使う", - "help": "AchievableQuest.Use_Consumables_1_time.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Log_in_to_the_game": { - "name": "ゲームにログインする", - "help": "AchievableQuest.Log_in_to_the_game.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Dispatch_1_assignments": { - "name": "依頼に1回派遣する", - "help": "AchievableQuest.Dispatch_1_assignments.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Complete_Divergent_Universe_or_Simulated_Universe_1_times": { - "name": "「階差宇宙」または「模擬宇宙」を合計1回クリアする", - "help": "AchievableQuest.Complete_Divergent_Universe_or_Simulated_Universe_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Clear_Calyx_Crimson_1_times": { - "name": "「疑似花萼(赤)」を1回クリアする", - "help": "AchievableQuest.Clear_Calyx_Crimson_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Enter_combat_by_attacking_enemie_Weakness_and_win_3_times": { - "name": "弱点を攻撃して戦闘に入り、3回勝利する", - "help": "AchievableQuest.Enter_combat_by_attacking_enemie_Weakness_and_win_3_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Use_Technique_2_times": { - "name": "累計で秘技を2回発動する", - "help": "AchievableQuest.Use_Technique_2_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Destroy_3_destructible_objects": { - "name": "破壊できるオブジェクトを累計で3個破壊する", - "help": "AchievableQuest.Destroy_3_destructible_objects.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Obtain_victory_in_combat_with_Support_Characters_1_times": { - "name": "サポートキャラを使い、戦闘に1回勝利する", - "help": "AchievableQuest.Obtain_victory_in_combat_with_Support_Characters_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Level_up_any_character_1_times": { - "name": "任意のキャラを1回レベルアップする", - "help": "AchievableQuest.Level_up_any_character_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Level_up_any_Light_Cone_1_times": { - "name": "任意の光円錐を1回レベルアップする", - "help": "AchievableQuest.Level_up_any_Light_Cone_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Use_the_Omni_Synthesizer_1_times": { - "name": "「万能合成マシン」を1回使用する", - "help": "AchievableQuest.Use_the_Omni_Synthesizer_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Take_photos_1_times": { - "name": "1回撮影する", - "help": "AchievableQuest.Take_photos_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Consume_120_Trailblaze_Power": { - "name": "累計で開拓力×120を消費する", - "help": "AchievableQuest.Consume_120_Trailblaze_Power.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - }, - "Level_up_any_Relic_1_times": { - "name": "任意の遺物を1回レベルアップする", - "help": "AchievableQuest.Level_up_any_Relic_1_times.help", - "achievable": "achievable", - "not_set": "not_set", - "not_supported": "not_supported" - } - }, "DailyStorage": { "_info": { "name": "DailyStorage._info.name", @@ -1083,6 +877,24 @@ "help": "ItemStorage.StallerJade.help" } }, + "CloudStorage": { + "_info": { + "name": "CloudStorage._info.name", + "help": "CloudStorage._info.help" + }, + "CloudRemainSeasonPass": { + "name": "CloudStorage.CloudRemainSeasonPass.name", + "help": "CloudStorage.CloudRemainSeasonPass.help" + }, + "CloudRemainPaid": { + "name": "CloudStorage.CloudRemainPaid.name", + "help": "CloudStorage.CloudRemainPaid.help" + }, + "CloudRemainFree": { + "name": "CloudStorage.CloudRemainFree.name", + "help": "CloudStorage.CloudRemainFree.help" + } + }, "RogueWorld": { "_info": { "name": "RogueWorld._info.name", diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index 7df14bdb3..3c1799431 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -230,24 +230,6 @@ "close_game": "关闭游戏" } }, - "CloudStorage": { - "_info": { - "name": "", - "help": "" - }, - "CloudRemainSeasonPass": { - "name": "畅玩卡剩余 X 天", - "help": "" - }, - "CloudRemainPaid": { - "name": "星云币剩余 X 分钟", - "help": "" - }, - "CloudRemainFree": { - "name": "免费时长剩余 X 分钟", - "help": "" - } - }, "Dungeon": { "_info": { "name": "每日副本设置", @@ -435,8 +417,8 @@ }, "DungeonStorage": { "_info": { - "name": "DungeonStorage._info.name", - "help": "DungeonStorage._info.help" + "name": "每日副本", + "help": "" }, "TrailblazePower": { "name": "开拓力", @@ -711,198 +693,10 @@ "9": "9" } }, - "AchievableQuest": { - "_info": { - "name": "可完成的任务", - "help": "任务状态为 \"未设置\" 时需要按照要求设置SRC,才能启用任务\n注意:请让更多的任务处于 \"可完成\" 状态,否则SRC可能无法完成500点的活跃度要求" - }, - "Complete_1_Daily_Mission": { - "name": "完成1个日常任务", - "help": "", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Clear_Calyx_Golden_1_times": { - "name": "完成1次「拟造花萼(金)」", - "help": "需要设置并启用\"每日副本\"任务", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Clear_Stagnant_Shadow_1_times": { - "name": "完成1次「凝滞虚影」", - "help": "需要设置并启用\"每日副本\"任务", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Clear_Cavern_of_Corrosion_1_times": { - "name": "完成1次「侵蚀隧洞」", - "help": "需要设置并启用\"每日副本\"任务", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": { - "name": "单场战斗中,触发3种不同属性的弱点击破", - "help": "默认可完成,将做姬子试用", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Inflict_Weakness_Break_5_times": { - "name": "累计触发弱点击破效果5次", - "help": "默认可完成,将做姬子试用", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Defeat_a_total_of_20_enemies": { - "name": "累计消灭20个敌人", - "help": "默认可完成,将做姬子试用", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Complete_Forgotten_Hall_1_time": { - "name": "完成1次「忘却之庭」", - "help": "默认可完成,将使用前四个角色打一次深渊一,请保证帐号练度足够打深渊一", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Complete_Echo_of_War_1_times": { - "name": "完成1次「历战余响」", - "help": "需要设置并启用\"历战余响\"任务", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Use_an_Ultimate_to_deal_the_final_blow_1_time": { - "name": "施放终结技造成制胜一击1次", - "help": "默认可完成,将做姬子试用", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Salvage_any_Relic": { - "name": "分解任意1件遗器", - "help": "默认可完成,将分解遗器稀有度倒序的第一个", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Use_Consumables_1_time": { - "name": "使用1件消耗品", - "help": "默认可完成,将使用护具,无材料时先合成再使用", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Log_in_to_the_game": { - "name": "登录游戏", - "help": "", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Dispatch_1_assignments": { - "name": "派遣1次委托", - "help": "需要设置并启用\"委托\"任务", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Complete_Divergent_Universe_or_Simulated_Universe_1_times": { - "name": "完成1次「差分宇宙」或「模拟宇宙」", - "help": "需要设置并启用\"模拟宇宙\"任务", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Clear_Calyx_Crimson_1_times": { - "name": "完成1次「拟造花萼(赤)」", - "help": "需要设置并启用\"每日副本\"任务", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Enter_combat_by_attacking_enemie_Weakness_and_win_3_times": { - "name": "利用弱点进入战斗并获胜3次", - "help": "默认可完成,将做姬子试用", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Use_Technique_2_times": { - "name": "累计施放2次秘技", - "help": "默认可完成,将前往深渊一施放2次秘技", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Destroy_3_destructible_objects": { - "name": "累计击碎3个可破坏物", - "help": "默认可完成,将做姬子试用", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Obtain_victory_in_combat_with_Support_Characters_1_times": { - "name": "使用支援角色并获得战斗胜利1次", - "help": "需要设置并启用\"每日副本\",且设置好友支援", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Level_up_any_character_1_times": { - "name": "将任意角色等级提升1次", - "help": "", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Level_up_any_Light_Cone_1_times": { - "name": "将任意光锥等级提升1次", - "help": "", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Use_the_Omni_Synthesizer_1_times": { - "name": "使用1次「万能合成机」", - "help": "默认可完成,将合成最低级材料", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Take_photos_1_times": { - "name": "拍照1次", - "help": "默认可完成", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Consume_120_Trailblaze_Power": { - "name": "累计消耗120点开拓力", - "help": "", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - }, - "Level_up_any_Relic_1_times": { - "name": "将任意遗器等级提升1次", - "help": "", - "achievable": "可完成", - "not_set": "未设置", - "not_supported": "暂未支持" - } - }, "DailyStorage": { "_info": { - "name": "DailyStorage._info.name", - "help": "DailyStorage._info.help" + "name": "每日任务", + "help": "" }, "DailyActivity": { "name": "活跃度", @@ -915,8 +709,8 @@ }, "BattlePassStorage": { "_info": { - "name": "BattlePassStorage._info.name", - "help": "BattlePassStorage._info.help" + "name": "无名勋礼", + "help": "" }, "BattlePassLevel": { "name": "无名勋礼", @@ -1071,8 +865,8 @@ }, "ItemStorage": { "_info": { - "name": "ItemStorage._info.name", - "help": "ItemStorage._info.help" + "name": "仪表盘", + "help": "" }, "Credit": { "name": "信用点", @@ -1083,6 +877,24 @@ "help": "" } }, + "CloudStorage": { + "_info": { + "name": "云游戏", + "help": "" + }, + "CloudRemainSeasonPass": { + "name": "畅玩卡剩余 X 天", + "help": "" + }, + "CloudRemainPaid": { + "name": "星云币剩余 X 分钟", + "help": "" + }, + "CloudRemainFree": { + "name": "免费时长剩余 X 分钟", + "help": "" + } + }, "RogueWorld": { "_info": { "name": "模拟宇宙设置", diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index 5009af9ef..3a2694342 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -230,24 +230,6 @@ "close_game": "關閉遊戲" } }, - "CloudStorage": { - "_info": { - "name": "CloudStorage._info.name", - "help": "CloudStorage._info.help" - }, - "CloudRemainSeasonPass": { - "name": "CloudStorage.CloudRemainSeasonPass.name", - "help": "CloudStorage.CloudRemainSeasonPass.help" - }, - "CloudRemainPaid": { - "name": "CloudStorage.CloudRemainPaid.name", - "help": "CloudStorage.CloudRemainPaid.help" - }, - "CloudRemainFree": { - "name": "CloudStorage.CloudRemainFree.name", - "help": "CloudStorage.CloudRemainFree.help" - } - }, "Dungeon": { "_info": { "name": "每日副本設定", @@ -435,8 +417,8 @@ }, "DungeonStorage": { "_info": { - "name": "DungeonStorage._info.name", - "help": "DungeonStorage._info.help" + "name": "每日副本", + "help": "" }, "TrailblazePower": { "name": "開拓力", @@ -711,198 +693,10 @@ "9": "9" } }, - "AchievableQuest": { - "_info": { - "name": "可完成的任務", - "help": "任務狀態為 \"未設定\" 時需要按照要求設定SRC,才能啟用任務\n注意:請讓更多的任務處於 \"可完成\" 狀態,否則SRC可能無法完成500點的活躍度要求" - }, - "Complete_1_Daily_Mission": { - "name": "完成1個每日任務", - "help": "", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Clear_Calyx_Golden_1_times": { - "name": "完成1次「擬造花萼(金)」", - "help": "需要設定並啟用\"每日副本\"任務", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Clear_Stagnant_Shadow_1_times": { - "name": "完成1次「凝滯虛影」", - "help": "需要設定並啟用\"每日副本\"任務", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Clear_Cavern_of_Corrosion_1_times": { - "name": "完成1次「侵蝕隧洞」", - "help": "需要設定並啟用\"每日副本\"任務", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": { - "name": "單場戰鬥中,觸發3種不同屬性的弱點擊破", - "help": "預設可完成,將做姬子試用", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Inflict_Weakness_Break_5_times": { - "name": "累積觸發弱點擊破效果5次", - "help": "預設可完成,將做姬子試用", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Defeat_a_total_of_20_enemies": { - "name": "累積消滅20個敵人", - "help": "預設可完成,將做姬子試用", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Complete_Forgotten_Hall_1_time": { - "name": "完成1次「忘卻之庭」", - "help": "預設可完成,將使用前四個角色打一次深淵一,請確保帳號練度足夠打深淵一", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Complete_Echo_of_War_1_times": { - "name": "完成1次「歷戰餘響」", - "help": "需要設定並啟用\"歷戰餘響\"任務", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Use_an_Ultimate_to_deal_the_final_blow_1_time": { - "name": "施放終結技造成制勝一擊1次", - "help": "預設可完成,將做姬子試用", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Salvage_any_Relic": { - "name": "分解任意1件遺器", - "help": "預設可完成,將分解遺器稀有度倒序的第一個", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Use_Consumables_1_time": { - "name": "使用1件消耗品", - "help": "預設可完成,將使用護具,無材料時先合成再使用", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Log_in_to_the_game": { - "name": "登入遊戲", - "help": "", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Dispatch_1_assignments": { - "name": "派遣1次委託", - "help": "需要設定並啟用\"委託\"任務", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Complete_Divergent_Universe_or_Simulated_Universe_1_times": { - "name": "完成1次「差分宇宙」或「模擬宇宙」", - "help": "需要設定並啟用\"模擬宇宙\"任務", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Clear_Calyx_Crimson_1_times": { - "name": "完成1次「擬造花萼(赤)」", - "help": "需要設定並啟用\"每日副本\"任務", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Enter_combat_by_attacking_enemie_Weakness_and_win_3_times": { - "name": "利用弱點進入戰鬥並獲勝3次", - "help": "預設可完成,將做姬子試用", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Use_Technique_2_times": { - "name": "累積施放2次秘技", - "help": "預設可完成,將前往深淵一施放2次秘技", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Destroy_3_destructible_objects": { - "name": "累積擊碎3個可破壞物", - "help": "預設可完成,將做姬子試用", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Obtain_victory_in_combat_with_Support_Characters_1_times": { - "name": "使用支援角色並獲得戰鬥勝利1次", - "help": "需要設定並啟用\"每日副本\",且設並好友支援", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Level_up_any_character_1_times": { - "name": "將任意角色等級提升1次", - "help": "", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Level_up_any_Light_Cone_1_times": { - "name": "將任意光錐等級提升1次", - "help": "", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Use_the_Omni_Synthesizer_1_times": { - "name": "使用1次「萬能合成機」", - "help": "預設可完成,將合成最低級素材", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Take_photos_1_times": { - "name": "拍照1次", - "help": "預設可完成", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Consume_120_Trailblaze_Power": { - "name": "累積消耗120點開拓力", - "help": "", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - }, - "Level_up_any_Relic_1_times": { - "name": "將任意遺器等級提升1次", - "help": "", - "achievable": "可完成", - "not_set": "未設定", - "not_supported": "暫未支援" - } - }, "DailyStorage": { "_info": { - "name": "DailyStorage._info.name", - "help": "DailyStorage._info.help" + "name": "每日任務", + "help": "" }, "DailyActivity": { "name": "活躍度", @@ -915,8 +709,8 @@ }, "BattlePassStorage": { "_info": { - "name": "BattlePassStorage._info.name", - "help": "BattlePassStorage._info.help" + "name": "無名勳禮", + "help": "" }, "BattlePassLevel": { "name": "無名勳禮", @@ -1071,8 +865,8 @@ }, "ItemStorage": { "_info": { - "name": "ItemStorage._info.name", - "help": "ItemStorage._info.help" + "name": "儀表板", + "help": "" }, "Credit": { "name": "信用點", @@ -1083,6 +877,24 @@ "help": "" } }, + "CloudStorage": { + "_info": { + "name": "雲遊戲", + "help": "" + }, + "CloudRemainSeasonPass": { + "name": "暢玩卡剩餘 X 天", + "help": "" + }, + "CloudRemainPaid": { + "name": "星雲幣剩餘 X 分鐘", + "help": "" + }, + "CloudRemainFree": { + "name": "免費時間剩餘 X 分鐘", + "help": "" + } + }, "RogueWorld": { "_info": { "name": "模拟宇宙设置", diff --git a/module/config/stored/stored_generated.py b/module/config/stored/stored_generated.py index 1597af3dd..a4a4d4fb2 100644 --- a/module/config/stored/stored_generated.py +++ b/module/config/stored/stored_generated.py @@ -31,9 +31,6 @@ from module.config.stored.classes import ( # ``` python -m module/config/config_updater.py ``` class StoredGenerated: - CloudRemainSeasonPass = StoredInt("Alas.CloudStorage.CloudRemainSeasonPass") - CloudRemainPaid = StoredInt("Alas.CloudStorage.CloudRemainPaid") - CloudRemainFree = StoredInt("Alas.CloudStorage.CloudRemainFree") PlannerOverall = StoredPlannerOverall("Dungeon.Planner.PlannerOverall") Item_Credit = StoredPlanner("Dungeon.Planner.Item_Credit") Item_Trailblaze_EXP = StoredPlanner("Dungeon.Planner.Item_Trailblaze_EXP") @@ -105,4 +102,7 @@ class StoredGenerated: Assignment = StoredAssignment("Assignment.Assignment.Assignment") Credit = StoredInt("DataUpdate.ItemStorage.Credit") StallerJade = StoredInt("DataUpdate.ItemStorage.StallerJade") + CloudRemainSeasonPass = StoredInt("DataUpdate.CloudStorage.CloudRemainSeasonPass") + CloudRemainPaid = StoredInt("DataUpdate.CloudStorage.CloudRemainPaid") + CloudRemainFree = StoredInt("DataUpdate.CloudStorage.CloudRemainFree") SimulatedUniverseFarm = StoredSimulatedUniverseElite("Rogue.RogueWorld.SimulatedUniverseFarm") From 998bb415d25394351cbfd7cf5404dbcbea49835f Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 03:40:54 +0800 Subject: [PATCH 21/27] Fix: [ALAS] Show empty stored --- module/webui/widgets.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/module/webui/widgets.py b/module/webui/widgets.py index 6cb75681d..b9e71b9f5 100644 --- a/module/webui/widgets.py +++ b/module/webui/widgets.py @@ -366,8 +366,10 @@ def put_arg_stored(kwargs: T_Output_Kwargs) -> Output: put_text(value).style("--dashboard-value--") ])] else: - # Empty - rows = [] + # No Data + rows = [put_scope(f"dashboard-value-{name}", [ + put_text(t("Gui.Dashboard.NoData")).style("--dashboard-value--") + ])] # Add other key-value in stored if values: rows += [ @@ -379,6 +381,11 @@ def put_arg_stored(kwargs: T_Output_Kwargs) -> Output: rows.append( put_text(time_).style("--dashboard-time--") ) + else: + # Blank row + rows.append( + put_text(" ").style("--dashboard-time--") + ) return put_scope( f"arg_container-stored-{name}", From 779d4e4c1cf4232c1c3afc2fc65d2f1d843add7c Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 04:25:25 +0800 Subject: [PATCH 22/27] Fix: Achieved weekly by doing Ornament_Extraction --- tasks/dungeon/dungeon.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tasks/dungeon/dungeon.py b/tasks/dungeon/dungeon.py index aeffbe13c..a38c0a1fb 100644 --- a/tasks/dungeon/dungeon.py +++ b/tasks/dungeon/dungeon.py @@ -143,6 +143,12 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): if self.config.stored.BattlePassQuestEchoOfWar.is_full(): logger.info('Achieved weekly quest Complete_Echo_of_War_1_times') self.achieved_weekly_quest = True + # Ornament_Extraction + if dungeon.is_Ornament_Extraction: + if KEYWORDS_BATTLE_PASS_QUEST.Complete_Divergent_Universe_or_Simulated_Universe_1_times in self.weekly_quests: + logger.info('Achieved weekly quest Complete_Divergent_Universe_or_Simulated_Universe_1_times') + # No need to add since it's 0/1 + self.achieved_weekly_quest = True # Support quest if support_character is not None: self.called_daily_support = True From 0339b1c8526866be303f40154febe9f6de480cd5 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 05:29:16 +0800 Subject: [PATCH 23/27] Fix: Ornament scheduling --- tasks/dungeon/dungeon.py | 4 ++-- tasks/ornament/combat.py | 21 ++++++++++++++++++--- tasks/ornament/ornament.py | 14 +++++++++++--- tasks/rogue/entry/entry.py | 5 +++++ 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/tasks/dungeon/dungeon.py b/tasks/dungeon/dungeon.py index a38c0a1fb..6969a4fe4 100644 --- a/tasks/dungeon/dungeon.py +++ b/tasks/dungeon/dungeon.py @@ -203,7 +203,7 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): elif require and not self.support_once: # Run with support all the way - return self._dungeon_run(dungeon=dungeon, team=team, wave_limit=1, + return self._dungeon_run(dungeon=dungeon, team=team, wave_limit=0, support_character=self.config.DungeonSupport_Character) else: @@ -281,7 +281,7 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): # Dungeon to clear all trailblaze power do_rogue = False - if self.config.is_task_enabled('Rogue'): + if self.config.is_task_enabled('Rogue') and not self.config.is_task_enabled('Ornament'): if self.config.cross_get('Rogue.RogueWorld.UseStamina'): logger.info('Going to use stamina in rogue') do_rogue = True diff --git a/tasks/ornament/combat.py b/tasks/ornament/combat.py index 37c434003..3903efb33 100644 --- a/tasks/ornament/combat.py +++ b/tasks/ornament/combat.py @@ -19,6 +19,10 @@ class OrnamentCombat(Dungeon, RouteLoader, DungeonState): # Enter from survival index instead pass + def _combat_should_reenter(self): + # Never re-enter, can only enter from Survival_Index + return False + def get_double_event_remain_at_combat(self, button=OCR_DOUBLE_EVENT_REMAIN_AT_OE): # Different position to OCR return super().get_double_event_remain_at_combat(button) @@ -100,10 +104,16 @@ class OrnamentCombat(Dungeon, RouteLoader, DungeonState): else: self._search_support(support_character_name) # Search support selected_support = True - self.device.click(OCR_DOUBLE_EVENT_REMAIN_AT_OE) + self.device.click(SUPPORT_ADD) self.interval_reset(COMBAT_SUPPORT_LIST) continue + def get_equivalent_stamina(self): + value = self.config.stored.Immersifier.value * 40 + if self.config.Ornament_UseStamina: + value += self.config.stored.TrailblazePower.value + return value + def combat_get_trailblaze_power(self, expect_reduce=False, skip_first_screenshot=True) -> int: """ Args: @@ -116,12 +126,12 @@ class OrnamentCombat(Dungeon, RouteLoader, DungeonState): Pages: in: COMBAT_PREPARE or COMBAT_REPEAT """ - before = self.config.stored.TrailblazePower.value + self.config.stored.Immersifier.value * 40 + before = self.get_equivalent_stamina() after = before for _ in range(3): self.dungeon_update_stamina() - after = self.config.stored.TrailblazePower.value + self.config.stored.Immersifier.value * 40 + after = self.get_equivalent_stamina() if expect_reduce: if before > after: break @@ -130,6 +140,11 @@ class OrnamentCombat(Dungeon, RouteLoader, DungeonState): return after + def is_trailblaze_power_exhausted(self): + flag = self.get_equivalent_stamina() < self.combat_wave_cost + logger.attr('TrailblazePowerExhausted', flag) + return flag + def is_team_prepared(self) -> bool: """ Pages: diff --git a/tasks/ornament/ornament.py b/tasks/ornament/ornament.py index 6b998dd1d..1d94fb35f 100644 --- a/tasks/ornament/ornament.py +++ b/tasks/ornament/ornament.py @@ -56,6 +56,14 @@ class Ornament(OrnamentCombat): return result + def delay_dungeon_task(self, dungeon: DungeonList): + with self.config.multi_set(): + super().delay_dungeon_task(dungeon) + if not self.config.Ornament_UseStamina and self.config.stored.DungeonDouble.rogue <= 0: + if self.config.stored.Immersifier.value <= 0: + logger.info('Immersifier exhausted') + self.config.task_delay(server_update=True) + def run(self): self.config.update_battle_pass_quests() self.config.update_daily_quests() @@ -79,6 +87,7 @@ class Ornament(OrnamentCombat): # Run dungeon = DungeonList.find(self.config.Ornament_Dungeon) + self.support_once = False self.combat_wave_cost = 40 self.dungeon = dungeon if self.config.Ornament_UseStamina: @@ -91,9 +100,8 @@ class Ornament(OrnamentCombat): self.running_double = True self.dungeon_run(dungeon, wave_limit=self.config.stored.DungeonDouble.rogue) self.running_double = False - - self.config.task_delay(server_update=True) + self.dungeon_stamina_delay(dungeon) else: # Use immersifier only, wave limited in _dungeon_wait_until_dungeon_list_loaded self.dungeon_run(dungeon, wave_limit=0) - self.config.task_delay(server_update=True) + self.dungeon_stamina_delay(dungeon) diff --git a/tasks/rogue/entry/entry.py b/tasks/rogue/entry/entry.py index 93a9e14f4..2f89e6b64 100644 --- a/tasks/rogue/entry/entry.py +++ b/tasks/rogue/entry/entry.py @@ -353,6 +353,8 @@ class RogueEntry(RouteBase, RogueRewardHandler, RoguePathHandler, DungeonRogueUI f'RogueWorld_DoubleEvent={self.config.RogueWorld_DoubleEvent}, ' f'RogueWorld_WeeklyFarming={self.config.RogueWorld_WeeklyFarming}, ' f'RogueDebug_DebugMode={self.config.RogueDebug_DebugMode}') + ornament = self.config.is_task_enabled('Ornament') + logger.info(f'Ornament: {ornament}') # This shouldn't happen if self.config.RogueWorld_UseStamina and not self.config.RogueWorld_UseImmersifier: logger.error('Invalid rogue reward settings') @@ -376,6 +378,9 @@ class RogueEntry(RouteBase, RogueRewardHandler, RoguePathHandler, DungeonRogueUI if self.config.RogueWorld_UseImmersifier and self.config.stored.Immersifier.value > 0: logger.info( 'Reached weekly point limit but still have immersifiers left, continue to use them') + if ornament: + logger.info('Ornament enabled, skip farming rogue') + raise RogueReachedWeeklyPointLimit elif self.config.RogueWorld_WeeklyFarming and not self.config.stored.SimulatedUniverseFarm.is_full(): logger.info( 'Reached weekly point limit but still continue to farm materials') From d6eb36fe70eb5e4b5d66432a72ee51002cd17eb3 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 23:46:10 +0800 Subject: [PATCH 24/27] Doc: Update planner_en --- README.md | 6 +++--- README_en.md | 8 +++++--- README_es.md | 8 +++++--- module/config/i18n/en-US.json | 2 +- module/config/i18n/es-ES.json | 2 +- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 008fc5191..821eca537 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Star Rail auto script | 星铁速溶茶,崩坏:星穹铁道脚本,基于 ![gui](https://raw.githubusercontent.com/wiki/LmeSzinc/StarRailCopilot/README.assets/gui_cn.png) - +![setting](https://raw.githubusercontent.com/wiki/LmeSzinc/StarRailCopilot/README.assets/setting_cn.png) ## 功能 @@ -15,7 +15,7 @@ Star Rail auto script | 星铁速溶茶,崩坏:星穹铁道脚本,基于 - **收获**:完成每日任务,收派委托,收取无名勋礼奖励。 - **模拟宇宙**:刷模拟宇宙,使用开拓力刷内圈遗器。 - **后台托管**:自动启动模拟器和游戏,后台托管清体力和每日,通过仪表盘了解资源情况。 -- **云游戏**:(仅国服)支持云崩坏星穹铁道。 +- **云游戏**:(仅国服)[在云崩坏星穹铁道上运行SRC](https://github.com/LmeSzinc/StarRailCopilot/wiki/Cloud_cn) ## 安装 [![](https://img.shields.io/github/downloads/LmeSzinc/StarRailCopilot/total?color=4e4c97)](https://github.com/LmeSzinc/StarRailCopilot/releases) @@ -31,7 +31,7 @@ Discord https://discord.gg/aJkt3mKDEr QQ群 752620927 - [小地图识别原理](https://github.com/LmeSzinc/StarRailCopilot/wiki/MinimapTracking) - 开发文档(目录在侧边栏):[Alas wiki](https://github.com/LmeSzinc/AzurLaneAutoScript/wiki/1.-Start),但很多内容是新写的,建议阅读源码和历史提交。 -- 开发路线图:[#10](https://github.com/LmeSzinc/StarRailCopilot/issues/10) ,欢迎提交 PR,挑选你感兴趣的部分进行开发即可。 +- 开发路线图:见置顶 issue,欢迎提交 PR,挑选你感兴趣的部分进行开发即可。 > **如何添加多语言/多服务器支持?** 需要适配 assets,参考 [开发文档 “添加一个 Button” 一节](https://github.com/LmeSzinc/AzurLaneAutoScript/wiki/4.1.-Detection-objects#%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA-button)。 diff --git a/README_en.md b/README_en.md index 844fa7914..ebd8a435a 100644 --- a/README_en.md +++ b/README_en.md @@ -6,13 +6,15 @@ Star Rail Instant Tea, a bot for Honkai: Star Rail, based on the next generation ![gui](https://raw.githubusercontent.com/wiki/LmeSzinc/StarRailCopilot/README.assets/gui_en.png) +![setting](https://raw.githubusercontent.com/wiki/LmeSzinc/StarRailCopilot/README.assets/setting_en.png) + ## Features -- **Dungeons**: [Character Planner](https://github.com/LmeSzinc/StarRailCopilot/wiki/Planner_cn), Dungeons, dungeons at double event, echo of war. +- **Dungeons**: [Character Planner](https://github.com/LmeSzinc/StarRailCopilot/wiki/Planner_en), Dungeons, dungeons at double event, echo of war. - **Rewards**: Complete daily quests, do assignment, claim nameless horner rewards. - **Simulated Universe**: Farm SU, farm planers using trailbalze power. - **AFK Auto Farming**: Automatically launch emulators and games, do dungeons and quests at background, keep track of resources through dashboard. -- **Cloud Gaming**: [CN only] Support Cloud HSR. +- **Cloud Gaming**: [CN only] [Run SRC on cloud HSR](https://github.com/LmeSzinc/StarRailCopilot/wiki/Cloud_cn) ## Install [![](https://img.shields.io/github/downloads/LmeSzinc/StarRailCopilot/total?color=4e4c97)](https://github.com/LmeSzinc/StarRailCopilot/releases) @@ -30,7 +32,7 @@ Discord https://discord.gg/aJkt3mKDEr - Development Docs (menu is on sidebar): [Alas wiki](https://github.com/LmeSzinc/AzurLaneAutoScript/wiki/1.-Start) (in Chinese). However, there is ton of code newly written, it is recommended to read the source code and historical commits. -- Development Road Map: [#10](https://github.com/LmeSzinc/StarRailCopilot/issues/10). Pull Requests are welcomed, just pick the part you interested to work on. +- Development Road Map: See pinned issues. Pull Requests are welcomed, just pick the part you interested to work on. > **How to add multi-language or multi-server support?** Need assets updates, see ["Adding a Button" in development docs](https://github.com/LmeSzinc/AzurLaneAutoScript/wiki/4.1.-Detection-objects#%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA-button). diff --git a/README_es.md b/README_es.md index 8acdc4e05..0f0ff3035 100644 --- a/README_es.md +++ b/README_es.md @@ -5,13 +5,15 @@ Star Rail Copilot, un bot para Honkai: Star Rail, basado en la siguiente generac ![gui](https://raw.githubusercontent.com/wiki/LmeSzinc/StarRailCopilot/README.assets/gui_es.png) +![setting](https://raw.githubusercontent.com/wiki/LmeSzinc/StarRailCopilot/README.assets/setting_es.png) + ## Características -- **Mazmorras**: [Planificador de personajes](https://github.com/LmeSzinc/StarRailCopilot/wiki/Planner_cn), Mazmorras, y mazmorras en eventos de doble recompensa (materiales de XP de personaje, de conos de luz, rastros, ascensión, artefactos...), ecos de la guerra. +- **Mazmorras**: [Planificador de personajes](https://github.com/LmeSzinc/StarRailCopilot/wiki/Planner_en), Mazmorras, y mazmorras en eventos de doble recompensa (materiales de XP de personaje, de conos de luz, rastros, ascensión, artefactos...), ecos de la guerra. - **Recompensas diarias**: Se completan las misiones de actividad diarias, la misión diaria, las misiones de Honor Anónimo... - **Universo Simulado**: Farm SU hasta alcanzar el límite de puntos semanal, farm planars usando poder trazacaminos. - **Farmeo automático AFK**: El bot lo hace todo de manera automática, abre los emuladores, completa las misiones y realiza las tareas diarias, realice un seguimiento de los recursos a través del panel. -- **Juegos en la nube**: [solo CN] Compatible con Cloud HSR. +- **Juegos en la nube**: [solo CN] [Ejecute SRC en HSR en la nube](https://github.com/LmeSzinc/StarRailCopilot/wiki/Cloud_cn) ## Instalación [![](https://img.shields.io/github/downloads/LmeSzinc/StarRailCopilot/total?color=4e4c97)](https://github.com/LmeSzinc/StarRailCopilot/releases) Dirígete a la [Guía de Instalación](https://github.com/LmeSzinc/StarRailCopilot/wiki/Installation_en) para consultar cómo hacer la instalación automática, el manual de uso, etc. @@ -25,7 +27,7 @@ Discord: https://discord.gg/aJkt3mKDEr - [Seguimiento del Minimapa](https://github.com/LmeSzinc/StarRailCopilot/wiki/MinimapTracking) - Documentación para desarrolladores (el menú está en la barra lateral): [Wiki de ALAS](https://github.com/LmeSzinc/AzurLaneAutoScript/wiki/1.-Start) (en Chino). Sin embargo, hay un montón de código nuevo, por lo que es recomendado leer el código fuente y el historial de commits. -- Roadmap del desarrollo: [#10](https://github.com/LmeSzinc/StarRailCopilot/issues/10). Los pull requests son bienvenidos. Simplemente, elige la parte en la que estás interesado trabajar. +- Roadmap del desarrollo: Ver issues fijados. Los pull requests son bienvenidos. Simplemente, elige la parte en la que estás interesado trabajar. > **¿Cómo añadir nuevos idiomas o servidores?** Si necesitas actualizar los recursos del bot, échale un vistazo a ["Añadiendo un Botón" en la documentación para desarrolladores](https://github.com/LmeSzinc/AzurLaneAutoScript/wiki/4.1.-Detection-objects#%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA-button). diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index fbb5a3e79..2fe47eee4 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -1064,7 +1064,7 @@ "PlannerScan": { "_info": { "name": "Scan Character Planner Results", - "help": "Tools need to stop the scheduler and then run independently\nBefore use, set planner goal in the in-game planner, calculate the results, and start scanning from the result page. Detailed usage see: https://github.com/LmeSzinc/StarRailCopilot/wiki/Planner_cn" + "help": "Tools need to stop the scheduler and then run independently\nBefore use, set planner goal in the in-game planner, calculate the results, and start scanning from the result page. Detailed usage see: https://github.com/LmeSzinc/StarRailCopilot/wiki/Planner_en" }, "ResultAdd": { "name": "Accumulate multiple scan results", diff --git a/module/config/i18n/es-ES.json b/module/config/i18n/es-ES.json index 4a49c5fe4..e4057ac0c 100644 --- a/module/config/i18n/es-ES.json +++ b/module/config/i18n/es-ES.json @@ -1064,7 +1064,7 @@ "PlannerScan": { "_info": { "name": "Escanear resultados del planificador de caracteres", - "help": "Las herramientas deben detener el programador y luego ejecutarse de forma independiente\nAntes de usarlo, establezca el objetivo del planificador en el planificador del juego, calcule los resultados y comience a escanear desde la página de resultados. Para uso detallado, consulte: https://github .com/LmeSzinc/StarRailCopilot/wiki/Planner_cn" + "help": "Las herramientas deben detener el programador y luego ejecutarse de forma independiente\nAntes de usarlo, establezca el objetivo del planificador en el planificador del juego, calcule los resultados y comience a escanear desde la página de resultados. Para uso detallado, consulte: https://github .com/LmeSzinc/StarRailCopilot/wiki/Planner_en" }, "ResultAdd": { "name": "Acumular múltiples resultados de escaneo", From 2c859504ac4a248b3cec2a53b5be711b52f99a85 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Tue, 2 Jul 2024 23:51:00 +0800 Subject: [PATCH 25/27] Fix: Add themeConfig.ts donno why it uses files in build directory --- webapp/packages/renderer/build/config/themeConfig.ts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 webapp/packages/renderer/build/config/themeConfig.ts diff --git a/webapp/packages/renderer/build/config/themeConfig.ts b/webapp/packages/renderer/build/config/themeConfig.ts new file mode 100644 index 000000000..f60ac5e26 --- /dev/null +++ b/webapp/packages/renderer/build/config/themeConfig.ts @@ -0,0 +1,4 @@ + +export const primaryColor = '#C079F2'; +export const darkMode = 'light'; + From 701df396ccd5dc847427be6ebed73fa345e7227f Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Wed, 3 Jul 2024 00:46:21 +0800 Subject: [PATCH 26/27] Fix: [ALAS] Should check current path first --- webapp/packages/common/utils/getAlasABSPath.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/packages/common/utils/getAlasABSPath.ts b/webapp/packages/common/utils/getAlasABSPath.ts index b53897d03..1c3e658e1 100644 --- a/webapp/packages/common/utils/getAlasABSPath.ts +++ b/webapp/packages/common/utils/getAlasABSPath.ts @@ -8,7 +8,7 @@ import fs from 'fs'; */ const getAlasABSPath = ( files: string[] = ['**/config/deploy.yaml', '**/config/deploy.template.yaml'], - rootName: string | string[] = ['AzurLaneAutoScript', 'Alas', 'StarRailCopilot'], + rootName: string | string[] = ['AzurLaneAutoScript', 'Alas', 'StarRailCopilot', 'SRC'], ) => { const path = require('path'); const sep = path.sep; @@ -53,7 +53,6 @@ const getAlasABSPath = ( const appAbsPathArr = appAbsPath.split(sep); let flag = false; while (step > 0 && !flag) { - appAbsPathArr.pop(); const entries = fg.sync(files, { dot: true, cwd: appAbsPathArr.join(sep) as string, @@ -63,6 +62,7 @@ const getAlasABSPath = ( alasABSPath = appAbsPathArr.join(sep); } step--; + appAbsPathArr.pop(); } } From 7f1d0a9c09fe616ebaffbd6590813f31e87bad5b Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Wed, 3 Jul 2024 12:42:09 +0800 Subject: [PATCH 27/27] Fix: Ornament task delayed dungeon task --- tasks/ornament/ornament.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/tasks/ornament/ornament.py b/tasks/ornament/ornament.py index 1d94fb35f..afbb71e9b 100644 --- a/tasks/ornament/ornament.py +++ b/tasks/ornament/ornament.py @@ -44,26 +44,24 @@ class Ornament(OrnamentCombat): # Check stamina logger.info('Check stamina') stamina = self.combat_get_trailblaze_power() - if stamina < self.combat_wave_cost: - logger.info('Current trailblaze power is not enough for a run') - self.delay_dungeon_task(self.dungeon) - self.config.task_stop() - if not self.config.Ornament_UseStamina and self.config.stored.DungeonDouble.rogue <= 0: + if self.config.Ornament_UseStamina: + if stamina < self.combat_wave_cost: + logger.info('Current trailblaze power is not enough for a run') + self.delay_dungeon_task(self.dungeon) + self.config.task_stop() + elif self.config.stored.DungeonDouble.rogue > 0: + if stamina < self.combat_wave_cost: + logger.info('Doing double rogue, current trailblaze power is not enough for a run') + self.delay_dungeon_task(self.dungeon) + self.config.task_stop() + else: if self.config.stored.Immersifier.value <= 0: logger.info('Current immersifier is not enough for a run') - self.delay_dungeon_task(self.dungeon) + self.config.task_delay(server_update=True) self.config.task_stop() return result - def delay_dungeon_task(self, dungeon: DungeonList): - with self.config.multi_set(): - super().delay_dungeon_task(dungeon) - if not self.config.Ornament_UseStamina and self.config.stored.DungeonDouble.rogue <= 0: - if self.config.stored.Immersifier.value <= 0: - logger.info('Immersifier exhausted') - self.config.task_delay(server_update=True) - def run(self): self.config.update_battle_pass_quests() self.config.update_daily_quests()