This readme covers the most technical aspects of Wrye Bash, namely the Wizard scripting language and syntax for certain other file types. Information on the most commonly used aspects of Wrye Bash may be found in the General Readme, and the Advanced Readme holds information on more advanced and less commonly used features. Wrye Bash's version history is stored in the Version History document.
The DarNified Books setting in the Bashed Patch's tweaks allows the use of Wtxt formatting, which is applied if the first line of a book is == title ==
<<
, ^^
or >>
at the beginning of a line generate a div align=left
, div align=center
or div align=right
tag respectively.
== text ==
generates a level 2 header.
=== text
generates a level 3 header.
__text__
, ~~text~~
and **text**
generate emphasised text.
BAIN Wizards allow mod authors to include a simple configuration script with their packages. Wizards run on a simple scripting language similar to OBMM script, contained in a wizard.txt
file in the package. When run, the wizard will run through a series of windows to allow you to select options, then show a summary page at the end telling you which sub-packages and plugins will be selected, and any INI tweaks that will be applied.
Those using Notepad++ to write their install scripts may want to use Utumno's BAIN wizard Script Highlighter for Notepad plus plus as it features code folding and syntax highlighting to make spotting mistakes easier.
There is a similar BAIN Wizard Syntax for EmEditor syntax highlighter for EmEditor created by broken85.
You may use a number of different dialogs in a wizard. The available dialogs are described in this section.
SelectOne - This dialog displays a list of options, but only one can be selected. It will be shown when a SelectOne keyword is used. Each option can display an image associated with it, and a description as well. To see a larger version of the image displayed, either double click or middle click on the image. The wizard can specify a default answer, and if you are running it as an Auto-Wizard, then this page will be skipped, using the default option.
SelectMany - This dialog displays a list of options, and any combination can be selected (including none at all). It will be shown when a SelectMany keyword is used. Each option can display an image associated with it, and a description as well. To see a larger version of the image displayed, either right click or middle click on the image. The wizard can specify default options, and if you are running it as an Auto-Wizard, then this page will be skipped, using the default options.
Cancel - This dialog will be shown if the wizard cancels execution for some reason, activated by the Cancel keyword. If a reason is given, it will be displayed.
Error - This dialog will be shown if the wizard encounters an error in the wizard file. The wizard will then quit.
Finish - This dialog will be shown at the end of the wizard, to show you which sub-packages and plugins will be selected. It will be shown either when the end of a wizard file is reached, or if the Return keyword is used. It also shows what INI Tweaks will be applied, and also serves as a place for any extra notes from the mod author to be displayed.
Version Warning - This dialog is displayed if the user's system doesn't meet the package's game, script extender or graphics extender requirements. These can be specified via the RequireVersions keyword.
Each line of a Wizard contains one statement. To carry a statement across multiple lines, end each line of the statement with a backslash \
. This will cause BAIN to read the next line as if it were part of the first.
Wizard syntax is case-sensitive, apart from filenames. Make sure when writing Wizards that you use the correct case.
Variable names may contain any alphanumeric characters (a-z, A-Z, 0-9) and underscores (_), but cannot start with a number. You cannot declare a variable with the same name as a keyword, function or constant. Variables can be assigned values using an assignment operator, and can hold the following data types:
0.123
, -3.5
, 7.0
. You can perform mathematical operations on decimals using the mathematical operators.
"Hello"
, 'World!'
. As in the examples, strings must be enclosed within double or single quotes. Special characters may be included in strings by using an escape sequence. Strings can be added and multiplied using the addition and multiplication operators. One string may be checked for within another using the in operator.
Constants are variables that are pre-defined by BAIN and cannot have their values changed. You cannot create new constants.
Comments are extra text ignored by the Wizard engine, to explain what the Wizard code does to other readers. Comments begin with a semicolon ;
and last until the end of the line.
Expressions are evaluated using the standard order of operations, e.g. 3 + 6 * 2
will evaluate to 15
.
SelectSubPackage
and not SeleCtsUbpacKage
.
"","",""\
CompareGameVersion - Used to test the installed version of the game Wrye Bash is running for against the version you specify.
CompareGameVersion(version_string)
"1.2.0.416"
.
Return values:
-1
- Installed version is less than the version specified in version_string.
0
- Installed version is equal to the version specified in version_string.
1
- Installed version is greater than the version specified in version_string.
CompareSEVersion - Used to test the installed version of the Script Extender of the game that Wrye Bash is running for against the one you specify.
CompareSEVersion(version_string)
"0.0.20.1"
.
Return values:
-1
- Installed version is less than the version specified in version_string.
0
- Installed version is equal to the version specified in version_string.
1
- Installed version is greater than the version specified in version_string, or there is no Script Extender available for the game.
CompareGEVersion - Used to test the installed version of the Graphics Extender of the game that Wrye Bash is running for against the one you specify.
CompareGEVersion(version_string)
"3.0.1"
.
Return values:
-1
- Installed version is less than the version specified in version_string.
0
- Installed version is equal to the version specified in version_string.
1
- Installed version is greater than the version specified in version_string, or there is no Graphics Extender available for the game.
CompareWBVersion - Used to test the installed version of Wrye Bash against the one you specify.
CompareWBVersion(version_string)
"307"
.
Return values:
-1
- Installed version is less than the version specified in version_string.
0
- Installed version is equal to the version specified in version_string.
1
- Installed version is greater than the version specified in version_string.
DataFileExists - Tests for the
existence of one or more files, relative to the Data directory. If the
files you are testing for are plugins, this will also detect ghosted
versions of them. All specified files must exist for this to return
True
.
DataFileExists(file_name [, ..., file_name_n])
"Oblivion.esm"
would test for
"[path to game]\Data\Oblivion.esm"
. Notes:
"obse\\plugins\\MenuQue.dll"
will work, but
"obse\plugins\MenuQue.dll"
will fail."..\\SoundCommands.log"
DataFileExists("Oblivion.esm","..\\SoundCommands.log",
"obse\\plugins\\MenuQue.dll")
will accurately test
to see if each of the files exist.Return values:
True
- All of the files exist.
False
- One or more of the files do not exist.
GetPluginLoadOrder - Returns the current load order index of a plugin in the Data directory. You may want to combine this with GetPluginStatus to check if the plugin is enabled first.
GetPluginLoadOrder(file_name [, fallback_val])
-1
by default.Return values:
GetPluginStatus - Tests the current status of a plugin in the Data directory. Takes ghosting into account when testing the status.
GetPluginStatus(file_name)
Return values:
-1
- The plugin does not exist.0
- The plugin is not active, imported, or merged. Its checkbox in Wrye Bash's Mods tab is .1
- The plugin is not active, but has portions imported into the Bashed Patch. Its checkbox in Wrye Bash's Mods tab is .2
- The plugin is active. Its checkbox in Wrye Bash's Mods tab is .3
- The plugin is merged into the Bashed Patch. Its checkbox in Wrye Bash's Mods tab is .DisableINILine - Tells Wrye Bash to create an ini tweak file that disables the specified setting by commenting it out. Otherwise, behaves identically to EditINI.
DisableINILine(file_name, section, setting)
EditINI - Tells Wrye Bash to create an ini tweak file with some tweaks in it. If the file that you tell Wrye Bash to apply the tweak to is from the current installer or is the game's ini file, then Wrye Bash will also automatically apply the tweak, otherwise, it will just be generated for the user to apply manually.
EditINI(file_name, section, setting, value [, comment])
Exec - This will cause the Wizard to execute lines that are passed to it. This is useful for creating dynamically generated menus.
Exec(lines)
\'
should be written \\\'
.
EndExec - Internal function used to mark the end of the lines executed by an Exec statement. Attempting to explicitly call it will result in an error.
EndExec(line_count)
str - Used to convert a value into a string, for example when trying to concantenate a integer or decimal to a string.
str(value)
Returns:
str(5)
would return "5"
.
int - Used to convert a value to an integer, for example converting a value held in a string to a integer value.
int(value)
Returns:
int('65')
would return 65
.
0
- If integer conversion is not possible.
float - Used to convert a value to decimal, for example converting a value held in a string to a decimal value.
float(value)
Return values:
float('2.4')
would return 2.4
.
0.0
- If decimal conversion is not possible.
len - Used to find the length of a string.
len(string)
Return values:
0
- If length calculation was not possible.
endswith - Test what a string ends with.
endswith(string, ending_1 [, ..., ending_n])
Return values:
True
- If the string ends in any of the endings specified.
False
- If the string does not end in any of the endings specified.
startswith - Test what a string starts with.
startswith(string, prefix_1 [, ..., prefix_n])
Return values:
True
- If the string begin with any of the prefixes specified.
False
- If the string does not begin with any of the prefixes specified.
lower - Convert a string to lower case.
lower(string)
Return values:
find - Return index of first occurrence of a substring.
find(string, substring [, start, stop])
Return values:
-1
- If substring could not be found.
rfind - Return index of last occurrence of a substring.
rfind(string, substring [, start, stop])
Return values:
-1
- If substring could not be found.
GetFilename - For a string that contains a path, returns the filename part of the string.
GetFilename(path_string)
Return values:
GetFolder - For a string that contains a path, returns the folder part of the string.
GetFolder(path_string)
Return values:
CompareObVersion - Use CompareGameVersion instead.
CompareOBSEVersion - Use CompareSEVersion instead.
CompareOBGEVersion - Use CompareGEVersion instead.
GetEspmStatus - Use GetPluginStatus instead.
Keywords are like functions, but don't require brackets around their arguments, and are used for controlling the flow of a wizard or performing special tasks.
SelectSubPackage - Cause the specified sub-package to be selected for installation. This is equivalent to checking the sub-package and all the plugins in that sub-package in the BAIN window.
SelectSubPackage name
DeSelectSubPackage - Cause the specified sub-package to be de-selected from installation. This is equivalent to un-checking the sub-package in the BAIN window.
DeSelectSubPackage name
name
- A string or variable holding the name of the sub-package to de-select.
SelectPlugin - Cause the specified plugin to be selected for installation. This is equivalent to checking the plugin in the Plugin Filter of the BAIN window.
SelectPlugin plugin_name
DeSelectPlugin - Cause the specified plugin to be deselected from installation. This is equivalent to un-checking the plugin in the Plugin Filter of the BAIN window.
DeSelectPlugin plugin_name
SelectAll - Cause all sub-packages and plugins to be selected for installation. This is equivalent to first checking all sub-packages in the BAIN window, then checking all plugins in the Plugin Filter of the BAIN window.
SelectAll
DeSelectAll - Cause all sub-packages and plugins to be de-selected from installation. This is equivalent to first un-checking all plugins in the Plugin Filter of the BAIN window, then un-checking all sub-packages in the BAIN window.
DeSelectAll
SelectAllPlugins - Cause all plugins to be selected for installation. This is equivalent to checking all plugins in the Plugin Filter of the BAIN window.
SelectAllPlugins
DeSelectAllPlugins - Cause all plugins to be de-selected from installation. This is equivalent to un-checking all plugins in the Plugin Filter of the BAIN window.
DeSelectAllPlugins
RenamePlugin - Change the installed name of a plugin. Note that the file extension must stay the same.
RenamePlugin original_name, new_name
ResetPluginName - Resets the name of a plugin back to its default name.
ResetPluginName original_name
ResetAllPluginNames - Resets the names of all plugins back to their default names.
ResetAllPluginNames
Note - Add a note to the user to be displayed at the end of the wizard, on the finish page. The '- '
will be added automatically.
Note text
Return - Signals completion of the wizard. This will jump right to the finish page.
Return
Cancel - Cancels the wizard, with an optional text to display in a dialog as to why the wizard was canceled.
Cancel [text]
RequireVersions - Tests the users system against version requirements you specify. If the requirements are not met, a warning dialog will be shown asking if you wish to continue anyway.
RequireVersions game_version [, se_version, ge_version, wrye_bash_version]
If-Elif-Else-EndIf - A basic If control block.
If statement
lines
Elif statement
lines
Elif statement
lines
Else
lines
EndIf
If
- Begins the control block.
True
, then the lines following it will be run, until the next Elif, Else, or EndIf.
Elif
True
, and the initial If
and none of the previous Elif
s were True
, then the lines following this Elif
will be run, until the next Elif
, Else
, or EndIf
.
Else
- If the initial If
and none of the previous Elif
s were True
, then the lines following will be run until an EndIf
is met.
EndIf
- Signals the end of the If
control block.
While-Continue-Break-EndWhile - A while loop.
While statement
lines
Continue
lines
Break
lines
EndWhile
While
- Begins the while loop.
True
, execution of the lines begins, otherwise execution skips to after the EndWhile
.
Continue
- Signals the while loop to begin over again at the While
statement.
Break
- Signals the while loop to end execution, skipping to after the EndWhile
.
EndWhile
- Ends the while loop. statement is re-evaluated, and if True
, execution begins again at the start of the While
block.
For-Continue-Break-EndFor - A For loop.
For var from start_value to end_value [by increment_value]
lines
Continue
lines
Break
lines
EndFor
For sub in SubPackages
For file in sub
lines
EndFor
EndFor
For
- Begins the for loop. There are three types of for loop.
var from start_value to end_value [by increment_value]
1
if start_value is greater than end_value or -1
otherwise.
sub in SubPackages
- This type of for loop iterates over the names of the sub-packages in the current package.file in sub
- This type of for loop iterates over the names of the files in the given sub-package. Filenames are relative to the Data directory, before any remapping that would normally be done by BAIN.
Continue
- Signals the for loop to begin over again at the For
statement.
Break
- Signals the for loop to end execution, skipping to after the EndFor
.
EndFor
- Ends the for loop.
SelectOne - Shows a dialog where the user can select one option from a list of options.
SelectOne 'description', \
'option 1', 'description 1', 'image 1', \
'option 2', 'description 2', 'image 2', \
..., \
'option n', 'description n', 'image n'
Case 'option 1'
lines
Break
Case 'option 2'
lines
Break
Case 'option n'
lines
Break
Default
lines
Break
EndSelect
SelectOne
- After the user presses the "Next" button, this begins a Select control block.
Mopy/bash/images/Wizard Images
folder.
Simply specify the path as Wizard Images\\[image]
, and Wrye
Bash will look there if it doesn't find a matching image in your
package. For example, specifying Wizard Images\\
would allow
you to use the Wrye Bash splash screen as an image in your wizard.Case option
- The lines following the Case
will be run if the user selected its corresponding option on the dialog, until a Break
or EndSelect
is met.
Case
corresponds to.
Default
- The lines following the Default
will be run, until a Break
or EndSelect
, if none of the Case
options have been run.
Break
- Stops running lines in the current Case
or Default
block.
EndSelect
- Signals the end of the Select control block.
SelectMany - Shows a dialog where the user can select multiple options from a list. After the user presses the "Next" button, this begins a Select control block. See SelectOne for usage.
SelectMany 'description', \
'option 1', 'description 1', 'image 1', \
'option 2', 'description 2', 'image 2', \
..., \
'option n', 'description n', 'image n'
Case 'option 1'
lines
Break
Case 'option 2'
lines
Break
Case 'option n'
lines
Break
EndSelect
SelectEspm - Use SelectPlugin instead.
DeSelectEspm - Use DeSelectPlugin instead.
SelectAllEspms - Use SelectAllPlugins instead.
DeSelectAllEspms - Use DeSelectAllPlugins instead.
RenameEspm - Use RenamePlugin instead.
ResetEspmName - Use ResetPluginName instead.
ResetAllEspmNames - Use ResetAllPluginNames instead.
Note: For any of these operators, you can mix decimals and integers. In such a case, the integer will simply be promoted to a decimal, and the result will be a decimal as well.
Addition: +
. Adds one integer or decimal to another, or concatenates two strings.
1 + 1 ; == 2
1 + 1.0 ; == 2.0
1.0 + 1 ; == 2.0
1.0 + 1.0 ; == 2.0
"foo" + "bar" ; == "foobar"
Subtraction: -
. Substracts one integer or decimal from another.
1 - 1 ; == 0
1 - 1.0 ; == 0.0
1.0 - 1 ; == 0.0
1.0 - 1.0 ; == 0.0
Multiplication: *
. Multiplies one integer or decimal with another, or copies a string multiple times (see example).
1 * 1 ; == 1
1 * 1.0 ; == 1.0
1.0 * 1 ; == 1.0
1.0 * 1.0 ; == 1.0
; Multiplying a string by
; an integer just concatenates
; several copies of it:
"foo" * 2 ; == "foofoo"
3 * "h" ; == "hhh"
; Note: the other type _must_
; be an integer, decimals
; are not allowed:
2.0 * "a" ; error
Division: /
. Divides one integer or decimal by another. Division by zero causes an error.
1 / 1 ; == 1
1 / 1.0 ; == 1.0
1.0 / 1 ; == 1.0
1.0 / 1.0 ; == 1.0
1 / 0 ; error
1.0 / 0.0 ; error
Modulo: %
. Returns the remainder of dividing one integer or decimal by another. If the second argument is 0, an error is raised.
5 % 2 ; == 1
4 % 2 ; == 0
5 % 5 ; == 0
5.0 % 2.5 ; == 0.0
-7 % 4 ; == -3
1 % 0 ; error
1.0 % 0.0 ; error
Exponentiation: ^
. Raises one integer or decimal to the power of another.
2 ^ 2 ; == 4
2 ^ 2.0 ; == 4.0
2.0 ^ 2 ; == 4.0
2.0 ^ 2.0 ; == 4.0
Assignment operators are used to assign values to variables. Compound assignment operators are a combination of assignment operator and mathematical operator, performing the operation and assigning it to a variable in one step.
Assignment: =
test = 3 ; test now has value 3
foo = "bar" ; foo now has value "bar"
Compound Assignment: +=
, -=
, *=
, /=
, ^=
var += expr
): Assigns the result of var + expr
to var. In other words, this is equivalent to var = var + expr
. May also be used to concatenate two strings, just like +
.var -= expr
): Assigns the result of var - expr
to var. In other words, this is equivalent to var = var - expr
.var *= expr
): Assigns the result of var * expr
to var. In other words, this is equivalent to var = var * expr
. May also be used to repeat a string using an integer, just like *
.var /= expr
): Assigns the result of var / expr
to var. In other words, this is equivalent to var = var / expr
.var %= expr
): Assigns the result of var % expr
to var. In other words, this is equivalent to var = var % expr
.var ^= expr
): Assigns the result of var ^ expr
to var. In other words, this is equivalent to var = var ^ expr
.These operators increase or decrease a variable containing an integer or decimal by 1 and then return the changed value. They can be placed them before or after the variable that should be changed.
Warning: If you are familiar with other programming languages, you may expect ++var
and var++
to behave differently. However, in wizards they both behave the same way, returning the new value (var + 1
) in both cases. In other words, wizards only support pre-increment and pre-decrement operators.
++
. Increases a variable by 1
and returns the new value.
foo = 1 ; foo == 1
bar = foo++ ; foo == 2, bar == 2
++bar ; foo == 2, bar == 3
--
. Decreases a variable by 1
and returns the new value.
foo = 3 ; foo == 3
bar = foo-- ; foo == 2, bar == 2
--bar ; foo == 2, bar == 1
Boolean operators can be used to test the logical truth of values.
And: &
, and
. Returns True
if both sides of the expression are true and False
otherwise.
var1 & var2
var1 and var2
Or: |
, or
. Returns True
if either side of the expression is true and False
otherwise.
var1 | var2
var1 or var2
Not: !
, not
. Returns True
if the expression is False
, and False
if the expression is True
.
!value
not value
In: in
. Returns True
if the left hand side of the expression is contained in the right hand side, and False
otherwise.
If value in SubPackages
; do something here
EndIf
Comparison operators are used to compare two values or variables with one another.
Equal: ==
. Returns True
if the left hand side of the expression is equal to the right hand side of the expression, and False
otherwise.
var1 == var2
Not Equal: !=
. Returns True
if the left hand side of the expression is not equal to the right hand side of the expression, and False
otherwise.
var1 != var2
Greater Than or Equal: >=
. Returns True
if the left hand side of the expression is greater than or equal to the right hand side of the expression, and False
otherwise.
var1 >= var2
Greater Than: >
. Returns True
if the left hand side of the expression is greater than the right hand side of the expression, and False
otherwise.
var1 > var2
Less Than or Equal: <=
. Returns True
if the left hand side of the expression is less than or equal to the right hand side of the expression, and False
otherwise.
var1 <= var2
Less Than: <
. Returns True
if the left hand side of the expression is less than the right hand side of the expression, and False
otherwise.
var1 < var2
Some of the operators have case insensitive versions, which function in the same way as their normal versions, but when comparing strings they ignore case. Case insensitive versions of operators end with a colon :
. The following case insensitive operators are available:
==:
!=:
>=:
>:
<=:
<:
in:
The dot operator can be used to call a function on a variable without having to specify the variable in the function's arguments. This functionality will be familiar to anyone with experience in object-oriented programming:
; These two are equivalent
myStr.startswith("foo")
startswith(myStr, "foo")
The following functions can be used with the dot operator:
len
endswith
startswith
lower
find
rfind
Indexing is used to access a specific location in a sequence. Slicing is an extension of indexing that returns a part of the sequence. Currently only strings and string variables can be indexed / sliced. The syntax used is identical to Python's syntax.
Indexing:
string[index]
Slicing:
string[start:stop:step]
:
is supplied, indexing will continue to the end of the sequence. If not specified and no colon is supplied, only one character will be indexed.2
would return every second item in the sequence. If not specified, a value of 1
will be used.Negative values for index, start and stop will be relative to the end of the sequence. For example, -1
would mean the first character from the end of the sequence.
Examples:
"Hello"[0] ; returns "H"
"Hello"[2] ; returns "l"
"Hello"[0:] ; returns "Hello"
"Hello"[:] ; returns "Hello"
"Hello"[0:2] ; returns "He"
"Hello"[-1] ; returns "o"
"Hello"[1:3] ; returns "el"
"Hello"[-2:] ; returns "lo"
Only three constants are defined in BAIN Wizards:
True - True
. Equal to boolean true
(text representation) or 1
(binary representation).
False - False
. Equal to boolean false
(text representation) or 0
(binary representation).
SubPackages - A list of strings. Contains the names of the sub-packages of the installer that this wizard belongs to. Can be iterated over with a For
statement or used with the in
operator.
Escape sequences are special sequences of characters you can use to get a different character outputted. The escape sequences allowed are:
\"
: Outputs a double quote character "
. This allows you to put quotes in a string without causing the Wizard engine to think it's reached the end of the string.
\'
: Outputs a single quote character '
. This allows you to put quotes in a string without causing the Wizard engine to think it's reached the end of the string.
\t
: Outputs a tab.
\n
: Outputs a new line.
\\
: Outputs a backslash \
.
The following mods have Wizard scripts that may be useful references: Animated Window Lighting System and Chimneys - AWLS, BAIN Conversion Files, Bananasplit Better Cities, Fast and Easy Frans WIZBAIN Archive Maker -ENGLISH ONLY-, Metallicow Cursor Mod, Unique Landscapes Compilation, Weather - All Natural.
Every Wizard should have a short overview for the user to read before proceeding with the actual installation questions. Notice how in the example below there are no Case
statements used and the default character |
is before the Start Here_Readme
.
SelectOne "Welcome to the ExampleMod's mod Setup Wizard", \
"|Start Here_Readme", "If this is the first time you install this mod it's recommended that you carefully read the rest of the selections readme's to have an idea of what the optional parts of this mod do.", "", \
"ExampleMod Overview", "ExampleText bla bla bla \n\nBla Bla Bla \n\n Bla Bla\n Bla", "", \
"Changelog", "Example Fixes Release 1.01 \nExample Full Public 1.0 Release \nExample 2nd Beta Release 0.91 \n0.9 - Example Beta Release \n0.3 - Example Alpha Release \n0.01 - Example Initial Release", "", \
"Guidelines for a Example install", "", "", \
"ExampleMod Screenshots", "", "Screenshots\\ExampleScreenshot.jpg", \
"Credits\\Authors", "Wrye - For BAIN. Woooooooot! \nLojack - For the wonderful BAIN wizard installer feature. \nMetallicow - For chewing the cud.", "", \
"Language", "Language or Nationality this BAIN wizard was written in. \n\n English (USA)", "Wizard Images\\EnglishUSA.jpg"
EndSelect
Useful for when you want to ask the user a yes/no question. SelectOne
and SelectSubPackage
in the example below could be replaced by another keyword.
SelectOne "Example: Yes/No Question?", \
"Yes", "Description", "Wizard Images\\Yes.jpg", \
"No", "Description", "Wizard Images\\No.jpg"
Case "Yes"
SelectSubPackage "00 Example Subpackage" ;;;Action/No Action
Break
Case "No"
;No Plugin ;;Action/No Action
Break
EndSelect
Lets say that you want to check the users data folder for a specific plugin, to check if a patch (you might have created) should apply.
If DataFileExists("ExamplePlugin.esp")
Note "ExamplePlugin Detected." ;;;Action/No Action
SelectPlugin "PatchPlugin.esp" ;;;Action/No Action
Else ; ExamplePlugin.esp wasn't detected
; No Plugin ;;;Action/No Action
EndIf
Useful for when you use features available only in recent versions of Wrye Bash but want to retain support for users with older versions.
If CompareWBVersion('292') >= 0
; User is running 292+
; Do some 292+ only stuff here, like...
EditINI('Oblivion.ini', 'Display', 'bAllowScreenShot', 1)
Else
; User is running < 292, so EditINI is unavailable.
Note "Don't forget to enable screenshots in Oblivion.ini"
EndIf
These:
EditINI('TargetINI.ini', 'set', 'ANVars.UseEW', 1)
EditINI('TargetINI.ini', 'setGS', 'fPCBaseMagickaMult', 1)
EditINI('TargetINI.ini', 'SetNumericGameSetting', 'fPerkSneakAttackMarksmanNoviceMult', 1.5, "default is 2.0")
Would create INI Tweaks:
set ANVars.UseEW to 1
setGS fPCBaseMagickaMult 1
SetNumericGameSetting fPerkSneakAttackMarksmanNoviceMult 1.5;default is 2.0
This:
GetFilename("C:\Program Files\Bethesda Softworks\Oblivion\Oblivion.exe")
Would return "Oblivion.exe"
. This:
GetFilename("C:\Program Files\Bethesda Softworks\Oblivion")
Would return an empty string.
This:
GetFolder("Data\mine.esp")
Would return "Data"
. This:
GetFolder("mine.esp")
Would return an empty string.
This section compares the functions and keywords available in Wizards against those available in OBMM scripts.
OBMM Script | Wizards |
---|---|
If <function> [...]
IfNot <function> [...]
| If statement
If not statement
|
Else
EndIf
| Elif
Else
EndIf
|
If DialogYesNo <Message> [Title]
| SelectOne message, "Yes", yes_description, yes_image, "No", no_description, no_image
Case "Yes"
statements
Break
Case "NO"
statements
Break
EndSelect
|
If DataFileExists <FileName>
| If DataFileExists(filename)
|
If ScriptExtenderPresent
| If CompareSEVersion("0.0.0.0") == 1
|
If ScriptExtenderNewerThan <version>
| If CompareSEVersion(version) == 1
|
If GraphicsExtenderPresent
| If CompareGEVersion("0.0.0.0") == 1
|
If GraphicsExtenderNewerThan <version>
| If CompareGEVersion(version) == 1
|
If OblivionNewerThan <version>
| If CompareGameVersion(version) == 1
|
If Equal <arg1> <arg2>
If GreaterThan <arg1> <arg2>
If GreaterEqual <arg1> <arg2>
If fGreaterThan <arg1> <arg2>
If fGreaterEqual <arg1> <arg2>
| If statement == statement
If statement > statement
If statement >= statement
If statement > statement
If statement >= statement
|
Select <Title> <Option1> [Option2] [...]
SelectWithPreview <Title> <Option1> <ImagePath1> [Option2] [ImagePath2] [...]
SelectWithDescriptions <Title> <Option1> <Description1> [Option2] [Description2] [...]
SelectWithDescriptionsAndPreviews <Title> <Option1> <ImagePath1> <Description1> [Option2] [ImagePath2] [Description2] [...]
| SelectOne title, option1, description1, image1, option2, description2, image2 [...]
|
SelectMany <Title> <Option1> [Option2] [...]
SelectManyWithPreview <Title> <Option1> <ImagePath1> [Option2] [ImagePath2] [...]
SelectManyWithDescriptions <Title> <Option1> <Description1> [Option2] [Description2] [...]
SelectManyWithDescriptionsAndPreviews <Title> <Option1> <ImagePath1> <Description1> [Option2] [ImagePath2] [Description2] [...]
| SelectMany title, option1, description1, image1 [...]
|
Case <option>
Default
Break
EndSelect
| Case option
Default
Break
EndSelect
|
For Count <Variable> <Start> <End> [Step]
Continue
Exit
EndFor
| For variable from start to end by step
Continue
Break
EndFor
|
Return
| Return
|
DontInstallPlugin <Plugin>
InstallPlugin <Plugin>
| DeSelectPlugin plugin
SelectPlugin plugin
|
CopyPlugin <CopyFrom> <CopyTo>
| RenamePlugin original_name new_name
|
EditINI <section> <key> <value>
| EditINI("Oblivion.ini", section, setting, value)
|
FatalError
| Cancel [message]
|
SetVar <Variable> <Value>
| variable = value
|
StringLength <Variable> <String>
| variable = len(string)
variable = string.len()
|
iSet <Variable> <expression>
fSet <Variable> <expression>
| variable = expression
|
ExecLines <lines>
| Exec(lines)
|
SubString <Variable> <String> <startfrom> [length]
| find(variable, string, start, stop)
variable.find(string, start, stop)
|
OBMM Script | Wizards |
---|---|
If VersionGreaterThan <version>
If VersionLessThan <version>
| Use CompareWBVersion to check the Wrye Bash version.
|
Message <Message> [Title]
DisplayImage <Image File Path> [Title]
DisplayText <Text File Path> [Title]
| Similar functionality can be reproduced using Note and SelectOne or SelectMany keywords.
|
ConflictWith <ModName> [Comment] [Level]
DependsOn <ModName> [Comment] [Level]
| Similar functionality can be reproduced using If DataFileExists(modname) .
|
DontInstallDataFile <FileName>
InstallDataFile <FileName>
DontInstallDataFolder <FolderName> [RecurseSubfolders]
InstallDataFolder <FolderName> [RecurseSubfolders]
CopyDataFile <CopyFrom> <CopyTo>
CopyDataFolder <CopyFrom> <CopyTo> [RecurseSubfolders]
| Similar functionality can be obtained by packaging the mod differently, and then using SelectSubPackage and DeSelectSubPackage .
|
For Each DataFolder <Variable> <FolderPath> [RecurseSubFolders] [SearchString]
For Each DataFile <Variable> <FolderPath> [RecurseSubFolders] [SearchString]
For Each PluginFolder <Variable> <FolderPath> [RecurseSubFolders] [SearchString]
For Each Plugin <Variable> <FolderPath> [RecurseSubFolders] [SearchString]
| Use:
For sub in SubPackages
and/or:
to iterate over files and folders in an installer. Then use:
and other string manipulation functions to test file names and folders. |
SelectVar <Variable>
SelectString <Variable>
Goto <label>
Label <label>
LoadBefore <Plugin1> <Plugin2>
LoadAfter <Plugin1> <Plugin2>
UncheckESP <plugin>
SetDeactivationWarning <plugin> <warning>
ConflictsWith <ModName> <MinMajorVersion> <MinMinorVersion><MaxMajorVersion> <MaxMinorVersion> [Comment] [Level]
ConflictsWithRegex <ModName> [Comment] [Level]
ConflictsWithRegex <ModName> <MinMajorVersion> <MinMinorVersion><MaxMajorVersion> <MaxMinorVersion> [Comment] [Level]
DependsOn <ModName> <MinMajorVersion> <MinMinorVersion><MaxMajorVersion> <MaxMinorVersion> [Comment] [Level]
DependsOnRegex <ModName> [Comment] [Level]
DependsOnRegex <ModName> <MinMajorVersion> <MinMinorVersion><MaxMajorVersion> <MaxMinorVersion> [Comment] [Level]
RegisterBSA <FileName>
UnregisterBSA <FileName>
EditShader <ShaderPackage> <ShaderName> <BinaryObjectPath>
SetGMST <file> <Editor ID> <new value>
SetGlobal <file> <Editor ID> <new value>
SetPluginByte <file> <offset> <new value>
SetPluginByte <file> <offset> <new value>
SetPluginShort <file> <offset> <new value>
SetPluginLong <file> <offset> <new value>
SetPluginFloat <file> <offset> <new value>
GetFolderName <Variable> <path>
GetFileName <Variable> <path>
GetFileNameWithoutExtension <Variable> <path>
CombinePaths <Variable> <path1> <path2>
RemoveString <Variable> <String> <startfrom> [length]
InputString <Variable> [Title] [Initial]
ReadINI <Variable> <section> <value>
ReadRenderInfo <Variable> <value>
EditXMLLine <file> <line number> <new line>
EditXMLReplace <file> <text to find> <text to replace>
CompareWBVersion(version)
GetPluginStatus(plugin)
DisableINILine(file_name, section, setting)
str(value)
int(value)
float(value)
SelectAll
DeSelectAll
SelectAllPlugins
DeSelectAllPlugins
While expression
Continue
Break
EndWhile
RequireVersions oblivion, obse, obge, wrye_bash
OBMM Script | Wizards |
---|---|
PatchDataFile <NewFile> <FileToPatch> [Create]
PatchPlugin <NewFile> <FileToPatch> [Create]
| Unnecessary due to BAIN's conflict resolution abilities. |
AllowRunOnLines | Wizards support run-on lines as standard. |
This format is used for exporting and importing data by the
Trusted Binaries
settings page. It is a simple plaintext format, stored with UTF-8 encoding
(do not include a BOM when writing, but be ready to handle a BOM
when reading since versions of Wrye Bash before 309 wrote BOMs) in files
with the .txt
extension.
Each line is either a statement or a comment. If the line begins with one of they statement keywords, as described below, it is a statement. Otherwise, it is considered a comment and ignored completely. Almost all spaces (the exceptions are spaces inside string variables) are optional and ignored. Line terminators may be either Windows-style or Unix-style.
As you may be able to tell, the syntax is pretty ugly. That's because a lot
of this was generated by simply writing out Python repr()
s,
and we can't change it for backwards compatibility reasons.
badDlls - Begins a block of 'bad' binaries. All dll statements after this one will be considered 'bad', meaning that BAIN will silently skip their installation.
badDlls [comment]
dll - Begins a new binary entry. May optionally be terminated with a colon.
dll: path [:]
/
and \
will
be considered valid path separators here, so Unix pathnames
like skse/plugins/my\file\with\backlashes.so
cannot be handled by BAIN. Maybe consider a saner name for your
binary?goodDlls - Begins a block of 'good' binaries. All dll statements after this one will be considered 'good', meaning that BAIN will allow their installation.
goodDlls [comment]
version - Adds a version
entry to the last binary (as specified by the last
dll statement). Note that the
\[
and \]
below stand for literal '[' and
']' characters, instead of the usual meaning (an optional part of
the syntax).
version [index]: \[[u]name, size[L], crc[L]\]
u
prefix (before the quotes), which is
ignored if it's present.L
suffix, which is
ignored if it's present.L
suffix, which is
ignored if it's present.There is no hard and fast structure for this format. Two rules do have to be observed, however:
Breaking one of these rules is a syntax error, which will result in Wrye Bash showing an error popup if one attempts to import the file.
It is suggested to use only one goodDlls and badDlls block per file and only one dll statement per binary per block. The following is an example file exported by Wrye Bash 307:
goodDlls (those dlls that you have chosen to allow to be installed)
dll:skse\plugins\chargen.dll:
version 00: [u'RaceMenu v3-4-5-29624-3-4-5', 585216, 2162501321L]
dll:skse\plugins\nioverride.dll:
version 00: [u'RaceMenu v3-4-5-29624-3-4-5', 827904, 1370081254]
dll:skse\plugins\additemmenule.dll:
version 00: [u'AddItemMenuLE320_SKSE173-64905-3-2-1557583553', 268800, 1953112203]
dll:skse\plugins\storageutil.dll:
version 00: [u'Campfire 1.11-64798-1-11', 978944, 50366834]
version 01: [u'PapyrusUtil - Scripting Utility Functions-58705-3-3', 978944, 50366834]
badDlls (those dlls that you have chosen to NOT allow to be installed)
None
Note the comments after the
goodDlls and
badDlls statements, as well as the
None
line - that is a comment too.
Importing this file would result in four binaries being added to the 'good' binaries list. BAIN would allow these to be installed according to the version entries they have. The following list illustrates this:
skse\plugins\chargen.dll
may be installed, but
only if:
skse\plugins\nioverride.dll
may be installed, but
only if:
skse\plugins\additemmenule.dll
may be installed, but
only if:
skse\plugins\storageutil.dll
may be installed, but
only if:
The Load Order..
commands
Export... and
Import...
use a format inspired by the plugins.txt
format used in
Skyrim: Special Edition (currently pretty much identical, in fact,
but fully specified here as an independent format in case Bethesda decides
to change it at some point in the future).
Additionally, there is a similar, but different format used by the
Load Order..
command
Import From OBMM....
This format is originally from OBMM. Wrye Bash does not export it, only
import it (for easy importing from OBMM). Both are defined in the following
sections.
This format uses a UTF-8-encoded file (no BOM). Line terminators may be either CR-LF or LF. There are three kinds of lines:
An empty line is a line consisting of nothing but whitespace (including the line terminator). They are simply skipped.
An active plugin is identified by the line beginning with an
asterisk (*, U+002A ASTERISK
) and followed by a string of
characters representing a plugin name (see below on what constitutes a
plugin name). Such a line identifies the position of the plugin in question
in the exported load order and also marks it as having been active at the
time the export was made. As a result of this representation, plugins that
have asterisks in their file names will not be exported. Asterisks are
illegal characters on Windows anyways and thus can't actually be handled by
the game, so this isn't a problem in practice.
An inactive plugin is a line consisting of a string of characters that represent a plugin name. Unlike an active plugin, there is no asterisk at the beginning of the line. Such a line identifies the position of the plugin in question and also marks it as having been inactive at the time the export was made.
For the purposes of this format, a plugin name is defined as any string of Unicode characters that end in a valid plugin file extension. Trailing spaces are fine - they are to be trimmed before checking for the extension. Leading spaces are fine as well, but should not be trimmed (they would be part of the plugin name).
Currently valid plugin file extensions are:
.esl
.esm
.esp
.esu
If a line would otherwise match as an active or inactive plugin, but does not because the resulting plugin name would be invalid, an implementation performing an import must reject the file and show an error message to the user. Ideally, the implementation should highlight the problematic line, so the user is informed and can fix the problem.
Note: implementations are free to limit this list of valid
extensions to the ones valid for a particular game (e.g. if the load order
is to be imported into Oblivion, .esl
would not make
sense). In that case, an error message has to be shown as well.
The format also supports comments. Comments begin with a hash
(#, U+0023 NUMBER SIGN)
and last until the end of the line
(i.e. the next line terminator). They are stripped out before the type of
line is identified. So a line that consists of whitespace and a comment
will become an empty line (and thus skipped), while a line that starts with
some characters followed by a comment will become an active or inactive
plugin line.
Implementations are encouraged to place a comment at the top of an exported file identifying themselves, for the benefit of human readers who will thereby know what tool was used to create the file (and can direct bug reports etc. to the right place).
Here is a simple pseudocode algorithm specifying how to parse and interpret a file in this format:
$lo := An empty list
$active := An empty set
For $line in $file: {
$strippedLine := Strip comments out of $line
Check if $strippedLine is empty or all whitespace: {
If yes, move on to the next line
Otherwise, do the following: {
$isActive := Does $strippedLine begin with an asterisk?
Check if $isActive is true: {
If yes, $plugin := Remove the leading asterisk from $strippedLine
Otherwise, $plugin := $strippedLine
}
$trimmedPlugin := Trim trailing spaces from $plugin
Check if $trimmedPlugin is a valid plugin name: {
If yes, append $trimmedPlugin to the end of $lo
Otherwise, reject the whole file and show an error to the user
}
Check if $isActive is true: {
If yes, add $trimmedPlugin to $active
}
}
}
}
After running this algorithm, the exported load order is in $lo
(with the earliest-loaded plugin at index 0 and the last-loading plugin at
the last index) and the exported active plugins are in
$active
. Implementations performing an export must never
export active or inactive plugin lines that do not resolve to valid plugin
names.
This format is similar to the Wrye Bash format, but much simpler. It only has one type of line: the active plugin line. Accordingly, no asterisks are used for this type of line either.
As a direct result of this design, this format cannot store information about inactive plugins and hence no import of data in this format can ever be perfect.
Wrye Bash makes further assumptions about this format: no comments are supported and plugin names still obey the same rules as above. Further, no assumptions about encoding are made. Instead, the encoding is guessed from the content.
Here is a simple pseudocode algorithm specifying how Wrye Bash parses and interprets a file in this format:
$lo := An empty list
$data := Read binary data from $file
Try to decode $data and split it into $lines {
If that is not possible, reject the whole file and show an error to the user
Otherwise, for $line in $lines: {
Check if $line is a valid plugin name: {
If yes, append $line to the end of $lo
Otherwise, reject the whole file and show an error to the user
}
}
}
After running this algorithm, the exported load order (and, simultaneously,
active plugins) are in $lo
(with the earliest-loaded plugin at
index 0 and the last-loading plugin at the last index).
This section covers CSV-based formats used by Wrye Bash. See Wikipedia's article on CSV files for an introduction to the format. All CSV files used by Wrye Bash must be encoded in UTF-8. They currently require a UTF-8 BOM, but this is for historical reasons and the BOMs will become optional in a future release.
All CSV files used by Wrye Bash use commas to separate values and double quotes to quote values. Usually all values are quoted, but CSV files created by older Wrye Bash versions may not have quotes around some values, so be prepared to handle those.
The names of the CSV columns are usually unimportant and may be localized. Only the context in which the CSV file is used and its contents determine the semantic meaning.
These properties define a WBCSV file, which is the term that will be used for the rest of this section.
This format is used by Export Order... and Import Order... to export and import BAIN package order.
The format is a WBCSV file, with two columns. Each row specifies a single entry in the package order. The order of the rows specifies the order of the packages. Missing packages will be skipped when importing.
Package Order Format | ||
---|---|---|
Column Name | Meaning | Example Value |
Package | The name of the package. | Alternate Start - Live Another Life 4.1.7.7z |
Installed? (Y/N) | Y if the package was installed, N if
it wasn't. |
Y |
"Package","Installed? (Y/N)"
"==Basics==","N"
"Vanilla Script Sources.zip","Y"
"SKSE Scripts 2.2.3.7z","Y"
"Address Libary - All in one (Anniversary Edition)-32444-8-1664465359.zip","Y"
"==Essentials==","N"
"Alternate Start - Live Another Life 4.1.7.7z","Y"
"Unofficial Skyrim Creation Club Content Patch-18975-7-2-1666561973.zip","Y"
"Unofficial Skyrim Special Edition Patch-266-4-2-8-1663527575.7z","Y"
"==SKSE Fixes & Plugins==","N"
"ConsoleUtilSSE-24858-1-4-0-1665802090.zip","Y"
"MfgFix-11669-1-6-1-1664520342.7z","Y"
"SSE Display Tweaks-34705-0-5-12-1664893623.zip","Y"
"SSEDT - Personal Config.7z","Y"
"SSE Engine Fixes for 1.6.629 and newer-17230-6-1-1-1664974106.7z","Y"
"Simple Item Spawner-64653-1-50-1653532324.zip","Y"
"==Body==","N"
"XP32 Maximum Skeleton Special Extended-1988-4-81-1660739371.7z","Y"
"==Characters==","N"
"Expressive Facial Animation - Female Edition-19181-1-7-1575746557.7z","Y"
"Expressive Facial Animation - Male Edition-19532-1-21-1575813430.7z","Y"
"RaceMenu Anniversary Edition v0-4-19-14-19080-0-4-19-14-1667000011.7z","Y"
"==Combat==","N"
"Armor Rating Rescaled Remake-35296-1-0-2-1663883868.zip","Y"
"==Crafting==","N"
"Ars Metallica 2.0.6.7z","Y"
"==Interface==","N"
"Immersive HUD - iHUD-12440-0-2b.7z","Y"
"SkyHUD v090B v4-463-0-90B.zip","Y"
"Better MessageBox Controls v1_2-1428-1-2.zip","Y"
"Dialogue Interface ReShaped-46546-1-03-1616150370.zip","Y"
"More Informative Console 1.1.0 AE (1.6.640 plus )-19250-1-1-0-1664127904.zip","Y"
"==Tools==","N"
"FNIS Behavior SE 7_6 XXL-3038-7-6-1582110624.7z","Y"
"My SkyHUD Preset.7z","Y"
"==Last==","N"