Oblivion Mod:FormID Fixup
Many mod utilities for Oblivion will need to be able to properly handle formids especially when merging plugins where modindexes will have to change. In order to do this one must know all places in the ESP format where formids are stored. This page attempts to describe the process of fixing formids when loading or merging plugins as well as the locations in the ESP format where formids are known to stored.
FormID Locations[edit]
Most of the following formid locations have been verified with a high, but not complete, amount of confidence except where noted.
Record | Subrecord | Size | Byte | Allowed Types | Notes |
---|---|---|---|---|---|
[All] | [Header] | 20 | 12 | Any | All records have a formid in their header |
GRUP | [Header] | 20 | 12 | Various | Occurs only in Worldspace, Cell, Persistent, Temporary, Distant and Topic group types |
ACHR | XESP | 8 | 0 | REFR, ACRE, ACHR | |
XPCI | 4 | 0 | CELL | ||
XMRC | 4 | 0 | REFR | ||
NAME | 4 | 0 | NPC_ | ||
XHRS | 4 | 0 | ACRE | ||
ACRE | XOWN | 4 | 0 | FACT, NPC_ | |
XESP | 8 | 0 | REFR, ACRE, ACHR | ||
NAME | 4 | 0 | CREA | ||
ACTI | SCRI | 4 | 0 | SCPT | |
SNAM | 4 | 0 | SOUN | ||
ALCH | SCIT | 16 | 0 | SCPT | |
SCRI | 4 | 0 | SCPT | ||
AMMO | ENAM | 4 | 0 | ENCH | |
ANIO | DATA | 4 | 0 | IDLE | |
APPA | SCRI | 4 | 0 | SCPT | |
ARMO | SCRI | 4 | 0 | SCPT | |
ENAM | 4 | 0 | ENCH | ||
BOOK | SCRI | 4 | 0 | SCPT | |
ENAM | 4 | 0 | ENCH | ||
BSGN | SPLO | 4 | 0 | SPEL | |
CELL | XOWN | 4 | 0 | FACT, NPC_ | |
XCCM | 4 | 0 | CLMT | ||
XGLB | 4 | 0 | GLOB | ||
XCWT | 4 | 0 | WATR | ||
XCLR | 4-28 | 0/4/8/... | REGN | Array of regions | |
CLAS | None | ||||
CLMT | WLST | 8, 24, 56 | 0/8/16/... | WTHR | An array of 8 byte structures with a formid in the first 4 bytes |
CLOT | SCRI | 4 | 0 | SCPT | |
ENAM | 4 | 0 | ENCH | ||
CONT | CNTO | 8 | 0 | Various items | |
SCRI | 4 | 0 | SCPT | ||
QNAM | 4 | 0 | SOUN | ||
SNAM | 4 | 0 | SOUN | ||
CREA | SPLO | 4 | 0 | SPEL, LVSP | |
CNT0 | 8 | 0 | Various items | ||
PKID | 4 | 0 | PACK | ||
CSCR | 4 | 0 | CREA | ||
CSDI | 4 | 0 | SOUN | ||
SCRI | 4 | 0 | SCPT | ||
INAM | 4 | 0 | LVLI | ||
ZNAM | 4 | 0 | CSTY | ||
SNAM | 8 | 0 | FACT | ||
CSTY | None | ||||
DIAL | QSTI | 4 | 0 | QUST | |
DOOR | SCRI | 4 | 0 | SCPT | |
BNAM | 4 | 0 | SOUN | ||
ANAM | 4 | 0 | SOUN | ||
TNAM | 4 | 0 | CELL, WRLD | ||
SNAM | 4 | 0 | SOUN | ||
EFSH | None | ||||
ENCH | SCIT | 16 | 0 | SCPT | |
EYES | None | ||||
FACT | XNAM | 8 | 0 | FACT | |
FLOR | PFIG | 4 | 0 | INGR | |
SCRI | 4 | 0 | SCPT | ||
FURN | SCRI | 4 | 0 | SCPT | |
GLOB | None | ||||
GMST | None | ||||
GRAS | None | ||||
HAIR | None | ||||
IDLE | DATA | 8 | 0 | IDLE, NULL | |
DATA | 8 | 4 | IDLE, NULL | ||
CTDA | 24 | 12 | Various | Only if function (byte 8) is a certain type (see below). | |
CTDA | 24 | 16 | Various | Only if function (byte 8) is a certain type (see below). | |
INFO | CTDT | 20 | 12 | Various | Only if function (byte 8) is a certain type (see below). |
CTDT | 20 | 16 | Various | Only if function (byte 8) is a certain type (see below). | |
CTDA | 24 | 12 | Various | Only if function (byte 8) is a certain type (see below). | |
CTDA | 24 | 16 | Various | Only if function (byte 8) is a certain type (see below). | |
SCRO | 4 | 0 | Various | ||
QSTI | 4 | 0 | QUST | ||
TCLT | 4 | 0 | DIAL | ||
TCLF | 4 | 0 | DIAL | ||
NAME | 4 | 0 | DIAL | ||
INGR | SCIT | 16 | 0 | SCPT | |
SCRI | 4 | 0 | SCPT | ||
KEYM | SCRI | 4 | 0 | SCPT | |
LAND | ATXT | 8 | 0 | LTEX, NULL | |
BTXT | 8 | 0 | LTEX | ||
VTEX | 256 | * | LTEX, NULL | Array of formids | |
LIGH | SCRI | 4 | 0 | SCPT | |
SNAM | 4 | 0 | SOUN | ||
LSCR | LNAM | 12 | 0 | CELL, WRLD, NULL | |
LNAM | 12 | 4 | NULL, WRLD | ||
LTEX | GNAM | 4 | 0 | GRAS | |
LVLC | LVLO | 8, 12 | 4 | NPC_, CREA, LVLC | Most LVLO subrecords are 12 bytes (only 1 in 2822 is 8 bytes) |
SCRI | 4 | 0 | SCPT | ||
TNAM | 4 | 0 | NPC_, CREA | ||
LVLI | LVLO | 8, 12 | 4 | Various items | |
LVSP | LVLO | 12 | 4 | SPEL, LVSP | |
MGEF | DATA | 64 | 24 | LIGH, NULL | |
DATA | 64 | 32 | EFSH, NULL | ||
DATA | 64 | 36 | EFSH, NULL | ||
DATA | 64 | 40 | SOUN | ||
DATA | 64 | 44 | SOUN | ||
DATA | 64 | 48 | NULL, SOUN | ||
DATA | 64 | 52 | SOUN | ||
MISC | SCRI | 4 | 0 | SCPT | |
NPC_ | SPLO | 4 | 0 | LVSP, SPEL | |
CNTO | 8 | 0 | Various | ||
PKID | 4 | 0 | PACK | ||
SCRI | 4 | 0 | SCPT | ||
ENAM | 4 | 0 | EYES | ||
HNAM | 4 | 0 | HAIR | ||
CNAM | 4 | 0 | CLASS | ||
RNAM | 4 | 0 | RACE | ||
INAM | 4 | 0 | LVLI | ||
ZNAM | 4 | 0 | CSTY | ||
SNAM | 8 | 0 | FACT | ||
PACK | CTDA | 24 | 12 | Various: | Only if function (byte 8) is a certain type (see below). |
CTDA | 24 | 16 | Various: NULL, NPC_, ACHR | Only if function (byte 8) is a certain type (see below). | |
CTDT | 20 | 12 | Various | Only if function (byte 8) is a certain type (see below). | |
CTDT | 20 | 16 | Various | Only if function (byte 8) is a certain type (see below). | |
PLDT | 12 | 4 | Various | Only if type (byte 0) is 0-4. | |
PTDT | 12 | 4 | Various | Only if type (byte 0) is 0-1. | |
PGRD | PGRL | 8-172 | 0 | REFR | Appears to be a REFR formid followed by a variable array of longs (unknown). |
QUST | CTDA | 24 | 12 | Various | Only if function (byte 8) is a certain type (see below). |
CTDA | 24 | 16 | Various | Only if function (byte 8) is a certain type (see below). | |
SCRI | 4 | 0 | SCPT | ||
QSTA | 8 | 0 | REFR, ACRE, ACHR | ||
SCRO | 4 | 0 | Various | ||
RACE | SPLO | 4 | 0 | SPEL | |
DNAM | 8 | 0 | HAIR | ||
DNAM | 8 | 4 | HAIR | ||
ENAM | 4 or 12 | 0 | EYES | ||
ENAM | 12 | 4 | EYES | ||
ENAM | 12 | 8 | EYES | ||
VNAM | 8 | 0 | RACE, NULL | ||
VNAM | 8 | 4 | RACE | ||
XNAM | 8 | 0 | RACE | ||
REFR | XRTM | 4 | 0 | REFR | |
XTEL | 28 | 0 | REFR | ||
XLOC | 12, 16 | 4 | KEYM, NULL | ||
XOWN | 4 | 0 | FACT, NPC_ | ||
XESP | 8 | 0 | REFR, ACRE, ACHR | ||
XGLB | 4 | 0 | GLOB | ||
XPCI | 4 | 0 | CELL | ||
XTRG | 4 | 0 | REFR, ACHR | ||
NAME | 4 | 0 | Various objects | ||
REGN | RDWT | 8-48 | 0/8/16... | WTHR | Array of 8 byte structures with a weather formid in the first 4 bytes |
RDGS | 32 | 0/8/16/... | GRAS | Array of 8 byte structures with a grass formid in the first 4 bytes | |
RDOT | 416-6916 | 0/52/104/... | LTEX, STAT? | Appears to be an array of structures 52 bytes in size with a formid at byte 0 (not confirmed) | |
RDSD | 12-384 | 0/12/24... | SOUN | Seems to be an array of 12 byte structures with a sound formid in the first 4 bytes | |
WNAM | 4 | 0 | WRLD | ||
ROAD | None | ||||
SBSP | None | ||||
SCPT | SCRO | 4 | 0 | Various | |
SGST | SCIT | 16 | 0 | SCPT | |
SKIL | None | ||||
SLGM | SCRI | 4 | 0 | SCPT | |
SOUN | None | ||||
SPEL | SCIT | 16 | 0 | SCPT | |
STAT | None | ||||
TES4 | None | ||||
TREE | None | ||||
WATR | SNAM | 4 | 0 | SOUN | |
WEAP | SCRI | 4 | 0 | SCPT | |
ENAM | 4 | 0 | ENCH | ||
WRLD | NAM2 | 4 | 0 | WATR | |
CNAM | 4 | 0 | CLMT | ||
WNAM | 4 | 0 | WRLD | ||
WTHR | SNAM | 8 | 0 | SOUN |
Locations Not a Formid[edit]
The following locations appear at first to be a possible formid location but in closer detail are not.
Record | Subrecord | Size | Byte | Apparent Types | Notes |
---|---|---|---|---|---|
IDLE, INFO, QUST, PACK | CTDA | 24 | 20 | Various | Seems to never be a formid (is almost always 0). |
REGN | RDAT | 8 | 0 | NPC_, DOOR, STAT | This appears to be a formid but it may just be coincidence (the purpose of RDAT is not known) |
RDAT | 8 | 4 | CELL, REFR, LAND | This appears to be a formid but it may just be coincidence (the purpose of RDAT is not known) |
CTDA/CTDT Functions[edit]
The CTDA and CTDT subrecords that occur in IDLE, INFO, QUST, and PACK records contain formids only in some cases. The basic structure of these records is:
byte CompareTypeAndFlags byte[3] Unknown float CompareValue long FunctionIndex long Parameter1 long Parameter2 long Unknown (only in CTDA)
Parameters 1 and 2 can represent a variety of values depending on what the function used accepts, including formids. The following table lists the functions that accept one or two formids as input (see also Function Indices):
Function | Index | Parameter1 | Parameter2 |
---|---|---|---|
GetCrime | 122 | Actor Reference | Crime Type |
GetDeadCount | 84 | Actor | |
GetDetected | 45 | Actor Reference | |
GetDetectionLevel | 180 | Actor Reference | |
GetDisposition | 76 | Actor Reference | |
GetDistance | 1 | Reference | |
GetEquipped | 182 | Object | |
GetFactionRank | 73 | Faction | |
GetFactionRankDifference | 60 | Faction | Actor Reference |
GetFriendHit | 288 | Actor Reference | |
GetGlobalValue | 74 | Global | |
GetHeadingAngle | 99 | Reference | |
GetInCell | 67 | Cell | |
GetInCellParam | 230 | Cell | Reference |
GetInFaction | 71 | Faction | |
GetInSameCell | 32 | Reference | |
GetInWorldspace | 310 | Worldspace | |
GetIsClass | 68 | Class | |
GetIsClassDefault | 228 | Class | |
GetIsCurrentPackage | 161 | AI Package | |
GetIsCurrentWeather | 149 | Weather | |
GetIsID | 72 | Object | |
GetIsPlayerBirthSign | 224 | Birthsign | |
GetIsRace | 69 | Race | |
GetIsReference | 136 | Reference | |
GetIsUsedItem | 246 | Object | |
GetItemCount | 47 | Object | |
GetLineOfSight | 27 | Reference | |
GetPCExpelled | 193 | Faction | |
GetPCFactionAttack | 199 | Faction | |
GetPCFactionMurder | 195 | Faction | |
GetPCFactionSteal | 197 | Faction | |
GetPCFactionSubmitAuthorithy | 201 | Faction | |
GetPCInFaction | 132 | Faction | |
GetPCIsClass | 129 | Class | |
GetPCIsRace | 130 | Race | |
GetQuestRunning | 56 | Quest | |
GetQuestVariable | 79 | Quest | Variable |
GetScriptVariable | 53 | Reference | Variable |
GetShouldAttack | 66 | Actor Reference | |
GetStage | 58 | Quest | |
GetStageDone | 59 | Quest | Stage |
GetTalkedToPCParam | 172 | Actor Reference | |
HasMagicEffect | 214 | Magic Effect | |
IsCellOwner | 280 | Cell | Owner (Optional) |
IsCurrentFurnitureObj | 163 | Furniture | |
IsCurrentFurnitureRef | 162 | Reference | |
IsOwner | 278 | Owner (Optional) | |
IsSpellTarget | 223 | Magic Enchantment, Spell, or Ingredient | |
SameFaction | 42 | Actor Reference | |
SameRace | 43 | Actor Reference | |
SameSex | 44 | Actor Reference |
Notes[edit]
-
- GMSTs do not appear to have their formids used anywhere.
- Some subrecord data only represents formids in some cases, depending on another value in the subrecord (ex: CTDA). This makes it difficult to confirm formid locations without completely knowing the file format.
- The formid 0x0000014 seems to represent the player reference object (i.e., the instance of the player in the game and not the actual player NPC). This formid does not actually exist in Oblivion.esm and is presumably hardcoded.
- The Oblivion.esm file contains many invalid formids in some subrecords. For example in SCIT subrecords there occurs several formid values greater than 0x01000000 which are not valid as well as one SCIT subrecord that actually specifies a LAND record (it must specify a SCPT record). Once again this makes it difficult or impossible to confirm formid locations when the data itself is not valid.
- Some subrecords which probably should be a fixed size actually have a variable size (ex: LVLO subrecords in LVLC records). This maybe due to versioning issues (the subrecord size was changed at some point but only updated or new subrecords had their size changed). When reading and modifying subrecord data for formid fixups or other purposes ensure you use the record size as read from the file. There are also some almost identical subrecords that appear to be from versioning (ex: the 16 byte CTDT appears to be identical to the 20 byte CTDA).
References[edit]
-
- ScripterRon's TES4Plugin utility source
- Ghostwheel's Tes4.xml (Must access main Ghostwheel site first)
- The ObTestFile module run with stats enabled on Oblivion.esm (use options "/o /m /s"). Currently not yet released (contact the Author for more information).