diff --git a/repo/js/诛贼-地方传奇-利亚姆/README.md b/repo/js/诛贼-地方传奇-利亚姆/README.md new file mode 100644 index 000000000..24f695f4e --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/README.md @@ -0,0 +1,13 @@ +# 说明 + +该脚本会打一只地方传奇-利亚姆。 + + + +- 关于利亚姆: + 1. 没有万叶拾取很难,所以请确保账号上有万叶在队伍的3号,否则不要选择拾取! + 2. 操作角色默认是 1号提纳里 其他弓箭手不是水就可以,没有小提换安柏,影响的原因是脚本的计算精度不够从而导致失败(作者的水平有限( •̀ ω •́ ))。 + 2号是钟离,一定一定要有钟离,成功率有74%以上! 当然如果你没有就换诺艾尔,不过成功率感人,基本是白跑。 + 3. 没有解密的水池还没有制作判断的逻辑,抱歉! + + diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/跳加下落.json b/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/跳加下落.json new file mode 100644 index 000000000..68a96c30e --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/跳加下落.json @@ -0,0 +1,13 @@ +{"macroEvents":[ +{"type":0,"keyCode":87,"mouseX":0,"mouseY":0,"time":25}, +{"type":0,"keyCode":32,"mouseX":0,"mouseY":0,"time":72}, +{"type":1,"keyCode":32,"mouseX":0,"mouseY":0,"time":197}, +{"type":0,"keyCode":32,"mouseX":0,"mouseY":0,"time":447}, +{"type":1,"keyCode":32,"mouseX":0,"mouseY":0,"time":556}, +{"type":0,"keyCode":65,"mouseX":0,"mouseY":0,"time":3081}, +{"type":1,"keyCode":65,"mouseX":0,"mouseY":0,"time":3991}, +{"type":4,"mouseX":960,"mouseY":540,"mouseButton":"Left","time":4681}, +{"type":5,"mouseX":960,"mouseY":540,"mouseButton":"Left","time":4760}, +{"type":1,"keyCode":87,"mouseX":0,"mouseY":0,"time":4847} +], +"info":{"name":"","description":"","x":0,"y":0,"width":1920,"height":1080,"recordDpi":1}} \ No newline at end of file diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标下一.json b/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标下一.json new file mode 100644 index 000000000..975abb72c --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标下一.json @@ -0,0 +1,15 @@ +{ + "macroEvents": [ + {"type": 3, "mouseX": 0, "mouseY": 0, "time": 0}, + {"type": 3, "mouseX": 0, "mouseY": 1, "time": 2} + ], + "info": { + "name": "向下移动一小段", + "description": "鼠标向下移动1单位", + "x": 0, + "y": 0, + "width": 1920, + "height": 1080, + "recordDpi": 1 + } +} \ No newline at end of file diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标右一.json b/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标右一.json new file mode 100644 index 000000000..1f8999810 --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标右一.json @@ -0,0 +1,15 @@ +{ + "macroEvents": [ + {"type": 3, "mouseX": 0, "mouseY": 0, "time": 0}, + {"type": 3, "mouseX": 1, "mouseY": 0, "time": 2} + ], + "info": { + "name": "横向移动一小段", + "description": "鼠标向右移动1单位", + "x": 0, + "y": 0, + "width": 1920, + "height": 1080, + "recordDpi": 1 + } +} \ No newline at end of file diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标右负十.json b/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标右负十.json new file mode 100644 index 000000000..cc0d33b22 --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标右负十.json @@ -0,0 +1,15 @@ +{ + "macroEvents": [ + {"type": 3, "mouseX": 0, "mouseY": 0, "time": 0}, + {"type": 3, "mouseX": -10, "mouseY": 0, "time": 50} + ], + "info": { + "name": "横向移动一小段", + "description": "鼠标向右移动1单位", + "x": 0, + "y": 0, + "width": 1920, + "height": 1080, + "recordDpi": 1 + } +} \ No newline at end of file diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标右负百.json b/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标右负百.json new file mode 100644 index 000000000..3db704a91 --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/assets/Laim/鼠标右负百.json @@ -0,0 +1,15 @@ +{ + "macroEvents": [ + {"type": 3, "mouseX": 0, "mouseY": 0, "time": 0}, + {"type": 3, "mouseX": -100, "mouseY": 0, "time": 50} + ], + "info": { + "name": "横向移动一小段", + "description": "鼠标向右移动1单位", + "x": 0, + "y": 0, + "width": 1920, + "height": 1080, + "recordDpi": 1 + } +} \ No newline at end of file diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/DENG.png b/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/DENG.png new file mode 100644 index 000000000..a2fbdf1c9 Binary files /dev/null and b/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/DENG.png differ diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/DENG02.png b/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/DENG02.png new file mode 100644 index 000000000..6a8917b09 Binary files /dev/null and b/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/DENG02.png differ diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/Shui.png b/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/Shui.png new file mode 100644 index 000000000..0d357c583 Binary files /dev/null and b/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/Shui.png differ diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/血条.png b/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/血条.png new file mode 100644 index 000000000..4d072c4ac Binary files /dev/null and b/repo/js/诛贼-地方传奇-利亚姆/assets/Recognition/血条.png differ diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/pathing/Laim/Laim.json b/repo/js/诛贼-地方传奇-利亚姆/assets/pathing/Laim/Laim.json new file mode 100644 index 000000000..66c40a5cb --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/assets/pathing/Laim/Laim.json @@ -0,0 +1,150 @@ +{ + "config": { + "realtime_triggers": { + "AutoPick": true + } + }, + "farming_info": { + "allow_farming_count": false, + "duration_seconds": 0, + "elite_details": "", + "elite_mob_count": 0, + "normal_mob_count": 0, + "primary_target": "", + "total_mora": 0 + }, + "info": { + "authors": [], + "bgi_version": "0.45.0", + "description": "", + "enable_monster_loot_split": false, + "items": [], + "last_modified_time": 1759326224575, + "map_match_method": "", + "map_name": "Teyvat", + "name": "Laim", + "order": 0, + "tags": [], + "type": "collect", + "version": "" + }, + "positions": [ + { + "action": "", + "id": 1, + "move_mode": "dash", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "teleport", + "x": 3032.96875, + "y": 3732.7021484375 + }, + { + "action": "", + "id": 2, + "move_mode": "run", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "path", + "x": 3024.32421875, + "y": 3775.64599609375 + }, + { + "action": "", + "id": 3, + "move_mode": "run", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "path", + "x": 2990.998046875, + "y": 3794.330078125 + }, + { + "action": "", + "action_params": "", + "id": 4, + "move_mode": "run", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "path", + "x": 2953.8056640625, + "y": 3780.5087890625 + }, + { + "action": "", + "action_params": "", + "id": 5, + "move_mode": "walk", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "target", + "x": 2946.76171875, + "y": 3774.2529296875 + }, + { + "action": "combat_script", + "action_params": "keydown(W),wait(0.08),keyup(W)", + "id": 6, + "move_mode": "walk", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "orientation", + "x": 2916.25, + "y": 3780 + } + ] +} \ No newline at end of file diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/pathing/Laim/Laim1.json b/repo/js/诛贼-地方传奇-利亚姆/assets/pathing/Laim/Laim1.json new file mode 100644 index 000000000..d3397514c --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/assets/pathing/Laim/Laim1.json @@ -0,0 +1,117 @@ +{ + "config": { + "realtime_triggers": { + "AutoPick": true + } + }, + "farming_info": { + "allow_farming_count": false, + "duration_seconds": 0, + "elite_details": "", + "elite_mob_count": 0, + "normal_mob_count": 0, + "primary_target": "", + "total_mora": 0 + }, + "info": { + "authors": [], + "bgi_version": "0.45.0", + "description": "", + "enable_monster_loot_split": false, + "items": [], + "last_modified_time": 1766719019531, + "map_match_method": "", + "map_name": "Teyvat", + "name": "Laim1", + "order": 0, + "tags": [], + "type": "collect", + "version": "" + }, + "positions": [ + { + "action": "", + "id": 1, + "move_mode": "dash", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "teleport", + "x": 3032.96875, + "y": 3732.7021484375 + }, + { + "action": "", + "id": 2, + "move_mode": "run", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "path", + "x": 3062.5, + "y": 3771.5 + }, + { + "action": "", + "id": 3, + "move_mode": "run", + "point_ext_params": { + "description": "", + "enable_monster_loot_split": false, + "misidentification": { + "arrival_time": 0, + "handling_mode": "previousDetectedPoint", + "type": [ + "unrecognized" + ] + } + }, + "type": "path", + "x": 2990.998046875, + "y": 3794.330078125 + }, + { + "action": "", + "action_params": "", + "id": 4, + "move_mode": "walk", + "type": "path", + "x": 2968.75, + "y": 3803.25 + }, + { + "action": "", + "action_params": "", + "id": 5, + "move_mode": "walk", + "type": "path", + "x": 2951, + "y": 3800.5 + }, + { + "action": "", + "action_params": "", + "id": 6, + "move_mode": "walk", + "type": "target", + "x": 2933.46875, + "y": 3794.75 + } + ] +} \ No newline at end of file diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/ui/a.png b/repo/js/诛贼-地方传奇-利亚姆/assets/ui/a.png new file mode 100644 index 000000000..47e13acf5 Binary files /dev/null and b/repo/js/诛贼-地方传奇-利亚姆/assets/ui/a.png differ diff --git a/repo/js/诛贼-地方传奇-利亚姆/assets/ui/确认.png b/repo/js/诛贼-地方传奇-利亚姆/assets/ui/确认.png new file mode 100644 index 000000000..6a8d84c25 Binary files /dev/null and b/repo/js/诛贼-地方传奇-利亚姆/assets/ui/确认.png differ diff --git a/repo/js/诛贼-地方传奇-利亚姆/lib/Laim/lib/MobFallAttack.js b/repo/js/诛贼-地方传奇-利亚姆/lib/Laim/lib/MobFallAttack.js new file mode 100644 index 000000000..60721a9fa --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/lib/Laim/lib/MobFallAttack.js @@ -0,0 +1,146 @@ +/* ========================================================= + * MobFallAttack.js + * 功能:自动寻怪 →攻击 → 确认血条出现 + * 用法:await MobFallAttack.executeMainProcess(); + * ========================================================= */ + eval(file.readTextSync("lib/Laim/lib/core.js")); + + xietiao = RecognitionObject.TemplateMatch( + file.ReadImageMatSync('assets/Recognition/血条.png'), 600, 0, 600, 120); + Shui = RecognitionObject.TemplateMatch( + file.ReadImageMatSync('assets/Recognition/Shui.png'), 740, 90, 100, 50); +var MobFallAttack = { + + + + + + /* ---------- 2. 主流程 ---------- */ + executeMainProcess: async function () { + log.info('[MobFallAttack] ====== 下落攻击流程启动 ======'); + try { + + + const filePath = 'assets/Laim/跳加下落.json'; + const deadline = Date.now() + 60000; // 60 秒总超时 + let foundInRect = false; + + // 主轮询:60 秒内不断找水图标,找到就行动 + while (Date.now() < deadline && !foundInRect) { + const result = await this.findLiamShui(); + if (result.found && result.x >= 740 && result.x <= 800) { + log.info('[MobFallAttack] 找到Liam水图标(合格区域) '); + + /* --- 一套 combo --- */ + await keyMouseScript.runFile(filePath); // 跳+下落 + await sleep(1200); + keyPress('2'); + await sleep(600); + keyDown('e'); + await sleep(1000); + keyUp('e'); + await sleep(1000); + + foundInRect = true; // 命中后结束外层 while + } + } + + log.info('[MobFallAttack] ====== 下落攻击流程结束 ======'); + return foundInRect; // true=成功出手 + } catch (err) { + log.error(`[MobFallAttack] 流程异常: ${err.message}`); + throw err; + } + }, + + /* ---------- 3. 核心函数:找 Liam 水 + 血条守护 ---------- */ + /** + * 在当前游戏画面里找「Liam」的水图标 + * @returns {Promise<{found:boolean, x:number, y:number}>} + */ + findLiamShui: async function () { + const LIMIT = 60_000; // 单轮搜索最多 60 秒 + const start = Date.now(); + + while (Date.now() - start < LIMIT) { + const region = captureGameRegion(); + const hit1 = region.find(Shui); + if (hit1?.x && hit1?.y) { + log.info(`[findLiamShui] 水图标确认 @ (${hit1.x}, ${hit1.y})`); + return { found: true, x: hit1.x, y: hit1.y }; + } + // 血条消失立即结束 + if (!region.find(xietiao)) { + log.info('[findLiamShui] 血条消失,停止搜索'); + return { found: false, x: -1, y: -1 }; + } + await sleep(20); // 高频轮询 + } + + // 60 秒到了仍没找到 + log.warn('[findLiamShui] 60 秒限时到,强制返回未找到'); + return { found: false, x: -1, y: -1 }; + }, + + /* ---------- 4. 工具:鼠标移动脚本(可选) ---------- */ + moveMouseScripts: async function (dx, dy) { + const right = 'assets/Laim/鼠标右一.json'; + const down = 'assets/Laim/鼠标下一.json'; + for (let i = 0; i < Math.abs(dx); i++) await keyMouseScript.runFile(right); + for (let i = 0; i < Math.abs(dy); i++) await keyMouseScript.runFile(down); + }, + + + /** + * 根据地点名称执行预设的路线脚本(跑图路线) + * @param {string} locationName - 地点名称(不含扩展名) + * @returns {Promise} + */ + pathingfiy: async function(locationName) { + log.info('前往路线: '); + const filePath = `assets/Laim/pathing/${locationName}.json`; + await pathingScript.RunFile(filePath); + }, + + + + pickUp: async function () { + log.info('[MobFallAttack] 开始拾取准备'); + + await core.recognizeOnePopup(); + await genshin.tpToStatueOfTheSeven(); + + await sleep(1200); + +// await genshin.Tp(3032.96875, 3732.70); + + dispatcher.addTimer(new RealtimeTimer("AutoPick", { forceInteraction: true })); + await sleep(1200); + keyPress("1"); + await sleep(1200); + keyPress("3"); + await sleep(1200); + await this.pathingfiy('Laim1'); + + + +await sleep(1200); + keyDown('e'); + await sleep(1000); + keyUp('e'); +await sleep(300);await click(960, 540); + + await sleep(3600); + dispatcher.addTimer(new RealtimeTimer("AutoPick", { forceInteraction: false })); + + + + } + + + + + + + +}; \ No newline at end of file diff --git a/repo/js/诛贼-地方传奇-利亚姆/lib/Laim/lib/MobPuller.js b/repo/js/诛贼-地方传奇-利亚姆/lib/Laim/lib/MobPuller.js new file mode 100644 index 000000000..b6d5d09e2 --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/lib/Laim/lib/MobPuller.js @@ -0,0 +1,209 @@ +/* ========================================================= + * MobPuller.js + * 功能:自动拉怪 → 寻灯 → 射击 直到出现血条! + * 用法:await MobPuller.executeMainProcess(); + * ========================================================= */ + xietiao = RecognitionObject.TemplateMatch( + file.ReadImageMatSync('assets/Recognition/血条.png'), 600, 0, 600, 120); + Shui = RecognitionObject.TemplateMatch( + file.ReadImageMatSync('assets/Recognition/Shui.png'), 740, 90, 100, 50); +var MobPuller = { + + /* ------------------------------------------------------ + * 委托前准备:目前空壳,后续可补充吃药、换队、开 Buff 等 + * ------------------------------------------------------ */ + Run01: async function() { + log.info("[MobPuller] 开始执行前准备"); + // TODO: 换角色、吃药、开盾、记时间戳等 + log.info("[MobPuller] 前准备完成"); + }, + + /* ------------------------------------------------------ + * 主流程:移植自原 main(),已补全日志 + * ------------------------------------------------------ */ + executeMainProcess: async function() { + log.info("[MobPuller] ====== 拉怪流程启动 ======"); + try { + await this.Run01(); // 预留准备阶段 + + await sleep(200); + log.info("[MobPuller] 开始路径脚本 "); + await this.pathingfiy('Laim'); + + await genshin.returnMainUi(); + keyPress("2"); + + await sleep(600); + keyDown('e'); + await sleep(1000); + keyUp('e'); + + await sleep(600); + keyPress("1"); + + await sleep(600); + keyPress("r"); + + await sleep(100); + keyDown('w'); + await sleep(800); + keyUp('w'); + + await sleep(1200); + log.info("[MobPuller] 开始寻灯并射击"); + // 主流程里 + const ok = await this.findLamp(); + log.info('[MobPuller] ====== 拉怪流程结束 ======'); + if (!ok) { + log.warn('[MobPuller] 未找到灯/血条,流程中断') + }else{ + const down400 = 'assets/Laim/鼠标右负百.json'; + const down20 = 'assets/Laim/鼠标右负十.json'; + for (let i = 0; i < 4; i++)await keyMouseScript.runFile(down400); + for (let j = 0; j < 3; j++)await keyMouseScript.runFile(down20); + } + + return ok; + } catch (err) { + log.error(`[MobPuller] 流程异常: ${err.message}`); + throw err; // 抛到最外层统一捕获 + } + }, + + + /** + * 在当前游戏画面里找「灯」图标 + * @returns {Promise} true=检测到血条 + */ + findLamp: async function() { + /* ========== 1. 直接初始化模板 ========== */ + const lampRo = RecognitionObject.TemplateMatch( + file.ReadImageMatSync('assets/Recognition/DENG.png'), + 1160, 540, // x, y + genshin.width - 1170, // w + genshin.height / 2 // h + ); + const lampRo02 = RecognitionObject.TemplateMatch( + file.ReadImageMatSync('assets/Recognition/DENG.png'), + 1160, 540, + genshin.width - 1170, + genshin.height / 2 + ); + const xietiaoRo = RecognitionObject.TemplateMatch( + file.ReadImageMatSync('assets/Recognition/血条.png'), + 0, 0, + genshin.width, + Math.round(genshin.height / 5) + ); + + /* ========== 2. 搜索逻辑(与原流程一致) ========== */ + let a = 0; + for (let j = 0; j < 3; j++) { + const region = captureGameRegion(); + const found = region.find(lampRo); + const found2 = region.find(lampRo02); + + if (found && found.x !== 0 && found.y !== 0) { + log.info(`[findLamp] 找到灯图标(模板1) @ (${found.x}, ${found.y})`); + a++; + await this.moveLampAndclick(found.x, found.y); + } + if (found2 && found2.x !== 0 && found2.y !== 0 && a === 0) { + log.info(`[findLamp] 找到灯图标(模板2) @ (${found2.x}, ${found2.y})`); + await this.moveLampAndclick(found2.x, found2.y); + } + await sleep(600); + + /* 血条子循环 */ + for (let k = 0; k < 64; k++) { + await sleep(100); + + const ocrRes = Array.from(captureGameRegion().findMulti(RecognitionObject.ocr(900, 10, 100, 40)) || []); + const found01 = ocrRes.some(r => r.text.includes('利亚姆')); + if (found01) { log.info('[findLamp] 找到利亚姆'); return true; } + + } + } + await sleep(200); + keyPress('r'); + await sleep(200); + middleButtonClick(); + await sleep(1200); + keyPress('r'); + await sleep(800); + + log.error('[findLamp] 未找到灯或血条'); + return false; + }, + + /** + * 将灯光目标点 (lx, ly) 映射到鼠标移动脚本并左键射击 + */ + moveLampAndclick: async function(lx, ly) { + const cx = 960, cy = 540; + const dx = Math.round((lx - cx) / 2.223) - 176 - 36; + const dy = Math.round((ly - cy) / 0.8) - 60 - 109; + + const right1 = 'assets/Laim/鼠标右一.json'; + const down1 = 'assets/Laim/鼠标下一.json'; + + log.info(`[moveLampAndclick] 计算偏移 → dx=${dx}, dy=${dy}`); + + for (let i = 0; i < Math.abs(dx); i++) await keyMouseScript.runFile(right1); + for (let i = 0; i < Math.abs(dy); i++) await keyMouseScript.runFile(down1); + + await sleep(150); + keyPress("VK_LBUTTON"); + await sleep(150); + log.info("[moveLampAndclick] 射击完成"); + }, + + /** + * 根据地点名称执行预设的路线脚本(跑图路线) + * @param {string} locationName - 地点名称(不含扩展名) + * @returns {Promise} + */ + pathingfiy: async function(locationName) { + log.info('[MobPuller] 前往路线: {name}', locationName); + const filePath = `assets/pathing/Laim/${locationName}.json`; + await pathingScript.RunFile(filePath); + }, + + /** + * 执行键鼠录制脚本 + * @param {string} locationName - 键鼠脚本文件名(不含扩展名) + * @param {boolean} [istp=true] - 是否先传送 + * @param {number} [x=253.3994140625] - 传送 X + * @param {number} [y=1285.4423828125] - 传送 Y + * @returns {Promise} + */ + captureCrystalfly: async function(locationName, istp = true, x = 253.3994140625, y = 1285.4423828125) { + if (istp) { + log.info('[MobPuller] 传送至: {name}', locationName); + await genshin.tp(x, y); + await sleep(1000); + } + log.info('[MobPuller] 开始键鼠脚本: {name}', locationName); + const filePath = `assets/KeyMouseScript/${locationName}.json`; + await keyMouseScript.runFile(filePath); + }, + + /** + * 将灯光目标点 (lx, ly) 映射到鼠标移动脚本并左键射击 + * @param {number} lx - 目标 x + * @param {number} ly - 目标 y + * @returns {Promise} + */ + moveLampToCenter: async function(lx, ly) { + const cx = 960, cy = 540; + const dx = Math.round((lx - cx) / 2.4); + const dy = Math.round((ly - cy) / 1.20); + moveMouseBy(dx, 0); + moveMouseBy(0, dy); + }, + + + + +}; + diff --git a/repo/js/诛贼-地方传奇-利亚姆/lib/Laim/lib/core.js b/repo/js/诛贼-地方传奇-利亚姆/lib/Laim/lib/core.js new file mode 100644 index 000000000..4820e35ff --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/lib/Laim/lib/core.js @@ -0,0 +1,177 @@ + +const pick = settings.liam_pick_dogfood || "节约时间,不拿了"; + +var core = { + + /* ------------------------------------------------------ + * 1. 前置准备(模板、别名、分辨率等) + * ------------------------------------------------------ */ + Run01: async function () { + log.info('[Core] 开始执行前准备'); + log.info('[Core] 模板加载完成'); + await genshin.tpToStatueOfTheSeven(); + // TODO: 吃药、换队、Buff 等 + log.info('[Core] 前准备完成'); + }, + + /* ------------------------------------------------------ + * 2. 识别摩拉(依赖三个工具函数) + * ------------------------------------------------------ */ + mora: async function () { + const CharacterMenuRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Recognition/DENG.png")); + let result = 0, tryTimes = 0; + while (result === 0 && tryTimes < 3) { + await genshin.returnMainUi(); + log.info('[Core] 开始识别摩拉'); + keyPress('C'); + await sleep(1500); + + let recognized = false, startTime = Date.now(); + while (Date.now() - startTime < 5000) { + /* ---- 角色菜单图标 ---- */ + const charRes = await this.recognizeImage(CharacterMenuRo, 5000); + if (charRes.success) { + await click(177, 433); + await sleep(500); + recognized = true; + break; + } + /* ---- 天赋文字 ---- */ + const talentRes = await this.recognizeTextAndClick('天赋', { x: 133, y: 395, width: 115, height: 70 }); + if (talentRes.success) { + log.info(`[Core] 点击天赋文字 @ ${talentRes.x}, ${talentRes.y}`); + recognized = true; + break; + } + await sleep(1000); + } + + if (recognized) { + const moraText = await this.recognizeTextInRegion({ x: 1620, y: 25, width: 152, height: 46 }); + if (moraText) { + log.info(`[Core] 识别到摩拉: ${moraText}`); + result = Number(moraText) || 0; + } + } + tryTimes++; + await genshin.returnMainUi(); + await sleep(500); + } + return result; + }, + + + recognizeImage: async function (recognitionObject, timeout = 5000) { + const start = Date.now(); + while (Date.now() - start < timeout) { + try { + const r = captureGameRegion().find(recognitionObject); + if (r) return { success: true, x: r.x, y: r.y }; + } catch (e) { log.error(`[Core] 识别图像异常: ${e.message}`); } + await sleep(500); + } + log.warn('[Core] 识别图像超时'); + return { success: false }; + }, + + recognizeTextAndClick: async function (targetText, ocrRegion, timeout = 3000) { + const start = Date.now(); + let retry = 0; + while (Date.now() - start < timeout) { + try { + const list = captureGameRegion() + .findMulti(RecognitionObject.ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height)); + for (const res of list) { + if (res.text.includes(targetText)) { + const cx = Math.round(res.x + res.width / 2); + const cy = Math.round(res.y + res.height / 2); + await click(cx, cy); + await sleep(500); + return { success: true, x: cx, y: cy }; + } + } + } catch (e) { + retry++; + log.warn(`[Core] 文字识别失败,第${retry}次重试...`); + } + await sleep(1000); + } + /* 超时点默认中心 */ + const cx = Math.round(ocrRegion.x + ocrRegion.width / 2); + const cy = Math.round(ocrRegion.y + ocrRegion.height / 2); + await click(cx, cy); + await sleep(1000); + return { success: false }; + }, + + recognizeTextInRegion: async function (ocrRegion, timeout = 5000) { + const start = Date.now(); + let retry = 0; + while (Date.now() - start < timeout) { + try { + const ocrResult = captureGameRegion() + .find(RecognitionObject.ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height)); + if (ocrResult) return ocrResult.text; + } catch (e) { + retry++; + log.warn(`[Core] OCR 识别失败,第${retry}次重试...`); + } + await sleep(500); + } + log.warn('[Core] 指定区域未识别到文字'); + return null; + }, + + /* ------------------------------------------------------ + * 3. 主流程(射击 → 下落 → 摩拉校验) + * ------------------------------------------------------ */ + executeMainProcess: async function () { + log.info('[Core] >>>>>> 核心主流程启动 >>>>>>'); + try { + eval(file.readTextSync("lib/Laim/lib/MobPuller.js")); + eval(file.readTextSync("lib/Laim/lib/MobFallAttack.js")); + await this.recognizeOnePopup(); + await this.Run01(); + const moraBefore = await this.mora(); + log.info(`[Core] 开始前摩拉: ${moraBefore}`); + + const shootOK = await MobPuller.executeMainProcess(); + if (!shootOK) return false; + await sleep(5200); + await this.recognizeOnePopup(); + + const fallOK = await MobFallAttack.executeMainProcess(); + if (!fallOK) return false; + + await sleep(10000); + await this.recognizeOnePopup(); + const moraAfter = await this.mora(); + const delta = moraAfter - moraBefore; + log.info(`[Core] 摩拉增长: ${delta}`); + if ((delta >= 2000) && pick === "我全都要!") { + await MobFallAttack.pickUp(); + } + await genshin.tpToStatueOfTheSeven(); + await this.recognizeOnePopup(); + return delta >= 2000; + } catch (err) { + log.error(`[Core] 主流程异常: ${err.message}`); + throw err; + } + }, + + /** + * 识别并处理多人复活 + */ + recognizeOnePopup: async function () { + /* ---------- 1. 拼路径 ---------- */ + const iconFiles = `assets/ui/a.png`; + const tplMat = RecognitionObject.TemplateMatch(file.ReadImageMatSync(iconFiles), 0, 0, 1920, 1080); + + const joinResult = captureGameRegion().find(tplMat); + if (joinResult.isExist()) { + joinResult.click(); + await sleep(6666); + } + } +}; \ No newline at end of file diff --git a/repo/js/诛贼-地方传奇-利亚姆/lib/core.js b/repo/js/诛贼-地方传奇-利亚姆/lib/core.js new file mode 100644 index 000000000..e2bcc547e --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/lib/core.js @@ -0,0 +1,49 @@ + +eval(file.readTextSync('lib/Laim/lib/core.js')); + + +var Core = { + + + /* ------------------------------------------------------ + * 仅执行单次流程(单人) + * ------------------------------------------------------ */ + executeSingleProcess: async function () { + try { + + await genshin.switchParty(settings.partyName); + + + keyPress('1'); + await genshin.returnMainUi(); + + await core.executeMainProcess(); + + keyPress('Space'); + + // 4. 检测复活 + const iconFiles = 'assets/ui/a.png';//可能是 + const tplMat = RecognitionObject.TemplateMatch(file.ReadImageMatSync(iconFiles), 0, 0, 1920, 1080); + const joinResult = captureGameRegion().find(tplMat); + if (joinResult.isExist()) { + joinResult.click(); + await sleep(8888); + } + const iconFiles1 = 'assets/ui/确认.png';//单人 + const tplMat1 = RecognitionObject.TemplateMatch(file.ReadImageMatSync(iconFiles1), 0, 0, 1920, 1080); + const joinResult1 = captureGameRegion().find(tplMat1); + if (joinResult1.isExist()) { + joinResult1.click(); + await sleep(8888); + } + + return { ok: true, reason: '单人流程完成' }; + + } catch (e) { + log.error(`[Core] 单次流程异常:${e.message}`); + return { ok: false, reason: `异常: ${e.message}` }; + } + }, + + +}; \ No newline at end of file diff --git a/repo/js/诛贼-地方传奇-利亚姆/main.js b/repo/js/诛贼-地方传奇-利亚姆/main.js new file mode 100644 index 000000000..c84511a43 --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/main.js @@ -0,0 +1,12 @@ +eval(file.readTextSync('lib/core.js')); + +(async function main() { + try { + await sleep(2000); + await Core.executeSingleProcess(); + + + } catch (err) { + log.error(`服务崩溃: ${err.message}`); + } +})(); diff --git a/repo/js/诛贼-地方传奇-利亚姆/manifest.json b/repo/js/诛贼-地方传奇-利亚姆/manifest.json new file mode 100644 index 000000000..3779fd8ab --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/manifest.json @@ -0,0 +1,14 @@ +{ + "manifest_version": 1, + "name": "地方传奇·药剂师-利亚姆", + "version": "3.0", + "description": "打利亚姆", + "authors": [ + { + "name": "xiaozhang12312", + "links": "https://github.com/xiaozhang12312" + } + ], + "settings_ui": "settings.json", + "main": "main.js" +} \ No newline at end of file diff --git a/repo/js/诛贼-地方传奇-利亚姆/settings.json b/repo/js/诛贼-地方传奇-利亚姆/settings.json new file mode 100644 index 000000000..bf5f11d9d --- /dev/null +++ b/repo/js/诛贼-地方传奇-利亚姆/settings.json @@ -0,0 +1,15 @@ +[ + + { + "name": "liam_pick_dogfood", + "type": "select", + "label": "关于利亚姆:是否拾取狗娘(要有万叶)", + "options": ["我全都要!", "没有万叶(≧口≦)", "节约时间,不拿了"], + "default": "节约时间,不拿了" + }, + { + "name": "partyName", + "type": "input-text", + "label": "配队名称, 推荐队伍中1号提纳里 2号是钟离 3号是万叶" + } +] \ No newline at end of file