# v46 发包打怪 —— 规格与实现 > 2026-10-12 01:00 | 全部结论均为 CE 实测,非推测。产物:`旧版本更新_修复后_v46.e` ## 一句话定案 **「发包打怪」的目标ID = 怪物对象 `+0x14`(网络实体ID)**,**不是**助手一直在用的 `+0xC`(槽位ID)。 两者是同一只怪身上的两个不同字段: | 字段 | 偏移 | 取值(同一只野猫) | 用途 | |---|---|---|---| | 槽位ID | `对象 + 0xC` | **9213** | 助手 `选中ID()` 写进 `[人物+0x1D24]`,让客户端"选中"它 | | **网络ID** | `对象 + 0x14` | **10370** | **所有发包(攻击 / 选中包)的目标ID** | ## 全链路读法(#怪物基址值 = 0x03C35758,#人物基址值 = #坐标基址值 = 0x03C441BC) ``` 对象 = 读dword(#怪物基址值 + (8000 + x)*4) x = 1..2000 ├ 读dword(对象 + 0x08) == 0x2E (46) → 是怪物(0x31=人物) ├ 读dword(对象 + 0x0C) → 槽位ID(8000+创建时槽号) ├ 读dword(对象 + 0x14) → ★网络ID(发包用) ├ 读文本(对象 + 0x364) → 名称(BIG5) ├ 读dword(对象 + 0x5F4 / 0x5F8 / 0x5FC) → 当前血 / 血上限 / 等级 └ 读小数(对象 + 0x1F84 / 0x1F8C) → 怪物坐标 x / y 选中槽位 = 读dword( 读dword(#坐标基址值) + 0x1D24 ) ← 助手 选中ID() 的写入点 自身坐标 = 读小数( 读dword(#人物基址值) + 0x1F84 / 0x1F88 / 0x1F8C ) (X / Z / Y) ``` ## 闭环证据(三条互证,同一数值 10370) 1. 用户实测攻击包 off8 = `82280000` = **10370**(`辅助测试拦截.txt` 23:40:13) 2. CE 读「槽位 9213 的怪对象」`+0x14` = **10370** 3. 日志里客户端自己发的选中包 `EB010000 88100400 82280000 55AA` —— off8 同样是 10370 另:相邻两只怪 `+0x14` = 10369 / 10370(连续),`+0xC` = 9212 / 9213,两套编号完全独立。 ## 攻击包 42 字节布局(修正版) ``` off 0 u16 0000 会话头(助手自造包一律填 0,实测可用) off 2 u16 0000 off 4 u16 0900 opcode = 9 off 6 u16 2000 长度 = 32 (= 总长 42 − 10) off 8 u32 网络ID ★对象 + 0x14 off 12 u32 技能编号 普攻 = 0;武功 = 职业×100000 + 101 off 16 f32 自身 X [人物基址值] + 0x1F84 off 20 f32 15.0 常量 0x41700000(实测全部 36 条包恒为此值) off 24 f32 自身 Y [人物基址值] + 0x1F8C off 28 u32 0 off 32 u32 普攻序号 普攻全局自增;放技能时为 0 off 36 u32 0 off 40 u16 55AA ``` 样例(真实抓包):`00000000 09002000 82280000 00000000 47AA8443 00007041 D4674A44 00000000 06000000 00000000 55AA` 选中包 14 字节:`0000 0000 8810 0400 [网络ID u32] 55AA`(off8 同样是 `+0x14`) ## v46 新增内容(纯新增,未改动任何既有子程序 / 未动界面) - 全局变量 `全局_普攻序号, 整数型` - 子程序 `发包打怪 (怪物对象, 技能编号=可空)` → 逻辑型 - 子程序 `发包打怪_打选中怪 (技能编号=可空)` → 逻辑型 - 子程序 `取怪物对象_按槽位ID (槽位ID)` → 整数型 ⚠️ 反查注意:**怪物表数组下标 ≠ 对象 `+0xC`**(对象会被复用/移动,实测槽位 9213 一度指向 `+0xC=9214` 的对象),所以 `取怪物对象_按槽位ID` 走的是「遍历 2000 槽比对 `+0xC`」。 ## 怎么用 **挂机打怪**(推荐,复用助手已有的怪物遍历): ``` 遍历怪物 → 拿到对象 → 发包打怪 (对象, 0) ' 普攻 遍历怪物 → 拿到对象 → 发包打怪 (对象, 900101) ' 乐师技能 ``` **手动测试**:在 IDE 给按钮写事件 `发包打怪_打选中怪 ()` —— 游戏里选中一只怪,点一下即可。 **纯手动验证**(用现有「发包1」按钮,无需装 v47): 把下面这串贴进「封包过滤编辑框」点发包(坐标是 01:54 读到的,若角色移动过需换新值): ``` CE040000090020008228000000000000008081430000704100C0554400000000010000000000000055AA ↑全服ID ↑op/len ↑网络ID ↑普攻 ↑自身X ↑15.0 ↑自身Y ↑序号 ``` > 旧版给的 `00000000` 抬头已作废 —— 见下面 v47 修正。 ## v47 修正:全服ID 必须填真值(01:55) **问题**:v46 把包首 2 字节硬填 `0000`(沿用了助手既有自造包的写法),但 DLL 权威实现是读真值: `人物全服ID = 内存_读字节集 (角色基址 + 20, 2)`(20 = 0x14)。 **CE 实测(角色「辅助测试」)**:`[人物对象 + 0x14]` = `CE04` = **1230**,与日志里该客户端自己发的 `CE04000007003800…` 完全一致。 (日志里看到的 `EB010000…` 是**另一个客户端**的包 —— 用户三开 `YGOnline.exe`,`辅助测试拦截.txt` 同时记录了同机其他窗口的流量。别拿 EB01 当本角色的全服ID。) **v47 改动**(一行): ``` - 封包内容 = 机器码到字节集 (“0000000009002000”) + … + 封包内容 = 内存_读字节集 (全局_进程句柄, 人物对象 + 十六到十 (“14”), 2) + 机器码到字节集 (“000009002000”) + … ``` 产品:`旧版本更新_修复后_v47.e`(2,984,584 B,t2e 0 错 0 警,三门禁 0,`助手版本号` = 47)。 ⚠️ 踩坑记录:把 `'` 注释插在 `.子程序` 声明行与 `.局部变量` 块之间 → t2e 报 43 个「无法识别的行代码(自动注释)」+「未知的变量」连锁错误。注释必须放在 `.局部变量` 块**之后**。 ## 待用户实测确认 1. 包发出去后怪是否掉血(服务端是否接受自造包) 2. 普攻序号是否必须严格自增(若服务端不校验,可恒填 1)