wait_wander.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. # -*- coding: utf-8 -*-
  2. """
  3. wait_wander.py — 登录角色 → (如在比奇则 @renwu_mov 传回等待图) → 等待图随机走动。
  4. 不杀怪、不点NPC、不做任务后续。
  5. 诊断背景(2026-09-23 run):
  6. 等待图出生行 Y=0/4 附近, 朝 NPC 的贪心方向 dir6/7 全被 SC28 拒 → 角色视觉站桩。
  7. 本脚本: 每步 0.55s, 70% 保持航向 / 30% 随机换向; 被拉回的方向进黑名单,
  8. SC11 自回显确认则清空黑名单。周期打印 服务器确认步数 vs 拉回次数。
  9. 用法:
  10. .venv/bin/python wait_wander.py --zone 14504562 --name 萌新4143 \
  11. -u longwu988 -p Longwu1988 --minutes 2
  12. """
  13. import argparse
  14. import json
  15. import random
  16. import time
  17. import requests as rq
  18. import urllib3
  19. urllib3.disable_warnings()
  20. import login_996pc as L
  21. import quest_bot3 as Q
  22. from combat_bot import log
  23. def renwu_to_wait(bot, g):
  24. """复刻 run_fsm 阶段1: CS3031 + @renwu_mov,1 → SC634 传送等待图。"""
  25. if bot.me.get("mapname") == Q.WAIT_MAP:
  26. return True
  27. if 1 in bot.mission_bodies:
  28. body3031 = json.dumps(bot.mission_bodies[1], separators=(",", ":")).encode()
  29. else:
  30. import os
  31. tpl = os.path.join(Q.HERE, "docs", "cs3031_template.txt")
  32. body3031 = open(tpl, "rb").read()
  33. bot.send(3031, 0, 0, 0, bot.sid, body3031)
  34. bot.pump(0.5)
  35. bot.tick_step_ack()
  36. bot.send(1011, 0, 0, 0, bot.sid, json.dumps(
  37. {"Act": "@renwu_mov,1", "UserID": "999999999", "index": 999999999},
  38. separators=(",", ":")).encode())
  39. bot.pump(0.5)
  40. bot.tick_step_ack()
  41. t0 = time.time()
  42. while time.time() - t0 < 15 and bot.alive:
  43. bot.pump(0.3)
  44. bot.tick_step_ack()
  45. if bot.me.get("mapname") == Q.WAIT_MAP:
  46. return True
  47. return bot.me.get("mapname") == Q.WAIT_MAP
  48. def wander(bot, seconds):
  49. t0 = time.time()
  50. heading = random.randrange(8)
  51. rejected = set()
  52. last_dir = None
  53. pulled = False
  54. confirmed = 0
  55. pulled_n = 0
  56. rep = 0.0
  57. step_iv = Q.STEP_MS / 1000.0 + 0.05
  58. while time.time() - t0 < seconds and bot.alive:
  59. evs = bot.pump(0.1)
  60. bot.tick_step_ack()
  61. for e in evs:
  62. if e[0] == "self_move":
  63. confirmed += 1
  64. pulled = False
  65. rejected.clear()
  66. elif e[0] == "pull_back":
  67. pulled_n += 1
  68. pulled = True
  69. if last_dir is not None:
  70. rejected.add(last_dir)
  71. elif e[0] == "pull_back_bogus_dropped":
  72. pulled_n += 1
  73. if time.time() - bot._last_step_t >= step_iv:
  74. if pulled and last_dir is not None:
  75. rejected.add(last_dir)
  76. cands = [d for d in range(8) if d not in rejected]
  77. if not cands:
  78. rejected.clear()
  79. cands = list(range(8))
  80. if random.random() < 0.7 and heading in cands:
  81. d = heading
  82. else:
  83. d = random.choice(cands)
  84. heading = d
  85. last_dir = d
  86. bot.step_move(*Q.DIRS[d])
  87. pulled = False
  88. if time.time() - rep > 10:
  89. rep = time.time()
  90. log(f"[WANDER] pos=({bot.me['x']},{bot.me['y']}) map={bot.me.get('mapname')} "
  91. f"服务器确认步数={confirmed} 拉回={pulled_n} 方向黑名单={sorted(rejected)}")
  92. log(f"[WANDER结束] pos=({bot.me['x']},{bot.me['y']}) 确认步数={confirmed} 拉回={pulled_n}")
  93. def main():
  94. ap = argparse.ArgumentParser()
  95. ap.add_argument("-u", "--user", default="longwu988")
  96. ap.add_argument("-p", "--password", default="Longwu1988")
  97. ap.add_argument("--zone", type=int, default=14504562)
  98. ap.add_argument("--name", default="萌新4143")
  99. ap.add_argument("--port", type=int, default=0)
  100. ap.add_argument("--minutes", type=float, default=2)
  101. args = ap.parse_args()
  102. args.minutes = min(args.minutes, 2)
  103. j = None
  104. for a in range(5):
  105. try:
  106. s = rq.Session()
  107. j, _ = L.do_login(s, args.user, args.password)
  108. if j.get("code") == 200:
  109. break
  110. except Exception as e:
  111. log(f"登录重试{a + 1}: {str(e)[:60]}")
  112. time.sleep(12)
  113. if not j or j.get("code") != 200:
  114. raise SystemExit(f"[!] 登录失败: {(j or {}).get('msg', '网络异常')}")
  115. jwt = j["data"]["token"]
  116. uid = str(j["data"]["userInfo"]["id"])
  117. g, bot = Q.enter_world(s, jwt, uid, args.zone, args.name, args.port)
  118. try:
  119. state = Q.P.enable_auto_heal(g, bot.sid, want_on=True)
  120. log(f"喝药保护: {state}")
  121. if not renwu_to_wait(bot, g):
  122. log(f"[!] 未到等待图, 当前 {bot.me.get('mapname')} — 就地走动")
  123. wander(bot, args.minutes * 60)
  124. finally:
  125. g.close()
  126. if __name__ == "__main__":
  127. main()