Construction Set Tips
The TES construction Set is the toolkit that Bethesda used to build TES III: Morrowind, and which they released for modders to use. All level and quest design is done using this tool. It comes bundled with the original game or (for the Steam version) is available for download on the Morrowind Nexus.
This page aims to list some common tips on using the Construction Set more effectively and warn about some pitfalls you may encounter.
Construction Set Extender
The Construction Set Extender (CSSE) is an absolutely crucial set of improvements to the original TES Construction Set that relies upon MGE XE for its functionality.
Its many features include huge performance improvements, automatic item alignment, resizable and filterable windows, and much more (see the full feature list).
The Extender is under active development, so users of it may find parts of the below page become outdated.
See the install and usage instructions on the project website.
Note: You may also be interested in TESCS: RR UI, which includes further UI tweaks and allows you to select font sizes. It is completely compatible with CSSE.
Note 2: There is also the older Construction Set Better UI, which increases the window sizes in a less configurable manner. It is compatible with CSSE (see instructions), but will override some of the nice functionality of the latter, like the ability to resize the dialogue window. Most of the functionality of Construction Set Better UI is by now superseded by CSSE.
Validator Check
There's a CSSE deprecation file that filters out objects you should not use during development by removing all Standards Validator-flagged vanilla IDs from the CS menus. After installing the CSSE, download this file and place it in your "Morrowind/Data Files" folder. Simply move or delete the file if you wish to see the objects again.
INI Edits
You can enable some useful additional options in the Morrowind.ini
file in your Morrowind install directory.
The .ini file has sections denoted by a header in brackets, like so: [General]
. Below the header are individual lines containing settings that all belong in this section.
These options often are not present in the file. To add them, type on a new line this general schema: Option = value
- Enable "Skip All" Warning Messages: add the line
AllowYesToAll=1
in the[General]
section. Now, when you load the CS, simply click "Cancel" when the first warning message pops up, and it will skip through them all. - Open multiple Construction Set windows: add the line
AllowMultipleEditors=1
in the[General]
section.
Startup
- Watch out for errors. When starting the CS with the "
AllowYesToAll=1
" change in Morrowind.ini, don't automatically clickCancel
on the first error you see. If the first message is "One or more plugins could not find the correct versions of the master files they depend on. (...)", clickYes
, then wait until you get the message "Previous string is different for topic (...)" to clickCancel
. If there are any other messages before the "Previous string" messages, it's probably something important. Be on the lookout for these messages when loading several files with dependences between them (dependences either visible or invisible, to ESM or ESP), which is frequent when working with Tamriel Rebuilt or Project Tamriel, or when loading a plugin after it's modified with another application.- Note: The issue with the always-present startup errors is fixed in CSSE. When using it, all errors you see should be addressed.
- Opening a second CS instance won't ask and will ignore errors, if you already cancelled error messages before with the CS still open (with
AllowMultipleEditors=1
in Morrowind.ini). - If the Object Window is missing object tabs (Static, Activator...) when you open the CS, just resize the object window.
- Try not to run the Construction Set as administrator. This will mess up your CS-specific Windows registry settings and with cause your CS to not remember your window sizes and positions between sessions, unless you run it as administrator every time.
General
- See the compilation of all Construction Set hotkeys on UESP. These are often impossible to figure out on your own, and some are very useful. Many were unknown until recently!
- Note: CSSE adds several new useful hotkeys; check its documentation.
- Creating new objects using meshes or icons contained in a .BSA archive. If the new object is the same type as an object that already uses those assets, change the ID of that object to your new object ID, save and click "
Yes
" to create a new ID; if it's a different type (e.g., creating an Activator from a Static) you can extract the files from the BSA but you don't have to – you can also create an empty file with the same filename and extension as the mesh or icon, place it in the folders it's supposed to be in, link the new object to that empty file, then delete the empty file. - You can jump to an object in the Object Window by clicking on the list and pressing the first letters of its ID. You can do the same in most windows, dropdowns and ID lists (scripts, globals, sounds...).
- Note: CSSE significantly improves the list jumping behavior and adds many other ways to find objects by name or ID, e.g., by the added filter bars at the bottom of windows or double-clicking results in the
Edit > Find text
window.
- Note: CSSE significantly improves the list jumping behavior and adds many other ways to find objects by name or ID, e.g., by the added filter bars at the bottom of windows or double-clicking results in the
- Object Window lists can be sorted by alphabetical order of a column by clicking on the tab at the top.
- The search function in
Edit > Find Text
also looks at some object property fields.- Note: CSSE improves the Find Text window; double-clicking a search result will allowing you to jump to the location of a reference in the Render or Dialogue windows.
- To delete something that doesn't show you any delete option (global variables, sounds), use the "Del" key.
- If the CS crashes, make a copy of the backup file "pukcab.bak" in Data Files before starting the CS again. (But you won't need that because you already know you have to save often and copy your active file into a new file each time you save, right?) You should also make use of the option to
Auto Save every X minutes
inEdit > Preferences
.
Interiors and Exteriors
- Click "Cancel" or press the escape key when editing the properties of an object in a cell (object instance), such as coordinates, scale, or owner extra data. If you click "Save" or press the enter key, you dirty the ID (object definition) itself.
- Clean or cancel specific edits to a cell: In
File > Data Files > (select the active plugin) > Details
, pressing "Delete" on reference edits marks them as ignored (these changes aren't saved on their own – if that selected plugin wasn't loaded or wasn't the active one, it then needs to be loaded and saved for the changes to apply). - Placing an object that comes from another ESP plugin: When placing an object not defined in the active plugin, nor in an ESM master into a cell, the object becomes dirtied in the active plugin when it's saved, and it will have to be cleaned manually. This will happen if you use an object from, e.g., TR_Mainland.esp, or a Data add-on that has the ESP format instead of ESM.
- It is generally safer to insert objects from the Objects window, instead of copying them from another cell. The latter often leaves the new one with ownerships you need to clean.
- Multiple objects can be snapped onto the grid together, provided the first selected object is a tiling object. If an entire tiled cell got moved off the grid, make sure nothing is selected, select a tiling object first, then select everything else (when drawing a square selection in the cell or using shift+click in the cell objects list make sure not to go over that first object again) - the first object's coordinates get used to gridsnap and the relative positions of all other objects shouldn't be altered. This is
- Note: CSSE changes this behavior by default – now, the last selected item will be used as the grid snap reference.
- Using
Ctrl+D
to duplicate an object instance. If you try to move the object after duplicating it, the original instance is still selected and is the one that will be moved, not the new duplicate instance. This is important to keep in mind when working on a plugin to an ESM file (e.g., TR_Mainland.esm) – you don't want to edit the original instance defined in the ESM file! You can find the new instance in the list of cell objects (has * after the ID, is the last object with that name in the list if sorted by default or by Object ID, and the first object with that name in the list if sorted by Type) and select it there, then click on the top frame of the cell Render Window, and usually pressingF
will move it away from the original instance and allow you to move it. It's often easier to place a new one from the objects list. - Hold X, Y, Z keys to move an object on that axis. If it doesn't work, try moving it in the opposite direction.
- Note: CSSE adds a very nice visualization to make it clear which axis the item will be moving on.
- Change a cell name. Select it by clicking on it once in "Cell View", then click again (or press
F2
). - Many objects in a row can be selected with Shift+click in the object list of a cell.
- CSSE Only: Alt-placement. Holding alt when placing an item will make it snap to surface.
- CSSE Only: Q-menu. Press Q to open the render window menu. This allows you to change what plane an alt-placed item will snap with. It also allows you to select multiple objects and align their position/rotation/scale (aligned to the last object selected), randomize their position/rotation/scale, reset their rotation/scale, amongst other features.
- If textures has been changed, resizing the render window will update textures in Construction Set, without the need for restarting the program.
NPCs
- You can quickly preview faces in
Edit > Preview Window
by browsing them in "Body Parts" like any other objects in the Object Window. For vanilla faces, you can also find them in an index. - Copying NPCs to make new ones often leaves the new NPCs with services or special AI packages. If you cookie-cut NPCs, always check the AI tabs for each of services, travel destination, AI packages, idle animation chances, and clean them.
- Some NPC classes have default services they will always provide if they have "
Autocalc
" toggled. The "Agent" class will always be a default trainer for Light Armour, etc. - To give a NPC specific spells or services, you must not give them
Autocalc
. If you toggleAutocalc
on after giving them a custom selection of spells, they will lose those spells. - Avoiding screaming corpses. NPCs or creatures are always persistent, but checking the "references persist" option has a different effect for actors defined with 0 health; without "references persist", they will play their death animation and scream when their cell is loaded; with "references persist", they will directly be loaded as corpses.
- Attacking on crime and bounties. NPCs with 90 or high enough Alarm will attack when you commit crimes and will "report" you to other NPCs in the cell, but if none of these NPCs have 100 Alarm, crimes will not give a bounty.
- NPCs can have more than one AI package. They can have Wander AND Follow. The Follow package isn't the same as
AiFollow
in scripting – it won't make the NPC follow the target; instead, it will make the NPC join the target in combat (if the package target is "player", then the NPC will also follow the player through loaddoors if they're close enough). - Applying NPC ownership to many objects in a cell. In the object list of a cell, many objects in a row can be selected with Shift+click. To apply ownership to all of them, Ctrl+click the last one in the render window, then Ctrl+doubleclick it to open its Properties while all other objects are still selected.
- Finding NPC or creature instance coordinates. In a cell, these cannot be found in a NPC or creature's instance properties. Their coordinates can instead be seen at the bottom bar of the CS window (the main one called "TES Construction Set").
Dialogue
- You can open and work in several dialogue windows at the same time.
- You can jump to a topic or dialogue line by selecting the list and pressing its first letters.
- Within a topic (or greeting...), you can jump to the first edited dialogue line of the active plugin by pressing the * (asterisk) key. You can jump to specific lines by pressing "space" after * and then the first letters of the dialogue line. (dialogue lines and their parameters have to finish loading before pressing the next letter – if you land on a dialogue entry with many conditions, due to the time the CS takes to display everything, you may have to wait and/or start pressing keys again from the beginning).
- You can move the position of a dialogue entry up and down using the left and right arrow keys.
- When creating a new dialogue entry, whether you click "new" or "copy", the new one will be above the entry you had selected. Always edit the one above. The entries above and below the new one will always be dirtied; see the cleaning instructions.
- Copying text from Microsoft Word, Google Docs or other text software will often leave you with ’bad apostrophes’, “bad quotes”, spaces at the end of IDs, Linux linebreak characters... none of these things are good to keep.
- If you create a new NPC, object ID or local variable while the dialogue window is already open, you won't find the new ID available in dialogue conditions until you select a different entry.
- When you edit the existing conditions of a dialogue entry, without changing the condition type (for instance changing a
Journal == 0
condition to< 0
, or to a different journal ID), the change won't be saved until you select a different entry, or edit the text, or add a new condition, or close the dialogue window... i.e., if you open an active plugin, open the dialogue window, edit the contents of a condition and immediately click to save the plugin, the condition won't be changed in the saved file. As long as you don't see a * sign to the right of the active file name in the top CS bar, there is no change to the file. - Don't edit the name of a master file's topic, such as a topic in TR_Mainland.ESM while editing another file. If you do, the plugin will attempt to delete the topic and that be won't easy to clean.
- Don't directly edit the name of a topic just to change capitalisation ("topic" also applies to journal IDs). If you do, the topic and its contents will be deleted when saving the plugin. If you need to only change capitalisation, either use tes3cmd, or first change the topic to a different word, then save, exit the CS, open the plugin again and change the topic back.
- The CS will not complain if a journal or topic is given the same ID as an object, but this will create bugs. When in doubt check that new journal or topic IDs aren't taken by an object.
- If the only condition the player doesn't meet for a dialogue entry is "
Disp
", they will still see the topic, but will get a response from the Persuasion->Info Refusal tab instead. - An EMPTY dialogue entry will not work with NPCs in the game (different for journals, see below in "Giving a journal entry with no text") and an EMPTY greeting can prevent the player from being able to talk to the NPC. Using a regular space (keyboard spacebar) to create an entry with no text will not work in the CS, as it will revert to an EMPTY entry or to the text it had before. Using a nonbreak space will work.
- You CAN see the ID (INFO ID) of each dialogue entry in the CS. The tab is normally hidden. You can expand the tab between "Info" (the tab under which the text is) and "Disp/Index".
- "Journal" names longer than the respective field. Sometimes under some condition slots, you may not be able to see the end of journal IDs, and be unable to tell which journal it is if there are several that start the same way. To see which journal ID is already there, you can expand that condition's "Fun/Var" tab in the dialogue list above. To add the journal ID you want you can type its full name while the dropdown list is expanded (you should do that anyway, it's faster).
- Note: This issue is fixed by CSSE.
Dialogue results
- Never save after using Error Check Results (see other related comments here) as it applies all changes to global variables in any dialogue results in the file, modifying the default values of those global variables.
- Dialogue results are scripts but they're not pre-compiled by the CS, so they will behave differently when giving explicit targets (i.e., when specifying
"targetID"->
, as opposed to implicitly targeting the actor that spoke the dialogue line). Compiled scripts can only target an explicit ID if an instance of that ID has been placed in the CS and they can only target the first instance that existed (if a NPC is the first instance and gets revived with "Resurrect
", it still counts as the first instance). Dialogue results do not have this limitation, but Error Check Results will report errors if no instance exists. - "
Startcombat, player
" isn't enough to make a NPC hostile. If they don't see the player when the dialogue result happens, they will never attack and will stay friendly. If they do attack, their hostility will fade after 72 hours outside of the cell. Use "SetFight
" too. - Normal NPC hostiles such as bandits have 90 Fight, and won't attack if they have 100 Disposition with the player. Fight 100 will always attack.
- You don't need to check if you've already given a journal entry in dialogue result. If you give the same entry again with Journal, nothing happens (except for potentially Restarting or Finishing, if the entry has these options and another entry closed or reopened that journal before). This is different when out of dialogue: giving the same journal entry again in a script will give a journal update message (but still no repeat entry in the journal).
- Giving a journal entry with no text (EMPTY) acts the same as giving a journal that was already given. There will be no journal entry and no update message in dialogue results. If you give an empty Journal stage in a script, still no journal entry will be added, but "Your journal has been updated" is displayed. The implication is that you can silently "Finish" or "Restart" a journal with an empty journal entry given in dialogue.
- A topic will not be hyperlinked in a dialogue line if no topic entry was available before that dialogue line's results. Example: if the greeting "Help me!" gives Journal "MyJournal" 10 but the topic "Help" has no available entry before a Journal "MyJournal" >= 10 condition, "Help" will not be hyperlinked the first time you see "Help me!"
- Choices should never be used in the Persuasion or Service Refusal tab. They won't lead to the same tab, but instead to greetings or to the last topic the player used.
Error Check Results
The Construction Set's Error Check Results is a button at the bottom right of the dialogue window that makes the Construction Set simulate the scripts in all dialogue results and progressively give reports about found errors in pop-up windows as well as in Warnings.txt
. It is a valuable tool for detecting simple syntax errors or ID errors, but with two caveats:
- you should never save your plugin after using this button,
- there will be a number of false positives.
See the dedicated page for more information.
Scripts
- Recompiling a script after editing the ID (that comes after "begin") will change the ID of that script. Start a new blank script.
- If you try to add a script to an object and its script stays blank after saving the object, check that the script ID doesn't have more than 31 characters.
- A script needs to be compiled once before any script can start or stop it, so it's normal for a script that terminates itself to give an error the first time it's compiled.
- A script also needs to be compiled once before its local variables can be targeted with the
"objectID".variable
syntax by a compiled script. If a script refers to its own variables using the"objectID".variable
syntax, and if you haven't compiled it with these variables yet (or accidentally saved this script by moving to another script in the window without compiling it), the "variable not found" error will prevent you from compiling the script, and it won't be able to find its own variables until it's compiled... You need to comment out these references to its own variables, compile, then uncomment and compile again. - The order in which local variables are defined in a script matters, not just for the 34th variable of a type which didn't work (without the code patch), but also for any other script that targets it with the
"objectID".variable
syntax. When editing an existing script, any new variables should be added at the end of existing variable definitions. - If you accidentally used an object ID in an argument that doesn't accept that type of object (like giving a NPC ID instead of a cell name) and get an error about it when trying to compile, you may find that your script has become the local script of that object, replacing its local script if it had one.
- Copying text from Microsoft Word, Google Docs or other text software will often leave you with ’bad apostrophes’, “bad quotes”, spaces at the end of IDs, linux linebreaks... none of these things are good to keep. A script copied from elsewhere can have characters that aren't visible in the CS and that still make the script fail.
- CS search will fail to find text in extremely long scripts.
- CS will not complain if a script is given the same ID as an object, but this will create bugs. When in doubt check that new script IDs aren't taken by an object. Same for topic IDs or journal IDs.
- A global variable shouldn't be declared as a local variable in a script if the script uses the global variable. For the global
DaysPassed
, don't use vanilla scripts as an example when they use "short daysPassed
" (besides, the vanilla script method for tracking time with "currentDay
" and "daysPassed
" only works correctly for global scripts that will always run with the player, not for local scripts that will only run when the player is in the same cell). - If you've fixed a script, but there are no changes in-game. Yes, you've edited and recompiled the script, but did you save the plugin? Yes, you've saved the plugin, but did you save the script? You don't get a warning on exit.
Sound Gen
- Creature soundgen is affected by models of existing creatures. If your new creature ID uses a mesh that hasn't been used by any creatures before, the "Sound Gen Creature" field in that new creature ID's properties will successfully give it the same sounds as whatever creature you select. But if your new creature ID uses the same mesh as an existing creature, it will get that creature's sounds even if you give it another "Sound Gen Creature" – if you want different sounds, or want to add sound types (Moan, Scream, Land...) that the first creature to use the mesh didn't have, you'll need to create new sounds for all the sound types you want and associate each of them with the new creature ID in
Gameplay > Sound Gen
.
Voices
- In the dialogue voice tab, all sound files will play in the CS, but they will only be played in the game if the file path of the .mp3 contains a "Vo" folder. It doesn't have to be the first folder after Sound/ or the last.