Oblivion Mod:Save File Format/ACHR Uncertainties

The UESPWiki – Your source for The Elder Scrolls since 1995
Jump to: navigation, search

This article summarizes uncertain information about the ACHR and ACRE change records.

Overview[edit]

Known record storing orders
Consult Locations of Subrecords for certain locations and Appearance of Subrecords table below to get an overview of currently known record storing order.

The Actor Flag is a one byte flag. It has following known states:

  • 0 - High
  • 1 - Mid High
  • 2 - Mid Low
  • 3 - Low
  • FF - None.

It seems that the Actor Flag defines the role of an NPC actor and the appearance of subrecords in the ACHR record. There are named subrecords like Scale, Run Once and so on triggered by the records general flags and subrecords or sections with coded names that seems to be presented as two byte hex values. For instance in different ACHR records of NPC high actors there can be found subrecords with hex codes 0x803F, 0x80BF or 0x3036 at fix locations. Meaning is unknown. Inside often found references (iref) and or values(float).

Some named subrecords can be found in a structure containing flags and corresponding sets of values. It is suggested to be the Actor Properties structure and describes changed essential actor properties. Consult Properties for detailed information.


Some change records internal formats are still unknown. At best you can see here:

  1. Is change record's length constant or variable.
  2. Flags that are indicating change record's existence in the record.
    • If there is more than one flag, then it is possible that there multiple flags indicating change record - or there wasn't enough data to find single flag.
    • It is also possible that multiple change records are sharing same flags or change records are actually same record - they just have different name in dump file.
  3. Change record's minimal and maximal lengths.
  4. Possible substructures lengths inside change record. This length is largest common divider from all change records minimal and maximal lengths.

Appearance of Subrecords depending on Actors Role[edit]

Table describes appearance of subrecords depending on the state of the Actor Flag. This table is very speculative but provides currently a usable understanding of subrecord locations that helps to walk through a ACHR change record. Subrecord names with unknown meaning but fix locations are represented by their hex-values. Some other have only suggested names because it is unknown where they belong to.

How to read the table:

  • a row filled with Aquamarine color means that the subrecord appears when the records general change flag is set
  • a colored cell under the Actor Flag name means that the subrecord appears only when the corresponding flag is set
Name Type Size [bytes] Info High MidHigh MidLow Low None
Cell Changed struct 16
Created struct 36
Moved struct 28
Actor Flag byte 1 flag
Form Flag ulong 4
Temporary Attribute Changes struct 876 present only if PC record (0x14)
Inventory struct
Actor Properties struct[num]
Havok Moved struct[size]
Scale float 4
Dialogue/Mount Horse struct
Active Pack Data struct
0x362e/0x3630/0x3646 32
Game Modifier struct[num]
unknown 9
Magic Modifier struct[num]
unknown 6/5/2/0 ?depends on actorFlag?
0x3F80 6
Run Once FormID 4
unknown 25
0xFFFF 34 ?0xff ff 00 7f in every save file?
0x3F80 18 also 0x3FB3, 0x3F8C, 0x3F86
Animation #1 struct
Unknown Struct struct[num] {{size, iref, flag, data[size]}, ... }
Divider 19 usually 0x1, ?belongs to Anim #1?
Divider 84 always present (0x1)
0x3F80 40
Unknown Struct struct[num] {{byte[13}, ... } ?thrown inventory items?
0x4CFF/0x4C03/0x58FF 77/77/87
0x3F80 74
Common Divider #1 flag 1 usually 0x1, common means it is a flag at a fix location for all records
Life State flag 1
Disposition Modifier struct[num]
Equipment ulong 4 meaning unknown
Indicator
short 2 belongs to Common Divider #1:
  • Indicator = 0x0
    • and Com Div #1 = 0, than skip 4 bytes
    • and Com Div #1 = 1, than skip 8 bytes
  • Indicator = 0x1 skip 16
  • Indicator = 0x100 skip 17byte
Script Modifiers struct[num]
unknown 17/8 skip 17 bytes if Actor Flag not 0xFF (None)
Common Divider #2 flag 1 Usually 0x1
  • PC record (0x14): always skip 38 bytes to reach PC section
  • NPC record: skip 9 + 2 bytes till records end
PC section present only if PC record (0x14)

Active Package Data[edit]

The interpretation of this subrecord is very speculative. It is not backed up by text file dumps and its meaning is deduced from found data inside this subrecord.
The subrecord is present for all type of actors. Its length is minimum 17 bytes except for None- actors where it has a fix length 6 bytes.
It is suggested that the subrecord stores the coordinate offset from a package's target reference point along with a flag that describes the state of the current package.

Name Type/Size Info
-AI Pack iref actually it appears and is an iref that points to a PACK only if the read number is greater than two otherwise it is the type (see next row), other conditions where not found
type ulong seems to be related to property flag 0x1f, see Properties
X float coordinate offset
Y float coordinate offset
Z float coordinate offset
flag ubyte unknown
None - Actor
value
float
unknown
ushort

Life State (6)[edit]

This change record is used in ACHR, ACRE record types.

Name Type/Size Info
state ubyte Enum:
  • 0 = Alive
  • 1 = Dying
  • 2 = Dead
  • 3 = Unconscious
  • 4 = ?
  • 5 = ?
  • 6 = ?

Disposition Modifiers (15)[edit]

Entries in this subrecord are modifying an actors disposition towards another NPC.

This change record is used in ACHR, ACRE record types.

Name Type/Size Info
num ushort length of sub structure array
dispModifiers struct[count]
reference
iref points to an actor (ACHR)
modifier
ulong value added to initial disposition

Movement Blocked (17)[edit]

This change record's length is constant 32 byte(s).

This change record is used in ACHR, ACRE record types. There was 14 change records in save files.

This information is NOT verified from actual save files.

Name Type/Size Info
unknown ubyte[32] Constant length of observed change records.

Run Once (19)[edit]

This change record's length is constant 22 byte(s).

This change record is used in ACHR, ACRE record types. There was 6 change records in save files.

This information is NOT verified from actual save files.

Name Type/Size Info
unknown ubyte[22] Constant length of observed change records.


Magic Modifiers (20)[edit]

Entries in this subrecord are modifying base actor values. They are used for temporary and dispellable magic effects.

Despite the fact that there is a counter for the amount of entries the sub structure array never contains only one entry. There will be zero entries (number equals zero) or not less than two entries.

This change record is used in ACHR, ACRE record types.

Name Type/Size Info
num ushort length of sub structure array
magModifiers struct[num] collection of modified actor values
index
ubyte base actor value that is modified, see Actor Value Indices
value
float modifier added to base actor value

Script Modifiers (21)[edit]

Entries in this subrecord are modifying base actor values. They are used for temporary and non-dispellable scripted effects.

This change record is used in ACHR, ACRE record types.

Name Type/Size Info
num ushort length of substructure array
scriptModifiers struct[num] collection of modified actor values
index
ubyte base actor value that is modified, see Actor Value Indices
value
float modifier added to base actor value

Game Modifiers (22)[edit]

Entries in this subrecord are modifiers to base actor values. They are used for permanent effects.

This change record is used in ACHR, ACRE record types.

Name Type/Size Info
num ushort length of struct
gameModifiers struct[num] collection of modified actor values
index
ubyte base actor value that is modified, see Actor Value Indicies
value
float modifier added to base actor value

Animation (25)[edit]

Part of properties section. See Properties, specifically flag 0x4a.

Animation data seems to be divided into two parts. For all records, if triggered by records flags, there is the Animation 3rd Person view section. Only for the PC change record (0x14) there exists a second part and this is probably the first person view data. In PC change record both parts are not connected. There is a defined gap in between filled with other data. It seems that the type of the current animation (Action, Idle) is described with special codes and only values of some variables are stored.

This change record is used in ACHR, ACRE, REFR record types.

This information was found in a couple of actual save files.

Name Type/Size Info
Animation 3rd Person
animName ushort ?type of animation?
list() list, terminates with 0x0000
animCode
ushort defines structure of data
dataStruct
different animation control data
...
next animation data code
...
next animation data
0x0
ushort indicates end of list
parent iref reference to parent animation (bench, bed)
animCode: 0x0022
ushort optional, only if parent not 0
dataStruct #2
...
gap other data
...
Animation 1st Person appears only within PC's ACHR change record
animName ushort ?type of animation?
list() list, terminates with 0x0000
animCode
ushort defines structure of data
dataStruct
different animation control data
...
next animation data code
...
next animation data
0x0
ushort indicates end of list
dataStruct #3 no animation code, always there
unknown byte[35] unknown animation data

Animation names[edit]

Meaning of animation names are unknown.

Name Info
0x01ff
0x05ff
0x09ff
0x11ff
...

Animation Data Codes[edit]

Meaning of codes are unknown.

Name Type/Size Dependent Data Structure Info
0x0100 ushort
1
0x0115 ushort
1
0x0029 ushort
1
0x0000 ushort
1
0x0021 ushort
1
0x0022 ushort
2
...

Data Structure[edit]

Only loop time variables are verified from in-game debug tables. All other are guessed.

Number Name Type/Size Info
1
unknown int ?
unknown byte[11] ?
time float ?loop time?
unknown int ?
time float ?loop time?
time float ?loop time?
unknown int ?always 0xff 7f ff ff?
2
unknown int ?
unknown int ?
unknown int ?
unknown ushort ?code?
time float ?
unknown int ?
time float ?
time float ?
unknown int ?
3
unknown int ?
unknown int ?
unknown int ?
time float ?
time float ?
time float ?
unknown int ?

Dialogue, Mount Horse, Follow[edit]

It is suggested that this subrecord defines the procedure of the current AI package of an NPC actor. Text file dumps from save files include a formid with the subrecord special names. Except for the named Dialogue subrecord there is encountered a fix length of 32 bytes.
The Dialogue subrecord seems to appear when two NPC actors are in a conversation. For one actor the subrecords length will be 5 bytes (formid and type flag). This can be recognized by simultaneously set 'Non-saved-Package' flag. The other conversation partner will have a full data section with used topic texts and paths to voice files along with a data section containing reference to the targeted actor.

This change record is used in ACHR, ACRE, REFR record types.

Name Type/Size Info
reference formid seems to be an in game created record (0xFF...)
flag ubyte
  • 0x12 - Dialogue
  • 0x16 - Mount Horse
type1 ubyte
  • 0x4 - horse data
  • 0x6 - target data
type2 ubyte
  • 0x8 - topic data
size ushort size of target data section, if Dialogue subrecord else it is zero
Dialogue
targetData
struct[size]
size
ushort overall size of topic data section
num
ushort Number of subrecords
topicData
struct[num]
flag
ubyte mostly 0x1
text
bstring used topic text
path
bstring relative path to voice file
unknown
struct[25]
indicator
ushort always 0x0, ?terminates subrecord?
Mount Horse
unknown
struct[23]

Equipment (29)[edit]

This change record is used in ACHR record types.

Name Type/Size Info
hash ulong