Skip to content

feat: 优化维琳娜和简战斗模板 - #2605

Merged
ShadowLemoon merged 1 commit into
OneDragon-Anything:mainfrom
kawayiYokami:feat/velina-void-hunter-awakening
Aug 3, 2026
Merged

feat: 优化维琳娜和简战斗模板#2605
ShadowLemoon merged 1 commit into
OneDragon-Anything:mainfrom
kawayiYokami:feat/velina-void-hunter-awakening

Conversation

@kawayiYokami

@kawayiYokami kawayiYokami commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

变更内容

  • 为维琳娜补充强化特殊技合轴,并按风华值调整速切和紧急切入分支。
  • 将简的长按 A 模板改名为萨霍夫跳,为合轴动作增加 3 秒状态窗口;红光期间优先松开普攻。
  • 补充命破双反模板,并更新受影响的合并配置。

验证

  • 运行 powershell -File skills/new-config/new-config.ps1 生成 merged 配置。
  • 解析 config/ 下全部 680 个 YAML 文件。
  • 执行 git diff --check

Summary by CodeRabbit

  • 新功能

    • 新增多项角色自动战斗连段与合轴处理,支持更精细的技能衔接。
    • 新增双反切人模板及维琳娜强化特殊技合轴流程。
    • 增强快速支援与紧急切入处理。
  • 优化

    • 缩短切人、普通攻击及闪避后的操作延迟,提升战斗响应速度。
    • 优化简、维琳娜、蕾米埃尔等角色的技能触发条件与连招顺序。
    • 调整黄光、红光闪避及后台切换流程,减少重复操作。

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

本次更新调整自动战斗配置的黄光切人节奏、双反模板路由、简的萨霍夫跳合轴连段、蕾米埃尔快速支援、维琳娜风华分支,以及多角色紧急切入条件。

Changes

自动战斗配置调整

Layer / File(s) Summary
黄光切人节奏与双反模板
config/auto_battle/*.yml, config/auto_battle_operation/双反-*.sample.yml, config/auto_battle_state_handler/双反模板-命破.sample.yml
移除部分等待和切换后延迟。普通攻击延迟统一调整为 0.02。黄光候选模板改为双反模板,并新增命破处理器。
简的萨霍夫跳与终结技分支
config/auto_battle/全配队通用.merged.yml, config/auto_battle/击破站场-强攻速切.merged.yml, config/auto_battle/强攻站场-击破支援速切.merged.yml, config/auto_battle/自动守护.merged.yml, config/auto_battle_operation/简-*.sample.yml, config/auto_battle_state_handler/速切模板-简.sample.yml
新增萨霍夫跳合轴状态和操作序列。简的终结技改用失衡时间条件。特殊技提高狂热心流下限,并调整普攻次数和互斥条件。
蕾米埃尔与维琳娜处理流程
config/auto_battle/*.merged.yml, config/auto_battle_operation/维琳娜-强化特殊技合轴.sample.yml, config/auto_battle_state_handler/速切模板-*.sample.yml
蕾米埃尔优先处理快速支援,并扩展长按技能的中断条件。维琳娜按风华区间执行高风华长按普攻或低风华强化特殊技合轴。
薇薇安状态清理与紧急切入
config/auto_battle/*.merged.yml, config/auto_battle_state_handler/轮换-紧急-全角色.sample.yml, config/auto_battle_operation/薇薇安-强化特殊技合轴.sample.yml
删除重复的合轴时间设置。南宫羽、千夏和维琳娜的紧急切入增加非前台条件或风华分支。

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant 黄光识别
  participant 状态处理器
  participant 自动战斗操作
  participant 角色状态
  黄光识别->>状态处理器: 选择双反模板或角色处理器
  状态处理器->>自动战斗操作: 执行闪避、普攻、技能或角色切换
  自动战斗操作->>角色状态: 设置黄光切人、萨霍夫跳或合轴状态
Loading

Possibly related PRs

Suggested reviewers: doctorreid, shadowlemoon

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了维琳娜和简战斗模板的主要优化,且与变更内容和PR目标一致。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kawayiYokami
kawayiYokami force-pushed the feat/velina-void-hunter-awakening branch from ee7310c to a32367d Compare July 30, 2026 18:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/zzz_od/application/shiyu_defense/shiyu_defense_app.py (1)

264-296: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

多间-等待预备编队 节点未声明 node_max_retry_times,画面加载稍慢就会失败。

这条路径需要反复点「下一步」并等待预备编队界面出现(第 290-296 行每轮 round_retry),依赖默认重试次数偏紧;对比同文件 多间-选择房间(30 次)、多间-战斗结束(30 次)都显式放宽了上限。建议这里也显式声明。

🛡️ 建议显式放宽上限
     `@node_from`(from_name='多间-选择房间')
-    `@operation_node`(name='多间-等待预备编队')
+    `@operation_node`(name='多间-等待预备编队', node_max_retry_times=30)
     def multi_room_wait_prepare(self) -> OperationRoundResult:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_app.py` around lines 264 -
296, 为 multi_room_wait_prepare 显式设置
node_max_retry_times,采用同文件“多间-选择房间”和“多间-战斗结束”使用的 30 次上限;保持现有
round_retry、点击“下一步”和编队选择逻辑不变。
docs/game/gameplay/式舆防卫战.md (1)

101-101: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

第 101 行仍引用已删除的 calc_teams

本次改动已把入口换成 select_teams / get_team_targets / get_team_targets_for_multi_room(第 44、91、93 行也已更新),但「信息来源与置信度」这段仍写着 shiyu_defense_team_utils.py(calc_teams),属于遗漏。

📝 建议同步
-- **代码反推**:`shiyu_defense_app.py`(节点链)/ `shiyu_defense_battle.py`(ShiyuDefenseBattle op 内部)/ `shiyu_defense_team_utils.py`(calc_teams)/ screen_info `shiyu_defense.yml` + `shiyu_defense_select_3.yml`。
+- **代码反推**:`shiyu_defense_app.py`(节点链)/ `shiyu_defense_battle.py`(ShiyuDefenseBattle op 内部)/ `shiyu_defense_team_utils.py`(get_team_targets / select_teams)/ screen_info `shiyu_defense.yml` + `shiyu_defense_select_3.yml`。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/game/gameplay/式舆防卫战.md` at line 101, 更新文档中的“代码反推”引用,移除已删除的
shiyu_defense_team_utils.py 中的 calc_teams,并改为当前使用的 select_teams、get_team_targets
和 get_team_targets_for_multi_room 相关入口;保持其余信息来源说明不变。
🧹 Nitpick comments (14)
src/zzz_od/gui/view/devtools/shiyu_defense_team_test_interface.py (1)

28-28: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

parent 标注类型。

__init__parent 参数缺少类型标注。

建议修改
-def __init__(self, ctx: ZContext, parent=None):
+def __init__(self, ctx: ZContext, parent: QWidget | None = None):

As per coding guidelines,src/**/*.py 要求“所有函数签名和类成员变量都必须有类型注解”。Based on learnings,本项目的 __init__ 保持不写 -> None;这里只需标注参数类型。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/gui/view/devtools/shiyu_defense_team_test_interface.py` at line
28, 为 devtools 防御队伍测试界面的 __init__ 方法中的 parent 参数添加合适的类型注解;保持现有的 __init__
签名风格,不添加 -> None 返回类型,也不要修改其他参数或逻辑。

Sources: Coding guidelines, Learnings

src/zzz_od/application/shiyu_defense/shiyu_defense_app.py (2)

305-308: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

第 307 行的 team_idx = -1 已无实际作用。

同一行上方已把 is_completed 置为 True,此后该房间既不会被 multi_room_select(按 not is_completed 筛选)选中,也不会进入 multi_room_wait_preparetarget_list(同样按 not is_completed 过滤)。这行残留会让读者误以为 team_idx 仍参与流程判断,建议删除。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_app.py` around lines 305 -
308, Remove the redundant self.room_teams[self.current_room_idx].team_idx = -1
assignment from the result.is_success branch, while preserving the is_completed
update and returning result unchanged.

178-197: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

「已完成房间」的 OCR 判定被写了两遍,且其中一份实际不可达。

第 184 行的 all_text != '0' and all_text != ''shiyu_defense_team_utils.get_team_targets_for_multi_room 第 265 行完全相同。由于这里一旦命中就会点「重置全部」并 round_retry,只有全部房间得分都为 0/空时才会走到第 192 行,所以 get_team_targets_for_multi_room 里那条 is_completed = True 的识别分支永远不会触发 —— is_completed 实际只来自 multi_room_deploy 的写入。

建议二选一:要么去掉这里的重置前置判定、让识别结果驱动跳过;要么去掉 get_team_targets_for_multi_room 里的完成态识别,避免两份同源判定各自演化。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_app.py` around lines 178 -
197, 统一“已完成房间”的 OCR 判定,避免 shiyu_defense_app 中的前置检查与
get_team_targets_for_multi_room 重复且导致完成态分支不可达;建议移除前置 need_reset 检查,让
get_team_targets_for_multi_room 的识别结果驱动跳过逻辑,并同步保留或迁移必要的重置行为,确保完成房间仍按预期处理。
src/zzz_od/operation/choose_predefined_team.py (5)

373-422: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

_find_select_button_find_selected_button 结构完全重复。

两个方法除了文本判定条件外完全一致,偏移窗口(300/850/40/250)和期望位置(650/130)这两组魔法数各写了两遍。建议提取为一个按谓词参数化的私有方法,并把魔法数提为类常量。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/operation/choose_predefined_team.py` around lines 373 - 422,
合并_find_select_button与_find_selected_button的重复候选查找逻辑,提取一个接收文本判定谓词的私有方法,并让两个现有方法分别传入对应的判定条件;同时将偏移范围300/850/40/250及期望位置650/130提取为类常量,确保行为保持不变。

64-64: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

shiyu 模式下 op_name 会显示为 选择预备编队 None

此时 target_team_idx_listNone,真实目标要到 _select_shiyu_teams 之后才确定,日志里这段后缀没有信息量反而有误导性。建议 shiyu 模式下省略或改为标注自动配队。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/operation/choose_predefined_team.py` at line 64, Update the
operation-name construction around op_name so shiyu mode does not append
target_team_idx_list when it is None. Use the existing mode indicator to omit
the suffix or label it as automatic team selection, while preserving the
target-list suffix for modes where _select_shiyu_teams is not responsible for
determining the teams.

517-522: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

卡片区域 Rect_recognize_team_agents 第 543-548 行完全重复。

同一组魔法偏移量(-10 / +800 / +250)写了两遍,两处一旦不同步,槽位判定与头像识别就会针对不同区域。建议抽成 _get_team_card_rect(team_name_mr)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/operation/choose_predefined_team.py` around lines 517 - 522, 在
choose team card 区域提取统一的 _get_team_card_rect(team_name_mr) 辅助方法,集中定义
-10、+800、+250 偏移量;更新当前 Rect 构造及 _recognize_team_agents
中的重复逻辑,全部复用该方法,确保槽位判定与头像识别使用完全相同的区域。

353-359: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

shiyu_click_target_list 必须是 shiyu_target_list 中的同一对象,建议显式校验。

team_idx 只回写给 shiyu_target_list 里的对象(第 349-351 行)。调用方(shiyu_defense_app.multi_room_wait_prepare)依赖 [current_team]target_list 的筛选条件(not is_completed)恰好一致、且是同一对象引用,才能拿到回写后的 team_idx;否则会静默得到 -1 并以 round_fail 收场,排查困难。加一句子集断言可以把这层隐式契约变显式。

🛡️ 建议补充校验
         click_target_list = (
             self.shiyu_target_list
             if self.shiyu_click_target_list is None
             else self.shiyu_click_target_list
         )
+        if any(target not in self.shiyu_target_list for target in click_target_list):
+            log.error('点击目标不在自动配队目标列表中,无法获取 team_idx')
+            return False
         self.target_team_idx_list = [target.team_idx for target in click_target_list]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/operation/choose_predefined_team.py` around lines 353 - 359, 在处理
shiyu_click_target_list 的逻辑中,显式校验其所有元素都与 shiyu_target_list
中的对象保持同一引用关系,而非仅通过值相等判断。将该校验放在生成 target_team_idx_list 之前,失败时立即触发断言;保留现有 team_idx
提取及非负值判断。

71-74: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

属性注解未加引号,与第 53-54 行的字符串注解不一致。

DefensePhaseTeamInfo 只在 TYPE_CHECKING 下导入。函数体内的变量注解运行时不求值,所以当前不会 NameError,但一旦有人对 __init__typing.get_type_hints 反射就会失败,且与参数注解写法不统一。

♻️ 建议统一为字符串注解
-        self.shiyu_target_list: list[DefensePhaseTeamInfo] | None = shiyu_target_list
-        self.shiyu_click_target_list: list[DefensePhaseTeamInfo] | None = (
+        self.shiyu_target_list: list['DefensePhaseTeamInfo'] | None = shiyu_target_list
+        self.shiyu_click_target_list: list['DefensePhaseTeamInfo'] | None = (
             shiyu_click_target_list
         )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/operation/choose_predefined_team.py` around lines 71 - 74,
将初始化方法中的 self.shiyu_target_list 和 self.shiyu_click_target_list 属性注解统一改为字符串形式
"DefensePhaseTeamInfo",与参数注解保持一致;保留现有可选类型和赋值逻辑不变。

Source: Coding guidelines

src/one_dragon/base/controller/pc_controller_base.py (1)

593-599: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

新增的 0.1s 未纳入 duration 计算,破坏了既有时长语义,且影响全部前台拖拽。

第 599 行刻意把 SLEEP_BEFORE_DRAG_ENDduration 中扣除,以保持「duration = 拖拽总时长」的约定;而这次新增的 time.sleep(0.1) 没有做同样处理,于是每次拖拽的实际耗时都比调用方声明的 duration 多 0.1s。drag_mouse 是所有前台 drag_to 的公共实现,这个偏移会累加到全部拖拽场景。

同时建议按本文件既有风格(SLEEP_BEFORE_DRAG_ENDDRAG_MIN_DURATION)把 0.1 提为具名常量,并补一句说明为何需要按下后停顿。

♻️ 建议提为常量并纳入时长计算
     pyautogui.moveTo(start.x, start.y)
     pyautogui.mouseDown()
-    time.sleep(0.1)
+    # 按下后短暂停顿,确保游戏已接收到按下事件再开始移动
+    time.sleep(PcControllerBase.SLEEP_AFTER_DRAG_START)
 
-    # 减去 PcControllerBase.SLEEP_BEFORE_DRAG_END 之后的间隔
-    duration_drag = max(duration - PcControllerBase.SLEEP_BEFORE_DRAG_END, PcControllerBase.DRAG_MIN_DURATION)
+    # 减去按下停顿与松开前定住的间隔
+    duration_drag = max(
+        duration - PcControllerBase.SLEEP_AFTER_DRAG_START - PcControllerBase.SLEEP_BEFORE_DRAG_END,
+        PcControllerBase.DRAG_MIN_DURATION,
+    )

同时在类常量区新增:

     SLEEP_BEFORE_DRAG_END:float = 0.2
+    SLEEP_AFTER_DRAG_START:float = 0.1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/one_dragon/base/controller/pc_controller_base.py` around lines 593 - 599,
Update the shared drag implementation, especially drag_mouse, to account for the
0.1-second post-mouseDown pause when calculating the drag duration, preserving
duration as the total elapsed drag time. Extract the pause into a named
PcControllerBase class constant alongside SLEEP_BEFORE_DRAG_END and
DRAG_MIN_DURATION, document why the pause is required, and subtract it from the
remaining duration before applying the minimum-duration clamp.
docs/game/screens/式舆防卫战.md (1)

67-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

「名称只用于抵消滚动重叠」表述不直白,建议改写。

这句读者需要猜测含义。实际机制是:相邻页会重复渲染同一张卡片,所以用队名去重,避免同一支队被扫描两次。按编码规范,文档应使用直白表述、不自造项目内部说法。

📝 建议改写
-3. `ChoosePredefinedTeam` 在当前列表内按游戏顺序扫描卡片,名称只用于抵消滚动重叠;扫描结果按首次顺序写入当前实例 `team.yml` 的同序号预备编队名称和前三名代理人,邦布不写入 `agent_id_list`,并保留该序号已有的自动战斗配置。
+3. `ChoosePredefinedTeam` 在当前列表内按游戏顺序扫描卡片;相邻页会重复显示同一张卡片,因此用队名去重,同一支队只扫描一次。扫描结果按首次出现的顺序写入当前实例 `team.yml` 的同序号预备编队名称和前三名代理人,邦布不写入 `agent_id_list`,并保留该序号已有的自动战斗配置。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/game/screens/式舆防卫战.md` at line 67, 将 ChoosePredefinedTeam
描述中的“名称只用于抵消滚动重叠”改为直白说明:由于相邻页面会重复渲染同一张卡片,使用队名去重,避免同一支队伍被重复扫描;保留其余扫描、写入和禁用规则不变。

Source: Coding guidelines

src/zzz_od/application/shiyu_defense/shiyu_defense_team_utils.py (2)

124-154: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

染色/耦合的评分规则缺少注释,不对称跳过难以判断是否有意。

第 136-140 行只在 agent.dmg_type == WIND 且队友为 LUMIFLUX 时跳过,反向(自己是 LUMIFLUX、队友是 WIND)不跳过。这层不对称属于游戏机制约定,从代码看不出意图,后续维护容易被"顺手对称化"改坏。建议补一句中文注释说明依据。

♻️ 建议补充注释
             dye_score_list = []
             for other_agent in agent_list:
                 if other_agent.agent_id == agent.agent_id:
                     continue
                 if other_agent.agent_type != AgentTypeEnum.ANOMALY:
                     continue
+                # 风属性染色无法从耦合队友取分,反向可以,故此处只单向跳过
                 if (
                     agent.dmg_type == DmgTypeEnum.WIND
                     and other_agent.dmg_type == DmgTypeEnum.LUMIFLUX
                 ):
                     continue
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_team_utils.py` around
lines 124 - 154, 在遍历异常角色并计算 dye_score_list 的配对过滤逻辑中,为 agent.dmg_type 为
WIND、other_agent.dmg_type 为 LUMIFLUX
时的单向跳过条件补充中文注释,明确说明这是染色/耦合机制规定的有意不对称行为,并提醒不要改为双向跳过;不要修改现有判断逻辑。

258-261: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

room_namesshiyu_defense_const.ROOM_NAMES 重复定义。

调用方(shiyu_defense_app.check_weakness)传的 room_count 就是 len(ROOM_NAMES),这里却另建一份同内容列表,两处任一变更就会 IndexError 或错位。建议直接复用常量。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_team_utils.py` around
lines 258 - 261, 更新相关房间遍历逻辑,移除局部定义的 room_names 列表,并直接复用
shiyu_defense_const.ROOM_NAMES;在循环中通过该常量按 room_idx 获取房间名称,保留现有 room_count 遍历行为。
src/zzz_od/config/team_config.py (1)

71-84: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

update_team_members 的「取 agent_id + 补齐 unknown」逻辑重复。

第 80-82 行与下方 update_team_members 第 94-97 行完全同构,可抽一个私有 helper 统一,避免后续补齐规则(例如允许 4 号位)只改一处。

♻️ 可选抽取
+    `@staticmethod`
+    def _build_agent_id_list(members: list[Agent]) -> list[str]:
+        agent_id_list = [member.agent_id for member in members[:3]]
+        while len(agent_id_list) < 3:
+            agent_id_list.append('unknown')
+        return agent_id_list
+
     def update_team_by_idx(self, team_idx: int, team_name: str, members: list[Agent]) -> None:
         """
         按游戏内列表顺序同步预备编队
         """
         team = self.get_team_by_idx(team_idx)
         if team is None:
             return
 
         team.name = team_name
-        team.agent_id_list = [member.agent_id for member in members[:3]]
-        while len(team.agent_id_list) < 3:
-            team.agent_id_list.append('unknown')
+        team.agent_id_list = self._build_agent_id_list(members)
         self.update_team(team)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/config/team_config.py` around lines 71 - 84, 抽取私有 helper 统一处理成员列表的
agent_id 提取及用 unknown 补齐逻辑,并让 update_team_by_idx 与 update_team_members 复用该
helper;保持当前最多 3 名成员及现有更新行为不变。
config/auto_battle_state_handler/双反模板-命破.sample.yml (1)

7-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

“设置状态”沿用了 OperationDef 中标注为待删除的 data 旧字段。 根因是命破双反模板使用 data: ["自定义-黄光切人"],生成的 merged 配置因此与同文件其余 state: 写法并存。

  • config/auto_battle_state_handler/双反模板-命破.sample.yml#L7-L13:两处 data: ["自定义-黄光切人"] 改为 state: "自定义-黄光切人"
  • config/auto_battle/自动守护.merged.yml#L143-L145:重新生成 merged 配置,使 8 个后台分支与兜底分支(L263)统一为 state 写法。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/auto_battle_state_handler/双反模板-命破.sample.yml` around lines 7 - 13,
Update both “设置状态” operations in
config/auto_battle_state_handler/双反模板-命破.sample.yml:7-13 to use the state field
with the existing string value instead of the deprecated data field. Regenerate
config/auto_battle/自动守护.merged.yml:143-145 so all affected backend branches and
the fallback branch use the state format consistently; no direct manual logic
change is needed beyond regenerating the merged configuration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@config/auto_battle_state_handler/速切模板-维琳娜.sample.yml`:
- Around line 48-51: 在配置中恢复“高风华长按普攻”状态对“按键可用-快速支援”的打断条件,或调整为等效且合理的
interrupt_cal_tree 配置;确保维琳娜执行“维琳娜-长按普攻”期间能通过优先级触发 _stop_running_task() 响应快速支援。

In
`@src/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_config.py`:
- Around line 39-58: Prevent the same damage type from appearing in both
weaknesses and resistances. In
src/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_config.py
lines 39-58, update set_target_dmg_type and/or get_target_list to reject or
normalize overlapping values before persistence or list generation. In
src/zzz_od/gui/view/devtools/shiyu_defense_team_test_interface.py lines 62-103,
when a type is selected on one side, disable or clear the matching type on the
other side and synchronize the configuration and control states.

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_app.py`:
- Around line 132-139: 在多间模式处理节点-05的分支中,更新 round_by_find_and_click_area
失败后的逻辑,复用普通节点分支的兜底流程:先检查并点击「下一步」,仍未找到时拖动「节点区域」重新寻找节点-05。仅在这些兜底操作都失败后调用
round_retry,成功则按现有方式调用 round_success。

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_team_utils.py`:
- Around line 274-302: Update the attribute-detection flow around attribute_area
and the OCR validation branches to make recognition failures explicit: emit a
warning with the room/context and failure reason, and propagate a
distinguishable failure state to the caller instead of treating both cases as a
normal all-UNKNOWN DefensePhaseTeamInfo. Preserve the existing UNKNOWN
representation only for successfully recognized rooms that genuinely have no
attribute preference, and update the calling flow so failed recognition does not
proceed through normal multi_room_select/team selection.

In `@src/zzz_od/operation/choose_predefined_team.py`:
- Around line 446-454: 收紧 _is_selected_text
的数字判定,避免将代理人卡片中的任意两位等级识别为已选按钮;仅接受选队序号的有效范围,或结合按钮列的窄 x 偏移进行校验,并将所需位置信息从
_find_selected_button 传入。删除被 startswith('TEAM') 覆盖的 normalized_text == 'TEAM'
分支,保持 SELECTED 和 TEAM 前缀识别不变。
- Around line 296-316: 调整预备编队扫描逻辑中 agent_list 为空的判定顺序:先依据 agent_slot_set
判断队伍是否具备 1P、2P、3P 槽位;仅当三个槽位都缺失时才在 choose_predefined_team 的扫描流程中返回空队结束。槽位存在但
agent_list 为空的队伍应按禁用队处理,保留真实序号并继续扫描,不要提前终止后续有效编队的发现。
- Line 110: These operation nodes currently rely on the framework's default 3
retry attempts but contain multiple rounds of round_retry and round_wait that
accumulate retries, causing premature failure without reaching the actual wait
budget. In src/zzz_od/operation/choose_predefined_team.py at line 110, add an
explicit node_max_retry_times parameter to the operation_node decorator for the
选择编队 node with a value sufficient for the multiple rounds of element finding and
confirmation clicks. In
src/zzz_od/application/shiyu_defense/shiyu_defense_app.py at lines 264-296, set
node_max_retry_times=30 for the 多间-等待预备编队 node to unify it with other multi-room
nodes in the same file that use round_retry to repeatedly click through
interface transitions.

---

Outside diff comments:
In `@docs/game/gameplay/式舆防卫战.md`:
- Line 101: 更新文档中的“代码反推”引用,移除已删除的 shiyu_defense_team_utils.py 中的
calc_teams,并改为当前使用的 select_teams、get_team_targets 和
get_team_targets_for_multi_room 相关入口;保持其余信息来源说明不变。

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_app.py`:
- Around line 264-296: 为 multi_room_wait_prepare 显式设置
node_max_retry_times,采用同文件“多间-选择房间”和“多间-战斗结束”使用的 30 次上限;保持现有
round_retry、点击“下一步”和编队选择逻辑不变。

---

Nitpick comments:
In `@config/auto_battle_state_handler/双反模板-命破.sample.yml`:
- Around line 7-13: Update both “设置状态” operations in
config/auto_battle_state_handler/双反模板-命破.sample.yml:7-13 to use the state field
with the existing string value instead of the deprecated data field. Regenerate
config/auto_battle/自动守护.merged.yml:143-145 so all affected backend branches and
the fallback branch use the state format consistently; no direct manual logic
change is needed beyond regenerating the merged configuration.

In `@docs/game/screens/式舆防卫战.md`:
- Line 67: 将 ChoosePredefinedTeam
描述中的“名称只用于抵消滚动重叠”改为直白说明:由于相邻页面会重复渲染同一张卡片,使用队名去重,避免同一支队伍被重复扫描;保留其余扫描、写入和禁用规则不变。

In `@src/one_dragon/base/controller/pc_controller_base.py`:
- Around line 593-599: Update the shared drag implementation, especially
drag_mouse, to account for the 0.1-second post-mouseDown pause when calculating
the drag duration, preserving duration as the total elapsed drag time. Extract
the pause into a named PcControllerBase class constant alongside
SLEEP_BEFORE_DRAG_END and DRAG_MIN_DURATION, document why the pause is required,
and subtract it from the remaining duration before applying the minimum-duration
clamp.

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_app.py`:
- Around line 305-308: Remove the redundant
self.room_teams[self.current_room_idx].team_idx = -1 assignment from the
result.is_success branch, while preserving the is_completed update and returning
result unchanged.
- Around line 178-197: 统一“已完成房间”的 OCR 判定,避免 shiyu_defense_app 中的前置检查与
get_team_targets_for_multi_room 重复且导致完成态分支不可达;建议移除前置 need_reset 检查,让
get_team_targets_for_multi_room 的识别结果驱动跳过逻辑,并同步保留或迁移必要的重置行为,确保完成房间仍按预期处理。

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_team_utils.py`:
- Around line 124-154: 在遍历异常角色并计算 dye_score_list 的配对过滤逻辑中,为 agent.dmg_type 为
WIND、other_agent.dmg_type 为 LUMIFLUX
时的单向跳过条件补充中文注释,明确说明这是染色/耦合机制规定的有意不对称行为,并提醒不要改为双向跳过;不要修改现有判断逻辑。
- Around line 258-261: 更新相关房间遍历逻辑,移除局部定义的 room_names 列表,并直接复用
shiyu_defense_const.ROOM_NAMES;在循环中通过该常量按 room_idx 获取房间名称,保留现有 room_count 遍历行为。

In `@src/zzz_od/config/team_config.py`:
- Around line 71-84: 抽取私有 helper 统一处理成员列表的 agent_id 提取及用 unknown 补齐逻辑,并让
update_team_by_idx 与 update_team_members 复用该 helper;保持当前最多 3 名成员及现有更新行为不变。

In `@src/zzz_od/gui/view/devtools/shiyu_defense_team_test_interface.py`:
- Line 28: 为 devtools 防御队伍测试界面的 __init__ 方法中的 parent 参数添加合适的类型注解;保持现有的 __init__
签名风格,不添加 -> None 返回类型,也不要修改其他参数或逻辑。

In `@src/zzz_od/operation/choose_predefined_team.py`:
- Around line 373-422:
合并_find_select_button与_find_selected_button的重复候选查找逻辑,提取一个接收文本判定谓词的私有方法,并让两个现有方法分别传入对应的判定条件;同时将偏移范围300/850/40/250及期望位置650/130提取为类常量,确保行为保持不变。
- Line 64: Update the operation-name construction around op_name so shiyu mode
does not append target_team_idx_list when it is None. Use the existing mode
indicator to omit the suffix or label it as automatic team selection, while
preserving the target-list suffix for modes where _select_shiyu_teams is not
responsible for determining the teams.
- Around line 517-522: 在 choose team card 区域提取统一的
_get_team_card_rect(team_name_mr) 辅助方法,集中定义 -10、+800、+250 偏移量;更新当前 Rect 构造及
_recognize_team_agents 中的重复逻辑,全部复用该方法,确保槽位判定与头像识别使用完全相同的区域。
- Around line 353-359: 在处理 shiyu_click_target_list 的逻辑中,显式校验其所有元素都与
shiyu_target_list 中的对象保持同一引用关系,而非仅通过值相等判断。将该校验放在生成 target_team_idx_list
之前,失败时立即触发断言;保留现有 team_idx 提取及非负值判断。
- Around line 71-74: 将初始化方法中的 self.shiyu_target_list 和
self.shiyu_click_target_list 属性注解统一改为字符串形式
"DefensePhaseTeamInfo",与参数注解保持一致;保留现有可选类型和赋值逻辑不变。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 237a0c48-9f1d-4b4f-9789-3064345204c9

📥 Commits

Reviewing files that changed from the base of the PR and between 9fd5ccf and ee7310c.

📒 Files selected for processing (37)
  • config/auto_battle/全配队通用.merged.yml
  • config/auto_battle/全配队通用.sample.yml
  • config/auto_battle/击破站场-强攻速切.merged.yml
  • config/auto_battle/异常站场-强攻速切.merged.yml
  • config/auto_battle/强攻站场-击破支援速切.merged.yml
  • config/auto_battle/自动守护.merged.yml
  • config/auto_battle/自动守护.sample.yml
  • config/auto_battle_operation/双反-上一个.sample.yml
  • config/auto_battle_operation/双反-下一个.sample.yml
  • config/auto_battle_operation/简-普通攻击.sample.yml
  • config/auto_battle_operation/简-萨霍夫跳.sample.yml
  • config/auto_battle_operation/简-萨霍夫跳合轴.sample.yml
  • config/auto_battle_operation/简-长按A合轴.sample.yml
  • config/auto_battle_operation/维琳娜-强化特殊技合轴.sample.yml
  • config/auto_battle_operation/蕾米埃尔-长按普攻.sample.yml
  • config/auto_battle_operation/薇薇安-强化特殊技合轴.sample.yml
  • config/auto_battle_state_handler/双反模板-命破.sample.yml
  • config/auto_battle_state_handler/轮换-紧急-全角色.sample.yml
  • config/auto_battle_state_handler/速切模板-简.sample.yml
  • config/auto_battle_state_handler/速切模板-维琳娜.sample.yml
  • config/auto_battle_state_handler/速切模板-蕾米埃尔.sample.yml
  • docs/game/gameplay/式舆防卫战.md
  • docs/game/screens/式舆防卫战.md
  • src/one_dragon/base/controller/pc_controller_base.py
  • src/zzz_od/application/devtools/shiyu_defense_team_test/__init__.py
  • src/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_app.py
  • src/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_app_factory.py
  • src/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_config.py
  • src/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_const.py
  • src/zzz_od/application/shiyu_defense/shiyu_defense_app.py
  • src/zzz_od/application/shiyu_defense/shiyu_defense_app_setting.py
  • src/zzz_od/application/shiyu_defense/shiyu_defense_team_utils.py
  • src/zzz_od/config/team_config.py
  • src/zzz_od/gui/app_setting/shiyu_defense_setting_interface.py
  • src/zzz_od/gui/view/devtools/app_devtools_interface.py
  • src/zzz_od/gui/view/devtools/shiyu_defense_team_test_interface.py
  • src/zzz_od/operation/choose_predefined_team.py
💤 Files with no reviewable changes (4)
  • src/zzz_od/application/shiyu_defense/shiyu_defense_app_setting.py
  • src/zzz_od/gui/app_setting/shiyu_defense_setting_interface.py
  • config/auto_battle_operation/简-长按A合轴.sample.yml
  • config/auto_battle_operation/薇薇安-强化特殊技合轴.sample.yml

Comment on lines 48 to 51
- states: "[维琳娜-风华]{85,135}"
interrupt_states: "[按键可用-快速支援]" # 不可用时打断
debug_name: "龙卷风"
debug_name: "高风华长按普攻"
operations:
- operation_template: "维琳娜-长按普攻"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C3 'interrupt_states_cal_tree|match_execution\(' src/one_dragon
rg -n -C3 '维琳娜-风华.*85|维琳娜-长按普攻' config

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 14621


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Top candidate files:"
fd -a 'execution|scenario|loop|operator|state_handler|scene' src/one_dragon/base src/one_dragon 2>/dev/null | sed 's#^\./##' | head -80

echo
echo "state_handler.py outline:"
ast-grep outline src/one_dragon/base/conditional_operation/state_handler.py || true

echo
echo "operator.py outline:"
ast-grep outline src/one_dragon/base/conditional_operation/operator.py || true

echo
echo "Scene/operator execution related lines:"
sed -n '1,260p' src/one_dragon/base/conditional_operation/operator.py
echo
sed -n '1,220p' src/one_dragon/base/conditional_operation/state_handler.py
echo
sed -n '1,140p' src/one_dragon/base/conditional_operation/execution.py 2>/dev/null || true
sed -n '1,120p' src/one_dragon/base/conditional_operation/scene.py 2>/dev/null || true

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 19723


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "operation_executor.py:"
ast-grep outline src/one_dragon/base/conditional_operation/operation_executor.py || true
sed -n '1,220p' src/one_dragon/base/conditional_operation/operation_executor.py

echo
echo "execution_info.py:"
sed -n '1,220p' src/one_dragon/base/conditional_operation/execution_info.py

echo
echo "OperationExecutor references:"
rg -n -C2 'running_executor_cnt|while|stop|ExecutionInfo|interrupt_states|op_list' src/one_dragon/base/conditional_operation/operation_executor.py src/one_dragon/base/conditional_operation/execution_info.py

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 11742


恢复长按期间的快速支援打断条件。

ExecutionInfo 会传递到 _run,但 OperationExecutor._run 执行操作期间不会读取 interrupt_cal_tree;只有触发场景通过优先级对比调用 _stop_running_task() 才能打断。速切移除这个条件后,维琳娜高风华长按期间不会响应 按键可用-快速支援,建议保留或改为更合理的打断配置。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/auto_battle_state_handler/速切模板-维琳娜.sample.yml` around lines 48 - 51,
在配置中恢复“高风华长按普攻”状态对“按键可用-快速支援”的打断条件,或调整为等效且合理的 interrupt_cal_tree
配置;确保维琳娜执行“维琳娜-长按普攻”期间能通过优先级触发 _stop_running_task() 响应快速支援。

Comment on lines +39 to +58
def set_target_dmg_type(
self,
target_idx: int,
is_weakness: bool,
type_idx: int,
new_value: str,
) -> None:
key = self._get_target_dmg_type_key(target_idx, is_weakness, type_idx)
self.update(key, new_value)

def get_target_list(self) -> list['DefensePhaseTeamInfo']:
from zzz_od.application.shiyu_defense.shiyu_defense_team_utils import (
DefensePhaseTeamInfo,
)

target_list: list[DefensePhaseTeamInfo] = []
for target_idx in range(min(max(self.target_count, 1), 3)):
weakness_list = self._get_target_dmg_type_list(target_idx, True)
resistance_list = self._get_target_dmg_type_list(target_idx, False)
target_list.append(DefensePhaseTeamInfo(weakness_list, resistance_list))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

禁止同一属性同时作为弱点和抗性。

评分逻辑先检查弱点,因此重叠属性的抗性选择会被静默忽略,可能导致配队评分不符合界面配置。

  • src/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_config.py#L39-L58: 在写入或生成目标列表时拒绝/规范化弱点与抗性的交集。
  • src/zzz_od/gui/view/devtools/shiyu_defense_team_test_interface.py#L62-L103: 用户选择某属性后,禁用或清除另一侧相同属性,并同步对应配置与控件状态。
📍 Affects 2 files
  • src/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_config.py#L39-L58 (this comment)
  • src/zzz_od/gui/view/devtools/shiyu_defense_team_test_interface.py#L62-L103
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_config.py`
around lines 39 - 58, Prevent the same damage type from appearing in both
weaknesses and resistances. In
src/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_config.py
lines 39-58, update set_target_dmg_type and/or get_target_list to reject or
normalize overlapping values before persistence or list generation. In
src/zzz_od/gui/view/devtools/shiyu_defense_team_test_interface.py lines 62-103,
when a type is selected on one side, disable or clear the matching type on the
other side and synchronize the configuration and control states.

Comment on lines 132 to 139
result1 = self.round_by_find_and_click_area(
self.last_screenshot, '式舆防卫战', '节点-05'
self.last_screenshot,
'式舆防卫战',
'节点-05',
)
if result1.is_success:
return self.round_success(result1.status, wait=1)
return self.round_retry(result1.status, wait=1)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

多间模式分支缺少「拖动找节点」兜底,节点-05 不在视野内时会直接重试到失败。

普通节点分支在找不到按钮时会先看「下一步」,再拖动 节点区域 换视野(第 149-157 行)。多间分支只有点击成功/重试两条路,而节点-05 恰恰是列表最右侧、最可能需要拖动才可见的一个。建议复用同一套兜底逻辑。

🐛 建议补充拖动兜底
             if result1.is_success:
                 return self.round_success(result1.status, wait=1)
+
+            area = self.ctx.screen_loader.get_area('式舆防卫战', '节点区域')
+            start_point = area.rect.center
+            self.ctx.controller.drag_to(start=start_point, end=start_point + Point(-300, 0))
             return self.round_retry(result1.status, wait=1)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
result1 = self.round_by_find_and_click_area(
self.last_screenshot, '式舆防卫战', '节点-05'
self.last_screenshot,
'式舆防卫战',
'节点-05',
)
if result1.is_success:
return self.round_success(result1.status, wait=1)
return self.round_retry(result1.status, wait=1)
result1 = self.round_by_find_and_click_area(
self.last_screenshot,
'式舆防卫战',
'节点-05',
)
if result1.is_success:
return self.round_success(result1.status, wait=1)
area = self.ctx.screen_loader.get_area('式舆防卫战', '节点区域')
start_point = area.rect.center
self.ctx.controller.drag_to(start=start_point, end=start_point + Point(-300, 0))
return self.round_retry(result1.status, wait=1)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_app.py` around lines 132 -
139, 在多间模式处理节点-05的分支中,更新 round_by_find_and_click_area
失败后的逻辑,复用普通节点分支的兜底流程:先检查并点击「下一步」,仍未找到时拖动「节点区域」重新寻找节点-05。仅在这些兜底操作都失败后调用
round_retry,成功则按现有方式调用 round_success。

Comment on lines 274 to 302
attribute_area = ctx.screen_loader.get_area(screen_template, f'{room_name}属性')
if attribute_area is None:
target_list.append(
DefensePhaseTeamInfo(
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
)
)
continue
ocr_result = ctx.ocr.crop_and_run_ocr(screen, area.rect)

# 收集所有包含"属性"的文本及 y 坐标
items: list[tuple[int, str]] = []
boundary_y: int | None = None
for text, match_list in ocr_result.items():
attribute_ocr_result = ctx.ocr.crop_and_run_ocr(screen, attribute_area.rect)
item_list: list[tuple[int, str]] = []
resistance_boundary_y: int | None = None
for text, match_list in attribute_ocr_result.items():
if '强敌抗性' in text:
for match in match_list:
boundary_y = match.y
resistance_boundary_y = match.y
elif '属性' in text:
for match in match_list:
items.append((match.y, text))

if len(items) == 0 or boundary_y is None:
# 属性识别失败,保留未知属性,不标记已完成跳过
team_list.append(DefensePhaseTeamInfo([DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN]))
item_list.append((match.y, text))

if len(item_list) == 0 or resistance_boundary_y is None:
target_list.append(
DefensePhaseTeamInfo(
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
)
)
continue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

属性识别失败被静默降级成「无偏好配队」,既不失败也无日志。

attribute_area is None(第 275 行)和 OCR 未解析出属性/边界(第 295 行)两条分支都回填全 UNKNOWNis_completed=False。下游 multi_room_select 会照常选中该房间,select_teams 对全 UNKNOWN 目标的每项 _get_dmg_type_score 都返回 1,于是照常选出一支「完全没有克制关系」的队伍出战,用户无从得知识别已经失败。

基于 learnings(式舆多间流程中 OCR/区域识别失败应走显式失败/退出路径,不要静默落入正常配队路径),建议至少打 warning 日志,并让调用方能区分「识别失败」与「正常识别到无属性」。

🛡️ 建议补充失败可见性
         attribute_area = ctx.screen_loader.get_area(screen_template, f'{room_name}属性')
         if attribute_area is None:
+            log.warning('%s 属性区域缺失,本间将按无属性偏好配队', room_name)
             target_list.append(
                 DefensePhaseTeamInfo(
                     [DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
                     [DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
                 )
             )
             continue
@@
         if len(item_list) == 0 or resistance_boundary_y is None:
+            log.warning('%s 属性识别失败 属性项:%d 抗性边界:%s', room_name, len(item_list), resistance_boundary_y)
             target_list.append(
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
attribute_area = ctx.screen_loader.get_area(screen_template, f'{room_name}属性')
if attribute_area is None:
target_list.append(
DefensePhaseTeamInfo(
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
)
)
continue
ocr_result = ctx.ocr.crop_and_run_ocr(screen, area.rect)
# 收集所有包含"属性"的文本及 y 坐标
items: list[tuple[int, str]] = []
boundary_y: int | None = None
for text, match_list in ocr_result.items():
attribute_ocr_result = ctx.ocr.crop_and_run_ocr(screen, attribute_area.rect)
item_list: list[tuple[int, str]] = []
resistance_boundary_y: int | None = None
for text, match_list in attribute_ocr_result.items():
if '强敌抗性' in text:
for match in match_list:
boundary_y = match.y
resistance_boundary_y = match.y
elif '属性' in text:
for match in match_list:
items.append((match.y, text))
if len(items) == 0 or boundary_y is None:
# 属性识别失败,保留未知属性,不标记已完成跳过
team_list.append(DefensePhaseTeamInfo([DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN]))
item_list.append((match.y, text))
if len(item_list) == 0 or resistance_boundary_y is None:
target_list.append(
DefensePhaseTeamInfo(
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
)
)
continue
attribute_area = ctx.screen_loader.get_area(screen_template, f'{room_name}属性')
if attribute_area is None:
log.warning('%s 属性区域缺失,本间将按无属性偏好配队', room_name)
target_list.append(
DefensePhaseTeamInfo(
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
)
)
continue
attribute_ocr_result = ctx.ocr.crop_and_run_ocr(screen, attribute_area.rect)
item_list: list[tuple[int, str]] = []
resistance_boundary_y: int | None = None
for text, match_list in attribute_ocr_result.items():
if '强敌抗性' in text:
for match in match_list:
resistance_boundary_y = match.y
elif '属性' in text:
for match in match_list:
item_list.append((match.y, text))
if len(item_list) == 0 or resistance_boundary_y is None:
log.warning('%s 属性识别失败 属性项:%d 抗性边界:%s', room_name, len(item_list), resistance_boundary_y)
target_list.append(
DefensePhaseTeamInfo(
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
[DmgTypeEnum.UNKNOWN, DmgTypeEnum.UNKNOWN],
)
)
continue
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/application/shiyu_defense/shiyu_defense_team_utils.py` around
lines 274 - 302, Update the attribute-detection flow around attribute_area and
the OCR validation branches to make recognition failures explicit: emit a
warning with the room/context and failure reason, and propagate a
distinguishable failure state to the caller instead of treating both cases as a
normal all-UNKNOWN DefensePhaseTeamInfo. Preserve the existing UNKNOWN
representation only for successfully recognized rooms that genuinely have no
attribute preference, and update the calling flow so failed recognition does not
proceed through normal multi_room_select/team selection.

Source: Learnings

@node_from(from_name='尝试查找编队')
@node_from(from_name='画面识别', status=STATUS_TEAM_LIST_READY)
@node_from(from_name='选择编队', status=STATUS_CONTINUE_CHOOSE)
@operation_node(name='选择编队')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 确认 operation_node 默认重试次数,以及 round_wait/round_retry 对计数的影响
rg -nP -C6 'node_max_retry_times' src/one_dragon/base/operation/operation_node.py
rg -nP -C8 '\bdef round_retry\s*\(|\bdef round_wait\s*\(' src/one_dragon/base/operation/operation.py

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 4159


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
git ls-files | rg 'operation_node.py|operation.py|choose_predefined_team.py|shiyu_defense_app.py' || true

echo
echo "== retry control references =="
rg -n -C 4 'node_max_retry_times|current_retry|retry_count|round_retry|round_wait|OperationRoundResultEnum' src/one_dragon/base/operation operation_node.py operation.py 2>/dev/null || true

echo
echo "== choose_predefined_team outline and relevant lines =="
sed -n '1,230p' src/zzz_od/operation/choose_predefined_team.py
echo
sed -n '420,470p' src/zzz_od/operation/choose_predefined_team.py

echo
echo "== shiyu_defense_app relevant lines =="
sed -n '1,70p' src/zzz_od/application/shiyu_defense/shiyu_defense_app.py
echo
sed -n '240,305p' src/zzz_od/application/shiyu_defense/shiyu_defense_app.py
echo
rg -n -C 3 '`@operation_node`' src/zzz_od/application/shiyu_defense/shiyu_defense_app.py

echo
echo "== operation retry execution references =="
rg -n -C 6 'operation_node_annotation|node_max_retry_times|round_result|OperationResultEnum|OperationRoundResultEnum|execute' src/zzz_od/operation/choose_predefined_team.py src/one_dragon/base src/zzz_od/application -g '*.py' | head -n 240

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 50400


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== operation.py retry loop =="
sed -n '445,468p' src/one_dragon/base/operation/operation.py

echo
echo "== shiyu_defense_app node annotations =="
rg -n -C 2 '`@operation_node`' src/zzz_od/application/shiyu_defense/shiyu_defense_app.py

echo
echo "== choose_predefined_team retry calls =="
rg -n 'round_retry|round_wait|round_success|round_fail|`@operation_node`|target_team_idx_list|ChoosePredefinedTeam' src/zzz_od/operation/choose_predefined_team.py src/zzz_od/application/shiyu_defense/shiyu_defense_app.py

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 15688


新增/重写的编队选择节点要显式声明 node_max_retry_times 目前这两个节点依赖框架默认 3 次重试预算,但流程中有多轮 round_retry 和等待画面的 round_wait;其中 选择编队 的扫描/翻页和确认点击可能跨编队累计重试,容易未达实际等待预算就降级为失败。

  • src/zzz_od/operation/choose_predefined_team.py#L110-L110选择编队 节点包含多轮找元素重试和等待画面,需要显式设置足够的重试上限。
  • src/zzz_od/application/shiyu_defense/shiyu_defense_app.py#L264-L296多间-等待预备编队 也使用 round_retry 反复点「下一步」等待界面出现;与同文件其它多间节点统一为 node_max_retry_times=30
📍 Affects 2 files
  • src/zzz_od/operation/choose_predefined_team.py#L110-L110 (this comment)
  • src/zzz_od/application/shiyu_defense/shiyu_defense_app.py#L264-L296
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/operation/choose_predefined_team.py` at line 110, These operation
nodes currently rely on the framework's default 3 retry attempts but contain
multiple rounds of round_retry and round_wait that accumulate retries, causing
premature failure without reaching the actual wait budget. In
src/zzz_od/operation/choose_predefined_team.py at line 110, add an explicit
node_max_retry_times parameter to the operation_node decorator for the 选择编队 node
with a value sufficient for the multiple rounds of element finding and
confirmation clicks. In
src/zzz_od/application/shiyu_defense/shiyu_defense_app.py at lines 264-296, set
node_max_retry_times=30 for the 多间-等待预备编队 node to unify it with other multi-room
nodes in the same file that use round_retry to repeatedly click through
interface transitions.

Comment on lines +296 to +316
if len(agent_list) == 0:
log.info('预备编队扫描结束:队名:%s 三个代理人位均为空', team_name)
return True

def __debug():
ctx = ZContext()
ctx.init()
ctx.init_ocr()
team_idx = self.next_scanned_team_idx
if team_idx >= self.MAX_TEAM_COUNT:
log.info('预备编队扫描结束:已达到最大队伍数量:%d', self.MAX_TEAM_COUNT)
return True
# 被禁用的队伍不参与自动配队,但仍占用游戏列表中的位置。
# 必须先递增真实序号,再跳过候选列表;否则后续有效队会错位。
self.next_scanned_team_idx += 1
self.scanned_team_name_set.add(team_name)

from one_dragon.utils import debug_utils
screen = debug_utils.get_debug_image('img')
print(ctx.ocr.run_ocr(screen))
if agent_slot_set != {'1P', '2P', '3P'}:
log.info(
'预备编队不可用:序号:%d 队名:%s 代理人槽位不完整:%s',
team_idx + 1,
team_name,
sorted(agent_slot_set),
)
continue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

空队判定排在禁用队判定之前,禁用队头像识别失败会提前终止整轮扫描。

第 296 行只要 len(agent_list) == 0return True 结束扫描,而槽位完整性检查在第 309 行。被禁用的队伍头像本来就更容易识别失败(灰显/遮罩),一旦某个禁用队 agent_list 为空,它会被当成「首个空队」,扫描直接结束,其后所有有效编队全部丢失 —— 这与第 304-305 行「禁用队要保留序号继续扫描」的意图相矛盾。

建议先看槽位:1P/2P/3P 都缺失才是真的空队;槽位存在而头像识别不到,应按禁用队处理并继续。

🐛 建议调整判定顺序
-                if len(agent_list) == 0:
-                    log.info('预备编队扫描结束:队名:%s 三个代理人位均为空', team_name)
-                    return True
-
                 team_idx = self.next_scanned_team_idx
                 if team_idx >= self.MAX_TEAM_COUNT:
                     log.info('预备编队扫描结束:已达到最大队伍数量:%d', self.MAX_TEAM_COUNT)
                     return True
+
+                if len(agent_slot_set) == 0 and len(agent_list) == 0:
+                    log.info('预备编队扫描结束:队名:%s 三个代理人位均为空', team_name)
+                    return True
+
                 # 被禁用的队伍不参与自动配队,但仍占用游戏列表中的位置。
                 # 必须先递增真实序号,再跳过候选列表;否则后续有效队会错位。
                 self.next_scanned_team_idx += 1
                 self.scanned_team_name_set.add(team_name)
 
-                if agent_slot_set != {'1P', '2P', '3P'}:
+                if agent_slot_set != {'1P', '2P', '3P'} or len(agent_list) == 0:
                     log.info(
                         '预备编队不可用:序号:%d 队名:%s 代理人槽位不完整:%s',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if len(agent_list) == 0:
log.info('预备编队扫描结束:队名:%s 三个代理人位均为空', team_name)
return True
def __debug():
ctx = ZContext()
ctx.init()
ctx.init_ocr()
team_idx = self.next_scanned_team_idx
if team_idx >= self.MAX_TEAM_COUNT:
log.info('预备编队扫描结束:已达到最大队伍数量:%d', self.MAX_TEAM_COUNT)
return True
# 被禁用的队伍不参与自动配队,但仍占用游戏列表中的位置。
# 必须先递增真实序号,再跳过候选列表;否则后续有效队会错位。
self.next_scanned_team_idx += 1
self.scanned_team_name_set.add(team_name)
from one_dragon.utils import debug_utils
screen = debug_utils.get_debug_image('img')
print(ctx.ocr.run_ocr(screen))
if agent_slot_set != {'1P', '2P', '3P'}:
log.info(
'预备编队不可用:序号:%d 队名:%s 代理人槽位不完整:%s',
team_idx + 1,
team_name,
sorted(agent_slot_set),
)
continue
team_idx = self.next_scanned_team_idx
if team_idx >= self.MAX_TEAM_COUNT:
log.info('预备编队扫描结束:已达到最大队伍数量:%d', self.MAX_TEAM_COUNT)
return True
if len(agent_slot_set) == 0 and len(agent_list) == 0:
log.info('预备编队扫描结束:队名:%s 三个代理人位均为空', team_name)
return True
# 被禁用的队伍不参与自动配队,但仍占用游戏列表中的位置。
# 必须先递增真实序号,再跳过候选列表;否则后续有效队会错位。
self.next_scanned_team_idx += 1
self.scanned_team_name_set.add(team_name)
if agent_slot_set != {'1P', '2P', '3P'} or len(agent_list) == 0:
log.info(
'预备编队不可用:序号:%d 队名:%s 代理人槽位不完整:%s',
team_idx + 1,
team_name,
sorted(agent_slot_set),
)
continue
🧰 Tools
🪛 Ruff (0.16.0)

[warning] 304-304: Comment contains ambiguous (FULLWIDTH COMMA). Did you mean , (COMMA)?

(RUF003)


[warning] 305-305: Comment contains ambiguous (FULLWIDTH COMMA). Did you mean , (COMMA)?

(RUF003)


[warning] 305-305: Comment contains ambiguous (FULLWIDTH SEMICOLON). Did you mean ; (SEMICOLON)?

(RUF003)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/operation/choose_predefined_team.py` around lines 296 - 316,
调整预备编队扫描逻辑中 agent_list 为空的判定顺序:先依据 agent_slot_set 判断队伍是否具备 1P、2P、3P
槽位;仅当三个槽位都缺失时才在 choose_predefined_team 的扫描流程中返回空队结束。槽位存在但 agent_list
为空的队伍应按禁用队处理,保留真实序号并继续扫描,不要提前终止后续有效编队的发现。

Comment on lines +446 to +454
@staticmethod
def _is_selected_text(normalized_text: str) -> bool:
"""统一已选按钮的 OCR 结果,仅在目标卡片的按钮区域内使用。"""
return (
normalized_text == 'SELECTED'
or normalized_text == 'TEAM'
or normalized_text.startswith('TEAM')
or re.fullmatch(r'\d{2}', normalized_text) is not None
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

\d{2} 把任意两位数字当作已选态,可能命中代理人等级。

_find_selected_button 的偏移窗口(x 300-850、y 40-250)与 _get_team_agent_slot_set 使用的代理人卡片区域基本重合,而该区域内本来就有代理人等级(两位数,如 60)。一旦等级框被当成「已选按钮」,第 219 行会把等级框中心存进 pending_cancel_button_center,之后 _is_select_button_visible 在错误位置找 SELECT,必然反复 round_retry 直至节点失败。

建议把数字判定收紧(例如限定为选队序号的取值范围,或要求其 x 偏移落在按钮列的窄区间内)。另外第 451-452 行 == 'TEAM' 已被 startswith('TEAM') 完全覆盖,可以删掉。

🐛 建议收紧判定
     `@staticmethod`
     def _is_selected_text(normalized_text: str) -> bool:
         """统一已选按钮的 OCR 结果,仅在目标卡片的按钮区域内使用。"""
         return (
             normalized_text == 'SELECTED'
-            or normalized_text == 'TEAM'
             or normalized_text.startswith('TEAM')
-            or re.fullmatch(r'\d{2}', normalized_text) is not None
+            # 选队序号只可能是 01~03,避免命中代理人等级
+            or re.fullmatch(r'0[1-3]', normalized_text) is not None
         )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@staticmethod
def _is_selected_text(normalized_text: str) -> bool:
"""统一已选按钮的 OCR 结果,仅在目标卡片的按钮区域内使用。"""
return (
normalized_text == 'SELECTED'
or normalized_text == 'TEAM'
or normalized_text.startswith('TEAM')
or re.fullmatch(r'\d{2}', normalized_text) is not None
)
`@staticmethod`
def _is_selected_text(normalized_text: str) -> bool:
"""统一已选按钮的 OCR 结果,仅在目标卡片的按钮区域内使用。"""
return (
normalized_text == 'SELECTED'
or normalized_text.startswith('TEAM')
# 选队序号只可能是 01~03,避免命中代理人等级
or re.fullmatch(r'0[1-3]', normalized_text) is not None
)
🧰 Tools
🪛 Ruff (0.16.0)

[warning] 448-448: Docstring contains ambiguous (FULLWIDTH COMMA). Did you mean , (COMMA)?

(RUF002)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/zzz_od/operation/choose_predefined_team.py` around lines 446 - 454, 收紧
_is_selected_text 的数字判定,避免将代理人卡片中的任意两位等级识别为已选按钮;仅接受选队序号的有效范围,或结合按钮列的窄 x
偏移进行校验,并将所需位置信息从 _find_selected_button 传入。删除被 startswith('TEAM') 覆盖的
normalized_text == 'TEAM' 分支,保持 SELECTED 和 TEAM 前缀识别不变。

@kawayiYokami
kawayiYokami force-pushed the feat/velina-void-hunter-awakening branch from a32367d to 0567803 Compare August 2, 2026 18:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@config/auto_battle/全配队通用.merged.yml`:
- Around line 10772-10780:
在速切区的“等待快速支援出现”分支及非速切区对应分支中,处理“自定义-蕾米埃尔-长按强化特殊技”状态:优先在两处“长按强化特殊技”分支补上该状态的设置点,并保持两份配置一致;若不设置,则从两处清除列表中移除该状态名。涉及
config/auto_battle/全配队通用.merged.yml#10772-10780(锚点)和 `#21572-21580`(同样修改)。
- Around line 12866-12899:
为“维琳娜高风华切入”子分支补充与另一子分支一致的“维琳娜-特殊技可用”条件,并增加失衡期约束,确保仅在允许的非失衡场景下切入;保留现有“维琳娜-风华”状态及普攻序列不变。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1f1b5d0e-4034-43d7-9907-908873d231c5

📥 Commits

Reviewing files that changed from the base of the PR and between a32367d and 0567803.

📒 Files selected for processing (20)
  • config/auto_battle/全配队通用.merged.yml
  • config/auto_battle/全配队通用.sample.yml
  • config/auto_battle/击破站场-强攻速切.merged.yml
  • config/auto_battle/异常站场-强攻速切.merged.yml
  • config/auto_battle/强攻站场-击破支援速切.merged.yml
  • config/auto_battle/自动守护.merged.yml
  • config/auto_battle/自动守护.sample.yml
  • config/auto_battle_operation/双反-上一个.sample.yml
  • config/auto_battle_operation/双反-下一个.sample.yml
  • config/auto_battle_operation/简-普通攻击.sample.yml
  • config/auto_battle_operation/简-萨霍夫跳.sample.yml
  • config/auto_battle_operation/简-萨霍夫跳合轴.sample.yml
  • config/auto_battle_operation/简-长按A合轴.sample.yml
  • config/auto_battle_operation/维琳娜-强化特殊技合轴.sample.yml
  • config/auto_battle_operation/薇薇安-强化特殊技合轴.sample.yml
  • config/auto_battle_state_handler/双反模板-命破.sample.yml
  • config/auto_battle_state_handler/轮换-紧急-全角色.sample.yml
  • config/auto_battle_state_handler/速切模板-简.sample.yml
  • config/auto_battle_state_handler/速切模板-维琳娜.sample.yml
  • config/auto_battle_state_handler/速切模板-蕾米埃尔.sample.yml
💤 Files with no reviewable changes (2)
  • config/auto_battle_operation/简-长按A合轴.sample.yml
  • config/auto_battle_operation/薇薇安-强化特殊技合轴.sample.yml
🚧 Files skipped from review as they are similar to previous changes (17)
  • config/auto_battle_operation/双反-上一个.sample.yml
  • config/auto_battle_operation/简-普通攻击.sample.yml
  • config/auto_battle_operation/双反-下一个.sample.yml
  • config/auto_battle/全配队通用.sample.yml
  • config/auto_battle/自动守护.sample.yml
  • config/auto_battle_state_handler/双反模板-命破.sample.yml
  • config/auto_battle_operation/简-萨霍夫跳.sample.yml
  • config/auto_battle_operation/简-萨霍夫跳合轴.sample.yml
  • config/auto_battle/异常站场-强攻速切.merged.yml
  • config/auto_battle_state_handler/轮换-紧急-全角色.sample.yml
  • config/auto_battle_operation/维琳娜-强化特殊技合轴.sample.yml
  • config/auto_battle_state_handler/速切模板-蕾米埃尔.sample.yml
  • config/auto_battle_state_handler/速切模板-维琳娜.sample.yml
  • config/auto_battle_state_handler/速切模板-简.sample.yml
  • config/auto_battle/自动守护.merged.yml
  • config/auto_battle/击破站场-强攻速切.merged.yml
  • config/auto_battle/强攻站场-击破支援速切.merged.yml

Comment on lines +10772 to +10780
- "debug_name": "等待快速支援出现"
"operations":
- "op_name": "清除状态"
"state_list":
- "自定义-动作不打断"
- "自定义-无视闪光"
- "自定义-蕾米埃尔-长按强化特殊技"
- "op_name": "按键-快速支援"
"states": "[按键可用-快速支援]"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

两处蕾米埃尔分支清除了从未被设置的状态。 根因是 自定义-蕾米埃尔-长按强化特殊技 在整个配置中没有任何“设置状态”写入点,两处“等待快速支援出现”分支的清除操作因此无效。

  • config/auto_battle/全配队通用.merged.yml#L10772-L10780:在速切区补上该状态的设置点(行 10799-10816 的「长按强化特殊技」分支),或从清除列表中移除该状态名。
  • config/auto_battle/全配队通用.merged.yml#L21572-L21580:在非速切区做同样处理,保持两份配置一致。
📍 Affects 1 file
  • config/auto_battle/全配队通用.merged.yml#L10772-L10780 (this comment)
  • config/auto_battle/全配队通用.merged.yml#L21572-L21580
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/auto_battle/全配队通用.merged.yml` around lines 10772 - 10780,
在速切区的“等待快速支援出现”分支及非速切区对应分支中,处理“自定义-蕾米埃尔-长按强化特殊技”状态:优先在两处“长按强化特殊技”分支补上该状态的设置点,并保持两份配置一致;若不设置,则从两处清除列表中移除该状态名。涉及
config/auto_battle/全配队通用.merged.yml#10772-10780(锚点)和 `#21572-21580`(同样修改)。

Comment on lines +12866 to +12899
- "debug_name": "维琳娜紧急切入"
"states": "![前台-维琳娜]"
"sub_handlers":
- "debug_name": "维琳娜高风华切入"
"interrupt_states": "[按键可用-快速支援]"
"operations":
- "agent_name": "维琳娜"
"op_name": "按键-切换角色"
- "op_name": "设置状态"
"seconds": 3
"state": "自定义-动作不打断"
- "op_name": "按键-普通攻击-松开"
- "op_name": "按键-普通攻击-按下"
- "op_name": "等待秒数"
"seconds": 0.5
- "op_name": "按键-普通攻击-按下"
- "op_name": "等待秒数"
"seconds": 0.5
- "op_name": "按键-普通攻击-按下"
- "op_name": "等待秒数"
"seconds": 0.5
- "op_name": "按键-普通攻击-按下"
- "op_name": "等待秒数"
"seconds": 0.5
- "op_name": "按键-普通攻击-按下"
- "op_name": "等待秒数"
"seconds": 0.5
- "op_name": "按键-普通攻击-按下"
- "op_name": "等待秒数"
"seconds": 0.5
- "op_name": "按键-普通攻击-松开"
- "op_name": "清除状态"
"state": "自定义-动作不打断"
"states": "[维琳娜-风华]{85,135}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 描述:列出“紧急切人检查”块内各角色切入分支的 states 条件,便于对比失衡期约束。
rg -n -A 3 '紧急切入' config/auto_battle/全配队通用.merged.yml | head -80

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 838


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== target block =="
sed -n '12750,12925p' config/auto_battle/全配队通用.merged.yml | cat -n

echo
echo "== relevant lines =="
sed -n '12710,12920p' config/auto_battle/全配队通用.merged.yml

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 15121


为维琳娜紧急切入补充失衡期约束。

两个子分支只判断 [维琳娜-风华][维琳娜-特殊技可用];高风华分支还缺少 [维琳娜-特殊技可用]。这样在失衡期也会切入维琳娜前台并执行普攻/特殊技序列,可能抢占失衡期的主 C 输出。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/auto_battle/全配队通用.merged.yml` around lines 12866 - 12899,
为“维琳娜高风华切入”子分支补充与另一子分支一致的“维琳娜-特殊技可用”条件,并增加失衡期约束,确保仅在允许的非失衡场景下切入;保留现有“维琳娜-风华”状态及普攻序列不变。

@ShadowLemoon
ShadowLemoon merged commit f1f274b into OneDragon-Anything:main Aug 3, 2026
7 of 8 checks passed
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Aug 7, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants