* 识别体力与树脂数量 * 璃月6-奥藏山 * update repo.json * 地图追踪 星银矿石 (#1025) * Add files via upload * 自动修复 JSON 格式和版本号 [ci skip] * Delete repo/pathing/矿物/星银矿石/desktop.ini * Add files via upload --------- Co-authored-by: GitHub Actions Bot <actions@github.com> * Update main.js (#1024) 手动终止夹断 * update repo.json * 6.7 富Abpro (#1022) * Add files via upload * Add files via upload * Delete repo/js/AutoArtifactsPro/assets/ArtifactsPath/A路线/01普通/000【激活程序】稻妻大炮.json * Delete repo/js/AutoArtifactsPro/assets/ArtifactsPath/A路线/01普通/404须弥-天臂池七天神像4.json * Delete repo/js/AutoArtifactsPro/assets/ArtifactsPath/A路线/01普通/601纳塔-流泉之众4.json * Delete repo/js/AutoArtifactsPro/assets/ArtifactsPath/A路线/01普通/602纳塔-悬木人声望2.json * Delete repo/js/AutoArtifactsPro/assets/ArtifactsPath/A路线/01普通/603纳塔-花羽会西2.json * Add files via upload * update repo.json * `七圣召唤七日历练`: 修复牌币已满时卡在出战界面的问题 (#1017) * update repo.json * js:狗粮重置版1.2更新 (#1026) * update repo.json * fix: 修复部分情况下未找到图标直接结束 * temp * add: 璃月7 * feat: 新的数据结构 * add: 合并代码,功能待实现 --------- Co-authored-by: 寒烟 <2841974482@qq.com> Co-authored-by: physligl <181079228+physligl@users.noreply.github.com> Co-authored-by: Tooltingsu <143606015+Tooltingsu@users.noreply.github.com> Co-authored-by: GitHub Actions Bot <actions@github.com> Co-authored-by: JJMdzh <jjjjedyx@qq.com> Co-authored-by: 汐 <121607261+jiegedabaobei@users.noreply.github.com> Co-authored-by: Patrick-Ze <19711799+Patrick-Ze@users.noreply.github.com> Co-authored-by: mno <718135749@qq.com> Co-authored-by: 秋云 <physligl@gmail.com>
198 lines
8.8 KiB
JavaScript
198 lines
8.8 KiB
JavaScript
/**
|
||
* 使用节点数据执行路径
|
||
* @param {Object} position - 位置对象
|
||
* @returns {Promise<void>}
|
||
*/
|
||
this.executePathsUsingNodeData =
|
||
async function (position) {
|
||
try {
|
||
const nodeData = await loadNodeData();
|
||
let currentNodePosition = position;
|
||
const targetNode = findTargetNodeByPosition(nodeData, currentNodePosition.x, currentNodePosition.y);
|
||
|
||
if (!targetNode) {
|
||
log.error(`未找到与坐标(${currentNodePosition.x}, ${currentNodePosition.y})匹配的目标节点`);
|
||
return;
|
||
}
|
||
log.debug(`找到目标节点: ID ${targetNode.id}, 位置(${targetNode.position.x}, ${targetNode.position.y})`);
|
||
const paths = findPathsToTarget(nodeData, targetNode);
|
||
|
||
if (paths.length === 0) {
|
||
log.error(`未找到通向目标节点(ID: ${targetNode.id})的路径`);
|
||
return;
|
||
}
|
||
|
||
// 选择最短的路径执行
|
||
const optimalPath = selectOptimalPath(paths);
|
||
log.debug(`选择了含有 ${optimalPath.routes.length} 个路径点的最优路径`);
|
||
|
||
// 执行路径
|
||
await executePath(optimalPath);
|
||
currentRunTimes++;
|
||
|
||
// 如果达到刷取次数上限,退出循环
|
||
if (currentRunTimes >= settings.timesValue) {
|
||
return;
|
||
}
|
||
|
||
// 循环检查并执行当前节点的单一next路径,直到遇到没有next或有多个next的情况
|
||
let currentNode = targetNode;
|
||
|
||
while (currentNode.next && currentRunTimes < settings.timesValue) {
|
||
if (currentNode.next.length === 1) { // 获取下一个节点的ID 和 路径,并在节点数据中找到下一个节点
|
||
const nextNodeId = currentNode.next[0].target;
|
||
const nextRoute = currentNode.next[0].route;
|
||
const nextNode = nodeData.node.find(node => node.id === nextNodeId);
|
||
|
||
if (!nextNode) {
|
||
return;
|
||
}
|
||
const pathObject = {
|
||
startNode: currentNode,
|
||
targetNode: nextNode,
|
||
routes: [nextRoute]
|
||
};
|
||
|
||
log.info(`直接执行下一个节点路径: ${nextRoute}`);
|
||
await executePath(pathObject);
|
||
|
||
currentRunTimes++;
|
||
|
||
log.info(`完成节点 ID ${nextNodeId}, 已执行 ${currentRunTimes}/${settings.timesValue} 次`); // 更新当前节点为下一个节点,继续检查
|
||
currentNode = nextNode;
|
||
currentNodePosition = { x: nextNode.position.x, y: nextNode.position.y };
|
||
} else if (currentNode.next.length > 1) {
|
||
// 如果存在分支路线,先打开大地图判断下一个地脉花的位置,然后结合顺序边缘数据选择最优路线
|
||
log.info("检测到多个分支路线,开始查找下一个地脉花位置");
|
||
|
||
// 备份当前地脉花坐标
|
||
const currentLeyLineX = leyLineX;
|
||
const currentLeyLineY = leyLineY;
|
||
|
||
// 打开大地图
|
||
await genshin.returnMainUi();
|
||
keyPress("M");
|
||
await sleep(1000);
|
||
|
||
// 查找下一个地脉花
|
||
const found = await locateLeyLineOutcrop(settings.leyLineOutcropType);
|
||
await genshin.returnMainUi();
|
||
|
||
if (!found) {
|
||
log.warn("无法在分支点找到下一个地脉花,退出本次循环");
|
||
return;
|
||
}
|
||
|
||
log.info(`找到下一个地脉花,位置: (${leyLineX}, ${leyLineY})`);
|
||
|
||
// 优先使用顺序边缘数据来选择路径,如果没有则回退到距离计算
|
||
const sequentialEdges = nodeData.indexes?.edgesBySource;
|
||
let selectedRoute = null;
|
||
let selectedNodeId = null;
|
||
|
||
if (sequentialEdges) {
|
||
const currentNodeIdStr = currentNode.id.toString();
|
||
const nextTargetIds = sequentialEdges[currentNodeIdStr];
|
||
|
||
if (nextTargetIds && nextTargetIds.length > 0) {
|
||
const nextTargetId = nextTargetIds[0];
|
||
log.info(`从顺序边缘数据中找到推荐的下一个目标节点ID: ${nextTargetId}`);
|
||
|
||
// 在当前节点的分支中查找通向推荐目标节点的路径
|
||
for (const nextRoute of currentNode.next) {
|
||
const nextNodeId = nextRoute.target;
|
||
|
||
// 检查这个路径是否通向推荐的目标节点(直接匹配或通过后续路径)
|
||
if (nextNodeId === nextTargetId) {
|
||
selectedRoute = nextRoute.route;
|
||
selectedNodeId = nextNodeId;
|
||
log.info(`使用顺序边缘数据:找到直接路径到推荐节点ID: ${nextTargetId}`);
|
||
break;
|
||
} else {
|
||
// 检查这个中间节点是否能通向推荐的目标节点
|
||
const intermediateNodeIdStr = nextNodeId.toString();
|
||
const intermediateNextTargets = sequentialEdges[intermediateNodeIdStr];
|
||
|
||
if (intermediateNextTargets && intermediateNextTargets.includes(nextTargetId)) {
|
||
selectedRoute = nextRoute.route;
|
||
selectedNodeId = nextNodeId;
|
||
log.info(`使用顺序边缘数据:找到通过中间节点ID ${nextNodeId} 到达推荐节点ID ${nextTargetId} 的路径`);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果顺序边缘数据没有找到合适的路径,回退到距离计算
|
||
if (!selectedRoute) {
|
||
log.info("顺序边缘数据未找到合适路径,使用距离计算方法选择路径");
|
||
|
||
let closestDistance = Infinity; for (const nextRoute of currentNode.next) {
|
||
const nextNodeId = nextRoute.target;
|
||
const nextNode = nodeData.node.find(node => node.id === nextNodeId);
|
||
|
||
if (!nextNode) continue;
|
||
|
||
const distance = calculate2DDistance(
|
||
leyLineX, leyLineY,
|
||
nextNode.position.x, nextNode.position.y
|
||
);
|
||
|
||
log.info(`路线到地脉花距离: ID ${nextNodeId}, 距离: ${distance.toFixed(2)}`);
|
||
|
||
if (distance < closestDistance) {
|
||
closestDistance = distance;
|
||
selectedRoute = nextRoute.route;
|
||
selectedNodeId = nextNodeId;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!selectedRoute) {
|
||
log.error("无法找到合适的路线,终止执行");
|
||
// 恢复原始坐标
|
||
leyLineX = currentLeyLineX;
|
||
leyLineY = currentLeyLineY;
|
||
return;
|
||
} const nextNode = nodeData.node.find(node => node.id === selectedNodeId);
|
||
if (!nextNode) {
|
||
log.error(`未找到节点ID ${selectedNodeId},终止执行`);
|
||
// 恢复原始坐标
|
||
leyLineX = currentLeyLineX;
|
||
leyLineY = currentLeyLineY;
|
||
return;
|
||
}
|
||
|
||
log.info(`选择路线: ${selectedRoute}, 目标节点ID: ${selectedNodeId}`);
|
||
|
||
// 创建路径对象并执行
|
||
const pathObject = {
|
||
startNode: currentNode,
|
||
targetNode: nextNode,
|
||
routes: [selectedRoute]
|
||
};
|
||
|
||
await executePath(pathObject);
|
||
currentRunTimes++;
|
||
|
||
// 更新当前节点为下一个节点,继续检查
|
||
currentNode = nextNode;
|
||
currentNodePosition = { x: nextNode.position.x, y: nextNode.position.y };
|
||
}
|
||
else {
|
||
log.info("当前路线完成,退出循环");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
catch (error) {
|
||
if(error.message.includes("战斗失败")) {
|
||
log.error("战斗失败,重新寻找地脉花后重试");
|
||
return;
|
||
}
|
||
// 其他错误需要向上传播
|
||
log.error(`执行路径时出错: ${error.message}`);
|
||
throw error;
|
||
}
|
||
} |