Skyrim Mod:Mod File Format/VMAD Field
VMAD fields contain Papyrus script data, and are present in any record that contains a script, including items, dialogues, packages, and quests. Information contained in the VMAD field includes:
- The names of all scripts attached to the record, including scripts attached to individual components (e.g., quest aliases) of the record.
- The initial values of all properties in each of those scripts
- The names of all script fragments attached to the record. Script fragments are most commonly used in quests, where each stage of a quest can have an associated script fragment.
The VMAD field contains several distinct sections. However, the entire field must be processed sequentially in order to identify the sections; the lengths and locations of the various sections are not provided, making it impossible to skip through the field to a specific section. All VMAD fields contain a Primary Scripts Section and its format is the same for all record types; in the majority of cases, that is the only section present. However, some records also contain a Fragments Section, with a format that is dependent upon the record type.
All script names mentioned in the VMAD field are provided without an extension. The game itself accesses compiled versions of each script, which are given a .pex extension and are stored in one of the game's .bsa archive files. The source versions of the scripts, which use a .psc extension, are not accessed by the game (and were not part of the original game distribution), but are instead only used by the Creation Kit. The source scripts were made available following the release of the Creation Kit, and all 10005 scripts (as of patch 1.5) are available in the Data/Scripts/Source directory of your Skyrim installation.
Primary Scripts Section[edit]
The Primary Scripts Section is present in all VMAD fields, and has the same format in all cases.
Name | Type/Size | Info |
---|---|---|
version | int16 | 5 most recent, 2 is minimum. |
objFormat | int16 | Seems to always be 1 or 2; affects how object-type properties are read. |
scriptCount | uint16 | Number of scripts directly attached to this record |
scripts | Script[scriptCount] | Information on each of the scripts, including name, list of properties, and their initial values. |
fragments | Fragments[] | Script fragments. See below for more information. |
Scripts Section[edit]
Name | Type/Size | Info |
---|---|---|
scriptName | wstring | Name of the script (without extension). |
status | uint8 | Only present if version >= 4. Defaults to 0 for earlier versions.
|
propertyCount | uint16 | The number of properties that are defined in this script. |
properties | Property[propertyCount] | The name and initial value of each property. The length of each property entry is different, depending upon its contents. |
Property Entry[edit]
Name | Type/Size | Info |
---|---|---|
propertyName | wstring | Name of the property. |
propertyType | uint8 | Lookup value indicating the type of data stored in the property. Only the following values are possible:
Only supported if version >= 5:
Object types are used to assign formid values to properties, in particular for quest aliases, but also for a range of other cases that use formids. The length of the data for an object is always 8 bytes, but how the bytes are decoded depend upon the value of objFormat:
The AliasID is set to -1 whenever the formid does not point to a quest (in which case the formid is directly assigned to the property). Otherwise, the AliasID provides the quest alias used to assign the value (which nearly always means that the property effectively points to itself, e.g., the |
status | uint8 | Only present if version >= 4. Defaults to 1 for earlier versions.
|
data | depends on type | If the data is an array (if type is 11-15), the data consists of:
|
Fragments Section[edit]
If there are no fragments attached to this record, the VMAD field simply ends after the Primary Scripts Section. However, when there are fragments, the specific format used to list those fragments is dependent upon the record type. Note in particular that the fragmentCount appears before the fileName in some cases, but after the fileName in other cases. Only the record types listed below ever use script fragments.
INFO Records[edit]
INFO record fragment scripts are by default stored in a TIF file, i.e., a file named "TIF_<editorID>_<formID>". Since most INFO records do not have an editorID, this actually ends up being "TIF__<formID>" (with two underscores, not one).
Name | Type/Size | Info |
---|---|---|
unknown | int8 | Always 2. |
flags | uint8 | Script locations.
|
fileName | wstring | Name of the script file containing the fragments (without extension). |
fragments | fragment[flagsCount] | Information on each fragment, as detailed in the following lines. Variable flagsCount is the number of bit flags activated in flags |
fragment.unknown | int8 | |
fragment.scriptName | wstring | Name of script (normally same as fileName). |
fragment.fragmentName | wstring | Name of function containing this fragment script. Typically a name such as "Fragment_5". |
PACK Records[edit]
PACK record fragment scripts are by default stored in a PF file, i.e., a file named "PF_<editorID>_<formID>".
Name | Type/Size | Info |
---|---|---|
unknown | int8 | Always 2. |
flags | uint8 | Script locations.
|
fileName | wstring | Name of the script file containing the fragments (without extension). |
fragments | fragment[flagsCount] | Information on each fragment, as detailed in the following lines. flagsCount is the number of bits set in the flags field. When more than one is present, fragments are emitted in the following order: On Begin, On End, On Change. |
fragment.unknown | int8 | |
fragment.scriptName | wstring | Name of script (normally same as fileName). |
fragment.fragmentName | wstring | Name of function containing this fragment script. Typically a name such as "Fragment_5". |
PERK Records[edit]
PERK record fragment scripts are by default stored in a PRKF file, i.e., a file named "PRKF_<editorID>_<formID>".
Name | Type/Size | Info |
---|---|---|
unknown | int8 | Always 2. |
fileName | wstring | Name of the script file containing the fragments (without extension). |
fragmentCount | uint16 | Number of script fragments in this record. |
fragments | fragment[fragmentCount] | Information on each fragment, as detailed in the following lines. |
fragment.index | uint16 | Index. |
fragment.unknown | int16 | |
fragment.unknown | int8 | |
fragment.scriptName | wstring | Name of script (normally same as fileName). |
fragment.fragmentName | wstring | Name of function containing this fragment script. Typically a name such as "Fragment_5". |
QUST Records[edit]
QUST record fragment scripts are by default stored in a QF file, i.e., a file named "QF_<editorID>_<formID>".
Name | Type/Size | Info |
---|---|---|
unknown | int8 | Always 2. If it's set to anything else, then the game will likely fail to load any script data for aliases. |
fragmentCount | uint16 | Number of script fragments in this record. |
fileName | wstring | Name of the script file containing the fragments (without extension). |
fragments | fragment[fragmentCount] | Information on each fragment, as detailed in the following lines. |
aliasCount | uint16 | Number of aliases that have attached scripts. If 0, the rest of the section is empty. |
aliases | alias[aliasCount] | Information on the scripts attached to each alias, as detailed in the following lines |
fragment.index | uint16 | Quest stage index (equivalent to QUST INDX field) this fragment is attached to. |
fragment.unknown | int16 | Always 0. |
fragment.logentry | int32 | Log Entry within a stage this fragment is attached to. |
fragment.unknown | int8 | Always 1. |
fragment.scriptName | wstring | Name of script (normally same as fileName). |
fragment.fragmentName | wstring | Name of function containing this fragment script. Typically a name such as "Fragment_5". |
alias.object | object | The FormID and AliasID to which the script is attached. Format is the same as documented under propertytype, above. The form ID here is always the form ID of the quest that contains this VMAD subrecord; the game engine actually will allow one quest to attach scripts to aliases on another quest, but official tools never generate that kind of data. |
alias.version | int16 | Always 4 or 5; always the same as the primary script's version. |
alias.objFormat | int16 | Always 1 or 2; always the same as the primary script's objFormat. |
alias.scriptCount | uint16 | Number of scripts attached to this alias |
alias.scripts | Script[alias.scriptCount] | Information on each of the scripts, including name, list of properties, and their initial values. |
SCEN Records[edit]
SCEN record fragment scripts are by default stored in a SF file, i.e., a file named "SF_<editorID>_<formID>".
Name | Type/Size | Info |
---|---|---|
unknown | int8 | Always 2. |
flags | uint8 | Script locations.
|
fileName | wstring | Name of the script file containing the fragments (without extension). |
begineend | beFragment[flagsCount] | Information on begin/end fragments, as detailed below. flagsCount is the number of bits set in the flags field. When both are present, the Begin fragment is emitted first. |
phaseCount | uint16 | Count of phase scripts. |
phases | phaseFragment[phaseCount] | Information on each phase fragment, as detailed below. |
beFragment.unknown | int8 | |
beFragment.scriptName | wstring | Name of script (normally same as fileName). |
beFragment.fragmentName | wstring | Name of function containing this fragment script. Typically a name such as "Fragment_5". |
phaseFragment.unknown | int8 | |
phaseFragment.phase | uint32 | Phase number. (Note: this is 0-based in the data, but 1-based in the CK.) |
phaseFragment.unknown | int8 | |
phaseFragment.scriptName | wstring | Name of script (normally same as fileName). |
phaseFragment.fragmentName | wstring | Name of function containing this fragment script. Typically a name such as "Fragment_5". |