# -*- coding: utf-8 -*- """ wait_wander.py — 登录角色 → (如在比奇则 @renwu_mov 传回等待图) → 等待图随机走动。 不杀怪、不点NPC、不做任务后续。 诊断背景(2026-09-23 run): 等待图出生行 Y=0/4 附近, 朝 NPC 的贪心方向 dir6/7 全被 SC28 拒 → 角色视觉站桩。 本脚本: 每步 0.55s, 70% 保持航向 / 30% 随机换向; 被拉回的方向进黑名单, SC11 自回显确认则清空黑名单。周期打印 服务器确认步数 vs 拉回次数。 用法: .venv/bin/python wait_wander.py --zone 14504562 --name 萌新4143 \ -u longwu988 -p Longwu1988 --minutes 2 """ import argparse import json import random import time import requests as rq import urllib3 urllib3.disable_warnings() import login_996pc as L import quest_bot3 as Q from combat_bot import log def renwu_to_wait(bot, g): """复刻 run_fsm 阶段1: CS3031 + @renwu_mov,1 → SC634 传送等待图。""" if bot.me.get("mapname") == Q.WAIT_MAP: return True if 1 in bot.mission_bodies: body3031 = json.dumps(bot.mission_bodies[1], separators=(",", ":")).encode() else: import os tpl = os.path.join(Q.HERE, "docs", "cs3031_template.txt") body3031 = open(tpl, "rb").read() bot.send(3031, 0, 0, 0, bot.sid, body3031) bot.pump(0.5) bot.tick_step_ack() bot.send(1011, 0, 0, 0, bot.sid, json.dumps( {"Act": "@renwu_mov,1", "UserID": "999999999", "index": 999999999}, separators=(",", ":")).encode()) bot.pump(0.5) bot.tick_step_ack() t0 = time.time() while time.time() - t0 < 15 and bot.alive: bot.pump(0.3) bot.tick_step_ack() if bot.me.get("mapname") == Q.WAIT_MAP: return True return bot.me.get("mapname") == Q.WAIT_MAP def wander(bot, seconds): t0 = time.time() heading = random.randrange(8) rejected = set() last_dir = None pulled = False confirmed = 0 pulled_n = 0 rep = 0.0 step_iv = Q.STEP_MS / 1000.0 + 0.05 while time.time() - t0 < seconds and bot.alive: evs = bot.pump(0.1) bot.tick_step_ack() for e in evs: if e[0] == "self_move": confirmed += 1 pulled = False rejected.clear() elif e[0] == "pull_back": pulled_n += 1 pulled = True if last_dir is not None: rejected.add(last_dir) elif e[0] == "pull_back_bogus_dropped": pulled_n += 1 if time.time() - bot._last_step_t >= step_iv: if pulled and last_dir is not None: rejected.add(last_dir) cands = [d for d in range(8) if d not in rejected] if not cands: rejected.clear() cands = list(range(8)) if random.random() < 0.7 and heading in cands: d = heading else: d = random.choice(cands) heading = d last_dir = d bot.step_move(*Q.DIRS[d]) pulled = False if time.time() - rep > 10: rep = time.time() log(f"[WANDER] pos=({bot.me['x']},{bot.me['y']}) map={bot.me.get('mapname')} " f"服务器确认步数={confirmed} 拉回={pulled_n} 方向黑名单={sorted(rejected)}") log(f"[WANDER结束] pos=({bot.me['x']},{bot.me['y']}) 确认步数={confirmed} 拉回={pulled_n}") def main(): ap = argparse.ArgumentParser() ap.add_argument("-u", "--user", default="longwu988") ap.add_argument("-p", "--password", default="Longwu1988") ap.add_argument("--zone", type=int, default=14504562) ap.add_argument("--name", default="萌新4143") ap.add_argument("--port", type=int, default=0) ap.add_argument("--minutes", type=float, default=2) args = ap.parse_args() args.minutes = min(args.minutes, 2) j = None for a in range(5): try: s = rq.Session() j, _ = L.do_login(s, args.user, args.password) if j.get("code") == 200: break except Exception as e: log(f"登录重试{a + 1}: {str(e)[:60]}") time.sleep(12) if not j or j.get("code") != 200: raise SystemExit(f"[!] 登录失败: {(j or {}).get('msg', '网络异常')}") jwt = j["data"]["token"] uid = str(j["data"]["userInfo"]["id"]) g, bot = Q.enter_world(s, jwt, uid, args.zone, args.name, args.port) try: state = Q.P.enable_auto_heal(g, bot.sid, want_on=True) log(f"喝药保护: {state}") if not renwu_to_wait(bot, g): log(f"[!] 未到等待图, 当前 {bot.me.get('mapname')} — 就地走动") wander(bot, args.minutes * 60) finally: g.close() if __name__ == "__main__": main()