Oblivion Mod:Save File Format/ACHR

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

This page describes the save file format for both ACHR and ACRE change records, since the two records share an identical format. An ACHR Change Record (change record type 50) describes changes to placed instances of the game's non-player characters (ACHR mod file records). An ACRE Change Record (change record type 51) describes changes to placed instances of the game's creatures (ACRE mod file records).

An ACHR change record, specifically the change record for formid 0x00000014, also provides most of the information about the player character. However, this information is detailed on a separate article, Oblivion Mod:Save File Format/Player Data, because the most important subrecords are unique to the player's change record.

The ACHR/ACRE change records are far more complicated than any other change records. Significant portions of the ACHR/ACRE change records have not yet been deciphered; other sections are, at best, poorly understood. This article specifically focusses on sections of the change records that are somewhat understood; all of the information on this article has been verified from actual save files. A separate article is dedicated to deciphering the more mysterious sections of the records.

Names of Subrecords[edit]

Using text file dumps, it is possible to identify the subrecord names associated with most of the record's overall Flags. The following table lists all such subrecord names. It also provides a one-line summary of what subrecords may appear when that flag is set, if known, and therefore provides a brief overview of the extent to which ACHR/ACRE records are understood.

  • "Standard subrecord" means that a single subrecord appears in a fixed location whenever the corresponding byte is set.
  • In many cases, the data appears in the Properties structure. This structure has its own system of flags which are used to identify the specific properties contained in the structure. These properties can appear in any order within the structure, and the properties that appear are only loosely related to the record's overall Flags.
  • Yellow rows are ones that are also found (with the same meaning) in REFR change records.
  • Pink rows are ones whose location is unknown; these rows are all documented on a separate page.

Summary information about the location and size of the known subrecords is listed in the next section.

Bit in Overall Flags Hex Value of Bit Subrecord Name Notes
0 0x00000001 Form Flags Standard subrecord; same as all Form Flags subrecords
1 0x00000002 Created Standard subrecord
2 0x00000004 Moved Standard subrecord
3 0x00000008 Havok Moved Two possible subrecords. One subrecord only appears if neither "Created" nor "Moved" is set. The second one is a standard subrecord.
4 0x00000010 Scale Standard subrecord.
6 0x00000040 Life State Location of data in change record is unknown.
7 0x00000080 Crime Gold ACHR only Data is found in the properties section, under property 0x3d.
[Owner] ACRE only This subrecord is not named in ACRE text file dumps, but based on record content, and by comparison to REFR change records, this flag is clearly used for owner information. The data is found in the properties section, under property 0x27.
13 0x00002000 Investment Gold Data is found in the properties section, under property 0x52.
14 0x00004000 Oblivion Entry Data is found in the properties section, under property 0x3e.
15 0x00008000 Disp Modifiers Location of data in change record is unknown.
16 0x00010000 Non-saved Package Location of data in change record is unknown (may be zero length).
17 0x00020000 Interrupt / Follow / Dialogue Interrupt, Follow, and Dialogue are all listed as names for flag 17. The text file dumps also always include a formid with the subrecord name (e.g., "Dialogue FF02E201"). The data is in a fixed-length 32-byte subrecord positioned after the Scale subrecord.
18 0x00040000 Trespass Data is found in the properties section, under property 0x20.
19 0x00080000 Run Once Location of data in change record is unknown.
20 0x00100000 Magic Modifiers Location of data in change record is unknown.
21 0x00200000 Script Modifiers Location of data in change record is unknown.
22 0x00400000 Game Modifiers Location of data in change record is unknown.
23 0x00800000 Oblivion Flag A subrecord only appears if none of "Created", "Moved", or "Havok Moved" is set.
24 0x01000000 Movement Extra Data can be found in one or both of two possible sections. It can be found in the properties section, under property 0x4b. It can also appear in the Miscellaneous section.
25 0x02000000 Animation Data can be found in one or both of two possible sections. It can be found in the properties section, under property 0x4a. It can also appear in the Miscellaneous section.
26 0x04000000 Script Data is found in the properties section, under property 0x12.
27 0x08000000 Inventory Standard subrecord (although it is a complex subrecord)
28 0x10000000 Leveled Creature Data is found in the properties section, under property 0x35.
29 0x20000000 Equipment Location of data in change record is unknown; data is definitely not in properties section.
30 0x40000000 Enabled/Disabled Zero-size subrecord (no data is ever added to record). Can be named "Enabled", "Disabled", or "Enabled/Disabled" in the text file dumps.
31 0x80000000 Cell Changed Standard subrecord.
N/A N/A High Only one of these five sections appears in any change record. Its appearance is not related to the record's overall flags, but rather is controlled by the Actor Flag. The names come from the text dump files. It is unlikely that the associated data is in one contiguous subrecord. Rather, this is probably a catch-all group for all subrecords and properties that are not associated with any other flags.
Mid High
Mid Low
Low
None

Locations of Subrecords[edit]

Relative Location Bit in Overall Flags Hex Value of Bit Subrecord Name Size Notes
1 31 0x80000000 Cell Changed 16 This subrecord has not actually been seen in any REFR records, but it seems safest to assume that it is theoretically possible for it to appear.
2 1 0x00000002 Created 36 Both "Created" and "Moved" are listed at relative position 2, because only one of them is found in a given record. "Havok Moved" can also appear at this same location, if neither "Created" nor "Moved" is set.
2 2 0x00000004 Moved 28
2* 3 0x00000008 Havok Moved var. "Havok Moved" only appears at position 2 (using the same 28-byte structure as "Moved") if neither "Created" nor "Moved" is set. Additional "Havok Moved" data may appear in the Miscellaneous section.
3* 23 0x00800000 Oblivion Flag 0-4 4 bytes of data is added for "Oblivion Flag" only if none of "Created", "Moved", or "Havok Moved" is set.
4 N/A N/A Temporary Attribute Changes 876 Only present in player ACHR record (formid 0x00000014)
5 N/A N/A Actor Flag 1 Always present in ACHR and ACRE change records. Previous documentation incorrectly placed the Actor Flag as the second subrecord, immediately following the Moved subrecord.
6 0 0x00000001 Form Flags 4
7 27 0x08000000 Inventory var.
10 N/A Properties
The properties section is always present in ACHR and ACRE change records. The following lines list named subrecords which are known to appear in the properties sections. Many other properties have also been seen in ACHR/ACRE records, but they are considered to be associated with the None/Low/Mid Low/Mid High/High subrecord. The properties can appear in any order within the section.

The sizes of fixed-length properties are listed as 1+x: 1 for the property flag, x for the actual contents of the property (x matches the size listed on the Properties page). Note that the text file dumps generally add 2 more to the size of these properties, to account for the two-byte "propertiesNum" entry that starts the Properties section -- except the 2 extra bytes are added to every single property, resulting in erroneous total sizes. Also, it is only useful to know the property flags associated with each subrecord name when making comparisons to text file dumps.

7 0x00000080 Owner 1+4 Only in ACRE change records Property flags = 0x27.
Crime Gold 1+4 Only in ACHR change records Property flags = 0x3d.
13 0x00002000 Investment Gold 1+4 Property flags = 0x52.
14 0x00004000 Oblivion Entry 1+16 Property flags = 0x3e.
18 0x00040000 Trespass 1+63 Property flags = 0x20.
24 0x01000000 Movement Extra var. Property flags = 0x4b. Movement Extra data can also appear in the Miscellaneous section.
25 0x02000000 Animation var. Property flags = 0x4a. Animation data can also appear in the Miscellaneous section.
26 0x04000000 Script var. Property flags = 0x12.
28 0x10000000 Leveled Creature 1+0 Property flags = 0x35.
After Properties
20 3 0x00000008 Havok Moved var
30 4 0x00000010 Scale 4
Unknown Data

The remainder of the ACHR/ACRE has not yet been decoded.

N/A Zero-size Records
N/A 30 0x40000000 Enabled/Disabled 0


Cell Changed[edit]

The Cell Changed subrecord is present when byte 31 (0x80000000) is set in an ACHR/ACRE/REFR record's overall Flags. Its length is a constant 16 bytes. It contains information about the original position of an actor who has moved from one cell to another. When present, it is always the first subrecord to appear.

In analyzed save files, Cell Changed subrecords have only been seen in ACHR and ACRE change records. However, occasionally REFR change records are seen for creature-related objects such as LVLC, which perhaps could also change cells. Therefore, it seems safest to assume that this subrecord could appear for any of the three change record types.

The x/y/z data in this subrecord is identical to the contents of the original mod record's DATA subrecord; the cell is the same as the CELL group in which the record originally appeared. One theory is that this data is used when cells are reset, to ensure that the actor is respawned at its original location (or perhaps is only respawned if it would not produce a duplicate).

Name Type/Size Info
cell iref Iref pointing to the cell where the object was originally located (before changing cells)
x float X coordinate of object's original location.
y float Y coordinate of object's original location.
z float Z coordinate of object's original location.

Created[edit]

The Created subrecord is present when byte 1 (0x00000002) is set in an ACHR/ACRE/REFR record's overall Flags. Its length is a constant 36 bytes. It contains information about the base item and the object's position.

The only subrecord that precedes the Created subrecord is Cell Changed, if both were to appear in the same record.

Note that newly-created ACHR/ACRE/REFR (e.g., placed instances of items) are only identified by this section -- they are not also listed in the save file's createdData section. The createdData section is reserved for new item definitions, e.g. custom-defined potions, weapons, or other item types.

Earlier documentation listed "Base Object" as the subrecord corresponding to byte 1; the Base Object subrecord was listed as a 4-byte subrecord containing the same information as base_item in the Created subrecord. The earlier information was probably based on an incomplete analysis of the record's contents.

Name Type/Size Info
flags ulong flag 0x2 (only one that seems to be read) determines whether to process this record as a world object or a bound object
base_item iref An iref pointing to the base object; equivalent to the NAME subrecord in a REFR mod record, except it is an iref instead of a formID.
cell iref Iref pointing to the cell where the object is located.
x float X coordinate of object's position.
y float Y coordinate of object's position.
z float Z coordinate of object's position
rX float Rotation around the X-axis in radians. See notes about rX under Moved
rY float Rotation around the Y-axis in radians.
rZ float Rotation around the Z-axis in radians.

Moved[edit]

The Moved subrecord is present when byte 2 (0x00000004) is set in an ACHR/ACRE/REFR record's overall Flags. Its length is a constant 28 bytes. It contains information about the object's new position.

The only subrecord that precedes the Moved subrecord is Cell Changed, if both were to appear in the same record. It appears in the same relative location as the Created subrecord, and presumably appears in place of the Created subrecord for pre-existing objects. Moved and Created subrecords have never been seen together, and it is assumed that they never would appear simultaneously, since all of the information provided in the Moved record is already covered by the Created record.

Name Type/Size Info
cell iref Iref pointing to the cell where the object is located. 0x00000000 means that the cell has not changed

(Previous documentation emphatically but incorrectly claimed that cell was a formid, not an iref. In current analyses, 59438 subrecords have been found that contain irefs; another 95156 subrecords contained 0x00000000. No subrecords were found containing formids, even formids to temporary objects).

x float X coordinate of object's position.
y float Y coordinate of object's position.
z float Z coordinate of object's position
rX float Rotation around the X-axis in radians.

rX frequently appears to contain some sort of flag, instead of the actual rotation. For example, rX values such as 0xFFFF7F7F have been seen, which translates into the improbable float value of 3.4E38. Generally, rY and rZ contain "normal" values for rotation in these cases (although rare cases of flag-type values for rY and rZ have also been seen). The significance of rX in these cases is unknown.

rY float Rotation around the Y-axis in radians.
rZ float Rotation around the Z-axis in radians.

Havok Moved[edit]

This Havok Moved subrecord is present when byte 3 (0x00000008) is set in an ACHR/ACRE/REFR record's overall Flags, but only if neither Created nor Moved appears (if neither flag 1 nor 2 is set). Its length is a constant 28 bytes, and uses the same format as a Moved subrecord. It contains information about the object's new position.

The only subrecord that precedes the Havok Moved subrecord is Cell Changed, if both were to appear in the same record. It appears in the same relative location as the Created and Moved subrecord, and appears in place of those records. Presumably it is used for objects which only moved as a result of the havok physics (e.g., because they were bumped, or the table on which they were located was jostled), as opposed to objects which were grabbed or dropped in a new location by the player. Objects that were Havok Moved are normally re-positioned in their original locations when the cell is reset.

Note that this subrecord is only one part of the "Havok Moved" data. Additional data can be added to the Miscellaneous section, although details of the additional data are poorly understood.

Oblivion Flag[edit]

The Oblivion Flag subrecord is present when byte 23 (0x00800000) is set in an ACHR/ACRE/REFR record's overall Flags, but only if none of Created, Moved, or Havok Moved) appears (if none of flags 1, 2, 3 or set). Its length is a constant 4 bytes, and contains information about the Oblivion cell in which the object is located.

The only subrecord that precedes the Oblivion Flag subrecord is Cell Changed, if both were to appear in the same record, but only because data is added for the Oblivion Flag only in the absence of the other preceding sections. Otherwise, no data is added to the record; the Oblivion cell information can instead be retrieved from the cell entry in one of the other sections.

One theory for this subrecord's rationale is that it is used when an Oblivion World is de-activated and all the change records associated with that world need to be found and deleted. Oblivion worldspaces are unique in that they are de-activated, and then later new instances of the entire worldspace may be created, with no memory of the earlier worldspace -- the cell reset on an Oblivion worldspace needs to be more thorough than on any other cell, and this subrecord is part of the mechanism for the thorough reset.

Name Type/Size Info
cell formid or iref Formid or iref for the Oblivion cell (i.e. Planes of Oblivion CELL or WRLD record) where the object is located. Both formids and irefs have clearly been seen in this record -- even for references to the same cell, within the same save file.

Actor Flag[edit]

The Actor Flag is always present in ACHR/ACRE change records. Its length is a constant 1 byte. Its value determines how much additional information is contained in the ACHR/ACRE change record, although the details of the additional information are not understood.

The Actor Flag has the following known values:

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

The name associated with each value comes from the text file dumps. Additional information about the Actor Flag, such as its significance and what data is associated with the flag, is uncertain but ACHR Uncertainties documents what has been determined so far.

Form Flags

The Form Flags subrecord is present when bit 0 (0x00000001) is set in any change record's overall Flags. Its length is a constant 4 bytes.

The Form Flags subrecord has been seen in nearly every type of change record, always associated with bit 0, always using the same name in the text dump files, and always using the same format. The only record types without any Form Flags (so far) have been: CELL, FACT, INFO, PACK, and QUST. Furthermore, in analyzed save files, bit 0 has never been set for any of those five record types, so it is possible that even for those records, bit 0 is reserved for the Form Flags subrecord.

Name Type/Size Info
flags ulong The record's current form flags. Related to form flags in mod files, but the meaning of some bits is unknown.
Example: If an item from an ESM file was originally a quest item, and stopped being one, flags = 0x00000009
Example: If an item from an ESM file was not originally a quest item, and became one, flags = 0x00000409


Inventory[edit]

The Inventory subrecord is present when byte 27 (0x08000000) is set in an ACHR/ACRE/REFR change record's overall Flags. Its length is variable. The parameters controlling its length are well-understood but complex: it consists of a specified number (itemNum) of entries, each of which is documented by a structure of variable length. You need to decode the entire Inventory subrecord in order to determine the total size of the subrecord. The subrecord details the items that the character, creature or containers (drawers, chests, etc.) currently possess -- and those that are no longer possessed.

Because this is a change record, the inventory lists changes relative to that specified in the ESM/ESP files, both additions and substractions. For example: at the start of the game, your character receives "royal jewelry" a.k.a. wrist irons. If you never drop or sell them they are not listed in your character's Inventory subrecord, because you are still carrying them. On the other hand, if you do drop the wrist irons, then they are listed in the Inventory, with stackedItemsNum=-1. Therefore, if you want get a complete list of the inventory contents, you need to read first the listing provided by the ESM and ESP files. Then you can read the save file's contents and add or remove items, yielding the inventory's final list.

A minimal inventory item entry provides the item's iref (ulong), item count (StackedItemsNum, ulong), and count of extra information (changedEntriesNum, ulong). If changedEntriesNum is 0, then no further data is provided for that item -- the total size of that item's entry is 12 bytes. However, many items include extra information, documenting changes to the item's properties (e.g., whether the item is equipped by the player, the item's health, the available charge of an enchanted weapon, etc.). The structure and data length for this extra information depends upon the number and type of the changed properties.

The extra information count, changedEntriesNum, does not list the number of changed properties, but rather the number of sets of changed properties. Each set of changed properties (each changedEntries structure) applies to one subset of the item stack. Multiple changedEntries information sets are provided if a stack of multiple items contains items with a range of properties; conversely, an inventory entry documenting a single item will only have one changedEntries set. For example, if the player is carrying 12 Iron Longswords (base health 140), 1 of which is equipped and damaged to 10% health and 4 of which have been repaired to 125% health (leaving 7 "unchanged" swords at 100% health), the inventory listing will consist of:

  • iref (4 bytes; value differs for every save game)
  • stackedItemsNum=12 (4 bytes)
  • changedEntriesNum=2 (4 bytes)
  • The first changedEntries set, describing the equipped but damaged sword (8 bytes total):
    • propertiesNum=2 (2 bytes)
      • itemHealth property: flag=0x2b; value=14.0 (5 bytes total)
      • equipped property: flag=0x1b; value=empty (1 byte total)
  • The second changedEntries set, describing the 4 expert-improved swords (10 bytes total):
    • propertiesNum=2 (2 bytes)
      • itemHealth property: flag=0x2b, value=175.0 (5 bytes total)
      • affectedItemsNum propery: flag=0x2a, value=4 (3 bytes total)

(Note that in earlier documentation of the inventory record, the structure and meaning of this extra information was inaccurate; the earlier documentation would only work for relatively simple sets of changed properties).

Name Type/Size Info
itemNum ushort Number of items in inventory.
item struct[itemNum] Items in characters inventory.
iref
ulong Points to the FormId's location in the FormIdArray (unless iref>0xFF000000, in which case it is the FormId of an item in the createdData array).
stackedItemsNum
ulong Number of items added to (or removed from) stack by the change record.
changedEntriesNum
ulong Number of entries listing changed properties (e.g. equipped, used, damaged etc)
  • If changedEntriesNum is 0, this is the end of the item's data
changedEntries
struct[changedEntriesNum] Each listing in changedEntries is a collection of properties describing one or more of the items in the stack.

If the properties apply to more than one item, then one of the properties entries will be affectedItemsNum; conversely, if affectedItemsNum does not appear, then the properties describe only one item. Since these are changed properties, any properties that are not specified have default values.

propertiesNum
short Number of properties changed for this subset of items
property
struct[propertiesNum] Structure detailing an individual property change.
Flag
byte Changed property indicator. The properties page documents all known values for this flag.
-Value
different Changed property value, The type of value and its length depends upon the flag; see properties. (Value is not present for flags with zero-length values)

Properties[edit]

This section was previously identified as the "Actor States" section, but was renamed for consistency with REFR change records and Inventory properties. It is always present in ACHR/ACRE subrecords, although it may be empty. Within this section, the individual properties can appear in any order -- each property is preceded by a flag identifying its contents. The full list of possible property flags and the format associated with each flag is documented on a separate Properties article.

Havok Moved[edit]

The Havok Moved subrecord is present immediately following the Properties section when byte 3 (0x00000008) is set in an ACHR/ACRE change record's overall Flags. This data is in addition to any that may appear in place of the Moved subrecord. The meaning of the Havok Moved data is unknown.

Unlike the Miscellaneous Section of the REFR change records, only Havok Moved ever appears in this location in ACHR/ACRE change records, and its appearance seems to be reliable -- with the caveat that ACHR/ACRE records are less well understood overall than REFR records.

Name Type/Size Info
dataLen ushort
data byte[dataLen]

Scale[edit]

The Scale subrecord is present when byte 4 (0x00000010) is set in an ACHR/ACRE/REFR change record's overall Flags. Its length is a constant 4 bytes, and provides the size of this particular object relative to the standard object size.

Note that there is also a Scale property (property flag 0x37), but the property is only found in Inventories, not in REFR property sections.

Name Type/Size Info
scale float


Enabled/Disabled[edit]

This value is true when byte 30 (0x80000000) is set in an ACHR/ACRE/REFR record's overall Flags. No subrecords or data are added to the record when this flag is set.

It is unclear, however, what this flag means. In text file dumps, this flag is described as "Enabled", "Disabled", or "Enabled/Disabled"; "Enabled/Disabled" is only used on NOT LOADED records. One logical explanation would be that this flag means the item's default status has been reversed: that objects which are initially enabled are disabled when this flag has been set, and vice versa. However, it does not seem to be that straightforward. For example, statistics from one save file show that:

  • This flag appeared 450 times for objects identified in Oblivion.esm as being "disabled by default" (byte 19 set in the flags1 field).
    • 46 of these objects were "Disabled" according to the text file dump.
    • 404 of these objects were "Enabled" according to the text file dump.
  • This flag appeared 932 times for objects identified in Oblivion.esm as being initially enabled (byte 19 was not set in the flags1 field).
    • 190 of these objects were "Disabled" according to the text file dump.
    • 742 of these objects were "Enabled" according to the text file dump.

In other words, in the majority of cases, this flag means that the object is Enabled, regardless of the object's initial status. It is unknown how savefile parsers are supposed to determine the correct meaning of this flag.

In a small number of cases (7 in the previous example), a property identified as meaning "Disabled" was also set.

Name Type/Size Info
N/A 0 No data is added to the record