========================================================== 遍历队员(组队成员)—— 2026-09-26 生成 ========================================================== 【先说结论:旧队员基址还在记录里,但不能用】 · 资料库原始记录(25_基址总表_更新版_0924.md:165): 队员基址 = 0x03148650 「固定 8,(x-1)×4+基址 读队员对象」 队员对象 +0x208 = 队员序号 / ID(2 字节,转队长/踢人封包用) · 但 基址全量复验报告.md:143 / :145 早就把它判死: 「26 项全部 0 引用,包括 #队员基址 0x03148650 …… 队员基址 依然是空白项,必须用指针扫描现找。」 · 本次(2026-09-26)用静态 PE 分析复核,结论一致: → 在当前 YGOnline.exe 里扫 0x03148650 的绝对寻址引用:0 处 → 对照组 0x03165090(公认失效的旧游戏基址):0 处 → 而本轮活体可用的 0x0188C60C:18 处 所以 0x03148650 确实已被本版本废弃,直接填进去遍历必然全是 0。 · 好消息:队员对象结构体本身是活的。 [reg+0x208] 这种「队员序号」访问,当前版本有 47 处读、 108 处写,说明成员对象还在,只是「从哪儿拿到对象指针」的 入口数组换了地方 —— 需要活体重新定位。 【所以这个子程序写成「基址可替换」的形式】 你找到一个能用的队员数组基址后,只改 #队员基址值 一个常量即可。 定位办法见本文件最下面第三节(CE 三步搞定)。 ========================================================== ★ 2026-09-27 二次修订:为什么「源码复制过去 无法识别」 ========================================================== 根因:.子程序 / .参数 / .局部变量 / .常量 这几种带点的行, 不是普通语句,而是【IDE 管理的结构】—— 代码区里根本敲不出来, 从外部整段粘文本它当然不认。 正确姿势:【先搭壳,再粘身】 壳(子程序名 / 返回值类型 / 参数 / 局部变量 / 常量)→ 用 IDE 表格建; 身(纯语句)→ 才是可以整段粘的。第三步给的三段就是纯语句体。 ────────────────────────────────────────────── 第一步:常量表加 4 行(左侧点「常量表」逐行加) ────────────────────────────────────────────── 名称 值 说明 队员基址值 51676752 0x03148650 旧记录(已失效,待换新) 队员位置值 1340 0x53C 容器槽位起点 队员序号值 520 0x208 队员序号 / ID 队员名称值 256 0x100 昵称(Big5),乱码就换 100 / 264 / 352 试 类型列默认(文本型)即可,语句里全部已套 到整数(),不用纠结。 ────────────────────────────────────────────── 第二步:搭三个子程序壳(插入 → 子程序,照下表填) ────────────────────────────────────────────── ① 遍历队员 返回值类型: 逻辑型 参数: 最大人数 (整数型)、是否打日志 (逻辑型) 局部变量: 容器指针、队员对象、格号、序号、成员数 (整数型) 名称、行文本 (文本型) ② 读队员序号 返回值类型: 整数型 参数: 格号 (整数型) 局部变量: 容器指针、队员对象 (整数型) ③ 更新流程指示线 返回值类型: 无 参数: 步骤文本 (文本型)、进度值 (整数型) 局部变量: 安全进度 (整数型) ────────────────────────────────────────────── 第三步:把下面三段语句体,各粘进对应的壳里 ────────────────────────────────────────────── 前提:全局_进程句柄 / 挂机信息 / 自定义时间() / 编码_BIG5到简体 / 内存_读整数型 / 内存_读文本型 你工程里已有(背包代码在用), 名字不一样的粘完按报错改掉即可。 「流程指示线」推进有三处:开始 0% / 每读到一人 (格号÷最大人数×100) / 结束 100%;真正动控件的是 ③,控件写法四选一见注释。 ═════ ① 遍历队员 → 语句体(整段粘进壳里) ═════ 容器指针 = 内存_读整数型 (全局_进程句柄, 到整数 (#队员基址值)) 如果 (容器指针 = 0) 如果 (是否打日志) 挂机信息.加入文本 (自定义时间 () + " [队员] 队员基址为空,队伍可能未成立" + #换行符) 结束如果 返回 (假) 结束如果 更新流程指示线 ("队员基址有效,开始遍历", 0) 如果 (最大人数 < 1) ' 防止外面传 0 进来把 除零 崩掉 最大人数 = 6 结束如果 成员数 = 0 格号 = 1 循环判断 (格号 > 最大人数) 队员对象 = 内存_读整数型 (全局_进程句柄, 容器指针 + 4 × (格号 - 1) + #队员位置值) 如果 (队员对象 = 0) ' 空格直接跳过,继续找下一格 到循环尾 () 结束如果 序号 = 内存_读整数型 (全局_进程句柄, 队员对象 + #队员序号值) 名称 = 编码_BIG5到简体 (内存_读文本型 (全局_进程句柄, 队员对象 + #队员名称值)) 行文本 = "格" + 到文本 (格号) + " 序号" + 到文本 (序号) + " " + 名称 更新流程指示线 (行文本, 到整数 (格号 ÷ 最大人数 × 100)) 如果 (是否打日志) 挂机信息.加入文本 (自定义时间 () + " [队员] " + 行文本 + #换行符) 结束如果 成员数 = 成员数 + 1 格号 = 格号 + 1 结束循环 更新流程指示线 ("遍历完成,共 " + 到文本 (成员数) + " 人", 100) 如果 (是否打日志) 挂机信息.加入文本 (自定义时间 () + " [队员] 本次读到 " + 到文本 (成员数) + " 人" + #换行符 + #换行符) 结束如果 返回 (真) ═════ ② 读队员序号 → 语句体 ═════ ' 只要某一个队员的序号(转队长 / 踢人封包用),不想遍历就调这个 容器指针 = 内存_读整数型 (全局_进程句柄, 到整数 (#队员基址值)) 如果 (容器指针 = 0) 返回 (0) 结束如果 队员对象 = 内存_读整数型 (全局_进程句柄, 容器指针 + 4 × (格号 - 1) + #队员位置值) 如果 (队员对象 = 0) 返回 (0) 结束如果 返回 (内存_读整数型 (全局_进程句柄, 队员对象 + #队员序号值)) ═════ ③ 更新流程指示线 → 语句体 ═════ ' ★ 把下面 A~E 注释行里的「流程指示线1」换成你工程里的真实控件名。 ' 控件类型不同、方法名不一样,按你实际的类型四选一,其它行删掉。 ' 另外:这个子程序若放在【全局】程序集里,控件名要带窗口前缀写成 ' 窗口1.流程指示线1.置进度值 (安全进度) ' 只有控件和本子程序在同一个窗口程序集里,才能直接写 流程指示线1。 安全进度 = 进度值 如果 (安全进度 < 0) 安全进度 = 0 结束如果 如果 (安全进度 > 100) 安全进度 = 100 结束如果 ' 【A】进度条型(最常见): ' 流程指示线1.置进度值 (安全进度) ' 【B】标签 / 文本型: ' 流程指示线1.标题 = 步骤文本 ' 【C】列表型(超级列表框 / 列表框,每一步追加一行): ' 流程指示线1.插入项 (-1, 步骤文本) ' 【D】状态条 / 滑块型: ' 流程指示线1.位置 = 安全进度 ' 【E】进度条 + 文字一起(若控件有 两个属性 可这么写): ' 流程指示线1.置进度值 (安全进度) ' 流程指示线1.标题 = 步骤文本 ========================================================== 二、找到了新基址之后怎么做(改动清单) ========================================================== 1. 把新的队员数组基址(十进制)填进常量表「队员基址值」的值里 例:找到 0x03C1A2F8 → 填 63021816(换算我已核过) 2. 如果 队员名称 读出来是乱码或空,把 #队员名称值 逐个试: 0x64(100) / 0x100(256) / 0x108(264) / 0x160(352) (跟物品对象一个套路,读出来是 Big5,用 编码_BIG5到简体 转) 3. 等级 / 血量 目前是 0 = 没读;你要哪个数值,告诉我字段, 我在当前版本静态扫一遍偏移量再给你,别拿旧表里的数字硬填。 ========================================================== 三、CE 里三步定位队员数组基址(游戏必须开着、已进组) ========================================================== 第 1 步 开组,组里至少 2 个人(自己 + 1 个队友),把组队窗打开。 第 2 步 CE 内存视图里 手动添加地址,逐步试这几个候选(都是「数组基址」, 不是成员对象): 0x03148650 ← 旧的,先确认它现在是 0 0x674590 ← InterGroup 组队窗实例(0924 记录) 0x00BA2800 ← InterMyParty 实例 0x00BBE970 ← InterParty 实例 0x00B7BC50 ← InterMemberParty 实例 第 3 步 对每个候选,在「地址 → 数值」列按容器式往下数 8 个: +0x53C / +0x540 / +0x544 …… 看哪一格是一个「像队员对象」的指针 (先读 该指针+0x208,能出来一个 4 位以内的数字 = 序号,基本就对了) ★ 更快的一招:CE 里对 0x208 下「是什么访问了这个地址」, 命中处往上追,一定能追到一个数组基址 —— 这条路我们之前 在热血江湖上被 XIGNCODE 的硬件断点清DY清掉过,实测全 0 命中, 所以优先用上面的手工法,别浪费时间。 第 4 步 把正确答案发我,我直接把常量表里「队员基址值」的值改成新的, 顺手把你需要的等级/血/职业字段偏移一起补齐。 【正常表现,别误判】基址现在还是那个已失效的旧地址, 所以运行只会打印一行「队员基址为空,队伍可能未成立」然后返回假 —— 这是符合预期的,不是代码坏了。等你按第三节找到新基址填进来才会真出人。 ========================================================== 四、顺带:上一轮活动背包遍历还剩两处没合上 ========================================================== · #背包物品名称值 请你确认一下是 100(0x64) 还是 256(0x100) —— 旧常量表写 100,本轮活体测出来是 0x100,差在文件版本。 · #背包物品数量值 旧常量写 3404(0xD4C),这个本轮复核过,是对的, 但上一轮那份遍历代码里被注释掉了却还拿它当内层循环次数, 会把循环直接跑 0 次 —— 记得把 物品数量 = ... 那行放回来。 ==========================================================