Compare commits

..

15 Commits

Author SHA1 Message Date
status102
1a30f9a7dd perf: 额外增加等待时的update_deployment前检查 2026-05-12 19:26:23 +08:00
status102
61345d8126 feat: 自动战斗剧情遇到剧情无法继续时, 回退到执行作业步骤 2026-05-12 19:25:49 +08:00
status102
07e01367e7 rft: 自动战斗暂停按钮状态区分 2026-05-12 19:22:30 +08:00
status102
b9274e1904 perf: Wpf 新配置修改日志记录等级提升至 Info 2026-05-12 11:38:57 +08:00
status102
9dcfeb28fd rft: 自动战斗拆出导航 2026-05-12 11:38:36 +08:00
uye
e21a6630f4 Release v.6.9.4 (#16554)
PV minigame rerun.

cc @Manicsteiner @HX3N

## Summary by Sourcery

调整主线关卡难度后缀的处理方式,提高窗口/任务处理与日志记录的健壮性,并使文档、资源与本地化行为与 v6.9.4 的新特性保持一致。

New Features:
- 支持按章节感知的难度映射:使 `-NORMAL` / `-HARD` 后缀在第 10–14 章映射到 Standard/Adverse,在第
15 章及之后映射到 Normal/Raid,并在关卡前/后根据需要切换难度。
- 一旦配置完成后,总是启用集成策略中的 JieGarden 铜币兑换行为,而不再受投资模式限制。

Bug Fixes:
- 防止在 WPF 调度器开始关闭之后仍尝试显示或激活窗口,从而避免运行时异常。
- 限制战斗助手技能就绪检查的频率,避免因检查过于频繁被误判为触发限频,同时保证就绪日志记录的准确性。
- 在删除多余调试图片时,对文件系统错误进行优雅处理,而不是静默失败或抛出异常。
- 确保问题报告归档文件生成在持久化的报告目录下。
- 在通过远程控制启动任务时记录任务开始时间,以保持日志与追踪信息的一致性。
- 修复日志记录器作用域处理方式,使作用域在创建日志流时注入,而不是在各个不同严重级别的辅助方法中注入。
- 使用 Attach Window 时避免传递账号名,以匹配当前支持的客户端类型。

Enhancements:
- 优化关卡导航逻辑,通过章节号解析难度后缀,并可选在关卡选定后再切换难度。
- 将“公告顽固点击”恶搞成就的解锁推迟到第三个发布阶段,并略微提高“Lucky”成就的随机触发概率。
- 明确和强化 MAA 问题日志分析的内部规范,特别是有状态 UI 自动化和接待线索流程相关内容。
- 改进 Bark/AppImage 品牌呈现,切换到新版 v2 徽标图标资源。

Build:
- 更新 CI 中的 AppImage 打包配置,以下载新的 v2 徽标图标路径。

CI:
- 调整 CI 工作流中的资源路径,以适配更新后的品牌资源。

Documentation:
- 在手册和集成协议中,用所有支持的语言记录基于章节的 `-NORMAL` / `-HARD` 后缀映射规则。
- 从多语言集成策略 schema 文档中移除过时的 JieGarden 铜币兑换启用条件说明,并刷新相关术语。
- 扩展内部问题分析文档,补充有状态 UI 自动化与接待线索的必读资料和知识库。

Chores:
- 为第 17 章的困难关卡添加格子位置信息,并刷新关卡/任务/资源/版本元数据,以支持 v6.9.4 内容。
- 更新本地化资源和外部通知设置 UI,使其与新行为和图标 URL 保持一致。
- 添加内部工具和助手使用的上下文 JSON 及知识文件。

<details>
<summary>Original summary in English</summary>

## Summary by Sourcery

Adjust main story difficulty suffix handling, improve robustness of
window/task handling and logging, and align documentation, resources,
and localization with new behaviors for v6.9.4.

New Features:
- Support chapter-aware difficulty mapping so -NORMAL/-HARD suffixes
route to Standard/Adverse in chapters 10–14 and Normal/Raid from chapter
15 onward, with pre/post stage difficulty switching as needed.
- Always enable JieGarden copper exchange behavior once configured,
regardless of investment mode.

Bug Fixes:
- Prevent WPF windows from being shown or activated after the dispatcher
has begun shutdown, avoiding runtime exceptions.
- Throttle battle helper skill readiness checks to avoid misclassifying
frequent checks as rate-limited while keeping readiness logging correct.
- Handle filesystem errors gracefully when deleting excess debug images
instead of silently failing or throwing.
- Ensure issue report archives are generated under the persistent
reports directory.
- Record task start time when launching tasks via remote control to keep
logs and traces consistent.
- Fix logger scope handling so scopes are injected at stream creation
instead of in individual severity helpers.
- Avoid passing account names when using Attach Window, matching
supported client types.

Enhancements:
- Refine stage navigation to interpret difficulty suffixes by chapter
number and optionally switch difficulty after stage selection.
- Delay unlocking of the "announcement stubborn click" humorous
achievement to the third release phase and slightly increase the random
trigger rate of the "Lucky" achievement.
- Clarify and strengthen internal guidelines for MAA issue log analysis,
especially for stateful UI automation and reception clue flows.
- Improve Bark/AppImage branding by switching to updated v2 logo icon
assets.

Build:
- Update CI AppImage packaging to download the new v2 logo icon path.

CI:
- Tweak CI workflow resource paths for updated branding assets.

Documentation:
- Document the new chapter-based mapping of -NORMAL/-HARD suffixes
across all supported languages in manuals and integration protocols.
- Remove outdated enable-condition notes for JieGarden copper exchange
from multilingual integrated strategy schema docs and refresh related
terminology.
- Expand internal issue-analysis documentation with required reading and
knowledge base for stateful UI automation and reception clues.

Chores:
- Add tile position data for Chapter 17 hard stages and refresh
stage/task/resource/version metadata to support v6.9.4 content.
- Update localization resources and external notification settings UI to
match new behaviors and icon URLs.
- Add contextual JSON and knowledge files used by internal tooling and
assistants.

</details>

Bug Fixes(缺陷修复):
- 防止在 Dispatcher 已关闭或窗口正在关闭期间仍尝试显示或激活 WPF 窗口,以避免运行时异常。
- 避免战斗助手中过于频繁的技能就绪检查导致误记为限流,并确保日志消息记录正确。
- 在删除多余调试图片时优雅处理文件系统错误,而不是静默失败。
- 确保问题上报时生成报告使用持久化的报告目录来存放临时压缩包。
- 通过远程控制启动任务时记录任务开始时间,以保持日志与追踪信息准确。

Enhancements(功能增强):
- 优化主线关卡难度选择逻辑,使 NORMAL/HARD 后缀映射到章节特定的难度模式(第 10–14 章为
Standard/Adverse,第 15 章及之后为 Normal/Raid),并根据需要在关卡选择前或后切换难度。
- 简化肉鸽模式中结园铜钱兑换行为,移除仅在“投资模式”下启用的条件,使其在配置开启后始终可用。
- 将“公告点不动”类幽默成就的解锁条件延后到第三阶段发售,以优化节奏。

Documentation(文档):
- 在多语言说明书和集成协议文档中澄清 `-NORMAL` 与 `-HARD`
后缀在不同章节区间对应到哪些具体难度模式,并移除关于结园铜钱兑换启用条件的过时说明。
- 刷新本地化 UI 资源和文档字符串,使其与新行为和术语在所有支持语言中保持一致。

Chores(杂项):
- 为第 17 章困难关卡新增地块坐标数据,并更新若干资源和版本元数据文件,以支持 v6.9.4 内容。

<details>
<summary>Original summary in English</summary>

## Summary by Sourcery

调整主线关卡难度后缀的处理方式,提高窗口/任务处理与日志记录的健壮性,并使文档、资源与本地化行为与 v6.9.4 的新特性保持一致。

New Features:
- 支持按章节感知的难度映射:使 `-NORMAL` / `-HARD` 后缀在第 10–14 章映射到 Standard/Adverse,在第
15 章及之后映射到 Normal/Raid,并在关卡前/后根据需要切换难度。
- 一旦配置完成后,总是启用集成策略中的 JieGarden 铜币兑换行为,而不再受投资模式限制。

Bug Fixes:
- 防止在 WPF 调度器开始关闭之后仍尝试显示或激活窗口,从而避免运行时异常。
- 限制战斗助手技能就绪检查的频率,避免因检查过于频繁被误判为触发限频,同时保证就绪日志记录的准确性。
- 在删除多余调试图片时,对文件系统错误进行优雅处理,而不是静默失败或抛出异常。
- 确保问题报告归档文件生成在持久化的报告目录下。
- 在通过远程控制启动任务时记录任务开始时间,以保持日志与追踪信息的一致性。
- 修复日志记录器作用域处理方式,使作用域在创建日志流时注入,而不是在各个不同严重级别的辅助方法中注入。
- 使用 Attach Window 时避免传递账号名,以匹配当前支持的客户端类型。

Enhancements:
- 优化关卡导航逻辑,通过章节号解析难度后缀,并可选在关卡选定后再切换难度。
- 将“公告顽固点击”恶搞成就的解锁推迟到第三个发布阶段,并略微提高“Lucky”成就的随机触发概率。
- 明确和强化 MAA 问题日志分析的内部规范,特别是有状态 UI 自动化和接待线索流程相关内容。
- 改进 Bark/AppImage 品牌呈现,切换到新版 v2 徽标图标资源。

Build:
- 更新 CI 中的 AppImage 打包配置,以下载新的 v2 徽标图标路径。

CI:
- 调整 CI 工作流中的资源路径,以适配更新后的品牌资源。

Documentation:
- 在手册和集成协议中,用所有支持的语言记录基于章节的 `-NORMAL` / `-HARD` 后缀映射规则。
- 从多语言集成策略 schema 文档中移除过时的 JieGarden 铜币兑换启用条件说明,并刷新相关术语。
- 扩展内部问题分析文档,补充有状态 UI 自动化与接待线索的必读资料和知识库。

Chores:
- 为第 17 章的困难关卡添加格子位置信息,并刷新关卡/任务/资源/版本元数据,以支持 v6.9.4 内容。
- 更新本地化资源和外部通知设置 UI,使其与新行为和图标 URL 保持一致。
- 添加内部工具和助手使用的上下文 JSON 及知识文件。

<details>
<summary>Original summary in English</summary>

## Summary by Sourcery

Adjust main story difficulty suffix handling, improve robustness of
window/task handling and logging, and align documentation, resources,
and localization with new behaviors for v6.9.4.

New Features:
- Support chapter-aware difficulty mapping so -NORMAL/-HARD suffixes
route to Standard/Adverse in chapters 10–14 and Normal/Raid from chapter
15 onward, with pre/post stage difficulty switching as needed.
- Always enable JieGarden copper exchange behavior once configured,
regardless of investment mode.

Bug Fixes:
- Prevent WPF windows from being shown or activated after the dispatcher
has begun shutdown, avoiding runtime exceptions.
- Throttle battle helper skill readiness checks to avoid misclassifying
frequent checks as rate-limited while keeping readiness logging correct.
- Handle filesystem errors gracefully when deleting excess debug images
instead of silently failing or throwing.
- Ensure issue report archives are generated under the persistent
reports directory.
- Record task start time when launching tasks via remote control to keep
logs and traces consistent.
- Fix logger scope handling so scopes are injected at stream creation
instead of in individual severity helpers.
- Avoid passing account names when using Attach Window, matching
supported client types.

Enhancements:
- Refine stage navigation to interpret difficulty suffixes by chapter
number and optionally switch difficulty after stage selection.
- Delay unlocking of the "announcement stubborn click" humorous
achievement to the third release phase and slightly increase the random
trigger rate of the "Lucky" achievement.
- Clarify and strengthen internal guidelines for MAA issue log analysis,
especially for stateful UI automation and reception clue flows.
- Improve Bark/AppImage branding by switching to updated v2 logo icon
assets.

Build:
- Update CI AppImage packaging to download the new v2 logo icon path.

CI:
- Tweak CI workflow resource paths for updated branding assets.

Documentation:
- Document the new chapter-based mapping of -NORMAL/-HARD suffixes
across all supported languages in manuals and integration protocols.
- Remove outdated enable-condition notes for JieGarden copper exchange
from multilingual integrated strategy schema docs and refresh related
terminology.
- Expand internal issue-analysis documentation with required reading and
knowledge base for stateful UI automation and reception clues.

Chores:
- Add tile position data for Chapter 17 hard stages and refresh
stage/task/resource/version metadata to support v6.9.4 content.
- Update localization resources and external notification settings UI to
match new behaviors and icon URLs.
- Add contextual JSON and knowledge files used by internal tooling and
assistants.

</details>

</details>
2026-05-12 03:21:25 +08:00
uye
fccaf06d6d docs: Update CHANGELOG for version 6.9.4
Updated changelog for version 6.9.4 with new features, improvements, fixes, and documentation updates.
2026-05-12 03:00:30 +08:00
github-actions[bot]
c99f05fbd9 feat: Update Submodules MAAUnified, MaaMacGui, maa-cli
https://github.com/MaaAssistantArknights/MaaAssistantArknights/actions/runs/25690745565
[skip changelog]
2026-05-11 18:56:45 +00:00
HY
4ed401f1f4 chore: 繁中服「快速放入線索」與「一鍵贈送重複線索」 (#16562) 2026-05-12 02:55:28 +08:00
uye
c9c8e9751d chore: Lucky 的概率改为 0.0799% 2026-05-12 02:36:34 +08:00
uye
6119232486 chore: 使用 PC 端时不传账号 2026-05-12 01:57:45 +08:00
uye
c9085e7d23 ai: 增加 issue 分析知识库 2026-05-11 21:59:31 +08:00
HY
5814f1a6ca fix: 調整繁中服部分幹員名稱 OCR (#16561) 2026-05-11 21:28:56 +08:00
Constrat
c59397b377 fix: Notification icon 2026-05-11 14:43:56 +02:00
Constrat
cccbef1637 ci: fix icon post design structure change 2026-05-11 14:38:19 +02:00
18 changed files with 194 additions and 52 deletions

View File

@@ -0,0 +1,29 @@
# MAA Issue Log Analysis Knowledge Base
## Stateful UI Automation Checks
- 分析 issue 时,先区分三层东西,不要混为一谈:
- 游戏规则
- MAA 当前自动化流程
- 用户对最终状态的预期
- 遇到“一键/快捷/批量”按钮时,先看资源任务和日志里的真实控制路径,不要只看现象。
- 对状态型 UI重点核对三件事
- 前置条件是什么
- 流程中哪些状态会被临时改写
- 结束条件满足后应停在哪个状态
## Reception Clue Analysis
- 会客室线索问题先对照当前资源任务和日志,不要只凭体感下结论。
- 取下线索 -> 赠送重复线索 -> 当前线索数量够开启线索交流时才统一放置,这是 by design。
- 因此,“送完重复线索后线索板暂时为空”或“用户自己放的线索被统一取下”本身不能直接判成 bug。
- 真正需要继续确认的是:
- 日志里的控制路径是否和资源任务定义一致
- 明明已经满足开启线索交流的条件,却没有触发统一放置
- 流程是否停在了不该停的位置,或提前退出
## Guardrails For Future Analysis
- 不要把维护者评论、机器人评论、或单张截图当成最终结论;必须回到日志和代码确认状态是怎么变化的。
- 对状态型 UI先回答“日志里的行为是否符合设计”再回答“这个设计是否符合用户预期”。
- 不要只看最终现象;要结合配置、`gui.log``asst.log`、资源任务和当前代码一起判断。

View File

@@ -5,6 +5,11 @@ description: 分析 MaaAssistantArknights 上游仓库公开 Issue`https://gi
# MAA Issue Log Analysis
## Required Reading
- 开始分析前,先读取同目录的 `KNOWLEDGE.md`,先用其中的通用误判规则校正自己的分析路径,再读 issue 和日志。
- 如果 issue 涉及会客室、线索、快捷按钮、批量按钮、自动领取/赠送/放置这类“会先改变界面状态再继续执行”的流程,必须先套用 `KNOWLEDGE.md` 中的 `Stateful UI Automation Checks``Reception Clue Analysis`
## Scope
- 仅用于上游公开仓库 `https://github.com/MaaAssistantArknights/MaaAssistantArknights`
@@ -25,6 +30,7 @@ description: 分析 MaaAssistantArknights 上游仓库公开 Issue`https://gi
- 读取正文和评论。
- 提取这些信息UI/Core/Resource 版本、资源时间、模拟器类型、分辨率、截图增强、GPU 推理、任务名、关卡名、是否有 `-hard`、用户现象、复现步骤、维护者或机器人评论。
- 不要把评论结论当成唯一证据;仍要用日志和代码自行验证。
- 如果 issue 文本或评论里已经有人下了“这是游戏设计 / 不是 bug / 本来就这样”的结论,先暂存,不要直接复述成最终判断;先核对日志、资源任务和当前代码是否真的支持这个结论。
3. 提取报告附件。
@@ -60,6 +66,10 @@ description: 分析 MaaAssistantArknights 上游仓库公开 Issue`https://gi
- 先在 `gui.log` 确认 `AttachWindow: Found window`
- 再在 `asst.log` 里看 `Win32Controller::screencap``Win32Controller::click`
- 不要再按 ADB 端口或 `ConnectionInfo.ConnectFailed` 的思路分析
- 如果问题属于状态型 UI 自动化(例如会客室线索、批量按钮、快捷按钮、先拆后放一类流程),时间线里必须单独标出:
- 自动化在什么时刻先修改了用户原状态
- 后续进入下一步或恢复终态由哪个条件控制
- 条件不满足时流程是停止、跳过,还是按设计停在别的状态
6. 区分 issue 当时环境和当前分支。
@@ -245,6 +255,12 @@ description: 分析 MaaAssistantArknights 上游仓库公开 Issue`https://gi
- 摘几十行足够支撑结论的片段即可。
- 不要把整份日志倾倒进回复。
8. 对状态型 UI 问题,结论前先做一次“设计一致性检查”。
- 先判断日志中的状态变化是否符合游戏规则、资源任务定义和当前实现。
- 如果流程与设计一致,不要把用户不喜欢的中间状态直接归为 bug。
- 只有当日志、资源任务和代码彼此冲突,或流程没有达到设计要求的终态时,再归类为实现缺陷。
## Common Patterns
- `gui.log` 只显示“连接失败”,但 `asst.log` 里已经给出 `adb devices``adb connect`、端口轮询和 `ConnectionInfo`。连接类问题必须以 `asst.log` 为准。
@@ -254,6 +270,8 @@ description: 分析 MaaAssistantArknights 上游仓库公开 Issue`https://gi
- `part02` 可以是空包,也可以只包含图片;不要因为没有文本日志就把它判成“无用分卷”。
- issue 机器人评论“日志没有上传成功”时,不要自动当真;先验证正文附件是否仍可下载。
- 如果 `gui.log` 说“任务出错”,但对应 `taskid``asst.log` 实际 `AllTasksCompleted`,要明确写“本次日志未复现用户描述的问题”。
- 对会客室 / 线索 issue如果 `asst.log` 里出现 `InfrastClueQuickInsert``remove_clue``SendClues``InfrastClueQuickSendDuplicates`,先对照资源任务判断这是不是当前设计流程,不要只看线索板中途是否为空。
- 如果线索流程里出现“取下线索 -> 赠送重复线索 -> 条件满足后统一放置”,默认先按 by design 处理;只有当日志显示本应统一放置却没有发生时,再继续追实现问题。
- 用户日志里的任务流程与当前主线代码明显不一致,且当前代码看起来已经修掉了该问题:
- 先确认用户版本,必要时切到对应 tag例如 `git checkout vXXX`)核对旧逻辑。

2
.gitignore vendored
View File

@@ -421,7 +421,7 @@ FodyWeavers.xsd
.history/
# Claude Code
.claude/
.claude/*
!.claude/skills/
# Windows Installer files from build outputs

View File

@@ -1,4 +1,4 @@
## v6.9.3
## v6.9.4
### 许愿墙前挂满愿签,牛牛顺手把更新器、作战流程和海外服体验都打磨了一遍 | Highlights
@@ -42,6 +42,55 @@ This update adapts to the 7th anniversary wishing wall, the “Reclamation” in
以下是详细内容:
## v.6.9.4
### 新增 | New
* 手动输入关卡名支持使用 -Normal/-Hard 切换 常规/险地 难度 @ABA2396
* use v2 version of icons (#16556) @Constrat @ABA2396
### 改进 | Improved
* optimize templates @Constrat
### 修复 | Fix
* 調整繁中服部分幹員名稱 OCR (#16561) @momomochi987
* 繁中服肉鴿薩卡滋事件辨識 聚思成塔 (#16541) @CC-creator2026
* LogWarn 等宏在 Release 下依旧输出 scope 导致额外间隔 @status102
* 修复通宝交换/投钱任务链以适配交换通宝/投钱后获得藏品的情况 (#16553) @travellerse
* 外部通知设置界面调整 (#16552) @2436238575
* 界园肉鸽投资模式也启用通宝插件 (#16551) @travellerse
* 修复窗体关闭过程中再次启动时报“关闭期间无法设置可见性或调用 Show/Close”的异常 @ABA2396
* 繁中服肉鴿辨識 (#16535) @CC-creator2026
* 修复删除 debug 截图时因文件被占用导致应用闪退的问题 @ABA2396
* 远程控制启动任务未记录开始时间 (#16522) @March7th-OvO
* 部分成就分期错误 @ABA2396
* IS6 encounter trailing `o` and `-` fix #16525 @Constrat
### 文档 | Docs
* 更新 wiki 文档,增强内容结构与描述 @AnnAngela
* update zh-tw preview image (#16517) @momomochi987
### 其他 | Other
* 繁中服「快速放入線索」與「一鍵贈送重複線索」 (#16562) @momomochi987
* Lucky 的概率改为 0.0799% @ABA2396
* 使用 PC 端时不传账号 @ABA2396
* 增加 issue 分析知识库 @ABA2396
* 修改手动输入关卡名的悬浮描述 @ABA2396
* 生成日志压缩包时的缓存目录改为本地 reports 目录 @ABA2396
* 提前最小截图间隔的检查,小于间隔时跳过识别 @ABA2396
* 繁中服界園肉鴿 DLC1 & sss 9 炭火安保派駐 (#16516) @momomochi987
* 繁中服「界園」主題與「齊聚」主題 (#16515) @momomochi987
* restore JP StageAnnihilation.png @Manicsteiner
* YostarKR PV minigame @HX3N
* fix JP time ocr (#16557) @Manicsteiner
* YostarJP PV templates and ocr (#16505) @Manicsteiner
* EN PV minigame @Constrat
* Add context7.json with URL and public key @AnnAngela
## v6.9.3
### 新增 | New

View File

@@ -314,7 +314,7 @@
["干擾波長", "干扰波长"],
["劣質閃光彈", "劣质闪光弹"],
["無需增調.+員", "无需增调干员"],
["截", "截云"],
["截(雲|雪)", "截云"],
["地形增傷控制", "地形增伤控制"],
["山海密語儀", "山海密语仪"],
[".*(麒|麟).+夜刀$", "麒麟R夜刀"],
@@ -420,7 +420,7 @@
["“二踢腳”型數據收集裝置", "“二踢脚”型数据收集装置"],
["勘察用自走車", "勘察用自走车"],
["喚血祭壇", "唤血祭坛"],
["維(荻|茨)", "维荻"],
["維(荻|茨|茲)", "维荻"],
["瀝血王座", "沥血王座"],
["炸彈載荷點", "炸弹载荷点"],
["創生之相", "创生之相"],
@@ -555,7 +555,7 @@
["靈活架設模組", "灵活架设模块"],
["荒蕪拉普蘭德", "荒芜拉普兰德"],
[".*君者", "弑君者"],
["跡", "云迹"],
["(雲|雪)跡", "云迹"],
["菲萊", "菲莱"],
["軍工廠指令平台", "军工厂指令平台"],
["煙火發射器", "烟花发射器"],
@@ -911,10 +911,6 @@
"InfrastClueSelfFull": {
"text": ["已達線索上限", "無法獲取新的線索", "上限", "無法"]
},
"SendClues": {
"doc": "待「快速放入線索」與「一鍵贈送重複線索」功能實裝後再移除 (#14966)",
"roi": [1160, 350, 80, 80]
},
"InfrastTrainingIdle": {
"text": ["空閒中"]
},

View File

@@ -3685,11 +3685,13 @@
"next": ["EndOfPlot"]
},
"BattleAvatarDialog": {
"doc": "战斗中带头像对话框, 类似于 SkipThePreBattlePlot(可见于画中人关卡) 的, 但是缺少 跳过 按钮",
"doc": "战斗中带头像对话框, 类似于 SkipThePreBattlePlot(可见于画中人关卡, 17章主线TR28) 的, 但是缺少 跳过 按钮",
"action": "ClickSelf",
"roi": [70, 30, 120, 30],
"maxTimes": 5,
"next": ["BattleAvatarDialog", "Stop"],
"rectMove": [125, 20, 200, 60]
"rectMove": [125, 20, 200, 60],
"specialParams": [98]
},
"EndOfPlot": {
"roi": [520, 0, 243, 206],
@@ -4761,8 +4763,8 @@
"Doc": "20260109 YJWL更新后暂停按钮向右移动约8像素, 且暂停后亮度上限245 (不知道以前是不是也有这个问题)",
"template": "empty.png",
"roi": [1178, 33, 53, 39],
"specialParams_Doc": "亮度阈值;点的数量",
"specialParams": [235, 200]
"specialParams_Doc": "亮度阈值; 暂停时阈值; 运行时阈值",
"specialParams": [235, 200, 450]
},
"BattleSpeedButton": {
"template": "empty.png",

View File

@@ -601,7 +601,7 @@ bool asst::BattleHelper::check_pause_button(const cv::Mat& reusable)
BattlefieldMatcher battle_flag_analyzer_2(image);
auto battle_result_opt = battle_flag_analyzer_2.analyze();
ret &= battle_result_opt && battle_result_opt->pause_button;
ret &= battle_result_opt && battle_result_opt->pause_button != BattlefieldMatcher::PauseStatus::Unknown;
return ret;
}
@@ -621,14 +621,39 @@ bool asst::BattleHelper::check_skip_plot_button(const cv::Mat& reusable)
bool asst::BattleHelper::check_avatar_dialog(const cv::Mat& reusable)
{
cv::Mat image = reusable.empty() ? m_inst_helper.ctrler()->get_image() : reusable;
const static auto& task = Task.get("BattleAvatarDialog");
const static double threshold = task->special_params[0] / 100.0;
Matcher battle_plot_analyzer(image);
battle_plot_analyzer.set_task_info("BattleAvatarDialog");
battle_plot_analyzer.set_task_info(task);
bool ret = battle_plot_analyzer.analyze().has_value();
if (ret) {
ProcessTask(this_task(), { "BattleAvatarDialog" }).run();
if (!ret) {
return false;
}
return ret;
ProcessTask(this_task(), { "BattleAvatarDialog" }).run();
const auto match_rect = battle_plot_analyzer.get_result().rect.move(task->rect_move);
cv::Mat image2 = m_inst_helper.ctrler()->get_image();
int retry = 100;
while (!m_inst_helper.need_exit() && retry > 0) {
Matcher matcher(image2);
matcher.set_templ(make_roi(image, match_rect));
matcher.set_roi(match_rect);
matcher.set_threshold(threshold);
matcher.set_method(MatchMethod::Ccoeff);
if (matcher.analyze()) {
LogInfo << __FUNCTION__ << "still in dialog, but not detected change, maybe need deploy or skill";
break;
}
--retry;
ret = ProcessTask(this_task(), { "BattleAvatarDialog" }).run();
if (!ret) {
break;
}
image = image2;
image2 = m_inst_helper.ctrler()->get_image();
}
return true;
}
bool asst::BattleHelper::check_in_speedup(const cv::Mat& reusable)
@@ -646,7 +671,7 @@ bool asst::BattleHelper::check_in_battle(const cv::Mat& reusable, bool weak)
BattlefieldMatcher analyzer(image);
auto result = analyzer.analyze();
m_in_battle = result.has_value();
if (m_in_battle && !result->pause_button) {
if (m_in_battle && result->pause_button == BattlefieldMatcher::PauseStatus::Unknown) {
if (check_skip_plot_button(image)) {
if (m_in_speedup && !check_in_speedup()) {
speed_up(); // 跳过剧情会退出2倍速
@@ -655,13 +680,13 @@ bool asst::BattleHelper::check_in_battle(const cv::Mat& reusable, bool weak)
else if (check_avatar_dialog(image)) {
if (m_in_speedup && !check_in_speedup()) {
speed_up(); // 跳过剧情会退出2倍速
m_inst_helper.sleep(Config.get_options().task_delay);
int times = 0;
while (times < 20 && !m_inst_helper.need_exit() && !check_in_speedup()) {
speed_up(); // 跳过剧情会退出2倍速
m_inst_helper.sleep(Config.get_options().task_delay);
times++;
}
}
}
}
else if (m_in_battle && result->pause_button == BattlefieldMatcher::PauseStatus::Pausing) {
if (check_avatar_dialog(image)) {
if (m_in_speedup && !check_in_speedup()) {
speed_up(); // 跳过剧情会退出2倍速
}
}
}

View File

@@ -248,7 +248,7 @@ bool asst::CombatRecordRecognitionTask::analyze_deployment()
oper_analyzer.set_image(frame);
auto oper_result_opt = oper_analyzer.analyze();
bool analyzed = oper_result_opt && oper_result_opt->pause_button;
bool analyzed = oper_result_opt && oper_result_opt->pause_button != BattlefieldMatcher::PauseStatus::Unknown;
if (analyzed) {
m_battle_start_frame = i;
deployment = std::move(oper_result_opt->deployment);
@@ -390,7 +390,7 @@ bool asst::CombatRecordRecognitionTask::slice_video()
pre_distance = distance;
}
bool oper_is_clicked = !result_opt->speed_button || !result_opt->pause_button;
bool oper_is_clicked = !result_opt->speed_button || result_opt->pause_button == BattlefieldMatcher::PauseStatus::Unknown;
bool oper_auto_retreat =
in_segment && continuity && !m_clips.empty() && cur_opers.size() != m_clips.back().deployment.size();

View File

@@ -462,6 +462,9 @@ bool asst::BattleProcessTask::wait_condition(const Action& action)
const std::string& name = get_name_from_group(action.name);
update_image_if_empty();
while (!need_exit()) {
if (!check_in_battle(image)) {
return false;
}
if (!update_deployment(false, image)) {
return false;
}

View File

@@ -36,12 +36,7 @@ bool asst::MultiCopilotTaskPlugin::_run()
callback(AsstMsg::SubTaskExtraInfo, info);
bool ret = true;
Task.get<OcrTaskInfo>(config.nav_name + "@Copilot@ClickStageName")->text = { config.nav_name };
std::string replace_navigate_name = config.nav_name;
utils::string_replace_all_in_place(replace_navigate_name, { { "-", "" } });
Task.get<OcrTaskInfo>(config.nav_name + "@Copilot@ClickedCorrectStage")->text = { config.nav_name,
replace_navigate_name };
ret = ret && ProcessTask(*this, { config.nav_name + "@Copilot@StageNavigationBegin" }).set_retry_times(20).run();
ret = ret && navigate_to_stage(config.nav_name);
ProcessTask(*this, { "NotUsePrts" }).set_ignore_error(true).set_retry_times(0).run();
if (config.is_raid) {
@@ -51,3 +46,12 @@ bool asst::MultiCopilotTaskPlugin::_run()
return ret;
}
bool asst::MultiCopilotTaskPlugin::navigate_to_stage(const std::string& stage_name)
{
Task.get<OcrTaskInfo>(stage_name + "@Copilot@ClickStageName")->text = { stage_name };
std::string replace_navigate_name = stage_name;
utils::string_replace_all_in_place(replace_navigate_name, { { "-", "" } });
Task.get<OcrTaskInfo>(stage_name + "@Copilot@ClickedCorrectStage")->text = { stage_name, replace_navigate_name };
return ProcessTask(*this, { stage_name + "@Copilot@StageNavigationBegin" }).set_retry_times(20).run();
}

View File

@@ -27,6 +27,7 @@ public:
private:
virtual bool _run() override;
bool navigate_to_stage(const std::string& stage_name);
std::vector<MultiCopilotConfig> m_copilot_configs;
int m_index_current = 0; // 当前执行的索引

View File

@@ -37,7 +37,7 @@ BattlefieldMatcher::ResultOpt BattlefieldMatcher::analyze() const
if (m_object_of_interest.flag) {
result.pause_button = pause_button_analyze();
if (!result.pause_button && !hp_flag_analyze() && !kills_flag_analyze() && !cost_symbol_analyze()) {
if (result.pause_button == PauseStatus::Unknown && !hp_flag_analyze() && !kills_flag_analyze() && !cost_symbol_analyze()) {
// flag 表明当前画面是在战斗场景的,不在的就没必要识别了
return std::nullopt;
}
@@ -440,7 +440,7 @@ bool asst::BattlefieldMatcher::hit_costs_cache() const
return mark > threshold;
}
bool BattlefieldMatcher::pause_button_analyze() const
asst::BattlefieldMatcher::PauseStatus BattlefieldMatcher::pause_button_analyze() const
{
auto task_ptr = Task.get("BattleHasStarted");
cv::Mat roi = m_image(make_rect<cv::Rect>(task_ptr->roi));
@@ -450,14 +450,22 @@ bool BattlefieldMatcher::pause_button_analyze() const
const int value_threshold = task_ptr->special_params[0];
cv::threshold(roi_gray, bin, value_threshold, 255, cv::THRESH_BINARY);
int count = cv::countNonZero(bin);
const int count_threshold = task_ptr->special_params[1];
Log.trace(__FUNCTION__, "count", count, "threshold", count_threshold);
const int threshold_base = task_ptr->special_params[1];
const int threshold_high = task_ptr->special_params[2];
Log.trace(__FUNCTION__, "count", count, "threshold", threshold_base, ",", threshold_high);
PauseStatus status = PauseStatus::Unknown;
if (count >= threshold_high) {
status = PauseStatus::Running;
}
else if (count >= threshold_base) {
status = PauseStatus::Pausing;
}
#ifdef ASST_DEBUG
cv::rectangle(m_image_draw, make_rect<cv::Rect>(task_ptr->roi), cv::Scalar(0, 0, 255), 2);
cv::putText(
m_image_draw,
std::to_string(count) + "/" + std::to_string(count_threshold),
std::to_string(count) + "/" + std::to_string(threshold_base) + "," + std::to_string(threshold_high),
cv::Point(task_ptr->roi.x, task_ptr->roi.y + task_ptr->roi.height + 10),
cv::FONT_HERSHEY_PLAIN,
1.2,
@@ -465,7 +473,7 @@ bool BattlefieldMatcher::pause_button_analyze() const
2);
#endif
return count > count_threshold;
return status;
}
bool BattlefieldMatcher::in_detail_analyze() const

View File

@@ -26,6 +26,13 @@ public:
HitCache = 2, // 图像命中缓存, 不进行识别
};
enum PauseStatus
{
Unknown = 0, // 没有找到暂停按钮
Pausing = 1, // 暂停中
Running = 2, // 运行中
};
template <typename T>
struct MatchResult
{
@@ -42,7 +49,7 @@ public:
// bool in_detail = false;
bool speed_button = false;
bool pause_button = false;
asst::BattlefieldMatcher::PauseStatus pause_button = PauseStatus::Unknown;
};
using ResultOpt = std::optional<Result>;
@@ -59,7 +66,7 @@ public:
protected:
bool hp_flag_analyze() const;
bool kills_flag_analyze() const;
bool pause_button_analyze() const;
asst::BattlefieldMatcher::PauseStatus pause_button_analyze() const;
std::vector<battle::DeploymentOper> deployment_analyze() const; // 识别干员
battle::Role oper_role_analyze(const Rect& roi) const;

View File

@@ -323,7 +323,7 @@ public static class ConfigFactory
_debounceTimer.Change(PendingDelayMs, Timeout.Infinite);
ConfigurationUpdateEvent?.Invoke(key, oldValue, newValue);
_logger.Debug("Configuration {Key} has been set: `{OldValue}` -> `{NewValue}`, save scheduled", key, oldValue, newValue);
_logger.Information("Configuration {Key} has been set: `{OldValue}` -> `{NewValue}`, save scheduled", key, oldValue, newValue);
}
private static void CreateSaveTask(object? state)

View File

@@ -788,8 +788,8 @@ public class AchievementTrackerHelper : PropertyChangedBase
Instance.Unlock(AchievementIds.Pioneer2);
}
// 0.066% 概率触发
if (new Random().NextDouble() < 0.00066)
// 0.0799% 概率触发
if (new Random().NextDouble() < 0.000799)
{
Instance.Unlock(AchievementIds.Lucky);
}

View File

@@ -79,7 +79,7 @@ public class BarkNotificationProvider(IHttpService httpService) : IExternalNotif
public string Group { get; } = "MaaAssistantArknights";
[JsonPropertyName("icon")]
public static string Icon { get => "https://cdn.jsdelivr.net/gh/MaaAssistantArknights/design@main/logo/maa-logo_256x256.png"; }
public static string Icon { get => "https://cdn.jsdelivr.net/gh/MaaAssistantArknights/design@main/v2/icons/maa-logo_256x256.png"; }
// ReSharper restore UnusedAutoPropertyAccessor.Local
// ReSharper restore UnusedMember.Local

View File

@@ -86,10 +86,10 @@ public class StartUpSettingsUserControlModel : TaskSettingsViewModel, StartUpSet
}
var clientType = SettingsViewModel.GameSettings.ClientType;
var accountName = clientType switch {
ClientType.Official or ClientType.Bilibili => startUp.AccountName,
_ => string.Empty,
};
var accountName = !SettingsViewModel.ConnectSettings.UseAttachWindow &&
clientType is ClientType.Official or ClientType.Bilibili
? startUp.AccountName
: string.Empty;
var task = new AsstStartUpTask() {
ClientType = clientType,