Просмотр исходного кода

feat(pipeline): T4矿区杀20/T5蜈蚣40杀+冲35级/T6神通开启 任务文件

wuzilong 1 месяц назад
Родитель
Сommit
4974aefbc6

+ 54 - 0
pipeline_bot/pipeline/tasks/t04_mine_kill20.py

@@ -0,0 +1,54 @@
+"""T4 — 任务指引→比奇矿区寻图杀怪 20(传送员链 + 自动战斗轮次)。"""
+from __future__ import annotations
+
+import sys
+import time
+from pathlib import Path
+
+from pipeline.ctx import PipelineContext, TaskResult
+
+TASK_TITLE = "T4 比奇矿区杀怪20"
+
+KILL_TARGET = 20
+MINE_MAP = "比奇矿区"
+_MAX_ROUNDS = 6
+_SCRIPTS = str(Path(__file__).resolve().parents[2] / "scripts")
+
+
+def run_task(ctx: PipelineContext) -> TaskResult:
+    """传送进矿区后按轮次自动战斗, 累计 instance 级 kills 至 20。"""
+    if _SCRIPTS not in sys.path:
+        sys.path.insert(0, _SCRIPTS)
+    from run_juece13_mine_farthest import (
+        MineEnterBehavior,
+        _d401_walls,
+        find_farthest,
+    )
+    from run_juece13_wugong_autofight import AutoFightBehavior
+
+    from pbot.bot.runner import pump, run
+
+    walls = _d401_walls()
+    total = 0
+    for rnd in range(1, _MAX_ROUNDS + 1):
+        if ctx.world.me.map_name != MINE_MAP:
+            ctx.log.info("[T4] 第%d轮 进图(当前 %s)", rnd, ctx.world.me.map_name)
+            bh = MineEnterBehavior(sid=ctx.sid, kill_target=0)
+            r = run(ctx.conn, ctx.world, ctx.updater, bh, duration_s=300.0)
+            if ctx.world.me.map_name != MINE_MAP:
+                ctx.log.warning("[T4] 传送失败 result=%s — 重试", r.value)
+                time.sleep(3.0)
+                continue
+            time.sleep(3.0)
+            _ = pump(ctx.conn, ctx.world, ctx.updater, 2.0)
+        need = KILL_TARGET - total
+        af = AutoFightBehavior(sid=ctx.sid, map_name=MINE_MAP, walls=walls,
+                               farthest_fn=find_farthest, kill_goal=need)
+        r = run(ctx.conn, ctx.world, ctx.updater, af,
+                duration_s=max(600.0, need * 60.0))
+        total += af.kills
+        ctx.log.info("[T4] 第%d轮 result=%s 轮杀=%d 累计=%d/%d",
+                     rnd, r.value, af.kills, total, KILL_TARGET)
+        if total >= KILL_TARGET:
+            return TaskResult.done(f"矿区击杀 {total}/{KILL_TARGET}")
+    return TaskResult.fail(f"{total}/{KILL_TARGET} 轮次耗尽")

+ 60 - 0
pipeline_bot/pipeline/tasks/t05_wugong_kill40.py

@@ -0,0 +1,60 @@
+"""T5 — 任务指引→蜈蚣洞穴杀怪 40; 若等级<35 继续杀到 35(用户决策)。"""
+from __future__ import annotations
+
+import sys
+import time
+from pathlib import Path
+
+from pipeline.ctx import PipelineContext, TaskResult
+
+TASK_TITLE = "T5 蜈蚣洞穴杀怪40+至35级"
+
+KILL_TARGET = 40
+LEVEL_GOAL = 35
+WUGONG_MAP = "地牢一层东"
+_MAX_ROUNDS = 8
+_SCRIPTS = str(Path(__file__).resolve().parents[2] / "scripts")
+
+
+def run_task(ctx: PipelineContext) -> TaskResult:
+    """进蜈蚣洞穴轮次自动战斗至击杀40且等级≥35, 双条件才算成功。"""
+    if _SCRIPTS not in sys.path:
+        sys.path.insert(0, _SCRIPTS)
+    from run_juece13_wugong_autofight import AutoFightBehavior
+    from run_juece13_wugong_farthest import (
+        CaveEnterBehavior,
+        _cave_walls,
+        find_farthest,
+    )
+
+    from pbot.bot.runner import pump, run
+
+    walls = _cave_walls()
+    total = 0
+    for rnd in range(1, _MAX_ROUNDS + 1):
+        if ctx.world.me.map_name != WUGONG_MAP:
+            ctx.log.info("[T5] 第%d轮 进图(当前 %s)", rnd, ctx.world.me.map_name)
+            bh = CaveEnterBehavior(sid=ctx.sid, kill_target=0)
+            r = run(ctx.conn, ctx.world, ctx.updater, bh, duration_s=300.0)
+            if ctx.world.me.map_name != WUGONG_MAP:
+                ctx.log.warning("[T5] 传送失败 result=%s", r.value)
+                time.sleep(3.0)
+                continue
+            time.sleep(3.0)
+            _ = pump(ctx.conn, ctx.world, ctx.updater, 2.0)
+        need = KILL_TARGET - total
+        # need==0 但等级不足 → kill_goal=0 = 无上限杀满一轮冲级
+        af = AutoFightBehavior(sid=ctx.sid, map_name=WUGONG_MAP, walls=walls,
+                               farthest_fn=find_farthest, kill_goal=need)
+        r = run(ctx.conn, ctx.world, ctx.updater, af,
+                duration_s=max(600.0, need * 60.0))
+        total += af.kills
+        lv = ctx.world.me.level
+        ctx.log.info("[T5] 第%d轮 result=%s 轮杀=%d 累计=%d/%d lv=%d",
+                     rnd, r.value, af.kills, total, KILL_TARGET, lv)
+        if total >= KILL_TARGET and lv >= LEVEL_GOAL:
+            return TaskResult.done(f"击杀 {total}/{KILL_TARGET} 等级 {lv}")
+    lv = ctx.world.me.level
+    if total >= KILL_TARGET:
+        return TaskResult.fail(f"杀满 {total} 但等级 {lv}<{LEVEL_GOAL} — 轮次耗尽")
+    return TaskResult.fail(f"{total}/{KILL_TARGET} 轮次耗尽 lv={lv}")

+ 57 - 0
pipeline_bot/pipeline/tasks/t06_shentong.py

@@ -0,0 +1,57 @@
+"""T6 — 35级开启神通: CS3199 @mingge_kaiqi,1; 静默5s无SC100(Type=9)=成功。"""
+from __future__ import annotations
+
+import json
+import time
+
+from pipeline.ctx import PipelineContext, TaskResult
+
+TASK_TITLE = "T6 开启神通(35级)"
+
+LEVEL_NEED = 35
+WAIT_S = 5.0
+
+
+def _send_3199(ctx: PipelineContext, act: str, index: int) -> None:
+    """CS3199 菜单 Act 帧(subid 恒 1, 与抓包一致)。"""
+    body = json.dumps({"index": index, "act": act, "subid": 1},
+                      separators=(",", ":")).encode()
+    _ = ctx.conn.send_frame(3199, 0, 0, 0, ctx.sid, body)
+
+
+def _scan_sc100_reject(ctx: PipelineContext, window: float) -> str | None:
+    """Pump 一个窗口并扫描帧: SC100 Type=9 → 返回 Msg, 否则 None。
+
+    SC-1 zlib 批量帧(msg_id==-1)不拆包 — 抓包实证存在独立 SC100 帧,
+    拆包成本高且无必要; 批量帧内的 SC100 视为观测不到(偏乐观)。
+    """
+    from pbot.bot.runner import pump
+    from pbot.world.update import body_json
+
+    frames = pump(ctx.conn, ctx.world, ctx.updater, window)
+    for f in frames:
+        if f.msg_id == -1:
+            continue  # 批量帧不拆包(ruling 4)
+        if f.msg_id == 100:
+            j = body_json(f)
+            if int(j.get("Type", 0)) == 9:
+                return str(j.get("Msg", ""))[:60]
+    return None
+
+
+def run_task(ctx: PipelineContext) -> TaskResult:
+    """发送开板+开启 Act, 5s 内无 SC100(Type=9) 拒绝即成功。"""
+    lv = ctx.world.me.level
+    if lv < LEVEL_NEED:
+        # 仍发一次 — 服务端是权威(抓包实证 40 级槽拒绝/35 级静默成功)
+        ctx.log.warning("[T6] 镜像等级 %d<%d — 发送并按回执判定", lv, LEVEL_NEED)
+    _send_3199(ctx, "@openmianban,1", 104)
+    time.sleep(1.0)
+    if msg := _scan_sc100_reject(ctx, 1.0):
+        return TaskResult.fail(f"开板即拒: {msg}")
+    _send_3199(ctx, "@mingge_kaiqi,1", 39)
+    deadline = time.time() + WAIT_S
+    while time.time() < deadline:
+        if msg := _scan_sc100_reject(ctx, 0.25):
+            return TaskResult.fail(f"服务器拒绝: {msg}")
+    return TaskResult.done("5s 静默 — 神通已开(35级槽)")