# 地面物品对象结构(CE 实测) 2026-10-12 ## 结论 **地面掉落物 = 对象表(`#怪物基址值` `0x03C35758`,槽位 8000~9999)中 `+0x08 == 0x33` 的对象。** 遍历方式与怪物完全一致: ``` for i = 0 to 1999: obj = 读整数(0x03C35758 + (8000+i) * 4) if obj ≠ 0 and 读整数(obj + 0x08) == 0x33: → 这就是一件地面物品 ``` 判据为什么成立:背包里近满(96 格占用 77+),但对象表里 `0x33` **只有 2 个**; 背包物品的类型是 `0x1A`(格子对象),**不登记在场上对象表**。 所以对象表里出现的 `0x33` 必然是"掉在地上"的。 ## 字段表(`0x33` 对象) | 偏移 | 类型 | 含义 | 实测样本 | |---|---|---|---| | `+0x00` | dword | 资源/虚表指针 | `0x010C1B28` | | `+0x08` | dword | **类型标记 = `0x33`** | 33 | | `+0x0C` | dword | 槽位ID(与对象表 slot 号一致) | 9512 | | `+0x10` | dword | **堆叠数量** | 2 | | `+0x14` | dword | 归属者 = `-1`(无归属/公开) | FFFFFFFF | | `+0x58` / `+0x5C` | float | 渲染尺寸(动态) | 5.935 / 4.443 | | `+0x78` | dword | **物品编号** | `800000013`(熱血石) / `1000001025` | | `+0x80` | dword | 1 | | | `+0x94` | char[] | **物品名(BIG5,NUL 结尾)** | "熱血石" | | `+0x148` | float | **世界坐标 X** | 1780.00 | | `+0x14C` | float | **高度 Y** | 191.85 | | `+0x150` | float | **世界坐标 Z** | -174.00 | | `+0x164` / `+0x16C` / `+0x1A0` … | float | 同一坐标三元组的重复副本(3 处) | 同 `+0x148` | | `+0x228` 起 | float×8帧 | 动态渲染/包围盒数据(**不是物品位置**,勿用) | 随镜头变化 | ### 坐标字段的确认依据 - 只有 `0x33` 对象在 `+0x148` 有非零坐标;**怪物对象(`0x2E`)与人物对象(`0x31`)在 `+0x148` 恒为 0** (它们各自的坐标分别在 `+0x107C` / `+0x1F84`),说明 `+0x148` 是物品类专用字段。 - 高度分量 `191.85` 与人物高度字段(`195.95`,即 `人物+0x1F88`)只差 ~4, 符合"物品躺在地面上、略低于人物中心"。 - `+0x164` / `+0x1A0` 三处存放同一三元组,是典型的"位置快照冗余"。 - 排除项:`+0x228` 那组 8 帧坐标虽然数值上更靠近角色(当时 3~10 单位), 但逐次采样会漂移、且对象被回收后读到垃圾 —— 属于渲染插值数据,不可当物品位置。 ## 对象类型速查(`+0x08`) | 类型 | 含义 | 依据 | |---|---|---| | `0x31` | 人物(含其他玩家) | 名字 `+0x18`、等级 `+0x2760`、坐标 `+0x1F84/1F8C` | | `0x2E` | 怪物 / NPC | 名字 `+0x364`、血 `+0x5F4/5F8`、等级 `+0x5FC`、坐标 `+0x107C/1084` | | `0x33` | **地面物品** | 名字 `+0x94`、编号 `+0x78`、数量 `+0x10`、坐标 `+0x148/150` | | `0x1A` | 背包/容器格子 | 背包容器 `0x03BEF5D0` → `+0x53C` 槽位数组里全是它 | (其余类型多为特效/资源/残留对象,未定名。) ## 实测样本(2026-10-12 01:4x) ``` player = (1611.06, -362.49) ptr=0x69BE3670 slot=9189 id=1000001025 coord=(1757.00, ?, -176.00) ptr=0x69BE47B0 slot=9407→9512 id=800000013(熱血石) coord=(1784.00 → 1780.00, 191.85, -174.00) ``` 两个坑: 1. **对象会生灭**:`slot 9189` 那件几分钟后再读已经变成垃圾(`+0x08` 不再是 `0x33`), 说明物品被捡走/超时后对象池立即回收 —— 遍历时必须**当场判类型**,不能缓存指针。 2. **槽位会漂移**:熱血石从 slot 9407 变到 9512(对象指针没变)——再次印证 "槽位号 ≠ 对象身份",反查要遍历比对,不能靠槽位号直接索引。 ## 待用户实测确认 `+0x148` 的坐标(如 (1780,-174))**距角色约 261 单位**,比同屏怪物(<30 单位)远得多。 需要确认这是"角色走过路过留下的旧掉落"还是坐标字段另有含义: - 请在游戏里看一眼**脚下/附近地面上有没有「熱血石」**; - 若方便,站到掉落物旁边再读一次,看 `+0x148` 是否与角色位置吻合。 ## 遍历用 Lua(可直接在 CE 跑) ```lua local base = 0x3C35758 + 8000 * 4 -- = 0x3C3D458,槽位 8000 起 local cp = readInteger(0x3C441BC) local px, pz = readFloat(cp + 0x1F84), readFloat(cp + 0x1F8C) for i = 0, 1999 do local p = readInteger(base + i * 4) if p ~= nil and p ~= 0 and readInteger(p + 8) % 4294967296 == 0x33 then local x, z = readFloat(p + 0x148), readFloat(p + 0x150) print(string.format("物品: %s id=%d x%d dist=%.1f", readString(p + 0x94, 24), readInteger(p + 0x78), readInteger(p + 0x10), math.sqrt((x - px) ^ 2 + (z - pz) ^ 2))) end end ```