feat: 诛贼-地方传奇-利亚姆脚本 (#2593)

This commit is contained in:
xiaozhang12312
2026-01-01 20:20:55 +08:00
committed by GitHub
parent a3de5b65d6
commit f89ad7d6c7
21 changed files with 975 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
# 说明
该脚本会打一只地方传奇-利亚姆。
- 关于利亚姆:
1. 没有万叶拾取很难所以请确保账号上有万叶在队伍的3号否则不要选择拾取
2. 操作角色默认是 1号提纳里 其他弓箭手不是水就可以,没有小提换安柏,影响的原因是脚本的计算精度不够从而导致失败(作者的水平有限( •̀ ω •́ ))。
2号是钟离,一定一定要有钟离成功率有74%以上! 当然如果你没有就换诺艾尔,不过成功率感人,基本是白跑。
3. 没有解密的水池还没有制作判断的逻辑,抱歉!

View File

@@ -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}}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

View File

@@ -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
}
]
}

View File

@@ -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
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -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<void>}
*/
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 }));
}
};

View File

@@ -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<boolean>} 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<void>}
*/
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<void>}
*/
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<void>}
*/
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);
},
};

View File

@@ -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);
}
}
};

View File

@@ -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}` };
}
},
};

View File

@@ -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}`);
}
})();

View File

@@ -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"
}

View File

@@ -0,0 +1,15 @@
[
{
"name": "liam_pick_dogfood",
"type": "select",
"label": "关于利亚姆:是否拾取狗娘(要有万叶)",
"options": ["我全都要!", "没有万叶(≧口≦)", "节约时间,不拿了"],
"default": "节约时间,不拿了"
},
{
"name": "partyName",
"type": "input-text",
"label": "配队名称, 推荐队伍中1号提纳里 2号是钟离 3号是万叶"
}
]