Coda is the scripting language for the Construction Set Extender (CSE). It is not Legacy, or the scripting language used for Oblivion. It is a scripting language that you can use to automate a variety of tasks in the editor, such as renaming objects, moving objects or batch editing object attributes. In this guide, or tutorial, I will show you how you can use Coda to accomplish a variety of tasks.
The Coda Manual is distributed with the Construction Set Extender. You will find it in Data\Docs\Construction Set Extender. The manual explains the general syntax of Coda scripts and how to execute them. It also describes the general language structure, including a description of variables and data types, operators and flow control. In addition to the manual, there is the Coda Command document, which is an HTML file listing all the functions and commands. Since the command set is still being developed, the command document is not included in the distribution. Instead you can generate the most recent version by typing DumpCodaDocs from the console command prompt (see below).
Creating and Running Scripts
The structure of Coda scripts is described in the manual, so I won't repeat it here. I will be listing several examples that you can use to get started. You create your scripts using a text editor. If you use an editor like TextPad or NotePad++, you can use an Oblivion script syntax highlighter. Coda shares its basic syntax with Legacy. Save your scripts with .coda for the extension. Scripts must be in Data\BGSEE\Coda to be accessed and executed from the command line.
Once you've created a script, you run it from the command line in the CSE console window. Here's an example:
Coda scripts are invoked with the RunCodaScript command. The command takes two parameters: the script name minus the extension and a boolean integer indicating whether it's a background script or not. You would use 0 for a regular script and 1 for a background script. Most scripts would be run as a foreground process. I will provide one example of a script that must be run as a background process.
Here are some sample scripts. They are all real scripts, so you can adapt them to your purposes.
Strip off Leading Digits from Editor IDs
This script will strip off the leading digits from editor IDs, which are known to cause problems with Oblivion scripts. It processes all AI packages. You can change the batch of editor IDs by changing the form type ID parameter for the GetDataHandlerFormList function. GetDataHandlerFormList can accept hexadecimal or decimal values. In this example we are using the hexidecimal value for AI packages. The decimal equivalent is 61. The full list of form type IDs is in the Coda Command Documentation or the OBSE documentation.
CODA(ChangeEditorID) var Buffer var EditorID var firstChar begin ; retrieve AI package forms forEach Buffer <- GetDataHandlerFormList(0x3D) EditorID = GetEditorID(Buffer) firstChar = StringSubStr(EditorID, 0, 1) ; we only want to change the editor IDs that start with a number if StringIsNumber(firstChar) printC("editorID (old) ="//$EditorID) ; skip the first character. If there is more than one digit, ; change the starting position so that it skips all the digits. EditorID = StringSubStr(EditorID, 1, StringLength(EditorID)) printC("editorID (new) ="//$EditorID) setEditorID(Buffer, $EditorID) endif loop ; It's pretty quick, but nice to know exactly when it's done. printc("All done.") endSave this script as ChangeEditorID.coda and execute it by typing
RunCodaScript ChangeEditorID 0at the command prompt. Note that the command and parameters are not case sensitive.
Add Mod Prefix to Editor IDs for Cells
This script will add the specified mod prefix to the cell editor IDs. This is handy if you would like to have a naming convention for the objects in your mod and some team members neglected to prefix their editor IDs accordingly. This example renames the editor IDs for cells, but once again, you can change the scope by changing the form type ID. This time we're using the decimal value for cell, which is 48. Semi-colons ( are used for comments in Coda, just as they are in Oblivion script. The printC commands have been commented out in this sample.
CODA(AddBMStartCell) var Buffer var EditorID var firstChars var length var formIDString var formStart begin forEach Buffer <- GetDataHandlerFormList(48) EditorID = GetEditorID(Buffer) formIDString = FormatNumber("%08X", (int)Buffer, 1) ;printc("form string = "//formIDString) formstart = StringSubStr(formIDString, 0, 2) if StringCompare(formStart, "01", 0) == 0 firstChars = StringSubStr(EditorID, 0, 2) length = StringLength(EditorID) if length == 0 continue() endif if (StringCompare(firstChars, "BM", 0) != 0) ;printC("editorID (old) ="//EditorID) EditorID = "BM" // EditorID ;printC("editorID (new) ="//EditorID) setEditorID(Buffer, EditorID) endif endif loop printc("All done.") endPrint Random Numbers
Here's a little test script to show how the random number function works. I use this function later. In this case, I'm generating random numbers between 0 and 359, which correspond to angles. The generated numbers are floats with six decimal places.
CODA(Random) var randomNum var i begin while i < 10 randomNum = RandomNumber(0, 359) printC("Random number: "//$randomNum) i += 1 loop endChange Imperials and Nords to Orcs and Dark Elves
Here's a script that shows an example of the Base Form Component (BFC) functions. It switches the race of all male Imperial and Nord NPCs to Orcs and Dark Elves.
CODA(SwapRace) var npc var race begin forEach npc <- getDataHandlerFormList(35) race = getBFCRace(npc) if (race && (race == getFormByEditorID("Imperial") || race == getFormByEditorID("Nord")) && getBFCActorBaseDataSex(npc) == 0) printC("NPC "//getEditorID(npc)//" switched to new race!") if (race == getFormByEditorID("Imperial")) setBFCRace(npc, getFormByEditorID("Orc")) else ; nord setBFCRace(npc, getFormByEditorID("DarkElf")) endif markAsModified(npc, 1) endif loop printC("All done!") endAll the scripts so far are executed as regular foreground scripts. Before I detail the monster background script, I'll direct you to the Disable Trees example on the CS Wiki. Disable Trees demonstrates how to scan exterior cells for specific objects and disable them. It also mentions a key CSE function: you can get a list of all cell form IDs by using the Export tool from the main menu.
File -> Export -> Interior and Exterior Cell Data