add 脱战血量低就地吃面包
This commit is contained in:
@@ -14,6 +14,9 @@ from logistics_manager import LogisticsManager
|
||||
KEY_TAB = '3'
|
||||
KEY_LOOT = '4' # 假设你在游戏里设置了互动按键为 F
|
||||
KEY_ATTACK = '2' # 假设你的主攻击技能是 1
|
||||
DEFAULT_FOOD_KEY = 'f1' # 面包快捷键
|
||||
DEFAULT_EAT_HP_THRESHOLD = 30
|
||||
DEFAULT_EAT_MAX_WAIT_SEC = 30.0
|
||||
|
||||
# 巡逻点配置文件
|
||||
WAYPOINTS_FILE = 'waypoints.json'
|
||||
@@ -79,7 +82,18 @@ def load_attack_loop(path):
|
||||
|
||||
|
||||
class AutoBotMove:
|
||||
def __init__(self, waypoints=None, waypoints_path=None, vendor_path=None, attack_loop_path=None, skinning_wait_sec=None):
|
||||
def __init__(
|
||||
self,
|
||||
waypoints=None,
|
||||
waypoints_path=None,
|
||||
vendor_path=None,
|
||||
attack_loop_path=None,
|
||||
skinning_wait_sec=None,
|
||||
food_key=None,
|
||||
eat_hp_threshold=None,
|
||||
eat_max_wait_sec=None,
|
||||
stop_check=None,
|
||||
):
|
||||
self.last_tab_time = 0
|
||||
self.is_running = True
|
||||
self.is_moving = False
|
||||
@@ -87,7 +101,14 @@ class AutoBotMove:
|
||||
# 记录上一帧是否处于战斗/有目标,用于检测“刚刚脱战”的瞬间
|
||||
self._was_in_combat_or_target = False
|
||||
self.skinning_wait_sec = float(skinning_wait_sec) if skinning_wait_sec is not None else 1.5
|
||||
self.food_key = (food_key or DEFAULT_FOOD_KEY).strip().lower() or DEFAULT_FOOD_KEY
|
||||
self.eat_hp_threshold = int(eat_hp_threshold) if eat_hp_threshold is not None else DEFAULT_EAT_HP_THRESHOLD
|
||||
self.eat_max_wait_sec = float(eat_max_wait_sec) if eat_max_wait_sec is not None else DEFAULT_EAT_MAX_WAIT_SEC
|
||||
self.attack_loop_config = load_attack_loop(attack_loop_path)
|
||||
self._prev_death_state = 0
|
||||
self._eating_started_at = None
|
||||
# stop_check: 返回 True 表示需要立即停止(用于中断阻塞中的后勤/路线导航)
|
||||
self._stop_check = stop_check if callable(stop_check) else (lambda: False)
|
||||
if waypoints is None:
|
||||
path = waypoints_path or get_config_path(WAYPOINTS_FILE)
|
||||
waypoints = load_waypoints(path) or DEFAULT_WAYPOINTS
|
||||
@@ -102,6 +123,12 @@ class AutoBotMove:
|
||||
vendor_file = vendor_path or get_config_path('vendor.json')
|
||||
self.logistics_manager = LogisticsManager(vendor_file)
|
||||
|
||||
def _should_stop(self) -> bool:
|
||||
try:
|
||||
return bool(self._stop_check())
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def execute_disengage_loot(self):
|
||||
"""从有战斗/目标切换到完全脱战的瞬间,执行拾取 + 剥皮。"""
|
||||
try:
|
||||
@@ -140,8 +167,39 @@ class AutoBotMove:
|
||||
if random.random() < 0.3:
|
||||
pydirectinput.press(KEY_ATTACK)
|
||||
|
||||
def _start_eating(self):
|
||||
"""开始就地吃面包恢复。"""
|
||||
self._eating_started_at = time.time()
|
||||
pydirectinput.press(self.food_key)
|
||||
|
||||
def _should_keep_eating(self, state) -> bool:
|
||||
"""
|
||||
返回 True 表示继续等待回血(暂停巡逻与找怪);
|
||||
返回 False 表示结束进食等待。
|
||||
"""
|
||||
if self._eating_started_at is None:
|
||||
return False
|
||||
hp = state.get('hp')
|
||||
if hp is not None and hp >= 100:
|
||||
self._eating_started_at = None
|
||||
return False
|
||||
if (time.time() - self._eating_started_at) >= self.eat_max_wait_sec:
|
||||
self._eating_started_at = None
|
||||
return False
|
||||
return True
|
||||
|
||||
def execute_logic(self, state):
|
||||
if self._should_stop():
|
||||
# 在停止按钮点击后,确保马上松开移动键,并避免继续执行后勤交互。
|
||||
self.patrol_controller.stop_all()
|
||||
self.logistics_manager.is_returning = False
|
||||
self.is_moving = False
|
||||
return
|
||||
|
||||
death = state.get('death_state', 0)
|
||||
if self._prev_death_state in (1, 2) and death == 0:
|
||||
self.death_manager.reset_when_alive()
|
||||
self._prev_death_state = death
|
||||
# 1. 死亡状态:尸体(1) 记录坐标并释放灵魂;灵魂(2) 跑尸
|
||||
if death == 1:
|
||||
self.patrol_controller.stop_all()
|
||||
@@ -160,12 +218,16 @@ class AutoBotMove:
|
||||
self.patrol_controller.stop_all()
|
||||
self.is_moving = False
|
||||
self.patrol_controller.reset_stuck()
|
||||
self.logistics_manager.run_route1_round(parse_game_state, self.patrol_controller)
|
||||
# 中断策略:一旦 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)
|
||||
return
|
||||
|
||||
# 3. 战斗/有目标:停止移动,执行攻击逻辑;仅在「跑向怪」短窗口内做卡死检测
|
||||
in_combat_or_target = bool(state['combat'] or state['target'])
|
||||
if in_combat_or_target:
|
||||
# 被动进战时立即打断进食等待,转入正常战斗流程
|
||||
self._eating_started_at = None
|
||||
if self.target_acquired_time is None:
|
||||
self.target_acquired_time = time.time()
|
||||
if self.is_moving:
|
||||
@@ -206,6 +268,18 @@ class AutoBotMove:
|
||||
pass
|
||||
self.target_acquired_time = None # 脱战/无目标时清零,下次获得目标再计时
|
||||
self._was_in_combat_or_target = False
|
||||
|
||||
# 4. 脱战低血量:就地吃面包(最多等待 30 秒或回满)
|
||||
hp = state.get('hp')
|
||||
if self._eating_started_at is None and hp is not None and hp < self.eat_hp_threshold:
|
||||
if self.is_moving:
|
||||
self.patrol_controller.stop_all()
|
||||
self.is_moving = False
|
||||
self._start_eating()
|
||||
if self._should_keep_eating(state):
|
||||
# 进食期间不巡逻、不主动找目标(不按 Tab)
|
||||
return
|
||||
|
||||
# 4. 没战斗没目标:巡逻(卡死检测在 patrol_controller.navigate 内)
|
||||
self.is_moving = True
|
||||
self.patrol_controller.navigate(state)
|
||||
|
||||
Reference in New Issue
Block a user