Add Ghostbox hardware and logistics automation

This commit is contained in:
王鹏
2026-05-07 15:19:59 +08:00
parent bf26de3244
commit a48ed597b4
14 changed files with 1287 additions and 323 deletions

View File

@@ -287,6 +287,7 @@ class AutoBotMove:
)
self.distance_interact_brake_sec = 0.08
self._last_mouse_path_scale_signature = None
self.logistics_resume_cooldown_until = 0.0
# stop_check: 返回 True 表示需要立即停止(用于中断阻塞中的后勤/路线导航)
self._stop_check = stop_check if callable(stop_check) else (lambda: False)
if waypoints is None:
@@ -327,6 +328,12 @@ class AutoBotMove:
self.logistics_manager = LogisticsManager(vendor_file)
self.logistics_manager.bag_full_hearthstone = bool(layout.get("bag_full_hearthstone", False))
self.logistics_manager.hearthstone_key = str(layout.get("hearthstone_key", "b") or "b")
self.logistics_manager.hearthstone_cast_sec = float(layout.get("hearthstone_wait_sec", 12.0))
self.logistics_manager.logistics_full_auto = bool(layout.get("logistics_full_auto", False))
self.logistics_manager.bag_slot_threshold = int(layout.get("bag_slot_threshold", 2))
self.logistics_manager.durability_threshold = float(layout.get("durability_threshold", 0.2))
self.logistics_manager.repair_target_key = str(layout.get("repair_target_key", "8") or "8")
self.logistics_manager.repair_interact_key = str(layout.get("repair_interact_key", "4") or "4")
self.logistics_manager.enable_bag_full_mail = bool(layout.get("enable_bag_full_mail", False))
self.logistics_manager.mailbox_route_file = str(
mailbox_route_path
@@ -342,6 +349,25 @@ class AutoBotMove:
def _has_prepare_route(self) -> bool:
return bool(self.prepare_route_waypoints)
def _reset_prepare_route_for_logistics_resume(self):
self.prepare_route_index = 0
self.prepare_route_completed = not bool(self.prepare_route_waypoints)
self.is_running_prepare_route = bool(self.prepare_route_waypoints)
self.prepare_route_snapped = False
self.target_acquired_time = None
self.last_turn_signal_time = 0.0
self.last_interaction_time = 0.0
self.distance_interact_brake_pending = False
self.distance_interact_pause_until = 0.0
self.logistics_resume_cooldown_until = time.time() + 5.0
self.last_tab_time = time.time() + 1.0
self.patrol_controller.stop_all()
self.patrol_controller.reset_stuck()
if self.prepare_route_waypoints:
print(">>> [后勤] 全自动续跑:重置准备路线,准备返回巡逻。")
else:
print(">>> [后勤] 全自动续跑:未配置准备路线,直接恢复巡逻。")
def _snap_prepare_route_to_nearest(self, state):
if self.prepare_route_snapped or self.prepare_route_completed or not self._has_prepare_route():
return
@@ -768,40 +794,46 @@ class AutoBotMove:
self.death_manager.run_to_corpse(state, get_state)
return
# 2. 后勤检查(脱战时):空格或耐久不足则回城
self.logistics_manager.check_logistics(state)
effective_target = self._is_effective_target(state)
in_combat_or_target = bool(state['combat'] or effective_target)
# 2. 后勤检查:只在脱战且无有效目标时触发,避免战斗中突然回城/修理/邮寄。
if not in_combat_or_target and time.time() >= self.logistics_resume_cooldown_until:
self.logistics_manager.check_logistics(state)
else:
self.logistics_manager.is_returning = False
if self.logistics_manager.is_returning:
if self.is_moving:
self.patrol_controller.stop_all()
self.is_moving = False
self.patrol_controller.reset_stuck()
bag_full_now = int(state.get('free_slots', 0) or 0) < 2
if bag_full_now and self.logistics_manager.enable_bag_full_mail:
get_state_fn = (lambda: None if self._should_stop() else parse_game_state())
self.logistics_manager.run_bag_full_mail_flow(
get_state_fn,
self.patrol_controller,
stop_check=self._should_stop,
)
if callable(getattr(self, '_on_hearthstone_stop', None)):
self._on_hearthstone_stop()
tasks = self.logistics_manager.get_pending_tasks(state)
get_state_fn = (lambda: None if self._should_stop() else parse_game_state())
ok, completed_tasks = self.logistics_manager.run_pending_tasks(
tasks,
get_state_fn,
self.patrol_controller,
stop_check=self._should_stop,
)
can_resume = (
ok
and self.logistics_manager.logistics_full_auto
and any(task in ("mail", "repair") for task in completed_tasks)
)
if can_resume:
self._reset_prepare_route_for_logistics_resume()
self.is_moving = False
return
# 勾选"包满炉石回城":只有真正包满时才炉石;耐久低仍走修理路线
if bag_full_now and self.logistics_manager.bag_full_hearthstone:
get_state_fn = (lambda: None if self._should_stop() else parse_game_state())
self.logistics_manager.use_hearthstone_and_stop(get_state=get_state_fn)
if callable(getattr(self, '_on_hearthstone_stop', None)):
self._on_hearthstone_stop()
return
# 中断策略:一旦 GUI 停止,后续 get_state 返回 None使 navigate_path 立即退出。
get_state = (lambda: None if self._should_stop() else parse_game_state())
self.logistics_manager.run_route1_round(get_state, self.patrol_controller)
if callable(getattr(self, '_on_hearthstone_stop', None)):
self._on_hearthstone_stop()
return
# 3. 战斗/有目标:停止移动,执行攻击逻辑;仅在「跑向怪」短窗口内做卡死检测
effective_target = self._is_effective_target(state)
# 核心修改:只要还在战斗中,就不算“完全脱战”,即使当前没目标(可能正在 Tab 找下一个)
in_combat_or_target = bool(state['combat'] or effective_target)
if in_combat_or_target:
# 被动进战时立即打断进食等待,转入正常战斗流程