Modders and those who delve into the technical depths of the game often have a very different view than that of the original developers. This page is a place where we can list areas that can be improved and things that can be added in future 'Elder Scrolls' games.
Please keep comments positive and related to modding or other technical aspects of Oblivion.
- Edit Records From Anywhere
- One of the largest frustrations I get when using the CS is editing records within other records. For example, editing a piece of armor with an enchantment. In order to edit the enchantment you have to manually find the enchantment in the appropriate list rather than just being able to click the enchantment from directly from the armor dialog (ed: gotta check to make sure you can't do this in the armor dialog). You can do this in a few places, namely opening scripts from items, but the majority of places you cannot. This turns an operation that would take a fraction of a second to complete into one that takes at least several seconds.
- Another place that could use this feature is the 'Find Text' dialog which is very useful as it is but could be even better if you could double-click items in the list to open them.
- Windows That Don't Remember Their Size
- Some (most?) windows/dialogs remember their size when you resize them. Others, however, do not including: (list windows here).
- Narrow Lists
- Narrow lists are found in a few places that cannot be resized make it difficult to see the entire item name and ID (script selection list for example). Wider and resizable lists are preferred.
- Simple Record Lists
- Simple lists are used for listing items in a few places, notably the open script selection list. A list with columns (CListCtrl) is preferred like used in most other places that include the script EditorID and FormID in separate columns that can be sorted (the existing script window does show the FormID but it is difficult to distinguish and you cannot sort by it).
- Global Dialog
- The dialog for editing globals has a number of simple improvements that could make it much easier to use:
- List globals by their editorid and not formid. The current global list only shows their formid making it difficult to quickly find a desired global in the list.
- Add new/delete buttons to quickly modify the global list. Context menus are great and should be included as well but adding obvious and frequently used commands (buttons or something similar) aids greatly in discoverability and speed.
- Make the dialog resizable or at least larger to show more globals and make the UI less crowded.
- All Record Types in the Left Tree View
- The Oblivion CS suffers from this same problem as the Morrowind CS where different record types are edited in different locations. Some records are in the main record tree on the left side of the screen, some are in the World menu, some in the Gameplay menu, etc.... All record types should be displayed in the record tree and the record list.
- Consistent UI as all records are edited in the same manner (select the record type in the tree and then double-click the desired record in the list). You don't have to remember or try hunting for a specific record type in the tree and all menus.
- Faster editing and easier discoverability.
- Removes the problem of some of the record specific UIs, like the global edit dialog.
- Simplifies the UI (removes the need of several of the menus from CS). Also simplifies the editor program as there are much fewer specific cases to handle (everything is handled by a common tree/list view control).
- Forcing Dialog Close on Save
- While there is a reason the CS forces you to close any open record dialogs when saving (forces the record contents to be updated) it also slows down the editing process a great. For example, when editing records that take a considerable effort of time to open (scripts, dialog, etc...) saving becomes a 10-20 second chore (close all dialogs, save, find and reopen all dialogs) while it should be virtually instant.
- A better method would be to allow a save with open dialogs but with a warning that those records will not be updated. An even better method would be to include an "Apply" button which would allow the record to be updated without requiring the dialog to be closed.
Mod File Format
- XXXX Special Subrecord
- Special cases in file formats make it difficult to write third party utilities. For example, consider the XXXX and OFST subrecord pairs in Oblivion.esm (required because that one OFST subrecord is greater than 65535 bytes in size). This breaks the incredibly useful pattern of [Header, Size] [Data] used everywhere else in the file.
- There are several possible alternatives:
- The simplest solution is to use 32 bit (or 24 bit) subrecord sizes instead of 16 bit. This would increase the Oblivion.esm file size by 3-6 MB (1-2%).
- Have the subrecord size of 0xffff indicate the current subrecord is continued in the following subrecord. A subrecord exactly 0xffff bytes in size would be stored as two subrecords, on 0xffff in size and the next 0x0000 in size.
- Use three sequential new subrecords (XXXX, OFS1 and OFS2) which all adhere to the known subrecord format.
- Effect Name Duplication
- For any record with effects (ENCH, INGR, SPEL, SGST) the effect name is duplicated in the initial EFID and the EFIT subrecords (this assumes there isn't a reason for the duplication).
- Storing Globals as Floats
- All globals, regardless of their type (short, long, float), are stored in the mod file as floats. This is fine for short globals but it creates potential issues with loss of precision when using long globals. Floats only have 6-7 significant digits which means any long global larger than 100 million (roughly) may lose digits. For example: 100,000,004 stored as a float is 100,000,000. While this will likely only affect a few mods it is still desirable to store long globals as longs and not as floats.
- Variable Sized Subrecords
- Some subrecord types that appear to hold fixed data actually occur in more than one size. For example, most LVLO subrecords in LVLC and LVLI records are 12 bytes in size there are also a few 8 bytes in size. A possible explanation for this size variation is that at one point the LVLO subrecord was changed from 8 to 12 bytes in size and not all subrecords were updated (not confirmed). While a minor issue this makes the parsing of the data more complex than needed.
- Solutions to this include forcing all subrecords to the most recent version or changing the subrecord name when its definition or size changes (assuming that versioning is the problem).
- Bad Formids
- The Oblivion.esm contains some references of invalid formids. For example, in SCIT subrecords there are several formids starting with 0x01000000 which cannot be valid in Oblivion.esm and there is one SCIT subrecord in ENCH(0x000018C5) that actually references a LAND record instead of a script. A possible cause for this bad formids is the deletion of existing script records without updating the referenced SCIT data.
- The following is the list of known bad formids:
- SPEL(0x00008879) -- SCIT: bad formid 0x103D132
- SPEL(0x00014F98) -- SCIT: bad formid 0x1030590
- ENCH(0x00090C66) -- SCIT: bad formid 0x1055315
- SPEL(0x0009812B) -- SCIT: bad formid 0x100C079
- SPEL(0x000A3DF9) -- SCIT: bad formid 0x1002A24
- SPEL(0x000C5987) -- SCIT: bad formid 0x1041CAF
- SPEL(0x000C5988) -- SCIT: bad formid 0x1041CB3
- (Note: all of these appear to have been corrected in later releases of Oblivion, with the exception of SPEL(0x0009812B))
- There should be some steps of validation both during the editing and loading process to identify and prevent such bad formids from occurring.
- Uninitialized Data
- In various places a byte sequence of several 0xCD values are found, for example the SLSD subrecord in SCPT records. These values are not consistent and change between saves for no apparent reason. A possible explanation for this is that some data fields are not being explicitly initialized. The 0xCD value is the default value for uninitialized data in some compilers (MS VC++ uses 0xCD for allocated memory via malloc or new but never written by the application in debug builds).
- All data fields should be initialized with relevant default data (00s) even if never used. At best such uninitialized data makes it very difficult to determine the file format and at worst may result in random program behavior if the data is ever used.
- GRUP Content Size
- The content size of groups in the group header includes the header data. In records and subrecords, however, the size of the data contained in the header does not include the header. While this is a minor issue a consistent format is preferred for simplicity.
- SCRO Player Formid
- The SCRO subrecord found in scripts and some other record types contains a formid of a reference used in the script. The one exception is when the reference is the player where the formid is the value 0x14 instead of the actual player's formid which is 0x07. The reason for this exception is not known but a good guess is that the player's formid was once 0x07 and was changed to 0x14. Note that there is no known record using the formid 0x14.
- 1-Based Indices
- There are several cases in the compiled script data that use a 1-based index into an array, i.e. a value of 1 is the first instance in the array. While this is a minor issue a 0-based index is preferred in most situations. Data that is manipulated by the computer, such as compiled data, should use 0-based indices, especially in languages such C/C++ where arrays are similarly 0-based. By consistently using 0-based indices it prevents the off-by-1 error that can easily occur when mixing 0 and 1-based arrays.
- Compiled Local Var Type Mixing
- When compiled both short and long local variables are output as a single type ('s') as well as float and reference local variables ('f'). While a minor issue it is better to keep explicit type definitions as long as possible for error checking and type conversion purposes, especially for float and reference types which are not compatible with each other.
- String Termination
- The script text stored in SCTX subrecords is never NUL terminated. All other strings seem to be NUL terminated.
- Kill Function
- Using the kill function from a script attached to the NPC seems to cause a crash during the game.
- Lack of Compile Messages
- Like the Morrowind script compiler, the Oblivion compiler is very stingy on giving out warning or error messages when compiling scripts. This makes it very easy to write scripts that may look valid but actually do not run as intended, or worse, crash the game. A stricter compiler is needed which properly checks for errors and warnings.
- The difference between a subtraction and negation operation in a script is merely one space character:
set a to -b ;No space, negation, will compile set a to - b ;Space, subtraction, will compile (same as previous set) set a to b-c ;No space, negation, will not compile! set a to b- c ;No space, subtraction, will not compile! set a to b -c ;No space, negation, will compile set a to b - c ;No space, subtraction, will compile (same as previous set) SetAV Luck - 10 ;Space, negation, will not compile! SetAV Luck -10 ;No space, negation, will compile
- Strangely, these compile errors only occur when using variables and not with numbers.
set a to b-1 ;Does not compile set a to 1-b ;Does compile set a to b+1 ;Does compile set a to b*1 ;Does compile
- This is likely due to how identifier names are parsed (they incorrectly include the '-' character as a valid identifier character). Expression parsing should not be dependent on whitespace and there should be no ambiguity between a subtraction and a negation in the above cases.
- Unary Operators
- The unary operators (+/-) operate differently, for example:
set a to 1 * -2 ;Outputs fine = 1 2 ~ * set a to 1 * +2 ;Outputs invalid expression stack = 1 * 2 +
- There is no compiler message in the second case even though it outputs a different expression stack which is either evaluated incorrectly or may even result in a crash (not yet confirmed). Note that the expression stack uses a postfix(?) notation. A multiply operation pops two expressions from the stack, multiplies them, and pushes the result back onto the stack. With the above output (1 * 2 +) there is only one number on the stack (1) when the multiply operation occurs.
- Required Spaces
- It seems that Oblivion suffers from another Morrowind scripting issue where the spaces in the script affects the script output. Spaces omitted in the wrong place can result in the script not functioning as intended. Tabs are not considered spaces in this respect (verified by looking at the compiled output from the example scripts from the Talk:If page on the CS Wiki).
- Bad Expressions
- The script compiler allows some invalid expressions to be compiled without any warnings or errors. For example,
Script: set localvar1 to GetAV Strength 10 * 9 8 7 Output As: set localvar1 to 8 * 7
- The actual compiled output output is far from the intended output even though there is no way of knowing.
- Local/Record Reference Priority
- Record IDs seem to have precedence over local variables, for example:
ref Enemy ref Test set Test to Enemy ;Uses the 'enemy' dialogue topic and not the local variable
There is no warning message saying that the local enemy conflicts with a global record. Typical scope rules (for example, C++, Java, etc...) would also suggest that the local Enemy would be used in this case. A warning/error message is require in this case to notify the user of a possible conflict.
- Crime Types
- While most enumerated types use string values (actor values for example), the crime type functions only accept numeric values (0-4) instead of the appropriate string value. It is much easier to use a string value (eg. 'steal') rather than having to remember the appropriate numeric value (0 = steal).
Save File Format
- Use Mod File Format
- Keeping save files the same overall format as mod files is preferred, as was done in Morrowind (unless there are significant reasons not to). New record and subrecord types can be created as needed. Using the mod file format allows third party utilities created for ESP/ESM to be relatively easily expanded to include save games as well.