Add Ghostbox hardware and logistics automation
This commit is contained in:
@@ -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:
|
||||
# 被动进战时立即打断进食等待,转入正常战斗流程
|
||||
|
||||
Reference in New Issue
Block a user