From 829e52c55cb6579038ea5b838fe0f2dc920b8da0 Mon Sep 17 00:00:00 2001 From: this-Fish Date: Thu, 1 Jan 2026 14:30:40 +0800 Subject: [PATCH] =?UTF-8?q?JS=20=E8=87=AA=E5=8A=A8=E8=B4=AD=E4=B9=B0?= =?UTF-8?q?=E6=AF=8F=E5=A4=A9&3=E5=A4=A9&=E6=AF=8F=E5=91=A8=E5=88=B7?= =?UTF-8?q?=E6=96=B0=E9=A3=9F=E6=9D=90=202.0=20=20(#2598)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Delete repo/js/自动购买每天&3天&每周刷新食材 directory * JS 自动购买每天&3天&每周刷新食材 2.0 添加記錄食材商店下次刷新時間(當天重跑跳過已購買成功的食材) 添加了禁用NPC功能 更新日志输出说明 拆分Npc&Food數據 路徑名增加規範(國家-地區-NPC名称) * 調整格式 * Add files via upload * Update manifest.json --- .../自动购买每天&3天&每周刷新食材/README.md | 278 ++- .../assets/data/foods.json | 173 ++ .../assets/data/npcs.json | 260 +++ ...挪德卡莱-杂货铺-采若.json => 挪德卡莱-那夏镇-采若.json} | 0 .../assets/path/{布希柯.json => 枫丹-枫丹廷-布希柯.json} | 0 .../assets/path/{阿鲁埃.json => 枫丹-枫丹廷-阿鲁埃.json} | 0 .../assets/path/{安特曼.json => 枫丹-白淞镇-安特曼.json} | 0 .../path/{枫丹-锈坨-皮托.json => 枫丹-锈舵酒馆-皮托.json} | 0 .../{菲尔戈黛特.json => 璃月-望舒客栈-菲尔戈黛特.json} | 0 .../assets/path/{东升.json => 璃月-璃月港-东升.json} | 0 .../assets/path/{卯师父.json => 璃月-璃月港-卯师父.json} | 0 .../assets/path/{老孙.json => 璃月-璃月港-老孙.json} | 0 .../assets/path/{老高.json => 璃月-璃月港-老高.json} | 0 .../assets/path/{阿桂.json => 璃月-璃月港-阿桂.json} | 0 .../assets/path/{丰泰.json => 璃月-遗珑埠-丰泰.json} | 0 .../assets/path/{连芳.json => 璃月-遗珑埠-连芳.json} | 0 .../assets/path/{小畑.json => 稻妻-离岛-小畑.json} | 0 .../path/{志村勘兵卫.json => 稻妻-稻妻城-志村勘兵卫.json} | 0 .../assets/path/{葵.json => 稻妻-稻妻城-葵.json} | 0 .../path/{夏安卡.json => 纳塔-圣火竞技场-夏安卡.json} | 0 .../path/{布纳马.json => 纳塔-圣火竞技场-布纳马.json} | 0 .../path/{钦特利.json => 纳塔-圣火竞技场-钦特利.json} | 0 ...神奇的霍普金斯.json => 蒙德-清泉镇-神奇的霍普金斯.json} | 0 .../assets/path/{布兰琪.json => 蒙德-蒙德城-布兰琪.json} | 0 .../assets/path/{莎拉.json => 蒙德-蒙德城-莎拉.json} | 0 .../assets/path/{巴巴克.json => 须弥-奥摩斯港-巴巴克.json} | 0 .../path/{布特罗斯.json => 须弥-奥摩斯港-布特罗斯.json} | 0 .../assets/path/{阿扎莱.json => 须弥-阿如村-阿扎莱.json} | 0 .../{兰巴德.json => 须弥-须弥城-兰巴德酒馆-兰巴德.json} | 0 .../assets/path/{哈马维.json => 须弥-须弥城-哈马维.json} | 0 .../{恩忒卡.json => 须弥-须弥城-普斯帕咖啡馆-恩忒卡.json} | 0 .../assets/path/{朱特.json => 须弥-须弥城-朱特.json} | 0 .../assets/path/{珀姆.json => 须弥-须弥城-珀姆.json} | 0 repo/js/自动购买每天&3天&每周刷新食材/main.js | 1870 +++++++++-------- .../manifest.json | 8 +- .../settings.json | 137 +- 36 files changed, 1715 insertions(+), 1011 deletions(-) create mode 100644 repo/js/自动购买每天&3天&每周刷新食材/assets/data/foods.json create mode 100644 repo/js/自动购买每天&3天&每周刷新食材/assets/data/npcs.json rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{挪德卡莱-杂货铺-采若.json => 挪德卡莱-那夏镇-采若.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{布希柯.json => 枫丹-枫丹廷-布希柯.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{阿鲁埃.json => 枫丹-枫丹廷-阿鲁埃.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{安特曼.json => 枫丹-白淞镇-安特曼.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{枫丹-锈坨-皮托.json => 枫丹-锈舵酒馆-皮托.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{菲尔戈黛特.json => 璃月-望舒客栈-菲尔戈黛特.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{东升.json => 璃月-璃月港-东升.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{卯师父.json => 璃月-璃月港-卯师父.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{老孙.json => 璃月-璃月港-老孙.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{老高.json => 璃月-璃月港-老高.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{阿桂.json => 璃月-璃月港-阿桂.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{丰泰.json => 璃月-遗珑埠-丰泰.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{连芳.json => 璃月-遗珑埠-连芳.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{小畑.json => 稻妻-离岛-小畑.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{志村勘兵卫.json => 稻妻-稻妻城-志村勘兵卫.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{葵.json => 稻妻-稻妻城-葵.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{夏安卡.json => 纳塔-圣火竞技场-夏安卡.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{布纳马.json => 纳塔-圣火竞技场-布纳马.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{钦特利.json => 纳塔-圣火竞技场-钦特利.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{神奇的霍普金斯.json => 蒙德-清泉镇-神奇的霍普金斯.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{布兰琪.json => 蒙德-蒙德城-布兰琪.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{莎拉.json => 蒙德-蒙德城-莎拉.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{巴巴克.json => 须弥-奥摩斯港-巴巴克.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{布特罗斯.json => 须弥-奥摩斯港-布特罗斯.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{阿扎莱.json => 须弥-阿如村-阿扎莱.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{兰巴德.json => 须弥-须弥城-兰巴德酒馆-兰巴德.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{哈马维.json => 须弥-须弥城-哈马维.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{恩忒卡.json => 须弥-须弥城-普斯帕咖啡馆-恩忒卡.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{朱特.json => 须弥-须弥城-朱特.json} (100%) rename repo/js/自动购买每天&3天&每周刷新食材/assets/path/{珀姆.json => 须弥-须弥城-珀姆.json} (100%) diff --git a/repo/js/自动购买每天&3天&每周刷新食材/README.md b/repo/js/自动购买每天&3天&每周刷新食材/README.md index c84b9a2f2..2f4585d2e 100644 --- a/repo/js/自动购买每天&3天&每周刷新食材/README.md +++ b/repo/js/自动购买每天&3天&每周刷新食材/README.md @@ -1,68 +1,248 @@ -# 說明 -## 本JS脚本只是基本框架 -- 由于提瓦特贩卖食物的商人太多,做成选项会太长,不方便操作,因此只制作主要框架。 -- 需要购买预设中没有的食材,可参照以下步骤操作 +# 自动购买每天&3天&每周刷新食材 - 使用说明 -# 如何加入自定义食材 -- 为方便后续维护,整个流程可分为以下五个主要步骤 +## 功能说明 -步骤 1:准备食材图片 -- 进入游戏中的购买页面,截取你要添加的食材在界面上的显示图。 -- 参考 assets/images/ 目录下已有的食材图片,调整截图为 90×90px。 -- 将裁剪好的图片命名为 <食材名称>.png(例如:新食材.png),并拷贝至项目的 assets/images/ 目录下。 +这个脚本可以自动购买原神游戏中各个商人的食材,支持三种刷新周期: +- **每天刷新食材**:每天凌晨4点刷新 +- **3天刷新食材**:每3天刷新一次 +- **每周刷新食材**:每周刷新,可指定购买日 +- **智能记录系统**:避免重复购买,只购买刷新后的商品 -步骤 2:录制卖食物NPC的行走路径 -- 启动脚本录制工具,前往并与“卖食物 NPC”互动的地图位置。 -- 结束录制后,将生成的路径脚本文件重命名为 <食物NPC名称>.json(例如:新卖食物NPC.json)。 -- 将此 JSON 文件放入项目的 assets/path/ 目录下。 +## 快速开始 + +### 1. 准备工作 +- 游戏分辨率:**1920×1080 解析度** +- 游戏内时间需可调整(非多人模式) +- 准备足够的摩拉购买食材 + +### 2. 首次使用 +1. 打开脚本设置界面 +2. 勾选要购买的食材 +3. 设置每周食材购买日 +4. 保存设置 +5. 在主界面运行脚本 + +## 设置说明 +- **账号名**:区分不同账号的记录 +- **无视记录强制购买**:不推荐开启,会重复购买 +- **记录调试模式**:显示详细日志信息 +- **禁用NPC功能**:可以输入要禁用的NPC名称(空格分隔): + ``` + 布兰琪 东升 莎拉 + ``` + + 禁用后,脚本会跳过这些NPC,不会前往购买。 + +### 食材设置 +食材分为三类,可以单独选择是否购买: +1. **每天刷新食材** - 每天凌晨4点刷新 +2. **3天刷新食材** - 每3天刷新一次 +3. **每周刷新食材** - 每周固定週一购买 + +### 购买日设置 +- **0**:跟随游戏系统周期自动判断 +- **1-7**:指定週几购买(1=週一,7=週日) + +## 调试模式 + +开启`记录调试模式`后,会显示详细执行信息: -步骤 3:更新 settings.json -打开根目录下的 settings.json,在合适的配置节点中: -- 找到与“购买食材”相关的字段(参考其他已有选项)。 -- 复制一组模板配置,并将其中的字段值,替换为你定义的“食材名称”。 -- 示例结构: ``` - , - { - "name": "新食材", - "type": "checkbox", - "label": "新食材", - "default": true - } +[调试] 开始处理NPC: 布兰琪 +[调试] NPC当前记录: {npcname: "布兰琪", 1d_time: "2024-12-10T04:00:00+08:00"} +[调试] 购买判断结果: +[调试] 1天商品: 盐, 胡椒, 洋葱 +[调试] 开始购买第 1 页 +[调试] 尝试购买: 盐 +[调试] 找到物品: 盐 位置(100,200,90,90) +购买成功: 盐 +交互或拾取:"盐" ``` -步骤 4:修改 main.js -在 main.js 中,需要同时在两个数据结构里新增对应条目。 -- npcData -- 参考文件末尾的注释,按格式插入一段新的 NPC 对象。 -- 示例: +```json +## 数据文件说明 + +脚本使用外部数据文件,方便维护: + +### 食材数据 (assets/data/foods.json) +```json +{ + "盐": { + "id": "盐", + "name": "盐", + "file": "assets/images/salt.png" + } +} ``` -, -"新卖食物NPC": { // NPC名字 - "name": "新卖食物NPC", // NPC名字 + +### NPC数据 (assets/data/npcs.json) +```json +{ + "布兰琪": { + "name": "布兰琪", "enable": true, - "page": 1, // 商人卖的物品页数 - "time": "any", //any 不调时间,day 早上8点, night 晚上8点 - "path": "assets/path/新卖食物NPC.json", //写入 卖食物NPC路径名 - "_1d_foods": ["新食材"]// 写入 新加入 每天刷新的 食材名字 - "_3d_foods": ["新食材"]// 写入 新加入 每3天刷新的 食材名字 - "_7d_foods": ["新食材"]// 写入 新加入 每週刷新的 食材名字 - } + "page": 2, + "time": "night", + "path": "assets/path/蒙德-蒙德城-布兰琪.json", + "_1d_foods": ["盐", "胡椒", "洋葱"] + } +} ``` -- foodsData -- 参考末尾注解,新增新的食材配置。 -- 示例: + +### 图片要求 +- 尺寸:90×90像素 +- 格式:PNG +- 路径:assets/images/ + +### 路径文件 +- 格式:JSON +- 路径:assets/path/ + +## 添加新食材 + +### 1. 添加食材图片 +将食材截图保存为`assets/images/新食材.png` +- 食材图片:85×85像素PNG格式 + +### 2. 添加食材设置 +在`settings.json`中添加: +```json +{ + "name": "新食材", + "type": "checkbox", + "label": "新食材", + "default": false +} ``` -, + +### 3. 添加食材数据 +在`assets/data/foods.json`中添加: +```json +"新食材": { + "id": "新食材", + "name": "新食材", + "file": "assets/images/新食材.png" +} +``` + +### 4. 添加NPC数据 +在`assets/data/npcs.json`中为对应的NPC添加: +```json +"_1d_foods": ["新食材"] // 根据刷新周期选择 +``` + +## 如何添加新的NPC商人 +### 准备工作 +1. 路径文件:錄製前往NPC的路径JSON文件 +2. 命名规则:`国家-地区-NPC名称.json` +### 添加步骤 + +#### 1. 添加食材数据(如未添加) +在 `assets/data/foods.json` 中添加: +```json "新食材": { "id": "新食材", "name": "新食材", "file": "assets/images/新食材.png" - } +} ``` +在 `settings.json` 对应区域添加食材选项。 + +#### 2. 添加NPC数据 +在 `assets/data/npcs.json` 中添加: +```json +"新NPC名称": { + "name": "新NPC名称", + "enable": true, + "page": 2, + "time": "any", + "path": "assets/path/国家-地区-新NPC名称.json", + "_1d_foods": ["食材1", "食材2"], + "_3d_foods": ["食材3"], + "_7d_foods": ["食材4"] +} +``` + +**参数说明**: +- `page`:商店总页数 +- `time`:`any`(任何时间)/`day`(白天)/`night`(晚上) +- `_1d_foods`:每天刷新食材列表 +- `_3d_foods`:3天刷新食材列表 +- `_7d_foods`:每周刷新食材列表 + +#### 3. 放置相关文件 +- 食材图片:`assets/images/新食材.png` +- 路径文件:`assets/path/国家-地区-NPC名称.json` + +#### 4. 测试验证 +1. 重新加载脚本设置 +2. 勾选新食材 +3. 运行脚本测试购买流程 +4. 检查日志确认执行成功 + +### 注意事项 +- NPC名称需与路径文件名称对应 +- 食材名称需与foods.json中的name一致 +- 首次添加建议开启调试模式检查 -步骤 5:重新配置并运行 -- 打开项目中的“配置组”界面,勾选或填写你新添加的“食材”采购项。 -- 保存设置后,重启脚本并验证能否正确购买并交互。 +## 常见问题 + +### 1. 脚本不购买食材 +- 检查游戏是否在主界面 +- 确认解析度设定正确(1920×1080) +- 检查NPC是否在正确时间出现(白天/晚上) +- 查看是否有足够的摩拉 + +### 2. 记录不更新 +- 检查`record/账号名/records.json`文件权限 +- 开启调试模式查看详细日志 + +### 3. 图片识别失败 +- 确认图片尺寸为90×90 +- 检查图片路径是否正确 +- 尝试重新截图 + +### 4. 路径执行失败 +- 确认路径文件存在 +- 检查NPC是否被障碍物阻挡 +- 尝试重新录制路径 + +## 记录系统 + +脚本会自动记录购买时间,保存在`record/账号名/records.json`: + +```json +[ + { + "npcname": "布兰琪", + "1d": ["盐", "胡椒", "洋葱"], + "1d_time": "2024-12-10T04:00:00+08:00", + "3d": [], + "3d_time": null, + "7d": [], + "7d_time": null + } +] +``` + +## 注意事项 + +1. 脚本运行时不要操作游戏 +2. 确保背包有足够空间 +3. 每个NPC购买完成后会返回主界面 +4. 脚本会自动调整游戏时间(白天/晚上) +5. 每周食材购买日设置后,只在指定日期购买4. 逐一添加食材测试 + +## 🤝 贡献指南 + +欢迎提交新的食材配置!请遵循以下格式: + +1. **提交新的NPC**:包含路径文件和图片 +2. **提交新的食材**:包含图片和设定 +3. **问题回报**:提供详细的重现步骤和日志 + +--- + +> 注意:本脚本仅供学习与研究使用,请遵守游戏使用条款。 \ No newline at end of file diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/data/foods.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/data/foods.json new file mode 100644 index 000000000..f9acbbe9c --- /dev/null +++ b/repo/js/自动购买每天&3天&每周刷新食材/assets/data/foods.json @@ -0,0 +1,173 @@ +{ + "salt": { + "id": "salt", + "name": "盐", + "file": "assets/images/salt.png" + }, + "pepper": { + "id": "pepper", + "name": "胡椒", + "file": "assets/images/pepper.png" + }, + "onion": { + "id": "onion", + "name": "洋葱", + "file": "assets/images/onion.png" + }, + "milk": { + "id": "milk", + "name": "牛奶", + "file": "assets/images/milk.png" + }, + "tomato": { + "id": "tomato", + "name": "番茄", + "file": "assets/images/tomato.png" + }, + "potato": { + "id": "potato", + "name": "土豆", + "file": "assets/images/potato.png" + }, + "wheat": { + "id": "wheat", + "name": "小麦", + "file": "assets/images/wheat.png" + }, + "rice": { + "id": "rice", + "name": "稻米", + "file": "assets/images/rice.png" + }, + "coffeeBeans": { + "id": "coffeeBeans", + "name": "咖啡豆", + "file": "assets/images/coffeeBeans.png" + }, + "glabrousBeans": { + "id": "glabrousBeans", + "name": "秃秃豆", + "file": "assets/images/glabrousBeans.png" + }, + "rawMeat": { + "id": "rawMeat", + "name": "兽肉", + "file": "assets/images/rawMeat.png" + }, + "fermentedJuice": { + "id": "fermentedJuice", + "name": "发酵果实汁", + "file": "assets/images/fermentedJuice.png" + }, + "fonta": { + "id": "fonta", + "name": "枫达", + "file": "assets/images/fonta.png" + }, + "shrimp": { + "id": "shrimp", + "name": "虾仁", + "file": "assets/images/shrimp.png" + }, + "almond": { + "id": "almond", + "name": "杏仁", + "file": "assets/images/almond.png" + }, + "cabbage": { + "id": "cabbage", + "name": "卷心菜", + "file": "assets/images/cabbage.png" + }, + "tofu": { + "id": "tofu", + "name": "豆腐", + "file": "assets/images/tofu.png" + }, + "fish": { + "id": "fish", + "name": "鱼肉", + "file": "assets/images/fish.png" + }, + "huMengbu": { + "id": "huMengbu", + "name": "胡萝卜", + "file": "assets/images/huMengbu.png" + }, + "viola": { + "id": "viola", + "name": "堇瓜", + "file": "assets/images/viola.png" + }, + "romaritimeFlower": { + "id": "romaritimeFlower", + "name": "海露花", + "file": "assets/images/romaritimeFlower.png" + }, + "Padisarah": { + "id": "Padisarah", + "name": "帕蒂沙兰", + "file": "assets/images/Padisarah.png" + }, + "松茸": { + "id": "松茸", + "name": "松茸", + "file": "assets/images/松茸.png" + }, + "沉玉仙茗": { + "id": "沉玉仙茗", + "name": "沉玉仙茗", + "file": "assets/images/沉玉仙茗.png" + }, + "青蜜梅": { + "id": "青蜜梅", + "name": "青蜜梅", + "file": "assets/images/青蜜梅.png" + }, + "苦种": { + "id": "苦种", + "name": "苦种", + "file": "assets/images/苦种.png" + }, + "清心": { + "id": "清心", + "name": "清心", + "file": "assets/images/清心.png" + }, + "琉璃袋": { + "id": "琉璃袋", + "name": "琉璃袋", + "file": "assets/images/琉璃袋.png" + }, + "蟹黃": { + "id": "蟹黃", + "name": "蟹黃", + "file": "assets/images/蟹黃.png" + }, + "crab": { + "id": "crab", + "name": "螃蟹", + "file": "assets/images/crab.png" + }, + "tidalga": { + "id": "tidalga", + "name": "汐藻", + "file": "assets/images/tidalga.png" + }, + "圣水": { + "id": "圣水", + "name": "圣水", + "file": "assets/images/圣水.png" + }, + "黑麦": { + "id": "黑麦", + "name": "黑麦", + "file": "assets/images/黑麦.png" + } + , + "絶云椒椒": { + "id": "絶云椒椒", + "name": "絶云椒椒", + "file": "assets/images/絶云椒椒.png" + } +} \ No newline at end of file diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/data/npcs.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/data/npcs.json new file mode 100644 index 000000000..ea0f5f6d7 --- /dev/null +++ b/repo/js/自动购买每天&3天&每周刷新食材/assets/data/npcs.json @@ -0,0 +1,260 @@ +{ + "神奇的霍普金斯": { + "name": "神奇的霍普金斯", + "enable": true, + "page": 2, + "time": "day", + "path": "assets/path/蒙德-清泉镇-神奇的霍普金斯.json", + "_1d_foods": ["圣水"] + }, + "Blanche": { + "name": "布兰琪", + "enable": true, + "page": 2, + "time": "night", + "path": "assets/path/蒙德-蒙德城-布兰琪.json", + "_1d_foods": ["盐", "胡椒", "洋葱", "牛奶", "番茄", "卷心菜", "土豆", "小麦"] + }, + "莎拉": { + "name": "莎拉", + "enable": true, + "page": 4, + "time": "night", + "path": "assets/path/蒙德-蒙德城-莎拉.json", + "_7d_foods": ["蟹黃"] + }, + "DongSheng": { + "name": "东升", + "enable": true, + "page": 2, + "time": "any", + "path": "assets/path/璃月-璃月港-东升.json", + "_1d_foods": ["洋葱", "牛奶", "卷心菜", "土豆", "小麦", "稻米", "虾仁", "豆腐", "杏仁", "盐", "胡椒", "番茄"] + }, + "ChefMao": { + "name": "卯师父", + "enable": true, + "page": 5, + "time": "any", + "path": "assets/path/璃月-璃月港-卯师父.json", + "_1d_foods": ["鱼肉", "螃蟹"], + "_3d_foods": ["胡萝卜", "松茸", "絶云椒椒"] + }, + "UncleSun": { + "name": "老孙", + "enable": true, + "page": 1, + "time": "day", + "path": "assets/path/璃月-璃月港-老孙.json", + "_1d_foods": ["鱼肉", "螃蟹", "虾仁"] + }, + "UncleGao": { + "name": "老高", + "enable": true, + "page": 1, + "time": "any", + "path": "assets/path/璃月-璃月港-老高.json", + "_1d_foods": ["鱼肉"] + }, + "阿桂": { + "name": "阿桂", + "enable": true, + "page": 2, + "time": "night", + "path": "assets/path/璃月-璃月港-阿桂.json", + "_3d_foods": ["清心", "琉璃袋"] + }, + "菲尔戈黛特": { + "name": "菲尔戈黛特", + "enable": true, + "page": 2, + "time": "any", + "path": "assets/path/璃月-望舒客栈-菲尔戈黛特.json", + "_3d_foods": ["松茸", "琉璃袋"] + }, + "丰泰": { + "name": "丰泰", + "enable": true, + "page": 2, + "time": "any", + "path": "assets/path/璃月-遗珑埠-丰泰.json", + "_3d_foods": ["沉玉仙茗", "琉璃袋", "絶云椒椒"], + "_7d_foods": ["蟹黃"] + }, + "连芳": { + "name": "连芳", + "enable": true, + "page": 2, + "time": "any", + "path": "assets/path/璃月-遗珑埠-连芳.json", + "_3d_foods": ["沉玉仙茗"] + }, + "Obata": { + "name": "小畑", + "enable": true, + "page": 1, + "time": "any", + "path": "assets/path/稻妻-离岛-小畑.json", + "_1d_foods": ["螃蟹"] + }, + "Aoi": { + "name": "葵", + "enable": true, + "page": 2, + "time": "any", + "path": "assets/path/稻妻-稻妻城-葵.json", + "_1d_foods": ["洋葱", "牛奶", "卷心菜", "土豆", "小麦", "稻米", "虾仁", "豆腐", "盐", "胡椒", "番茄"] + }, + "ShimuraKanbei": { + "name": "志村勘兵卫", + "enable": true, + "page": 4, + "time": "any", + "path": "assets/path/稻妻-稻妻城-志村勘兵卫.json", + "_1d_foods": ["鱼肉", "螃蟹"], + "_3d_foods": ["堇瓜"] + }, + "清子": { + "name": "清子", + "enable": true, + "page": 1, + "time": "any", + "path": "assets/path/稻妻-海祇岛-清子.json", + "_7d_foods": ["牛奶", "番茄", "土豆", "小麦", "豆腐"] + }, + "Zhute": { + "name": "朱特", + "enable": true, + "page": 1, + "time": "any", + "path": "assets/path/须弥-须弥城-朱特.json", + "_3d_foods": ["帕蒂沙兰"] + }, + "Butrus": { + "name": "布特罗斯", + "enable": true, + "page": 1, + "time": "any", + "path": "assets/path/须弥-奥摩斯港-布特罗斯.json", + "_1d_foods": ["鱼肉", "螃蟹", "虾仁"] + + }, + "Pam": { + "name": "珀姆", + "enable": true, + "page": 1, + "time": "any", + "path": "assets/path/须弥-须弥城-珀姆.json", + "_1d_foods": ["鱼肉", "螃蟹", "虾仁"] + + }, + "Hamawi": { + "name": "哈马维", + "enable": true, + "page": 2, + "time": "any", + "path": "assets/path/须弥-须弥城-哈马维.json", + "_1d_foods": ["洋葱", "牛奶", "卷心菜", "土豆", "小麦", "稻米", "虾仁", "豆腐", "盐", "胡椒", "番茄"] + }, + "Lambad": { + "name": "兰巴德", + "enable": true, + "page": 3, + "time": "any", + "path": "assets/path/须弥-须弥城-兰巴德酒馆-兰巴德.json", + "_1d_foods": ["鱼肉", "螃蟹"] + }, + "Enteka": { + "name": "恩忒卡", + "enable": true, + "page": 2, + "time": "any", + "path": "assets/path/须弥-须弥城-普斯帕咖啡馆-恩忒卡.json", + "_1d_foods": ["咖啡豆"] + } + , + "Azalai": { + "name": "阿扎莱", + "enable": true, + "page": 2, + "time": "night", + "path": "assets/path/须弥-阿如村-阿扎莱.json", + "_1d_foods": ["鱼肉", "兽肉", "秃秃豆"] + }, + "巴巴克": { + "name": "巴巴克", + "enable": true, + "page": 1, + "time": "any", + "path": "assets/path/须弥-奥摩斯港-巴巴克.json", + "_3d_foods": ["清心", "琉璃袋"] + }, + "Boucicaut": { + "name": "布希柯", + "enable": true, + "page": 2, + "time": "any", + "path": "assets/path/枫丹-枫丹廷-布希柯.json", + "_1d_foods": ["枫达", "洋葱", "牛奶", "卷心菜", "土豆", "小麦", "秃秃豆", "杏仁", "发酵果实汁", "盐", "胡椒", "番茄"] + }, + "Arouet": { + "name": "阿鲁埃", + "enable": true, + "page": 2, + "time": "any", + "path": "assets/path/枫丹-枫丹廷-阿鲁埃.json", + "_1d_foods": ["咖啡豆", "枫达"] + }, + "Antman": { + "name": "安特曼", + "enable": true, + "page": 1, + "time": "any", + "path": "assets/path/枫丹-白淞镇-安特曼.json", + "_1d_foods": ["鱼肉", "螃蟹"], + "_3d_foods": ["海露花", "汐藻"] + }, + "皮托": { + "name": "皮托", + "enable": true, + "page": 1, + "time": "any", + "path": "assets/path/枫丹-锈舵酒馆-皮托.json", + "_1d_foods": ["牛奶"], + "_7d_foods": ["培根", "火腿", "香肠", "奶酪"] + }, + "钦特利": { + "name": "钦特利", + "enable": true, + "page": 1, + "time": "any", + "path": "assets/path/纳塔-圣火竞技场-钦特利.json", + "_3d_foods": ["青蜜梅", "苦种"] + }, + "夏安卡": { + "name": "夏安卡", + "enable": true, + "page": 3, + "time": "any", + "path": "assets/path/纳塔-圣火竞技场-夏安卡.json", + "_7d_foods": ["蟹黃"] + }, + "Bunama": { + "name": "布纳马", + "enable": true, + "page": 2, + "time": "any", + "path": "assets/path/纳塔-圣火竞技场-布纳马.json", + "_1d_foods": ["盐", "胡椒", "小麦", "洋葱", "牛奶", "番茄", "卷心菜", "土豆", "秃秃豆"] + } + , + "采若": { + "name": "采若", + "enable": true, + "page": 3, + "time": "any", + "path": "assets/path/挪德卡莱-那夏镇-采若.json", + "_1d_foods": ["黑麦", "盐", "胡椒", "洋葱", "牛奶", "番茄", "卷心菜", "土豆", "小麦"] + } + +} \ No newline at end of file diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/挪德卡莱-杂货铺-采若.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/挪德卡莱-那夏镇-采若.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/挪德卡莱-杂货铺-采若.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/挪德卡莱-那夏镇-采若.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/布希柯.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/枫丹-枫丹廷-布希柯.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/布希柯.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/枫丹-枫丹廷-布希柯.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/阿鲁埃.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/枫丹-枫丹廷-阿鲁埃.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/阿鲁埃.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/枫丹-枫丹廷-阿鲁埃.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/安特曼.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/枫丹-白淞镇-安特曼.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/安特曼.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/枫丹-白淞镇-安特曼.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/枫丹-锈坨-皮托.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/枫丹-锈舵酒馆-皮托.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/枫丹-锈坨-皮托.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/枫丹-锈舵酒馆-皮托.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/菲尔戈黛特.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-望舒客栈-菲尔戈黛特.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/菲尔戈黛特.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-望舒客栈-菲尔戈黛特.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/东升.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-璃月港-东升.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/东升.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-璃月港-东升.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/卯师父.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-璃月港-卯师父.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/卯师父.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-璃月港-卯师父.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/老孙.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-璃月港-老孙.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/老孙.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-璃月港-老孙.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/老高.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-璃月港-老高.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/老高.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-璃月港-老高.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/阿桂.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-璃月港-阿桂.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/阿桂.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-璃月港-阿桂.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/丰泰.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-遗珑埠-丰泰.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/丰泰.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-遗珑埠-丰泰.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/连芳.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-遗珑埠-连芳.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/连芳.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/璃月-遗珑埠-连芳.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/小畑.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/稻妻-离岛-小畑.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/小畑.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/稻妻-离岛-小畑.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/志村勘兵卫.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/稻妻-稻妻城-志村勘兵卫.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/志村勘兵卫.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/稻妻-稻妻城-志村勘兵卫.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/葵.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/稻妻-稻妻城-葵.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/葵.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/稻妻-稻妻城-葵.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/夏安卡.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/纳塔-圣火竞技场-夏安卡.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/夏安卡.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/纳塔-圣火竞技场-夏安卡.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/布纳马.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/纳塔-圣火竞技场-布纳马.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/布纳马.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/纳塔-圣火竞技场-布纳马.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/钦特利.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/纳塔-圣火竞技场-钦特利.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/钦特利.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/纳塔-圣火竞技场-钦特利.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/神奇的霍普金斯.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/蒙德-清泉镇-神奇的霍普金斯.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/神奇的霍普金斯.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/蒙德-清泉镇-神奇的霍普金斯.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/布兰琪.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/蒙德-蒙德城-布兰琪.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/布兰琪.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/蒙德-蒙德城-布兰琪.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/莎拉.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/蒙德-蒙德城-莎拉.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/莎拉.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/蒙德-蒙德城-莎拉.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/巴巴克.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-奥摩斯港-巴巴克.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/巴巴克.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-奥摩斯港-巴巴克.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/布特罗斯.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-奥摩斯港-布特罗斯.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/布特罗斯.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-奥摩斯港-布特罗斯.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/阿扎莱.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-阿如村-阿扎莱.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/阿扎莱.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-阿如村-阿扎莱.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/兰巴德.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-须弥城-兰巴德酒馆-兰巴德.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/兰巴德.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-须弥城-兰巴德酒馆-兰巴德.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/哈马维.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-须弥城-哈马维.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/哈马维.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-须弥城-哈马维.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/恩忒卡.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-须弥城-普斯帕咖啡馆-恩忒卡.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/恩忒卡.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-须弥城-普斯帕咖啡馆-恩忒卡.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/朱特.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-须弥城-朱特.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/朱特.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-须弥城-朱特.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/assets/path/珀姆.json b/repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-须弥城-珀姆.json similarity index 100% rename from repo/js/自动购买每天&3天&每周刷新食材/assets/path/珀姆.json rename to repo/js/自动购买每天&3天&每周刷新食材/assets/path/须弥-须弥城-珀姆.json diff --git a/repo/js/自动购买每天&3天&每周刷新食材/main.js b/repo/js/自动购买每天&3天&每周刷新食材/main.js index 2652df3f6..dcfc79bcd 100644 --- a/repo/js/自动购买每天&3天&每周刷新食材/main.js +++ b/repo/js/自动购买每天&3天&每周刷新食材/main.js @@ -10,1020 +10,1082 @@ // isStart: 布尔值,true表示开始日志,false表示结束日志 // duration: 整数,表示脚本或地图追踪的运行时间(仅在结束日志时使用),单位为毫秒_基本填0即可 // 示例: -// JS腳本開始 +// JS脚本开始 // await fakeLog("js脚本名", true, true, 0); -// JS腳本結束 +// JS脚本结束 // await fakeLog("js脚本名", true, false, 0); // 地图追踪开始 // await fakeLog("地图追踪名", false, true, 0); // 地图追踪结束 // await fakeLog("地图追踪名", false, false, 0); // 交互或拾取:"XXXX" -// await fakeLog("XXXX", false, false, 9527); - +// await fakeLog("XXXX", false, false, 23333); async function fakeLog(name, isJs, isStart, duration) { - await sleep(10); - const currentTime = Date.now(); - // 参数检查 - if (typeof name !== 'string') { - log.error("参数 'name' 必须是字符串类型!"); - return; - } - if (typeof isJs !== 'boolean') { - log.error("参数 'isJs' 必须是布尔型!"); - return; - } - if (typeof isStart !== 'boolean') { - log.error("参数 'isStart' 必须是布尔型!"); - return; - } - if (typeof currentTime !== 'number' || !Number.isInteger(currentTime)) { - log.error("参数 'currentTime' 必须是整数!"); - return; - } - if (typeof duration !== 'number' || !Number.isInteger(duration)) { - log.error("参数 'duration' 必须是整数!"); - return; - } + await sleep(10); + const currentTime = Date.now(); + // 参数检查 + if (typeof name !== 'string') { + log.error("参数 'name' 必须是字符串类型!"); + return; + } + if (typeof isJs !== 'boolean') { + log.error("参数 'isJs' 必须是布尔型!"); + return; + } + if (typeof isStart !== 'boolean') { + log.error("参数 'isStart' 必须是布尔型!"); + return; + } + if (typeof currentTime !== 'number' || !Number.isInteger(currentTime)) { + log.error("参数 'currentTime' 必须是整数!"); + return; + } + if (typeof duration !== 'number' || !Number.isInteger(duration)) { + log.error("参数 'duration' 必须是整数!"); + return; + } - // 将 currentTime 转换为 Date 对象并格式化为 HH:mm:ss.sss - const date = new Date(currentTime); - const hours = String(date.getHours()).padStart(2, '0'); - const minutes = String(date.getMinutes()).padStart(2, '0'); - const seconds = String(date.getSeconds()).padStart(2, '0'); - const milliseconds = String(date.getMilliseconds()).padStart(3, '0'); - const formattedTime = `${hours}:${minutes}:${seconds}.${milliseconds}`; + // 将 currentTime 转换为 Date 对象并格式化为 HH:mm:ss.sss + const date = new Date(currentTime); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + const milliseconds = String(date.getMilliseconds()).padStart(3, '0'); + const formattedTime = `${hours}:${minutes}:${seconds}.${milliseconds}`; - // 将 duration 转换为分钟和秒,并保留三位小数 - const durationInSeconds = duration / 1000; // 转换为秒 - const durationMinutes = Math.floor(durationInSeconds / 60); - const durationSeconds = (durationInSeconds % 60).toFixed(3); // 保留三位小数 - - // 使用四个独立的 if 语句处理四种情况 - if (isJs && isStart) { - // 处理 isJs = true 且 isStart = true 的情况 - const logMessage = `正在伪造js开始的日志记录\n\n` + - `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + - `------------------------------\n\n` + - `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + - `→ 开始执行JS脚本: "${name}"`; - log.debug(logMessage); - } - if (isJs && !isStart) { - // 处理 isJs = true 且 isStart = false 的情况 - const logMessage = `正在伪造js结束的日志记录\n\n` + - `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + - `→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}分${durationSeconds}秒\n\n` + - `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + - `------------------------------`; - log.debug(logMessage); - } - if (!isJs && isStart) { - // 处理 isJs = false 且 isStart = true 的情况 - const logMessage = `正在伪造地图追踪开始的日志记录\n\n` + - `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + - `------------------------------\n\n` + - `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + - `→ 开始执行地图追踪任务: "${name}"`; - log.debug(logMessage); - } - if (!isJs && !isStart) { - // 处理 isJs = false 且 isStart = false 的情况 - const logMessage = `正在伪造地图追踪结束的日志记录\n\n` + - `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + - `→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}分${durationSeconds}秒\n\n` + - `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + - `------------------------------`; - log.debug(logMessage); - } - // 交互或拾取:"XXXX" - if (duration == 9527) { - // const logMessage = `正在 交互或拾取 的日志记录\n\n` + - // `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + - // `------------------------------\n\n` + - // `[${formattedTime}] [INF] BetterGenshinImpact.Service.AutoPick.AutoPickTrigger\n` + - // `交互或拾取:"${name}"`; - // log.debug(logMessage); - log.info(`交互或拾取:"${name}"`); - } + // 将 duration 转换为分钟和秒,并保留三位小数 + const durationInSeconds = duration / 1000; // 转换为秒 + const durationMinutes = Math.floor(durationInSeconds / 60); + const durationSeconds = (durationInSeconds % 60).toFixed(3); // 保留三位小数 + // 使用四个独立的 if 语句处理四种情况 + if (isJs && isStart) { + // 处理 isJs = true 且 isStart = true 的情况 + const logMessage = `正在伪造js开始的日志记录\n\n` + + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + + `------------------------------\n\n` + + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + + `→ 开始执行JS脚本: "${name}"`; + log.debug(logMessage); + } + if (isJs && !isStart) { + // 处理 isJs = true 且 isStart = false 的情况 + const logMessage = `正在伪造js结束的日志记录\n\n` + + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + + `→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}分${durationSeconds}秒\n\n` + + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + + `------------------------------`; + log.debug(logMessage); + } + if (!isJs && isStart) { + // 处理 isJs = false 且 isStart = true 的情况 + const logMessage = `正在伪造地图追踪开始的日志记录\n\n` + + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + + `------------------------------\n\n` + + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + + `→ 开始执行地图追踪任务: "${name}"`; + log.debug(logMessage); + } + if (!isJs && !isStart) { + // 处理 isJs = false 且 isStart = false 的情况 + const logMessage = `正在伪造地图追踪结束的日志记录\n\n` + + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + + `→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}分${durationSeconds}秒\n\n` + + `[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` + + `------------------------------`; + log.debug(logMessage); + } + // 交互或拾取:"XXXX" + if (duration == 23333) { + log.info(`交互或拾取:"${name}"`); + } } -const AFK = parseInt(settings.AKF) || 1; // 从settings读取用户选择的购买日 -const AFKDay = AFK === 7 ? 0 : AFK; // 将7转换为0(周日) - -const npcData = { - "神奇的霍普金斯": { - "name": "神奇的霍普金斯", - "enable": true, - "page": 2, - "time": "day", - "path": "assets/path/神奇的霍普金斯.json", - "_1d_foods": ["圣水"] - }, - "Blanche": { - "name": "布兰琪", - "enable": true, - "page": 2, - "time": "night", - "path": "assets/path/布兰琪.json", - "_1d_foods": ["盐", "胡椒", "洋葱", "牛奶", "番茄", "卷心菜", "土豆", "小麦"] - }, - "莎拉": { - "name": "莎拉", - "enable": true, - "page": 4, - "time": "night", - "path": "assets/path/莎拉.json", - "_7d_foods": ["蟹黃"] - }, - "DongSheng": { - "name": "东升", - "enable": true, - "page": 2, - "time": "any", - "path": "assets/path/东升.json", - "_1d_foods": ["洋葱", "牛奶", "卷心菜", "土豆", "小麦", "稻米", "虾仁", "豆腐", "杏仁", "盐", "胡椒", "番茄"] - }, - "ChefMao": { - "name": "香菱爹", - "enable": true, - "page": 5, - "time": "any", - "path": "assets/path/卯师父.json", - "_1d_foods": ["鱼肉", "螃蟹"], - "_3d_foods": ["胡梦卜", "松茸", "絶云椒椒"] - }, - "UncleSun": { - "name": "奸商老孙", - "enable": true, - "page": 1, - "time": "day", - "path": "assets/path/老孙.json", - "_1d_foods": ["鱼肉", "螃蟹", "虾仁"], - }, - "UncleGao": { - "name": "奸商老高", - "enable": true, - "page": 1, - "time": "any", - "path": "assets/path/老高.json", - "_1d_foods": ["鱼肉"] - }, - "阿桂": { - "name": "阿桂", - "enable": true, - "page": 2, - "time": "night", - "path": "assets/path/阿桂.json", - "_3d_foods": ["清心", "琉璃袋"] - }, - "菲尔戈黛特": { - "name": "菲尔戈黛特", - "enable": true, - "page": 2, - "time": "any", - "path": "assets/path/菲尔戈黛特.json", - "_3d_foods": ["松茸", "琉璃袋"] - }, - "丰泰": { - "name": "丰泰", - "enable": true, - "page": 2, - "time": "any", - "path": "assets/path/丰泰.json", - "_3d_foods": ["沉玉仙茗", "琉璃袋", "絶云椒椒"], - "_7d_foods": ["蟹黃"] - }, - "连芳": { - "name": "连芳", - "enable": true, - "page": 2, - "time": "any", - "path": "assets/path/连芳.json", - "_3d_foods": ["沉玉仙茗"] - }, - "Obata": { - "name": "小畑", - "enable": true, - "page": 1, - "time": "any", - "path": "assets/path/小畑.json", - "_1d_foods": ["螃蟹"], - - }, - "Aoi": { - "name": "葵", - "enable": true, - "page": 2, - "time": "any", - "path": "assets/path/葵.json", - "_1d_foods": ["洋葱", "牛奶", "卷心菜", "土豆", "小麦", "稻米", "虾仁", "豆腐", "盐", "胡椒", "番茄"] - }, - "ShimuraKanbei": { - "name": "志村勘兵卫", - "enable": true, - "page": 4, - "time": "any", - "path": "assets/path/志村勘兵卫.json", - "_1d_foods": ["鱼肉", "螃蟹"], - "_3d_foods": ["堇瓜"] - }, - "清子": { - "name": "清子", - "enable": true, - "page": 1, - "time": "any", - "path": "assets/path/稻妻-海祇岛-清子.json", - "_7d_foods": ["牛奶", "番茄", "土豆", "小麦", "豆腐"] - }, - "Zhute": { - "name": "朱特", - "enable": true, - "page": 1, - "time": "any", - "path": "assets/path/朱特.json", - "_3d_foods": ["帕蒂沙兰"] - }, - "Butrus": { - "name": "布特罗斯", - "enable": true, - "page": 1, - "time": "any", - "path": "assets/path/布特罗斯.json", - "_1d_foods": ["鱼肉", "螃蟹", "虾仁"], - - }, - "Pam": { - "name": "珀姆", - "enable": true, - "page": 1, - "time": "any", - "path": "assets/path/珀姆.json", - "_1d_foods": ["鱼肉", "螃蟹", "虾仁"], - - }, - "Hamawi": { - "name": "哈马维", - "enable": true, - "page": 2, - "time": "any", - "path": "assets/path/哈马维.json", - "_1d_foods": ["洋葱", "牛奶", "卷心菜", "土豆", "小麦", "稻米", "虾仁", "豆腐", "盐", "胡椒", "番茄"] - }, - "Lambad": { - "name": "兰巴德", - "enable": true, - "page": 3, - "time": "any", - "path": "assets/path/兰巴德.json", - "_1d_foods": ["鱼肉", "螃蟹"], - }, - "Enteka": { - "name": "恩忒卡", - "enable": true, - "page": 2, - "time": "any", - "path": "assets/path/恩忒卡.json", - "_1d_foods": ["咖啡豆"] - } - , - "Azalai": { - "name": "阿扎莱", - "enable": false, - "page": 2, - "time": "night", - "path": "assets/path/阿扎莱.json", - "_1d_foods": ["鱼肉", "兽肉", "秃秃豆"] - }, - "巴巴克": { - "name": "巴巴克", - "enable": true, - "page": 1, - "time": "any", - "path": "assets/path/巴巴克.json", - "_3d_foods": ["清心", "琉璃袋"] - }, - "Boucicaut": { - "name": "布希柯", - "enable": true, - "page": 2, - "time": "any", - "path": "assets/path/布希柯.json", - "_1d_foods": ["枫达", "洋葱", "牛奶", "卷心菜", "土豆", "小麦", "秃秃豆", "杏仁", "发酵果实汁", "盐", "胡椒", "番茄"] - }, - "Arouet": { - "name": "阿鲁埃", - "enable": true, - "page": 2, - "time": "any", - "path": "assets/path/阿鲁埃.json", - "_1d_foods": ["咖啡豆", "枫达"] - }, - "Antman": { - "name": "安特曼", - "enable": true, - "page": 1, - "time": "any", - "path": "assets/path/安特曼.json", - "_1d_foods": ["鱼肉", "螃蟹"], - "_3d_foods": ["海露花", "汐藻"] - }, - "皮托": { - "name": "皮托", - "enable": true, - "page": 1, - "time": "any", - "path": "assets/path/枫丹-锈坨-皮托.json", - "_1d_foods": ["牛奶"], - "_7d_foods": ["培根", "火腿", "香肠", "奶酪"] - }, - "钦特利": { - "name": "钦特利", - "enable": true, - "page": 1, - "time": "any", - "path": "assets/path/钦特利.json", - "_3d_foods": ["青蜜梅", "苦种"] - }, - "夏安卡": { - "name": "夏安卡", - "enable": true, - "page": 3, - "time": "any", - "path": "assets/path/夏安卡.json", - "_7d_foods": ["蟹黃"] - }, - "Bunama": { - "name": "布纳马", - "enable": true, - "page": 2, - "time": "any", - "path": "assets/path/布纳马.json", - "_1d_foods": ["盐", "胡椒", "小麦", "洋葱", "牛奶", "番茄", "卷心菜", "土豆", "秃秃豆"] - } - , - "采若": { // NPC名字 - "name": "采若", // NPC名字 - "enable": true, - "page": 3, // 商人卖的物品页数 - "time": "any", //any 不调时间,day 早上8点, night 晚上8点 - "path": "assets/path/挪德卡莱-杂货铺-采若.json", //写入 卖食物NPC路径名 - "_1d_foods": ["黑麦", "盐", "胡椒", "洋葱", "牛奶", "番茄", "卷心菜", "土豆", "小麦"]// 写入 新加入 的 食材名字 - } - // // 參考 - // , - // "新卖食物NPC": { // NPC名字 - // "name": "新卖食物NPC", // NPC名字 - // "enable": true, - // "page": 1, // 商人卖的物品页数 - // "time": "any", //any 不调时间,day 早上8点, night 晚上8点 - // "path": "assets/path/新卖食物NPC.json", //写入 卖食物NPC路径名 - // "_3d__3d_foods": ["新食材"]// 写入 新加入 的 食材名字 - // } - +// ==================== 日志辅助函数 ==================== +function logConditional(message) { + if (ignoreRecords || recordDebug) { + log.info(message); + } else { + log.debug(message); + } } -const foodsData = { - "salt": { - "id": "salt", - "name": "盐", - "file": "assets/images/salt.png" - }, - "pepper": { - "id": "pepper", - "name": "胡椒", - "file": "assets/images/pepper.png" - }, - "onion": { - "id": "onion", - "name": "洋葱", - "file": "assets/images/onion.png" - }, - "milk": { - "id": "milk", - "name": "牛奶", - "file": "assets/images/milk.png" - }, - "tomato": { - "id": "tomato", - "name": "番茄", - "file": "assets/images/tomato.png" - }, - "potato": { - "id": "potato", - "name": "土豆", - "file": "assets/images/potato.png" - }, - "wheat": { - "id": "wheat", - "name": "小麦", - "file": "assets/images/wheat.png" - }, - "rice": { - "id": "rice", - "name": "稻米", - "file": "assets/images/rice.png" - }, - "coffeeBeans": { - "id": "coffeeBeans", - "name": "咖啡豆", - "file": "assets/images/coffeeBeans.png" - }, - "glabrousBeans": { - "id": "glabrousBeans", - "name": "秃秃豆", - "file": "assets/images/glabrousBeans.png" - }, - "rawMeat": { - "id": "rawMeat", - "name": "兽肉", - "file": "assets/images/rawMeat.png" - }, - "fermentedJuice": { - "id": "fermentedJuice", - "name": "发酵果实汁", - "file": "assets/images/fermentedJuice.png" - }, - "fonta": { - "id": "fonta", - "name": "枫达", - "file": "assets/images/fonta.png" - }, - "shrimp": { - "id": "shrimp", - "name": "虾仁", - "file": "assets/images/shrimp.png" - }, - "almond": { - "id": "almond", - "name": "杏仁", - "file": "assets/images/almond.png" - }, - "cabbage": { - "id": "cabbage", - "name": "卷心菜", - "file": "assets/images/cabbage.png" - }, - "tofu": { - "id": "tofu", - "name": "豆腐", - "file": "assets/images/tofu.png" - }, - "fish": { - "id": "fish", - "name": "鱼肉", - "file": "assets/images/fish.png" - }, - "huMengbu": { - "id": "huMengbu", - "name": "胡梦卜", - "file": "assets/images/huMengbu.png" - }, - "viola": { - "id": "viola", - "name": "堇瓜", - "file": "assets/images/viola.png" - }, - "romaritimeFlower": { - "id": "romaritimeFlower", - "name": "海露花", - "file": "assets/images/romaritimeFlower.png" - }, - "Padisarah": { - "id": "Padisarah", - "name": "帕蒂沙兰", - "file": "assets/images/Padisarah.png" - }, - "松茸": { - "id": "松茸", - "name": "松茸", - "file": "assets/images/松茸.png" - }, - "沉玉仙茗": { - "id": "沉玉仙茗", - "name": "沉玉仙茗", - "file": "assets/images/沉玉仙茗.png" - }, - "青蜜梅": { - "id": "青蜜梅", - "name": "青蜜梅", - "file": "assets/images/青蜜梅.png" - }, - "苦种": { - "id": "苦种", - "name": "苦种", - "file": "assets/images/苦种.png" - }, - "清心": { - "id": "清心", - "name": "清心", - "file": "assets/images/清心.png" - }, - "琉璃袋": { - "id": "琉璃袋", - "name": "琉璃袋", - "file": "assets/images/琉璃袋.png" - }, - "蟹黃": { - "id": "蟹黃", - "name": "蟹黃", - "file": "assets/images/蟹黃.png" - }, - "crab": { - "id": "crab", - "name": "螃蟹", - "file": "assets/images/crab.png" - }, - "tidalga": { - "id": "tidalga", - "name": "汐藻", - "file": "assets/images/tidalga.png" - }, - "圣水": { - "id": "圣水", - "name": "圣水", - "file": "assets/images/圣水.png" - }, - "黑麦": { - "id": "黑麦", - "name": "黑麦", - "file": "assets/images/黑麦.png" - } - , - "絶云椒椒": { - "id": "絶云椒椒", - "name": "絶云椒椒", - "file": "assets/images/絶云椒椒.png" - } - // // 參考 - // , - // "新食材": { - // "id": "新食材", - // "name": "新食材", - // "file": "assets/images/新食材.png" - // } -}; +// ==================== 加载外部数据文件 ==================== +let foodsData = {}; +let npcData = {}; + +async function loadExternalData() { + try { + // 加载食材数据 + const foodsContent = await file.readText("assets/data/foods.json"); + foodsData = JSON.parse(foodsContent); + logConditional(`已加载食材数据: ${Object.keys(foodsData).length} 种食材`); + + // 加载NPC数据 + const npcsContent = await file.readText("assets/data/npcs.json"); + npcData = JSON.parse(npcsContent); + logConditional(`已加载NPC数据: ${Object.keys(npcData).length} 个NPC`); + + return true; + } catch (error) { + log.error(`加载外部数据失败: ${error.message}`); + return false; + } +} + +// ==================== 辅助函数:获取调整后的星期几(1-7,周一为1) ==================== +function getAdjustedDayOfWeek() { + const now = new Date(); + let dayOfWeek = now.getDay(); // 0-6 (0是周日) + const hours = now.getHours(); + + // 如果时间在00:00~04:00之间,视为前一天 + if (hours < 4) { + dayOfWeek = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // 前一天 + if (recordDebug) { + log.info(`[调试] 当前时间 ${now.getHours()}:${now.getMinutes()},视为前一天(周 ${dayOfWeek === 0 ? 7 : dayOfWeek})`); + } + } else if (recordDebug) { + log.info(`[调试] 当前时间 ${now.getHours()}:${now.getMinutes()},使用当天(周 ${dayOfWeek === 0 ? 7 : dayOfWeek})`); + } + + // 转换为1-7格式(7代表周日) + return dayOfWeek === 0 ? 7 : dayOfWeek; +} + +// ==================== 辅助函数:获取给定日期所在的周一日期 ==================== +function getMondayOfWeek(date) { + const d = new Date(date); + // 调整到4点刷新 + if (d.getHours() < 4) { + d.setDate(d.getDate() - 1); + } + const day = d.getDay(); + const diff = day === 0 ? 6 : day - 1; + d.setDate(d.getDate() - diff); + d.setHours(4, 0, 0, 0); + return d; +} + +// ==================== 账号管理功能 ==================== +let userName = settings.userName || "默认账户"; + +// 确保设置变量存在 +const ignoreRecords = settings.ignoreRecords || false; +const recordDebug = settings.recordDebug || false; + +// 解析禁用的NPC列表 +const disabledNpcs = (settings.disabledNpcs || "").split(/\s+/).filter(npc => npc.trim() !== ""); +if (disabledNpcs.length > 0) { + log.info(`已禁用NPC: ${disabledNpcs.join(", ")}`); +} + +// 修改AKF设置处理 +const AKFValue = parseInt(settings.AKF) || 1; +let AFKDay = null; +let followSystem = false; + +if (AKFValue === 0) { + // 0 表示跟随系统判定 + followSystem = true; + log.info("7天食材购买: 跟随系统判定"); +} else { + AFKDay = AKFValue === 7 ? 0 : AKFValue; + log.info(`7天食材购买: 每周${AFKDay === 0 ? "日" : AFKDay}购买`); +} + +// 获取账号记录路径 +function getRecordPath(accountName) { + // 简单处理账户名,如果为空则使用默认账户 + if (!accountName || accountName.trim() === "") { + accountName = "默认账户"; + } + return `record/${accountName.trim()}/records.json`; +} + +// 确保账号目录存在 +async function ensureAccountDirectory(accountName) { + const validName = validateUserName(accountName); + const dirPath = `record/${validName}`; + + try { + // 检查目录是否存在 + await file.readText(dirPath + "/.keep"); + } catch (error) { + // 目录不存在,尝试创建 + try { + // 创建目录(通过写入一个临时文件) + await file.writeText(dirPath + "/.keep", ""); + log.info(`创建账号目录: ${dirPath}`); + } catch (mkdirError) { + log.error(`创建账号目录失败: ${mkdirError.message}`); + } + } +} + +// ==================== 新增函数:读取NPC记录文件 ==================== +async function loadNpcRecords() { + const recordPath = getRecordPath(userName); + try { + const content = await file.readText(recordPath); + if (content.trim()) { + return JSON.parse(content); + } + } catch (error) { + // 文件不存在或格式错误,返回空数组 + } + return []; +} + +// ==================== 保存NPC记录 ==================== +async function saveNpcRecords(records) { + const recordPath = getRecordPath(userName); + try { + await file.writeText(recordPath, JSON.stringify(records, null, 2)); + return true; + } catch (error) { + log.error(`保存记录文件失败: ${error.message}`); + return false; + } +} + +// ==================== 获取NPC记录 ==================== +function getNpcRecord(records, npcName) { + return records.find(record => record.npcname === npcName); +} + +// ==================== 更新NPC记录 ==================== +function updateNpcRecord(records, npcName, refreshType, purchasedItems) { + // 如果没有购买任何商品,不更新记录 + if (!purchasedItems || purchasedItems.length === 0) { + return records; + } + + let record = getNpcRecord(records, npcName); + + if (!record) { + record = { + npcname: npcName, + "1d": [], + "1d_time": null, + "3d": [], + "3d_time": null, + "7d": [], + "7d_time": null + }; + records.push(record); + } + + const now = new Date(); + let refreshTime; + + if (refreshType === "1d") { + // 1天商品:下次刷新是购买日+1天 + refreshTime = new Date(now); + refreshTime.setHours(4, 0, 0, 0); + // 如果当前时间在4点前,刷新时间从昨天开始算 + if (now.getHours() < 4) { + refreshTime.setDate(refreshTime.getDate() - 1); + } + refreshTime.setDate(refreshTime.getDate() + 1); + } else if (refreshType === "3d") { + // 3天商品:基于基准日的3天周期计算 + // 基准时间:2025-08-09 04:00 GMT+8 (转换为本地时间) + const baseTime = new Date(2025, 7, 9, 4, 0, 0); // 2025-08-09 04:00 + + // 调整当前时间到4点基准 + const adjustedNow = new Date(now); + if (adjustedNow.getHours() < 4) { + adjustedNow.setDate(adjustedNow.getDate() - 1); + } + adjustedNow.setHours(4, 0, 0, 0); + + // 计算距离基准日的天数 + const timeDiff = adjustedNow.getTime() - baseTime.getTime(); + const daysDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24)); + + // 计算当前3天周期 + const currentPeriod = Math.floor(daysDiff / 3); + + // 下一个3天周期的开始时间 + const nextPeriod = currentPeriod + 1; + refreshTime = new Date(baseTime); + refreshTime.setDate(baseTime.getDate() + (nextPeriod * 3)); + + // 确保刷新时间是04:00 + refreshTime.setHours(4, 0, 0, 0); + } else if (refreshType === "7d") { + // 7天商品:下次刷新是下周一 + refreshTime = getMondayOfWeek(now); + refreshTime.setDate(refreshTime.getDate() + 7); + } + + // 只更新实际购买的商品 + record[refreshType] = purchasedItems; + record[`${refreshType}_time`] = formatDateToLocalISO(refreshTime); + + // 计算下次刷新日期 + if (recordDebug) { + const nextRefresh = new Date(refreshTime); + log.info(`${npcName} 下次${refreshType}刷新时间: ${formatDateToLocalISO(nextRefresh)}`); + } + + return records; +} + +// ==================== 新增函数:计算基准日周期 ==================== +function getBasePeriod(currentDate) { + // 基准时间:2025-08-08 20:00 UTC (对应2025-08-09 04:00 GMT+8) + const baseTime = Date.UTC(2025, 7, 8, 20, 0, 0); + + // 转换当前时间到UTC+8 + const utcNowMs = currentDate.getTime() + currentDate.getTimezoneOffset() * 60 * 1000; + const gmt8Ms = utcNowMs + 8 * 60 * 60 * 1000; + const gmt8Date = new Date(gmt8Ms); + + // 如果还没到凌晨4点,算作前一天 + if (gmt8Date.getHours() < 4) { + gmt8Date.setDate(gmt8Date.getDate() - 1); + } + + // 计算距离基准日的天数 + const daysDiff = Math.floor((gmt8Date.getTime() - baseTime) / (24 * 60 * 60 * 1000)); + + return { + day: gmt8Date, + daysDiff: daysDiff, + threeDayPeriod: Math.floor(daysDiff / 3), + sevenDayPeriod: Math.floor(daysDiff / 7) + }; +} + +// ==================== 判断是否需要购买 ==================== +function shouldBuyFoods(npc, npcRecord, currentPeriod, forceRefresh = false) { + const now = new Date(); + const foodsToBuy = { + "1d": [], + "3d": [], + "7d": [] + }; + + if (forceRefresh) { + // 强制刷新,但只购买已启用的商品 + if (npc._1d_foods) foodsToBuy["1d"] = filterEnabledFoods(npc._1d_foods); + if (npc._3d_foods) foodsToBuy["3d"] = filterEnabledFoods(npc._3d_foods); + if (npc._7d_foods) foodsToBuy["7d"] = filterEnabledFoods(npc._7d_foods); + return foodsToBuy; + } + + // 1天商品逻辑 + if (npc._1d_foods) { + const enabledFoods = filterEnabledFoods(npc._1d_foods); + if (enabledFoods.length > 0) { + if (!npcRecord || !npcRecord["1d_time"]) { + // 没有记录,需要购买已启用的商品 + foodsToBuy["1d"] = enabledFoods; + } else { + // 读取记录中的下次刷新时间 + const nextRefreshTime = new Date(npcRecord["1d_time"]); + + if (now >= nextRefreshTime) { + // 已到刷新时间,需要购买 + foodsToBuy["1d"] = enabledFoods; + } else if (recordDebug) { + log.info(`[调试] ${npc.name} 的1天商品未到刷新时间,下次刷新: ${formatDateToLocalISO(nextRefreshTime)}`); + } + } + } + } + + // 3天商品逻辑 + if (npc._3d_foods) { + const enabledFoods = filterEnabledFoods(npc._3d_foods); + if (enabledFoods.length > 0) { + if (!npcRecord || !npcRecord["3d_time"]) { + // 没有记录,直接购买 + foodsToBuy["3d"] = enabledFoods; + if (recordDebug) { + log.info(`[调试] ${npc.name} 的3天商品没有记录,直接购买`); + } + } else { + // 有记录,检查是否已刷新 + const nextRefreshTime = new Date(npcRecord["3d_time"]); + + if (now >= nextRefreshTime) { + // 已到刷新时间,需要购买 + foodsToBuy["3d"] = enabledFoods; + if (recordDebug) { + log.info(`[调试] ${npc.name} 的3天商品已到刷新时间,需要购买`); + } + } else if (recordDebug) { + log.info(`[调试] ${npc.name} 的3天商品未到刷新时间,下次刷新: ${formatDateToLocalISO(nextRefreshTime)}`); + } + } + } + } + + // 7天商品逻辑 + if (npc._7d_foods) { + const enabledFoods = filterEnabledFoods(npc._7d_foods); + if (enabledFoods.length > 0) { + if (!npcRecord || !npcRecord["7d_time"]) { + // 没有记录,直接购买 + foodsToBuy["7d"] = enabledFoods; + if (recordDebug) { + log.info(`[调试] ${npc.name} 的7天商品没有记录,直接购买`); + } + } else { + // 有记录,检查是否已刷新 + const nextRefreshTime = new Date(npcRecord["7d_time"]); + + if (now >= nextRefreshTime) { + // 已到刷新时间,检查是否应该购买 + if (followSystem) { + // 跟随系统模式:直接购买 + foodsToBuy["7d"] = enabledFoods; + if (recordDebug) { + log.info(`[调试] ${npc.name} 的7天商品已到刷新时间,跟随系统模式,直接购买`); + } + } else { + // 固定日模式:检查今天是否是指定购买日 + const today = getAdjustedDayOfWeek(); + const targetDay = AFKDay === 0 ? 7 : AFKDay; // 将0(周日)转换为7 + + if (today === targetDay) { + foodsToBuy["7d"] = enabledFoods; + if (recordDebug) { + log.info(`[调试] ${npc.name} 的7天商品已到刷新时间,今天是指定购买日(${targetDay}),购买`); + } + } else if (recordDebug) { + log.info(`[调试] ${npc.name} 的7天商品已到刷新时间,但今天(${today})不是指定购买日(${targetDay}),不购买`); + } + } + } else if (recordDebug) { + log.info(`[调试] ${npc.name} 的7天商品未到刷新时间,下次刷新: ${formatDateToLocalISO(nextRefreshTime)}`); + } + } + } + } + + return foodsToBuy; +} + +// ==================== 新增函数:过滤已启用的食材 ==================== +function filterEnabledFoods(foodList) { + if (!foodList || !Array.isArray(foodList)) { + return []; + } + + return foodList.filter(food => { + // 检查食材是否在 settings 中被启用 + const foodId = translationList[food] || food; + return settings[foodId] === true; + }); +} const translationList = {}; - const enableFoods = new Set([]); const othrtRo = { - "buy": { - "name": "购买按钮", - "file": "assets/images/buyBtn.png" - } -} - -// ==================== 新增函数:判断是否是刷新日 ==================== - -function isRefreshDay() { - // 1. 计算基准刷新时间的 UTC 毫秒值 - // 2025-08-09 04:00 (GMT+8) == 2025-08-08 20:00Z - const baseUtcMs = Date.UTC(2025, 7, 8, 20, 0, 0); - - // 2. 获取当前时间的 UTC 毫秒 - const now = new Date(); - const utcNowMs = now.getTime() + now.getTimezoneOffset() * 60 * 1000; - - // 3. 构造 GMT+8 的时间对象 - const gmt8Ms = utcNowMs + 8 * 60 * 60 * 1000; - const gmt8Date = new Date(gmt8Ms); - - // 4. 如果还没到“当天”凌晨 4 点,算作前一天 - if (gmt8Date.getHours() < 4) { - gmt8Date.setDate(gmt8Date.getDate() - 1); - // 加12小時,避免常作前一天0:0至4:0 - gmt8Date.setTime(gmt8Date.getTime() + 12 * 60 * 60 * 1000); - } - - // 5. 计算天数差并判断是否为 3 的倍数 - const daysDiff = Math.floor((gmt8Date.getTime() - baseUtcMs) / (24 * 60 * 60 * 1000)); - return daysDiff >= 0 && daysDiff % 3 === 0; + "buy": { + "name": "购买按钮", + "file": "assets/images/buyBtn.png" + } } // 获取游戏内时间(考虑4点刷新) function getGameTime() { - const now = new Date(); - const utcNowMs = now.getTime() + now.getTimezoneOffset() * 60 * 1000; - const gmt8Ms = utcNowMs + 8 * 60 * 60 * 1000; - const gmt8Date = new Date(gmt8Ms); + const now = new Date(); + const utcNowMs = now.getTime() + now.getTimezoneOffset() * 60 * 1000; + const gmt8Ms = utcNowMs + 8 * 60 * 60 * 1000; + const gmt8Date = new Date(gmt8Ms); - // 如果还没到凌晨4点,算作前一天 - if (gmt8Date.getHours() < 4) { - gmt8Date.setDate(gmt8Date.getDate() - 1); - } + // 如果还没到凌晨4点,算作前一天 + if (gmt8Date.getHours() < 4) { + gmt8Date.setDate(gmt8Date.getDate() - 1); + } - return gmt8Date; + return gmt8Date; +} + +// ==================== 新增函数:格式化为本地ISO时间 ==================== +function formatDateToLocalISO(date) { + // 将日期格式化为 "YYYY-MM-DDTHH:mm:ss+08:00" 格式 + const pad = (n) => n.toString().padStart(2, '0'); + + const year = date.getFullYear(); + const month = pad(date.getMonth() + 1); + const day = pad(date.getDate()); + const hours = pad(date.getHours()); + const minutes = pad(date.getMinutes()); + const seconds = pad(date.getSeconds()); + + return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}+08:00`; } // 设置游戏时间 async function setTime(hour, minute) { - // 关于setTime - // 原作者: Tim - // 脚本名称: SetTimeMinute - 精确调整游戏时间到分钟 - // 脚本版本: 1.0 - // Hash: f5c2547dfc286fc643c733d630f775e8fbf12971 + // 关于setTime + // 原作者: Tim + // 脚本名称: SetTimeMinute - 精确调整游戏时间到分钟 + // 脚本版本: 1.0 + // Hash: f5c2547dfc286fc643c733d630f775e8fbf12971 - // 设置游戏分辨率和DPI缩放 - setGameMetrics(1920, 1080, 1); - // 圆心坐标 - const centerX = 1441; - const centerY = 501.6; - // 半径 - const r1 = 30; - const r2 = 150; - const r3 = 300; - const stepDuration = 50; + // 设置游戏分辨率和DPI缩放 + setGameMetrics(1920, 1080, 1); + // 圆心坐标 + const centerX = 1441; + const centerY = 501.6; + // 半径 + const r1 = 30; + const r2 = 150; + const r3 = 300; + const stepDuration = 50; - function getPosition(r, index) { - let angle = index * Math.PI / 720; - return [Math.round(centerX + r * Math.cos(angle)), Math.round(centerY + r * Math.sin(angle))]; - } - async function mouseClick(x, y) { - moveMouseTo(x, y); - await sleep(50); - leftButtonDown(); - await sleep(50); - leftButtonUp(); - await sleep(stepDuration); - } - async function mouseClickAndMove(x1, y1, x2, y2) { - moveMouseTo(x1, y1); - await sleep(50); - leftButtonDown(); - await sleep(50); - moveMouseTo(x2, y2); - await sleep(50); - leftButtonUp(); - await sleep(stepDuration); - } - async function setTime(hour, minute) { - const end = (hour + 6) * 60 + minute - 20; - const n = 3; - for (let i = - n + 1; i < 1; i++) { - let [x, y] = getPosition(r1, end + i * 1440 / n); - await mouseClick(x, y); - } - let [x1, y1] = getPosition(r2, end + 5); - let [x2, y2] = getPosition(r3, end + 20 + 0.5); - await mouseClickAndMove(x1, y1, x2, y2); - } + function getPosition(r, index) { + let angle = index * Math.PI / 720; + return [Math.round(centerX + r * Math.cos(angle)), Math.round(centerY + r * Math.sin(angle))]; + } + async function mouseClick(x, y) { + moveMouseTo(x, y); + await sleep(50); + leftButtonDown(); + await sleep(50); + leftButtonUp(); + await sleep(stepDuration); + } + async function mouseClickAndMove(x1, y1, x2, y2) { + moveMouseTo(x1, y1); + await sleep(50); + leftButtonDown(); + await sleep(50); + moveMouseTo(x2, y2); + await sleep(50); + leftButtonUp(); + await sleep(stepDuration); + } + async function setTime(hour, minute) { + const end = (hour + 6) * 60 + minute - 20; + const n = 3; + for (let i = - n + 1; i < 1; i++) { + let [x, y] = getPosition(r1, end + i * 1440 / n); + await mouseClick(x, y); + } + let [x1, y1] = getPosition(r2, end + 5); + let [x2, y2] = getPosition(r3, end + 20 + 0.5); + await mouseClickAndMove(x1, y1, x2, y2); + } - let h = Math.floor(hour + minute / 60); - const m = Math.floor(hour * 60 + minute) - h * 60; - h = ((h % 24) + 24) % 24; - log.info(`设置时间到 ${h} 点 ${m} 分`); - await keyPress("Escape"); - await sleep(1000); - await click(50, 700); - await sleep(2000); - await setTime(h, m); - await sleep(1000); - await click(1500, 1000);//确认 - await sleep(18000); - await keyPress("Escape"); - await sleep(2000); - await keyPress("Escape"); - await sleep(2000); + let h = Math.floor(hour + minute / 60); + const m = Math.floor(hour * 60 + minute) - h * 60; + h = ((h % 24) + 24) % 24; + log.info(`设置时间到 ${h} 点 ${m} 分`); + await keyPress("Escape"); + await sleep(1000); + await click(50, 700); + await sleep(2000); + await setTime(h, m); + await sleep(1000); + await click(1500, 1000);//确认 + await sleep(18000); + await keyPress("Escape"); + await sleep(2000); + await keyPress("Escape"); + await sleep(2000); } // 地图追踪 async function autoPath(locationPath) { - try { - let filePath = locationPath; - await pathingScript.runFile(filePath); - sleep(2000); + try { + let filePath = locationPath; + await pathingScript.runFile(filePath); + await sleep(200); - return true; - } catch (error) { - log.error(`执行 ${locationName} 路径时发生错误`); - log.error(error.message); - } - - return false; + return true; + } catch (error) { + log.error(`执行路径时发生错误: ${error.message}`); + return false; + } } // 平滑过渡函数(缓动效果) function smoothStep(t) { - return t * t * (3 - 2 * t); + return t * t * (3 - 2 * t); } // 模拟鼠标移动到指定位置(带曲线路径) async function naturalMove(initX, initY, targetX, targetY, duration, wiggle = 30) { - // 生成控制点(使路径形成曲线) - const controlX = (initX + targetX) / 2 + (Math.random() * wiggle * 2 - wiggle); - const controlY = (initY + targetY) / 2 + (Math.random() * wiggle * 2 - wiggle); + // 生成控制点(使路径形成曲线) + const controlX = (initX + targetX) / 2 + (Math.random() * wiggle * 2 - wiggle); + const controlY = (initY + targetY) / 2 + (Math.random() * wiggle * 2 - wiggle); - const steps = Math.max(duration / 20, 10); // 计算步数 + const steps = Math.max(duration / 20, 10); // 计算步数 - for (let i = 0; i <= steps; i++) { - const progress = i / steps; - const t = smoothStep(progress); // 使用平滑过渡 + for (let i = 0; i <= steps; i++) { + const progress = i / steps; + const t = smoothStep(progress); // 使用平滑过渡 - // 二次贝塞尔曲线计算 - const x = (1 - t) * (1 - t) * initX + 2 * (1 - t) * t * controlX + t * t * targetX; - const y = (1 - t) * (1 - t) * initY + 2 * (1 - t) * t * controlY + t * t * targetY; + // 二次贝塞尔曲线计算 + const x = (1 - t) * (1 - t) * initX + 2 * (1 - t) * t * controlX + t * t * targetX; + const y = (1 - t) * (1 - t) * initY + 2 * (1 - t) * t * controlY + t * t * targetY; - moveMouseTo(Math.trunc(x), Math.trunc(y)); + moveMouseTo(Math.trunc(x), Math.trunc(y)); - // 随机延迟使移动更自然 - await sleep(Math.trunc(duration / steps * (0.8 + Math.random() * 0.4))); - } + // 随机延迟使移动更自然 + await sleep(Math.trunc(duration / steps * (0.8 + Math.random() * 0.4))); + } - await sleep(200); - // 确保最终位置准确 - moveMouseTo(targetX, targetY); + await sleep(200); + // 确保最终位置准确 + moveMouseTo(targetX, targetY); } // 切换下一页商品 async function nextFoodsPage() { - //设置脚本环境的游戏分辨率和DPI缩放 - setGameMetrics(3840, 2160, 1.5); + //设置脚本环境的游戏分辨率和DPI缩放 + setGameMetrics(3840, 2160, 1.5); - let [initX, initY] = [1500, 1850]; - let [targetX, targetY] = [1800, 260]; + let [initX, initY] = [1500, 1850]; + let [targetX, targetY] = [1800, 260]; - moveMouseTo(initX, initY); - leftButtonDown(); - await naturalMove(initX, initY, targetX, targetY, 300); + moveMouseTo(initX, initY); + leftButtonDown(); + await naturalMove(initX, initY, targetX, targetY, 300); - // 按住了, 防止弹太远 - await sleep(520); - leftButtonUp(); + // 按住了, 防止弹太远 + await sleep(520); + leftButtonUp(); } // 快速购买 async function qucikBuy() { - //设置脚本环境的游戏分辨率和DPI缩放 - setGameMetrics(3840, 2160, 1.5); + //设置脚本环境的游戏分辨率和DPI缩放 + setGameMetrics(3840, 2160, 1.5); - let [buyBtnX, buyBtnY] = [3200, 2045]; - let [confirmBtnX, confirmBtnY] = [2025, 1570]; - let [addNumX, addNumY] = [2060, 1208]; + let [buyBtnX, buyBtnY] = [3200, 2045]; + let [confirmBtnX, confirmBtnY] = [2025, 1570]; + let [addNumX, addNumY] = [2060, 1208]; - // 等待界面切换 - await sleep(200); + // 等待界面切换 + await sleep(200); - // 查找购买按钮 - let captureRegion = captureGameRegion(); - let buyBtn = captureRegion.Find(othrtRo.buy.ro); - captureRegion.dispose(); - if (buyBtn.isEmpty()) { - return false; - } - // 点击购买按钮 - click(buyBtn.x * 2 + buyBtn.width, buyBtn.y * 2 + buyBtn.height); - // 等待购买窗口弹出 - await sleep(300); + try { + // 查找购买按钮 + let captureRegion = captureGameRegion(); + let buyBtn = captureRegion.Find(othrtRo.buy.ro); + captureRegion.dispose(); - // 增加数量至最大 - leftButtonDown(); - await naturalMove(addNumX, addNumY, addNumX + 666, addNumY - 233, 100); - leftButtonUp(); + if (buyBtn.isEmpty()) { + log.warn("未找到购买按钮"); + return false; + } - // 确保最终数量至最大 - await sleep(200); - click(2372, 1205); - await sleep(200); + // 点击购买按钮 + click(buyBtn.x * 2 + buyBtn.width, buyBtn.y * 2 + buyBtn.height); + // 等待购买窗口弹出 + await sleep(300); - // 点击确认按钮 - click(confirmBtnX, confirmBtnY); - // 等待购买完成 - await sleep(200); - // 点击空白关闭 - click(buyBtnX, buyBtnY); - await sleep(200); + // 增加数量至最大 + leftButtonDown(); + await naturalMove(addNumX, addNumY, addNumX + 666, addNumY - 233, 100); + leftButtonUp(); - return true; + // 确保最终数量至最大 + await sleep(200); + click(2372, 1205); + await sleep(200); + + // 点击确认按钮 + click(confirmBtnX, confirmBtnY); + // 等待购买完成 + await sleep(200); + // 点击空白关闭 + click(buyBtnX, buyBtnY); + await sleep(200); + + return true; + } catch (error) { + log.error(`快速购买失败: ${error.message}`); + return false; + } } // 跳过对话 async function spikChat(npcName) { - count = 5 - await sleep(1000); - if (npcName == "布纳马") { - // 设置脚本环境的游戏分辨率和DPI缩放 - setGameMetrics(1920, 1080, 1); + let count = 5; // 添加let声明 + await sleep(1000); + if (npcName == "布纳马") { + // 设置脚本环境的游戏分辨率和DPI缩放 + setGameMetrics(1920, 1080, 1); - await sleep(1000); - // 交互 - for (let i = 0; i < 3; i++) { - keyPress("VK_F"); - await sleep(1500); - } + await sleep(1000); + // 交互 + for (let i = 0; i < 3; i++) { + keyPress("VK_F"); + await sleep(1500); + } - // 点击有什么卖的 - let captureRegion = captureGameRegion() - let resList = captureRegion.findMulti(RecognitionObject.ocrThis); - for (let i = 0; i < resList.count; i++) { - if (resList[i].text.includes("有什么卖的")) { - await sleep(500); - click(resList[i].x + 30, resList[i].y + 30); // 点击有什么卖的 - await sleep(500); + // 点击有什么卖的 + let captureRegion = captureGameRegion() + let resList = captureRegion.findMulti(RecognitionObject.ocrThis); + for (let i = 0; i < resList.count; i++) { + if (resList[i].text.includes("有什么卖的")) { + await sleep(500); + click(resList[i].x + 30, resList[i].y + 30); // 点击有什么卖的 + await sleep(500); - // 使用完后释放资源 - captureRegion.dispose(); - } - } + // 使用完后释放资源 + captureRegion.dispose(); + } + } - await sleep(1500); - keyPress("VK_F"); - await sleep(1500); - keyPress("VK_F"); - await sleep(1500); - } else { - for (let i = 0; i < count; i++) { - keyPress("VK_F"); - await sleep(1300); - } - } + await sleep(1500); + keyPress("VK_F"); + await sleep(1500); + keyPress("VK_F"); + await sleep(1500); + } else { + for (let i = 0; i < count; i++) { + keyPress("VK_F"); + await sleep(1300); + } + } } -// 购买逻辑 -async function buyFoods(npcName) { - // 设置脚本环境的游戏分辨率和DPI缩放 - setGameMetrics(3840, 2160, 1.5); +// 修改后的购买逻辑 +async function buyFoods(npcName, npcRecords, currentPeriod) { + // 设置脚本环境的游戏分辨率和DPI缩放 + setGameMetrics(3840, 2160, 1.5); - let tempFoods = [...npcData[npcName].enableFoods]; + // 获取NPC数据 + const npc = npcData[npcName]; + const npcRecord = getNpcRecord(npcRecords, npc.name); - // 多页购买 - for (let i = 0; i < npcData[npcName].page; i++) { - log.info("购买列表: {foods}", [...tempFoods].join(", ")); - await sleep(500); - // 获取一张截图 - let captureRegion = captureGameRegion(); + if (recordDebug) { + log.info(`[调试] 开始处理NPC: ${npc.name}`); + if (npcRecord) { + log.info(`[调试] NPC当前记录: 1d=${npcRecord["1d_time"] || "无"}, 3d=${npcRecord["3d_time"] || "无"}, 7d=${npcRecord["7d_time"] || "无"}`); + } + } - // 记录已经购买的物品 - let boughtFoods = new Set([]); + // 判断需要购买的商品 + const foodsToBuy = shouldBuyFoods(npc, npcRecord, currentPeriod, ignoreRecords); - // 匹配商品 - for (let item of tempFoods) { - let resList = captureRegion.FindMulti(foodsData[item].ro); + if (recordDebug) { + log.info(`[调试] ${npc.name} 购买判断结果:`); + log.info(`[调试] 1天商品: ${foodsToBuy["1d"].join(", ")}`); + log.info(`[调试] 3天商品: ${foodsToBuy["3d"].join(", ")}`); + log.info(`[调试] 7天商品: ${foodsToBuy["7d"].join(", ")}`); + } - for (let res of resList) { - log.info("找到物品: {i} 位置({x},{y},{h},{w})", foodsData[item].name, res.x, res.y, res.width, res.height); - // 移除已购买的物品 - boughtFoods.add(item); - // 点击商品 - click(res.x * 2 + res.width, res.y * 2 + res.height); - if (await qucikBuy()) { + // 合并所有要购买的食物 + const allFoodsToBuy = []; + if (foodsToBuy["1d"]) allFoodsToBuy.push(...foodsToBuy["1d"]); + if (foodsToBuy["3d"]) allFoodsToBuy.push(...foodsToBuy["3d"]); + if (foodsToBuy["7d"]) allFoodsToBuy.push(...foodsToBuy["7d"]); - log.info("购买成功: {item}", foodsData[item].name); - // 交互或拾取:"XXXX" - await fakeLog(foodsData[item].name, false, false, 9527); - await sleep(2000); - // 重新截图 - captureRegion = captureGameRegion(); - } - else { - log.info("购买失败: {item}, 背包已经满或商品已售罄", foodsData[item].name); - } - } - } + if (allFoodsToBuy.length === 0) { + logConditional(`${npc.name} 没有需要购买的商品`); + return { + purchased: [], + "1d": [], + "3d": [], + "7d": [] + }; + } - captureRegion.dispose(); - // 从已购买物品中移除 - tempFoods = tempFoods.filter(item => !boughtFoods.has(item)); + logConditional(`${npc.name} 购买列表: ${allFoodsToBuy.join(", ")}`); + let tempFoods = [...allFoodsToBuy]; + const purchasedFoods = []; + const purchasedByType = { + "1d": [], + "3d": [], + "7d": [] + }; - // 若不是最后一页且还有未购买的物品 - if (tempFoods.length > 0 && i !== npcData[npcName].page - 1) { - log.info("切换到下一页商品"); - await nextFoodsPage(); + // 构建商品到刷新类型的映射 + const foodToRefreshType = {}; + for (const type of ["1d", "3d", "7d"]) { + if (foodsToBuy[type]) { + for (const food of foodsToBuy[type]) { + foodToRefreshType[food] = type; + } + } + } - // 最后一次切换界面, 等待UI回弹 - if (i === npcData[npcName].page - 2) { - log.info("等待界面回弹"); - await sleep(500); - } - } - } + // 多页购买 + for (let i = 0; i < npc.page; i++) { + await sleep(520); + // 获取一张截图 + let captureRegion = captureGameRegion(); + + // 记录已经购买的物品 + let boughtFoods = new Set([]); + + // 匹配商品 + for (let item of tempFoods) { + if (recordDebug) { + log.info(`[调试] 尝试购买: ${item}`); + } + + // 将中文食材名转换为对应的英文ID + let foodId = null; + + // 首先在translationList中查找(中文名->英文ID) + if (translationList[item]) { + foodId = translationList[item]; + } else { + // 如果没有找到,直接在foodsData中查找是否有中文键 + foodId = Object.keys(foodsData).find(key => + foodsData[key].name === item || foodsData[key].id === item + ); + } + + if (!foodId) { + log.warn(`未找到食材 "${item}" 的识别数据,跳过`); + continue; + } + + if (!foodsData[foodId] || !foodsData[foodId].ro) { + log.warn(`食材 "${item}" (ID: ${foodId}) 未启用或没有识别对象,跳过`); + continue; + } + + let resList = captureRegion.FindMulti(foodsData[foodId].ro); + + for (let res of resList) { + if (recordDebug) { + log.info(`[调试] 找到物品: ${foodsData[foodId].name} 位置(${res.x},${res.y},${res.width},${res.height})`); + } + // 移除已购买的物品 + boughtFoods.add(item); + // 点击商品 + click(res.x * 2 + res.width, res.y * 2 + res.height); + if (await qucikBuy()) { + log.info(`购买成功: ${foodsData[foodId].name}`); + // 交互或拾取:"XXXX" + await fakeLog(foodsData[foodId].name, false, false, 23333); + + // 记录购买的商品 + purchasedFoods.push(item); + const refreshType = foodToRefreshType[item]; + if (refreshType) { + purchasedByType[refreshType].push(item); + + // 立即更新记录 + npcRecords = updateNpcRecord(npcRecords, npc.name, refreshType, purchasedByType[refreshType]); + await saveNpcRecords(npcRecords); + } + + await sleep(2000); + // 重新截图 + captureRegion = captureGameRegion(); + } + else { + log.info(`购买失败: ${foodsData[foodId].name}, 背包已经满或商品已售罄`); + } + } + } + + captureRegion.dispose(); + // 从已购买物品中移除 + tempFoods = tempFoods.filter(item => !boughtFoods.has(item)); + + // 若不是最后一页且还有未购买的物品 + if (tempFoods.length > 0 && i !== npc.page - 1) { + logConditional("切换到下一页商品"); + await nextFoodsPage(); + + // 最后一次切换界面, 等待UI回弹 + if (i === npc.page - 2) { + logConditional("等待界面回弹"); + await sleep(520); + } + } + } + + if (purchasedFoods.length > 0) { + log.info(`${npc.name} 购买完成,成功购买: ${purchasedFoods.join(", ")}`); + } else { + logConditional(`${npc.name} 没有成功购买任何商品`); + } + + // 返回购买结果 + return { + purchased: purchasedFoods, + "1d": purchasedByType["1d"], + "3d": purchasedByType["3d"], + "7d": purchasedByType["7d"] + }; } -// 初始化NPC商品 -async function initNpcData() { - // 获取游戏内时间(考虑4点刷新) - const gameTime = getGameTime(); - const gameDay = gameTime.getDay(); // 游戏内的星期几(0-6) +// 修改后的初始化NPC商品 +async function initNpcData(records) { + for (let [key, npc] of Object.entries(npcData)) { + // 检查是否在禁用列表中 + if (disabledNpcs.includes(npc.name)) { + npc.enable = false; + logConditional(`已禁用NPC: ${npc.name}`); + continue; + } - // log.info(`游戏内时间: ${gameTime}, 星期: ${gameDay}, 用户选择的购买日: ${AFKDay}`); + const npcRecord = getNpcRecord(records, npc.name); - for (let [key, npc] of Object.entries(npcData)) { + // 判断是否需要强制刷新 + const forceRefresh = ignoreRecords; - // 翻译物品名称 - let npcFoods = new Set([]); + // 判断需要购买的商品(这里只是检查是否有商品需要购买) + const gameTime = getGameTime(); + const currentPeriod = getBasePeriod(gameTime); + const foodsToBuy = shouldBuyFoods(npc, npcRecord, currentPeriod, forceRefresh); - // 添加每天刷新周期的商品(如果存在) - if (npc._1d_foods && npc._1d_foods.length > 0) { - npc._1d_foods.forEach(item => { - npcFoods.add(translationList[item]); - }); - } + // 检查是否有需要购买的商品 + const hasFoodsToBuy = foodsToBuy["1d"].length > 0 || + foodsToBuy["3d"].length > 0 || + foodsToBuy["7d"].length > 0; - // ==================== 检查是否是刷新日 ==================== - if (isRefreshDay()) { - // 添加3天刷新周期的商品(如果存在) - if (npc._3d_foods && npc._3d_foods.length > 0) { - npc._3d_foods.forEach(item => { - npcFoods.add(translationList[item]); - }); - } - } + npc.enable = npc.enable && hasFoodsToBuy; - // ==================== 检查是否是用户选择的购买日 ==================== - if (gameDay === AFKDay) { - // 添加7天刷新周期的商品(如果存在) - if (npc._7d_foods && npc._7d_foods.length > 0) { - npc._7d_foods.forEach(item => { - npcFoods.add(translationList[item]); - }); - } - } - - // 筛选已启用的商品 - npc.enableFoods = [...enableFoods].filter(item => npcFoods.has(item)); - - // 如果没有启用的商品, 则不启用该NPC - if (npc.enableFoods.length === 0) { - npc.enable = false; - } - } + if (recordDebug && !npc.enable && hasFoodsToBuy) { + log.info(`${npc.name} 有商品需要购买但NPC被禁用`); + } + } } // 加载识别对象 async function initRo() { - try { - // 加载识别对象 - for (let [key, item] of Object.entries(foodsData)) { - // 填充中英文对照表 - translationList[item.name] = item.id; - // 判断启动商品、加载识别对象 - if (settings[item.id]) { - enableFoods.add(item.id); - item.ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync(item.file)); - item.ro.Threshold = 0.75; - item.ro.Use3Channels = true; - } - } - // 加载其他识别对象 - for (let [key, item] of Object.entries(othrtRo)) { - item.ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync(item.file)); - item.ro.Threshold = 0.85; - } - return true; - } - catch (error) { - log.error("加载识别对象时发生错误: {error}", error.message); - throw error; - } + try { + // 加载识别对象 + for (let [key, item] of Object.entries(foodsData)) { + // 填充中英文对照表 + translationList[item.name] = item.id; + // 判断启动商品、加载识别对象 + if (settings[item.id]) { + enableFoods.add(item.id); + item.ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync(item.file)); + item.ro.Threshold = 0.75; + item.ro.Use3Channels = true; + logConditional(`已启用食材: ${item.name} (${item.id})`); + } + } + // 加载其他识别对象 + for (let [key, item] of Object.entries(othrtRo)) { + item.ro = RecognitionObject.TemplateMatch(file.ReadImageMatSync(item.file)); + item.ro.Threshold = 0.85; + } + + logConditional(`总共启用了 ${enableFoods.size} 种食材`); + return true; + } + catch (error) { + log.error("加载识别对象时发生错误: {error}", error.message); + throw error; + } } (async function () { + try { + // ==================== 初始化账号 ==================== + log.info(`当前账户: ${userName}`); - try { - // ==================== 初始化识别对象 ==================== - await initRo(); - log.info("识别对象初始化完成"); + // ==================== 加载外部数据 ==================== + if (!await loadExternalData()) { + log.error("食材或NPC数据加载失败,脚本终止"); + return; + } - // ==================== 初始化NPC数据 ==================== - await initNpcData(); - log.info("NPC数据初始化完成"); + // ==================== 初始化识别对象 ==================== + await initRo(); + + logConditional("识别对象初始化完成"); + // ==================== 加载NPC购买记录 ==================== + let npcRecords = await loadNpcRecords(); + + logConditional(`已加载 ${npcRecords.length} 个NPC的购买记录`); + + if (recordDebug && npcRecords.length > 0) { + log.info("[调试] 当前NPC记录:"); + npcRecords.forEach(record => { + log.info(`[调试] ${record.npcname}:`); + if (record["1d_time"]) log.info(`[调试] 1天刷新: ${record["1d_time"]}`); + if (record["3d_time"]) log.info(`[调试] 3天刷新: ${record["3d_time"]}`); + if (record["7d_time"]) log.info(`[调试] 7天刷新: ${record["7d_time"]}`); + }); + } - // ==================== 自动购买 ==================== - for (let [key, npc] of Object.entries(npcData)) { - if (npc.enable) { - await genshin.returnMainUi(); - log.info("开始购买NPC: {npcName}", npc.name); - // 地图追踪开始 - await fakeLog(npc.name, false, true, 0); - // 设置游戏时间 - if (npc.time === "night") { - await setTime(20, 0); // 设置为晚上8点 - } - else if (npc.time === "day") { - await setTime(8, 0); // 设置为早上8点 - } - await autoPath(npc.path); - await spikChat(npc.name); - await buyFoods(key); - // 返回主界面 - await genshin.returnMainUi(); - log.info("完成购买NPC: {npcName}", npc.name); - // 偽造日志任務結東 - await fakeLog(npc.name, false, false, 0); - } - else { - log.info("跳过未启用的NPC: {npcName}", npc.name); - } - } - } catch (error) { - log.error(`执行时时发生错误`); - log.error(error.message); - } + // ==================== 初始化NPC数据 ==================== + await initNpcData(npcRecords); + + logConditional("NPC数据初始化完成"); + + // 统计启用的NPC数量 + const enabledNpcs = Object.values(npcData).filter(npc => npc.enable); + log.info(`本次执行将处理 ${enabledNpcs.length} 个NPC`); + + // ==================== 自动购买 ==================== + // 获取当前时间和周期 + const gameTime = getGameTime(); + const currentPeriod = getBasePeriod(gameTime); + + if (recordDebug) { + log.info(`[调试] 当前游戏时间: ${formatDateToLocalISO(gameTime)}`); + log.info(`[调试] 当前周期信息: 3天周期=${currentPeriod.threeDayPeriod}, 7天周期=${currentPeriod.sevenDayPeriod}`); + } + + let npcIndex = 0; + for (let [key, npc] of Object.entries(npcData)) { + if (npc.enable) { + npcIndex++; + log.info(`当前进度:${npcIndex}/${enabledNpcs.length}`); + log.info(`开始前往NPC ${npc.name} 购买`); + + await genshin.returnMainUi(); + + // 地图追踪开始 + await fakeLog(npc.name, false, true, 0); + + // 设置游戏时间 + if (npc.time === "night") { + await setTime(20, 0); // 设置为晚上8点 + } + else if (npc.time === "day") { + await setTime(8, 0); // 设置为早上8点 + } + + await autoPath(npc.path); + await spikChat(npc.name); + + // 购买商品,传入当前记录和周期 + const purchaseResult = await buyFoods(key, npcRecords, currentPeriod); + + // 返回主界面 + await genshin.returnMainUi(); + log.info(`完成购买NPC: ${npc.name}`); + + // 伪造日志任务结束 + await fakeLog(npc.name, false, false, 0); + + // NPC之间等待 + if (npcIndex < enabledNpcs.length) { + logConditional("等待2秒后处理下一个NPC"); + await sleep(2000); + } + } + else { + if (recordDebug) { + log.info(`[调试] 跳过未启用的NPC: ${npc.name}`); + } + } + } + + log.info("=== 食材购买脚本执行完成 ==="); + + } catch (error) { + log.error(`执行时发生错误: ${error.message}`); + } })(); \ No newline at end of file diff --git a/repo/js/自动购买每天&3天&每周刷新食材/manifest.json b/repo/js/自动购买每天&3天&每周刷新食材/manifest.json index 02eb67c5b..5189b8808 100644 --- a/repo/js/自动购买每天&3天&每周刷新食材/manifest.json +++ b/repo/js/自动购买每天&3天&每周刷新食材/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "自动购买每天&3天&每周刷新食材", - "version": "1.3", + "version": "2.0.0", "description": "自动购买每天&3天&每周刷新食材\n每天刷新食材:自动购买食材\n3天刷新食材:未到刷新日不购买该食材\n每周刷新食材:可指定每周购买食材", "authors": [ { @@ -13,6 +13,10 @@ "购买食材", "模拟点击" ], + "saved_files": [ + "record/" + ], "settings_ui": "settings.json", "main": "main.js" -} \ No newline at end of file + +} diff --git a/repo/js/自动购买每天&3天&每周刷新食材/settings.json b/repo/js/自动购买每天&3天&每周刷新食材/settings.json index efad8eb2b..ff04c0f50 100644 --- a/repo/js/自动购买每天&3天&每周刷新食材/settings.json +++ b/repo/js/自动购买每天&3天&每周刷新食材/settings.json @@ -1,201 +1,226 @@ [ + { + "name": "userName", + "type": "input-text", + "label": "账号名(用于区分不同账户的记录)", + "default": "默认账户" + }, + { + "name": "ignoreRecords", + "type": "checkbox", + "label": "-----------------\n无视记录强制购买(不推荐)", + "default": false + }, + { + "name": "recordDebug", + "type": "checkbox", + "label": "记录调试模式(显示详细日志)", + "default": false + }, + { + "name": "disabledNpcs", + "type": "input-text", + "label": "禁用 NPC\n(多個NPC以空格隔)", + "default": "阿扎莱 皮托" + }, { "name": "圣水", "type": "checkbox", "label": "每天刷新食材\n\n圣水", - "default": true + "default": false }, { "name": "crab", "type": "checkbox", "label": "螃蟹", - "default": true + "default": false }, { "name": "salt", "type": "checkbox", "label": "盐", - "default": true + "default": false }, { "name": "pepper", "type": "checkbox", "label": "胡椒", - "default": true + "default": false }, { "name": "onion", "type": "checkbox", "label": "洋葱", - "default": true + "default": false }, { "name": "milk", "type": "checkbox", "label": "牛奶", - "default": true + "default": false }, { "name": "tomato", "type": "checkbox", "label": "番茄", - "default": true + "default": false }, { "name": "potato", "type": "checkbox", "label": "土豆", - "default": true + "default": false }, { "name": "wheat", "type": "checkbox", "label": "小麦", - "default": true + "default": false + }, + { + "name": "rice", + "type": "checkbox", + "label": "稻米", + "default": false }, - // { - // "name": "rice", - // "type": "checkbox", - // "label": "稻米", - // "default": true - // }, { "name": "shrimp", "type": "checkbox", "label": "虾仁", - "default": true + "default": false }, { "name": "almond", "type": "checkbox", "label": "杏仁", - "default": true + "default": false + }, + { + "name": "cabbage", + "type": "checkbox", + "label": "卷心菜", + "default": false + }, + { + "name": "tofu", + "type": "checkbox", + "label": "豆腐", + "default": false }, - // { - // "name": "cabbage", - // "type": "checkbox", - // "label": "卷心菜", - // "default": true - // }, - // { - // "name": "tofu", - // "type": "checkbox", - // "label": "豆腐", - // "default": true - // }, { "name": "fish", "type": "checkbox", "label": "鱼肉", - "default": true + "default": false }, { "name": "coffeeBeans", "type": "checkbox", "label": "咖啡豆", - "default": true + "default": false + }, + { + "name": "glabrousBeans", + "type": "checkbox", + "label": "秃秃豆", + "default": false }, - // { - // "name": "glabrousBeans", - // "type": "checkbox", - // "label": "秃秃豆", - // "default": true - // }, { "name": "rawMeat", "type": "checkbox", "label": "兽肉", - "default": true + "default": false }, { "name": "fermentedJuice", "type": "checkbox", "label": "发酵果实汁", - "default": true + "default": false }, { "name": "黑麦", "type": "checkbox", "label": "黑麦", - "default": true + "default": false }, { "name": "松茸", "type": "checkbox", "label": "-----------------\n3天刷新食材\n\n松茸", - "default": true + "default": false }, { "name": "huMengbu", "type": "checkbox", - "label": "胡梦卜", - "default": true + "label": "胡萝卜", + "default": false }, { "name": "沉玉仙茗", "type": "checkbox", "label": "沉玉仙茗", - "default": true + "default": false }, { "name": "清心", "type": "checkbox", "label": "清心", - "default": true + "default": false }, { "name": "琉璃袋", "type": "checkbox", "label": "琉璃袋", - "default": true + "default": false }, { "name": "viola", "type": "checkbox", "label": "堇瓜", - "default": true + "default": false }, { "name": "Padisarah", "type": "checkbox", "label": "帕蒂沙兰", - "default": true + "default": false }, { "name": "romaritimeFlower", "type": "checkbox", "label": "海露花", - "default": true + "default": false }, { "name": "tidalga", "type": "checkbox", "label": "汐藻", - "default": true + "default": false }, { "name": "苦种", "type": "checkbox", "label": "苦种", - "default": true + "default": false }, { "name": "青蜜梅", "type": "checkbox", "label": "青蜜梅", - "default": true + "default": false }, { "name": "絶云椒椒", "type": "checkbox", "label": "絶云椒椒", - "default": true + "default": false }, { "name": "AKF", "type": "select", - "label": "-----------------\n每週一刷新食材\n\n可选週几買每週食材", + "label": "-----------------\n每周刷新食材\n\n可选购买方式:\n0=跟随系统周期自动判定\n1-7=指定星期几购买(1=周一,7=周日)", "options": [ + "0", "1", "2", "3", @@ -204,12 +229,12 @@ "6", "7" ], - "default": "2" + "default": "0" }, { "name": "蟹黃", "type": "checkbox", "label": "蟹黃", - "default": true + "default": false } ] \ No newline at end of file