feat: 优化维琳娜和简战斗模板 - #2605
Conversation
📝 WalkthroughWalkthrough本次更新调整自动战斗配置的黄光切人节奏、双反模板路由、简的萨霍夫跳合轴连段、蕾米埃尔快速支援、维琳娜风华分支,以及多角色紧急切入条件。 Changes自动战斗配置调整
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant 黄光识别
participant 状态处理器
participant 自动战斗操作
participant 角色状态
黄光识别->>状态处理器: 选择双反模板或角色处理器
状态处理器->>自动战斗操作: 执行闪避、普攻、技能或角色切换
自动战斗操作->>角色状态: 设置黄光切人、萨霍夫跳或合轴状态
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
ee7310c to
a32367d
Compare
There was a problem hiding this comment.
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_prepare的target_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 valueshiyu 模式下
op_name会显示为选择预备编队 None。此时
target_team_idx_list为None,真实目标要到_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_END从duration中扣除,以保持「duration= 拖拽总时长」的约定;而这次新增的time.sleep(0.1)没有做同样处理,于是每次拖拽的实际耗时都比调用方声明的duration多 0.1s。drag_mouse是所有前台drag_to的公共实现,这个偏移会累加到全部拖拽场景。同时建议按本文件既有风格(
SLEEP_BEFORE_DRAG_END、DRAG_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_names与shiyu_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
📒 Files selected for processing (37)
config/auto_battle/全配队通用.merged.ymlconfig/auto_battle/全配队通用.sample.ymlconfig/auto_battle/击破站场-强攻速切.merged.ymlconfig/auto_battle/异常站场-强攻速切.merged.ymlconfig/auto_battle/强攻站场-击破支援速切.merged.ymlconfig/auto_battle/自动守护.merged.ymlconfig/auto_battle/自动守护.sample.ymlconfig/auto_battle_operation/双反-上一个.sample.ymlconfig/auto_battle_operation/双反-下一个.sample.ymlconfig/auto_battle_operation/简-普通攻击.sample.ymlconfig/auto_battle_operation/简-萨霍夫跳.sample.ymlconfig/auto_battle_operation/简-萨霍夫跳合轴.sample.ymlconfig/auto_battle_operation/简-长按A合轴.sample.ymlconfig/auto_battle_operation/维琳娜-强化特殊技合轴.sample.ymlconfig/auto_battle_operation/蕾米埃尔-长按普攻.sample.ymlconfig/auto_battle_operation/薇薇安-强化特殊技合轴.sample.ymlconfig/auto_battle_state_handler/双反模板-命破.sample.ymlconfig/auto_battle_state_handler/轮换-紧急-全角色.sample.ymlconfig/auto_battle_state_handler/速切模板-简.sample.ymlconfig/auto_battle_state_handler/速切模板-维琳娜.sample.ymlconfig/auto_battle_state_handler/速切模板-蕾米埃尔.sample.ymldocs/game/gameplay/式舆防卫战.mddocs/game/screens/式舆防卫战.mdsrc/one_dragon/base/controller/pc_controller_base.pysrc/zzz_od/application/devtools/shiyu_defense_team_test/__init__.pysrc/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_app.pysrc/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_app_factory.pysrc/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_config.pysrc/zzz_od/application/devtools/shiyu_defense_team_test/shiyu_defense_team_test_const.pysrc/zzz_od/application/shiyu_defense/shiyu_defense_app.pysrc/zzz_od/application/shiyu_defense/shiyu_defense_app_setting.pysrc/zzz_od/application/shiyu_defense/shiyu_defense_team_utils.pysrc/zzz_od/config/team_config.pysrc/zzz_od/gui/app_setting/shiyu_defense_setting_interface.pysrc/zzz_od/gui/view/devtools/app_devtools_interface.pysrc/zzz_od/gui/view/devtools/shiyu_defense_team_test_interface.pysrc/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
| - states: "[维琳娜-风华]{85,135}" | ||
| interrupt_states: "[按键可用-快速支援]" # 不可用时打断 | ||
| debug_name: "龙卷风" | ||
| debug_name: "高风华长按普攻" | ||
| operations: | ||
| - operation_template: "维琳娜-长按普攻" |
There was a problem hiding this comment.
🎯 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|维琳娜-长按普攻' configRepository: 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 || trueRepository: 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.pyRepository: 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() 响应快速支援。
| 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)) |
There was a problem hiding this comment.
🎯 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.
| 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) |
There was a problem hiding this comment.
🩺 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.
| 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。
| 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 |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
属性识别失败被静默降级成「无偏好配队」,既不失败也无日志。
attribute_area is None(第 275 行)和 OCR 未解析出属性/边界(第 295 行)两条分支都回填全 UNKNOWN 且 is_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.
| 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='选择编队') |
There was a problem hiding this comment.
🩺 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.pyRepository: 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 240Repository: 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.pyRepository: 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.
| 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 |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
空队判定排在禁用队判定之前,禁用队头像识别失败会提前终止整轮扫描。
第 296 行只要 len(agent_list) == 0 就 return 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.
| 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
为空的队伍应按禁用队处理,保留真实序号并继续扫描,不要提前终止后续有效编队的发现。
| @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 | ||
| ) |
There was a problem hiding this comment.
🎯 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.
| @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 前缀识别不变。
a32367d to
0567803
Compare
There was a problem hiding this comment.
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
📒 Files selected for processing (20)
config/auto_battle/全配队通用.merged.ymlconfig/auto_battle/全配队通用.sample.ymlconfig/auto_battle/击破站场-强攻速切.merged.ymlconfig/auto_battle/异常站场-强攻速切.merged.ymlconfig/auto_battle/强攻站场-击破支援速切.merged.ymlconfig/auto_battle/自动守护.merged.ymlconfig/auto_battle/自动守护.sample.ymlconfig/auto_battle_operation/双反-上一个.sample.ymlconfig/auto_battle_operation/双反-下一个.sample.ymlconfig/auto_battle_operation/简-普通攻击.sample.ymlconfig/auto_battle_operation/简-萨霍夫跳.sample.ymlconfig/auto_battle_operation/简-萨霍夫跳合轴.sample.ymlconfig/auto_battle_operation/简-长按A合轴.sample.ymlconfig/auto_battle_operation/维琳娜-强化特殊技合轴.sample.ymlconfig/auto_battle_operation/薇薇安-强化特殊技合轴.sample.ymlconfig/auto_battle_state_handler/双反模板-命破.sample.ymlconfig/auto_battle_state_handler/轮换-紧急-全角色.sample.ymlconfig/auto_battle_state_handler/速切模板-简.sample.ymlconfig/auto_battle_state_handler/速切模板-维琳娜.sample.ymlconfig/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
| - "debug_name": "等待快速支援出现" | ||
| "operations": | ||
| - "op_name": "清除状态" | ||
| "state_list": | ||
| - "自定义-动作不打断" | ||
| - "自定义-无视闪光" | ||
| - "自定义-蕾米埃尔-长按强化特殊技" | ||
| - "op_name": "按键-快速支援" | ||
| "states": "[按键可用-快速支援]" |
There was a problem hiding this comment.
📐 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`(同样修改)。
| - "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}" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 描述:列出“紧急切人检查”块内各角色切入分支的 states 条件,便于对比失衡期约束。
rg -n -A 3 '紧急切入' config/auto_battle/全配队通用.merged.yml | head -80Repository: 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.ymlRepository: 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,
为“维琳娜高风华切入”子分支补充与另一子分支一致的“维琳娜-特殊技可用”条件,并增加失衡期约束,确保仅在允许的非失衡场景下切入;保留现有“维琳娜-风华”状态及普攻序列不变。
变更内容
验证
powershell -File skills/new-config/new-config.ps1生成 merged 配置。config/下全部 680 个 YAML 文件。git diff --check。Summary by CodeRabbit
新功能
优化