Oblivion Mod:Save File Format/Player Data
Most of the player data in save files is contained in the ACHR change record for formid 0x00000014, and the majority of that data is in subrecords that only exist for the player's ACHR change record. This page describes the player-specific subrecords in the ACHR change record, as well as providing some other notes of interest to programmers specifically looking for player data.
Contents
The Player ACHR Change Record[edit]
The player's ACHR change record is always a "High" record. However, the subrecords detailed here are only present for the player -- they are not present for NPCs that have the "High" actor flag.
Structure of Subrecords[edit]
The following table summarizes which subrecords appear where (and when), specifically for the player. This is the same table as shown for the standard ACHR record, except subrecords that never appear for the player have been removed, and the player-specific subrecords are included.
Name | Type | Size [bytes] | Info |
---|---|---|---|
Moved | struct | 28 | Always present for the player ACHR record; provides player's current location. |
Temporary Attribute Changes | struct | 876 | Player-specific subrecord (previous documentation incorrectly placed this subrecord after the Actor Flag) |
Actor Flag | byte | 1 | Value is always 0 for the player |
Inventory | struct | variable | Present if byte 27 (0x08000000) in set in overall "flags" (which is essentially always the case for the player)
If you are interested only in the inventory, this subrecord starts at offset 905 for the player. |
Properties | struct | variable | Always present, but the contents of the section vary substantially, in part based on the record's overall flags. |
This section of the ACHR change record has not yet been decoded. See ACHR Uncertainties for available speculation about this section's contents. |
|||
Player Statistics | struct | variable | Player-specific subrecord, located at the end of the ACHR record. |
Notes:
- The Cell Changed and Created flags are never set for the player; the Moved flag is always set. Therefore, the ACHR record always starts with the Moved subrecord
- Since the Moved flag is set, flags such as the Oblivion Flag and Havok Moved flag never add extra subrecords.
- The first player-specific subrecord appears before the actor flag in the ACHR record. In other words, the player record has to be identified before starting to process any of the change data -- which, luckily, is easy to do since the formid of the ACHR record (0x00000014) is fixed.
- The Form Flags subrecord has never been observed for the player ACHR change record, and therefore has been left out of this table.
Temporary Attribute Changes[edit]
This subrecord always found in the player's ACHR change record, but is never found in any other ACHR records (even ones with Actor Flag=High). Its length is a constant 876 bytes. It contains the modifications to the player's attributes caused by any non-permanent effects.
These values are all modifications -- they must be added to the base attribute values to provide the player's current attributes. Attributes for the purpose of this table is very broadly defined, covering 71 different values. The effects covered by the table are everything other than racial effects (which are summarized in the [[Tes4Mod:Save_File_Format/NPC_#Base Modifiers|NPC Base Modifiers subrecord): enchantments, physical damage, potions, poisons, spells,
(The name of this subrecord is not provided in the text dump, so a name has been invented instead.)
Name | Type/Size | Info |
---|---|---|
Active Effects | float[71] | The total modifications to attributes from all Active Effects. Actor Value Indices lists the attributes and their indices. |
Unknown | float[71] | This section is presumably reserved for another category of attribute modifications. However, all values have been 0 in all analyzed save files. |
Damage | float[71] | The modifications to attributes caused by Damage Attribute effects, from both spells and poisons. Presumably it would also list any other modifications that are not listed in the Active Effects section of the journal |
ΔHealth | float | The total of all changes to the player's health -- including physical damage, damage from spells, and damage from poisons.
Note that the values for health in the previous three sections are always zero. |
ΔMagicka | float | The total of all changes to the player's magicka -- including magicka used when casting spells, damage from spells, and damage from poisons.
Note that the values for magicka in the previous three sections are always zero. |
ΔFatigue | float | The total of all changes to the player's fatigue -- including fatigue lost from using weapons, damage from spells, and damage from poisons.
Note that the values for fatigue in the previous three sections are always zero. |
Player Statistics[edit]
This section is always found at the end of the player's ACHR change record. It contains various statistics relevant specifically to the player's character, which therefore affects overall gameplay.
The original documentation never explained where in the ACHR record the Player Statistics subrecord appears. One way to find this section is to scan, starting from the end of the Properties section, for the bytes 0xec,0x42 (marking the start of the unknown 21-byte section listed below), and then 19 bytes later 0x96,0x42 (marking the start of the unknown 30-byte section listed below). This allows the Player Statistics to be read without requiring the rest of the ACHR subrecords to be understood.
Name | Type/Size | Info |
---|---|---|
Animation #2 | different | see Animation subrecord description, possibly first person data |
unknown | byte[21] | section starting with 0x42ec, possibly a name or code |
unknown | byte[30] | section starting with 0x4296, possibly a name or code |
statistics | ulong[34] | overall stats for PC, found order:
|
unknown | ubyte | |
unknown | byte[95] | Previous documentation assumed that this section included a structure but this was neglected by at least one save file. |
unknown | byte[22] | usually starts with 0x1 |
pcBirthsign | iref | current birthsign; iref points to a BSGN record. |
unknownArray | iref[13] | bunch of irefs, found: currentSpell, currentHorse, weatherRegion, weatherType, questMarker, suggested pcClass |
num2 | ushort | length of following struct |
unknown | byte[2] | |
unknown | byte[4][num2] | Previous documentation neglected to include this structure (num2 was merged into the unknownArray, presumably because num2 was zero in the cases previously examined) |
unknown | byte[2] | |
randODoorsNum | ushort | |
randODoors | struct[randODoorsNum] | random Oblivion doors |
|
iref | |
|
ubyte | |
unknown | byte[2] | |
activeEffectsNum | ushort | |
activeEffects | struct[activeEffectsNum] | provides information on all of the magical effects listed in the Active Effects section of the player's journal |
|
ushort | |
|
iref | iref points to a SPEL record |
|
ubyte | the EFID index of the SPEL that is being described |
|
struct[size] | Variable-length structure (frequently 33 bytes, other times larger). Values that have been tentatively located include:
|
expPoints | float[21] | Experience Points gathered per skill; see Experience Points |
advancements | ||
|
ulong | number of advancements since last PC level up (has not slept one or more times between level advances) |
|
byte[advancement][8] | number of skill advances counting towards each attribute bonus; for order see Actor Value Indices |
specCounts | byte[3] | order: combat, magic, stealth; number of Specialization skill advances since last level advance (i.e., since last time that the player advanced 10 major skills, regardless of when the player last slept) |
skillUsage | ulong[21] | times each skill has been advanced since last level advance; for order see Skill Indices |
majorSkillAdv | ulong | number of major skill advancements since last level advance |
unknown | byte | |
activeQuest | iref | PC's current active quest (0x00000000 if PC does not have a current active quest) |
knownTopicsNum | ushort | Number of topics known by PC. |
knownTopics | iref[knownTopicsNum] | Array of irefs for topics known by PC. |
openQuestsNum | ushort | Number of quests started by PC |
openQuests | struct[openQuestNum] | Each line lists a log entry that has been shown to the PC. The name openQuests is misleading -- every started quest, both completed and incomplete, is included in the array, and most quests have multiple entries. Presumably this array is used so that when the player reviews quests, the correct log entries are shown (since the player didn't necessarily complete all quest stages, and many quest stages have multiple possible log entries). |
|
iref | iref to QUST record |
|
ubyte | Quest stage (e.g., 10, 100), as listed under "Stage" in the Journal Entries section of the quest's wiki page. |
|
ubyte | Number of the log entry text to be displayed in the player's journal |
magEffectNum | ulong | Number of magic effects |
magEffect | struct[magEffectNum] | Magic effects known by player character (i.e., the magic effects that are available to the player at the Spellmaking Altar) |
|
char[4] | editor id of magic effect |
fgGeoSym | ubyte[200] | FaceGen Geometry Symmetric data. |
fgGeoAsym | ubyte[120] | FaceGen Geometry Asymmetric data |
fgTexSym | ubyte[200] | FaceGen Texture symmetric data |
race | iref | |
hair | iref | |
eyes | iref | |
hairLength | float | 1.0 seem to be maximal length. |
hairColor | ubyte[3] | rgb |
unknown | ubyte | ?Hair flag? |
gender | ubyte | 0: male; 1: female |
pcName | bzstring | PC's name. |
pcClass | iref | PC's class. |
customClass | struct | Custom class data, only present if the pcClass iref points to PlayerCustomClass (00022843), using same structure as DATA subrecord of CLAS (structure only confirmed through the end of the major skills). |
|
ulong | See Actor Value Indices for possible values. |
|
ulong | See Actor Value Indices for possible values. |
|
ulong | Values:
|
|
ulong | See Actor Value Indices for possible values. (Note that all of the major skills are indices in the range 12-32, not in the range 0-20 used by Skill Indices) |
|
ulong | See Actor Value Indices for possible values. |
|
ulong | See Actor Value Indices for possible values. |
|
ulong | See Actor Value Indices for possible values. |
|
ulong | See Actor Value Indices for possible values. |
|
ulong | See Actor Value Indices for possible values. |
|
ulong | See Actor Value Indices for possible values. |
|
ulong | See CLAS DATA for values |
|
ulong | Buys/sells and services. See CLAS DATA for values |
|
ubyte | See Skill Indices for possible values. |
|
ubyte | maximum level to which skill is trained |
|
ushort | |
|
bstring | |
|
bstring | |
|
iref |