#!/usr/bin/env python3 """run_juece13_wugong_kill100.py — 角色【新角色】→ 蜈蚣洞穴(地牢一层东)杀 N 只. 复用 AutoFightBehavior(§2.6.4 SC10 修复版) + CaveEnterBehavior 传送链 (@jiuxian_move_1,1,2)。洞穴怪强(dmg60-83) — 沿用矿区验证过的 FLEE_RATIO=0.55 保命; run13 已证 SC10 推送含名字/坐标, 远距发现 (12-17格)同样适用本图。 用法: uv run python scripts/run_juece13_wugong_kill100.py -u longwu988 -p Longwu1988 \ --zone 14570166 --name 新角色 [--kills 100] [--minutes 90] [--wait 90] """ from __future__ import annotations import argparse import logging import sys import time sys.path.insert(0, "scripts") from run_juece13_mine_farthest import setup_logging, banner # noqa: E402 from run_juece13_wugong_autofight import AutoFightBehavior # noqa: E402 from run_juece13_wugong_farthest import ( # noqa: E402 CAVE_MAP, CaveEnterBehavior, _cave_walls, find_farthest, ) import requests from pbot.bot.runner import pump, run from pbot.config import Account from pbot.errors import PbotError from pbot.game.session import enter_world from pbot.login.box_client import enter_game_client, login from pbot.transport.gateway import login_gate_with_retry from pbot.types import ZoneId _LOG = logging.getLogger("juece13_wugong100") _PORTS: tuple[int, ...] = (8021, 8061, 8001, 8041) def parse_args() -> argparse.Namespace: """命令行.""" ap = argparse.ArgumentParser() _ = ap.add_argument("-u", "--user", required=True) _ = ap.add_argument("-p", "--password", required=True) _ = ap.add_argument("--zone", type=int, required=True) _ = ap.add_argument("--name", required=True) _ = ap.add_argument("--kills", type=int, default=100) _ = ap.add_argument("--minutes", type=float, default=90.0) _ = ap.add_argument("--wait", type=float, default=0.0, help="进图后原地静默秒数(仅心跳+收帧, 不移动不攻击)") _ = ap.add_argument("--login-port", type=int, default=0) return ap.parse_args() def main() -> int: """登录 → 蜈蚣洞穴 → 静默等待 → 自动战斗至 N 杀或超时 → 退出.""" a = parse_args() setup_logging() banner("[0] 洞穴自动战斗: 区=%d 角色=%s 目标=%d杀 时限=%.0fmin 静默=%.0fs", a.zone, a.name, a.kills, a.minutes, a.wait) http = requests.Session() http.trust_env = False http.verify = False jwt, uid = login(Account(username=a.user, password=a.password)) _ = enter_game_client(http, jwt, ZoneId(a.zone)) ports = (a.login_port,) if a.login_port else _PORTS key32, sid, real_name, ticket_key, game_port = login_gate_with_retry( ZoneId(a.zone), jwt, uid, a.name, ports) _LOG.info("[票据] sid=%d 角色=%s 游戏端口=%d", sid, real_name, game_port) stop: list[bool] = [False] conn, world, updater = enter_world(ZoneId(a.zone), real_name, ticket_key, sid, game_port, uid, stop=stop) _LOG.info("[✓] 出生 map=%s @(%d,%d)", world.me.map_name, world.me.x, world.me.y) try: from pbot.game.heal import enable_auto_heal state = None for _ in range(2): state = enable_auto_heal(conn, sid, want_on=True, world=world) if state == "on": break _LOG.warning("[喝药✗] 状态=%s — 重试一轮", state) time.sleep(1.0) if state != "on": _LOG.error("[喝药✗✗] 高危图无喝药保护 — 终止, 拒绝送死") return 1 _LOG.info("[喝药✓] on") if world.me.map_name != CAVE_MAP: banner("[1] 传送蜈蚣洞穴") bh = CaveEnterBehavior(sid=sid, kill_target=0) r = run(conn, world, updater, bh, duration_s=300.0) if world.me.map_name != CAVE_MAP: _LOG.error("[✗] 传送失败 result=%s", r.value) return 1 time.sleep(3.0) _ = pump(conn, world, updater, 2.0) if a.wait > 0: banner("[2] 原地静默 %.0f 秒(仅心跳+收帧)", a.wait) deadline = time.time() + a.wait while time.time() < deadline: _ = pump(conn, world, updater, 0.5) _LOG.info("[静默✓] hp=%d/%d 视野怪=%d 位置=(%d,%d) map=%s", world.me.hp, world.me.max_hp, len(world.monsters), world.me.x, world.me.y, world.me.map_name) banner("[3] 自动战斗: 目标 %d 杀", a.kills) af = AutoFightBehavior( sid=sid, map_name=CAVE_MAP, walls=_cave_walls(), farthest_fn=find_farthest, kill_goal=a.kills) r = run(conn, world, updater, af, duration_s=a.minutes * 60) _LOG.info("[结束] result=%s 击杀=%d/%d 腿=%d 弹回=%d 位置=(%d,%d) " "hp=%d/%d map=%s", r.value, af.kills, a.kills, af.legs, af.rejected, world.me.x, world.me.y, world.me.hp, world.me.max_hp, world.me.map_name) return 0 if af.kills >= a.kills else 1 finally: stop[0] = True conn.close() _LOG.info("连接已关闭") if __name__ == "__main__": try: sys.exit(main()) except PbotError as e: _LOG.error("失败: %s", e.detail) sys.exit(1)