From 303a1a820cd5eec034c05c9e756a58e54ee77382 Mon Sep 17 00:00:00 2001 From: xoipz <85264015+xoipz@users.noreply.github.com> Date: Sun, 28 Sep 2025 22:12:13 +0800 Subject: [PATCH] =?UTF-8?q?js:=E6=AF=8F=E6=97=A5=E5=A7=94=E6=89=98=200.98.?= =?UTF-8?q?6=20(#2025)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/RecognitionObject/TalkExit.png | Bin 0 -> 1922 bytes .../Data/RecognitionObject/TalkIcon.png | Bin 0 -> 596 bytes .../Data/RecognitionObject/商店.png | Bin 0 -> 5336 bytes repo/js/AutoCommission/README.md | 15 +- .../process/冒险家安娜/蒙德城/process.json | 50 ++-- .../process/冒险家安娜/蒙德城/与安娜对话.json | 16 +- .../蒙德城/冒险家,安娜!-蒙德城-2.json | 72 +++--- .../蒙德城/冒险家,安娜!-蒙德城-4(1).json | 53 ++-- .../蒙德城/冒险家,安娜!-蒙德城-5.json | 53 ++-- .../process/冒险家安娜/蒙德城/击退盗宝团.json | 16 +- .../process/冒险家安娜/蒙德城/执行分支一.json | 31 +++ .../process/冒险家安娜/蒙德城/执行分支二.json | 13 +- .../process/应急补给/龙脊雪山/process.json | 114 +++++++++ .../应急补给/龙脊雪山/与里瑟对话1.json | 34 +++ .../应急补给/龙脊雪山/与里瑟对话2.json | 34 +++ .../应急补给/龙脊雪山/与里瑟对话3.json | 34 +++ .../应急补给/龙脊雪山/与里瑟对话4.json | 34 +++ .../应急补给/龙脊雪山/与里瑟对话5.json | 34 +++ .../应急补给/龙脊雪山/与里瑟对话6.json | 34 +++ .../应急补给/龙脊雪山/与里瑟对话7.json | 34 +++ .../应急补给/龙脊雪山/与里瑟对话总文件.json | 45 ++++ .../应急补给/龙脊雪山/向里瑟回报1.json | 33 +++ .../应急补给/龙脊雪山/向里瑟回报2.json | 33 +++ .../应急补给/龙脊雪山/向里瑟回报3.json | 33 +++ .../应急补给/龙脊雪山/向里瑟回报4.json | 33 +++ .../应急补给/龙脊雪山/向里瑟回报5.json | 33 +++ .../应急补给/龙脊雪山/向里瑟回报6.json | 33 +++ .../应急补给/龙脊雪山/向里瑟回报7.json | 33 +++ .../应急补给/龙脊雪山/向里瑟回报对话.json | 38 +++ .../process/应急补给/龙脊雪山/应急补给-1.json | 35 +++ .../process/应急补给/龙脊雪山/应急补给-2.json | 26 ++ .../process/应急补给/龙脊雪山/应急补给-3.json | 26 ++ .../process/应急补给/龙脊雪山/应急补给-4.json | 26 ++ .../应急补给/龙脊雪山/应急补给-5 (2).json | 26 ++ .../process/应急补给/龙脊雪山/应急补给-5.json | 89 +++++++ .../应急补给/龙脊雪山/应急补给-6 (2).json | 26 ++ .../process/应急补给/龙脊雪山/应急补给-6.json | 67 +++++ .../应急补给/龙脊雪山/应急补给-7 (2).json | 26 ++ .../process/应急补给/龙脊雪山/应急补给-7.json | 49 ++++ .../process/应急补给/龙脊雪山/应急补给-8.json | 44 ++++ .../process/惊喜大礼/蒙德城/process.json | 14 +- .../process/愿风带走思念/蒙德城/process.json | 63 ++--- .../愿风带走思念/蒙德城/采集蒲公英籽path.json | 107 ++++++++ .../蒙德城/采集蒲公英籽process.json | 17 ++ .../愿鲜花气息逗留/蒙德城/process.json | 59 +++-- .../新的风暴尚未出现/望风海岸/process.json | 68 +++++ .../望风海岸/前往望风角塔楼顶部.json | 170 +++++++++++++ .../望风海岸/新的风暴尚未出现-1.json | 84 +++++++ .../望风海岸/新的风暴尚未出现-2.json | 107 ++++++++ .../望风海岸/新的风暴尚未出现-3.json | 44 ++++ .../望风海岸/新的风暴尚未出现-4.json | 35 +++ .../新的风暴尚未出现/望风角/process.json | 76 +++++- .../望风角/前往望风角塔楼顶部.json | 109 +++++--- .../望风角/新的风暴尚未出现-2.json | 89 +++++-- .../望风角/新的风暴尚未出现-3.json | 50 ++-- .../望风角/新的风暴尚未出现-4.json | 35 +++ .../艾伯特先生别再冲了/蒙德城/process.json | 15 ++ .../蒙德城/艾伯特先生别再冲了-蒙德城-2.json | 17 +- .../蒙德城/艾伯特先生别再冲了-蒙德城-3.json | 24 +- .../蒙德城/艾伯特先生别再冲了-蒙德城-6.json | 215 ++++++++++++++++ .../艾伯特先生别再冲了一/蒙德城/process.json | 15 ++ .../蒙德城/艾伯特先生别再冲了-蒙德城-2.json | 17 +- .../蒙德城/艾伯特先生别再冲了-蒙德城-3.json | 24 +- .../蒙德城/艾伯特先生别再冲了-蒙德城-6.json | 215 ++++++++++++++++ .../蒙德城/process.json | 15 ++ .../蒙德城/艾伯特先生别再冲了-蒙德城-2.json | 17 +- .../蒙德城/艾伯特先生别再冲了-蒙德城-3.json | 24 +- .../蒙德城/艾伯特先生别再冲了-蒙德城-6.json | 215 ++++++++++++++++ .../钥匙是易丢品/晨曦酒庄/process.json | 69 +++-- .../钥匙是易丢品/晨曦酒庄/东南方向位置.json | 46 ++++ .../钥匙是易丢品/晨曦酒庄/西北方向位置.json | 46 ++++ .../钥匙是易丢品/晨曦酒庄/钥匙是易丢品-2.json | 76 ++++++ .../钥匙是易丢品/晨曦酒庄/钥匙是易丢品-3.json | 76 ++++++ .../钥匙是易丢品/晨曦酒庄/钥匙是易丢品-4.json | 58 +++++ .../钥匙是易丢品/晨曦酒庄/钥匙是易丢品-5.json | 103 ++++++++ .../钥匙是易丢品/晨曦酒庄/钥匙是易丢品-6.json | 76 ++++++ .../钥匙是易丢品/晨曦酒庄/钥匙是易丢品-7.json | 49 ++++ .../钥匙是易丢品/晨曦酒庄/钥匙是易丢品-8.json | 58 +++++ .../钥匙是易丢品/晨曦酒庄/钥匙是易丢品-9.json | 76 ++++++ .../晨曦酒庄/钥匙是易丢品-晨曦酒庄-1.json | 76 ++++++ .../钥匙是易丢品/达达乌帕谷/process.json | 74 +++--- .../达达乌帕谷/去达达乌帕谷西南方位置.json | 41 +++ .../达达乌帕谷/没拿到钥匙重试.json | 36 +++ .../达达乌帕谷/达达乌帕谷北方位置.json | 40 +++ .../达达乌帕谷/钥匙是易丢品-1.json | 76 ++++++ .../达达乌帕谷/钥匙是易丢品-2-1.json | 130 ++++++++++ .../达达乌帕谷/钥匙是易丢品-2-2.json | 58 +++++ .../达达乌帕谷/钥匙是易丢品-2-3.json | 113 +++++++++ .../达达乌帕谷/钥匙是易丢品-2-4.json | 76 ++++++ .../达达乌帕谷/钥匙是易丢品-2.json | 112 +++++++++ .../达达乌帕谷/钥匙是易丢品-3.json | 76 ++++++ .../达达乌帕谷/钥匙是易丢品-4.json | 49 ++++ .../process/餐品订单/蒙德城/process.json | 49 ++-- .../assets/process/餐品订单/蒙德城/取餐.json | 4 + .../assets/危险运输现象/望风山地-1.json | 160 +++++++----- .../assets/固若金汤/龙脊雪山-1.json | 193 ++++++++------ .../assets/极速前进/龙脊雪山-1.json | 238 +++++++++++------- .../assets/邪恶的扩张/望风山地-1.json | 112 ++++----- repo/js/AutoCommission/{lib => }/constants.js | 4 +- .../js/AutoCommission/lib/commission-basic.js | 33 --- repo/js/AutoCommission/lib/core.js | 6 +- .../js/AutoCommission/lib/dialog-processor.js | 69 ++++- repo/js/AutoCommission/lib/execute.js | 11 +- repo/js/AutoCommission/lib/image_utils.js | 134 ++++++++++ repo/js/AutoCommission/lib/steps/base.js | 19 ++ .../AutoCommission/lib/steps/close-store.js | 25 ++ .../steps/commission-description-detection.js | 29 ++- .../lib/steps/commission-tracking.js | 7 +- .../lib/steps/location-detection.js | 2 +- repo/js/AutoCommission/lib/ui.js | 27 +- repo/js/AutoCommission/lib/utils.js | 207 ++++++++++++--- repo/js/AutoCommission/main.js | 4 +- repo/js/AutoCommission/manifest.json | 2 +- repo/js/AutoCommission/name.json | 5 +- 114 files changed, 5597 insertions(+), 798 deletions(-) create mode 100644 repo/js/AutoCommission/Data/RecognitionObject/TalkExit.png create mode 100644 repo/js/AutoCommission/Data/RecognitionObject/TalkIcon.png create mode 100644 repo/js/AutoCommission/Data/RecognitionObject/商店.png create mode 100644 repo/js/AutoCommission/assets/process/冒险家安娜/蒙德城/执行分支一.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/process.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/与里瑟对话1.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/与里瑟对话2.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/与里瑟对话3.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/与里瑟对话4.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/与里瑟对话5.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/与里瑟对话6.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/与里瑟对话7.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/与里瑟对话总文件.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/向里瑟回报1.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/向里瑟回报2.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/向里瑟回报3.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/向里瑟回报4.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/向里瑟回报5.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/向里瑟回报6.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/向里瑟回报7.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/向里瑟回报对话.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/应急补给-1.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/应急补给-2.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/应急补给-3.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/应急补给-4.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/应急补给-5 (2).json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/应急补给-5.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/应急补给-6 (2).json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/应急补给-6.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/应急补给-7 (2).json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/应急补给-7.json create mode 100644 repo/js/AutoCommission/assets/process/应急补给/龙脊雪山/应急补给-8.json create mode 100644 repo/js/AutoCommission/assets/process/愿风带走思念/蒙德城/采集蒲公英籽path.json create mode 100644 repo/js/AutoCommission/assets/process/愿风带走思念/蒙德城/采集蒲公英籽process.json create mode 100644 repo/js/AutoCommission/assets/process/新的风暴尚未出现/望风海岸/process.json create mode 100644 repo/js/AutoCommission/assets/process/新的风暴尚未出现/望风海岸/前往望风角塔楼顶部.json create mode 100644 repo/js/AutoCommission/assets/process/新的风暴尚未出现/望风海岸/新的风暴尚未出现-1.json create mode 100644 repo/js/AutoCommission/assets/process/新的风暴尚未出现/望风海岸/新的风暴尚未出现-2.json create mode 100644 repo/js/AutoCommission/assets/process/新的风暴尚未出现/望风海岸/新的风暴尚未出现-3.json create mode 100644 repo/js/AutoCommission/assets/process/新的风暴尚未出现/望风海岸/新的风暴尚未出现-4.json create mode 100644 repo/js/AutoCommission/assets/process/新的风暴尚未出现/望风角/新的风暴尚未出现-4.json create mode 100644 repo/js/AutoCommission/assets/process/艾伯特先生别再冲了/蒙德城/艾伯特先生别再冲了-蒙德城-6.json create mode 100644 repo/js/AutoCommission/assets/process/艾伯特先生别再冲了一/蒙德城/艾伯特先生别再冲了-蒙德城-6.json create mode 100644 repo/js/AutoCommission/assets/process/艾伯特先生别再冲了一一/蒙德城/艾伯特先生别再冲了-蒙德城-6.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/晨曦酒庄/东南方向位置.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/晨曦酒庄/西北方向位置.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/晨曦酒庄/钥匙是易丢品-2.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/晨曦酒庄/钥匙是易丢品-3.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/晨曦酒庄/钥匙是易丢品-4.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/晨曦酒庄/钥匙是易丢品-5.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/晨曦酒庄/钥匙是易丢品-6.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/晨曦酒庄/钥匙是易丢品-7.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/晨曦酒庄/钥匙是易丢品-8.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/晨曦酒庄/钥匙是易丢品-9.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/晨曦酒庄/钥匙是易丢品-晨曦酒庄-1.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/达达乌帕谷/去达达乌帕谷西南方位置.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/达达乌帕谷/没拿到钥匙重试.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/达达乌帕谷/达达乌帕谷北方位置.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/达达乌帕谷/钥匙是易丢品-1.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/达达乌帕谷/钥匙是易丢品-2-1.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/达达乌帕谷/钥匙是易丢品-2-2.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/达达乌帕谷/钥匙是易丢品-2-3.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/达达乌帕谷/钥匙是易丢品-2-4.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/达达乌帕谷/钥匙是易丢品-2.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/达达乌帕谷/钥匙是易丢品-3.json create mode 100644 repo/js/AutoCommission/assets/process/钥匙是易丢品/达达乌帕谷/钥匙是易丢品-4.json rename repo/js/AutoCommission/{lib => }/constants.js (98%) create mode 100644 repo/js/AutoCommission/lib/image_utils.js create mode 100644 repo/js/AutoCommission/lib/steps/base.js create mode 100644 repo/js/AutoCommission/lib/steps/close-store.js diff --git a/repo/js/AutoCommission/Data/RecognitionObject/TalkExit.png b/repo/js/AutoCommission/Data/RecognitionObject/TalkExit.png new file mode 100644 index 0000000000000000000000000000000000000000..a3b6f129b07efa2c725e3735594360ec75164ef4 GIT binary patch literal 1922 zcmbVN4Tuy~9G{B}Dp*G#=_MD69Vn(&LK>aW5gLXeQ7I9T(FNL@{pym_q=A`v^WN|M z{=fgn`_HRwv6cn%?wv;v#DYj`IF8@7_+CEe7W~}*QSYbtHP>!k;}XRD#r|DGYatzR|Bw`9V8>0zg<*I@WU1u@_Rpiz1*q>%8vIy}qL8{R=NOncr z$dKhAQf3qy@{&w8s0^=&lBzyR3LGC`xd6+HG_Pn9rwIaCz9?+X(NkJHyt-@)e+8+u z=h+&|=JRk+HjZ4Y*MX?H56i6ey|J~BgMeo_3Cqe> z64h3bOol>!VpOuO(=c@_@7B-QgTlZ=K}z5RndVel5E8uTCr%Em-~t-Qm7q~eH&Xqx zLWOIgxN3CZf&T>SP)k`(4q%^+9Oyx;ZT3)PHIiD$%32OKjMa%V=Odv|n`5PnEM9Qq zElp&kIi&EaqR;}v7v)ByTEuicU_ulL2PqsM#xQhES9l0fN~Dttt}CcW0b1o!3avsh zpr|Si5ieEthb`FaSAoC3bRcvKVvc|0DJg_xv4NvSSx(U$CqX(XBRmR7Iubb~0U%V^ zo^lL)CP8*4tFKDOj8Z@iBo!6Xa#8{`N=gb1WGP8Q5v2f^Nu6>Dd-mj(y8*aF-tsd%5r&sK8-Nx4XUJM-L+C)9yqA62gmMa z3X#2@ei!uJSpCgqvm|R)^)n0if2uDB2d079gK(>5Dc>K~Z%U=qu-9g-xHhAKRp7WQ z`on5F#vj#&j!aDL;C9{Fq8uZL8YU8MOmrQ+G_}s!KrSJ=uUy@^?rz$6^MeCxCI@3H zhUK%<-AzO8+uaX-^RPPh$OGqV?jX_&>+U(R^O!ny`Q5s67ncR$dPnG36hHOGNWA@_ z;nVvsqKQ}P2Ny3n@_R!~`^a|tv)1}OqeuDi>EBkbJ$_=@+}w_d5BKny6Y3Yqmxp)k zy2^BP1mk0OzO{Sz*K6mWi^m3;BV*xKV^QFTL(7J~e4>7s93A>@`q#W?p++_GUZ-x8Svdgb-^{d8zxXx~={;d7^Ag@s)6`114L_x&tBpEnQJ zt$g}Vvhmiy>z_oP*>-zv&4SepC!NJtHf}z?cfQzu=F*lI-`g|^PEGCm_WrXI=)mQ3 vO@rsX&55bb*Zw%YJa!f@UfBNEy3xlrMu!d_{P?cV{l8?SITqgA)cw-m58sL* literal 0 HcmV?d00001 diff --git a/repo/js/AutoCommission/Data/RecognitionObject/TalkIcon.png b/repo/js/AutoCommission/Data/RecognitionObject/TalkIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..9f2865cc11d0cc4ab9e467362f94f048febbe652 GIT binary patch literal 596 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9e!3HGRnB|`UDb}Eakt!T9t@@)p(fTMZ9?SFX_STSH1BXlflX;-kl$x-TwKGzy93W?e`pa1|5uIRY+X>^xN)tPj}n@v3xe^ z^twkE-NQdG-yd@%dG$4>2?3#DYvWGO*ZZN}zc%Wy{Qpnka?xAa8a#o#)ARoo2?FV6 z&cgx?H=@ek-()_pNg?radT~g&XWKd!{@EE8>uD>IJVID8rgPS1gSXB2arVk}6wU&iw z1+ER_JUqdoZ{xK^t5g`WR%&r(>lVrgy9y>s1nEsT{LAbdvO4tCQ=`dRQ@O5YO|4xS zqBZ4os?gG)&Z3<@BCa#~Yrkd36rSxB@m76gq1L5z$Y4p-+MtyoD?-5rYjkxymIzI~ b^q=wdAJ=w;0<8tWWWwO->gTe~DWM4fXd4UO literal 0 HcmV?d00001 diff --git a/repo/js/AutoCommission/Data/RecognitionObject/商店.png b/repo/js/AutoCommission/Data/RecognitionObject/商店.png new file mode 100644 index 0000000000000000000000000000000000000000..3d8502bdc802eb70c935e6985284b0a40ce2b491 GIT binary patch literal 5336 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 5) { + if (repetition >= 5 && !isInMainUI()) { log.info("连续5次选项数量一样,执行F跳过"); keyPress("F"); repetition = 0; @@ -188,9 +191,48 @@ var DialogProcessor = { } // 如果没有找到优先选项,则使用默认跳过 - if (!foundPriorityOption) { - keyPress("F"); - await sleep(100); + if (!foundPriorityOption && !isInMainUI()) { + let exitList = await Utils.easyTemplateMatch( + Constants.TALK_EXIT_IMAGE_PATH, + dialogRegion, + (useMask = true) + ); + let iconList = await Utils.easyTemplateMatch( + Constants.TALK_ICON_IMAGE_PATH, + dialogRegion + ); + let clickXY = null; + //正常应该只识别到一个退出选项,如果识别到多个,则去点击气泡对话选项 + if (exitList.count === 1) { + log.info("发现一个退出对话选项"); + clickXY = [exitList[0].x, exitList[0].y]; + + //点击最下边的气泡选项 + } else if (iconList.count > 0) { + log.info( + `发现{count}个气泡对话选项,点击最后一个`, + iconList.count + ); + iconList = [...iconList]; + iconList.sort((a, b) => b.y - a.y); + clickXY = [iconList[0].x, iconList[0].y]; + } else { + log.warn("指定类型的对话选项不符合数量条件,不进行操作"); + log.warn( + `退出图标:{exit}个,气泡图标:{icon}个`, + exitList.count, + iconList.count + ); + } + + //点击对话选项 + if (clickXY) { + keyDown("VK_MENU"); + await sleep(300); + click(...clickXY); + leftButtonClick(); + keyUp("VK_MENU"); + } } } } @@ -206,7 +248,10 @@ var DialogProcessor = { log.info("已返回主界面,自动剧情执行完成"); keyPress("V"); } else { - log.warn("已达到最大尝试次数 {attempts},但未检测到返回主界面", maxAttempts); + log.warn( + "已达到最大尝试次数 {attempts},但未检测到返回主界面", + maxAttempts + ); } }, -}; \ No newline at end of file +}; diff --git a/repo/js/AutoCommission/lib/execute.js b/repo/js/AutoCommission/lib/execute.js index f0ca05fc7..d9ebf627c 100644 --- a/repo/js/AutoCommission/lib/execute.js +++ b/repo/js/AutoCommission/lib/execute.js @@ -222,10 +222,10 @@ var Execute = { }, // 自动导航到NPC对话位置(从main_branch.js移植) - autoNavigateToTalk: async function(npcName, iconType) { + autoNavigateToTalk: async function(npcName, iconType,autoTalk) { npcName = npcName || ""; iconType = iconType || ""; - + autoTalk = autoTalk || false; try { // 设置目标NPC名称 var textArray = npcName; @@ -271,6 +271,9 @@ var Execute = { // 检测到特点文字则结束!!! if (rewardResult.text == textArray) { log.info("已到达指定位置,检测到文字: " + rewardResult.text); + if (autoTalk) { + keyPress("VK_F"); + } return; } else if (advanceNum > 80) { throw new Error("前进时间超时"); @@ -327,7 +330,7 @@ var Execute = { } // 初始化UI检测器和配置 - var isInMainUI = UI.UIUtils.createMainUIChecker(); + var isInMainUI = UI.UIUtils.isInMainUI; var priorityOptions = []; var npcWhiteList = []; @@ -559,7 +562,7 @@ var Execute = { file.readTextSync(scriptPath); var targetPos = await CommissionBasic.getCommissionTargetPosition(scriptPath); if (targetPos) { - var distance = CommissionBasic.calculateDistance( + var distance = Utils.calculateDistance( commission.CommissionPosition, targetPos ); diff --git a/repo/js/AutoCommission/lib/image_utils.js b/repo/js/AutoCommission/lib/image_utils.js new file mode 100644 index 000000000..172ca050f --- /dev/null +++ b/repo/js/AutoCommission/lib/image_utils.js @@ -0,0 +1,134 @@ +// 原神每日委托自动执行脚本 - 图像识别工具模块 +// 感谢 吉吉喵 +// OTZ +var ImageUtils = { + + // 全局资源管理变量 + globalLatestRa: null, + + // 增强版图像识别函数 + recognizeImage: async function( + recognitionObject, + ra, + timeout, + interval, + useNewScreenshot, + iconType + ) { + timeout = timeout || 1000; + interval = interval || 500; + useNewScreenshot = useNewScreenshot || false; + iconType = iconType || null; + + var startTime = Date.now(); + + // 只释放与当前ra不同的全局资源 + if (ImageUtils.globalLatestRa && ImageUtils.globalLatestRa !== ra) { + ImageUtils.globalLatestRa.dispose(); + } + ImageUtils.globalLatestRa = ra; + var originalRa = ra; + var tempRa = null; + + try { + while (Date.now() - startTime < timeout) { + var currentRa; + if (useNewScreenshot) { + // 释放之前的临时资源 + if (tempRa) { + tempRa.dispose(); + } + tempRa = captureGameRegion(); + currentRa = tempRa; + ImageUtils.globalLatestRa = currentRa; + } else { + // 不使用新截图时直接使用原始ra,不重复释放 + currentRa = originalRa; + } + + if (currentRa) { + try { + var result = currentRa.find(recognitionObject); + if (result.isExist() && result.x !== 0 && result.y !== 0) { + return { + isDetected: true, + iconType: iconType, + x: result.x, + y: result.y, + width: result.width, + height: result.height, + ra: ImageUtils.globalLatestRa, + usedNewScreenshot: useNewScreenshot + }; + } + } catch (error) { + log.error("【{iconType}识别异常】: {error}", iconType || "未知", error.message); + } + } + + await sleep(interval); + } + } finally { + // 释放临时资源但保留全局引用的资源 + if (tempRa && tempRa !== ImageUtils.globalLatestRa) { + tempRa.dispose(); + } + // 只释放原始资源如果它不再是全局引用 + if (originalRa && originalRa !== ImageUtils.globalLatestRa) { + originalRa.dispose(); + } + } + + return { + isDetected: false, + iconType: iconType, + x: null, + y: null, + width: null, + height: null, + ra: ImageUtils.globalLatestRa, + usedNewScreenshot: useNewScreenshot + }; + }, + + // 释放全局图像资源 + disposeGlobalResources: function() { + if (ImageUtils.globalLatestRa) { + ImageUtils.globalLatestRa.dispose(); + ImageUtils.globalLatestRa = null; + } + }, + + // 获取当前全局图像资源 + getGlobalImageResource: function() { + return ImageUtils.globalLatestRa; + } +}; + +// 使用示例: +// +// 1. 基础使用 +// var captureRegion = captureGameRegion(); +// var ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/button.png")); +// var result = await ImageUtils.recognizeImage(ro, captureRegion); +// +// 2. 完整参数使用 +// var result = await ImageUtils.recognizeImage( +// recognitionObject, // 识别对象 +// captureRegion, // 截图区域 +// 2000, // 超时时间(毫秒) +// 300, // 重试间隔(毫秒) +// true, // 使用新截图 +// "按钮图标" // 图标类型(用于日志) +// ); +// +// 3. 处理识别结果 +// if (result.isDetected) { +// log.info("找到{iconType},位置: ({x}, {y})", result.iconType, result.x, result.y); +// click(result.x + result.width/2, result.y + result.height/2); +// } else { +// log.warn("未找到{iconType}", result.iconType); +// } +// +// 4. 清理资源 +// ImageUtils.disposeGlobalResources(); diff --git a/repo/js/AutoCommission/lib/steps/base.js b/repo/js/AutoCommission/lib/steps/base.js new file mode 100644 index 000000000..5e53dc6f1 --- /dev/null +++ b/repo/js/AutoCommission/lib/steps/base.js @@ -0,0 +1,19 @@ +// 按键步骤处理器 +(function () { + StepProcessorLoader.register("按键", async function (step, context) { + try { + } catch (error) { + log.error("执行按键步骤时出错: {error}", error.message); + throw error; + } + }); +})(); + +/* +JSON使用示例: +{ + "type": "", + "data": "", + "note": "" +} +*/ diff --git a/repo/js/AutoCommission/lib/steps/close-store.js b/repo/js/AutoCommission/lib/steps/close-store.js new file mode 100644 index 000000000..2870a7f75 --- /dev/null +++ b/repo/js/AutoCommission/lib/steps/close-store.js @@ -0,0 +1,25 @@ +// 按键步骤处理器 +(function () { + StepProcessorLoader.register("关闭商店界面", async function (step, context) { + try { + const isStoreUI = UI.UIUtils.isStoreUI; + + await sleep(500); + if (isStoreUI) { + keyPress("ESC"); + } + await sleep(500); + } catch (error) { + log.error("执行按键步骤时出错: {error}", error.message); + throw error; + } + }); +})(); + +/* +JSON使用示例: +{ + "type": "关闭商店界面", + "note": "关闭商店界面(如果现在在商店页面)" +} +*/ diff --git a/repo/js/AutoCommission/lib/steps/commission-description-detection.js b/repo/js/AutoCommission/lib/steps/commission-description-detection.js index b7834fe6d..23290b58b 100644 --- a/repo/js/AutoCommission/lib/steps/commission-description-detection.js +++ b/repo/js/AutoCommission/lib/steps/commission-description-detection.js @@ -7,7 +7,9 @@ // 处理step.data,支持字符串和对象格式 var targetDescription = ""; var executeFile = step.run || ""; - + var runType = step.data?.runType || "process"; + var useKeyword = step.data?.useKeyword || false; + if (typeof step.data === "string") { targetDescription = step.data; } else if (typeof step.data === "object") { @@ -42,10 +44,13 @@ log.debug("检测到委托名称或空文本,继续等待..."); } // 成功匹配,开始插入step - else if (ocrResult === targetDescription) { + else if ( + (!useKeyword && ocrResult === targetDescription) || + (useKeyword && ocrResult.includes(targetDescription)) + ) { log.info("委托描述检测成功,执行后续步骤"); - - if (executeFile) { + + if (executeFile && runType === "process") { var nextSteps = await Execute.loadAndParseProcessFile( context.commissionName, context.location, @@ -56,6 +61,20 @@ context.processSteps.splice(context.currentIndex + 1, 0, ...nextSteps); log.info("已插入 {count} 个后续步骤", nextSteps.length); } + } else if (executeFile && runType === "path") { + executeFile = executeFile || "path.json" + filePath = Constants.TALK_PROCESS_BASE_PATH + "/" + context.commissionName + "/" + context.location + "/" + executeFile; + try { + await pathingScript.runFile(filePath); + } catch (error) { + log.warn( + "未找到对话委托 {name} 在 {location} 的地图追踪文件: {path}", + context.commissionName, + context.location, + executeFile + ); + return false; + } } break; } else { @@ -89,6 +108,8 @@ JSON使用示例: "data": { "description": "目标描述文本", // 必需: 要检测的描述 "executeFile": "后续文件.json" // 可选: 检测成功后执行的文件 + "runType": "process" // 可选: process | path 默认process, process表示执行流程文件, path表示执行路径文件 + "useKeyword": false // 可选: 是否使用关键字匹配, 默认false, true表示完全匹配description, false表示委托描述部分包含description即可 }, "note": "检测委托描述并执行后续步骤" } diff --git a/repo/js/AutoCommission/lib/steps/commission-tracking.js b/repo/js/AutoCommission/lib/steps/commission-tracking.js index 841cd0131..19cfd1457 100644 --- a/repo/js/AutoCommission/lib/steps/commission-tracking.js +++ b/repo/js/AutoCommission/lib/steps/commission-tracking.js @@ -5,12 +5,14 @@ // 获取目标NPC名称和图标类型 var targetNpc = ""; var iconType = "bigmap"; - + var autoTalk = false; + if (typeof step.data === "string") { targetNpc = step.data; } else if (typeof step.data === "object") { if (step.data.npc) targetNpc = step.data.npc; if (step.data.iconType) iconType = step.data.iconType; + if (step.data.autoTalk) autoTalk = step.data.autoTalk; } log.info( @@ -20,7 +22,7 @@ ); // 执行自动导航到对话位置 - await Execute.autoNavigateToTalk(targetNpc, iconType); + await Execute.autoNavigateToTalk(targetNpc, iconType, autoTalk); log.info("追踪委托执行完成"); } catch (error) { @@ -49,6 +51,7 @@ JSON使用示例: "data": { "npc": "NPC名称", // 必需: 目标NPC名称 "iconType": "bigmap" // 可选: 图标类型,默认"bigmap" + "autoTalk": true // 可选: 是否自动对话,默认false }, "note": "追踪委托到指定NPC" } diff --git a/repo/js/AutoCommission/lib/steps/location-detection.js b/repo/js/AutoCommission/lib/steps/location-detection.js index ea00c3609..bd6bbbb3b 100644 --- a/repo/js/AutoCommission/lib/steps/location-detection.js +++ b/repo/js/AutoCommission/lib/steps/location-detection.js @@ -29,7 +29,7 @@ ); if (commissionTarget) { - var distance = CommissionBasic.calculateDistance(commissionTarget, { + var distance = Utils.calculateDistance(commissionTarget, { x: targetX, y: targetY, }); diff --git a/repo/js/AutoCommission/lib/ui.js b/repo/js/AutoCommission/lib/ui.js index 238f1e4d0..6cfacd8f0 100644 --- a/repo/js/AutoCommission/lib/ui.js +++ b/repo/js/AutoCommission/lib/ui.js @@ -91,8 +91,8 @@ var UI = { // UI工具模块 - 处理UI检测和文本提取等工具函数 UIUtils: { - // 创建主界面检测函数 - createMainUIChecker: function() { + // 检测是否在主界面 + isInMainUI: function() { var paimonMenuRo = RecognitionObject.TemplateMatch( file.ReadImageMatSync("Data/RecognitionObject/paimon_menu.png"), 0, @@ -101,11 +101,24 @@ var UI = { genshin.width / 5.0 ); - return function() { - var captureRegion = captureGameRegion(); - var res = captureRegion.Find(paimonMenuRo); - return !res.isEmpty(); - }; + var captureRegion = captureGameRegion(); + var res = captureRegion.Find(paimonMenuRo); + return !res.isEmpty(); }, + + isStoreUI: function() { + var paimonMenuRo = RecognitionObject.TemplateMatch( + file.ReadImageMatSync("Data/RecognitionObject/商店.png"), + 0, + 0, + genshin.width / 3.0, + genshin.width / 5.0 + ); + + var captureRegion = captureGameRegion(); + var res = captureRegion.Find(paimonMenuRo); + return !res.isEmpty(); + }, + } }; \ No newline at end of file diff --git a/repo/js/AutoCommission/lib/utils.js b/repo/js/AutoCommission/lib/utils.js index cc05fb7be..1d967441d 100644 --- a/repo/js/AutoCommission/lib/utils.js +++ b/repo/js/AutoCommission/lib/utils.js @@ -1,26 +1,39 @@ // 原神每日委托自动执行脚本 - 工具函数模块 var Utils = { // OCR区域调试工具 - iframe: async function(ocrRegion) { + iframe: async function (ocrRegion) { try { // 参数验证 if (!ocrRegion || typeof ocrRegion !== "object") { log.error("OCR区域参数不能为空且必须是对象, 收到: " + typeof ocrRegion); return; } - + var X = ocrRegion.X; var Y = ocrRegion.Y; var WIDTH = ocrRegion.WIDTH; var HEIGHT = ocrRegion.HEIGHT; - + // 属性验证 - if (typeof X !== "number" || typeof Y !== "number" || - typeof WIDTH !== "number" || typeof HEIGHT !== "number") { - log.error("OCR区域的X、Y、WIDTH、HEIGHT必须都是数字, 收到: X=" + X + ", Y=" + Y + ", WIDTH=" + WIDTH + ", HEIGHT=" + HEIGHT); + if ( + typeof X !== "number" || + typeof Y !== "number" || + typeof WIDTH !== "number" || + typeof HEIGHT !== "number" + ) { + log.error( + "OCR区域的X、Y、WIDTH、HEIGHT必须都是数字, 收到: X=" + + X + + ", Y=" + + Y + + ", WIDTH=" + + WIDTH + + ", HEIGHT=" + + HEIGHT + ); return; } - + log.info("i{index}", { X: X, Y: Y, WIDTH: WIDTH, HEIGHT: HEIGHT }); // 最简单的方式创建OCR识别对象 @@ -33,7 +46,7 @@ var Utils = { region.Find(ro); // 2000毫秒后移除绘制的边框 - setTimeout(function() { + setTimeout(function () { // 使用相同的名称移除边框 var drawContent = VisionContext.Instance().DrawContent; drawContent.RemoveRect("debug"); @@ -46,34 +59,125 @@ var Utils = { log.error("详细错误: " + JSON.stringify(error)); } }, - - // 简单OCR识别函数 - easyOCR: async function(ocrRegion) { + easyTemplateMatch: async function (imgPath, ocrRegion, useMask = false) { try { // 参数验证 if (!ocrRegion || typeof ocrRegion !== "object") { log.error("OCR区域参数不能为空且必须是对象, 收到: " + typeof ocrRegion); return { count: 0 }; } - + var X = ocrRegion.X; var Y = ocrRegion.Y; var WIDTH = ocrRegion.WIDTH; var HEIGHT = ocrRegion.HEIGHT; - + // 属性验证 - if (typeof X !== "number" || typeof Y !== "number" || - typeof WIDTH !== "number" || typeof HEIGHT !== "number") { - log.error("OCR区域的X、Y、WIDTH、HEIGHT必须都是数字, 收到: X=" + X + ", Y=" + Y + ", WIDTH=" + WIDTH + ", HEIGHT=" + HEIGHT); + if ( + typeof X !== "number" || + typeof Y !== "number" || + typeof WIDTH !== "number" || + typeof HEIGHT !== "number" + ) { + log.error( + "OCR区域的X、Y、WIDTH、HEIGHT必须都是数字, 收到: X=" + + X + + ", Y=" + + Y + + ", WIDTH=" + + WIDTH + + ", HEIGHT=" + + HEIGHT + ); return { count: 0 }; } - + // 数值合理性验证 if (X < 0 || Y < 0 || WIDTH <= 0 || HEIGHT <= 0) { - log.error("OCR区域参数必须为正数, 收到: X=" + X + ", Y=" + Y + ", WIDTH=" + WIDTH + ", HEIGHT=" + HEIGHT); + log.error( + "OCR区域参数必须为正数, 收到: X=" + + X + + ", Y=" + + Y + + ", WIDTH=" + + WIDTH + + ", HEIGHT=" + + HEIGHT + ); return { count: 0 }; } - + + // log.info("进行文字识别") + // 创建OCR识别对象 + let mat = file.readImageMatSync(imgPath); + var TemplateMatchRo = RecognitionObject.TemplateMatch( + mat, + X, + Y, + WIDTH, + HEIGHT + ); + TemplateMatchRo.UseMask = useMask; + + // 截图识别 + var captureRegion = captureGameRegion(); + var results = await captureRegion.findMulti(TemplateMatchRo); + + return results; + } catch (error) { + log.error("easyOCR识别出错: {error}", error.message); + return { count: 0 }; + } + }, + // 简单OCR识别函数 + easyOCR: async function (ocrRegion) { + try { + // 参数验证 + if (!ocrRegion || typeof ocrRegion !== "object") { + log.error("OCR区域参数不能为空且必须是对象, 收到: " + typeof ocrRegion); + return { count: 0 }; + } + + var X = ocrRegion.X; + var Y = ocrRegion.Y; + var WIDTH = ocrRegion.WIDTH; + var HEIGHT = ocrRegion.HEIGHT; + + // 属性验证 + if ( + typeof X !== "number" || + typeof Y !== "number" || + typeof WIDTH !== "number" || + typeof HEIGHT !== "number" + ) { + log.error( + "OCR区域的X、Y、WIDTH、HEIGHT必须都是数字, 收到: X=" + + X + + ", Y=" + + Y + + ", WIDTH=" + + WIDTH + + ", HEIGHT=" + + HEIGHT + ); + return { count: 0 }; + } + + // 数值合理性验证 + if (X < 0 || Y < 0 || WIDTH <= 0 || HEIGHT <= 0) { + log.error( + "OCR区域参数必须为正数, 收到: X=" + + X + + ", Y=" + + Y + + ", WIDTH=" + + WIDTH + + ", HEIGHT=" + + HEIGHT + ); + return { count: 0 }; + } + // log.info("进行文字识别") // 创建OCR识别对象 var locationOcrRo = RecognitionObject.Ocr(X, Y, WIDTH, HEIGHT); @@ -90,7 +194,7 @@ var Utils = { }, // 单个OCR识别函数 - easyOCROne: async function(ocrdata) { + easyOCROne: async function (ocrdata) { var results = await Utils.easyOCR(ocrdata); if (results.count > 0) { // 取第一个结果作为地点 @@ -100,14 +204,14 @@ var Utils = { }, // 清理文本(去除标点符号等) - cleanText: function(text) { + cleanText: function (text) { if (!text) return ""; // 去除标点符号和特殊字符 return text.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, "").trim(); }, // 解析跳过的委托列表 - parseSkipCommissions: function(skipCommissionsStr) { + parseSkipCommissions: function (skipCommissionsStr) { if (!skipCommissionsStr || typeof skipCommissionsStr !== "string") { return []; } @@ -115,12 +219,16 @@ var Utils = { // 支持中文逗号和英文逗号分割 return skipCommissionsStr .split(/[,,]/) - .map(function(name) { return name.trim(); }) - .filter(function(name) { return name.length > 0; }); + .map(function (name) { + return name.trim(); + }) + .filter(function (name) { + return name.length > 0; + }); }, // 读取角色别名文件 - readAliases: function() { + readAliases: function () { try { var combatText = file.ReadTextSync("Data/avatar/combat_avatar.json"); var combatData = JSON.parse(combatText); @@ -142,7 +250,7 @@ var Utils = { }, // 获取设置配置 - getSetting: async function() { + getSetting: async function () { try { var skipRecognition = settings.skipRecognition || false; var prepare = settings.prepare || false; @@ -171,7 +279,7 @@ var Utils = { }, // 输出版本和编译时间信息 - errorlog: async function() { + errorlog: async function () { // 输出版本和编译时间信息 log.info("=".repeat(20)); log.info("版本: {version}", Constants.VERSION); @@ -180,18 +288,18 @@ var Utils = { }, // 睡眠函数包装 - sleep: function(ms) { + sleep: function (ms) { return sleep(ms); }, // 随机延迟函数 - randomDelay: async function(min, max) { + randomDelay: async function (min, max) { var delay = Math.random() * (max - min) + min; return await Utils.sleep(delay); }, // 人名提取函数 - extractName: function(text) { + extractName: function (text) { var patterns = [ /与(.+?)对话/, /与(.+?)一起/, @@ -225,7 +333,7 @@ var Utils = { }, // 错误处理和恢复函数 - handleError: async function(error, context) { + handleError: async function (error, context) { log.error("发生错误: {error}", error.message); if (context) { @@ -238,5 +346,38 @@ var Utils = { } catch (recoveryError) { log.warn("返回主界面时出错: {error}", recoveryError.message); } - } -}; \ No newline at end of file + }, + + // 计算两点之间的距离 + calculateDistance: function (point1, point2) { + if ( + !point1 || + !point2 || + !point1.X || + !point1.Y || + !point2.x || + !point2.y + ) { + log.warn("无效的位置数据"); + return Infinity; + } + return Math.sqrt( + Math.pow(point1.X - point2.x, 2) + Math.pow(point1.Y - point2.y, 2) + ); + }, + + // 确保目录存在 + ensureDirectoryExists: async function (dirPath) { + try { + // 尝试创建目录,如果目录已存在,writeTextSync不会报错 + // 创建一个临时文件来确保目录存在 + var tempFilePath = dirPath + "/.temp"; + file.writeTextSync(tempFilePath, ""); + // log.info(`已确保目录存在: ${dirPath}`); + return true; + } catch (error) { + log.error("创建目录时出错: {error}", error); + return false; + } + }, +}; diff --git a/repo/js/AutoCommission/main.js b/repo/js/AutoCommission/main.js index 6be31889d..391fea53f 100644 --- a/repo/js/AutoCommission/main.js +++ b/repo/js/AutoCommission/main.js @@ -2,7 +2,7 @@ // BGI兼容的模块化架构实现 // === 模块加载区域(顶层执行,BGI要求) === -eval(file.readTextSync("lib/constants.js")); +eval(file.readTextSync("constants.js")); eval(file.readTextSync("lib/utils.js")); eval(file.readTextSync("lib/ui.js")); eval(file.readTextSync("lib/core.js")); @@ -32,7 +32,7 @@ const test = async () => { location: "测试位置", processSteps: processSteps, currentIndex: 0, - isInMainUI: UI.UIUtils.createMainUIChecker(), + isInMainUI: UI.UIUtils.isInMainUI, priorityOptions: [], npcWhiteList: [] }; diff --git a/repo/js/AutoCommission/manifest.json b/repo/js/AutoCommission/manifest.json index 34cf88542..fe6acf868 100644 --- a/repo/js/AutoCommission/manifest.json +++ b/repo/js/AutoCommission/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "(对话+成就)全自动蒙德地区每日委托", - "version": "0.98.5", + "version": "0.98.6", "tags": ["委托","对话","战斗","成就","历练点"], "description": "自动完成每日委托、自动识别委托内容、自动追踪战斗委托、自动完成对话委托、自动获得到隐藏成就。使用前请阅读README.md获取详细说明和常见问题解答。目前项目急需人手,有意者可加群。感谢云闲vsv & 换苏伟u & 小鹰划船不用桨 & 塔台 & 未知_ 的共同开发", "authors": [ diff --git a/repo/js/AutoCommission/name.json b/repo/js/AutoCommission/name.json index e11cb4328..c1e1a8d2c 100644 --- a/repo/js/AutoCommission/name.json +++ b/repo/js/AutoCommission/name.json @@ -21,7 +21,6 @@ "艾琳未来的骑士", "艾琳未来的骑士一", "报答神明的方式", - "餐品订单", "趁鲜花气息逗留", "触不可及的恋人", "此路不通", @@ -53,11 +52,13 @@ "钥匙是易丢品", "一个男孩的去信", "应付尽付", + "应急补给", "永不停歇的风与米歇尔小姐", "语言交流", "圆滚滚的大团骚乱", "愿风带走思念", - "中度冰寒" + "中度冰寒", + "餐品订单" ], "ban": ["愿鲜花气息逗留"] } \ No newline at end of file