diff --git a/repo/js/AutoFriendshipFowl/README.md b/repo/js/AutoFriendshipFowl/README.md new file mode 100644 index 000000000..da01c4ded --- /dev/null +++ b/repo/js/AutoFriendshipFowl/README.md @@ -0,0 +1,21 @@ +**简介:** +--- +- 通过完成“动物密友”突发事件,获取角色好感、摩拉、锻造矿。 +- 完成突发事件每天最多可获得10次奖励。 +- 脚本会确保游戏模式为单人模式。 +- 当完成突发事件10次,或事件完成后未获得奖励时,脚本将结束运行。 +- 测试正常任务时间在8分钟左右 +--- + + +**使用说明:** + + 1. 添加脚本 + - 在 BGI 配置组中添加“禽肉好感”脚本。请不要在调度器外直接运行。 + 2. 配置组设置 + - 无需设置 + 3. JS脚本自定义配置(右键点击“禽肉好感”脚本 → 修改JS脚本自定义配置) + - 填写好感队的队伍名称 + - 确保选择的好感队为4人队 + - 确保背包里“禽肉”充足 + diff --git a/repo/js/AutoFriendshipFowl/assets/AutoPath/到狗盆.json b/repo/js/AutoFriendshipFowl/assets/AutoPath/到狗盆.json deleted file mode 100644 index ec640d5e9..000000000 --- a/repo/js/AutoFriendshipFowl/assets/AutoPath/到狗盆.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "info": { - "name": "到狗盆", - "type": "collect", - "author": "花火", - "version": "1.2", - "description": "", - "bgi_version": "0.35.1" - }, - "positions": [ - { - "id": 1, - "x": -4500.28125, - "y": -3116.0146484375, - "type": "target", - "move_mode": "walk", - "action": "" - } - ] -} \ No newline at end of file diff --git a/repo/js/AutoFriendshipFowl/assets/AutoPath/到甜甜花.json b/repo/js/AutoFriendshipFowl/assets/AutoPath/到甜甜花.json deleted file mode 100644 index 27933b165..000000000 --- a/repo/js/AutoFriendshipFowl/assets/AutoPath/到甜甜花.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "info": { - "name": "到甜甜花", - "type": "collect", - "author": "花火", - "version": "1.2", - "description": "", - "bgi_version": "0.43.5" - }, - "positions": [ - { - "id": 1, - "action": "", - "move_mode": "walk", - "type": "target", - "x": -4529.2578125, - "y": -3084.009765625 - } - ] -} \ No newline at end of file diff --git a/repo/js/AutoFriendshipFowl/assets/AutoPath/导航至甜甜花位置.json b/repo/js/AutoFriendshipFowl/assets/AutoPath/导航至甜甜花位置.json deleted file mode 100644 index bc9e003ee..000000000 --- a/repo/js/AutoFriendshipFowl/assets/AutoPath/导航至甜甜花位置.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "info": { - "name": "到达甜甜花位置", - "type": "collect", - "author": "花火", - "version": "1.2", - "description": "", - "bgi_version": "0.43.5" - }, - "positions": [ - { - "id": 1, - "action": "", - "move_mode": "walk", - "type": "teleport", - "x": -4402.525390625, - "y": -3052.986328125 - }, - { - "id": 2, - "x": -4407.537109375, - "y": -3055.0751953125, - "type": "path", - "move_mode": "walk", - "action": "" - }, - { - "id": 3, - "x": -4480.993107617283, - "y": -2996, - "type": "path", - "move_mode": "fly", - "action": "" - }, - { - "id": 4, - "x": -4500.1015625, - "y": -3004.046875, - "type": "path", - "move_mode": "walk", - "action": "" - }, - { - "id": 5, - "x": -4529.2578125, - "y": -3084.009765625, - "type": "target", - "move_mode": "walk", - "action": "" - } - ] -} \ No newline at end of file diff --git a/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_初始化.json b/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_初始化.json new file mode 100644 index 000000000..72d941105 --- /dev/null +++ b/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_初始化.json @@ -0,0 +1,85 @@ +{ + "info": { + "authors": [ + { + "links": "https://github.com/Gedley", + "name": "Gedley" + } + ], + "bgi_version": "0.45.0", + "description": "", + "enable_monster_loot_split": false, + "last_modified_time": 1776789201832, + "map_match_method": "", + "map_name": "Teyvat", + "name": "禽肉好感_初始化", + "tags": [], + "type": "collect", + "version": "1.0" + }, + "positions": [ + { + "action": "", + "action_params": "", + "id": 1, + "move_mode": "walk", + "type": "teleport", + "x": -4492, + "y": -3208 + }, + { + "action": "", + "action_params": "", + "id": 2, + "move_mode": "fly", + "type": "path", + "x": -4477.25, + "y": -3188.93 + }, + { + "action": "", + "action_params": "", + "id": 3, + "move_mode": "dash", + "type": "path", + "x": -4495.12, + "y": -3124.78 + }, + { + "action": "", + "action_params": "", + "id": 4, + "move_mode": "fly", + "type": "path", + "x": -4510.1, + "y": -3108.09 + }, + { + "action": "", + "action_params": "", + "id": 5, + "move_mode": "jump", + "type": "path", + "x": -4512.96, + "y": -3104.62 + }, + { + "action": "", + "action_params": "", + "id": 6, + "move_mode": "dash", + "type": "path", + "x": -4526.72, + "y": -3086.67 + }, + { + "action": "", + "action_params": "", + "id": 7, + "move_mode": "walk", + "type": "path", + "x": -4529.26, + "y": -3084.01 + } + ] +} \ No newline at end of file diff --git a/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_喂狗.json b/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_喂狗.json new file mode 100644 index 000000000..a93fd47a9 --- /dev/null +++ b/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_喂狗.json @@ -0,0 +1,58 @@ +{ + "info": { + "authors": [ + { + "links": "https://github.com/Gedley", + "name": "Gedley" + } + ], + "bgi_version": "0.45.0", + "description": "", + "enable_monster_loot_split": false, + "last_modified_time": 1777125351967, + "map_match_method": "", + "map_name": "Teyvat", + "name": "禽肉好感_喂狗", + "tags": [], + "type": "collect", + "version": "1.0" + }, + "positions": [ + { + "action": "", + "action_params": "", + "id": 1, + "move_mode": "dash", + "type": "path", + "x": -4512.81, + "y": -3105.59 + }, + { + "action": "", + "action_params": "", + "id": 2, + "move_mode": "jump", + "type": "path", + "x": -4510.76, + "y": -3106.63 + }, + { + "action": "", + "action_params": "", + "id": 3, + "move_mode": "dash", + "type": "path", + "x": -4502.67, + "y": -3113.98 + }, + { + "action": "", + "action_params": "", + "id": 4, + "move_mode": "walk", + "type": "path", + "x": -4500.11, + "y": -3116.63 + } + ] +} \ No newline at end of file diff --git a/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_狗盆点位.json b/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_狗盆点位.json new file mode 100644 index 000000000..5a4d8f8ef --- /dev/null +++ b/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_狗盆点位.json @@ -0,0 +1,31 @@ +{ + "info": { + "authors": [ + { + "links": "https://github.com/Gedley", + "name": "Gedley" + } + ], + "bgi_version": "0.45.0", + "description": "突发事件“动物密友”中狗盆的位置", + "enable_monster_loot_split": false, + "last_modified_time": 1776787867681, + "map_match_method": "", + "map_name": "Teyvat", + "name": "禽肉好感_狗盆点位", + "tags": [], + "type": "collect", + "version": "1.0" + }, + "positions": [ + { + "action": "", + "action_params": "", + "id": 1, + "move_mode": "walk", + "type": "target", + "x": -4500.26, + "y": -3116.57 + } + ] +} \ No newline at end of file diff --git a/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_甜甜花点位.json b/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_甜甜花点位.json new file mode 100644 index 000000000..071867017 --- /dev/null +++ b/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_甜甜花点位.json @@ -0,0 +1,31 @@ +{ + "info": { + "authors": [ + { + "links": "https://github.com/Gedley", + "name": "Gedley" + } + ], + "bgi_version": "0.45.0", + "description": "突发事件“动物密友”中甜甜花的位置", + "enable_monster_loot_split": false, + "last_modified_time": 1776787867681, + "map_match_method": "", + "map_name": "Teyvat", + "name": "禽肉好感_甜甜花点位", + "tags": [], + "type": "collect", + "version": "1.0" + }, + "positions": [ + { + "action": "", + "action_params": "", + "id": 1, + "move_mode": "walk", + "type": "target", + "x": -4529.25, + "y": -3084.01 + } + ] +} \ No newline at end of file diff --git a/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_返回.json b/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_返回.json new file mode 100644 index 000000000..873bc126a --- /dev/null +++ b/repo/js/AutoFriendshipFowl/assets/pathing/鸡腿好感_返回.json @@ -0,0 +1,58 @@ +{ + "info": { + "authors": [ + { + "links": "https://github.com/Gedley", + "name": "Gedley" + } + ], + "bgi_version": "0.45.0", + "description": "", + "enable_monster_loot_split": false, + "last_modified_time": 1776787861554, + "map_match_method": "", + "map_name": "Teyvat", + "name": "禽肉好感_返回", + "tags": [], + "type": "collect", + "version": "1.0" + }, + "positions": [ + { + "action": "", + "action_params": "", + "id": 1, + "move_mode": "dash", + "type": "path", + "x": -4510.72, + "y": -3107.23 + }, + { + "action": "", + "action_params": "", + "id": 2, + "move_mode": "jump", + "type": "path", + "x": -4512.82, + "y": -3104.66 + }, + { + "action": "", + "action_params": "", + "id": 3, + "move_mode": "dash", + "type": "path", + "x": -4527.63, + "y": -3085.92 + }, + { + "action": "", + "action_params": "", + "id": 4, + "move_mode": "walk", + "type": "path", + "x": -4529.2, + "y": -3084.2 + } + ] +} \ No newline at end of file diff --git a/repo/js/AutoFriendshipFowl/assets/事件完成.png b/repo/js/AutoFriendshipFowl/assets/事件完成.png new file mode 100644 index 000000000..8bbe550de Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/事件完成.png differ diff --git a/repo/js/AutoFriendshipFowl/assets/动物密友.png b/repo/js/AutoFriendshipFowl/assets/动物密友.png new file mode 100644 index 000000000..6f456274e Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/动物密友.png differ diff --git a/repo/js/AutoFriendshipFowl/assets/动物密友完成.png b/repo/js/AutoFriendshipFowl/assets/动物密友完成.png new file mode 100644 index 000000000..2dd845c66 Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/动物密友完成.png differ diff --git a/repo/js/AutoFriendshipFowl/assets/单人模式.png b/repo/js/AutoFriendshipFowl/assets/单人模式.png new file mode 100644 index 000000000..0e877ecf5 Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/单人模式.png differ diff --git a/repo/js/AutoFriendshipFowl/assets/单人模式确认.png b/repo/js/AutoFriendshipFowl/assets/单人模式确认.png new file mode 100644 index 000000000..7595664e0 Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/单人模式确认.png differ diff --git a/repo/js/AutoFriendshipFowl/assets/投喂.png b/repo/js/AutoFriendshipFowl/assets/投喂.png new file mode 100644 index 000000000..0339f3821 Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/投喂.png differ diff --git a/repo/js/AutoFriendshipFowl/assets/摩拉.png b/repo/js/AutoFriendshipFowl/assets/摩拉.png new file mode 100644 index 000000000..091281b74 Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/摩拉.png differ diff --git a/repo/js/AutoFriendshipFowl/assets/确认.png b/repo/js/AutoFriendshipFowl/assets/确认.png new file mode 100644 index 000000000..12645c09a Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/确认.png differ diff --git a/repo/js/AutoFriendshipFowl/assets/离开队伍.png b/repo/js/AutoFriendshipFowl/assets/离开队伍.png new file mode 100644 index 000000000..0924dfb70 Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/离开队伍.png differ diff --git a/repo/js/AutoFriendshipFowl/assets/禽肉数量.png b/repo/js/AutoFriendshipFowl/assets/禽肉数量.png new file mode 100644 index 000000000..03623b593 Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/禽肉数量.png differ diff --git a/repo/js/AutoFriendshipFowl/assets/突发事件.png b/repo/js/AutoFriendshipFowl/assets/突发事件.png new file mode 100644 index 000000000..f0f46595c Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/突发事件.png differ diff --git a/repo/js/AutoFriendshipFowl/assets/联机.png b/repo/js/AutoFriendshipFowl/assets/联机.png new file mode 100644 index 000000000..d9444e3d4 Binary files /dev/null and b/repo/js/AutoFriendshipFowl/assets/联机.png differ diff --git a/repo/js/AutoFriendshipFowl/main.js b/repo/js/AutoFriendshipFowl/main.js index b49d62eb2..ff96153c7 100644 --- a/repo/js/AutoFriendshipFowl/main.js +++ b/repo/js/AutoFriendshipFowl/main.js @@ -1,131 +1,310 @@ -(async function () { - const TELEPORT_COORDS = { x: 2297.60, y: -824.45 }; - async function switchPartyIfNeeded(partyName) { - if (!partyName) { - await genshin.returnMainUi(); - return; +// 全局变量 +// 标记任务是否结束 +let finished = false; +// 投喂次数 +let feedCount = 0; + +//模板与识别对象预加载 +// “联机”指示图标裁剪范围为346, 29, 30, 30 +const coOpModeRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/联机.png'), 336, 19, 50, 50); +// “回到单人模式”按钮完整范围为1483, 986, 308, 63,图像裁剪范围为1514, 997, 230, 42 +const singlePlayer1Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/单人模式.png'), 1483, 986, 308, 63); +// 单人模式“确认”按钮完整区域为979, 726, 370, 63,裁剪范围为1010, 736, 210, 42 +const singlePlayer1ConfirmRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/单人模式确认.png'), 979, 726, 370, 63); +// “离开队伍”按钮完整范围为1483, 986, 308, 63,图像裁剪范围为1514, 997, 230, 42 +const singlePlayer2Ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/离开队伍.png'), 1483, 986, 308, 63); + +//“动物密友”任务文字图像裁剪范围为83, 253, 84, 21。登陆完成后约500毫秒后可以检测到 +const friendToAnimalsRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/动物密友.png'), 30, 240, 150, 400); +friendToAnimalsRo.Threshold = 0.5; +friendToAnimalsRo.InitTemplate(); +// 完成“动物密友”任务文字图像裁剪范围为83, 253, 84, 21。投喂完成几乎是可以立即检测到,持续时间约3000毫秒。 +const finishedFriendToAnimalsRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/动物密友完成.png'), 30, 240, 150, 400); +// “动物密友突发事件”图像的裁剪范围为892, 167, 136, 37,该图像在登陆完成后的1500-5500毫秒的时间内存在 +const randomEventRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/突发事件.png'), 832, 151, 256, 69); +// “动物密友突发事件”图像的裁剪范围为892, 167, 136, 37。投喂完成后约1500毫秒后可以检测到,持续时间约3500毫秒 +const finishedRandomEventRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/事件完成.png'), 832, 151, 256, 69); + +// “投喂”图像的裁剪范围为1221, 525, 60, 28 +const feedRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/投喂.png'), 1215, 523, 72, 32); +// “确认”按钮完整裁剪范围为978, 725, 372, 64,图像裁剪范围为1012, 736, 200, 42 +const confirmRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/确认.png'), 978, 725, 372, 64); +// “禽肉数量”裁剪范围为945, 540, 14, 18 +const zeroFowlRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/禽肉数量.png'), 940, 535, 40, 28); + +// 事件奖励的摩拉图标裁剪范围:124, 602, 21, 21。确认投喂后约2500毫秒后可以检测到,持续时间约2500毫秒 +const moraRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync('assets/摩拉.png'), 61, 500, 300, 300); + +// 监测是否联机,若联机则退出联机状态 +async function ensureSinglePlayerMode() { + let gameRegion; + let result; + let exists; + + gameRegion = captureGameRegion(); + result = gameRegion.find(coOpModeRo); + gameRegion.dispose(); + exists = result.isExist(); + result.dispose(); + if (exists) { + log.info("单人模式"); + return true; + } else { + log.info("多人游戏中,尝试回到单人模式"); + await genshin.tp(-4492, -3208, "Teyvat", true); + await sleep(1500); + keyPress("F2"); + await sleep(1500); + gameRegion = captureGameRegion(); + let result1 = gameRegion.find(singlePlayer1Ro); + let result2 = gameRegion.find(singlePlayer2Ro); + gameRegion.dispose(); + if (result1.isExist()) { + result1.click(); + await sleep(1500); + gameRegion = captureGameRegion(); + result1.dispose(); + result1 = gameRegion.find(singlePlayer1ConfirmRo); + gameRegion.dispose(); + if (result1.isExist()) { + result1.click(); + log.info("回到单人模式"); + } + } else if (result2.isExist()) { + result2.click(); + log.info("回到单人模式"); } - try { - await genshin.tp(TELEPORT_COORDS.x, TELEPORT_COORDS.y); - await sleep(3000); - log.info(`正在尝试切换至:${partyName}`); - await genshin.switchParty(partyName); - log.info(`队伍切换成功,继续下一步任务`); - } catch (error) { - log.warn("队伍切换失败,可能处于联机模式或其他不可切换状态"); - await genshin.returnMainUi(); - } - } - async function Feed() { - await sleep(500); - keyPress("F"); - await sleep(500); - keyPress("F"); - await sleep(1000); - click(1010, 760); - await sleep(1000); - } - - async function AutoPath(locationName) { - try { - const filePath = `assets/AutoPath/${locationName}.json`; - await pathingScript.runFile(filePath); - } catch (error) { - log.error(`执行 ${locationName} 路径时发生错误: ${error.message}`); - } + result1.dispose(); + result2.dispose(); await sleep(2000); - } + await genshin.returnMainUi(); - async function OcrF() { - let capture = await captureGameRegion(); - let ocr = await capture.find(RecognitionObject.ocrThis); - capture.dispose(); - if (ocr.text.includes('投喂')) { - return true; - } return false; } +} - async function AutoFriendshipDev(times) { - - log.info(`导航至甜甜花位置`); - await AutoPath('导航至甜甜花位置'); - await AutoPath('到甜甜花'); - await genshin.relogin(); - log.info(`自动好感开始...`); - const startFirstTime = Date.now(); - for (let i = 0; i < times; i++) { - log.info(`自动好感当前次数:${i + 1}/${times}`); - await AutoPath('到狗盆'); - for (let j = 0; j < 3 && !await OcrF(); j++) { - await AutoPath('到狗盆'); - } - await Feed(); - if (i != times - 1) { - await AutoPath('到甜甜花'); - await AutoPath('到甜甜花'); - await genshin.relogin(); - } //最后一次不需要返回到甜甜花 - const estimatedCompletion = CalculateEstimatedCompletion(startFirstTime, i + 1, times); - const currentTime = LogTimeTaken(startFirstTime); - log.info(`当前进度:${i + 1}/${times} (${((i + 1) / times * 100).toFixed(1)}%)`); - log.info(`当前运行总时长:${currentTime}`); - log.info(`预计完成时间:${estimatedCompletion}`); +//切换队伍 +async function switchPartyIfNeeded(partyName) { + if (!partyName) { + await genshin.returnMainUi(); + return; + } + try { + log.info(`正在尝试切换至: ${partyName}`); + if (!(await genshin.switchParty(partyName))) { + throw new Error("切换失败"); } - log.info('自动好感已完成'); + log.info(`成功切换至: ${partyName}`); + } catch { + log.error("队伍切换失败,可能处于联机模式或其他不可切换状态"); + await genshin.returnMainUi(); + } +} + +//判断好感突发事件是否触发 +async function randomEventTriggered() { + let index; + let gameRegion; + let result; + let exists; + + await sleep(300); + + for (index = 0; index < 10; index++) { + gameRegion = captureGameRegion(); + result = gameRegion.find(friendToAnimalsRo); + gameRegion.dispose(); + exists = result.isExist(); + result.dispose(); + if (!exists) { await sleep(100); } + else { return true; } + } + for (index = 0; index < 10; index++) { + gameRegion = captureGameRegion(); + result = gameRegion.find(randomEventRo); + gameRegion.dispose(); + exists = result.isExist(); + result.dispose(); + if (!exists) { await sleep(400); } + else { return true; } + } + gameRegion = captureGameRegion(); + result = gameRegion.find(friendToAnimalsRo); + gameRegion.dispose(); + exists = result.isExist(); + result.dispose(); + if (exists) { return true; } + + return false; +} + +// 判断投喂后是否完成事件 +async function finishedEvent() { + let index; + let gameRegion; + let result; + let exists; + + for (index = 0; index < 10; index++) { + gameRegion = captureGameRegion(); + result = gameRegion.find(finishedFriendToAnimalsRo); + gameRegion.dispose(); + exists = result.isExist(); + result.dispose(); + if (!exists) { await sleep(100); } + else { return true; } } - function LogTimeTaken(startTimeParam) { - const currentTime = Date.now(); - const totalTimeInSeconds = (currentTime - startTimeParam) / 1000; - const minutes = Math.floor(totalTimeInSeconds / 60); - const seconds = totalTimeInSeconds % 60; - const formattedTime = `${minutes} 分 ${seconds.toFixed(0).padStart(2, '0')} 秒`; - return formattedTime; + for (index = 0; index < 10; index++) { + gameRegion = captureGameRegion(); + result = gameRegion.find(finishedRandomEventRo); + gameRegion.dispose(); + exists = result.isExist(); + result.dispose(); + if (!exists) { await sleep(100); } + else { return true; } } - // 计算预估时间 - function CalculateEstimatedCompletion(startTime, current, total) { - if (current === 0) return "计算中..."; + return false; +} - const elapsedTime = Date.now() - startTime; - const timePerTask = elapsedTime / current; - const remainingTasks = total - current; - const remainingTime = timePerTask * remainingTasks; - const completionDate = new Date(Date.now() + remainingTime); - return `${completionDate.toLocaleTimeString()} (约 ${Math.round(remainingTime / 60000)} 分钟)`; +// 识别奖励 +async function hasEventReward() { + let index; + let gameRegion; + let result; + let exists; + + for (index = 0; index < 50; index++) { + gameRegion = captureGameRegion(); + result = gameRegion.find(moraRo); + gameRegion.dispose(); + exists = result.isExist(); + result.dispose(); + if (!exists) { await sleep(100); } + else { return true; } + } + return false; +} + +// 寻找“投喂”,按下F,点击“确认”按钮,完成投喂 +async function feedDog() { + let gameRegion; + let result; + let exists; + let retry; + + retry = 0; + await sleep(200); // 等待角色站稳,避免二次调整位置 + do { + gameRegion = captureGameRegion(); + result = gameRegion.find(feedRo); + gameRegion.dispose(); + exists = result.isExist(); + result.dispose(); + if (!exists) { + if (++retry > 5) { + log.error("多次尝试仍未识别到“投喂”,结束任务"); + return false; + } + await pathingScript.runFile("assets/pathing/鸡腿好感_狗盆点位.json"); + } else { keyPress("F"); } + } while (!exists); + + await sleep(1000); + gameRegion = captureGameRegion(); + result = gameRegion.find(confirmRo); + try { + if (result.isExist()) { result.click(); } + else { + log.error("未识别到可交互的确认按钮"); + result.dispose(); + result = gameRegion.find(zeroFowlRo); + keyPress("Escape"); + await sleep(1000); + await genshin.returnMainUi(); + if (result.isExist()) { log.error("禽肉数量为0,无法完成任务"); } + return false; + } + } finally { + result.dispose(); + gameRegion.dispose(); } - function isPositiveInteger(value) { - value = Number(value); - return Number.isInteger(value) && value > 0; - } - // 启用自动拾取的实时任务 - const startTime = Date.now(); - dispatcher.addTimer(new RealtimeTimer("AutoPick")); + return true; +} - const messages = [ - '请确保有足够的鸡腿', - '请确保队伍满员', - ]; - for (let message of messages) { - log.info(message); - await sleep(500); +// 检查“投喂”的结果 +async function checkFeed() { + if (await finishedEvent()) { + feedCount++; + log.info("投喂成功"); + if (feedCount >= 10) { + log.info("10次投喂完成"); + finished = true; + return true; + } + if (!(await hasEventReward())) { + log.info("投喂成功后未识别到奖励,当日突发事件奖励已达上限"); + finished = true; + } } +} +async function main() { + let retry; + + // 等待返回主界面 + await genshin.returnMainUi(); + // 强制传送,避免在奇奇怪怪的地方,例如“银月之庭” + await genshin.tp(-4492, -3208, "Teyvat", true); + // 判断是否为联机模式,通过模拟点击回到单人模式 + while (!(await ensureSinglePlayerMode())) { await sleep(500); } + // 移动到任务刷新点 + await pathingScript.runFile("assets/pathing/鸡腿好感_初始化.json"); + // 判断是否设置了好感队,切换队伍 await switchPartyIfNeeded(settings.partyName); - - log.info('自动好感开始...'); - //默认10次自动好感 - if (isPositiveInteger(settings.times)) { - log.info(`自动好感任务开始,运行:${settings.times} 次`); - await AutoFriendshipDev(settings.times); - } else { - log.info(`运行次数输入不合法或者未输入,使用默认值`); - times = 10; - log.info(`自动好感任务开始,运行:${times} 次`); - await AutoFriendshipDev(10); + retry = 0; + const startTime = Date.now(); + // 任务循环 + task: while (!finished) { + // 重新登陆,刷新任务 + await genshin.relogin(); + // 检测“动物密友”任务是否触发,若未触发则重新登陆触发 + if (!(await randomEventTriggered())) { + if (++retry > 5) { + log.error("多次尝试触发突发事件失败,结束任务"); + break; + } + await pathingScript.runFile("assets/pathing/鸡腿好感_甜甜花点位.json"); + continue; + } else { retry = 0; } + // 前往狗盆 + await pathingScript.runFile("assets/pathing/鸡腿好感_喂狗.json"); + // 等待投喂 + if (!(await feedDog())) { break; } + // 异步检查投喂结果 + const checkFeedPromise = checkFeed(); + // 返回前判断任务是否已完成,减少时间 + for (let index = 0; index < 10; index++) { + if (finished) { break task; } + await sleep(10); + } + // 返回甜甜花 + await pathingScript.runFile("assets/pathing/鸡腿好感_返回.json"); + // 计算剩余时间 + if (feedCount > 0) { + const remainingTime = (Date.now() - startTime) / feedCount * (10 - feedCount) / 1000; + const remainingMinutes = Math.floor(remainingTime / 60); + const remainingSeconds = remainingTime % 60; + log.info(`当前进度:第 ${feedCount}/10 次已完成,预计剩余时间:${remainingMinutes} 分 ${remainingSeconds.toFixed(0)} 秒`); + } + await checkFeedPromise; } - log.info(`自动好感运行总时长:${LogTimeTaken(startTime)}`); -})(); + log.info("好感任务结束"); +} + +(async function () { + await main(); +})(); \ No newline at end of file diff --git a/repo/js/AutoFriendshipFowl/manifest.json b/repo/js/AutoFriendshipFowl/manifest.json index 275e29c0a..71eb6284c 100644 --- a/repo/js/AutoFriendshipFowl/manifest.json +++ b/repo/js/AutoFriendshipFowl/manifest.json @@ -1,13 +1,13 @@ { "manifest_version": 1, "name": "鸡腿好感", - "version": "1.4", + "version": "1.5", "tags": [ "好感", "突发事件" ], - "bgi_version": "0.44.0", - "description": "通过喂狗突发事件刷好感度,确保队伍满员,4个角色都能刷,每天上限10次", + "bgi_version": "0.45.0", + "description": "消耗禽肉喂狗,完成“动物密友”好感任务,获取角色好感、摩拉、锻造矿。确保队伍满员,每天最多10次。", "authors": [ { "name": "花火" @@ -15,6 +15,10 @@ { "name": "秋云", "links": "https://github.com/physligl" + }, + { + "name": "Gedley", + "link": "https://github.com/Gedley" } ], "settings_ui": "settings.json", diff --git a/repo/js/AutoFriendshipFowl/settings.json b/repo/js/AutoFriendshipFowl/settings.json index cd2de5c2e..ab4d47a7f 100644 --- a/repo/js/AutoFriendshipFowl/settings.json +++ b/repo/js/AutoFriendshipFowl/settings.json @@ -1,12 +1,7 @@ [ { - "name": "times", - "type": "input-text", - "label": "(选填)运行次数【默认10,为避免失败可以酌情添加次数】" - }, - { "name": "partyName", "type": "input-text", - "label": "(选填)需要切换的队伍名称【前往设置的七天神像切换好感队】" + "label": "好感队的队伍名称,若未设置则使用当前队伍" } ] \ No newline at end of file