From 2b874442abb8e3e66ce49e1c3dc1b8a53646cd35 Mon Sep 17 00:00:00 2001 From: iris10086 <93846901+iris10086@users.noreply.github.com> Date: Sat, 16 Aug 2025 11:48:07 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E8=AF=86=E5=88=AB=E5=AE=9D?= =?UTF-8?q?=E7=AE=B1=E9=80=BB=E8=BE=91=E3=80=82=20=E6=9A=82=E6=9C=AA?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=9C=B0=E8=84=89=E8=8A=B1=E3=80=82=20(#2073?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AutoOpenChest/Assets/1920x1080/chest.png | Bin 0 -> 2671 bytes .../Assets/1920x1080/chest_F_icon.png | Bin 0 -> 1477 bytes .../Assets/1920x1080/flower_F_icon.png | Bin 0 -> 1076 bytes .../Assets/AutoOpenChestAssets.cs | 60 ++++++++++ .../AutoOpenChest/AutoOpenChestTask.cs | 106 ++++++++++++++++++ 5 files changed, 166 insertions(+) create mode 100644 BetterGenshinImpact/GameTask/AutoOpenChest/Assets/1920x1080/chest.png create mode 100644 BetterGenshinImpact/GameTask/AutoOpenChest/Assets/1920x1080/chest_F_icon.png create mode 100644 BetterGenshinImpact/GameTask/AutoOpenChest/Assets/1920x1080/flower_F_icon.png create mode 100644 BetterGenshinImpact/GameTask/AutoOpenChest/Assets/AutoOpenChestAssets.cs create mode 100644 BetterGenshinImpact/GameTask/AutoOpenChest/AutoOpenChestTask.cs diff --git a/BetterGenshinImpact/GameTask/AutoOpenChest/Assets/1920x1080/chest.png b/BetterGenshinImpact/GameTask/AutoOpenChest/Assets/1920x1080/chest.png new file mode 100644 index 0000000000000000000000000000000000000000..7797de1c1e70c5a4fc92df28012bc2a867a7dc5b GIT binary patch literal 2671 zcmV-#3Xt`QP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D3Is_+K~z{rg_muN zT}OGxe=~E=x##ZQ-Mwqaj$!RMab&WNEj1*js({cB6)ypm1o%!Mv;s>(s#=vVq$!1x z5Ml*H3u*~zV+Wg;L{&or1o4iDOhQs1lq9xO?|QS&?%wx%_uhNn=7kS)_S%W4I#;7P z_sp4@|2*@b=l?unZeg#Rs#d7RG2n0xq!0)xz&RY?oMTc1h^+@d;$q(`$|YY35cbvm zV64R$ORZL;*=&N6h&|U_>n_{Ajla0V6DX%L!cBYP$;F4Qj(+@&prP(+9HGvRRD-ofT2y2nfp@2X@C?%niMDmiVB#~59lq6D$ zP)R~538Wwj0;*9&ty(26=ahhOj+wZ^;n!csYwP^_H^1S`i!U-7jR1#|ib@m#kfs^N z7^F6abLY-o91R2r#)FjqIenJjo?oIn8euZ+?cp5OXo@1kxviTfa8}Um_WYp<_X@{T z7(=_)_mjb>|N-7VZpE6WT023~j6HgA#I&`7Y zMM0<2@u0e0k~E$4TkEhuyVXW(<4K)ox%bja5d@yxMr-Xfz}U0sySFSmUt9 zAq6~i;spPG{1~78+1ff$14_nYM&l7G^e(|!htY;2*F5qckMh+MC;8R0zopUX@X*N<-2asaXf!+i zJOrrHPYni}kmK7KYZ#_G@DH%Fcn3-c=jw09(#~)KJp0TG>6Fr6gcNF#!_fKksafpu#l!H z<21nuQ3A>`dV>KDCMGYmK_G~O2qhGzBp*U>{Ny+I%+Y%pY;MwMG}u?AATZWY6dGeK4$#Js z7-4fmeXdTRLe^V7e)yB0a?ia-873)7ma(v~z(dE5arExbaP2jV#Bt33E-i8V#T-X`b`^>C-e?ZN&Dy``l)~ z%VqUCQ5=(`3ANc-jI(U4Z%~b^7-N{N%`jc7(QLH{qlo?cU&n2?zMuErd^59g+ZrxBN3b+wCwfIoS|VHOt`NwO5@EY>+h z`Saog>&*tgc}=s)$8or zdnH%xy%M7fq!dUgvCd$uL8<^L1J*Yhym0yqgW(XdbKibftH#{^kq`5MTW|H^s5RCY z0u>ObpwuwI@`aap@WfYnu@hz7&tIg`Y7u}BH9OrdQcC8gr?AeE zr>PILq?#z;;^HDlKKv2lsVe_={5WeDF7T~y{TCR^Os&Sxo_K=6V8DF6&KuwSM*jYe zzhmdN?Np-(E{SfoigS=@?*@vZz!-~~p5Ok7P$~B8Uf>Of4^ypHQA!eqAu0%vN+N@@ zN|>+D^4f(x^m|=~o11KGG+1vmc;?r?qTB7VW9JUua^sEM`SClLpPOT5dJ2TkF#JWo zSdt`RFdXv4sZ;#&nP*7S6e*=7&vW{{9$A(m$H1a za%-5Hsd4DgA@0264)*TeO?_r&GDZl2yflUqf=b0F4((Q(qVU;`lv0vq8NGhL)HLCh z(HWdGW$NNHjjf~8g`uJp|MZ0~aLX;XFf%txW({w;@y#4PdXzm23!pX5ltOELRQT!$ zQz?mcj&{3EQ51w>h|G)Jn^Q;-(uWm7Od>)jO4pBfV%9o@^hY{Zo8q&dzKgfs_@}(* zZSUZ|yYFH5u3bn#1eC-T|JoWU`jK^c|@uWn&_Q18y<{Fb199X=Do8IwuDwU8*6ifp3EmI3u z+OBM!04IHm5MD8@E0xoE3P?`{>nu`Aq)=GnbNVF9`0nH1Kx933IbMES8>2x dy^ahNzXuW~tsb86_NxE@002ovPDHLkV1kifAL#%9 literal 0 HcmV?d00001 diff --git a/BetterGenshinImpact/GameTask/AutoOpenChest/Assets/1920x1080/chest_F_icon.png b/BetterGenshinImpact/GameTask/AutoOpenChest/Assets/1920x1080/chest_F_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2c79d58854cb2aaba959a3ce7d55280a144539b8 GIT binary patch literal 1477 zcmV;$1v>hPP)Px#1ZP1_K>z@;j|==^1poj7YEVp6MKeB3i;|hTzQen}!@9k~ue7rMr@6htijkNyK1+#^m+tTI|NsB~{{HFe?8(f}$ji>!+~52A`-qU2xV*sq z{r=?T=flRz!o|th+THs4`?tHmt+BV`yhK}_0^{lbB%+Jz)hmLD=eem(} z*V){tt+T4Hw8zTMYjk~IXmZuq+M%Ybp{K3)`1tMa?_X(hO;=;xlnI!7@)O4{7sCp1BOf{WYT;N0He%g)hZ zX>^yJqpTb!;o;)a)75>1i!wb*E;>g>QC!s3*L#79 zZFYY^OIP*w_Wk|+_4W1F*x7%EjWn|fLMb&u`T6;YkC#taW5mbF>gww8@$vHV^7Hfa#mCAgG(syj zL{C^`YI1vRbbV}ed`?(oCNn`ZwLZuI000SaNLh0L01m?d01m?e$8V@)0008yNkl}8CCm=~oN={+6b|Ne#IVllI!ZDDFPJ*45p25vT0#Aj5z8;dv%}7r}a{L51DMym# z7NM|L*s0TJ>{+HF!i}lqXF=9EB%WtFn} zTD7vKGJvyDVb{w6UCY;Ka9LeleFI)`L#x&i0z#+O#^1yn>g(!cxJJXTZ3OhKCaF}f zAc#m_a|=mVWjC-JZdcJ{OEWK$AQXD3wCN74)CL4akp@EA-T4^wl6xG^R zQ`7!nqcV_cwVI|=_2?}zeJV}EF==R9uO2>n4CxRXjV3c)_(TOO)zd=SY%&_f9i5#W z9nsGkf%19R3rKfQZ*O1!06l0Dumz?;dZ53rx3{MoJ?eT1s{)C}0X{TrrnDyRD=lRn z9)e$INAen0H6s=~7-k(E8>e({bkz9Rs1?H;^CRuBnqaPo0kchtt0{`A7EjvjH;xFL zKoxVNb}Y83xA{~)F=ewjW+0+>up$+X5dyPLz5np>lXY_?He1mOtIyMpksW+yYUba6 z<}^I7**R|Px#1ZP1_K>z@;j|==^1poj6@=#1vMJzW(D>g(bHbW^jLqAGZU1o7`c!GO_i*I;= zSz>KDL{Ta>M0g;80 zcREE;&(hWU`uoGj%aWL%m7Ai|)!3`AwPtR3>g(*Apr9ysI0N4tFWf3ucD@_ z{r&yK#>s+-kcyF*i;|gec!B2T=IiY2`~3X$^!1OGoag7~?d|QWu(j;$?D_fm@bU72 zh>+;$=-YEf`uh5}yT4CaWc&O3sjjoAt+UkD z*WlvhAsa~E(u8yaxWCs|JnP_96itI`@^31`+1(7ncbZQ za5x-?^Z>mWMp*dah=|CjXoCU>&gdgCM~}t2;*Q5BxEW($FqU}Yq{l1cJC)?-92h&D zY$~DnQc}@U z4sapFm8&%8!Zo?v^&4cxB{bi(t<>O%WogRFE9hBS#WB@2G}pqdbb4C119eq*>gD0@ zLc=||nH6kIYT7@GXx7hc*0z9f-?y8JtJM!ew6)t+rm%yfiR#WSxe~5blvgGM887Zm z?jd?mA6|!D8t3^zB=g}TY|1c3rN`s#eXPp9Ju%Uqs-oF5RWy69ie@ix!VNWh`M-r; zy)J*#*H54ApLqrbGtHslx0;QNTHa7-OtJ-cuz^4J6_Y8|G_yGFz`Y% u=J<)$vn$`j>E0t7d%xm-|DnGEW9% +{ + public RecognitionObject ChestIconRo; + public RecognitionObject ChestFIconRo; + public RecognitionObject FlowerFIconRo; + + +#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑添加 "required" 修饰符或声明为可为 null。 + private AutoOpenChestAssets() : base() + { + Initialization(this.systemInfo); + } + + protected AutoOpenChestAssets(ISystemInfo systemInfo) : base(systemInfo) + { + Initialization(systemInfo); + } +#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑添加 "required" 修饰符或声明为可为 null。 + + private void Initialization(ISystemInfo systemInfo) + { + var assetScale = systemInfo.AssetScale; + ChestIconRo = new RecognitionObject + { + Name = "ChestIcon", + RecognitionType = RecognitionTypes.TemplateMatch, + TemplateImageMat = GameTaskManager.LoadAssetImage("AutoOpenChest", "chest.png", systemInfo), + RegionOfInterest = new Rect((int)(330* assetScale), + (int)(130*assetScale), + (int)(1250*assetScale), + (int)(840 * assetScale)), + DrawOnWindow = false + }.InitTemplate(); + + ChestFIconRo = new RecognitionObject + { + Name = "ChestFIcon", + RecognitionType = RecognitionTypes.TemplateMatch, + TemplateImageMat = GameTaskManager.LoadAssetImage("AutoOpenChest", "chest_F_icon.png", systemInfo), + RegionOfInterest = new Rect((int)(1150 * assetScale),(int)(450 * assetScale),(int)(100 * assetScale),(int)(300 * assetScale)), + DrawOnWindow = false + }.InitTemplate(); + + + FlowerFIconRo = new RecognitionObject + { + Name = "FlowerFIcon", + RecognitionType = RecognitionTypes.TemplateMatch, + TemplateImageMat = GameTaskManager.LoadAssetImage("AutoOpenChest", "flower_F_icon.png", systemInfo), + RegionOfInterest = new Rect((int)(1150 * assetScale), (int)(450 * assetScale), (int)(100 * assetScale), (int)(300 * assetScale)), + DrawOnWindow = false + }.InitTemplate(); + } +} diff --git a/BetterGenshinImpact/GameTask/AutoOpenChest/AutoOpenChestTask.cs b/BetterGenshinImpact/GameTask/AutoOpenChest/AutoOpenChestTask.cs new file mode 100644 index 00000000..73074c0b --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoOpenChest/AutoOpenChestTask.cs @@ -0,0 +1,106 @@ +using BetterGenshinImpact.Core.Simulator; +using BetterGenshinImpact.Core.Simulator.Extensions; +using BetterGenshinImpact.GameTask; +using BetterGenshinImpact.GameTask.AutoFishing.Assets; +using BetterGenshinImpact.GameTask.Common.BgiVision; +using BetterGenshinImpact.GameTask.Model.Area; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using static BetterGenshinImpact.GameTask.Common.TaskControl; +using static TorchSharp.torch.distributions.constraints; +namespace GameTask.AutoOpenChest; + +/// +/// 识别宝箱图标,走向宝箱并开启。 +/// +public class AutoOpenChestTask : ISoloTask +{ + public string Name => "识别并开启宝箱"; + + private AutoOpenChestAssets assets = AutoOpenChestAssets.Instance; + + public async Task Start(CancellationToken ct) + { + var ra = CaptureToRectArea(); + + if (ra.Find(assets.ChestFIconRo).IsExist()) + { + CancellationTokenSource _ct = new(); + ct.Register(_ct.Cancel); + bool isFlower = false; // 是否是地脉花 + // 限制寻找宝箱的时间 + var timeLimit = 60; + var timeoutTask = Task.Delay(TimeSpan.FromSeconds(timeLimit), _ct.Token) + .ContinueWith(_ => _ct.Cancel(), TaskContinuationOptions.OnlyOnRanToCompletion); + try + { + while (!_ct.IsCancellationRequested) + { + ra = CaptureToRectArea(); + Region chestIcon = ra.Find(assets.ChestIconRo); + int limit = chestIcon.Width; + if (!chestIcon.IsExist()) + { + Logger.LogInformation("未找到宝箱图标"); + return; + } + + if (ra.Find(assets.ChestFIconRo).IsExist() || ra.Find(assets.FlowerFIconRo).IsExist()) + { + // 找到宝箱/ 地脉花 + isFlower = ra.Find(assets.FlowerFIconRo).IsExist(); + Simulation.SendInput.SimulateAction(GIActions.PickUpOrInteract, KeyType.KeyPress); + Simulation.SendInput.SimulateAction(GIActions.MoveForward, KeyType.KeyUp); + break; + } + + if (Math.Abs(chestIcon.Width / 2 - chestIcon.X) < limit) + { + Simulation.SendInput.SimulateAction(GIActions.MoveForward, KeyType.KeyDown); + } + + if (chestIcon.Y > 600) + { + // 若宝箱图标在下方就表示宝箱在后面。 + Simulation.SendInput.SimulateAction(GIActions.MoveBackward); + await Delay(30, _ct.Token); + Simulation.SendInput.Mouse.MiddleButtonClick(); + } + else + { + var gap = (ra.Width / 2) - chestIcon.X; + int rate = 2; + Simulation.SendInput.Mouse.MoveMouseBy(gap / rate, 0); + } + + await Delay(500, _ct.Token); + } + } + finally + { + // 如果循环提前退出,取消计时任务 + Simulation.SendInput.SimulateAction(GIActions.MoveForward, KeyType.KeyUp); + _ct.Cancel(); + await timeoutTask; // 等待超时任务结束(忽略可能的异常) + } + + // TODO : 是否考虑兼容地脉花 以及地脉花的获取策略 + + if (isFlower) { + // 地脉花策略 + flowerHandle(); + } + } + } + + private async void flowerHandle() + { + Simulation.SendInput.SimulateAction(GIActions.OpenPaimonMenu); + } + + +}