.版本 2 '══════════════════════════════════════════════════════════════════ ' 开关小助手(大漠版)—— 纠正版 v2 2026-09-25 '────────────────────────────────────────────────────────────────── ' 这次纠正的 4 个硬伤: ' ' ① 删掉 按钮名称取编号 子程序。 ' 它是"找不到控件"的真凶:里头写死 啟動內掛丸=49 / 停止=50, ' 然后拿 控件+0x364 的值去比对。但实测(2026-09-25)内挂丸那几个 ' 控件的 +0x364 全是 0 → 比对永远不成立 → 取助手控件永远返回 0。 ' +0x364 根本不是功能号,已证实。 ' 现在改成纯按名称(+0x368,BIG5_GBK 转出来是简体)匹配。 ' ' ② 状态 参数不再被覆写。 ' 旧代码把 状态 = 读(控件+0x364) 覆写了参数, ' 后面 push 状态 推进去的其实是 0,不是 31/32。 ' 现在状态 只用来选命令字,读到的值另存 偏移值。 ' ' ③ ecx 传控件对象本身,不再传 控件地址 + 4。 ' (此前"控件+4"那条是从虚调用调度器混来的,跟 0x682880 不是一条路) ' ' ④ 名称必须用简体:启动内挂丸 / 停止内挂丸 / 设定内挂丸 / 关闭内挂丸 ' +0x368 经 BIG5_GBK 转换后是简体,传繁体一个都匹配不上。 ' '────────────────────────────────────────────────────────────────── ' ⚠ 必须知道的崩溃事实(静态反汇编坐实,别再试了): ' 命令字 50(停止)→ handler 0x683E29,全程不碰 0x3C441BC,安全。 ' 命令字 49(启动)→ handler 0x683834,第一句就读 [edx+0x54C0]: ' edx = 0 → 读 0x54C0 踩 64KB 禁区 → 崩 ' edx = -1 → 读 0x54BF 同样踩禁区 → 崩 ((-1)+0x54C0 会绕回) ' [0x3C441BC] 实测取值只有 0 或 -1 → 49 这条路径在当前游戏里必崩。 ' ' 所以本版:关(32) 已打通,可以放心用;开(31) 代码留着,但会崩, ' 要真正"开",得等「点击控件回调」那条路研究出来。 '══════════════════════════════════════════════════════════════════ ' ─────────────────────────────────────────────────────────────── ' 开关小助手 ' 用法: 开关小助手 (主线程编号, 32) 关 ← 可用 ' 开关小助手 (主线程编号, 31) 开 ← 会崩,别用 ' ─────────────────────────────────────────────────────────────── .子程序 开关小助手, , , 31是开 32是关 .参数 主线程编号, 整数型 .参数 状态, 整数型, , 31是开 32是关 .局部变量 控件地址, 整数型 .局部变量 命令字, 整数型 .局部变量 偏移值, 整数型 ' ── 1. 状态 → 命令字(状态 参数保持不动)── .如果 (状态 = 31) 命令字 = 49 ' ⚠ handler 0x683834,会崩 .否则 命令字 = 50 ' handler 0x683E29,安全 .如果结束 ' ── 2. 按名称找控件(不再经过 +0x364 那道错误的过滤)── .如果 (状态 = 31) 控件地址 = 取助手控件 (主线程编号, “启动内挂丸”) .否则 控件地址 = 取助手控件 (主线程编号, “停止内挂丸”) .如果结束 .如果真 (控件地址 > 0) ' 顺手把 +0x364 读出来看看(实测是 0, confirming 它不是功能号) 偏移值 = DM_CusData [主线程编号].dm.ReadIntAddr (DM_CusData [主线程编号].主窗口句柄, 控件地址 + 进制_十六到十 (“364”), 0) 调试输出 (“开关小助手 控件=” + 到文本 (控件地址) + “ +0x364=” + 到文本 (偏移值)) DM_CusData [主线程编号].dm.AsmClear () DM_CusData [主线程编号].dm.AsmAdd (“push 0”) DM_CusData [主线程编号].dm.AsmAdd (“push 0x” + 进制_十到十六 (命令字, )) DM_CusData [主线程编号].dm.AsmAdd (“mov ecx,0x” + 进制_十到十六 (控件地址, )) DM_CusData [主线程编号].dm.AsmAdd (“call ” + DM_CusData [主线程编号].基址.小助手CALL基址) DM_CusData [主线程编号].dm.AsmCall (DM_CusData [主线程编号].主窗口句柄, 6) DM_CusData [主线程编号].dm.Delays (300, 600) .如果真结束 ' ─────────────────────────────────────────────────────────────── ' 取助手控件 —— 纯按名称匹配,池容量 0x3A98 = 14998 ' 参数 按钮名称 请用简体: ' “启动内挂丸” / “停止内挂丸” / “设定内挂丸” / “关闭内挂丸” ' ─────────────────────────────────────────────────────────────── .子程序 取助手控件, 整数型 .参数 主线程编号, 整数型 .参数 按钮名称, 文本型, , 可空 .局部变量 S, 整数型 .局部变量 N, 整数型 .局部变量 控件对象, 整数型 .局部变量 读取值, 文本型 S = 0 计次循环首 (进制_十六到十 (“3A98”), N) 控件对象 = DM_CusData [主线程编号].dm.ReadIntAddr (DM_CusData [主线程编号].主窗口句柄, DM_CusData [主线程编号].基址.全局大列表基址 + S × 4, 0) .如果真 (控件对象 > 0 且 控件对象 ≠ 65535) 读取值 = BIG5_GBK (DM_CusData [主线程编号].dm.ReadStringAddr (DM_CusData [主线程编号].主窗口句柄, 控件对象 + 进制_十六到十 (“368”), 0, 0)) .如果真 (读取值 = 按钮名称) 返回 (控件对象) .如果真结束 ' 想看每个控件的名字,把下面这行反注释 '调试输出 (读取值) .如果真结束 S = S + 1 处理事件 () 计次循环尾 () 返回 (0) ' ─────────────────────────────────────────────────────────────── ' 按钮名称取编号 —— 整个子程序已删除 ' 原因:内挂丸控件的 +0x364 实测为 0,跟 49/50 比对永远匹配不上, ' 靠它做过滤会导致取助手控件 100% 失败。 ' 如果将来查明别的菜单控件 +0x364 确实存功能号,再恢复不迟。 ' ───────────────────────────────────────────────────────────────