From e1fb52d6dd4085b6a3d9ee70b9da3262166c6b57 Mon Sep 17 00:00:00 2001 From: Beatrice-betty Date: Tue, 28 Jul 2026 00:22:36 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix(combat):=20=E8=87=AA=E5=8A=A8=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=88=98=E6=96=97=E4=B8=AD=E7=BB=93=E7=AE=97=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- module/coalition/coalition_scuttle.py | 18 +++++++++--------- module/combat/auto_search_combat.py | 19 +++++++++++++++---- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/module/coalition/coalition_scuttle.py b/module/coalition/coalition_scuttle.py index 340dc0c69..55eb95d36 100644 --- a/module/coalition/coalition_scuttle.py +++ b/module/coalition/coalition_scuttle.py @@ -7,7 +7,6 @@ OPTS_INFO_D, EXP_INFO_D, EXP_INFO_A, EXP_INFO_B, EXP_INFO_S ) -from module.handler.assets import GET_MISSION from module.coalition.assets import * from module.coalition.combat import CoalitionCombat from module.coalition.coalition import Coalition @@ -21,6 +20,7 @@ class CoalitionScuttleCombat(CoalitionCombat): triggered_normal_end = False _is_shipwreck = False # 当前战斗是否为沉船D评价 + _is_s_rank = False # 当前战斗是否为S评价 def auto_search_combat_execute(self, emotion_reduce=True, fleet_index=1, expected_end=None): """ @@ -91,10 +91,8 @@ def auto_search_combat_execute(self, emotion_reduce=True, fleet_index=1, expecte break # D评价结算界面:S/A/B评价的动画过渡帧可能短暂误匹配D评价模板, # 但只有真正的沉船才会出现OPTS_INFO_D弹窗。 - # 此处仅break退出循环,不设置沉船标记(未经过OPTS_INFO_D确认)。 - # 真正的沉船由上方OPTS_INFO_D路径触发并设置_is_shipwreck。 + # 此处不设置沉船标记(未经过OPTS_INFO_D确认),让后续S/A/B条件覆盖。 if self.appear(BATTLE_STATUS_D) or self.appear(EXP_INFO_D): - self._withdraw = True break if confirm_timer.reached(): self._withdraw = True @@ -111,7 +109,8 @@ def auto_search_combat_execute(self, emotion_reduce=True, fleet_index=1, expecte # S评价或自动搜索运行中 if self.appear(BATTLE_STATUS_S) or self.appear(EXP_INFO_S) \ - or self.appear(GET_MISSION) or self.is_auto_search_running(): + or self.is_auto_search_running(): + self._is_s_rank = True self.device.screenshot_interval_set() break @@ -136,6 +135,7 @@ def coalition_combat(self): while 1: logger.hr(f'{self.FUNCTION_NAME_BASE}{self.battle_count}', level=2) self._is_shipwreck = False + self._is_s_rank = False # 仅第一场战斗扣减2心情(关卡进入代价),后续战斗不再扣减 self.auto_search_combat_execute( emotion_reduce=self.battle_count == 0, @@ -387,10 +387,10 @@ def run(self, event='', mode='', fleet='', total=0): if self.config.StopCondition_RunCount: self.config.StopCondition_RunCount -= 1 - # SP关卡非D评价(沉船):视为已通过,延迟至服务器刷新 - # D评价视为未通过,继续出击 - if mode == 'sp' and self.triggered_normal_end and not self._is_shipwreck: - logger.info('SP以非D评价通过') + # SP关卡仅S评价视为已通过,延迟至服务器刷新 + # A/B/C/D评价均视为未通过,继续出击 + if mode == 'sp' and self._is_s_rank and not self._is_shipwreck: + logger.info('SP以S评价通过') self.config.task_delay(server_update=True) self.config.task_stop() diff --git a/module/combat/auto_search_combat.py b/module/combat/auto_search_combat.py index 19957ee5f..0e6730897 100644 --- a/module/combat/auto_search_combat.py +++ b/module/combat/auto_search_combat.py @@ -321,11 +321,9 @@ def auto_search_combat_execute(self, emotion_reduce, fleet_index, battle=None, e # D评价结算界面(BATTLE_STATUS_D / EXP_INFO_D) # S/A/B评价的动画过渡帧可能短暂误匹配D评价模板, # 但只有真正的沉船才会出现OPTS_INFO_D弹窗。 - # 此处仅break退出循环,不扣减shipwreck心情。 - # 真正的沉船扣减由上方OPTS_INFO_D路径触发。 - # 退出后由auto_search_combat_status()中的handle_battle_status()处理结算画面。 + # 此处不设置 _withdraw,让后续S/A/B评价条件覆盖误匹配。 + # 真正的D评价会先被上方OPTS_INFO_D捕获。 if self.appear(BATTLE_STATUS_D) or self.appear(EXP_INFO_D): - self._withdraw = True break if confirm_timer.reached(): self._withdraw = True @@ -505,6 +503,19 @@ def auto_search_combat_status(self): if self.handle_mission_popup_ack(): continue + # 处理战斗结算界面——SABC评价在自动搜索中可能快速自动过渡, + # 若截图恰好捕获到结算画面则点击推进并记录评价 + # D评价点击BATTLE_STATUS_D后,会出现OPTS_INFO_D沉船弹窗 + if self.handle_battle_status(): + continue + if self.handle_exp_info(): + continue + # 检测D评价(沉船)弹窗——这是沉船的确认性标志 + if self.appear(OPTS_INFO_D, offset=(30, 30)): + logger.info('[自动搜索-结算] 检测到沉船弹窗,进入撤退处理') + self._withdraw = True + continue + # Handle low emotion combat # Combat status if self._auto_search_status_confirm: From c4ee366b581b986700acb04c73bf0998c070acb8 Mon Sep 17 00:00:00 2001 From: Beatrice-betty Date: Tue, 28 Jul 2026 10:18:54 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix(combat):=20=E4=BF=AE=E5=A4=8D=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=90=9C=E7=B4=A2=E6=88=98=E6=96=97=E4=B8=AD=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E6=89=A3=E5=87=8F=E5=BF=83=E6=83=85=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增相关状态变量防止重复触发沉船心情扣减 2. 调整结算超时处理逻辑,避免误触扣心情和点击 3. 规范沉船判定和心情扣减的触发时机 --- module/combat/auto_search_combat.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/module/combat/auto_search_combat.py b/module/combat/auto_search_combat.py index 0e6730897..91630218f 100644 --- a/module/combat/auto_search_combat.py +++ b/module/combat/auto_search_combat.py @@ -35,6 +35,9 @@ class AutoSearchCombat(MapOperation, Combat, CampaignStatus): _auto_search_status_confirm (bool): 自动搜索状态是否已确认。 _withdraw (bool): 是否已执行撤退。 _defeat_count (int): 战败次数。 + _shipwreck_emotion_reduced (bool): 沉船心情扣减是否已执行,防止重复扣减。 + _auto_search_emotion_reduce (bool): 当前战斗是否启用心情扣减。 + _auto_search_fleet_index (int): 当前战斗的舰队索引。 auto_search_oil_limit_triggered (bool): 石油限制是否已触发。 auto_search_coin_limit_triggered (bool): 物资限制是否已触发。 """ @@ -42,6 +45,9 @@ class AutoSearchCombat(MapOperation, Combat, CampaignStatus): _auto_search_status_confirm = False _withdraw = False _defeat_count = 0 + _shipwreck_emotion_reduced = False + _auto_search_emotion_reduce = False + _auto_search_fleet_index = 1 auto_search_oil_limit_triggered = False auto_search_coin_limit_triggered = False @@ -314,8 +320,9 @@ def auto_search_combat_execute(self, emotion_reduce, fleet_index, battle=None, e if self.handle_get_ship(): continue if self.appear_then_click(OPTS_INFO_D, offset=(30, 30), interval=2): - if emotion_reduce: + if emotion_reduce and not self._shipwreck_emotion_reduced: self.emotion.reduce(fleet_index, shipwreck=True) + self._shipwreck_emotion_reduced = True self._withdraw = True break # D评价结算界面(BATTLE_STATUS_D / EXP_INFO_D) @@ -326,10 +333,10 @@ def auto_search_combat_execute(self, emotion_reduce, fleet_index, battle=None, e if self.appear(BATTLE_STATUS_D) or self.appear(EXP_INFO_D): break if confirm_timer.reached(): + # 结算确认超时:不扣心情、不盲目点击OPTS_INFO_D + # 只设置_withdraw让status处理,status中检测到OPTS_INFO_D才扣心情 + logger.warning('[自动搜索-战斗] 结算确认超时,进入status处理') self._withdraw = True - self.device.click(OPTS_INFO_D) - if emotion_reduce: - self.emotion.reduce(fleet_index, shipwreck=True) confirm_timer.reset() break if self.appear(BATTLE_STATUS_A) or self.appear(BATTLE_STATUS_B) \ @@ -510,9 +517,14 @@ def auto_search_combat_status(self): continue if self.handle_exp_info(): continue - # 检测D评价(沉船)弹窗——这是沉船的确认性标志 + # 检测D评价(沉船)弹窗——这是沉船的确认性标志(二次确认) + # 只有OPTS_INFO_D出现才确认是真正的D评价并扣心情 + # S/A/B/C转场误匹配BATTLE_STATUS_D不会出现OPTS_INFO_D,不会扣心情 if self.appear(OPTS_INFO_D, offset=(30, 30)): logger.info('[自动搜索-结算] 检测到沉船弹窗,进入撤退处理') + if self._auto_search_emotion_reduce and not self._shipwreck_emotion_reduced: + self.emotion.reduce(self._auto_search_fleet_index, shipwreck=True) + self._shipwreck_emotion_reduced = True self._withdraw = True continue @@ -540,6 +552,9 @@ def auto_search_combat(self, emotion_reduce=None, fleet_index=1, battle=None): """ emotion_reduce = emotion_reduce if emotion_reduce is not None else self.emotion.is_calculate + self._auto_search_emotion_reduce = emotion_reduce + self._auto_search_fleet_index = fleet_index + self._shipwreck_emotion_reduced = False self.auto_search_combat_execute(emotion_reduce=emotion_reduce, fleet_index=fleet_index, battle=battle) self.auto_search_combat_status() From a56673cb5e7b37ed6d1c589b10d61cbe73e0df4f Mon Sep 17 00:00:00 2001 From: wess09 <> Date: Tue, 28 Jul 2026 19:42:32 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix(python):=20=E6=9B=B4=E6=96=B0=20Python?= =?UTF-8?q?=20=E7=89=88=E6=9C=AC=E5=8C=B9=E9=85=8D=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E4=BB=A5=E6=94=AF=E6=8C=81=E6=9B=B4=E5=B9=BF=E6=B3=9B=E7=9A=84?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/uv.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/deploy/uv.py b/deploy/uv.py index 945e64cef..3d3cff3bc 100644 --- a/deploy/uv.py +++ b/deploy/uv.py @@ -16,7 +16,6 @@ BOOTSTRAPPED_ENV = "AZURPILOT_UV_BOOTSTRAPPED" BOOTSTRAP_UV_ENV = "AZURPILOT_BOOTSTRAP_UV" NO_BOOTSTRAP_ENV = "AZURPILOT_NO_UV_BOOTSTRAP" -PYTHON_VERSION = "3.14.3" DEPENDENCY_SYNC_TIMEOUT = 30 * 60 @@ -183,10 +182,10 @@ def _uv_python_env(root: Path): def _managed_python_executable(root: Path) -> Optional[Path]: install_dir = venv_python_install_dir(root) - for python_home in sorted(install_dir.glob(f"cpython-{PYTHON_VERSION}-*")): + for python_home in sorted(install_dir.glob("cpython-*-*"), reverse=True): candidates = [ python_home / "python.exe", - python_home / "bin" / "python3.14", + python_home / "bin" / "python3", python_home / "bin" / "python", ] for candidate in candidates: @@ -204,7 +203,7 @@ def _venv_python_works(root: Path) -> bool: [ str(python), "-c", - "import sys; raise SystemExit(0 if sys.version_info[:2] == (3, 14) else 1)", + "import sys; raise SystemExit(0)", ], cwd=str(root), stdout=subprocess.DEVNULL, @@ -335,10 +334,10 @@ def _ensure_self_contained_python( outputs: Optional[list[str]] = None, deadline: float | None = None, ): + env = _uv_python_env(root) if _venv_python_works(root) and _managed_python_executable(root): return - env = _uv_python_env(root) managed_python = _managed_python_executable(root) if managed_python is None: command = [ @@ -349,7 +348,6 @@ def _ensure_self_contained_python( venv_python_install_dir(root), "--no-bin", "--managed-python", - PYTHON_VERSION, ] _run_and_collect( command, @@ -365,7 +363,6 @@ def _ensure_self_contained_python( "python", "find", "--managed-python", - PYTHON_VERSION, ] output = _run_output( command,