|
|
@@ -14,7 +14,6 @@ from typing import TYPE_CHECKING
|
|
|
if TYPE_CHECKING:
|
|
|
|
|
|
from pbot.world.actor import Npc
|
|
|
- from pbot.world.mirror import WorldMirror
|
|
|
|
|
|
import json
|
|
|
import re
|
|
|
@@ -33,13 +32,24 @@ _NO_MON_SPAWN_AFTER_S = 5.0
|
|
|
_SPAWN_GAP_S = 8.0
|
|
|
_SPAWN_TALK_DIST = 3
|
|
|
|
|
|
+# 比奇【点我刷怪】NPC 定案(2026-10-02 cap_v5 用户真机点击抓包):
|
|
|
+# CS1010 {"index":83,"UserID":"10074"} — aid=10074/index=83 跨会话稳定
|
|
|
+# (probe6 会话同ID), NPC 站 (287,615) 不走 SC10 推送(贴脸8s零帧实证),
|
|
|
+# 服务器对"怪物多"时点击静默不推 SC643(用户预告+抓包确认) — 即点击
|
|
|
+# 无副作用, 可放心按冷却重复点。点击成功后地图刷出大量怪(用户实机确认)。
|
|
|
+_SPAWN_NPC_AID: str = "10074"
|
|
|
+_SPAWN_NPC_INDEX: int = 83
|
|
|
+_SPAWN_NPC_POS: tuple[int, int] = (287, 615)
|
|
|
|
|
|
-def _find_spawn_npc(world: WorldMirror) -> Npc | None:
|
|
|
- """视野内名字含'刷怪'的 NPC(KillBehavior._find_spawn_npc 同源)。"""
|
|
|
- for npc in world.npcs.values():
|
|
|
- if "刷怪" in npc.name:
|
|
|
- return npc
|
|
|
- return None
|
|
|
+
|
|
|
+def _find_spawn_npc() -> Npc:
|
|
|
+ """比奇刷怪NPC: 静态 cfgID 直造(服务器不推送此NPC, 抓包定案)。"""
|
|
|
+ from pbot.types import ActorId
|
|
|
+ from pbot.world.actor import ActorKey
|
|
|
+ from pbot.world.actor import Npc as NpcCls
|
|
|
+ return NpcCls(key=ActorKey(10074), aid=ActorId(_SPAWN_NPC_AID),
|
|
|
+ name="点我刷怪", x=_SPAWN_NPC_POS[0], y=_SPAWN_NPC_POS[1],
|
|
|
+ index=_SPAWN_NPC_INDEX)
|
|
|
|
|
|
|
|
|
def _try_spawn(ctx: PipelineContext, last: dict) -> bool:
|
|
|
@@ -73,7 +83,7 @@ def _try_spawn(ctx: PipelineContext, last: dict) -> bool:
|
|
|
last["spawn_cd"] = now + _SPAWN_GAP_S
|
|
|
return True
|
|
|
# 阶段1: 找 NPC → 走近 → 开对话
|
|
|
- snpc = _find_spawn_npc(world)
|
|
|
+ snpc = _find_spawn_npc()
|
|
|
if snpc is None:
|
|
|
return False
|
|
|
dist = max(abs(snpc.x - me.x), abs(snpc.y - me.y))
|
|
|
@@ -95,9 +105,11 @@ def _try_spawn(ctx: PipelineContext, last: dict) -> bool:
|
|
|
body = json.dumps({"UserID": snpc.aid, "index": snpc.index},
|
|
|
separators=(",", ":")).encode()
|
|
|
_ = ctx.conn.send_frame(1010, 0, 0, 0, ctx.sid, body)
|
|
|
+ # cap_v5 定案: 怪多时服务器静默(不推SC643), 点击本身即刷怪触发
|
|
|
+ # — 发出即完成, 不等对话; 若对话真的来了, 下一 tick 走阶段2点按钮
|
|
|
last["dlg_clicked"] = False
|
|
|
last["dlg_open_t"] = now
|
|
|
- ctx.log.info("[T2·刷怪] 点NPC «%s» @(%d,%d)", snpc.name,
|
|
|
+ ctx.log.info("[T2·刷怪] 点NPC «%s» @(%d,%d) — 发出即触发", snpc.name,
|
|
|
snpc.x, snpc.y)
|
|
|
last["spawn_cd"] = now + _SPAWN_GAP_S
|
|
|
return True
|
|
|
@@ -105,24 +117,24 @@ def _try_spawn(ctx: PipelineContext, last: dict) -> bool:
|
|
|
|
|
|
def _spawn_on_land(ctx: PipelineContext,
|
|
|
last: dict, tag: str = "") -> None:
|
|
|
- """落地即点一次【点我刷怪】: 走到 NPC → 开对话 → 点确认 → 立即返回。
|
|
|
+ """落地即点一次【点我刷怪】: 走到 NPC (287,615) → 发 CS1010 → 返回。
|
|
|
|
|
|
- 不论服务器报"已有怪物"还是其他错误都无碍 — 点完即继续正常杀怪
|
|
|
- (2026-10-01 用户定案: 落地必点, 不等无怪窗口)。视野推送范围大于
|
|
|
- 贴身杀怪圈, "无怪5秒"条件在有远怪时永不成立, 曾致院落清空后角色
|
|
|
- 跑远追怪而落点旁的刷怪 NPC 从未被点(spawn6 实证)。
|
|
|
+ cap_v5 定案: 点击帧即刷怪触发(怪多时服务器静默无对话也无副作用)。
|
|
|
+ 落地点(≈292,616)距 NPC 5-6 格, 跑步 3-4s 到位。
|
|
|
"""
|
|
|
from pbot.bot.runner import pump
|
|
|
|
|
|
world = ctx.world
|
|
|
- deadline = time.time() + 25.0
|
|
|
+ deadline = time.time() + 30.0
|
|
|
while time.time() < deadline:
|
|
|
_ = pump(ctx.conn, world, ctx.updater, 0.1)
|
|
|
+ before = last.get("spawn_cd", 0.0)
|
|
|
_ = _try_spawn(ctx, last)
|
|
|
- if last.get("dlg_clicked"):
|
|
|
- ctx.log.info("[%s·落地刷怪] 已点过一次 — 继续杀怪", tag)
|
|
|
+ # spawn_cd 被推进 = CS1010 已发出 → 本次落地点击完成
|
|
|
+ if last.get("spawn_cd", 0.0) > before:
|
|
|
+ ctx.log.info("[%s·落地刷怪] CS1010 已发 — 继续杀怪", tag)
|
|
|
return
|
|
|
- ctx.log.info("[%s·落地刷怪] 25s 未完成(NPC不在视野?) — 继续杀怪", tag)
|
|
|
+ ctx.log.info("[%s·落地刷怪] 30s 未完成(走位受阻?) — 继续杀怪", tag)
|
|
|
|
|
|
|
|
|
def run_task(ctx: PipelineContext) -> TaskResult:
|