(async function () { setGameMetrics(1920, 1080, 1); const STATUS_FILE = "status.json"; const requestId = String(settings.requestId || "").trim(); let lastCandidates = []; function writeStatus(state, data) { const payload = Object.assign({ state: state, request_id: requestId, party_name: "", candidates: lastCandidates, message: "", updated_at: new Date().toISOString() }, data || {}); file.writeTextSync(STATUS_FILE, JSON.stringify(payload, null, 2)); } function normalizeText(value) { return String(value || "").replace(/\s+/g, "").trim(); } function isPartyNameCandidate(text) { if (!text || text.length > 20) { return false; } const ignored = [ "队伍配置", "快速编队", "元素共鸣", "调整队伍", "当前队伍", "部署", "出战", "详情" ]; if (ignored.some((label) => text === label || text.includes(label))) { return false; } return !/^(esc|enter|space|l|f\d{1,2})$/i.test(text); } function isPartyPageOpen() { const capture = captureGameRegion(); try { const results = capture.findMulti(RecognitionObject.ocr(0, 0, 720, 180)); for (let index = 0; index < results.count; index++) { const text = normalizeText(results[index].text); if (text.includes("队伍配置")) { return true; } } return false; } finally { capture.dispose(); } } function recognizePartyNameCandidates() { const capture = captureGameRegion(); try { const results = capture.findMulti(RecognitionObject.ocr(0, 940, 520, 140)); const candidates = []; for (let index = 0; index < results.count; index++) { const result = results[index]; const text = normalizeText(result.text); log.info( "当前队伍名称候选位置:({x},{y},{w},{h}), 识别结果:{text}", result.x, result.y, result.Width, result.Height, text ); if (isPartyNameCandidate(text)) { candidates.push({ text: text, x: Number(result.x || 0), y: Number(result.y || 0) }); } } candidates.sort((left, right) => { if (left.x !== right.x) { return left.x - right.x; } return right.y - left.y; }); return candidates.filter( (candidate, index, values) => values.findIndex((value) => value.text === candidate.text) === index ); } finally { capture.dispose(); } } async function openPartyPageAndRead() { for (let attempt = 0; attempt < 3; attempt++) { keyPress("VK_L"); await sleep(2200); for (let scan = 0; scan < 4; scan++) { if (isPartyPageOpen()) { const candidates = recognizePartyNameCandidates(); if (candidates.length > 0) { return candidates; } } await sleep(600); } keyPress("VK_ESCAPE"); await sleep(800); await genshin.returnMainUi(); } return []; } try { if (!requestId) { throw new Error("读取请求标识为空"); } writeStatus("running"); await genshin.returnMainUi(); const candidates = await openPartyPageAndRead(); lastCandidates = candidates.map((candidate) => candidate.text); if (candidates.length === 0) { throw new Error("未识别到当前队伍名称,请确认游戏处于可打开配队界面的状态"); } if (candidates.length > 1) { throw new Error("识别到多个队伍名称候选:" + lastCandidates.join("、")); } const partyName = candidates[0].text; await genshin.returnMainUi(); await sleep(500); writeStatus("success", { party_name: partyName, candidates: lastCandidates }); log.info("当前队伍名称读取成功: {name}", partyName); } catch (error) { try { await genshin.returnMainUi(); } catch (_) { } const message = String(error && error.message ? error.message : error); writeStatus("error", { candidates: lastCandidates, message: message }); log.error("当前队伍名称读取失败: {message}", message); } })();