Open main menu

UESPWiki β

Skyrim Mod:ChangeFlags

< Mod / Skyrim: Skyrim Mod: Save File Format

Change FlagsEdit

  • ChangeFlags are part of the ChangeForm structure in a savefile.
  • It's the uint32 that follows the changeFormId for every changeForm in a savefile.
  • The changeFormId may influence the amount of data stored per ChangeFlag.
  • ChangeFlags have different meanings per ChangeForm type.
  • Sizes may also be different for combinations of ChangeFlags
All Change Flags (As of SkyrimSE 1.5.97)
Bit Value Constant Name Pretty Name (In code)
All records
0 0x00000001 CHANGE_FORM_FLAGS Flags
CLAS
1 0x00000002 CHANGE_CLASS_TAG_SKILLS Tag Skills
FACT
1 0x00000002 CHANGE_FACTION_FLAGS Faction Flags
2 0x00000004 CHANGE_FACTION_REACTIONS Faction Reactions
31 0x80000000 CHANGE_FACTION_CRIME_COUNTS Faction Crime Counts
ACTI
23 0x00800000 CHANGE_TALKING_ACTIVATOR_SPEAKER Speaker
BOOK
5 0x00000020 CHANGE_BOOK_TEACHES Teaches Skill
6 0x00000040 CHANGE_BOOK_READ Read
DOOR
! The instructions for this flag appear to be unreachable in SkyrimSE 1.5.97
17 0x00020000 CHANGE_DOOR_EXTRA_TELEPORT Teleport Extra
INGR
31 0x80000000 CHANGE_INGREDIENT_USE Ingredient Use
NPC_
1 0x00000002 CHANGE_ACTOR_BASE_DATA Base Data
2 0x00000004 CHANGE_ACTOR_BASE_ATTRIBUTES Attributes
3 0x00000008 CHANGE_ACTOR_BASE_AIDATA AI Data
4 0x00000010 CHANGE_ACTOR_BASE_SPELLLIST Spell List
5 0x00000020 CHANGE_ACTOR_BASE_FULLNAME Full Name
6 0x00000040 CHANGE_ACTOR_BASE_FACTIONS Factions
9 0x00000200 CHANGE_NPC_SKILLS NPC Skills
10 0x00000400 CHANGE_NPC_CLASS Class
11 0x00000800 CHANGE_NPC_FACE Face
12 0x00001000 CHANGE_NPC_DEFAULT_OUTFIT Default Outfit
13 0x00002000 CHANGE_NPC_SLEEP_OUTFIT Sleep Outfit
24 0x01000000 CHANGE_NPC_GENDER Gender
25 0x02000000 CHANGE_NPC_RACE Race
LVLN, LVLI, LVSP
31 0x80000000 CHANGE_LEVELED_LIST_ADDED_OBJECT Added Object
NOTE
31 0x80000000 CHANGE_NOTE_READ Note Read
CELL
1 0x00000002 CHANGE_CELL_FLAGS Flags
2 0x00000004 CHANGE_CELL_FULLNAME Full name
3 0x00000008 CHANGE_CELL_OWNERSHIP Ownership
28 0x10000000 CHANGE_CELL_EXTERIOR_SHORT Exterior Short
29 0x20000000 CHANGE_CELL_EXTERIOR_CHAR Exterior Char
30 0x40000000 CHANGE_CELL_DETACHTIME Detach Time
31 0x80000000 CHANGE_CELL_SEENDATA Seen Data
REFR, ACHR, PMIS, PARW, PGRE, PBEA, PFLA, PCON, PBAR, PHZD
1 0x00000002 CHANGE_REFR_MOVE Moved
2 0x00000004 CHANGE_REFR_HAVOK_MOVE Havok Moved
3 0x00000008 CHANGE_REFR_CELL_CHANGED Cell Changed
4 0x00000010 CHANGE_REFR_SCALE Scale
5 0x00000020 CHANGE_REFR_INVENTORY Inventory
6 0x00000040 CHANGE_REFR_EXTRA_OWNERSHIP Ownership Extra
7 0x00000080 CHANGE_REFR_BASEOBJECT BaseObject
25 0x02000000 CHANGE_REFR_PROMOTED Promoted
26 0x04000000 CHANGE_REFR_EXTRA_ACTIVATING_CHILDREN Activating Children
27 0x08000000 CHANGE_REFR_LEVELED_INVENTORY Leveled Inventory
28 0x10000000 CHANGE_REFR_ANIMATION Animation
29 0x20000000 CHANGE_REFR_EXTRA_ENCOUNTER_ZONE Enc Zone Extra
30 0x40000000 CHANGE_REFR_EXTRA_CREATED_ONLY Created Only Extra
31 0x80000000 CHANGE_REFR_EXTRA_GAME_ONLY Game Only Extra
! ACHR only
10 0x00000400 CHANGE_ACTOR_LIFESTATE Life State
11 0x00000800 CHANGE_ACTOR_EXTRA_PACKAGE_DATA Package Data Extra
12 0x00001000 CHANGE_ACTOR_EXTRA_MERCHANT_CONTAINER Merchant Container
17 0x00020000 CHANGE_ACTOR_EXTRA_DISMEMBERED_LIMBS Dismembered Limbs
18 0x00040000 CHANGE_ACTOR_LEVELED_ACTOR Leveled Actor
19 0x00080000 CHANGE_ACTOR_DISPOSITION_MODIFIERS Disp Modifiers
20 0x00100000 CHANGE_ACTOR_TEMP_MODIFIERS Temp Modifiers
21 0x00200000 CHANGE_ACTOR_DAMAGE_MODIFIERS Damage Modifiers
22 0x00400000 CHANGE_ACTOR_OVERRIDE_MODIFIERS Override Modifiers
23 0x00800000 CHANGE_ACTOR_PERMANENT_MODIFIERS Permanent Modifiers
! All except ACHR
10 0x00000400 CHANGE_OBJECT_EXTRA_ITEM_DATA Item Data Extra
11 0x00000800 CHANGE_OBJECT_EXTRA_AMMO Ammo Extra
12 0x00001000 CHANGE_OBJECT_EXTRA_LOCK Lock Extra
21 0x00200000 CHANGE_OBJECT_EMPTY Empty
22 0x00400000 CHANGE_OBJECT_OPEN_DEFAULT_STATE Open Default State
23 0x00800000 CHANGE_OBJECT_OPEN_STATE Open Dtate
INFO
31 0x80000000 CHANGE_TOPIC_SAIDONCE Said Once
QUST
1 0x00000002 CHANGE_QUEST_FLAGS Quest Flags
2 0x00000004 CHANGE_QUEST_SCRIPT_DELAY Quest Script Delay
26 0x04000000 CHANGE_QUEST_ALREADY_RUN Quest Already Run
27 0x08000000 CHANGE_QUEST_INSTANCES Quest Instance Data
28 0x10000000 CHANGE_QUEST_RUNDATA Quest Runtime Data
29 0x20000000 CHANGE_QUEST_OBJECTIVES Quest Objectives
30 0x40000000 CHANGE_QUEST_SCRIPT Quest Script
31 0x80000000 CHANGE_QUEST_STAGES Quest Stages
PACK
30 0x40000000 CHANGE_PACKAGE_WAITING Waiting Flag
31 0x80000000 CHANGE_PACKAGE_NEVER_RUN Never Run Flag
FLST
31 0x80000000 CHANGE_FORM_LIST_ADDED_FORM Added Form
ECZN
1 0x00000002 CHANGE_ENCOUNTER_ZONE_FLAGS Zone Flags
31 0x80000000 CHANGE_ENCOUNTER_ZONE_GAME_DATA Game Data
LCTN
30 0x40000000 CHANGE_LOCATION_KEYWORDDATA KeywordData
31 0x80000000 CHANGE_LOCATION_CLEARED Cleared
SMQN
31 0x80000000 CHANGE_QUEST_NODE_TIME_RUN Time Last Run
RELA
1 0x00000002 CHANGE_RELATIONSHIP_DATA Relationship Data
SCEN
31 0x80000000 CHANGE_SCENE_ACTIVE Active
All records not yet named
1 0x00000002 CHANGE_BASE_OBJECT_VALUE Object Value
2 0x00000004 CHANGE_BASE_OBJECT_FULLNAME Object Full Name

Initial typeEdit

  • Certain changeforms first have an initial data type and data.
  • These are applied in order.

If change form type is CELL:

If flag CHANGE_CELL_DETACHTIME is not set, initialType = 0.
Else if flag CHANGE_CELL_EXTERIOR_CHAR is set, initialType = 1.
Else if flag CHANGE_CELL_EXTERIOR_SHORT is set initialType = 2.
Else if flag CHANGE_CELL_DETACHTIME is set initialType = 3.
Else initialType = 0.

If change form type is one of these (REFR, ACHR, PMIS, PGRE, PBEA, PFLA, PHZD, PBAR, PCON, PARW):

If change form is created one (FormId >= FF000000) intialType = 5.
Else if flag CHANGE_REFR_PROMOTED or CHANGE_REFR_CELL_CHANGED is set, initialType is 6.
Else if flag CHANGE_REFR_HAVOK_MOVE or CHANGE_REFR_MOVE is set, initialType = 4.
Else initialType = 0.


Initial type Data Size Data
0 0 none
1 8 uint16 unk
uint8 Cell_X, Cell_Y
uint32 unk2
2 10 uint16 unk
sint16 unk1, unk2
uint32 unk3
3 4 uint32 unk
4 27 RefId Cell / world
float pos[3], rot[3]
5 31 RefId Cell / world
float pos[3], rot[3]
uint8 unk
RefId base object
6 34 RefId Cell / world
float pos[3], rot[3]
RefId starting cell / world?
sint16 unk1, unk2

Change form flagsEdit

Name Type Description
flag uint32
unknown uint16


CELL change form flagsEdit

Bit Value Name Description
0 0000 0001 CHANGE_FORM_FLAGS
1 0000 0002 CHANGE_CELL_FLAGS
2 0000 0004 CHANGE_CELL_FULLNAME
3 0000 0008 CHANGE_CELL_OWNERSHIP
28 1000 0000 CHANGE_CELL_EXTERIOR_SHORT
29 2000 0000 CHANGE_CELL_EXTERIOR_CHAR
30 4000 0000 CHANGE_CELL_DETACHTIME
31 8000 0000 CHANGE_CELL_SEENDATA


QUST change formEdit

Bit Value Data Size Name Description
1 0000 0002 2 CHANGE_QUEST_FLAGS
26 0400 0000 1 CHANGE_QUEST_ALREADY_RUN
27 0800 0000 CHANGE_QUEST_INSTANCES
28 1000 0000 CHANGE_QUEST_RUNDATA
29 2000 0000 CHANGE_QUEST_OBJECTIVES
31 8000 0000 CHANGE_QUEST_STAGES


REFR change formEdit

Data ElementsEdit

These are the elements I have so far seen in a REFR change form.

Field Size Contents Notes
cellId 3 refId Contains a reference to the cell where this object currently is
location 24 float x
float y
float z
float rx
float ry
float rz
Contains the location and orientation of the object
unknown1 1 byte Always (and only) present in created objects (formId starts with 0xff)
refIdx 3 refId Only seen on objects with the CHANGE_REFR_PROMOTED flag set and always seems to contain the same refId as the cellId.
unkown2 4 int16 a
int16 b
A tuple containing (moderately) positive or negative numbers
havokData var byte[1-3] size
byte[size] data
The two lowest bits of the first byte indicate how many bytes are used to store the size. The other bits indicate the size (bit 3 of the first byte thus indicates a size of one byte, the lowest bit of byte 2 equals 64 bytes).
flags 6 byte[6] flags Six bytes of flags
scale 4 float New scale to appplied to the object (not 100% certain about the order of scale and baseId)
baseId 3 refId A reference to a new base object for this object
gameOnly var byte[1-3?] itemCount
per item:
- byte itemType
- [opt] byte itemRepeat
- byte[var] itemData
itemCount should be shifted by two bits to get the count, the other bit probably indicate additional count bytes. The itemType influences what is next, in some cases another count that has to be shifted as well, in some cases a fixed number of bytes. If a count is present, it seems to indicate how many repeats of a certain fixed size are following.
inventory var byte[1-3?] itemCount
per item:
- refId item
- uint32 count
- complex
The refId and count are followed by some complex nested structure that's similar to the "gameOnly" field above. I.e. each item can have extra properties from the table below.
animation var complex

FlagsEdit

This table lists which fields will be present for which flags. It is incomplete at the moment.

changeFormId = 0x00......
Bit Value Name cellId location unknown1 refIdX unknown2 havokData flags scale baseId gameOnly inventory
0 0000 0001 CHANGE_FORM_FLAGS x
1 0000 0002 CHANGE_REFR_MOVE x x
2 0000 0004 CHANGE_REFR_HAVOK_MOVE x x x
3 0000 0008 CHANGE_REFR_CELL_CHANGED x x x x
4 0000 0010 CHANGE_REFR_SCALE
5 0000 0020 CHANGE_REFR_INVENTORY x
6 0000 0040 CHANGE_REFR_EXTRA_OWNERSHIP
7 0000 0080 CHANGE_REFR_BASEOBJECT x
10 0000 0400 CHANGE_OBJECT_EXTRA_ITEM_DATA x
12 0000 1000 CHANGE_OBJECT_EXTRA_LOCK x
21 0020 0000 CHANGE_OBJECT_EMPTY no extra data, just a flag
23 0080 0000 CHANGE_OBJECT_OPEN_STATE no extra data, just a flag
25 0200 0000 CHANGE_REFR_PROMOTED x x x x x
26 0400 0000 CHANGE_REFR_EXTRA_ACTIVATING_CHILDREN
27 0800 0000 CHANGE_REFR_LEVELED_INVENTORY x
28 1000 0000 CHANGE_REFR_ANIMATION
29 2000 0000 CHANGE_REFR_EXTRA_ENCOUNTER_ZONE x
31 8000 0000 CHANGE_REFR_EXTRA_GAME_ONLY x
changeFormId = 0xff......
Bit Value Name cellId location unknown1 refIdX unknown2 havokData flags scale baseId gameOnly inventory
0 0000 0001 CHANGE_FORM_FLAGS x x x x x
1 0000 0002 CHANGE_REFR_MOVE x x x x
3 0000 0008 CHANGE_REFR_CELL_CHANGED x x x x
4 0000 0010 CHANGE_REFR_SCALE x
10 0000 0400 CHANGE_OBJECT_EXTRA_ITEM_DATA x x x x x
25 0200 0000 CHANGE_REFR_PROMOTED x x x x x
31 8000 0000 CHANGE_REFR_EXTRA_GAME_ONLY x x x x x

The 0xff000000 type changeFormIds have at least 31 bytes of data in structure called 'Base', containing at least a RefId and the location/rotation fields. In this case the additional data added by the other flags may be different, for example CHANGE_REFR_MOVE and CHANGE_REFR_CELL_CHANGED will not add any data, while CHANGE_REFR_PROMOTED will only add 6 bytes instead of 40. The CHANGE_REFR_MOVE flag appears to be set on every changeForm of this type.

extraDataEdit

The extra data starts with the number of items contained in the field. Bit 0 and 1 of the first byte probably indicate how many bytes are used to store the size: 00 = just this byte, 01 = 1 extra byte, 10 = ?, 11 = ?. The count is obtained by reading the bytes and shifting them two bits to the right. 0x04 thus becomes 1, 0x08 becomes 2, ...

The next bytes tell something about the data that follows.

An incomplete list of possible data in the extraData field:

fieldType hasRepeatCount bytesToFollow comment
0x1c 3
0x21 3 Seen when Extra Item Data flag set, could be owner
0x24 2
0x25 4 Appears to be a float
0x28 4
0x2a 13 Seen when Lock Extra flag is set. Bytes 0 is the lock level (like XLOC in REFR), byte 1 is unknown, bytes 2-4 are the KEYM RefId to open the lock, bytes 5-12 always zero?
0x2c 1
0x2e 5
0x2f 4
0x31 29
0x32 4
0x38 3
0x48 3
0x49 5
0x55 4
0x58 7
0x5d 4
0x70 3 This is present when the Extra Encounter Zone flag is set. Probably a refId to the zone then
0x78 x 8
0x85 3
0x88 x 7 A QUST RefId, followed by a uint32 equal to one of the ALST fields in that QUST. It probably means this reference is assigned to that alias in that quest.
0x8c x 3 Present on promoted objects, usually with one item that looks like a refId: 0x40028A
0x8e 3 A OTFT RefId, probably indicating that this inventory item is part of that outfit.
0x92 3
0x95 7
0x98 14(may vary) ExtraData_AttachedArrows3D - Appears to always be 14 bytes long, but the first 2 bytes are always 0c 00. If read as a UInt16, this would be 12, which is also the number of bytes that follow. It's unknown what type of data is contained in the remaining bytes, as the only values seen so far are 00 and 02.
0x99 10+var When this is in an inventory object and the last 4 bytes are 0xfffffffe, a string follows (2 bytes for the length, then the characters). This is used to store user modified names during enchanting
0x9b 5
0x9f 6
0xa0 4
0xa1 88

The fields with a repeat should be interpreted like this: after the fieldType there is a count (again bit 0 and 1 of the first count byte indicate how many extra bytes are used for the count). After the count, count * bytesToFollow will follow. So 0x8c 0x08 .... indicates that 2 (0x08 shifted by 2) records of type 0x8c follow, which are 3 bytes per record, so 6 bytes in total. Frequently 0x88 0x00 is observed, meaning 0 * 7 bytes follow. As another example, 0x88 0x81 0x01 means count is (81>>2 + 1<<6) = 96, so 96 * 7 bytes follow.

NPC_ change formEdit

Bit Value Name Data Size Data
0 0000 0001 CHANGE_FORM_FLAGS 6 Change form flags
1 0000 0002 CHANGE_ACTOR_BASE_DATA 24 See ACBS field of NPC_ record
6 0000 0040 CHANGE_ACTOR_BASE_FACTIONS var vsval count

struct {refID factionID; uint8 rank} [count]

4 0000 0010 CHANGE_ACTOR_BASE_SPELLLIST var vsval spellCount

refID spells[spellCount]

vsval leveledspellCount

refID leveledspells[leveledspellCount]

vsval shoutCount

refID shouts[shoutCount]

3 0000 0008 CHANGE_ACTOR_BASE_AIDATA 20 See AIDT field of NPC_ record
5 0000 0020 CHANGE_ACTOR_BASE_FULLNAME var wstring name
9 0000 0200 CHANGE_NPC_SKILLS 52 See DNAM field of NPC_ record
10 0000 0400 CHANGE_NPC_CLASS 3 refID class
25 0200 0000 CHANGE_NPC_RACE 6 refID race

refID race2 (?)

11 0000 0800 CHANGE_NPC_FACE var ?
24 0100 0000 CHANGE_NPC_GENDER 1 uint8 gender (0 – male, 1 - female)
12 0000 1000 CHANGE_NPC_DEFAULT_OUTFIT 3 refID defOutfit
12 0000 1000 CHANGE_NPC_SLEEP_OUTFIT 3 refID sleepOutfit

The order of data in changeForm is the same as in the table

Skills/Health, etc are stored in ACHR records (as floats) associated with the NPC (for the player this is formid 0x00000014, refid=0x40 0x00 0x14 and is zlib compressed)

  • if any of the data is stored in the NPC_ record it seems to be ignored by the game.