import math import time from hardware_control import hw_ctrl class DeathManager: ROUTE_SELECTION_EPSILON = 0.3 def __init__( self, patrol_system, resurrection_waypoints_path=None, resurrection_route_a_path=None, resurrection_route_b_path=None, release_spirit_key='9', resurrect_key='0', ): self.patrol_system = patrol_system self.release_spirit_key = str(release_spirit_key).strip() or '9' self.resurrect_key = str(resurrect_key).strip() or '0' self.resurrection_route_a = self._load_waypoints( resurrection_route_a_path or resurrection_waypoints_path ) self.resurrection_route_b = self._load_waypoints(resurrection_route_b_path) self.corpse_pos = None self.graveyard_pos = None self.is_running_to_corpse = False self.selected_resurrection_route = None self.selected_resurrection_route_name = None self._spirit_release_sent = False self._route_selected = False self._resurrection_completed = False def _load_waypoints(self, path): """Load a resurrection route JSON file, allowing empty configuration.""" if not path: return None import json import os if not os.path.exists(path): return None try: with open(path, 'r', encoding='utf-8') as f: data = json.load(f) if isinstance(data, list) and data: return [(float(point[0]), float(point[1])) for point in data] except Exception: pass return None def _clear_death_run_state(self): self.graveyard_pos = None self.selected_resurrection_route = None self.selected_resurrection_route_name = None self._route_selected = False self._resurrection_completed = False def _build_resurrection_route_candidates(self): candidates = [] if self.resurrection_route_a: candidates.append(("A", self.resurrection_route_a)) if self.resurrection_route_b: candidates.append(("B", self.resurrection_route_b)) return candidates def _record_graveyard_pos(self, state): if self.graveyard_pos is not None: return True x = state.get('x') y = state.get('y') if x is None or y is None: return False self.graveyard_pos = (float(x), float(y)) print(f">>> [系统] 记录墓地坐标: {self.graveyard_pos}") return True def _choose_resurrection_route(self): if self.graveyard_pos is None: return None, None candidates = self._build_resurrection_route_candidates() if not candidates: return None, None best_name = None best_points = None best_dist = None for name, points in candidates: start_pos = points[0] dist = math.dist(self.graveyard_pos, start_pos) print(f">>> [系统] 复活路线{name} 起点距离墓地: {dist:.3f} | 起点: {start_pos}") if best_dist is None or dist + self.ROUTE_SELECTION_EPSILON < best_dist: best_name = name best_points = points best_dist = dist return best_name, best_points def reset_when_alive(self): """Clear death-related state after the character is alive again.""" self._spirit_release_sent = False self.corpse_pos = None self.is_running_to_corpse = False self._clear_death_run_state() def on_death(self, state): """Record corpse coordinates once, then release spirit.""" if self._spirit_release_sent: return self._spirit_release_sent = True self._clear_death_run_state() self.corpse_pos = (state['x'], state['y']) self.is_running_to_corpse = True print(f">>> [系统] 记录死亡坐标: {self.corpse_pos},准备释放灵魂...") hw_ctrl.press(self.release_spirit_key) time.sleep(5) def run_to_corpse(self, state, get_state=None): """ Run the configured resurrection route first, then navigate back to the corpse. """ if not self.corpse_pos: return if not self._record_graveyard_pos(state): return if not self._route_selected: route_name, route_points = self._choose_resurrection_route() self.selected_resurrection_route_name = route_name self.selected_resurrection_route = route_points self._route_selected = True if route_name: print(f">>> [系统] 本次死亡选择复活路线: {route_name}") else: print(">>> [系统] 未配置可用复活路线,直接前往尸体...") if self.selected_resurrection_route and not self._resurrection_completed: if get_state is None: return if self.patrol_system.navigate_path(get_state, self.selected_resurrection_route): self._resurrection_completed = True print( f">>> [系统] 复活路线{self.selected_resurrection_route_name}跑完,开始前往尸体..." ) return is_arrived = self.patrol_system.navigate_to_point(state, self.corpse_pos) if is_arrived: print(">>> 已到达尸体附近,尝试复活...") hw_ctrl.press(self.resurrect_key) time.sleep(5) if get_state: new_state = get_state() if new_state and new_state.get('death_state') == 2: print(">>> 仍为灵魂状态,再次尝试复活...") hw_ctrl.press(self.resurrect_key) time.sleep(5) self.is_running_to_corpse = False self.corpse_pos = None self._clear_death_run_state()