外观
Unit Record 单位记录
状态:Authoritative Reference v1
1. 记录版本
Unit 有两种磁盘长度:
| BTL 版本 | 磁盘长度 | 原版加载路径 |
|---|---|---|
| v1 | 0x30 | FUN_0048052C 先扩展到 common 0x40 表示,再进入正常加载 |
| v2/v3 | 0x40 | FUN_0048059C 直接消费 common 记录 |
原版 Unit 构造主链:
text
raw Unit record
-> resolve Tile from +0x00
-> resolve ArmySettings from Army/Country/Ranking/Formation inputs
-> allocate runtime Unit
-> FUN_00476580 initialize
-> FUN_0048059C apply disk state
-> attach to Tile and Country collections因此本页描述的是 BTL 磁盘记录,不是 runtime Unit 对象布局。
当前 1.28.0 corpus:
text
Unit total = 127512
v1 = 17571
v2/v3 = 109941主要证据:
text
reports/btl_v1280_so_recovery.md
reports/btl_editor/round4/field_write_whitelist_matrix.csv
reconstruction/src/WC4.Runtime.BattleData/BtlRecords.cs2. 完整 byte map
说明:
Confirmed表示该行所写的具体语义已确认,不代表所有值域和运行时后续写入都闭合;Partial表示用途范围已知但完整业务语义仍开放;Unknown表示不得用经验名称填空;NoGo写入状态表示当前 Reference 明确不授权按该解释修改;- 其余字段的实际写权限由当前 BTL writer 产品门禁另行裁决,本 Reference 不自动授予写权限。
| Offset | Size | Raw type | 当前中文语义 / code name | 版本 | 语义状态 | 写入状态 |
|---|---|---|---|---|---|---|
+0x00 | 2 | uint16 LE | Unit Tile ID / TileId | v1-v3 | Confirmed | NotAssessed |
+0x02 | 1 | uint8 | Army bucket / ArmyTypeId,参与 ArmySettings 解析 | v1-v3 | Confirmed | NotAssessed |
+0x03 | 1 | uint8 | Ranking / effective elite level raw / Level;不是普通 HUD 经验等级 | v1-v3 | Confirmed | NotAssessed |
+0x04 | 1 | uint8 | 编制 / Formation | v1-v3 | Confirmed | NotAssessed |
+0x05 | 1 | uint8 | 朝向 / Direction | v1-v3 | Confirmed | NotAssessed |
+0x06 | 1 | int8 | 初始移动/运行状态 / MovementRaw | v1-v3 | Partial | NotAssessed |
+0x07 | 1 | uint8 | 初始回合/行动状态 / TurnStateRaw | v1-v3 | Partial | NotAssessed |
+0x08 | 2 | int16 LE | 未闭合 scalar / Stat08Raw | v1-v3 | Unknown | NoGo |
+0x0A | 2 | int16 LE | 未闭合 scalar / Stat0ARaw | v1-v3 | Unknown | NoGo |
+0x0C | 2 | int16 LE | 初始当前 HP / CurrentHp | v1-v3 | Confirmed | NotAssessed |
+0x0E | 2 | int16 LE | 初始最大 HP / MaximumHp | v1-v3 | Confirmed | NotAssessed |
+0x10 | 2 | int16 LE | 将领 ID / GeneralId | v1-v3 | Confirmed | NotAssessed |
+0x12 | 1 | uint8 | 将领军衔 / GeneralRank | v1-v3 | Confirmed | NotAssessed |
+0x13 | 1 | uint8 | 将领品质 / GeneralQuality | v1-v3 | Confirmed | NotAssessed |
+0x14..+0x16 | 3 | raw bytes | legacy/unknown bytes;不是将领装备槽 | v1-v3 | Unknown | NoGo |
+0x17 | 1 | uint8 | 技能等级槽 0 | v1-v3 | Confirmed | NotAssessed |
+0x18 | 1 | uint8 | 技能等级槽 1 | v1-v3 | Confirmed | NotAssessed |
+0x19 | 1 | uint8 | 技能等级槽 2 | v1-v3 | Confirmed | NotAssessed |
+0x1A | 1 | uint8 | 技能等级槽 3 | v1-v3 | Confirmed | NotAssessed |
+0x1B | 1 | uint8 | 技能等级槽 4 | v1-v3 | Confirmed | NotAssessed |
+0x1C | 1 | int8 | 单位目标标记 / ObjectiveMarker | v1-v3 | Confirmed | NotAssessed |
+0x1D | 1 | uint8 | 单位 AI mode raw / UnitAiModeRaw | v1-v3 | Partial | NotAssessed |
+0x1E | 1 | uint8 | 运输限制/状态 raw / TransportRestrictionRaw | v1-v3 | Partial | NotAssessed |
+0x1F | 1 | int8 | signed AI priority / PriorityRaw | v1-v3 | Confirmed | NotAssessed |
+0x20 | 2 | int16 LE | target-Tile-like reference / TargetTileRaw | v1-v3 | Partial | NoGo |
+0x22 | 2 | int16 LE | ArmyAIConfig group ID / ArmyAiConfigurationId | v1-v3 | Confirmed | NotAssessed |
+0x24 | 1 | int8 | behavior state / BehaviorStateRaw | v1-v3 | Confirmed | NotAssessed |
+0x25 | 1 | uint8 raw | BattleMode 6 / Frontier 相关 override gate/input | v1-v3 | Partial | NoGo |
+0x26 | 2 | int16 LE | behavior change round / BehaviorChangeRoundRaw | v1-v3 | Confirmed | NotAssessed |
+0x28 | 1 | uint8 | 初始士气状态 / MoraleRaw | v1-v3 | Confirmed | NotAssessed |
+0x29 | 1 | uint8 | 初始士气持续回合 / MoraleDurationRaw | v1-v3 | Confirmed | NotAssessed |
+0x2A | 1 | int8 | 死亡 Event ID / DeathEventId | v1-v3 | Confirmed | NotAssessed |
+0x2B | 1 | packed uint8 | mixed active flags / PackedFlags2B | v1-v3 | Partial | NoGo |
+0x2C | 1 | uint8 | defensive-distance raw / DefensiveDistanceRaw | v1-v3 | Partial | NoGo |
+0x2D | 1 | raw byte | 已确认可加载到 runtime counter-qualification blocker;完整生命周期/含义未闭合 | v1-v3 | Partial | NoGo |
+0x2E | 1 | raw byte | 未闭合 | v1-v3 | Unknown | NoGo |
+0x2F | 1 | uint8 raw | Elite 条件下的 skin/variant selector raw | v1-v3 | Partial | NoGo |
+0x30 | 1 | compressed uint8 | General equipment slot 0:medal-family code | v2/v3 | Confirmed | NotAssessed |
+0x31 | 1 | compressed uint8 | General equipment slot 1:medal-family code | v2/v3 | Confirmed | NotAssessed |
+0x32 | 1 | compressed uint8 | General equipment slot 2:medal-family code | v2/v3 | Confirmed | NotAssessed |
+0x33 | 1 | compressed uint8 | General equipment slot 3:ribbon-family code | v2/v3 | Confirmed | NotAssessed |
+0x34 | 1 | compressed uint8 | General equipment slot 4:ribbon-family code | v2/v3 | Confirmed | NotAssessed |
+0x35 | 1 | compressed uint8 | General equipment slot 5:ribbon-family code | v2/v3 | Confirmed | NotAssessed |
+0x36 | 1 | active extension byte | 原版会读取;精确语义未闭合 | v2/v3 | Partial | NoGo |
+0x37 | 1 | packed nibbles | active Feature slot0/slot1 cooldown | v2/v3 | Confirmed | NoGo |
+0x38..+0x3F | 8 | active extension bytes | 原版会读取,包含 signed/bitfield 等消费;逐字段完整语义未闭合 | v2/v3 | Partial | NoGo |
3. 关键字段详解
3.1 +0x02 不是简单的 ArmySettings.Type
+0x02 是 Army bucket 输入。最终 ArmySettings 解析还会结合 CountryDefinition、有效 Ranking 和 Formation。
因此旧工具若直接把 +0x02 显示为完整 ArmySettings.Type,会丢失真实解析关系。
3.2 +0x03 不是普通经验等级
当前证据支持它作为构造时 Ranking / effective elite level 类输入。它不能直接等同于 HUD 中玩家理解的普通“经验等级”。
当前 corpus:12 种值,范围 1..12。
3.3 +0x0C/+0x0E 是 HP 对
text
+0x0C CurrentHp
+0x0E MaximumHp当前 corpus:
text
CurrentHp = 0..25000
MaximumHp = 1..25000两者虽然是独立磁盘 scalar,但作者工具修改时必须考虑 CurrentHp <= MaximumHp 以及模式/定义缩放;读取语义确认不自动授权任意写入。
3.4 +0x14..+0x16 不是勋章槽
社区/第三方编辑器曾把这三个字节候选解释为将领徽章/装备。
原版 FUN_0048059C 不把它们作为装备读取;真正的 v2+ 六个装备槽位于 +0x30..+0x35。
语料还显示:
- 全部 Unit:
127512,+0x14..+0x16组合存在251条非零记录; - v2/v3 Unit:
109941,这三个字节全部为零。
因此当前非零实例来自 legacy v1 范围,但其原版语义仍未闭合。“v2+ 恒零”不能升级成 padding 结论。
3.5 +0x20 与 +0x22 必须区分
社区旧说法把 +0x22 称为 attack target。该说法已被原版 resolver 链否定。
text
+0x20 -> target-Tile-like short
+0x22 -> FUN_004BB7B4 -> ArmyAIConfig group lookup因此:
+0x22:ArmyAIConfig ID,Confirmed;+0x20:确实具有目标 Tile 类引用性质,但 behavior-specific 完整语义仍为Partial。
3.6 +0x25:Frontier 相关输入,但不能直接叫 Frontier flag
+0x25 是一个独立 byte,不属于 +0x24。
当前表现链已经确认:
text
BattleMode != 6
-> FrontierOverrideActive = false
BattleMode == 6 && Unit raw[0x25] == 0
-> FrontierOverrideActive = false
BattleMode == 6 && Unit raw[0x25] != 0
-> 继续依赖未闭合的 owner / feature gate
-> 当前必须 Deferred / Unknown原版后续路径可以在条件满足时解析 replacement ArmyDefinition,再选择新的 Motion template。
因此 +0x25 当前安全描述是:
BattleMode 6 / Frontier 相关单位定义覆盖的 gate/input。
不能直接命名为:
- Frontier flag;
- Frontier Army ID;
- skin ID。
证据:reconstruction/docs/rendering/static_unit_integration_report.md。
3.7 +0x2D:已从纯 Unknown 前进到 Partial
早期 writer audit 将 +0x2D..+0x2F 整体保留为 Unknown。后续 Fight 证据已经确认一个具体映射:
text
BTL Unit record +0x2D
-> FUN_0048059C
-> runtime Unit counter-qualification blocker field在已审计 selected Unit87 中,磁盘 +0x2D = 0 对应 runtime blocker Unit+0x104 = 0,并参与 Unit+0x104 <= 0 的 counter qualification。
但任意值域、其他 writer、生命周期和完整业务名称尚未闭合,所以仍为 Partial,不能把 selected-case 名称扩张成最终全局字段名。
证据:
text
reports/route5_fixed_seed_fight_recovery/fight_input_field_matrix.csv
reports/route5_fixed_seed_fight_recovery/final_counter_predicate_matrix.csv3.8 +0x2F:Elite 条件 skin/variant selector
静态单位表现链确认:
text
skin = ArmyDefinition.IsElite ? UnitRaw[0x2F] : 0随后该值进入 Unit 初始化的 skin/variant 状态。
这证明 +0x2F 不是安全 padding,但当前 Reference 仍保留 Partial,因为完整值域、所有 Elite 定义和其他消费者尚未形成全局闭合。
证据:reconstruction/docs/rendering/static_unit_integration_report.md。
4. General equipment +0x30..+0x35
这些字段只存在于 v2/v3 0x40 Unit record;v1 0x30 磁盘记录没有该区域。
4.1 槽 0-2:medal-family
空槽:
text
raw == 0默认解码:
text
type = raw
level = 1扩展编码区 171..230:
text
type = (raw - 1) / 10
level = (raw - 1) % 10 + 1原版槽族门:
text
Type 1..22
Type 40..43此外 (Type, Level) 必须能解析到 GeneralMedalSettings。
4.2 槽 3-5:ribbon-family
空槽:
text
raw == 0非零解码:
text
type = raw / 10 + 20
level = raw % 10原版槽族门:
text
Type 23..39同样必须存在对应定义。
4.3 Corpus
| Slot | 非零次数 | 不同 raw 值 | 观察范围 |
|---|---|---|---|
| 0 | 1568 | 38 | 1..229 |
| 1 | 1274 | 42 | 1..226 |
| 2 | 754 | 62 | 1..230 |
| 3 | 7050 | 76 | 31..195 |
| 4 | 6822 | 83 | 31..195 |
| 5 | 5230 | 79 | 32..195 |
所有审计到的非零值都能命中定义并通过对应槽族门。
详细证据:reconstruction/docs/btl_editor_round11_unit_medal_ribbon_field_audit_report.md。
5. +0x37 active Feature cooldown packed byte
这是 +0x36..+0x3F 中目前闭合程度最高的字段。
v2+ 持久化格式:
text
low nibble = active Feature slot0 cooldown
high nibble = active Feature slot1 cooldown反序列化:
text
slot0 = packed & 0x0F
slot1 = packed >> 4序列化:
text
packed = (slot1 << 4) | slot0该结论已经跨 ARM64/x86 对齐:
- 构造时两个 cooldown 清零;
- runtime copy 会复制两槽;
- v2+ load/save 使用
record+0x37; - 正值在回合维护中递减;
- active Feature 执行会写入对应槽 cooldown。
Type 0x5D death-protection 只是 slot0 cooldown 的一个消费者,不能因此把整个 +0x37 命名成“死亡保护冷却”。
主要证据:
text
reconstruction/docs/route5_fixed_seed_fight_round8_death_protection_report.md
reports/route5_fixed_seed_fight_recovery/death_protection_lifecycle_matrix.csv6. +0x36..+0x3F 不得视为 padding
社区旧资料曾遗漏或把该区间视为 unused/unknown padding。原版 FUN_0048059C 实际会读取整个 v2+ extension range。
当前 109941 个 v2/v3 Unit 中有 440 条记录在该区间存在非零值;native consumer 已证明这里包含 signed、nibble 和 bitfield 数据。
目前只有部分子字段达到独立命名标准,尤其 +0x37 已闭合。其余字节仍应 raw-preserve,不能因为 Reference 尚未命名就删除、清零或批量编辑。
7. 当前 corpus 摘要
以下统计来自既有 field audit:
| 字段 | 观察值摘要 |
|---|---|
+0x02 ArmyTypeId | 74 种,1..101 |
+0x03 Level | 12 种,1..12 |
+0x04 Formation | 5 种,0..4 |
+0x05 Direction | 2 种,0..1 |
+0x06 MovementRaw | 25 种,0..28 |
+0x07 TurnStateRaw | 当前 corpus 全 0 |
+0x08 Stat08Raw | 当前 corpus 全 0 |
+0x0A Stat0ARaw | 63 种,1..3000 |
+0x1F PriorityRaw | -100..100 |
+0x20 TargetTileRaw | -1..12006 |
+0x22 ArmyAIConfig ID | 0..529 |
+0x24 BehaviorStateRaw | 当前 corpus 全 0 |
+0x26 BehaviorChangeRoundRaw | 当前 corpus 全 0 |
+0x2A DeathEventId | 0..77 |
+0x2C DefensiveDistanceRaw | 0..200 |
这些是 观察范围,不是允许写入范围,也不是格式允许值域的上限证明。
8. 社区兼容结论
| 旧说法 | 当前裁决 |
|---|---|
+0x22 = attack target | Refuted;实际为 ArmyAIConfig ID |
+0x14..+0x16 = General equipment | Refuted |
+0x30..+0x35 = medal/ribbon | Confirmed with slot-family refinement |
+0x36..+0x3F = padding/unused | Refuted |
完整社区勘误见 ../community/corrections.md。
9. 当前主要 Unknown / Partial backlog
优先级较高:
+0x08完整语义;+0x0A完整语义;- legacy
+0x14..+0x16; +0x1D完整 AI mode enum;+0x1E各 Army/运输类型状态矩阵;+0x20behavior-specific target 语义;+0x25非零值与 Frontier owner/feature gate 完整语义;+0x2B全 bit mask;+0x2Cdefensive-distance 完整 consumer;+0x2D完整生命周期与值域;+0x2E;+0x2F完整 Elite selector 值域;+0x36/+0x38..+0x3F逐字段/逐 bit consumer。
这些条目应通过 native/corpus/runtime evidence 逐项闭合,不进行“合理化设计”。