热血江湖 YGOnline.exe —— 自动处理组队(子程序集) 时间:2026-09-28 17:0x 目标:D:\rxjh2025\client\YGOnline.exe(32位,无ASLR,模块基址恒 0x400000) ================================================================================ 【一句话】 组队窗 = IFManager + 1256(0x4E8,InterParty) 左按钮 = 窗口 + 952(0x3B8,85,178) 右按钮 = 窗口 + 960(0x3C0,156,178) 中按钮 = 窗口 + 936(0x3A8,119,178) ← 未启用,别用 点法 = 按钮对象 + 12 现读控件ID → 按钮点击call(派发事件 0x409) 组队接受=952(左)/ 组队拒绝=960(右)已按你的命名采用为事实常量。 若担心版本更新把"左=接受"反置,下面"带闸门/带日志"可用 取组队接受按钮ID() 自判定代替; 该函数当场读按钮文字(接受/確認/確定/同意)判定,不会点反。 ★ 本文件顺带修正一处常量错误: 《窗口是否弹出_参数防呆_0928.txt》里写的 `组队按钮左 = 968 / 组队按钮右 = 976` **是错的**(0x3C8 / 0x3D0 那两个格子不是按钮)。 实测正确值:左 = 952(0x3B8)/ 右 = 960(0x3C0)。 以本文件与《按钮点击call_纠正_0928.txt》为准。 ================================================================================ 一、常量表(本次新增的都在最后 4 行;前面已有的别重复粘) ================================================================================ .版本 2 .常量 IFManager基址, "25740828" .常量 控件ID偏移, "12" .常量 控件类型偏移, "8" .常量 面板类型码, "24" .常量 窗口可见标志, "64" .常量 按钮类型码, "34" .常量 窗口子槽起点, "768" .常量 窗口子槽终点, "1532" .常量 窗口子槽个数, "192" .常量 交易窗口槽, "1236" .常量 组队窗口槽, "1256" .常量 通知窗口槽, "1028" .常量 交易接受, "908" .常量 交易拒绝, "916" .常量 组队接受, "952" .常量 组队拒绝, "960" ================================================================================ 二、变量声明(放「全局变量」表) ================================================================================ .版本 2 .全局变量 全局_组队已处理, 逻辑型 .全局变量 全局_交易已处理, 逻辑型 ================================================================================ 三、① 自动处理组队(最小版,直接可用) ================================================================================ 逻辑:窗口没弹 → 返回;弹出 → 点左按钮(接受)。 连点问题由「五、带闸门版」解决;只跑一次的场景用这个就够。 .版本 2 .子程序 自动处理组队 .局部变量 接口管理, 整数型 .局部变量 组队窗, 整数型 .局部变量 按钮, 整数型 .如果真 (窗口是否弹出 (窗口.组队) = 假) 返回 () .如果真结束 接口管理 = 内存_读整数型 (全局_进程句柄, #IFManager基址) 组队窗 = 内存_读整数型 (全局_进程句柄, 接口管理 + 窗口.组队) 按钮 = 内存_读整数型 (全局_进程句柄, 组队窗 + #组队接受) .如果真 (按钮 > 65536) 按钮点击call (内存_读整数型 (全局_进程句柄, 按钮 + #控件ID偏移)) .如果真结束 返回 () ================================================================================ 四、② 自动拒绝组队(想反过来就换这一行) ================================================================================ .版本 2 .子程序 自动拒绝组队 .局部变量 接口管理, 整数型 .局部变量 组队窗, 整数型 .局部变量 按钮, 整数型 .如果真 (窗口是否弹出 (窗口.组队) = 假) 返回 () .如果真结束 接口管理 = 内存_读整数型 (全局_进程句柄, #IFManager基址) 组队窗 = 内存_读整数型 (全局_进程句柄, 接口管理 + 窗口.组队) 按钮 = 内存_读整数型 (全局_进程句柄, 组队窗 + #组队拒绝) .如果真 (按钮 > 65536) 按钮点击call (内存_读整数型 (全局_进程句柄, 按钮 + #控件ID偏移)) .如果真结束 返回 () ================================================================================ 五、③ 自动处理组队_带闸门(推荐用这个:不会连点、窗口关了自动复位) ================================================================================ 闸门原理:点过一次就置 全局_组队已处理 = 真;窗口一旦消失就自动清零。 这样窗口弹着期间只点一次,新的一次邀请弹出来又能立刻响应。 不依赖计时器、不依赖延时,纯内存判定。 .版本 2 .子程序 自动处理组队_带闸门 .局部变量 接口管理, 整数型 .局部变量 组队窗, 整数型 .局部变量 接受ID, 整数型 .如果真 (窗口是否弹出 (窗口.组队) = 假) 全局_组队已处理 = 假 返回 () .如果真结束 .如果真 (全局_组队已处理 = 真) 返回 () .如果真结束 接口管理 = 内存_读整数型 (全局_进程句柄, #IFManager基址) 组队窗 = 内存_读整数型 (全局_进程句柄, 接口管理 + 窗口.组队) 接受ID = 取组队接受按钮ID (组队窗) .如果真 (接受ID ≤ 0) 返回 () .如果真结束 按钮点击call (接受ID) 全局_组队已处理 = 真 返回 () ================================================================================ 六、④ 自动处理组队_带开关与日志(受界面勾选框控制 + 全记录) ================================================================================ 开关控件名按你工程实际写。参考《队长自动组队_0928.txt》里用的是 `接受组队.选中` —— 名字不一致就改这一行,别改别的。 .版本 2 .子程序 自动处理组队_带日志 .局部变量 接口管理, 整数型 .局部变量 组队窗, 整数型 .局部变量 控件ID, 整数型 .如果真 (窗口是否弹出 (窗口.组队) = 假) 全局_组队已处理 = 假 返回 () .如果真结束 .如果真 (接受组队.选中 = 假) 返回 () .如果真结束 .如果真 (全局_组队已处理 = 真) 返回 () .如果真结束 接口管理 = 内存_读整数型 (全局_进程句柄, #IFManager基址) 组队窗 = 内存_读整数型 (全局_进程句柄, 接口管理 + 窗口.组队) 控件ID = 取组队接受按钮ID (组队窗) .如果真 (控件ID ≤ 0) 挂机信息.加入文本 (自定义时间 () + “[组队] 组队窗弹出但接受按钮读不到(窗口=” + 到文本 (组队窗) + “)” + #换行符) 返回 () .如果真结束 挂机信息.加入文本 (自定义时间 () + “[组队] 点接受按钮 窗口=” + 到文本 (组队窗) + “ 控件ID=” + 到文本 (控件ID) + #换行符) 按钮点击call (控件ID) 全局_组队已处理 = 真 返回 () ================================================================================ 七、⑤ 通用版:不依赖固定偏移,扫出来按坐标认左右(抗游戏更新) ================================================================================ 组队窗和交易窗用同一套对话框模板,三个竖条按钮坐标完全一样: 85 = 左(接受) 119 = 中(未启用) 156 = 右(拒绝) .版本 2 .子程序 取窗口按钮ID_按横坐标, 整数型 .参数 槽偏移, 整数型 .参数 横坐标, 整数型 .局部变量 接口管理, 整数型 .局部变量 窗口对象, 整数型 .局部变量 i, 整数型 .局部变量 子对象, 整数型 接口管理 = 内存_读整数型 (全局_进程句柄, #IFManager基址) .如果真 (接口管理 ≤ 65536) 返回 (0) .如果真结束 窗口对象 = 内存_读整数型 (全局_进程句柄, 接口管理 + 槽偏移) .如果真 (窗口对象 ≤ 65536) 返回 (0) .如果真结束 .计次循环首 (#窗口子槽个数, i) 子对象 = 内存_读整数型 (全局_进程句柄, 窗口对象 + #窗口子槽起点 + (i - 1) × 4) .如果真 (子对象 > 65536) .如果真 (内存_读整数型 (全局_进程句柄, 子对象 + #控件类型偏移) = #按钮类型码) .如果真 (内存_读整数型 (全局_进程句柄, 子对象 + 40) = 横坐标) 返回 (内存_读整数型 (全局_进程句柄, 子对象 + #控件ID偏移)) .如果真结束 .如果真结束 .如果真结束 .计次循环尾 () 返回 (0) .版本 2 .子程序 自动处理组队_按坐标 .局部变量 控件ID, 整数型 .如果真 (窗口是否弹出 (窗口.组队) = 假) 全局_组队已处理 = 假 返回 () .如果真结束 .如果真 (全局_组队已处理 = 真) 返回 () .如果真结束 控件ID = 取窗口按钮ID_按横坐标 (窗口.组队, 85) .如果真 (控件ID ≤ 0) 返回 () .如果真结束 按钮点击call (控件ID) 全局_组队已处理 = 真 返回 () ================================================================================ 八、⑥ 统一入口:一个子程序把交易 + 组队都管了 ================================================================================ 塞进挂机主循环里,每轮调一次即可(顺序:交易在前、组队在后,互不干扰)。 前提:主循环第一行已调过 窗口槽位表_初始化 ()。 .版本 2 .子程序 自动处理弹窗 自动处理交易 () 自动处理组队_带闸门 () 返回 () ================================================================================ 九、⑦ 诊断:点之前先看一眼(确认哪个是接受、哪个是拒绝) ================================================================================ .版本 2 .子程序 打印组队窗按钮表 .局部变量 接口管理, 整数型 .局部变量 组队窗, 整数型 .局部变量 i, 整数型 .局部变量 子对象, 整数型 接口管理 = 内存_读整数型 (全局_进程句柄, #IFManager基址) 组队窗 = 内存_读整数型 (全局_进程句柄, 接口管理 + 窗口.组队) 挂机信息.加入文本 (“=== 组队窗 槽1256 按钮表 窗口=” + 到文本 (组队窗) + “ ===” + #换行符) .如果真 (组队窗 > 65536) .计次循环首 (#窗口子槽个数, i) 子对象 = 内存_读整数型 (全局_进程句柄, 组队窗 + #窗口子槽起点 + (i - 1) × 4) .如果真 (子对象 > 65536) .如果真 (内存_读整数型 (全局_进程句柄, 子对象 + #控件类型偏移) = #按钮类型码) 挂机信息.加入文本 (“ +0x” + 取十六进制文本 (内存_读整数型 (全局_进程句柄, 组队窗 + #窗口子槽起点 + (i - 1) × 4)) + “ 槽” + 到文本 (#窗口子槽起点 + (i - 1) × 4) + “ ID=” + 到文本 (内存_读整数型 (全局_进程句柄, 子对象 + #控件ID偏移)) + “ 坐标” + 到文本 (内存_读整数型 (全局_进程句柄, 子对象 + 40)) + “,” + 到文本 (内存_读整数型 (全局_进程句柄, 子对象 + 44)) + “ 可用=” + 到文本 (内存_读整数型 (全局_进程句柄, 子对象 + 64)) + “ 生效=” + 到文本 (内存_读整数型 (全局_进程句柄, 子对象 + 72)) + #换行符) .如果真结束 .如果真结束 .如果真结束 .计次循环尾 () .如果真结束 ================================================================================ 十、组队窗实测结构(PID 14256,槽 1256,窗口对象 id 7029) ================================================================================ 偏移 对象 类型 控件ID 可见 坐标x,y 大小cx,cy 说明 +0x330 577C46B8 InterWindow 7030 1 362,95 220,300 ★内容面板 +0x3A4 5774C0B0 InterSTATIC 7031 0 0,0 0,0 (标签) +0x3A8 572C5518 ButtonClass 7032 0 119,178 18,60 (中按钮,未启用) +0x3B4 577502C8 InterSTATIC 7033 1 0,0 0,0 (标签) +0x3B8 572C9D00 ButtonClass 7034 1 85,178 18,60 ★左按钮(接受) +0x3C0 572C28D8 ButtonClass 7035 1 156,178 18,60 ★右按钮(拒绝) +0x3D4~+0x3F8 队员格/状态格 ×8(未显示) +0x400/+0x404 侧按钮(0,0 / 0,28 15x70) 要点: · 组队窗**没有 TextBox 子控件**(交易窗有 8 个)—— 别照抄交易窗的偏移。 · 取按钮不要从内容面板(+0x330)往下找:面板和按钮在内存里是**兄弟**, 都挂在 InterParty 对象的并列子槽上。直接从窗口对象 + 0x3B8 / +0x3C0 拿。 · 控件ID 每次开游戏都不一样(同一天见过 7034/7035、7037/7038…), 一律 读(按钮对象 + 12) 现读,**不要写死**。 ================================================================================ 十一、坑(三条,都是实测踩出来的) ================================================================================ 1. 组队窗按钮偏移 **不能套交易窗的**。交易窗 +0x3B8 读到的是垃圾(2543863649), +8 位置根本不是类型码 —— 套错不报错、但点了没反应。 两个窗口的偏移不同,因为 InterExchange 和 InterParty 是两个不同的类, 各自按自己的成员声明顺序排,差 0x2C(≈11 个成员)。 2. 判弹出只能看内容面板 +0x40,不能看窗口对象自己的 +0x40。 窗口对象的 +0x40 是"曾激活过"的粘滞标志,关窗不清零: 组队窗关掉之后它可能还是 1 → 会对着一个没显示的窗口点按钮。 用 窗口是否弹出 (窗口.组队),它扫的就是类型码 24 的面板。 3. 控件ID 从按钮对象 +0x0C 现读。`自动处理组队` 里那一行 `内存_读整数型 (全局_进程句柄, 按钮 + #控件ID偏移)` 就是干这个的,不要改成常量。 ================================================================================ 十二、最小接入步骤 ================================================================================ ① 工程里已有:窗口是否弹出 / 窗口槽位表_初始化 / 按钮点击call(没有就先看 《窗口是否弹出_参数防呆_0928.txt》《按钮点击call_纠正_0928.txt》) ② 粘本文件「一、常量表」里缺的那几行(至少 组队窗口槽 / 组队接受 / 组队拒绝 / 按钮类型码) ③ 粘「二、变量声明」两行 ④ 粘「五、③ 自动处理组队_带闸门」 ⑤ 挂机主循环里,`窗口槽位表_初始化 ()` 之后加一行 `自动处理组队_带闸门 ()` 或直接用「八、⑥ 自动处理弹窗 ()」一次把交易和组队都带上 挂机主循环示意: .版本 2 .子程序 挂机主循环 .局部变量 继续跑, 逻辑型 窗口槽位表_初始化 () 继续跑 = 真 .判断循环首 (继续跑) 自动处理弹窗 () 挂机逻辑 () 延时 (500) .判断循环尾 () 返回 () ================================================================================ 十三、依赖:取组队接受按钮ID(运行时自判定,不靠"左=接受"假设) ---------------------------------------------------------------- 上面"带闸门/带日志"都调这个。逻辑:当场读左/右两个按钮【指向的文字】, 匹配接受类词(接受/確認/確定/同意)就返回它;匹配到拒绝类词在左则改返回右。 两个都读不到时兜底返回左(沿用旧假设,并在日志提示)。 Big5 接受类:接受=B1B5A8FC 確認=BD54BB7B 確定=BD54A977 同意=A650B74E 拒绝类:拒絕=A9DAB5B4 取消=A8FAAEF8 忽略=A9BFB2A4 關閉=C3F6B3AC .版本 2 .子程序 取组队接受按钮ID, 整数型, , 自动判定左/右哪个是"接受",返回它的控件ID;都读不到返回 0 .参数 窗口对象, 整数型 .局部变量 左, 整数型 .局部变量 右, 整数型 左 = 内存_读整数型 (全局_进程句柄, 窗口对象 + #组队接受) 右 = 内存_读整数型 (全局_进程句柄, 窗口对象 + #组队拒绝) .如果真 (左 ≤ 65536 或 右 ≤ 65536) 返回 (0) .如果真结束 .如果 (按钮文字是接受 (左)) 返回 (内存_读整数型 (全局_进程句柄, 左 + 12)) .否则如果 (按钮文字是拒绝 (左)) 返回 (内存_读整数型 (全局_进程句柄, 右 + 12)) .否则如果 (按钮文字是接受 (右)) 返回 (内存_读整数型 (全局_进程句柄, 右 + 12)) .否则 返回 (内存_读整数型 (全局_进程句柄, 左 + 12)) .如果结束 .子程序 按钮文字是接受, 逻辑型 .参数 按钮对象, 整数型 .局部变量 前4字节, 字节集 .局部变量 i, 整数型 .计次循环首 (192, i) 前4字节 = 取字节集左边 (内存_读字节集 (全局_进程句柄, 内存_读整数型 (全局_进程句柄, 按钮对象 + (i - 1) × 4), 4), 4) .如果真 (前4字节 = 机器码到字节集 (“B1B5A8FC”) 或 前4字节 = 机器码到字节集 (“BD54BB7B”) 或 前4字节 = 机器码到字节集 (“BD54A977”) 或 前4字节 = 机器码到字节集 (“A650B74E”)) 返回 (真) .如果真结束 .计次循环尾 () 返回 (假) .子程序 按钮文字是拒绝, 逻辑型 .参数 按钮对象, 整数型 .局部变量 前4字节, 字节集 .局部变量 i, 整数型 .计次循环首 (192, i) 前4字节 = 取字节集左边 (内存_读字节集 (全局_进程句柄, 内存_读整数型 (全局_进程句柄, 按钮对象 + (i - 1) × 4), 4), 4) .如果真 (前4字节 = 机器码到字节集 (“A9DAB5B4”) 或 前4字节 = 机器码到字节集 (“A8FAAEF8”) 或 前4字节 = 机器码到字节集 (“A9BFB2A4”) 或 前4字节 = 机器码到字节集 (“C3F6B3AC”)) 返回 (真) .如果真结束 .计次循环尾 () 返回 (假) ================================================================================ 相关文件 D:\AI空间\rxjh\窗口是否弹出_参数防呆_0928.txt 判定子程序 + 初始化放哪 D:\AI空间\rxjh\按钮点击call_纠正_0928.txt 点按钮的机器码 + 三个名字的区别 D:\AI空间\rxjh\窗口按钮取法_固定吗_实测_0928.txt 偏移固定性 + 按钮对象结构 D:\AI空间\rxjh\组队窗口7034_7035_与弹出判定修正_0928.txt 组队窗完整子控件表 D:\AI空间\rxjh\队长自动组队_0928.txt 自己是队长 / 队长调度 ================================================================================