This chapter explains how to set up SFO, and the basics of its modding environment.
Installing SFO is simple. Just follow these steps:
INCLUDE "sfo/sfo_init.tpc"
Once installed, SFO loads the SFO and SFO-LUA function libraries, so that you can use SFO functions. It also does the following things:
If you don't want any of these features and just want to load SFO's function library, set the variable sfo_lite=1 before installing:
OUTER_SET sfo_lite=1
INCLUDE "sfo/sfo_init.tpc"
There are a number of other variables that can be set to customize an SFO install more finely; again, this needs to be done in the ALWAYS block before INCLUDEing sfo_init. I describe various of them below.
Ini files are used by some mods to fine-tune installation options, beyond what the normal WEIDU subcomponent framework can handle. An ini file is a text file consisting of a series of 'key=value' pairs. Here key should be some string without spaces, and value should either have no spaces or be wrapped in quotes (" or ~ should both be fine). Optionally, your ini file can be separated into sections. A section starts with a string wrapped in "[]".
For instance, here's a fragment of the ini file for Talents of Faerun:
[alignment]
jaheira_is_ng=1
faldorn_is_ne=1
[class]
lay_on_hands_level=5
lay_on_hands_interval=4
smite_evil_level=7
smite_evil_interval=6
number_of_required_specialist_spells=1
list_specialist_spells=1
[default_start]
start_iwd=iwd
start_bg=bg
start_bg2=bg2
start_eet=bg
SFO assumes that your ini file, if you have one, is sitting at %MOD_FOLDER%/%MOD_FOLDER%.ini, and if it finds a file there, it will load it. As far as SFO is concerned your ini file is case-insensitive, so it loads everything lowercased. (If you prefer to keep your ini file somewhere else, you can tell SFO about it; see below.)
You can access your ini file via the (dimorphic) function check_ini, like this:
LAF check_ini STR_VAR ini=smite_evil_level RET value END
LAF check_ini STR_VAR ini=smite_evil_level section=class RET value END
By default, check_ini will throw a WARNING if you check an ini entry that does not occur in the ini file. This is a debugging feature that guards against typos and against forgetting to set up the ini. If you want to check an ini without assuming it is present, use the INT_VAR silent=1, as in
LAF check_ini INT_VAR silent=1 STR_VAR ini=smite_evil_level RET value END
If you want to keep your ini function somewhere else, you do it like this:
OUTER_SPRINT sfo_ini_file "my_awesome_ini.ini" // the filename of your ini file
OUTER_SPRINT sfo_ini_file_location "%MOD_FOLDER%/lib" // set to the full path (relative to your game directory)
//of the folder where your ini file lives.
INCLUDE "sfo/sfo_init.tpc"
SFO automatically handles your tra files (using the 'charset_wrapper' function, which is called automatically when you run it). If:
LOAD_TRA "%sfo_tra_loc%/english/my_tra.tra" "%sfo_tra_loc%/%LANGUAGE%/my_tra.tra
If one or more of these isn't correct, you can change the defaults by setting various variables before INCLUDEing sfo_init.tpc. Here's the full syntax:
OUTER_SPRINT sfo_tra_path "tra" // the location of your tra files, relative to MOD_FOLDER
OUTER_SET sfo_from_utf8=1 // set to 0 if your tra files are encoded in oBG2 style
//and need converting to UTF-8 on enhanced-edition installs
OUTER_SPRINT sfo_setup_tra "setup" // set to the name (without .tra) of the file in which your tp2 component names,
//component-compatibility messages, component group names, etc live
OUTER_SPRINT sfo_iconv_path "tra/iconv" // set to the location (relative to MOD_FOLDER) of iconv.exe
OUTER_SPRINT sfo_tra_load "" // set to a space-separated list of names (.tra is optional) of
//tra files that you want loaded after conversion/copyover
OUTER_SPRINT sfo_default_language "english" // set to the language in which you are developing the mod
OUTER_SPRINT sfo_extra_tra_folders "" // set to a space-separated list of additional folders that also contain
//tra files (you still need to avoid namespace conflict)
INCLUDE "sfo/sfo_init.tpc"
SFO sets a group of variables which give convenient access to details of the environment in which you are installing. Here's the full list (each is equal to 0 by default). It saves a bit of typing to define them, and also has some runtime advantages over native checks like GAME_IS.
weidu_external is a folder in your mod directory, used by SFO (and other) mods to store files. SFO will set up the directory and a number of subdirectories, and defines variables that point to them. A partial list is:
In addition, SFO sets up a system of 'labels' that can be created to tell your mod, or other people's mods, that some task has been carried out or some object is present. You create labels using the make_label (dimorphic) function:
LAF make_label STR_VAR label=dw#iwd_spells_are_installed END
LAF check_label STR_VAR label=dw#iwd_spells_are_installed RET value END
SFO's 'lib_data' library contains a number of macros designed to load data into memory. Two of those macros, data_spell_resrefs and data_joinable_dvs, run automatically when SFO is INCLUDEd, and contain, respectively, all the resrefs of the spells in spell.ids and all the death variables of party-joinable NPCs. I'll give the details below.
data_spell_resrefs
The main thing this does is go through spell.ids and, for each entry, set a variable whose name is the entry and whose value is the (uppercased) resref of the associated spell. For instance, WIZARD_FIREBALL is set to SPWI304. This makes for hopefully-more-readable code: you can do things like
COPY_EXISTING "%WIZARD_FIREBALL%.spl" override
[patch]
There are a few details worth knowing:
data_joinable_dvs
This simply outputs an associative array, 'sfo_joinable_dvs', whose keys are the lowercased death variables (i.e. script name) of any NPC who can join the party (the values are blank). Joinable NPCs are defined as any that occur in pdialog.2da or in any file in the PDIALOG column of campaign.2da. In addition, the joinable NPCS in Candlekeep in BG (arkanis, canderous, deder, mordaine, osprey) are hardcoded to be added.A major nuisance of modding BG specifically is that there are no fewer than five versions - original BG, the TUTU conversion, the Baldur's Gate Trilogy combination of oBG with original BG2, the Enhanced Edition, and the Enhanced Edition Trilogy (EET) combination of BGEE and BG2EE - and all have different naming conventions. This also causes a few issues when modding BG2 - mostly the Trilogy combinations leave the BG2 filenames invariant, but EET in particular changes the chapter-number conventions. The community standard for handling this is to define a number of 'crossplatform' variables that evaluate differently on different installs.
SFO automates this, automatically loading the right crossplatform variables for your install. The full details of crossplatform modding are a bit out of scope for this course so here I'll just summarise what is defined.
Areas
SFO sets a variable for every area in BG, whose name is that area's human-readable name in the usual conventions used in crossplatform modding and whose value is the resref of that area on your current install. For instance, 'NWBaldursGate' resolves to AR0100 on oBG or BGEE, FW0100 on TUTU, AR7200 on BGT, and BG0100 on EET. A full list can be found in sfo/data/bg1_area_list.2da.
Area scripts
SFO also sets a variable for the script of each BG area, whose name is the area name followed by '_BCS' and whose value is the area script. For example, 'NWBaldursGate_BCS' would resolve as AR0100 on oBG or BGEE, _AR0100 on TUTU, BG0100 on EET, and AR7200 on BGT.
Prefix/suffix variables
SFO sets variables 'tutu_var' and 'tutuscripta' through 'tutuscriptz'. On TUTU, all of these are set to '_'. On any other install, tutu_var is set to "" and the others are set to the appropriate letter of the alphabet, e.g. tutuscriptk=k.
SFO also sets 'eet_var', which equals '_' on EET and is blank otherwise.
Chapter variables
SFO sets variables 'bg1_chapter_1' through 'bg1_chapter_7' and 'bg2_chapter_1' through 'bg2_chapter_10', which resolve as the chapter numbers used in the respective installs.
Special cases
There are a few specific variables which aren't conveniently captured by a systematic scheme and need to be set by hand. These can be found in sfo/data/bg1_file_names.2da
SFO is not a fixpack, but there are a few bugs on the various IE games that actually get in its way, and so SFO quietly fixes them when you first install. Here's the list.
Enable dir.ids
Not all versions of the IE use dir.ids, which allows directions to be given on a compass (N,NNW, etc) and not just as integers in the 0-15 range. SFO enables it.
Add missing gtimes.ids entries
The IE games are very inconsistent as to which times are present in gtimes.ids. SFO insists that at least a large group are present.
Add missing spell.ids entries
Certain spell.ids entries are not present in some versions of the game even when the spell itself is present. SFO standardizes spell.ids a bit by adding a bunch of entries if they are not already there. (This only applies on games with a spell system based on BG2, i.e. BG2 itself, BGEE, and IWDEE.)
Make sure FarthestObject and variants are present
The Enhanced Edition introduces the FarthestObject object (and variants) but they are not always present in object.ids. SFO puts them there if they're not there already.
Remove broken oBG2 items
The non-Enhanced version of BG2 has a number of broken itm and are files which disrupt regexp patching. SFO removes them if they haven't been removed already (e.g., by the BG2 fixpack).
Remove + signs from missile.ids
Version 2.6 of the EE introduces some entries in missile.ids that contain a + sign. That's legal in the IE but WEIDU can't parse them, so SFO swaps them for the string 'plus_'.
Make rows in weapprof.2da unique
weapprof.2da reuses two row titles, 'SPEAR' and 'AXE'. SFO leans heavily on the paradigm of unique lookup of 2da entries by row/column, so it would find this confusing. It swaps the first appearance of 'SPEAR' for 'SPEAR_BG1' and does similarly for the first appearance of 'AXE'.
Fix minor bugs in the UI
The EE game's UI ships with a couple of minor bugs: they're harmless in-game but make it a pain to debug UI edits. SFO fixes them. (This fix doesn't happen if Lefreut's UI is present.)