Open main menu

UESPWiki β

Oblivion Mod:Save File Format/Player Data

< Mod / Oblivion: Oblivion Mod: Modding: Save File Format

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.

The Player ACHR Change RecordEdit

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 SubrecordsEdit

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 ChangesEdit

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 StatisticsEdit

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 game play.

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 sub-record 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:
  • skill advances
  • unknown
  • largest bounty
  • killed creatures
  • killed persons
  • explored places
  • lock picked
  • picks broken
  • captured souls
  • used ingredients
  • mixed potions
  • Oblivion gates closed
  • horses owned
  • houses owned
  • investments
  • books read
  • teaching books read
  • artifacts found
  • hours slept
  • hours waited
  • unknown
  • unknown
  • unknown
  • jokes told
  • disease
  • Nirn root found
  • burglary
  • pickpocketing
  • unknown
  • attacks
  • murder
  • stolen horses
  • unknown
  • unknown
  • unknown
  • unknown
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
door
iref
flag
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
size
ushort
reference
iref iref points to a SPEL record
index
ubyte the EFID index of the SPEL that is being described
effectDetails
struct[size] Variable-length structure (frequently 33 bytes, other times larger). Values that have been tentatively located include:
  • bytes 0-3 appear to be a float value providing the number of game seconds for which the effect has been active (this value is even set for abilities, in which case the value can be quite large)
  • bytes 7-10 are a float value providing the magnitude of the effect (taking into account caster's spell effectiveness?)
  • bytes 11-13 are a float value providing the original duration of the effect (0 for constant effects)
  • bytes 14-17 and 18-20 are irefs that typically point to the player (spellcaster? spell target?)
expPoints float[21] Experience Points gathered per skill; see Experience Points
advancements
advancement
ulong number of advancements since last PC level up (has not slept one or more times between level advances)
attrSkillCounts
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).
quest
iref iref to QUST record
questStage
ubyte Quest stage (e.g., 10, 100), as listed under "Stage" in the Journal Entries section of the quest's wiki page.
logEntry
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)
edid
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).
favoredAttribute1
ulong See Actor Value Indices for possible values.
favoredAttribute2
ulong See Actor Value Indices for possible values.
specialization
ulong Values:
  • 0=Combat
  • 1=Magic
  • 2=Stealth
majorSkill1
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)
majorSkill2
ulong See Actor Value Indices for possible values.
majorSkill3
ulong See Actor Value Indices for possible values.
majorSkill4
ulong See Actor Value Indices for possible values.
majorSkill5
ulong See Actor Value Indices for possible values.
majorSkill6
ulong See Actor Value Indices for possible values.
majorSkill7
ulong See Actor Value Indices for possible values.
flags
ulong See CLAS DATA for values
services
ulong Buys/sells and services. See CLAS DATA for values
skillTrained
ubyte See Skill Indices for possible values.
maxTraining
ubyte maximum level to which skill is trained
empty
ushort
name
bstring
icon
bstring
unknown
iref